Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/web-platform/web-core-wasm/css/in_shadow.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@import url("./linear.css");
@import url("@lynx-js/web-elements/elements.css");
[lynx-default-display-linear="false"] * {
--lynx-display: flex;
--lynx-display-toggle: var(--lynx-display-flex);
}
[lynx-default-overflow-visible="true"] x-view {
overflow: visible;
}
119 changes: 119 additions & 0 deletions packages/web-platform/web-core-wasm/css/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
// Copyright 2023 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.
*/

lynx-view {
contain: strict;
display: none;
}

lynx-view[width="auto"] {
--lynx-view-width: 100%;
width: var(--lynx-view-width);
inline-size: var(--lynx-view-width);
}

lynx-view[height="auto"], lynx-view[width="auto"] {
contain: content;
}

lynx-view::part(page) {
height: 100%;
width: 100%;
}

@property --lynx-display {
syntax: "linear | flex";
inherits: false;
initial-value: linear;
}
@property --lynx-linear-weight-sum {
syntax: "<number>";
inherits: false;
initial-value: 1;
}
@property --lynx-linear-weight {
syntax: "<number>";
inherits: false;
initial-value: 0;
}
@property --justify-content-column {
syntax: "flex-start|flex-end|center|space-between|space-around";
inherits: false;
initial-value: flex-start;
}
@property --justify-content-column-reverse {
syntax: "flex-start|flex-end|center|space-between|space-around";
inherits: false;
initial-value: flex-start;
}
@property --justify-content-row {
syntax: "flex-start|flex-end|center|space-between|space-around";
inherits: false;
initial-value: flex-start;
}
@property --justify-content-row-reverse {
syntax: "flex-start|flex-end|center|space-between|space-around";
inherits: false;
initial-value: flex-start;
}
@property --align-self-row {
syntax: "start|end|center|stretch|auto";
inherits: false;
initial-value: auto;
}
@property --align-self-column {
syntax: "start|end|center|stretch|auto";
inherits: false;
initial-value: auto;
}
@property --lynx-linear-weight-basis {
syntax: "auto|<number>|<length>";
inherits: false;
initial-value: auto;
}
@property --lynx-linear-orientation {
syntax: "<custom-ident>";
inherits: false;
initial-value: vertical;
}

@property --flex-direction {
syntax: "*";
inherits: false;
}
@property --flex-wrap {
syntax: "*";
inherits: false;
}
@property --flex-grow {
syntax: "<number>";
inherits: false;
initial-value: 0;
}
@property --flex-shrink {
syntax: "<number>";
inherits: false;
initial-value: 1;
}
@property --flex-basis {
syntax: "*";
inherits: false;
initial-value: auto;
}
@property --flex-value {
syntax: "*";
inherits: false;
}
@property --flex {
syntax: "*";
inherits: false;
}

@property --linear-justify-content {
syntax: "flex-start|flex-end|center|space-between|space-around";
inherits: false;
initial-value: flex-start;
}
167 changes: 167 additions & 0 deletions packages/web-platform/web-core-wasm/css/linear.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
div * {
display: flex;
box-sizing: border-box;
border-width: 0px;
position: relative;
overflow: clip;
min-width: 0;
min-height: 0;
border-style: solid;
scrollbar-width: none;
}

x-view::--webkit-scrollbar {
display: none;
}

/**
* only enable this toggle logic for those container elements
*/
div * {
/*
--lynx-display-toggle is compile-time generated.
*/
--lynx-display-toggle: var(--lynx-display-linear);
--lynx-display-linear: var(--lynx-display-toggle,);
--lynx-display-flex: var(--lynx-display-toggle,);
/*
--lynx-linear-orientation-toggle is compile-time generated.
*/
--lynx-linear-orientation-toggle: var(--lynx-linear-orientation-vertical);
--lynx-linear-orientation-horizontal: var(--lynx-linear-orientation-toggle,);
--lynx-linear-orientation-vertical: var(--lynx-linear-orientation-toggle,);
--lynx-linear-orientation-horizontal-reverse: var(
--lynx-linear-orientation-toggle,
);
--lynx-linear-orientation-vertical-reverse: var(
--lynx-linear-orientation-toggle,
);

--linear-flex-direction: var(--lynx-linear-orientation-horizontal, row) var(
--lynx-linear-orientation-vertical,
column
) var(--lynx-linear-orientation-horizontal-reverse, row-reverse) var(
--lynx-linear-orientation-vertical-reverse,
column-reverse
);
--linear-justify-content: var(
--lynx-linear-orientation-horizontal,
var(--justify-content-row)
) var(--lynx-linear-orientation-vertical, var(--justify-content-column)) var(
--lynx-linear-orientation-horizontal-reverse,
var(--justify-content-row-reverse)
) var(
--lynx-linear-orientation-vertical-reverse,
var(--justify-content-column-reverse)
);
}
div * {
flex-wrap: var(--lynx-display-linear, nowrap)
var(
--lynx-display-flex,
var(--flex-wrap)
);
flex-direction: var(--lynx-display-linear, var(--linear-flex-direction))
var(
--lynx-display-flex,
var(--flex-direction)
);
justify-content: var(--lynx-display-linear, var(--linear-justify-content));
}

