@mantou/gem 2.1.1 → 2.2.1
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/dist/gem.es.js +2082 -2153
- package/dist/gem.umd.js +25 -199
- package/elements/base/dialog.d.ts +1 -5
- package/elements/base/dialog.d.ts.map +1 -1
- package/elements/base/dialog.js +2 -6
- package/elements/base/dialog.js.map +1 -1
- package/elements/base/gesture.d.ts +6 -15
- package/elements/base/gesture.d.ts.map +1 -1
- package/elements/base/gesture.js +38 -34
- package/elements/base/gesture.js.map +1 -1
- package/elements/base/link.d.ts +1 -17
- package/elements/base/link.d.ts.map +1 -1
- package/elements/base/link.js +12 -37
- package/elements/base/link.js.map +1 -1
- package/elements/base/modal-factory.d.ts +48 -38
- package/elements/base/modal-factory.d.ts.map +1 -1
- package/elements/base/modal-factory.js +14 -14
- package/elements/base/modal-factory.js.map +1 -1
- package/elements/base/reflect.d.ts +1 -5
- package/elements/base/reflect.d.ts.map +1 -1
- package/elements/base/reflect.js +8 -13
- package/elements/base/reflect.js.map +1 -1
- package/elements/base/route.d.ts +17 -17
- package/elements/base/route.d.ts.map +1 -1
- package/elements/base/route.js +15 -27
- package/elements/base/route.js.map +1 -1
- package/elements/base/title.d.ts +1 -6
- package/elements/base/title.d.ts.map +1 -1
- package/elements/base/title.js +3 -8
- package/elements/base/title.js.map +1 -1
- package/elements/base/unsafe.d.ts +1 -6
- package/elements/base/unsafe.d.ts.map +1 -1
- package/elements/base/unsafe.js +3 -9
- package/elements/base/unsafe.js.map +1 -1
- package/elements/base/use.d.ts +1 -4
- package/elements/base/use.d.ts.map +1 -1
- package/elements/base/use.js +4 -11
- package/elements/base/use.js.map +1 -1
- package/elements/link.js +1 -1
- package/elements/link.js.map +1 -1
- package/elements/route.js +1 -1
- package/elements/route.js.map +1 -1
- package/helper/hmr.d.ts +11 -0
- package/helper/hmr.d.ts.map +1 -0
- package/helper/hmr.js +255 -0
- package/helper/hmr.js.map +1 -0
- package/helper/i18n.d.ts +2 -2
- package/helper/i18n.d.ts.map +1 -1
- package/helper/i18n.js +5 -4
- package/helper/i18n.js.map +1 -1
- package/helper/logger.d.ts +1 -1
- package/helper/logger.d.ts.map +1 -1
- package/helper/logger.js +8 -5
- package/helper/logger.js.map +1 -1
- package/helper/mediaquery.js +1 -1
- package/helper/mediaquery.js.map +1 -1
- package/helper/ssr-shim.d.ts.map +1 -1
- package/helper/ssr-shim.js +2 -0
- package/helper/ssr-shim.js.map +1 -1
- package/helper/theme.d.ts +4 -5
- package/helper/theme.d.ts.map +1 -1
- package/helper/theme.js +3 -3
- package/helper/theme.js.map +1 -1
- package/index.d.ts +1 -3
- package/index.d.ts.map +1 -1
- package/index.js +1 -4
- package/index.js.map +1 -1
- package/lib/decorators.d.ts +9 -16
- package/lib/decorators.d.ts.map +1 -1
- package/lib/decorators.js +84 -71
- package/lib/decorators.js.map +1 -1
- package/lib/directive.d.ts +65 -0
- package/lib/directive.d.ts.map +1 -0
- package/lib/directive.js +58 -0
- package/lib/directive.js.map +1 -0
- package/lib/element.d.ts +10 -153
- package/lib/element.d.ts.map +1 -1
- package/lib/element.js +19 -480
- package/lib/element.js.map +1 -1
- package/lib/history.d.ts +67 -9
- package/lib/history.d.ts.map +1 -1
- package/lib/history.js +12 -12
- package/lib/history.js.map +1 -1
- package/lib/lit-html.d.ts +232 -0
- package/lib/lit-html.d.ts.map +1 -0
- package/lib/lit-html.js +987 -0
- package/lib/lit-html.js.map +1 -0
- package/lib/reactive.d.ts +123 -0
- package/lib/reactive.d.ts.map +1 -0
- package/lib/reactive.js +478 -0
- package/lib/reactive.js.map +1 -0
- package/lib/repeat.d.ts +126 -0
- package/lib/repeat.d.ts.map +1 -0
- package/lib/repeat.js +533 -0
- package/lib/repeat.js.map +1 -0
- package/lib/store.d.ts +13 -2
- package/lib/store.d.ts.map +1 -1
- package/lib/store.js +5 -4
- package/lib/store.js.map +1 -1
- package/lib/utils.d.ts +24 -15
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +25 -30
- package/lib/utils.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +8 -9
- package/src/dist.ts +6 -8
- package/src/elements/base/dialog.ts +2 -6
- package/src/elements/base/gesture.ts +35 -36
- package/src/elements/base/link.ts +20 -46
- package/src/elements/base/modal-factory.ts +14 -14
- package/src/elements/base/reflect.ts +2 -6
- package/src/elements/base/route.ts +22 -33
- package/src/elements/base/title.ts +4 -9
- package/src/elements/base/unsafe.ts +4 -9
- package/src/elements/base/use.ts +4 -11
- package/src/elements/link.ts +1 -1
- package/src/elements/route.ts +1 -1
- package/src/helper/hmr.ts +305 -0
- package/src/helper/i18n.ts +7 -7
- package/src/helper/logger.ts +9 -5
- package/src/helper/mediaquery.ts +1 -1
- package/src/helper/ssr-shim.ts +3 -0
- package/src/helper/theme.ts +6 -6
- package/src/index.ts +1 -5
- package/src/lib/decorators.ts +101 -100
- package/src/lib/directive.ts +137 -0
- package/src/lib/element.ts +26 -614
- package/src/lib/history.ts +14 -15
- package/src/lib/lit-html.ts +1269 -0
- package/src/lib/reactive.ts +596 -0
- package/src/lib/repeat.ts +580 -0
- package/src/lib/store.ts +5 -4
- package/src/lib/utils.ts +40 -46
- package/src/lib/version.ts +1 -1
- package/src/test/elements/link.test.ts +2 -3
- package/src/test/elements/reflect.test.ts +13 -3
- package/src/test/elements/title.test.ts +2 -3
- package/src/test/gem-element/advance.test.ts +22 -14
- package/src/test/gem-element/basic.test.ts +23 -11
- package/src/test/gem-element/decorators.test.ts +14 -17
- package/src/test/gem-element/multi.test.ts +20 -11
- package/src/test/history.test.ts +1 -2
- package/src/test/store.test.ts +3 -4
- package/src/test/utils.test.ts +12 -14
- package/src/test/utils.ts +22 -0
- package/lib/directives.d.ts +0 -4
- package/lib/directives.d.ts.map +0 -1
- package/lib/directives.js +0 -5
- package/lib/directives.js.map +0 -1
- package/src/lib/directives.ts +0 -6
package/src/lib/utils.ts
CHANGED
|
@@ -1,24 +1,45 @@
|
|
|
1
|
-
const { assign,
|
|
1
|
+
const { assign, fromEntries, entries, keys } = Object;
|
|
2
2
|
|
|
3
3
|
const microtaskSet = new Set<() => void>();
|
|
4
|
-
export function addMicrotask(func: () => void) {
|
|
4
|
+
export function addMicrotask(func: () => void, isNodeForceMicrotask?: boolean) {
|
|
5
5
|
if (microtaskSet.has(func)) return;
|
|
6
|
-
|
|
6
|
+
const next = () => {
|
|
7
7
|
microtaskSet.delete(func);
|
|
8
8
|
func();
|
|
9
|
-
}
|
|
9
|
+
};
|
|
10
|
+
if (isNodeForceMicrotask) {
|
|
11
|
+
process.nextTick(next);
|
|
12
|
+
} else {
|
|
13
|
+
Promise.resolve().then(next);
|
|
14
|
+
}
|
|
10
15
|
microtaskSet.add(func);
|
|
11
16
|
}
|
|
12
17
|
|
|
18
|
+
type OverrideFn = {
|
|
19
|
+
name: never;
|
|
20
|
+
apply: never;
|
|
21
|
+
call: never;
|
|
22
|
+
bind: never;
|
|
23
|
+
toString: never;
|
|
24
|
+
prototype: never;
|
|
25
|
+
length: never;
|
|
26
|
+
arguments: never;
|
|
27
|
+
caller: never;
|
|
28
|
+
[Symbol.hasInstance]: never;
|
|
29
|
+
[Symbol.metadata]: never;
|
|
30
|
+
};
|
|
31
|
+
|
|
13
32
|
// 注意 typeof state === 'function' 但是没有 Function 的方法和属性
|
|
14
33
|
export function createUpdater<T, Fn = (payload?: Partial<T>) => any>(initState: T, fn: Fn) {
|
|
15
34
|
const state: any = fn;
|
|
16
|
-
|
|
35
|
+
// https://github.com/vitejs/vite/issues/18540 现在覆盖 call 也一样会报错
|
|
36
|
+
// setPrototypeOf(state, null);
|
|
17
37
|
delete state.name;
|
|
18
38
|
delete state.length;
|
|
19
39
|
assign(state, initState);
|
|
20
|
-
//
|
|
21
|
-
|
|
40
|
+
// ts 不允许直接 Omit 掉 Fn 上的属性
|
|
41
|
+
// 只能利用 ts plugin 移除多余的自动完成项
|
|
42
|
+
return state as Fn & Omit<OverrideFn, keyof T> & T;
|
|
22
43
|
}
|
|
23
44
|
|
|
24
45
|
// 不编码 hash 用于比较
|
|
@@ -106,8 +127,10 @@ export class LinkedList<T = any> extends EventTarget {
|
|
|
106
127
|
return this.#map.get(value);
|
|
107
128
|
}
|
|
108
129
|
|
|
109
|
-
|
|
110
|
-
|
|
130
|
+
/**
|
|
131
|
+
* 添加到尾部,已存在时会删除老的项目
|
|
132
|
+
* 如果是添加第一个,start 事件会在添加前触发,避免处理事件重复的逻辑
|
|
133
|
+
*/
|
|
111
134
|
add(value: T) {
|
|
112
135
|
if (!this.#lastItem) {
|
|
113
136
|
this.dispatchEvent(new CustomEvent('start'));
|
|
@@ -125,7 +148,7 @@ export class LinkedList<T = any> extends EventTarget {
|
|
|
125
148
|
this.#map.set(value, item);
|
|
126
149
|
}
|
|
127
150
|
|
|
128
|
-
|
|
151
|
+
/** 删除这个元素后没有其他元素时立即出发 end 事件 */
|
|
129
152
|
delete(value: T) {
|
|
130
153
|
const deleteItem = this.#delete(value);
|
|
131
154
|
if (!this.#firstItem) {
|
|
@@ -134,8 +157,7 @@ export class LinkedList<T = any> extends EventTarget {
|
|
|
134
157
|
return deleteItem;
|
|
135
158
|
}
|
|
136
159
|
|
|
137
|
-
|
|
138
|
-
// 会从链表删除
|
|
160
|
+
/** 获取头部元素,会从链表删除 */
|
|
139
161
|
get(): T | undefined {
|
|
140
162
|
const firstItem = this.#firstItem;
|
|
141
163
|
if (!firstItem) return;
|
|
@@ -156,10 +178,6 @@ export class PropProxyMap<T extends NonPrimitive, V = unknown> extends WeakMap<T
|
|
|
156
178
|
}
|
|
157
179
|
|
|
158
180
|
export class QueryString extends URLSearchParams {
|
|
159
|
-
constructor(param?: any) {
|
|
160
|
-
super(param);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
181
|
// support `{ key: ObjectValue }`
|
|
164
182
|
concat(param: any) {
|
|
165
183
|
let query: any;
|
|
@@ -223,8 +241,8 @@ export function raw(arr: TemplateStringsArray, ...args: any[]) {
|
|
|
223
241
|
return arr.reduce((prev, current, index) => prev + (args[index - 1] ?? '') + current);
|
|
224
242
|
}
|
|
225
243
|
|
|
226
|
-
//
|
|
227
|
-
export const
|
|
244
|
+
// 在 html 中引用 class 时使用,仅提供高亮功能
|
|
245
|
+
export const styled = raw;
|
|
228
246
|
|
|
229
247
|
export function randomStr(len = 5): string {
|
|
230
248
|
const str = Math.random()
|
|
@@ -234,20 +252,8 @@ export function randomStr(len = 5): string {
|
|
|
234
252
|
return str;
|
|
235
253
|
}
|
|
236
254
|
|
|
237
|
-
// 写 css 文本,在 CSSStyleSheet 中使用,使用 styed-components 高亮
|
|
238
|
-
//
|
|
239
|
-
// createCSSSheet({
|
|
240
|
-
// red: styled.class`
|
|
241
|
-
// background: red;
|
|
242
|
-
// &:hover {
|
|
243
|
-
// background: blue;
|
|
244
|
-
// }
|
|
245
|
-
// `,
|
|
246
|
-
// });
|
|
247
|
-
export const styled = { class: raw };
|
|
248
|
-
|
|
249
255
|
export function camelToKebabCase(str: string) {
|
|
250
|
-
return str.replace(/[A-Z]/g,
|
|
256
|
+
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
export function kebabToCamelCase(str: string) {
|
|
@@ -280,25 +286,18 @@ export function isArrayChange(newValues: any[], oldValues: any[]) {
|
|
|
280
286
|
export function objectMapToString<T = any>(
|
|
281
287
|
object: Record<string, T>,
|
|
282
288
|
separate: string,
|
|
283
|
-
|
|
289
|
+
toStr: (key: string, value: T) => string,
|
|
284
290
|
) {
|
|
285
291
|
let result = separate;
|
|
286
292
|
for (const key in object) {
|
|
287
|
-
const s =
|
|
293
|
+
const s = toStr(key, object[key]);
|
|
288
294
|
result += s ? s + separate : '';
|
|
289
295
|
}
|
|
290
296
|
return result;
|
|
291
297
|
}
|
|
292
298
|
|
|
293
299
|
// Wait: Typescript lib dom CSSStyleDeclaration anchor position
|
|
294
|
-
type StyleProp =
|
|
295
|
-
| keyof CSSStyleDeclaration
|
|
296
|
-
| `--${string}`
|
|
297
|
-
| 'scrollbarWidth'
|
|
298
|
-
| 'scrollbarColor'
|
|
299
|
-
| 'positionAnchor'
|
|
300
|
-
| 'anchorDefault'
|
|
301
|
-
| 'anchorName';
|
|
300
|
+
type StyleProp = keyof CSSStyleDeclaration | `--${string}` | 'positionAnchor' | 'anchorDefault' | 'anchorName';
|
|
302
301
|
|
|
303
302
|
export type StyleObject = Partial<Record<StyleProp, string | number | false | undefined | null>>;
|
|
304
303
|
|
|
@@ -321,8 +320,3 @@ export function exportPartsMap(object: Record<string, string | boolean | undefin
|
|
|
321
320
|
value === true || key === value ? key : value ? `${key}:${value}` : '',
|
|
322
321
|
);
|
|
323
322
|
}
|
|
324
|
-
|
|
325
|
-
declare global {
|
|
326
|
-
interface PropertyIndexedKeyframes extends StyleObject {}
|
|
327
|
-
interface Keyframe extends StyleObject {}
|
|
328
|
-
}
|
package/src/lib/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.
|
|
1
|
+
export const version = '2.2.1';
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { fixture, expect } from '@open-wc/testing';
|
|
2
|
-
|
|
3
|
-
import { html } from '../../lib/element';
|
|
4
1
|
import type { GemActiveLinkElement } from '../../elements/link';
|
|
2
|
+
import { html } from '../../lib/element';
|
|
3
|
+
import { expect, fixture } from '../utils';
|
|
5
4
|
|
|
6
5
|
import '../../elements/link';
|
|
7
6
|
|
|
@@ -1,16 +1,25 @@
|
|
|
1
|
-
import { fixture, expect, nextFrame } from '@open-wc/testing';
|
|
2
|
-
|
|
3
|
-
import { html } from '../../lib/element';
|
|
4
1
|
import type { GemReflectElement } from '../../elements/reflect';
|
|
2
|
+
import { adoptedStyle, customElement } from '../../lib/decorators';
|
|
3
|
+
import { css, GemElement, html } from '../../lib/element';
|
|
4
|
+
import { expect, fixture, nextFrame } from '../utils';
|
|
5
5
|
|
|
6
6
|
import '../../elements/reflect';
|
|
7
7
|
|
|
8
|
+
@adoptedStyle(css`
|
|
9
|
+
:scope {
|
|
10
|
+
color: rgb(255, 0, 0);
|
|
11
|
+
}
|
|
12
|
+
`)
|
|
13
|
+
@customElement('light-dom')
|
|
14
|
+
export class Children extends GemElement {}
|
|
15
|
+
|
|
8
16
|
describe('GemReflectElement', () => {
|
|
9
17
|
it('basic', async () => {
|
|
10
18
|
const reflect: GemReflectElement = await fixture(html`
|
|
11
19
|
<gem-reflect>
|
|
12
20
|
<div id="one"></div>
|
|
13
21
|
<div id="two"></div>
|
|
22
|
+
<light-dom></light-dom>
|
|
14
23
|
</gem-reflect>
|
|
15
24
|
`);
|
|
16
25
|
const div = document.head.querySelector('#one');
|
|
@@ -20,6 +29,7 @@ describe('GemReflectElement', () => {
|
|
|
20
29
|
reflect.target = document.body;
|
|
21
30
|
await nextFrame();
|
|
22
31
|
expect(document.body.querySelector('#one')).to.equal(div);
|
|
32
|
+
expect(getComputedStyle(document.body.querySelector('light-dom')!).color).to.equal('rgb(255, 0, 0)');
|
|
23
33
|
expect(div?.nextSibling).to.equal(comment);
|
|
24
34
|
reflect.remove();
|
|
25
35
|
expect(!!document.querySelector('#one')).to.equal(false);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { fixture, expect, nextFrame } from '@open-wc/testing';
|
|
2
|
-
|
|
3
|
-
import { html } from '../../lib/element';
|
|
4
1
|
import type { GemTitleElement } from '../../elements/title';
|
|
2
|
+
import { html } from '../../lib/element';
|
|
3
|
+
import { expect, fixture, nextFrame } from '../utils';
|
|
5
4
|
|
|
6
5
|
import '../../elements/title';
|
|
7
6
|
|
|
@@ -6,23 +6,22 @@
|
|
|
6
6
|
* - 派生元素(类扩展)
|
|
7
7
|
* - 无渲染内容 Gem 元素
|
|
8
8
|
*/
|
|
9
|
-
import { fixture, expect, nextFrame } from '@open-wc/testing';
|
|
10
9
|
|
|
11
|
-
import type { Metadata } from '../../lib/element';
|
|
12
|
-
import { createCSSSheet, createState, GemElement, html, createRef } from '../../lib/element';
|
|
13
|
-
import { createStore } from '../../lib/store';
|
|
14
10
|
import {
|
|
11
|
+
adoptedStyle,
|
|
12
|
+
async,
|
|
15
13
|
attribute,
|
|
16
|
-
|
|
14
|
+
connectStore,
|
|
17
15
|
customElement,
|
|
18
16
|
emitter,
|
|
19
|
-
adoptedStyle,
|
|
20
|
-
connectStore,
|
|
21
|
-
async,
|
|
22
|
-
shadow,
|
|
23
17
|
mounted,
|
|
18
|
+
property,
|
|
19
|
+
shadow,
|
|
24
20
|
} from '../../lib/decorators';
|
|
25
|
-
import {
|
|
21
|
+
import type { Metadata } from '../../lib/element';
|
|
22
|
+
import { createRef, createState, css, GemElement, html } from '../../lib/element';
|
|
23
|
+
import { createStore } from '../../lib/store';
|
|
24
|
+
import { expect, fixture, nextFrame } from '../utils';
|
|
26
25
|
|
|
27
26
|
const store = createStore({
|
|
28
27
|
a: 1,
|
|
@@ -54,11 +53,11 @@ describe('异步 gem element 测试', () => {
|
|
|
54
53
|
});
|
|
55
54
|
});
|
|
56
55
|
|
|
57
|
-
const lightStyle =
|
|
56
|
+
const lightStyle = css`
|
|
58
57
|
div {
|
|
59
58
|
font-size: 18.1px;
|
|
60
59
|
}
|
|
61
|
-
|
|
60
|
+
`;
|
|
62
61
|
|
|
63
62
|
@customElement('light-gem-demo')
|
|
64
63
|
@adoptedStyle(lightStyle)
|
|
@@ -100,7 +99,7 @@ class LifecycleGemElement extends GemElement {
|
|
|
100
99
|
this.appTitle2 = appTitle2 ?? this.appTitle2;
|
|
101
100
|
this.effect(
|
|
102
101
|
() => {
|
|
103
|
-
this.refInConstructor = this.divRef.
|
|
102
|
+
this.refInConstructor = this.divRef.value;
|
|
104
103
|
},
|
|
105
104
|
() => [],
|
|
106
105
|
);
|
|
@@ -118,7 +117,7 @@ class LifecycleGemElement extends GemElement {
|
|
|
118
117
|
|
|
119
118
|
render() {
|
|
120
119
|
this.renderCount++;
|
|
121
|
-
return html`<div
|
|
120
|
+
return html`<div ${this.divRef}></div>`;
|
|
122
121
|
}
|
|
123
122
|
}
|
|
124
123
|
describe('gem element 生命周期', () => {
|
|
@@ -304,12 +303,20 @@ class InheritGem extends I {
|
|
|
304
303
|
@attribute appTitle = '1';
|
|
305
304
|
@attribute appTitle2 = '2';
|
|
306
305
|
}
|
|
306
|
+
|
|
307
|
+
@customElement('inherit-gem1')
|
|
308
|
+
class InheritGem1 extends I {}
|
|
309
|
+
|
|
307
310
|
describe('gem element 继承', () => {
|
|
308
311
|
it('静态字段继承', async () => {
|
|
309
312
|
new I();
|
|
310
313
|
new InheritGem(); // 触发装饰器自定义初始化函数
|
|
311
314
|
const metadata: Metadata = Reflect.get(InheritGem, Symbol.metadata);
|
|
312
315
|
expect(metadata.observedAttributes).to.eql(['app-title', 'app-title2']);
|
|
316
|
+
|
|
317
|
+
new InheritGem1(); // 触发装饰器自定义初始化函数
|
|
318
|
+
const metadata1: Metadata = Reflect.get(InheritGem1, Symbol.metadata);
|
|
319
|
+
expect(metadata1.observedAttributes).to.eql(['app-title']);
|
|
313
320
|
});
|
|
314
321
|
it('attr/prop/emitter 继承', async () => {
|
|
315
322
|
const name = window.name;
|
|
@@ -333,6 +340,7 @@ describe('gem element 继承', () => {
|
|
|
333
340
|
window.name += '2';
|
|
334
341
|
});
|
|
335
342
|
el.sayHi();
|
|
343
|
+
await Promise.resolve();
|
|
336
344
|
expect(window.name).to.equal(name + '21');
|
|
337
345
|
});
|
|
338
346
|
});
|
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
import { fixture, expect, nextFrame } from '@open-wc/testing';
|
|
2
|
-
|
|
3
|
-
import { createCSSSheet, createState, GemElement, html } from '../../lib/element';
|
|
4
|
-
import { createStore } from '../../lib/store';
|
|
5
|
-
import { css } from '../../lib/utils';
|
|
6
1
|
import {
|
|
7
2
|
adoptedStyle,
|
|
8
3
|
attribute,
|
|
9
4
|
boolattribute,
|
|
10
5
|
connectStore,
|
|
11
6
|
customElement,
|
|
7
|
+
fallback,
|
|
12
8
|
numattribute,
|
|
13
9
|
property,
|
|
14
10
|
shadow,
|
|
15
11
|
} from '../../lib/decorators';
|
|
12
|
+
import { createState, css, GemElement, html } from '../../lib/element';
|
|
13
|
+
import { createStore } from '../../lib/store';
|
|
14
|
+
import { expect, fixture, nextFrame } from '../utils';
|
|
16
15
|
|
|
17
16
|
const store = createStore({
|
|
18
17
|
a: 1,
|
|
19
18
|
});
|
|
20
19
|
|
|
21
|
-
const styles =
|
|
20
|
+
const styles = css`
|
|
22
21
|
:host {
|
|
23
22
|
background: rgb(255, 0, 0);
|
|
24
23
|
}
|
|
25
|
-
|
|
24
|
+
`;
|
|
26
25
|
|
|
27
26
|
@connectStore(store)
|
|
28
27
|
@adoptedStyle(styles)
|
|
@@ -40,11 +39,15 @@ class GemDemo extends GemElement {
|
|
|
40
39
|
renderCount = 0;
|
|
41
40
|
|
|
42
41
|
render() {
|
|
42
|
+
if (this.attr === 'error') throw new Error();
|
|
43
43
|
const { attr, disabled, count, prop } = this;
|
|
44
44
|
const { value } = this.#state;
|
|
45
45
|
this.renderCount++;
|
|
46
46
|
return html`attr: ${attr}, disabled: ${disabled}, count: ${count}, prop: ${prop.value}, state: ${value}`;
|
|
47
47
|
}
|
|
48
|
+
|
|
49
|
+
@fallback()
|
|
50
|
+
#error = () => html`Error`;
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
describe('基本 gem element 测试', () => {
|
|
@@ -68,12 +71,14 @@ describe('基本 gem element 测试', () => {
|
|
|
68
71
|
});
|
|
69
72
|
it('渲染 gem element', async () => {
|
|
70
73
|
const el: GemDemo = await fixture(html`<gem-demo attr="attr" .prop=${{ value: 'prop' }}></gem-demo>`);
|
|
71
|
-
expect(el).
|
|
74
|
+
expect(el.shadowRoot?.textContent).to.equal('attr: attr, disabled: false, count: 0, prop: prop, state: ');
|
|
72
75
|
await Promise.resolve();
|
|
73
76
|
expect(el.renderCount).to.equal(1);
|
|
74
77
|
el.update();
|
|
75
78
|
await Promise.resolve();
|
|
76
79
|
expect(el.renderCount).to.equal(2);
|
|
80
|
+
const errEl: GemDemo = await fixture(html`<gem-demo attr="error"></gem-demo>`);
|
|
81
|
+
expect(errEl.shadowRoot?.textContent).to.equal('Error');
|
|
77
82
|
});
|
|
78
83
|
it('读取 attr', async () => {
|
|
79
84
|
const el: GemDemo = await fixture(html`
|
|
@@ -102,7 +107,7 @@ describe('基本 gem element 测试', () => {
|
|
|
102
107
|
expect(el.attr).to.equal('value');
|
|
103
108
|
expect(el.disabled).to.equal(true);
|
|
104
109
|
expect(el.count).to.equal(2);
|
|
105
|
-
expect(el).
|
|
110
|
+
expect(el.shadowRoot?.textContent).to.equal('attr: value, disabled: true, count: 2, prop: , state: ');
|
|
106
111
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
107
112
|
// @ts-ignore
|
|
108
113
|
el.attr = null;
|
|
@@ -124,7 +129,14 @@ describe('基本 gem element 测试', () => {
|
|
|
124
129
|
await Promise.resolve();
|
|
125
130
|
expect(el.renderCount).to.equal(2);
|
|
126
131
|
expect(el.prop).to.deep.equal({ value: 'value' });
|
|
127
|
-
expect(el).
|
|
132
|
+
expect(el.shadowRoot?.textContent).to.equal('attr: , disabled: false, count: 0, prop: value, state: ');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('只能在 initEffect 前修改 state', async () => {
|
|
136
|
+
const syncUpdateEle = new GemDemo();
|
|
137
|
+
expect(() => syncUpdateEle.internals.stateList[0]()).to.not.throw();
|
|
138
|
+
document.body.append(syncUpdateEle);
|
|
139
|
+
expect(() => syncUpdateEle.internals.stateList[0]()).to.throw();
|
|
128
140
|
});
|
|
129
141
|
|
|
130
142
|
it('修改 state', async () => {
|
|
@@ -136,7 +148,7 @@ describe('基本 gem element 测试', () => {
|
|
|
136
148
|
await Promise.resolve();
|
|
137
149
|
expect(el.renderCount).to.equal(2);
|
|
138
150
|
expect({ ...el.internals.stateList[0] }).to.deep.equal({ value: 'state' });
|
|
139
|
-
expect(el).
|
|
151
|
+
expect(el.shadowRoot?.textContent).to.equal('attr: , disabled: false, count: 0, prop: , state: state');
|
|
140
152
|
});
|
|
141
153
|
|
|
142
154
|
it('更新 store', async () => {
|
|
@@ -1,34 +1,32 @@
|
|
|
1
|
-
import { fixture, expect } from '@open-wc/testing';
|
|
2
|
-
|
|
3
|
-
import type { Metadata } from '../../lib/element';
|
|
4
|
-
import { createCSSSheet, GemElement, html, createRef } from '../../lib/element';
|
|
5
|
-
import { createStore } from '../../lib/store';
|
|
6
|
-
import { css } from '../../lib/utils';
|
|
7
1
|
import type { Emitter } from '../../lib/decorators';
|
|
8
2
|
import {
|
|
3
|
+
adoptedStyle,
|
|
9
4
|
attribute,
|
|
10
|
-
|
|
11
|
-
customElement,
|
|
5
|
+
boolattribute,
|
|
12
6
|
connectStore,
|
|
13
|
-
|
|
7
|
+
customElement,
|
|
14
8
|
emitter,
|
|
15
|
-
boolattribute,
|
|
16
9
|
numattribute,
|
|
17
10
|
part,
|
|
11
|
+
property,
|
|
12
|
+
shadow,
|
|
18
13
|
slot,
|
|
19
14
|
state,
|
|
20
|
-
shadow,
|
|
21
15
|
} from '../../lib/decorators';
|
|
16
|
+
import type { Metadata } from '../../lib/element';
|
|
17
|
+
import { css, GemElement, html } from '../../lib/element';
|
|
18
|
+
import { createStore } from '../../lib/store';
|
|
19
|
+
import { expect, fixture } from '../utils';
|
|
22
20
|
|
|
23
21
|
const store = createStore({
|
|
24
22
|
a: 1,
|
|
25
23
|
});
|
|
26
24
|
|
|
27
|
-
const styles =
|
|
25
|
+
const styles = css`
|
|
28
26
|
:host {
|
|
29
27
|
background: rgb(255, 0, 0);
|
|
30
28
|
}
|
|
31
|
-
|
|
29
|
+
`;
|
|
32
30
|
|
|
33
31
|
@connectStore(store)
|
|
34
32
|
@adoptedStyle(styles)
|
|
@@ -47,7 +45,6 @@ class DecoratorGemElement extends GemElement {
|
|
|
47
45
|
@state openState: boolean;
|
|
48
46
|
@part headerPart: string;
|
|
49
47
|
@slot bodySlot: string;
|
|
50
|
-
inputRef = createRef<HTMLElement>();
|
|
51
48
|
renderCount = 0;
|
|
52
49
|
render() {
|
|
53
50
|
this.renderCount++;
|
|
@@ -84,7 +81,7 @@ describe('装饰器', () => {
|
|
|
84
81
|
store({ a: 1 });
|
|
85
82
|
await Promise.resolve();
|
|
86
83
|
const metadata: Metadata = Reflect.get(DecoratorGemElement, Symbol.metadata);
|
|
87
|
-
expect({ ...metadata.observedStores
|
|
84
|
+
expect({ ...metadata.observedStores?.at(0) }).to.eql({ a: 1 });
|
|
88
85
|
expect(metadata.observedAttributes).to.eql(['rank-attr', 'rank-disabled', 'rank-count']);
|
|
89
86
|
expect(metadata.definedEvents).to.eql(['say-hi']);
|
|
90
87
|
expect(metadata.definedCSSStates).to.eql(['open-state']);
|
|
@@ -99,13 +96,13 @@ describe('装饰器', () => {
|
|
|
99
96
|
expect(el.propData).to.eql({ value: 'prop' });
|
|
100
97
|
expect(el.openState).to.equal(false);
|
|
101
98
|
expect(el.headerPart).to.equal('header-part');
|
|
102
|
-
expect(el.inputRef.ref.startsWith('ref-')).to.equal(true);
|
|
103
99
|
expect(el.bodySlot).to.equal('body-slot');
|
|
104
|
-
expect(el).
|
|
100
|
+
expect(el.shadowRoot?.textContent).to.equal('attr: attr, disabled: true, count: 2, prop: prop');
|
|
105
101
|
store({ a: 3 });
|
|
106
102
|
await Promise.resolve();
|
|
107
103
|
expect(el.renderCount).to.equal(3);
|
|
108
104
|
el.sayHi(2);
|
|
105
|
+
await Promise.resolve();
|
|
109
106
|
expect(el.renderCount).to.equal(3);
|
|
110
107
|
expect(a).to.equal(2);
|
|
111
108
|
});
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import { GemElement, html, createRef } from '../../lib/element';
|
|
1
|
+
import { attribute, customElement, type Emitter, emitter, mounted, property } from '../../lib/decorators';
|
|
2
|
+
import { createRef, createState, GemElement, html } from '../../lib/element';
|
|
3
|
+
import { expect, fixture } from '../utils';
|
|
5
4
|
|
|
6
5
|
@customElement('app-children')
|
|
7
6
|
export class Children extends GemElement {
|
|
8
7
|
@property value?: { value: number };
|
|
9
8
|
@attribute attr: string;
|
|
9
|
+
@emitter sayHi: Emitter<null>;
|
|
10
|
+
|
|
10
11
|
inputRef = createRef<HTMLInputElement>();
|
|
11
12
|
|
|
13
|
+
@mounted()
|
|
14
|
+
#init = () => this.sayHi();
|
|
15
|
+
|
|
12
16
|
render() {
|
|
13
|
-
return html`<input
|
|
17
|
+
return html`<input ${this.inputRef} />`;
|
|
14
18
|
}
|
|
15
19
|
}
|
|
16
20
|
|
|
@@ -18,20 +22,25 @@ export class Children extends GemElement {
|
|
|
18
22
|
export class App extends GemElement {
|
|
19
23
|
childrenRef1 = createRef<Children>();
|
|
20
24
|
childrenRef2 = createRef<Children>();
|
|
25
|
+
|
|
26
|
+
// 还未 mounted, 不应该发生错误
|
|
27
|
+
#state = createState({});
|
|
28
|
+
#onSayHi = () => this.#state();
|
|
29
|
+
|
|
21
30
|
render() {
|
|
22
31
|
return html`
|
|
23
|
-
<app-children
|
|
24
|
-
<app-children
|
|
32
|
+
<app-children ${this.childrenRef1} .value=${{ value: 1 }} attr="1" @say-hi=${this.#onSayHi}></app-children>
|
|
33
|
+
<app-children ${this.childrenRef2} .value=${{ value: 2 }} attr="2"></app-children>
|
|
25
34
|
`;
|
|
26
35
|
}
|
|
27
36
|
}
|
|
28
37
|
describe('多个 gem element 一起工作', () => {
|
|
29
38
|
it('ref & prop & attr', async () => {
|
|
30
39
|
const el: App = await fixture(html`<app-root></app-root>`);
|
|
31
|
-
const children1 = el.childrenRef1.
|
|
32
|
-
const children2 = el.childrenRef2.
|
|
33
|
-
const input1 = children1.inputRef.
|
|
34
|
-
const input2 = children2.inputRef.
|
|
40
|
+
const children1 = el.childrenRef1.value!;
|
|
41
|
+
const children2 = el.childrenRef2.value!;
|
|
42
|
+
const input1 = children1.inputRef.value!;
|
|
43
|
+
const input2 = children2.inputRef.value!;
|
|
35
44
|
expect(input1 !== input2).to.equal(true);
|
|
36
45
|
expect(children1.value).to.eql({ value: 1 });
|
|
37
46
|
expect(children2.value).to.eql({ value: 2 });
|
package/src/test/history.test.ts
CHANGED
package/src/test/store.test.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { StoreListenerMap, createStore, connect } from '../lib/store';
|
|
1
|
+
import { _StoreListenerMap, connect, createStore } from '../lib/store';
|
|
2
|
+
import { aTimeout, expect } from './utils';
|
|
4
3
|
|
|
5
4
|
describe('store 测试', () => {
|
|
6
5
|
it('create store', () => {
|
|
7
6
|
const origin = { a: 1 };
|
|
8
7
|
const store = createStore(origin);
|
|
9
8
|
expect({ ...store }).to.deep.equal(origin);
|
|
10
|
-
expect(!!
|
|
9
|
+
expect(!!_StoreListenerMap.get(store)).to.equal(true);
|
|
11
10
|
});
|
|
12
11
|
it('update store', async () => {
|
|
13
12
|
const store = createStore({ a: 1 });
|
package/src/test/utils.test.ts
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { createCSSSheet, SheetToken } from '../lib/element';
|
|
1
|
+
import { css, SheetToken } from '../lib/element';
|
|
4
2
|
import {
|
|
3
|
+
absoluteLocation,
|
|
4
|
+
classMap,
|
|
5
|
+
exportPartsMap,
|
|
5
6
|
LinkedList,
|
|
6
7
|
QueryString,
|
|
7
|
-
css,
|
|
8
8
|
raw,
|
|
9
9
|
styled,
|
|
10
10
|
styleMap,
|
|
11
|
-
classMap,
|
|
12
|
-
exportPartsMap,
|
|
13
|
-
absoluteLocation,
|
|
14
11
|
} from '../lib/utils';
|
|
12
|
+
import { expect } from './utils';
|
|
15
13
|
|
|
16
14
|
declare global {
|
|
17
15
|
interface CSSRuleList {
|
|
@@ -78,15 +76,15 @@ describe('utils 测试', () => {
|
|
|
78
76
|
query.setAny('obj', [{ a: 1, b: 2 }]);
|
|
79
77
|
expect(query.getAny('obj')).to.deep.equal({ a: 1, b: 2 });
|
|
80
78
|
expect(query.getAnyAll('obj')).to.deep.equal([{ a: 1, b: 2 }]);
|
|
81
|
-
expect(new QueryString({ a: 1 }).toString()).to.equal('?a=1');
|
|
79
|
+
expect(new QueryString({ a: '1' }).toString()).to.equal('?a=1');
|
|
82
80
|
expect(new QueryString(query).toString()).to.equal(query.toString());
|
|
83
81
|
});
|
|
84
|
-
it('
|
|
85
|
-
const cssSheet =
|
|
82
|
+
it('css', () => {
|
|
83
|
+
const cssSheet = css`
|
|
86
84
|
div {
|
|
87
85
|
background: red;
|
|
88
86
|
}
|
|
89
|
-
|
|
87
|
+
`;
|
|
90
88
|
const rules = cssSheet[SheetToken].getStyle().cssRules;
|
|
91
89
|
expect(rules.item(0).selectorText).to.equal('div');
|
|
92
90
|
expect(rules.item(0).style.background).to.equal('red');
|
|
@@ -101,9 +99,9 @@ describe('utils 测试', () => {
|
|
|
101
99
|
expect(raw`<div>${'str'}</div>`).to.equal('<div>str</div>');
|
|
102
100
|
});
|
|
103
101
|
it('styled', () => {
|
|
104
|
-
const cssSheet =
|
|
105
|
-
$: styled
|
|
106
|
-
scroll: styled
|
|
102
|
+
const cssSheet = css({
|
|
103
|
+
$: styled``,
|
|
104
|
+
scroll: styled`
|
|
107
105
|
background: red;
|
|
108
106
|
&:hover * {
|
|
109
107
|
background: blue;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { assert, expect, should } from 'chai';
|
|
2
|
+
|
|
3
|
+
import type { TemplateResult } from '../lib/element';
|
|
4
|
+
import { render } from '../lib/element';
|
|
5
|
+
|
|
6
|
+
export { expect, should, assert };
|
|
7
|
+
|
|
8
|
+
export function nextFrame() {
|
|
9
|
+
return new Promise((resolve) => requestAnimationFrame(() => resolve(null)));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function aTimeout(ms = 0) {
|
|
13
|
+
return new Promise((resolve) => setTimeout(() => resolve(null), ms));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function fixture(template: TemplateResult) {
|
|
17
|
+
const wrapper = document.createElement('div');
|
|
18
|
+
document.body.appendChild(wrapper);
|
|
19
|
+
render(template, wrapper);
|
|
20
|
+
await nextFrame();
|
|
21
|
+
return wrapper.firstElementChild as any;
|
|
22
|
+
}
|
package/lib/directives.d.ts
DELETED
package/lib/directives.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../src/lib/directives.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAGpD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC"}
|