@greypan/web-ui 2.1.5 → 2.1.8

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 (111) hide show
  1. package/README.CN.md +52 -36
  2. package/README.md +55 -36
  3. package/dist/assets/glass.js.map +1 -1
  4. package/dist/components/avatar/index.js +1 -1
  5. package/dist/components/avatar/index.js.map +1 -1
  6. package/dist/components/back-top/index.js +1 -1
  7. package/dist/components/back-top/index.js.map +1 -1
  8. package/dist/components/button/index.d.ts +6 -1
  9. package/dist/components/button/index.js +35 -14
  10. package/dist/components/button/index.js.map +1 -1
  11. package/dist/components/button/style.js +1 -1
  12. package/dist/components/button/style.js.map +1 -1
  13. package/dist/components/checkbox/index.d.ts +0 -3
  14. package/dist/components/checkbox/index.js.map +1 -1
  15. package/dist/components/checkbox/style.js +1 -1
  16. package/dist/components/checkbox/style.js.map +1 -1
  17. package/dist/components/context-menu/index.d.ts +4 -3
  18. package/dist/components/context-menu/index.js +47 -50
  19. package/dist/components/context-menu/index.js.map +1 -1
  20. package/dist/components/dialog/index.d.ts +1 -1
  21. package/dist/components/dialog/index.js +20 -19
  22. package/dist/components/dialog/index.js.map +1 -1
  23. package/dist/components/dialog/style.js +1 -1
  24. package/dist/components/dialog/style.js.map +1 -1
  25. package/dist/components/drawer/index.d.ts +2 -3
  26. package/dist/components/drawer/index.js +41 -31
  27. package/dist/components/drawer/index.js.map +1 -1
  28. package/dist/components/drawer/style.js +1 -1
  29. package/dist/components/drawer/style.js.map +1 -1
  30. package/dist/components/dropdown/index.d.ts +2 -9
  31. package/dist/components/dropdown/index.js +55 -51
  32. package/dist/components/dropdown/index.js.map +1 -1
  33. package/dist/components/dropdown-item/index.d.ts +0 -1
  34. package/dist/components/dropdown-item/index.js.map +1 -1
  35. package/dist/components/dropdown-item/style.js +1 -1
  36. package/dist/components/dropdown-item/style.js.map +1 -1
  37. package/dist/components/empty/index.js.map +1 -1
  38. package/dist/components/input/index.d.ts +1 -0
  39. package/dist/components/input/index.js +27 -14
  40. package/dist/components/input/index.js.map +1 -1
  41. package/dist/components/input/style.js +1 -1
  42. package/dist/components/input/style.js.map +1 -1
  43. package/dist/components/input-number/index.d.ts +3 -0
  44. package/dist/components/input-number/index.js +11 -3
  45. package/dist/components/input-number/index.js.map +1 -1
  46. package/dist/components/input-number/style.js +1 -1
  47. package/dist/components/input-number/style.js.map +1 -1
  48. package/dist/components/layout/style.js +1 -1
  49. package/dist/components/layout/style.js.map +1 -1
  50. package/dist/components/option/index.js +1 -1
  51. package/dist/components/option/index.js.map +1 -1
  52. package/dist/components/option/style.js +1 -1
  53. package/dist/components/option/style.js.map +1 -1
  54. package/dist/components/popover/index.d.ts +1 -5
  55. package/dist/components/popover/index.js +41 -36
  56. package/dist/components/popover/index.js.map +1 -1
  57. package/dist/components/radio/index.d.ts +0 -3
  58. package/dist/components/radio/index.js.map +1 -1
  59. package/dist/components/radio/style.js +1 -1
  60. package/dist/components/radio/style.js.map +1 -1
  61. package/dist/components/segmented/index.js +6 -2
  62. package/dist/components/segmented/index.js.map +1 -1
  63. package/dist/components/segmented/style.js +1 -1
  64. package/dist/components/segmented/style.js.map +1 -1
  65. package/dist/components/segmented-trigger/index.js +1 -1
  66. package/dist/components/segmented-trigger/index.js.map +1 -1
  67. package/dist/components/segmented-trigger/style.js +1 -1
  68. package/dist/components/segmented-trigger/style.js.map +1 -1
  69. package/dist/components/select/index.d.ts +1 -0
  70. package/dist/components/select/index.js +11 -6
  71. package/dist/components/select/index.js.map +1 -1
  72. package/dist/components/slider/index.d.ts +0 -2
  73. package/dist/components/slider/index.js +1 -1
  74. package/dist/components/slider/index.js.map +1 -1
  75. package/dist/components/spinner/index.d.ts +0 -2
  76. package/dist/components/spinner/index.js.map +1 -1
  77. package/dist/components/svg-draw-lines/index.d.ts +0 -2
  78. package/dist/components/svg-draw-lines/index.js.map +1 -1
  79. package/dist/components/switch/index.d.ts +0 -1
  80. package/dist/components/switch/index.js.map +1 -1
  81. package/dist/components/switch/style.js +1 -1
  82. package/dist/components/switch/style.js.map +1 -1
  83. package/dist/components/textarea/index.d.ts +1 -0
  84. package/dist/components/textarea/index.js +47 -33
  85. package/dist/components/textarea/index.js.map +1 -1
  86. package/dist/components/textarea/style.js +1 -1
  87. package/dist/components/textarea/style.js.map +1 -1
  88. package/dist/components/theme/index.d.ts +0 -2
  89. package/dist/components/theme/index.js.map +1 -1
  90. package/dist/components/theme/style.js +1 -1
  91. package/dist/components/theme/style.js.map +1 -1
  92. package/dist/components/toast/manager.js.map +1 -1
  93. package/dist/components/toast/style.js +1 -1
  94. package/dist/components/toast/style.js.map +1 -1
  95. package/dist/components/toast/toast.d.ts +0 -4
  96. package/dist/components/toast/toast.js +14 -6
  97. package/dist/components/toast/toast.js.map +1 -1
  98. package/dist/components/toast/types.d.ts +0 -3
  99. package/dist/components/tooltip/index.d.ts +1 -0
  100. package/dist/components/tooltip/index.js +31 -30
  101. package/dist/components/tooltip/index.js.map +1 -1
  102. package/dist/shared/events/user-change.js +17 -0
  103. package/dist/shared/events/user-change.js.map +1 -0
  104. package/dist/shared/normalize/index.js.map +1 -1
  105. package/dist/shared/overlay/native-dialog-presence.js +8 -3
  106. package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
  107. package/dist/shared/overlay/overlay.js.map +1 -1
  108. package/dist/shared/overlay/portal.js +3 -1
  109. package/dist/shared/overlay/portal.js.map +1 -1
  110. package/dist/shared/overlay/presence.js.map +1 -1
  111. package/package.json +9 -4
@@ -1,14 +1,15 @@
1
1
  import e from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
2
2
  import t from "../../assets/glass.js";
3
3
  import { normalizeLiteral as n, normalizeNumber as r } from "../../shared/normalize/index.js";
4
- import i from "../../assets/overlay-motion.js";
5
- import { defineAnchoredPanel as a } from "../../shared/overlay/anchored-panel.js";
6
- import { createOverlayPortal as o } from "../../shared/overlay/portal.js";
7
- import s from "./style.js";
8
- import { LitElement as c, html as l, unsafeCSS as u } from "lit";
9
- import { customElement as d, property as f } from "lit/decorators.js";
4
+ import { UserChangeController as i } from "../../shared/events/user-change.js";
5
+ import a from "../../assets/overlay-motion.js";
6
+ import { defineAnchoredPanel as o } from "../../shared/overlay/anchored-panel.js";
7
+ import { createOverlayPortal as s } from "../../shared/overlay/portal.js";
8
+ import c from "./style.js";
9
+ import { LitElement as l, html as u, unsafeCSS as d } from "lit";
10
+ import { customElement as f, property as p } from "lit/decorators.js";
10
11
  //#region src/components/tooltip/index.ts
