@greypan/web-ui 10.2.1 → 11.1.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 (210) hide show
  1. package/README.CN.md +132 -68
  2. package/README.md +112 -43
  3. package/dist/assets/menu-portal.js.map +1 -1
  4. package/dist/assets/modal-surface.js.map +1 -1
  5. package/dist/assets/overlay-motion.js +1 -1
  6. package/dist/assets/overlay-motion.js.map +1 -1
  7. package/dist/assets/selection-control.js +1 -1
  8. package/dist/assets/selection-control.js.map +1 -1
  9. package/dist/classes/glass.js +6 -0
  10. package/dist/classes/glass.js.map +1 -0
  11. package/dist/classes/glow.js +6 -0
  12. package/dist/classes/glow.js.map +1 -0
  13. package/dist/classes/style.css +1 -0
  14. package/dist/components/autocomplete/index.d.ts +13 -6
  15. package/dist/components/autocomplete/index.js +34 -14
  16. package/dist/components/autocomplete/index.js.map +1 -1
  17. package/dist/components/autocomplete/style.js +1 -1
  18. package/dist/components/autocomplete/style.js.map +1 -1
  19. package/dist/components/avatar/index.js +2 -2
  20. package/dist/components/avatar/index.js.map +1 -1
  21. package/dist/components/avatar/style.js +1 -1
  22. package/dist/components/avatar/style.js.map +1 -1
  23. package/dist/components/back-top/index.d.ts +4 -0
  24. package/dist/components/back-top/index.js +60 -22
  25. package/dist/components/back-top/index.js.map +1 -1
  26. package/dist/components/back-top/style.js +1 -1
  27. package/dist/components/back-top/style.js.map +1 -1
  28. package/dist/components/badge/index.d.ts +3 -0
  29. package/dist/components/badge/index.js +30 -15
  30. package/dist/components/badge/index.js.map +1 -1
  31. package/dist/components/badge/style.js +1 -1
  32. package/dist/components/badge/style.js.map +1 -1
  33. package/dist/components/button/index.d.ts +4 -0
  34. package/dist/components/button/index.js +32 -19
  35. package/dist/components/button/index.js.map +1 -1
  36. package/dist/components/button/style.js +1 -1
  37. package/dist/components/button/style.js.map +1 -1
  38. package/dist/components/button-group/index.d.ts +3 -0
  39. package/dist/components/button-group/index.js +15 -2
  40. package/dist/components/button-group/index.js.map +1 -1
  41. package/dist/components/button-group/style.js +1 -1
  42. package/dist/components/button-group/style.js.map +1 -1
  43. package/dist/components/checkbox/index.d.ts +1 -1
  44. package/dist/components/checkbox/index.js +7 -7
  45. package/dist/components/checkbox/index.js.map +1 -1
  46. package/dist/components/checkbox/style.js +1 -1
  47. package/dist/components/checkbox/style.js.map +1 -1
  48. package/dist/components/checkbox-group/index.js +1 -1
  49. package/dist/components/checkbox-group/index.js.map +1 -1
  50. package/dist/components/collapse/index.d.ts +8 -6
  51. package/dist/components/collapse/index.js +45 -25
  52. package/dist/components/collapse/index.js.map +1 -1
  53. package/dist/components/collapse/style.js +1 -1
  54. package/dist/components/collapse/style.js.map +1 -1
  55. package/dist/components/context-menu/index.d.ts +60 -60
  56. package/dist/components/context-menu/index.js +2 -2
  57. package/dist/components/context-menu/index.js.map +1 -1
  58. package/dist/components/context-menu/scrim.js.map +1 -1
  59. package/dist/components/context-menu/style.js.map +1 -1
  60. package/dist/components/dialog/index.d.ts +5 -4
  61. package/dist/components/dialog/index.js +6 -3
  62. package/dist/components/dialog/index.js.map +1 -1
  63. package/dist/components/dialog/style.js +1 -1
  64. package/dist/components/dialog/style.js.map +1 -1
  65. package/dist/components/drawer/index.d.ts +8 -8
  66. package/dist/components/drawer/index.js +2 -2
  67. package/dist/components/drawer/index.js.map +1 -1
  68. package/dist/components/drawer/style.js.map +1 -1
  69. package/dist/components/dropdown/index.d.ts +22 -6
  70. package/dist/components/dropdown/index.js +147 -18
  71. package/dist/components/dropdown/index.js.map +1 -1
  72. package/dist/components/dropdown-item/index.js.map +1 -1
  73. package/dist/components/dropdown-item/style.js +1 -1
  74. package/dist/components/dropdown-item/style.js.map +1 -1
  75. package/dist/components/editable-text/index.d.ts +2 -2
  76. package/dist/components/editable-text/index.js +7 -3
  77. package/dist/components/editable-text/index.js.map +1 -1
  78. package/dist/components/editable-text/style.js +1 -1
  79. package/dist/components/editable-text/style.js.map +1 -1
  80. package/dist/components/empty/index.d.ts +3 -3
  81. package/dist/components/empty/index.js.map +1 -1
  82. package/dist/components/image-preview/index.d.ts +5 -5
  83. package/dist/components/image-preview/index.js +9 -9
  84. package/dist/components/image-preview/index.js.map +1 -1
  85. package/dist/components/image-preview/style.js.map +1 -1
  86. package/dist/components/input/index.d.ts +1 -0
  87. package/dist/components/input/index.js +6 -3
  88. package/dist/components/input/index.js.map +1 -1
  89. package/dist/components/input/style.js +1 -1
  90. package/dist/components/input/style.js.map +1 -1
  91. package/dist/components/input-number/index.d.ts +31 -1
  92. package/dist/components/input-number/index.js +281 -22
  93. package/dist/components/input-number/index.js.map +1 -1
  94. package/dist/components/input-number/style.js +1 -1
  95. package/dist/components/input-number/style.js.map +1 -1
  96. package/dist/components/layout/index.d.ts +7 -7
  97. package/dist/components/layout/index.js +47 -42
  98. package/dist/components/layout/index.js.map +1 -1
  99. package/dist/components/layout/style.js +1 -1
  100. package/dist/components/layout/style.js.map +1 -1
  101. package/dist/components/middle-ellipsis/index.d.ts +9 -2
  102. package/dist/components/middle-ellipsis/index.js +68 -10
  103. package/dist/components/middle-ellipsis/index.js.map +1 -1
  104. package/dist/components/middle-ellipsis/truncate.d.ts +1 -1
  105. package/dist/components/middle-ellipsis/truncate.js.map +1 -1
  106. package/dist/components/option/style.js +1 -1
  107. package/dist/components/option/style.js.map +1 -1
  108. package/dist/components/popover/index.d.ts +1 -1
  109. package/dist/components/popover/index.js +1 -1
  110. package/dist/components/popover/index.js.map +1 -1
  111. package/dist/components/popover/style.js +1 -1
  112. package/dist/components/popover/style.js.map +1 -1
  113. package/dist/components/radio/index.d.ts +6 -1
  114. package/dist/components/radio/index.js +34 -24
  115. package/dist/components/radio/index.js.map +1 -1
  116. package/dist/components/radio/interaction.d.ts +4 -0
  117. package/dist/components/radio/interaction.js +17 -0
  118. package/dist/components/radio/interaction.js.map +1 -0
  119. package/dist/components/radio/style.js +1 -1
  120. package/dist/components/radio/style.js.map +1 -1
  121. package/dist/components/radio-group/index.d.ts +23 -1
  122. package/dist/components/radio-group/index.js +220 -29
  123. package/dist/components/radio-group/index.js.map +1 -1
  124. package/dist/components/segmented/index.d.ts +2 -0
  125. package/dist/components/segmented/index.js +74 -18
  126. package/dist/components/segmented/index.js.map +1 -1
  127. package/dist/components/segmented/style.js +1 -1
  128. package/dist/components/segmented/style.js.map +1 -1
  129. package/dist/components/segmented-trigger/index.js +3 -2
  130. package/dist/components/segmented-trigger/index.js.map +1 -1
  131. package/dist/components/segmented-trigger/style.js +1 -1
  132. package/dist/components/segmented-trigger/style.js.map +1 -1
  133. package/dist/components/select/index.d.ts +8 -0
  134. package/dist/components/select/index.js +77 -26
  135. package/dist/components/select/index.js.map +1 -1
  136. package/dist/components/select/style.js +1 -1
  137. package/dist/components/select/style.js.map +1 -1
  138. package/dist/components/slider/index.d.ts +15 -0
  139. package/dist/components/slider/index.js +175 -39
  140. package/dist/components/slider/index.js.map +1 -1
  141. package/dist/components/slider/style.js +1 -1
  142. package/dist/components/slider/style.js.map +1 -1
  143. package/dist/components/spinner/index.d.ts +15 -0
  144. package/dist/components/spinner/index.js +79 -22
  145. package/dist/components/spinner/index.js.map +1 -1
  146. package/dist/components/spinner/style.js +1 -1
  147. package/dist/components/spinner/style.js.map +1 -1
  148. package/dist/components/svg-draw-lines/index.js +48 -12
  149. package/dist/components/svg-draw-lines/index.js.map +1 -1
  150. package/dist/components/switch/index.d.ts +11 -3
  151. package/dist/components/switch/index.js +58 -54
  152. package/dist/components/switch/index.js.map +1 -1
  153. package/dist/components/switch/style.js +1 -1
  154. package/dist/components/switch/style.js.map +1 -1
  155. package/dist/components/textarea/index.js +3 -3
  156. package/dist/components/textarea/index.js.map +1 -1
  157. package/dist/components/textarea/style.js +1 -1
  158. package/dist/components/textarea/style.js.map +1 -1
  159. package/dist/components/theme/index.d.ts +1 -0
  160. package/dist/components/theme/index.js +26 -15
  161. package/dist/components/theme/index.js.map +1 -1
  162. package/dist/components/theme/style.js +1 -1
  163. package/dist/components/theme/style.js.map +1 -1
  164. package/dist/components/toast/style.js +1 -1
  165. package/dist/components/toast/style.js.map +1 -1
  166. package/dist/components/toast/toast.js +2 -2
  167. package/dist/components/toast/toast.js.map +1 -1
  168. package/dist/components/tooltip/index.d.ts +2 -1
  169. package/dist/components/tooltip/index.js +10 -5
  170. package/dist/components/tooltip/index.js.map +1 -1
  171. package/dist/components/tooltip/style.js.map +1 -1
  172. package/dist/scrollbars/index.d.ts +8 -8
  173. package/dist/scrollbars/index.js.map +1 -1
  174. package/dist/scrollbars/internal.js.map +1 -1
  175. package/dist/shared/element-height/index.js.map +1 -1
  176. package/dist/shared/focus/pointer-focus.js +12 -10
  177. package/dist/shared/focus/pointer-focus.js.map +1 -1
  178. package/dist/shared/gesture/drag-gesture.js +4 -4
  179. package/dist/shared/gesture/drag-gesture.js.map +1 -1
  180. package/dist/shared/group-management/index.js +43 -18
  181. package/dist/shared/group-management/index.js.map +1 -1
  182. package/dist/shared/label-emptiness/index.js.map +1 -1
  183. package/dist/shared/menu-behavior/index.js.map +1 -1
  184. package/dist/shared/menu-portal/menu-portal.js +1 -1
  185. package/dist/shared/menu-portal/menu-portal.js.map +1 -1
  186. package/dist/shared/menu-portal/menu-tree.js.map +1 -1
  187. package/dist/shared/option-portal/combobox-shell.js.map +1 -1
  188. package/dist/shared/option-portal/index.js.map +1 -1
  189. package/dist/shared/overlay/anchored-panel.js.map +1 -1
  190. package/dist/shared/overlay/native-dialog-presence.js.map +1 -1
  191. package/dist/shared/overlay/nested-drawer-layers.js.map +1 -1
  192. package/dist/shared/overlay/open-overlay.js.map +1 -1
  193. package/dist/shared/overlay/overlay-root.js +1 -1
  194. package/dist/shared/overlay/overlay-root.js.map +1 -1
  195. package/dist/shared/overlay/overlay.js +7 -1
  196. package/dist/shared/overlay/overlay.js.map +1 -1
  197. package/dist/shared/overlay/portal.js.map +1 -1
  198. package/dist/shared/overlay/presence.js.map +1 -1
  199. package/dist/shared/scroll-lock/scroll-lock.js.map +1 -1
  200. package/dist/shared/theme/root-sync.js.map +1 -1
  201. package/package.json +5 -2
  202. package/dist/assets/glass.js +0 -6
  203. package/dist/assets/glass.js.map +0 -1
  204. package/dist/icons/generated/heroicons-arrow-down-16-solid.d.ts +0 -6
  205. package/dist/icons/generated/heroicons-arrow-up-16-solid.d.ts +0 -6
  206. package/dist/icons/generated/jam-volume.d.ts +0 -8
  207. package/dist/icons/generated/jam-watch-f.d.ts +0 -8
  208. package/dist/icons/generated/ooui-check.d.ts +0 -6
  209. package/dist/icons/generated/radix-icons-check.d.ts +0 -6
  210. package/dist/icons/generated/si-check-alt-fill.d.ts +0 -6
@@ -1,5 +1,5 @@
1
1
  import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
2
- import t from "../../assets/glass.js";
2
+ import t from "../../classes/glass.js";
3
3
  import { GroupController as n, buttonGroupContextKey as r, defineGroupPresentation as i } from "../../shared/group-management/index.js";
4
4
  import { normalizeLiteral as a } from "../../shared/normalize/index.js";
5
5
  import o from "./style.js";
@@ -16,7 +16,7 @@ var f = ["horizontal", "vertical"], p = class extends s {
16
16
  direction: this.direction,
17
17
  isLast: t === n.length - 1
18
18
  })
19
- }).make());
19
+ }).make()), this._trackResizeObserver = null;
20
20
  }
