@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,5 +1,5 @@
1
1
  //#region src/components/dialog/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{display:contents}dialog{transform:scale(var(--wui-scale-enter,.97));box-sizing:border-box;max-width:min(90vw, var(--wui-dialog-max-width,360px));max-height:90vh;color:var(--wui-color-text,#1b1b1b);opacity:0;transition:opacity var(--wui-duration-overlay-enter,.18s) var(--wui-ease-out,cubic-bezier(.23, 1, .32, 1)), transform var(--wui-duration-overlay-enter,.18s) var(--wui-ease-out,cubic-bezier(.23, 1, .32, 1));background:0 0;border:none;padding:0;font-family:inherit;overflow:visible}dialog::backdrop{opacity:0;background:var(--wui-dialog-overlay-bg,var(--wui-color-backdrop,#0000001a));transition:opacity var(--wui-duration-overlay-enter,.18s) ease}dialog[open].is-visible{opacity:1;transform:scale(1)}dialog.is-closing{pointer-events:none;transition-duration:var(--wui-duration-overlay-exit,.14s)}dialog.is-closing::backdrop{transition-duration:var(--wui-duration-overlay-exit,.14s)}dialog[open].is-visible::backdrop{opacity:1}@media (prefers-reduced-motion:reduce){dialog,dialog[open].is-visible{transition-duration:.12s;transform:none}}.wui-dialog-body{--wui-glass-shadow:var(--wui-shadow-overlay,2px 16px 40px #0006);background-color:var(--wui-color-surface-overlay,#f6f6f6e0);border-radius:20px;padding:24px}.title{color:var(--wui-color-text,#1b1b1b);margin:0 0 8px;padding:0;font-size:18px;font-weight:600;line-height:1.4}.desc{color:var(--wui-color-text-muted,#6a6a6a);margin:0 0 20px;padding:0;font-size:14px;line-height:1.5}.wui-dialog-footer{flex-direction:column;gap:10px;display:flex}.wui-dialog-footer ::slotted(web-ui-button){width:100%;display:flex}:host([horizontal]) .wui-dialog-footer{flex-direction:row;justify-content:center;gap:10px}:host([horizontal]) .wui-dialog-footer ::slotted(web-ui-button:not([full])){width:auto}:host([horizontal]) .wui-dialog-footer ::slotted(web-ui-button[full]){flex:1;min-width:0}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{display:contents}dialog{transform:scale(var(--wui-scale-enter,.97));box-sizing:border-box;max-width:min(90vw, var(--wui-dialog-max-width,360px));max-height:90vh;color:var(--wui-color-text,#1b1b1b);opacity:0;transition:opacity var(--wui-duration-overlay-enter,.18s) var(--wui-ease-enter,cubic-bezier(.23, 1, .32, 1)), transform var(--wui-duration-overlay-enter,.18s) var(--wui-ease-enter,cubic-bezier(.23, 1, .32, 1));background:0 0;border:none;padding:0;font-family:inherit;overflow:visible}dialog::backdrop{opacity:0;background:var(--wui-dialog-overlay-bg,var(--wui-color-backdrop,#0000001a));transition:opacity var(--wui-duration-overlay-enter,.18s) ease}dialog[open].is-visible{opacity:1;transform:scale(1)}dialog.is-closing{pointer-events:none;transition-duration:var(--wui-duration-overlay-exit,.14s)}dialog.is-closing::backdrop{transition-duration:var(--wui-duration-overlay-exit,.14s)}dialog[open].is-visible::backdrop{opacity:1}@media (prefers-reduced-motion:reduce){dialog,dialog[open].is-visible{transition-duration:var(--wui-duration-feedback,.1s);transform:none}}.wui-dialog-body{--wui-glass-shadow:var(--wui-shadow-overlay,2px 16px 40px #0006);background-color:var(--wui-color-surface-overlay,#f6f6f6e0);border-radius:32px;padding:32px 24px 24px}.title{color:var(--wui-color-text,#1b1b1b);margin:0 0 16px;padding:0;font-size:18px;font-weight:600;line-height:1.4}.desc{color:var(--wui-color-text,#1b1b1b);margin:0 0 24px;padding:0;font-size:14px;line-height:1.5}.wui-dialog-footer{flex-direction:column;gap:10px;display:flex}.wui-dialog-footer ::slotted(web-ui-button){width:100%;display:flex}:host([horizontal]) .wui-dialog-footer{flex-direction:row;justify-content:center;gap:12px}:host([horizontal]) .wui-dialog-footer ::slotted(web-ui-button:not([full])){width:auto}:host([horizontal]) .wui-dialog-footer ::slotted(web-ui-button[full]){flex:1;min-width:0}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/dialog/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: contents;\n}\n\ndialog {\n transform: scale(var(--wui-scale-enter, 0.97));\n\n overflow: visible;\n\n box-sizing: border-box;\n max-width: min(90vw, var(--wui-dialog-max-width, 360px));\n max-height: 90vh;\n padding: 0;\n border: none;\n\n font-family: inherit;\n color: var(--wui-color-text, #1b1b1b);\n\n opacity: 0;\n background: transparent;\n\n transition:\n opacity var(--wui-duration-overlay-enter, 180ms) var(--wui-ease-out, cubic-bezier(0.23, 1, 0.32, 1)),\n transform var(--wui-duration-overlay-enter, 180ms) var(--wui-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n\n &::backdrop {\n opacity: 0;\n background: var(--wui-dialog-overlay-bg, var(--wui-color-backdrop, rgb(0 0 0 / 0.1)));\n transition: opacity var(--wui-duration-overlay-enter, 180ms) ease;\n }\n}\n\ndialog[open].is-visible {\n transform: scale(1);\n opacity: 1;\n}\n\ndialog.is-closing {\n pointer-events: none;\n transition-duration: var(--wui-duration-overlay-exit, 140ms);\n}\n\ndialog.is-closing::backdrop {\n transition-duration: var(--wui-duration-overlay-exit, 140ms);\n}\n\ndialog[open].is-visible::backdrop {\n opacity: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n dialog,\n dialog[open].is-visible {\n transform: none;\n transition-duration: 120ms;\n }\n}\n\n/* ===== 玻璃卡片主体(样式由 glass.css 提供) ===== */\n\n.wui-dialog-body {\n --wui-glass-shadow: var(--wui-shadow-overlay, 2px 16px 40px rgb(0 0 0 / 0.4));\n padding: 24px;\n border-radius: 20px;\n background-color: var(--wui-color-surface-overlay, rgb(246 246 246 / 0.88));\n}\n\n/* ===== 标题 ===== */\n\n.title {\n margin: 0 0 8px;\n padding: 0;\n\n font-size: 18px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--wui-color-text, #1b1b1b);\n}\n\n/* ===== 描述 ===== */\n\n.desc {\n margin: 0 0 20px;\n padding: 0;\n\n font-size: 14px;\n line-height: 1.5;\n color: var(--wui-color-text-muted, #6a6a6a);\n}\n\n/* ===== 按钮区域 ===== */\n\n.wui-dialog-footer {\n display: flex;\n flex-direction: column;\n gap: 10px;\n\n /* ===== 按钮全宽(默认垂直排列) ===== */\n\n & ::slotted(web-ui-button) {\n display: flex;\n width: 100%;\n }\n}\n\n/* ===== horizontal 模式 ===== */\n\n:host([horizontal]) .wui-dialog-footer {\n flex-direction: row;\n gap: 10px;\n justify-content: center;\n\n /* 非 full 按钮:居中,不拉伸 */\n\n & ::slotted(web-ui-button:not([full])) {\n width: auto;\n }\n\n /* full 按钮:平分剩余空间 */\n\n & ::slotted(web-ui-button[full]) {\n flex: 1;\n min-width: 0;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/dialog/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: contents;\n}\n\ndialog {\n transform: scale(var(--wui-scale-enter, 0.97));\n\n overflow: visible;\n\n box-sizing: border-box;\n max-width: min(90vw, var(--wui-dialog-max-width, 360px));\n max-height: 90vh;\n padding: 0;\n border: none;\n\n font-family: inherit;\n color: var(--wui-color-text, #1b1b1b);\n\n opacity: 0;\n background: transparent;\n\n transition:\n opacity var(--wui-duration-overlay-enter, 180ms) var(--wui-ease-enter, cubic-bezier(0.23, 1, 0.32, 1)),\n transform var(--wui-duration-overlay-enter, 180ms) var(--wui-ease-enter, cubic-bezier(0.23, 1, 0.32, 1));\n\n &::backdrop {\n opacity: 0;\n background: var(--wui-dialog-overlay-bg, var(--wui-color-backdrop, rgb(0 0 0 / 0.1)));\n transition: opacity var(--wui-duration-overlay-enter, 180ms) ease;\n }\n}\n\ndialog[open].is-visible {\n transform: scale(1);\n opacity: 1;\n}\n\ndialog.is-closing {\n pointer-events: none;\n transition-duration: var(--wui-duration-overlay-exit, 140ms);\n}\n\ndialog.is-closing::backdrop {\n transition-duration: var(--wui-duration-overlay-exit, 140ms);\n}\n\ndialog[open].is-visible::backdrop {\n opacity: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n dialog,\n dialog[open].is-visible {\n transform: none;\n transition-duration: var(--wui-duration-feedback, 100ms);\n }\n}\n\n/* ===== 玻璃卡片主体(样式由 glass.css 提供) ===== */\n\n.wui-dialog-body {\n --wui-glass-shadow: var(--wui-shadow-overlay, 2px 16px 40px rgb(0 0 0 / 0.4));\n padding: 32px 24px 24px;\n border-radius: 32px;\n background-color: var(--wui-color-surface-overlay, rgb(246 246 246 / 0.88));\n}\n\n/* ===== 标题 ===== */\n\n.title {\n margin: 0 0 16px;\n padding: 0;\n\n font-size: 18px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--wui-color-text, #1b1b1b);\n}\n\n/* ===== 描述 ===== */\n\n.desc {\n margin: 0 0 24px;\n padding: 0;\n\n font-size: 14px;\n line-height: 1.5;\n color: var(--wui-color-text, #1b1b1b);\n}\n\n/* ===== 按钮区域 ===== */\n\n.wui-dialog-footer {\n display: flex;\n flex-direction: column;\n gap: 10px;\n\n /* ===== 按钮全宽(默认垂直排列) ===== */\n\n & ::slotted(web-ui-button) {\n display: flex;\n width: 100%;\n }\n}\n\n/* ===== horizontal 模式 ===== */\n\n:host([horizontal]) .wui-dialog-footer {\n flex-direction: row;\n gap: 12px;\n justify-content: center;\n\n /* 非 full 按钮:居中,不拉伸 */\n\n & ::slotted(web-ui-button:not([full])) {\n width: auto;\n }\n\n /* full 按钮:平分剩余空间 */\n\n & ::slotted(web-ui-button[full]) {\n flex: 1;\n min-width: 0;\n }\n}\n"],"mappings":""}
