@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.
Files changed (151) hide show
  1. package/dist/gem.es.js +2082 -2153
  2. package/dist/gem.umd.js +25 -199
  3. package/elements/base/dialog.d.ts +1 -5
  4. package/elements/base/dialog.d.ts.map +1 -1
  5. package/elements/base/dialog.js +2 -6
  6. package/elements/base/dialog.js.map +1 -1
  7. package/elements/base/gesture.d.ts +6 -15
  8. package/elements/base/gesture.d.ts.map +1 -1
  9. package/elements/base/gesture.js +38 -34
  10. package/elements/base/gesture.js.map +1 -1
  11. package/elements/base/link.d.ts +1 -17
  12. package/elements/base/link.d.ts.map +1 -1
  13. package/elements/base/link.js +12 -37
  14. package/elements/base/link.js.map +1 -1
  15. package/elements/base/modal-factory.d.ts +48 -38
  16. package/elements/base/modal-factory.d.ts.map +1 -1
  17. package/elements/base/modal-factory.js +14 -14
  18. package/elements/base/modal-factory.js.map +1 -1
  19. package/elements/base/reflect.d.ts +1 -5
  20. package/elements/base/reflect.d.ts.map +1 -1
  21. package/elements/base/reflect.js +8 -13
  22. package/elements/base/reflect.js.map +1 -1
  23. package/elements/base/route.d.ts +17 -17
  24. package/elements/base/route.d.ts.map +1 -1
  25. package/elements/base/route.js +15 -27
  26. package/elements/base/route.js.map +1 -1
  27. package/elements/base/title.d.ts +1 -6
  28. package/elements/base/title.d.ts.map +1 -1
  29. package/elements/base/title.js +3 -8
  30. package/elements/base/title.js.map +1 -1
  31. package/elements/base/unsafe.d.ts +1 -6
  32. package/elements/base/unsafe.d.ts.map +1 -1
  33. package/elements/base/unsafe.js +3 -9
  34. package/elements/base/unsafe.js.map +1 -1
  35. package/elements/base/use.d.ts +1 -4
  36. package/elements/base/use.d.ts.map +1 -1
  37. package/elements/base/use.js +4 -11
  38. package/elements/base/use.js.map +1 -1
  39. package/elements/link.js +1 -1
  40. package/elements/link.js.map +1 -1
  41. package/elements/route.js +1 -1
  42. package/elements/route.js.map +1 -1
  43. package/helper/hmr.d.ts +11 -0
  44. package/helper/hmr.d.ts.map +1 -0
  45. package/helper/hmr.js +255 -0
  46. package/helper/hmr.js.map +1 -0
  47. package/helper/i18n.d.ts +2 -2
  48. package/helper/i18n.d.ts.map +1 -1
  49. package/helper/i18n.js +5 -4
  50. package/helper/i18n.js.map +1 -1
  51. package/helper/logger.d.ts +1 -1
  52. package/helper/logger.d.ts.map +1 -1
  53. package/helper/logger.js +8 -5
  54. package/helper/logger.js.map +1 -1
  55. package/helper/mediaquery.js +1 -1
  56. package/helper/mediaquery.js.map +1 -1
  57. package/helper/ssr-shim.d.ts.map +1 -1
  58. package/helper/ssr-shim.js +2 -0
  59. package/helper/ssr-shim.js.map +1 -1
  60. package/helper/theme.d.ts +4 -5
  61. package/helper/theme.d.ts.map +1 -1
  62. package/helper/theme.js +3 -3
  63. package/helper/theme.js.map +1 -1
  64. package/index.d.ts +1 -3
  65. package/index.d.ts.map +1 -1
  66. package/index.js +1 -4
  67. package/index.js.map +1 -1
  68. package/lib/decorators.d.ts +9 -16
  69. package/lib/decorators.d.ts.map +1 -1
  70. package/lib/decorators.js +84 -71
  71. package/lib/decorators.js.map +1 -1
  72. package/lib/directive.d.ts +65 -0
  73. package/lib/directive.d.ts.map +1 -0
  74. package/lib/directive.js +58 -0
  75. package/lib/directive.js.map +1 -0
  76. package/lib/element.d.ts +10 -153
  77. package/lib/element.d.ts.map +1 -1
  78. package/lib/element.js +19 -480
  79. package/lib/element.js.map +1 -1
  80. package/lib/history.d.ts +67 -9
  81. package/lib/history.d.ts.map +1 -1
  82. package/lib/history.js +12 -12
  83. package/lib/history.js.map +1 -1
  84. package/lib/lit-html.d.ts +232 -0
  85. package/lib/lit-html.d.ts.map +1 -0
  86. package/lib/lit-html.js +987 -0
  87. package/lib/lit-html.js.map +1 -0
  88. package/lib/reactive.d.ts +123 -0
  89. package/lib/reactive.d.ts.map +1 -0
  90. package/lib/reactive.js +478 -0
  91. package/lib/reactive.js.map +1 -0
  92. package/lib/repeat.d.ts +126 -0
  93. package/lib/repeat.d.ts.map +1 -0
  94. package/lib/repeat.js +533 -0
  95. package/lib/repeat.js.map +1 -0
  96. package/lib/store.d.ts +13 -2
  97. package/lib/store.d.ts.map +1 -1
  98. package/lib/store.js +5 -4
  99. package/lib/store.js.map +1 -1
  100. package/lib/utils.d.ts +24 -15
  101. package/lib/utils.d.ts.map +1 -1
  102. package/lib/utils.js +25 -30
  103. package/lib/utils.js.map +1 -1
  104. package/lib/version.d.ts +1 -1
  105. package/lib/version.js +1 -1
  106. package/package.json +8 -9
  107. package/src/dist.ts +6 -8
  108. package/src/elements/base/dialog.ts +2 -6
  109. package/src/elements/base/gesture.ts +35 -36
  110. package/src/elements/base/link.ts +20 -46
  111. package/src/elements/base/modal-factory.ts +14 -14
  112. package/src/elements/base/reflect.ts +2 -6
  113. package/src/elements/base/route.ts +22 -33
  114. package/src/elements/base/title.ts +4 -9
  115. package/src/elements/base/unsafe.ts +4 -9
  116. package/src/elements/base/use.ts +4 -11
  117. package/src/elements/link.ts +1 -1
  118. package/src/elements/route.ts +1 -1
  119. package/src/helper/hmr.ts +305 -0
  120. package/src/helper/i18n.ts +7 -7
  121. package/src/helper/logger.ts +9 -5
  122. package/src/helper/mediaquery.ts +1 -1
  123. package/src/helper/ssr-shim.ts +3 -0
  124. package/src/helper/theme.ts +6 -6
  125. package/src/index.ts +1 -5
  126. package/src/lib/decorators.ts +101 -100
  127. package/src/lib/directive.ts +137 -0
  128. package/src/lib/element.ts +26 -614
  129. package/src/lib/history.ts +14 -15
  130. package/src/lib/lit-html.ts +1269 -0
  131. package/src/lib/reactive.ts +596 -0
  132. package/src/lib/repeat.ts +580 -0
  133. package/src/lib/store.ts +5 -4
  134. package/src/lib/utils.ts +40 -46
  135. package/src/lib/version.ts +1 -1
  136. package/src/test/elements/link.test.ts +2 -3
  137. package/src/test/elements/reflect.test.ts +13 -3
  138. package/src/test/elements/title.test.ts +2 -3
  139. package/src/test/gem-element/advance.test.ts +22 -14
  140. package/src/test/gem-element/basic.test.ts +23 -11
  141. package/src/test/gem-element/decorators.test.ts +14 -17
  142. package/src/test/gem-element/multi.test.ts +20 -11
  143. package/src/test/history.test.ts +1 -2
  144. package/src/test/store.test.ts +3 -4
  145. package/src/test/utils.test.ts +12 -14
  146. package/src/test/utils.ts +22 -0
  147. package/lib/directives.d.ts +0 -4
  148. package/lib/directives.d.ts.map +0 -1
  149. package/lib/directives.js +0 -5
  150. package/lib/directives.js.map +0 -1
  151. package/src/lib/directives.ts +0 -6