21
21
  static {
22
22
  this.styles = [l(t), l(o)];
@@ -28,6 +28,19 @@ var f = ["horizontal", "vertical"], p = class extends s {
28
28
  let t = this._direction;
29
29
  this._direction = a(e, f, "horizontal"), this.requestUpdate("direction", t);
30
30
  }
31
+ connectedCallback() {
32
+ super.connectedCallback(), this.updateComplete.then(() => {
33
+ if (!this.isConnected || typeof ResizeObserver > "u") return;
34
+ let e = this.renderRoot.querySelector(".wui-button-group-inner");
35
+ e && (this._trackResizeObserver ??= new ResizeObserver(() => {
36
+ let { width: t, height: n } = getComputedStyle(e), r = Math.min(Number.parseFloat(t), Number.parseFloat(n)) / 2;
37
+ e.style.setProperty("--wui-glass-corner-radius", `${r}px`);
38
+ }), this._trackResizeObserver.observe(e, { box: "border-box" }));
39
+ });
40
+ }
41
+ disconnectedCallback() {
42
+ this._trackResizeObserver?.disconnect(), super.disconnectedCallback();
43
+ }
31
44
  render() {
32
45
  return c`
33
46
  <div class="wui-glass wui-button-group-inner">
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/button-group/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport glass from '@/assets/glass.css?inline'\nimport {\n buttonGroupContextKey,\n defineGroupPresentation,\n GroupController,\n type ButtonGroupContext\n} from '@/shared/group-management'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport type { WebUiButton } from '../button'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_DIRECTIONS = ['horizontal', 'vertical'] as const\n\n@customElement('web-ui-button-group')\nexport class WebUiButtonGroup extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: String, reflect: true })\n get direction(): 'horizontal' | 'vertical' {\n return this._direction\n }\n set direction(v: string) {\n const old = this._direction\n this._direction = normalizeLiteral(v, ALLOWED_DIRECTIONS, 'horizontal')\n this.requestUpdate('direction', old)\n }\n private _direction: 'horizontal' | 'vertical' = 'horizontal'\n\n private readonly _groupController = new GroupController(\n this,\n defineGroupPresentation<WebUiButton, ButtonGroupContext>({\n host: this,\n context: buttonGroupContextKey,\n getItems: () => [...this.querySelectorAll<WebUiButton>('web-ui-button')],\n getContext: (_, index, buttons) => ({\n direction: this.direction,\n isLast: index === buttons.length - 1\n })\n }).make()\n )\n\n override render() {\n return html`\n <div class=\"wui-glass wui-button-group-inner\">\n <slot></slot>\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-button-group': WebUiButtonGroup\n }\n}\n"],"mappings":";;;;;;;;AAgBA,IAAM,IAAqB,CAAC,cAAc,UAAU,GAGvC,IAAN,cAA+B,EAAW;;EAcX,aAFY,KAAA,aAAA,cAEZ,KAAA,mBAAA,IAAI,EACtC,MACA,EAAyD;GACvD,MAAM;GACN,SAAS;GACT,gBAAgB,CAAC,GAAG,KAAK,iBAA8B,eAAe,CAAC;GACvE,aAAa,GAAG,GAAO,OAAa;IAClC,WAAW,KAAK;IAChB,QAAQ,MAAU,EAAQ,SAAS;GACrC;EACF,CAAC,CAAC,CAAC,KAAK,CACV;;;EAxByB,KAAA,SAAA,CAAC,EAAU,CAAK,GAAG,EAAU,CAAK,CAAC;;CAE5D,IACI,YAAuC;EACzC,OAAO,KAAK;CACd;CACA,IAAI,UAAU,GAAW;EACvB,IAAM,IAAM,KAAK;EAEjB,AADA,KAAK,aAAa,EAAiB,GAAG,GAAoB,YAAY,GACtE,KAAK,cAAc,aAAa,CAAG;CACrC;CAgBA,SAAkB;EAChB,OAAO,CAAI;;;;;CAKb;AACF;AA/BG,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,aAAA,IAAA,GAJ1C,IAAA,EAAA,CAAA,EAAc,qBAAqB,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/button-group/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport glass from '@/classes/glass.css?inline'\nimport {\n buttonGroupContextKey,\n defineGroupPresentation,\n GroupController,\n type ButtonGroupContext\n} from '@/shared/group-management'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport type { WebUiButton } from '../button'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_DIRECTIONS = ['horizontal', 'vertical'] as const\n\n@customElement('web-ui-button-group')\nexport class WebUiButtonGroup extends LitElement {\n static override styles = [unsafeCSS(glass), unsafeCSS(style)]\n\n @property({ type: String, reflect: true })\n get direction(): 'horizontal' | 'vertical' {\n return this._direction\n }\n set direction(v: string) {\n const old = this._direction\n this._direction = normalizeLiteral(v, ALLOWED_DIRECTIONS, 'horizontal')\n this.requestUpdate('direction', old)\n }\n private _direction: 'horizontal' | 'vertical' = 'horizontal'\n\n private readonly _groupController = new GroupController(\n this,\n defineGroupPresentation<WebUiButton, ButtonGroupContext>({\n host: this,\n context: buttonGroupContextKey,\n getItems: () => [...this.querySelectorAll<WebUiButton>('web-ui-button')],\n getContext: (_, index, buttons) => ({\n direction: this.direction,\n isLast: index === buttons.length - 1\n })\n }).make()\n )\n\n private _trackResizeObserver: ResizeObserver | null = null\n\n override connectedCallback(): void {\n super.connectedCallback()\n void this.updateComplete.then(() => {\n if (!this.isConnected || typeof ResizeObserver === 'undefined') return\n\n const track = this.renderRoot.querySelector<HTMLElement>('.wui-button-group-inner')\n if (!track) return\n\n this._trackResizeObserver ??= new ResizeObserver(() => {\n // 读取未变换的布局尺寸,避免 dialog 进退场缩放污染玻璃圆角。\n const { width, height } = getComputedStyle(track)\n const cornerRadius = Math.min(Number.parseFloat(width), Number.parseFloat(height)) / 2\n // max-content 垂直轨道的短边会随成员内容变化,玻璃角点渐变需要同步跟随。\n track.style.setProperty('--wui-glass-corner-radius', `${cornerRadius}px`)\n })\n this._trackResizeObserver.observe(track, { box: 'border-box' })\n })\n }\n\n override disconnectedCallback(): void {\n this._trackResizeObserver?.disconnect()\n super.disconnectedCallback()\n }\n\n override render() {\n return html`\n <div class=\"wui-glass wui-button-group-inner\">\n <slot></slot>\n </div>\n `\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-button-group': WebUiButtonGroup\n }\n}\n"],"mappings":";;;;;;;;AAgBA,IAAM,IAAqB,CAAC,cAAc,UAAU,GAGvC,IAAN,cAA+B,EAAW;;EA2BO,aAfN,KAAA,aAAA,cAEZ,KAAA,mBAAA,IAAI,EACtC,MACA,EAAyD;GACvD,MAAM;GACN,SAAS;GACT,gBAAgB,CAAC,GAAG,KAAK,iBAA8B,eAAe,CAAC;GACvE,aAAa,GAAG,GAAO,OAAa;IAClC,WAAW,KAAK;IAChB,QAAQ,MAAU,EAAQ,SAAS;GACrC;EACF,CAAC,CAAC,CAAC,KAAK,CACV,GAEsD,KAAA,uBAAA;;;EA1B7B,KAAA,SAAA,CAAC,EAAU,CAAK,GAAG,EAAU,CAAK,CAAC;;CAE5D,IACI,YAAuC;EACzC,OAAO,KAAK;CACd;CACA,IAAI,UAAU,GAAW;EACvB,IAAM,IAAM,KAAK;EAEjB,AADA,KAAK,aAAa,EAAiB,GAAG,GAAoB,YAAY,GACtE,KAAK,cAAc,aAAa,CAAG;CACrC;CAkBA,oBAAmC;EAEjC,AADA,MAAM,kBAAkB,GACxB,KAAU,eAAe,WAAW;GAClC,IAAI,CAAC,KAAK,eAAe,OAAO,iBAAmB,KAAa;GAEhE,IAAM,IAAQ,KAAK,WAAW,cAA2B,yBAAyB;GAC7E,MAEL,KAAK,yBAAyB,IAAI,qBAAqB;IAErD,IAAM,EAAE,UAAO,cAAW,iBAAiB,CAAK,GAC1C,IAAe,KAAK,IAAI,OAAO,WAAW,CAAK,GAAG,OAAO,WAAW,CAAM,CAAC,IAAI;IAErF,EAAM,MAAM,YAAY,6BAA6B,GAAG,EAAa,GAAG;GAC1E,CAAC,GACD,KAAK,qBAAqB,QAAQ,GAAO,EAAE,KAAK,aAAa,CAAC;EAChE,CAAC;CACH;CAEA,uBAAsC;EAEpC,AADA,KAAK,sBAAsB,WAAW,GACtC,MAAM,qBAAqB;CAC7B;CAEA,SAAkB;EAChB,OAAO,CAAI;;;;;CAKb;AACF;AAzDG,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,aAAA,IAAA,GAJ1C,IAAA,EAAA,CAAA,EAAc,qBAAqB,CAAA,GAAA,CAAA"}
@@ -1,5 +1,5 @@
1
1
  //#region src/components/button-group/style.css?inline
2
- var e = "*,:before,:after{box-sizing:border-box}:host{display:inline-block}.wui-button-group-inner{--wui-glass-corner-radius:calc(var(--wui-control-size,36px) / 2);flex-direction:var(--wui-button-group-flex-direction,row);gap:var(--wui-space-1,4px);width:max-content;height:var(--wui-control-size,36px);padding:0 var(--wui-space-1,4px);border-radius:var(--wui-radius-control,calc(infinity * 1px));align-items:center;display:flex}:host([direction=vertical]){--wui-button-group-flex-direction:column}:host([direction=vertical]) .wui-button-group-inner{width:var(--wui-control-size,36px);height:auto;padding:var(--wui-space-1,4px) 0}";
2
+ var e = "*,:before,:after{box-sizing:border-box}:host{--wui-internal-button-group-button-size:calc(var(--wui-control-size,36px) * 5 / 6);display:inline-block}.wui-button-group-inner{--wui-glass-corner-radius:calc(var(--wui-control-size,36px) / 2);flex-direction:var(--wui-button-group-flex-direction,row);gap:var(--wui-space-1,4px);width:max-content;height:var(--wui-control-size,36px);padding:0 var(--wui-space-1,4px);border-radius:var(--wui-radius-control,calc(infinity * 1px));align-items:center;display:flex}:host([direction=vertical]){--wui-button-group-flex-direction:column}:host([direction=vertical]) .wui-button-group-inner{height:auto;padding:var(--wui-space-1,4px) 0}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/button-group/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n display: inline-block;\n}\n\n.wui-button-group-inner {\n --wui-glass-corner-radius: calc(var(--wui-control-size, 36px) / 2);\n\n display: flex;\n flex-direction: var(--wui-button-group-flex-direction, row);\n gap: var(--wui-space-1, 4px);\n align-items: center;\n\n width: max-content;\n height: var(--wui-control-size, 36px);\n padding: 0 var(--wui-space-1, 4px);\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n}\n\n:host([direction='vertical']) {\n --wui-button-group-flex-direction: column;\n}\n\n:host([direction='vertical']) .wui-button-group-inner {\n width: var(--wui-control-size, 36px);\n height: auto;\n padding: var(--wui-space-1, 4px) 0;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/button-group/style.css?inline"],"sourcesContent":["*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n:host {\n --wui-internal-button-group-button-size: calc(var(--wui-control-size, 36px) * 5 / 6);\n\n display: inline-block;\n}\n\n.wui-button-group-inner {\n --wui-glass-corner-radius: calc(var(--wui-control-size, 36px) / 2);\n\n display: flex;\n flex-direction: var(--wui-button-group-flex-direction, row);\n gap: var(--wui-space-1, 4px);\n align-items: center;\n\n width: max-content;\n height: var(--wui-control-size, 36px);\n padding: 0 var(--wui-space-1, 4px);\n border-radius: var(--wui-radius-control, calc(infinity * 1px));\n}\n\n:host([direction='vertical']) {\n --wui-button-group-flex-direction: column;\n}\n\n:host([direction='vertical']) .wui-button-group-inner {\n height: auto;\n padding: var(--wui-space-1, 4px) 0;\n}\n"],"mappings":""}
@@ -369,7 +369,7 @@ export declare class WebUiCheckbox extends WebUiCheckbox_base {
369
369
  private _checked;
370
370
  /** 描边收回期间把勾按在可见档,见 willUpdate。 */
371
371
  private _retracting;
372
- /** 标签没有可渲染内容(空槽位,或只挂着一个无障碍名)时收掉 gap,见 LabelEmptinessController。 */
372
+ /** label 没有可渲染内容(空槽位,或只挂着一个无障碍名)时收掉 gap,见 LabelEmptinessController。 */
373
373
  private _labelEmpty;
374
374
  get checked(): boolean;
375
375
  set checked(v: boolean);
@@ -5,8 +5,8 @@ import { installPointerFocusSuppression as n } from "../../shared/focus/pointer-
5
5
  import { FormAssociated as r, FormAssociationController as i, defineFormAssociation as a } from "../../shared/form-association/index.js";
6
6
  import { defineGroupManaged as o, selectionGroupContextKey as s } from "../../shared/group-management/index.js";
7
7
  import { parseDuration as c } from "../../shared/theme/duration.js";
8
- import l from "../../assets/selection-control.js";
9
- import { prefersReducedMotion as u } from "../../shared/theme/reduced-motion.js";
8
+ import { prefersReducedMotion as l } from "../../shared/theme/reduced-motion.js";
9
+ import u from "../../assets/selection-control.js";
10
10
  import "../svg-draw-lines/index.js";
11
11
  import { LabelEmptinessController as d } from "../../shared/label-emptiness/index.js";
12
12
  import f from "./style.js";
@@ -45,7 +45,7 @@ var S = class extends r(p) {
45
45
  }), this._drawDurationMs = 160;
46
46
  }
47
47
  static {
48
- this.styles = [h(l), h(f)];
48
+ this.styles = [h(u), h(f)];
49
49
  }
50
50
  get checked() {
51
51
  return this._checked;
@@ -67,7 +67,7 @@ var S = class extends r(p) {
67
67
  e.setValidity({});
68
68
  return;
69
69
  }
70
- e.setValidity({ valueMissing: !0 }, "请选择此项");
70
+ e.setValidity({ valueMissing: !0 }, "Select this option");
71
71
  }
72
72
  }
