@ixfx/components 0.5.8 → 0.5.10

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 (53) hide show
  1. package/bundle/index.d.ts +25 -1
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +67 -11
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.d.ts +1 -1
  6. package/dist/{button-CU8eLcxB.js → button-dwmqCXHM.js} +11 -1
  7. package/dist/button-dwmqCXHM.js.map +1 -0
  8. package/dist/button.d.ts +2 -1
  9. package/dist/button.d.ts.map +1 -1
  10. package/dist/button.js +1 -1
  11. package/dist/colour-picker.d.ts +1 -1
  12. package/dist/crumbs.d.ts +1 -1
  13. package/dist/{icon-DpA9x2Ve.d.ts → icon-BUwP1CZ1.d.ts} +2 -2
  14. package/dist/icon-BUwP1CZ1.d.ts.map +1 -0
  15. package/dist/icons.d.ts +2 -2
  16. package/dist/{index-DfEkTGvT.d.ts → index-B1UKcA7l.d.ts} +3 -3
  17. package/dist/{index-DfEkTGvT.d.ts.map → index-B1UKcA7l.d.ts.map} +1 -1
  18. package/dist/{index-D_ftz_IT.d.ts → index-BKAlRgbq.d.ts} +2 -2
  19. package/dist/{index-D_ftz_IT.d.ts.map → index-BKAlRgbq.d.ts.map} +1 -1
  20. package/dist/{index-CoqtMSd9.d.ts → index-BUB5SICW.d.ts} +2 -2
  21. package/dist/{index-CoqtMSd9.d.ts.map → index-BUB5SICW.d.ts.map} +1 -1
  22. package/dist/{index-BtGFYfaK.d.ts → index-RqMh1i-O.d.ts} +2 -2
  23. package/dist/{index-BtGFYfaK.d.ts.map → index-RqMh1i-O.d.ts.map} +1 -1
  24. package/dist/index.d.ts +11 -10
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +22 -2
  27. package/dist/index.js.map +1 -1
  28. package/dist/{labelled-input-base-DiTme1JO.d.ts → labelled-input-base-Dp_9KP0G.d.ts} +2 -2
  29. package/dist/{labelled-input-base-DiTme1JO.d.ts.map → labelled-input-base-Dp_9KP0G.d.ts.map} +1 -1
  30. package/dist/labelled-radial-input.d.ts +2 -2
  31. package/dist/labelled-radial-input.d.ts.map +1 -1
  32. package/dist/labelled-range-input.d.ts +1 -1
  33. package/dist/{menu-item-DSyf9f_L.d.ts → menu-item-CQ4Qg731.d.ts} +2 -2
  34. package/dist/{menu-item-DSyf9f_L.d.ts.map → menu-item-CQ4Qg731.d.ts.map} +1 -1
  35. package/dist/menu.d.ts +2 -2
  36. package/dist/panel.d.ts +1 -1
  37. package/dist/panel.d.ts.map +1 -1
  38. package/dist/panel.js +1 -2
  39. package/dist/panel.js.map +1 -1
  40. package/dist/{tab-list-BohmbvqF.d.ts → tab-list-VtWT-_FG.d.ts} +2 -2
  41. package/dist/{tab-list-BohmbvqF.d.ts.map → tab-list-VtWT-_FG.d.ts.map} +1 -1
  42. package/dist/tabs.d.ts +1 -1
  43. package/dist/{tree-KAXDGm7w.js → tree-CL-txefQ.js} +37 -10
  44. package/dist/tree-CL-txefQ.js.map +1 -0
  45. package/dist/tree.d.ts +23 -1
  46. package/dist/tree.d.ts.map +1 -1
  47. package/dist/tree.js +1 -1
  48. package/docs-user/tree.md +38 -0
  49. package/docs-user/vertical-list.md +23 -0
  50. package/package.json +1 -1
  51. package/dist/button-CU8eLcxB.js.map +0 -1
  52. package/dist/icon-DpA9x2Ve.d.ts.map +0 -1
  53. package/dist/tree-KAXDGm7w.js.map +0 -1
@@ -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(): typeof nothing | import("lit").TemplateResult<1>;
36
+ protected _renderEditableNumber(): import("lit").TemplateResult<1> | typeof nothing;
37
37
  updated(changedProperties: Map<string, unknown>): void;
38
38
  }
39
39
  //#endregion
40
40
  export { LabelledInputBase as t };
41
- //# sourceMappingURL=labelled-input-base-DiTme1JO.d.ts.map
41
+ //# sourceMappingURL=labelled-input-base-Dp_9KP0G.d.ts.map
@@ -1 +1 @@
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;;YAWxC,qBAAsB,GAAG;IAAc;;YAavC,qBAAsB,GAAG;IAAc;;YAYvC,WAAW;YAYX,gCAAqB,wBAAA;EAuBtB,QAAQ,mBAAmB"}
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;;YAWxC,qBAAsB,GAAG;IAAc;;YAavC,qBAAsB,GAAG;IAAc;;YAYvC,WAAW;YAYX,uCAAqB,2BAAA;EAuBtB,QAAQ,mBAAmB"}
@@ -1,4 +1,4 @@
1
- import { t as LabelledInputBase } from "./labelled-input-base-DiTme1JO.js";
1
+ import { t as LabelledInputBase } from "./labelled-input-base-Dp_9KP0G.js";
2
2
  import { i as MarkerStyle, l as ValueMode } from "./radial-input-BhZeyyP-.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(): typeof nothing | import("lit").TemplateResult<1>;
22
+ protected _renderEditableNumber(): import("lit").TemplateResult<1> | typeof nothing;
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,gCAAqB,wBAAA;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,uCAAqB,2BAAA;EA0B/B,wBAAM;UA6BP;SAYD,QAAQ;;QA0ET;YACI;IACR,8BAA8B"}
@@ -1,2 +1,2 @@
1
- import { t as LabelledRangeInput } from "./index-CoqtMSd9.js";
1
+ import { t as LabelledRangeInput } from "./index-BUB5SICW.js";
2
2
  export { LabelledRangeInput };
@@ -1,4 +1,4 @@
1
- import "./icon-DpA9x2Ve.js";
1
+ import "./icon-BUwP1CZ1.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
@@ -124,4 +124,4 @@ declare global {
124
124
  }
125
125
  //#endregion
126
126
  export { MenuContainer as i, MenuTrigger as n, MenuTriggerCommandDetail as r, MenuItem as t };
127
- //# sourceMappingURL=menu-item-DSyf9f_L.d.ts.map
127
+ //# sourceMappingURL=menu-item-CQ4Qg731.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"menu-item-DSyf9f_L.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;;;;;KCxWtB;KACA;KAEO;WACD;WACA;WACA;;cAME,oBAAoB;EACH,MAAM;EACN;EACI,WAAW;EACX,kBAAkB;EACtB,WAAW;UAEtB;UACA;UACA;UAEc;UACN;iBAEV;UAEP;UACA;EAER;EAOA;EAQA;EAkBA,QAAQ,mBAAmB;UAMnB;UAYA;UAWA;UAOA;MAKJ;EAIJ;EAIA;EAIA;UAIQ;UAgBA;UAQA;UAYA;UAUA;UAYA;UAOA;UAeA;UAeA;UAkBA;SAiBD,sBAAM;EAoEb,wBAAM;;QAwBA;YACI;IACR,qBAAqB;;;;;cCjVZ,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"}
1
+ {"version":3,"file":"menu-item-CQ4Qg731.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;;;;;KCxWtB;KACA;KAEO;WACD;WACA;WACA;;cAME,oBAAoB;EACH,MAAM;EACN;EACI,WAAW;EACX,kBAAkB;EACtB,WAAW;UAEtB;UACA;UACA;UAEc;UACN;iBAEV;UAEP;UACA;EAER;EAOA;EAQA;EAkBA,QAAQ,mBAAmB;UAMnB;UAYA;UAWA;UAOA;MAKJ;EAIJ;EAIA;EAIA;UAIQ;UAgBA;UAQA;UAYA;UAUA;UAYA;UAOA;UAeA;UAeA;UAkBA;SAiBD,sBAAM;EAoEb,wBAAM;;QAwBA;YACI;IACR,qBAAqB;;;;;cCjVZ,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"}
package/dist/menu.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { i as MenuContainer, n as MenuTrigger, t as MenuItem } from "./menu-item-DSyf9f_L.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-DfEkTGvT.js";
1
+ import { i as MenuContainer, n as MenuTrigger, t as MenuItem } from "./menu-item-CQ4Qg731.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-B1UKcA7l.js";
3
3
  export { MenuBar, MenuCheckItem, MenuCommandController, MenuContainer, type MenuFromTreeOptions, MenuHeader, MenuItem, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubTrigger, MenuTrigger, menuFromTree, menuFromTreeToElements };
package/dist/panel.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import "./icon-DpA9x2Ve.js";
1
+ import "./icon-BUwP1CZ1.js";
2
2
  import { LitElement } from "lit";
3
3
  //#region src/panel/panel.d.ts
4
4
  type PanelOrientation = `horizontal` | `vertical`;
