@greypan/web-ui 2.1.7 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.CN.md +95 -41
  2. package/README.md +100 -42
  3. package/dist/assets/glass.js.map +1 -1
  4. package/dist/assets/menu-portal.js +1 -1
  5. package/dist/assets/menu-portal.js.map +1 -1
  6. package/dist/components/autocomplete/index.d.ts +121 -0
  7. package/dist/components/autocomplete/index.js +414 -0
  8. package/dist/components/autocomplete/index.js.map +1 -0
  9. package/dist/components/autocomplete/style.js +6 -0
  10. package/dist/components/autocomplete/style.js.map +1 -0
  11. package/dist/components/avatar/index.d.ts +0 -1
  12. package/dist/components/avatar/index.js +9 -9
  13. package/dist/components/avatar/index.js.map +1 -1
  14. package/dist/components/back-top/index.d.ts +0 -1
  15. package/dist/components/back-top/index.js +1 -1
  16. package/dist/components/back-top/index.js.map +1 -1
  17. package/dist/components/badge/index.d.ts +0 -1
  18. package/dist/components/badge/index.js +5 -5
  19. package/dist/components/badge/index.js.map +1 -1
  20. package/dist/components/button/index.d.ts +6 -2
  21. package/dist/components/button/index.js +40 -19
  22. package/dist/components/button/index.js.map +1 -1
  23. package/dist/components/button/style.js +1 -1
  24. package/dist/components/button/style.js.map +1 -1
  25. package/dist/components/button-group/index.d.ts +0 -1
  26. package/dist/components/button-group/index.js.map +1 -1
  27. package/dist/components/checkbox/index.d.ts +0 -3
  28. package/dist/components/checkbox/index.js +7 -5
  29. package/dist/components/checkbox/index.js.map +1 -1
  30. package/dist/components/checkbox-group/index.js +2 -2
  31. package/dist/components/checkbox-group/index.js.map +1 -1
  32. package/dist/components/context-menu/index.d.ts +4 -3
  33. package/dist/components/context-menu/index.js +47 -50
  34. package/dist/components/context-menu/index.js.map +1 -1
  35. package/dist/components/dialog/index.d.ts +1 -1
  36. package/dist/components/dialog/index.js +20 -19
  37. package/dist/components/dialog/index.js.map +1 -1
  38. package/dist/components/drawer/index.d.ts +2 -3
  39. package/dist/components/drawer/index.js +43 -33
  40. package/dist/components/drawer/index.js.map +1 -1
  41. package/dist/components/drawer/style.js +1 -1
  42. package/dist/components/drawer/style.js.map +1 -1
  43. package/dist/components/dropdown/index.d.ts +2 -9
  44. package/dist/components/dropdown/index.js +58 -53
  45. package/dist/components/dropdown/index.js.map +1 -1
  46. package/dist/components/dropdown-divider/index.d.ts +0 -1
  47. package/dist/components/dropdown-divider/index.js.map +1 -1
  48. package/dist/components/dropdown-header/index.d.ts +0 -1
  49. package/dist/components/dropdown-header/index.js.map +1 -1
  50. package/dist/components/dropdown-item/index.d.ts +0 -2
  51. package/dist/components/dropdown-item/index.js.map +1 -1
  52. package/dist/components/dropdown-item/style.js +1 -1
  53. package/dist/components/dropdown-item/style.js.map +1 -1
  54. package/dist/components/empty/index.d.ts +0 -1
  55. package/dist/components/empty/index.js +6 -6
  56. package/dist/components/empty/index.js.map +1 -1
  57. package/dist/components/icon/index.d.ts +0 -1
  58. package/dist/components/icon/index.js.map +1 -1
  59. package/dist/components/index.d.ts +5 -0
  60. package/dist/components/index.js +36 -35
  61. package/dist/components/input/index.d.ts +3 -0
  62. package/dist/components/input/index.js +48 -24
  63. package/dist/components/input/index.js.map +1 -1
  64. package/dist/components/input/style.js +1 -1
  65. package/dist/components/input/style.js.map +1 -1
  66. package/dist/components/input-number/index.d.ts +2 -0
  67. package/dist/components/input-number/index.js +25 -12
  68. package/dist/components/input-number/index.js.map +1 -1
  69. package/dist/components/input-number/style.js +1 -1
  70. package/dist/components/input-number/style.js.map +1 -1
  71. package/dist/components/layout/index.d.ts +0 -1
  72. package/dist/components/layout/index.js +4 -4
  73. package/dist/components/layout/index.js.map +1 -1
  74. package/dist/components/option/index.d.ts +0 -11
  75. package/dist/components/option/index.js +1 -1
  76. package/dist/components/option/index.js.map +1 -1
  77. package/dist/components/option/style.js +1 -1
  78. package/dist/components/option/style.js.map +1 -1
  79. package/dist/components/popover/index.d.ts +1 -5
  80. package/dist/components/popover/index.js +42 -37
  81. package/dist/components/popover/index.js.map +1 -1
  82. package/dist/components/radio/index.d.ts +0 -3
  83. package/dist/components/radio/index.js +8 -5
  84. package/dist/components/radio/index.js.map +1 -1
  85. package/dist/components/radio-group/index.js +2 -2
  86. package/dist/components/radio-group/index.js.map +1 -1
  87. package/dist/components/segmented/index.js +8 -4
  88. package/dist/components/segmented/index.js.map +1 -1
  89. package/dist/components/segmented-trigger/index.d.ts +1 -0
  90. package/dist/components/segmented-trigger/index.js +12 -3
  91. package/dist/components/segmented-trigger/index.js.map +1 -1
  92. package/dist/components/segmented-trigger/style.js +1 -1
  93. package/dist/components/segmented-trigger/style.js.map +1 -1
  94. package/dist/components/select/index.d.ts +0 -1
  95. package/dist/components/select/index.js +22 -31
  96. package/dist/components/select/index.js.map +1 -1
  97. package/dist/components/select/style.js +1 -1
  98. package/dist/components/select/style.js.map +1 -1
  99. package/dist/components/slider/index.d.ts +0 -2
  100. package/dist/components/slider/index.js +1 -1
  101. package/dist/components/slider/index.js.map +1 -1
  102. package/dist/components/spinner/index.d.ts +0 -3
  103. package/dist/components/spinner/index.js.map +1 -1
  104. package/dist/components/svg-draw-lines/index.d.ts +0 -3
  105. package/dist/components/svg-draw-lines/index.js.map +1 -1
  106. package/dist/components/switch/index.d.ts +0 -1
  107. package/dist/components/switch/index.js +6 -6
  108. package/dist/components/switch/index.js.map +1 -1
  109. package/dist/components/switch/style.js +1 -1
  110. package/dist/components/switch/style.js.map +1 -1
  111. package/dist/components/textarea/index.d.ts +1 -0
  112. package/dist/components/textarea/index.js +51 -34
  113. package/dist/components/textarea/index.js.map +1 -1
  114. package/dist/components/textarea/style.js +1 -1
  115. package/dist/components/textarea/style.js.map +1 -1
  116. package/dist/components/theme/index.d.ts +0 -3
  117. package/dist/components/theme/index.js.map +1 -1
  118. package/dist/components/toast/manager.js.map +1 -1
  119. package/dist/components/toast/style.js +1 -1
  120. package/dist/components/toast/style.js.map +1 -1
  121. package/dist/components/toast/toast.d.ts +0 -4
  122. package/dist/components/toast/toast.js +25 -17
  123. package/dist/components/toast/toast.js.map +1 -1
  124. package/dist/components/toast/types.d.ts +0 -3
  125. package/dist/components/tooltip/index.d.ts +1 -0
  126. package/dist/components/tooltip/index.js +34 -33
  127. package/dist/components/tooltip/index.js.map +1 -1
  128. package/dist/shared/events/user-change.js +17 -0
  129. package/dist/shared/events/user-change.js.map +1 -0
  130. package/dist/shared/menu-portal/menu-portal.js +10 -11
  131. package/dist/shared/menu-portal/menu-portal.js.map +1 -1
  132. package/dist/shared/normalize/index.js.map +1 -1
  133. package/dist/shared/overlay/anchored-panel.js +12 -12
  134. package/dist/shared/overlay/native-dialog-presence.js +8 -3
  135. package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
  136. package/dist/shared/overlay/overlay.js +55 -33
  137. package/dist/shared/overlay/overlay.js.map +1 -1
  138. package/dist/shared/overlay/portal.js +27 -13
  139. package/dist/shared/overlay/portal.js.map +1 -1
  140. package/dist/shared/overlay/presence.js.map +1 -1
  141. package/dist/shared/scroll-lock/scroll-lock.js +13 -12
  142. package/dist/shared/scroll-lock/scroll-lock.js.map +1 -1
  143. package/dist/shared/theme/overlay-root.js +3 -3
  144. package/dist/types/react.d.ts +15 -41
  145. package/dist/types/utils.d.ts +33 -4
  146. package/dist/types/vue.d.ts +17 -49
  147. package/package.json +11 -6
@@ -1,41 +1,44 @@
1
1
  import e from "../../_virtual/_@oxc-project_runtime@0.140.0/helpers/esm/decorate.js";
2
+ import { hideOverlayPresence as t, showOverlayPresence as n } from "../../shared/overlay/presence.js";
3
+ import { defineScrollLockLease as r } from "../../shared/scroll-lock/scroll-lock.js";
2
4
  import "../dropdown-divider/index.js";
3
5
  import "../dropdown-header/index.js";
4
6
  import "../dropdown-item/index.js";
5
- import { createMenuPortalOverlay as t } from "../../shared/menu-portal/menu-portal.js";
6
- import { findFocusedMenuItem as n, focusMenuItem as r, getEnabledMenuItems as i, getMenuChildren as a, getMenuItemFromEvent as o, hideNestedMenuChildren as s, moveMenuChildren as c } from "../../shared/menu-portal/menu-tree.js";
7
- import { hideOverlayPresence as l, showOverlayPresence as u } from "../../shared/overlay/presence.js";
8
- import { createScrollLockLease as d } from "../../shared/scroll-lock/scroll-lock.js";
9
- import f from "./style.js";
10
- import { LitElement as p, html as m, unsafeCSS as h } from "lit";
11
- import { customElement as g, property as _, state as v } from "lit/decorators.js";
7
+ import { UserChangeController as i } from "../../shared/events/user-change.js";
8
+ import { createMenuPortalOverlay as a } from "../../shared/menu-portal/menu-portal.js";
9
+ import { findFocusedMenuItem as o, focusMenuItem as s, getEnabledMenuItems as c, getMenuChildren as l, getMenuItemFromEvent as u, hideNestedMenuChildren as d, moveMenuChildren as f } from "../../shared/menu-portal/menu-tree.js";
10
+ import p from "./style.js";
11
+ import { LitElement as m, html as h, unsafeCSS as g } from "lit";
12
+ import { customElement as _, property as v, state as y } from "lit/decorators.js";
12
13
  //#region src/components/context-menu/index.ts
