@mantou/gem 1.7.0 → 1.7.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 (51) hide show
  1. package/dist/gem.es.js +65 -201
  2. package/dist/gem.umd.js +28 -30
  3. package/elements/base/dialog.d.ts +2 -0
  4. package/elements/base/dialog.d.ts.map +1 -1
  5. package/elements/base/dialog.js +2 -0
  6. package/elements/base/dialog.js.map +1 -1
  7. package/elements/base/gesture.js +1 -1
  8. package/elements/base/link.d.ts +3 -0
  9. package/elements/base/link.d.ts.map +1 -1
  10. package/elements/base/link.js +17 -4
  11. package/elements/base/link.js.map +1 -1
  12. package/elements/base/modal-factory.d.ts +7 -6
  13. package/elements/base/modal-factory.d.ts.map +1 -1
  14. package/elements/base/route.js +1 -1
  15. package/elements/base/unsafe.js +1 -1
  16. package/elements/base/use.d.ts.map +1 -1
  17. package/elements/base/use.js +1 -3
  18. package/elements/base/use.js.map +1 -1
  19. package/helper/i18n.d.ts +2 -2
  20. package/helper/i18n.d.ts.map +1 -1
  21. package/helper/i18n.js.map +1 -1
  22. package/helper/ssr-shim.d.ts +2 -0
  23. package/helper/ssr-shim.d.ts.map +1 -0
  24. package/helper/ssr-shim.js +29 -0
  25. package/helper/ssr-shim.js.map +1 -0
  26. package/index.d.ts +0 -10
  27. package/index.d.ts.map +1 -1
  28. package/index.js +0 -7
  29. package/index.js.map +1 -1
  30. package/lib/element.d.ts +12 -4
  31. package/lib/element.d.ts.map +1 -1
  32. package/lib/element.js +21 -15
  33. package/lib/element.js.map +1 -1
  34. package/lib/utils.js +1 -1
  35. package/lib/utils.js.map +1 -1
  36. package/lib/version.d.ts +1 -1
  37. package/lib/version.js +1 -1
  38. package/package.json +1 -1
  39. package/src/elements/base/dialog.ts +2 -0
  40. package/src/elements/base/gesture.ts +1 -1
  41. package/src/elements/base/link.ts +10 -4
  42. package/src/elements/base/route.ts +1 -1
  43. package/src/elements/base/unsafe.ts +1 -1
  44. package/src/elements/base/use.ts +1 -3
  45. package/src/helper/i18n.ts +3 -3
  46. package/src/helper/ssr-shim.ts +29 -0
  47. package/src/index.ts +0 -16
  48. package/src/lib/element.ts +33 -19
  49. package/src/lib/utils.ts +1 -1
  50. package/src/lib/version.ts +1 -1
  51. package/src/test/gem-element/decorators.test.ts +6 -6
