@mantou/gem 1.5.5 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/elements/modal-base.d.ts +13 -12
- package/elements/modal-base.d.ts.map +1 -1
- package/helper/i18n.d.ts +3 -4
- package/helper/i18n.d.ts.map +1 -1
- package/helper/i18n.js +82 -44
- package/helper/i18n.js.map +1 -1
- package/helper/mediaquery.d.ts +2 -0
- package/helper/mediaquery.d.ts.map +1 -1
- package/helper/mediaquery.js +18 -13
- package/helper/mediaquery.js.map +1 -1
- package/lib/decorators.d.ts +1 -1
- package/lib/decorators.d.ts.map +1 -1
- package/lib/element.d.ts +3 -2
- package/lib/element.d.ts.map +1 -1
- package/lib/element.js +38 -30
- package/lib/element.js.map +1 -1
- package/lib/utils.d.ts +1 -2
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +19 -2
- package/lib/utils.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/examples/decorator/index.ts +1 -1
- package/src/examples/dialog/index.ts +1 -1
- package/src/examples/i18n/index.ts +14 -0
- package/src/examples/ref-route/index.ts +2 -2
- package/src/helper/i18n.ts +56 -24
- package/src/helper/mediaquery.ts +20 -13
- package/src/lib/decorators.ts +1 -1
- package/src/lib/element.ts +42 -29
- package/src/lib/utils.ts +17 -2
- package/src/lib/version.ts +1 -1
- package/src/test/gem-element/advance.test.ts +8 -2
- package/umd.js +10 -6
- package/umd.js.map +1 -1
package/src/helper/mediaquery.ts
CHANGED
|
@@ -1,70 +1,77 @@
|
|
|
1
1
|
// https://gist.github.com/gokulkrishh/242e68d1ee94ad05f488
|
|
2
2
|
// https://mediag.com/news/popular-screen-resolutions-designing-for-all/
|
|
3
3
|
|
|
4
|
+
const matche = (query: string) => window.matchMedia(query).matches;
|
|
5
|
+
|
|
4
6
|
export const mediaQuery = {
|
|
5
7
|
PRINT: 'print',
|
|
6
8
|
get isPrint() {
|
|
7
|
-
return
|
|
9
|
+
return matche(this.PRINT);
|
|
8
10
|
},
|
|
9
11
|
HOVER: '(hover: hover)',
|
|
10
12
|
get isHover() {
|
|
11
|
-
return
|
|
13
|
+
return matche(this.HOVER);
|
|
12
14
|
},
|
|
13
15
|
|
|
14
16
|
PHONE: '(min-width: 319px) and (max-width: 480px)',
|
|
15
17
|
get isPhone() {
|
|
16
|
-
return
|
|
18
|
+
return matche(this.PHONE);
|
|
17
19
|
},
|
|
18
20
|
|
|
19
21
|
LAPTOP: '(min-width: 1023px) and (max-width: 1280px) and (orientation: landscape)',
|
|
20
22
|
get isLaptop() {
|
|
21
|
-
return
|
|
23
|
+
return matche(this.LAPTOP);
|
|
22
24
|
},
|
|
23
25
|
|
|
24
26
|
DESKTOP: '(min-width: 1279px) and (orientation: landscape)',
|
|
25
27
|
get isDesktop() {
|
|
26
|
-
return
|
|
28
|
+
return matche(this.DESKTOP);
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
WIDTHSCREEN: '(min-width: 1919px) and (orientation: landscape)',
|
|
32
|
+
get isWidthScreen() {
|
|
33
|
+
return matche(this.WIDTHSCREEN);
|
|
27
34
|
},
|
|
28
35
|
|
|
29
36
|
PHONE_LANDSCAPE: '(min-width: 479px) and (max-width: 767px) and (orientation: landscape)',
|
|
30
37
|
// PHONE_LANDSCAPE: '(min-width: 481px) and (max-width: 767px)',
|
|
31
38
|
get isPhoneLandscape() {
|
|
32
|
-
return
|
|
39
|
+
return matche(this.PHONE_LANDSCAPE);
|
|
33
40
|
},
|
|
34
41
|
|
|
35
42
|
TABLET: '(min-width: 768px) and (max-width: 1024px)',
|
|
36
43
|
get isTablet() {
|
|
37
|
-
return
|
|
44
|
+
return matche(this.TABLET);
|
|
38
45
|
},
|
|
39
46
|
|
|
40
47
|
SMALL_PHONE: '(min-width: 319px) and (max-width: 480px) and (max-height: 640px)',
|
|
41
48
|
get isSmallPhone() {
|
|
42
|
-
return
|
|
49
|
+
return matche(this.SMALL_PHONE);
|
|
43
50
|
},
|
|
44
51
|
|
|
45
52
|
WATCH: '(max-width: 319px)',
|
|
46
53
|
get isWatch() {
|
|
47
|
-
return
|
|
54
|
+
return matche(this.WATCH);
|
|
48
55
|
},
|
|
49
56
|
|
|
50
57
|
SHORT: '(min-width: 479px) and (max-height: 320px)',
|
|
51
58
|
get isShort() {
|
|
52
|
-
return
|
|
59
|
+
return matche(this.SHORT);
|
|
53
60
|
},
|
|
54
61
|
|
|
55
62
|
PWA: '(display-mode: standalone)',
|
|
56
63
|
// PWA: '(display-mode: browser)', // debugging
|
|
57
64
|
get isPWA() {
|
|
58
|
-
return
|
|
65
|
+
return matche(this.PWA);
|
|
59
66
|
},
|
|
60
67
|
|
|
61
68
|
MOTION_REDUCE: '(prefers-reduced-motion: reduce)',
|
|
62
69
|
get isMotionReduce() {
|
|
63
|
-
return
|
|
70
|
+
return matche(this.MOTION_REDUCE);
|
|
64
71
|
},
|
|
65
72
|
|
|
66
73
|
DATA_REDUCE: '(prefers-reduced-data: reduce)',
|
|
67
74
|
get isDataReduce() {
|
|
68
|
-
return
|
|
75
|
+
return matche(this.DATA_REDUCE);
|
|
69
76
|
},
|
|
70
77
|
};
|
package/src/lib/decorators.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { defineAttribute, defineCSSState, defineProperty, defineRef, GemElement,
|
|
|
2
2
|
import { Store } from './store';
|
|
3
3
|
import { Sheet, camelToKebabCase, randomStr } from './utils';
|
|
4
4
|
|
|
5
|
-
type GemElementPrototype = GemElement
|
|
5
|
+
type GemElementPrototype = GemElement<any>;
|
|
6
6
|
type GemElementConstructor = typeof GemElement;
|
|
7
7
|
type StaticField = Exclude<keyof GemElementConstructor, 'prototype' | 'rootElement'>;
|
|
8
8
|
type StaticFieldMember = string | Store<unknown> | Sheet<unknown>;
|
package/src/lib/element.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
kebabToCamelCase,
|
|
13
13
|
PropProxyMap,
|
|
14
14
|
removeItems,
|
|
15
|
+
useNativeCSSStyleSheet,
|
|
15
16
|
} from './utils';
|
|
16
17
|
|
|
17
18
|
export { html, svg, render, directive, TemplateResult, SVGTemplateResult } from 'lit-html';
|
|
@@ -52,20 +53,15 @@ function execCallback(fun: any) {
|
|
|
52
53
|
|
|
53
54
|
// global render task pool
|
|
54
55
|
const asyncRenderTaskList = new LinkedList<() => void>();
|
|
55
|
-
const tick = () => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (task) {
|
|
63
|
-
task();
|
|
64
|
-
callback(timestamp);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
56
|
+
const tick = (timeStamp = performance.now()) => {
|
|
57
|
+
if (performance.now() > timeStamp + 16) return requestAnimationFrame(tick);
|
|
58
|
+
const task = asyncRenderTaskList.get();
|
|
59
|
+
if (task) {
|
|
60
|
+
task();
|
|
61
|
+
tick(timeStamp);
|
|
62
|
+
}
|
|
67
63
|
};
|
|
68
|
-
asyncRenderTaskList.addEventListener('start', tick);
|
|
64
|
+
asyncRenderTaskList.addEventListener('start', () => addMicrotask(tick));
|
|
69
65
|
|
|
70
66
|
type GetDepFun<T> = () => T;
|
|
71
67
|
type EffectCallback<T> = (depValues: T, oldDepValues?: T) => any;
|
|
@@ -80,7 +76,7 @@ type EffectItem<T> = {
|
|
|
80
76
|
const initSymbol = Symbol('init');
|
|
81
77
|
const updateSymbol = Symbol('update');
|
|
82
78
|
|
|
83
|
-
interface GemElementOptions {
|
|
79
|
+
export interface GemElementOptions {
|
|
84
80
|
isLight?: boolean;
|
|
85
81
|
isAsync?: boolean;
|
|
86
82
|
delegatesFocus?: boolean;
|
|
@@ -153,11 +149,13 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
|
|
|
153
149
|
if (!this.#internals) {
|
|
154
150
|
const getCustomStateSet = () => {
|
|
155
151
|
// https://wicg.github.io/custom-state-pseudo-class/
|
|
156
|
-
const
|
|
152
|
+
const getV = (v: string) => v.replace('--', '');
|
|
157
153
|
return {
|
|
158
|
-
has: (v) =>
|
|
159
|
-
add: (v) =>
|
|
160
|
-
|
|
154
|
+
has: (v) => getV(v) in this.dataset,
|
|
155
|
+
add: (v) => {
|
|
156
|
+
this.dataset[getV(v)] = '';
|
|
157
|
+
},
|
|
158
|
+
delete: (v) => delete this.dataset[getV(v)],
|
|
161
159
|
} as CustomStateSet;
|
|
162
160
|
};
|
|
163
161
|
if (!this.attachInternals) {
|
|
@@ -197,7 +195,7 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
|
|
|
197
195
|
list?.forEach((effectItem) => {
|
|
198
196
|
const { callback, getDep, values, preCallback } = effectItem;
|
|
199
197
|
const newValues = getDep?.();
|
|
200
|
-
if (!getDep || isArrayChange(values, newValues)) {
|
|
198
|
+
if (!getDep || !values || isArrayChange(values, newValues)) {
|
|
201
199
|
execCallback(preCallback);
|
|
202
200
|
effectItem.preCallback = callback(newValues, values);
|
|
203
201
|
effectItem.values = newValues;
|
|
@@ -234,15 +232,17 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
|
|
|
234
232
|
getDep?: T extends any[] ? () => [...T] : undefined,
|
|
235
233
|
) => {
|
|
236
234
|
if (!this.#effectList) this.#effectList = [];
|
|
237
|
-
const values = getDep?.() as T;
|
|
238
235
|
const effectItem: EffectItem<T> = {
|
|
239
236
|
callback,
|
|
240
237
|
getDep,
|
|
241
|
-
values,
|
|
238
|
+
values: undefined,
|
|
242
239
|
initialized: !!this.isConnected,
|
|
243
240
|
};
|
|
244
241
|
// 以挂载时立即执行副作用,未挂载时等挂载后执行
|
|
245
|
-
if (this.isConnected)
|
|
242
|
+
if (this.isConnected) {
|
|
243
|
+
effectItem.values = getDep?.() as T;
|
|
244
|
+
effectItem.preCallback = callback(effectItem.values);
|
|
245
|
+
}
|
|
246
246
|
this.#effectList.push(effectItem);
|
|
247
247
|
};
|
|
248
248
|
|
|
@@ -278,7 +278,8 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
|
|
|
278
278
|
this.#effectList?.forEach((effectItem) => {
|
|
279
279
|
const { callback, getDep, initialized } = effectItem;
|
|
280
280
|
if (!initialized) {
|
|
281
|
-
effectItem.
|
|
281
|
+
effectItem.values = getDep?.();
|
|
282
|
+
effectItem.preCallback = callback(effectItem.values);
|
|
282
283
|
effectItem.initialized = true;
|
|
283
284
|
}
|
|
284
285
|
});
|
|
@@ -296,8 +297,18 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
|
|
|
296
297
|
|
|
297
298
|
#render = () => {
|
|
298
299
|
this.#execMemo();
|
|
299
|
-
|
|
300
|
-
|
|
300
|
+
const styles = useNativeCSSStyleSheet
|
|
301
|
+
? ''
|
|
302
|
+
: html`${this.shadowRoot?.adoptedStyleSheets?.map(
|
|
303
|
+
(e: any) =>
|
|
304
|
+
html`
|
|
305
|
+
<style media=${e.media.mediaText}>
|
|
306
|
+
${e.style}
|
|
307
|
+
</style>
|
|
308
|
+
`,
|
|
309
|
+
)}`;
|
|
310
|
+
if (this.render) return html`${this.render()}${styles}`;
|
|
311
|
+
return this.#renderRoot === this ? undefined : html`<slot></slot>${styles}`;
|
|
301
312
|
};
|
|
302
313
|
|
|
303
314
|
/**@lifecycle */
|
|
@@ -377,14 +388,16 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
|
|
|
377
388
|
}
|
|
378
389
|
};
|
|
379
390
|
|
|
380
|
-
closestElement(
|
|
381
|
-
|
|
382
|
-
|
|
391
|
+
closestElement<K extends keyof HTMLElementTagNameMap>(tag: K): HTMLElementTagNameMap[K] | null;
|
|
392
|
+
closestElement<K extends abstract new (...args: any) => any>(constructor: K): InstanceType<K> | null;
|
|
393
|
+
closestElement<K extends abstract new (...args: any) => any>(constructorOrTag: K | string): Element | null {
|
|
394
|
+
const isConstructor = typeof constructorOrTag === 'function';
|
|
395
|
+
const tagName = typeof constructorOrTag === 'string' && constructorOrTag.toUpperCase();
|
|
383
396
|
const getRootElement = (ele: Element): Element | null => {
|
|
384
397
|
const rootEle = ele.parentElement || (ele.getRootNode() as ShadowRoot).host;
|
|
385
398
|
if (!rootEle) return null;
|
|
386
399
|
if (isConstructor) {
|
|
387
|
-
if (rootEle.constructor ===
|
|
400
|
+
if (rootEle.constructor === constructorOrTag) {
|
|
388
401
|
return rootEle;
|
|
389
402
|
}
|
|
390
403
|
} else if (rootEle.tagName === tagName) {
|
package/src/lib/utils.ts
CHANGED
|
@@ -84,6 +84,7 @@ export class LinkedList<T = any> extends (globalThis.EventTarget || Object) {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// 添加到尾部,已存在时会删除老的项目
|
|
87
|
+
// 如果是添加第一个,start 事件会在添加前触发,避免处理事件重复的逻辑
|
|
87
88
|
add(value: T) {
|
|
88
89
|
if (!this.#lastItem) {
|
|
89
90
|
this.dispatchEvent(new CustomEvent('start'));
|
|
@@ -101,6 +102,7 @@ export class LinkedList<T = any> extends (globalThis.EventTarget || Object) {
|
|
|
101
102
|
this.#map.set(value, item);
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
// 删除这个元素后没有其他元素时立即出发 end 事件
|
|
104
106
|
delete(value: T) {
|
|
105
107
|
const deleteItem = this.#delete(value);
|
|
106
108
|
if (!this.#firstItem) {
|
|
@@ -238,9 +240,22 @@ export interface StyledKeyValuePair {
|
|
|
238
240
|
[key: string]: StyledValueObject;
|
|
239
241
|
}
|
|
240
242
|
|
|
243
|
+
// !!! 目前只有 Chrome/FirefoxNightly 支持
|
|
244
|
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=1520690
|
|
245
|
+
// https://bugs.webkit.org/show_bug.cgi?id=228684
|
|
246
|
+
export let useNativeCSSStyleSheet = true;
|
|
247
|
+
try {
|
|
248
|
+
new (CSSStyleSheet as any)();
|
|
249
|
+
} catch {
|
|
250
|
+
useNativeCSSStyleSheet = false;
|
|
251
|
+
window.CSSStyleSheet = class {
|
|
252
|
+
media = { mediaText: '' };
|
|
253
|
+
style = '';
|
|
254
|
+
replaceSync = (style: string) => (this.style = style);
|
|
255
|
+
} as any;
|
|
256
|
+
}
|
|
257
|
+
|
|
241
258
|
/**
|
|
242
|
-
* !!! 目前只有 Chrome/FirefoxNightly 支持
|
|
243
|
-
* https://bugzilla.mozilla.org/show_bug.cgi?id=1520690
|
|
244
259
|
*
|
|
245
260
|
* 创建 style sheet 用于 `adoptedStyleSheets`,不支持样式更新
|
|
246
261
|
* @param rules string | Record<string, string> 不能动态更新的 css
|
package/src/lib/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Do not modify manually
|
|
2
|
-
export const version = '1.
|
|
2
|
+
export const version = '1.6.0';
|
|
@@ -25,10 +25,11 @@ customElements.define('async-gem-demo', AsyncGemDemo);
|
|
|
25
25
|
describe('异步 gem element 测试', () => {
|
|
26
26
|
it('异步 gem element 更新', async () => {
|
|
27
27
|
const el: AsyncGemDemo = await fixture(html`<async-gem-demo></async-gem-demo>`);
|
|
28
|
+
expect(el.renderCount).to.equal(1);
|
|
28
29
|
updateStore(store, { a: ++store.a });
|
|
29
30
|
el.setState({ a: ++el.state.a });
|
|
30
31
|
await nextFrame();
|
|
31
|
-
expect(el.renderCount).to.equal(
|
|
32
|
+
expect(el.renderCount).to.equal(2);
|
|
32
33
|
await nextFrame();
|
|
33
34
|
expect(el.renderCount).to.equal(2);
|
|
34
35
|
});
|
|
@@ -146,11 +147,15 @@ class EffectGemDemo extends GemElement {
|
|
|
146
147
|
@attribute attr = 'a';
|
|
147
148
|
@property prop = {};
|
|
148
149
|
effectCount = 0;
|
|
150
|
+
compareCount = 0;
|
|
149
151
|
constructor() {
|
|
150
152
|
super();
|
|
151
153
|
this.effect(
|
|
152
154
|
() => this.effectCount++,
|
|
153
|
-
() =>
|
|
155
|
+
() => {
|
|
156
|
+
this.compareCount++;
|
|
157
|
+
return [this.attr, this.prop];
|
|
158
|
+
},
|
|
154
159
|
);
|
|
155
160
|
}
|
|
156
161
|
mounted() {
|
|
@@ -170,6 +175,7 @@ customElements.define('effect-gem-demo', EffectGemDemo);
|
|
|
170
175
|
describe('gem element 副作用', () => {
|
|
171
176
|
it('依赖当前值', async () => {
|
|
172
177
|
const el: EffectGemDemo = await fixture(html`<effect-gem-demo></effect-gem-demo>`);
|
|
178
|
+
expect(el.compareCount).to.equal(1);
|
|
173
179
|
expect(el.effectCount).to.equal(3);
|
|
174
180
|
el.attr = 'b';
|
|
175
181
|
el.prop = {};
|