@@ -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;
@@ -4,34 +4,37 @@ import t from "../../assets/glass.js";
4
4
  import n from "../../icons/generated/ooui-close.js";
5
5
  import { normalizeLiteral as r } from "../../shared/normalize/index.js";
6
6
  import "../button/index.js";
7
- import { createScrollLockLease as i } from "../../shared/scroll-lock/scroll-lock.js";
8
- import { defineNativeDialogPresence as a } from "../../shared/overlay/native-dialog-presence.js";
9
- import o from "./style.js";
10
- import { LitElement as s, html as c, nothing as l, unsafeCSS as u } from "lit";
11
- import { customElement as d, property as f } from "lit/decorators.js";
7
+ import { UserChangeController as i } from "../../shared/events/user-change.js";
8
+ import { createScrollLockLease as a } from "../../shared/scroll-lock/scroll-lock.js";
9
+ import { defineNativeDialogPresence as o } from "../../shared/overlay/native-dialog-presence.js";
10
+ import s from "./style.js";
11
+ import { LitElement as c, html as l, nothing as u, unsafeCSS as d } from "lit";
12
+ import { customElement as f, property as p } from "lit/decorators.js";
12
13
  //#region src/components/drawer/index.ts
13
- var p = [
14
+ var m = [
14
15
  "right",
15
16
  "left",
16
17
  "top",
17
18
  "bottom"
18
- ], m = class extends s {
19
+ ], h = class extends c {
19
20
  constructor(...e) {
20
- super(...e), this.open = !1, this.noScrollLock = !1, this.noBackdropClose = !1, this._placement = "right", this.heading = "", this.closable = !1, this._hasHeaderSlot = !1, this._hasFooterSlot = !1, this._scrollLock = i(), this._presence = a().make({
21
+ super(...e), this.open = !1, this.noScrollLock = !1, this.noBackdropClose = !1, this._placement = "right", this.heading = "", this.closable = !1, this._hasHeaderSlot = !1, this._hasFooterSlot = !1, this._userOpenChange = new i(), this._scrollLock = a(), this._presence = o().make({
21
22
  getDialog: () => this.dialog,
22
23
  isConnected: () => this.isConnected,
23
24
  isOpen: () => this.open
24
- });
25
+ }), this._closeFromUser = () => {
26
+ this.open && (this._userOpenChange.mark(), this.close());
27
+ };
25
28
  }
26
29
  static {
27
- this.styles = [u(t), u(o)];
30
+ this.styles = [d(t), d(s)];
28
31
  }
29
32
  get placement() {
30
33
  return this._placement;
31
34
  }
32
35
  set placement(e) {
33
36
  let t = this._placement;
34
- this._placement = r(e, p, "right"), this.requestUpdate("placement", t);
37
+ this._placement = r(e, m, "right"), this.requestUpdate("placement", t);
35
38
  }
36
39
  get dialog() {
37
40
  return this.shadowRoot?.querySelector("dialog") ?? null;
@@ -60,13 +63,13 @@ var p = [
60
63
  t !== this._hasFooterSlot && (this._hasFooterSlot = t, this.requestUpdate());
61
64
  }
62
65
  updated(e) {
63
- super.updated(e), this.isConnected && (e.has("open") && (this.emitOpenChange(), this._presence.sync(this.open)), (e.has("open") || e.has("noScrollLock")) && this._syncScrollLock());
66
+ 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());
64
67
  }
65
68
  handleTransitionEnd(e) {
66
69
  this._presence.handleTransitionEnd(e);
67
70
  }
68
71
  handleKeydown(e) {
69
- e.key === "Escape" && (e.preventDefault(), this.close());
72
+ e.key === "Escape" && (e.preventDefault(), this._closeFromUser());
70
73
  }
71
74
  show() {
72
75
  this.open ||= !0;
@@ -75,13 +78,13 @@ var p = [
75
78
  this.open &&= !1;
76
79
  }
77
80
  handleCancel(e) {
78
- e.preventDefault(), this.close();
81
+ e.preventDefault(), this._closeFromUser();
79
82
  }
80
83
  handleNativeClose() {
81
- this.open &&= (this._presence.handleNativeClose(), !1);
84
+ this.open &&= (this._presence.handleNativeClose(), this._userOpenChange.mark(), !1);
82
85
  }
83
86
  handleBackdropClick(e) {
84
- e.target === e.currentTarget && (this.noBackdropClose || this.close());
87
+ e.target === e.currentTarget && (this.noBackdropClose || this._closeFromUser());
85
88
  }
86
89
  emitOpenChange() {
87
90
  this.dispatchEvent(new CustomEvent("open-change", {
@@ -95,7 +98,7 @@ var p = [
95
98
  }
96
99
  render() {
97
100
  let e = this._hasHeaderSlot || !!this.heading;
98
- return c`
101
+ return l`
99
102
  <dialog
100
103
  @cancel=${this.handleCancel}
101
104
  @close=${this.handleNativeClose}
@@ -104,13 +107,13 @@ var p = [
104
107
  @transitionend=${this.handleTransitionEnd}
105
108
  >
106
109
  <div class="wui-drawer-body wui-glass">
107
- ${e ? c`
110
+ ${e ? l`
108
111
  <div class="wui-drawer-header">
109
112
  <slot name="header" @slotchange=${this.handleHeaderSlotChange}>
110
- ${this.heading ? c`<span class="wui-drawer-heading">${this.heading}</span>` : l}
113
+ ${this.heading ? l`<span class="wui-drawer-heading">${this.heading}</span>` : u}
111
114
  </slot>
112
115
  </div>
113
- ` : l}
116
+ ` : u}
114
117
  <div class="wui-drawer-content">
115
118
  <slot></slot>
116
119
  </div>
@@ -118,34 +121,41 @@ var p = [
118
121
  <slot name="footer" @slotchange=${this.handleFooterSlotChange}></slot>
119
122
  </div>
120
123
  </div>
121
- ${this.closable ? c`
122
- <web-ui-button class="wui-drawer-close" @click=${this.close} aria-label="关闭" variant="secondary" icon>
123
- <web-ui-icon .icon=${n}></web-ui-icon>
124
+ ${this.closable ? l`
125
+ <web-ui-button
126
+ class="wui-drawer-close"
127
+ @click=${this._closeFromUser}
128
+ aria-label="关闭"
129
+ variant="secondary"
130
+ icon
131
+ size="26"
132
+ >
133
+ <web-ui-icon .icon=${n} size="16"></web-ui-icon>
124
134
  </web-ui-button>
125
- ` : l}
135
+ ` : u}
126
136
  </dialog>
127
137
  `;
128
138
  }
129
139
  };
130
- e([f({
140
+ e([p({
131
141
  type: Boolean,
132
142
  reflect: !0
133
- })], m.prototype, "open", void 0), e([f({
143
+ })], h.prototype, "open", void 0), e([p({
134
144
  type: Boolean,
135
145
  reflect: !0,
136
146
  attribute: "no-scroll-lock"
137
- })], m.prototype, "noScrollLock", void 0), e([f({
147
+ })], h.prototype, "noScrollLock", void 0), e([p({
138
148
  type: Boolean,
139
149
  reflect: !0,
140
150
  attribute: "no-backdrop-close"
141
- })], m.prototype, "noBackdropClose", void 0), e([f({
151
+ })], h.prototype, "noBackdropClose", void 0), e([p({
142
152
  type: String,
143
153
  reflect: !0
144
- })], m.prototype, "placement", null), e([f({ type: String })], m.prototype, "heading", void 0), e([f({
154
+ })], h.prototype, "placement", null), e([p({ type: String })], h.prototype, "heading", void 0), e([p({
145
155
  type: Boolean,
146
156
  reflect: !0
147
- })], m.prototype, "closable", void 0), m = e([d("web-ui-drawer")], m);
157
+ })], h.prototype, "closable", void 0), h = e([f("web-ui-drawer")], h);
148
158
  //#endregion
149
- export { m as WebUiDrawer };
159
+ export { h as WebUiDrawer };
150
160
 
151
161
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/drawer/index.ts"],"sourcesContent":["import { html, LitElement, nothing, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport '@/components/icon'\nimport '@/components/button'\nimport glass from '@/assets/glass.css?inline'\nimport { oouiClose } from '@/icons'\nimport { normalizeLiteral } from '@/shared/normalize'\nimport { defineNativeDialogPresence } from '@/shared/overlay/native-dialog-presence'\nimport { createScrollLockLease } from '@/shared/scroll-lock/scroll-lock'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_PLACEMENTS = ['right', 'left', 'top', 'bottom'] as const\n\nexport type DrawerPlacement = (typeof ALLOWED_PLACEMENTS)[number]\n\n@customElement('web-ui-drawer')\nexport class WebUiDrawer 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 @property({ type: String, reflect: true })\n get placement(): DrawerPlacement {\n return this._placement\n }\n set placement(v: string) {\n const old = this._placement\n this._placement = normalizeLiteral(v, ALLOWED_PLACEMENTS, 'right')\n this.requestUpdate('placement', old)\n }\n private _placement: DrawerPlacement = 'right'\n\n /** 标题文字(未传 header slot 时显示默认 header) */\n @property({ type: String }) heading = ''\n\n @property({ type: Boolean, reflect: true }) closable = false\n\n private get dialog() {\n return this.shadowRoot?.querySelector('dialog') ?? null\n }\n\n private _hasHeaderSlot = false\n private _hasFooterSlot = false\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 override connectedCallback() {\n super.connectedCallback()\n this._hasHeaderSlot = Array.from(this.children).some(child => child.getAttribute?.('slot') === 'header')\n this._hasFooterSlot = Array.from(this.children).some(child => child.getAttribute?.('slot') === 'footer')\n }\n\n override firstUpdated() {\n this._checkSlotContent('footer')\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._presence.dispose()\n this._scrollLock.release()\n }\n\n private _checkSlotContent(name: string) {\n const slot = this.shadowRoot?.querySelector(`slot[name=\"${name}\"]`) as HTMLSlotElement | null\n if (!slot) return\n const has = slot.assignedNodes().length > 0\n if (name === 'footer' && has !== this._hasFooterSlot) {\n this._hasFooterSlot = has\n this.requestUpdate()\n }\n }\n\n private handleHeaderSlotChange(e: Event) {\n const has = (e.target as HTMLSlotElement).assignedNodes().length > 0\n if (has !== this._hasHeaderSlot) {\n this._hasHeaderSlot = has\n this.requestUpdate()\n }\n }\n\n private handleFooterSlotChange(e: Event) {\n const has = (e.target as HTMLSlotElement).assignedNodes().length > 0\n if (has !== this._hasFooterSlot) {\n this._hasFooterSlot = has\n this.requestUpdate()\n }\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 private handleTransitionEnd(e: TransitionEvent) {\n this._presence.handleTransitionEnd(e)\n }\n\n private handleKeydown(e: KeyboardEvent) {\n if (e.key !== 'Escape') return\n e.preventDefault()\n this.close()\n }\n\n /** 打开抽屉(命令式) */\n show() {\n if (this.open) return\n this.open = true\n }\n\n /** 关闭抽屉(带动画) */\n close() {\n if (!this.open) return\n this.open = false\n }\n\n private handleCancel(e: Event) {\n // 保留 top layer 直到 CSS 过渡结束,避免原生关闭跳过退出动画。\n e.preventDefault()\n this.close()\n }\n\n private handleNativeClose() {\n if (!this.open) return\n\n // 原生关闭可绕过 cancel;同步受控状态,避免 show() 误判为已打开。\n this._presence.handleNativeClose()\n this.open = false\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 _syncScrollLock(isOpen = this.open) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n override render() {\n const showHeader = this._hasHeaderSlot || !!this.heading\n\n return html`\n <dialog\n @cancel=${this.handleCancel}\n @close=${this.handleNativeClose}\n @click=${this.handleBackdropClick}\n @keydown=${this.handleKeydown}\n @transitionend=${this.handleTransitionEnd}\n >\n <div class=\"wui-drawer-body wui-glass\">\n ${showHeader\n ? html`\n <div class=\"wui-drawer-header\">\n <slot name=\"header\" @slotchange=${this.handleHeaderSlotChange}>\n ${this.heading ? html`<span class=\"wui-drawer-heading\">${this.heading}</span>` : nothing}\n </slot>\n </div>\n `\n : nothing}\n <div class=\"wui-drawer-content\">\n <slot></slot>\n </div>\n <div class=\"wui-drawer-footer\" ?hidden=${!this._hasFooterSlot}>\n <slot name=\"footer\" @slotchange=${this.handleFooterSlotChange}></slot>\n </div>\n </div>\n ${this.closable\n ? html`\n <web-ui-button class=\"wui-drawer-close\" @click=${this.close} aria-label=\"关闭\" variant=\"secondary\" icon>\n <web-ui-icon .icon=${oouiClose}></web-ui-icon>\n </web-ui-button>\n `\n : nothing}\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-drawer': WebUiDrawer\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/drawer/index.ts"],"sourcesContent":["import { html, LitElement, nothing, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport '@/components/icon'\nimport '@/components/button'\nimport glass from '@/assets/glass.css?inline'\nimport { oouiClose } from '@/icons'\nimport { UserChangeController } from '@/shared/events/user-change'\nimport { normalizeLiteral } from '@/shared/normalize'\nimport { defineNativeDialogPresence } from '@/shared/overlay/native-dialog-presence'\nimport { createScrollLockLease } from '@/shared/scroll-lock/scroll-lock'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_PLACEMENTS = ['right', 'left', 'top', 'bottom'] as const\n\nexport type DrawerPlacement = (typeof ALLOWED_PLACEMENTS)[number]\n\n@customElement('web-ui-drawer')\nexport class WebUiDrawer 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 @property({ type: String, reflect: true })\n get placement(): DrawerPlacement {\n return this._placement\n }\n set placement(v: string) {\n const old = this._placement\n this._placement = normalizeLiteral(v, ALLOWED_PLACEMENTS, 'right')\n this.requestUpdate('placement', old)\n }\n private _placement: DrawerPlacement = 'right'\n\n // 标题文字(未传 header slot 时显示默认 header)\n @property({ type: String }) heading = ''\n\n @property({ type: Boolean, reflect: true }) closable = false\n\n private get dialog() {\n return this.shadowRoot?.querySelector('dialog') ?? null\n }\n\n private _hasHeaderSlot = false\n private _hasFooterSlot = false\n private readonly _userOpenChange = new UserChangeController()\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 override connectedCallback() {\n super.connectedCallback()\n this._hasHeaderSlot = Array.from(this.children).some(child => child.getAttribute?.('slot') === 'header')\n this._hasFooterSlot = Array.from(this.children).some(child => child.getAttribute?.('slot') === 'footer')\n }\n\n override firstUpdated() {\n this._checkSlotContent('footer')\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._presence.dispose()\n this._scrollLock.release()\n }\n\n private _checkSlotContent(name: string) {\n const slot = this.shadowRoot?.querySelector(`slot[name=\"${name}\"]`) as HTMLSlotElement | null\n if (!slot) return\n const has = slot.assignedNodes().length > 0\n if (name === 'footer' && has !== this._hasFooterSlot) {\n this._hasFooterSlot = has\n this.requestUpdate()\n }\n }\n\n private handleHeaderSlotChange(e: Event) {\n const has = (e.target as HTMLSlotElement).assignedNodes().length > 0\n if (has !== this._hasHeaderSlot) {\n this._hasHeaderSlot = has\n this.requestUpdate()\n }\n }\n\n private handleFooterSlotChange(e: Event) {\n const has = (e.target as HTMLSlotElement).assignedNodes().length > 0\n if (has !== this._hasFooterSlot) {\n this._hasFooterSlot = has\n this.requestUpdate()\n }\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 private handleTransitionEnd(e: TransitionEvent) {\n this._presence.handleTransitionEnd(e)\n }\n\n private handleKeydown(e: KeyboardEvent) {\n if (e.key !== 'Escape') return\n e.preventDefault()\n this._closeFromUser()\n }\n\n // 打开抽屉(命令式)\n show() {\n if (this.open) return\n this.open = true\n }\n\n // 关闭抽屉(带动画)\n close() {\n if (!this.open) return\n this.open = false\n }\n\n private readonly _closeFromUser = () => {\n if (!this.open) return\n this._userOpenChange.mark()\n this.close()\n }\n\n private handleCancel(e: Event) {\n // 保留 top layer 直到 CSS 过渡结束,避免原生关闭跳过退出动画。\n e.preventDefault()\n this._closeFromUser()\n }\n\n private handleNativeClose() {\n if (!this.open) return\n\n // 原生关闭可绕过 cancel;同步受控状态,避免 show() 误判为已打开。\n this._presence.handleNativeClose()\n this._userOpenChange.mark()\n this.open = false\n }\n\n private handleBackdropClick(e: MouseEvent) {\n if (e.target !== (e.currentTarget as HTMLDialogElement)) return\n if (this.noBackdropClose) return\n this._closeFromUser()\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 _syncScrollLock(isOpen = this.open) {\n this._scrollLock.sync(isOpen && !this.noScrollLock)\n }\n\n override render() {\n const showHeader = this._hasHeaderSlot || !!this.heading\n\n return html`\n <dialog\n @cancel=${this.handleCancel}\n @close=${this.handleNativeClose}\n @click=${this.handleBackdropClick}\n @keydown=${this.handleKeydown}\n @transitionend=${this.handleTransitionEnd}\n >\n <div class=\"wui-drawer-body wui-glass\">\n ${showHeader\n ? html`\n <div class=\"wui-drawer-header\">\n <slot name=\"header\" @slotchange=${this.handleHeaderSlotChange}>\n ${this.heading ? html`<span class=\"wui-drawer-heading\">${this.heading}</span>` : nothing}\n </slot>\n </div>\n `\n : nothing}\n <div class=\"wui-drawer-content\">\n <slot></slot>\n </div>\n <div class=\"wui-drawer-footer\" ?hidden=${!this._hasFooterSlot}>\n <slot name=\"footer\" @slotchange=${this.handleFooterSlotChange}></slot>\n </div>\n </div>\n ${this.closable\n ? html`\n <web-ui-button\n class=\"wui-drawer-close\"\n @click=${this._closeFromUser}\n aria-label=\"关闭\"\n variant=\"secondary\"\n icon\n size=\"26\"\n >\n <web-ui-icon .icon=${oouiClose} size=\"16\"></web-ui-icon>\n </web-ui-button>\n `\n : nothing}\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-drawer': WebUiDrawer\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  //#region src/components/drawer/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{display:contents}dialog{box-sizing:border-box;width:var(--wui-drawer-width,320px);max-width:90vw;height:100dvh;max-height:100dvh;color:var(--wui-color-text,#1b1b1b);transition:transform var(--wui-duration-drawer,.28s) var(--wui-ease-out,cubic-bezier(.23, 1, .32, 1));background:0 0;border:none;margin:0;padding:0;font-family:inherit;inset:0 0 0 auto;overflow:visible;transform:translate(100%)}dialog::backdrop{opacity:0;background:var(--wui-drawer-overlay-bg,#0000001f);transition:opacity var(--wui-duration-drawer,.28s) ease}dialog[open].is-visible,:host([placement=left]) dialog[open].is-visible,:host([placement=top]) dialog[open].is-visible,:host([placement=bottom]) dialog[open].is-visible{transform:translate(0)}dialog.is-closing{pointer-events:none}dialog[open].is-visible::backdrop{opacity:1}:host([placement=left]) dialog{left:0;right:auto;transform:translate(-100%)}:host([placement=top]) dialog,:host([placement=bottom]) dialog{width:100vw;max-width:100vw;height:var(--wui-drawer-height,300px);max-height:90dvh}:host([placement=top]) dialog{inset:0 0 auto;transform:translateY(-100%)}:host([placement=bottom]) dialog{inset:auto 0 0;transform:translateY(100%)}.wui-drawer-body{--wui-glass-shadow:var(--wui-shadow-overlay,2px 16px 40px #0006);background-color:var(--wui-color-surface-overlay,#f6f6f6e0);flex-direction:column;height:100%;display:flex}.wui-drawer-header{border-bottom:1px solid #0000000f;justify-content:space-between;align-items:center;padding:16px 20px;font-size:18px;font-weight:600;line-height:1.4;display:flex}.wui-drawer-content{overscroll-behavior:contain;font-size:var(--wui-font-size,14px);color:var(--wui-color-text,#1b1b1b);flex:1;padding:20px;line-height:1.5;overflow-y:auto}.wui-drawer-footer{border-top:1px solid #0000000f;flex-shrink:0;padding:16px 20px}@media (prefers-reduced-motion:reduce){dialog{transition:opacity .12s}dialog::backdrop{transition-duration:.12s}dialog[open].is-visible{transform:none}}.wui-drawer-footer[hidden]{display:none}.wui-drawer-close{z-index:3;position:absolute;top:8px;right:8px}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{display:contents}dialog{box-sizing:border-box;width:var(--wui-drawer-width,320px);max-width:90vw;height:100dvh;max-height:100dvh;color:var(--wui-color-text,#1b1b1b);transition:transform var(--wui-duration-drawer-enter,.28s) var(--wui-ease-enter,cubic-bezier(.23, 1, .32, 1));background:0 0;border:none;margin:0;padding:0;font-family:inherit;inset:0 0 0 auto;overflow:visible;transform:translate(100%)}dialog::backdrop{opacity:0;background:var(--wui-drawer-overlay-bg,#0000001f);transition:opacity var(--wui-duration-drawer-enter,.28s) ease}dialog[open].is-visible,:host([placement=left]) dialog[open].is-visible,:host([placement=top]) dialog[open].is-visible,:host([placement=bottom]) dialog[open].is-visible{transform:translate(0)}dialog.is-closing{pointer-events:none;transition:transform var(--wui-duration-drawer-exit,.24s) var(--wui-ease-enter,cubic-bezier(.23, 1, .32, 1))}dialog.is-closing::backdrop{transition:opacity var(--wui-duration-drawer-exit,.24s) ease}dialog[open].is-visible::backdrop{opacity:1}:host([placement=left]) dialog{left:0;right:auto;transform:translate(-100%)}:host([placement=top]) dialog,:host([placement=bottom]) dialog{width:100vw;max-width:100vw;height:var(--wui-drawer-height,300px);max-height:90dvh}:host([placement=top]) dialog{inset:0 0 auto;transform:translateY(-100%)}:host([placement=bottom]) dialog{inset:auto 0 0;transform:translateY(100%)}.wui-drawer-body{--wui-glass-shadow:var(--wui-shadow-overlay,2px 16px 40px #0006);background-color:var(--wui-color-surface-overlay,#f6f6f6e0);flex-direction:column;height:100%;display:flex}.wui-drawer-header{border-bottom:1px solid #0000000f;justify-content:space-between;align-items:center;padding:16px 20px;font-size:18px;font-weight:600;line-height:1.4;display:flex}.wui-drawer-content{overscroll-behavior:contain;font-size:var(--wui-font-size,14px);color:var(--wui-color-text,#1b1b1b);flex:1;padding:20px;line-height:1.5;overflow-y:auto}.wui-drawer-footer{border-top:1px solid #0000000f;flex-shrink:0;padding:16px 20px}@media (prefers-reduced-motion:reduce){dialog{transition:opacity var(--wui-duration-feedback,.1s) ease}dialog::backdrop{transition-duration:var(--wui-duration-feedback,.1s)}dialog[open].is-visible{transform:none}}.wui-drawer-footer[hidden]{display:none}.wui-drawer-close{z-index:3;position:absolute;top:16px;right:16px}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/drawer/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: contents;\n}\n\n/* ===== Dialog 容器 ===== */\ndialog {\n /* 默认:右侧滑出 — 需显式 left:auto 覆盖 UA dialog:modal 的 left:0 */\n top: 0;\n right: 0;\n bottom: 0;\n left: auto;\n transform: translateX(100%);\n\n /* 阴影属于抽屉主体,不能由同尺寸的原生 dialog 裁剪。内容滚动由 .wui-drawer-content 管理。 */\n overflow: visible;\n\n box-sizing: border-box;\n width: var(--wui-drawer-width, 320px);\n max-width: 90vw;\n height: 100dvh;\n max-height: 100dvh;\n margin: 0;\n padding: 0;\n border: none;\n\n font-family: inherit;\n color: var(--wui-color-text, #1b1b1b);\n\n background: transparent;\n\n transition: transform var(--wui-duration-drawer, 280ms) var(--wui-ease-out, cubic-bezier(0.23, 1, 0.32, 1));\n\n &::backdrop {\n opacity: 0;\n background: var(--wui-drawer-overlay-bg, rgb(0 0 0 / 0.12));\n transition: opacity var(--wui-duration-drawer, 280ms) ease;\n }\n}\n\ndialog[open].is-visible {\n transform: translate(0, 0);\n}\n\n:host([placement='left']) dialog[open].is-visible,\n:host([placement='top']) dialog[open].is-visible,\n:host([placement='bottom']) dialog[open].is-visible {\n transform: translate(0, 0);\n}\n\ndialog.is-closing {\n pointer-events: none;\n}\n\ndialog[open].is-visible::backdrop {\n opacity: 1;\n}\n\n/* ===== Placement 变体 ===== */\n\n:host([placement='left']) dialog {\n right: auto;\n left: 0;\n transform: translateX(-100%);\n}\n\n:host([placement='top']) dialog,\n:host([placement='bottom']) dialog {\n width: 100vw;\n max-width: 100vw;\n height: var(--wui-drawer-height, 300px);\n max-height: 90dvh;\n}\n\n:host([placement='top']) dialog {\n top: 0;\n right: 0;\n bottom: auto;\n left: 0;\n transform: translateY(-100%);\n}\n\n:host([placement='bottom']) dialog {\n top: auto;\n right: 0;\n bottom: 0;\n left: 0;\n transform: translateY(100%);\n}\n\n/* ===== 抽屉主体 ===== */\n\n.wui-drawer-body {\n --wui-glass-shadow: var(--wui-shadow-overlay, 2px 16px 40px rgb(0 0 0 / 0.4));\n display: flex;\n flex-direction: column;\n height: 100%;\n background-color: var(--wui-color-surface-overlay, rgb(246 246 246 / 0.88));\n}\n\n/* ===== Header ===== */\n\n.wui-drawer-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 16px 20px;\n border-bottom: 1px solid rgb(0 0 0 / 0.06);\n\n font-size: 18px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n/* ===== 内容区 ===== */\n\n.wui-drawer-content {\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n\n padding: 20px;\n\n font-size: var(--wui-font-size, 14px);\n line-height: 1.5;\n color: var(--wui-color-text, #1b1b1b);\n}\n\n/* ===== Footer ===== */\n\n.wui-drawer-footer {\n flex-shrink: 0;\n padding: 16px 20px;\n border-top: 1px solid rgb(0 0 0 / 0.06);\n}\n\n@media (prefers-reduced-motion: reduce) {\n dialog {\n transition: opacity 120ms ease;\n }\n\n dialog::backdrop {\n transition-duration: 120ms;\n }\n\n dialog[open].is-visible {\n transform: none;\n }\n}\n\n.wui-drawer-footer[hidden] {\n display: none;\n}\n\n/* ===== 关闭按钮(独立定位,与 header 解耦) ===== */\n\n.wui-drawer-close {\n position: absolute;\n z-index: 3;\n top: 8px;\n right: 8px;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/drawer/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: contents;\n}\n\n/* ===== Dialog 容器 ===== */\ndialog {\n /* 默认:右侧滑出 — 需显式 left:auto 覆盖 UA dialog:modal 的 left:0 */\n top: 0;\n right: 0;\n bottom: 0;\n left: auto;\n transform: translateX(100%);\n\n /* 阴影属于抽屉主体,不能由同尺寸的原生 dialog 裁剪。内容滚动由 .wui-drawer-content 管理。 */\n overflow: visible;\n\n box-sizing: border-box;\n width: var(--wui-drawer-width, 320px);\n max-width: 90vw;\n height: 100vh;\n height: 100dvh;\n max-height: 100vh;\n max-height: 100dvh;\n margin: 0;\n padding: 0;\n border: none;\n\n font-family: inherit;\n color: var(--wui-color-text, #1b1b1b);\n\n background: transparent;\n\n transition: transform var(--wui-duration-drawer-enter, 280ms) var(--wui-ease-enter, cubic-bezier(0.23, 1, 0.32, 1));\n\n &::backdrop {\n opacity: 0;\n background: var(--wui-drawer-overlay-bg, rgb(0 0 0 / 0.12));\n transition: opacity var(--wui-duration-drawer-enter, 280ms) ease;\n }\n}\n\ndialog[open].is-visible {\n transform: translate(0, 0);\n}\n\n:host([placement='left']) dialog[open].is-visible,\n:host([placement='top']) dialog[open].is-visible,\n:host([placement='bottom']) dialog[open].is-visible {\n transform: translate(0, 0);\n}\n\ndialog.is-closing {\n pointer-events: none;\n transition: transform var(--wui-duration-drawer-exit, 240ms) var(--wui-ease-enter, cubic-bezier(0.23, 1, 0.32, 1));\n}\n\ndialog.is-closing::backdrop {\n transition: opacity var(--wui-duration-drawer-exit, 240ms) ease;\n}\n\ndialog[open].is-visible::backdrop {\n opacity: 1;\n}\n\n/* ===== Placement 变体 ===== */\n\n:host([placement='left']) dialog {\n right: auto;\n left: 0;\n transform: translateX(-100%);\n}\n\n:host([placement='top']) dialog,\n:host([placement='bottom']) dialog {\n width: 100vw;\n max-width: 100vw;\n height: var(--wui-drawer-height, 300px);\n max-height: 90dvh;\n}\n\n:host([placement='top']) dialog {\n top: 0;\n right: 0;\n bottom: auto;\n left: 0;\n transform: translateY(-100%);\n}\n\n:host([placement='bottom']) dialog {\n top: auto;\n right: 0;\n bottom: 0;\n left: 0;\n transform: translateY(100%);\n}\n\n/* ===== 抽屉主体 ===== */\n\n.wui-drawer-body {\n --wui-glass-shadow: var(--wui-shadow-overlay, 2px 16px 40px rgb(0 0 0 / 0.4));\n display: flex;\n flex-direction: column;\n height: 100%;\n background-color: var(--wui-color-surface-overlay, rgb(246 246 246 / 0.88));\n}\n\n/* ===== Header ===== */\n\n.wui-drawer-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 16px 20px;\n border-bottom: 1px solid rgb(0 0 0 / 0.06);\n\n font-size: 18px;\n font-weight: 600;\n line-height: 1.4;\n}\n\n/* ===== 内容区 ===== */\n\n.wui-drawer-content {\n overflow-y: auto;\n overscroll-behavior: contain;\n flex: 1;\n\n padding: 20px;\n\n font-size: var(--wui-font-size, 14px);\n line-height: 1.5;\n color: var(--wui-color-text, #1b1b1b);\n}\n\n/* ===== Footer ===== */\n\n.wui-drawer-footer {\n flex-shrink: 0;\n padding: 16px 20px;\n border-top: 1px solid rgb(0 0 0 / 0.06);\n}\n\n@media (prefers-reduced-motion: reduce) {\n dialog {\n transition: opacity var(--wui-duration-feedback, 100ms) ease;\n }\n\n dialog::backdrop {\n transition-duration: var(--wui-duration-feedback, 100ms);\n }\n\n dialog[open].is-visible {\n transform: none;\n }\n}\n\n.wui-drawer-footer[hidden] {\n display: none;\n}\n\n/* ===== 关闭按钮(独立定位,与 header 解耦) ===== */\n\n.wui-drawer-close {\n position: absolute;\n z-index: 3;\n top: 16px;\n right: 16px;\n}\n"],"mappings":""}
@@ -21,24 +21,17 @@ export declare class WebUiDropdown extends LitElement {
21
21
  private _ignoreOutsideClickTimer?;
22
22
  private _hoverCleanupFns;
23
23
  private readonly _scrollLock;
24
+ private readonly _userOpenChange;
24
25
  private _restoreFocusTarget?;
25
26
  private _shouldOpenInstantly;
26
27
  get isOpen(): boolean;
27
28
  connectedCallback(): void;
28
29
  disconnectedCallback(): void;
29
30
  protected updated(changed: Map<string, unknown>): void;
30
- /**
31
- * 打开菜单。
32
- * @returns 无返回值;打开后派发 `open-change` 事件。
33
- */
34
31
  openMenu(): void;
35
32
  private _openMenu;
36
- /**
37
- * 关闭所有层级。
38
- * @returns 无返回值;关闭后派发 `open-change` 事件。
39
- */
40
33
  closeAll(): void;
41
- /** 清理子菜单状态(不影响 open prop) */
34
+ private _closeAll;
42
35
  private _closeAllSubmenus;
43
36
  private _cleanupClosedMenu;
44
37
  private _closeRootAfterPresence;
@@ -3,16 +3,17 @@ import { normalizeLiteral as t, normalizeNumber as n } from "../../shared/normal
3
3
  import "../dropdown-divider/index.js";
4
4
  import "../dropdown-header/index.js";
5
5
  import "../dropdown-item/index.js";
6
- import { createMenuPortalOverlay as r } from "../../shared/menu-portal/menu-portal.js";
7
- import { findFocusedMenuItem as i, focusMenuItem as a, getEnabledMenuItems as o, getMenuChildren as s, getMenuItemFromEvent as c, hideNestedMenuChildren as l, moveMenuChildren as u } from "../../shared/menu-portal/menu-tree.js";
8
- import { hideOverlayPresence as d, showOverlayPresence as f } from "../../shared/overlay/presence.js";
9
- import { createScrollLockLease as p } from "../../shared/scroll-lock/scroll-lock.js";
10
- import { defineOverlay as m } from "../../shared/overlay/overlay.js";
11
- import h from "./style.js";
12
- import { LitElement as g, html as _, unsafeCSS as v } from "lit";
13
- import { customElement as y, property as b, state as x } from "lit/decorators.js";
6
+ import { UserChangeController as r } from "../../shared/events/user-change.js";
7
+ import { createMenuPortalOverlay as i } from "../../shared/menu-portal/menu-portal.js";
8
+ import { findFocusedMenuItem as a, focusMenuItem as o, getEnabledMenuItems as s, getMenuChildren as c, getMenuItemFromEvent as l, hideNestedMenuChildren as u, moveMenuChildren as d } from "../../shared/menu-portal/menu-tree.js";
9
+ import { hideOverlayPresence as f, showOverlayPresence as p } from "../../shared/overlay/presence.js";
10
+ import { createScrollLockLease as m } from "../../shared/scroll-lock/scroll-lock.js";
11
+ import { defineOverlay as h } from "../../shared/overlay/overlay.js";
12
+ import g from "./style.js";
13
+ import { LitElement as _, html as v, unsafeCSS as y } from "lit";
14
+ import { customElement as b, property as x, state as S } from "lit/decorators.js";
14
15
  //#region src/components/dropdown/index.ts
15
- var S = "web-ui-menu-level-", C = [
16
+ var C = "web-ui-menu-level-", w = [
16
17
  "top",
17
18
  "top-start",
18
19
  "top-end",
@@ -25,14 +26,14 @@ var S = "web-ui-menu-level-", C = [
25
26
  "left",
26
27
  "left-start",
27
28
  "left-end"
28
- ], w = class extends g {
29
+ ], T = class extends _ {
29
30
  constructor(...e) {
30
- super(...e), this.open = !1, this.disabled = !1, this.matchWidth = !1, this.noScrollLock = !1, this._placement = "bottom-start", this._offset = 4, this._activePath = [], this._overlays = /* @__PURE__ */ new Map(), this._closingSubmenuOverlays = /* @__PURE__ */ new Map(), this._ignoreOutsideClick = !1, this._hoverCleanupFns = [], this._scrollLock = p(), this._shouldOpenInstantly = !0, this._onTriggerClick = (e) => {
31
- this.disabled || (this.open ? this.closeAll() : this._openMenu(e.detail === 0));
31
+ super(...e), this.open = !1, this.disabled = !1, this.matchWidth = !1, this.noScrollLock = !1, this._placement = "bottom-start", this._offset = 4, this._activePath = [], this._overlays = /* @__PURE__ */ new Map(), this._closingSubmenuOverlays = /* @__PURE__ */ new Map(), this._ignoreOutsideClick = !1, this._hoverCleanupFns = [], this._scrollLock = m(), this._userOpenChange = new r(), this._shouldOpenInstantly = !0, this._onTriggerClick = (e) => {
32
+ this.disabled || (this.open ? this._closeAll(!0) : this._openMenu(e.detail === 0, !0));
32
33
  }, this._onClickOutside = (e) => {
33
- !this.isOpen || this._ignoreOutsideClick || this._isInsideShadowRoot(e) || this.closeAll();
34
+ !this.isOpen || this._ignoreOutsideClick || this._isInsideShadowRoot(e) || this._closeAll(!0);
34
35
  }, this._onMenuClick = (e) => {
35
- let t = c(e);
36
+ let t = l(e);
36
37
  if (!t || t.hasAttribute("disabled") || !t.hasAttribute("submenu")) return;
37
38
  let n = this._getFocusedLevel(t);
38
39
  if (n === void 0) return;
@@ -40,8 +41,8 @@ var S = "web-ui-menu-level-", C = [
40
41
  r >= 0 && this._toggleSubmenu(n, r, e.detail === 0);
41
42
  }, this._onKeydown = (e) => {
42
43
  if (this.disabled || !this.open) return;
43
- if (e.key === "Escape" && e.target === this) {
44
- this._activePath.length > 0 ? this._closeSubmenuFrom(this._activePath.length) : this.closeAll(), e.preventDefault();
44
+ if (e.key === "Escape") {
45
+ this._activePath.length > 0 ? this._closeSubmenuFrom(this._activePath.length) : this._closeAll(!0), e.preventDefault();
45
46
  return;
46
47
  }
47
48
  let t = this._getFocusedItem(e), n = this._getFocusedLevel(t);
@@ -74,7 +75,7 @@ var S = "web-ui-menu-level-", C = [
74
75
  t?.click();
75
76
  break;
76
77
  case "Escape":
77
- this._activePath.length > 0 ? this._closeSubmenuFrom(this._activePath.length) : this.closeAll();
78
+ this._activePath.length > 0 ? this._closeSubmenuFrom(this._activePath.length) : this._closeAll(!0);
78
79
  break;
79
80
  default: return;
80
81
  }
@@ -82,13 +83,13 @@ var S = "web-ui-menu-level-", C = [
82
83
  };
83
84
  }
84
85
  static {
85
- this.styles = v(h);
86
+ this.styles = y(g);
86
87
  }
87
88
  get placement() {
88
89
  return this._placement;
89
90
  }
90
91
  set placement(e) {
91
- this._placement = t(e, C, "bottom-start");
92
+ this._placement = t(e, w, "bottom-start");
92
93
  }
93
94
  get offset() {
94
95
  return this._offset;
@@ -108,7 +109,7 @@ var S = "web-ui-menu-level-", C = [
108
109
  updated(e) {
109
110
  e.has("open") && (this.open ? (this._restoreFocusTarget ??= document.activeElement instanceof HTMLElement ? document.activeElement : void 0, this._ignoreCurrentOutsideClick(), this._syncScrollLock(), this._hideAllSubmenuChildren(), requestAnimationFrame(() => {
110
111
  this.open && (this._ensureOverlay(0, this._shouldOpenInstantly), this._shouldOpenInstantly = !0, this._focusMenuItem(this._getEnabledLevelItems(0)[0]));
111
- }), this._bindHoversAfterUpdate()) : (this._syncScrollLock(), this._closeRootAfterPresence()), this.dispatchEvent(new CustomEvent("open-change", {
112
+ }), this._bindHoversAfterUpdate()) : (this._syncScrollLock(), this._closeRootAfterPresence()), this._userOpenChange.consume() && this.dispatchEvent(new CustomEvent("open-change", {
112
113
  detail: { open: this.open },
113
114
  bubbles: !0,
114
115
  composed: !0
@@ -119,13 +120,16 @@ var S = "web-ui-menu-level-", C = [
119
120
  }), this._bindLevelHovers();
120
121
  }
121
122
  openMenu() {
122
- this._openMenu(!0);
123
+ this._openMenu(!0, !1);
123
124
  }
124
- _openMenu(e) {
125
- this.disabled || this.open || (this._ignoreCurrentOutsideClick(), this._shouldOpenInstantly = e, this.open = !0);
125
+ _openMenu(e, t) {
126
+ this.disabled || this.open || (this._ignoreCurrentOutsideClick(), this._shouldOpenInstantly = e, t && this._userOpenChange.mark(), this.open = !0);
126
127
  }
127
128
  closeAll() {
128
- this.open &&= !1;
129
+ this._closeAll(!1);
130
+ }
131
+ _closeAll(e) {
132
+ this.open &&= (e && this._userOpenChange.mark(), !1);
129
133
  }
130
134
  _closeAllSubmenus() {
131
135
  this._closeSubmenuFrom(1, !0), this._disposeClosingSubmenuOverlays(), this._syncActiveAttrs();
@@ -135,10 +139,10 @@ var S = "web-ui-menu-level-", C = [
135
139
  }
136
140
  async _closeRootAfterPresence() {
137
141
  let e = this._overlays.get(0)?.overlay;
138
- e && !await d(e) || this.open || !this.isConnected || (this._cleanupClosedMenu(), this._restoreFocusTarget?.focus(), this._restoreFocusTarget = void 0);
142
+ e && !await f(e) || this.open || !this.isConnected || (this._cleanupClosedMenu(), this._restoreFocusTarget?.focus(), this._restoreFocusTarget = void 0);
139
143
  }
140
144
  _hideAllSubmenuChildren() {
141
- l(this, `${S}-hidden`);
145
+ u(this, `${C}-hidden`);
142
146
  }
143
147
  _toggleSubmenu(e, t, n = !1) {
144
148
  if (this._activePath[e] === t) return;
@@ -168,38 +172,38 @@ var S = "web-ui-menu-level-", C = [
168
172
  }
169
173
  _getLevelItems(e) {
170
174
  let t = this._overlays.get(e)?.content;
171
- return t ? s(t) : [];
175
+ return t ? c(t) : [];
172
176
  }
173
177
  _populateLevel0() {
174
178
  let e = this._overlays.get(0)?.content;
175
- e && u(this, e);
179
+ e && d(this, e);
176
180
  }
177
181
  _returnLevel0Items() {
178
182
  let e = this._overlays.get(0)?.content;
179
- e && u(e, this);
183
+ e && d(e, this);
180
184
  }
181
185
  _populateOverlay(e, t) {
182
186
  let n = this._overlays.get(e)?.content;
183
- n && u(t, n);
187
+ n && d(t, n);
184
188
  }
185
189
  _depopulateOverlay(e, t) {
186
190
  let n = this._overlays.get(e)?.content;
187
191
  if (!n) return;
188
192
  let r = e - 1, i = t ?? this._getLevelItems(r)[this._activePath[r]];
189
- i && u(n, i);
193
+ i && d(n, i);
190
194
  }
191
195
  _ensureOverlay(e, t = !1, n) {
192
196
  let r = n ? this._closingSubmenuOverlays.get(n) : void 0;
193
- if (r) return this._closingSubmenuOverlays.delete(n), this._overlays.set(e, r), r.api.open(), f(r.overlay, { isInstant: t }), !0;
197
+ if (r) return this._closingSubmenuOverlays.delete(n), this._overlays.set(e, r), r.api.open(), p(r.overlay, { isInstant: t }), !0;
194
198
  let i = this._overlays.get(e);
195
- return i ? (i.api.open(), f(i.overlay, { isInstant: t }), !1) : (this._buildOverlay(e, t), !1);
199
+ return i ? (i.api.open(), p(i.overlay, { isInstant: t }), !1) : (this._buildOverlay(e, t), !1);
196
200
  }
197
201
  _buildOverlay(e, t = !1) {
198
- let { panel: n, content: i } = r("dropdown-overlay");
202
+ let { panel: n, content: r } = i("dropdown-overlay");
199
203
  n.setAttribute("role", "menu"), n.dataset.level = String(e), n.addEventListener("click", this._onMenuClick), n.addEventListener("keydown", this._onKeydown);
200
204
  let a = e === 0 ? this._queryTriggerAnchor() : this._getSubmenuTriggerAnchor(e - 1);
201
205
  if (a) {
202
- let r = m().make({
206
+ let i = h().make({
203
207
  anchor: a,
204
208
  overlay: n,
205
209
  placement: e === 0 ? this.placement : "right-start",
@@ -208,10 +212,10 @@ var S = "web-ui-menu-level-", C = [
208
212
  strategy: "fixed"
209
213
  });
210
214
  this._overlays.set(e, {
211
- api: r,
215
+ api: i,
212
216
  overlay: n,
213
- content: i
214
- }), e === 0 && this._populateLevel0(), r.open(), f(n, { isInstant: t });
217
+ content: r
218
+ }), e === 0 && this._populateLevel0(), i.open(), p(n, { isInstant: t });
215
219
  }
216
220
  }
217
221
  _disposeOverlay(e) {
@@ -222,7 +226,7 @@ var S = "web-ui-menu-level-", C = [
222
226
  for (let e of this._overlays.keys()) this._disposeOverlay(e);
223
227
  }
224
228
  async _closeSubmenuAfterPresence(e, t) {
225
- await d(e.overlay) && this._closingSubmenuOverlays.get(t) === e && (this._closingSubmenuOverlays.delete(t), this._restoreSubmenuItems(e, t), e.api.dispose(), e.overlay.remove());
229
+ await f(e.overlay) && this._closingSubmenuOverlays.get(t) === e && (this._closingSubmenuOverlays.delete(t), this._restoreSubmenuItems(e, t), e.api.dispose(), e.overlay.remove());
226
230
  }
227
231
  _disposeClosingSubmenuOverlays() {
228
232
  this._closingSubmenuOverlays.forEach((e, t) => {
@@ -230,7 +234,7 @@ var S = "web-ui-menu-level-", C = [
230
234
  }), this._closingSubmenuOverlays.clear();
231
235
  }
232
236
  _restoreSubmenuItems(e, t) {
233
- u(e.content, t);
237
+ d(e.content, t);
234
238
  }
235
239
  _syncScrollLock(e = this.open) {
236
240
  this._scrollLock.sync(e && !this.noScrollLock);
@@ -247,16 +251,16 @@ var S = "web-ui-menu-level-", C = [
247
251
  }
248
252
  _getEnabledLevelItems(e) {
249
253
  let t = this._overlays.get(e)?.content;
250
- return t ? o(t) : [];
254
+ return t ? s(t) : [];
251
255
  }
252
256
  _getFocusedItem(e) {
253
- return e?.composedPath().find((e) => e instanceof HTMLElement && e.matches("web-ui-dropdown-item")) || i([...this._overlays.values()].map(({ overlay: e }) => e));
257
+ return e?.composedPath().find((e) => e instanceof HTMLElement && e.matches("web-ui-dropdown-item")) || a([...this._overlays.values()].map(({ overlay: e }) => e));
254
258
  }
255
259
  _getFocusedLevel(e = this._getFocusedItem()) {
256
260
  if (e) return [...this._overlays.entries()].find(([, t]) => t.overlay.contains(e))?.[0];
257
261
  }
258
262
  _focusMenuItem(e) {
259
- a(e);
263
+ o(e);
260
264
  }
261
265
  _isInsideShadowRoot(e) {
262
266
  for (let t of e.composedPath()) if (t === this || t === this.shadowRoot || t instanceof Node && t.getRootNode() === this.shadowRoot || t instanceof Node && [...this._overlays.values()].some(({ overlay: e }) => e.contains(t))) return !0;
@@ -285,32 +289,32 @@ var S = "web-ui-menu-level-", C = [
285
289
  requestAnimationFrame(() => this._bindLevelHovers());
286
290
  }
287
291
  render() {
288
- return _`
292
+ return v`
289
293
  <div class="dropdown-trigger" @click=${this._onTriggerClick}>
290
294
  <slot name="trigger"></slot>
291
295
  </div>
292
296
  `;
293
297
  }
294
298
  };
295
- e([b({
299
+ e([x({
296
300
  type: Boolean,
297
301
  reflect: !0
298
- })], w.prototype, "open", void 0), e([b({
302
+ })], T.prototype, "open", void 0), e([x({
299
303
  type: Boolean,
300
304
  reflect: !0
301
- })], w.prototype, "disabled", void 0), e([b({
305
+ })], T.prototype, "disabled", void 0), e([x({
302
306
  type: Boolean,
303
307
  reflect: !0,
304
308
  attribute: "match-width"
305
- })], w.prototype, "matchWidth", void 0), e([b({
309
+ })], T.prototype, "matchWidth", void 0), e([x({
306
310
  type: Boolean,
307
311
  reflect: !0,
308
312
  attribute: "no-scroll-lock"
309
- })], w.prototype, "noScrollLock", void 0), e([b({
313
+ })], T.prototype, "noScrollLock", void 0), e([x({
310
314
  type: String,
311
315
  reflect: !0
312
- })], w.prototype, "placement", null), e([b({ type: Number })], w.prototype, "offset", null), e([x()], w.prototype, "_activePath", void 0), w = e([y("web-ui-dropdown")], w);
316
+ })], T.prototype, "placement", null), e([x({ type: Number })], T.prototype, "offset", null), e([S()], T.prototype, "_activePath", void 0), T = e([b("web-ui-dropdown")], T);
313
317
  //#endregion
314
- export { w as WebUiDropdown };
318
+ export { T as WebUiDropdown };
315
319
 
316
320
  //# sourceMappingURL=index.js.map