@@ -30,11 +30,17 @@ export class GemLinkElement extends GemElement {
30
30
 
31
31
  // 动态路由,根据 route.pattern 和 options.params 计算出 path
32
32
  @property route: RouteItem | undefined;
33
+ /**@deprecated */
33
34
  @property options: RouteOptions | undefined;
35
+ @property routeOptions: RouteOptions | undefined;
34
36
  @property prepare: (() => void | Promise<void>) | undefined;
35
37
 
36
38
  @part link: string;
37
39
 
40
+ get #routeOptions() {
41
+ return this.routeOptions || this.options;
42
+ }
43
+
38
44
  constructor() {
39
45
  super();
40
46
  this.tabIndex = 0;
@@ -44,9 +50,9 @@ export class GemLinkElement extends GemElement {
44
50
  // 不包含 basePath
45
51
  getPathInfo() {
46
52
  if (this.route) {
47
- const queryProp = this.options?.query || '';
48
- const hashProp = this.options?.hash || '';
49
- return createPath(this.route, this.options) + queryProp + hashProp;
53
+ const queryProp = this.#routeOptions?.query || '';
54
+ const hashProp = this.#routeOptions?.hash || '';
55
+ return createPath(this.route, this.#routeOptions) + queryProp + hashProp;
50
56
  } else {
51
57
  const url = this.href || this.path + this.query + this.hash;
52
58
  const { path, query } = history.getParams();
@@ -101,7 +107,7 @@ export class GemLinkElement extends GemElement {
101
107
 
102
108
  if (this.route) {
103
109
  history.pushIgnoreCloseHandle({
104
- ...createHistoryParams(this.route, this.options),
110
+ ...createHistoryParams(this.route, this.#routeOptions),
105
111
  title: this.route.title || this.docTitle,
106
112
  });
107
113
  } else if (this.href) {
@@ -236,7 +236,7 @@ export class GemRouteElement extends GemElement<State> {
236
236
 
237
237
  return html`
238
238
  <style>
239
- :host,
239
+ :host(:where(:not([hidden]))),
240
240
  :not(:defined) {
241
241
  display: contents;
242
242
  }
@@ -18,7 +18,7 @@ export class GemUnsafeElement extends GemElement {
18
18
  if (this.shadowRoot) {
19
19
  this.shadowRoot.innerHTML = `
20
20
  <style>
21
- :host {
21
+ :host(:where(:not([hidden]))) {
22
22
  display: contents;
23
23
  }
24
24
  ${this.contentcss}
@@ -38,10 +38,8 @@ export class GemUseElement extends GemElement {
38
38
  render() {
39
39
  return html`
40
40
  <style>
41
- :host {
41
+ :host(:where(:not([hidden]))) {
42
42
  position: relative;
43
- }
44
- :host(:not([hidden])) {
45
43
  display: inline-flex;
46
44
  align-items: center;
47
45
  }
@@ -40,7 +40,7 @@ interface Resources<T> {
40
40
  [key: string]: Partial<T> | string;
41
41
  }
42
42
 
43
- interface Options<T> {
43
+ interface I18nOptions<T> {
44
44
  resources: Resources<T>;
45
45
  fallbackLanguage: string;
46
46
  // 可以在构造函数中指定,但会被 URL 中的语言参数覆盖
@@ -107,13 +107,13 @@ export class I18n<T = Record<string, Msg>> {
107
107
  this.onChange?.(lang);
108
108
  }
109
109
 
110
- constructor(options: Options<T>) {
110
+ constructor(options: I18nOptions<T>) {
111
111
  if (!options.resources[options.fallbackLanguage]) {
112
112
  throw new GemError('i18n: fallbackLanguage invalid');
113
113
  }
114
114
 
115
115
  this.store = createStore(this as any);
116
- Object.assign<I18n<T>, Options<T>>(this as I18n<T>, options);
116
+ Object.assign<I18n<T>, I18nOptions<T>>(this as I18n<T>, options);
117
117
 
118
118
  let currentLanguage = this.#urlParamsLang || this.currentLanguage || this.#cacheLang;
119
119
 
@@ -0,0 +1,29 @@
1
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2
+ // @ts-nocheck
3
+ if (typeof window === 'undefined') {
4
+ const getAny = () => {
5
+ const anonymous = () => getAny();
6
+ Object.defineProperties(anonymous, {
7
+ length: { writable: true },
8
+ name: { writable: true },
9
+ });
10
+ return new Proxy(anonymous, {
11
+ get(target, key) {
12
+ if (key === Symbol.toPrimitive) return () => '';
13
+ return target[key] || (target[key] = getAny());
14
+ },
15
+ });
16
+ };
17
+ const any = getAny();
18
+
19
+ globalThis.document = any;
20
+ globalThis.addEventListener = any;
21
+ globalThis.history = any;
22
+ globalThis.navigator = any;
23
+ globalThis.customElements = any;
24
+ globalThis.HTMLElement = null;
25
+ globalThis.location = new URL('about:blank');
26
+ globalThis.window = globalThis;
27
+ }
28
+
29
+ export {};
package/src/index.ts CHANGED
@@ -1,19 +1,3 @@
1
- /**
2
- * 不支持多个 gem
3
- */
4
- import * as Gem from './';
5
-
6
- export type DevToolsHook = typeof Gem;
7
- declare global {
8
- interface Window {
9
- __GEM_DEVTOOLS__HOOK__?: DevToolsHook;
10
- }
11
- }
12
-
13
- if (window.__GEM_DEVTOOLS__HOOK__) {
14
- Object.assign(window.__GEM_DEVTOOLS__HOOK__, { ...Gem });
15
- }
16
-
17
1
  export * from './lib/store';
18
2
  export * from './lib/history';
19
3
  export * from './lib/element';
@@ -15,6 +15,8 @@ import {
15
15
  removeItems,
16
16
  useNativeCSSStyleSheet,
17
17
  } from './utils';
18
+ import * as GemExports from './element';
19
+ import * as VersionExports from './version';
18
20
 
19
21
  export { html, svg, render, directive, TemplateResult, SVGTemplateResult } from 'lit-html';
20
22
  export { repeat } from 'lit-html/directives/repeat';
@@ -27,9 +29,8 @@ export { ifDefined } from 'lit-html/directives/if-defined';
27
29
  declare global {
28
30
  interface ElementInternals extends ARIAMixin {
29
31
  // https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet
30
- states?: Set<string>;
31
- // https://w3c.github.io/aria/#role_definitions
32
- role?: string;
32
+ states: Set<string>;
33
+ role?: string | null;
33
34
  }
34
35
  // 用于 css 选择器选择元素,使用 @refobject 自动选择获取
35
36
  // 必须使用 attr 赋值
@@ -38,8 +39,8 @@ declare global {
38
39
  * @attr inert
39
40
  */
40
41
  interface HTMLElement {
41
- attachInternals: () => ElementInternals;
42
42
  inert: boolean;
43
+ ref: string;
43
44
  }
44
45
  }
45
46
 
@@ -81,7 +82,9 @@ const updateSymbol = Symbol('update');
81
82
  export interface GemElementOptions {
82
83
  isLight?: boolean;
83
84
  isAsync?: boolean;
85
+ // https://developer.mozilla.org/en-US/docs/Web/API/Element/attachShadow#options
84
86
  delegatesFocus?: boolean;
87
+ slotAssignment?: 'named' | 'manual';
85
88
  }
86
89
 
87
90
  export abstract class GemElement<T = Record<string, unknown>> extends HTMLElement {
@@ -114,7 +117,7 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
114
117
  #memoList?: EffectItem<any>[];
115
118
  #unmountCallback?: any;
116
119
 
117
- constructor({ isAsync, isLight, delegatesFocus }: GemElementOptions = {}) {
120
+ constructor({ isAsync, isLight, delegatesFocus, slotAssignment }: GemElementOptions = {}) {
118
121
  super();
119
122
  (this as any)[constructorSymbol] = true;
120
123
 
@@ -128,7 +131,7 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
128
131
  };
129
132
 
130
133
  this.#isAsync = isAsync;
131
- this.#renderRoot = isLight ? this : this.attachShadow({ mode: 'open', delegatesFocus });
134
+ this.#renderRoot = isLight ? this : this.attachShadow({ mode: 'open', delegatesFocus, slotAssignment });
132
135
 
133
136
  const { adoptedStyleSheets } = new.target;
134
137
  if (adoptedStyleSheets) {
@@ -178,16 +181,18 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
178
181
  if (!this.#internals) {
179
182
  this.#internals = this.attachInternals();
180
183
  // https://groups.google.com/a/chromium.org/g/blink-dev/c/JvpHoUfhJYE?pli=1
184
+ // https://bugs.webkit.org/show_bug.cgi?id=215911
185
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1588763
181
186
  try {
182
- this.#internals.states?.add('foo');
183
- this.#internals.states?.delete('foo');
187
+ this.#internals.states.add('foo');
188
+ this.#internals.states.delete('foo');
184
189
  } catch {
185
190
  Reflect.defineProperty(this.#internals, 'states', {
186
- value: new Proxy(this.#internals.states!, {
187
- get(target: any, p) {
188
- return (str: string) => target[p](`--${str}`);
189
- },
190
- }),
191
+ value: {
192
+ has: (v: string) => kebabToCamelCase(v) in this.dataset,
193
+ add: (v: string) => (this.dataset[kebabToCamelCase(v)] = ''),
194
+ delete: (v: string) => delete this.dataset[kebabToCamelCase(v)],
195
+ },
191
196
  });
192
197
  }
193
198
  }
@@ -318,12 +323,11 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen
318
323
  const styles = useNativeCSSStyleSheet
319
324
  ? ''
320
325
  : html`${this.shadowRoot?.adoptedStyleSheets?.map(
321
- (e: any) =>
322
- html`
323
- <style media=${e.media.mediaText}>
324
- ${e.style}
325
- </style>
326
- `,
326
+ (e: any) => html`
327
+ <style media=${e.media.mediaText}>
328
+ ${e.style}
329
+ </style>
330
+ `,
327
331
  )}`;
328
332
  if (this.render) {
329
333
  const r = this.render();
@@ -625,3 +629,13 @@ customElements.define = (name: string, cls: CustomElementConstructor, options?:
625
629
 
626
630
  nativeDefineElement(name, cls as CustomElementConstructor, options);
627
631
  };
632
+
633
+ declare global {
634
+ interface Window {
635
+ __GEM_DEVTOOLS__HOOK__?: (typeof GemExports & typeof VersionExports) | Record<string, never>;
636
+ }
637
+ }
638
+
639
+ if (window.__GEM_DEVTOOLS__HOOK__) {
640
+ Object.assign(window.__GEM_DEVTOOLS__HOOK__, { ...GemExports, ...VersionExports });
641
+ }
package/src/lib/utils.ts CHANGED
@@ -245,7 +245,7 @@ export interface StyledKeyValuePair {
245
245
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1520690
246
246
  // https://bugs.webkit.org/show_bug.cgi?id=228684
247
247
  export let useNativeCSSStyleSheet = true;
248
- let CSSStyleSheet = window.CSSStyleSheet;
248
+ let CSSStyleSheet = globalThis.CSSStyleSheet;
249
249
  try {
250
250
  new (CSSStyleSheet as any)();
251
251
  } catch {
@@ -1 +1 @@
1
- export const version = '1.7.0';
1
+ export const version = '1.7.1';
@@ -38,7 +38,7 @@ class DecoratorGemElement extends GemElement {
38
38
  @attribute rankAttr: string;
39
39
  @boolattribute rankDisabled: boolean;
40
40
  @numattribute rankCount: number;
41
- @property dataProp = { value: '' };
41
+ @property propData = { value: '' };
42
42
  @state openState: boolean;
43
43
  @part headerPart: string;
44
44
  @refobject inputRef: RefObject<HTMLElement>;
@@ -46,8 +46,8 @@ class DecoratorGemElement extends GemElement {
46
46
  renderCount = 0;
47
47
  render() {
48
48
  this.renderCount++;
49
- const { rankAttr, rankDisabled, rankCount, dataProp } = this;
50
- return html`attr: ${rankAttr}, disabled: ${rankDisabled}, count: ${rankCount}, prop: ${dataProp.value}`;
49
+ const { rankAttr, rankDisabled, rankCount, propData } = this;
50
+ return html`attr: ${rankAttr}, disabled: ${rankDisabled}, count: ${rankCount}, prop: ${propData.value}`;
51
51
  }
52
52
  }
53
53
 
@@ -70,7 +70,7 @@ describe('装饰器', () => {
70
70
  const el: DecoratorGemElement = await fixture(html`
71
71
  <decorator-gem-demo
72
72
  @say-hi=${(e: CustomEvent) => (a = e.detail)}
73
- .dataProp=${{ value: 'prop' }}
73
+ .propData=${{ value: 'prop' }}
74
74
  rank-attr="attr"
75
75
  rank-disabled
76
76
  rank-count="2"
@@ -87,11 +87,11 @@ describe('装饰器', () => {
87
87
  expect(DecoratorGemElement.defineParts).to.eql(['header-part']);
88
88
  expect(DecoratorGemElement.defineSlots).to.eql(['body-slot']);
89
89
  expect(DecoratorGemElement.defineRefs?.[0].startsWith('input-ref-')).to.equal(true);
90
- expect(DecoratorGemElement.observedProperties).to.eql(['dataProp']);
90
+ expect(DecoratorGemElement.observedProperties).to.eql(['propData']);
91
91
  expect(el.rankAttr).to.equal('attr');
92
92
  expect(el.rankDisabled).to.equal(true);
93
93
  expect(el.rankCount).to.equal(2);
94
- expect(el.dataProp).to.eql({ value: 'prop' });
94
+ expect(el.propData).to.eql({ value: 'prop' });
95
95
  expect(el.openState).to.equal(false);
96
96
  expect(el.headerPart).to.equal('header-part');
97
97
  expect(el.inputRef.ref.startsWith('input-ref-')).to.equal(true);