13
- var y = class extends p {
14
+ var b = class extends m {
14
15
  constructor(...e) {
15
- super(...e), this.disabled = !1, this.noScrollLock = !1, this._isOpen = !1, this._x = 0, this._y = 0, this._activeSubmenus = [], this._activeSubmenuItems = [], this._closingSubmenus = /* @__PURE__ */ new Map(), this._ignoreOutsideClick = !1, this._hoverCleanupFns = [], this._scrollLock = d(), this._shouldOpenInstantly = !0, this._onContextMenu = (e) => {
16
- this.disabled || (e.preventDefault(), this._restoreFocusTarget = e.target instanceof HTMLElement ? e.target : void 0, this._openAt(e.clientX, e.clientY, !1));
16
+ super(...e), this.disabled = !1, this.noScrollLock = !1, this._isOpen = !1, this._x = 0, this._y = 0, this._activeSubmenus = [], this._activeSubmenuItems = [], this._closingSubmenus = /* @__PURE__ */ new Map(), this._ignoreOutsideClick = !1, this._hoverCleanupFns = [], this._scrollLock = r().make(), this._userOpenChange = new i(), this._shouldOpenInstantly = !0, this._closeFromUser = () => {
17
+ this._isOpen && (this._userOpenChange.mark(), this.close());
18
+ }, this._onContextMenu = (e) => {
19
+ this.disabled || (e.preventDefault(), this._restoreFocusTarget = e.target instanceof HTMLElement ? e.target : void 0, this._openAt(e.clientX, e.clientY, !1) && this._userOpenChange.mark());
17
20
  }, this._onContextMenuOutside = (e) => {
18
- this._isOpen && !this._isInsideShadowRoot(e) && this.close();
21
+ this._isOpen && !this._isInsideShadowRoot(e) && this._closeFromUser();
19
22
  }, this._onKeydown = (e) => {
20
23
  if (!this.disabled && (e.key === "ContextMenu" || e.shiftKey && e.key === "F10")) {
21
24
  e.preventDefault();
22
25
  let t = document.activeElement;
23
26
  if (t && t !== document.body) {
24
27
  let e = t.getBoundingClientRect();
25
- this._openAt(e.left, e.bottom, !0);
26
- } else this._openAt(window.innerWidth / 2, window.innerHeight / 2, !0);
28
+ this._openAt(e.left, e.bottom, !0) && this._userOpenChange.mark();
29
+ } else this._openAt(window.innerWidth / 2, window.innerHeight / 2, !0) && this._userOpenChange.mark();
27
30
  return;
28
31
  }
29
32
  }, this._onClickOutside = (e) => {
30
- !this._isOpen || this._ignoreOutsideClick || this._isInsideShadowRoot(e) || this.close();
33
+ !this._isOpen || this._ignoreOutsideClick || this._isInsideShadowRoot(e) || this._closeFromUser();
31
34
  }, this._onMenuClick = (e) => {
32
- let t = o(e);
35
+ let t = u(e);
33
36
  if (!(!t || t.hasAttribute("disabled"))) {
34
37
  if (t.hasAttribute("submenu")) {
35
38
  this._openSubmenu(t);
36
39
  return;
37
40
  }
38
- this.close();
41
+ this._closeFromUser();
39
42
  }
40
43
  }, this._onWheel = (e) => {
41
44
  this._preventBackgroundScroll(e);
@@ -43,7 +46,7 @@ var y = class extends p {
43
46
  this._preventBackgroundScroll(e);
44
47
  }, this._onDocumentKeydown = (e) => {
45
48
  if (!this._isOpen) return;
46
- if (e.key === "Escape" && e.target === this) {
49
+ if (e.key === "Escape") {
47
50
  this._closeLastSubmenuOrMenu(), e.preventDefault();
48
51
  return;
49
52
  }
@@ -85,7 +88,7 @@ var y = class extends p {
85
88
  };
86
89
  }
87
90
  static {
88
- this.styles = h(f);
91
+ this.styles = g(p);
89
92
  }
90
93
  get isOpen() {
91
94
  return this._isOpen;
@@ -107,21 +110,15 @@ var y = class extends p {
107
110
  this._syncScrollLock(!1);
108
111
  return;
109
112
  }
110
- e.has("_isOpen") && (this._isOpen ? (this._syncScrollLock(), this._menu || (this._menu = t("context-menu", this), this._menu.panel.setAttribute("role", "menu"), this._menu.panel.setAttribute("aria-label", "上下文菜单"), this._menu.panel.addEventListener("click", this._onMenuClick)), requestAnimationFrame(() => {
111
- !this._isOpen || !this._menu || (this._setupMenuItems(), this._positionMenu(), u(this._menu.panel, { isInstant: this._shouldOpenInstantly }), this._shouldOpenInstantly = !0, this._focusFirstItem(), this._bindLevelHovers());
112
- })) : (this._syncScrollLock(!1), this._closeMenuAfterPresence()), this._dispatchChange(this._isOpen)), e.has("noScrollLock") && this._syncScrollLock();
113
+ e.has("_isOpen") && (this._isOpen ? (this._syncScrollLock(), this._menu || (this._menu = a("context-menu", this), this._menu.panel.setAttribute("role", "menu"), this._menu.panel.setAttribute("aria-label", "上下文菜单"), this._menu.panel.addEventListener("click", this._onMenuClick)), requestAnimationFrame(() => {
114
+ !this._isOpen || !this._menu || (this._setupMenuItems(), this._positionMenu(), n(this._menu.panel, { isInstant: this._shouldOpenInstantly }), this._shouldOpenInstantly = !0, this._focusFirstItem(), this._bindLevelHovers());
115
+ })) : (this._syncScrollLock(!1), this._closeMenuAfterPresence()), this._userOpenChange.consume() && this._dispatchChange(this._isOpen)), e.has("noScrollLock") && this._syncScrollLock();
113
116
  }
114
117
  openAt(e, t) {
115
118
  this._openAt(e, t, !0);
116
119
  }
117
120
  _openAt(e, t, n) {
118
- if (!this.disabled) {
119
- if (this._x = e, this._y = t, this._shouldOpenInstantly = n, this._ignoreCurrentOutsideClick(), this._isOpen) {
120
- requestAnimationFrame(() => this._positionMenu());
121
- return;
122
- }
123
- this._restoreFocusTarget ??= document.activeElement instanceof HTMLElement ? document.activeElement : void 0, this._isOpen = !0;
124
- }
121
+ return this.disabled ? !1 : (this._x = e, this._y = t, this._shouldOpenInstantly = n, this._ignoreCurrentOutsideClick(), this._isOpen ? (requestAnimationFrame(() => this._positionMenu()), !1) : (this._restoreFocusTarget ??= document.activeElement instanceof HTMLElement ? document.activeElement : void 0, this._isOpen = !0, !0));
125
122
  }
126
123
  close() {
127
124
  this._isOpen &&= !1;
@@ -141,33 +138,33 @@ var y = class extends p {
141
138
  }
142
139
  _setupMenuItems() {
143
140
  let e = this._menu;
144
- e && (this._hideMenuItems(), c(this, e.content));
141
+ e && (this._hideMenuItems(), f(this, e.content));
145
142
  }
146
143
  _returnItemsToSlot() {
147
144
  let e = this._menu;
148
- e && (this._closeSubmenusFrom(0, !0), this._restoreClosingSubmenus(), c(e.content, this));
145
+ e && (this._closeSubmenusFrom(0, !0), this._restoreClosingSubmenus(), f(e.content, this));
149
146
  }
150
147
  async _closeMenuAfterPresence() {
151
148
  let e = this._menu;
152
- e && !await l(e.panel) || this._isOpen || !this.isConnected || this._menu !== e || (this._returnItemsToSlot(), e?.panel.remove(), this._menu = void 0, this._restoreFocusTarget?.focus(), this._restoreFocusTarget = void 0);
149
+ e && !await t(e.panel) || this._isOpen || !this.isConnected || this._menu !== e || (this._returnItemsToSlot(), e?.panel.remove(), this._menu = void 0, this._restoreFocusTarget?.focus(), this._restoreFocusTarget = void 0);
153
150
  }
154
151
  _hideMenuItems() {
155
- a(this).forEach((e) => e.setAttribute("slot", "context-menu-hidden")), s(this, "context-menu-hidden");
152
+ l(this).forEach((e) => e.setAttribute("slot", "context-menu-hidden")), d(this, "context-menu-hidden");
156
153
  }
157
- _openSubmenu(e, n = !1) {
154
+ _openSubmenu(e, t = !1) {
158
155
  if (!this._isOpen || !e.hasAttribute("submenu") || e.hasAttribute("disabled")) return;
159
156
  let r = this._getItemLevel(e);
160
157
  if (r === -1 || this._activeSubmenuItems[r] === e) return;
161
158
  this._closeSubmenusFrom(r);
162
159
  let i = this._closingSubmenus.get(e);
163
160
  if (i) {
164
- this._closingSubmenus.delete(e), this._activeSubmenus[r] = i, this._activeSubmenuItems[r] = e, e.setAttribute("active", ""), this._positionSubmenu(e, i), u(i.panel, { isInstant: n }), this._bindLevelHovers();
161
+ this._closingSubmenus.delete(e), this._activeSubmenus[r] = i, this._activeSubmenuItems[r] = e, e.setAttribute("active", ""), this._positionSubmenu(e, i), n(i.panel, { isInstant: t }), this._bindLevelHovers();
165
162
  return;
166
163
  }
167
- let o = a(e);
164
+ let o = l(e);
168
165
  if (o.length === 0) return;
169
- let s = t("context-submenu", this);
170
- s.panel.dataset.level = String(r), s.panel.setAttribute("role", "menu"), s.panel.setAttribute("aria-label", "子菜单"), s.panel.style.visibility = "hidden", s.panel.addEventListener("click", this._onMenuClick), s.content.append(...o), this._activeSubmenus[r] = s, this._activeSubmenuItems[r] = e, e.setAttribute("active", ""), this._positionSubmenu(e, s), u(s.panel, { isInstant: n }), this._bindLevelHovers();
166
+ let s = a("context-submenu", this);
167
+ s.panel.dataset.level = String(r), s.panel.setAttribute("role", "menu"), s.panel.setAttribute("aria-label", "子菜单"), s.panel.style.visibility = "hidden", s.panel.addEventListener("click", this._onMenuClick), s.content.append(...o), this._activeSubmenus[r] = s, this._activeSubmenuItems[r] = e, e.setAttribute("active", ""), this._positionSubmenu(e, s), n(s.panel, { isInstant: t }), this._bindLevelHovers();
171
168
  }
172
169
  _closeSubmenusFrom(e, t = !1) {
173
170
  for (let n = this._activeSubmenus.length - 1; n >= e; n--) {
@@ -176,11 +173,11 @@ var y = class extends p {
176
173
  }
177
174
  this._activeSubmenus.length = e, this._activeSubmenuItems.length = e;
178
175
  }
179
- async _closeSubmenuAfterPresence(e, t) {
180
- await l(e.panel) && this._closingSubmenus.get(t) === e && (this._closingSubmenus.delete(t), this._restoreSubmenuItems(e, t), e.panel.remove());
176
+ async _closeSubmenuAfterPresence(e, n) {
177
+ await t(e.panel) && this._closingSubmenus.get(n) === e && (this._closingSubmenus.delete(n), this._restoreSubmenuItems(e, n), e.panel.remove());
181
178
  }
182
179
  _restoreSubmenuItems(e, t) {
183
- t && c(e.content, t);
180
+ t && f(e.content, t);
184
181
  }
185
182
  _restoreClosingSubmenus() {
186
183
  this._closingSubmenus.forEach((e, t) => {
@@ -209,7 +206,7 @@ var y = class extends p {
209
206
  }
210
207
  _getLevelItems(e) {
211
208
  let t = e === 0 ? this._menu?.content : this._activeSubmenus[e - 1]?.content;
212
- return t ? a(t) : [];
209
+ return t ? l(t) : [];
213
210
  }
214
211
  _bindLevelHovers() {
215
212
  this._hoverCleanupFns.forEach((e) => e()), this._hoverCleanupFns.length = 0;
@@ -230,7 +227,7 @@ var y = class extends p {
230
227
  if (this._activeSubmenus.length > 0) {
231
228
  let e = this._activeSubmenus.length - 1, t = this._activeSubmenuItems[e];
232
229
  this._closeSubmenusFrom(e), this._focusMenuItem(t), this._bindLevelHovers();
233
- } else this.close();
230
+ } else this._closeFromUser();
234
231
  }
235
232
  _preventBackgroundScroll(e) {
236
233
  !this._isOpen || this.noScrollLock || this._isMenuPanelEvent(e) || e.preventDefault();
@@ -240,10 +237,10 @@ var y = class extends p {
240
237
  }
241
238
  _getEnabledLevelItems(e) {
242
239
  let t = e === 0 ? this._menu?.content : this._activeSubmenus[e - 1]?.content;
243
- return t ? i(t) : [];
240
+ return t ? c(t) : [];
244
241
  }
245
242
  _getFocusedItem() {
246
- return n([this._menu?.content, ...this._activeSubmenus.map((e) => e.content)]);
243
+ return o([this._menu?.content, ...this._activeSubmenus.map((e) => e.content)]);
247
244
  }
248
245
  _getFocusedLevel() {
249
246
  let e = this._getFocusedItem();
@@ -253,28 +250,28 @@ var y = class extends p {
253
250
  return t < 0 ? void 0 : t + 1;
254
251
  }
255
252
  _focusMenuItem(e) {
256
- r(e);
253
+ s(e);
257
254
  }
258
255
  _isMenuPanelEvent(e) {
259
256
  return e.composedPath().some((e) => e instanceof HTMLElement && (e.classList.contains("context-menu") || e.classList.contains("context-submenu")));
260
257
  }
261
258
  render() {
262
- return m`
259
+ return h`
263
260
  <div class="context-menu-anchor">
264
261
  <slot @slotchange=${this._hideMenuItems}></slot>
265
262
  </div>
266
263
  `;
267
264
  }
268
265
  };
269
- e([_({
266
+ e([v({
270
267
  type: Boolean,
271
268
  reflect: !0
272
- })], y.prototype, "disabled", void 0), e([_({
269
+ })], b.prototype, "disabled", void 0), e([v({
273
270
  type: Boolean,
274
271
  reflect: !0,
275
272
  attribute: "no-scroll-lock"
276
- })], y.prototype, "noScrollLock", void 0), e([v()], y.prototype, "_isOpen", void 0), e([v()], y.prototype, "_x", void 0), e([v()], y.prototype, "_y", void 0), y = e([g("web-ui-context-menu")], y);
273
+ })], b.prototype, "noScrollLock", void 0), e([y()], b.prototype, "_isOpen", void 0), e([y()], b.prototype, "_x", void 0), e([y()], b.prototype, "_y", void 0), b = e([_("web-ui-context-menu")], b);
277
274
  //#endregion
278
- export { y as WebUiContextMenu };
275
+ export { b as WebUiContextMenu };
279
276
 
280
277
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/context-menu/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport '@/components/dropdown-divider'\nimport '@/components/dropdown-header'\nimport '@/components/dropdown-item'\nimport { createMenuPortalOverlay, type MenuPortalOverlay } from '@/shared/menu-portal/menu-portal'\nimport {\n findFocusedMenuItem,\n focusMenuItem,\n getEnabledMenuItems,\n getMenuChildren,\n getMenuItemFromEvent,\n hideNestedMenuChildren,\n moveMenuChildren\n} from '@/shared/menu-portal/menu-tree'\nimport { hideOverlayPresence, showOverlayPresence } from '@/shared/overlay/presence'\nimport { createScrollLockLease } from '@/shared/scroll-lock/scroll-lock'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-context-menu')\nexport class WebUiContextMenu extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true, attribute: 'no-scroll-lock' }) noScrollLock = false\n\n @state() private _isOpen = false\n @state() private _x = 0\n @state() private _y = 0\n\n private _activeSubmenus: MenuPortalOverlay[] = []\n private _activeSubmenuItems: HTMLElement[] = []\n private readonly _closingSubmenus = new Map<HTMLElement, MenuPortalOverlay>()\n private _submenuTimer?: ReturnType<typeof setTimeout>\n private _ignoreOutsideClick = false\n private _ignoreOutsideClickTimer?: ReturnType<typeof setTimeout>\n private _hoverCleanupFns: (() => void)[] = []\n private _menu?: MenuPortalOverlay\n private readonly _scrollLock = createScrollLockLease()\n private _restoreFocusTarget?: HTMLElement\n private _shouldOpenInstantly = true\n\n /** 当前菜单是否打开 */\n get isOpen(): boolean {\n return this._isOpen\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._hideMenuItems()\n this.addEventListener('contextmenu', this._onContextMenu)\n this.addEventListener('keydown', this._onKeydown)\n this.addEventListener('click', this._onMenuClick)\n document.addEventListener('click', this._onClickOutside)\n document.addEventListener('contextmenu', this._onContextMenuOutside)\n document.addEventListener('wheel', this._onWheel, { capture: true, passive: false })\n document.addEventListener('touchmove', this._onTouchMove, { capture: true, passive: false })\n document.addEventListener('keydown', this._onDocumentKeydown)\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('contextmenu', this._onContextMenu)\n this.removeEventListener('keydown', this._onKeydown)\n this.removeEventListener('click', this._onMenuClick)\n document.removeEventListener('click', this._onClickOutside)\n document.removeEventListener('contextmenu', this._onContextMenuOutside)\n document.removeEventListener('wheel', this._onWheel, true)\n document.removeEventListener('touchmove', this._onTouchMove, true)\n document.removeEventListener('keydown', this._onDocumentKeydown)\n clearTimeout(this._submenuTimer)\n clearTimeout(this._ignoreOutsideClickTimer)\n this._hoverCleanupFns.forEach(cleanup => cleanup())\n this._scrollLock.release()\n this._returnItemsToSlot()\n this._menu?.panel.remove()\n this._menu = undefined\n this._closeSubmenusFrom(0, true)\n this._restoreClosingSubmenus()\n }\n\n protected override updated(changed: Map<string, unknown>) {\n // Lit 的已排队更新可在卸载后执行,不能让已失效实例重新获取全局滚动锁。\n if (!this.isConnected) {\n this._syncScrollLock(false)\n return\n }\n\n if (changed.has('_isOpen')) {\n if (this._isOpen) {\n this._syncScrollLock()\n if (!this._menu) {\n this._menu = createMenuPortalOverlay('context-menu', this)\n this._menu.panel.setAttribute('role', 'menu')\n this._menu.panel.setAttribute('aria-label', '上下文菜单')\n this._menu.panel.addEventListener('click', this._onMenuClick)\n }\n requestAnimationFrame(() => {\n if (!this._isOpen || !this._menu) return\n this._setupMenuItems()\n this._positionMenu()\n showOverlayPresence(this._menu.panel, { isInstant: this._shouldOpenInstantly })\n this._shouldOpenInstantly = true\n this._focusFirstItem()\n this._bindLevelHovers()\n })\n } else {\n this._syncScrollLock(false)\n void this._closeMenuAfterPresence()\n }\n this._dispatchChange(this._isOpen)\n }\n if (changed.has('noScrollLock')) this._syncScrollLock()\n }\n\n /**\n * 在指定视口坐标打开菜单。\n * @param x 水平坐标(px)。\n * @param y 垂直坐标(px)。\n * @returns 无返回值;打开后派发 `open-change` 事件。\n */\n openAt(x: number, y: number) {\n this._openAt(x, y, true)\n }\n\n private _openAt(x: number, y: number, isInstant: boolean) {\n if (this.disabled) return\n this._x = x\n this._y = y\n this._shouldOpenInstantly = isInstant\n this._ignoreCurrentOutsideClick()\n if (this._isOpen) {\n requestAnimationFrame(() => this._positionMenu())\n return\n }\n this._restoreFocusTarget ??= document.activeElement instanceof HTMLElement ? document.activeElement : undefined\n this._isOpen = true\n }\n\n /**\n * 关闭菜单。\n * @returns 无返回值;关闭后派发 `open-change` 事件。\n */\n close() {\n if (!this._isOpen) return\n this._isOpen = false\n }\n\n private _positionMenu() {\n const panel = this._menu?.panel\n if (!panel) return\n\n panel.style.visibility = 'hidden'\n panel.style.display = ''\n\n const { width, height } = panel.getBoundingClientRect()\n const vw = window.innerWidth\n const vh = window.innerHeight\n\n let x = this._x\n let y = this._y\n\n if (x + width > vw) x = vw - width - 8\n if (y + height > vh) y = vh - height - 8\n if (x < 0) x = 8\n if (y < 0) y = 8\n\n panel.style.left = `${x}px`\n panel.style.top = `${y}px`\n const horizontalOrigin = x < this._x ? 'right' : 'left'\n const verticalOrigin = y < this._y ? 'bottom' : 'top'\n panel.style.setProperty('--wui-overlay-transform-origin', `${verticalOrigin} ${horizontalOrigin}`)\n panel.style.visibility = ''\n }\n\n private _focusFirstItem() {\n const items = this._menu?.content.querySelectorAll<HTMLElement>('web-ui-dropdown-item:not([disabled])')\n const firstItem = items?.[0]\n if (firstItem) {\n this._focusMenuItem(firstItem)\n }\n }\n\n private _setupMenuItems() {\n const menu = this._menu\n if (!menu) return\n\n this._hideMenuItems()\n moveMenuChildren(this, menu.content)\n }\n\n private _returnItemsToSlot() {\n const menu = this._menu\n if (!menu) return\n\n this._closeSubmenusFrom(0, true)\n this._restoreClosingSubmenus()\n moveMenuChildren(menu.content, this)\n }\n\n private async _closeMenuAfterPresence() {\n const menu = this._menu\n if (menu && !(await hideOverlayPresence(menu.panel))) return\n if (this._isOpen || !this.isConnected || this._menu !== menu) return\n\n this._returnItemsToSlot()\n menu?.panel.remove()\n this._menu = undefined\n this._restoreFocusTarget?.focus()\n this._restoreFocusTarget = undefined\n }\n\n private _hideMenuItems() {\n getMenuChildren(this).forEach(child => child.setAttribute('slot', 'context-menu-hidden'))\n hideNestedMenuChildren(this, 'context-menu-hidden')\n }\n\n private _openSubmenu(item: HTMLElement, isInstant = false) {\n if (!this._isOpen || !item.hasAttribute('submenu') || item.hasAttribute('disabled')) return\n\n const level = this._getItemLevel(item)\n if (level === -1 || this._activeSubmenuItems[level] === item) return\n\n this._closeSubmenusFrom(level)\n const closingSubmenu = this._closingSubmenus.get(item)\n if (closingSubmenu) {\n this._closingSubmenus.delete(item)\n this._activeSubmenus[level] = closingSubmenu\n this._activeSubmenuItems[level] = item\n item.setAttribute('active', '')\n this._positionSubmenu(item, closingSubmenu)\n showOverlayPresence(closingSubmenu.panel, { isInstant })\n this._bindLevelHovers()\n return\n }\n const children = getMenuChildren(item)\n if (children.length === 0) return\n\n const submenu = createMenuPortalOverlay('context-submenu', this)\n submenu.panel.dataset.level = String(level)\n submenu.panel.setAttribute('role', 'menu')\n submenu.panel.setAttribute('aria-label', '子菜单')\n submenu.panel.style.visibility = 'hidden'\n submenu.panel.addEventListener('click', this._onMenuClick)\n submenu.content.append(...children)\n\n this._activeSubmenus[level] = submenu\n this._activeSubmenuItems[level] = item\n item.setAttribute('active', '')\n this._positionSubmenu(item, submenu)\n showOverlayPresence(submenu.panel, { isInstant })\n this._bindLevelHovers()\n }\n\n private _closeSubmenusFrom(level: number, isInstant = false) {\n for (let index = this._activeSubmenus.length - 1; index >= level; index--) {\n const submenu = this._activeSubmenus[index]\n const item = this._activeSubmenuItems[index]\n item?.removeAttribute('active')\n if (!item || isInstant) {\n this._restoreSubmenuItems(submenu, item)\n submenu.panel.remove()\n } else {\n this._closingSubmenus.set(item, submenu)\n void this._closeSubmenuAfterPresence(submenu, item)\n }\n }\n this._activeSubmenus.length = level\n this._activeSubmenuItems.length = level\n }\n\n private async _closeSubmenuAfterPresence(submenu: MenuPortalOverlay, item: HTMLElement) {\n if (!(await hideOverlayPresence(submenu.panel))) return\n if (this._closingSubmenus.get(item) !== submenu) return\n\n this._closingSubmenus.delete(item)\n this._restoreSubmenuItems(submenu, item)\n submenu.panel.remove()\n }\n\n private _restoreSubmenuItems(submenu: MenuPortalOverlay, item?: HTMLElement) {\n if (item) moveMenuChildren(submenu.content, item)\n }\n\n private _restoreClosingSubmenus() {\n this._closingSubmenus.forEach((submenu, item) => {\n this._restoreSubmenuItems(submenu, item)\n submenu.panel.remove()\n })\n this._closingSubmenus.clear()\n }\n\n private _getItemLevel(item: HTMLElement): number {\n const menu = this._menu\n if (menu?.panel.contains(item)) return 0\n const parentLevel = this._activeSubmenus.findIndex(submenu => submenu.panel.contains(item))\n return parentLevel === -1 ? -1 : parentLevel + 1\n }\n\n private _positionSubmenu(item: HTMLElement, submenu: MenuPortalOverlay) {\n const itemRect = item.getBoundingClientRect()\n const submenuRect = submenu.panel.getBoundingClientRect()\n const padding = 8\n const canOpenRight = itemRect.right + submenuRect.width + padding <= window.innerWidth\n const left = canOpenRight ? itemRect.right : Math.max(padding, itemRect.left - submenuRect.width)\n const top = Math.min(Math.max(padding, itemRect.top), window.innerHeight - submenuRect.height - padding)\n\n submenu.panel.style.left = `${left}px`\n submenu.panel.style.top = `${top}px`\n submenu.panel.style.setProperty('--wui-overlay-transform-origin', canOpenRight ? 'top left' : 'top right')\n submenu.panel.style.visibility = ''\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 _isInsideShadowRoot(e: MouseEvent): boolean {\n for (const node of e.composedPath()) {\n if (node === this || node === this.shadowRoot) return true\n if (node instanceof Node && node.getRootNode() === this.shadowRoot) return true\n if (\n node instanceof Node &&\n (this._menu?.panel.contains(node) || this._activeSubmenus.some(menu => menu.panel.contains(node)))\n ) {\n return true\n }\n }\n return false\n }\n\n private _onContextMenu = (e: MouseEvent) => {\n if (this.disabled) return\n e.preventDefault()\n this._restoreFocusTarget = e.target instanceof HTMLElement ? e.target : undefined\n this._openAt(e.clientX, e.clientY, false)\n }\n\n private _onContextMenuOutside = (e: MouseEvent) => {\n if (this._isOpen && !this._isInsideShadowRoot(e)) {\n this.close()\n }\n }\n\n private _onKeydown = (e: KeyboardEvent) => {\n if (this.disabled) return\n\n // 键盘 ContextMenu 键或 Shift+F10\n if (e.key === 'ContextMenu' || (e.shiftKey && e.key === 'F10')) {\n e.preventDefault()\n const focused = document.activeElement\n if (focused && focused !== document.body) {\n const rect = focused.getBoundingClientRect()\n this._openAt(rect.left, rect.bottom, true)\n } else {\n this._openAt(window.innerWidth / 2, window.innerHeight / 2, true)\n }\n return\n }\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this._isOpen || this._ignoreOutsideClick) return\n if (this._isInsideShadowRoot(e)) return\n this.close()\n }\n\n private _onMenuClick = (e: MouseEvent) => {\n const item = getMenuItemFromEvent(e)\n if (!item || item.hasAttribute('disabled')) return\n if (item.hasAttribute('submenu')) {\n this._openSubmenu(item)\n return\n }\n this.close()\n }\n\n private _getLevelItems(level: number): HTMLElement[] {\n const container = level === 0 ? this._menu?.content : this._activeSubmenus[level - 1]?.content\n if (!container) return []\n return getMenuChildren(container)\n }\n\n private _bindLevelHovers() {\n this._hoverCleanupFns.forEach(cleanup => cleanup())\n this._hoverCleanupFns.length = 0\n\n for (let level = 0; level <= this._activeSubmenus.length; level++) {\n this._getLevelItems(level).forEach(item => {\n if (!item.matches('web-ui-dropdown-item') || item.hasAttribute('disabled')) return\n const handler = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n clearTimeout(this._submenuTimer)\n if (item.hasAttribute('submenu')) {\n if (this._activeSubmenuItems[level] !== item) {\n this._submenuTimer = setTimeout(() => this._openSubmenu(item), 200)\n }\n } else if (this._activeSubmenus.length > level) {\n this._closeSubmenusFrom(level)\n this._bindLevelHovers()\n }\n }\n item.addEventListener('pointerenter', handler, { passive: true })\n this._hoverCleanupFns.push(() => item.removeEventListener('pointerenter', handler))\n })\n }\n }\n\n private _ignoreCurrentOutsideClick() {\n this._ignoreOutsideClick = true\n clearTimeout(this._ignoreOutsideClickTimer)\n this._ignoreOutsideClickTimer = setTimeout(() => {\n this._ignoreOutsideClick = false\n })\n }\n\n private _onWheel = (e: WheelEvent) => {\n this._preventBackgroundScroll(e)\n }\n\n private _onTouchMove = (e: TouchEvent) => {\n this._preventBackgroundScroll(e)\n }\n\n private _onDocumentKeydown = (e: KeyboardEvent) => {\n if (!this._isOpen) return\n if (e.key === 'Escape' && e.target === this) {\n this._closeLastSubmenuOrMenu()\n e.preventDefault()\n return\n }\n const level = this._getFocusedLevel()\n if (level === undefined) return\n const items = this._getEnabledLevelItems(level)\n const focused = this._getFocusedItem()\n const currentIndex = focused ? items.indexOf(focused) : -1\n\n switch (e.key) {\n case 'ArrowDown':\n this._focusMenuItem(items[(currentIndex + 1 + items.length) % items.length])\n break\n case 'ArrowUp':\n this._focusMenuItem(items[(currentIndex - 1 + items.length) % items.length])\n break\n case 'Home':\n this._focusMenuItem(items[0])\n break\n case 'End':\n this._focusMenuItem(items.at(-1))\n break\n case 'ArrowRight':\n if (focused?.hasAttribute('submenu')) {\n this._openSubmenu(focused, true)\n requestAnimationFrame(() => this._focusMenuItem(this._getEnabledLevelItems(level + 1)[0]))\n }\n break\n case 'ArrowLeft':\n if (level > 0) {\n const parent = this._activeSubmenuItems[level - 1]\n this._closeSubmenusFrom(level - 1)\n this._focusMenuItem(parent)\n this._bindLevelHovers()\n }\n break\n case 'Enter':\n case ' ':\n focused?.click()\n break\n case 'Escape':\n this._closeLastSubmenuOrMenu()\n break\n default:\n return\n }\n e.preventDefault()\n }\n\n private _closeLastSubmenuOrMenu() {\n if (this._activeSubmenus.length > 0) {\n const level = this._activeSubmenus.length - 1\n const parent = this._activeSubmenuItems[level]\n this._closeSubmenusFrom(level)\n this._focusMenuItem(parent)\n this._bindLevelHovers()\n } else {\n this.close()\n }\n }\n\n private _preventBackgroundScroll(e: Event) {\n if (!this._isOpen || this.noScrollLock || this._isMenuPanelEvent(e)) return\n e.preventDefault()\n }\n\n private _syncScrollLock(isOpen = this._isOpen) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n private _getEnabledLevelItems(level: number) {\n const container = level === 0 ? this._menu?.content : this._activeSubmenus[level - 1]?.content\n return container ? getEnabledMenuItems(container) : []\n }\n\n private _getFocusedItem(): HTMLElement | undefined {\n return findFocusedMenuItem([this._menu?.content, ...this._activeSubmenus.map(submenu => submenu.content)])\n }\n\n private _getFocusedLevel(): number | undefined {\n const item = this._getFocusedItem()\n if (!item) return undefined\n if (this._menu?.panel.contains(item)) return 0\n const submenuIndex = this._activeSubmenus.findIndex(menu => menu.panel.contains(item))\n return submenuIndex < 0 ? undefined : submenuIndex + 1\n }\n\n private _focusMenuItem(item: HTMLElement | undefined) {\n focusMenuItem(item)\n }\n\n private _isMenuPanelEvent(e: Event): boolean {\n return e\n .composedPath()\n .some(\n node =>\n node instanceof HTMLElement &&\n (node.classList.contains('context-menu') || node.classList.contains('context-submenu'))\n )\n }\n\n override render() {\n return html`\n <div class=\"context-menu-anchor\">\n <slot @slotchange=${this._hideMenuItems}></slot>\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-context-menu': WebUiContextMenu\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/context-menu/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport '@/components/dropdown-divider'\nimport '@/components/dropdown-header'\nimport '@/components/dropdown-item'\nimport { UserChangeController } from '@/shared/events/user-change'\nimport { createMenuPortalOverlay, type MenuPortalOverlay } from '@/shared/menu-portal/menu-portal'\nimport {\n findFocusedMenuItem,\n focusMenuItem,\n getEnabledMenuItems,\n getMenuChildren,\n getMenuItemFromEvent,\n hideNestedMenuChildren,\n moveMenuChildren\n} from '@/shared/menu-portal/menu-tree'\nimport { hideOverlayPresence, showOverlayPresence } from '@/shared/overlay/presence'\nimport { defineScrollLockLease } from '@/shared/scroll-lock/scroll-lock'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-context-menu')\nexport class WebUiContextMenu extends LitElement {\n static override styles = unsafeCSS(style)\n\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true, attribute: 'no-scroll-lock' }) noScrollLock = false\n\n @state() private _isOpen = false\n @state() private _x = 0\n @state() private _y = 0\n\n private _activeSubmenus: MenuPortalOverlay[] = []\n private _activeSubmenuItems: HTMLElement[] = []\n private readonly _closingSubmenus = new Map<HTMLElement, MenuPortalOverlay>()\n private _submenuTimer?: ReturnType<typeof setTimeout>\n private _ignoreOutsideClick = false\n private _ignoreOutsideClickTimer?: ReturnType<typeof setTimeout>\n private _hoverCleanupFns: (() => void)[] = []\n private _menu?: MenuPortalOverlay\n private readonly _scrollLock = defineScrollLockLease().make()\n private readonly _userOpenChange = new UserChangeController()\n private _restoreFocusTarget?: HTMLElement\n private _shouldOpenInstantly = true\n\n // 当前菜单是否打开\n get isOpen(): boolean {\n return this._isOpen\n }\n\n override connectedCallback() {\n super.connectedCallback()\n this._hideMenuItems()\n this.addEventListener('contextmenu', this._onContextMenu)\n this.addEventListener('keydown', this._onKeydown)\n this.addEventListener('click', this._onMenuClick)\n document.addEventListener('click', this._onClickOutside)\n document.addEventListener('contextmenu', this._onContextMenuOutside)\n document.addEventListener('wheel', this._onWheel, { capture: true, passive: false })\n document.addEventListener('touchmove', this._onTouchMove, { capture: true, passive: false })\n document.addEventListener('keydown', this._onDocumentKeydown)\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('contextmenu', this._onContextMenu)\n this.removeEventListener('keydown', this._onKeydown)\n this.removeEventListener('click', this._onMenuClick)\n document.removeEventListener('click', this._onClickOutside)\n document.removeEventListener('contextmenu', this._onContextMenuOutside)\n document.removeEventListener('wheel', this._onWheel, true)\n document.removeEventListener('touchmove', this._onTouchMove, true)\n document.removeEventListener('keydown', this._onDocumentKeydown)\n clearTimeout(this._submenuTimer)\n clearTimeout(this._ignoreOutsideClickTimer)\n this._hoverCleanupFns.forEach(cleanup => cleanup())\n this._scrollLock.release()\n this._returnItemsToSlot()\n this._menu?.panel.remove()\n this._menu = undefined\n this._closeSubmenusFrom(0, true)\n this._restoreClosingSubmenus()\n }\n\n protected override updated(changed: Map<string, unknown>) {\n // Lit 的已排队更新可在卸载后执行,不能让已失效实例重新获取全局滚动锁。\n if (!this.isConnected) {\n this._syncScrollLock(false)\n return\n }\n\n if (changed.has('_isOpen')) {\n if (this._isOpen) {\n this._syncScrollLock()\n if (!this._menu) {\n this._menu = createMenuPortalOverlay('context-menu', this)\n this._menu.panel.setAttribute('role', 'menu')\n this._menu.panel.setAttribute('aria-label', '上下文菜单')\n this._menu.panel.addEventListener('click', this._onMenuClick)\n }\n requestAnimationFrame(() => {\n if (!this._isOpen || !this._menu) return\n this._setupMenuItems()\n this._positionMenu()\n showOverlayPresence(this._menu.panel, { isInstant: this._shouldOpenInstantly })\n this._shouldOpenInstantly = true\n this._focusFirstItem()\n this._bindLevelHovers()\n })\n } else {\n this._syncScrollLock(false)\n void this._closeMenuAfterPresence()\n }\n if (this._userOpenChange.consume()) this._dispatchChange(this._isOpen)\n }\n if (changed.has('noScrollLock')) this._syncScrollLock()\n }\n\n /**\n * 在指定视口坐标打开菜单。\n * @param x 水平坐标(px)。\n * @param y 垂直坐标(px)。\n * @returns 无返回值;命令式打开不派发 `open-change` 事件。\n */\n openAt(x: number, y: number) {\n this._openAt(x, y, true)\n }\n\n private _openAt(x: number, y: number, isInstant: boolean): boolean {\n if (this.disabled) return false\n this._x = x\n this._y = y\n this._shouldOpenInstantly = isInstant\n this._ignoreCurrentOutsideClick()\n if (this._isOpen) {\n requestAnimationFrame(() => this._positionMenu())\n return false\n }\n this._restoreFocusTarget ??= document.activeElement instanceof HTMLElement ? document.activeElement : undefined\n this._isOpen = true\n return true\n }\n\n /**\n * 关闭菜单。\n * @returns 无返回值;命令式关闭不派发 `open-change` 事件。\n */\n close() {\n if (!this._isOpen) return\n this._isOpen = false\n }\n\n private readonly _closeFromUser = () => {\n if (!this._isOpen) return\n this._userOpenChange.mark()\n this.close()\n }\n\n private _positionMenu() {\n const panel = this._menu?.panel\n if (!panel) return\n\n panel.style.visibility = 'hidden'\n panel.style.display = ''\n\n const { width, height } = panel.getBoundingClientRect()\n const vw = window.innerWidth\n const vh = window.innerHeight\n\n let x = this._x\n let y = this._y\n\n if (x + width > vw) x = vw - width - 8\n if (y + height > vh) y = vh - height - 8\n if (x < 0) x = 8\n if (y < 0) y = 8\n\n panel.style.left = `${x}px`\n panel.style.top = `${y}px`\n const horizontalOrigin = x < this._x ? 'right' : 'left'\n const verticalOrigin = y < this._y ? 'bottom' : 'top'\n panel.style.setProperty('--wui-overlay-transform-origin', `${verticalOrigin} ${horizontalOrigin}`)\n panel.style.visibility = ''\n }\n\n private _focusFirstItem() {\n const items = this._menu?.content.querySelectorAll<HTMLElement>('web-ui-dropdown-item:not([disabled])')\n const firstItem = items?.[0]\n if (firstItem) {\n this._focusMenuItem(firstItem)\n }\n }\n\n private _setupMenuItems() {\n const menu = this._menu\n if (!menu) return\n\n this._hideMenuItems()\n moveMenuChildren(this, menu.content)\n }\n\n private _returnItemsToSlot() {\n const menu = this._menu\n if (!menu) return\n\n this._closeSubmenusFrom(0, true)\n this._restoreClosingSubmenus()\n moveMenuChildren(menu.content, this)\n }\n\n private async _closeMenuAfterPresence() {\n const menu = this._menu\n if (menu && !(await hideOverlayPresence(menu.panel))) return\n if (this._isOpen || !this.isConnected || this._menu !== menu) return\n\n this._returnItemsToSlot()\n menu?.panel.remove()\n this._menu = undefined\n this._restoreFocusTarget?.focus()\n this._restoreFocusTarget = undefined\n }\n\n private _hideMenuItems() {\n getMenuChildren(this).forEach(child => child.setAttribute('slot', 'context-menu-hidden'))\n hideNestedMenuChildren(this, 'context-menu-hidden')\n }\n\n private _openSubmenu(item: HTMLElement, isInstant = false) {\n if (!this._isOpen || !item.hasAttribute('submenu') || item.hasAttribute('disabled')) return\n\n const level = this._getItemLevel(item)\n if (level === -1 || this._activeSubmenuItems[level] === item) return\n\n this._closeSubmenusFrom(level)\n const closingSubmenu = this._closingSubmenus.get(item)\n if (closingSubmenu) {\n this._closingSubmenus.delete(item)\n this._activeSubmenus[level] = closingSubmenu\n this._activeSubmenuItems[level] = item\n item.setAttribute('active', '')\n this._positionSubmenu(item, closingSubmenu)\n showOverlayPresence(closingSubmenu.panel, { isInstant })\n this._bindLevelHovers()\n return\n }\n const children = getMenuChildren(item)\n if (children.length === 0) return\n\n const submenu = createMenuPortalOverlay('context-submenu', this)\n submenu.panel.dataset.level = String(level)\n submenu.panel.setAttribute('role', 'menu')\n submenu.panel.setAttribute('aria-label', '子菜单')\n submenu.panel.style.visibility = 'hidden'\n submenu.panel.addEventListener('click', this._onMenuClick)\n submenu.content.append(...children)\n\n this._activeSubmenus[level] = submenu\n this._activeSubmenuItems[level] = item\n item.setAttribute('active', '')\n this._positionSubmenu(item, submenu)\n showOverlayPresence(submenu.panel, { isInstant })\n this._bindLevelHovers()\n }\n\n private _closeSubmenusFrom(level: number, isInstant = false) {\n for (let index = this._activeSubmenus.length - 1; index >= level; index--) {\n const submenu = this._activeSubmenus[index]\n const item = this._activeSubmenuItems[index]\n item?.removeAttribute('active')\n if (!item || isInstant) {\n this._restoreSubmenuItems(submenu, item)\n submenu.panel.remove()\n } else {\n this._closingSubmenus.set(item, submenu)\n void this._closeSubmenuAfterPresence(submenu, item)\n }\n }\n this._activeSubmenus.length = level\n this._activeSubmenuItems.length = level\n }\n\n private async _closeSubmenuAfterPresence(submenu: MenuPortalOverlay, item: HTMLElement) {\n if (!(await hideOverlayPresence(submenu.panel))) return\n if (this._closingSubmenus.get(item) !== submenu) return\n\n this._closingSubmenus.delete(item)\n this._restoreSubmenuItems(submenu, item)\n submenu.panel.remove()\n }\n\n private _restoreSubmenuItems(submenu: MenuPortalOverlay, item?: HTMLElement) {\n if (item) moveMenuChildren(submenu.content, item)\n }\n\n private _restoreClosingSubmenus() {\n this._closingSubmenus.forEach((submenu, item) => {\n this._restoreSubmenuItems(submenu, item)\n submenu.panel.remove()\n })\n this._closingSubmenus.clear()\n }\n\n private _getItemLevel(item: HTMLElement): number {\n const menu = this._menu\n if (menu?.panel.contains(item)) return 0\n const parentLevel = this._activeSubmenus.findIndex(submenu => submenu.panel.contains(item))\n return parentLevel === -1 ? -1 : parentLevel + 1\n }\n\n private _positionSubmenu(item: HTMLElement, submenu: MenuPortalOverlay) {\n const itemRect = item.getBoundingClientRect()\n const submenuRect = submenu.panel.getBoundingClientRect()\n const padding = 8\n const canOpenRight = itemRect.right + submenuRect.width + padding <= window.innerWidth\n const left = canOpenRight ? itemRect.right : Math.max(padding, itemRect.left - submenuRect.width)\n const top = Math.min(Math.max(padding, itemRect.top), window.innerHeight - submenuRect.height - padding)\n\n submenu.panel.style.left = `${left}px`\n submenu.panel.style.top = `${top}px`\n submenu.panel.style.setProperty('--wui-overlay-transform-origin', canOpenRight ? 'top left' : 'top right')\n submenu.panel.style.visibility = ''\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 _isInsideShadowRoot(e: MouseEvent): boolean {\n for (const node of e.composedPath()) {\n if (node === this || node === this.shadowRoot) return true\n if (node instanceof Node && node.getRootNode() === this.shadowRoot) return true\n if (\n node instanceof Node &&\n (this._menu?.panel.contains(node) || this._activeSubmenus.some(menu => menu.panel.contains(node)))\n ) {\n return true\n }\n }\n return false\n }\n\n private _onContextMenu = (e: MouseEvent) => {\n if (this.disabled) return\n e.preventDefault()\n this._restoreFocusTarget = e.target instanceof HTMLElement ? e.target : undefined\n if (this._openAt(e.clientX, e.clientY, false)) this._userOpenChange.mark()\n }\n\n private _onContextMenuOutside = (e: MouseEvent) => {\n if (this._isOpen && !this._isInsideShadowRoot(e)) {\n this._closeFromUser()\n }\n }\n\n private _onKeydown = (e: KeyboardEvent) => {\n if (this.disabled) return\n\n // 键盘 ContextMenu 键或 Shift+F10\n if (e.key === 'ContextMenu' || (e.shiftKey && e.key === 'F10')) {\n e.preventDefault()\n const focused = document.activeElement\n if (focused && focused !== document.body) {\n const rect = focused.getBoundingClientRect()\n if (this._openAt(rect.left, rect.bottom, true)) this._userOpenChange.mark()\n } else {\n if (this._openAt(window.innerWidth / 2, window.innerHeight / 2, true)) this._userOpenChange.mark()\n }\n return\n }\n }\n\n private _onClickOutside = (e: MouseEvent) => {\n if (!this._isOpen || this._ignoreOutsideClick) return\n if (this._isInsideShadowRoot(e)) return\n this._closeFromUser()\n }\n\n private _onMenuClick = (e: MouseEvent) => {\n const item = getMenuItemFromEvent(e)\n if (!item || item.hasAttribute('disabled')) return\n if (item.hasAttribute('submenu')) {\n this._openSubmenu(item)\n return\n }\n this._closeFromUser()\n }\n\n private _getLevelItems(level: number): HTMLElement[] {\n const container = level === 0 ? this._menu?.content : this._activeSubmenus[level - 1]?.content\n if (!container) return []\n return getMenuChildren(container)\n }\n\n private _bindLevelHovers() {\n this._hoverCleanupFns.forEach(cleanup => cleanup())\n this._hoverCleanupFns.length = 0\n\n for (let level = 0; level <= this._activeSubmenus.length; level++) {\n this._getLevelItems(level).forEach(item => {\n if (!item.matches('web-ui-dropdown-item') || item.hasAttribute('disabled')) return\n const handler = (event: PointerEvent) => {\n if (event.pointerType === 'touch') return\n clearTimeout(this._submenuTimer)\n if (item.hasAttribute('submenu')) {\n if (this._activeSubmenuItems[level] !== item) {\n this._submenuTimer = setTimeout(() => this._openSubmenu(item), 200)\n }\n } else if (this._activeSubmenus.length > level) {\n this._closeSubmenusFrom(level)\n this._bindLevelHovers()\n }\n }\n item.addEventListener('pointerenter', handler, { passive: true })\n this._hoverCleanupFns.push(() => item.removeEventListener('pointerenter', handler))\n })\n }\n }\n\n private _ignoreCurrentOutsideClick() {\n this._ignoreOutsideClick = true\n clearTimeout(this._ignoreOutsideClickTimer)\n this._ignoreOutsideClickTimer = setTimeout(() => {\n this._ignoreOutsideClick = false\n })\n }\n\n private _onWheel = (e: WheelEvent) => {\n this._preventBackgroundScroll(e)\n }\n\n private _onTouchMove = (e: TouchEvent) => {\n this._preventBackgroundScroll(e)\n }\n\n private _onDocumentKeydown = (e: KeyboardEvent) => {\n if (!this._isOpen) return\n // 鼠标右键打开的菜单焦点不在菜单内,e.target !== this 时也必须能 Escape 关闭;\n // 菜单为模态浮层,按 Escape 即关闭,无需限定焦点位置\n if (e.key === 'Escape') {\n this._closeLastSubmenuOrMenu()\n e.preventDefault()\n return\n }\n const level = this._getFocusedLevel()\n if (level === undefined) return\n const items = this._getEnabledLevelItems(level)\n const focused = this._getFocusedItem()\n const currentIndex = focused ? items.indexOf(focused) : -1\n\n switch (e.key) {\n case 'ArrowDown':\n this._focusMenuItem(items[(currentIndex + 1 + items.length) % items.length])\n break\n case 'ArrowUp':\n this._focusMenuItem(items[(currentIndex - 1 + items.length) % items.length])\n break\n case 'Home':\n this._focusMenuItem(items[0])\n break\n case 'End':\n this._focusMenuItem(items.at(-1))\n break\n case 'ArrowRight':\n if (focused?.hasAttribute('submenu')) {\n this._openSubmenu(focused, true)\n requestAnimationFrame(() => this._focusMenuItem(this._getEnabledLevelItems(level + 1)[0]))\n }\n break\n case 'ArrowLeft':\n if (level > 0) {\n const parent = this._activeSubmenuItems[level - 1]\n this._closeSubmenusFrom(level - 1)\n this._focusMenuItem(parent)\n this._bindLevelHovers()\n }\n break\n case 'Enter':\n case ' ':\n focused?.click()\n break\n case 'Escape':\n this._closeLastSubmenuOrMenu()\n break\n default:\n return\n }\n e.preventDefault()\n }\n\n private _closeLastSubmenuOrMenu() {\n if (this._activeSubmenus.length > 0) {\n const level = this._activeSubmenus.length - 1\n const parent = this._activeSubmenuItems[level]\n this._closeSubmenusFrom(level)\n this._focusMenuItem(parent)\n this._bindLevelHovers()\n } else {\n this._closeFromUser()\n }\n }\n\n private _preventBackgroundScroll(e: Event) {\n if (!this._isOpen || this.noScrollLock || this._isMenuPanelEvent(e)) return\n e.preventDefault()\n }\n\n private _syncScrollLock(isOpen = this._isOpen) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n private _getEnabledLevelItems(level: number) {\n const container = level === 0 ? this._menu?.content : this._activeSubmenus[level - 1]?.content\n return container ? getEnabledMenuItems(container) : []\n }\n\n private _getFocusedItem(): HTMLElement | undefined {\n return findFocusedMenuItem([this._menu?.content, ...this._activeSubmenus.map(submenu => submenu.content)])\n }\n\n private _getFocusedLevel(): number | undefined {\n const item = this._getFocusedItem()\n if (!item) return undefined\n if (this._menu?.panel.contains(item)) return 0\n const submenuIndex = this._activeSubmenus.findIndex(menu => menu.panel.contains(item))\n return submenuIndex < 0 ? undefined : submenuIndex + 1\n }\n\n private _focusMenuItem(item: HTMLElement | undefined) {\n focusMenuItem(item)\n }\n\n private _isMenuPanelEvent(e: Event): boolean {\n return e\n .composedPath()\n .some(\n node =>\n node instanceof HTMLElement &&\n (node.classList.contains('context-menu') || node.classList.contains('context-submenu'))\n )\n }\n\n override render() {\n return html`\n <div class=\"context-menu-anchor\">\n <slot @slotchange=${this._hideMenuItems}></slot>\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-context-menu': WebUiContextMenu\n }\n}\n"],"mappings":"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"}
@@ -5,12 +5,12 @@ export declare class WebUiDialog extends LitElement {
5
5
  noScrollLock: boolean;
6
6
  noBackdropClose: boolean;
7
7
  private _hasBody;
8
+ private readonly _userOpenChange;
8
9
  private readonly _scrollLock;
9
10
  private readonly _presence;
10
11
  private get dialog();
11
12
  protected updated(props: PropertyValues): void;
12
13
  disconnectedCallback(): void;
13
- /** 以模态方式打开对话框(命令式) */
14
14
  showModal(): void;
15
15
  close(): void;
16
16
  private handleCancel;
@@ -1,32 +1,33 @@
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
+ import { defineScrollLockLease as n } from "../../shared/scroll-lock/scroll-lock.js";
3
4
  import "../button/index.js";
4
- import { createScrollLockLease as n } from "../../shared/scroll-lock/scroll-lock.js";
5
- import { defineNativeDialogPresence as r } from "../../shared/overlay/native-dialog-presence.js";
6
- import i from "./style.js";
7
- import { LitElement as a, html as o, unsafeCSS as s } from "lit";
8
- import { customElement as c, property as l, state as u } from "lit/decorators.js";
5
+ import { UserChangeController as r } from "../../shared/events/user-change.js";
6
+ import { defineNativeDialogPresence as i } from "../../shared/overlay/native-dialog-presence.js";
7
+ import a from "./style.js";
8
+ import { LitElement as o, html as s, unsafeCSS as c } from "lit";
9
+ import { customElement as l, property as u, state as d } from "lit/decorators.js";
9
10
  //#region src/components/dialog/index.ts
10
- var d = class extends a {
11
+ var f = class extends o {
11
12
  constructor(...e) {
12
- super(...e), this.open = !1, this.noScrollLock = !1, this.noBackdropClose = !1, this._hasBody = !1, this._scrollLock = n(), this._presence = r().make({
13
+ super(...e), this.open = !1, this.noScrollLock = !1, this.noBackdropClose = !1, this._hasBody = !1, this._userOpenChange = new r(), this._scrollLock = n().make(), this._presence = i().make({
13
14
  getDialog: () => this.dialog,
14
15
  isConnected: () => this.isConnected,
15
16
  isOpen: () => this.open
16
17
  }), this._onTransitionEnd = (e) => {
17
18
  this._presence.handleTransitionEnd(e);
18
19
  }, this._onNativeClose = () => {
19
- this.open &&= (this._presence.handleNativeClose(), !1);
20
+ this.open &&= (this._presence.handleNativeClose(), this._userOpenChange.mark(), !1);
20
21
  };
21
22
  }
22
23
  static {
23
- this.styles = [s(t), s(i)];
24
+ this.styles = [c(t), c(a)];
24
25
  }
25
26
  get dialog() {
26
27
  return this.shadowRoot?.querySelector("dialog") ?? null;
27
28
  }
28
29
  updated(e) {
29
- super.updated(e), this.isConnected && (e.has("open") && (this.emitOpenChange(), this._presence.sync(this.open)), (e.has("open") || e.has("noScrollLock")) && this._syncScrollLock());
30
+ super.updated(e), this.isConnected && (e.has("open") && (this._userOpenChange.consume() && this.emitOpenChange(), this._presence.sync(this.open)), (e.has("open") || e.has("noScrollLock")) && this._syncScrollLock());
30
31
  }
31
32
  disconnectedCallback() {
32
33
  super.disconnectedCallback(), this._presence.dispose(), this._scrollLock.release();
@@ -38,10 +39,10 @@ var d = class extends a {
38
39
  this.open = !1;
39
40
  }
40
41
  handleCancel(e) {
41
- e.preventDefault(), this.close();
42
+ e.preventDefault(), this._userOpenChange.mark(), this.close();
42
43
  }
43
44
  handleBackdropClick(e) {
44
- e.target === e.currentTarget && (this.noBackdropClose || this.close());
45
+ e.target === e.currentTarget && (this.noBackdropClose || (this._userOpenChange.mark(), this.close()));
45
46
  }
46
47
  emitOpenChange() {
47
48
  this.dispatchEvent(new CustomEvent("open-change", {
@@ -57,7 +58,7 @@ var d = class extends a {
57
58
  e.target instanceof HTMLSlotElement && (this._hasBody = e.target.assignedElements().length > 0);
58
59
  }
59
60
  render() {
60
- return o`
61
+ return s`
61
62
  <dialog
62
63
  @cancel=${this.handleCancel}
63
64
  @close=${this._onNativeClose}
@@ -65,7 +66,7 @@ var d = class extends a {
65
66
  @transitionend=${this._onTransitionEnd}
66
67
  >
67
68
  <div class="wui-dialog-body wui-glass">
68
- ${this._hasBody ? o`<slot name="body" @slotchange=${this._onBodySlotChange}></slot>` : o`
69
+ ${this._hasBody ? s`<slot name="body" @slotchange=${this._onBodySlotChange}></slot>` : s`
69
70
  <slot name="body" @slotchange=${this._onBodySlotChange} hidden></slot>
70
71
  <div class="title"><slot name="title"></slot></div>
71
72
  <div class="desc"><slot></slot></div>
@@ -76,19 +77,19 @@ var d = class extends a {
76
77
  `;
77
78
  }
78
79
  };
79
- e([l({
80
+ e([u({
80
81
  type: Boolean,
81
82
  reflect: !0
82
- })], d.prototype, "open", void 0), e([l({
83
+ })], f.prototype, "open", void 0), e([u({
83
84
  type: Boolean,
84
85
  reflect: !0,
85
86
  attribute: "no-scroll-lock"
86
- })], d.prototype, "noScrollLock", void 0), e([l({
87
+ })], f.prototype, "noScrollLock", void 0), e([u({
87
88
  type: Boolean,
88
89
  reflect: !0,
89
90
  attribute: "no-backdrop-close"
90
- })], d.prototype, "noBackdropClose", void 0), e([u()], d.prototype, "_hasBody", void 0), d = e([c("web-ui-dialog")], d);
91
+ })], f.prototype, "noBackdropClose", void 0), e([d()], f.prototype, "_hasBody", void 0), f = e([l("web-ui-dialog")], f);
91
92
  //#endregion
92
- export { d as WebUiDialog };
93
+ export { f as WebUiDialog };
93
94
 
94
95
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/dialog/index.ts"],"sourcesContent":["import { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport '@/components/button'\nimport glass from '@/assets/glass.css?inline'\nimport { defineNativeDialogPresence } from '@/shared/overlay/native-dialog-presence'\nimport { createScrollLockLease } from '@/shared/scroll-lock/scroll-lock'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-dialog')\nexport class WebUiDialog extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: Boolean, reflect: true }) open = false\n @property({ type: Boolean, reflect: true, attribute: 'no-scroll-lock' }) noScrollLock = false\n @property({ type: Boolean, reflect: true, attribute: 'no-backdrop-close' }) noBackdropClose = false\n\n @state() private _hasBody = false\n\n private readonly _scrollLock = createScrollLockLease()\n private readonly _presence = defineNativeDialogPresence().make({\n getDialog: () => this.dialog,\n isConnected: () => this.isConnected,\n isOpen: () => this.open\n })\n\n private get dialog() {\n return this.shadowRoot?.querySelector('dialog') ?? null\n }\n\n protected override updated(props: PropertyValues) {\n super.updated(props)\n if (!this.isConnected) return\n\n if (props.has('open')) {\n this.emitOpenChange()\n this._presence.sync(this.open)\n }\n if (props.has('open') || props.has('noScrollLock')) this._syncScrollLock()\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._presence.dispose()\n this._scrollLock.release()\n }\n\n /** 以模态方式打开对话框(命令式) */\n showModal() {\n if (this.open) return\n this.open = true\n }\n\n close() {\n this.open = false\n }\n\n private handleCancel(e: Event) {\n // 保留 top layer 直到视觉退场完成,避免原生关闭跳过退出动画。\n e.preventDefault()\n this.close()\n }\n\n private handleBackdropClick(e: MouseEvent) {\n if (e.target !== (e.currentTarget as HTMLDialogElement)) return\n if (this.noBackdropClose) return\n this.close()\n }\n\n private emitOpenChange() {\n this.dispatchEvent(\n new CustomEvent('open-change', {\n detail: { open: this.open },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _onTransitionEnd = (event: TransitionEvent) => {\n this._presence.handleTransitionEnd(event)\n }\n\n private _onNativeClose = () => {\n if (!this.open) return\n this._presence.handleNativeClose()\n this.open = false\n }\n\n private _syncScrollLock(isOpen = this.open) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n private _onBodySlotChange(e: Event) {\n if (!(e.target instanceof HTMLSlotElement)) return\n this._hasBody = e.target.assignedElements().length > 0\n }\n\n override render() {\n return html`\n <dialog\n @cancel=${this.handleCancel}\n @close=${this._onNativeClose}\n @click=${this.handleBackdropClick}\n @transitionend=${this._onTransitionEnd}\n >\n <div class=\"wui-dialog-body wui-glass\">\n ${this._hasBody\n ? html`<slot name=\"body\" @slotchange=${this._onBodySlotChange}></slot>`\n : html`\n <slot name=\"body\" @slotchange=${this._onBodySlotChange} hidden></slot>\n <div class=\"title\"><slot name=\"title\"></slot></div>\n <div class=\"desc\"><slot></slot></div>\n <div class=\"wui-dialog-footer\"><slot name=\"footer\"></slot></div>\n `}\n </div>\n </dialog>\n `\n }\n\n declare readonly $events: {\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-dialog': WebUiDialog\n }\n}\n"],"mappings":";;;;;;;;;AAWO,IAAM,IAAN,cAA0B,EAAW;;EAyEX,aAtEoB,KAAA,OAAA,IACqC,KAAA,eAAA,IACM,KAAA,kBAAA,IAElE,KAAA,WAAA,IAEG,KAAA,cAAA,EAAsB,GACxB,KAAA,YAAA,EAA2B,CAAC,CAAC,KAAK;GAC7D,iBAAiB,KAAK;GACtB,mBAAmB,KAAK;GACxB,cAAc,KAAK;EACrB,CAAC,GAuD2B,KAAA,oBAAA,MAA2B;GACrD,KAAK,UAAU,oBAAoB,CAAK;EAC1C,GAE+B,KAAA,uBAAA;GACxB,AAEL,KAAK,UADL,KAAK,UAAU,kBAAkB,GACrB;EACd;;;EA5EyB,KAAA,SAAA,CAAC,EAAU,CAAK,GAAG,EAAU,CAAK,CAAC;;CAe5D,IAAY,SAAS;EACnB,OAAO,KAAK,YAAY,cAAc,QAAQ,KAAK;CACrD;CAEA,QAA2B,GAAuB;EAChD,MAAM,QAAQ,CAAK,GACd,KAAK,gBAEN,EAAM,IAAI,MAAM,MAClB,KAAK,eAAe,GACpB,KAAK,UAAU,KAAK,KAAK,IAAI,KAE3B,EAAM,IAAI,MAAM,KAAK,EAAM,IAAI,cAAc,MAAG,KAAK,gBAAgB;CAC3E;CAEA,uBAAgC;EAG9B,AAFA,MAAM,qBAAqB,GAC3B,KAAK,UAAU,QAAQ,GACvB,KAAK,YAAY,QAAQ;CAC3B;CAGA,YAAY;EACN,AACJ,KAAK,SAAO;CACd;CAEA,QAAQ;EACN,KAAK,OAAO;CACd;CAEA,aAAqB,GAAU;EAG7B,AADA,EAAE,eAAe,GACjB,KAAK,MAAM;CACb;CAEA,oBAA4B,GAAe;EACrC,EAAE,WAAY,EAAE,kBAChB,KAAK,mBACT,KAAK,MAAM;CACb;CAEA,iBAAyB;EACvB,KAAK,cACH,IAAI,YAAY,eAAe;GAC7B,QAAQ,EAAE,MAAM,KAAK,KAAK;GAC1B,SAAS;GACT,UAAU;EACZ,CAAC,CACH;CACF;CAYA,gBAAwB,IAAS,KAAK,MAAM;EAC1C,KAAK,YAAY,KAAK,KAAU,CAAC,KAAK,YAAY;CACpD;CAEA,kBAA0B,GAAU;EAC5B,EAAE,kBAAkB,oBAC1B,KAAK,WAAW,EAAE,OAAO,iBAAiB,CAAC,CAAC,SAAS;CACvD;CAEA,SAAkB;EAChB,OAAO,CAAI;;kBAEG,KAAK,aAAa;iBACnB,KAAK,eAAe;iBACpB,KAAK,oBAAoB;yBACjB,KAAK,iBAAiB;;;YAGnC,KAAK,WACH,CAAI,iCAAiC,KAAK,kBAAkB,YAC5D,CAAI;gDAC8B,KAAK,kBAAkB;;;;gBAIvD;;;;CAId;AAKF;AA9GG,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,WAAW;AAAiB,CAAC,CAAA,GAAA,EAAA,WAAA,gBAAA,KAAA,CAAA,GACtE,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,WAAW;AAAoB,CAAC,CAAA,GAAA,EAAA,WAAA,mBAAA,KAAA,CAAA,GAEzE,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GARR,IAAA,EAAA,CAAA,EAAc,eAAe,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/dialog/index.ts"],"sourcesContent":["import { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport '@/components/button'\nimport glass from '@/assets/glass.css?inline'\nimport { UserChangeController } from '@/shared/events/user-change'\nimport { defineNativeDialogPresence } from '@/shared/overlay/native-dialog-presence'\nimport { defineScrollLockLease } from '@/shared/scroll-lock/scroll-lock'\n\nimport style from './style.css?inline'\n\n@customElement('web-ui-dialog')\nexport class WebUiDialog extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: Boolean, reflect: true }) open = false\n @property({ type: Boolean, reflect: true, attribute: 'no-scroll-lock' }) noScrollLock = false\n @property({ type: Boolean, reflect: true, attribute: 'no-backdrop-close' }) noBackdropClose = false\n\n @state() private _hasBody = false\n private readonly _userOpenChange = new UserChangeController()\n\n private readonly _scrollLock = defineScrollLockLease().make()\n private readonly _presence = defineNativeDialogPresence().make({\n getDialog: () => this.dialog,\n isConnected: () => this.isConnected,\n isOpen: () => this.open\n })\n\n private get dialog() {\n return this.shadowRoot?.querySelector('dialog') ?? null\n }\n\n protected override updated(props: PropertyValues) {\n super.updated(props)\n if (!this.isConnected) return\n\n if (props.has('open')) {\n if (this._userOpenChange.consume()) this.emitOpenChange()\n this._presence.sync(this.open)\n }\n if (props.has('open') || props.has('noScrollLock')) this._syncScrollLock()\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._presence.dispose()\n this._scrollLock.release()\n }\n\n // 以模态方式打开对话框(命令式)\n showModal() {\n if (this.open) return\n this.open = true\n }\n\n close() {\n this.open = false\n }\n\n private handleCancel(e: Event) {\n // 保留 top layer 直到视觉退场完成,避免原生关闭跳过退出动画。\n e.preventDefault()\n this._userOpenChange.mark()\n this.close()\n }\n\n private handleBackdropClick(e: MouseEvent) {\n if (e.target !== (e.currentTarget as HTMLDialogElement)) return\n if (this.noBackdropClose) return\n this._userOpenChange.mark()\n this.close()\n }\n\n private emitOpenChange() {\n this.dispatchEvent(\n new CustomEvent('open-change', {\n detail: { open: this.open },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private _onTransitionEnd = (event: TransitionEvent) => {\n this._presence.handleTransitionEnd(event)\n }\n\n private _onNativeClose = () => {\n if (!this.open) return\n this._presence.handleNativeClose()\n this._userOpenChange.mark()\n this.open = false\n }\n\n private _syncScrollLock(isOpen = this.open) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n private _onBodySlotChange(e: Event) {\n if (!(e.target instanceof HTMLSlotElement)) return\n this._hasBody = e.target.assignedElements().length > 0\n }\n\n override render() {\n return html`\n <dialog\n @cancel=${this.handleCancel}\n @close=${this._onNativeClose}\n @click=${this.handleBackdropClick}\n @transitionend=${this._onTransitionEnd}\n >\n <div class=\"wui-dialog-body wui-glass\">\n ${this._hasBody\n ? html`<slot name=\"body\" @slotchange=${this._onBodySlotChange}></slot>`\n : html`\n <slot name=\"body\" @slotchange=${this._onBodySlotChange} hidden></slot>\n <div class=\"title\"><slot name=\"title\"></slot></div>\n <div class=\"desc\"><slot></slot></div>\n <div class=\"wui-dialog-footer\"><slot name=\"footer\"></slot></div>\n `}\n </div>\n </dialog>\n `\n }\n\n declare readonly $events: {\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-dialog': WebUiDialog\n }\n}\n"],"mappings":";;;;;;;;;;AAYO,IAAM,IAAN,cAA0B,EAAW;;EA4EX,aAzEoB,KAAA,OAAA,IACqC,KAAA,eAAA,IACM,KAAA,kBAAA,IAElE,KAAA,WAAA,IACO,KAAA,kBAAA,IAAI,EAAqB,GAE7B,KAAA,cAAA,EAAsB,CAAC,CAAC,KAAK,GAC/B,KAAA,YAAA,EAA2B,CAAC,CAAC,KAAK;GAC7D,iBAAiB,KAAK;GACtB,mBAAmB,KAAK;GACxB,cAAc,KAAK;EACrB,CAAC,GAyD2B,KAAA,oBAAA,MAA2B;GACrD,KAAK,UAAU,oBAAoB,CAAK;EAC1C,GAE+B,KAAA,uBAAA;GACxB,AAGL,KAAK,UAFL,KAAK,UAAU,kBAAkB,GACjC,KAAK,gBAAgB,KAAK,GACd;EACd;;;EAhFyB,KAAA,SAAA,CAAC,EAAU,CAAK,GAAG,EAAU,CAAK,CAAC;;CAgB5D,IAAY,SAAS;EACnB,OAAO,KAAK,YAAY,cAAc,QAAQ,KAAK;CACrD;CAEA,QAA2B,GAAuB;EAChD,MAAM,QAAQ,CAAK,GACd,KAAK,gBAEN,EAAM,IAAI,MAAM,MACd,KAAK,gBAAgB,QAAQ,KAAG,KAAK,eAAe,GACxD,KAAK,UAAU,KAAK,KAAK,IAAI,KAE3B,EAAM,IAAI,MAAM,KAAK,EAAM,IAAI,cAAc,MAAG,KAAK,gBAAgB;CAC3E;CAEA,uBAAgC;EAG9B,AAFA,MAAM,qBAAqB,GAC3B,KAAK,UAAU,QAAQ,GACvB,KAAK,YAAY,QAAQ;CAC3B;CAGA,YAAY;EACN,AACJ,KAAK,SAAO;CACd;CAEA,QAAQ;EACN,KAAK,OAAO;CACd;CAEA,aAAqB,GAAU;EAI7B,AAFA,EAAE,eAAe,GACjB,KAAK,gBAAgB,KAAK,GAC1B,KAAK,MAAM;CACb;CAEA,oBAA4B,GAAe;EACrC,EAAE,WAAY,EAAE,kBAChB,KAAK,oBACT,KAAK,gBAAgB,KAAK,GAC1B,KAAK,MAAM;CACb;CAEA,iBAAyB;EACvB,KAAK,cACH,IAAI,YAAY,eAAe;GAC7B,QAAQ,EAAE,MAAM,KAAK,KAAK;GAC1B,SAAS;GACT,UAAU;EACZ,CAAC,CACH;CACF;CAaA,gBAAwB,IAAS,KAAK,MAAM;EAC1C,KAAK,YAAY,KAAK,KAAU,CAAC,KAAK,YAAY;CACpD;CAEA,kBAA0B,GAAU;EAC5B,EAAE,kBAAkB,oBAC1B,KAAK,WAAW,EAAE,OAAO,iBAAiB,CAAC,CAAC,SAAS;CACvD;CAEA,SAAkB;EAChB,OAAO,CAAI;;kBAEG,KAAK,aAAa;iBACnB,KAAK,eAAe;iBACpB,KAAK,oBAAoB;yBACjB,KAAK,iBAAiB;;;YAGnC,KAAK,WACH,CAAI,iCAAiC,KAAK,kBAAkB,YAC5D,CAAI;gDAC8B,KAAK,kBAAkB;;;;gBAIvD;;;;CAId;AAKF;AAlHG,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,WAAW;AAAiB,CAAC,CAAA,GAAA,EAAA,WAAA,gBAAA,KAAA,CAAA,GACtE,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;CAAM,WAAW;AAAoB,CAAC,CAAA,GAAA,EAAA,WAAA,mBAAA,KAAA,CAAA,GAEzE,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GARR,IAAA,EAAA,CAAA,EAAc,eAAe,CAAA,GAAA,CAAA"}
@@ -9,12 +9,12 @@ export declare class WebUiDrawer extends LitElement {
9
9
  get placement(): DrawerPlacement;
10
10
  set placement(v: string);
11
11
  private _placement;
12
- /** 标题文字(未传 header slot 时显示默认 header) */
13
12
  heading: string;
14
13
  closable: boolean;
15
14
  private get dialog();
16
15
  private _hasHeaderSlot;
17
16
  private _hasFooterSlot;
17
+ private readonly _userOpenChange;
18
18
  private readonly _scrollLock;
19
19
  private readonly _presence;
20
20
  connectedCallback(): void;
@@ -26,10 +26,9 @@ export declare class WebUiDrawer extends LitElement {
26
26
  protected updated(props: PropertyValues): void;
27
27
  private handleTransitionEnd;
28
28
  private handleKeydown;
29
- /** 打开抽屉(命令式) */
30
29
  show(): void;
31
- /** 关闭抽屉(带动画) */
32
30
  close(): void;
31
+ private readonly _closeFromUser;
33
32
  private handleCancel;
34
33
  private handleNativeClose;
35
34
  private handleBackdropClick;