@ixfx/components 0.11.4 → 0.11.6

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 (113) hide show
  1. package/bundle/index.d.ts +451 -120
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +2267 -540
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.d.ts +1 -1
  6. package/dist/{ac-token-TCLAZeVg.d.ts → ac-token--_vCHXWw.d.ts} +2 -2
  7. package/dist/{ac-token-TCLAZeVg.d.ts.map → ac-token--_vCHXWw.d.ts.map} +1 -1
  8. package/dist/ac-token.d.ts +1 -1
  9. package/dist/{button-CTL45aBl.d.ts → button-BYuf72aR.d.ts} +2 -2
  10. package/dist/{button-CTL45aBl.d.ts.map → button-BYuf72aR.d.ts.map} +1 -1
  11. package/dist/button.d.ts +1 -1
  12. package/dist/colour-picker.d.ts +1 -1
  13. package/dist/crumbs.d.ts +3 -3
  14. package/dist/crumbs.js +1 -1
  15. package/dist/{data-grid-CfiaBqTA.d.ts → data-grid-C6EjCe5O.d.ts} +48 -6
  16. package/dist/data-grid-C6EjCe5O.d.ts.map +1 -0
  17. package/dist/data-grid.d.ts +3 -3
  18. package/dist/data-grid.js +67 -3
  19. package/dist/data-grid.js.map +1 -1
  20. package/dist/{detail-list-DxQZkK-C.d.ts → detail-list-CmdCxddo.d.ts} +22 -5
  21. package/dist/detail-list-CmdCxddo.d.ts.map +1 -0
  22. package/dist/detail-list.d.ts +3 -3
  23. package/dist/detail-list.js +67 -4
  24. package/dist/detail-list.js.map +1 -1
  25. package/dist/{grid-list-k89JpiNy.js → grid-list-3fGhdaFA.js} +92 -7
  26. package/dist/grid-list-3fGhdaFA.js.map +1 -0
  27. package/dist/{grid-list-ChgYpUUq.d.ts → grid-list-D6AfWfwn.d.ts} +27 -4
  28. package/dist/grid-list-D6AfWfwn.d.ts.map +1 -0
  29. package/dist/grid-list.d.ts +2 -2
  30. package/dist/grid-list.js +1 -1
  31. package/dist/{grouped-item-lister-Bhyo-dkH.d.ts → grouped-item-lister-DETte0Dh.d.ts} +2 -2
  32. package/dist/{grouped-item-lister-Bhyo-dkH.d.ts.map → grouped-item-lister-DETte0Dh.d.ts.map} +1 -1
  33. package/dist/grouped-item-lister.d.ts +1 -1
  34. package/dist/{icon-DR_3rSyZ.d.ts → icon-CDGprSdE.d.ts} +2 -2
  35. package/dist/icon-CDGprSdE.d.ts.map +1 -0
  36. package/dist/icons.d.ts +2 -2
  37. package/dist/incr-search.d.ts +1 -1
  38. package/dist/{index-CHbuPyLL.d.ts → index-CMsmZ6Or.d.ts} +4 -4
  39. package/dist/{index-CHbuPyLL.d.ts.map → index-CMsmZ6Or.d.ts.map} +1 -1
  40. package/dist/{index-garxxqgV.d.ts → index-CYndvTWH.d.ts} +2 -2
  41. package/dist/{index-garxxqgV.d.ts.map → index-CYndvTWH.d.ts.map} +1 -1
  42. package/dist/{index-BUB5SICW.d.ts → index-CoqtMSd9.d.ts} +2 -2
  43. package/dist/{index-BUB5SICW.d.ts.map → index-CoqtMSd9.d.ts.map} +1 -1
  44. package/dist/{index-CDllxjVG.d.ts → index-DyTSt9OK.d.ts} +4 -4
  45. package/dist/{index-CDllxjVG.d.ts.map → index-DyTSt9OK.d.ts.map} +1 -1
  46. package/dist/{index-CJ5fshD3.d.ts → index-UvnoZUAo.d.ts} +2 -2
  47. package/dist/{index-CJ5fshD3.d.ts.map → index-UvnoZUAo.d.ts.map} +1 -1
  48. package/dist/{index-BOUaDIW-.d.ts → index-tq6f8007.d.ts} +2 -2
  49. package/dist/{index-BOUaDIW-.d.ts.map → index-tq6f8007.d.ts.map} +1 -1
  50. package/dist/index.d.ts +337 -140
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +2038 -646
  53. package/dist/index.js.map +1 -1
  54. package/dist/item-appearance-BjcMyauw.js +31 -0
  55. package/dist/item-appearance-BjcMyauw.js.map +1 -0
  56. package/dist/{labelled-input-base-Dp_9KP0G.d.ts → labelled-input-base-DiTme1JO.d.ts} +2 -2
  57. package/dist/{labelled-input-base-Dp_9KP0G.d.ts.map → labelled-input-base-DiTme1JO.d.ts.map} +1 -1
  58. package/dist/labelled-radial-input.d.ts +2 -2
  59. package/dist/labelled-radial-input.d.ts.map +1 -1
  60. package/dist/labelled-range-input.d.ts +1 -1
  61. package/dist/labelled-slider-input.d.ts +1 -1
  62. package/dist/{list-native-drag-controller-B9reY4uM.d.ts → list-native-drag-controller-CllsHLxw.d.ts} +2 -2
  63. package/dist/{list-native-drag-controller-B9reY4uM.d.ts.map → list-native-drag-controller-CllsHLxw.d.ts.map} +1 -1
  64. package/dist/{menu-BHT6HRND.js → menu-CsBUyUuS.js} +2 -2
  65. package/dist/{menu-BHT6HRND.js.map → menu-CsBUyUuS.js.map} +1 -1
  66. package/dist/{menu-item-DlxAb0Xr.d.ts → menu-item-BbgdcwBX.d.ts} +11 -2
  67. package/dist/menu-item-BbgdcwBX.d.ts.map +1 -0
  68. package/dist/{menu-item-JcpHCyF0.js → menu-item-CfndBGO8.js} +38 -3
  69. package/dist/menu-item-CfndBGO8.js.map +1 -0
  70. package/dist/menu.d.ts +2 -2
  71. package/dist/menu.js +2 -2
  72. package/dist/miller.d.ts +3 -3
  73. package/dist/miller.d.ts.map +1 -1
  74. package/dist/miller.js +18 -2
  75. package/dist/miller.js.map +1 -1
  76. package/dist/panel.d.ts +1 -1
  77. package/dist/{split-layout-C5SYbDrq.d.ts → split-layout-JK3xWVX2.d.ts} +2 -2
  78. package/dist/{split-layout-C5SYbDrq.d.ts.map → split-layout-JK3xWVX2.d.ts.map} +1 -1
  79. package/dist/split-layout.d.ts +1 -1
  80. package/dist/{tab-list-v8mKX7Fu.d.ts → tab-list-pqfKaVAE.d.ts} +2 -2
  81. package/dist/{tab-list-v8mKX7Fu.d.ts.map → tab-list-pqfKaVAE.d.ts.map} +1 -1
  82. package/dist/tabs.d.ts +1 -1
  83. package/dist/{titlebar-B5zSTZnF.d.ts → titlebar-Tqu-VvMU.d.ts} +2 -2
  84. package/dist/{titlebar-B5zSTZnF.d.ts.map → titlebar-Tqu-VvMU.d.ts.map} +1 -1
  85. package/dist/titlebar.d.ts +1 -1
  86. package/dist/{tree-component-CMGeqyjZ.d.ts → tree-component-DukLqesg.d.ts} +2 -2
  87. package/dist/{tree-component-CMGeqyjZ.d.ts.map → tree-component-DukLqesg.d.ts.map} +1 -1
  88. package/dist/tree.d.ts +4 -4
  89. package/dist/{types-3Jfcaxvo.d.ts → types-D-kYF16b.d.ts} +21 -1
  90. package/dist/types-D-kYF16b.d.ts.map +1 -0
  91. package/dist/{vertical-list-R25WqAVO.d.ts → vertical-list-DTp-UIUE.d.ts} +26 -3
  92. package/dist/vertical-list-DTp-UIUE.d.ts.map +1 -0
  93. package/dist/vertical-list.d.ts +2 -2
  94. package/dist/vertical-list.js +53 -4
  95. package/dist/vertical-list.js.map +1 -1
  96. package/docs-user/data-grid.md +51 -1
  97. package/docs-user/detail-list.md +46 -0
  98. package/docs-user/grid-list.md +49 -2
  99. package/docs-user/hyperbolic-tree.md +98 -18
  100. package/docs-user/index.json +2 -2
  101. package/docs-user/menu.md +30 -9
  102. package/docs-user/miller.md +52 -7
  103. package/docs-user/vertical-list.md +63 -0
  104. package/package.json +1 -1
  105. package/dist/data-grid-CfiaBqTA.d.ts.map +0 -1
  106. package/dist/detail-list-DxQZkK-C.d.ts.map +0 -1
  107. package/dist/grid-list-ChgYpUUq.d.ts.map +0 -1
  108. package/dist/grid-list-k89JpiNy.js.map +0 -1
  109. package/dist/icon-DR_3rSyZ.d.ts.map +0 -1
  110. package/dist/menu-item-DlxAb0Xr.d.ts.map +0 -1
  111. package/dist/menu-item-JcpHCyF0.js.map +0 -1
  112. package/dist/types-3Jfcaxvo.d.ts.map +0 -1
  113. package/dist/vertical-list-R25WqAVO.d.ts.map +0 -1
@@ -0,0 +1,31 @@
1
+ //#region src/common/item-appearance.ts
2
+ /**
3
+ * Shared helpers for the list components' per-item appearance hooks — the
4
+ * per-item icon colour / text colour / badge that miller-list, detail-list,
5
+ * grid-list, data-grid and vertical-list all accept.
6
+ *
7
+ * Every component takes these three features in its own idiom (plain fields
8
+ * on a `TreeItem`, a property-name lookup, an adapter function, a nominated
9
+ * column) but they all agree on what "not supplied" means, and on never
10
+ * emitting an empty slot for an absent value.
11
+ */
12
+ /**
13
+ * Whether a per-item appearance value counts as "not supplied". `false` and
14
+ * `''` are included so a consumer can clear a feature without rebuilding the
15
+ * collection — e.g. `badge: flags && tagChip(flags.colour)`.
16
+ */
17
+ function appearanceAbsent(value) {
18
+ return value === void 0 || value === null || value === false || value === ``;
19
+ }
20
+ /**
21
+ * A usable CSS colour from a per-item value, or `undefined`. Non-strings and
22
+ * empty strings are ignored rather than stringified, so a stray number or
23
+ * `0` never lands in a `style` attribute.
24
+ */
25
+ function appearanceColor(value) {
26
+ return typeof value === `string` && value.length > 0 ? value : void 0;
27
+ }
28
+ //#endregion
29
+ export { appearanceColor as n, appearanceAbsent as t };
30
+
31
+ //# sourceMappingURL=item-appearance-BjcMyauw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item-appearance-BjcMyauw.js","names":[],"sources":["../src/common/item-appearance.ts"],"sourcesContent":["/**\n * Shared helpers for the list components' per-item appearance hooks — the\n * per-item icon colour / text colour / badge that miller-list, detail-list,\n * grid-list, data-grid and vertical-list all accept.\n *\n * Every component takes these three features in its own idiom (plain fields\n * on a `TreeItem`, a property-name lookup, an adapter function, a nominated\n * column) but they all agree on what \"not supplied\" means, and on never\n * emitting an empty slot for an absent value.\n */\n\n/**\n * Whether a per-item appearance value counts as \"not supplied\". `false` and\n * `''` are included so a consumer can clear a feature without rebuilding the\n * collection — e.g. `badge: flags && tagChip(flags.colour)`.\n */\nexport function appearanceAbsent(value: unknown): boolean {\n return value === undefined || value === null || value === false || value === ``;\n}\n\n/**\n * A usable CSS colour from a per-item value, or `undefined`. Non-strings and\n * empty strings are ignored rather than stringified, so a stray number or\n * `0` never lands in a `style` attribute.\n */\nexport function appearanceColor(value: unknown): string | undefined {\n return typeof value === `string` && value.length > 0 ? value : undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,SAAgB,iBAAiB,OAAyB;CACxD,OAAO,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,SAAS,UAAU;AAC/E;;;;;;AAOA,SAAgB,gBAAgB,OAAoC;CAClE,OAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ,KAAA;AACjE"}
@@ -33,9 +33,9 @@ declare abstract class LabelledInputBase extends LitElement {
33
33
  value: number;
34
34
  }>) => void;
35
35
  protected _syncValue(v: number): void;
36
- protected _renderEditableNumber(): import("lit").TemplateResult<1> | typeof nothing;
36
+ protected _renderEditableNumber(): typeof nothing | import("lit").TemplateResult<1>;
37
37
  updated(changedProperties: Map<string, unknown>): void;
38
38
  }
39
39
  //#endregion
40
40
  export { LabelledInputBase as t };
41
- //# sourceMappingURL=labelled-input-base-Dp_9KP0G.d.ts.map
41
+ //# sourceMappingURL=labelled-input-base-DiTme1JO.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"labelled-input-base-Dp_9KP0G.d.ts","names":[],"sources":["../src/mixins/labelled-input-base.ts"],"mappings":";;uBAIsB,0BAA0B;EAClC;EAEgB;EACA;EACA;EACA;EACA;EAC+B;EAEI;EACC;EAEjB;YAE5B;YACA;YACA,cAAc;UAEzB;UACA;oBAEU;MAEd,cAAc;MAId,UAAU,SAAS;gBAIT;EAIL;EAMA;YAMC,cAAc,SAAS;YAcvB,sBAAuB,GAAG;IAAc;;YAYxC,qBAAsB,GAAG;IAAc;;YAcvC,qBAAsB,GAAG;IAAc;;YAavC,WAAW;YAYX,uCAAqB,2BAAA;EAuBtB,QAAQ,mBAAmB"}
1
+ {"version":3,"file":"labelled-input-base-DiTme1JO.d.ts","names":[],"sources":["../src/mixins/labelled-input-base.ts"],"mappings":";;uBAIsB,0BAA0B;EAClC;EAEgB;EACA;EACA;EACA;EACA;EAC+B;EAEI;EACC;EAEjB;YAE5B;YACA;YACA,cAAc;UAEzB;UACA;oBAEU;MAEd,cAAc;MAId,UAAU,SAAS;gBAIT;EAIL;EAMA;YAMC,cAAc,SAAS;YAcvB,sBAAuB,GAAG;IAAc;;YAYxC,qBAAsB,GAAG;IAAc;;YAcvC,qBAAsB,GAAG;IAAc;;YAavC,WAAW;YAYX,gCAAqB,wBAAA;EAuBtB,QAAQ,mBAAmB"}
@@ -1,4 +1,4 @@
1
- import { t as LabelledInputBase } from "./labelled-input-base-Dp_9KP0G.js";
1
+ import { t as LabelledInputBase } from "./labelled-input-base-DiTme1JO.js";
2
2
  import { i as MarkerStyle, l as ValueMode } from "./radial-input-DU6t2hYO.js";