/** For @container
*
* when the chromuim version is less than 116.0.5806.0, the following code will crash:
* ```
* <style>
#container {
--lynx-display: flex;
}

#target {
background-color: red;
width: 400px;
height: 400px;
}

@container style(--lynx-display: flex) {
#target {
background-color: green;
}
}
</style>
<div id="container">
<div id="target"></div>
</div>
<script>
const target = document.getElementById('container');
container.style.setProperty('display', 'none');
setTimeout(() => {
target.style.removeProperty('display');
}, 10);
</script>
* ```
* it fixed in 116.0.5806.0, detail: https://issues.chromium.org/issues/40270007
*
* so we limit this feature to chrome 117, safari 18, firefox no:
* rex unit: chrome 111, safari 17.2, firefox no
* https://developer.mozilla.org/en-US/docs/Web/CSS/length
* transition-behavior:allow-discrete: chrome 117, safari 18, firefox 125
* https://developer.mozilla.org/en-US/docs/Web/CSS/transition-behavior
* https://caniuse.com/mdn-css_properties_display_is_transitionable
*
* update this once firefox supports this.
*
* If you want to be fully compatible with chrome below 117, you need to use a plugin @lynx-js/web-elements-compat.
*/
@supports (content-visibility: auto) and
(transition-behavior: allow-discrete) and (width: 1rex) {
@container style(--lynx-display: linear) {
div * {
/*
`--lynx-linear-weight-sum`
0 -> 1
<value> -> <value>
*/
flex-shrink: 0;
/* The following `calc` and `clamp` logic ensures that if
`--lynx-linear-weight-sum` is zero, it defaults to 1. This prevents
division by zero and ensures consistent behavior. */
flex-grow: calc(
var(--lynx-linear-weight) /
calc(
var(--lynx-linear-weight-sum) +
(
1 - clamp(0, var(--lynx-linear-weight-sum) * 999999, 1)
)
)
);
flex-basis: var(--lynx-linear-weight-basis);
}
}

@container not style(--lynx-display: linear) {
div * {
flex: var(
--flex,
var(--flex-grow) var(--flex-shrink) var(--flex-basis)
);
}
}

@container style(--lynx-display: linear) and
(style(--lynx-linear-orientation: vertical) or
style(--lynx-linear-orientation: vertical-reverse)) {
div * {
align-self: var(--align-self-column);
}
}

@container style(--lynx-display: linear) and
(style(--lynx-linear-orientation: horizontal) or
style(--lynx-linear-orientation: horizontal-reverse)) {
div * {
align-self: var(--align-self-row);
}
}
}
5 changes: 5 additions & 0 deletions packages/web-platform/web-core-wasm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
"last 1 chrome version"
]
},
"dependencies": {
"@lynx-js/web-elements": "workspace:*",
"@lynx-js/web-worker-rpc": "workspace:*",
"hyphenate-style-name": "^1.1.0"
},
"devDependencies": {
"@lynx-js/css-serializer": "workspace:*",
"@lynx-js/lynx-core": "0.1.3",
Expand Down
72 changes: 72 additions & 0 deletions packages/web-platform/web-core-wasm/tests/I18n.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2025 The Lynx Authors. All rights reserved.
* Licensed under the Apache License Version 2.0 that can be found in the
* LICENSE file in the root directory of this source tree.
*/
import './jsdom.js';
import { describe, expect, test, vi } from 'vitest';
import { I18nManager } from '../ts/client/mainthread/I18n.js';
import { BackgroundThread } from '../ts/client/mainthread/Background.js';
import { i18nResourceMissedEventName } from '../ts/constants.js';

describe('I18nManager', () => {
const mockBackground = {
dispatchI18nResource: vi.fn(),
} as unknown as BackgroundThread;

const rootDom = document.createElement('div').attachShadow({ mode: 'open' });

test('should return matched resource and dispatch to background', () => {
const initData = [
{
options: { locale: 'en', channel: 'default' },
resource: { key: 'value' },
},
];
const i18nManager = new I18nManager(mockBackground, rootDom, initData);

const result = i18nManager._I18nResourceTranslation({
locale: 'en',
channel: 'default',
});

expect(result).toEqual({ key: 'value' });
expect(mockBackground.dispatchI18nResource).toHaveBeenCalledWith({
key: 'value',
});
});

test('should return undefined and trigger fallback when resource not found', () => {
const i18nManager = new I18nManager(mockBackground, rootDom, []);
const dispatchEventSpy = vi.spyOn(rootDom, 'dispatchEvent');

const result = i18nManager._I18nResourceTranslation({
locale: 'fr',
channel: 'default',
});

expect(result).toBeUndefined();
expect(mockBackground.dispatchI18nResource).toHaveBeenCalledWith(undefined);
expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
const event = dispatchEventSpy.mock.calls[0]![0] as CustomEvent;
expect(event.type).toBe(i18nResourceMissedEventName);
expect(event.detail).toEqual({ locale: 'fr', channel: 'default' });
});

test('should update data using setData', () => {
const i18nManager = new I18nManager(mockBackground, rootDom, []);
i18nManager.updateData([
{
options: { locale: 'es', channel: 'default' },
resource: { key: 'valor' },
},
], { locale: 'es', channel: 'default' });

const result = i18nManager._I18nResourceTranslation({
locale: 'es',
channel: 'default',
});

expect(result).toEqual({ key: 'valor' });
});
});
Loading
Loading