@mantou/gem 2.0.0-alpha.1 → 2.1.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/dist/gem.es.js +1159 -1166
- package/dist/gem.umd.js +25 -25
- package/elements/base/modal-factory.d.ts +12 -7
- package/elements/base/modal-factory.d.ts.map +1 -1
- package/elements/base/modal-factory.js +3 -3
- package/elements/base/modal-factory.js.map +1 -1
- package/elements/base/route.d.ts +8 -2
- package/elements/base/route.d.ts.map +1 -1
- package/elements/base/route.js +21 -16
- package/elements/base/route.js.map +1 -1
- package/elements/base/title.js +2 -2
- package/elements/base/title.js.map +1 -1
- package/helper/i18n.d.ts.map +1 -1
- package/helper/i18n.js +11 -11
- package/helper/i18n.js.map +1 -1
- package/helper/theme.d.ts +8 -7
- package/helper/theme.d.ts.map +1 -1
- package/helper/theme.js +21 -21
- package/helper/theme.js.map +1 -1
- package/lib/decorators.d.ts +2 -1
- package/lib/decorators.d.ts.map +1 -1
- package/lib/decorators.js +6 -0
- package/lib/decorators.js.map +1 -1
- package/lib/element.d.ts +6 -4
- package/lib/element.d.ts.map +1 -1
- package/lib/element.js +12 -15
- package/lib/element.js.map +1 -1
- package/lib/history.d.ts +20 -8
- package/lib/history.d.ts.map +1 -1
- package/lib/history.js +12 -12
- package/lib/history.js.map +1 -1
- package/lib/store.d.ts +5 -10
- package/lib/store.d.ts.map +1 -1
- package/lib/store.js +7 -22
- package/lib/store.js.map +1 -1
- package/lib/utils.d.ts +1 -0
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +19 -14
- package/lib/utils.js.map +1 -1
- package/package.json +4 -4
- package/src/elements/base/modal-factory.ts +3 -3
- package/src/elements/base/route.ts +7 -9
- package/src/elements/base/title.ts +2 -2
- package/src/helper/i18n.ts +11 -8
- package/src/helper/theme.ts +27 -26
- package/src/lib/decorators.ts +9 -2
- package/src/lib/element.ts +18 -19
- package/src/lib/history.ts +12 -12
- package/src/lib/store.ts +11 -31
- package/src/lib/utils.ts +21 -14
- package/src/test/gem-element/advance.test.ts +2 -2
- package/src/test/gem-element/basic.test.ts +3 -3
- package/src/test/gem-element/decorators.test.ts +4 -4
- package/src/test/store.test.ts +7 -7
- package/src/test/utils.test.ts +1 -1
package/src/lib/store.ts
CHANGED
|
@@ -1,40 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { addMicrotask, GemError } from './utils';
|
|
1
|
+
import { addMicrotask, createUpdater } from './utils';
|
|
3
2
|
|
|
4
|
-
export
|
|
3
|
+
export type Store<T = any> = ReturnType<typeof createUpdater<T>>;
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
export type Store<T> = T & { '': string };
|
|
5
|
+
export const StoreListenerMap = new WeakMap<Store<any>, Set<() => void>>();
|
|
8
6
|
|
|
9
|
-
export function createStore<T
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
StoreListenerMap.set(originStore, new Set<() => void>());
|
|
14
|
-
return originStore as Store<T>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function updateStore<T extends NonPrimitive>(store: Store<T>, value?: Partial<T>) {
|
|
18
|
-
Object.assign(store, value);
|
|
19
|
-
StoreListenerMap.get(store)?.forEach((func) => {
|
|
20
|
-
addMicrotask(func);
|
|
7
|
+
export function createStore<T = any>(originStore: T) {
|
|
8
|
+
const store = createUpdater(originStore, (value?: Partial<T>) => {
|
|
9
|
+
Object.assign(store, value);
|
|
10
|
+
StoreListenerMap.get(store)?.forEach((func) => addMicrotask(func));
|
|
21
11
|
});
|
|
12
|
+
StoreListenerMap.set(store, new Set<() => void>());
|
|
13
|
+
return store;
|
|
22
14
|
}
|
|
23
15
|
|
|
24
|
-
export function
|
|
25
|
-
const store = createStore(originStore);
|
|
26
|
-
return [store, (value?: Partial<T>) => updateStore(store, value)] as const;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function connect<T extends NonPrimitive>(store: Store<T>, func: () => void) {
|
|
16
|
+
export function connect(store: Store<any>, func: () => void) {
|
|
30
17
|
const listeners = StoreListenerMap.get(store);
|
|
31
18
|
listeners?.add(func);
|
|
32
|
-
return () =>
|
|
33
|
-
listeners?.delete(func);
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function disconnect<T extends NonPrimitive>(store: Store<T>, func: () => void) {
|
|
38
|
-
const listeners = StoreListenerMap.get(store);
|
|
39
|
-
listeners?.delete(func);
|
|
19
|
+
return () => listeners?.delete(func);
|
|
40
20
|
}
|
package/src/lib/utils.ts
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
const { assign, setPrototypeOf, fromEntries, entries, keys } = Object;
|
|
2
|
+
|
|
3
|
+
const microtaskSet = new Set<() => void>();
|
|
2
4
|
export function addMicrotask(func: () => void) {
|
|
3
|
-
if (
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
microtaskSet = new Set();
|
|
9
|
-
set.forEach((f) => f());
|
|
10
|
-
});
|
|
11
|
-
}
|
|
12
|
-
microtaskSet.delete(func);
|
|
5
|
+
if (microtaskSet.has(func)) return;
|
|
6
|
+
queueMicrotask(() => {
|
|
7
|
+
microtaskSet.delete(func);
|
|
8
|
+
func();
|
|
9
|
+
});
|
|
13
10
|
microtaskSet.add(func);
|
|
14
11
|
}
|
|
15
12
|
|
|
13
|
+
export function createUpdater<T, Fn = (payload?: Partial<T>) => any>(initState: T, fn: Fn) {
|
|
14
|
+
const state: any = fn;
|
|
15
|
+
setPrototypeOf(state, null);
|
|
16
|
+
delete state.name;
|
|
17
|
+
delete state.length;
|
|
18
|
+
assign(state, initState);
|
|
19
|
+
// TODO: type
|
|
20
|
+
return state as Fn & T;
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
// 不编码 hash 用于比较
|
|
17
24
|
export function absoluteLocation(currentPath = '', relativePath = '') {
|
|
18
25
|
const { pathname, search, hash } = new URL(relativePath, location.origin + currentPath);
|
|
@@ -156,11 +163,11 @@ export class QueryString extends URLSearchParams {
|
|
|
156
163
|
concat(param: any) {
|
|
157
164
|
let query: any;
|
|
158
165
|
if (typeof param === 'string') {
|
|
159
|
-
query =
|
|
166
|
+
query = fromEntries(new URLSearchParams(param).entries());
|
|
160
167
|
} else {
|
|
161
168
|
query = param;
|
|
162
169
|
}
|
|
163
|
-
|
|
170
|
+
entries(query).forEach(([key, value]) => {
|
|
164
171
|
this.append(key, this.#stringify(value));
|
|
165
172
|
});
|
|
166
173
|
}
|
|
@@ -247,7 +254,7 @@ export function kebabToCamelCase(str: string) {
|
|
|
247
254
|
}
|
|
248
255
|
|
|
249
256
|
export function cleanObject<T extends Record<string, unknown>>(o: T) {
|
|
250
|
-
|
|
257
|
+
keys(o).forEach((key: keyof T) => {
|
|
251
258
|
delete o[key];
|
|
252
259
|
});
|
|
253
260
|
return o;
|
|
@@ -10,7 +10,7 @@ import { fixture, expect, nextFrame } from '@open-wc/testing';
|
|
|
10
10
|
|
|
11
11
|
import type { Metadata } from '../../lib/element';
|
|
12
12
|
import { createCSSSheet, createState, GemElement, html, createRef } from '../../lib/element';
|
|
13
|
-
import { createStore
|
|
13
|
+
import { createStore } from '../../lib/store';
|
|
14
14
|
import {
|
|
15
15
|
attribute,
|
|
16
16
|
property,
|
|
@@ -45,7 +45,7 @@ describe('异步 gem element 测试', () => {
|
|
|
45
45
|
it('异步 gem element 更新', async () => {
|
|
46
46
|
const el: AsyncGemDemo = await fixture(html`<async-gem-demo></async-gem-demo>`);
|
|
47
47
|
expect(el.renderCount).to.equal(1);
|
|
48
|
-
|
|
48
|
+
store({ a: ++store.a });
|
|
49
49
|
el.internals.stateList[0]({ a: ++(el.internals.stateList[0] as any).a });
|
|
50
50
|
await nextFrame();
|
|
51
51
|
expect(el.renderCount).to.equal(2);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fixture, expect, nextFrame } from '@open-wc/testing';
|
|
2
2
|
|
|
3
3
|
import { createCSSSheet, createState, GemElement, html } from '../../lib/element';
|
|
4
|
-
import { createStore
|
|
4
|
+
import { createStore } from '../../lib/store';
|
|
5
5
|
import { css } from '../../lib/utils';
|
|
6
6
|
import {
|
|
7
7
|
adoptedStyle,
|
|
@@ -142,8 +142,8 @@ describe('基本 gem element 测试', () => {
|
|
|
142
142
|
it('更新 store', async () => {
|
|
143
143
|
const a = store.a;
|
|
144
144
|
const el: GemDemo = await fixture(html`<gem-demo></gem-demo>`);
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
store({ a: ++store.a });
|
|
146
|
+
store({ a: ++store.a });
|
|
147
147
|
expect(store.a).to.equal(a + 2);
|
|
148
148
|
expect(el.renderCount).to.equal(1);
|
|
149
149
|
await Promise.resolve();
|
|
@@ -2,7 +2,7 @@ import { fixture, expect } from '@open-wc/testing';
|
|
|
2
2
|
|
|
3
3
|
import type { Metadata } from '../../lib/element';
|
|
4
4
|
import { createCSSSheet, GemElement, html, createRef } from '../../lib/element';
|
|
5
|
-
import { createStore
|
|
5
|
+
import { createStore } from '../../lib/store';
|
|
6
6
|
import { css } from '../../lib/utils';
|
|
7
7
|
import type { Emitter } from '../../lib/decorators';
|
|
8
8
|
import {
|
|
@@ -81,10 +81,10 @@ describe('装饰器', () => {
|
|
|
81
81
|
rank-count="2"
|
|
82
82
|
></decorator-gem-demo>
|
|
83
83
|
`);
|
|
84
|
-
|
|
84
|
+
store({ a: 1 });
|
|
85
85
|
await Promise.resolve();
|
|
86
86
|
const metadata: Metadata = Reflect.get(DecoratorGemElement, Symbol.metadata);
|
|
87
|
-
expect(metadata.observedStores).to.eql(
|
|
87
|
+
expect({ ...metadata.observedStores.at(0) }).to.eql({ a: 1 });
|
|
88
88
|
expect(metadata.observedAttributes).to.eql(['rank-attr', 'rank-disabled', 'rank-count']);
|
|
89
89
|
expect(metadata.definedEvents).to.eql(['say-hi']);
|
|
90
90
|
expect(metadata.definedCSSStates).to.eql(['open-state']);
|
|
@@ -102,7 +102,7 @@ describe('装饰器', () => {
|
|
|
102
102
|
expect(el.inputRef.ref.startsWith('ref-')).to.equal(true);
|
|
103
103
|
expect(el.bodySlot).to.equal('body-slot');
|
|
104
104
|
expect(el).shadowDom.to.equal('attr: attr, disabled: true, count: 2, prop: prop');
|
|
105
|
-
|
|
105
|
+
store({ a: 3 });
|
|
106
106
|
await Promise.resolve();
|
|
107
107
|
expect(el.renderCount).to.equal(3);
|
|
108
108
|
el.sayHi(2);
|
package/src/test/store.test.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import { expect, aTimeout } from '@open-wc/testing';
|
|
2
2
|
|
|
3
|
-
import { StoreListenerMap, createStore,
|
|
3
|
+
import { StoreListenerMap, createStore, connect } from '../lib/store';
|
|
4
4
|
|
|
5
5
|
describe('store 测试', () => {
|
|
6
6
|
it('create store', () => {
|
|
7
7
|
const origin = { a: 1 };
|
|
8
8
|
const store = createStore(origin);
|
|
9
|
-
expect(store).to.equal(origin);
|
|
9
|
+
expect({ ...store }).to.deep.equal(origin);
|
|
10
10
|
expect(!!StoreListenerMap.get(store)).to.equal(true);
|
|
11
11
|
});
|
|
12
12
|
it('update store', async () => {
|
|
13
13
|
const store = createStore({ a: 1 });
|
|
14
14
|
let flag = true;
|
|
15
15
|
const update = () => (flag = !flag);
|
|
16
|
-
connect(store, update);
|
|
17
|
-
|
|
16
|
+
const disconnect = connect(store, update);
|
|
17
|
+
store({ a: 1 });
|
|
18
18
|
await aTimeout(0);
|
|
19
19
|
expect(flag).to.equal(false);
|
|
20
|
-
|
|
20
|
+
store();
|
|
21
21
|
await aTimeout(0);
|
|
22
22
|
expect(flag).to.equal(true);
|
|
23
|
-
disconnect(
|
|
24
|
-
|
|
23
|
+
disconnect();
|
|
24
|
+
store({ a: 1 });
|
|
25
25
|
await aTimeout(0);
|
|
26
26
|
expect(flag).to.equal(true);
|
|
27
27
|
});
|
package/src/test/utils.test.ts
CHANGED
|
@@ -112,7 +112,7 @@ describe('utils 测试', () => {
|
|
|
112
112
|
});
|
|
113
113
|
expect(cssSheet.scroll.startsWith('scroll')).to.true;
|
|
114
114
|
const rules = cssSheet[SheetToken].getStyle().cssRules;
|
|
115
|
-
expect(rules.item(0).selectorText).to.equal(':scope, :host');
|
|
115
|
+
expect(rules.item(0).selectorText).to.equal(':where(:scope:not([hidden])), :host(:where(:not([hidden])))');
|
|
116
116
|
expect(rules.item(1).selectorText.startsWith('.scroll')).to.true;
|
|
117
117
|
expect(rules.item(1).style.background).to.equal('red');
|
|
118
118
|
expect(rules.item(1).cssRules.item(0).selectorText).to.equal('&:hover *');
|