73
73
  handleClick() {
@@ -89,7 +89,7 @@ var S = class extends r(p) {
89
89
  willUpdate(e) {
90
90
  super.willUpdate(e), this._drawDurationMs = x(this);
91
91
  let t = e.get("_checked");
92
- typeof t == "boolean" && (this._retracting = t && !u(this));
92
+ typeof t == "boolean" && (this._retracting = t && !l(this));
93
93
  }
94
94
  updated(e) {
95
95
  super.updated(e);
@@ -105,7 +105,7 @@ var S = class extends r(p) {
105
105
  "is-disabled": this._isDisabled
106
106
  };
107
107
  return m`
108
- <label
108
+ <span
109
109
  class=${b(e)}
110
110
  tabindex=${this._isDisabled ? "-1" : "0"}
111
111
  role="checkbox"
@@ -121,7 +121,7 @@ var S = class extends r(p) {
121
121
  ></span>
122
122
  </span>
123
123
  <span class="wui-checkbox-label"><slot></slot></span>
124
- </label>
124
+ </span>
125
125
  `;
126
126
  }
127
127
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox/index.ts"],"sourcesContent":["import '@/components/icon'\n\nimport { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport selectionControl from '@/assets/selection-control.css?inline'\nimport { WebUiSvgDrawLines } from '@/components/svg-draw-lines'\nimport { akarIconsCheck } from '@/icons'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupManaged, selectionGroupContextKey, type SelectionGroupContext } from '@/shared/group-management'\nimport { LabelEmptinessController } from '@/shared/label-emptiness'\nimport { parseDuration } from '@/shared/theme/duration'\nimport { prefersReducedMotion } from '@/shared/theme/reduced-motion'\n\nimport style from './style.css?inline'\n\ninstallPointerFocusSuppression()\n\n/*\n * 描边时长取 `--wui-duration-trigger`,让勾和指示器底色那条 transition 落在同一拍。\n * 读不到 token 或格式不符时兜底 160,负值钳到 0。\n */\nfunction triggerDuration(el: HTMLElement): number {\n const parsed = parseDuration(getComputedStyle(el).getPropertyValue('--wui-duration-trigger'))\n return parsed === null ? 160 : Math.max(0, parsed)\n}\n\n@customElement('web-ui-checkbox')\nexport class WebUiCheckbox extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(selectionControl), unsafeCSS(style)]\n private readonly _groupManagement = defineGroupManaged<SelectionGroupContext>(this, {\n context: selectionGroupContextKey,\n requestUpdate: () => this.requestUpdate()\n }).make()\n\n @state() private _checked = false\n\n /** 描边收回期间把勾按在可见档,见 willUpdate。 */\n @state() private _retracting = false\n\n /** 标签没有可渲染内容(空槽位,或只挂着一个无障碍名)时收掉 gap,见 LabelEmptinessController。 */\n @state() private _labelEmpty = false\n\n get checked(): boolean {\n return this._checked\n }\n\n set checked(v: boolean) {\n const old = this._checked\n this._checked = v\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String }) value = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private get _isDisabled(): boolean {\n return (\n this.disabled || this._formAssociation.isFormDisabled() || this._groupManagement.getContext()?.disabled === true\n )\n }\n\n private get _isManagedByGroup(): boolean {\n return this._groupManagement.getContext() !== undefined\n }\n\n private readonly _formAssociation = defineFormAssociation<boolean>({\n host: this,\n initialize: () => {\n if (this.hasAttribute('checked')) this._checked = true\n },\n getState: () => this._checked,\n setState: checked => {\n this.checked = checked\n },\n getFormValue: () => (!this._isManagedByGroup && this._checked ? this.value || 'on' : null),\n getFormState: () => String(this._checked),\n restoreState: state => {\n if (typeof state === 'string') this.checked = state === 'true'\n },\n isStateManaged: () => this._isManagedByGroup,\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private readonly _labelEmptiness = new LabelEmptinessController(this, '.wui-checkbox-label', empty => {\n this._labelEmpty = empty\n })\n\n @query('web-ui-svg-draw-lines') private readonly _drawLines?: WebUiSvgDrawLines\n\n /** 每次更新重读一次,交给内层描边的 duration 属性;见 willUpdate。 */\n private _drawDurationMs = 160\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n internals.setValidity({})\n return\n }\n internals.setValidity({ valueMissing: true }, '请选择此项')\n }\n\n private handleClick() {\n if (this._isDisabled) return\n const old = this._checked\n this._checked = !old\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n // group-managed 时事件不冒泡/不组合,由 group 统一派发一次 host 事件,避免同名事件外泄\n const opts: EventInit = this._isManagedByGroup\n ? { bubbles: false, composed: false }\n : { bubbles: true, composed: true }\n this.dispatchEvent(new Event('input', opts))\n this.dispatchEvent(new Event('change', opts))\n }\n\n private handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n /*\n * 收回期间勾要留在可见档,否则 160ms 淡出抢在描边收回之前把它藏掉。翻转放在 willUpdate:\n * 与 checked 同一次 update 落地,渲染后不再改状态。收回的终点是留在内联样式上的空白,所以这一位\n * 不需要在动画结束后复位,下一次勾选会清掉;reduced motion 下收回根本不跑,按住可见位就是把勾\n * 永久留在未勾选的框里,所以那里必须让位给淡出。\n */\n override willUpdate(changed: PropertyValues) {\n super.willUpdate(changed)\n this._drawDurationMs = triggerDuration(this)\n const wasChecked = changed.get('_checked')\n if (typeof wasChecked === 'boolean') {\n this._retracting = wasChecked && !prefersReducedMotion(this)\n }\n }\n\n /*\n * 挂载时就勾选是初始状态而非用户勾选,不画线:_checked 的字段初始化器在构造阶段写过一次,\n * Lit 对同一轮里已记录过旧值的键不再覆盖,所以首帧拿到的是 undefined,之后的每次真实切换才带\n * boolean 旧值——包括 group 在子项首帧前把选中态写回去那一种。\n */\n override updated(changed: PropertyValues) {\n super.updated(changed)\n const wasChecked = changed.get('_checked')\n if (typeof wasChecked !== 'boolean') return\n\n if (wasChecked) void this._drawLines?.replay({ reverse: true })\n else void this._drawLines?.replay()\n }\n\n override render() {\n const cls = {\n 'wui-checkbox': true,\n 'is-checked': this._checked,\n 'is-retracting': this._retracting,\n 'is-label-empty': this._labelEmpty,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <label\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"checkbox\"\n aria-checked=${String(this._checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <span class=\"wui-checkbox-box\">\n <span class=\"wui-checkbox-icon\"\n ><web-ui-svg-draw-lines duration=${this._drawDurationMs} no-autoplay\n ><web-ui-icon .icon=${akarIconsCheck}></web-ui-icon></web-ui-svg-draw-lines\n ></span>\n </span>\n <span class=\"wui-checkbox-label\"><slot></slot></span>\n </label>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-checkbox': WebUiCheckbox\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAkBA,EAA+B;AAM/B,SAAS,EAAgB,GAAyB;CAChD,IAAM,IAAS,EAAc,iBAAiB,CAAE,CAAC,CAAC,iBAAiB,wBAAwB,CAAC;CAC5F,OAAO,MAAW,OAAO,MAAM,KAAK,IAAI,GAAG,CAAM;AACnD;AAGO,IAAM,IAAN,cAA4B,EAAe,CAAU,CAAC,CAAC;;EAoElC,aAlEU,KAAA,mBAAA,EAA0C,MAAM;GAClF,SAAS;GACT,qBAAqB,KAAK,cAAc;EAC1C,CAAC,CAAC,CAAC,KAAK,GAEoB,KAAA,WAAA,IAGG,KAAA,cAAA,IAGA,KAAA,cAAA,IAaK,KAAA,QAAA,IACc,KAAA,OAAA,IACK,KAAA,WAAA,IACA,KAAA,WAAA,IAYnB,KAAA,mBAAA,EAA+B;GACjE,MAAM;GACN,kBAAkB;IAChB,AAAI,KAAK,aAAa,SAAS,MAAG,KAAK,WAAW;GACpD;GACA,gBAAgB,KAAK;GACrB,WAAU,MAAW;IACnB,KAAK,UAAU;GACjB;GACA,oBAAqB,CAAC,KAAK,qBAAqB,KAAK,WAAW,KAAK,SAAS,OAAO;GACrF,oBAAoB,OAAO,KAAK,QAAQ;GACxC,eAAc,MAAS;IACrB,AAAI,OAAO,KAAU,aAAU,KAAK,UAAU,MAAU;GAC1D;GACA,sBAAsB,KAAK;GAC3B,oBAAoB,KAAK,cAAc;EACzC,CAAC,CAAC,CAAC,KAAK,GAEsC,KAAA,6BAAA,IAAI,EAA0B,MAAM,KAAK,gBAAgB,GAEpE,KAAA,kBAAA,IAAI,EAAyB,MAAM,wBAAuB,MAAS;GACpG,KAAK,cAAc;EACrB,CAAC,GAKyB,KAAA,kBAAA;;;EAnED,KAAA,SAAA,CAAC,EAAU,CAAgB,GAAG,EAAU,CAAK,CAAC;;CAcvE,IAAI,UAAmB;EACrB,OAAO,KAAK;CACd;CAEA,IAAI,QAAQ,GAAY;EACtB,IAAM,IAAM,KAAK;EAGjB,AAFA,KAAK,WAAW,GAChB,KAAK,iBAAiB,KAAK,GAC3B,KAAK,cAAc,WAAW,CAAG;CACnC;CAOA,IAAY,cAAuB;EACjC,OACE,KAAK,YAAY,KAAK,iBAAiB,eAAe,KAAK,KAAK,iBAAiB,WAAW,CAAC,EAAE,aAAa;CAEhH;CAEA,IAAY,oBAA6B;EACvC,OAAO,KAAK,iBAAiB,WAAW,MAAM,KAAA;CAChD;CA+BA,gBAAwB;EACtB,IAAM,IAAY,KAAK,iBAAiB,aAAa;EACjD,IAAC,KAAa,OAAO,EAAU,eAAgB,YACnD;OAAI,KAAK,eAAe,KAAK,qBAAqB,CAAC,KAAK,YAAY,KAAK,UAAU;IACjF,EAAU,YAAY,CAAC,CAAC;IACxB;GACF;GACA,EAAU,YAAY,EAAE,cAAc,GAAK,GAAG,OAAO;EADrD;CAEF;CAEA,cAAsB;EACpB,IAAI,KAAK,aAAa;EACtB,IAAM,IAAM,KAAK;EAGjB,AAFA,KAAK,WAAW,CAAC,GACjB,KAAK,iBAAiB,KAAK,GAC3B,KAAK,cAAc,WAAW,CAAG;EAEjC,IAAM,IAAkB,KAAK,oBACzB;GAAE,SAAS;GAAO,UAAU;EAAM,IAClC;GAAE,SAAS;GAAM,UAAU;EAAK;EAEpC,AADA,KAAK,cAAc,IAAI,MAAM,SAAS,CAAI,CAAC,GAC3C,KAAK,cAAc,IAAI,MAAM,UAAU,CAAI,CAAC;CAC9C;CAEA,cAAsB,GAAkB;EACtC,CAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,eAAe,GACjB,KAAK,YAAY;CAErB;CAQA,WAAoB,GAAyB;EAE3C,AADA,MAAM,WAAW,CAAO,GACxB,KAAK,kBAAkB,EAAgB,IAAI;EAC3C,IAAM,IAAa,EAAQ,IAAI,UAAU;EACzC,AAAI,OAAO,KAAe,cACxB,KAAK,cAAc,KAAc,CAAC,EAAqB,IAAI;CAE/D;CAOA,QAAiB,GAAyB;EACxC,MAAM,QAAQ,CAAO;EACrB,IAAM,IAAa,EAAQ,IAAI,UAAU;EACrC,OAAO,KAAe,cAEtB,IAAY,KAAU,YAAY,OAAO,EAAE,SAAS,GAAK,CAAC,IACzD,KAAU,YAAY,OAAO;CACpC;CAEA,SAAkB;EAChB,IAAM,IAAM;GACV,gBAAgB;GAChB,cAAc,KAAK;GACnB,iBAAiB,KAAK;GACtB,kBAAkB,KAAK;GACvB,eAAe,KAAK;EACtB;EAEA,OAAO,CAAI;;gBAEC,EAAS,CAAG,EAAE;mBACX,KAAK,cAAc,OAAO,IAAI;;uBAE1B,OAAO,KAAK,QAAQ,EAAE;wBACrB,OAAO,KAAK,WAAW,EAAE;iBAChC,KAAK,YAAY;mBACf,KAAK,cAAc;;;;+CAIS,KAAK,gBAAgB;oCAChC,EAAe;;;;;;CAMjD;AAMF;AA7JG,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GAGN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,eAAA,KAAA,CAAA,GAGN,EAAA,CAAA,EAAM,CAAA,GAAA,EAAA,WAAA,eAAA,KAAA,CAAA,GAaN,EAAA,CAAA,EAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,EAAA,WAAA,SAAA,KAAA,CAAA,GACzB,EAAA,CAAA,EAAS;CAAE,MAAM;CAAQ,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GACxC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GACzC,EAAA,CAAA,EAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,YAAA,KAAA,CAAA,GAoCzC,EAAA,CAAA,EAAM,uBAAuB,CAAA,GAAA,EAAA,WAAA,cAAA,KAAA,CAAA,GAlE/B,IAAA,EAAA,CAAA,EAAc,iBAAiB,CAAA,GAAA,CAAA"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox/index.ts"],"sourcesContent":["import '@/components/icon'\n\nimport { html, LitElement, type PropertyValues, unsafeCSS } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport selectionControl from '@/assets/selection-control.css?inline'\nimport { WebUiSvgDrawLines } from '@/components/svg-draw-lines'\nimport { akarIconsCheck } from '@/icons'\nimport { installPointerFocusSuppression } from '@/shared/focus/pointer-focus'\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupManaged, selectionGroupContextKey, type SelectionGroupContext } from '@/shared/group-management'\nimport { LabelEmptinessController } from '@/shared/label-emptiness'\nimport { parseDuration } from '@/shared/theme/duration'\nimport { prefersReducedMotion } from '@/shared/theme/reduced-motion'\n\nimport style from './style.css?inline'\n\ninstallPointerFocusSuppression()\n\n/*\n * 描边时长取 `--wui-duration-trigger`,让勾和 indicator 底色那条 transition 落在同一拍。\n * 读不到 token 或格式不符时兜底 160,负值钳到 0。\n */\nfunction triggerDuration(el: HTMLElement): number {\n const parsed = parseDuration(getComputedStyle(el).getPropertyValue('--wui-duration-trigger'))\n return parsed === null ? 160 : Math.max(0, parsed)\n}\n\n@customElement('web-ui-checkbox')\nexport class WebUiCheckbox extends FormAssociated(LitElement) {\n static override styles = [unsafeCSS(selectionControl), unsafeCSS(style)]\n private readonly _groupManagement = defineGroupManaged<SelectionGroupContext>(this, {\n context: selectionGroupContextKey,\n requestUpdate: () => this.requestUpdate()\n }).make()\n\n @state() private _checked = false\n\n /** 描边收回期间把勾按在可见档,见 willUpdate。 */\n @state() private _retracting = false\n\n /** label 没有可渲染内容(空槽位,或只挂着一个无障碍名)时收掉 gap,见 LabelEmptinessController。 */\n @state() private _labelEmpty = false\n\n get checked(): boolean {\n return this._checked\n }\n\n set checked(v: boolean) {\n const old = this._checked\n this._checked = v\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n }\n\n @property({ type: String }) value = ''\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n private get _isDisabled(): boolean {\n return (\n this.disabled || this._formAssociation.isFormDisabled() || this._groupManagement.getContext()?.disabled === true\n )\n }\n\n private get _isManagedByGroup(): boolean {\n return this._groupManagement.getContext() !== undefined\n }\n\n private readonly _formAssociation = defineFormAssociation<boolean>({\n host: this,\n initialize: () => {\n if (this.hasAttribute('checked')) this._checked = true\n },\n getState: () => this._checked,\n setState: checked => {\n this.checked = checked\n },\n getFormValue: () => (!this._isManagedByGroup && this._checked ? this.value || 'on' : null),\n getFormState: () => String(this._checked),\n restoreState: state => {\n if (typeof state === 'string') this.checked = state === 'true'\n },\n isStateManaged: () => this._isManagedByGroup,\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n private readonly _labelEmptiness = new LabelEmptinessController(this, '.wui-checkbox-label', empty => {\n this._labelEmpty = empty\n })\n\n @query('web-ui-svg-draw-lines') private readonly _drawLines?: WebUiSvgDrawLines\n\n /** 每次更新重读一次,交给内层描边的 duration 属性;见 willUpdate。 */\n private _drawDurationMs = 160\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || this._isManagedByGroup || !this.required || this._checked) {\n internals.setValidity({})\n return\n }\n internals.setValidity({ valueMissing: true }, 'Select this option')\n }\n\n private handleClick() {\n if (this._isDisabled) return\n const old = this._checked\n this._checked = !old\n this._formAssociation.sync()\n this.requestUpdate('checked', old)\n // group-managed 时事件不冒泡/不组合,由 group 统一派发一次 host 事件,避免同名事件外泄\n const opts: EventInit = this._isManagedByGroup\n ? { bubbles: false, composed: false }\n : { bubbles: true, composed: true }\n this.dispatchEvent(new Event('input', opts))\n this.dispatchEvent(new Event('change', opts))\n }\n\n private handleKeyDown(e: KeyboardEvent) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n this.handleClick()\n }\n }\n\n /*\n * 收回期间勾要留在可见档,否则 160ms 淡出抢在描边收回之前把它藏掉。翻转放在 willUpdate:\n * 与 checked 同一次 update 落地,渲染后不再改状态。收回的终点是留在内联样式上的空白,所以这一位\n * 不需要在动画结束后复位,下一次勾选会清掉;reduced motion 下收回根本不跑,按住可见位就是把勾\n * 永久留在未勾选的框里,所以那里必须让位给淡出。\n */\n override willUpdate(changed: PropertyValues) {\n super.willUpdate(changed)\n this._drawDurationMs = triggerDuration(this)\n const wasChecked = changed.get('_checked')\n if (typeof wasChecked === 'boolean') {\n this._retracting = wasChecked && !prefersReducedMotion(this)\n }\n }\n\n /*\n * 挂载时就勾选是初始状态而非用户勾选,不画线:_checked 的字段初始化器在构造阶段写过一次,\n * Lit 对同一轮里已记录过旧值的键不再覆盖,所以首帧拿到的是 undefined,之后的每次真实切换才带\n * boolean 旧值——包括 group 在子项首帧前把选中态写回去那一种。\n */\n override updated(changed: PropertyValues) {\n super.updated(changed)\n const wasChecked = changed.get('_checked')\n if (typeof wasChecked !== 'boolean') return\n\n if (wasChecked) void this._drawLines?.replay({ reverse: true })\n else void this._drawLines?.replay()\n }\n\n override render() {\n const cls = {\n 'wui-checkbox': true,\n 'is-checked': this._checked,\n 'is-retracting': this._retracting,\n 'is-label-empty': this._labelEmpty,\n 'is-disabled': this._isDisabled\n }\n\n return html`\n <span\n class=${classMap(cls)}\n tabindex=${this._isDisabled ? '-1' : '0'}\n role=\"checkbox\"\n aria-checked=${String(this._checked)}\n aria-disabled=${String(this._isDisabled)}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <span class=\"wui-checkbox-box\">\n <span class=\"wui-checkbox-icon\"\n ><web-ui-svg-draw-lines duration=${this._drawDurationMs} no-autoplay\n ><web-ui-icon .icon=${akarIconsCheck}></web-ui-icon></web-ui-svg-draw-lines\n ></span>\n </span>\n <span class=\"wui-checkbox-label\"><slot></slot></span>\n </span>\n `\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-checkbox': WebUiCheckbox\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  //#region src/components/checkbox/style.css?inline
2
- var e = ".wui-checkbox-box{border-radius:var(--wui-internal-checkbox-radius,6px)}.is-checked .wui-checkbox-box{border-color:var(--wui-color-accent,#08f);background-color:var(--wui-color-accent,#08f)}.wui-checkbox-icon{--wui-icon-color:var(--wui-color-on-control,#fff);opacity:0;transition:opacity var(--wui-duration-trigger,.16s) ease;font-size:0;line-height:0;display:block;overflow:hidden}.is-checked .wui-checkbox-icon,.is-retracting .wui-checkbox-icon{opacity:1}";
2
+ var e = ".wui-checkbox-box{border-radius:var(--wui-internal-checkbox-radius,6px)}.is-checked .wui-checkbox-box{border-color:var(--wui-color-accent,#0071e3);background-color:var(--wui-color-accent,#0071e3)}.wui-checkbox-icon{--wui-icon-color:var(--wui-color-on-control,#fff);opacity:0;transition:opacity var(--wui-duration-trigger,.16s) ease;font-size:0;line-height:0;display:block;overflow:hidden}.is-checked .wui-checkbox-icon,.is-retracting .wui-checkbox-icon{opacity:1}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/checkbox/style.css?inline"],"sourcesContent":[".wui-checkbox-box {\n border-radius: var(--wui-internal-checkbox-radius, 6px);\n}\n\n.is-checked .wui-checkbox-box {\n border-color: var(--wui-color-accent, #08f);\n background-color: var(--wui-color-accent, #08f);\n}\n\n/*\n * 勾是 @/icons 的描边资产,颜色经 web-ui-icon 的 --wui-icon-color 传入并取 on-control 档:勾选后\n * 指示器底是 accent,勾留在继承的文字色就是深灰压深蓝。资产必须是 fill:none + stroke:currentColor,\n * 换成实心图标那条 dash 动画照跑但什么都看不见(判据见 checkbox.motion.browser.spec.ts)。\n * 尺寸是 web-ui-icon 自己的默认 18,宿主够不到嵌套 shadow root 里的 svg,因此不随\n * --wui-selection-control-size 按比例放大。\n */\n.wui-checkbox-icon {\n --wui-icon-color: var(--wui-color-on-control, #fff);\n\n overflow: hidden;\n display: block;\n\n font-size: 0;\n line-height: 0;\n\n opacity: 0;\n\n transition: opacity var(--wui-duration-trigger, 160ms) ease;\n}\n\n/*\n * is-retracting 是描边收回的那一段:勾得留在可见档,否则这条 160ms 的淡出会抢在收回结束之前\n * 把它藏掉,收回根本看不见。收回的终点是留在内联样式上的「整条路径落在 dash 间隙里」,动画自己\n * 收尾就撤销了,所以停在这里就是看不见的勾,不必再等一次淡出;复位由下一次勾选负责(见 index.ts 的 willUpdate)。\n */\n.is-checked .wui-checkbox-icon,\n.is-retracting .wui-checkbox-icon {\n opacity: 1;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"style.js","names":[],"sources":["../../../src/components/checkbox/style.css?inline"],"sourcesContent":[".wui-checkbox-box {\n border-radius: var(--wui-internal-checkbox-radius, 6px);\n}\n\n.is-checked .wui-checkbox-box {\n border-color: var(--wui-color-accent, #0071e3);\n background-color: var(--wui-color-accent, #0071e3);\n}\n\n/*\n * 勾是 @/icons 的描边资产,颜色经 web-ui-icon 的 --wui-icon-color 传入并取 on-control 档:勾选后\n * indicator 底是 accent,勾留在继承的文字色就是深灰压深蓝。资产必须是 fill:none + stroke:currentColor,\n * 换成实心 icon 那条 dash 动画照跑但什么都看不见(判据见 checkbox.motion.browser.spec.ts)。\n * 尺寸是 web-ui-icon 自己的默认 18,宿主够不到嵌套 shadow root 里的 svg,因此不随\n * --wui-selection-control-size 按比例放大。\n */\n.wui-checkbox-icon {\n --wui-icon-color: var(--wui-color-on-control, #fff);\n\n overflow: hidden;\n display: block;\n\n font-size: 0;\n line-height: 0;\n\n opacity: 0;\n\n transition: opacity var(--wui-duration-trigger, 160ms) ease;\n}\n\n/*\n * is-retracting 是描边收回的那一段:勾得留在可见档,否则这条 160ms 的淡出会抢在收回结束之前\n * 把它藏掉,收回根本看不见。收回的终点是留在内联样式上的「整条路径落在 dash 间隙里」,动画自己\n * 收尾就撤销了,所以停在这里就是看不见的勾,不必再等一次淡出;复位由下一次勾选负责(见 index.ts 的 willUpdate)。\n */\n.is-checked .wui-checkbox-icon,\n.is-retracting .wui-checkbox-icon {\n opacity: 1;\n}\n"],"mappings":""}
@@ -95,7 +95,7 @@ var m = ["horizontal", "vertical"], h = class extends t(c) {
95
95
  e.setValidity({});
96
96
  return;
97
97
  }
98
- e.setValidity({ valueMissing: !0 }, "请至少选择一项");
98
+ e.setValidity({ valueMissing: !0 }, "Select at least one option");
99
99
  }
100
100
  }
101
101
  render() {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox-group/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupCoordinator, GroupController } from '@/shared/group-management'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport type { WebUiCheckbox } from '../checkbox'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_DIRECTIONS = ['horizontal', 'vertical'] as const\n\n@customElement('web-ui-checkbox-group')\nexport class WebUiCheckboxGroup extends FormAssociated(LitElement) {\n static override styles = unsafeCSS(style)\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n @property({ type: String, reflect: true })\n get direction(): 'horizontal' | 'vertical' {\n return this._direction\n }\n set direction(v: string) {\n const old = this._direction\n this._direction = normalizeLiteral(v, ALLOWED_DIRECTIONS, 'vertical')\n this.requestUpdate('direction', old)\n }\n private _direction: 'horizontal' | 'vertical' = 'vertical'\n\n @state() private _value: string[] = []\n\n private readonly _groupController = new GroupController(\n this,\n defineGroupCoordinator<WebUiCheckbox, string[]>({\n host: this,\n getItems: () => [...this.querySelectorAll<WebUiCheckbox>('web-ui-checkbox')],\n getValue: () => this._value,\n setValue: value => {\n this.value = value\n },\n getDisabled: () => this._isDisabled,\n isItem: (target): target is WebUiCheckbox => target instanceof HTMLElement && target.matches('web-ui-checkbox'),\n isItemSelected: (checkbox, value) => value.includes(checkbox.value),\n getNextValue: (checkbox, value) =>\n checkbox.checked ? [...new Set([...value, checkbox.value])] : value.filter(item => item !== checkbox.value),\n valuesEqual: (a, b) => a.length === b.length && a.every((value, index) => value === b[index]),\n copyValue: value => [...value],\n setItemSelected: (checkbox, selected) => {\n checkbox.checked = selected\n },\n dispatchValueChange: () => {\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n }).make(),\n // 每次成员集合同步后把组值剪到现存成员范围内\n { afterSync: () => this._pruneRemovedMembers() }\n )\n\n /**\n * 成员被移除后,它的 value 会作为不可见、也取消不掉的幽灵值留在组值里,\n * 并能继续进 FormData。这里以「曾经出现在成员里、现在消失了」为剪枝条件。\n *\n * 不能用「不在现存成员里就剪」:v-if / 异步渲染下组值常常先于成员出现,\n * 那样会把合法的预设值当成幽灵值清掉。\n */\n private _knownMemberValues = new Set<string>()\n\n private _pruneRemovedMembers() {\n const items = [...this.querySelectorAll<WebUiCheckbox>('web-ui-checkbox')]\n if (items.length === 0) return\n const alive = new Set(items.map(item => item.value))\n const next = this._value.filter(value => alive.has(value) || !this._knownMemberValues.has(value))\n this._knownMemberValues = alive\n if (next.length !== this._value.length) this.value = next\n }\n\n get value(): string[] {\n return this._value\n }\n\n set value(v: string[]) {\n const old = this._value\n this._value = [...v]\n this._formAssociation.sync()\n this.requestUpdate('value', old)\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n private readonly _formAssociation = defineFormAssociation<string[]>({\n host: this,\n initialize: () => {\n const attributeValue = this.getAttribute('value')\n if (attributeValue !== null) this.value = attributeValue.split(',').filter(Boolean)\n },\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n copyState: value => [...value],\n getFormValue: () => {\n if (!this.name || this._value.length === 0) return null\n const formData = new FormData()\n this._value.forEach(value => formData.append(this.name, value))\n return formData\n },\n getFormState: () => JSON.stringify(this._value),\n restoreState: state => {\n if (typeof state !== 'string') return\n try {\n const value = JSON.parse(state)\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) this.value = value\n } catch {\n // 忽略无法解析的历史表单状态。\n }\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n override formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n this._groupController.sync()\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || !this.required || this._value.length > 0) {\n internals.setValidity({})\n return\n }\n internals.setValidity({ valueMissing: true }, '请至少选择一项')\n }\n\n override render() {\n return html`<div class=\"wui-checkbox-group\"><slot></slot></div>`\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-checkbox-group': WebUiCheckboxGroup\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/checkbox-group/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { FormAssociated, defineFormAssociation, FormAssociationController } from '@/shared/form-association'\nimport { defineGroupCoordinator, GroupController } from '@/shared/group-management'\nimport { normalizeLiteral } from '@/shared/normalize'\n\nimport type { WebUiCheckbox } from '../checkbox'\n\nimport style from './style.css?inline'\n\nconst ALLOWED_DIRECTIONS = ['horizontal', 'vertical'] as const\n\n@customElement('web-ui-checkbox-group')\nexport class WebUiCheckboxGroup extends FormAssociated(LitElement) {\n static override styles = unsafeCSS(style)\n @property({ type: String, reflect: true }) name = ''\n @property({ type: Boolean, reflect: true }) disabled = false\n @property({ type: Boolean, reflect: true }) required = false\n\n @property({ type: String, reflect: true })\n get direction(): 'horizontal' | 'vertical' {\n return this._direction\n }\n set direction(v: string) {\n const old = this._direction\n this._direction = normalizeLiteral(v, ALLOWED_DIRECTIONS, 'vertical')\n this.requestUpdate('direction', old)\n }\n private _direction: 'horizontal' | 'vertical' = 'vertical'\n\n @state() private _value: string[] = []\n\n private readonly _groupController = new GroupController(\n this,\n defineGroupCoordinator<WebUiCheckbox, string[]>({\n host: this,\n getItems: () => [...this.querySelectorAll<WebUiCheckbox>('web-ui-checkbox')],\n getValue: () => this._value,\n setValue: value => {\n this.value = value\n },\n getDisabled: () => this._isDisabled,\n isItem: (target): target is WebUiCheckbox => target instanceof HTMLElement && target.matches('web-ui-checkbox'),\n isItemSelected: (checkbox, value) => value.includes(checkbox.value),\n getNextValue: (checkbox, value) =>\n checkbox.checked ? [...new Set([...value, checkbox.value])] : value.filter(item => item !== checkbox.value),\n valuesEqual: (a, b) => a.length === b.length && a.every((value, index) => value === b[index]),\n copyValue: value => [...value],\n setItemSelected: (checkbox, selected) => {\n checkbox.checked = selected\n },\n dispatchValueChange: () => {\n this.dispatchEvent(new Event('input', { bubbles: true, composed: true }))\n this.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n }\n }).make(),\n // 每次成员集合同步后把组值剪到现存成员范围内\n { afterSync: () => this._pruneRemovedMembers() }\n )\n\n /**\n * 成员被移除后,它的 value 会作为不可见、也取消不掉的幽灵值留在组值里,\n * 并能继续进 FormData。这里以「曾经出现在成员里、现在消失了」为剪枝条件。\n *\n * 不能用「不在现存成员里就剪」:v-if / 异步渲染下组值常常先于成员出现,\n * 那样会把合法的预设值当成幽灵值清掉。\n */\n private _knownMemberValues = new Set<string>()\n\n private _pruneRemovedMembers() {\n const items = [...this.querySelectorAll<WebUiCheckbox>('web-ui-checkbox')]\n if (items.length === 0) return\n const alive = new Set(items.map(item => item.value))\n const next = this._value.filter(value => alive.has(value) || !this._knownMemberValues.has(value))\n this._knownMemberValues = alive\n if (next.length !== this._value.length) this.value = next\n }\n\n get value(): string[] {\n return this._value\n }\n\n set value(v: string[]) {\n const old = this._value\n this._value = [...v]\n this._formAssociation.sync()\n this.requestUpdate('value', old)\n }\n\n private get _isDisabled(): boolean {\n return this.disabled || this._formAssociation.isFormDisabled()\n }\n\n private readonly _formAssociation = defineFormAssociation<string[]>({\n host: this,\n initialize: () => {\n const attributeValue = this.getAttribute('value')\n if (attributeValue !== null) this.value = attributeValue.split(',').filter(Boolean)\n },\n getState: () => this._value,\n setState: value => {\n this.value = value\n },\n copyState: value => [...value],\n getFormValue: () => {\n if (!this.name || this._value.length === 0) return null\n const formData = new FormData()\n this._value.forEach(value => formData.append(this.name, value))\n return formData\n },\n getFormState: () => JSON.stringify(this._value),\n restoreState: state => {\n if (typeof state !== 'string') return\n try {\n const value = JSON.parse(state)\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) this.value = value\n } catch {\n // 忽略无法解析的历史表单状态。\n }\n },\n syncValidity: () => this._syncValidity()\n }).make()\n\n private readonly _formAssociationController = new FormAssociationController(this, this._formAssociation)\n\n override formDisabledCallback(disabled: boolean) {\n this._formAssociation.setDisabled(disabled)\n this._groupController.sync()\n }\n\n private _syncValidity() {\n const internals = this._formAssociation.getInternals()\n if (!internals || typeof internals.setValidity !== 'function') return\n if (this._isDisabled || !this.required || this._value.length > 0) {\n internals.setValidity({})\n return\n }\n internals.setValidity({ valueMissing: true }, 'Select at least one option')\n }\n\n override render() {\n return html`<div class=\"wui-checkbox-group\"><slot></slot></div>`\n }\n\n declare readonly $events: {\n input: Event\n change: Event\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-checkbox-group': WebUiCheckboxGroup\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { LitElement } from 'lit';
2
2
  /**
3
- * 文档流内折叠面板:trigger 经默认 slot 提供,内容经 `slot="content"` 提供。
3
+ * 文档流内 collapse panel:trigger 经默认 slot 提供,内容经 `slot="content"` 提供。
4
4
  *
5
5
  * trigger 语义完全来自 slot 进来的交互元素(原生 button / web-ui-button 等):
6
6
  * Enter/Space 激活走该元素的原生 click,不做 role="button" 补齐;组件把
@@ -12,15 +12,15 @@ import { LitElement } from 'lit';
12
12
  * 选型保留)。关闭稳态三态(消费者 light DOM 永不移动,hidden 全部命令式管理,
13
13
  * 避免渲染绑定在关闭动画起点抢先 display:none):
14
14
  * - 默认:content 容器 `hidden`(display:none,脱离渲染与可访问性树);
15
- * - `keep-mounted`:inner `inert`(保留在 0fr 轨道内,滚动位置与布局可测量);
16
- * - `peek`:inner `inert`,轨道停在固定长度的裁剪窗口,只露出内容头部;
15
+ * - `keep-mounted`:inner `inert`(保留在 0fr track 内,滚动位置与布局可测量);
16
+ * - `peek`:inner `inert`,track 停在固定长度的裁剪窗口,只露出内容头部;
17
17
  * - 动画进行中:inner `inert` + track pointer-events 禁用,结束后进入对应稳态。
18
18
  *
19
19
  * `peek` 与展开态之间是固定长度与内容自适应高度的过渡,CSS 无法插值;这两个
20
- * 方向的动画改为读出像素后以显式长度写入轨道,落稳态时清除内联值交回 CSS 规则。
20
+ * 方向的动画改为读出像素后以显式长度写入 track,落稳态时清除内联值交回 CSS 规则。
21
21
  */
22
22
  export declare class WebUiCollapse extends LitElement {
23
- static styles: import('lit').CSSResult;
23
+ static styles: import('lit').CSSResult[];
24
24
  /** 展开状态;严格受控,唯一状态源。 */
25
25
  open: boolean;
26
26
  /** 禁用触发:点击忽略、aria-disabled 写入 trigger 元素;已展开内容保持现状。 */
@@ -33,7 +33,7 @@ export declare class WebUiCollapse extends LitElement {
33
33
  * 关闭稳态露出的尺寸(CSS 长度,如 `120px`、`6rem`),沿动画轴生效:默认是高度,
34
34
  * `horizontal` 时为宽度;未设置时保持完全收起。
35
35
  *
36
- * 设置后关闭稳态语义等同 `keep-mounted`(内容留在轨道内、`inert` 阻断交互),
36
+ * 设置后关闭稳态语义等同 `keep-mounted`(内容留在 track 内、`inert` 阻断交互),
37
37
  * 只露出 `peek` 范围内的部分;内容本身不足 `peek` 时按内容实际尺寸收起。
38
38
  * 注意 `peek` 是固定长度与内容自适应高度之间的过渡:CSS 无法在两者之间插值,
39
39
  * 因此这两个方向的动画由本组件读出内容尺寸后以显式长度驱动(其余路径仍是
@@ -50,6 +50,7 @@ export declare class WebUiCollapse extends LitElement {
50
50
  private _exitTimer?;
51
51
  private _generation;
52
52
  private _lastOpen?;
53
+ private _triggerAriaSnapshot?;
53
54
  connectedCallback(): void;
54
55
  disconnectedCallback(): void;
55
56
  protected updated(changed: Map<string, unknown>): void;
@@ -60,6 +61,7 @@ export declare class WebUiCollapse extends LitElement {
60
61
  private _onTriggerClick;
61
62
  private _queryTrigger;
62
63
  private readonly _onTriggerSlotChange;
64
+ private _restoreTriggerAriaSnapshot;
63
65
  private _syncTriggerAria;
64
66
  /** 关闭稳态是否露出部分内容;空值与非空判断避免 `peek=""` 被当作有效长度。 */
65
67
  private get _peeks();
@@ -1,40 +1,41 @@
1
1
  import e from "../../_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
2
2
  import { dispatchOpenChangeEvent as t } from "../../shared/open-state/index.js";
3
3
  import { getTransitionDuration as n } from "../../shared/overlay/presence.js";
4
- import { UserChangeController as r } from "../../shared/events/user-change.js";
5
- import i from "./style.js";
6
- import { LitElement as a, html as o, unsafeCSS as s } from "lit";
7
- import { customElement as c, property as l, query as u } from "lit/decorators.js";
8
- import { classMap as d } from "lit/directives/class-map.js";
4
+ import r from "../../classes/glow.js";
5
+ import { UserChangeController as i } from "../../shared/events/user-change.js";
6
+ import a from "./style.js";
7
+ import { LitElement as o, html as s, unsafeCSS as c } from "lit";
8
+ import { customElement as l, property as u, query as d } from "lit/decorators.js";
9
+ import { classMap as f } from "lit/directives/class-map.js";
9
10
  //#region src/components/collapse/index.ts
10
- var f = 80, p = "--wui-collapse-peek-edge-active";
11
- function m() {
11
+ var p = 80, m = "--wui-collapse-peek-edge-active";
12
+ function h() {
12
13
  if (!(typeof CSS > "u" || typeof CSS.registerProperty != "function")) try {
13
14
  CSS.registerProperty({
14
- name: p,
15
+ name: m,
15
16
  syntax: "<length>",
16
17
  inherits: !0,
17
18
  initialValue: "0px"
18
19
  });
19
20
  } catch {}
20
21
  }
21
- m();
22
- var h = 0, g = class extends a {
22
+ h();
23
+ var g = 0, _ = class extends o {
23
24
  constructor(...e) {
24
- super(...e), this.open = !1, this.disabled = !1, this.horizontal = !1, this.keepMounted = !1, this.peek = null, this._contentId = `wui-collapse-content-${++h}`, this._userOpenChange = new r(), this._generation = 0, this._onTriggerClick = (e) => {
25
+ super(...e), this.open = !1, this.disabled = !1, this.horizontal = !1, this.keepMounted = !1, this.peek = null, this._contentId = `wui-collapse-content-${++g}`, this._userOpenChange = new i(), this._generation = 0, this._onTriggerClick = (e) => {
25
26
  this.disabled || e.composedPath().includes(this._triggerWrapper) && (this._userOpenChange.mark(), this.toggle());
26
27
  }, this._onTriggerSlotChange = () => {
27
28
  this.requestUpdate();
28
29
  };
29
30
  }
30
31
  static {
31
- this.styles = s(i);
32
+ this.styles = [c(r), c(a)];
32
33
  }
33
34
  connectedCallback() {
34
35
  super.connectedCallback(), this.addEventListener("click", this._onTriggerClick), this.hasUpdated && (this._generation++, this._clearExitTimer(), this._lastOpen = void 0, this.requestUpdate());
35
36
  }
36
37
  disconnectedCallback() {
37
- super.disconnectedCallback(), this._clearExitTimer();
38
+ super.disconnectedCallback(), this._clearExitTimer(), this._restoreTriggerAriaSnapshot();
38
39
  }
39
40
  updated(e) {
40
41
  if (this._syncTriggerAria(), this._syncPeek(), this._lastOpen === void 0) {
@@ -59,9 +60,25 @@ var h = 0, g = class extends a {
59
60
  let e = (this.shadowRoot?.querySelector(".wui-collapse-trigger-wrapper slot"))?.assignedElements()[0];
60
61
  return e instanceof HTMLElement ? e : null;
61
62
  }
63
+ _restoreTriggerAriaSnapshot() {
64
+ let e = this._triggerAriaSnapshot;
65
+ if (e) {
66
+ for (let [t, n] of Object.entries({
67
+ "aria-expanded": e.expanded,
68
+ "aria-controls": e.controls,
69
+ "aria-disabled": e.disabled
70
+ })) n === null ? e.trigger.removeAttribute(t) : e.trigger.setAttribute(t, n);
71
+ this._triggerAriaSnapshot = void 0;
72
+ }
73
+ }
62
74
  _syncTriggerAria() {
63
75
  let e = this._queryTrigger();
64
- e && (e.setAttribute("aria-expanded", String(this.open)), e.setAttribute("aria-controls", this._contentId), this.disabled ? e.setAttribute("aria-disabled", "true") : e.removeAttribute("aria-disabled"));
76
+ this._triggerAriaSnapshot?.trigger !== e && (this._restoreTriggerAriaSnapshot(), e && (this._triggerAriaSnapshot = {
77
+ trigger: e,
78
+ expanded: e.getAttribute("aria-expanded"),
79
+ controls: e.getAttribute("aria-controls"),
80
+ disabled: e.getAttribute("aria-disabled")
81
+ })), e && (e.setAttribute("aria-expanded", String(this.open)), e.setAttribute("aria-controls", this._contentId), this.disabled ? e.setAttribute("aria-disabled", "true") : e.removeAttribute("aria-disabled"));
65
82
  }
66
83
  get _peeks() {
67
84
  return typeof this.peek == "string" && this.peek.trim() !== "";
@@ -136,7 +153,7 @@ var h = 0, g = class extends a {
136
153
  }
137
154
  let o = !1, s = () => {
138
155
  e.removeEventListener("transitionend", l), this._exitTimer === c && (this._exitTimer = void 0), clearTimeout(c), !(o || t !== this._generation) && (o = !0, r());
139
- }, c = setTimeout(s, a + f);
156
+ }, c = setTimeout(s, a + p);
140
157
  this._exitTimer = c;
141
158
  let l = (t) => {
142
159
  t.target === e && i.includes(t.propertyName) && s();
@@ -183,11 +200,14 @@ var h = 0, g = class extends a {
183
200
  "wui-collapse-track": !0,
184
201
  "is-horizontal": this.horizontal
185
202
  };
186
- return o`
203
+ return s`
187
204
  <div class="wui-collapse-trigger-wrapper" @slotchange=${this._onTriggerSlotChange}><slot></slot></div>
188
205
  <div class="wui-collapse-content">
189
- <div class=${d(e)} id=${this._contentId}>
190
- <div class="wui-collapse-inner">
206
+ <div class=${f(e)} id=${this._contentId}>
207
+ <div class=${f({
208
+ "wui-collapse-inner": !0,
209
+ "wui-glow": this._peeks
210
+ })}>
191
211
  <slot name="content"></slot>
192
212
  </div>
193
213
  </div>
@@ -195,24 +215,24 @@ var h = 0, g = class extends a {
195
215
  `;
196
216
  }
197
217
  };
198
- e([l({
218
+ e([u({
199
219
  type: Boolean,
200
220
  reflect: !0
201
- })], g.prototype, "open", void 0), e([l({
221
+ })], _.prototype, "open", void 0), e([u({
202
222
  type: Boolean,
203
223
  reflect: !0
204
- })], g.prototype, "disabled", void 0), e([l({
224
+ })], _.prototype, "disabled", void 0), e([u({
205
225
  type: Boolean,
206
226
  reflect: !0
207
- })], g.prototype, "horizontal", void 0), e([l({
227
+ })], _.prototype, "horizontal", void 0), e([u({
208
228
  type: Boolean,
209
229
  reflect: !0,
210
230
  attribute: "keep-mounted"
211
- })], g.prototype, "keepMounted", void 0), e([l({
231
+ })], _.prototype, "keepMounted", void 0), e([u({
212
232
  type: String,
213
233
  reflect: !0
214
- })], g.prototype, "peek", void 0), e([u(".wui-collapse-trigger-wrapper")], g.prototype, "_triggerWrapper", void 0), g = e([c("web-ui-collapse")], g);
234
+ })], _.prototype, "peek", void 0), e([d(".wui-collapse-trigger-wrapper")], _.prototype, "_triggerWrapper", void 0), _ = e([l("web-ui-collapse")], _);
215
235
  //#endregion
216
- export { g as WebUiCollapse };
236
+ export { _ as WebUiCollapse };
217
237
 
218
238
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/collapse/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport { UserChangeController } from '@/shared/events/user-change'\nimport { dispatchOpenChangeEvent } from '@/shared/open-state'\nimport { getTransitionDuration } from '@/shared/overlay/presence'\n\nimport style from './style.css?inline'\n\nconst EXIT_FALLBACK_BUFFER = 80\n\n/** peek 边缘渐隐的活动长度:关闭/收起态取由 peek 推导的长度,展开态归 0。 */\nconst PEEK_EDGE_ACTIVE = '--wui-collapse-peek-edge-active'\n\n/*\n * 注册成 `<length>` 才能被 transition 插值(未注册的自定义属性是离散值,只能瞬变)。\n *\n * 必须用 JS 的 `CSS.registerProperty` 而不是 CSS 里的 `@property`:实测后者写在\n * shadow root 的样式表里不产生注册(getComputedStyle 读打开态得到空串而非\n * initial-value),而自定义属性的注册本质上是 document 级的。\n * 注册失败(jsdom、旧浏览器、重复注册)时降级为离散过渡——渐变带长度瞬变,\n * 但位置百分比仍跟随裁剪边缘,行为依旧正确。\n *\n * `inherits` 必须是 true:晕染伪元素(style.css 的 ::after)读同一个值来调制模糊,\n * 继承为 false 时伪元素读到的是 initialValue 0px——mask 的各色标随之塌缩到 100%,\n * 模糊层静默消失且其余渲染一切照旧,只少一层效果。\n */\nfunction registerPeekEdgeActive() {\n // jsdom 与不支持的环境直接跳过;样式里的 var() fallback 保证声明仍然有效。\n if (typeof CSS === 'undefined' || typeof CSS.registerProperty !== 'function') return\n try {\n CSS.registerProperty({\n name: PEEK_EDGE_ACTIVE,\n syntax: '<length>',\n inherits: true,\n initialValue: '0px'\n })\n } catch {\n // 已注册过(HMR、多份副本)或定义冲突:保持现有注册即可。\n }\n}\n\nregisterPeekEdgeActive()\n\nlet collapseIdCounter = 0\n\n/**\n * 文档流内折叠面板:trigger 经默认 slot 提供,内容经 `slot=\"content\"` 提供。\n *\n * trigger 语义完全来自 slot 进来的交互元素(原生 button / web-ui-button 等):\n * Enter/Space 激活走该元素的原生 click,不做 role=\"button\" 补齐;组件把\n * `aria-expanded` / `aria-controls` / `aria-disabled` 回写到首个 assigned\n * element(与 popover trigger 的既定回写模式一致)。wrapper 仅负责点击代理,\n * 不可聚焦,不承载 ARIA。\n *\n * 内容区在 shadow 内以 grid `0fr ↔ 1fr` track 过渡驱动高度/宽度动画(ADR-0030\n * 选型保留)。关闭稳态三态(消费者 light DOM 永不移动,hidden 全部命令式管理,\n * 避免渲染绑定在关闭动画起点抢先 display:none):\n * - 默认:content 容器 `hidden`(display:none,脱离渲染与可访问性树);\n * - `keep-mounted`:inner `inert`(保留在 0fr 轨道内,滚动位置与布局可测量);\n * - `peek`:inner `inert`,轨道停在固定长度的裁剪窗口,只露出内容头部;\n * - 动画进行中:inner `inert` + track pointer-events 禁用,结束后进入对应稳态。\n *\n * `peek` 与展开态之间是固定长度与内容自适应高度的过渡,CSS 无法插值;这两个\n * 方向的动画改为读出像素后以显式长度写入轨道,落稳态时清除内联值交回 CSS 规则。\n */\n@customElement('web-ui-collapse')\nexport class WebUiCollapse extends LitElement {\n static override styles = unsafeCSS(style)\n\n /** 展开状态;严格受控,唯一状态源。 */\n @property({ type: Boolean, reflect: true }) open = false\n\n /** 禁用触发:点击忽略、aria-disabled 写入 trigger 元素;已展开内容保持现状。 */\n @property({ type: Boolean, reflect: true }) disabled = false\n\n /** 水平方向:true 时沿宽度展开,默认沿高度。 */\n @property({ type: Boolean, reflect: true }) horizontal = false\n\n /** 关闭稳态保持内容 `inert` 而非 `hidden`(保留滚动位置,可测量)。 */\n @property({ type: Boolean, reflect: true, attribute: 'keep-mounted' }) keepMounted = false\n\n /**\n * 关闭稳态露出的尺寸(CSS 长度,如 `120px`、`6rem`),沿动画轴生效:默认是高度,\n * `horizontal` 时为宽度;未设置时保持完全收起。\n *\n * 设置后关闭稳态语义等同 `keep-mounted`(内容留在轨道内、`inert` 阻断交互),\n * 只露出 `peek` 范围内的部分;内容本身不足 `peek` 时按内容实际尺寸收起。\n * 注意 `peek` 是固定长度与内容自适应高度之间的过渡:CSS 无法在两者之间插值,\n * 因此这两个方向的动画由本组件读出内容尺寸后以显式长度驱动(其余路径仍是\n * 零测量的 grid fr 过渡)。\n *\n * 露出区域末端自带一段边缘渐隐(提示下方还有内容),长度由 `peek` 按比例推导,\n * 无需也不接受调用方单独指定——见 style.css 中 `--wui-collapse-peek-edge-*`\n * 系列变量(比例、上限、末端颜色可用 CSS 覆盖,属于主题级调优而非组件 API)。\n */\n @property({ type: String, reflect: true }) peek: string | null = null\n\n @query('.wui-collapse-trigger-wrapper') private _triggerWrapper!: HTMLElement\n\n private _contentId = `wui-collapse-content-${++collapseIdCounter}`\n\n private readonly _userOpenChange = new UserChangeController()\n\n private _exitTimer?: ReturnType<typeof setTimeout>\n // 动画代际:每次管线启动自增,旧管线的 transitionend/兜底定时器/rAF 全部失效。\n private _generation = 0\n private _lastOpen?: boolean\n\n override connectedCallback() {\n super.connectedCallback()\n // 点击监听与生命周期同寿(宿主移除即整体销毁),无需 disconnected 清理。\n this.addEventListener('click', this._onTriggerClick)\n // 断连可能打断动画管线(瞬态残留:presence='closing'、容器未 hidden)。\n // 首次连接不必处理(初始 render 走 _lastOpen===undefined 落稳态,请求多余\n // 渲染会触发「scheduled an update after update completed」告警);重连时\n // 重置同步状态并强制一轮 update,由首次同步分支重新落稳态、丢弃在途管线。\n if (this.hasUpdated) {\n this._generation++\n this._clearExitTimer()\n this._lastOpen = undefined\n this.requestUpdate()\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._clearExitTimer()\n }\n\n protected override updated(changed: Map<string, unknown>) {\n // ARIA 回写不依赖 open 分支,任何渲染后都保持与宿主状态同步。\n this._syncTriggerAria()\n // peek 的稳态长度与动画写入共用轨道内联样式,先同步再落稳态,避免被稳态清除。\n this._syncPeek()\n\n // 首次同步(含 open 为默认值的场景,changed map 不含默认值属性):\n // 直接落到正确稳态,不播动画(popover 初始 open 同款)。\n if (this._lastOpen === undefined) {\n this._lastOpen = this.open\n if (this.open) this._applyOpenSteadyState()\n else this._applyClosedSteadyState()\n return\n }\n\n if ((changed.has('keepMounted') || changed.has('peek')) && !this.open) {\n // 运行态切换 keep-mounted / peek:关闭稳态需在 hidden / inert / 裁剪长度间重新落地。\n this._applyClosedSteadyState()\n }\n if (!changed.has('open') || this.open === this._lastOpen) return\n\n this._lastOpen = this.open\n if (this._userOpenChange.consume()) this._dispatchChange(this.open)\n if (this.open) this._beginExpand()\n else this._beginCollapse()\n }\n\n show() {\n if (this.open) return\n this.open = true\n }\n\n close() {\n if (!this.open) return\n this.open = false\n }\n\n toggle() {\n if (this.open) this.close()\n else this.show()\n }\n\n private _dispatchChange(open: boolean) {\n dispatchOpenChangeEvent(this, open)\n }\n\n /*\n * 点击代理:冒泡路径穿过 trigger wrapper 的 click 一律切换。语义由 slot 内\n * 的交互元素(原生 button / web-ui-button)提供;slot 放纯文本时无激活语义\n * (README 约定)。内容区与嵌套内层 collapse 的 click 不经过本 wrapper,天然隔离。\n */\n private _onTriggerClick = (event: MouseEvent) => {\n if (this.disabled) return\n if (!event.composedPath().includes(this._triggerWrapper)) return\n this._userOpenChange.mark()\n this.toggle()\n }\n\n /*\n * Trigger 元素取首个 assigned element(与 popover `_queryTrigger` 同款惰性查询,\n * 不依赖 slotchange——jsdom 不派发该事件,无法用状态缓存)。slot 为空时无回写目标。\n */\n private _queryTrigger(): HTMLElement | null {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('.wui-collapse-trigger-wrapper slot')\n const el = slot?.assignedElements()[0]\n return el instanceof HTMLElement ? el : null\n }\n\n /*\n * slot 内容增删不触发宿主响应式更新:显式请求一轮渲染,由 updated() 的\n * ARIA 回写覆盖晚到的 trigger 元素(slotchange 在 jsdom 不派发,无法监听)。\n */\n private readonly _onTriggerSlotChange = () => {\n this.requestUpdate()\n }\n\n // ARIA 状态回写到 trigger 元素本身(wrapper 不可聚焦,AT 读不到)。\n private _syncTriggerAria() {\n const trigger = this._queryTrigger()\n if (!trigger) return\n trigger.setAttribute('aria-expanded', String(this.open))\n trigger.setAttribute('aria-controls', this._contentId)\n if (this.disabled) trigger.setAttribute('aria-disabled', 'true')\n else trigger.removeAttribute('aria-disabled')\n }\n\n // ===== 内容区动画管线(三态语义自 ADR-0030 迁移) =====\n\n /** 关闭稳态是否露出部分内容;空值与非空判断避免 `peek=\"\"` 被当作有效长度。 */\n private get _peeks(): boolean {\n return typeof this.peek === 'string' && this.peek.trim() !== ''\n }\n\n private _applyOpenSteadyState() {\n this._generation++\n this._clearExitTimer()\n const container = this._contentContainer()\n const track = this._contentTrack()\n if (container) container.hidden = false\n if (track) track.dataset.wuiPresence = 'open'\n this._clearInnerClamp()\n this._setInnerInert(false)\n }\n\n private _applyClosedSteadyState() {\n this._generation++\n this._clearExitTimer()\n const container = this._contentContainer()\n const track = this._contentTrack()\n if (track) delete track.dataset.wuiPresence\n this._clearInnerClamp()\n if (this.keepMounted || this._peeks) {\n if (container) container.hidden = false\n this._setInnerInert(true)\n return\n }\n this._setInnerInert(false)\n if (container) container.hidden = true\n }\n\n private _beginExpand() {\n this._generation++\n this._clearExitTimer()\n const container = this._contentContainer()\n const track = this._contentTrack()\n if (!container || !track) return\n\n const generation = this._generation\n // 中断关闭动画时 inner 已 inert:先恢复可交互,内容随展开重新可见。\n this._setInnerInert(false)\n // 从 display:none 进入时无先前计算样式可过渡:提交 0fr 起点后再翻转。\n container.hidden = false\n\n if (this._peeks) {\n const inner = this._contentInner()\n // 无过渡时长(reduced motion、jsdom)或无 inner 时不做测量,直接落展开稳态。\n if (!inner || getTransitionDuration(inner, 0) === 0) {\n this._applyOpenSteadyState()\n return\n }\n /*\n * peek 的裁剪长度是固定值,展开目标是内容自适应高度,两者无法由 CSS 插值,\n * 动画必须由两个显式长度驱动:起点是当前露出的长度,目标是内容完整尺寸。\n * 起点要在同任务内先写入并提交回流,否则过渡会退化成跳变(实测分帧写入\n * 反而完全不参与插值判定);目标读 inner 的 scroll 尺寸,不写探针样式。\n */\n const from = this._measureInnerSize(inner)\n const to = this._measureContentSize(inner)\n this._setInnerClamp(inner, `${from}px`)\n void this._measureInnerSize(inner)\n track.dataset.wuiPresence = 'open'\n this._setInnerClamp(inner, `${to}px`)\n this._awaitTransition(inner, generation, () => this._settle(true), [this._clampProperty()])\n return\n }\n\n void track.offsetWidth\n\n requestAnimationFrame(() => {\n if (generation !== this._generation || !this.open) return\n track.dataset.wuiPresence = 'open'\n this._awaitTransition(track, generation, () => this._settle(true))\n })\n }\n\n private _beginCollapse() {\n this._generation++\n this._clearExitTimer()\n const track = this._contentTrack()\n if (!track) return\n\n // 收起期间立即阻断交互,防止焦点落入正在消失的区域。\n this._setInnerInert(true)\n const generation = this._generation\n\n if (this._peeks) {\n const inner = this._contentInner()\n // 无过渡时长(reduced motion、jsdom)或无 inner 时不做测量,直接落裁剪稳态。\n if (!inner || getTransitionDuration(inner, 0) === 0) {\n this._applyClosedSteadyState()\n return\n }\n /*\n * 收起目标是 `peek` 长度本身:与内容尺寸的较小值由 CSS 稳态规则解析,\n * 动画只需把当前展开长度过渡到这个长度。起点同样要先写入并提交回流,\n * 顺序与 _beginExpand 一致。\n */\n const from = this._measureInnerSize(inner)\n this._setInnerClamp(inner, `${from}px`)\n void this._measureInnerSize(inner)\n track.dataset.wuiPresence = 'closing'\n this._setInnerClamp(inner, `${this.peek}`)\n this._awaitTransition(inner, generation, () => this._settle(false), [this._clampProperty()])\n return\n }\n\n track.dataset.wuiPresence = 'closing'\n this._awaitTransition(track, generation, () => this._settle(false))\n }\n\n // 关闭稳态:keep-mounted → 内容保留在 0fr 轨道内并 inert;peek → 保留在裁剪\n // 窗口内并 inert;默认 → 容器 hidden。\n private _settle(open: boolean) {\n this._clearExitTimer()\n const track = this._contentTrack()\n // peek 过渡以显式长度写入 inner:落稳态一律清除,交回 CSS 稳态规则(长度声明)。\n this._clearInnerClamp()\n if (open) {\n this._setInnerInert(false)\n return\n }\n // 落稳态必须清除 closing 瞬态标记:否则 track 永久保留 pointer-events:none\n // 与 exit 过渡配置(keep-mounted 分支同样清除,避免残留)。\n if (track) delete track.dataset.wuiPresence\n if (this.keepMounted || this._peeks) return\n const container = this._contentContainer()\n this._setInnerInert(false)\n if (container) container.hidden = true\n }\n\n // 等待动画属性过渡结束;时长为 0(reduced motion、jsdom)直接稳态,\n // transitionend 不触发时按时长 + 缓冲兜底。默认等待 grid 轨道过渡;peek 的\n // 过渡落在 inner 的裁剪长度上,由调用方传入对应属性。\n private _awaitTransition(\n animated: HTMLElement,\n generation: number,\n onDone: () => void,\n properties: readonly string[] = ['grid-template-rows', 'grid-template-columns']\n ) {\n const duration = getTransitionDuration(animated, 0)\n if (duration === 0) {\n if (generation === this._generation) onDone()\n return\n }\n\n let settled = false\n const finish = () => {\n animated.removeEventListener('transitionend', onTransitionEnd)\n if (this._exitTimer === timer) this._exitTimer = undefined\n clearTimeout(timer)\n // 过渡可能被属性匹配的后续动画触发(如中断重开):代际不符时静默退场。\n if (settled || generation !== this._generation) return\n settled = true\n onDone()\n }\n const timer = setTimeout(finish, duration + EXIT_FALLBACK_BUFFER)\n this._exitTimer = timer\n\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === animated && properties.includes(event.propertyName)) finish()\n }\n animated.addEventListener('transitionend', onTransitionEnd)\n }\n\n private _clearExitTimer() {\n if (this._exitTimer !== undefined) {\n clearTimeout(this._exitTimer)\n this._exitTimer = undefined\n }\n }\n\n // ===== peek 尺寸读写(裁剪长度落在 inner 上,轨道只负责 1fr 与裁剪窗口) =====\n\n /*\n * peek 长度经自定义属性下发给 shadow 样式规则,而不是直接写 inner 的裁剪长度:\n * 关闭稳态由 CSS 声明(长度与内容尺寸的较小值由 CSS 原生解析),动画写入的内联\n * 长度在其上覆盖,落稳态时清除即可回到声明值。\n */\n private _syncPeek() {\n const track = this._contentTrack()\n if (!track) return\n track.toggleAttribute('data-wui-peek', this._peeks)\n if (this._peeks) {\n track.style.setProperty('--wui-collapse-peek', this.peek ?? '')\n } else {\n track.style.removeProperty('--wui-collapse-peek')\n }\n }\n\n private _clampProperty(): 'max-height' | 'max-width' {\n return this.horizontal ? 'max-width' : 'max-height'\n }\n\n private _measureInnerSize(inner: HTMLElement): number {\n return this.horizontal ? inner.offsetWidth : inner.offsetHeight\n }\n\n /*\n * 内容在动画轴上的完整尺寸(px):裁剪只作用在 inner 的 max-height/max-width 上,\n * 被测内容的布局盒子仍是完整尺寸,故读 scroll 尺寸即可,不写任何样式——写样式\n * 会被 grid 过渡机制当作过渡起点读取,必须避开。\n */\n private _measureContentSize(inner: HTMLElement): number {\n return this.horizontal ? inner.scrollWidth : inner.scrollHeight\n }\n\n private _setInnerClamp(inner: HTMLElement, size: string) {\n inner.style.setProperty(this._clampProperty(), size)\n }\n\n private _clearInnerClamp() {\n const inner = this._contentInner()\n if (!inner) return\n inner.style.removeProperty('max-height')\n inner.style.removeProperty('max-width')\n }\n\n private _setInnerInert(inert: boolean) {\n this._contentInner()?.toggleAttribute('inert', inert)\n }\n\n private _contentInner(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>('.wui-collapse-inner') ?? null\n }\n\n private _contentContainer(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>('.wui-collapse-content') ?? null\n }\n\n private _contentTrack(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>('.wui-collapse-track') ?? null\n }\n\n override render() {\n // 三态由 data-wui-presence 驱动(open/closing),缺省即关闭稳态。\n const trackClass = {\n 'wui-collapse-track': true,\n 'is-horizontal': this.horizontal\n }\n\n return html`\n <div class=\"wui-collapse-trigger-wrapper\" @slotchange=${this._onTriggerSlotChange}><slot></slot></div>\n <div class=\"wui-collapse-content\">\n <div class=${classMap(trackClass)} id=${this._contentId}>\n <div class=\"wui-collapse-inner\">\n <slot name=\"content\"></slot>\n </div>\n </div>\n </div>\n `\n }\n\n declare readonly $events: {\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-collapse': WebUiCollapse\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/collapse/index.ts"],"sourcesContent":["import { html, LitElement, unsafeCSS } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\n\nimport glow from '@/classes/glow.css?inline'\nimport { UserChangeController } from '@/shared/events/user-change'\nimport { dispatchOpenChangeEvent } from '@/shared/open-state'\nimport { getTransitionDuration } from '@/shared/overlay/presence'\n\nimport style from './style.css?inline'\n\nconst EXIT_FALLBACK_BUFFER = 80\n\n/** peek 边缘渐隐的活动长度:关闭/收起态取由 peek 推导的长度,展开态归 0。 */\nconst PEEK_EDGE_ACTIVE = '--wui-collapse-peek-edge-active'\n\n/*\n * 注册成 `<length>` 才能被 transition 插值(未注册的自定义属性是离散值,只能瞬变)。\n *\n * 必须用 JS 的 `CSS.registerProperty` 而不是 CSS 里的 `@property`:实测后者写在\n * shadow root 的样式表里不产生注册(getComputedStyle 读打开态得到空串而非\n * initial-value),而自定义属性的注册本质上是 document 级的。\n * 注册失败(jsdom、旧浏览器、重复注册)时降级为离散过渡——渐变带长度瞬变,\n * 但位置百分比仍跟随裁剪边缘,行为依旧正确。\n *\n * `inherits` 必须是 true:晕染伪元素(style.css 的 ::after)读同一个值来调制模糊,\n * 继承为 false 时伪元素读到的是 initialValue 0px——mask 的各色标随之塌缩到 100%,\n * 模糊层静默消失且其余渲染一切照旧,只少一层效果。\n */\nfunction registerPeekEdgeActive() {\n // jsdom 与不支持的环境直接跳过;样式里的 var() fallback 保证声明仍然有效。\n if (typeof CSS === 'undefined' || typeof CSS.registerProperty !== 'function') return\n try {\n CSS.registerProperty({\n name: PEEK_EDGE_ACTIVE,\n syntax: '<length>',\n inherits: true,\n initialValue: '0px'\n })\n } catch {\n // 已注册过(HMR、多份副本)或定义冲突:保持现有注册即可。\n }\n}\n\nregisterPeekEdgeActive()\n\nlet collapseIdCounter = 0\n\n/**\n * 文档流内 collapse panel:trigger 经默认 slot 提供,内容经 `slot=\"content\"` 提供。\n *\n * trigger 语义完全来自 slot 进来的交互元素(原生 button / web-ui-button 等):\n * Enter/Space 激活走该元素的原生 click,不做 role=\"button\" 补齐;组件把\n * `aria-expanded` / `aria-controls` / `aria-disabled` 回写到首个 assigned\n * element(与 popover trigger 的既定回写模式一致)。wrapper 仅负责点击代理,\n * 不可聚焦,不承载 ARIA。\n *\n * 内容区在 shadow 内以 grid `0fr ↔ 1fr` track 过渡驱动高度/宽度动画(ADR-0030\n * 选型保留)。关闭稳态三态(消费者 light DOM 永不移动,hidden 全部命令式管理,\n * 避免渲染绑定在关闭动画起点抢先 display:none):\n * - 默认:content 容器 `hidden`(display:none,脱离渲染与可访问性树);\n * - `keep-mounted`:inner `inert`(保留在 0fr track 内,滚动位置与布局可测量);\n * - `peek`:inner `inert`,track 停在固定长度的裁剪窗口,只露出内容头部;\n * - 动画进行中:inner `inert` + track pointer-events 禁用,结束后进入对应稳态。\n *\n * `peek` 与展开态之间是固定长度与内容自适应高度的过渡,CSS 无法插值;这两个\n * 方向的动画改为读出像素后以显式长度写入 track,落稳态时清除内联值交回 CSS 规则。\n */\n@customElement('web-ui-collapse')\nexport class WebUiCollapse extends LitElement {\n static override styles = [unsafeCSS(glow), unsafeCSS(style)]\n\n /** 展开状态;严格受控,唯一状态源。 */\n @property({ type: Boolean, reflect: true }) open = false\n\n /** 禁用触发:点击忽略、aria-disabled 写入 trigger 元素;已展开内容保持现状。 */\n @property({ type: Boolean, reflect: true }) disabled = false\n\n /** 水平方向:true 时沿宽度展开,默认沿高度。 */\n @property({ type: Boolean, reflect: true }) horizontal = false\n\n /** 关闭稳态保持内容 `inert` 而非 `hidden`(保留滚动位置,可测量)。 */\n @property({ type: Boolean, reflect: true, attribute: 'keep-mounted' }) keepMounted = false\n\n /**\n * 关闭稳态露出的尺寸(CSS 长度,如 `120px`、`6rem`),沿动画轴生效:默认是高度,\n * `horizontal` 时为宽度;未设置时保持完全收起。\n *\n * 设置后关闭稳态语义等同 `keep-mounted`(内容留在 track 内、`inert` 阻断交互),\n * 只露出 `peek` 范围内的部分;内容本身不足 `peek` 时按内容实际尺寸收起。\n * 注意 `peek` 是固定长度与内容自适应高度之间的过渡:CSS 无法在两者之间插值,\n * 因此这两个方向的动画由本组件读出内容尺寸后以显式长度驱动(其余路径仍是\n * 零测量的 grid fr 过渡)。\n *\n * 露出区域末端自带一段边缘渐隐(提示下方还有内容),长度由 `peek` 按比例推导,\n * 无需也不接受调用方单独指定——见 style.css 中 `--wui-collapse-peek-edge-*`\n * 系列变量(比例、上限、末端颜色可用 CSS 覆盖,属于主题级调优而非组件 API)。\n */\n @property({ type: String, reflect: true }) peek: string | null = null\n\n @query('.wui-collapse-trigger-wrapper') private _triggerWrapper!: HTMLElement\n\n private _contentId = `wui-collapse-content-${++collapseIdCounter}`\n\n private readonly _userOpenChange = new UserChangeController()\n\n private _exitTimer?: ReturnType<typeof setTimeout>\n // 动画代际:每次管线启动自增,旧管线的 transitionend/兜底定时器/rAF 全部失效。\n private _generation = 0\n private _lastOpen?: boolean\n private _triggerAriaSnapshot?: {\n trigger: HTMLElement\n expanded: string | null\n controls: string | null\n disabled: string | null\n }\n\n override connectedCallback() {\n super.connectedCallback()\n // 点击监听与生命周期同寿(宿主移除即整体销毁),无需 disconnected 清理。\n this.addEventListener('click', this._onTriggerClick)\n // 断连可能打断动画管线(瞬态残留:presence='closing'、容器未 hidden)。\n // 首次连接不必处理(初始 render 走 _lastOpen===undefined 落稳态,请求多余\n // 渲染会触发「scheduled an update after update completed」告警);重连时\n // 重置同步状态并强制一轮 update,由首次同步分支重新落稳态、丢弃在途管线。\n if (this.hasUpdated) {\n this._generation++\n this._clearExitTimer()\n this._lastOpen = undefined\n this.requestUpdate()\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback()\n this._clearExitTimer()\n this._restoreTriggerAriaSnapshot()\n }\n\n protected override updated(changed: Map<string, unknown>) {\n // ARIA 回写不依赖 open 分支,任何渲染后都保持与宿主状态同步。\n this._syncTriggerAria()\n // peek 的稳态长度与动画写入共用 track 内联样式,先同步再落稳态,避免被稳态清除。\n this._syncPeek()\n\n // 首次同步(含 open 为默认值的场景,changed map 不含默认值属性):\n // 直接落到正确稳态,不播动画(popover 初始 open 同款)。\n if (this._lastOpen === undefined) {\n this._lastOpen = this.open\n if (this.open) this._applyOpenSteadyState()\n else this._applyClosedSteadyState()\n return\n }\n\n if ((changed.has('keepMounted') || changed.has('peek')) && !this.open) {\n // 运行态切换 keep-mounted / peek:关闭稳态需在 hidden / inert / 裁剪长度间重新落地。\n this._applyClosedSteadyState()\n }\n if (!changed.has('open') || this.open === this._lastOpen) return\n\n this._lastOpen = this.open\n if (this._userOpenChange.consume()) this._dispatchChange(this.open)\n if (this.open) this._beginExpand()\n else this._beginCollapse()\n }\n\n show() {\n if (this.open) return\n this.open = true\n }\n\n close() {\n if (!this.open) return\n this.open = false\n }\n\n toggle() {\n if (this.open) this.close()\n else this.show()\n }\n\n private _dispatchChange(open: boolean) {\n dispatchOpenChangeEvent(this, open)\n }\n\n /*\n * 点击代理:冒泡路径穿过 trigger wrapper 的 click 一律切换。语义由 slot 内\n * 的交互元素(原生 button / web-ui-button)提供;slot 放纯文本时无激活语义\n * (README 约定)。内容区与嵌套内层 collapse 的 click 不经过本 wrapper,天然隔离。\n */\n private _onTriggerClick = (event: MouseEvent) => {\n if (this.disabled) return\n if (!event.composedPath().includes(this._triggerWrapper)) return\n this._userOpenChange.mark()\n this.toggle()\n }\n\n /*\n * Trigger 元素取首个 assigned element(与 popover `_queryTrigger` 同款惰性查询,\n * 不依赖 slotchange——jsdom 不派发该事件,无法用状态缓存)。slot 为空时无回写目标。\n */\n private _queryTrigger(): HTMLElement | null {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('.wui-collapse-trigger-wrapper slot')\n const el = slot?.assignedElements()[0]\n return el instanceof HTMLElement ? el : null\n }\n\n /*\n * slot 内容增删不触发宿主响应式更新:显式请求一轮渲染,由 updated() 的\n * ARIA 回写覆盖晚到的 trigger 元素(slotchange 在 jsdom 不派发,无法监听)。\n */\n private readonly _onTriggerSlotChange = () => {\n this.requestUpdate()\n }\n\n private _restoreTriggerAriaSnapshot() {\n const snapshot = this._triggerAriaSnapshot\n if (!snapshot) return\n\n for (const [attribute, value] of Object.entries({\n 'aria-expanded': snapshot.expanded,\n 'aria-controls': snapshot.controls,\n 'aria-disabled': snapshot.disabled\n })) {\n if (value === null) snapshot.trigger.removeAttribute(attribute)\n else snapshot.trigger.setAttribute(attribute, value)\n }\n this._triggerAriaSnapshot = undefined\n }\n\n // ARIA 状态回写到 trigger 元素本身(wrapper 不可聚焦,AT 读不到)。\n private _syncTriggerAria() {\n const trigger = this._queryTrigger()\n if (this._triggerAriaSnapshot?.trigger !== trigger) {\n this._restoreTriggerAriaSnapshot()\n if (trigger) {\n this._triggerAriaSnapshot = {\n trigger,\n expanded: trigger.getAttribute('aria-expanded'),\n controls: trigger.getAttribute('aria-controls'),\n disabled: trigger.getAttribute('aria-disabled')\n }\n }\n }\n if (!trigger) return\n trigger.setAttribute('aria-expanded', String(this.open))\n trigger.setAttribute('aria-controls', this._contentId)\n if (this.disabled) trigger.setAttribute('aria-disabled', 'true')\n else trigger.removeAttribute('aria-disabled')\n }\n\n // ===== 内容区动画管线(三态语义自 ADR-0030 迁移) =====\n\n /** 关闭稳态是否露出部分内容;空值与非空判断避免 `peek=\"\"` 被当作有效长度。 */\n private get _peeks(): boolean {\n return typeof this.peek === 'string' && this.peek.trim() !== ''\n }\n\n private _applyOpenSteadyState() {\n this._generation++\n this._clearExitTimer()\n const container = this._contentContainer()\n const track = this._contentTrack()\n if (container) container.hidden = false\n if (track) track.dataset.wuiPresence = 'open'\n this._clearInnerClamp()\n this._setInnerInert(false)\n }\n\n private _applyClosedSteadyState() {\n this._generation++\n this._clearExitTimer()\n const container = this._contentContainer()\n const track = this._contentTrack()\n if (track) delete track.dataset.wuiPresence\n this._clearInnerClamp()\n if (this.keepMounted || this._peeks) {\n if (container) container.hidden = false\n this._setInnerInert(true)\n return\n }\n this._setInnerInert(false)\n if (container) container.hidden = true\n }\n\n private _beginExpand() {\n this._generation++\n this._clearExitTimer()\n const container = this._contentContainer()\n const track = this._contentTrack()\n if (!container || !track) return\n\n const generation = this._generation\n // 中断关闭动画时 inner 已 inert:先恢复可交互,内容随展开重新可见。\n this._setInnerInert(false)\n // 从 display:none 进入时无先前计算样式可过渡:提交 0fr 起点后再翻转。\n container.hidden = false\n\n if (this._peeks) {\n const inner = this._contentInner()\n // 无过渡时长(reduced motion、jsdom)或无 inner 时不做测量,直接落展开稳态。\n if (!inner || getTransitionDuration(inner, 0) === 0) {\n this._applyOpenSteadyState()\n return\n }\n /*\n * peek 的裁剪长度是固定值,展开目标是内容自适应高度,两者无法由 CSS 插值,\n * 动画必须由两个显式长度驱动:起点是当前露出的长度,目标是内容完整尺寸。\n * 起点要在同任务内先写入并提交回流,否则过渡会退化成跳变(实测分帧写入\n * 反而完全不参与插值判定);目标读 inner 的 scroll 尺寸,不写探针样式。\n */\n const from = this._measureInnerSize(inner)\n const to = this._measureContentSize(inner)\n this._setInnerClamp(inner, `${from}px`)\n void this._measureInnerSize(inner)\n track.dataset.wuiPresence = 'open'\n this._setInnerClamp(inner, `${to}px`)\n this._awaitTransition(inner, generation, () => this._settle(true), [this._clampProperty()])\n return\n }\n\n void track.offsetWidth\n\n requestAnimationFrame(() => {\n if (generation !== this._generation || !this.open) return\n track.dataset.wuiPresence = 'open'\n this._awaitTransition(track, generation, () => this._settle(true))\n })\n }\n\n private _beginCollapse() {\n this._generation++\n this._clearExitTimer()\n const track = this._contentTrack()\n if (!track) return\n\n // 收起期间立即阻断交互,防止焦点落入正在消失的区域。\n this._setInnerInert(true)\n const generation = this._generation\n\n if (this._peeks) {\n const inner = this._contentInner()\n // 无过渡时长(reduced motion、jsdom)或无 inner 时不做测量,直接落裁剪稳态。\n if (!inner || getTransitionDuration(inner, 0) === 0) {\n this._applyClosedSteadyState()\n return\n }\n /*\n * 收起目标是 `peek` 长度本身:与内容尺寸的较小值由 CSS 稳态规则解析,\n * 动画只需把当前展开长度过渡到这个长度。起点同样要先写入并提交回流,\n * 顺序与 _beginExpand 一致。\n */\n const from = this._measureInnerSize(inner)\n this._setInnerClamp(inner, `${from}px`)\n void this._measureInnerSize(inner)\n track.dataset.wuiPresence = 'closing'\n this._setInnerClamp(inner, `${this.peek}`)\n this._awaitTransition(inner, generation, () => this._settle(false), [this._clampProperty()])\n return\n }\n\n track.dataset.wuiPresence = 'closing'\n this._awaitTransition(track, generation, () => this._settle(false))\n }\n\n // 关闭稳态:keep-mounted → 内容保留在 0fr track 内并 inert;peek → 保留在裁剪\n // 窗口内并 inert;默认 → 容器 hidden。\n private _settle(open: boolean) {\n this._clearExitTimer()\n const track = this._contentTrack()\n // peek 过渡以显式长度写入 inner:落稳态一律清除,交回 CSS 稳态规则(长度声明)。\n this._clearInnerClamp()\n if (open) {\n this._setInnerInert(false)\n return\n }\n // 落稳态必须清除 closing 瞬态标记:否则 track 永久保留 pointer-events:none\n // 与 exit 过渡配置(keep-mounted 分支同样清除,避免残留)。\n if (track) delete track.dataset.wuiPresence\n if (this.keepMounted || this._peeks) return\n const container = this._contentContainer()\n this._setInnerInert(false)\n if (container) container.hidden = true\n }\n\n // 等待动画属性过渡结束;时长为 0(reduced motion、jsdom)直接稳态,\n // transitionend 不触发时按时长 + 缓冲兜底。默认等待 grid track 过渡;peek 的\n // 过渡落在 inner 的裁剪长度上,由调用方传入对应属性。\n private _awaitTransition(\n animated: HTMLElement,\n generation: number,\n onDone: () => void,\n properties: readonly string[] = ['grid-template-rows', 'grid-template-columns']\n ) {\n const duration = getTransitionDuration(animated, 0)\n if (duration === 0) {\n if (generation === this._generation) onDone()\n return\n }\n\n let settled = false\n const finish = () => {\n animated.removeEventListener('transitionend', onTransitionEnd)\n if (this._exitTimer === timer) this._exitTimer = undefined\n clearTimeout(timer)\n // 过渡可能被属性匹配的后续动画触发(如中断重开):代际不符时静默退场。\n if (settled || generation !== this._generation) return\n settled = true\n onDone()\n }\n const timer = setTimeout(finish, duration + EXIT_FALLBACK_BUFFER)\n this._exitTimer = timer\n\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === animated && properties.includes(event.propertyName)) finish()\n }\n animated.addEventListener('transitionend', onTransitionEnd)\n }\n\n private _clearExitTimer() {\n if (this._exitTimer !== undefined) {\n clearTimeout(this._exitTimer)\n this._exitTimer = undefined\n }\n }\n\n // ===== peek 尺寸读写(裁剪长度落在 inner 上,track 只负责 1fr 与裁剪窗口) =====\n\n /*\n * peek 长度经自定义属性下发给 shadow 样式规则,而不是直接写 inner 的裁剪长度:\n * 关闭稳态由 CSS 声明(长度与内容尺寸的较小值由 CSS 原生解析),动画写入的内联\n * 长度在其上覆盖,落稳态时清除即可回到声明值。\n */\n private _syncPeek() {\n const track = this._contentTrack()\n if (!track) return\n track.toggleAttribute('data-wui-peek', this._peeks)\n if (this._peeks) {\n track.style.setProperty('--wui-collapse-peek', this.peek ?? '')\n } else {\n track.style.removeProperty('--wui-collapse-peek')\n }\n }\n\n private _clampProperty(): 'max-height' | 'max-width' {\n return this.horizontal ? 'max-width' : 'max-height'\n }\n\n private _measureInnerSize(inner: HTMLElement): number {\n return this.horizontal ? inner.offsetWidth : inner.offsetHeight\n }\n\n /*\n * 内容在动画轴上的完整尺寸(px):裁剪只作用在 inner 的 max-height/max-width 上,\n * 被测内容的布局盒子仍是完整尺寸,故读 scroll 尺寸即可,不写任何样式——写样式\n * 会被 grid 过渡机制当作过渡起点读取,必须避开。\n */\n private _measureContentSize(inner: HTMLElement): number {\n return this.horizontal ? inner.scrollWidth : inner.scrollHeight\n }\n\n private _setInnerClamp(inner: HTMLElement, size: string) {\n inner.style.setProperty(this._clampProperty(), size)\n }\n\n private _clearInnerClamp() {\n const inner = this._contentInner()\n if (!inner) return\n inner.style.removeProperty('max-height')\n inner.style.removeProperty('max-width')\n }\n\n private _setInnerInert(inert: boolean) {\n this._contentInner()?.toggleAttribute('inert', inert)\n }\n\n private _contentInner(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>('.wui-collapse-inner') ?? null\n }\n\n private _contentContainer(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>('.wui-collapse-content') ?? null\n }\n\n private _contentTrack(): HTMLElement | null {\n return this.shadowRoot?.querySelector<HTMLElement>('.wui-collapse-track') ?? null\n }\n\n override render() {\n // 三态由 data-wui-presence 驱动(open/closing),缺省即关闭稳态。\n const trackClass = {\n 'wui-collapse-track': true,\n 'is-horizontal': this.horizontal\n }\n\n return html`\n <div class=\"wui-collapse-trigger-wrapper\" @slotchange=${this._onTriggerSlotChange}><slot></slot></div>\n <div class=\"wui-collapse-content\">\n <div class=${classMap(trackClass)} id=${this._contentId}>\n <div class=${classMap({ 'wui-collapse-inner': true, 'wui-glow': this._peeks })}>\n <slot name=\"content\"></slot>\n </div>\n </div>\n </div>\n `\n }\n\n declare readonly $events: {\n 'open-change': CustomEvent<{ open: boolean }>\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'web-ui-collapse': WebUiCollapse\n }\n}\n"],"mappings":"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"}