@@ -1 +1 @@
1
- {"version":3,"file":"panel.d.ts","names":[],"sources":["../src/panel/panel.ts"],"mappings":";;;KAOY;KACA;KACA;UAEK;WACN;;KAGC,mBAAmB,YAAY;KAC/B,kBAAkB;UAEb;EACf,QAAQ;EACR,OAAO;;cAII,qBAAqB;EACY;EACyB,aAAa;EACrD;EACD;EACwB;EACS,mBAAmB;EACf,SAAS;UAEzD;UAET;UAWA;UAUA;YAIW,QAAQ,SAAS;YAOjB,wBAAM;SAyDT,sBAAM;;QAkShB;YACI;IACR,cAAc;;;UAID;EACf,oBAAoB,gBAAgB,sBAClC,MAAM,GACN,WAAW,MAAM,cAAc,OAAO,qBAAqB,aAC3D,oBAAoB,sCAEpB,cACA,UAAU,oCACV,oBAAoB"}
1
+ {"version":3,"file":"panel.d.ts","names":[],"sources":["../src/panel/panel.ts"],"mappings":";;;KAOY;KACA;KACA;UAEK;WACN;;KAGC,mBAAmB,YAAY;KAC/B,kBAAkB;UAEb;EACf,QAAQ;EACR,OAAO;;cAII,qBAAqB;EACY;EACyB,aAAa;EACrD;EACD;EACwB;EACS,mBAAmB;EACf,SAAS;UAEzD;UAET;UAWA;UAUA;YAIW,QAAQ,SAAS;YAOjB,wBAAM;SAyDT,sBAAM;;QAiShB;YACI;IACR,cAAc;;;UAID;EACf,oBAAoB,gBAAgB,sBAClC,MAAM,GACN,WAAW,MAAM,cAAc,OAAO,qBAAqB,aAC3D,oBAAoB,sCAEpB,cACA,UAAU,oCACV,oBAAoB"}
package/dist/panel.js CHANGED
@@ -235,11 +235,10 @@ let PanelElement = class PanelElement extends LitElement {
235
235
 
236
236
  .content-inner {
237
237
  box-shadow: var(--deboss-3);
238
-
239
238
  min-height: 0;
240
239
  min-width: 0;
241
240
  overflow: hidden;
242
- padding: var(--space-m);
241
+ padding: var(--space-s);
243
242
  transform: translateY(-100%);
244
243
  transition: transform var(--transition, 0.2s ease-out);
245
244
  }
package/dist/panel.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"panel.js","names":["customElement"],"sources":["../src/panel/panel.ts"],"sourcesContent":["/* eslint-disable ts/no-unsafe-declaration-merging */\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type PanelOrientation = `horizontal` | `vertical`;\nexport type PanelVariant = `titlebar` | `midline`;\nexport type PanelToggleInteraction = `implicit` | `explicit` | `disabled`;\n\nexport interface PanelToggleDetail {\n readonly collapsed: boolean;\n}\n\nexport type PanelToggleEvent = CustomEvent<PanelToggleDetail>;\nexport type PanelCloseEvent = CustomEvent<void>;\n\nexport interface PanelElementEventMap {\n toggle: PanelToggleEvent;\n close: PanelCloseEvent;\n}\n\n@customElement(`ixfx-panel`)\nexport class PanelElement extends LitElement {\n @property({ type: Boolean, reflect: true }) collapsed = false;\n @property({ type: String, attribute: `orientation`, reflect: true }) orientation: PanelOrientation = `horizontal`;\n @property({ type: Boolean }) closable = false;\n @property({ type: String }) title = ``;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n @property({ type: String, attribute: `toggle-interaction` }) toggleInteraction: PanelToggleInteraction = `implicit`;\n @property({ type: String, attribute: `variant`, reflect: true }) variant: PanelVariant = `titlebar`;\n\n @state() private _isVertical = false;\n\n private _onToggleClick() {\n this.collapsed = !this.collapsed;\n this.dispatchEvent(\n new CustomEvent<PanelToggleDetail>(`toggle`, {\n detail: { collapsed: this.collapsed },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _onCloseClick() {\n this.dispatchEvent(\n new CustomEvent<void>(`close`, {\n bubbles: true,\n composed: true,\n }),\n );\n this.remove();\n }\n\n private _getCaretIcon(): string {\n return `chevron-down`;\n }\n\n protected override updated(changed: Map<string, unknown>): void {\n super.updated(changed);\n if (changed.has(`orientation`)) {\n this._isVertical = this.orientation === `vertical`;\n }\n }\n\n protected override render() {\n const caretIcon = this._getCaretIcon();\n const showCaret = this.toggleInteraction !== `disabled`;\n const implicitToggle = this.toggleInteraction === `implicit`;\n\n const caretRotation = this._isVertical\n ? (this.collapsed ? `` : `-90deg`)\n : (this.collapsed ? `-90deg` : ``);\n\n return html`\n <div\n class=\"titlebar\"\n role=\"toolbar\"\n @click=${implicitToggle ? this._onToggleClick : nothing}\n >\n <div class=\"title-text-wrapper\">\n ${this.iconName ? html`<ixfx-icon class=\"title-icon\" name=${this.iconName}></ixfx-icon>` : nothing}\n <span class=\"title-text\">${this.title}</span>\n </div>\n\n <div class=\"toolbar\" @click=${(e: Event) => e.stopPropagation()}>\n <slot name=\"toolbar\"></slot>\n ${this.closable\n ? html`\n <button\n class=\"close-btn\"\n type=\"button\"\n aria-label=\"Close panel\"\n @click=${this._onCloseClick}\n >\n <ixfx-icon name=\"close\"></ixfx-icon>\n </button>\n `\n : nothing}\n ${showCaret\n ? html`\n <button\n class=\"caret-btn\"\n type=\"button\"\n aria-label=${this.collapsed ? `Expand panel` : `Collapse panel`}\n @click=${this._onToggleClick}\n >\n <ixfx-icon name=${caretIcon} prominence .rotate=${caretRotation.length > 0 ? caretRotation : nothing}></ixfx-icon>\n </button>\n `\n : nothing}\n </div>\n </div>\n\n <div class=\"content-wrapper\" ?expanded=${!this.collapsed}>\n <div class=\"content-inner\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n\n static override styles = [themeFallbacks, css`\n :host {\n display: flex;\n flex-direction: column;\n background: var(--surface-3);\n border: var(--border-subtle);\n border-radius: var(--radius-m);\n overflow: hidden;\n box-sizing: border-box;\n }\n\n :host([orientation=\"vertical\"]) {\n flex-direction: row;\n align-self: flex-start;\n min-width: 0 !important;\n flex-shrink: 1;\n }\n\n .titlebar {\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: var(--space-s) var(--space-m);\n background: var(--surface-4);\n color: var(--surface-3-text);\n min-height: 2em;\n flex-shrink: 0;\n }\n\n :host([orientation=\"vertical\"]) .titlebar {\n flex-direction: row;\n min-width: 2em;\n writing-mode: vertical-rl;\n text-orientation: mixed;\n }\n\n .caret-btn,\n .close-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: var(--space-xs);\n margin: 0;\n cursor: pointer;\n color: inherit;\n border-radius: var(--radius-s);\n transition: background var(--transition);\n opacity: var(--prominence-idle-opacity);\n }\n\n .caret-btn:hover,\n .close-btn:hover {\n background: var(--surface-5);\n opacity: var(--prominence-tickled-opacity);\n\n }\n\n .caret-btn:focus-visible,\n .close-btn:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 1px;\n }\n\n ixfx-icon {\n width: 1.25em;\n height: 1.25em;\n transition: transform var(--transition);\n }\n\n .title-icon {\n flex-shrink: 0;\n }\n\n .title-text {\n flex: 1;\n padding-left: 1ch;\n font-family: var(--font-family);\n font-size: var(--text-m);\n font-weight: var(--font-weight-bold, 600);\n white-space: nowrap;\n overflow: hidden;\n align-self: center;\n text-overflow: ellipsis;\n user-select: none;\n -webkit-user-select: none;\n }\n\n :host([toggle-interaction=\"implicit\"]) .titlebar {\n cursor: pointer;\n }\n\n :host([orientation=\"vertical\"]) .title-text {\n writing-mode: vertical-rl;\n padding-left: 0;\n padding-bottom: 1ch;\n text-orientation: mixed;\n transform: rotate(180deg);\n }\n\n .toolbar {\n display: flex;\n align-items: center;\n gap: var(--space-xs);\n margin-left: auto;\n }\n\n :host([orientation=\"vertical\"]) .toolbar {\n flex-direction: column;\n margin-left: 0;\n margin-top: auto;\n writing-mode: horizontal-tb;\n }\n\n slot[name=\"toolbar\"] {\n display: contents;\n }\n\n ::slotted(slot[name=\"toolbar\"]) {\n display: contents;\n }\n\n .content-wrapper {\n interpolate-size: allow-keywords;\n overflow: hidden;\n height: 0;\n transition: height var(--transition, 0.2s ease-out);\n background: var(--surface-3);\n \n }\n\n .content-wrapper[expanded] {\n height: auto;\n }\n\n :host([orientation=\"vertical\"]) .content-wrapper {\n height: unset;\n width: 0;\n transition: width var(--transition, 0.2s ease-out);\n }\n\n :host([orientation=\"vertical\"]) .content-wrapper[expanded] {\n width: auto;\n }\n\n .content-inner {\n box-shadow: var(--deboss-3);\n\n min-height: 0;\n min-width: 0;\n overflow: hidden;\n padding: var(--space-m);\n transform: translateY(-100%);\n transition: transform var(--transition, 0.2s ease-out);\n }\n\n .content-wrapper[expanded] .content-inner {\n transform: translateY(0);\n }\n\n :host([orientation=\"vertical\"]) .content-inner {\n width: max-content;\n height:100%;\n transform: translateX(-100%);\n }\n\n :host([orientation=\"vertical\"]) .content-wrapper[expanded] .content-inner {\n transform: translateX(0);\n }\n\n .title-text-wrapper {\n display:flex;\n padding: 0 var(--space-s);\n }\n\n /* === Midline variant === */\n\n :host([variant=\"midline\"]) {\n border: none !important;\n border-radius: 0 !important;\n background: transparent;\n }\n\n :host([variant=\"midline\"][orientation=\"horizontal\"]) .titlebar,\n :host([variant=\"midline\"][orientation=\"vertical\"]) .titlebar {\n background: transparent;\n padding: var(--space-xs) var(--space-m);\n min-height: unset;\n position: relative;\n }\n\n :host([variant=\"midline\"][orientation=\"vertical\"]) .titlebar {\n padding: var(--space-m) var(--space-xs);\n min-width: unset;\n }\n\n :host([variant=\"midline\"]) .title-text-wrapper {\n position: relative;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: var(--space-s);\n background: var(--surface-3);\n }\n\n :host([variant=\"midline\"]) .title-text {\n font-weight: normal;\n color: var(--surface-3-text);\n padding: 0 0.5ch 0 0.5ch;\n background: transparent;\n box-shadow: none;\n flex: unset;\n width: auto;\n white-space: nowrap;\n }\n\n :host([variant=\"midline\"]) .title-icon {\n background: transparent;\n flex-shrink: 0;\n }\n\n :host([variant=\"midline\"]) .caret-btn {\n position: relative;\n z-index: 1;\n background: var(--surface-3);\n opacity: 1;\n }\n\n :host([variant=\"midline\"][orientation=\"vertical\"]) .title-text {\n transform: rotate(180deg);\n padding: 0.5ch 0 0.5ch 0ch;\n }\n\n :host([variant=\"midline\"]) .toolbar {\n position: relative;\n z-index: 2;\n background: var(--surface-3);\n margin-left: 0;\n }\n\n :host([variant=\"midline\"][orientation=\"horizontal\"]) .toolbar {\n margin-left: auto;\n }\n\n /* Debossed line runs from after title-text to before toolbar */\n :host([variant=\"midline\"]) .titlebar::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n height: 1px;\n transform: translateY(-50%);\n background: var(--surface-2);\n box-shadow:\n 0 -1px 0 var(--surface-5),\n 0 1px 0 var(--surface-1);\n z-index: 0;\n }\n\n /* For vertical midline, line runs vertically */\n :host([variant=\"midline\"][orientation=\"vertical\"]) .titlebar::after {\n top: 0;\n bottom: 0;\n left: 50%;\n right: unset;\n width: 1px;\n height: 100%;\n transform: translateX(-50%);\n box-shadow:\n -1px 0 0 var(--surface-5),\n 1px 0 0 var(--surface-1);\n }\n\n :host([variant=\"midline\"]) .content-inner {\n box-shadow: none;\n background: var(--surface-3);\n }\n\n :host([variant=\"midline\"]) .content-wrapper {\n background: transparent;\n }\n\n :host([variant=\"midline\"][orientation=\"vertical\"]) .content-wrapper {\n background: transparent;\n }\n `];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-panel': PanelElement;\n }\n}\n\nexport interface PanelElement {\n addEventListener: (<K extends keyof PanelElementEventMap>(\n type: K,\n listener: (this: PanelElement, event: PanelElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"panel.js","names":["customElement"],"sources":["../src/panel/panel.ts"],"sourcesContent":["/* eslint-disable ts/no-unsafe-declaration-merging */\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type PanelOrientation = `horizontal` | `vertical`;\nexport type PanelVariant = `titlebar` | `midline`;\nexport type PanelToggleInteraction = `implicit` | `explicit` | `disabled`;\n\nexport interface PanelToggleDetail {\n readonly collapsed: boolean;\n}\n\nexport type PanelToggleEvent = CustomEvent<PanelToggleDetail>;\nexport type PanelCloseEvent = CustomEvent<void>;\n\nexport interface PanelElementEventMap {\n toggle: PanelToggleEvent;\n close: PanelCloseEvent;\n}\n\n@customElement(`ixfx-panel`)\nexport class PanelElement extends LitElement {\n @property({ type: Boolean, reflect: true }) collapsed = false;\n @property({ type: String, attribute: `orientation`, reflect: true }) orientation: PanelOrientation = `horizontal`;\n @property({ type: Boolean }) closable = false;\n @property({ type: String }) title = ``;\n @property({ type: String, attribute: `icon-name` }) iconName = ``;\n @property({ type: String, attribute: `toggle-interaction` }) toggleInteraction: PanelToggleInteraction = `implicit`;\n @property({ type: String, attribute: `variant`, reflect: true }) variant: PanelVariant = `titlebar`;\n\n @state() private _isVertical = false;\n\n private _onToggleClick() {\n this.collapsed = !this.collapsed;\n this.dispatchEvent(\n new CustomEvent<PanelToggleDetail>(`toggle`, {\n detail: { collapsed: this.collapsed },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _onCloseClick() {\n this.dispatchEvent(\n new CustomEvent<void>(`close`, {\n bubbles: true,\n composed: true,\n }),\n );\n this.remove();\n }\n\n private _getCaretIcon(): string {\n return `chevron-down`;\n }\n\n protected override updated(changed: Map<string, unknown>): void {\n super.updated(changed);\n if (changed.has(`orientation`)) {\n this._isVertical = this.orientation === `vertical`;\n }\n }\n\n protected override render() {\n const caretIcon = this._getCaretIcon();\n const showCaret = this.toggleInteraction !== `disabled`;\n const implicitToggle = this.toggleInteraction === `implicit`;\n\n const caretRotation = this._isVertical\n ? (this.collapsed ? `` : `-90deg`)\n : (this.collapsed ? `-90deg` : ``);\n\n return html`\n <div\n class=\"titlebar\"\n role=\"toolbar\"\n @click=${implicitToggle ? this._onToggleClick : nothing}\n >\n <div class=\"title-text-wrapper\">\n ${this.iconName ? html`<ixfx-icon class=\"title-icon\" name=${this.iconName}></ixfx-icon>` : nothing}\n <span class=\"title-text\">${this.title}</span>\n </div>\n\n <div class=\"toolbar\" @click=${(e: Event) => e.stopPropagation()}>\n <slot name=\"toolbar\"></slot>\n ${this.closable\n ? html`\n <button\n class=\"close-btn\"\n type=\"button\"\n aria-label=\"Close panel\"\n @click=${this._onCloseClick}\n >\n <ixfx-icon name=\"close\"></ixfx-icon>\n </button>\n `\n : nothing}\n ${showCaret\n ? html`\n <button\n class=\"caret-btn\"\n type=\"button\"\n aria-label=${this.collapsed ? `Expand panel` : `Collapse panel`}\n @click=${this._onToggleClick}\n >\n <ixfx-icon name=${caretIcon} prominence .rotate=${caretRotation.length > 0 ? caretRotation : nothing}></ixfx-icon>\n </button>\n `\n : nothing}\n </div>\n </div>\n\n <div class=\"content-wrapper\" ?expanded=${!this.collapsed}>\n <div class=\"content-inner\">\n <slot></slot>\n </div>\n </div>\n `;\n }\n\n static override styles = [themeFallbacks, css`\n :host {\n display: flex;\n flex-direction: column;\n background: var(--surface-3);\n border: var(--border-subtle);\n border-radius: var(--radius-m);\n overflow: hidden;\n box-sizing: border-box;\n }\n\n :host([orientation=\"vertical\"]) {\n flex-direction: row;\n align-self: flex-start;\n min-width: 0 !important;\n flex-shrink: 1;\n }\n\n .titlebar {\n display: flex;\n flex-direction: row;\n align-items: center;\n padding: var(--space-s) var(--space-m);\n background: var(--surface-4);\n color: var(--surface-3-text);\n min-height: 2em;\n flex-shrink: 0;\n }\n\n :host([orientation=\"vertical\"]) .titlebar {\n flex-direction: row;\n min-width: 2em;\n writing-mode: vertical-rl;\n text-orientation: mixed;\n }\n\n .caret-btn,\n .close-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n background: none;\n border: none;\n padding: var(--space-xs);\n margin: 0;\n cursor: pointer;\n color: inherit;\n border-radius: var(--radius-s);\n transition: background var(--transition);\n opacity: var(--prominence-idle-opacity);\n }\n\n .caret-btn:hover,\n .close-btn:hover {\n background: var(--surface-5);\n opacity: var(--prominence-tickled-opacity);\n\n }\n\n .caret-btn:focus-visible,\n .close-btn:focus-visible {\n outline: 2px solid var(--accent);\n outline-offset: 1px;\n }\n\n ixfx-icon {\n width: 1.25em;\n height: 1.25em;\n transition: transform var(--transition);\n }\n\n .title-icon {\n flex-shrink: 0;\n }\n\n .title-text {\n flex: 1;\n padding-left: 1ch;\n font-family: var(--font-family);\n font-size: var(--text-m);\n font-weight: var(--font-weight-bold, 600);\n white-space: nowrap;\n overflow: hidden;\n align-self: center;\n text-overflow: ellipsis;\n user-select: none;\n -webkit-user-select: none;\n }\n\n :host([toggle-interaction=\"implicit\"]) .titlebar {\n cursor: pointer;\n }\n\n :host([orientation=\"vertical\"]) .title-text {\n writing-mode: vertical-rl;\n padding-left: 0;\n padding-bottom: 1ch;\n text-orientation: mixed;\n transform: rotate(180deg);\n }\n\n .toolbar {\n display: flex;\n align-items: center;\n gap: var(--space-xs);\n margin-left: auto;\n }\n\n :host([orientation=\"vertical\"]) .toolbar {\n flex-direction: column;\n margin-left: 0;\n margin-top: auto;\n writing-mode: horizontal-tb;\n }\n\n slot[name=\"toolbar\"] {\n display: contents;\n }\n\n ::slotted(slot[name=\"toolbar\"]) {\n display: contents;\n }\n\n .content-wrapper {\n interpolate-size: allow-keywords;\n overflow: hidden;\n height: 0;\n transition: height var(--transition, 0.2s ease-out);\n background: var(--surface-3);\n \n }\n\n .content-wrapper[expanded] {\n height: auto;\n }\n\n :host([orientation=\"vertical\"]) .content-wrapper {\n height: unset;\n width: 0;\n transition: width var(--transition, 0.2s ease-out);\n }\n\n :host([orientation=\"vertical\"]) .content-wrapper[expanded] {\n width: auto;\n }\n\n .content-inner {\n box-shadow: var(--deboss-3);\n min-height: 0;\n min-width: 0;\n overflow: hidden;\n padding: var(--space-s);\n transform: translateY(-100%);\n transition: transform var(--transition, 0.2s ease-out);\n }\n\n .content-wrapper[expanded] .content-inner {\n transform: translateY(0);\n }\n\n :host([orientation=\"vertical\"]) .content-inner {\n width: max-content;\n height:100%;\n transform: translateX(-100%);\n }\n\n :host([orientation=\"vertical\"]) .content-wrapper[expanded] .content-inner {\n transform: translateX(0);\n }\n\n .title-text-wrapper {\n display:flex;\n padding: 0 var(--space-s);\n }\n\n /* === Midline variant === */\n\n :host([variant=\"midline\"]) {\n border: none !important;\n border-radius: 0 !important;\n background: transparent;\n }\n\n :host([variant=\"midline\"][orientation=\"horizontal\"]) .titlebar,\n :host([variant=\"midline\"][orientation=\"vertical\"]) .titlebar {\n background: transparent;\n padding: var(--space-xs) var(--space-m);\n min-height: unset;\n position: relative;\n }\n\n :host([variant=\"midline\"][orientation=\"vertical\"]) .titlebar {\n padding: var(--space-m) var(--space-xs);\n min-width: unset;\n }\n\n :host([variant=\"midline\"]) .title-text-wrapper {\n position: relative;\n z-index: 1;\n display: flex;\n align-items: center;\n gap: var(--space-s);\n background: var(--surface-3);\n }\n\n :host([variant=\"midline\"]) .title-text {\n font-weight: normal;\n color: var(--surface-3-text);\n padding: 0 0.5ch 0 0.5ch;\n background: transparent;\n box-shadow: none;\n flex: unset;\n width: auto;\n white-space: nowrap;\n }\n\n :host([variant=\"midline\"]) .title-icon {\n background: transparent;\n flex-shrink: 0;\n }\n\n :host([variant=\"midline\"]) .caret-btn {\n position: relative;\n z-index: 1;\n background: var(--surface-3);\n opacity: 1;\n }\n\n :host([variant=\"midline\"][orientation=\"vertical\"]) .title-text {\n transform: rotate(180deg);\n padding: 0.5ch 0 0.5ch 0ch;\n }\n\n :host([variant=\"midline\"]) .toolbar {\n position: relative;\n z-index: 2;\n background: var(--surface-3);\n margin-left: 0;\n }\n\n :host([variant=\"midline\"][orientation=\"horizontal\"]) .toolbar {\n margin-left: auto;\n }\n\n /* Debossed line runs from after title-text to before toolbar */\n :host([variant=\"midline\"]) .titlebar::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n height: 1px;\n transform: translateY(-50%);\n background: var(--surface-2);\n box-shadow:\n 0 -1px 0 var(--surface-5),\n 0 1px 0 var(--surface-1);\n z-index: 0;\n }\n\n /* For vertical midline, line runs vertically */\n :host([variant=\"midline\"][orientation=\"vertical\"]) .titlebar::after {\n top: 0;\n bottom: 0;\n left: 50%;\n right: unset;\n width: 1px;\n height: 100%;\n transform: translateX(-50%);\n box-shadow:\n -1px 0 0 var(--surface-5),\n 1px 0 0 var(--surface-1);\n }\n\n :host([variant=\"midline\"]) .content-inner {\n box-shadow: none;\n background: var(--surface-3);\n }\n\n :host([variant=\"midline\"]) .content-wrapper {\n background: transparent;\n }\n\n :host([variant=\"midline\"][orientation=\"vertical\"]) .content-wrapper {\n background: transparent;\n }\n `];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-panel': PanelElement;\n }\n}\n\nexport interface PanelElement {\n addEventListener: (<K extends keyof PanelElementEventMap>(\n type: K,\n listener: (this: PanelElement, event: PanelElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import "./icon-DpA9x2Ve.js";
1
+ import "./icon-BUwP1CZ1.js";
2
2
  import { LitElement, PropertyValues } from "lit";
3
3
  import { CommandRegistry } from "@clinth/ui-commands";
4
4
  //#region src/tabs/tab-list-item.d.ts
@@ -71,4 +71,4 @@ declare global {
71
71
  }
72
72
  //#endregion
73
73
  export { TabListReorderDetail as a, TabListElement as i, TabListChangeEvent as n, TabListReorderEvent as o, TabListDragMode as r, TabListItemElement as s, TabListChangeDetail as t };
74
- //# sourceMappingURL=tab-list-BohmbvqF.d.ts.map
74
+ //# sourceMappingURL=tab-list-VtWT-_FG.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tab-list-BohmbvqF.d.ts","names":[],"sources":["../src/tabs/tab-list-item.ts","../src/tabs/tab-list.ts"],"mappings":";;;;;;;;;;cAgBa,2BAA2B;EAEtC;EAGA;EAGA;EAGA;EAGA,UAAU;UAEO;UACT;UACA;EAEC;EAQA;EAQA,QAAQ,SAAS;UAQlB;UAUA;EAWC,wBAAM;UAyBP;SAWQ,sBAAM;;QA0GhB;YACI;IACR,sBAAsB;;;;;;;;;;KCnNd;WACD;WACA;WACA;;KAGC,qBAAqB,YAAY;KAEjC;WACD;WACA;WACA;;KAGC,sBAAsB,YAAY;KAElC;cAMC,uBAAuB;;EAElC;EAGA;EAGA;EAGA,UAAU;EA2BD,wBAAM;EA4BN;EAQA,QAAQ,mBAAmB;EA8FpC,sBAAkB;EAwBlB,cAAc,IAAI;SAwaX,sBAAM;;QAgGP;YACI;IACR,iBAAiB"}
1
+ {"version":3,"file":"tab-list-VtWT-_FG.d.ts","names":[],"sources":["../src/tabs/tab-list-item.ts","../src/tabs/tab-list.ts"],"mappings":";;;;;;;;;;cAgBa,2BAA2B;EAEtC;EAGA;EAGA;EAGA;EAGA,UAAU;UAEO;UACT;UACA;EAEC;EAQA;EAQA,QAAQ,SAAS;UAQlB;UAUA;EAWC,wBAAM;UAyBP;SAWQ,sBAAM;;QA0GhB;YACI;IACR,sBAAsB;;;;;;;;;;KCnNd;WACD;WACA;WACA;;KAGC,qBAAqB,YAAY;KAEjC;WACD;WACA;WACA;;KAGC,sBAAsB,YAAY;KAElC;cAMC,uBAAuB;;EAElC;EAGA;EAGA;EAGA,UAAU;EA2BD,wBAAM;EA4BN;EAQA,QAAQ,mBAAmB;EA8FpC,sBAAkB;EAwBlB,cAAc,IAAI;SAwaX,sBAAM;;QAgGP;YACI;IACR,iBAAiB"}
package/dist/tabs.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as TabListReorderDetail, i as TabListElement, n as TabListChangeEvent, o as TabListReorderEvent, r as TabListDragMode, t as TabListChangeDetail } from "./tab-list-BohmbvqF.js";
1
+ import { a as TabListReorderDetail, i as TabListElement, n as TabListChangeEvent, o as TabListReorderEvent, r as TabListDragMode, t as TabListChangeDetail } from "./tab-list-VtWT-_FG.js";
2
2
  export { TabListChangeDetail, TabListChangeEvent, TabListDragMode, TabListElement, TabListReorderDetail, TabListReorderEvent };
@@ -1187,18 +1187,33 @@ let TreeListElement = class TreeListElement extends TreeBaseElement {
1187
1187
  `;
1188
1188
  if (this.interactionMode === `checked`) {
1189
1189
  const state = computeCheckboxState(node, this._selectedNodes);
1190
- return html`
1191
- <input
1192
- type="checkbox"
1193
- class="tree-checkbox"
1194
- .checked=${state === `checked`}
1195
- .indeterminate=${state === `indeterminate`}
1196
- aria-label="Select ${node.item.label}"
1197
- @click=${(e) => this._handleCheckboxClick(e, node, depth)}
1198
- />${caretAndLabel}`;
1190
+ return html`${this.#renderCheckbox(node, depth, state)}${caretAndLabel}`;
1199
1191
  }
1200
1192
  return caretAndLabel;
1201
1193
  }
1194
+ #renderCheckbox(node, depth, state) {
1195
+ const onClick = (e) => this._handleCheckboxClick(e, node, depth);
1196
+ if (this.checkboxRenderer) return html`
1197
+ <span
1198
+ class="tree-checkbox tree-checkbox-custom"
1199
+ part="checkbox"
1200
+ role="checkbox"
1201
+ tabindex="-1"
1202
+ aria-checked=${state === `indeterminate` ? `mixed` : state === `checked` ? `true` : `false`}
1203
+ aria-label="Select ${node.item.label}"
1204
+ @click=${onClick}
1205
+ >${this.checkboxRenderer(state)}</span>`;
1206
+ return html`
1207
+ <input
1208
+ type="checkbox"
1209
+ class="tree-checkbox"
1210
+ part="checkbox"
1211
+ .checked=${state === `checked`}
1212
+ .indeterminate=${state === `indeterminate`}
1213
+ aria-label="Select ${node.item.label}"
1214
+ @click=${onClick}
1215
+ />`;
1216
+ }
1202
1217
  _renderNode(node, depth) {
1203
1218
  const selected = this._isSelected(node);
1204
1219
  const tickled = this._isFocused(node);
@@ -1277,6 +1292,17 @@ let TreeListElement = class TreeListElement extends TreeBaseElement {
1277
1292
  pointer-events: auto;
1278
1293
  }
1279
1294
 
1295
+ .tree-checkbox-custom {
1296
+ display: inline-flex;
1297
+ align-items: center;
1298
+ justify-content: center;
1299
+ /* Reserves a click target even when the renderer returns empty content
1300
+ (e.g. the "nothing when unchecked" subtle style) — without an explicit
1301
+ size the empty span collapses to 0×0 and becomes unclickable. */
1302
+ width: var(--tree-checkbox-size, 14px);
1303
+ height: var(--tree-checkbox-size, 14px);
1304
+ }
1305
+
1280
1306
  /* In checked mode the checkbox communicates selection state —
1281
1307
  suppress the row highlight so it doesn't double-signal */
1282
1308
  :host([interaction-mode="checked"]) .item.selected {
@@ -1298,6 +1324,7 @@ let TreeListElement = class TreeListElement extends TreeBaseElement {
1298
1324
  ];
1299
1325
  }
1300
1326
  };
1327
+ __decorate([property({ attribute: false })], TreeListElement.prototype, "checkboxRenderer", void 0);
1301
1328
  TreeListElement = __decorate([safeCustomElement(`ixfx-tree-list`)], TreeListElement);
1302
1329
  //#endregion
1303
1330
  //#region src/tree/tree-controller.ts
@@ -1391,4 +1418,4 @@ var TreeController = class {
1391
1418
  //#endregion
1392
1419
  export { TreeDataModel as i, TreeListElement as n, TreeBaseElement as r, TreeController as t };
1393
1420
 
1394
- //# sourceMappingURL=tree-KAXDGm7w.js.map
1421
+ //# sourceMappingURL=tree-CL-txefQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-CL-txefQ.js","names":["#root","#loadChildren","#cache","#notify","#subscribers","#getAllNodes","#getFocusedIndex","#setFocusedIndex","#extendRangeSelection","#anchor","#toggleExpand","#toggleSelection","#abortPending","#clearSelectionInternal","#modelUnsubscribe","#ownedRegistry","#config","#canSelect","#dispatchSelect","#applyCheckedToggle","#applyExclusivity","#scrollKeyIntoView","#findNodePath","#pendingNode","#handleImplicitClick","#handleStandardClick","#handleManualClick","#handleExpandOnly","#getFlatIndexOf","#allDescendantsSelected","#pendingController","#invokeLoadChildren","#matchesFilter","#collapseSiblingsAtDepth","#findAncestorKeys","#findParent","#getVisibleNodes","#scrollTickledIntoView","#onKeyDown","#onDblClick","#renderNodes","customElement","#detectIcons","#depthsWithIcons","#renderCheckbox","customElement","#root","#element","#options","#connectSignal","#childrenOf","#nodeToTree","#findTreePath","#findInChildren","#toTreeNode","#identityToTreeNode"],"sources":["../src/common/tree-data-model.ts","../src/tree/tree-base.ts","../src/tree/tree-list.ts","../src/tree/tree-controller.ts"],"sourcesContent":["import type { LoadChildrenCallback, TreeItem, TreeNode } from './types.js';\nimport { collectDataResult } from './data-provider.js';\n\n// ---------------------------------------------------------------------------\n// Subscription event types (internal — not part of the public API)\n// ---------------------------------------------------------------------------\n\ntype InvalidateEvent = { type: `invalidate`; key: string };\ntype RootEvent = { type: `root`; root: TreeNode };\ntype ModelEvent = InvalidateEvent | RootEvent;\n\ntype ModelSubscriber = (event: ModelEvent) => void;\n\n// ---------------------------------------------------------------------------\n// Pure tree-mutation helpers (functional, produce new roots)\n// ---------------------------------------------------------------------------\n\n// function cloneNode(node: TreeNode): TreeNode {\n// if (node.children === undefined)\n// return { item: { ...node.item } };\n// return { item: { ...node.item }, children: node.children.map(cloneNode) };\n// }\n\nfunction findNode(root: TreeNode, key: string): TreeNode | undefined {\n if (root.item.key === key)\n return root;\n if (!root.children)\n return undefined;\n for (const child of root.children) {\n const found = findNode(child, key);\n if (found)\n return found;\n }\n return undefined;\n}\n\n/** Return a new root with the node at `key` replaced by `replacer(node)`. */\nfunction mapNode(root: TreeNode, key: string, replacer: (n: TreeNode) => TreeNode): TreeNode {\n if (root.item.key === key)\n return replacer(root);\n if (!root.children)\n return root;\n return { item: root.item, children: root.children.map(c => mapNode(c, key, replacer)) };\n}\n\n/** Return a new root with `newChild` appended to the children of the node at `parentKey`. */\nfunction addChildTo(root: TreeNode, parentKey: string, newChild: TreeNode): TreeNode {\n return mapNode(root, parentKey, parent => ({\n item: parent.item,\n children: [...(parent.children ?? []), newChild],\n }));\n}\n\n/** Return a new root with the node at `key` removed (along with all its descendants). */\nfunction removeNodeFrom(root: TreeNode, key: string): TreeNode {\n if (!root.children)\n return root;\n return {\n item: root.item,\n children: root.children\n .filter(c => c.item.key !== key)\n .map(c => removeNodeFrom(c, key)),\n };\n}\n\n/** Return a new root with the node at `key` moved to become a child of `newParentKey`. */\nfunction moveNodeTo(root: TreeNode, key: string, newParentKey: string): TreeNode {\n const target = findNode(root, key);\n if (!target)\n return root;\n const withoutTarget = removeNodeFrom(root, key);\n return addChildTo(withoutTarget, newParentKey, target);\n}\n\n// ---------------------------------------------------------------------------\n// TreeDataModelOptions\n// ---------------------------------------------------------------------------\n\nexport type TreeDataModelOptions = {\n /** The initial root node. Required. */\n root: TreeNode;\n /**\n * Optional callback for lazily loading children.\n * If omitted, nodes with `children === undefined` are treated as empty branches.\n */\n loadChildren?: LoadChildrenCallback;\n};\n\n// ---------------------------------------------------------------------------\n// TreeDataModel\n// ---------------------------------------------------------------------------\n\n/**\n * Manages tree data for tree-like components.\n *\n * Handles two concerns:\n * 1. **Lazy loading** — caches children fetched via `loadChildren` and can invalidate\n * specific branches so they are re-fetched on next expand.\n * 2. **Structural mutations** — convenience methods to add, remove, update, or move\n * nodes. Each mutation produces a new immutable root and notifies connected components.\n *\n * Assign an instance to a component's `model` property instead of setting `root`/`loadChildren`\n * directly. The same model instance can be shared across multiple components.\n *\n * @example\n * ```typescript\n * const model = new TreeDataModel({\n * root: { item: { key: 'root', label: 'Root' }, children: [] },\n * loadChildren: async (node, depth, signal) => fetchChildren(node.item.key),\n * });\n * myTreeList.model = model;\n * myMillerList.model = model;\n *\n * // Later — invalidate a branch to force a re-fetch on next expand:\n * model.invalidate('some-key');\n * ```\n */\nexport class TreeDataModel {\n #root: TreeNode;\n #loadChildren: LoadChildrenCallback | undefined;\n #cache = new Map<string, TreeNode[]>();\n #subscribers = new Set<ModelSubscriber>();\n\n constructor(options: TreeDataModelOptions) {\n this.#root = options.root;\n this.#loadChildren = options.loadChildren;\n }\n\n // ---------------------------------------------------------------------------\n // Root\n // ---------------------------------------------------------------------------\n\n /** The current immutable root snapshot. */\n get root(): TreeNode {\n return this.#root;\n }\n\n /**\n * Replace the entire root with a new immutable snapshot.\n * All cached children are cleared. Connected components re-render.\n */\n setRoot(root: TreeNode): void {\n this.#root = root;\n this.#cache.clear();\n this.#notify({ type: `root`, root });\n }\n\n // ---------------------------------------------------------------------------\n // Child loading\n // ---------------------------------------------------------------------------\n\n /**\n * Returns children for the given node.\n * If children are cached, they are returned immediately (as a resolved Promise).\n * Otherwise the `loadChildren` callback is invoked and the result is cached.\n * If no `loadChildren` is set and no cache entry exists, returns `[]`.\n *\n * Called by components internally — not typically called by application code.\n */\n async getChildren(node: TreeNode, depth: number, signal: AbortSignal): Promise<TreeNode[]> {\n const key = node.item.key;\n if (this.#cache.has(key)) {\n return this.#cache.get(key)!;\n }\n if (!this.#loadChildren) {\n return [];\n }\n const items = await collectDataResult(this.#loadChildren({ node, depth }, signal), signal);\n const children = [...items] as TreeNode[];\n if (!signal.aborted) {\n this.#cache.set(key, children);\n }\n return children;\n }\n\n // ---------------------------------------------------------------------------\n // Cache invalidation\n // ---------------------------------------------------------------------------\n\n /**\n * Clears the cached children for the node with the given key.\n * Connected components will collapse that node (if currently expanded), so that\n * the next expand triggers a fresh `loadChildren` call.\n */\n invalidate(key: string): void {\n this.#cache.delete(key);\n this.#notify({ type: `invalidate`, key });\n }\n\n // ---------------------------------------------------------------------------\n // Convenience mutators\n // ---------------------------------------------------------------------------\n\n /**\n * Adds `node` as a child of the node identified by `parentKey`.\n * Returns the new root (connected components are notified automatically).\n */\n addNode(parentKey: string, node: TreeNode): TreeNode {\n this.#root = addChildTo(this.#root, parentKey, node);\n this.#notify({ type: `root`, root: this.#root });\n return this.#root;\n }\n\n /**\n * Removes the node with the given key and all its descendants.\n * Returns the new root (connected components are notified automatically).\n */\n removeNode(key: string): TreeNode {\n this.#cache.delete(key);\n this.#root = removeNodeFrom(this.#root, key);\n this.#notify({ type: `root`, root: this.#root });\n return this.#root;\n }\n\n /**\n * Applies a partial update to the `item` of the node with the given key.\n * Returns the new root (connected components are notified automatically).\n */\n updateItem(key: string, patch: Partial<TreeItem>): TreeNode {\n this.#root = mapNode(this.#root, key, n => ({\n item: { ...n.item, ...patch },\n children: n.children,\n }));\n this.#notify({ type: `root`, root: this.#root });\n return this.#root;\n }\n\n /**\n * Moves the node with the given key to become a child of `newParentKey`.\n * Returns the new root (connected components are notified automatically).\n */\n moveNode(key: string, newParentKey: string): TreeNode {\n this.#root = moveNodeTo(this.#root, key, newParentKey);\n this.#notify({ type: `root`, root: this.#root });\n return this.#root;\n }\n\n // ---------------------------------------------------------------------------\n // Internal subscription (used by components — not part of the public API)\n // ---------------------------------------------------------------------------\n\n /**\n * Subscribe to model events. Returns an unsubscribe function.\n * Components call this when the `model` property is set, and unsubscribe when it is unset.\n *\n * @internal\n */\n _subscribe(callback: ModelSubscriber): () => void {\n this.#subscribers.add(callback);\n return () => this.#subscribers.delete(callback);\n }\n\n #notify(event: ModelEvent): void {\n for (const sub of this.#subscribers) {\n sub(event);\n }\n }\n}\n","/* eslint-disable ts/no-unsafe-declaration-merging */\nimport type { CommandRegistry } from '@clinth/ui-commands';\nimport type { PropertyValues, TemplateResult } from 'lit';\nimport type { TreeSearchHost } from '../common/searchable.js';\nimport type {\n TreeActivateDetail,\n TreeActivateEvent,\n TreeCollapseDetail,\n TreeCollapseEvent,\n TreeComponent,\n TreeComponentEventMap,\n TreeExpandDetail,\n TreeExpandEvent,\n TreeItemClickDetail,\n TreeItemClickEvent,\n TreeSelectDetail,\n TreeSelectEvent,\n TreeTickleDetail,\n TreeTickleEvent,\n} from '../common/tree-component.js';\nimport type { TreeDataModel } from '../common/tree-data-model.js';\nimport type {\n LoadChildrenCallback,\n TreeExclusivity,\n TreeFilterPredicate,\n TreeInteractionMode,\n TreeNode,\n TreeSelectionFilter,\n} from '../common/types.js';\nimport type { TreeConfig } from './types.js';\nimport { createCommandRegistry } from '@clinth/ui-commands';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { collectDataResult } from '../common/data-provider.js';\nimport { tickledItemStyles, tickledStyles } from '../interaction/index.js';\nimport { TickledController } from '../interaction/tickled-controller.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\n@customElement(`ixfx-tree-base`)\nexport class TreeBaseElement extends LitElement implements TreeComponent, TreeSearchHost {\n @property({ type: Object })\n root: TreeNode | undefined;\n\n @property({ attribute: false })\n model: TreeDataModel | undefined;\n\n /** Callback to lazily load children for a node. Superseded by `model` when both are set. */\n @property({ attribute: false })\n loadChildren: LoadChildrenCallback | undefined;\n\n @property({ reflect: true, attribute: `exclusivity` })\n exclusivity: TreeExclusivity = `none`;\n\n @property({ reflect: true, attribute: `selection-filter` })\n selectionFilter: TreeSelectionFilter = `all`;\n\n /** Controls how pointer/keyboard gestures map to selection changes. Default: `'standard'`. */\n @property({ type: String, attribute: `interaction-mode` })\n interactionMode: TreeInteractionMode = `standard`;\n\n @property({ attribute: false })\n selectedNode: TreeNode | undefined;\n\n @state()\n protected _selectedNodes = new Set<TreeNode>();\n\n get selectedNodes(): ReadonlySet<TreeNode> {\n return this._selectedNodes;\n }\n\n @property({ attribute: false })\n filterPredicate: TreeFilterPredicate | undefined;\n\n @property({ type: Boolean, attribute: `disable-keyboard-navigation` })\n disableKeyboardNavigation = false;\n\n @property({ attribute: false })\n registry: CommandRegistry<unknown> | undefined = undefined;\n\n @state()\n protected _expandedKeys = new Set<string>();\n\n protected tickled = new TickledController<string>(this, {\n getItems: () => {\n const nodes = this.#getAllNodes();\n return nodes.map(({ node }) => ({ id: node.item.key, enabled: true }));\n },\n onStateChange: () => {\n this.setAttribute(`data-input-mode`, this.tickled.inputMode);\n },\n });\n\n @state()\n protected _focusedDepth = 0;\n\n #pendingNode: TreeNode | undefined;\n #pendingController: AbortController | undefined;\n #modelUnsubscribe: (() => void) | undefined;\n // Range-select anchor: the flat-list index and node from which a Shift-range is measured.\n #anchor: { node: TreeNode; flatIndex: number; selectionSnapshot?: ReadonlySet<TreeNode> } | undefined;\n #ownedRegistry: CommandRegistry<unknown> | undefined;\n\n #config: TreeConfig = {\n indent: 20,\n };\n\n override updated(changedProps: PropertyValues) {\n if (changedProps.has(`root`) && this.root) {\n this.#abortPending();\n this._expandedKeys.clear();\n this.#clearSelectionInternal();\n this.tickled.clearTickled();\n this._focusedDepth = 0;\n }\n\n if (changedProps.has(`model`)) {\n this.#modelUnsubscribe?.();\n this.#modelUnsubscribe = undefined;\n const model = this.model;\n if (model) {\n this.root = model.root;\n this.#modelUnsubscribe = model._subscribe((event) => {\n if (event.type === `root`) {\n this.root = event.root;\n this.requestUpdate();\n } else if (event.type === `invalidate`) {\n // If the invalidated node is currently expanded, collapse it\n if (this._expandedKeys.has(event.key)) {\n this._expandedKeys.delete(event.key);\n this.requestUpdate();\n }\n }\n });\n }\n }\n\n if (changedProps.has(`interactionMode`)) {\n this.#anchor = undefined;\n this.clearSelection();\n }\n\n // When selectedNode is set externally, sync focus to match\n if (changedProps.has(`selectedNode`) && this.selectedNode) {\n const prev = changedProps.get(`selectedNode`) as TreeNode | undefined;\n if (prev !== this.selectedNode) {\n this.tickled.setTickled(this.selectedNode.item.key);\n }\n }\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.setAttribute(`data-input-mode`, `mouse`);\n const registry = this.#ownedRegistry = createCommandRegistry();\n registry.register({\n id: `select-all`,\n label: `Select All`,\n description: `Select all visible items`,\n execute: () => this.selectAll(),\n });\n registry.register({\n id: `deselect-all`,\n label: `Deselect All`,\n description: `Clear all selection`,\n execute: () => this.deselectAll(),\n });\n this.registry = registry;\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.#modelUnsubscribe?.();\n this.#modelUnsubscribe = undefined;\n if (this.#ownedRegistry) {\n this.#ownedRegistry.unregister(`select-all`);\n this.#ownedRegistry.unregister(`deselect-all`);\n this.#ownedRegistry = undefined;\n this.registry = undefined;\n }\n }\n\n getConfig(): TreeConfig {\n return { ...this.#config };\n }\n\n setConfig(config: Partial<TreeConfig>) {\n this.#config = { ...this.#config, ...config };\n this.requestUpdate();\n }\n\n // --- Programmatic selection ---\n\n select(node: TreeNode): void {\n if (!this.#canSelect(node))\n return;\n const prev = new Set(this._selectedNodes);\n this._selectedNodes.clear();\n this._selectedNodes.add(node);\n this.selectedNode = node;\n this.#dispatchSelect(prev);\n this.requestUpdate();\n }\n\n deselect(node: TreeNode): void {\n if (!this._selectedNodes.has(node))\n return;\n const prev = new Set(this._selectedNodes);\n this._selectedNodes.delete(node);\n if (this.selectedNode === node) {\n this.selectedNode = [...this._selectedNodes].at(-1);\n }\n this.#dispatchSelect(prev);\n this.requestUpdate();\n }\n\n clearSelection(): void {\n if (this._selectedNodes.size === 0)\n return;\n const prev = new Set(this._selectedNodes);\n this.#clearSelectionInternal();\n this.#dispatchSelect(prev);\n this.requestUpdate();\n }\n\n selectAll(): void {\n const prev = new Set(this._selectedNodes);\n if (this.interactionMode === `checked`) {\n for (const { node } of this.#getAllNodes()) {\n if (!this.#canSelect(node))\n continue;\n this.#applyCheckedToggle(node, true);\n }\n } else {\n for (const { node } of this.#getAllNodes()) {\n if (!this.#canSelect(node))\n continue;\n this._selectedNodes.add(node);\n }\n this.selectedNode = [...this._selectedNodes].at(-1);\n }\n this.#dispatchSelect(prev);\n this.requestUpdate();\n }\n\n deselectAll(): void {\n const prev = new Set(this._selectedNodes);\n if (this.interactionMode === `checked`) {\n for (const { node } of this.#getAllNodes()) {\n if (!this.#canSelect(node))\n continue;\n this.#applyCheckedToggle(node, false);\n }\n } else {\n this.#clearSelectionInternal();\n }\n this.#dispatchSelect(prev);\n this.requestUpdate();\n }\n\n // --- Navigation ---\n\n navigateTo(keys: readonly string[]): boolean {\n if (!this.root?.children)\n return false;\n\n this.#abortPending();\n this.#clearSelectionInternal();\n this.tickled.clearTickled();\n this._focusedDepth = 0;\n\n let currentNode: TreeNode | undefined = this.root;\n\n for (const key of keys) {\n const children: TreeNode[] | undefined = currentNode?.children;\n if (!children)\n return false;\n\n const found: TreeNode | undefined = children.find(n => n.item.key === key);\n if (!found)\n return false;\n\n this.#applyExclusivity(found.item.key);\n this._expandedKeys.add(found.item.key);\n\n if (key === keys.at(-1)) {\n this.select(found);\n this.tickled.setTickled(found.item.key);\n }\n\n currentNode = found;\n }\n\n this.requestUpdate();\n this.#scrollKeyIntoView(keys.at(-1)!);\n return true;\n }\n\n navigateToNode(predicate: (node: TreeNode) => boolean): boolean {\n if (!this.root?.children)\n return false;\n const keyPath = this.#findNodePath(this.root.children, predicate);\n if (!keyPath)\n return false;\n return this.navigateTo(keyPath);\n }\n\n getNodes(): ReadonlyArray<{ node: TreeNode; depth: number }> {\n if (!this.root?.children)\n return [];\n const result: Array<{ node: TreeNode; depth: number }> = [];\n const visit = (node: TreeNode, depth: number) => {\n result.push({ node, depth });\n if (node.children) {\n for (const child of node.children) visit(child, depth + 1);\n }\n };\n for (const child of this.root.children) visit(child, 0);\n return result;\n }\n\n // --- Internal helpers ---\n\n #canSelect(node: TreeNode): boolean {\n if (this.selectionFilter === `none`)\n return false;\n if (this.selectionFilter === `leaf`)\n return node.item.isLeaf === true;\n if (this.selectionFilter === `branch`)\n return node.item.isLeaf === false || (node.children !== undefined && node.children.length > 0);\n return true;\n }\n\n #clearSelectionInternal(): void {\n this._selectedNodes.clear();\n this.selectedNode = undefined;\n }\n\n #dispatchSelect(previous: ReadonlySet<TreeNode>): void {\n const detail: TreeSelectDetail = {\n selected: new Set(this._selectedNodes),\n previous,\n };\n this.dispatchEvent(new CustomEvent<TreeSelectDetail>(`select`, {\n detail,\n bubbles: true,\n composed: true,\n }));\n }\n\n #findNodePath(\n nodes: TreeNode[],\n predicate: (node: TreeNode) => boolean,\n prefix: string[] = [],\n ): string[] | undefined {\n for (const node of nodes) {\n const path = [...prefix, node.item.key];\n if (predicate(node))\n return path;\n if (node.children?.length) {\n const result = this.#findNodePath(node.children, predicate, path);\n if (result)\n return result;\n }\n }\n return undefined;\n }\n\n protected renderNodeContent(node: TreeNode, _depth: number): TemplateResult | typeof nothing {\n const isBranch = node.item.isLeaf !== true;\n const isExpanded = this._isExpanded(node);\n return html`\n <span class=\"tree-caret\">\n ${isBranch ? html`<ixfx-icon class=\"caret-icon\" name=\"chevron-down\" .rotate=${isExpanded ? nothing : `-90deg`}></ixfx-icon>` : ``}\n </span>\n <span class=\"tree-label\">${node.item.label}</span>\n `;\n }\n\n protected _handleItemClick(node: TreeNode, depth: number, event?: MouseEvent) {\n if (this.#pendingNode && this._expandedKeys.has(this.#pendingNode.item.key)) {\n this.#abortPending();\n }\n\n this.tickled.handlePointerEnter(node.item.key);\n this._focusedDepth = depth;\n\n this.dispatchEvent(new CustomEvent<TreeItemClickDetail>(`item-click`, {\n detail: { node, depth },\n bubbles: true,\n composed: true,\n }));\n\n switch (this.interactionMode) {\n case `implicit`: this.#handleImplicitClick(node, depth); break;\n case `standard`: this.#handleStandardClick(node, depth, event); break;\n case `vscode`: this.#handleStandardClick(node, depth, event); break;\n case `manual`: this.#handleManualClick(node, depth, event); break;\n case `checked`: this.#handleExpandOnly(node, depth); break;\n }\n\n this.requestUpdate();\n }\n\n #handleImplicitClick(node: TreeNode, depth: number): void {\n if (this.#canSelect(node)) {\n const prev = new Set(this._selectedNodes);\n this._selectedNodes.clear();\n this._selectedNodes.add(node);\n this.selectedNode = node;\n if (!prev.has(node) || prev.size !== 1)\n this.#dispatchSelect(prev);\n }\n this.#toggleExpand(node, depth);\n }\n\n #handleStandardClick(node: TreeNode, depth: number, event?: MouseEvent): void {\n const isMeta = event ? (event.metaKey || event.ctrlKey) : false;\n const isShift = event ? event.shiftKey : false;\n\n if (isMeta) {\n if (this.#canSelect(node)) {\n const prev = new Set(this._selectedNodes);\n if (this._selectedNodes.has(node)) {\n this._selectedNodes.delete(node);\n if (this.selectedNode === node)\n this.selectedNode = [...this._selectedNodes].at(-1);\n } else {\n this._selectedNodes.add(node);\n this.selectedNode = node;\n this.#anchor = { node, flatIndex: this.#getFlatIndexOf(node) };\n }\n this.#dispatchSelect(prev);\n }\n return; // no expand on Ctrl+click\n }\n\n if (isShift && this.#anchor) {\n const visible = this.#getAllNodes();\n const anchorIdx = visible.findIndex(n => n.node === this.#anchor!.node);\n const targetIdx = visible.findIndex(n => n.node === node);\n if (anchorIdx >= 0 && targetIdx >= 0) {\n const prev = new Set(this._selectedNodes);\n const from = Math.min(anchorIdx, targetIdx);\n const to = Math.max(anchorIdx, targetIdx);\n const rangeNodes = visible.slice(from, to + 1)\n .map(n => n.node)\n .filter(n => this.#canSelect(n));\n this._selectedNodes = new Set(rangeNodes);\n this.selectedNode = node;\n this.#dispatchSelect(prev);\n }\n return; // no expand on Shift+click\n }\n\n // Plain click: select + toggle expand\n if (this.#canSelect(node)) {\n const prev = new Set(this._selectedNodes);\n this._selectedNodes.clear();\n this._selectedNodes.add(node);\n this.selectedNode = node;\n this.#anchor = { node, flatIndex: this.#getFlatIndexOf(node) };\n if (!prev.has(node) || prev.size !== 1)\n this.#dispatchSelect(prev);\n }\n this.#toggleExpand(node, depth);\n }\n\n #handleExpandOnly(node: TreeNode, depth: number): void {\n this.#toggleExpand(node, depth);\n }\n\n #handleManualClick(node: TreeNode, depth: number, event?: MouseEvent): void {\n const isMeta = event ? (event.metaKey || event.ctrlKey) : false;\n const isShift = event ? event.shiftKey : false;\n\n if (isMeta) {\n if (this.#canSelect(node)) {\n const prev = new Set(this._selectedNodes);\n if (this._selectedNodes.has(node)) {\n this._selectedNodes.delete(node);\n if (this.selectedNode === node)\n this.selectedNode = [...this._selectedNodes].at(-1);\n } else {\n this._selectedNodes.add(node);\n this.selectedNode = node;\n this.#anchor = { node, flatIndex: this.#getFlatIndexOf(node) };\n }\n this.#dispatchSelect(prev);\n }\n return; // no expand on Meta+click\n }\n\n if (isShift && this.#anchor) {\n const visible = this.#getAllNodes();\n const anchorIdx = visible.findIndex(n => n.node === this.#anchor!.node);\n const targetIdx = visible.findIndex(n => n.node === node);\n if (anchorIdx >= 0 && targetIdx >= 0) {\n const prev = new Set(this._selectedNodes);\n const from = Math.min(anchorIdx, targetIdx);\n const to = Math.max(anchorIdx, targetIdx);\n const rangeNodes = visible.slice(from, to + 1)\n .map(n => n.node)\n .filter(n => this.#canSelect(n));\n this._selectedNodes = new Set(rangeNodes);\n this.selectedNode = node;\n this.#dispatchSelect(prev);\n }\n return; // no expand on Shift+click\n }\n\n this.#toggleExpand(node, depth);\n }\n\n #toggleSelection(node: TreeNode, _depth: number): void {\n if (!this.#canSelect(node))\n return;\n const prev = new Set(this._selectedNodes);\n if (this._selectedNodes.has(node)) {\n this._selectedNodes.delete(node);\n if (this.selectedNode === node)\n this.selectedNode = [...this._selectedNodes].at(-1);\n } else {\n this._selectedNodes.add(node);\n this.selectedNode = node;\n this.#anchor = { node, flatIndex: this.#getFlatIndexOf(node) };\n }\n this.#dispatchSelect(prev);\n }\n\n protected _handleCheckboxClick(event: MouseEvent, node: TreeNode, _depth: number): void {\n event.stopPropagation();\n const prev = new Set(this._selectedNodes);\n const allSelected = this.#allDescendantsSelected(node);\n this.#applyCheckedToggle(node, !allSelected);\n if (this.selectedNode === undefined || !this._selectedNodes.has(this.selectedNode)) {\n this.selectedNode = [...this._selectedNodes].at(-1);\n }\n this.#dispatchSelect(prev);\n this.requestUpdate();\n }\n\n #toggleExpand(node: TreeNode, depth: number): void {\n const isExpanded = this._expandedKeys.has(node.item.key);\n if (isExpanded) {\n this._expandedKeys.delete(node.item.key);\n this.dispatchEvent(new CustomEvent<TreeCollapseDetail>(`collapse`, {\n detail: { node, depth },\n bubbles: true,\n composed: true,\n }));\n } else {\n if (node.children === undefined) {\n if (node.item.isLeaf !== false)\n return;\n const loader = this.model ?? (this.loadChildren ? this : undefined);\n if (loader) {\n this.#pendingNode = node;\n const controller = new AbortController();\n this.#pendingController = controller;\n this.#invokeLoadChildren(node, depth, controller).catch(() => {});\n }\n } else {\n this.#applyExclusivity(node.item.key);\n this._expandedKeys.add(node.item.key);\n this.dispatchEvent(new CustomEvent<TreeExpandDetail>(`expand`, {\n detail: { node, depth },\n bubbles: true,\n composed: true,\n }));\n }\n }\n }\n\n #allDescendantsSelected(node: TreeNode): boolean {\n if (!this._selectedNodes.has(node))\n return false;\n if (!node.children?.length)\n return true;\n return node.children.every(child => this.#allDescendantsSelected(child));\n }\n\n #applyCheckedToggle(node: TreeNode, selected: boolean): void {\n if (this.#canSelect(node)) {\n if (selected) {\n this._selectedNodes.add(node);\n } else {\n this._selectedNodes.delete(node);\n }\n }\n if (node.children) {\n for (const child of node.children) {\n this.#applyCheckedToggle(child, selected);\n }\n }\n }\n\n #getFlatIndexOf(node: TreeNode): number {\n return this.#getAllNodes().findIndex(n => n.node === node);\n }\n\n #extendRangeSelection(nodes: Array<{ node: TreeNode; depth: number }>, fromIdx: number, toIdx: number): void {\n // Set anchor at `fromIdx` if not already anchored\n if (!this.#anchor) {\n const anchorNode = nodes[fromIdx]?.node;\n if (anchorNode)\n this.#anchor = { node: anchorNode, flatIndex: fromIdx };\n }\n if (!this.#anchor)\n return;\n\n const anchorIdx = nodes.findIndex(n => n.node === this.#anchor!.node);\n if (anchorIdx < 0)\n return;\n\n const from = Math.min(anchorIdx, toIdx);\n const to = Math.max(anchorIdx, toIdx);\n\n if (this.interactionMode === `vscode`) {\n // On first Shift+arrow: snapshot current selection\n if (!this.#anchor.selectionSnapshot) {\n this.#anchor = { ...this.#anchor, selectionSnapshot: new Set(this._selectedNodes) };\n }\n const snap = this.#anchor.selectionSnapshot!;\n const rangeNodes = nodes.slice(from, to + 1).map(n => n.node).filter(n => this.#canSelect(n));\n // Toggle: items in snapshot stay toggled based on presence in snapshot\n const next = new Set(snap);\n for (const n of rangeNodes) {\n if (snap.has(n))\n next.delete(n);\n else next.add(n);\n }\n const prev = new Set(this._selectedNodes);\n this._selectedNodes = next;\n this.selectedNode = nodes[toIdx]?.node ?? this.selectedNode;\n this.#dispatchSelect(prev);\n } else {\n // standard: range replaces selection\n const prev = new Set(this._selectedNodes);\n const rangeNodes = nodes.slice(from, to + 1).map(n => n.node).filter(n => this.#canSelect(n));\n this._selectedNodes = new Set(rangeNodes);\n this.selectedNode = nodes[toIdx]?.node ?? this.selectedNode;\n this.#dispatchSelect(prev);\n }\n }\n\n async #invokeLoadChildren(node: TreeNode, depth: number, controller: AbortController): Promise<void> {\n try {\n let children: TreeNode[];\n if (this.model) {\n children = await this.model.getChildren(node, depth, controller.signal);\n } else {\n children = [...await collectDataResult(\n this.loadChildren!({ node, depth }, controller.signal),\n controller.signal,\n )];\n }\n if (controller.signal.aborted)\n return;\n node.children = children;\n this.#applyExclusivity(node.item.key);\n this._expandedKeys.add(node.item.key);\n this.#pendingNode = undefined;\n this.#pendingController = undefined;\n this.dispatchEvent(new CustomEvent<TreeExpandDetail>(`expand`, {\n detail: { node, depth },\n bubbles: true,\n composed: true,\n }));\n this.requestUpdate();\n } catch {\n if (controller.signal.aborted)\n return;\n node.children = [];\n this.#pendingNode = undefined;\n this.#pendingController = undefined;\n this.requestUpdate();\n }\n }\n\n protected _isSelected(node: TreeNode): boolean {\n return this._selectedNodes.has(node);\n }\n\n protected _isFocused(node: TreeNode): boolean {\n return this.tickled.isTickled(node.item.key);\n }\n\n protected _isExpanded(node: TreeNode): boolean {\n if (this._expandedKeys.has(node.item.key))\n return true;\n if (this.filterPredicate && node.children) {\n return node.children.some(child => this.#matchesFilter(child, 0));\n }\n return false;\n }\n\n #matchesFilter(node: TreeNode, depth: number): boolean {\n if (!this.filterPredicate)\n return true;\n if (this.filterPredicate(node, depth))\n return true;\n return node.children?.some(child => this.#matchesFilter(child, depth + 1)) ?? false;\n }\n\n protected get _pendingNode(): TreeNode | undefined {\n return this.#pendingNode;\n }\n\n #scrollKeyIntoView(key: string) {\n requestAnimationFrame(() => {\n const el = this.shadowRoot?.querySelector(`[data-key=\"${CSS.escape(key)}\"]`) as HTMLElement | null;\n if (!el)\n return;\n const elRect = el.getBoundingClientRect();\n const hostRect = this.getBoundingClientRect();\n const relativeTop = elRect.top - hostRect.top;\n const relativeBottom = relativeTop + elRect.height;\n if (relativeTop < 0) {\n this.scrollTop += relativeTop;\n } else if (relativeBottom > this.clientHeight) {\n this.scrollTop += relativeBottom - this.clientHeight;\n }\n });\n }\n\n #abortPending() {\n if (this.#pendingController) {\n this.#pendingController.abort();\n this.#pendingController = undefined;\n this.#pendingNode = undefined;\n }\n }\n\n /** Apply exclusivity rules when a node is about to be expanded. */\n #applyExclusivity(expandKey: string): void {\n if (this.exclusivity === `none`)\n return;\n\n if (this.exclusivity === `depth`) {\n this.#collapseSiblingsAtDepth(expandKey);\n } else if (this.exclusivity === `global`) {\n // Collapse all expanded nodes except direct ancestors of the expanding node\n const ancestorKeys = this.#findAncestorKeys(expandKey);\n for (const key of [...this._expandedKeys]) {\n if (!ancestorKeys.has(key) && key !== expandKey) {\n this._expandedKeys.delete(key);\n }\n }\n }\n }\n\n #collapseSiblingsAtDepth(expandKey: string): void {\n if (!this.root)\n return;\n\n const parent = this.#findParent(this.root, expandKey);\n if (!parent?.children)\n return;\n\n for (const child of parent.children) {\n if (child.item.key !== expandKey && this._expandedKeys.has(child.item.key)) {\n this._expandedKeys.delete(child.item.key);\n }\n }\n }\n\n #findAncestorKeys(targetKey: string): Set<string> {\n const keys = new Set<string>();\n const walk = (node: TreeNode): boolean => {\n if (node.item.key === targetKey)\n return true;\n if (!node.children)\n return false;\n for (const child of node.children) {\n if (walk(child)) {\n keys.add(node.item.key);\n return true;\n }\n }\n return false;\n };\n if (this.root)\n walk(this.root);\n return keys;\n }\n\n #findParent(node: TreeNode, targetKey: string, parent: TreeNode | undefined = undefined): TreeNode | undefined {\n if (!node.children)\n return undefined;\n\n for (const child of node.children) {\n if (child.item.key === targetKey) {\n return parent ?? node;\n }\n const found = this.#findParent(child, targetKey, child);\n if (found)\n return found;\n }\n return undefined;\n }\n\n #getVisibleNodes(node: TreeNode, depth: number): Array<{ node: TreeNode; depth: number }> {\n const result: Array<{ node: TreeNode; depth: number }> = [];\n\n const visit = (n: TreeNode, d: number) => {\n result.push({ node: n, depth: d });\n if (this._expandedKeys.has(n.item.key) && n.children) {\n for (const child of n.children) {\n visit(child, d + 1);\n }\n }\n };\n\n if (node.children) {\n for (const child of node.children) {\n visit(child, depth + 1);\n }\n }\n\n return result;\n }\n\n #getAllNodes(): Array<{ node: TreeNode; depth: number }> {\n if (!this.root)\n return [];\n return this.#getVisibleNodes(this.root, 0);\n }\n\n #getFocusedIndex(): number {\n const nodes = this.#getAllNodes();\n const tickledKey = this.tickled.tickledId;\n if (!tickledKey)\n return 0;\n return nodes.findIndex(n => n.node.item.key === tickledKey);\n }\n\n #setFocusedIndex(index: number) {\n const nodes = this.#getAllNodes();\n if (index < 0 || index >= nodes.length)\n return;\n const { node, depth } = nodes[index];\n this.tickled.setTickled(node.item.key);\n this._focusedDepth = depth;\n // Emit tickle for keyboard cursor movement\n this.dispatchEvent(new CustomEvent<TreeTickleDetail>(`tickle`, {\n detail: { node, depth },\n bubbles: true,\n composed: true,\n }));\n this.requestUpdate();\n this.updateComplete.then(() => this.#scrollTickledIntoView());\n }\n\n #scrollTickledIntoView() {\n const tickledKey = this.tickled.tickledId;\n if (tickledKey === undefined)\n return;\n const item = this.shadowRoot?.querySelector(`[data-key=\"${tickledKey}\"]`);\n item?.scrollIntoView({ block: `nearest`, behavior: `smooth` });\n }\n\n #onKeyDown = (event: KeyboardEvent) => {\n const nodes = this.#getAllNodes();\n if (nodes.length === 0)\n return;\n\n if ((event.ctrlKey || event.metaKey) && event.key === `a`) {\n event.preventDefault();\n this.selectAll();\n return;\n }\n\n // Switch to keyboard mode for any navigation key\n if ([`ArrowDown`, `ArrowUp`, `ArrowLeft`, `ArrowRight`, `Enter`, ` `].includes(event.key)) {\n this.tickled.setInputMode(`keyboard`);\n }\n\n const currentIdx = this.#getFocusedIndex();\n\n switch (event.key) {\n case `ArrowDown`: {\n event.preventDefault();\n const nextIdx = Math.min(currentIdx + 1, nodes.length - 1);\n if (this.interactionMode === `implicit`) {\n this.select(nodes[nextIdx].node);\n }\n this.#setFocusedIndex(nextIdx);\n if (event.shiftKey && (this.interactionMode === `standard` || this.interactionMode === `vscode`)) {\n this.#extendRangeSelection(nodes, currentIdx, nextIdx);\n } else if (this.interactionMode === `vscode`) {\n this.#anchor = undefined; // clear snapshot on plain navigation\n }\n this.requestUpdate();\n break;\n }\n case `ArrowUp`: {\n event.preventDefault();\n const prevIdx = Math.max(currentIdx - 1, 0);\n if (this.interactionMode === `implicit`) {\n this.select(nodes[prevIdx].node);\n }\n this.#setFocusedIndex(prevIdx);\n if (event.shiftKey && (this.interactionMode === `standard` || this.interactionMode === `vscode`)) {\n this.#extendRangeSelection(nodes, currentIdx, prevIdx);\n } else if (this.interactionMode === `vscode`) {\n this.#anchor = undefined; // clear snapshot on plain navigation\n }\n this.requestUpdate();\n break;\n }\n case `ArrowRight`: {\n event.preventDefault();\n const current = nodes[currentIdx];\n if (current && current.node.item.isLeaf !== true) {\n if (!this._expandedKeys.has(current.node.item.key)) {\n this.#toggleExpand(current.node, current.depth);\n } else if (currentIdx + 1 < nodes.length) {\n this.#setFocusedIndex(currentIdx + 1);\n }\n }\n this.requestUpdate();\n break;\n }\n case `ArrowLeft`: {\n event.preventDefault();\n const current = nodes[currentIdx];\n if (current && this._expandedKeys.has(current.node.item.key)) {\n this._expandedKeys.delete(current.node.item.key);\n this.dispatchEvent(new CustomEvent(`collapse`, {\n detail: { node: current.node, depth: current.depth },\n bubbles: true,\n composed: true,\n }));\n } else if (current.depth > 1) {\n const parentDepth = current.depth - 1;\n for (let i = currentIdx - 1; i >= 0; i--) {\n if (nodes[i].depth === parentDepth) {\n this.#setFocusedIndex(i);\n break;\n }\n }\n }\n this.requestUpdate();\n break;\n }\n case `Enter`: {\n event.preventDefault();\n const current = nodes[currentIdx];\n if (current) {\n if (this.interactionMode !== `manual` && this.interactionMode !== `checked`) {\n this.select(current.node);\n }\n this.dispatchEvent(new CustomEvent<TreeActivateDetail>(`activate`, {\n detail: { node: current.node, depth: current.depth },\n bubbles: true,\n composed: true,\n }));\n this.requestUpdate();\n }\n break;\n }\n case ` `: {\n event.preventDefault();\n const current = nodes[currentIdx];\n if (!current)\n break;\n\n if (this.interactionMode === `checked`) {\n this._handleCheckboxClick(new MouseEvent(`click`), current.node, current.depth);\n } else if (this.interactionMode === `standard` || this.interactionMode === `vscode` || this.interactionMode === `manual`) {\n this.#toggleSelection(current.node, current.depth);\n }\n break;\n }\n case `Escape`: {\n event.preventDefault();\n this.#abortPending();\n break;\n }\n }\n };\n\n protected renderLoadingIndicator(): TemplateResult | typeof nothing {\n return html`<span class=\"loading-spinner\"></span>`;\n }\n\n protected override render() {\n const nodes = this.#getAllNodes();\n\n return html`\n <div\n id=\"container\"\n data-input-mode=${this.tickled.inputMode}\n @keydown=${this.#onKeyDown}\n @dblclick=${this.#onDblClick}\n @pointerleave=${(e: PointerEvent) => this.tickled.handlePointerLeave(e)}\n tabindex=\"0\"\n >\n ${this.root ? this.#renderNodes(nodes) : nothing}\n </div>\n `;\n }\n\n #onDblClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n const li = target.closest(`li`) as HTMLElement | null;\n if (!li)\n return;\n const key = li.dataset.key;\n if (!key)\n return;\n const nodes = this.#getAllNodes();\n const node = nodes.find(n => n.node.item.key === key);\n if (!node)\n return;\n this.dispatchEvent(new CustomEvent<TreeActivateDetail>(`activate`, {\n detail: { node: node.node, depth: node.depth },\n bubbles: true,\n composed: true,\n }));\n };\n\n #renderNodes(nodes: Array<{ node: TreeNode; depth: number }>) {\n if (nodes.length === 0 && this.#pendingNode) {\n return html`\n <div class=\"tree-loading\">\n ${this.renderLoadingIndicator()}\n </div>\n `;\n }\n\n return html`\n <ul class=\"tree-list\" role=\"tree\">\n ${nodes.map(({ node, depth }) => this._renderNode(node, depth))}\n </ul>\n `;\n }\n\n protected _renderNode(node: TreeNode, depth: number): TemplateResult {\n const selected = this._isSelected(node);\n const tickled = this._isFocused(node);\n const isBranch = node.item.isLeaf !== true;\n const isExpanded = this._isExpanded(node);\n const isPending = this.#pendingNode === node;\n const isFiltered = this.filterPredicate !== undefined && !this.#matchesFilter(node, depth);\n\n return html`\n <li\n class=\"item ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${isBranch ? `branch` : `leaf`} ${isFiltered ? `filtered` : ``}\"\n role=\"treeitem\"\n aria-selected=${selected}\n aria-expanded=${isBranch ? isExpanded : nothing}\n aria-level=${depth + 1}\n data-key=${node.item.key}\n style=${`--depth: ${depth}`}\n @click=${(e: MouseEvent) => this._handleItemClick(node, depth, e)}\n @pointerenter=${() => {\n this.tickled.handlePointerEnter(node.item.key);\n this.dispatchEvent(new CustomEvent<TreeTickleDetail>(`tickle`, {\n detail: { node, depth },\n bubbles: true,\n composed: true,\n }));\n }}\n >\n ${this.renderNodeContent(node, depth)}\n ${isPending ? this.renderLoadingIndicator() : nothing}\n </li>\n `;\n }\n\n static override styles = [\n themeFallbacks,\n tickledStyles,\n tickledItemStyles,\n css`\n :host {\n --tree-bg: var(--surface-3);\n --tree-text: var(--surface-3-text);\n --tree-muted-text: var(--surface-muted-text);\n --tree-indent: 1ch;\n --tree-item-height: 28px;\n --tree-caret-size: 10px;\n --tree-radius: var(--radius-s);\n\n display: block;\n overflow: auto;\n box-sizing: border-box;\n background: var(--tree-bg);\n color: var(--tree-text);\n }\n\n #container {\n outline: none;\n min-height: 100%;\n }\n\n .tree-list {\n list-style: none;\n margin: 0;\n padding: var(--space-xs);\n }\n\n .item {\n display: flex;\n align-items: center;\n height: var(--tree-item-height);\n padding-left: calc(var(--tree-indent) * var(--depth, 0));\n cursor: pointer;\n user-select: none;\n font-family: var(--font-family);\n font-size: var(--text-m);\n border-radius: var(--tree-radius);\n transition: background var(--transition, 0.15s ease-out);\n margin: 1px 0;\n }\n\n .tree-caret {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tree-caret-size);\n height: var(--tree-caret-size);\n flex-shrink: 0;\n margin-right: var(--space-xs);\n }\n\n .caret-icon {\n width: var(--tree-caret-size);\n height: var(--tree-caret-size);\n color: var(--tree-muted-text);\n transition: transform var(--transition, 0.15s ease-out);\n }\n\n .item.selected .caret-icon {\n color: var(--accent-text);\n }\n\n .tree-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .tree-loading {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--space-m);\n }\n\n .loading-spinner {\n width: 16px;\n height: 16px;\n border: 2px solid var(--surface-5);\n border-top-color: var(--accent);\n border-radius: 50%;\n animation: tree-spin 0.7s linear infinite;\n }\n\n @keyframes tree-spin {\n to { transform: rotate(360deg); }\n }\n\n .item.filtered {\n display: none;\n }\n\n ::highlight(incr-search-highlight) {\n background: var(--search-highlight-bg, var(--accent));\n color: var(--search-highlight-color, var(--accent-text, #fff));\n border-radius: 2px;\n padding: 0 1px;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-tree-base': TreeBaseElement;\n }\n}\n\nexport interface TreeBaseElementEventMap extends TreeComponentEventMap {\n 'item-click': TreeItemClickEvent;\n 'expand': TreeExpandEvent;\n 'collapse': TreeCollapseEvent;\n 'select': TreeSelectEvent;\n 'tickle': TreeTickleEvent;\n 'activate': TreeActivateEvent;\n}\n\nexport interface TreeBaseElement {\n addEventListener: (<K extends keyof TreeBaseElementEventMap>(\n type: K,\n listener: (this: TreeBaseElement, event: TreeBaseElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n removeEventListener: (<K extends keyof TreeBaseElementEventMap>(\n type: K,\n listener: (this: TreeBaseElement, event: TreeBaseElementEventMap[K]) => void,\n options?: boolean | EventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ) => void);\n}\n","/* eslint-disable ts/no-unsafe-declaration-merging */\nimport type { TemplateResult } from 'lit';\nimport type { TreeBaseElementEventMap } from './tree-base.js';\nimport type { TreeNode } from './types.js';\nimport { css, html, nothing } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport { TreeBaseElement } from './tree-base.js';\n\n/** Checkbox tri-state in `checked` interactionMode: a branch node is `indeterminate` when some but not all of its descendants are selected. */\nexport type TreeCheckboxState = `checked` | `unchecked` | `indeterminate`;\n\nfunction computeCheckboxState(node: TreeNode, selectedNodes: ReadonlySet<TreeNode>): TreeCheckboxState {\n if (node.item.isLeaf || !node.children?.length) {\n return selectedNodes.has(node) ? `checked` : `unchecked`;\n }\n const childStates = node.children.map(c => computeCheckboxState(c, selectedNodes));\n const allChecked = childStates.every(s => s === `checked`);\n const allUnchecked = childStates.every(s => s === `unchecked`);\n if (allChecked)\n return `checked`;\n if (allUnchecked)\n return `unchecked`;\n return `indeterminate`;\n}\n\n@customElement(`ixfx-tree-list`)\nexport class TreeListElement extends TreeBaseElement {\n /**\n * Optional renderer for the checkbox shown in `checked` interactionMode.\n * Receives the node's current tri-state (`checked` / `unchecked` / `indeterminate`,\n * the latter when some but not all descendants are selected) and returns a Lit\n * template.\n *\n * When set, the checkbox becomes a `<span role=\"checkbox\">` whose contents are\n * whatever this returns. When unset, a native `<input type=\"checkbox\">` is used.\n *\n * @example\n * list.checkboxRenderer = (state) => state === `unchecked`\n * ? html``\n * : html`<svg viewBox=\"0 0 16 16\" width=\"14\" height=\"14\"\n * fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\n * stroke-linecap=\"round\" stroke-linejoin=\"round\"\n * style=\"opacity:${state === `indeterminate` ? 0.35 : 0.6}\">\n * <polyline points=\"3,8 7,12 13,4\" />\n * </svg>`;\n */\n @property({ attribute: false })\n checkboxRenderer: ((state: TreeCheckboxState) => unknown) | undefined;\n\n #depthsWithIcons = new Set<number>();\n\n protected override render() {\n this.#detectIcons();\n return super.render();\n }\n\n #detectIcons() {\n this.#depthsWithIcons.clear();\n const visit = (node: TreeNode, depth: number) => {\n if (node.item.icon) {\n this.#depthsWithIcons.add(depth);\n }\n if (node.children) {\n for (const child of node.children) {\n visit(child, depth + 1);\n }\n }\n };\n if (this.root) {\n visit(this.root, 0);\n }\n }\n\n protected override renderNodeContent(node: TreeNode, depth: number): TemplateResult {\n const isBranch = node.item.isLeaf !== true;\n const isExpanded = this._isExpanded(node);\n const icon = node.item.icon;\n const tooltip = node.item.tooltip;\n\n const caretAndLabel = html`\n <span class=\"tree-caret\">\n ${isBranch ? html`<ixfx-icon class=\"caret-icon\" name=\"chevron-down\" .rotate=${isExpanded ? nothing : `-90deg`}></ixfx-icon>` : ``}\n </span>\n ${icon ? html`<ixfx-icon class=\"tree-icon\" name=\"${icon}\"></ixfx-icon>` : nothing}\n <span class=\"tree-label\">\n ${node.item.label}\n ${tooltip ? html`<ixfx-tooltip class=\"tree-tooltip\" anchor=\"--tooltip-tree-${node.item.key}\" .value=${tooltip}></ixfx-tooltip>` : nothing}\n </span>\n `;\n\n if (this.interactionMode === `checked`) {\n const state = computeCheckboxState(node, this._selectedNodes);\n return html`${this.#renderCheckbox(node, depth, state)}${caretAndLabel}`;\n }\n\n return caretAndLabel;\n }\n\n #renderCheckbox(node: TreeNode, depth: number, state: TreeCheckboxState): TemplateResult {\n const onClick = (e: MouseEvent) => this._handleCheckboxClick(e, node, depth);\n\n if (this.checkboxRenderer) {\n const ariaChecked = state === `indeterminate` ? `mixed` : state === `checked` ? `true` : `false`;\n return html`\n <span\n class=\"tree-checkbox tree-checkbox-custom\"\n part=\"checkbox\"\n role=\"checkbox\"\n tabindex=\"-1\"\n aria-checked=${ariaChecked}\n aria-label=\"Select ${node.item.label}\"\n @click=${onClick}\n >${this.checkboxRenderer(state)}</span>`;\n }\n\n return html`\n <input\n type=\"checkbox\"\n class=\"tree-checkbox\"\n part=\"checkbox\"\n .checked=${state === `checked`}\n .indeterminate=${state === `indeterminate`}\n aria-label=\"Select ${node.item.label}\"\n @click=${onClick}\n />`;\n }\n\n protected override _renderNode(node: TreeNode, depth: number): TemplateResult {\n const selected = this._isSelected(node);\n const tickled = this._isFocused(node);\n const isBranch = node.item.isLeaf !== true;\n const isExpanded = this._isExpanded(node);\n const isPending = this._pendingNode === node;\n const hasIconAtDepth = this.#depthsWithIcons.has(depth);\n\n return html`\n <li\n class=\"item ${selected ? `selected` : ``} ${tickled ? `tickled` : ``} ${isBranch ? `branch` : `leaf`} ${hasIconAtDepth ? `has-icon-at-depth` : ``}\"\n data-key=${node.item.key}\n role=\"treeitem\"\n aria-selected=${selected}\n aria-expanded=${isBranch ? isExpanded : nothing}\n aria-level=${depth + 1}\n style=${`--depth: ${depth}`}\n @click=${(e: MouseEvent) => this._handleItemClick(node, depth, e)}\n @pointerenter=${() => this.tickled.handlePointerEnter(node.item.key)}\n >\n ${this.renderNodeContent(node, depth)}\n ${isPending ? this.renderLoadingIndicator() : nothing}\n </li>\n `;\n }\n\n static override styles = [\n themeFallbacks,\n ...TreeBaseElement.styles,\n css`\n .tree-caret {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--tree-caret-size);\n height: var(--tree-caret-size);\n flex-shrink: 0;\n margin-right: var(--space-xs);\n }\n\n .caret-icon {\n width: var(--tree-caret-size);\n height: var(--tree-caret-size);\n color: var(--tree-muted-text);\n transition: transform var(--transition, 0.15s ease-out);\n }\n\n .item.selected .caret-icon {\n color: var(--accent-text);\n }\n\n .tree-icon {\n flex-shrink: 0;\n width: var(--icon-size, 1em);\n height: var(--icon-size, 1em);\n margin-right: var(--icon-spacing, 0.3em);\n }\n\n .item:not(.has-icon-at-depth) .tree-icon {\n display: none;\n }\n\n .item.has-icon-at-depth .tree-label {\n margin-left: var(--icon-size, 1em);\n }\n\n .tree-tooltip {\n position: absolute;\n anchor-name: --tooltip-tree;\n }\n\n .tree-checkbox {\n flex-shrink: 0;\n margin-right: var(--space-xs, 3px);\n cursor: pointer;\n accent-color: var(--accent);\n pointer-events: auto;\n }\n\n .tree-checkbox-custom {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* Reserves a click target even when the renderer returns empty content\n (e.g. the \"nothing when unchecked\" subtle style) — without an explicit\n size the empty span collapses to 0×0 and becomes unclickable. */\n width: var(--tree-checkbox-size, 14px);\n height: var(--tree-checkbox-size, 14px);\n }\n\n /* In checked mode the checkbox communicates selection state —\n suppress the row highlight so it doesn't double-signal */\n :host([interaction-mode=\"checked\"]) .item.selected {\n background: transparent;\n color: inherit;\n outline: none;\n }\n\n \n\n .tree-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n position: relative;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-tree-list': TreeListElement;\n }\n}\n\nexport interface TreeListElement {\n addEventListener: (<K extends keyof TreeBaseElementEventMap>(\n type: K,\n listener: (this: TreeListElement, event: TreeBaseElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n}\n","import type { TraversableTree } from '@ixfx/collections';\nimport type { TreeBaseElement } from './tree-base.js';\nimport type { TreeItem, TreeNode } from './types.js';\n\nexport type TreeControllerOptions<T> = {\n valueToItem: (value: T, node: TraversableTree<T>) => TreeItem;\n};\n\nexport class TreeController<T> {\n #root: TraversableTree<T>;\n #element: TreeBaseElement;\n #options: TreeControllerOptions<T>;\n\n #nodeToTree = new WeakMap<TreeNode, TraversableTree<T>>();\n #identityToTreeNode = new Map<unknown, TraversableTree<T>>();\n\n #connectSignal: AbortController | undefined;\n\n constructor(\n root: TraversableTree<T>,\n element: TreeBaseElement,\n options: TreeControllerOptions<T>,\n ) {\n this.#root = root;\n this.#element = element;\n this.#options = options;\n }\n\n connect() {\n this.disconnect();\n this.#connectSignal = new AbortController();\n const { signal } = this.#connectSignal;\n\n const rootValue = this.#root.getValue();\n const rootItem = this.#options.valueToItem(rootValue, this.#root);\n const rootChildren = this.#childrenOf(this.#root);\n\n this.#element.root = { item: rootItem, children: rootChildren };\n\n this.#element.addEventListener(`expand`, (e: Event) => {\n const { node } = (e as CustomEvent<{ node: TreeNode }>).detail;\n const treeNode = this.#nodeToTree.get(node);\n if (!treeNode)\n return;\n node.children = this.#childrenOf(treeNode);\n this.#element.requestUpdate();\n }, { signal });\n\n this.#element.addEventListener(`collapse`, (_e: Event) => {\n }, { signal });\n }\n\n disconnect() {\n this.#connectSignal?.abort();\n this.#connectSignal = undefined;\n }\n\n navigateToValue(predicate: (value: T) => boolean): boolean {\n const treePath = this.#findTreePath(this.#root, predicate);\n if (!treePath)\n return false;\n\n const keys: string[] = [];\n\n for (let i = 1; i < treePath.length; i++) {\n const treeNode = treePath[i];\n const key = this.#options.valueToItem(treeNode.getValue(), treeNode).key;\n keys.push(key);\n\n if (i < treePath.length - 1) {\n const currentChildren = i === 1\n ? this.#element.root?.children ?? []\n : this.#findInChildren(this.#element.root?.children ?? [], keys);\n\n const treeNodeMap = this.#nodeToTree;\n const node = currentChildren.find(n => n.item.key === key);\n if (!node)\n return false;\n\n if (node.children === undefined) {\n const mapped = treeNodeMap.get(node);\n if (mapped)\n node.children = this.#childrenOf(mapped);\n }\n }\n }\n\n return this.#element.navigateTo(keys);\n }\n\n #findInChildren(children: TreeNode[], keys: string[]): TreeNode[] {\n if (keys.length === 0)\n return children;\n const key = keys[0];\n const found = children.find(n => n.item.key === key);\n return found?.children ?? [];\n }\n\n #childrenOf(treeNode: TraversableTree<T>): TreeNode[] {\n return Array.from(treeNode.children(), child => this.#toTreeNode(child));\n }\n\n #toTreeNode(treeNode: TraversableTree<T>): TreeNode {\n const value = treeNode.getValue();\n const childList = [...treeNode.children()];\n const userItem = this.#options.valueToItem(value, treeNode);\n\n const isLeaf = userItem.isLeaf ?? childList.length === 0;\n\n const treeNodeMap: TreeNode = {\n item: { ...userItem, isLeaf },\n };\n\n this.#nodeToTree.set(treeNodeMap, treeNode);\n this.#identityToTreeNode.set(treeNode.getIdentity(), treeNode);\n return treeNodeMap;\n }\n\n #findTreePath(\n node: TraversableTree<T>,\n predicate: (value: T) => boolean,\n ancestors: Array<TraversableTree<T>> = [],\n ): Array<TraversableTree<T>> | undefined {\n const path = [...ancestors, node];\n if (predicate(node.getValue()))\n return path;\n for (const child of node.children()) {\n const result = this.#findTreePath(child, predicate, path);\n if (result)\n return result;\n }\n return undefined;\n }\n}\n"],"mappings":"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"}
package/dist/tree.d.ts CHANGED
@@ -77,8 +77,30 @@ interface TreeBaseElement {
77
77
  }
78
78
  //#endregion
79
79
  //#region src/tree/tree-list.d.ts
80
+ /** Checkbox tri-state in `checked` interactionMode: a branch node is `indeterminate` when some but not all of its descendants are selected. */
81
+ type TreeCheckboxState = `checked` | `unchecked` | `indeterminate`;
80
82
  declare class TreeListElement extends TreeBaseElement {
81
83
  #private;
84
+ /**
85
+ * Optional renderer for the checkbox shown in `checked` interactionMode.
86
+ * Receives the node's current tri-state (`checked` / `unchecked` / `indeterminate`,
87
+ * the latter when some but not all descendants are selected) and returns a Lit
88
+ * template.
89
+ *
90
+ * When set, the checkbox becomes a `<span role="checkbox">` whose contents are
91
+ * whatever this returns. When unset, a native `<input type="checkbox">` is used.
92
+ *
93
+ * @example
94
+ * list.checkboxRenderer = (state) => state === `unchecked`
95
+ * ? html``
96
+ * : html`<svg viewBox="0 0 16 16" width="14" height="14"
97
+ * fill="none" stroke="currentColor" stroke-width="2"
98
+ * stroke-linecap="round" stroke-linejoin="round"
99
+ * style="opacity:${state === `indeterminate` ? 0.35 : 0.6}">
100
+ * <polyline points="3,8 7,12 13,4" />
101
+ * </svg>`;
102
+ */
103
+ checkboxRenderer: ((state: TreeCheckboxState) => unknown) | undefined;
82
104
  protected render(): TemplateResult<1>;
83
105
  protected renderNodeContent(node: TreeNode, depth: number): TemplateResult;
84
106
  protected _renderNode(node: TreeNode, depth: number): TemplateResult;
@@ -105,5 +127,5 @@ declare class TreeController<T> {
105
127
  navigateToValue(predicate: (value: T) => boolean): boolean;
106
128
  }
107
129
  //#endregion
108
- export { type LoadChildrenCallback, type TreeActivateDetail, type TreeActivateEvent, TreeBaseElement, TreeBaseElementEventMap, type TreeCollapseDetail, type TreeCollapseEvent, type TreeComponentEventMap, TreeConfig, TreeController, TreeControllerOptions, TreeDataModel, type TreeDataModelOptions, type TreeExclusivity, type TreeExpandDetail, type TreeExpandEvent, type TreeFilterPredicate, type TreeItem, type TreeItemClickDetail, type TreeItemClickEvent, TreeListElement, type TreeNode, type TreeSelectDetail, type TreeSelectEvent, type TreeSelectionFilter, type TreeTickleDetail, type TreeTickleEvent };
130
+ export { type LoadChildrenCallback, type TreeActivateDetail, type TreeActivateEvent, TreeBaseElement, TreeBaseElementEventMap, TreeCheckboxState, type TreeCollapseDetail, type TreeCollapseEvent, type TreeComponentEventMap, TreeConfig, TreeController, TreeControllerOptions, TreeDataModel, type TreeDataModelOptions, type TreeExclusivity, type TreeExpandDetail, type TreeExpandEvent, type TreeFilterPredicate, type TreeItem, type TreeItemClickDetail, type TreeItemClickEvent, TreeListElement, type TreeNode, type TreeSelectDetail, type TreeSelectEvent, type TreeSelectionFilter, type TreeTickleDetail, type TreeTickleEvent };
109
131
  //# sourceMappingURL=tree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tree.d.ts","names":[],"sources":["../src/tree/types.ts","../src/tree/tree-base.ts","../src/tree/tree-list.ts","../src/tree/tree-controller.ts"],"mappings":";;;;;;;;KAqCY;EACV;;;;cCEW,wBAAwB,sBAAsB,eAAe;;EAExE,MAAM;EAGN,OAAO;;EAIP,cAAc;EAGd,aAAa;EAGb,iBAAiB;;EAIjB,iBAAiB;EAGjB,cAAc;YAGJ,gBAAc,IAAA;MAEpB,iBAAiB,YAAY;EAKjC,iBAAiB;EAGjB;EAGA,UAAU;YAGA,eAAa;YAEb,SAAO;YAWP;EAaD,QAAQ,cAAc;EA4CtB;EAmBA;EAYT,aAAa;EAIb,UAAU,QAAQ,QAAQ;EAO1B,OAAO,MAAM;EAWb,SAAS,MAAM;EAYf;EASA;EAoBA;EAiBA,WAAW;EAoCX,eAAe,YAAY,MAAM;EASjC,YAAY;IAAgB,MAAM;IAAU;;YA6DlC,kBAAkB,MAAM,UAAU,iBAAiB,wBAAwB;YAW3E,iBAAiB,MAAM,UAAU,eAAe,QAAQ;YAuJxD,qBAAqB,OAAO,YAAY,MAAM,UAAU;YAsJxD,YAAY,MAAM;YAIlB,WAAW,MAAM;YAIjB,YAAY,MAAM;gBAiBd,gBAAgB;YAsRpB,0BAA0B,wBAAwB;YAIzC,UAAM;YAoDf,YAAY,MAAM,UAAU,gBAAgB;SAiCtC,sBAAM;;QA4GhB;YACI;IACR,kBAAkB;;;UAIL,gCAAgC;EAC/C,cAAc;EACd,UAAU;EACV,YAAY;EACZ,UAAU;EACV,UAAU;EACV,YAAY;;UAGG;EACf,oBAAoB,gBAAgB,yBAClC,MAAM,GACN,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aACjE,oBAAoB,sCAEpB,cACA,UAAU,oCACV,oBAAoB;EAEtB,uBAAuB,gBAAgB,yBACrC,MAAM,GACN,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aACjE,oBAAoB,mCAEpB,cACA,UAAU,oCACV,oBAAoB;;;;cClqCX,wBAAwB;;YAGhB,UAAM;YAsBN,kBAAkB,MAAM,UAAU,gBAAgB;YAiClD,YAAY,MAAM,UAAU,gBAAgB;SA0B/C,sBAAM;;QA0EhB;YACI;IACR,kBAAkB;;;UAIL;EACf,oBAAoB,gBAAgB,yBAClC,MAAM,GACN,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aACjE,oBAAoB,sCAEpB,cACA,UAAU,oCACV,oBAAoB;;;;KClMZ,sBAAsB;EAChC,cAAc,OAAO,GAAG,MAAM,gBAAgB,OAAO;;cAG1C,eAAe;;EAWxB,YAAA,MAAM,gBAAgB,IACtB,SAAS,iBACT,SAAS,sBAAsB;EAOjC;EAwBA;EAKA,gBAAgB,YAAY,OAAO"}
1
+ {"version":3,"file":"tree.d.ts","names":[],"sources":["../src/tree/types.ts","../src/tree/tree-base.ts","../src/tree/tree-list.ts","../src/tree/tree-controller.ts"],"mappings":";;;;;;;;KAqCY;EACV;;;;cCEW,wBAAwB,sBAAsB,eAAe;;EAExE,MAAM;EAGN,OAAO;;EAIP,cAAc;EAGd,aAAa;EAGb,iBAAiB;;EAIjB,iBAAiB;EAGjB,cAAc;YAGJ,gBAAc,IAAA;MAEpB,iBAAiB,YAAY;EAKjC,iBAAiB;EAGjB;EAGA,UAAU;YAGA,eAAa;YAEb,SAAO;YAWP;EAaD,QAAQ,cAAc;EA4CtB;EAmBA;EAYT,aAAa;EAIb,UAAU,QAAQ,QAAQ;EAO1B,OAAO,MAAM;EAWb,SAAS,MAAM;EAYf;EASA;EAoBA;EAiBA,WAAW;EAoCX,eAAe,YAAY,MAAM;EASjC,YAAY;IAAgB,MAAM;IAAU;;YA6DlC,kBAAkB,MAAM,UAAU,iBAAiB,wBAAwB;YAW3E,iBAAiB,MAAM,UAAU,eAAe,QAAQ;YAuJxD,qBAAqB,OAAO,YAAY,MAAM,UAAU;YAsJxD,YAAY,MAAM;YAIlB,WAAW,MAAM;YAIjB,YAAY,MAAM;gBAiBd,gBAAgB;YAsRpB,0BAA0B,wBAAwB;YAIzC,UAAM;YAoDf,YAAY,MAAM,UAAU,gBAAgB;SAiCtC,sBAAM;;QA4GhB;YACI;IACR,kBAAkB;;;UAIL,gCAAgC;EAC/C,cAAc;EACd,UAAU;EACV,YAAY;EACZ,UAAU;EACV,UAAU;EACV,YAAY;;UAGG;EACf,oBAAoB,gBAAgB,yBAClC,MAAM,GACN,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aACjE,oBAAoB,sCAEpB,cACA,UAAU,oCACV,oBAAoB;EAEtB,uBAAuB,gBAAgB,yBACrC,MAAM,GACN,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aACjE,oBAAoB,mCAEpB,cACA,UAAU,oCACV,oBAAoB;;;;;KCjrCZ;cAiBC,wBAAwB;;;;;;;;;;;;;;;;;;;;;EAqBnC,oBAAoB,OAAO;YAIR,UAAM;YAsBN,kBAAkB,MAAM,UAAU,gBAAgB;YAsDlD,YAAY,MAAM,UAAU,gBAAgB;SA0B/C,sBAAM;;QAqFhB;YACI;IACR,kBAAkB;;;UAIL;EACf,oBAAoB,gBAAgB,yBAClC,MAAM,GACN,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aACjE,oBAAoB,sCAEpB,cACA,UAAU,oCACV,oBAAoB;;;;KC1PZ,sBAAsB;EAChC,cAAc,OAAO,GAAG,MAAM,gBAAgB,OAAO;;cAG1C,eAAe;;EAWxB,YAAA,MAAM,gBAAgB,IACtB,SAAS,iBACT,SAAS,sBAAsB;EAOjC;EAwBA;EAKA,gBAAgB,YAAY,OAAO"}
package/dist/tree.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as TreeDataModel, n as TreeListElement, r as TreeBaseElement, t as TreeController } from "./tree-KAXDGm7w.js";
1
+ import { i as TreeDataModel, n as TreeListElement, r as TreeBaseElement, t as TreeController } from "./tree-CL-txefQ.js";
2
2
  export { TreeBaseElement, TreeController, TreeDataModel, TreeListElement };
package/docs-user/tree.md CHANGED
@@ -10,6 +10,7 @@ Three components share a common `TreeComponent` interface: **`ixfx-tree-list`**,
10
10
 
11
11
  1. [Data model](#data-model)
12
12
  2. [Properties](#properties)
13
+ - [Custom checkbox (`checkboxRenderer`)](#custom-checkbox-ixfx-tree-list-only--checkboxrenderer)
13
14
  3. [Selection](#selection)
14
15
  4. [Events](#events)
15
16
  5. [Keyboard navigation](#keyboard-navigation)
@@ -155,6 +156,40 @@ Controls how pointer and keyboard gestures translate to selection changes.
155
156
 
156
157
  Switching `interactionMode` clears the current selection.
157
158
 
159
+ ### Custom checkbox (`ixfx-tree-list` only) — `checkboxRenderer`
160
+
161
+ In `checked` mode every checkable row gets a checkbox before its caret/icon/label. By default that's a native `<input type="checkbox">`, with `.indeterminate` set when a branch has some but not all descendants selected.
162
+
163
+ Set `checkboxRenderer` on `ixfx-tree-list` to replace it with your own template. The function receives the row's current tri-state — `'checked' | 'unchecked' | 'indeterminate'` — so a branch with a partial selection can render distinctly (a dash, a dimmer mark, etc.) rather than collapsing to just checked/unchecked:
164
+
165
+ ```typescript
166
+ import { html } from 'lit';
167
+ import type { TreeListElement } from '@ixfx/components';
168
+
169
+ const tree = document.querySelector<TreeListElement>('#my-tree')!;
170
+ tree.interactionMode = 'checked';
171
+
172
+ tree.checkboxRenderer = (state) => state === `unchecked`
173
+ ? html``
174
+ : html`<svg viewBox="0 0 16 16" width="14" height="14"
175
+ fill="none" stroke="currentColor" stroke-width="2"
176
+ stroke-linecap="round" stroke-linejoin="round"
177
+ style="opacity:${state === `indeterminate` ? 0.35 : 0.7}">
178
+ <polyline points="3,8 7,12 13,4" />
179
+ </svg>`;
180
+ ```
181
+
182
+ When `checkboxRenderer` is set, the checkbox becomes a `<span class="tree-checkbox" role="checkbox" part="checkbox">` holding your template, with `aria-checked` set to `"true"`, `"false"`, or `"mixed"` to match the tri-state. The span owns the click (same as the native input), so clicking anywhere in it — including empty space when you render nothing for `unchecked` — toggles the row.
183
+
184
+ Both the native input and the custom span expose the `checkbox` CSS part for external styling:
185
+
186
+ ```css
187
+ ixfx-tree-list::part(checkbox) {
188
+ width: 18px;
189
+ margin-right: 6px;
190
+ }
191
+ ```
192
+
158
193
  ### `selectionFilter`
159
194
 
160
195
  | Value | Behaviour |
@@ -583,6 +618,9 @@ type TreeExclusivity = 'none' | 'depth' | 'global';
583
618
  type TreeSelectionFilter = 'none' | 'leaf' | 'branch';
584
619
  type TreeInteractionMode = 'implicit' | 'standard' | 'manual' | 'checked' | 'vscode';
585
620
 
621
+ // ixfx-tree-list only
622
+ type TreeCheckboxState = 'checked' | 'unchecked' | 'indeterminate';
623
+
586
624
  interface TreeComponent extends EventTarget {
587
625
  root: TreeNode | undefined;
588
626
  model: TreeDataModel | undefined;