11
- var p = [
12
+ var m = [
12
13
  "top",
13
14
  "top-start",
14
15
  "top-end",
@@ -21,9 +22,9 @@ var p = [
21
22
  "right",
22
23
  "right-start",
23
24
  "right-end"
24
- ], m = 0, h = class extends c {
25
+ ], h = 0, g = class extends l {
25
26
  constructor(...e) {
26
- super(...e), this._placement = "top", this._showDelay = 200, this._hideDelay = 100, this.disabled = !1, this._offset = 6, this.content = "", this.open = !1, this.portal = !1, this._isCountedVisible = !1, this._shouldOpenInstantly = !0, this._panel = a().make({
27
+ super(...e), this._placement = "top", this._showDelay = 200, this._hideDelay = 100, this.disabled = !1, this._offset = 6, this.content = "", this.open = !1, this.portal = !1, this._isCountedVisible = !1, this._userOpenChange = new i(), this._shouldOpenInstantly = !0, this._panel = o().make({
27
28
  getAnchor: () => this.shadowRoot?.querySelector(".tooltip-trigger") ?? null,
28
29
  getLocalPanel: () => this.shadowRoot?.querySelector(".tooltip-panel") ?? null,
29
30
  getPositioning: () => ({
@@ -34,7 +35,7 @@ var p = [
34
35
  isPortal: () => this.portal,
35
36
  createPortal: () => this._createPortal()
36
37
  }), this._onPointerEnter = (e) => {
37
- e.pointerType !== "touch" && (this.disabled || (clearTimeout(this._hideTimer), this._showTimer = setTimeout(() => this._show(), m > 0 ? 0 : this.showDelay)));
38
+ e.pointerType !== "touch" && (this.disabled || (clearTimeout(this._hideTimer), this._showTimer = setTimeout(() => this._show(), h > 0 ? 0 : this.showDelay)));
38
39
  }, this._onPointerLeave = (e) => {
39
40
  e.pointerType !== "touch" && (this.disabled || (clearTimeout(this._showTimer), this._hideTimer = setTimeout(() => this._hide(), this.hideDelay)));
40
41
  }, this._onFocusIn = () => {
@@ -45,9 +46,9 @@ var p = [
45
46
  }
46
47
  static {
47
48
  this.styles = [
48
- u(t),
49
- u(i),
50
- u(s)
49
+ d(t),
50
+ d(a),
51
+ d(c)
51
52
  ];
52
53
  }
53
54
  get placement() {
@@ -55,7 +56,7 @@ var p = [
55
56
  }
56
57
  set placement(e) {
57
58
  let t = this._placement;
58
- this._placement = n(e, p, "top"), this.requestUpdate("placement", t);
59
+ this._placement = n(e, m, "top"), this.requestUpdate("placement", t);
59
60
  }
60
61
  get showDelay() {
61
62
  return this._showDelay;
@@ -91,22 +92,22 @@ var p = [
91
92
  this.open && (this._openOverlay(this._shouldOpenInstantly), this._shouldOpenInstantly = !0);
92
93
  }
93
94
  updated(e) {
94
- e.has("portal") || e.has("overlayContainer") ? requestAnimationFrame(() => this._reconfigureOverlay()) : (e.has("placement") || e.has("offset")) && requestAnimationFrame(() => this._panel.updatePosition()), e.has("open") && (this._syncVisibleTooltipCount(this.open), this.open ? (this._openOverlay(this._shouldOpenInstantly), this._shouldOpenInstantly = !0) : this._closeOverlay(), this._dispatchChange(this.open)), e.has("content") && this._syncPortalContent();
95
+ e.has("portal") || e.has("overlayContainer") ? requestAnimationFrame(() => this._reconfigureOverlay()) : (e.has("placement") || e.has("offset")) && requestAnimationFrame(() => this._panel.updatePosition()), e.has("open") && (this._syncVisibleTooltipCount(this.open), this.open ? (this._openOverlay(this._shouldOpenInstantly), this._shouldOpenInstantly = !0) : this._closeOverlay(), this._userOpenChange.consume() && this._dispatchChange(this.open)), e.has("content") && this._syncPortalContent();
95
96
  }
96
97
  _show(e = !1) {
97
- this.open ||= (this._shouldOpenInstantly = e, !0);
98
+ this.open ||= (this._shouldOpenInstantly = e, this._userOpenChange.mark(), !0);
98
99
  }
99
100
  _hide() {
100
- this.open &&= !1;
101
+ this.open &&= (this._userOpenChange.mark(), !1);
101
102
  }
102
103
  _openOverlay(e = !1) {
103
104
  this._panel.open(e);
104
105
  }
105
106
  _createPortal() {
106
- let e = o({
107
+ let e = s({
107
108
  container: this.overlayContainer,
108
109
  target: this,
109
- style: `${t}\n${i}\n${s}`,
110
+ style: `${t}\n${a}\n${c}`,
110
111
  className: "tooltip-panel portal wui-glass wui-floating-panel"
111
112
  });
112
113
  if (this.content) {
@@ -143,39 +144,39 @@ var p = [
143
144
  }));
144
145
  }
145
146
  _syncVisibleTooltipCount(e) {
146
- e && !this._isCountedVisible ? (m += 1, this._isCountedVisible = !0) : !e && this._isCountedVisible && (m = Math.max(0, m - 1), this._isCountedVisible = !1);
147
+ e && !this._isCountedVisible ? (h += 1, this._isCountedVisible = !0) : !e && this._isCountedVisible && (h = Math.max(0, h - 1), this._isCountedVisible = !1);
147
148
  }
148
149
  render() {
149
- return l`
150
+ return u`
150
151
  <div class="tooltip-anchor">
151
152
  <div class="tooltip-trigger"><slot></slot></div>
152
153
  <div class="tooltip-panel wui-glass wui-floating-panel" hidden role="tooltip">
153
- ${this.content ? l`<span class="tooltip-text">${this.content}</span>` : l`<slot name="content"></slot>`}
154
+ ${this.content ? u`<span class="tooltip-text">${this.content}</span>` : u`<slot name="content"></slot>`}
154
155
  </div>
155
156
  </div>
156
157
  `;
157
158
  }
158
159
  };
159
- e([f({
160
+ e([p({
160
161
  type: String,
161
162
  reflect: !0
162
- })], h.prototype, "placement", null), e([f({
163
+ })], g.prototype, "placement", null), e([p({
163
164
  type: Number,
164
165
  attribute: "show-delay"
165
- })], h.prototype, "showDelay", null), e([f({
166
+ })], g.prototype, "showDelay", null), e([p({
166
167
  type: Number,
167
168
  attribute: "hide-delay"
168
- })], h.prototype, "hideDelay", null), e([f({
169
+ })], g.prototype, "hideDelay", null), e([p({
169
170
  type: Boolean,
170
171
  reflect: !0
171
- })], h.prototype, "disabled", void 0), e([f({ type: Number })], h.prototype, "offset", null), e([f({ type: String })], h.prototype, "content", void 0), e([f({
172
+ })], g.prototype, "disabled", void 0), e([p({ type: Number })], g.prototype, "offset", null), e([p({ type: String })], g.prototype, "content", void 0), e([p({
172
173
  type: Boolean,
173
174
  reflect: !0
174
- })], h.prototype, "open", void 0), e([f({
175
+ })], g.prototype, "open", void 0), e([p({
175
176
  type: Boolean,
176
177
  reflect: !0
177
- })], h.prototype, "portal", void 0), e([f({ attribute: !1 })], h.prototype, "overlayContainer", void 0), h = e([d("web-ui-tooltip")], h);
178
+ })], g.prototype, "portal", void 0), e([p({ attribute: !1 })], g.prototype, "overlayContainer", void 0), g = e([f("web-ui-tooltip")], g);
178
179
  //#endregion
179
- export { h as WebUiTooltip };
180
+ export { g as WebUiTooltip };
180
181
 
181
182
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/tooltip/index.ts"],"sourcesContent":["import type { Placement } from '@floating-ui/dom'\nimport { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport overlayMotion from '@/assets/overlay-motion.css?inline'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { createOverlayPortal } from '@/shared/overlay/portal'\nimport type { OverlayContainer, OverlayPortal } from '@/shared/overlay/portal'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_PLACEMENTS = [\n 'top',\n 'top-start',\n 'top-end',\n 'bottom',\n 'bottom-start',\n 'bottom-end',\n 'left',\n 'left-start',\n 'left-end',\n 'right',\n 'right-start',\n 'right-end'\n] as const\n\nlet visibleTooltipCount = 0\n\n@customElement('web-ui-tooltip')\nexport class WebUiTooltip extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(style)]\n\n @property({ type: String, reflect: true })\n get placement(): Placement {\n return this._placement\n }\n set placement(v: string) {\n const old = this._placement\n this._placement = normalizeLiteral(v, ALLOWED_PLACEMENTS, 'top')\n this.requestUpdate('placement', old)\n }\n private _placement: Placement = 'top'\n\n @property({ type: Number, attribute: 'show-delay' })\n get showDelay(): number {\n return this._showDelay\n }\n set showDelay(v: number) {\n const old = this._showDelay\n this._showDelay = normalizeNumber(v, 0, 5000, 200)\n this.requestUpdate('showDelay', old)\n }\n private _showDelay = 200\n\n @property({ type: Number, attribute: 'hide-delay' })\n get hideDelay(): number {\n return this._hideDelay\n }\n set hideDelay(v: number) {\n const old = this._hideDelay\n this._hideDelay = normalizeNumber(v, 0, 5000, 100)\n this.requestUpdate('hideDelay', old)\n }\n private _hideDelay = 100\n\n @property({ type: Boolean, reflect: true }) disabled = false\n\n @property({ type: Number })\n get offset(): number {\n return this._offset\n }\n set offset(v: number) {\n const old = this._offset\n this._offset = normalizeNumber(v, 0, 100, 6)\n this.requestUpdate('offset', old)\n }\n private _offset = 6\n\n @property({ type: String }) content = ''\n\n @property({ type: Boolean, reflect: true }) open = false\n @property({ type: Boolean, reflect: true }) portal = false\n @property({ attribute: false }) overlayContainer?: OverlayContainer\n\n private _showTimer?: ReturnType<typeof setTimeout>\n private _hideTimer?: ReturnType<typeof setTimeout>\n private _isCountedVisible = false\n private _shouldOpenInstantly = true\n private readonly _panel = defineAnchoredPanel().make({\n getAnchor: () => this.shadowRoot?.querySelector<HTMLElement>('.tooltip-trigger') ?? null,\n getLocalPanel: () => this.shadowRoot?.querySelector<HTMLElement>('.tooltip-panel') ?? null,\n getPositioning: () => ({\n placement: this.placement,\n offset: this.offset,\n strategy: this.portal ? 'fixed' : 'absolute'\n }),\n isPortal: () => this.portal,\n createPortal: () => this._createPortal()\n })\n\n get isOpen(): boolean {\n return this.open\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this.addEventListener('pointerenter', this._onPointerEnter)\n this.addEventListener('pointerleave', this._onPointerLeave)\n this.addEventListener('focusin', this._onFocusIn)\n this.addEventListener('focusout', this._onFocusOut)\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('pointerenter', this._onPointerEnter)\n this.removeEventListener('pointerleave', this._onPointerLeave)\n this.removeEventListener('focusin', this._onFocusIn)\n this.removeEventListener('focusout', this._onFocusOut)\n clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n this._syncVisibleTooltipCount(false)\n this._panel.dispose()\n }\n\n override firstUpdated() {\n if (this.open) {\n this._openOverlay(this._shouldOpenInstantly)\n this._shouldOpenInstantly = true\n }\n }\n\n protected override updated(changed: Map<string, unknown>) {\n if (changed.has('portal') || changed.has('overlayContainer')) {\n requestAnimationFrame(() => this._reconfigureOverlay())\n } else if (changed.has('placement') || changed.has('offset'))\n requestAnimationFrame(() => this._panel.updatePosition())\n\n if (changed.has('open')) {\n this._syncVisibleTooltipCount(this.open)\n if (this.open) {\n this._openOverlay(this._shouldOpenInstantly)\n this._shouldOpenInstantly = true\n } else {\n void this._closeOverlay()\n }\n this._dispatchChange(this.open)\n }\n if (changed.has('content')) this._syncPortalContent()\n }\n\n private _onPointerEnter = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.disabled) return\n clearTimeout(this._hideTimer)\n this._showTimer = setTimeout(() => this._show(), visibleTooltipCount > 0 ? 0 : this.showDelay)\n }\n\n private _onPointerLeave = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.disabled) return\n clearTimeout(this._showTimer)\n this._hideTimer = setTimeout(() => this._hide(), this.hideDelay)\n }\n\n private _onFocusIn = () => {\n if (this.disabled) return\n clearTimeout(this._hideTimer)\n this._show(true)\n }\n\n private _onFocusOut = () => {\n if (this.disabled) return\n clearTimeout(this._showTimer)\n this._hide()\n }\n\n private _show(isInstant = false) {\n if (this.open) return\n this._shouldOpenInstantly = isInstant\n this.open = true\n }\n\n private _hide() {\n if (!this.open) return\n this.open = false\n }\n\n private _openOverlay(isInstant = false) {\n this._panel.open(isInstant)\n }\n\n private _createPortal(): OverlayPortal {\n const portal = createOverlayPortal({\n container: this.overlayContainer,\n target: this,\n style: `${glass}\\n${overlayMotion}\\n${style}`,\n className: 'tooltip-panel portal wui-glass wui-floating-panel'\n })\n if (this.content) {\n const text = document.createElement('span')\n text.className = 'tooltip-text'\n text.textContent = this.content\n portal.panel.append(text)\n } else portal.moveContent(Array.from(this.querySelectorAll('[slot=\"content\"]')))\n portal.panel.setAttribute('role', 'tooltip')\n return portal\n }\n\n private async _closeOverlay() {\n await this._panel.close(() => this.open)\n }\n\n private _reconfigureOverlay() {\n this._panel.reconfigure(this.open)\n }\n\n private _syncPortalContent() {\n if (!this.portal || !this.open) return\n const panel = this._panel.getPanel()\n if (!panel) return\n const text = panel.querySelector<HTMLElement>('.tooltip-text')\n if (text) {\n text.textContent = this.content\n return\n }\n if (!this.content) return\n panel.replaceChildren()\n const nextText = document.createElement('span')\n nextText.className = 'tooltip-text'\n nextText.textContent = this.content\n panel.append(nextText)\n }\n\n private _dispatchChange(open: boolean) {\n this.dispatchEvent(\n new CustomEvent('open-change', {\n detail: { open },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _syncVisibleTooltipCount(isVisible: boolean) {\n if (isVisible && !this._isCountedVisible) {\n visibleTooltipCount += 1\n this._isCountedVisible = true\n } else if (!isVisible && this._isCountedVisible) {\n visibleTooltipCount = Math.max(0, visibleTooltipCount - 1)\n this._isCountedVisible = false\n }\n }\n\n override render() {\n return html`\n <div class=\"tooltip-anchor\">\n <div class=\"tooltip-trigger\"><slot></slot></div>\n <div class=\"tooltip-panel wui-glass wui-floating-panel\" hidden role=\"tooltip\">\n ${this.content ? html`<span class=\"tooltip-text\">${this.content}</span>` : html`<slot name=\"content\"></slot>`}\n </div>\n </div>\n `\n }\n\n declare readonly $events: {\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-tooltip': WebUiTooltip\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/tooltip/index.ts"],"sourcesContent":["import type { Placement } from '@floating-ui/dom'\nimport { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport overlayMotion from '@/assets/overlay-motion.css?inline'\nimport { UserChangeController } from '@/shared/events/user-change'\nimport { normalizeLiteral, normalizeNumber } from '@/shared/normalize'\nimport { defineAnchoredPanel } from '@/shared/overlay/anchored-panel'\nimport { createOverlayPortal } from '@/shared/overlay/portal'\nimport type { OverlayContainer, OverlayPortal } from '@/shared/overlay/portal'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_PLACEMENTS = [\n 'top',\n 'top-start',\n 'top-end',\n 'bottom',\n 'bottom-start',\n 'bottom-end',\n 'left',\n 'left-start',\n 'left-end',\n 'right',\n 'right-start',\n 'right-end'\n] as const\n\nlet visibleTooltipCount = 0\n\n@customElement('web-ui-tooltip')\nexport class WebUiTooltip extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(overlayMotion), unsafeCSS(style)]\n\n @property({ type: String, reflect: true })\n get placement(): Placement {\n return this._placement\n }\n set placement(v: string) {\n const old = this._placement\n this._placement = normalizeLiteral(v, ALLOWED_PLACEMENTS, 'top')\n this.requestUpdate('placement', old)\n }\n private _placement: Placement = 'top'\n\n @property({ type: Number, attribute: 'show-delay' })\n get showDelay(): number {\n return this._showDelay\n }\n set showDelay(v: number) {\n const old = this._showDelay\n this._showDelay = normalizeNumber(v, 0, 5000, 200)\n this.requestUpdate('showDelay', old)\n }\n private _showDelay = 200\n\n @property({ type: Number, attribute: 'hide-delay' })\n get hideDelay(): number {\n return this._hideDelay\n }\n set hideDelay(v: number) {\n const old = this._hideDelay\n this._hideDelay = normalizeNumber(v, 0, 5000, 100)\n this.requestUpdate('hideDelay', old)\n }\n private _hideDelay = 100\n\n @property({ type: Boolean, reflect: true }) disabled = false\n\n @property({ type: Number })\n get offset(): number {\n return this._offset\n }\n set offset(v: number) {\n const old = this._offset\n this._offset = normalizeNumber(v, 0, 100, 6)\n this.requestUpdate('offset', old)\n }\n private _offset = 6\n\n @property({ type: String }) content = ''\n\n @property({ type: Boolean, reflect: true }) open = false\n @property({ type: Boolean, reflect: true }) portal = false\n @property({ attribute: false }) overlayContainer?: OverlayContainer\n\n private _showTimer?: ReturnType<typeof setTimeout>\n private _hideTimer?: ReturnType<typeof setTimeout>\n private _isCountedVisible = false\n private readonly _userOpenChange = new UserChangeController()\n private _shouldOpenInstantly = true\n private readonly _panel = defineAnchoredPanel().make({\n getAnchor: () => this.shadowRoot?.querySelector<HTMLElement>('.tooltip-trigger') ?? null,\n getLocalPanel: () => this.shadowRoot?.querySelector<HTMLElement>('.tooltip-panel') ?? null,\n getPositioning: () => ({\n placement: this.placement,\n offset: this.offset,\n strategy: this.portal ? 'fixed' : 'absolute'\n }),\n isPortal: () => this.portal,\n createPortal: () => this._createPortal()\n })\n\n get isOpen(): boolean {\n return this.open\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this.addEventListener('pointerenter', this._onPointerEnter)\n this.addEventListener('pointerleave', this._onPointerLeave)\n this.addEventListener('focusin', this._onFocusIn)\n this.addEventListener('focusout', this._onFocusOut)\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('pointerenter', this._onPointerEnter)\n this.removeEventListener('pointerleave', this._onPointerLeave)\n this.removeEventListener('focusin', this._onFocusIn)\n this.removeEventListener('focusout', this._onFocusOut)\n clearTimeout(this._showTimer)\n clearTimeout(this._hideTimer)\n this._syncVisibleTooltipCount(false)\n this._panel.dispose()\n }\n\n override firstUpdated() {\n if (this.open) {\n this._openOverlay(this._shouldOpenInstantly)\n this._shouldOpenInstantly = true\n }\n }\n\n protected override updated(changed: Map<string, unknown>) {\n if (changed.has('portal') || changed.has('overlayContainer')) {\n requestAnimationFrame(() => this._reconfigureOverlay())\n } else if (changed.has('placement') || changed.has('offset'))\n requestAnimationFrame(() => this._panel.updatePosition())\n\n if (changed.has('open')) {\n this._syncVisibleTooltipCount(this.open)\n if (this.open) {\n this._openOverlay(this._shouldOpenInstantly)\n this._shouldOpenInstantly = true\n } else {\n void this._closeOverlay()\n }\n if (this._userOpenChange.consume()) this._dispatchChange(this.open)\n }\n if (changed.has('content')) this._syncPortalContent()\n }\n\n private _onPointerEnter = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.disabled) return\n clearTimeout(this._hideTimer)\n this._showTimer = setTimeout(() => this._show(), visibleTooltipCount > 0 ? 0 : this.showDelay)\n }\n\n private _onPointerLeave = (e: PointerEvent) => {\n if (e.pointerType === 'touch') return\n if (this.disabled) return\n clearTimeout(this._showTimer)\n this._hideTimer = setTimeout(() => this._hide(), this.hideDelay)\n }\n\n private _onFocusIn = () => {\n if (this.disabled) return\n clearTimeout(this._hideTimer)\n this._show(true)\n }\n\n private _onFocusOut = () => {\n if (this.disabled) return\n clearTimeout(this._showTimer)\n this._hide()\n }\n\n private _show(isInstant = false) {\n if (this.open) return\n this._shouldOpenInstantly = isInstant\n this._userOpenChange.mark()\n this.open = true\n }\n\n private _hide() {\n if (!this.open) return\n this._userOpenChange.mark()\n this.open = false\n }\n\n private _openOverlay(isInstant = false) {\n this._panel.open(isInstant)\n }\n\n private _createPortal(): OverlayPortal {\n const portal = createOverlayPortal({\n container: this.overlayContainer,\n target: this,\n style: `${glass}\\n${overlayMotion}\\n${style}`,\n className: 'tooltip-panel portal wui-glass wui-floating-panel'\n })\n if (this.content) {\n const text = document.createElement('span')\n text.className = 'tooltip-text'\n text.textContent = this.content\n portal.panel.append(text)\n } else portal.moveContent(Array.from(this.querySelectorAll('[slot=\"content\"]')))\n portal.panel.setAttribute('role', 'tooltip')\n return portal\n }\n\n private async _closeOverlay() {\n await this._panel.close(() => this.open)\n }\n\n private _reconfigureOverlay() {\n this._panel.reconfigure(this.open)\n }\n\n private _syncPortalContent() {\n if (!this.portal || !this.open) return\n const panel = this._panel.getPanel()\n if (!panel) return\n const text = panel.querySelector<HTMLElement>('.tooltip-text')\n if (text) {\n text.textContent = this.content\n return\n }\n if (!this.content) return\n panel.replaceChildren()\n const nextText = document.createElement('span')\n nextText.className = 'tooltip-text'\n nextText.textContent = this.content\n panel.append(nextText)\n }\n\n private _dispatchChange(open: boolean) {\n this.dispatchEvent(\n new CustomEvent('open-change', {\n detail: { open },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _syncVisibleTooltipCount(isVisible: boolean) {\n if (isVisible && !this._isCountedVisible) {\n visibleTooltipCount += 1\n this._isCountedVisible = true\n } else if (!isVisible && this._isCountedVisible) {\n visibleTooltipCount = Math.max(0, visibleTooltipCount - 1)\n this._isCountedVisible = false\n }\n }\n\n override render() {\n return html`\n <div class=\"tooltip-anchor\">\n <div class=\"tooltip-trigger\"><slot></slot></div>\n <div class=\"tooltip-panel wui-glass wui-floating-panel\" hidden role=\"tooltip\">\n ${this.content ? html`<span class=\"tooltip-text\">${this.content}</span>` : html`<slot name=\"content\"></slot>`}\n </div>\n </div>\n `\n }\n\n declare readonly $events: {\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-tooltip': WebUiTooltip\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ //#region src/shared/events/user-change.ts
2
+ var e = class {
3
+ constructor() {
4
+ this.pending = !1;
5
+ }
6
+ mark() {
7
+ this.pending = !0;
8
+ }
9
+ consume() {
10
+ let e = this.pending;
11
+ return this.pending = !1, e;
12
+ }
13
+ };
14
+ //#endregion
15
+ export { e as UserChangeController };
16
+
17
+ //# sourceMappingURL=user-change.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-change.js","names":[],"sources":["../../../src/shared/events/user-change.ts"],"sourcesContent":["/**\n * Tracks whether the next reactive state update was caused by user interaction.\n *\n * Lit updates are asynchronous, so a boolean that is reset immediately after\n * assigning a property would be lost before `updated()` runs. Components use\n * this small controller to keep `*-change` events user-originated only.\n */\nexport class UserChangeController {\n private pending = false\n\n mark() {\n this.pending = true\n }\n\n consume(): boolean {\n const pending = this.pending\n this.pending = false\n return pending\n }\n}\n"],"mappings":";AAOA,IAAa,IAAb,MAAkC;;EACd,KAAA,UAAA;;CAElB,OAAO;EACL,KAAK,UAAU;CACjB;CAEA,UAAmB;EACjB,IAAM,IAAU,KAAK;EAErB,OADA,KAAK,UAAU,IACR;CACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/shared/normalize/index.ts"],"sourcesContent":["/**\n * 运行时参数规范化工具。\n *\n * 组件的属性 setter 在赋值前调用这些函数,确保非法输入回退到文档化默认值。\n * 这与 TypeScript 类型系统互补——类型保证编译期安全,运行时规范化保证 JS 调用方的健壮性。\n *\n * 使用方式:\n * ```\n * import { normalizeLiteral } from '@/shared/normalize'\n *\n * @property({ type: String, reflect: true })\n * get variant(): 'primary' | 'secondary' | 'ghost' { return this._variant }\n * set variant(v: string) {\n * this._variant = normalizeLiteral(v, ALLOWED_VARIANTS, 'primary')\n * this.requestUpdate('variant', old)\n * }\n * ```\n */\n\n/** 字面量联合类型属性可接受的值 */\nexport type LiteralValues<T extends string> = readonly T[]\n\n/**\n * 将输入值规范化为字面量联合类型之一。\n * 不在允许集合中的值回退到默认值。\n */\nexport function normalizeLiteral<T extends string>(value: unknown, allowed: LiteralValues<T>, defaultValue: T): T {\n if (typeof value === 'string' && (allowed as readonly string[]).includes(value)) {\n return value as T\n }\n return defaultValue\n}\n\n/**\n * 将输入值规范化为指定范围内的数值。\n * NaN、Infinity 或非数值回退到默认值。\n */\nexport function normalizeNumber(value: unknown, min: number, max: number, defaultValue: number): number {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return Math.min(max, Math.max(min, value))\n }\n return defaultValue\n}\n"],"mappings":";AA0BA,SAAgB,EAAmC,GAAgB,GAA2B,GAAoB;CAIhH,OAHI,OAAO,KAAU,YAAa,EAA8B,SAAS,CAAK,IACrE,IAEF;AACT;AAMA,SAAgB,EAAgB,GAAgB,GAAa,GAAa,GAA8B;CAItG,OAHI,OAAO,KAAU,YAAY,OAAO,SAAS,CAAK,IAC7C,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,CAAK,CAAC,IAEpC;AACT"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/shared/normalize/index.ts"],"sourcesContent":["/**\n * 运行时参数规范化工具。\n *\n * 组件的属性 setter 在赋值前调用这些函数,确保非法输入回退到文档化默认值。\n * 这与 TypeScript 类型系统互补——类型保证编译期安全,运行时规范化保证 JS 调用方的健壮性。\n *\n * 使用方式:\n * ```\n * import { normalizeLiteral } from '@/shared/normalize'\n *\n * @property({ type: String, reflect: true })\n * get variant(): 'primary' | 'secondary' | 'ghost' { return this._variant }\n * set variant(v: string) {\n * this._variant = normalizeLiteral(v, ALLOWED_VARIANTS, 'primary')\n * this.requestUpdate('variant', old)\n * }\n * ```\n */\n\n// 字面量联合类型属性可接受的值\nexport type LiteralValues<T extends string> = readonly T[]\n\n/**\n * 将输入值规范化为字面量联合类型之一。\n * 不在允许集合中的值回退到默认值。\n */\nexport function normalizeLiteral<T extends string>(value: unknown, allowed: LiteralValues<T>, defaultValue: T): T {\n if (typeof value === 'string' && (allowed as readonly string[]).includes(value)) {\n return value as T\n }\n return defaultValue\n}\n\n/**\n * 将输入值规范化为指定范围内的数值。\n * NaN、Infinity 或非数值回退到默认值。\n */\nexport function normalizeNumber(value: unknown, min: number, max: number, defaultValue: number): number {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return Math.min(max, Math.max(min, value))\n }\n return defaultValue\n}\n"],"mappings":";AA0BA,SAAgB,EAAmC,GAAgB,GAA2B,GAAoB;CAIhH,OAHI,OAAO,KAAU,YAAa,EAA8B,SAAS,CAAK,IACrE,IAEF;AACT;AAMA,SAAgB,EAAgB,GAAgB,GAAa,GAAa,GAA8B;CAItG,OAHI,OAAO,KAAU,YAAY,OAAO,SAAS,CAAK,IAC7C,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,CAAK,CAAC,IAEpC;AACT"}
@@ -11,9 +11,14 @@ var n = () => t((t) => {
11
11
  !e || !i || t.isOpen() || (a(), i = !1, e.classList.remove("is-closing", "is-visible"), e.open && e.close?.());
12
12
  }, c = () => {
13
13
  let e = t.getDialog();
14
- e && (i = !1, a(), e.classList.remove("is-closing"), e.open || e.showModal?.(), o(), r = requestAnimationFrame(() => {
15
- r = void 0, !(!t.isConnected() || !t.isOpen() || !e.open) && e.classList.add("is-visible");
16
- }));
14
+ if (e) {
15
+ if (i = !1, a(), e.classList.remove("is-closing"), !e.open) try {
16
+ e.showModal?.();
17
+ } catch {}
18
+ o(), r = requestAnimationFrame(() => {
19
+ r = void 0, !(!t.isConnected() || !t.isOpen() || !e.open) && e.classList.add("is-visible");
20
+ });
21
+ }
17
22
  }, l = () => {
18
23
  let r = t.getDialog();
19
24
  if (r?.open) {
@@ -1 +1 @@
1
- {"version":3,"file":"native-dialog-presence.js","names":[],"sources":["../../../src/shared/overlay/native-dialog-presence.ts"],"sourcesContent":["import { definePlugin } from '@greypan/js-kit'\n\nimport { getTransitionDuration } from './presence'\n\nexport interface NativeDialogPresenceOptions {\n getDialog(): HTMLDialogElement | null\n isConnected(): boolean\n isOpen(): boolean\n}\n\nexport interface NativeDialogPresenceApi {\n sync(open: boolean): void\n handleTransitionEnd(event: TransitionEvent): void\n handleNativeClose(): void\n dispose(): void\n}\n\n/** 管理原生 dialog 保持在 top layer 直至退出动画完成的生命周期。 */\nexport const defineNativeDialogPresence = () =>\n definePlugin<NativeDialogPresenceApi, NativeDialogPresenceOptions>(ctx => {\n let closeFallbackTimer: ReturnType<typeof setTimeout> | undefined\n let openFrame: number | undefined\n let isClosing = false\n\n const clearCloseFallback = () => {\n if (closeFallbackTimer === undefined) return\n clearTimeout(closeFallbackTimer)\n closeFallbackTimer = undefined\n }\n\n const cancelOpenFrame = () => {\n if (openFrame === undefined) return\n cancelAnimationFrame(openFrame)\n openFrame = undefined\n }\n\n const finishClosing = () => {\n const dialog = ctx.getDialog()\n if (!dialog || !isClosing || ctx.isOpen()) return\n clearCloseFallback()\n isClosing = false\n dialog.classList.remove('is-closing', 'is-visible')\n if (dialog.open) dialog.close?.()\n }\n\n const startOpening = () => {\n const dialog = ctx.getDialog()\n if (!dialog) return\n isClosing = false\n clearCloseFallback()\n dialog.classList.remove('is-closing')\n if (!dialog.open) dialog.showModal?.()\n\n cancelOpenFrame()\n openFrame = requestAnimationFrame(() => {\n openFrame = undefined\n if (!ctx.isConnected() || !ctx.isOpen() || !dialog.open) return\n dialog.classList.add('is-visible')\n })\n }\n\n const startClosing = () => {\n const dialog = ctx.getDialog()\n if (!dialog?.open) return\n cancelOpenFrame()\n isClosing = true\n if (!dialog.classList.contains('is-visible')) {\n finishClosing()\n return\n }\n\n dialog.classList.add('is-closing')\n dialog.classList.remove('is-visible')\n clearCloseFallback()\n closeFallbackTimer = setTimeout(() => finishClosing(), getTransitionDuration(dialog) + 80)\n }\n\n return {\n sync(open) {\n if (open) startOpening()\n else startClosing()\n },\n\n handleTransitionEnd(event) {\n if (event.target !== ctx.getDialog() || event.propertyName !== 'transform') return\n finishClosing()\n },\n\n handleNativeClose() {\n cancelOpenFrame()\n clearCloseFallback()\n isClosing = false\n ctx.getDialog()?.classList.remove('is-closing', 'is-visible')\n },\n\n dispose() {\n cancelOpenFrame()\n clearCloseFallback()\n isClosing = false\n }\n }\n })\n"],"mappings":";;;AAkBA,IAAa,UACX,GAAmE,MAAO;CACxE,IAAI,GACA,GACA,IAAY,IAEV,UAA2B;EAC3B,MAAuB,KAAA,MAC3B,aAAa,CAAkB,GAC/B,IAAqB,KAAA;CACvB,GAEM,UAAwB;EACxB,MAAc,KAAA,MAClB,qBAAqB,CAAS,GAC9B,IAAY,KAAA;CACd,GAEM,UAAsB;EAC1B,IAAM,IAAS,EAAI,UAAU;EACzB,CAAC,KAAU,CAAC,KAAa,EAAI,OAAO,MACxC,EAAmB,GACnB,IAAY,IACZ,EAAO,UAAU,OAAO,cAAc,YAAY,GAC9C,EAAO,QAAM,EAAO,QAAQ;CAClC,GAEM,UAAqB;EACzB,IAAM,IAAS,EAAI,UAAU;EACxB,MACL,IAAY,IACZ,EAAmB,GACnB,EAAO,UAAU,OAAO,YAAY,GAC/B,EAAO,QAAM,EAAO,YAAY,GAErC,EAAgB,GAChB,IAAY,4BAA4B;GACtC,IAAY,KAAA,GACR,GAAC,EAAI,YAAY,KAAK,CAAC,EAAI,OAAO,KAAK,CAAC,EAAO,SACnD,EAAO,UAAU,IAAI,YAAY;EACnC,CAAC;CACH,GAEM,UAAqB;EACzB,IAAM,IAAS,EAAI,UAAU;EACxB,OAAQ,MAGb;OAFA,EAAgB,GAChB,IAAY,IACR,CAAC,EAAO,UAAU,SAAS,YAAY,GAAG;IAC5C,EAAc;IACd;GACF;GAKA,AAHA,EAAO,UAAU,IAAI,YAAY,GACjC,EAAO,UAAU,OAAO,YAAY,GACpC,EAAmB,GACnB,IAAqB,iBAAiB,EAAc,GAAG,EAAsB,CAAM,IAAI,EAAE;EALzF;CAMF;CAEA,OAAO;EACL,KAAK,GAAM;GACT,AAAI,IAAM,EAAa,IAClB,EAAa;EACpB;EAEA,oBAAoB,GAAO;GACrB,EAAM,WAAW,EAAI,UAAU,KAAK,EAAM,iBAAiB,eAC/D,EAAc;EAChB;EAEA,oBAAoB;GAIlB,AAHA,EAAgB,GAChB,EAAmB,GACnB,IAAY,IACZ,EAAI,UAAU,CAAC,EAAE,UAAU,OAAO,cAAc,YAAY;EAC9D;EAEA,UAAU;GAGR,AAFA,EAAgB,GAChB,EAAmB,GACnB,IAAY;EACd;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"native-dialog-presence.js","names":[],"sources":["../../../src/shared/overlay/native-dialog-presence.ts"],"sourcesContent":["import { definePlugin } from '@greypan/js-kit'\n\nimport { getTransitionDuration } from './presence'\n\nexport interface NativeDialogPresenceOptions {\n getDialog(): HTMLDialogElement | null\n isConnected(): boolean\n isOpen(): boolean\n}\n\nexport interface NativeDialogPresenceApi {\n sync(open: boolean): void\n handleTransitionEnd(event: TransitionEvent): void\n handleNativeClose(): void\n dispose(): void\n}\n\n// 管理原生 dialog 保持在 top layer 直至退出动画完成的生命周期。\nexport const defineNativeDialogPresence = () =>\n definePlugin<NativeDialogPresenceApi, NativeDialogPresenceOptions>(ctx => {\n let closeFallbackTimer: ReturnType<typeof setTimeout> | undefined\n let openFrame: number | undefined\n let isClosing = false\n\n const clearCloseFallback = () => {\n if (closeFallbackTimer === undefined) return\n clearTimeout(closeFallbackTimer)\n closeFallbackTimer = undefined\n }\n\n const cancelOpenFrame = () => {\n if (openFrame === undefined) return\n cancelAnimationFrame(openFrame)\n openFrame = undefined\n }\n\n const finishClosing = () => {\n const dialog = ctx.getDialog()\n if (!dialog || !isClosing || ctx.isOpen()) return\n clearCloseFallback()\n isClosing = false\n dialog.classList.remove('is-closing', 'is-visible')\n if (dialog.open) dialog.close?.()\n }\n\n const startOpening = () => {\n const dialog = ctx.getDialog()\n if (!dialog) return\n isClosing = false\n clearCloseFallback()\n dialog.classList.remove('is-closing')\n if (!dialog.open) {\n try {\n dialog.showModal?.()\n } catch {\n // 顶层已有其他 modal dialog 时 showModal 抛 InvalidStateError;\n // 记录未打开状态,由 rAF 回调中的 dialog.open 判断中止动画\n }\n }\n\n cancelOpenFrame()\n openFrame = requestAnimationFrame(() => {\n openFrame = undefined\n if (!ctx.isConnected() || !ctx.isOpen() || !dialog.open) return\n dialog.classList.add('is-visible')\n })\n }\n\n const startClosing = () => {\n const dialog = ctx.getDialog()\n if (!dialog?.open) return\n cancelOpenFrame()\n isClosing = true\n if (!dialog.classList.contains('is-visible')) {\n finishClosing()\n return\n }\n\n dialog.classList.add('is-closing')\n dialog.classList.remove('is-visible')\n clearCloseFallback()\n closeFallbackTimer = setTimeout(() => finishClosing(), getTransitionDuration(dialog) + 80)\n }\n\n return {\n sync(open) {\n if (open) startOpening()\n else startClosing()\n },\n\n handleTransitionEnd(event) {\n if (event.target !== ctx.getDialog() || event.propertyName !== 'transform') return\n finishClosing()\n },\n\n handleNativeClose() {\n cancelOpenFrame()\n clearCloseFallback()\n isClosing = false\n ctx.getDialog()?.classList.remove('is-closing', 'is-visible')\n },\n\n dispose() {\n cancelOpenFrame()\n clearCloseFallback()\n isClosing = false\n }\n }\n })\n"],"mappings":";;;AAkBA,IAAa,UACX,GAAmE,MAAO;CACxE,IAAI,GACA,GACA,IAAY,IAEV,UAA2B;EAC3B,MAAuB,KAAA,MAC3B,aAAa,CAAkB,GAC/B,IAAqB,KAAA;CACvB,GAEM,UAAwB;EACxB,MAAc,KAAA,MAClB,qBAAqB,CAAS,GAC9B,IAAY,KAAA;CACd,GAEM,UAAsB;EAC1B,IAAM,IAAS,EAAI,UAAU;EACzB,CAAC,KAAU,CAAC,KAAa,EAAI,OAAO,MACxC,EAAmB,GACnB,IAAY,IACZ,EAAO,UAAU,OAAO,cAAc,YAAY,GAC9C,EAAO,QAAM,EAAO,QAAQ;CAClC,GAEM,UAAqB;EACzB,IAAM,IAAS,EAAI,UAAU;EACxB,OAIL;OAHA,IAAY,IACZ,EAAmB,GACnB,EAAO,UAAU,OAAO,YAAY,GAChC,CAAC,EAAO,MACV,IAAI;IACF,EAAO,YAAY;GACrB,QAAQ,CAGR;GAIF,AADA,EAAgB,GAChB,IAAY,4BAA4B;IACtC,IAAY,KAAA,GACR,GAAC,EAAI,YAAY,KAAK,CAAC,EAAI,OAAO,KAAK,CAAC,EAAO,SACnD,EAAO,UAAU,IAAI,YAAY;GACnC,CAAC;EARC;CASJ,GAEM,UAAqB;EACzB,IAAM,IAAS,EAAI,UAAU;EACxB,OAAQ,MAGb;OAFA,EAAgB,GAChB,IAAY,IACR,CAAC,EAAO,UAAU,SAAS,YAAY,GAAG;IAC5C,EAAc;IACd;GACF;GAKA,AAHA,EAAO,UAAU,IAAI,YAAY,GACjC,EAAO,UAAU,OAAO,YAAY,GACpC,EAAmB,GACnB,IAAqB,iBAAiB,EAAc,GAAG,EAAsB,CAAM,IAAI,EAAE;EALzF;CAMF;CAEA,OAAO;EACL,KAAK,GAAM;GACT,AAAI,IAAM,EAAa,IAClB,EAAa;EACpB;EAEA,oBAAoB,GAAO;GACrB,EAAM,WAAW,EAAI,UAAU,KAAK,EAAM,iBAAiB,eAC/D,EAAc;EAChB;EAEA,oBAAoB;GAIlB,AAHA,EAAgB,GAChB,EAAmB,GACnB,IAAY,IACZ,EAAI,UAAU,CAAC,EAAE,UAAU,OAAO,cAAc,YAAY;EAC9D;EAEA,UAAU;GAGR,AAFA,EAAgB,GAChB,EAAmB,GACnB,IAAY;EACd;CACF;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.js","names":[],"sources":["../../../src/shared/overlay/overlay.ts"],"sourcesContent":["import {\n autoUpdate,\n computePosition,\n flip,\n offset,\n shift,\n size,\n type Middleware,\n type Placement,\n type Strategy\n} from '@floating-ui/dom'\nimport { definePlugin } from '@greypan/js-kit'\n\nexport interface OverlayOptions {\n placement?: Placement\n offset?: number\n flip?: boolean\n shift?: boolean\n /** Sync overlay width to anchor width */\n matchWidth?: boolean\n /** Set overlay min-width to anchor width (content can expand wider) */\n minAnchorWidth?: boolean\n strategy?: Strategy\n}\n\nexport interface OverlayApi {\n isOpen(): boolean\n readonly options: Required<OverlayOptions>\n open(): void\n close(): void\n toggle(): void\n update(options: Partial<OverlayOptions>): void\n updateAnchor(anchor: HTMLElement): void\n dispose(): void\n}\n\nconst DEFAULT_OPTIONS: Required<OverlayOptions> = {\n placement: 'bottom-start',\n offset: 4,\n flip: true,\n shift: true,\n matchWidth: false,\n minAnchorWidth: false,\n strategy: 'absolute'\n}\n\nfunction getTransformOrigin(placement: Placement): string {\n const [side, alignment] = placement.split('-')\n const horizontalOrigin = alignment === 'start' ? 'left' : alignment === 'end' ? 'right' : 'center'\n const verticalOrigin = alignment === 'start' ? 'top' : alignment === 'end' ? 'bottom' : 'center'\n\n if (side === 'top') return `bottom ${horizontalOrigin}`\n if (side === 'bottom') return `top ${horizontalOrigin}`\n if (side === 'left') return `right ${verticalOrigin}`\n return `left ${verticalOrigin}`\n}\n\nexport const defineOverlay = () =>\n definePlugin<OverlayApi, { anchor: HTMLElement; overlay: HTMLElement } & OverlayOptions>(ctx => {\n const options: Required<OverlayOptions> = {\n placement: ctx.placement ?? DEFAULT_OPTIONS.placement,\n offset: ctx.offset ?? DEFAULT_OPTIONS.offset,\n flip: ctx.flip ?? DEFAULT_OPTIONS.flip,\n shift: ctx.shift ?? DEFAULT_OPTIONS.shift,\n matchWidth: ctx.matchWidth ?? DEFAULT_OPTIONS.matchWidth,\n minAnchorWidth: ctx.minAnchorWidth ?? DEFAULT_OPTIONS.minAnchorWidth,\n strategy: ctx.strategy ?? DEFAULT_OPTIONS.strategy\n }\n\n const overlay = ctx.overlay\n let isOpen = false\n let cleanup: (() => void) | null = null\n let anchor = ctx.anchor\n\n function updatePosition() {\n const middleware: Middleware[] = [offset(options.offset)]\n if (options.flip) middleware.push(flip())\n if (options.shift) middleware.push(shift({ padding: 8 }))\n if (options.matchWidth) {\n middleware.push(\n size({\n apply({ rects }) {\n overlay.style.width = `${rects.reference.width}px`\n }\n })\n )\n } else if (options.minAnchorWidth) {\n middleware.push(\n size({\n apply({ rects }) {\n overlay.style.minWidth = `${Math.max(rects.reference.width, 120)}px`\n }\n })\n )\n }\n\n cleanup?.()\n cleanup = autoUpdate(anchor, overlay, () => {\n void computePosition(anchor, overlay, {\n placement: options.placement,\n strategy: options.strategy,\n middleware\n }).then(({ x, y, placement }) => {\n overlay.style.left = `${x}px`\n overlay.style.top = `${y}px`\n overlay.style.setProperty('--wui-overlay-transform-origin', getTransformOrigin(placement))\n })\n })\n }\n\n return {\n isOpen() {\n return isOpen\n },\n options,\n\n open() {\n if (isOpen) return\n isOpen = true\n overlay.style.display = ''\n updatePosition()\n },\n\n close() {\n if (!isOpen) return\n isOpen = false\n cleanup?.()\n cleanup = null\n },\n\n toggle() {\n if (isOpen) this.close()\n else this.open()\n },\n\n update(nextOptions) {\n Object.assign(options, nextOptions)\n if (isOpen) updatePosition()\n },\n\n updateAnchor(newAnchor: HTMLElement) {\n anchor = newAnchor\n if (isOpen) updatePosition()\n },\n\n dispose() {\n this.close()\n }\n }\n })\n"],"mappings":";;;AAoCA,IAAM,IAA4C;CAChD,WAAW;CACX,QAAQ;CACR,MAAM;CACN,OAAO;CACP,YAAY;CACZ,gBAAgB;CAChB,UAAU;AACZ;AAEA,SAAS,EAAmB,GAA8B;CACxD,IAAM,CAAC,GAAM,KAAa,EAAU,MAAM,GAAG,GACvC,IAAmB,MAAc,UAAU,SAAS,MAAc,QAAQ,UAAU,UACpF,IAAiB,MAAc,UAAU,QAAQ,MAAc,QAAQ,WAAW;CAKxF,OAHI,MAAS,QAAc,UAAU,MACjC,MAAS,WAAiB,OAAO,MACjC,MAAS,SAAe,SAAS,MAC9B,QAAQ;AACjB;AAEA,IAAa,UACX,GAAyF,MAAO;CAC9F,IAAM,IAAoC;EACxC,WAAW,EAAI,aAAa,EAAgB;EAC5C,QAAQ,EAAI,UAAU,EAAgB;EACtC,MAAM,EAAI,QAAQ,EAAgB;EAClC,OAAO,EAAI,SAAS,EAAgB;EACpC,YAAY,EAAI,cAAc,EAAgB;EAC9C,gBAAgB,EAAI,kBAAkB,EAAgB;EACtD,UAAU,EAAI,YAAY,EAAgB;CAC5C,GAEM,IAAU,EAAI,SAChB,IAAS,IACT,IAA+B,MAC/B,IAAS,EAAI;CAEjB,SAAS,IAAiB;EACxB,IAAM,IAA2B,CAAC,EAAO,EAAQ,MAAM,CAAC;EAsBxD,AArBI,EAAQ,QAAM,EAAW,KAAK,EAAK,CAAC,GACpC,EAAQ,SAAO,EAAW,KAAK,EAAM,EAAE,SAAS,EAAE,CAAC,CAAC,GACpD,EAAQ,aACV,EAAW,KACT,EAAK,EACH,MAAM,EAAE,YAAS;GACf,EAAQ,MAAM,QAAQ,GAAG,EAAM,UAAU,MAAM;EACjD,EACF,CAAC,CACH,IACS,EAAQ,kBACjB,EAAW,KACT,EAAK,EACH,MAAM,EAAE,YAAS;GACf,EAAQ,MAAM,WAAW,GAAG,KAAK,IAAI,EAAM,UAAU,OAAO,GAAG,EAAE;EACnE,EACF,CAAC,CACH,GAGF,IAAU,GACV,IAAU,EAAW,GAAQ,SAAe;GAC1C,EAAqB,GAAQ,GAAS;IACpC,WAAW,EAAQ;IACnB,UAAU,EAAQ;IAClB;GACF,CAAC,CAAC,CAAC,MAAM,EAAE,MAAG,MAAG,mBAAgB;IAG/B,AAFA,EAAQ,MAAM,OAAO,GAAG,EAAE,KAC1B,EAAQ,MAAM,MAAM,GAAG,EAAE,KACzB,EAAQ,MAAM,YAAY,kCAAkC,EAAmB,CAAS,CAAC;GAC3F,CAAC;EACH,CAAC;CACH;CAEA,OAAO;EACL,SAAS;GACP,OAAO;EACT;EACA;EAEA,OAAO;GACD,MACJ,IAAS,IACT,EAAQ,MAAM,UAAU,IACxB,EAAe;EACjB;EAEA,QAAQ;GACD,MACL,IAAS,IACT,IAAU,GACV,IAAU;EACZ;EAEA,SAAS;GACP,AAAI,IAAQ,KAAK,MAAM,IAClB,KAAK,KAAK;EACjB;EAEA,OAAO,GAAa;GAElB,AADA,OAAO,OAAO,GAAS,CAAW,GAC9B,KAAQ,EAAe;EAC7B;EAEA,aAAa,GAAwB;GAEnC,AADA,IAAS,GACL,KAAQ,EAAe;EAC7B;EAEA,UAAU;GACR,KAAK,MAAM;EACb;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"overlay.js","names":[],"sources":["../../../src/shared/overlay/overlay.ts"],"sourcesContent":["import {\n autoUpdate,\n computePosition,\n flip,\n offset,\n shift,\n size,\n type Middleware,\n type Placement,\n type Strategy\n} from '@floating-ui/dom'\nimport { definePlugin } from '@greypan/js-kit'\n\nexport interface OverlayOptions {\n placement?: Placement\n offset?: number\n flip?: boolean\n shift?: boolean\n // Sync overlay width to anchor width\n matchWidth?: boolean\n // Set overlay min-width to anchor width (content can expand wider)\n minAnchorWidth?: boolean\n strategy?: Strategy\n}\n\nexport interface OverlayApi {\n isOpen(): boolean\n readonly options: Required<OverlayOptions>\n open(): void\n close(): void\n toggle(): void\n update(options: Partial<OverlayOptions>): void\n updateAnchor(anchor: HTMLElement): void\n dispose(): void\n}\n\nconst DEFAULT_OPTIONS: Required<OverlayOptions> = {\n placement: 'bottom-start',\n offset: 4,\n flip: true,\n shift: true,\n matchWidth: false,\n minAnchorWidth: false,\n strategy: 'absolute'\n}\n\nfunction getTransformOrigin(placement: Placement): string {\n const [side, alignment] = placement.split('-')\n const horizontalOrigin = alignment === 'start' ? 'left' : alignment === 'end' ? 'right' : 'center'\n const verticalOrigin = alignment === 'start' ? 'top' : alignment === 'end' ? 'bottom' : 'center'\n\n if (side === 'top') return `bottom ${horizontalOrigin}`\n if (side === 'bottom') return `top ${horizontalOrigin}`\n if (side === 'left') return `right ${verticalOrigin}`\n return `left ${verticalOrigin}`\n}\n\nexport const defineOverlay = () =>\n definePlugin<OverlayApi, { anchor: HTMLElement; overlay: HTMLElement } & OverlayOptions>(ctx => {\n const options: Required<OverlayOptions> = {\n placement: ctx.placement ?? DEFAULT_OPTIONS.placement,\n offset: ctx.offset ?? DEFAULT_OPTIONS.offset,\n flip: ctx.flip ?? DEFAULT_OPTIONS.flip,\n shift: ctx.shift ?? DEFAULT_OPTIONS.shift,\n matchWidth: ctx.matchWidth ?? DEFAULT_OPTIONS.matchWidth,\n minAnchorWidth: ctx.minAnchorWidth ?? DEFAULT_OPTIONS.minAnchorWidth,\n strategy: ctx.strategy ?? DEFAULT_OPTIONS.strategy\n }\n\n const overlay = ctx.overlay\n let isOpen = false\n let cleanup: (() => void) | null = null\n let anchor = ctx.anchor\n\n function updatePosition() {\n const middleware: Middleware[] = [offset(options.offset)]\n if (options.flip) middleware.push(flip())\n if (options.shift) middleware.push(shift({ padding: 8 }))\n if (options.matchWidth) {\n middleware.push(\n size({\n apply({ rects }) {\n overlay.style.width = `${rects.reference.width}px`\n }\n })\n )\n } else if (options.minAnchorWidth) {\n middleware.push(\n size({\n apply({ rects }) {\n overlay.style.minWidth = `${Math.max(rects.reference.width, 120)}px`\n }\n })\n )\n }\n\n cleanup?.()\n cleanup = autoUpdate(anchor, overlay, () => {\n void computePosition(anchor, overlay, {\n placement: options.placement,\n strategy: options.strategy,\n middleware\n }).then(({ x, y, placement }) => {\n overlay.style.left = `${x}px`\n overlay.style.top = `${y}px`\n overlay.style.setProperty('--wui-overlay-transform-origin', getTransformOrigin(placement))\n })\n })\n }\n\n return {\n isOpen() {\n return isOpen\n },\n options,\n\n open() {\n if (isOpen) return\n isOpen = true\n overlay.style.display = ''\n updatePosition()\n },\n\n close() {\n if (!isOpen) return\n isOpen = false\n cleanup?.()\n cleanup = null\n },\n\n toggle() {\n if (isOpen) this.close()\n else this.open()\n },\n\n update(nextOptions) {\n Object.assign(options, nextOptions)\n if (isOpen) updatePosition()\n },\n\n updateAnchor(newAnchor: HTMLElement) {\n anchor = newAnchor\n if (isOpen) updatePosition()\n },\n\n dispose() {\n this.close()\n }\n }\n })\n"],"mappings":";;;AAoCA,IAAM,IAA4C;CAChD,WAAW;CACX,QAAQ;CACR,MAAM;CACN,OAAO;CACP,YAAY;CACZ,gBAAgB;CAChB,UAAU;AACZ;AAEA,SAAS,EAAmB,GAA8B;CACxD,IAAM,CAAC,GAAM,KAAa,EAAU,MAAM,GAAG,GACvC,IAAmB,MAAc,UAAU,SAAS,MAAc,QAAQ,UAAU,UACpF,IAAiB,MAAc,UAAU,QAAQ,MAAc,QAAQ,WAAW;CAKxF,OAHI,MAAS,QAAc,UAAU,MACjC,MAAS,WAAiB,OAAO,MACjC,MAAS,SAAe,SAAS,MAC9B,QAAQ;AACjB;AAEA,IAAa,UACX,GAAyF,MAAO;CAC9F,IAAM,IAAoC;EACxC,WAAW,EAAI,aAAa,EAAgB;EAC5C,QAAQ,EAAI,UAAU,EAAgB;EACtC,MAAM,EAAI,QAAQ,EAAgB;EAClC,OAAO,EAAI,SAAS,EAAgB;EACpC,YAAY,EAAI,cAAc,EAAgB;EAC9C,gBAAgB,EAAI,kBAAkB,EAAgB;EACtD,UAAU,EAAI,YAAY,EAAgB;CAC5C,GAEM,IAAU,EAAI,SAChB,IAAS,IACT,IAA+B,MAC/B,IAAS,EAAI;CAEjB,SAAS,IAAiB;EACxB,IAAM,IAA2B,CAAC,EAAO,EAAQ,MAAM,CAAC;EAsBxD,AArBI,EAAQ,QAAM,EAAW,KAAK,EAAK,CAAC,GACpC,EAAQ,SAAO,EAAW,KAAK,EAAM,EAAE,SAAS,EAAE,CAAC,CAAC,GACpD,EAAQ,aACV,EAAW,KACT,EAAK,EACH,MAAM,EAAE,YAAS;GACf,EAAQ,MAAM,QAAQ,GAAG,EAAM,UAAU,MAAM;EACjD,EACF,CAAC,CACH,IACS,EAAQ,kBACjB,EAAW,KACT,EAAK,EACH,MAAM,EAAE,YAAS;GACf,EAAQ,MAAM,WAAW,GAAG,KAAK,IAAI,EAAM,UAAU,OAAO,GAAG,EAAE;EACnE,EACF,CAAC,CACH,GAGF,IAAU,GACV,IAAU,EAAW,GAAQ,SAAe;GAC1C,EAAqB,GAAQ,GAAS;IACpC,WAAW,EAAQ;IACnB,UAAU,EAAQ;IAClB;GACF,CAAC,CAAC,CAAC,MAAM,EAAE,MAAG,MAAG,mBAAgB;IAG/B,AAFA,EAAQ,MAAM,OAAO,GAAG,EAAE,KAC1B,EAAQ,MAAM,MAAM,GAAG,EAAE,KACzB,EAAQ,MAAM,YAAY,kCAAkC,EAAmB,CAAS,CAAC;GAC3F,CAAC;EACH,CAAC;CACH;CAEA,OAAO;EACL,SAAS;GACP,OAAO;EACT;EACA;EAEA,OAAO;GACD,MACJ,IAAS,IACT,EAAQ,MAAM,UAAU,IACxB,EAAe;EACjB;EAEA,QAAQ;GACD,MACL,IAAS,IACT,IAAU,GACV,IAAU;EACZ;EAEA,SAAS;GACP,AAAI,IAAQ,KAAK,MAAM,IAClB,KAAK,KAAK;EACjB;EAEA,OAAO,GAAa;GAElB,AADA,OAAO,OAAO,GAAS,CAAW,GAC9B,KAAQ,EAAe;EAC7B;EAEA,aAAa,GAAwB;GAEnC,AADA,IAAS,GACL,KAAQ,EAAe;EAC7B;EAEA,UAAU;GACR,KAAK,MAAM;EACb;CACF;AACF,CAAC"}
@@ -2,7 +2,9 @@ import { getFallbackOverlayRoot as e } from "../theme/overlay-root.js";
2
2
  import { findNearestTheme as t } from "../theme/theme-scope.js";
3
3
  //#region src/shared/overlay/portal.ts
4
4
  function n(e) {
5
- let t = document.createElement("div"), n = t.attachShadow({ mode: "open" }), i = document.createElement("style");
5
+ let t = document.createElement("div");
6
+ t.style.display = "contents";
7
+ let n = t.attachShadow({ mode: "open" }), i = document.createElement("style");
6
8
  i.textContent = e.style;
7
9
  let a = document.createElement("div");
8
10
  a.className = e.className, a.dataset.wuiPresence = "entering", n.append(i, a), r(e.container, e.target).appendChild(t);
@@ -1 +1 @@
1
- {"version":3,"file":"portal.js","names":[],"sources":["../../../src/shared/overlay/portal.ts"],"sourcesContent":["import { getFallbackOverlayRoot } from '@/shared/theme/overlay-root'\nimport { findNearestTheme } from '@/shared/theme/theme-scope'\n\nexport type OverlayContainer = HTMLElement | (() => HTMLElement | undefined)\n\ninterface OverlayPortalOptions {\n container?: OverlayContainer\n target: Element\n style: string\n className: string\n}\n\nexport interface OverlayPortal {\n readonly panel: HTMLElement\n restoreContent(): void\n moveContent(nodes: Node[], target?: HTMLElement): void\n remove(): void\n}\n\nexport function createOverlayPortal(options: OverlayPortalOptions): OverlayPortal {\n const host = document.createElement('div')\n const root = host.attachShadow({ mode: 'open' })\n const style = document.createElement('style')\n style.textContent = options.style\n const panel = document.createElement('div')\n panel.className = options.className\n panel.dataset.wuiPresence = 'entering'\n root.append(style, panel)\n resolveOverlayContainer(options.container, options.target).appendChild(host)\n\n const nodes: Node[] = []\n return {\n panel,\n moveContent(content, target = panel) {\n nodes.splice(0, nodes.length, ...content)\n target.append(...nodes)\n },\n restoreContent() {\n options.target.append(...nodes)\n nodes.length = 0\n },\n remove() {\n host.remove()\n }\n }\n}\n\nexport function resolveOverlayContainer(container: OverlayContainer | undefined, target: Element): HTMLElement {\n const explicit = typeof container === 'function' ? container() : container\n return explicit ?? findNearestTheme(target)?.getOverlayRoot() ?? getFallbackOverlayRoot()\n}\n"],"mappings":";;;AAmBA,SAAgB,EAAoB,GAA8C;CAChF,IAAM,IAAO,SAAS,cAAc,KAAK,GACnC,IAAO,EAAK,aAAa,EAAE,MAAM,OAAO,CAAC,GACzC,IAAQ,SAAS,cAAc,OAAO;CAC5C,EAAM,cAAc,EAAQ;CAC5B,IAAM,IAAQ,SAAS,cAAc,KAAK;CAI1C,AAHA,EAAM,YAAY,EAAQ,WAC1B,EAAM,QAAQ,cAAc,YAC5B,EAAK,OAAO,GAAO,CAAK,GACxB,EAAwB,EAAQ,WAAW,EAAQ,MAAM,CAAC,CAAC,YAAY,CAAI;CAE3E,IAAM,IAAgB,CAAC;CACvB,OAAO;EACL;EACA,YAAY,GAAS,IAAS,GAAO;GAEnC,AADA,EAAM,OAAO,GAAG,EAAM,QAAQ,GAAG,CAAO,GACxC,EAAO,OAAO,GAAG,CAAK;EACxB;EACA,iBAAiB;GAEf,AADA,EAAQ,OAAO,OAAO,GAAG,CAAK,GAC9B,EAAM,SAAS;EACjB;EACA,SAAS;GACP,EAAK,OAAO;EACd;CACF;AACF;AAEA,SAAgB,EAAwB,GAAyC,GAA8B;CAE7G,QADiB,OAAO,KAAc,aAAa,EAAU,IAAI,MAC9C,EAAiB,CAAM,CAAC,EAAE,eAAe,KAAK,EAAuB;AAC1F"}
1
+ {"version":3,"file":"portal.js","names":[],"sources":["../../../src/shared/overlay/portal.ts"],"sourcesContent":["import { getFallbackOverlayRoot } from '@/shared/theme/overlay-root'\nimport { findNearestTheme } from '@/shared/theme/theme-scope'\n\nexport type OverlayContainer = HTMLElement | (() => HTMLElement | undefined)\n\ninterface OverlayPortalOptions {\n container?: OverlayContainer\n target: Element\n style: string\n className: string\n}\n\nexport interface OverlayPortal {\n readonly panel: HTMLElement\n restoreContent(): void\n moveContent(nodes: Node[], target?: HTMLElement): void\n remove(): void\n}\n\nexport function createOverlayPortal(options: OverlayPortalOptions): OverlayPortal {\n const host = document.createElement('div')\n // 宿主只是固定定位面板的挂载点:注入的组件样式中的 :host 规则(如 display:inline-block)\n // 会匹配到宿主,在块级 overlay 容器里产生匿名行盒,把布局撑开一行。display: contents\n // 让宿主不生成盒;面板本身 position: fixed,定位不受影响。\n host.style.display = 'contents'\n const root = host.attachShadow({ mode: 'open' })\n const style = document.createElement('style')\n style.textContent = options.style\n const panel = document.createElement('div')\n panel.className = options.className\n panel.dataset.wuiPresence = 'entering'\n root.append(style, panel)\n resolveOverlayContainer(options.container, options.target).appendChild(host)\n\n const nodes: Node[] = []\n return {\n panel,\n moveContent(content, target = panel) {\n nodes.splice(0, nodes.length, ...content)\n target.append(...nodes)\n },\n restoreContent() {\n options.target.append(...nodes)\n nodes.length = 0\n },\n remove() {\n host.remove()\n }\n }\n}\n\nexport function resolveOverlayContainer(container: OverlayContainer | undefined, target: Element): HTMLElement {\n const explicit = typeof container === 'function' ? container() : container\n return explicit ?? findNearestTheme(target)?.getOverlayRoot() ?? getFallbackOverlayRoot()\n}\n"],"mappings":";;;AAmBA,SAAgB,EAAoB,GAA8C;CAChF,IAAM,IAAO,SAAS,cAAc,KAAK;CAIzC,EAAK,MAAM,UAAU;CACrB,IAAM,IAAO,EAAK,aAAa,EAAE,MAAM,OAAO,CAAC,GACzC,IAAQ,SAAS,cAAc,OAAO;CAC5C,EAAM,cAAc,EAAQ;CAC5B,IAAM,IAAQ,SAAS,cAAc,KAAK;CAI1C,AAHA,EAAM,YAAY,EAAQ,WAC1B,EAAM,QAAQ,cAAc,YAC5B,EAAK,OAAO,GAAO,CAAK,GACxB,EAAwB,EAAQ,WAAW,EAAQ,MAAM,CAAC,CAAC,YAAY,CAAI;CAE3E,IAAM,IAAgB,CAAC;CACvB,OAAO;EACL;EACA,YAAY,GAAS,IAAS,GAAO;GAEnC,AADA,EAAM,OAAO,GAAG,EAAM,QAAQ,GAAG,CAAO,GACxC,EAAO,OAAO,GAAG,CAAK;EACxB;EACA,iBAAiB;GAEf,AADA,EAAQ,OAAO,OAAO,GAAG,CAAK,GAC9B,EAAM,SAAS;EACjB;EACA,SAAS;GACP,EAAK,OAAO;EACd;CACF;AACF;AAEA,SAAgB,EAAwB,GAAyC,GAA8B;CAE7G,QADiB,OAAO,KAAc,aAAa,EAAU,IAAI,MAC9C,EAAiB,CAAM,CAAC,EAAE,eAAe,KAAK,EAAuB;AAC1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"presence.js","names":[],"sources":["../../../src/shared/overlay/presence.ts"],"sourcesContent":["const DEFAULT_EXIT_DURATION = 160\nconst EXIT_FALLBACK_BUFFER = 80\n\nconst pendingExits = new WeakMap<HTMLElement, () => void>()\n\ninterface OverlayPresenceOptions {\n isInstant?: boolean\n}\n\nfunction parseDuration(value: string): number {\n const trimmed = value.trim()\n if (trimmed.endsWith('ms')) return Number.parseFloat(trimmed)\n if (trimmed.endsWith('s')) return Number.parseFloat(trimmed) * 1000\n return 0\n}\n\n/** 读取元素实际 CSS transition 的最长时长,供可覆盖主题 token 的 JS 生命周期使用。 */\nexport function getTransitionDuration(panel: HTMLElement, fallback = DEFAULT_EXIT_DURATION): number {\n const style = getComputedStyle(panel)\n const durations = style.transitionDuration.split(',').map(parseDuration)\n const delays = style.transitionDelay.split(',').map(parseDuration)\n const longest = durations.reduce(\n (max, duration, index) => Math.max(max, duration + (delays[index] ?? delays[0] ?? 0)),\n 0\n )\n\n return longest || fallback\n}\n\n/** 以可中断的方式显示浮层,避免快速切换时重启动画。 */\nexport function showOverlayPresence(panel: HTMLElement, options: OverlayPresenceOptions = {}) {\n pendingExits.get(panel)?.()\n panel.hidden = false\n if (options.isInstant) {\n panel.dataset.wuiPresence = 'open'\n return\n }\n panel.dataset.wuiPresence = 'entering'\n\n // Commit the initial state so a newly mounted panel has a transition source.\n void panel.offsetWidth\n\n requestAnimationFrame(() => {\n if (panel.dataset.wuiPresence === 'entering') panel.dataset.wuiPresence = 'open'\n })\n}\n\n/** 播放退出过渡;若在结束前重新显示则返回 false。 */\nexport function hideOverlayPresence(panel: HTMLElement): Promise<boolean> {\n pendingExits.get(panel)?.()\n panel.dataset.wuiPresence = 'closing'\n\n // jsdom 等没有计算 CSS transition 的环境无需伪造退场等待。\n if (getTransitionDuration(panel, 0) === 0) {\n panel.hidden = true\n return Promise.resolve(true)\n }\n\n return new Promise(resolve => {\n let settled = false\n const finish = (didClose: boolean) => {\n if (settled) return\n settled = true\n panel.removeEventListener('transitionend', onTransitionEnd)\n clearTimeout(timeout)\n pendingExits.delete(panel)\n if (didClose && panel.dataset.wuiPresence === 'closing') panel.hidden = true\n resolve(didClose)\n }\n\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === panel && (event.propertyName === 'opacity' || event.propertyName === 'transform'))\n finish(true)\n }\n\n pendingExits.set(panel, () => finish(false))\n panel.addEventListener('transitionend', onTransitionEnd)\n const timeout = setTimeout(() => finish(true), getTransitionDuration(panel) + EXIT_FALLBACK_BUFFER)\n })\n}\n"],"mappings":";AAAA,IAGM,oBAAe,IAAI,QAAiC;AAM1D,SAAS,EAAc,GAAuB;CAC5C,IAAM,IAAU,EAAM,KAAK;CAG3B,OAFI,EAAQ,SAAS,IAAI,IAAU,OAAO,WAAW,CAAO,IACxD,EAAQ,SAAS,GAAG,IAAU,OAAO,WAAW,CAAO,IAAI,MACxD;AACT;AAGA,SAAgB,EAAsB,GAAoB,IAAW,KAA+B;CAClG,IAAM,IAAQ,iBAAiB,CAAK,GAC9B,IAAY,EAAM,mBAAmB,MAAM,GAAG,CAAC,CAAC,IAAI,CAAa,GACjE,IAAS,EAAM,gBAAgB,MAAM,GAAG,CAAC,CAAC,IAAI,CAAa;CAMjE,OALgB,EAAU,QACvB,GAAK,GAAU,MAAU,KAAK,IAAI,GAAK,KAAY,EAAO,MAAU,EAAO,MAAM,EAAE,GACpF,CAGK,KAAW;AACpB;AAGA,SAAgB,EAAoB,GAAoB,IAAkC,CAAC,GAAG;CAG5F,IAFA,EAAa,IAAI,CAAK,CAAC,GAAG,GAC1B,EAAM,SAAS,IACX,EAAQ,WAAW;EACrB,EAAM,QAAQ,cAAc;EAC5B;CACF;CAMA,AALA,EAAM,QAAQ,cAAc,YAG5B,EAAW,aAEX,4BAA4B;EAC1B,AAAI,EAAM,QAAQ,gBAAgB,eAAY,EAAM,QAAQ,cAAc;CAC5E,CAAC;AACH;AAGA,SAAgB,EAAoB,GAAsC;CAUxE,OATA,EAAa,IAAI,CAAK,CAAC,GAAG,GAC1B,EAAM,QAAQ,cAAc,WAGxB,EAAsB,GAAO,CAAC,MAAM,KACtC,EAAM,SAAS,IACR,QAAQ,QAAQ,EAAI,KAGtB,IAAI,SAAQ,MAAW;EAC5B,IAAI,IAAU,IACR,KAAU,MAAsB;GAChC,MACJ,IAAU,IACV,EAAM,oBAAoB,iBAAiB,CAAe,GAC1D,aAAa,CAAO,GACpB,EAAa,OAAO,CAAK,GACrB,KAAY,EAAM,QAAQ,gBAAgB,cAAW,EAAM,SAAS,KACxE,EAAQ,CAAQ;EAClB,GAEM,KAAmB,MAA2B;GAClD,AAAI,EAAM,WAAW,MAAU,EAAM,iBAAiB,aAAa,EAAM,iBAAiB,gBACxF,EAAO,EAAI;EACf;EAGA,AADA,EAAa,IAAI,SAAa,EAAO,EAAK,CAAC,GAC3C,EAAM,iBAAiB,iBAAiB,CAAe;EACvD,IAAM,IAAU,iBAAiB,EAAO,EAAI,GAAG,EAAsB,CAAK,IAAI,EAAoB;CACpG,CAAC;AACH"}
1
+ {"version":3,"file":"presence.js","names":[],"sources":["../../../src/shared/overlay/presence.ts"],"sourcesContent":["const DEFAULT_EXIT_DURATION = 160\nconst EXIT_FALLBACK_BUFFER = 80\n\nconst pendingExits = new WeakMap<HTMLElement, () => void>()\n\ninterface OverlayPresenceOptions {\n isInstant?: boolean\n}\n\nfunction parseDuration(value: string): number {\n const trimmed = value.trim()\n if (trimmed.endsWith('ms')) return Number.parseFloat(trimmed)\n if (trimmed.endsWith('s')) return Number.parseFloat(trimmed) * 1000\n return 0\n}\n\n// 读取元素实际 CSS transition 的最长时长,供可覆盖主题 token 的 JS 生命周期使用。\nexport function getTransitionDuration(panel: HTMLElement, fallback = DEFAULT_EXIT_DURATION): number {\n const style = getComputedStyle(panel)\n const durations = style.transitionDuration.split(',').map(parseDuration)\n const delays = style.transitionDelay.split(',').map(parseDuration)\n const longest = durations.reduce(\n (max, duration, index) => Math.max(max, duration + (delays[index] ?? delays[0] ?? 0)),\n 0\n )\n\n return longest || fallback\n}\n\n// 以可中断的方式显示浮层,避免快速切换时重启动画。\nexport function showOverlayPresence(panel: HTMLElement, options: OverlayPresenceOptions = {}) {\n pendingExits.get(panel)?.()\n panel.hidden = false\n if (options.isInstant) {\n panel.dataset.wuiPresence = 'open'\n return\n }\n panel.dataset.wuiPresence = 'entering'\n\n // Commit the initial state so a newly mounted panel has a transition source.\n void panel.offsetWidth\n\n requestAnimationFrame(() => {\n if (panel.dataset.wuiPresence === 'entering') panel.dataset.wuiPresence = 'open'\n })\n}\n\n// 播放退出过渡;若在结束前重新显示则返回 false。\nexport function hideOverlayPresence(panel: HTMLElement): Promise<boolean> {\n pendingExits.get(panel)?.()\n panel.dataset.wuiPresence = 'closing'\n\n // jsdom 等没有计算 CSS transition 的环境无需伪造退场等待。\n if (getTransitionDuration(panel, 0) === 0) {\n panel.hidden = true\n return Promise.resolve(true)\n }\n\n return new Promise(resolve => {\n let settled = false\n const finish = (didClose: boolean) => {\n if (settled) return\n settled = true\n panel.removeEventListener('transitionend', onTransitionEnd)\n clearTimeout(timeout)\n pendingExits.delete(panel)\n if (didClose && panel.dataset.wuiPresence === 'closing') panel.hidden = true\n resolve(didClose)\n }\n\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === panel && (event.propertyName === 'opacity' || event.propertyName === 'transform'))\n finish(true)\n }\n\n pendingExits.set(panel, () => finish(false))\n panel.addEventListener('transitionend', onTransitionEnd)\n const timeout = setTimeout(() => finish(true), getTransitionDuration(panel) + EXIT_FALLBACK_BUFFER)\n })\n}\n"],"mappings":";AAAA,IAGM,oBAAe,IAAI,QAAiC;AAM1D,SAAS,EAAc,GAAuB;CAC5C,IAAM,IAAU,EAAM,KAAK;CAG3B,OAFI,EAAQ,SAAS,IAAI,IAAU,OAAO,WAAW,CAAO,IACxD,EAAQ,SAAS,GAAG,IAAU,OAAO,WAAW,CAAO,IAAI,MACxD;AACT;AAGA,SAAgB,EAAsB,GAAoB,IAAW,KAA+B;CAClG,IAAM,IAAQ,iBAAiB,CAAK,GAC9B,IAAY,EAAM,mBAAmB,MAAM,GAAG,CAAC,CAAC,IAAI,CAAa,GACjE,IAAS,EAAM,gBAAgB,MAAM,GAAG,CAAC,CAAC,IAAI,CAAa;CAMjE,OALgB,EAAU,QACvB,GAAK,GAAU,MAAU,KAAK,IAAI,GAAK,KAAY,EAAO,MAAU,EAAO,MAAM,EAAE,GACpF,CAGK,KAAW;AACpB;AAGA,SAAgB,EAAoB,GAAoB,IAAkC,CAAC,GAAG;CAG5F,IAFA,EAAa,IAAI,CAAK,CAAC,GAAG,GAC1B,EAAM,SAAS,IACX,EAAQ,WAAW;EACrB,EAAM,QAAQ,cAAc;EAC5B;CACF;CAMA,AALA,EAAM,QAAQ,cAAc,YAG5B,EAAW,aAEX,4BAA4B;EAC1B,AAAI,EAAM,QAAQ,gBAAgB,eAAY,EAAM,QAAQ,cAAc;CAC5E,CAAC;AACH;AAGA,SAAgB,EAAoB,GAAsC;CAUxE,OATA,EAAa,IAAI,CAAK,CAAC,GAAG,GAC1B,EAAM,QAAQ,cAAc,WAGxB,EAAsB,GAAO,CAAC,MAAM,KACtC,EAAM,SAAS,IACR,QAAQ,QAAQ,EAAI,KAGtB,IAAI,SAAQ,MAAW;EAC5B,IAAI,IAAU,IACR,KAAU,MAAsB;GAChC,MACJ,IAAU,IACV,EAAM,oBAAoB,iBAAiB,CAAe,GAC1D,aAAa,CAAO,GACpB,EAAa,OAAO,CAAK,GACrB,KAAY,EAAM,QAAQ,gBAAgB,cAAW,EAAM,SAAS,KACxE,EAAQ,CAAQ;EAClB,GAEM,KAAmB,MAA2B;GAClD,AAAI,EAAM,WAAW,MAAU,EAAM,iBAAiB,aAAa,EAAM,iBAAiB,gBACxF,EAAO,EAAI;EACf;EAGA,AADA,EAAa,IAAI,SAAa,EAAO,EAAK,CAAC,GAC3C,EAAM,iBAAiB,iBAAiB,CAAe;EACvD,IAAM,IAAU,iBAAiB,EAAO,EAAI,GAAG,EAAsB,CAAK,IAAI,EAAoB;CACpG,CAAC;AACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greypan/web-ui",
3
- "version": "2.1.5",
3
+ "version": "2.1.8",
4
4
  "description": "Lit-based web components for React, Vue, and vanilla JS",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,8 +41,8 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@floating-ui/dom": "^1.8.0",
44
- "@greypan/browser-kit": "1.7.6",
45
- "@greypan/js-kit": "1.6.5"
44
+ "@greypan/browser-kit": "1.7.7",
45
+ "@greypan/js-kit": "1.6.6"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@iconify-json/jam": "^1.2.3",
@@ -72,7 +72,12 @@
72
72
  }
73
73
  },
74
74
  "browserslist": [
75
- "defaults"
75
+ "Chrome >=111",
76
+ "Edge >=111",
77
+ "Safari >=16.4",
78
+ "iOS >=16.4",
79
+ "Firefox >=128",
80
+ "not dead"
76
81
  ],
77
82
  "scripts": {
78
83
  "build": "vp build",