3
3
  import { CSSResultGroup, nothing } from "lit";
4
4
  //#region src/labelled-radial-input/labelled-radial-input.d.ts
@@ -19,7 +19,7 @@ declare class LabelledRadialInput extends LabelledInputBase {
19
19
  private _isWide;
20
20
  private _getEffectivePrecision;
21
21
  protected _handleResize(entries: ResizeObserverEntry[]): void;
22
- protected _renderEditableNumber(): import("lit").TemplateResult<1> | typeof nothing;
22
+ protected _renderEditableNumber(): typeof nothing | import("lit").TemplateResult<1>;
23
23
  render(): import("lit").TemplateResult<1>;
24
24
  private _getTooltipValue;
25
25
  static styles: CSSResultGroup;
@@ -1 +1 @@
1
- {"version":3,"file":"labelled-radial-input.d.ts","names":[],"sources":["../src/labelled-radial-input/labelled-radial-input.ts"],"mappings":";;;;cA0Da,4BAA4B;WAC9B;EAGA;EACA;EAEmB;EACA;EAC2B,aAAa;EACvC;EACwB,WAAW;EACnC;EACA;EAEoC;;EAGpC;UAEZ;UAIT;YAeW,cAAc,SAAS;YAMvB,uCAAqB,2BAAA;EA0B/B,wBAAM;UA6BP;SAYD,QAAQ;;QA0ET;YACI;IACR,8BAA8B"}
1
+ {"version":3,"file":"labelled-radial-input.d.ts","names":[],"sources":["../src/labelled-radial-input/labelled-radial-input.ts"],"mappings":";;;;cA0Da,4BAA4B;WAC9B;EAGA;EACA;EAEmB;EACA;EAC2B,aAAa;EACvC;EACwB,WAAW;EACnC;EACA;EAEoC;;EAGpC;UAEZ;UAIT;YAeW,cAAc,SAAS;YAMvB,gCAAqB,wBAAA;EA0B/B,wBAAM;UA6BP;SAYD,QAAQ;;QA0ET;YACI;IACR,8BAA8B"}
@@ -1,2 +1,2 @@
1
- import { t as LabelledRangeInput } from "./index-BUB5SICW.js";
1
+ import { t as LabelledRangeInput } from "./index-CoqtMSd9.js";
2
2
  export { LabelledRangeInput };
@@ -1,2 +1,2 @@
1
- import { t as LabelledSliderInput } from "./index-CJ5fshD3.js";
1
+ import { t as LabelledSliderInput } from "./index-UvnoZUAo.js";
2
2
  export { LabelledSliderInput };
@@ -1,4 +1,4 @@
1
- import { F as ListDragPreviewSourceResolver, I as ListDragSource, L as ListNativeDragStartDetail, N as ListDragPreviewContext, P as ListDragPreviewRenderer, j as ListDragEntry } from "./tree-component-CMGeqyjZ.js";
1
+ import { F as ListDragPreviewSourceResolver, I as ListDragSource, L as ListNativeDragStartDetail, N as ListDragPreviewContext, P as ListDragPreviewRenderer, j as ListDragEntry } from "./tree-component-DukLqesg.js";
2
2
  import { ReactiveController, ReactiveControllerHost } from "lit";
3
3
  //#region src/interaction/list-native-drag-controller.d.ts
4
4
  type ListNativeDragControllerConfig<T> = {
@@ -66,4 +66,4 @@ declare class ListNativeDragController<T> implements ReactiveController {
66
66
  }
67
67
  //#endregion
68
68
  export { ListNativeDragControllerConfig as n, ListNativeDragController as t };
69
- //# sourceMappingURL=list-native-drag-controller-B9reY4uM.d.ts.map
69
+ //# sourceMappingURL=list-native-drag-controller-CllsHLxw.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"list-native-drag-controller-B9reY4uM.d.ts","names":[],"sources":["../src/interaction/list-native-drag-controller.ts"],"mappings":";;;KAYY,+BAA+B;WAChC,QAAQ;;EAEjB;;EAEA,oBAAoB,QAAQ;;;;;;EAM5B,mBAAmB;IAAwB,QAAQ,cAAc;IAAI,UAAU,MAAM,cAAc;;EACnG,kBAAkB,uBAAuB;EACzC,mBAAmB,wBAAwB;EAC3C,qCAAqC,8BAA8B;;EAEnE,WAAW,QAAQ,0BAA0B;;;;;;EAM7C,qBAAqB,cAAc,cAAc,QAAQ,0BAA0B;;EAEnF,iBAAiB,iBAAiB;;EAElC;;EAEA;;;;;;;EAOA,eAAe,OAAO;;KAGnB,WAAW,yBAAyB;;;;;;;;;;cAW5B,yBAAyB,cAAc;;EAUtC,YAAA,MAAM,UAAU,QAAQ,+BAA+B;MAM/D;;MAKA;;EASJ;EAQA;;EAYA;EAIA"}
1
+ {"version":3,"file":"list-native-drag-controller-CllsHLxw.d.ts","names":[],"sources":["../src/interaction/list-native-drag-controller.ts"],"mappings":";;;KAYY,+BAA+B;WAChC,QAAQ;;EAEjB;;EAEA,oBAAoB,QAAQ;;;;;;EAM5B,mBAAmB;IAAwB,QAAQ,cAAc;IAAI,UAAU,MAAM,cAAc;;EACnG,kBAAkB,uBAAuB;EACzC,mBAAmB,wBAAwB;EAC3C,qCAAqC,8BAA8B;;EAEnE,WAAW,QAAQ,0BAA0B;;;;;;EAM7C,qBAAqB,cAAc,cAAc,QAAQ,0BAA0B;;EAEnF,iBAAiB,iBAAiB;;EAElC;;EAEA;;;;;;;EAOA,eAAe,OAAO;;KAGnB,WAAW,yBAAyB;;;;;;;;;;cAW5B,yBAAyB,cAAc;;EAUtC,YAAA,MAAM,UAAU,QAAQ,+BAA+B;MAM/D;;MAKA;;EASJ;EAQA;;EAYA;EAIA"}
@@ -4,7 +4,7 @@ import { t as themeFallbacks } from "./fallbacks-DQ_5OsmR.js";
4
4
  import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
5
5
  import "./icon-1gpwtPx8.js";
6
6
  import "./interaction-BskmlA9t.js";
7
- import { n as MenuTrigger, r as MenuContainer, t as MenuItem } from "./menu-item-JcpHCyF0.js";
7
+ import { n as MenuTrigger, r as MenuContainer, t as MenuItem } from "./menu-item-CfndBGO8.js";
8
8
  import { LitElement, css, html, nothing } from "lit";
9
9
  import { property, query, state } from "lit/decorators.js";
10
10
  //#region src/menu/menu-bar.ts
@@ -823,4 +823,4 @@ var menu_exports = /* @__PURE__ */ __exportAll({
823
823
  //#endregion
824
824
  export { menuFromTreeToElements as a, MenuSubTrigger as c, MenuBar as d, menuFromTree as i, MenuCommandController as l, MenuRadioGroup as n, MenuHeader as o, MenuRadioItem as r, MenuSeparator as s, menu_exports as t, MenuCheckItem as u };
825
825
 
826
- //# sourceMappingURL=menu-BHT6HRND.js.map
826
+ //# sourceMappingURL=menu-CsBUyUuS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menu-BHT6HRND.js","names":["customElement","customElement","customElement","customElement","customElement","customElement","customElement"],"sources":["../src/menu/menu-bar.ts","../src/menu/menu-check-item.ts","../src/menu/menu-command-controller.ts","../src/menu/menu-sub-trigger.ts","../src/menu/menu-separator.ts","../src/menu/menu-header.ts","../src/menu/menu-from-tree.ts","../src/menu/menu-radio-item.ts","../src/menu/menu-radio-group.ts","../src/menu/index.ts"],"sourcesContent":["import type { MenuTrigger } from './menu-trigger.js';\nimport { css, html, LitElement } from 'lit';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport './menu-trigger.js';\n\n@customElement(`ixfx-menu-bar`)\nexport class MenuBar extends LitElement {\n private _openTrigger: MenuTrigger | null = null;\n private _inputMode: `keyboard` | `mouse` = `mouse`;\n\n connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener(`menu-trigger-open`, this._handleTriggerOpen as EventListener);\n this.addEventListener(`menu-trigger-close`, this._handleTriggerClose as EventListener);\n this.addEventListener(`focusin`, this._handleFocusIn as EventListener);\n this.addEventListener(`keydown`, this._handleKeydown);\n this.addEventListener(`pointermove`, this._handlePointerMove);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`menu-trigger-open`, this._handleTriggerOpen as EventListener);\n this.removeEventListener(`menu-trigger-close`, this._handleTriggerClose as EventListener);\n this.removeEventListener(`focusin`, this._handleFocusIn as EventListener);\n this.removeEventListener(`keydown`, this._handleKeydown);\n this.removeEventListener(`pointermove`, this._handlePointerMove);\n }\n\n private _setInputMode(mode: `keyboard` | `mouse`): void {\n if (this._inputMode === mode)\n return;\n this._inputMode = mode;\n this.setAttribute(`data-input-mode`, mode);\n }\n\n private _handlePointerMove = (): void => {\n this._setInputMode(`mouse`);\n };\n\n private _getTriggers(): MenuTrigger[] {\n return [...this.children].filter(\n el => el.tagName === `IXFX-MENU-TRIGGER`,\n ) as MenuTrigger[];\n }\n\n private _handleTriggerOpen = (e: Event): void => {\n this._openTrigger = e.target as MenuTrigger;\n };\n\n private _handleTriggerClose = (e: Event): void => {\n if (e.target === this._openTrigger) {\n this._openTrigger = null;\n }\n };\n\n // When focus moves to a trigger button while another menu is open, switch menus.\n // focusin is composed, so e.target is retargeted to the ixfx-menu-trigger host.\n private _handleFocusIn = (e: FocusEvent): void => {\n const triggers = this._getTriggers();\n const trigger = triggers.find(t => t === e.target);\n if (!trigger || !this._openTrigger || trigger === this._openTrigger)\n return;\n this._openTrigger.closeMenu();\n trigger.openMenu();\n };\n\n private _handleKeydown = (e: KeyboardEvent): void => {\n if (e.key !== `ArrowLeft` && e.key !== `ArrowRight`)\n return;\n\n const triggers = this._getTriggers();\n if (triggers.length === 0)\n return;\n\n // When a menu is open, navigate from the open trigger.\n // When no menu is open, navigate from the focused trigger button\n // (e.target is retargeted to ixfx-menu-trigger when focus is on its inner button).\n const current = this._openTrigger ?? triggers.find(t => t === e.target);\n if (!current)\n return;\n\n const idx = triggers.indexOf(current);\n if (idx === -1)\n return;\n\n e.preventDefault();\n e.stopPropagation();\n this._setInputMode(`keyboard`);\n\n const dir = e.key === `ArrowRight` ? 1 : -1;\n const next = triggers[(idx + dir + triggers.length) % triggers.length];\n\n if (this._openTrigger) {\n this._openTrigger.closeMenu();\n next.openMenu();\n } else {\n next.focusTrigger();\n }\n };\n\n static styles = css`\n :host {\n display: flex;\n align-items: center;\n }\n\n /* Keyboard mode: suppress hover highlight on trigger buttons */\n :host([data-input-mode=\"keyboard\"]) {\n --_trigger-hover-bg: transparent;\n --_trigger-hover-opacity: 0.6;\n }\n `;\n\n render() {\n return html`<slot role=\"menubar\"></slot>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-bar': MenuBar;\n }\n}\n","import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { tickledItemStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type MenuCheckItemCommandDetail = {\n readonly command: string;\n readonly checked: boolean;\n readonly args: string;\n};\n\nexport type MenuCheckItemCommandEvent = CustomEvent<MenuCheckItemCommandDetail>;\n\n@customElement(`ixfx-menu-check-item`)\nexport class MenuCheckItem extends LitElement {\n @property({ type: String }) command = ``;\n @property({ type: String, attribute: `command-args` }) commandArgs = ``;\n @property({ type: String }) label = ``;\n @property({ type: Boolean }) checked = false;\n @property({ type: Boolean }) disabled = false;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n @property({ attribute: false }) registry?: CommandRegistry<unknown>;\n @property({ attribute: false }) keyboardManager?: KeyboardManager;\n\n private handleClick(): void {\n if (this.disabled)\n return;\n\n this.checked = !this.checked;\n this.dispatchEvent(new CustomEvent<MenuCheckItemCommandDetail>(`command`, {\n detail: { command: this.command, checked: this.checked, args: this.commandArgs },\n bubbles: true,\n composed: true,\n }));\n }\n\n private _resolvedLabel(): string {\n if (this.label)\n return this.label;\n if (this.registry && this.command) {\n return this.registry.get(this.command)?.label ?? ``;\n }\n return ``;\n }\n\n private _resolvedIcon(): string | null {\n if (this.iconName)\n return this.iconName;\n if (this.registry && this.command) {\n return this.registry.get(this.command)?.icon ?? null;\n }\n return null;\n }\n\n willUpdate(changedProperties: Map<string, unknown>): void {\n super.willUpdate(changedProperties);\n const resolvedIcon = this._resolvedIcon();\n if (resolvedIcon && !this.iconName) {\n this.setAttribute(`data-icon-section`, ``);\n } else if (!resolvedIcon && !this.iconName) {\n this.removeAttribute(`data-icon-section`);\n }\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n }\n\n private _getShortcut(): string | null {\n if (!this.keyboardManager || !this.command)\n return null;\n const bindings = (this.keyboardManager as any).getBindings?.() ?? [];\n const binding = bindings.find((b: any) => b.commandId === this.command);\n if (!binding)\n return null;\n const mods = Array.from(binding.modifiers ?? [], (m: string) =>\n ({ ctrl: `⌃`, shift: `⇧`, alt: `⌥`, meta: `⌘` })[m] ?? m);\n const key = binding.key?.length === 1 ? binding.key.toUpperCase() : binding.key;\n return [...mods, key].join(``);\n }\n\n static override styles = [themeFallbacks, tickledItemStyles, css`\n :host {\n display: block;\n }\n\n .item {\n display: flex;\n padding: 6px var(--space-m);\n font-size: var(--text-m);\n }\n\n :host(:focus) {\n outline: none;\n }\n\n .item.disabled {\n opacity: var(--disabled-opacity);\n cursor: default;\n }\n\n .item.disabled:hover {\n background: transparent;\n }\n\n .check {\n width: 1em;\n margin-left: var(--space-xs);\n display: inline-flex;\n align-items: center;\n color: var(--accent);\n }\n\n .icon-slot {\n width: 0;\n overflow: hidden;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n :host([icon-name]) .icon-slot,\n :host([data-icon-section]) .icon-slot {\n width: 1em;\n height: 1em;\n margin-right: var(--space-s);\n }\n\n .label {\n flex: 1;\n }\n\n .shortcut {\n margin-left: var(--space-l);\n color: var(--surface-muted-text);\n font-size: var(--text-s);\n }\n `];\n\n render() {\n const shortcut = this._getShortcut();\n const resolvedIcon = this._resolvedIcon();\n return html`\n <div \n class=\"item ${this.disabled ? `disabled` : ``}\"\n @click=${this.handleClick}\n tabindex=\"${this.disabled ? -1 : 0}\"\n role=\"menuitemcheckbox\"\n aria-checked=\"${this.checked}\"\n >\n <span class=\"check\">${this.checked ? html`<ixfx-icon name=\"check\" size=\"14\"></ixfx-icon>` : ``}</span>\n <span class=\"icon-slot\">${resolvedIcon ? html`<ixfx-icon name=\"${resolvedIcon}\"></ixfx-icon>` : null}</span>\n <span class=\"label\">${this._resolvedLabel()}</span>\n ${shortcut ? html`<span class=\"shortcut\">${shortcut}</span>` : null}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-check-item': MenuCheckItem;\n }\n}\n","import type { CommandRegistry } from '@clinth/ui-commands';\n\nexport class MenuCommandController {\n private registry: CommandRegistry<unknown>;\n private target: EventTarget;\n private boundHandler: (e: Event) => void;\n\n constructor(options: { registry: CommandRegistry<unknown>; target?: EventTarget }) {\n this.registry = options.registry;\n this.target = options.target ?? document;\n this.boundHandler = this.handleCommand.bind(this);\n }\n\n start(): void {\n this.target.addEventListener(`command`, this.boundHandler);\n }\n\n stop(): void {\n this.target.removeEventListener(`command`, this.boundHandler);\n }\n\n private handleCommand(e: Event): void {\n const target = e.target as any;\n const command = target?.command;\n if (!command)\n return;\n\n const args = target?.commandArgs ?? ``;\n this.registry.invoke(command, { args });\n }\n}\n","import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { tickledItemStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\n@customElement(`ixfx-menu-sub-trigger`)\nexport class MenuSubTrigger extends LitElement {\n @property({ type: String }) command = ``;\n @property({ type: String, attribute: `command-args` }) commandArgs = ``;\n @property({ type: String }) label = ``;\n @property({ type: Boolean }) disabled = false;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n @property({ attribute: false }) registry?: CommandRegistry<unknown>;\n @property({ attribute: false }) keyboardManager?: KeyboardManager;\n\n @state() private _hasSubmenu = false;\n @query(`slot[name=\"submenu\"]`) private _slot!: HTMLSlotElement;\n @query(`.submenu-popover`) private _submenuPopover!: HTMLElement;\n @query(`.item`) private _itemEl!: HTMLElement;\n\n private static _count = 0;\n private _anchorName = `--mst-${MenuSubTrigger._count++}`;\n private _hoverTimeout: number | null = null;\n private _hideTimeout: number | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener(`keydown`, this._handleKeydown);\n }\n\n firstUpdated(): void {\n this.style.setProperty(`--anchor-name`, this._anchorName);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`keydown`, this._handleKeydown);\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n }\n if (this._hideTimeout) {\n clearTimeout(this._hideTimeout);\n }\n }\n\n private _propagateContext(): void {\n const items = this._slot?.assignedElements({ flatten: true }) ?? [];\n for (const el of items) {\n if (`registry` in el)\n (el as any).registry = this.registry;\n if (`keyboardManager` in el)\n (el as any).keyboardManager = this.keyboardManager;\n }\n }\n\n override updated(changedProperties: Map<string, unknown>): void {\n if (changedProperties.has(`registry`) || changedProperties.has(`keyboardManager`)) {\n this._propagateContext();\n }\n }\n\n willUpdate(changedProperties: Map<string, unknown>): void {\n super.willUpdate(changedProperties);\n const resolvedIcon = this._resolvedIcon();\n if (resolvedIcon && !this.iconName) {\n this.setAttribute(`data-icon-section`, ``);\n } else if (!resolvedIcon && !this.iconName) {\n this.removeAttribute(`data-icon-section`);\n }\n }\n\n private _resolvedIcon(): string | null {\n if (this.iconName)\n return this.iconName;\n if (this.registry && this.command) {\n return this.registry.get(this.command)?.icon ?? null;\n }\n return null;\n }\n\n private _handleSlotChange(): void {\n this._hasSubmenu = this._slot?.assignedElements().length > 0;\n this._propagateContext();\n }\n\n private _showSubmenu(): void {\n if (!this._submenuPopover?.popover)\n return;\n try {\n (this._submenuPopover as any).showPopover();\n } catch { /* ignore */ }\n }\n\n private _hideSubmenu(): void {\n if (!this._submenuPopover?.popover)\n return;\n try {\n (this._submenuPopover as any).hidePopover();\n } catch { /* ignore */ }\n }\n\n private _cancelHide(): void {\n if (this._hideTimeout) {\n clearTimeout(this._hideTimeout);\n this._hideTimeout = null;\n }\n }\n\n private _scheduleHide(): void {\n this._cancelHide();\n this._hideTimeout = window.setTimeout(() => {\n this._hideSubmenu();\n this._hideTimeout = null;\n }, 100);\n }\n\n private _handleMouseEnter(): void {\n if (this.disabled || !this._hasSubmenu)\n return;\n this._cancelHide();\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n }\n this._hoverTimeout = window.setTimeout(() => {\n this._showSubmenu();\n }, 150);\n }\n\n private _handleMouseLeave(): void {\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n this._hoverTimeout = null;\n }\n this._scheduleHide();\n }\n\n private _handleSubmenuMouseEnter(): void {\n this._cancelHide();\n }\n\n private _handleSubmenuMouseLeave(): void {\n this._scheduleHide();\n }\n\n private _handleClick(): void {\n if (this.disabled || !this.command)\n return;\n\n this.dispatchEvent(new CustomEvent(`command`, {\n detail: { command: this.command, args: this.commandArgs },\n bubbles: true,\n composed: true,\n }));\n }\n\n private _handleKeydown(e: KeyboardEvent): void {\n if (this.disabled)\n return;\n\n switch (e.key) {\n case `ArrowRight`:\n case `Enter`:\n case ` `:\n e.preventDefault();\n e.stopPropagation();\n if (this._hasSubmenu) {\n this._showSubmenu();\n requestAnimationFrame(() => {\n const container = this._slot?.assignedElements({ flatten: true })\n .find(el => el.tagName === `IXFX-MENU-CONTAINER`) as (HTMLElement & { focusFirst: () => void }) | undefined;\n container?.focusFirst();\n });\n }\n break;\n case `ArrowLeft`:\n e.preventDefault();\n e.stopPropagation();\n this._hideSubmenu();\n this._itemEl?.focus();\n break;\n case `Escape`:\n e.preventDefault();\n e.stopPropagation();\n this._hideSubmenu();\n break;\n }\n }\n\n static override styles = [themeFallbacks, tickledItemStyles, css`\n :host {\n display: block;\n }\n\n .item {\n anchor-name: var(--anchor-name);\n display: flex;\n padding: 6px var(--space-m);\n font-size: var(--text-m);\n }\n\n .submenu-popover {\n position: fixed;\n position-anchor: var(--anchor-name);\n inset: auto;\n top: anchor(top);\n left: anchor(right);\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n /* UA stylesheet sets overflow:auto on [popover], which clips the box-shadow\n of the inner ixfx-menu-container child. Override to let the shadow render. */\n overflow: visible;\n position-try-fallbacks: flip-inline, flip-block, flip-block flip-inline;\n }\n\n :host(:focus) {\n outline: none;\n }\n\n .item.disabled {\n opacity: var(--disabled-opacity);\n cursor: default;\n }\n\n .item.disabled:hover {\n background: transparent;\n }\n\n .icon-slot {\n width: 0;\n overflow: hidden;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n :host([icon-name]) .icon-slot,\n :host([data-icon-section]) .icon-slot {\n width: 1em;\n height: 1em;\n margin-right: var(--space-s);\n }\n\n .label {\n flex: 1;\n }\n\n .arrow {\n color: var(--surface-muted-text);\n margin-left: var(--space-m);\n }\n `];\n\n render() {\n const resolvedIcon = this._resolvedIcon();\n return html`\n <div\n class=\"item ${this.disabled ? `disabled` : ``}\"\n @click=${this._handleClick}\n @mouseenter=${this._handleMouseEnter}\n @mouseleave=${this._handleMouseLeave}\n tabindex=\"${this.disabled ? -1 : 0}\"\n role=\"menuitem\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n <span class=\"icon-slot\">${resolvedIcon ? html`<ixfx-icon name=\"${resolvedIcon}\"></ixfx-icon>` : null}</span>\n <span class=\"label\"><slot></slot>${this.label}</span>\n <span class=\"arrow\">${this._hasSubmenu ? html`<ixfx-icon name=\"chevron-right\"></ixfx-icon>` : nothing}</span>\n </div>\n <div class=\"submenu-popover\" popover=\"auto\"\n @mouseenter=${this._handleSubmenuMouseEnter}\n @mouseleave=${this._handleSubmenuMouseLeave}\n >\n <slot name=\"submenu\" @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-sub-trigger': MenuSubTrigger;\n }\n}\n","import { css, html, LitElement } from 'lit';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\n@customElement(`ixfx-menu-separator`)\nexport class MenuSeparator extends LitElement {\n static styles = [themeFallbacks, css`\n :host {\n display: block;\n margin: var(--space-xs) 0;\n }\n\n .separator {\n height: 1px;\n background: var(--surface-4);\n }\n `];\n\n render() {\n return html`<div class=\"separator\"></div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-separator': MenuSeparator;\n }\n}\n","import { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\n@customElement(`ixfx-menu-header`)\nexport class MenuHeader extends LitElement {\n @property({ type: String }) label = ``;\n\n static styles = [themeFallbacks, css`\n :host {\n display: block;\n padding: 6px var(--space-m) var(--space-xs);\n font-size: var(--text-s);\n font-weight: var(--font-weight-bold);\n text-transform: uppercase;\n color: var(--surface-muted-text);\n letter-spacing: 0.5px;\n }\n `];\n\n render() {\n return html`<div>${this.label}</div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-header': MenuHeader;\n }\n}\n","import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport type { TemplateResult } from 'lit';\nimport type { TreeNode } from '../tree/types.js';\nimport type { MenuTriggerCommandDetail } from './menu-trigger.js';\nimport { html, nothing } from 'lit';\nimport './menu-container.js';\nimport './menu-item.js';\nimport './menu-sub-trigger.js';\nimport './menu-separator.js';\nimport './menu-header.js';\n\nexport type MenuFromTreeOptions = {\n onCommand?: (detail: MenuTriggerCommandDetail) => void;\n registry?: CommandRegistry<unknown>;\n keyboardManager?: KeyboardManager;\n};\n\nfunction isLeaf(node: TreeNode): boolean {\n return node.children === undefined || node.children.length === 0;\n}\n\nexport function menuFromTree(\n nodes: TreeNode[],\n options: MenuFromTreeOptions = {},\n): TemplateResult {\n const { onCommand, registry, keyboardManager } = options;\n\n return html`${nodes.map((node) => {\n const label = node.item.label;\n\n if (label === `-`) {\n return html`<ixfx-menu-separator></ixfx-menu-separator>`;\n }\n\n if (label.startsWith(`# `)) {\n return html`<ixfx-menu-header label=\"${label.slice(2)}\"></ixfx-menu-header>`;\n }\n\n if (!isLeaf(node)) {\n const submenu = menuFromTree(node.children!, options);\n return html`\n <ixfx-menu-sub-trigger label=\"${label}\">\n <ixfx-menu-container\n slot=\"submenu\"\n .registry=${registry ?? nothing}\n .keyboardManager=${keyboardManager ?? nothing}\n >${submenu}</ixfx-menu-container>\n </ixfx-menu-sub-trigger>\n `;\n }\n\n return html`\n <ixfx-menu-item\n command=\"${node.item.key}\"\n label=\"${label}\"\n icon-name=\"${node.item.icon ?? nothing}\"\n @command=${onCommand ? (e: CustomEvent) => onCommand(e.detail) : nothing}\n ></ixfx-menu-item>\n `;\n })}`;\n}\n\nfunction buildMenuItemEl(\n node: TreeNode,\n options: MenuFromTreeOptions,\n): HTMLElement {\n const { onCommand, registry } = options;\n const label = node.item.label;\n\n const el = document.createElement(`ixfx-menu-item`);\n el.setAttribute(`command`, node.item.key);\n el.setAttribute(`label`, label);\n if (node.item.icon) {\n el.setAttribute(`icon-name`, node.item.icon);\n }\n if (onCommand) {\n el.addEventListener(`command`, e => onCommand((e as CustomEvent).detail));\n }\n if (registry) {\n (el as any).registry = registry;\n }\n return el;\n}\n\nfunction buildMenuSeparatorEl(): HTMLElement {\n return document.createElement(`ixfx-menu-separator`);\n}\n\nfunction buildMenuHeaderEl(label: string): HTMLElement {\n const el = document.createElement(`ixfx-menu-header`);\n el.setAttribute(`label`, label);\n return el;\n}\n\nfunction buildMenuSubTriggerEl(\n node: TreeNode,\n options: MenuFromTreeOptions,\n): HTMLElement {\n const { registry, keyboardManager } = options;\n\n const el = document.createElement(`ixfx-menu-sub-trigger`);\n el.setAttribute(`label`, node.item.label);\n if (registry)\n (el as any).registry = registry;\n if (keyboardManager)\n (el as any).keyboardManager = keyboardManager;\n\n const container = document.createElement(`ixfx-menu-container`);\n container.setAttribute(`slot`, `submenu`);\n if (registry)\n (container as any).registry = registry;\n if (keyboardManager)\n (container as any).keyboardManager = keyboardManager;\n\n const childEls = menuFromTreeToElements(node.children!, options);\n for (const child of childEls) {\n container.appendChild(child);\n }\n\n el.appendChild(container);\n return el;\n}\n\nexport function menuFromTreeToElements(\n nodes: TreeNode[],\n options: MenuFromTreeOptions = {},\n): HTMLElement[] {\n return nodes.map((node) => {\n const label = node.item.label;\n\n if (label === `-`) {\n return buildMenuSeparatorEl();\n }\n\n if (label.startsWith(`# `)) {\n return buildMenuHeaderEl(label.slice(2));\n }\n\n if (!isLeaf(node)) {\n return buildMenuSubTriggerEl(node, options);\n }\n\n return buildMenuItemEl(node, options);\n });\n}\n","import { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { tickledItemStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type MenuRadioItemSelectDetail = {\n readonly value: string;\n};\n\nexport type MenuRadioItemSelectEvent = CustomEvent<MenuRadioItemSelectDetail>;\n\n@customElement(`ixfx-menu-radio-item`)\nexport class MenuRadioItem extends LitElement {\n @property({ type: String }) value = ``;\n @property({ type: String }) label = ``;\n @property({ type: Boolean }) disabled = false;\n @property({ type: String }) groupValue = ``;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n\n private handleClick(): void {\n if (this.disabled)\n return;\n\n this.dispatchEvent(new CustomEvent<MenuRadioItemSelectDetail>(`radio-select`, {\n detail: { value: this.value },\n bubbles: true,\n composed: true,\n }));\n }\n\n static override styles = [themeFallbacks, tickledItemStyles, css`\n :host {\n display: block;\n }\n\n .item {\n display: flex;\n padding: 6px var(--space-m);\n font-size: var(--text-m);\n }\n\n :host(:focus) {\n outline: none;\n }\n\n .item.disabled {\n opacity: var(--disabled-opacity);\n cursor: default;\n }\n\n .item.disabled:hover {\n background: transparent;\n }\n\n .radio {\n width: 1em;\n margin-left: var(--space-xs);\n font-size: var(--text-m);\n color: var(--accent);\n }\n\n .icon-slot {\n width: 0;\n overflow: hidden;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n :host([icon-name]) .icon-slot,\n :host([data-icon-section]) .icon-slot {\n width: 1em;\n height: 1em;\n margin-right: var(--space-s);\n }\n\n .label {\n flex: 1;\n }\n `];\n\n render() {\n const isSelected = this.groupValue === this.value;\n\n return html`\n <div \n class=\"item ${this.disabled ? `disabled` : ``}\"\n @click=${this.handleClick}\n tabindex=\"${this.disabled ? -1 : 0}\"\n role=\"menuitemradio\"\n aria-checked=\"${isSelected}\"\n >\n <span class=\"radio\">${isSelected ? `●` : ``}</span>\n <span class=\"icon-slot\">${this.iconName ? html`<ixfx-icon name=\"${this.iconName}\"></ixfx-icon>` : null}</span>\n <span class=\"label\">${this.label}</span>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-radio-item': MenuRadioItem;\n }\n}\n","import { css, html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport './menu-radio-item.js';\n\nexport type MenuRadioGroupChangeDetail = {\n readonly name: string;\n readonly value: string;\n};\n\nexport type MenuRadioGroupChangeEvent = CustomEvent<MenuRadioGroupChangeDetail>;\n\n@customElement(`ixfx-menu-radio-group`)\nexport class MenuRadioGroup extends LitElement {\n @property({ type: String }) name = ``;\n @property({ type: String }) value = ``;\n\n @state() private slottedElements: Element[] = [];\n\n private handleSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this.slottedElements = slot.assignedElements();\n this.updateSlottedValues();\n }\n\n private updateSlottedValues(): void {\n for (const el of this.slottedElements) {\n (el as any).groupValue = this.value;\n }\n }\n\n private handleRadioSelect(e: CustomEvent): void {\n this.value = e.detail.value;\n this.dispatchEvent(new CustomEvent<MenuRadioGroupChangeDetail>(`radio-change`, {\n detail: {\n name: this.name,\n value: this.value,\n },\n bubbles: true,\n composed: true,\n }));\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n if (changedProperties.has(`value`)) {\n this.updateSlottedValues();\n }\n }\n\n static styles = css`\n :host {\n display: block;\n }\n\n ::slotted(menu-radio-item) {\n display: block;\n }\n `;\n\n render() {\n return html`\n <slot @slotchange=${this.handleSlotChange} @radio-select=${this.handleRadioSelect}></slot>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-radio-group': MenuRadioGroup;\n }\n}\n","export { MenuBar } from './menu-bar.js';\nexport { MenuCheckItem } from './menu-check-item.js';\nexport { MenuCommandController } from './menu-command-controller.js';\nexport { MenuContainer } from './menu-container.js';\nexport { menuFromTree, menuFromTreeToElements } from './menu-from-tree.js';\nexport type { MenuFromTreeOptions } from './menu-from-tree.js';\nexport { MenuHeader } from './menu-header.js';\nexport { MenuItem } from './menu-item.js';\nexport { MenuRadioGroup } from './menu-radio-group.js';\nexport { MenuRadioItem } from './menu-radio-item.js';\nexport { MenuSeparator } from './menu-separator.js';\nexport { MenuSubTrigger } from './menu-sub-trigger.js';\nexport { MenuTrigger } from './menu-trigger.js';\n"],"mappings":"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"}
1
+ {"version":3,"file":"menu-CsBUyUuS.js","names":["customElement","customElement","customElement","customElement","customElement","customElement","customElement"],"sources":["../src/menu/menu-bar.ts","../src/menu/menu-check-item.ts","../src/menu/menu-command-controller.ts","../src/menu/menu-sub-trigger.ts","../src/menu/menu-separator.ts","../src/menu/menu-header.ts","../src/menu/menu-from-tree.ts","../src/menu/menu-radio-item.ts","../src/menu/menu-radio-group.ts","../src/menu/index.ts"],"sourcesContent":["import type { MenuTrigger } from './menu-trigger.js';\nimport { css, html, LitElement } from 'lit';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport './menu-trigger.js';\n\n@customElement(`ixfx-menu-bar`)\nexport class MenuBar extends LitElement {\n private _openTrigger: MenuTrigger | null = null;\n private _inputMode: `keyboard` | `mouse` = `mouse`;\n\n connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener(`menu-trigger-open`, this._handleTriggerOpen as EventListener);\n this.addEventListener(`menu-trigger-close`, this._handleTriggerClose as EventListener);\n this.addEventListener(`focusin`, this._handleFocusIn as EventListener);\n this.addEventListener(`keydown`, this._handleKeydown);\n this.addEventListener(`pointermove`, this._handlePointerMove);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`menu-trigger-open`, this._handleTriggerOpen as EventListener);\n this.removeEventListener(`menu-trigger-close`, this._handleTriggerClose as EventListener);\n this.removeEventListener(`focusin`, this._handleFocusIn as EventListener);\n this.removeEventListener(`keydown`, this._handleKeydown);\n this.removeEventListener(`pointermove`, this._handlePointerMove);\n }\n\n private _setInputMode(mode: `keyboard` | `mouse`): void {\n if (this._inputMode === mode)\n return;\n this._inputMode = mode;\n this.setAttribute(`data-input-mode`, mode);\n }\n\n private _handlePointerMove = (): void => {\n this._setInputMode(`mouse`);\n };\n\n private _getTriggers(): MenuTrigger[] {\n return [...this.children].filter(\n el => el.tagName === `IXFX-MENU-TRIGGER`,\n ) as MenuTrigger[];\n }\n\n private _handleTriggerOpen = (e: Event): void => {\n this._openTrigger = e.target as MenuTrigger;\n };\n\n private _handleTriggerClose = (e: Event): void => {\n if (e.target === this._openTrigger) {\n this._openTrigger = null;\n }\n };\n\n // When focus moves to a trigger button while another menu is open, switch menus.\n // focusin is composed, so e.target is retargeted to the ixfx-menu-trigger host.\n private _handleFocusIn = (e: FocusEvent): void => {\n const triggers = this._getTriggers();\n const trigger = triggers.find(t => t === e.target);\n if (!trigger || !this._openTrigger || trigger === this._openTrigger)\n return;\n this._openTrigger.closeMenu();\n trigger.openMenu();\n };\n\n private _handleKeydown = (e: KeyboardEvent): void => {\n if (e.key !== `ArrowLeft` && e.key !== `ArrowRight`)\n return;\n\n const triggers = this._getTriggers();\n if (triggers.length === 0)\n return;\n\n // When a menu is open, navigate from the open trigger.\n // When no menu is open, navigate from the focused trigger button\n // (e.target is retargeted to ixfx-menu-trigger when focus is on its inner button).\n const current = this._openTrigger ?? triggers.find(t => t === e.target);\n if (!current)\n return;\n\n const idx = triggers.indexOf(current);\n if (idx === -1)\n return;\n\n e.preventDefault();\n e.stopPropagation();\n this._setInputMode(`keyboard`);\n\n const dir = e.key === `ArrowRight` ? 1 : -1;\n const next = triggers[(idx + dir + triggers.length) % triggers.length];\n\n if (this._openTrigger) {\n this._openTrigger.closeMenu();\n next.openMenu();\n } else {\n next.focusTrigger();\n }\n };\n\n static styles = css`\n :host {\n display: flex;\n align-items: center;\n }\n\n /* Keyboard mode: suppress hover highlight on trigger buttons */\n :host([data-input-mode=\"keyboard\"]) {\n --_trigger-hover-bg: transparent;\n --_trigger-hover-opacity: 0.6;\n }\n `;\n\n render() {\n return html`<slot role=\"menubar\"></slot>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-bar': MenuBar;\n }\n}\n","import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { tickledItemStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type MenuCheckItemCommandDetail = {\n readonly command: string;\n readonly checked: boolean;\n readonly args: string;\n};\n\nexport type MenuCheckItemCommandEvent = CustomEvent<MenuCheckItemCommandDetail>;\n\n@customElement(`ixfx-menu-check-item`)\nexport class MenuCheckItem extends LitElement {\n @property({ type: String }) command = ``;\n @property({ type: String, attribute: `command-args` }) commandArgs = ``;\n @property({ type: String }) label = ``;\n @property({ type: Boolean }) checked = false;\n @property({ type: Boolean }) disabled = false;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n @property({ attribute: false }) registry?: CommandRegistry<unknown>;\n @property({ attribute: false }) keyboardManager?: KeyboardManager;\n\n private handleClick(): void {\n if (this.disabled)\n return;\n\n this.checked = !this.checked;\n this.dispatchEvent(new CustomEvent<MenuCheckItemCommandDetail>(`command`, {\n detail: { command: this.command, checked: this.checked, args: this.commandArgs },\n bubbles: true,\n composed: true,\n }));\n }\n\n private _resolvedLabel(): string {\n if (this.label)\n return this.label;\n if (this.registry && this.command) {\n return this.registry.get(this.command)?.label ?? ``;\n }\n return ``;\n }\n\n private _resolvedIcon(): string | null {\n if (this.iconName)\n return this.iconName;\n if (this.registry && this.command) {\n return this.registry.get(this.command)?.icon ?? null;\n }\n return null;\n }\n\n willUpdate(changedProperties: Map<string, unknown>): void {\n super.willUpdate(changedProperties);\n const resolvedIcon = this._resolvedIcon();\n if (resolvedIcon && !this.iconName) {\n this.setAttribute(`data-icon-section`, ``);\n } else if (!resolvedIcon && !this.iconName) {\n this.removeAttribute(`data-icon-section`);\n }\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n }\n\n private _getShortcut(): string | null {\n if (!this.keyboardManager || !this.command)\n return null;\n const bindings = (this.keyboardManager as any).getBindings?.() ?? [];\n const binding = bindings.find((b: any) => b.commandId === this.command);\n if (!binding)\n return null;\n const mods = Array.from(binding.modifiers ?? [], (m: string) =>\n ({ ctrl: `⌃`, shift: `⇧`, alt: `⌥`, meta: `⌘` })[m] ?? m);\n const key = binding.key?.length === 1 ? binding.key.toUpperCase() : binding.key;\n return [...mods, key].join(``);\n }\n\n static override styles = [themeFallbacks, tickledItemStyles, css`\n :host {\n display: block;\n }\n\n .item {\n display: flex;\n padding: 6px var(--space-m);\n font-size: var(--text-m);\n }\n\n :host(:focus) {\n outline: none;\n }\n\n .item.disabled {\n opacity: var(--disabled-opacity);\n cursor: default;\n }\n\n .item.disabled:hover {\n background: transparent;\n }\n\n .check {\n width: 1em;\n margin-left: var(--space-xs);\n display: inline-flex;\n align-items: center;\n color: var(--accent);\n }\n\n .icon-slot {\n width: 0;\n overflow: hidden;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n :host([icon-name]) .icon-slot,\n :host([data-icon-section]) .icon-slot {\n width: 1em;\n height: 1em;\n margin-right: var(--space-s);\n }\n\n .label {\n flex: 1;\n }\n\n .shortcut {\n margin-left: var(--space-l);\n color: var(--surface-muted-text);\n font-size: var(--text-s);\n }\n `];\n\n render() {\n const shortcut = this._getShortcut();\n const resolvedIcon = this._resolvedIcon();\n return html`\n <div \n class=\"item ${this.disabled ? `disabled` : ``}\"\n @click=${this.handleClick}\n tabindex=\"${this.disabled ? -1 : 0}\"\n role=\"menuitemcheckbox\"\n aria-checked=\"${this.checked}\"\n >\n <span class=\"check\">${this.checked ? html`<ixfx-icon name=\"check\" size=\"14\"></ixfx-icon>` : ``}</span>\n <span class=\"icon-slot\">${resolvedIcon ? html`<ixfx-icon name=\"${resolvedIcon}\"></ixfx-icon>` : null}</span>\n <span class=\"label\">${this._resolvedLabel()}</span>\n ${shortcut ? html`<span class=\"shortcut\">${shortcut}</span>` : null}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-check-item': MenuCheckItem;\n }\n}\n","import type { CommandRegistry } from '@clinth/ui-commands';\n\nexport class MenuCommandController {\n private registry: CommandRegistry<unknown>;\n private target: EventTarget;\n private boundHandler: (e: Event) => void;\n\n constructor(options: { registry: CommandRegistry<unknown>; target?: EventTarget }) {\n this.registry = options.registry;\n this.target = options.target ?? document;\n this.boundHandler = this.handleCommand.bind(this);\n }\n\n start(): void {\n this.target.addEventListener(`command`, this.boundHandler);\n }\n\n stop(): void {\n this.target.removeEventListener(`command`, this.boundHandler);\n }\n\n private handleCommand(e: Event): void {\n const target = e.target as any;\n const command = target?.command;\n if (!command)\n return;\n\n const args = target?.commandArgs ?? ``;\n this.registry.invoke(command, { args });\n }\n}\n","import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { tickledItemStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\n@customElement(`ixfx-menu-sub-trigger`)\nexport class MenuSubTrigger extends LitElement {\n @property({ type: String }) command = ``;\n @property({ type: String, attribute: `command-args` }) commandArgs = ``;\n @property({ type: String }) label = ``;\n @property({ type: Boolean }) disabled = false;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n @property({ attribute: false }) registry?: CommandRegistry<unknown>;\n @property({ attribute: false }) keyboardManager?: KeyboardManager;\n\n @state() private _hasSubmenu = false;\n @query(`slot[name=\"submenu\"]`) private _slot!: HTMLSlotElement;\n @query(`.submenu-popover`) private _submenuPopover!: HTMLElement;\n @query(`.item`) private _itemEl!: HTMLElement;\n\n private static _count = 0;\n private _anchorName = `--mst-${MenuSubTrigger._count++}`;\n private _hoverTimeout: number | null = null;\n private _hideTimeout: number | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n this.addEventListener(`keydown`, this._handleKeydown);\n }\n\n firstUpdated(): void {\n this.style.setProperty(`--anchor-name`, this._anchorName);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener(`keydown`, this._handleKeydown);\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n }\n if (this._hideTimeout) {\n clearTimeout(this._hideTimeout);\n }\n }\n\n private _propagateContext(): void {\n const items = this._slot?.assignedElements({ flatten: true }) ?? [];\n for (const el of items) {\n if (`registry` in el)\n (el as any).registry = this.registry;\n if (`keyboardManager` in el)\n (el as any).keyboardManager = this.keyboardManager;\n }\n }\n\n override updated(changedProperties: Map<string, unknown>): void {\n if (changedProperties.has(`registry`) || changedProperties.has(`keyboardManager`)) {\n this._propagateContext();\n }\n }\n\n willUpdate(changedProperties: Map<string, unknown>): void {\n super.willUpdate(changedProperties);\n const resolvedIcon = this._resolvedIcon();\n if (resolvedIcon && !this.iconName) {\n this.setAttribute(`data-icon-section`, ``);\n } else if (!resolvedIcon && !this.iconName) {\n this.removeAttribute(`data-icon-section`);\n }\n }\n\n private _resolvedIcon(): string | null {\n if (this.iconName)\n return this.iconName;\n if (this.registry && this.command) {\n return this.registry.get(this.command)?.icon ?? null;\n }\n return null;\n }\n\n private _handleSlotChange(): void {\n this._hasSubmenu = this._slot?.assignedElements().length > 0;\n this._propagateContext();\n }\n\n private _showSubmenu(): void {\n if (!this._submenuPopover?.popover)\n return;\n try {\n (this._submenuPopover as any).showPopover();\n } catch { /* ignore */ }\n }\n\n private _hideSubmenu(): void {\n if (!this._submenuPopover?.popover)\n return;\n try {\n (this._submenuPopover as any).hidePopover();\n } catch { /* ignore */ }\n }\n\n private _cancelHide(): void {\n if (this._hideTimeout) {\n clearTimeout(this._hideTimeout);\n this._hideTimeout = null;\n }\n }\n\n private _scheduleHide(): void {\n this._cancelHide();\n this._hideTimeout = window.setTimeout(() => {\n this._hideSubmenu();\n this._hideTimeout = null;\n }, 100);\n }\n\n private _handleMouseEnter(): void {\n if (this.disabled || !this._hasSubmenu)\n return;\n this._cancelHide();\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n }\n this._hoverTimeout = window.setTimeout(() => {\n this._showSubmenu();\n }, 150);\n }\n\n private _handleMouseLeave(): void {\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n this._hoverTimeout = null;\n }\n this._scheduleHide();\n }\n\n private _handleSubmenuMouseEnter(): void {\n this._cancelHide();\n }\n\n private _handleSubmenuMouseLeave(): void {\n this._scheduleHide();\n }\n\n private _handleClick(): void {\n if (this.disabled || !this.command)\n return;\n\n this.dispatchEvent(new CustomEvent(`command`, {\n detail: { command: this.command, args: this.commandArgs },\n bubbles: true,\n composed: true,\n }));\n }\n\n private _handleKeydown(e: KeyboardEvent): void {\n if (this.disabled)\n return;\n\n switch (e.key) {\n case `ArrowRight`:\n case `Enter`:\n case ` `:\n e.preventDefault();\n e.stopPropagation();\n if (this._hasSubmenu) {\n this._showSubmenu();\n requestAnimationFrame(() => {\n const container = this._slot?.assignedElements({ flatten: true })\n .find(el => el.tagName === `IXFX-MENU-CONTAINER`) as (HTMLElement & { focusFirst: () => void }) | undefined;\n container?.focusFirst();\n });\n }\n break;\n case `ArrowLeft`:\n e.preventDefault();\n e.stopPropagation();\n this._hideSubmenu();\n this._itemEl?.focus();\n break;\n case `Escape`:\n e.preventDefault();\n e.stopPropagation();\n this._hideSubmenu();\n break;\n }\n }\n\n static override styles = [themeFallbacks, tickledItemStyles, css`\n :host {\n display: block;\n }\n\n .item {\n anchor-name: var(--anchor-name);\n display: flex;\n padding: 6px var(--space-m);\n font-size: var(--text-m);\n }\n\n .submenu-popover {\n position: fixed;\n position-anchor: var(--anchor-name);\n inset: auto;\n top: anchor(top);\n left: anchor(right);\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n /* UA stylesheet sets overflow:auto on [popover], which clips the box-shadow\n of the inner ixfx-menu-container child. Override to let the shadow render. */\n overflow: visible;\n position-try-fallbacks: flip-inline, flip-block, flip-block flip-inline;\n }\n\n :host(:focus) {\n outline: none;\n }\n\n .item.disabled {\n opacity: var(--disabled-opacity);\n cursor: default;\n }\n\n .item.disabled:hover {\n background: transparent;\n }\n\n .icon-slot {\n width: 0;\n overflow: hidden;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n :host([icon-name]) .icon-slot,\n :host([data-icon-section]) .icon-slot {\n width: 1em;\n height: 1em;\n margin-right: var(--space-s);\n }\n\n .label {\n flex: 1;\n }\n\n .arrow {\n color: var(--surface-muted-text);\n margin-left: var(--space-m);\n }\n `];\n\n render() {\n const resolvedIcon = this._resolvedIcon();\n return html`\n <div\n class=\"item ${this.disabled ? `disabled` : ``}\"\n @click=${this._handleClick}\n @mouseenter=${this._handleMouseEnter}\n @mouseleave=${this._handleMouseLeave}\n tabindex=\"${this.disabled ? -1 : 0}\"\n role=\"menuitem\"\n aria-haspopup=\"true\"\n aria-expanded=\"false\"\n >\n <span class=\"icon-slot\">${resolvedIcon ? html`<ixfx-icon name=\"${resolvedIcon}\"></ixfx-icon>` : null}</span>\n <span class=\"label\"><slot></slot>${this.label}</span>\n <span class=\"arrow\">${this._hasSubmenu ? html`<ixfx-icon name=\"chevron-right\"></ixfx-icon>` : nothing}</span>\n </div>\n <div class=\"submenu-popover\" popover=\"auto\"\n @mouseenter=${this._handleSubmenuMouseEnter}\n @mouseleave=${this._handleSubmenuMouseLeave}\n >\n <slot name=\"submenu\" @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-sub-trigger': MenuSubTrigger;\n }\n}\n","import { css, html, LitElement } from 'lit';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\n@customElement(`ixfx-menu-separator`)\nexport class MenuSeparator extends LitElement {\n static styles = [themeFallbacks, css`\n :host {\n display: block;\n margin: var(--space-xs) 0;\n }\n\n .separator {\n height: 1px;\n background: var(--surface-4);\n }\n `];\n\n render() {\n return html`<div class=\"separator\"></div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-separator': MenuSeparator;\n }\n}\n","import { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\n@customElement(`ixfx-menu-header`)\nexport class MenuHeader extends LitElement {\n @property({ type: String }) label = ``;\n\n static styles = [themeFallbacks, css`\n :host {\n display: block;\n padding: 6px var(--space-m) var(--space-xs);\n font-size: var(--text-s);\n font-weight: var(--font-weight-bold);\n text-transform: uppercase;\n color: var(--surface-muted-text);\n letter-spacing: 0.5px;\n }\n `];\n\n render() {\n return html`<div>${this.label}</div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-header': MenuHeader;\n }\n}\n","import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport type { TemplateResult } from 'lit';\nimport type { TreeNode } from '../tree/types.js';\nimport type { MenuTriggerCommandDetail } from './menu-trigger.js';\nimport { html, nothing } from 'lit';\nimport './menu-container.js';\nimport './menu-item.js';\nimport './menu-sub-trigger.js';\nimport './menu-separator.js';\nimport './menu-header.js';\n\nexport type MenuFromTreeOptions = {\n onCommand?: (detail: MenuTriggerCommandDetail) => void;\n registry?: CommandRegistry<unknown>;\n keyboardManager?: KeyboardManager;\n};\n\nfunction isLeaf(node: TreeNode): boolean {\n return node.children === undefined || node.children.length === 0;\n}\n\nexport function menuFromTree(\n nodes: TreeNode[],\n options: MenuFromTreeOptions = {},\n): TemplateResult {\n const { onCommand, registry, keyboardManager } = options;\n\n return html`${nodes.map((node) => {\n const label = node.item.label;\n\n if (label === `-`) {\n return html`<ixfx-menu-separator></ixfx-menu-separator>`;\n }\n\n if (label.startsWith(`# `)) {\n return html`<ixfx-menu-header label=\"${label.slice(2)}\"></ixfx-menu-header>`;\n }\n\n if (!isLeaf(node)) {\n const submenu = menuFromTree(node.children!, options);\n return html`\n <ixfx-menu-sub-trigger label=\"${label}\">\n <ixfx-menu-container\n slot=\"submenu\"\n .registry=${registry ?? nothing}\n .keyboardManager=${keyboardManager ?? nothing}\n >${submenu}</ixfx-menu-container>\n </ixfx-menu-sub-trigger>\n `;\n }\n\n return html`\n <ixfx-menu-item\n command=\"${node.item.key}\"\n label=\"${label}\"\n icon-name=\"${node.item.icon ?? nothing}\"\n @command=${onCommand ? (e: CustomEvent) => onCommand(e.detail) : nothing}\n ></ixfx-menu-item>\n `;\n })}`;\n}\n\nfunction buildMenuItemEl(\n node: TreeNode,\n options: MenuFromTreeOptions,\n): HTMLElement {\n const { onCommand, registry } = options;\n const label = node.item.label;\n\n const el = document.createElement(`ixfx-menu-item`);\n el.setAttribute(`command`, node.item.key);\n el.setAttribute(`label`, label);\n if (node.item.icon) {\n el.setAttribute(`icon-name`, node.item.icon);\n }\n if (onCommand) {\n el.addEventListener(`command`, e => onCommand((e as CustomEvent).detail));\n }\n if (registry) {\n (el as any).registry = registry;\n }\n return el;\n}\n\nfunction buildMenuSeparatorEl(): HTMLElement {\n return document.createElement(`ixfx-menu-separator`);\n}\n\nfunction buildMenuHeaderEl(label: string): HTMLElement {\n const el = document.createElement(`ixfx-menu-header`);\n el.setAttribute(`label`, label);\n return el;\n}\n\nfunction buildMenuSubTriggerEl(\n node: TreeNode,\n options: MenuFromTreeOptions,\n): HTMLElement {\n const { registry, keyboardManager } = options;\n\n const el = document.createElement(`ixfx-menu-sub-trigger`);\n el.setAttribute(`label`, node.item.label);\n if (registry)\n (el as any).registry = registry;\n if (keyboardManager)\n (el as any).keyboardManager = keyboardManager;\n\n const container = document.createElement(`ixfx-menu-container`);\n container.setAttribute(`slot`, `submenu`);\n if (registry)\n (container as any).registry = registry;\n if (keyboardManager)\n (container as any).keyboardManager = keyboardManager;\n\n const childEls = menuFromTreeToElements(node.children!, options);\n for (const child of childEls) {\n container.appendChild(child);\n }\n\n el.appendChild(container);\n return el;\n}\n\nexport function menuFromTreeToElements(\n nodes: TreeNode[],\n options: MenuFromTreeOptions = {},\n): HTMLElement[] {\n return nodes.map((node) => {\n const label = node.item.label;\n\n if (label === `-`) {\n return buildMenuSeparatorEl();\n }\n\n if (label.startsWith(`# `)) {\n return buildMenuHeaderEl(label.slice(2));\n }\n\n if (!isLeaf(node)) {\n return buildMenuSubTriggerEl(node, options);\n }\n\n return buildMenuItemEl(node, options);\n });\n}\n","import { css, html, LitElement } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { tickledItemStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type MenuRadioItemSelectDetail = {\n readonly value: string;\n};\n\nexport type MenuRadioItemSelectEvent = CustomEvent<MenuRadioItemSelectDetail>;\n\n@customElement(`ixfx-menu-radio-item`)\nexport class MenuRadioItem extends LitElement {\n @property({ type: String }) value = ``;\n @property({ type: String }) label = ``;\n @property({ type: Boolean }) disabled = false;\n @property({ type: String }) groupValue = ``;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n\n private handleClick(): void {\n if (this.disabled)\n return;\n\n this.dispatchEvent(new CustomEvent<MenuRadioItemSelectDetail>(`radio-select`, {\n detail: { value: this.value },\n bubbles: true,\n composed: true,\n }));\n }\n\n static override styles = [themeFallbacks, tickledItemStyles, css`\n :host {\n display: block;\n }\n\n .item {\n display: flex;\n padding: 6px var(--space-m);\n font-size: var(--text-m);\n }\n\n :host(:focus) {\n outline: none;\n }\n\n .item.disabled {\n opacity: var(--disabled-opacity);\n cursor: default;\n }\n\n .item.disabled:hover {\n background: transparent;\n }\n\n .radio {\n width: 1em;\n margin-left: var(--space-xs);\n font-size: var(--text-m);\n color: var(--accent);\n }\n\n .icon-slot {\n width: 0;\n overflow: hidden;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n :host([icon-name]) .icon-slot,\n :host([data-icon-section]) .icon-slot {\n width: 1em;\n height: 1em;\n margin-right: var(--space-s);\n }\n\n .label {\n flex: 1;\n }\n `];\n\n render() {\n const isSelected = this.groupValue === this.value;\n\n return html`\n <div \n class=\"item ${this.disabled ? `disabled` : ``}\"\n @click=${this.handleClick}\n tabindex=\"${this.disabled ? -1 : 0}\"\n role=\"menuitemradio\"\n aria-checked=\"${isSelected}\"\n >\n <span class=\"radio\">${isSelected ? `●` : ``}</span>\n <span class=\"icon-slot\">${this.iconName ? html`<ixfx-icon name=\"${this.iconName}\"></ixfx-icon>` : null}</span>\n <span class=\"label\">${this.label}</span>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-radio-item': MenuRadioItem;\n }\n}\n","import { css, html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport './menu-radio-item.js';\n\nexport type MenuRadioGroupChangeDetail = {\n readonly name: string;\n readonly value: string;\n};\n\nexport type MenuRadioGroupChangeEvent = CustomEvent<MenuRadioGroupChangeDetail>;\n\n@customElement(`ixfx-menu-radio-group`)\nexport class MenuRadioGroup extends LitElement {\n @property({ type: String }) name = ``;\n @property({ type: String }) value = ``;\n\n @state() private slottedElements: Element[] = [];\n\n private handleSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this.slottedElements = slot.assignedElements();\n this.updateSlottedValues();\n }\n\n private updateSlottedValues(): void {\n for (const el of this.slottedElements) {\n (el as any).groupValue = this.value;\n }\n }\n\n private handleRadioSelect(e: CustomEvent): void {\n this.value = e.detail.value;\n this.dispatchEvent(new CustomEvent<MenuRadioGroupChangeDetail>(`radio-change`, {\n detail: {\n name: this.name,\n value: this.value,\n },\n bubbles: true,\n composed: true,\n }));\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n if (changedProperties.has(`value`)) {\n this.updateSlottedValues();\n }\n }\n\n static styles = css`\n :host {\n display: block;\n }\n\n ::slotted(menu-radio-item) {\n display: block;\n }\n `;\n\n render() {\n return html`\n <slot @slotchange=${this.handleSlotChange} @radio-select=${this.handleRadioSelect}></slot>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-radio-group': MenuRadioGroup;\n }\n}\n","export { MenuBar } from './menu-bar.js';\nexport { MenuCheckItem } from './menu-check-item.js';\nexport { MenuCommandController } from './menu-command-controller.js';\nexport { MenuContainer } from './menu-container.js';\nexport { menuFromTree, menuFromTreeToElements } from './menu-from-tree.js';\nexport type { MenuFromTreeOptions } from './menu-from-tree.js';\nexport { MenuHeader } from './menu-header.js';\nexport { MenuItem } from './menu-item.js';\nexport { MenuRadioGroup } from './menu-radio-group.js';\nexport { MenuRadioItem } from './menu-radio-item.js';\nexport { MenuSeparator } from './menu-separator.js';\nexport { MenuSubTrigger } from './menu-sub-trigger.js';\nexport { MenuTrigger } from './menu-trigger.js';\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import "./icon-DR_3rSyZ.js";
1
+ import "./icon-CDGprSdE.js";
2
2
  import { LitElement } from "lit";
3
3
  import { CommandRegistry, KeyboardManager } from "@clinth/ui-commands";
4
4
  //#region src/menu/menu-container.d.ts
@@ -63,6 +63,8 @@ declare class MenuTrigger extends LitElement {
63
63
  private static _count;
64
64
  private _anchorName;
65
65
  private _clickListener;
66
+ /** Element focused when the menu opened; focus returns here on Escape/Tab when there is no trigger button (context-target mode). */
67
+ private _focusBeforeOpen;
66
68
  connectedCallback(): void;
67
69
  disconnectedCallback(): void;
68
70
  firstUpdated(): void;
@@ -83,6 +85,13 @@ declare class MenuTrigger extends LitElement {
83
85
  private _handleClickOutside;
84
86
  private _getMenuContainer;
85
87
  private _handleKeydown;
88
+ /**
89
+ * Return focus after a keyboard close. The trigger button is the natural
90
+ * target, but it is not rendered for a context target — then fall back to
91
+ * whatever was focused at open (don't rely on the browser's popover focus
92
+ * restoration), and finally the host.
93
+ */
94
+ private _restoreFocus;
86
95
  private _handleCommand;
87
96
  private _handleRadioChange;
88
97
  private _handleContextMenu;
@@ -130,4 +139,4 @@ declare global {
130
139
  }
131
140
  //#endregion
132
141
  export { MenuContainer as i, MenuTrigger as n, MenuTriggerCommandDetail as r, MenuItem as t };
133
- //# sourceMappingURL=menu-item-DlxAb0Xr.d.ts.map
142
+ //# sourceMappingURL=menu-item-BbgdcwBX.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-item-BbgdcwBX.d.ts","names":[],"sources":["../src/menu/menu-container.ts","../src/menu/menu-trigger.ts","../src/menu/menu-item.ts"],"mappings":";;;;cASa,sBAAsB;EACgB;EACjB,WAAW;EACX,kBAAkB;UACvB;UAGnB;SAwBD,sBAAM;UA4BL;UAkDA;EAYC,QAAQ,mBAAmB;;;;EASpC,WAAW,SAAS,IAAI;EAOxB,wBAAM;UAaE;;;;;UAoCA;UAiCA;EA0BR;UAIQ;UAQA;UAUA;UAqDA;;QAqCF;YACI;IACR,uBAAuB;;;;;KCvWtB;KACA;KAEO;WACD;WACA;WACA;;cAME,oBAAoB;EACY,MAAM;EACrB;;EAEwB;EACpB,WAAW;EACX,kBAAkB;EACtB,WAAW;;EAEa;UAEnC;UACA;UACA;UACA;UAEc;UACN;iBAEV;UAEP;UACA;;UAEA;EAER;EAOA;EAQA;EA0BA,QAAQ,mBAAmB;UAgBnB;UAqBA;UAWA;UAOA;UAKA;MAKJ;EAIJ;EAIA;EAIA;UAIQ;UAiBA;UAQA;UAYA;UAeA;UAYA;UAOA;;;;;;;UAqBA;UAcA;UAeA;UAkBA;SAeD,sBAAM;EAsGb,wBAAM;;QAsCA;YACI;IACR,qBAAqB;;;;;cCjcZ,iBAAiB;EACA;EAC2B;EAC3B;EACC;EACuB;EACpB,WAAW;EACX,kBAAkB;EAClB,iBAAiB;UAEhC;UACM;UAEf;EAER;UAOQ;UAKA;UAWA;UAQA;UAUA;UAUA;UAWA;UASA;EASR,WAAW,mBAAmB;EAU9B,QAAQ,mBAAmB;UAInB;SAaQ,sBAAM;EAkEtB,wBAAM;;QAwBA;YACI;IACR,kBAAkB"}
@@ -289,6 +289,7 @@ let MenuTrigger = class MenuTrigger extends LitElement {
289
289
  this._hasContextTarget = false;
290
290
  this._anchorName = `--mt-${_MenuTrigger._count++}`;
291
291
  this._clickListener = this._handleClickOutside.bind(this);
292
+ this._focusBeforeOpen = null;
292
293
  this._handlePopoverToggle = (e) => {
293
294
  if (e.newState === `closed`) {
294
295
  this._isOpen = false;
@@ -305,10 +306,10 @@ let MenuTrigger = class MenuTrigger extends LitElement {
305
306
  e.preventDefault();
306
307
  e.stopPropagation();
307
308
  this._closeMenu();
308
- this._triggerBtn?.focus();
309
+ this._restoreFocus();
309
310
  } else if (e.key === `Tab`) {
310
311
  this._closeMenu();
311
- this._triggerBtn?.focus();
312
+ this._restoreFocus();
312
313
  }
313
314
  };
314
315
  }
@@ -346,6 +347,7 @@ let MenuTrigger = class MenuTrigger extends LitElement {
346
347
  }
347
348
  updated(changedProperties) {
348
349
  if (changedProperties.has(`registry`) || changedProperties.has(`keyboardManager`)) this._propagateContext();
350
+ if (changedProperties.has(`mode`) || changedProperties.has(`_hasContextTarget`)) this.toggleAttribute(`has-context-target`, this.mode === `context` && this._hasContextTarget);
349
351
  if (changedProperties.has(`mode`)) this._updatePosition();
350
352
  }
351
353
  _updatePosition() {
@@ -411,6 +413,7 @@ let MenuTrigger = class MenuTrigger extends LitElement {
411
413
  }
412
414
  _openMenu() {
413
415
  if (this._isOpen || !this._popup?.popover) return;
416
+ this._focusBeforeOpen = deepActiveElement();
414
417
  try {
415
418
  this._popup.showPopover({ source: this });
416
419
  this._isOpen = true;
@@ -452,6 +455,22 @@ let MenuTrigger = class MenuTrigger extends LitElement {
452
455
  _getMenuContainer() {
453
456
  return ((this.shadowRoot?.querySelector(`slot[name="menu"]`))?.assignedElements({ flatten: true }) ?? []).find((el) => el.tagName === `IXFX-MENU-CONTAINER`) ?? null;
454
457
  }
458
+ /**
459
+ * Return focus after a keyboard close. The trigger button is the natural
460
+ * target, but it is not rendered for a context target — then fall back to
461
+ * whatever was focused at open (don't rely on the browser's popover focus
462
+ * restoration), and finally the host.
463
+ */
464
+ _restoreFocus() {
465
+ if (this._triggerBtn) {
466
+ this._triggerBtn.focus();
467
+ return;
468
+ }
469
+ const previous = this._focusBeforeOpen;
470
+ this._focusBeforeOpen = null;
471
+ if (previous?.isConnected && previous !== document.body) previous.focus();
472
+ else this.focus();
473
+ }
455
474
  _handleCommand(e) {
456
475
  if (this._popup?.popover) try {
457
476
  this._popup.hidePopover();
@@ -495,6 +514,16 @@ let MenuTrigger = class MenuTrigger extends LitElement {
495
514
  --ixfx-button-padding: var(--ixfx-button-padding, var(--space-s) var(--space-m));
496
515
  }
497
516
 
517
+ /* Context mode with a context-target: dissolve the host's box so the
518
+ slotted surface is itself the item in the consumer's flex/grid layout.
519
+ Otherwise the host sizes to the surface's full un-scrolled content and
520
+ a height-constrained parent never clips it. Safe because context opens
521
+ position the popup at the pointer (fixed), not via the anchor.
522
+ Override with --menu-trigger-display (e.g. block) to keep a box. */
523
+ :host([mode="context"][has-context-target]) {
524
+ display: var(--menu-trigger-display, contents);
525
+ }
526
+
498
527
  .trigger-area {
499
528
  anchor-name: var(--anchor-name);
500
529
  /* Block flex (not inline-flex): as an inline-level box this would join
@@ -622,6 +651,12 @@ __decorate([state()], MenuTrigger.prototype, "_hasContextTarget", void 0);
622
651
  __decorate([query(`.trigger-btn`)], MenuTrigger.prototype, "_triggerBtn", void 0);
623
652
  __decorate([query(`.popup`)], MenuTrigger.prototype, "_popup", void 0);
624
653
  MenuTrigger = _MenuTrigger = __decorate([safeCustomElement(`ixfx-menu-trigger`)], MenuTrigger);
654
+ /** `document.activeElement`, followed down through open shadow roots. */
655
+ function deepActiveElement() {
656
+ let el = document.activeElement;
657
+ while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;
658
+ return el instanceof HTMLElement ? el : null;
659
+ }
625
660
  //#endregion
626
661
  //#region src/menu/menu-item.ts
627
662
  let MenuItem = class MenuItem extends LitElement {
@@ -830,4 +865,4 @@ MenuItem = __decorate([safeCustomElement(`ixfx-menu-item`)], MenuItem);
830
865
  //#endregion
831
866
  export { MenuTrigger as n, MenuContainer as r, MenuItem as t };
832
867
 
833
- //# sourceMappingURL=menu-item-JcpHCyF0.js.map
868
+ //# sourceMappingURL=menu-item-CfndBGO8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu-item-CfndBGO8.js","names":["customElement","customElement","customElement"],"sources":["../src/menu/menu-container.ts","../src/menu/menu-trigger.ts","../src/menu/menu-item.ts"],"sourcesContent":["import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport { css, html, LitElement } from 'lit';\nimport { property, query } from 'lit/decorators.js';\nimport { TickledController, tickledStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { popupSurfaceStyles } from '../styles/popup.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\n@customElement(`ixfx-menu-container`)\nexport class MenuContainer extends LitElement {\n @property({ type: String, attribute: `anchor` }) anchor?: string;\n @property({ attribute: false }) registry?: CommandRegistry<unknown>;\n @property({ attribute: false }) keyboardManager?: KeyboardManager;\n @query(`.popover`) private _popover!: HTMLElement;\n\n // TickledController manages input mode and tickled state\n private tickled = new TickledController<number>(this, {\n getItems: () => {\n const items = this._getMenuItems();\n return items.map((item, i) => ({\n id: i,\n enabled: !item.hasAttribute(`disabled`),\n }));\n },\n onTickle: (index) => {\n // When an item is tickled (hovered/keyboard focused), handle submenu opening\n const items = this._getMenuItems();\n if (index !== undefined) {\n const item = items[index];\n // Ensure the item is focusable and focus it\n item.tabIndex = 0;\n item.focus({ preventScroll: true });\n }\n },\n onStateChange: () => {\n // Sync DOM attributes for slotted content\n this._syncTickledClasses();\n },\n });\n\n static styles = [popupSurfaceStyles, themeFallbacks, tickledStyles, css`\n :host {\n display: block;\n }\n\n .popover {\n padding: var(--space-xs) 0;\n min-width: 160px;\n }\n\n :host {\n opacity: 1;\n transform: translateY(0) scale(1);\n transition: opacity 0.12s ease-out, transform 0.12s ease-out,\n display 0.12s allow-discrete, overlay 0.12s allow-discrete;\n }\n\n @starting-style :host {\n opacity: 0;\n transform: translateY(-4px) scale(0.97);\n }\n\n ::slotted(menu-separator) {\n display: block;\n margin: var(--space-xs) 0;\n }\n `];\n\n private _updateIconSections(): void {\n const slot = this.shadowRoot?.querySelector(`slot`) as HTMLSlotElement | null;\n if (!slot)\n return;\n\n const assigned = slot.assignedElements({ flatten: true });\n\n // Group direct children into sections delimited by separators and headers\n const sections: Element[][] = [];\n let section: Element[] = [];\n for (const el of assigned) {\n if (el.tagName === `IXFX-MENU-SEPARATOR` || el.tagName === `IXFX-MENU-HEADER`) {\n if (section.length > 0) {\n sections.push(section); section = [];\n }\n } else {\n section.push(el);\n }\n }\n if (section.length > 0)\n sections.push(section);\n\n this._propagateContext();\n\n for (const sec of sections) {\n const hasIcon = sec.some((el) => {\n if (el.tagName === `IXFX-MENU-RADIO-GROUP`) {\n return [...el.children].some(ri => ri.hasAttribute(`icon-name`));\n }\n return el.hasAttribute(`icon-name`);\n });\n\n for (const el of sec) {\n if (el.tagName === `IXFX-MENU-RADIO-GROUP`) {\n for (const ri of el.children) {\n if (hasIcon)\n ri.setAttribute(`data-icon-section`, ``);\n else ri.removeAttribute(`data-icon-section`);\n }\n } else {\n if (hasIcon)\n el.setAttribute(`data-icon-section`, ``);\n else el.removeAttribute(`data-icon-section`);\n }\n }\n }\n\n this.performUpdate();\n }\n\n private _propagateContext(): void {\n const slot = this.shadowRoot?.querySelector(`slot`) as HTMLSlotElement | null;\n if (!slot)\n return;\n for (const el of slot.assignedElements({ flatten: true })) {\n if (`registry` in el)\n (el as any).registry = this.registry;\n if (`keyboardManager` in el)\n (el as any).keyboardManager = this.keyboardManager;\n }\n }\n\n override updated(changedProperties: Map<string, unknown>): void {\n if (changedProperties.has(`registry`) || changedProperties.has(`keyboardManager`)) {\n this._propagateContext();\n }\n }\n\n /**\n * Sync data-input-mode to :host so CSS variables cascade to slotted items\n */\n willUpdate(changed: Map<PropertyKey, unknown>): void {\n super.willUpdate(changed);\n // Set data-input-mode on :host so tickledStyles CSS variables cascade\n // through shadow DOM to slotted menu items\n this.setAttribute(`data-input-mode`, this.tickled.inputMode);\n }\n\n render() {\n return html`\n <div\n class=\"popover popup-surface\"\n role=\"menu\"\n @keydown=${this._handleKeydown}\n @mouseover=${this._handleMouseOver}\n >\n <slot @slotchange=${this._updateIconSections}></slot>\n </div>\n `;\n }\n\n private _getMenuItems(): HTMLElement[] {\n const slot = this.shadowRoot?.querySelector(`slot`);\n if (!slot)\n return [];\n\n const skipTags = [`IXFX-MENU-SEPARATOR`, `IXFX-MENU-HEADER`];\n const result: HTMLElement[] = [];\n\n for (const el of slot.assignedElements({ flatten: true })) {\n if (skipTags.includes(el.tagName))\n continue;\n if (el.hasAttribute(`disabled`))\n continue;\n const role = el.getAttribute(`role`);\n if (role === `none` || role === `presentation`)\n continue;\n\n if (el.tagName === `IXFX-MENU-RADIO-GROUP`) {\n const groupSlot = el.shadowRoot?.querySelector(`slot`) as HTMLSlotElement | null;\n for (const radioItem of groupSlot?.assignedElements({ flatten: true }) ?? []) {\n if (!radioItem.hasAttribute(`disabled`)) {\n result.push(radioItem as HTMLElement);\n }\n }\n } else {\n result.push(el as HTMLElement);\n }\n }\n\n return result;\n }\n\n /**\n * Sync .tickled class on slotted items to match controller state\n * This is called via onStateChange whenever the tickled state changes\n */\n private _syncTickledClasses(): void {\n const items = this._getMenuItems();\n items.forEach((item, i) => {\n if (this.tickled.isTickled(i)) {\n item.classList.add(`tickled`);\n item.tabIndex = 0;\n // Set inline styles to ensure visibility across shadow DOM boundaries\n const innerItem = item.shadowRoot?.querySelector(`.item`) as HTMLElement | null;\n if (innerItem) {\n innerItem.style.background = `rgba(0, 0, 0, 0.06)`;\n innerItem.style.borderColor = `var(--accent)`;\n innerItem.style.color = `inherit`;\n }\n } else {\n item.classList.remove(`tickled`);\n item.tabIndex = -1;\n // Clear inline styles\n const innerItem = item.shadowRoot?.querySelector(`.item`) as HTMLElement | null;\n if (innerItem) {\n innerItem.style.background = ``;\n innerItem.style.borderColor = ``;\n innerItem.style.color = ``;\n }\n }\n });\n\n // Focus the tickled item if in keyboard mode\n if (this.tickled.inputMode === `keyboard` && this.tickled.tickledId !== undefined) {\n const tickledItem = items[this.tickled.tickledId];\n tickledItem?.focus();\n }\n }\n\n private _handleMouseOver = (e: MouseEvent): void => {\n const items = this._getMenuItems();\n // composedPath crosses shadow boundaries to find the hovered menu item\n const path = e.composedPath();\n const hoveredIndex = items.findIndex(item => path.includes(item));\n if (hoveredIndex !== -1) {\n const item = items[hoveredIndex];\n // If IXFX-MENU-CONTAINER appears before this item in the composed path, the\n // event originated from inside a nested submenu. Skip the focus override so the\n // inner container keeps ownership of focus. stopPropagation() alone is not\n // sufficient because it does not reliably cross shadow-root boundaries with\n // popovers in the stack — both this handler and the inner one will fire.\n const itemPathIndex = path.indexOf(item);\n const isFromInsideSubmenu = path.slice(0, itemPathIndex).some(\n node => node instanceof Element && node.tagName === `IXFX-MENU-CONTAINER`,\n );\n if (!isFromInsideSubmenu) {\n // Use TickledController to handle mouse hover\n this.tickled.handlePointerEnter(hoveredIndex);\n }\n // Stop propagation so ancestor MenuContainers don't override this focus\n // with their own mouseover handler (e.g. outer menu focusing the sub-trigger).\n e.stopPropagation();\n }\n };\n\n focusFirst(): void {\n this.tickled.handleKeyboardNavigation(`first`);\n }\n\n private _focusNext(items: HTMLElement[], direction: number): void {\n if (items.length === 0) {\n return;\n }\n\n this.tickled.handleKeyboardNavigation(direction > 0 ? `next` : `previous`);\n }\n\n private _focusItem(items: HTMLElement[], index: number): void {\n if (items.length === 0) {\n return;\n }\n\n // Clamp index to valid range\n const clampedIndex = Math.max(0, Math.min(index, items.length - 1));\n this.tickled.handleKeyboardNavigation(clampedIndex);\n }\n\n private _activateFocusedItem(items: HTMLElement[]): void {\n const tickledIndex = this.tickled.tickledId;\n if (tickledIndex === undefined) {\n return;\n }\n\n const item = items[tickledIndex];\n if (!item) {\n return;\n }\n\n const tagName = item.tagName;\n\n if (tagName === `IXFX-MENU-SUB-TRIGGER`) {\n // Native menu behavior handles submenu navigation automatically\n return;\n }\n\n if (tagName === `IXFX-MENU-CHECK-ITEM`) {\n const checkItem = item as any;\n checkItem.checked = !checkItem.checked;\n checkItem.dispatchEvent(new CustomEvent(`command`, {\n detail: { command: checkItem.command, checked: checkItem.checked },\n bubbles: true,\n composed: true,\n }));\n return;\n }\n\n if (tagName === `IXFX-MENU-RADIO-ITEM`) {\n item.dispatchEvent(new CustomEvent(`radio-select`, {\n detail: { value: (item as any).value },\n bubbles: true,\n composed: true,\n }));\n return;\n }\n\n if (tagName === `IXFX-MENU-ITEM`) {\n const command = (item as any).command;\n if (command) {\n item.dispatchEvent(new CustomEvent(`command`, {\n detail: { command },\n bubbles: true,\n composed: true,\n }));\n }\n return;\n }\n\n (item as HTMLElement).click();\n }\n\n private _handleKeydown = (e: KeyboardEvent): void => {\n const items = this._getMenuItems();\n if (items.length === 0) {\n return;\n }\n\n switch (e.key) {\n case `ArrowDown`:\n e.preventDefault();\n e.stopPropagation();\n this._focusNext(items, 1);\n break;\n case `ArrowUp`:\n e.preventDefault();\n e.stopPropagation();\n this._focusNext(items, -1);\n break;\n case `Home`:\n e.preventDefault();\n e.stopPropagation();\n this._focusItem(items, 0);\n break;\n case `End`:\n e.preventDefault();\n e.stopPropagation();\n this._focusItem(items, items.length - 1);\n break;\n case `Enter`:\n case ` `:\n e.preventDefault();\n e.stopPropagation();\n this._activateFocusedItem(items);\n break;\n }\n };\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-container': MenuContainer;\n }\n}\n","import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport { css, html, LitElement } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { popupSurfaceStyles } from '../styles/popup.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\nimport './menu-container.js';\n\ntype MenuMode = `trigger` | `dropdown` | `context`;\ntype Placement = `bottom-start` | `bottom-end` | `right-start`;\n\nexport type MenuTriggerCommandDetail = {\n readonly command?: string;\n readonly value?: string;\n readonly checked?: boolean;\n};\n\nexport type MenuTriggerCommandEvent = CustomEvent<MenuTriggerCommandDetail>;\n\n@customElement(`ixfx-menu-trigger`)\nexport class MenuTrigger extends LitElement {\n @property({ type: String, reflect: true }) mode: MenuMode = `trigger`;\n @property({ type: String }) label = ``;\n /** Render an `ixfx-icon` in the default button instead of the text `label`. */\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n @property({ attribute: false }) registry?: CommandRegistry<unknown>;\n @property({ attribute: false }) keyboardManager?: KeyboardManager;\n @property({ type: String }) placement: Placement = `bottom-start`;\n /** Set false when a host widget manages its own roving/virtual focus (e.g. crumb-navigation) and opens this menu programmatically, so the trigger button should not be a native Tab stop. */\n @property({ type: Boolean, attribute: `tab-stop` }) tabStop = true;\n\n @state() private _isOpen = false;\n @state() private _hasMenu = false;\n @state() private _hasTriggerSlot = false;\n @state() private _hasContextTarget = false;\n\n @query(`.trigger-btn`) private _triggerBtn!: HTMLButtonElement;\n @query(`.popup`) private _popup!: HTMLElement;\n\n private static _count = 0;\n\n private _anchorName = `--mt-${MenuTrigger._count++}`;\n private _clickListener = this._handleClickOutside.bind(this);\n /** Element focused when the menu opened; focus returns here on Escape/Tab when there is no trigger button (context-target mode). */\n private _focusBeforeOpen: HTMLElement | null = null;\n\n connectedCallback(): void {\n super.connectedCallback();\n document.addEventListener(`keydown`, this._handleKeydown);\n this.addEventListener(`command`, this._handleCommand as EventListener);\n this.addEventListener(`radio-change`, this._handleRadioChange as EventListener);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener(`keydown`, this._handleKeydown);\n this.removeEventListener(`command`, this._handleCommand as EventListener);\n this.removeEventListener(`radio-change`, this._handleRadioChange as EventListener);\n document.removeEventListener(`click`, this._clickListener);\n }\n\n firstUpdated(): void {\n this.style.setProperty(`--anchor-name`, this._anchorName);\n this._popup.addEventListener(`toggle`, this._handlePopoverToggle);\n\n this.updateComplete.then(() => {\n const slot = this.shadowRoot?.querySelector(`slot[name=\"menu\"]`) as HTMLSlotElement | undefined;\n if (slot) {\n const assigned = slot.assignedElements({ flatten: true });\n if (assigned.length > 0) {\n this._hasMenu = true;\n this._propagateContext();\n }\n }\n\n // Initialise slot-derived state directly: browsers fire slotchange\n // asynchronously (after this first paint), so this avoids a flash of\n // the default trigger button for context targets present at load.\n const contextSlot = this.shadowRoot?.querySelector(`slot[name=\"context-target\"]`) as HTMLSlotElement | undefined;\n if (contextSlot) {\n this._hasContextTarget = contextSlot.assignedElements({ flatten: true }).length > 0;\n }\n\n this._updatePosition();\n });\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n if (changedProperties.has(`registry`) || changedProperties.has(`keyboardManager`)) {\n this._propagateContext();\n }\n if (changedProperties.has(`mode`) || changedProperties.has(`_hasContextTarget`)) {\n // Drives the :host sizing contract (see styles). Only meaningful when\n // the context-target slot is rendered, i.e. in context mode.\n this.toggleAttribute(`has-context-target`, this.mode === `context` && this._hasContextTarget);\n }\n if (changedProperties.has(`mode`)) {\n // Context opens overwrite the anchor positioning with pointer-fixed\n // styles; restore the anchor placement when leaving context mode.\n this._updatePosition();\n }\n }\n\n private _updatePosition(): void {\n const placements: Record<Placement, { insetArea: string }> = {\n 'bottom-start': { insetArea: `block-end span-inline-start` },\n 'bottom-end': { insetArea: `block-end span-inline-end` },\n 'right-start': { insetArea: `inline-end span-block-start` },\n };\n const pos = placements[this.placement];\n (this._popup.style as any).insetArea = pos.insetArea;\n (this._popup.style as any).positionAnchor = this._anchorName;\n // fallback for browsers without inset-area\n const fallbacks: Record<Placement, { top: string; left: string; right: string }> = {\n 'bottom-start': { top: `anchor(bottom)`, left: `anchor(left)`, right: `auto` },\n 'bottom-end': { top: `anchor(bottom)`, left: `auto`, right: `anchor(left)` },\n 'right-start': { top: `anchor(top)`, left: `anchor(right)`, right: `auto` },\n };\n const fb = fallbacks[this.placement];\n this._popup.style.top = fb.top;\n this._popup.style.left = fb.left;\n (this._popup.style as any).right = fb.right;\n }\n\n private _propagateContext(): void {\n const slot = this.shadowRoot?.querySelector(`slot[name=\"menu\"]`) as HTMLSlotElement | undefined;\n const items = slot?.assignedElements({ flatten: true }) ?? [];\n for (const el of items) {\n if (`registry` in el)\n (el as any).registry = this.registry;\n if (`keyboardManager` in el)\n (el as any).keyboardManager = this.keyboardManager;\n }\n }\n\n private _handleSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const assigned = slot.assignedElements({ flatten: true });\n this._hasMenu = assigned.length > 0;\n this._propagateContext();\n }\n\n private _handleTriggerSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasTriggerSlot = slot.assignedElements({ flatten: true }).length > 0;\n }\n\n private _handleContextTargetSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasContextTarget = slot.assignedElements({ flatten: true }).length > 0;\n }\n\n get isOpen(): boolean {\n return this._isOpen;\n }\n\n openMenu(): void {\n this._openMenu();\n }\n\n closeMenu(): void {\n this._closeMenu();\n }\n\n focusTrigger(): void {\n this._triggerBtn?.focus();\n }\n\n private _openMenu(): void {\n if (this._isOpen || !this._popup?.popover)\n return;\n this._focusBeforeOpen = deepActiveElement();\n try {\n (this._popup as any).showPopover({ source: this });\n this._isOpen = true;\n document.addEventListener(`click`, this._clickListener);\n this.dispatchEvent(new CustomEvent(`menu-trigger-open`, { bubbles: true, composed: true }));\n requestAnimationFrame(() => {\n this._getMenuContainer()?.focusFirst();\n });\n } catch (err) {\n console.warn(`showPopover failed:`, err);\n }\n }\n\n private _handlePopoverToggle = (e: Event): void => {\n if ((e as ToggleEvent).newState === `closed`) {\n this._isOpen = false;\n document.removeEventListener(`click`, this._clickListener);\n this.dispatchEvent(new CustomEvent(`menu-trigger-close`, { bubbles: true, composed: true }));\n }\n };\n\n private _closeMenu(): void {\n if (!this._isOpen)\n return;\n if (this._popup?.popover) {\n try {\n (this._popup as any).hidePopover();\n } catch { /* ignore */ }\n }\n this._isOpen = false;\n document.removeEventListener(`click`, this._clickListener);\n }\n\n private _handleTriggerClick(e: Event): void {\n // `context` mode opens only via `_handleContextMenu` (right-click). The\n // context target is the consumer's own interactive surface, so a plain\n // left click must reach the page, not toggle the menu.\n if (this.mode === `context`)\n return;\n e.stopPropagation();\n if (this._isOpen) {\n this._closeMenu();\n this._triggerBtn?.focus();\n } else {\n this._openMenu();\n }\n }\n\n private _handleClickOutside(e: Event): void {\n if (!this.contains(e.target as Node)) {\n if (this._popup?.popover && this._popup.hasAttribute(`open`)) {\n try {\n (this._popup as any).hidePopover();\n } catch {\n // ignore\n }\n }\n }\n }\n\n private _getMenuContainer(): (HTMLElement & { focusFirst: () => void }) | null {\n const slot = this.shadowRoot?.querySelector(`slot[name=\"menu\"]`) as HTMLSlotElement | null;\n const assigned = slot?.assignedElements({ flatten: true }) ?? [];\n const container = assigned.find(el => el.tagName === `IXFX-MENU-CONTAINER`);\n return (container as any) ?? null;\n }\n\n private _handleKeydown = (e: KeyboardEvent): void => {\n if (!this._isOpen)\n return;\n\n if (e.key === `Escape`) {\n e.preventDefault();\n e.stopPropagation();\n this._closeMenu();\n this._restoreFocus();\n } else if (e.key === `Tab`) {\n this._closeMenu();\n this._restoreFocus();\n }\n };\n\n /**\n * Return focus after a keyboard close. The trigger button is the natural\n * target, but it is not rendered for a context target — then fall back to\n * whatever was focused at open (don't rely on the browser's popover focus\n * restoration), and finally the host.\n */\n private _restoreFocus(): void {\n if (this._triggerBtn) {\n this._triggerBtn.focus();\n return;\n }\n const previous = this._focusBeforeOpen;\n this._focusBeforeOpen = null;\n if (previous?.isConnected && previous !== document.body) {\n previous.focus();\n } else {\n this.focus();\n }\n }\n\n private _handleCommand(e: CustomEvent): void {\n if (this._popup?.popover) {\n try {\n (this._popup as any).hidePopover();\n } catch {\n // ignore\n }\n }\n this.dispatchEvent(new CustomEvent<MenuTriggerCommandDetail>(`menu-command`, {\n detail: e.detail,\n bubbles: true,\n composed: true,\n }));\n }\n\n private _handleRadioChange(e: CustomEvent): void {\n if (this._popup?.popover) {\n try {\n (this._popup as any).hidePopover();\n } catch {\n // ignore\n }\n }\n this.dispatchEvent(new CustomEvent<MenuTriggerCommandDetail>(`menu-command`, {\n detail: {\n command: e.detail.name,\n value: e.detail.value,\n },\n bubbles: true,\n composed: true,\n }));\n }\n\n private _handleContextMenu(e: MouseEvent): void {\n if (this.mode !== `context`)\n return;\n e.preventDefault();\n this._popup.style.top = `${e.clientY}px`;\n this._popup.style.left = `${e.clientX}px`;\n this._popup.style.position = `fixed`;\n (this._popup.style as any).positionAnchor = `none`;\n // Route through the same state machine as trigger/dropdown opens so\n // `_isOpen`, the outside-click listener and `menu-trigger-open` all\n // behave identically. Position styles are live while open, so a repeat\n // right-click repositions; _openMenu() no-ops when already open.\n this._openMenu();\n }\n\n static styles = [\n themeFallbacks,\n popupSurfaceStyles,\n css`\n :host {\n display: inline-block;\n position: relative;\n --ixfx-button-padding: var(--ixfx-button-padding, var(--space-s) var(--space-m));\n }\n\n /* Context mode with a context-target: dissolve the host's box so the\n slotted surface is itself the item in the consumer's flex/grid layout.\n Otherwise the host sizes to the surface's full un-scrolled content and\n a height-constrained parent never clips it. Safe because context opens\n position the popup at the pointer (fixed), not via the anchor.\n Override with --menu-trigger-display (e.g. block) to keep a box. */\n :host([mode=\"context\"][has-context-target]) {\n display: var(--menu-trigger-display, contents);\n }\n\n .trigger-area {\n anchor-name: var(--anchor-name);\n /* Block flex (not inline-flex): as an inline-level box this would join\n the host's inline formatting context and pick up strut/baseline gaps\n above and below the button, offsetting the glyph from center. */\n display: flex;\n align-items: stretch;\n }\n\n /* In context mode the target is the consumer's own content surface (a\n list, canvas, whole panel) rather than a button wrapper. Dissolve the\n wrapper's box by default so slotted content participates directly in\n the layout established around the host and can be clipped/scroll within\n the space actually available. Set --menu-trigger-area-display: flex\n (plus --menu-trigger-area-flex) to keep a real box instead, e.g. for\n a mixed visible-trigger + context-target use. */\n :host([mode=\"context\"]) .trigger-area {\n display: var(--menu-trigger-area-display, contents);\n flex: var(--menu-trigger-area-flex, initial);\n }\n\n .trigger-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n background: none;\n border: none;\n color: var(--surface-3-text);\n cursor: pointer;\n padding: var(--ixfx-button-padding);\n font-family: var(--font-family, inherit);\n font-size: var(--text-m);\n font-weight: 600;\n border-radius: var(--radius-s);\n opacity: 0.6;\n transition: opacity var(--transition), background var(--transition);\n }\n\n .trigger-btn:hover {\n background: var(--_trigger-hover-bg, var(--surface-4));\n color: var(--surface-3-text);\n opacity: var(--_trigger-hover-opacity, 1);\n }\n\n .trigger-btn:focus-visible {\n background: var(--surface-4);\n color: var(--surface-3-text);\n outline: none;\n opacity: 1;\n }\n\n .popup {\n position: fixed;\n position-anchor: var(--anchor-name);\n inset: auto;\n margin: 8px;\n padding: 0;\n border: none;\n background: transparent;\n z-index: 100;\n max-height: min(60vh, 400px);\n max-width: min(90vw, 320px);\n overflow: auto;\n overscroll-behavior: contain;\n position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;\n }\n\n .popup[popover] {\n opacity: 1;\n transform: translateY(0) scale(1);\n transition: opacity 0.12s ease-out, transform 0.12s ease-out,\n display 0.12s allow-discrete, overlay 0.12s allow-discrete;\n }\n\n @starting-style .popup {\n opacity: 0;\n transform: translateY(-4px) scale(0.97);\n }\n `,\n ];\n\n render() {\n const showButton = this.mode !== `dropdown` && this._hasMenu && !this._hasTriggerSlot\n // A context target is the consumer's own interactive surface — the\n // default button would be a duplicate, and inert, affordance.\n && !(this.mode === `context` && this._hasContextTarget);\n return html`\n <div\n class=\"trigger-area\"\n @click=${this._handleTriggerClick}\n @contextmenu=${this._handleContextMenu}\n >\n ${showButton\n ? html`<button class=\"trigger-btn\" part=\"base\" tabindex=${this.tabStop ? `0` : `-1`}>${this.iconName ? html`<ixfx-icon name=${this.iconName}></ixfx-icon>` : this.label || html`<ixfx-icon name=\"ellipsis-vertical\"></ixfx-icon>`}</button>`\n : null}\n ${this.mode === `context`\n ? html`<slot name=\"context-target\" @slotchange=${this._handleContextTargetSlotChange}></slot>`\n : null}\n <slot name=\"trigger\" @slotchange=${this._handleTriggerSlotChange}></slot>\n </div>\n <div\n class=\"popup popup-surface\"\n popover=\"auto\"\n @click=${(e: Event) => e.stopPropagation()}\n >\n <slot name=\"menu\" @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\n/** `document.activeElement`, followed down through open shadow roots. */\nfunction deepActiveElement(): HTMLElement | null {\n let el = document.activeElement;\n while (el?.shadowRoot?.activeElement)\n el = el.shadowRoot.activeElement;\n return el instanceof HTMLElement ? el : null;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-trigger': MenuTrigger;\n }\n}\n","import type { CommandRegistry, KeyboardManager } from '@clinth/ui-commands';\nimport { css, html, LitElement } from 'lit';\nimport { property, query, state } from 'lit/decorators.js';\nimport { tickledItemStyles } from '../interaction/index.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type MenuItemCommandDetail = {\n readonly command: string;\n readonly args: string;\n};\n\nexport type MenuItemCommandEvent = CustomEvent<MenuItemCommandDetail>;\n\n@customElement(`ixfx-menu-item`)\nexport class MenuItem extends LitElement {\n @property({ type: String }) command = ``;\n @property({ type: String, attribute: `command-args` }) commandArgs = ``;\n @property({ type: String }) label = ``;\n @property({ type: Boolean }) disabled = false;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n @property({ attribute: false }) registry?: CommandRegistry<unknown>;\n @property({ attribute: false }) keyboardManager?: KeyboardManager;\n @property({ attribute: false }) submenuPopover?: HTMLElement;\n\n @state() private _hasChildren = false;\n @query(`slot`) private _slot!: HTMLSlotElement;\n\n private _hoverTimeout: number | null = null;\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n }\n }\n\n private _handleSlotChange(): void {\n const assigned = this._slot?.assignedElements() ?? [];\n this._hasChildren = assigned.length > 0;\n }\n\n private _handleMouseEnter(): void {\n if (this.disabled || !this._hasChildren || !this.submenuPopover)\n return;\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n }\n this._hoverTimeout = window.setTimeout(() => {\n this._showSubmenu();\n }, 150);\n }\n\n private _handleMouseLeave(): void {\n if (this._hoverTimeout) {\n clearTimeout(this._hoverTimeout);\n this._hoverTimeout = null;\n }\n this._hideSubmenu();\n }\n\n private _showSubmenu(): void {\n if (!this.submenuPopover?.popover)\n return;\n try {\n this.submenuPopover.showPopover();\n } catch (err) {\n console.warn(`showPopover failed:`, err);\n }\n }\n\n private _hideSubmenu(): void {\n if (!this.submenuPopover?.popover)\n return;\n try {\n this.submenuPopover.hidePopover();\n } catch (err) {\n console.warn(`hidePopover failed:`, err);\n }\n }\n\n private handleClick(): void {\n if (this.disabled)\n return;\n\n this.dispatchEvent(new CustomEvent<MenuItemCommandDetail>(`command`, {\n detail: { command: this.command, args: this.commandArgs },\n bubbles: true,\n composed: true,\n }));\n }\n\n private _resolvedLabel(): string {\n if (this.label)\n return this.label;\n if (this.registry && this.command) {\n return this.registry.get(this.command)?.label ?? ``;\n }\n return ``;\n }\n\n private _resolvedIcon(): string | null {\n if (this.iconName)\n return this.iconName;\n if (this.registry && this.command) {\n return this.registry.get(this.command)?.icon ?? null;\n }\n return null;\n }\n\n willUpdate(changedProperties: Map<string, unknown>): void {\n super.willUpdate(changedProperties);\n const resolvedIcon = this._resolvedIcon();\n if (resolvedIcon && !this.iconName) {\n this.setAttribute(`data-icon-section`, ``);\n } else if (!resolvedIcon && !this.iconName) {\n this.removeAttribute(`data-icon-section`);\n }\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n }\n\n private _getShortcut(): string | null {\n if (!this.keyboardManager || !this.command)\n return null;\n const bindings = (this.keyboardManager as any).getBindings?.() ?? [];\n const binding = bindings.find((b: any) => b.commandId === this.command);\n if (!binding)\n return null;\n const mods = Array.from(binding.modifiers ?? [], (m: string) =>\n ({ ctrl: `⌃`, shift: `⇧`, alt: `⌥`, meta: `⌘` })[m] ?? m);\n const key = binding.key?.length === 1 ? binding.key.toUpperCase() : binding.key;\n return [...mods, key].join(``);\n }\n\n static override styles = [themeFallbacks, tickledItemStyles, css`\n :host {\n display: block;\n }\n\n .item {\n display: flex !important;\n align-items: center;\n padding: 6px var(--space-m);\n font-size: var(--text-m);\n background: var(--item-bg, transparent);\n border: var(--item-border, 1px solid transparent);\n color: var(--item-text, inherit);\n }\n\n :host(.tickled) .item {\n background: var(--item-bg-tickled);\n border: var(--item-border-tickled);\n color: var(--item-text-tickled);\n }\n\n :host(:focus) {\n outline: none;\n }\n\n .item.disabled {\n opacity: var(--disabled-opacity);\n cursor: default;\n }\n\n .item.disabled:hover {\n background: transparent;\n }\n\n .icon-slot {\n width: 0;\n overflow: hidden;\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n\n :host([icon-name]) .icon-slot,\n :host([data-icon-section]) .icon-slot {\n width: 1em;\n height: 1em;\n margin-right: var(--space-s);\n }\n\n .label {\n flex: 1;\n }\n\n .shortcut {\n margin-left: auto;\n color: var(--surface-muted-text);\n font-size: var(--text-s);\n }\n\n .arrow {\n color: var(--surface-muted-text);\n margin-left: var(--space-m);\n }\n `];\n\n render() {\n const shortcut = this._getShortcut();\n const resolvedIcon = this._resolvedIcon();\n return html`\n <div \n class=\"item ${this.disabled ? `disabled` : ``}\"\n @click=${this.handleClick}\n @mouseenter=${this._handleMouseEnter}\n @mouseleave=${this._handleMouseLeave}\n tabindex=\"${this.disabled ? -1 : 0}\"\n role=\"menuitem\"\n aria-haspopup=\"${this._hasChildren ? `true` : `false`}\"\n aria-expanded=\"${this.submenuPopover?.matches(`:popover-open`) ?? false}\"\n >\n <span class=\"icon-slot\">${resolvedIcon ? html`<ixfx-icon name=\"${resolvedIcon}\"></ixfx-icon>` : null}</span>\n <span class=\"label\"><slot></slot>${this._resolvedLabel()}</span>\n ${shortcut ? html`<span class=\"shortcut\">${shortcut}</span>` : null}\n ${this._hasChildren ? html`<span class=\"arrow\"><ixfx-icon name=\"chevron-right\"></ixfx-icon></span>` : null}\n </div>\n <slot @slotchange=${this._handleSlotChange}></slot>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-menu-item': MenuItem;\n }\n}\n"],"mappings":"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"}
package/dist/menu.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { i as MenuContainer, n as MenuTrigger, t as MenuItem } from "./menu-item-DlxAb0Xr.js";
2
- import { a as menuFromTree, c as MenuSeparator, d as MenuCheckItem, f as MenuBar, i as MenuFromTreeOptions, l as MenuSubTrigger, n as MenuRadioGroup, o as menuFromTreeToElements, r as MenuRadioItem, s as MenuHeader, u as MenuCommandController } from "./index-CDllxjVG.js";
1
+ import { i as MenuContainer, n as MenuTrigger, t as MenuItem } from "./menu-item-BbgdcwBX.js";
2
+ import { a as menuFromTree, c as MenuSeparator, d as MenuCheckItem, f as MenuBar, i as MenuFromTreeOptions, l as MenuSubTrigger, n as MenuRadioGroup, o as menuFromTreeToElements, r as MenuRadioItem, s as MenuHeader, u as MenuCommandController } from "./index-DyTSt9OK.js";
3
3
  export { MenuBar, MenuCheckItem, MenuCommandController, MenuContainer, type MenuFromTreeOptions, MenuHeader, MenuItem, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubTrigger, MenuTrigger, menuFromTree, menuFromTreeToElements };
package/dist/menu.js CHANGED
@@ -1,3 +1,3 @@
1
- import { n as MenuTrigger, r as MenuContainer, t as MenuItem } from "./menu-item-JcpHCyF0.js";
2
- import { a as menuFromTreeToElements, c as MenuSubTrigger, d as MenuBar, i as menuFromTree, l as MenuCommandController, n as MenuRadioGroup, o as MenuHeader, r as MenuRadioItem, s as MenuSeparator, u as MenuCheckItem } from "./menu-BHT6HRND.js";
1
+ import { n as MenuTrigger, r as MenuContainer, t as MenuItem } from "./menu-item-CfndBGO8.js";
2
+ import { a as menuFromTreeToElements, c as MenuSubTrigger, d as MenuBar, i as menuFromTree, l as MenuCommandController, n as MenuRadioGroup, o as MenuHeader, r as MenuRadioItem, s as MenuSeparator, u as MenuCheckItem } from "./menu-CsBUyUuS.js";
3
3
  export { MenuBar, MenuCheckItem, MenuCommandController, MenuContainer, MenuHeader, MenuItem, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubTrigger, MenuTrigger, menuFromTree, menuFromTreeToElements };