@@ -1,20 +1,24 @@
1
1
  export class Logger {
2
- _type: string;
2
+ #type: string;
3
+
4
+ get #prefix() {
5
+ return `[${this.#type}]`;
6
+ }
3
7
 
4
8
  constructor(type: string) {
5
- this._type = type;
9
+ this.#type = type;
6
10
  }
7
11
 
8
12
  info = (...args: any[]) => {
9
- console.log(`[${this._type}]:`, ...args);
13
+ console.log(this.#prefix, ...args);
10
14
  };
11
15
 
12
16
  warn = (...args: any[]) => {
13
- console.warn(`[${this._type}]:`, ...args);
17
+ console.warn(this.#prefix, ...args);
14
18
  };
15
19
 
16
20
  error = (...args: any[]) => {
17
- console.error(`[${this._type}]:`, ...args);
21
+ console.error(this.#prefix, ...args);
18
22
  };
19
23
  }
20
24
 
@@ -1,7 +1,7 @@
1
1
  // https://gist.github.com/gokulkrishh/242e68d1ee94ad05f488
2
2
  // https://mediag.com/news/popular-screen-resolutions-designing-for-all/
3
3
 
4
- const match = (query: string) => window.matchMedia(query).matches;
4
+ const match = (query: string) => matchMedia(query).matches;
5
5
 
6
6
  export const mediaQuery = {
7
7
  PRINT: 'print',
@@ -1,3 +1,6 @@
1
+ /// 简单的垫片,让 GemElement 服务端渲染不报错
2
+ /// 渲染时将忽略 GemElement 内容
3
+
1
4
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2
5
  // @ts-nocheck
3
6
  if (typeof window === 'undefined') {
@@ -1,14 +1,14 @@
1
+ import type { GemElement, Sheet } from '../lib/reactive';
2
+ import { css, SheetToken } from '../lib/reactive';
1
3
  import type { Store } from '../lib/store';
2
4
  import { connect, createStore } from '../lib/store';
3
5
  import { camelToKebabCase, createUpdater, randomStr } from '../lib/utils';
4
- import type { GemElement } from '../lib/element';
5
- import { SheetToken, createCSSSheet } from '../lib/element';
6
6
 
7
7
  export type Theme<T> = ReturnType<typeof createUpdater<T>> &
8
- ReturnType<typeof createCSSSheet> & {
8
+ Sheet<unknown> & {
9
9
  [K in keyof T as K extends `${string}Color`
10
10
  ? `${string & K}${'' | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900}`
11
- : K]: T[K];
11
+ : K]: string;
12
12
  };
13
13
 
14
14
  const themeStoreMap = new WeakMap();
@@ -26,7 +26,7 @@ export function getThemeProps<T>(theme: Theme<T>) {
26
26
 
27
27
  function createThemeFromProps<T extends Record<string, unknown>>(themeObj: T, props: Record<string, string> = {}) {
28
28
  const salt = randomStr();
29
- const styleSheet = createCSSSheet({})[SheetToken];
29
+ const styleSheet = css({})[SheetToken];
30
30
  const store = createStore<T>(themeObj);
31
31
  const theme: any = new Proxy(
32
32
  createUpdater({ [SheetToken]: styleSheet }, (payload: Partial<T>) => store(payload)),
@@ -63,7 +63,7 @@ function createThemeFromProps<T extends Record<string, unknown>>(themeObj: T, pr
63
63
  }
64
64
 
65
65
  /**
66
- * 用于 `@adoptedStyle(theme)`,类似 `createCSSSheet`
66
+ * 用于 `@adoptedStyle(theme)`,类似 `css`
67
67
  */
68
68
  export function createScopedTheme<T extends Record<string, unknown>>(themeObj: T) {
69
69
  return createThemeFromProps(themeObj);
package/src/index.ts CHANGED
@@ -1,9 +1,5 @@
1
- export * from './lib/decorators';
2
1
  export * from './lib/element';
2
+ export * from './lib/history';
3
3
  export * from './lib/store';
4
4
  export * from './lib/utils';
5
5
  export * from './lib/version';
6
-
7
- // 使用路径时可选模块
8
- export * from './lib/history';
9
- export * from './lib/directives';
@@ -1,27 +1,22 @@
1
- import type { createCSSSheet, Metadata, TemplateResult } from './element';
2
- import { GemElement, UpdateToken, _createTemplate, _RenderErrorEvent, render } from './element';
3
- import { camelToKebabCase, PropProxyMap, GemError } from './utils';
1
+ import type { TemplateResult } from './lit-html';
2
+ import type { Metadata, Sheet } from './reactive';
3
+ import { _createTemplate, _RenderErrorEvent, GemElement, render, UpdateToken } from './reactive';
4
4
  import type { Store } from './store';
5
- import * as elementExports from './element';
6
- import * as decoratorsExports from './decorators';
7
- import * as storeExports from './store';
8
- import * as versionExports from './version';
5
+ import { camelToKebabCase, GemError, PropProxyMap } from './utils';
9
6
 
10
- type GemElementPrototype = GemElement;
7
+ type GemElementPrototype = GemElement & { '': never };
11
8
  type StaticField = Exclude<keyof Metadata, keyof ShadowRootInit | 'aria' | 'noBlocking' | 'penetrable'>;
12
9
 
13
10
  const { deleteProperty, getOwnPropertyDescriptor, defineProperty } = Reflect;
14
- const { getPrototypeOf, assign } = Object;
11
+ const { getPrototypeOf, assign, hasOwn } = Object;
15
12
  const gemElementProxyMap = new PropProxyMap<GemElement>();
16
13
 
17
14
  function pushStaticField(context: ClassFieldDecoratorContext | ClassDecoratorContext, field: StaticField, member: any) {
18
15
  const metadata = context.metadata as Metadata;
19
16
  if (!getOwnPropertyDescriptor(metadata, field)) {
20
17
  // 继承基类
21
- const current = new Set<unknown>(metadata[field]);
22
- current.delete(member);
23
18
  defineProperty(metadata, field, {
24
- value: [...current],
19
+ value: metadata[field]?.filter((e) => e !== member) || [],
25
20
  });
26
21
  }
27
22
 
@@ -29,7 +24,8 @@ function pushStaticField(context: ClassFieldDecoratorContext | ClassDecoratorCon
29
24
  }
30
25
 
31
26
  function clearField<T extends GemElement>(instance: T, prop: string) {
32
- const { value } = getOwnPropertyDescriptor(instance, prop)!;
27
+ // hmr 支持不存在属性
28
+ const { value } = getOwnPropertyDescriptor(instance, prop) || {};
33
29
  deleteProperty(instance, prop);
34
30
  (instance as any)[prop] = value;
35
31
  }
@@ -39,18 +35,19 @@ const observedTargetAttributes = new WeakMap<GemElementPrototype, Map<string, st
39
35
  // 不在 Devtools 中工作 https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#dom_access
40
36
  // 使用 Gem DevTools 注入脚本监听 attribute 变化
41
37
  const { setAttribute, toggleAttribute, removeAttribute } = Element.prototype;
38
+ const getObservedPropName = (i: GemElement, n: string) => observedTargetAttributes.get(getPrototypeOf(i))?.get(n);
42
39
  GemElement.prototype.setAttribute = function (n: string, v: string) {
43
- const prop = observedTargetAttributes.get(getPrototypeOf(this))?.get(n);
40
+ const prop = getObservedPropName(this, n);
44
41
  if (!prop) return setAttribute.call(this, n, v);
45
42
  (this as any)[prop] = v;
46
43
  };
47
44
  GemElement.prototype.removeAttribute = function (n: string) {
48
- const prop = observedTargetAttributes.get(getPrototypeOf(this))?.get(n);
45
+ const prop = getObservedPropName(this, n);
49
46
  if (!prop) return removeAttribute.call(this, n);
50
47
  (this as any)[prop] = null;
51
48
  };
52
49
  GemElement.prototype.toggleAttribute = function (n: string, force?: boolean) {
53
- const prop = observedTargetAttributes.get(getPrototypeOf(this))?.get(n);
50
+ const prop = getObservedPropName(this, n);
54
51
  if (!prop) return toggleAttribute.call(this, n, force);
55
52
  return ((this as any)[prop] = force ?? !this.hasAttribute(n));
56
53
  };
@@ -96,10 +93,13 @@ function defineProp(
96
93
  if (event) {
97
94
  proxy[prop] = v?.[isEventHandleSymbol]
98
95
  ? v
99
- : (detail: any, options: any) => {
96
+ : async (detail: any, options: any) => {
97
+ // 事件如果同步触发,则祖先元素可能还没有挂载好,其中就不能更新 state
98
+ // https://github.com/mantou132/gem/issues/203
99
+ await Promise.resolve();
100
100
  const evt = new CustomEvent(event, { ...options, ...eventOptions, detail });
101
101
  that.dispatchEvent(evt);
102
- v(detail, options);
102
+ await v(detail, options);
103
103
  };
104
104
  (proxy[prop] as any)[isEventHandleSymbol] = true;
105
105
  // emitter 不触发元素更新
@@ -111,21 +111,35 @@ function defineProp(
111
111
  });
112
112
  }
113
113
 
114
+ // https://github.com/tc39/proposal-decorators/issues/517
115
+ const targetCache = new WeakMap<DecoratorMetadataObject, GemElementPrototype>();
116
+ function getDecoratorTarget(element: GemElement, { metadata }: ClassMemberDecoratorContext) {
117
+ const target = targetCache.get(metadata);
118
+ if (target) return target;
119
+ let result = element as GemElementPrototype;
120
+ do {
121
+ result = getPrototypeOf(result);
122
+ } while (result.constructor[Symbol.metadata] !== metadata);
123
+ targetCache.set(metadata, result);
124
+ return result;
125
+ }
126
+
114
127
  type AttrType = BooleanConstructor | NumberConstructor | StringConstructor;
115
128
  function decoratorAttr<T extends GemElement>(context: ClassFieldDecoratorContext<T>, attrType: AttrType) {
116
129
  const prop = context.name as string;
117
130
  const attr = camelToKebabCase(prop);
118
131
  context.addInitializer(function (this: T) {
119
- const target = getPrototypeOf(this);
120
- if (!target.hasOwnProperty(prop)) {
132
+ const target = getDecoratorTarget(this, context);
133
+ if (!hasOwn(target, prop)) {
121
134
  pushStaticField(context, 'observedAttributes', attr); // 没有 observe 的效果
122
135
  defineProp(target, prop, { attr, attrType });
123
- // 记录观察的 attribute
124
- const attrMap = observedTargetAttributes.get(target) || new Map<string, string>();
125
- attrMap.set(attr, prop);
126
- observedTargetAttributes.set(target, attrMap);
127
136
  }
128
137
  clearField(this, prop);
138
+ // 记录观察的 attribute, 用于 hack 的 setAttribute
139
+ const proto = getPrototypeOf(this);
140
+ const attrMap = observedTargetAttributes.get(proto) || new Map<string, string>();
141
+ attrMap.set(attr, prop);
142
+ observedTargetAttributes.set(proto, attrMap);
129
143
  });
130
144
  // 延时定义的元素需要继承原实例属性值
131
145
  return function (this: any, initValue: any) {
@@ -166,8 +180,8 @@ export function numattribute<T extends GemElement>(_: undefined, context: ClassF
166
180
  export function property<T extends GemElement>(_: undefined, context: ClassFieldDecoratorContext<T>) {
167
181
  const prop = context.name as string;
168
182
  context.addInitializer(function (this: T) {
169
- const target = getPrototypeOf(this);
170
- if (!target.hasOwnProperty(prop)) {
183
+ const target = getDecoratorTarget(this, context);
184
+ if (!hasOwn(target, prop)) {
171
185
  pushStaticField(context, 'observedProperties', prop);
172
186
  defineProp(target, prop);
173
187
  }
@@ -195,33 +209,42 @@ export function property<T extends GemElement>(_: undefined, context: ClassField
195
209
  export function memo<T extends GemElement, V = any, K = any[] | undefined>(
196
210
  getDep?: K extends readonly any[] ? (instance: T) => K : undefined,
197
211
  ) {
198
- return function (
212
+ return (
199
213
  _: any,
200
214
  context: ClassGetterDecoratorContext<T, V> | ClassFieldDecoratorContext<T> | ClassMethodDecoratorContext<T>,
201
- ) {
215
+ ) => {
202
216
  const { addInitializer, name, access, kind } = context;
203
217
  addInitializer(function (this: T) {
204
218
  const dep = getDep && (() => getDep(this) as any);
205
219
  if (kind === 'getter') {
206
220
  // 不能设置私有字段 https://github.com/tc39/proposal-decorators/issues/509
207
221
  if (context.private) throw new GemError('not support');
208
- this.memo(() => defineProperty(this, name, { configurable: true, value: access.get(this) }), dep);
222
+ const target = getDecoratorTarget(this, context as any);
223
+ // 不能直接用 `access.get.bind(this)` 是现有 builder 工具的 bug?
224
+ const getter = getOwnPropertyDescriptor(target, name)!.get!.bind(this);
225
+ this.memo(() => {
226
+ defineProperty(this, name, {
227
+ configurable: true,
228
+ value: getter(),
229
+ });
230
+ }, dep);
209
231
  } else {
210
- this.memo((access.get(this) as any).bind(this) as any, dep);
232
+ this.memo((access.get.call(this, this) as any).bind(this), dep);
211
233
  }
212
234
  });
213
235
  };
214
236
  }
215
237
 
216
238
  /**
217
- * 依赖 `GemElement.effect`
218
- * 方法执行在字段前面
239
+ * - 依赖 `GemElement.effect`
240
+ * - 方法执行在字段前面
241
+ * - 如果没有 oldValue,在为首次执行
219
242
  *
220
243
  * For example
221
244
  * ```ts
222
245
  * class App extends GemElement {
223
246
  * @effect(() => [])
224
- * #fetchData() {
247
+ * #fetchData(newValue, oldValue) {
225
248
  * console.log('fetch')
226
249
  * }
227
250
  * }
@@ -230,24 +253,18 @@ export function memo<T extends GemElement, V = any, K = any[] | undefined>(
230
253
  export function effect<T extends GemElement, V extends (depValues: K, oldDepValues?: K) => any, K = any[] | undefined>(
231
254
  getDep?: K extends readonly any[] ? (instance: T) => K : undefined,
232
255
  ) {
233
- return function (
234
- _: any,
235
- { addInitializer, access }: ClassFieldDecoratorContext<T, V> | ClassMethodDecoratorContext<T, V>,
236
- ) {
256
+ return (_: any, { addInitializer, access }: ClassFieldDecoratorContext<T, V> | ClassMethodDecoratorContext<T, V>) => {
237
257
  addInitializer(function (this: T) {
238
- this.effect(access.get(this).bind(this) as any, getDep && (() => getDep(this) as any));
258
+ this.effect(access.get.call(this, this).bind(this) as any, getDep && (() => getDep(this) as any));
239
259
  });
240
260
  };
241
261
  }
242
262
 
243
263
  export function unmounted<T extends GemElement, V extends () => any>() {
244
- return function (
245
- _: any,
246
- { addInitializer, access }: ClassFieldDecoratorContext<T, V> | ClassMethodDecoratorContext<T, V>,
247
- ) {
264
+ return (_: any, { addInitializer, access }: ClassFieldDecoratorContext<T, V> | ClassMethodDecoratorContext<T, V>) => {
248
265
  addInitializer(function (this: T) {
249
266
  this.effect(
250
- () => access.get(this).bind(this) as any,
267
+ () => access.get.call(this, this).bind(this) as any,
251
268
  () => [],
252
269
  );
253
270
  });
@@ -268,13 +285,10 @@ export function template<T extends GemElement, V extends () => TemplateResult |
268
285
  /** 当所有 `template` 返回 `false` 时不进行更新,包括 `memo` */
269
286
  condition?: (instance: T) => boolean,
270
287
  ) {
271
- return function (
272
- _: any,
273
- { addInitializer, access }: ClassFieldDecoratorContext<T, V> | ClassMethodDecoratorContext<T, V>,
274
- ) {
288
+ return (_: any, { addInitializer, access }: ClassFieldDecoratorContext<T, V> | ClassMethodDecoratorContext<T, V>) => {
275
289
  addInitializer(function (this: T) {
276
290
  _createTemplate(this, {
277
- render: access.get(this).bind(this),
291
+ render: access.get.call(this, this).bind(this),
278
292
  condition: condition && (() => condition(this) as any),
279
293
  });
280
294
  });
@@ -282,13 +296,10 @@ export function template<T extends GemElement, V extends () => TemplateResult |
282
296
  }
283
297
 
284
298
  export function fallback<T extends GemElement, V extends (err: any) => TemplateResult | null | undefined>() {
285
- return function (
286
- _: any,
287
- { addInitializer, access }: ClassFieldDecoratorContext<T, V> | ClassMethodDecoratorContext<T, V>,
288
- ) {
299
+ return (_: any, { addInitializer, access }: ClassFieldDecoratorContext<T, V> | ClassMethodDecoratorContext<T, V>) => {
289
300
  addInitializer(function (this: T) {
290
301
  this.addEventListener(_RenderErrorEvent, ({ detail }: CustomEvent) => {
291
- render(access.get(this).apply(this, [detail]), this.internals.shadowRoot || this);
302
+ render(access.get.call(this, this).apply(this, [detail]), this.internals.shadowRoot || this);
292
303
  });
293
304
  });
294
305
  };
@@ -328,11 +339,11 @@ function defineCSSState(target: GemElementPrototype, prop: string, stateStr: str
328
339
  * ```
329
340
  */
330
341
  export function state<T extends GemElement>(_: undefined, context: ClassFieldDecoratorContext<T, boolean>) {
342
+ const prop = context.name as string;
343
+ const attr = camelToKebabCase(prop);
331
344
  context.addInitializer(function (this: T) {
332
- const target = getPrototypeOf(this);
333
- const prop = context.name as string;
334
- if (!target.hasOwnProperty(prop)) {
335
- const attr = camelToKebabCase(prop);
345
+ const target = getDecoratorTarget(this, context);
346
+ if (!hasOwn(target, prop)) {
336
347
  pushStaticField(context, 'definedCSSStates', attr);
337
348
  defineCSSState(target, prop, attr);
338
349
  }
@@ -394,7 +405,17 @@ export function part(_: undefined, context: ClassFieldDecoratorContext<any, stri
394
405
  };
395
406
  }
396
407
 
397
- export type Emitter<T = any> = (detail?: T, options?: Omit<CustomEventInit<unknown>, 'detail'>) => void;
408
+ type EmitterHandler<T> = (evt: CustomEvent<T>) => void;
409
+
410
+ export type Emitter<T = any> = ((
411
+ detail?: T,
412
+ options?: Omit<CustomEventInit<unknown>, 'detail'>,
413
+ ) => Promise<void> | void) & {
414
+ /**
415
+ * @internal 用来为 ts plugin 提供类型签名,没有值
416
+ */
417
+ handler?: EmitterHandler<T> | (AddEventListenerOptions & { handleEvent: EmitterHandler<T> });
418
+ };
398
419
 
399
420
  /**
400
421
  * 定义一个事件发射器,类似 `HTMLElement.click`,
@@ -408,28 +429,25 @@ export type Emitter<T = any> = (detail?: T, options?: Omit<CustomEventInit<unkno
408
429
  * ```
409
430
  */
410
431
  export function emitter<T extends GemElement>(_: undefined, context: ClassFieldDecoratorContext<T, Emitter>) {
411
- context.addInitializer(function (this: T) {
412
- defineEmitter(context, this, context.name as string);
413
- });
432
+ defineEmitter(context);
414
433
  }
415
434
  export function globalemitter<T extends GemElement>(_: undefined, context: ClassFieldDecoratorContext<T, Emitter>) {
416
- context.addInitializer(function (this: T) {
417
- defineEmitter(context, this, context.name as string, { bubbles: true, composed: true });
418
- });
435
+ defineEmitter(context, { bubbles: true, composed: true });
419
436
  }
420
- function defineEmitter(
437
+ function defineEmitter<T extends GemElement>(
421
438
  context: ClassFieldDecoratorContext,
422
- t: GemElement,
423
- prop: string,
424
439
  eventOptions?: Omit<CustomEventInit<unknown>, 'detail'>,
425
440
  ) {
426
- const target = getPrototypeOf(t);
427
- if (!target.hasOwnProperty(prop)) {
428
- const event = camelToKebabCase(prop);
429
- pushStaticField(context, 'definedEvents', event);
430
- defineProp(target, prop, { event, eventOptions });
431
- }
432
- clearField(t, prop);
441
+ const prop = context.name as string;
442
+ const event = camelToKebabCase(prop);
443
+ context.addInitializer(function (this: T) {
444
+ const target = getDecoratorTarget(this, context);
445
+ if (!hasOwn(target, prop)) {
446
+ pushStaticField(context, 'definedEvents', event);
447
+ defineProp(target, prop, { event, eventOptions });
448
+ }
449
+ clearField(this, prop);
450
+ });
433
451
  }
434
452
 
435
453
  /**
@@ -441,8 +459,8 @@ function defineEmitter(
441
459
  * class App extends GemElement {}
442
460
  * ```
443
461
  */
444
- export function adoptedStyle(sheet: ReturnType<typeof createCSSSheet>) {
445
- return function (_: unknown, context: ClassDecoratorContext) {
462
+ export function adoptedStyle(sheet: Sheet<unknown>) {
463
+ return (_: unknown, context: ClassDecoratorContext) => {
446
464
  pushStaticField(context, 'adoptedStyleSheets', sheet);
447
465
  };
448
466
  }
@@ -457,7 +475,7 @@ export function adoptedStyle(sheet: ReturnType<typeof createCSSSheet>) {
457
475
  * ```
458
476
  */
459
477
  export function connectStore(store: Store<any>) {
460
- return function (_: unknown, context: ClassDecoratorContext) {
478
+ return (_: unknown, context: ClassDecoratorContext) => {
461
479
  pushStaticField(context, 'observedStores', store);
462
480
  };
463
481
  }
@@ -468,14 +486,14 @@ export function shadow({
468
486
  delegatesFocus,
469
487
  slotAssignment,
470
488
  }: Partial<ShadowRootInit> = {}) {
471
- return function (_: any, context: ClassDecoratorContext) {
489
+ return (_: any, context: ClassDecoratorContext) => {
472
490
  const metadata = context.metadata as Metadata;
473
491
  assign(metadata, { mode, serializable, delegatesFocus, slotAssignment });
474
492
  };
475
493
  }
476
494
 
477
495
  export function light({ penetrable }: Pick<Metadata, 'penetrable'>) {
478
- return function (_: any, context: ClassDecoratorContext) {
496
+ return (_: any, context: ClassDecoratorContext) => {
479
497
  const metadata = context.metadata as Metadata;
480
498
  metadata.penetrable = penetrable;
481
499
  };
@@ -486,7 +504,7 @@ export function light({ penetrable }: Pick<Metadata, 'penetrable'>) {
486
504
  * 例如:https://examples.gemjs.org/async
487
505
  */
488
506
  export function async() {
489
- return function (_: any, context: ClassDecoratorContext) {
507
+ return (_: any, context: ClassDecoratorContext) => {
490
508
  const metadata = context.metadata as Metadata;
491
509
  metadata.noBlocking = true;
492
510
  };
@@ -496,7 +514,7 @@ export function async() {
496
514
  * 定义元素的可访问性属性
497
515
  */
498
516
  export function aria(info: Metadata['aria']) {
499
- return function (_: any, context: ClassDecoratorContext) {
517
+ return (_: any, context: ClassDecoratorContext) => {
500
518
  const metadata = context.metadata as Metadata;
501
519
  metadata.aria = { ...metadata.aria, ...info };
502
520
  };
@@ -512,26 +530,9 @@ export function aria(info: Metadata['aria']) {
512
530
  * ```
513
531
  */
514
532
  export function customElement(name: string) {
515
- return function (cls: new (...args: any) => any, { addInitializer }: ClassDecoratorContext) {
516
- addInitializer(function () {
533
+ return (cls: new (...args: any) => any, { addInitializer }: ClassDecoratorContext) => {
534
+ addInitializer(() => {
517
535
  customElements.define(name, cls);
518
536
  });
519
537
  };
520
538
  }
521
-
522
- declare global {
523
- interface Window {
524
- __GEM_DEVTOOLS__HOOK__?:
525
- | (typeof elementExports & typeof decoratorsExports & typeof storeExports & typeof versionExports)
526
- | Record<string, never>;
527
- }
528
- }
529
-
530
- if (window.__GEM_DEVTOOLS__HOOK__ && !window.__GEM_DEVTOOLS__HOOK__.GemElement) {
531
- assign(window.__GEM_DEVTOOLS__HOOK__, {
532
- ...elementExports,
533
- ...decoratorsExports,
534
- ...storeExports,
535
- ...versionExports,
536
- });
537
- }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2017 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+
7
+ import type { Disconnectable, Part } from './lit-html.js';
8
+
9
+ export type {
10
+ AttributePart,
11
+ BooleanAttributePart,
12
+ ChildPart,
13
+ ElementPart,
14
+ EventPart,
15
+ Part,
16
+ PropertyPart,
17
+ } from './lit-html.js';
18
+
19
+ export interface DirectiveClass {
20
+ new (part: PartInfo): Directive;
21
+ }
22
+
23
+ /**
24
+ * This utility type extracts the signature of a directive class's render()
25
+ * method so we can use it for the type of the generated directive function.
26
+ */
27
+ export type DirectiveParameters<C extends Directive> = Parameters<C['render']>;
28
+
29
+ /**
30
+ * A generated directive function doesn't evaluate the directive, but just
31
+ * returns a DirectiveResult object that captures the arguments.
32
+ */
33
+ export interface DirectiveResult<C extends DirectiveClass = DirectiveClass> {
34
+ /**
35
+ * This property needs to remain unminified.
36
+ * @internal
37
+ */
38
+ _$litDirective$: C;
39
+ /** @internal */
40
+ values: DirectiveParameters<InstanceType<C>>;
41
+ }
42
+
43
+ export const PartType = {
44
+ ATTRIBUTE: 1,
45
+ CHILD: 2,
46
+ PROPERTY: 3,
47
+ BOOLEAN_ATTRIBUTE: 4,
48
+ EVENT: 5,
49
+ ELEMENT: 6,
50
+ } as const;
51
+
52
+ export type PartType = (typeof PartType)[keyof typeof PartType];
53
+
54
+ export interface ChildPartInfo {
55
+ readonly type: typeof PartType.CHILD;
56
+ }
57
+
58
+ export interface AttributePartInfo {
59
+ readonly type:
60
+ | typeof PartType.ATTRIBUTE
61
+ | typeof PartType.PROPERTY
62
+ | typeof PartType.BOOLEAN_ATTRIBUTE
63
+ | typeof PartType.EVENT;
64
+ readonly strings?: ReadonlyArray<string>;
65
+ readonly name: string;
66
+ readonly tagName: string;
67
+ }
68
+
69
+ export interface ElementPartInfo {
70
+ readonly type: typeof PartType.ELEMENT;
71
+ }
72
+
73
+ /**
74
+ * Information about the part a directive is bound to.
75
+ *
76
+ * This is useful for checking that a directive is attached to a valid part,
77
+ * such as with directive that can only be used on attribute bindings.
78
+ */
79
+ export type PartInfo = ChildPartInfo | AttributePartInfo | ElementPartInfo;
80
+
81
+ /**
82
+ * Creates a user-facing directive function from a Directive class. This
83
+ * function has the same parameters as the directive's render() method.
84
+ */
85
+ export const directive =
86
+ <C extends DirectiveClass>(c: C) =>
87
+ (...values: DirectiveParameters<InstanceType<C>>): DirectiveResult<C> => ({
88
+ // This property needs to remain unminified.
89
+ _$litDirective$: c,
90
+ values,
91
+ });
92
+
93
+ /**
94
+ * Base class for creating custom directives. Users should extend this class,
95
+ * implement `render` and/or `update`, and then pass their subclass to
96
+ * `directive`.
97
+ */
98
+ export abstract class Directive implements Disconnectable {
99
+ //@internal
100
+ __part!: Part;
101
+ //@internal
102
+ __attributeIndex: number | undefined;
103
+ //@internal
104
+ __directive?: Directive;
105
+
106
+ //@internal
107
+ _$parent!: Disconnectable;
108
+
109
+ // These will only exist on the AsyncDirective subclass
110
+ //@internal
111
+ _$disconnectableChildren?: Set<Disconnectable>;
112
+ // This property needs to remain unminified.
113
+ //@internal
114
+ _$notifyDirectiveConnectionChanged?(isConnected: boolean): void;
115
+
116
+ // See comment in Disconnectable interface for why this is a getter
117
+ get _$isConnected() {
118
+ return this._$parent._$isConnected;
119
+ }
120
+
121
+ /** @internal */
122
+ _$initialize(part: Part, parent: Disconnectable, attributeIndex: number | undefined) {
123
+ this.__part = part;
124
+ this._$parent = parent;
125
+ this.__attributeIndex = attributeIndex;
126
+ }
127
+ /** @internal */
128
+ _$resolve(part: Part, props: Array<unknown>): unknown {
129
+ return this.update(part, props);
130
+ }
131
+
132
+ abstract render(...props: Array<unknown>): unknown;
133
+
134
+ update(_part: Part, props: Array<unknown>): unknown {
135
+ return this.render(...props);
136
+ }
137
+ }