luxen-ui 0.6.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.mjs +54 -10
- package/cdn/chunks/decorate.js +1 -1
- package/cdn/chunks/floating-ui.dom.js +2 -0
- package/cdn/chunks/floating-ui.dom.js.map +1 -0
- package/cdn/chunks/lit-html.js +3 -0
- package/cdn/chunks/lit-html.js.map +1 -0
- package/cdn/chunks/lit.js +1 -2
- package/cdn/chunks/lit.js.map +1 -1
- package/cdn/chunks/module.js +717 -0
- package/cdn/chunks/module.js.map +1 -0
- package/cdn/chunks/native.js +2 -0
- package/cdn/chunks/native.js.map +1 -0
- package/cdn/chunks/static-html.js +2 -0
- package/cdn/chunks/static-html.js.map +1 -0
- package/cdn/custom-elements.json +1412 -12629
- package/cdn/elements/avatar/avatar.d.ts +5 -0
- package/cdn/elements/avatar/avatar.d.ts.map +1 -1
- package/cdn/elements/avatar/avatar.js +5 -5
- package/cdn/elements/avatar/avatar.js.map +1 -1
- package/cdn/elements/button/button.meta.d.ts +33 -0
- package/cdn/elements/button/button.meta.d.ts.map +1 -0
- package/cdn/elements/button/button.meta.js +0 -0
- package/cdn/elements/carousel/carousel.d.ts +6 -0
- package/cdn/elements/carousel/carousel.d.ts.map +1 -1
- package/cdn/elements/carousel/carousel.js +1 -1
- package/cdn/elements/carousel/carousel.js.map +1 -1
- package/cdn/elements/carousel-item/carousel-item.d.ts +2 -0
- package/cdn/elements/carousel-item/carousel-item.d.ts.map +1 -1
- package/cdn/elements/carousel-item/carousel-item.js +1 -1
- package/cdn/elements/carousel-item/carousel-item.js.map +1 -1
- package/cdn/elements/close-button/close-button.meta.d.ts +24 -0
- package/cdn/elements/close-button/close-button.meta.d.ts.map +1 -0
- package/cdn/elements/close-button/close-button.meta.js +0 -0
- package/cdn/elements/dialog/dialog.d.ts +12 -6
- package/cdn/elements/dialog/dialog.d.ts.map +1 -1
- package/cdn/elements/dialog/dialog.js +8 -5
- package/cdn/elements/dialog/dialog.js.map +1 -1
- package/cdn/elements/dialog/dialog.styles.js +1 -1
- package/cdn/elements/dialog/dialog.styles.js.map +1 -1
- package/cdn/elements/disclosure/disclosure.meta.d.ts +28 -0
- package/cdn/elements/disclosure/disclosure.meta.d.ts.map +1 -0
- package/cdn/elements/disclosure/disclosure.meta.js +0 -0
- package/cdn/elements/divider/divider.d.ts +1 -1
- package/cdn/elements/divider/divider.js.map +1 -1
- package/cdn/elements/drawer/drawer.d.ts +5 -0
- package/cdn/elements/drawer/drawer.d.ts.map +1 -1
- package/cdn/elements/drawer/drawer.js +1 -1
- package/cdn/elements/drawer/drawer.js.map +1 -1
- package/cdn/elements/dropdown/dropdown.d.ts +2 -0
- package/cdn/elements/dropdown/dropdown.d.ts.map +1 -1
- package/cdn/elements/dropdown/dropdown.js +1 -1
- package/cdn/elements/dropdown/dropdown.js.map +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.d.ts +2 -0
- package/cdn/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js.map +1 -1
- package/cdn/elements/icon/icon.js +1 -1
- package/cdn/elements/icon/icon.js.map +1 -1
- package/cdn/elements/input-otp/input-otp.d.ts +2 -0
- package/cdn/elements/input-otp/input-otp.d.ts.map +1 -1
- package/cdn/elements/input-otp/input-otp.js.map +1 -1
- package/cdn/elements/input-stepper/input-stepper.d.ts +2 -0
- package/cdn/elements/input-stepper/input-stepper.d.ts.map +1 -1
- package/cdn/elements/input-stepper/input-stepper.js +1 -1
- package/cdn/elements/input-stepper/input-stepper.js.map +1 -1
- package/cdn/elements/kbd/kbd.meta.d.ts +14 -0
- package/cdn/elements/kbd/kbd.meta.d.ts.map +1 -0
- package/cdn/elements/kbd/kbd.meta.js +0 -0
- package/cdn/elements/popover/popover.js +1 -1
- package/cdn/elements/popover/popover.js.map +1 -1
- package/cdn/elements/progress/progress.meta.d.ts +22 -0
- package/cdn/elements/progress/progress.meta.d.ts.map +1 -0
- package/cdn/elements/progress/progress.meta.js +0 -0
- package/cdn/elements/prose-editor/index.d.ts +2 -0
- package/cdn/elements/prose-editor/index.d.ts.map +1 -0
- package/cdn/elements/prose-editor/index.js +2 -0
- package/cdn/elements/prose-editor/index.js.map +1 -0
- package/cdn/elements/prose-editor/prose-editor.d.ts +113 -0
- package/cdn/elements/prose-editor/prose-editor.d.ts.map +1 -0
- package/cdn/elements/prose-editor/prose-editor.js +180 -0
- package/cdn/elements/prose-editor/prose-editor.js.map +1 -0
- package/cdn/elements/rating/rating.d.ts +2 -0
- package/cdn/elements/rating/rating.d.ts.map +1 -1
- package/cdn/elements/rating/rating.js +1 -1
- package/cdn/elements/rating/rating.js.map +1 -1
- package/cdn/elements/select/select.meta.d.ts +28 -0
- package/cdn/elements/select/select.meta.d.ts.map +1 -0
- package/cdn/elements/select/select.meta.js +0 -0
- package/cdn/elements/skeleton/skeleton.d.ts +3 -0
- package/cdn/elements/skeleton/skeleton.d.ts.map +1 -1
- package/cdn/elements/skeleton/skeleton.js.map +1 -1
- package/cdn/elements/spinner/spinner.js +1 -1
- package/cdn/elements/spinner/spinner.js.map +1 -1
- package/cdn/elements/sticky-bar/sticky-bar.js +1 -1
- package/cdn/elements/sticky-bar/sticky-bar.js.map +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.d.ts +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.d.ts.map +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.js +26 -26
- package/cdn/elements/stories-viewer/stories-viewer.js.map +1 -1
- package/cdn/elements/story/story.d.ts +10 -1
- package/cdn/elements/story/story.d.ts.map +1 -1
- package/cdn/elements/story/story.js +20 -20
- package/cdn/elements/story/story.js.map +1 -1
- package/cdn/elements/toast/toast.d.ts +5 -0
- package/cdn/elements/toast/toast.d.ts.map +1 -1
- package/cdn/elements/toast/toast.js.map +1 -1
- package/cdn/elements/tooltip/tooltip.js +1 -1
- package/cdn/elements/tooltip/tooltip.js.map +1 -1
- package/cdn/elements/tree/tree.d.ts +2 -0
- package/cdn/elements/tree/tree.d.ts.map +1 -1
- package/cdn/elements/tree/tree.js +1 -1
- package/cdn/elements/tree/tree.js.map +1 -1
- package/cdn/elements/tree-item/tree-item.d.ts +2 -0
- package/cdn/elements/tree-item/tree-item.d.ts.map +1 -1
- package/cdn/elements/tree-item/tree-item.js +1 -1
- package/cdn/elements/tree-item/tree-item.js.map +1 -1
- package/cdn/registry.d.ts +1 -1
- package/cdn/registry.d.ts.map +1 -1
- package/cdn/registry.js.map +1 -1
- package/cdn/shared/controllers/has-slot-controller.d.ts +37 -0
- package/cdn/shared/controllers/has-slot-controller.d.ts.map +1 -0
- package/cdn/shared/controllers/has-slot-controller.js +2 -0
- package/cdn/shared/controllers/has-slot-controller.js.map +1 -0
- package/cdn/shared/controllers/popover.js +1 -1
- package/cdn/shared/controllers/popover.js.map +1 -1
- package/cdn/shared/styles/host.styles.js +1 -1
- package/cdn/standalone.css +132 -1
- package/cdn/standalone.js +25743 -191
- package/cdn/standalone.js.map +1 -1
- package/cdn/static-tag.d.ts +17 -0
- package/cdn/static-tag.d.ts.map +1 -0
- package/cdn/static-tag.js +2 -0
- package/cdn/static-tag.js.map +1 -0
- package/cdn/styles/elements/prose-editor.css +129 -0
- package/cdn/styles/elements/toast.css +1 -1
- package/dist/css/elements/prose-editor.css +129 -0
- package/dist/css/elements/toast.css +1 -1
- package/dist/custom-elements.json +1412 -12629
- package/dist/elements/avatar/avatar.d.ts +5 -0
- package/dist/elements/avatar/avatar.d.ts.map +1 -1
- package/dist/elements/avatar/avatar.js +5 -0
- package/dist/elements/button/button.meta.d.ts +33 -0
- package/dist/elements/button/button.meta.d.ts.map +1 -0
- package/dist/elements/button/button.meta.js +44 -0
- package/dist/elements/carousel/carousel.d.ts +6 -0
- package/dist/elements/carousel/carousel.d.ts.map +1 -1
- package/dist/elements/carousel/carousel.js +6 -0
- package/dist/elements/carousel-item/carousel-item.d.ts +2 -0
- package/dist/elements/carousel-item/carousel-item.d.ts.map +1 -1
- package/dist/elements/carousel-item/carousel-item.js +2 -0
- package/dist/elements/close-button/close-button.meta.d.ts +24 -0
- package/dist/elements/close-button/close-button.meta.d.ts.map +1 -0
- package/dist/elements/close-button/close-button.meta.js +30 -0
- package/dist/elements/dialog/dialog.css +15 -0
- package/dist/elements/dialog/dialog.d.ts +12 -6
- package/dist/elements/dialog/dialog.d.ts.map +1 -1
- package/dist/elements/dialog/dialog.js +21 -7
- package/dist/elements/disclosure/disclosure.meta.d.ts +28 -0
- package/dist/elements/disclosure/disclosure.meta.d.ts.map +1 -0
- package/dist/elements/disclosure/disclosure.meta.js +34 -0
- package/dist/elements/divider/divider.d.ts +1 -1
- package/dist/elements/divider/divider.js +1 -1
- package/dist/elements/drawer/drawer.d.ts +5 -0
- package/dist/elements/drawer/drawer.d.ts.map +1 -1
- package/dist/elements/drawer/drawer.js +5 -0
- package/dist/elements/dropdown/dropdown.d.ts +2 -0
- package/dist/elements/dropdown/dropdown.d.ts.map +1 -1
- package/dist/elements/dropdown/dropdown.js +2 -0
- package/dist/elements/dropdown-item/dropdown-item.d.ts +2 -0
- package/dist/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
- package/dist/elements/dropdown-item/dropdown-item.js +2 -0
- package/dist/elements/input-otp/input-otp.d.ts +2 -0
- package/dist/elements/input-otp/input-otp.d.ts.map +1 -1
- package/dist/elements/input-otp/input-otp.js +2 -0
- package/dist/elements/input-stepper/input-stepper.d.ts +2 -0
- package/dist/elements/input-stepper/input-stepper.d.ts.map +1 -1
- package/dist/elements/input-stepper/input-stepper.js +5 -1
- package/dist/elements/kbd/kbd.meta.d.ts +14 -0
- package/dist/elements/kbd/kbd.meta.d.ts.map +1 -0
- package/dist/elements/kbd/kbd.meta.js +20 -0
- package/dist/elements/progress/progress.meta.d.ts +22 -0
- package/dist/elements/progress/progress.meta.d.ts.map +1 -0
- package/dist/elements/progress/progress.meta.js +28 -0
- package/dist/elements/prose-editor/index.d.ts +2 -0
- package/dist/elements/prose-editor/index.d.ts.map +1 -0
- package/dist/elements/prose-editor/index.js +4 -0
- package/dist/elements/prose-editor/prose-editor.css +133 -0
- package/dist/elements/prose-editor/prose-editor.d.ts +114 -0
- package/dist/elements/prose-editor/prose-editor.d.ts.map +1 -0
- package/dist/elements/prose-editor/prose-editor.js +481 -0
- package/dist/elements/rating/rating.d.ts +2 -0
- package/dist/elements/rating/rating.d.ts.map +1 -1
- package/dist/elements/rating/rating.js +2 -0
- package/dist/elements/select/select.meta.d.ts +28 -0
- package/dist/elements/select/select.meta.d.ts.map +1 -0
- package/dist/elements/select/select.meta.js +34 -0
- package/dist/elements/skeleton/skeleton.d.ts +3 -0
- package/dist/elements/skeleton/skeleton.d.ts.map +1 -1
- package/dist/elements/skeleton/skeleton.js +3 -0
- package/dist/elements/stories-viewer/stories-viewer.d.ts +1 -1
- package/dist/elements/stories-viewer/stories-viewer.d.ts.map +1 -1
- package/dist/elements/stories-viewer/stories-viewer.js +23 -19
- package/dist/elements/story/story.d.ts +10 -1
- package/dist/elements/story/story.d.ts.map +1 -1
- package/dist/elements/story/story.js +29 -17
- package/dist/elements/toast/toast.d.ts +5 -0
- package/dist/elements/toast/toast.d.ts.map +1 -1
- package/dist/elements/toast/toast.js +5 -0
- package/dist/elements/tree/tree.d.ts +2 -0
- package/dist/elements/tree/tree.d.ts.map +1 -1
- package/dist/elements/tree/tree.js +2 -0
- package/dist/elements/tree-item/tree-item.d.ts +2 -0
- package/dist/elements/tree-item/tree-item.d.ts.map +1 -1
- package/dist/elements/tree-item/tree-item.js +2 -0
- package/dist/metadata/avatar.json +83 -0
- package/dist/metadata/badge.json +59 -0
- package/dist/metadata/button.json +138 -0
- package/dist/metadata/carousel-item.json +32 -0
- package/dist/metadata/carousel.json +388 -0
- package/dist/metadata/close-button.json +90 -0
- package/dist/metadata/dialog.json +163 -0
- package/dist/metadata/disclosure.json +88 -0
- package/dist/metadata/divider.json +65 -0
- package/dist/metadata/drawer.json +176 -0
- package/dist/metadata/dropdown-item.json +85 -0
- package/dist/metadata/dropdown.json +157 -0
- package/dist/metadata/icon.json +49 -0
- package/dist/metadata/index.json +4062 -0
- package/dist/metadata/input-otp.json +86 -0
- package/dist/metadata/input-stepper.json +122 -0
- package/dist/metadata/kbd.json +37 -0
- package/dist/metadata/popover.json +157 -0
- package/dist/metadata/progress.json +71 -0
- package/dist/metadata/prose-editor.json +365 -0
- package/dist/metadata/rating.json +126 -0
- package/dist/metadata/select.json +82 -0
- package/dist/metadata/skeleton.json +56 -0
- package/dist/metadata/spinner.json +47 -0
- package/dist/metadata/sticky-bar.json +93 -0
- package/dist/metadata/stories-viewer.json +316 -0
- package/dist/metadata/stories.json +109 -0
- package/dist/metadata/story.json +148 -0
- package/dist/metadata/tabs.json +74 -0
- package/dist/metadata/toast.json +122 -0
- package/dist/metadata/tooltip.json +144 -0
- package/dist/metadata/tree-item.json +199 -0
- package/dist/metadata/tree.json +130 -0
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/shared/controllers/has-slot-controller.d.ts +37 -0
- package/dist/shared/controllers/has-slot-controller.d.ts.map +1 -0
- package/dist/shared/controllers/has-slot-controller.js +66 -0
- package/dist/static-tag.d.ts +17 -0
- package/dist/static-tag.d.ts.map +1 -0
- package/dist/static-tag.js +22 -0
- package/dist/templates/elements/avatar.md +21 -24
- package/dist/templates/elements/badge.md +9 -15
- package/dist/templates/elements/button.md +31 -41
- package/dist/templates/elements/close-button.md +24 -36
- package/dist/templates/elements/dialog.md +73 -54
- package/dist/templates/elements/drawer.md +39 -52
- package/dist/templates/elements/progress.md +13 -23
- package/dist/templates/elements/prose-editor.md +211 -0
- package/dist/templates/elements/select.md +20 -31
- package/dist/templates/elements/sticky-bar.md +16 -60
- package/dist/templates/elements/toast.md +33 -53
- package/dist/templates/elements/tree.md +39 -67
- package/elements.json +46 -1
- package/package.json +13 -3
- package/templates/SKILL.md.tpl +5 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tree/tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAM1D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpE
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tree/tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAM1D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,IAAK,SAAQ,YAAY;IACpC,OAAgB,MAAM,4BAAwB;IAE9C,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAC7C,OAAO,CAAC,gBAAgB,CAAyB;IAEjD;;;;;;OAMG;IAEH,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAY;IAE7C;;;;OAIG;IAEH,QAAQ,CAAC,WAAW,UAAS;IAEpB,iBAAiB;IAUjB,oBAAoB;IAMpB,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;IAQ9C,yEAAyE;IACzE,WAAW,CAAC,EAAE,eAAsB,EAAE;;KAAK,GAAG,QAAQ,EAAE;IAOxD,wCAAwC;IACxC,YAAY,IAAI,QAAQ,EAAE;IAI1B,4CAA4C;IAC5C,SAAS;IAMT,4BAA4B;IAC5B,WAAW;IAQX,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,cAAc;IAUtB,2DAA2D;IAC3D,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa,CAGnB;IAEF,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,oBAAoB;IAS5B,0EAA0E;IAC1E,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,QAAQ,CAqDd;IAEF,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,UAAU,CAMhB;IAEF,OAAO,CAAC,UAAU,CAqEhB;IAEO,MAAM;CAehB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{tagName as e}from"../../registry.js";import{
|
|
1
|
+
import{tagName as e}from"../../registry.js";import{i as t}from"../../chunks/lit.js";import{a as n}from"../../chunks/lit-html.js";import{LuxenElement as r}from"../../shared/luxen-element.js";import{i,t as a}from"../../chunks/decorate.js";import o from"../../shared/styles/host.styles.js";var s=t(`:host{--indent-size:1rem;--indent-guide-width:1px;--indent-guide-style:solid;--indent-guide-color:var(--l-color-border-interactive,var(--lightningcss-light,#d1d5db)var(--lightningcss-dark,#3a4048));--row-height:1.75rem;--row-padding-inline:.25rem;--chevron-size:1.125rem;--item-gap:.375rem;color:var(--l-color-text-primary,CanvasText);font-family:inherit;line-height:1.5;display:block}.tree{outline:none;display:block}.tree:focus-visible{outline:2px solid var(--l-focus-ring,Highlight);outline-offset:2px;border-radius:.375rem}`),c=class extends r{constructor(...t){super(...t),this._lastFocusedItem=null,this.#e=`single`,this.#t=!1,this._onItemToggle=e=>{let{item:t,checked:n}=e.detail;this._selectItem(t,n)},this._onClick=e=>{let t=this._itemFromEvent(e);if(!t||t.disabled)return;let n=e.composedPath();if(n.some(e=>e instanceof HTMLInputElement&&e.type===`checkbox`))return;let r=new Set([`BUTTON`,`A`,`INPUT`,`SELECT`,`TEXTAREA`]),i=new Set([`button`,`link`,`menuitem`,`menuitemcheckbox`]);if(n.some(e=>{if(!(e instanceof HTMLElement)||e===t||e.getAttribute?.(`part`)===`expand-button`||e instanceof HTMLInputElement&&e.type===`checkbox`)return!1;if(r.has(e.tagName))return!0;let n=e.getAttribute?.(`role`);return n!==null&&i.has(n)}))return;let a=n.some(e=>e instanceof HTMLElement&&e.getAttribute?.(`part`)===`expand-button`);if(this._focusItem(t),a){t.toggle();return}switch(this.selection){case`single`:this._setSingleSelection(t),t.isLeaf()||t.toggle();break;case`leaf`:t.isLeaf()?this._setSingleSelection(t):t.toggle();break;case`multiple`:this._selectItem(t,!t.selected);break;case`none`:t.toggle();break}},this._onFocusIn=t=>{let n=t.target;if(n instanceof HTMLElement){let t=n.closest(e(`tree-item`));t&&(this._lastFocusedItem=t)}},this._onKeyDown=t=>{let n=this._lastFocusedItem??this._visibleItems()[0];if(!n)return;let r=this._visibleItems(),i=r.indexOf(n);switch(t.key){case`ArrowDown`:{t.preventDefault();let e=r[Math.min(i+1,r.length-1)];e&&this._focusItem(e);break}case`ArrowUp`:{t.preventDefault();let e=r[Math.max(i-1,0)];e&&this._focusItem(e);break}case`ArrowRight`:if(t.preventDefault(),!n.isLeaf()&&!n.expanded)n.expanded=!0;else if(n.expanded){let e=n.getChildrenItems()[0];e&&this._focusItem(e)}break;case`ArrowLeft`:if(t.preventDefault(),n.expanded&&!n.isLeaf())n.expanded=!1;else{let t=n.parentElement?.closest(e(`tree-item`));t&&this._focusItem(t)}break;case`Home`:t.preventDefault(),r[0]&&this._focusItem(r[0]);break;case`End`:{t.preventDefault();let e=r[r.length-1];e&&this._focusItem(e);break}case`Enter`:case` `:t.preventDefault(),this._handleRowActivate(n);break;case`*`:{t.preventDefault();let r=(n.parentElement?Array.from(n.parentElement.children):[]).filter(t=>t.tagName===e(`tree-item`).toUpperCase());for(let e of r)e.isLeaf()||(e.expanded=!0);break}}}}static{this.styles=[o,s]}#e;get selection(){return this.#e}set selection(e){this.#e=e}#t;get independent(){return this.#t}set independent(e){this.#t=e}connectedCallback(){super.connectedCallback(),this._mutationObserver=new MutationObserver(()=>this._syncAll()),this._mutationObserver.observe(this,{childList:!0,subtree:!0}),this.addEventListener(`l-tree-item-toggle`,this._onItemToggle),queueMicrotask(()=>this._syncAll())}disconnectedCallback(){super.disconnectedCallback(),this._mutationObserver?.disconnect(),this.removeEventListener(`l-tree-item-toggle`,this._onItemToggle)}updated(e){(e.has(`selection`)||e.has(`independent`))&&this._syncAll()}getAllItems({includeDisabled:t=!0}={}){let n=e(`tree-item`);return Array.from(this.querySelectorAll(n)).filter(e=>t||!e.disabled)}getSelection(){return this.getAllItems().filter(e=>e.selected)}expandAll(){for(let e of this.getAllItems())e.isLeaf()||(e.expanded=!0)}collapseAll(){for(let e of this.getAllItems())e.expanded=!1}_syncAll(){let e=this.selection===`multiple`,t=this._rootItems();for(let n of t)this._syncSubtree(n,0,e);this._updateBranchStates(),this._ensureTabStop()}_syncSubtree(e,t,n){e.depth=t,e.showCheckbox=n&&this._canShowCheckboxOn(e);for(let r of e.getChildrenItems())this._syncSubtree(r,t+1,n)}_canShowCheckboxOn(e){return this.selection===`multiple`}_rootItems(){let t=e(`tree-item`).toUpperCase();return Array.from(this.children).filter(e=>e.tagName===t)}_ensureTabStop(){let e=this._visibleItems();if(e.length!==0&&!e.some(e=>e.tabIndex===0)){for(let t of e)t.tabIndex=-1;e[0].tabIndex=0}}_visibleItems(){let e=[],t=n=>{for(let r of n)e.push(r),r.expanded&&t(r.getChildrenItems())};return t(this._rootItems()),e}_handleRowActivate(e){if(!e.disabled)switch(this.selection){case`single`:this._setSingleSelection(e);break;case`leaf`:e.isLeaf()?this._setSingleSelection(e):e.toggle();break;case`multiple`:this._selectItem(e,!e.selected);break;case`none`:e.toggle();break}}_setSingleSelection(e){for(let t of this.getAllItems())t!==e&&t.selected&&(t.selected=!1);e.selected=!0,this._emitSelectionChange()}_selectItem(e,t){e.disabled||(e.selected=t,this.selection===`multiple`&&!this.independent&&this._setSubtreeSelection(e,t),e.indeterminate=!1,this._updateBranchStates(),this._emitSelectionChange())}_setSubtreeSelection(e,t){for(let n of e.getChildrenItems())n.disabled||(n.selected=t,n.indeterminate=!1,this._setSubtreeSelection(n,t))}_updateBranchStates(){if(this.selection!==`multiple`||this.independent){for(let e of this.getAllItems())e.indeterminate=!1;return}let e=t=>{let n=t.getChildrenItems({includeDisabled:!1});if(n.length===0)return{all:t.selected,any:t.selected};let r=!0,i=!1;for(let t of n){let n=e(t);n.all||(r=!1),n.any&&(i=!0)}return t.selected=r,t.indeterminate=!r&&i,{all:r&&(t.getChildrenItems().length>0?r:t.selected),any:i}};for(let t of this._rootItems())e(t)}_emitSelectionChange(){this.emit(`selection-change`,{detail:{selection:this.getSelection()}})}_itemFromEvent(t){let n=e(`tree-item`),r=t.composedPath();for(let e of r)if(e instanceof HTMLElement&&e.matches?.(n))return e;return null}_focusItem(e){let t=this._visibleItems();for(let e of t)e.tabIndex=-1;e.tabIndex=0,e.focus(),this._lastFocusedItem=e}render(){return n`
|
|
2
2
|
<div
|
|
3
3
|
class="tree"
|
|
4
4
|
part="base"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.js","names":[],"sources":["../../../src/html/elements/tree/tree.css?inline","../../../src/html/elements/tree/tree.ts"],"sourcesContent":[":host {\n --indent-size: 1rem;\n --indent-guide-width: 1px;\n --indent-guide-style: solid;\n --indent-guide-color: var(--l-color-border-interactive, light-dark(#d1d5db, #3a4048));\n --row-height: 1.75rem;\n --row-padding-inline: 0.25rem;\n --chevron-size: 1.125rem;\n --item-gap: 0.375rem;\n\n display: block;\n color: var(--l-color-text-primary, CanvasText);\n font-family: inherit;\n line-height: 1.5;\n}\n\n.tree {\n display: block;\n outline: none;\n}\n\n.tree:focus-visible {\n outline: 2px solid var(--l-focus-ring, Highlight);\n outline-offset: 2px;\n border-radius: 0.375rem;\n}\n","import { html, unsafeCSS, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { tagName } from '../../registry.js';\nimport type { TreeItem } from '../tree-item/tree-item.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './tree.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\nexport type TreeSelection = 'single' | 'multiple' | 'leaf' | 'none';\n\n/**\n * A hierarchical tree view composed of `<l-tree-item>` children.\n *\n * @slot - One or more `l-tree-item` elements.\n *\n * @csspart base - The root tree container.\n *\n * @cssproperty --indent-size - Horizontal indent per depth level. Default `1rem`.\n * @cssproperty --indent-guide-width - Thickness of the vertical guide line between a parent and its children. Default `1px`. Set to `0` to hide guides.\n * @cssproperty --indent-guide-style - Line style of the guide (`solid`, `dashed`, `dotted`, `double`…). Default `solid`.\n * @cssproperty --indent-guide-color - Color of the guide line.\n * @cssproperty --row-height - Minimum row height. Default `1.75rem`.\n * @cssproperty --row-padding-inline - Inner inline padding of the row; also drives the content slot left indent and the indent guide column. Default `0.25rem`.\n * @cssproperty --chevron-size - Size of the expand/collapse chevron box. Default `1.125rem`.\n * @cssproperty --item-gap - Horizontal gap between chevron, prefix, label and suffix on the row; also drives the content slot left indent. Default `0.375rem`.\n *\n * @event selection-change - Fired when the selected items change. Detail: `{ selection: TreeItem[] }`.\n */\nexport class Tree extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _mutationObserver?: MutationObserver;\n private _lastFocusedItem: TreeItem | null = null;\n\n /**\n * Selection behaviour:\n * - `single` (default): at most one item selected via `aria-selected`.\n * - `multiple`: any number of items selected. Checkboxes are rendered.\n * - `leaf`: only leaf items can be selected (single). Branches just toggle.\n * - `none`: purely navigable, no selection state.\n */\n @property({ reflect: true })\n accessor selection: TreeSelection = 'single';\n\n /**\n * When set with `selection=\"multiple\"`, parent and children selection are decoupled:\n * toggling a parent does NOT toggle its descendants and vice versa.\n * Without it, selection cascades both ways and branches may become indeterminate.\n */\n @property({ type: Boolean, reflect: true })\n accessor independent = false;\n\n override connectedCallback() {\n super.connectedCallback();\n this._mutationObserver = new MutationObserver(() => this._syncAll());\n this._mutationObserver.observe(this, { childList: true, subtree: true });\n this.addEventListener('l-tree-item-toggle', this._onItemToggle as EventListener);\n\n // Defer sync to let light DOM upgrade.\n queueMicrotask(() => this._syncAll());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._mutationObserver?.disconnect();\n this.removeEventListener('l-tree-item-toggle', this._onItemToggle as EventListener);\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('selection') || changed.has('independent')) {\n this._syncAll();\n }\n }\n\n // --- Public API ---\n\n /** Returns all items in document (flat) order, including nested ones. */\n getAllItems({ includeDisabled = true } = {}): TreeItem[] {\n const tag = tagName('tree-item');\n return Array.from(this.querySelectorAll<TreeItem>(tag)).filter(\n (item) => includeDisabled || !item.disabled,\n );\n }\n\n /** Returns currently selected items. */\n getSelection(): TreeItem[] {\n return this.getAllItems().filter((i) => i.selected);\n }\n\n /** Expands every item that has children. */\n expandAll() {\n for (const item of this.getAllItems()) {\n if (!item.isLeaf()) item.expanded = true;\n }\n }\n\n /** Collapses every item. */\n collapseAll() {\n for (const item of this.getAllItems()) {\n item.expanded = false;\n }\n }\n\n // --- Sync / ARIA / depth / checkbox visibility ---\n\n private _syncAll() {\n const showCheckbox = this.selection === 'multiple';\n const roots = this._rootItems();\n for (const root of roots) {\n this._syncSubtree(root, 0, showCheckbox);\n }\n this._updateBranchStates();\n // Ensure at least one item is tabbable.\n this._ensureTabStop();\n }\n\n private _syncSubtree(item: TreeItem, depth: number, showCheckbox: boolean) {\n item.depth = depth;\n item.showCheckbox = showCheckbox && this._canShowCheckboxOn(item);\n for (const child of item.getChildrenItems()) {\n this._syncSubtree(child, depth + 1, showCheckbox);\n }\n }\n\n private _canShowCheckboxOn(_item: TreeItem): boolean {\n if (this.selection !== 'multiple') return false;\n // In cascade mode, branches get a checkbox too so you can bulk-toggle children.\n // In leaf-only selection, hidden here because selection !== 'multiple'.\n return true;\n }\n\n private _rootItems(): TreeItem[] {\n const tag = tagName('tree-item').toUpperCase();\n return (Array.from(this.children) as TreeItem[]).filter((el) => el.tagName === tag);\n }\n\n private _ensureTabStop() {\n const items = this._visibleItems();\n if (items.length === 0) return;\n const hasTabStop = items.some((i) => i.tabIndex === 0);\n if (!hasTabStop) {\n for (const i of items) i.tabIndex = -1;\n items[0].tabIndex = 0;\n }\n }\n\n /** Items currently visible (parent chain all expanded). */\n private _visibleItems(): TreeItem[] {\n const out: TreeItem[] = [];\n const walk = (items: TreeItem[]) => {\n for (const i of items) {\n out.push(i);\n if (i.expanded) walk(i.getChildrenItems());\n }\n };\n walk(this._rootItems());\n return out;\n }\n\n // --- Selection handling ---\n\n private _onItemToggle = (event: CustomEvent<{ item: TreeItem; checked: boolean }>) => {\n const { item, checked } = event.detail;\n this._selectItem(item, checked);\n };\n\n private _handleRowActivate(item: TreeItem) {\n if (item.disabled) return;\n\n switch (this.selection) {\n case 'single':\n this._setSingleSelection(item);\n break;\n case 'leaf':\n if (item.isLeaf()) this._setSingleSelection(item);\n else item.toggle();\n break;\n case 'multiple':\n this._selectItem(item, !item.selected);\n break;\n case 'none':\n item.toggle();\n break;\n }\n }\n\n private _setSingleSelection(item: TreeItem) {\n for (const i of this.getAllItems()) {\n if (i !== item && i.selected) i.selected = false;\n }\n item.selected = true;\n this._emitSelectionChange();\n }\n\n private _selectItem(item: TreeItem, value: boolean) {\n if (item.disabled) return;\n item.selected = value;\n\n if (this.selection === 'multiple' && !this.independent) {\n // Cascade DOWN: toggling a branch toggles all descendants.\n this._setSubtreeSelection(item, value);\n }\n\n item.indeterminate = false;\n this._updateBranchStates();\n this._emitSelectionChange();\n }\n\n private _setSubtreeSelection(item: TreeItem, value: boolean) {\n for (const child of item.getChildrenItems()) {\n if (child.disabled) continue;\n child.selected = value;\n child.indeterminate = false;\n this._setSubtreeSelection(child, value);\n }\n }\n\n /** Propagate child state UP to parents (indeterminate / auto-checked). */\n private _updateBranchStates() {\n if (this.selection !== 'multiple' || this.independent) {\n // In independent or non-multiple modes, clear any indeterminate flags.\n for (const i of this.getAllItems()) i.indeterminate = false;\n return;\n }\n\n const recompute = (item: TreeItem): { all: boolean; any: boolean } => {\n const children = item.getChildrenItems({ includeDisabled: false });\n if (children.length === 0) {\n return { all: item.selected, any: item.selected };\n }\n\n let all = true;\n let any = false;\n for (const child of children) {\n const state = recompute(child);\n if (!state.all) all = false;\n if (state.any) any = true;\n }\n\n item.selected = all;\n item.indeterminate = !all && any;\n return { all: all && (item.getChildrenItems().length > 0 ? all : item.selected), any };\n };\n\n for (const root of this._rootItems()) recompute(root);\n }\n\n private _emitSelectionChange() {\n this.emit('selection-change', { detail: { selection: this.getSelection() } });\n }\n\n // --- Keyboard / focus ---\n\n private _onClick = (event: MouseEvent) => {\n const item = this._itemFromEvent(event);\n if (!item || item.disabled) return;\n\n const path = event.composedPath();\n const onCheckbox = path.some((n) => n instanceof HTMLInputElement && n.type === 'checkbox');\n if (onCheckbox) return; // handled via change event\n\n // Clicks on consumer-provided interactive elements (buttons, links, form\n // controls, menu items…) must not toggle the row — the consumer owns that\n // interaction. Works regardless of which slot the element was placed in.\n const INTERACTIVE_TAGS = new Set(['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA']);\n const INTERACTIVE_ROLES = new Set(['button', 'link', 'menuitem', 'menuitemcheckbox']);\n const onInteractive = path.some((n) => {\n if (!(n instanceof HTMLElement) || n === item) return false;\n if (n.getAttribute?.('part') === 'expand-button') return false;\n if (n instanceof HTMLInputElement && n.type === 'checkbox') return false;\n if (INTERACTIVE_TAGS.has(n.tagName)) return true;\n const role = n.getAttribute?.('role');\n return role !== null && INTERACTIVE_ROLES.has(role);\n });\n if (onInteractive) return;\n\n const onExpand = path.some(\n (n) => n instanceof HTMLElement && n.getAttribute?.('part') === 'expand-button',\n );\n\n this._focusItem(item);\n\n if (onExpand) {\n item.toggle();\n return;\n }\n\n // Row click (label area): mode-dependent behaviour.\n switch (this.selection) {\n case 'single':\n this._setSingleSelection(item);\n if (!item.isLeaf()) item.toggle();\n break;\n case 'leaf':\n if (item.isLeaf()) this._setSingleSelection(item);\n else item.toggle();\n break;\n case 'multiple':\n // The whole row acts like a <label> for the checkbox: clicking anywhere\n // on it toggles selection. Use the chevron to expand/collapse branches.\n this._selectItem(item, !item.selected);\n break;\n case 'none':\n item.toggle();\n break;\n }\n };\n\n private _itemFromEvent(event: Event): TreeItem | null {\n const tag = tagName('tree-item');\n const path = event.composedPath();\n for (const node of path) {\n if (node instanceof HTMLElement && node.matches?.(tag)) {\n return node as TreeItem;\n }\n }\n return null;\n }\n\n private _focusItem(item: TreeItem) {\n const visible = this._visibleItems();\n for (const i of visible) i.tabIndex = -1;\n item.tabIndex = 0;\n item.focus();\n this._lastFocusedItem = item;\n }\n\n private _onFocusIn = (event: FocusEvent) => {\n const target = event.target;\n if (target instanceof HTMLElement) {\n const item = target.closest<TreeItem>(tagName('tree-item'));\n if (item) this._lastFocusedItem = item;\n }\n };\n\n private _onKeyDown = (event: KeyboardEvent) => {\n const current = this._lastFocusedItem ?? this._visibleItems()[0];\n if (!current) return;\n\n const visible = this._visibleItems();\n const index = visible.indexOf(current);\n\n switch (event.key) {\n case 'ArrowDown': {\n event.preventDefault();\n const next = visible[Math.min(index + 1, visible.length - 1)];\n if (next) this._focusItem(next);\n break;\n }\n case 'ArrowUp': {\n event.preventDefault();\n const prev = visible[Math.max(index - 1, 0)];\n if (prev) this._focusItem(prev);\n break;\n }\n case 'ArrowRight': {\n event.preventDefault();\n if (!current.isLeaf() && !current.expanded) {\n current.expanded = true;\n } else if (current.expanded) {\n const first = current.getChildrenItems()[0];\n if (first) this._focusItem(first);\n }\n break;\n }\n case 'ArrowLeft': {\n event.preventDefault();\n if (current.expanded && !current.isLeaf()) {\n current.expanded = false;\n } else {\n const parent = current.parentElement?.closest(tagName('tree-item')) as TreeItem | null;\n if (parent) this._focusItem(parent);\n }\n break;\n }\n case 'Home': {\n event.preventDefault();\n if (visible[0]) this._focusItem(visible[0]);\n break;\n }\n case 'End': {\n event.preventDefault();\n const last = visible[visible.length - 1];\n if (last) this._focusItem(last);\n break;\n }\n case 'Enter':\n case ' ': {\n event.preventDefault();\n this._handleRowActivate(current);\n break;\n }\n case '*': {\n event.preventDefault();\n // Expand all siblings of the current item.\n const siblings = (\n current.parentElement ? (Array.from(current.parentElement.children) as TreeItem[]) : []\n ).filter((el) => el.tagName === tagName('tree-item').toUpperCase());\n for (const sib of siblings) {\n if (!sib.isLeaf()) sib.expanded = true;\n }\n break;\n }\n }\n };\n\n override render() {\n return html`\n <div\n class=\"tree\"\n part=\"base\"\n role=\"tree\"\n aria-multiselectable=${this.selection === 'multiple' ? 'true' : 'false'}\n @click=${this._onClick}\n @keydown=${this._onKeyDown}\n @focusin=${this._onFocusIn}\n >\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tree.js","names":[],"sources":["../../../src/html/elements/tree/tree.css?inline","../../../src/html/elements/tree/tree.ts"],"sourcesContent":[":host {\n --indent-size: 1rem;\n --indent-guide-width: 1px;\n --indent-guide-style: solid;\n --indent-guide-color: var(--l-color-border-interactive, light-dark(#d1d5db, #3a4048));\n --row-height: 1.75rem;\n --row-padding-inline: 0.25rem;\n --chevron-size: 1.125rem;\n --item-gap: 0.375rem;\n\n display: block;\n color: var(--l-color-text-primary, CanvasText);\n font-family: inherit;\n line-height: 1.5;\n}\n\n.tree {\n display: block;\n outline: none;\n}\n\n.tree:focus-visible {\n outline: 2px solid var(--l-focus-ring, Highlight);\n outline-offset: 2px;\n border-radius: 0.375rem;\n}\n","import { html, unsafeCSS, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { tagName } from '../../registry.js';\nimport type { TreeItem } from '../tree-item/tree-item.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './tree.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\nexport type TreeSelection = 'single' | 'multiple' | 'leaf' | 'none';\n\n/**\n * A hierarchical tree view composed of `<l-tree-item>` children.\n *\n * @slot - One or more `l-tree-item` elements.\n *\n * @csspart base - The root tree container.\n *\n * @cssproperty --indent-size - Horizontal indent per depth level. Default `1rem`.\n * @cssproperty --indent-guide-width - Thickness of the vertical guide line between a parent and its children. Default `1px`. Set to `0` to hide guides.\n * @cssproperty --indent-guide-style - Line style of the guide (`solid`, `dashed`, `dotted`, `double`…). Default `solid`.\n * @cssproperty --indent-guide-color - Color of the guide line.\n * @cssproperty --row-height - Minimum row height. Default `1.75rem`.\n * @cssproperty --row-padding-inline - Inner inline padding of the row; also drives the content slot left indent and the indent guide column. Default `0.25rem`.\n * @cssproperty --chevron-size - Size of the expand/collapse chevron box. Default `1.125rem`.\n * @cssproperty --item-gap - Horizontal gap between chevron, prefix, label and suffix on the row; also drives the content slot left indent. Default `0.375rem`.\n *\n * @event selection-change - Fired when the selected items change. Detail: `{ selection: TreeItem[] }`.\n *\n * @customElement l-tree\n */\nexport class Tree extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _mutationObserver?: MutationObserver;\n private _lastFocusedItem: TreeItem | null = null;\n\n /**\n * Selection behaviour:\n * - `single` (default): at most one item selected via `aria-selected`.\n * - `multiple`: any number of items selected. Checkboxes are rendered.\n * - `leaf`: only leaf items can be selected (single). Branches just toggle.\n * - `none`: purely navigable, no selection state.\n */\n @property({ reflect: true })\n accessor selection: TreeSelection = 'single';\n\n /**\n * When set with `selection=\"multiple\"`, parent and children selection are decoupled:\n * toggling a parent does NOT toggle its descendants and vice versa.\n * Without it, selection cascades both ways and branches may become indeterminate.\n */\n @property({ type: Boolean, reflect: true })\n accessor independent = false;\n\n override connectedCallback() {\n super.connectedCallback();\n this._mutationObserver = new MutationObserver(() => this._syncAll());\n this._mutationObserver.observe(this, { childList: true, subtree: true });\n this.addEventListener('l-tree-item-toggle', this._onItemToggle as EventListener);\n\n // Defer sync to let light DOM upgrade.\n queueMicrotask(() => this._syncAll());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._mutationObserver?.disconnect();\n this.removeEventListener('l-tree-item-toggle', this._onItemToggle as EventListener);\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('selection') || changed.has('independent')) {\n this._syncAll();\n }\n }\n\n // --- Public API ---\n\n /** Returns all items in document (flat) order, including nested ones. */\n getAllItems({ includeDisabled = true } = {}): TreeItem[] {\n const tag = tagName('tree-item');\n return Array.from(this.querySelectorAll<TreeItem>(tag)).filter(\n (item) => includeDisabled || !item.disabled,\n );\n }\n\n /** Returns currently selected items. */\n getSelection(): TreeItem[] {\n return this.getAllItems().filter((i) => i.selected);\n }\n\n /** Expands every item that has children. */\n expandAll() {\n for (const item of this.getAllItems()) {\n if (!item.isLeaf()) item.expanded = true;\n }\n }\n\n /** Collapses every item. */\n collapseAll() {\n for (const item of this.getAllItems()) {\n item.expanded = false;\n }\n }\n\n // --- Sync / ARIA / depth / checkbox visibility ---\n\n private _syncAll() {\n const showCheckbox = this.selection === 'multiple';\n const roots = this._rootItems();\n for (const root of roots) {\n this._syncSubtree(root, 0, showCheckbox);\n }\n this._updateBranchStates();\n // Ensure at least one item is tabbable.\n this._ensureTabStop();\n }\n\n private _syncSubtree(item: TreeItem, depth: number, showCheckbox: boolean) {\n item.depth = depth;\n item.showCheckbox = showCheckbox && this._canShowCheckboxOn(item);\n for (const child of item.getChildrenItems()) {\n this._syncSubtree(child, depth + 1, showCheckbox);\n }\n }\n\n private _canShowCheckboxOn(_item: TreeItem): boolean {\n if (this.selection !== 'multiple') return false;\n // In cascade mode, branches get a checkbox too so you can bulk-toggle children.\n // In leaf-only selection, hidden here because selection !== 'multiple'.\n return true;\n }\n\n private _rootItems(): TreeItem[] {\n const tag = tagName('tree-item').toUpperCase();\n return (Array.from(this.children) as TreeItem[]).filter((el) => el.tagName === tag);\n }\n\n private _ensureTabStop() {\n const items = this._visibleItems();\n if (items.length === 0) return;\n const hasTabStop = items.some((i) => i.tabIndex === 0);\n if (!hasTabStop) {\n for (const i of items) i.tabIndex = -1;\n items[0].tabIndex = 0;\n }\n }\n\n /** Items currently visible (parent chain all expanded). */\n private _visibleItems(): TreeItem[] {\n const out: TreeItem[] = [];\n const walk = (items: TreeItem[]) => {\n for (const i of items) {\n out.push(i);\n if (i.expanded) walk(i.getChildrenItems());\n }\n };\n walk(this._rootItems());\n return out;\n }\n\n // --- Selection handling ---\n\n private _onItemToggle = (event: CustomEvent<{ item: TreeItem; checked: boolean }>) => {\n const { item, checked } = event.detail;\n this._selectItem(item, checked);\n };\n\n private _handleRowActivate(item: TreeItem) {\n if (item.disabled) return;\n\n switch (this.selection) {\n case 'single':\n this._setSingleSelection(item);\n break;\n case 'leaf':\n if (item.isLeaf()) this._setSingleSelection(item);\n else item.toggle();\n break;\n case 'multiple':\n this._selectItem(item, !item.selected);\n break;\n case 'none':\n item.toggle();\n break;\n }\n }\n\n private _setSingleSelection(item: TreeItem) {\n for (const i of this.getAllItems()) {\n if (i !== item && i.selected) i.selected = false;\n }\n item.selected = true;\n this._emitSelectionChange();\n }\n\n private _selectItem(item: TreeItem, value: boolean) {\n if (item.disabled) return;\n item.selected = value;\n\n if (this.selection === 'multiple' && !this.independent) {\n // Cascade DOWN: toggling a branch toggles all descendants.\n this._setSubtreeSelection(item, value);\n }\n\n item.indeterminate = false;\n this._updateBranchStates();\n this._emitSelectionChange();\n }\n\n private _setSubtreeSelection(item: TreeItem, value: boolean) {\n for (const child of item.getChildrenItems()) {\n if (child.disabled) continue;\n child.selected = value;\n child.indeterminate = false;\n this._setSubtreeSelection(child, value);\n }\n }\n\n /** Propagate child state UP to parents (indeterminate / auto-checked). */\n private _updateBranchStates() {\n if (this.selection !== 'multiple' || this.independent) {\n // In independent or non-multiple modes, clear any indeterminate flags.\n for (const i of this.getAllItems()) i.indeterminate = false;\n return;\n }\n\n const recompute = (item: TreeItem): { all: boolean; any: boolean } => {\n const children = item.getChildrenItems({ includeDisabled: false });\n if (children.length === 0) {\n return { all: item.selected, any: item.selected };\n }\n\n let all = true;\n let any = false;\n for (const child of children) {\n const state = recompute(child);\n if (!state.all) all = false;\n if (state.any) any = true;\n }\n\n item.selected = all;\n item.indeterminate = !all && any;\n return { all: all && (item.getChildrenItems().length > 0 ? all : item.selected), any };\n };\n\n for (const root of this._rootItems()) recompute(root);\n }\n\n private _emitSelectionChange() {\n this.emit('selection-change', { detail: { selection: this.getSelection() } });\n }\n\n // --- Keyboard / focus ---\n\n private _onClick = (event: MouseEvent) => {\n const item = this._itemFromEvent(event);\n if (!item || item.disabled) return;\n\n const path = event.composedPath();\n const onCheckbox = path.some((n) => n instanceof HTMLInputElement && n.type === 'checkbox');\n if (onCheckbox) return; // handled via change event\n\n // Clicks on consumer-provided interactive elements (buttons, links, form\n // controls, menu items…) must not toggle the row — the consumer owns that\n // interaction. Works regardless of which slot the element was placed in.\n const INTERACTIVE_TAGS = new Set(['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA']);\n const INTERACTIVE_ROLES = new Set(['button', 'link', 'menuitem', 'menuitemcheckbox']);\n const onInteractive = path.some((n) => {\n if (!(n instanceof HTMLElement) || n === item) return false;\n if (n.getAttribute?.('part') === 'expand-button') return false;\n if (n instanceof HTMLInputElement && n.type === 'checkbox') return false;\n if (INTERACTIVE_TAGS.has(n.tagName)) return true;\n const role = n.getAttribute?.('role');\n return role !== null && INTERACTIVE_ROLES.has(role);\n });\n if (onInteractive) return;\n\n const onExpand = path.some(\n (n) => n instanceof HTMLElement && n.getAttribute?.('part') === 'expand-button',\n );\n\n this._focusItem(item);\n\n if (onExpand) {\n item.toggle();\n return;\n }\n\n // Row click (label area): mode-dependent behaviour.\n switch (this.selection) {\n case 'single':\n this._setSingleSelection(item);\n if (!item.isLeaf()) item.toggle();\n break;\n case 'leaf':\n if (item.isLeaf()) this._setSingleSelection(item);\n else item.toggle();\n break;\n case 'multiple':\n // The whole row acts like a <label> for the checkbox: clicking anywhere\n // on it toggles selection. Use the chevron to expand/collapse branches.\n this._selectItem(item, !item.selected);\n break;\n case 'none':\n item.toggle();\n break;\n }\n };\n\n private _itemFromEvent(event: Event): TreeItem | null {\n const tag = tagName('tree-item');\n const path = event.composedPath();\n for (const node of path) {\n if (node instanceof HTMLElement && node.matches?.(tag)) {\n return node as TreeItem;\n }\n }\n return null;\n }\n\n private _focusItem(item: TreeItem) {\n const visible = this._visibleItems();\n for (const i of visible) i.tabIndex = -1;\n item.tabIndex = 0;\n item.focus();\n this._lastFocusedItem = item;\n }\n\n private _onFocusIn = (event: FocusEvent) => {\n const target = event.target;\n if (target instanceof HTMLElement) {\n const item = target.closest<TreeItem>(tagName('tree-item'));\n if (item) this._lastFocusedItem = item;\n }\n };\n\n private _onKeyDown = (event: KeyboardEvent) => {\n const current = this._lastFocusedItem ?? this._visibleItems()[0];\n if (!current) return;\n\n const visible = this._visibleItems();\n const index = visible.indexOf(current);\n\n switch (event.key) {\n case 'ArrowDown': {\n event.preventDefault();\n const next = visible[Math.min(index + 1, visible.length - 1)];\n if (next) this._focusItem(next);\n break;\n }\n case 'ArrowUp': {\n event.preventDefault();\n const prev = visible[Math.max(index - 1, 0)];\n if (prev) this._focusItem(prev);\n break;\n }\n case 'ArrowRight': {\n event.preventDefault();\n if (!current.isLeaf() && !current.expanded) {\n current.expanded = true;\n } else if (current.expanded) {\n const first = current.getChildrenItems()[0];\n if (first) this._focusItem(first);\n }\n break;\n }\n case 'ArrowLeft': {\n event.preventDefault();\n if (current.expanded && !current.isLeaf()) {\n current.expanded = false;\n } else {\n const parent = current.parentElement?.closest(tagName('tree-item')) as TreeItem | null;\n if (parent) this._focusItem(parent);\n }\n break;\n }\n case 'Home': {\n event.preventDefault();\n if (visible[0]) this._focusItem(visible[0]);\n break;\n }\n case 'End': {\n event.preventDefault();\n const last = visible[visible.length - 1];\n if (last) this._focusItem(last);\n break;\n }\n case 'Enter':\n case ' ': {\n event.preventDefault();\n this._handleRowActivate(current);\n break;\n }\n case '*': {\n event.preventDefault();\n // Expand all siblings of the current item.\n const siblings = (\n current.parentElement ? (Array.from(current.parentElement.children) as TreeItem[]) : []\n ).filter((el) => el.tagName === tagName('tree-item').toUpperCase());\n for (const sib of siblings) {\n if (!sib.isLeaf()) sib.expanded = true;\n }\n break;\n }\n }\n };\n\n override render() {\n return html`\n <div\n class=\"tree\"\n part=\"base\"\n role=\"tree\"\n aria-multiselectable=${this.selection === 'multiple' ? 'true' : 'false'}\n @click=${this._onClick}\n @keydown=${this._onKeyDown}\n @focusin=${this._onFocusIn}\n >\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
|
|
@@ -25,6 +25,8 @@ import { LuxenElement } from '../../shared/luxen-element.js';
|
|
|
25
25
|
* @event expand - Fired when the item is expanded.
|
|
26
26
|
* @event collapse - Fired when the item is collapsed.
|
|
27
27
|
* @event lazy-load - Fired when a lazy item is expanded for the first time. Consumers should append children and set `lazy=false`.
|
|
28
|
+
*
|
|
29
|
+
* @customElement l-tree-item
|
|
28
30
|
*/
|
|
29
31
|
export declare class TreeItem extends LuxenElement {
|
|
30
32
|
static styles: import('lit').CSSResult[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-item.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tree-item/tree-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAO7D
|
|
1
|
+
{"version":3,"file":"tree-item.d.ts","sourceRoot":"","sources":["../../../src/html/elements/tree-item/tree-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAO7D;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,QAAS,SAAQ,YAAY;IACxC,OAAgB,MAAM,4BAAwB;IAE9C,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,cAAc,CAAC,CAAmB;IAE1C,oCAAoC;IAEpC,QAAQ,CAAC,QAAQ,UAAS;IAE1B,oCAAoC;IAEpC,QAAQ,CAAC,QAAQ,UAAS;IAE1B,yEAAyE;IAEzE,QAAQ,CAAC,aAAa,UAAS;IAE/B,oCAAoC;IAEpC,QAAQ,CAAC,QAAQ,UAAS;IAE1B,8EAA8E;IAE9E,QAAQ,CAAC,IAAI,UAAS;IAEtB,+DAA+D;IAE/D,QAAQ,CAAC,OAAO,UAAS;IAEzB,sDAAsD;IACtD,IAAI,YAAY,CAAC,KAAK,EAAE,OAAO,EAG9B;IACD,IAAI,YAAY,IAAI,OAAO,CAE1B;IACD,OAAO,CAAC,aAAa,CAAS;IAE9B,mEAAmE;IACnE,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAGtB;IACD,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,OAAO,CAAC,MAAM,CAAK;IAEnB,uDAAuD;IACvD,IAAI,WAAW,IAAI,OAAO,CAEzB;IACD,OAAO,CAAC,YAAY,CAAS;IAE7B,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,eAAsB,EAAE;;KAAK,GAAG,QAAQ,EAAE;IAO7D,4DAA4D;IAC5D,MAAM,IAAI,OAAO;IAIjB,2CAA2C;IAC3C,YAAY,IAAI,MAAM;IAUb,iBAAiB;IAQjB,oBAAoB;IAKpB,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;IAe9C,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,aAAa;IAmBrB,+EAA+E;IAC/E,MAAM;IASN,OAAO,CAAC,iBAAiB,CAUvB;IAEO,MAAM;CAwFhB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{tagName as e}from"../../registry.js";import{
|
|
1
|
+
import{tagName as e}from"../../registry.js";import{i as t}from"../../chunks/lit.js";import{a as n}from"../../chunks/lit-html.js";import{LuxenElement as r}from"../../shared/luxen-element.js";import{i,t as a}from"../../chunks/decorate.js";import o from"../../shared/styles/host.styles.js";var s=t(`:host{color:var(--l-color-text-primary,CanvasText);font-size:.875rem;line-height:1.5;display:block}:host([disabled]){opacity:.4}:host([disabled]) .item{cursor:not-allowed}.item{align-items:center;gap:var(--item-gap);min-block-size:var(--row-height);padding-inline:var(--row-padding-inline);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:.375rem;padding-inline-start:calc(var(--indent-size) * var(--_depth,0) + var(--row-padding-inline));transition:background-color .12s,color .12s;display:flex;position:relative}.item:focus-visible,:host(:focus-visible) .item{outline:2px solid var(--l-focus-ring,Highlight);outline-offset:1px}@media (hover:hover){:host(:not([disabled])) .item:hover{background-color:var(--l-color-bg-state-hover)}}:host([selected]:not([disabled])) .item{background-color:var(--l-color-bg-state-selected)}.expand{inline-size:var(--chevron-size);block-size:var(--chevron-size);color:var(--l-color-text-secondary,CanvasText);cursor:pointer;border-radius:3px;flex:none;place-items:center;display:grid}:host(:not(:state(has-children)):not([lazy])) .expand>svg{display:none}.expand svg{width:100%;height:100%;display:block}.checkbox{accent-color:var(--l-color-bg-fill-brand,Highlight);cursor:pointer;flex:none;block-size:1rem;inline-size:1rem;margin:0}:host(:not(:state(checkbox))) .checkbox{display:none}.label{text-overflow:ellipsis;white-space:nowrap;flex:1;align-items:center;gap:.375rem;min-inline-size:0;display:flex;overflow:hidden}.label ::slotted(*){min-inline-size:0}.branch{position:relative}.content{padding-inline-start:calc(var(--indent-size) * var(--_depth,0) + var(--row-padding-inline) + var(--chevron-size) + var(--item-gap));padding-inline-end:var(--row-padding-inline);display:block}:host(:state(has-children):not([expanded])) .content,.children{display:none}:host([expanded]) .children{display:block}.branch:before{content:"";border-inline-start:var(--indent-guide-width) var(--indent-guide-style) var(--indent-guide-color);pointer-events:none;inline-size:0;position:absolute;inset-block:0;inset-inline-start:calc(var(--indent-size) * var(--_depth,0) + var(--row-padding-inline) + (var(--chevron-size) / 2) - (var(--indent-guide-width) / 2))}:host(:not([expanded])) .branch:before,:host(:not(:state(has-children))) .branch:before{display:none}.spinner{border:2px solid var(--l-color-border,currentColor);border-block-start-color:#0000;border-radius:50%;block-size:.875rem;inline-size:.875rem;animation:.7s linear infinite spin}@media (prefers-reduced-motion:reduce){.spinner{animation:none}}@keyframes spin{to{transform:rotate(360deg)}}`),c=class extends r{constructor(...e){super(...e),this._internals=this.attachInternals(),this.#e=!1,this.#t=!1,this.#n=!1,this.#r=!1,this.#i=!1,this.#a=!1,this._showCheckbox=!1,this._depth=0,this._hasChildren=!1,this._onCheckboxChange=e=>{e.stopPropagation();let t=e.target;this.dispatchEvent(new CustomEvent(`l-tree-item-toggle`,{bubbles:!0,composed:!0,detail:{item:this,checked:t.checked}}))}}static{this.styles=[o,s]}#e;get expanded(){return this.#e}set expanded(e){this.#e=e}#t;get selected(){return this.#t}set selected(e){this.#t=e}#n;get indeterminate(){return this.#n}set indeterminate(e){this.#n=e}#r;get disabled(){return this.#r}set disabled(e){this.#r=e}#i;get lazy(){return this.#i}set lazy(e){this.#i=e}#a;get loading(){return this.#a}set loading(e){this.#a=e}set showCheckbox(e){this._showCheckbox=e,this._setState(`checkbox`,e)}get showCheckbox(){return this._showCheckbox}set depth(e){this._depth=e,this.style.setProperty(`--_depth`,String(e))}get depth(){return this._depth}get hasChildren(){return this._hasChildren}getChildrenItems({includeDisabled:t=!0}={}){let n=e(`tree-item`).toUpperCase();return Array.from(this.children).filter(e=>e.tagName===n&&(t||!e.disabled))}isLeaf(){return!this.lazy&&this.getChildrenItems().length===0}getTextLabel(){let e=this.shadowRoot?.querySelector(`slot:not([name])`);return e?e.assignedNodes({flatten:!0}).map(e=>e.textContent??``).join(``).trim():(this.textContent??``).trim()}connectedCallback(){super.connectedCallback(),this._internals.role=`treeitem`,this._childObserver=new MutationObserver(()=>this._syncChildren()),this._childObserver.observe(this,{childList:!0}),this._syncChildren()}disconnectedCallback(){super.disconnectedCallback(),this._childObserver?.disconnect()}updated(e){e.has(`expanded`)&&(this._internals.ariaExpanded=this.isLeaf()?null:String(this.expanded),this.emit(this.expanded?`expand`:`collapse`)),e.has(`selected`)&&(this._internals.ariaSelected=String(this.selected)),e.has(`disabled`)&&(this._internals.ariaDisabled=this.disabled?`true`:null)}_setState(e,t){this._internals.states&&(t?this._internals.states.add(e):this._internals.states.delete(e))}_syncChildren(){let t=e(`tree-item`).toUpperCase(),n=0;for(let e of Array.from(this.children))e.tagName===t&&(n++,e.slot!==`children`&&(e.slot=`children`));this._hasChildren=n>0,this._setState(`has-children`,this._hasChildren),!this._hasChildren&&!this.lazy&&this.expanded&&(this.expanded=!1),this._internals.ariaExpanded=this.isLeaf()?null:String(this.expanded)}toggle(){if(this.isLeaf()&&!this.lazy)return;let e=!this.expanded;e&&this.lazy&&this.emit(`lazy-load`),this.expanded=e}render(){return n`
|
|
2
2
|
<div
|
|
3
3
|
class="item"
|
|
4
4
|
part="base"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-item.js","names":[],"sources":["../../../src/html/elements/tree-item/tree-item.css?inline","../../../src/html/elements/tree-item/tree-item.ts"],"sourcesContent":[":host {\n display: block;\n color: var(--l-color-text-primary, CanvasText);\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n:host([disabled]) {\n opacity: 0.4;\n}\n\n:host([disabled]) .item {\n cursor: not-allowed;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--item-gap);\n min-block-size: var(--row-height);\n padding-inline: var(--row-padding-inline);\n padding-inline-start: calc(var(--indent-size) * var(--_depth, 0) + var(--row-padding-inline));\n border-radius: 0.375rem;\n cursor: pointer;\n user-select: none;\n transition:\n background-color 120ms ease,\n color 120ms ease;\n position: relative;\n}\n\n.item:focus-visible,\n:host(:focus-visible) .item {\n outline: 2px solid var(--l-focus-ring, Highlight);\n outline-offset: 1px;\n}\n\n@media (hover: hover) {\n :host(:not([disabled])) .item:hover {\n background-color: var(--l-color-bg-state-hover);\n }\n}\n\n:host([selected]:not([disabled])) .item {\n background-color: var(--l-color-bg-state-selected);\n}\n\n.expand {\n inline-size: var(--chevron-size);\n block-size: var(--chevron-size);\n display: grid;\n place-items: center;\n flex: none;\n color: var(--l-color-text-secondary, CanvasText);\n border-radius: 3px;\n cursor: pointer;\n}\n\n/* Hide the DEFAULT fallback chevron SVG on a leaf — slotted content\n (user-provided icon, avatar, etc.) remains visible. */\n:host(:not(:state(has-children)):not([lazy])) .expand > svg {\n display: none;\n}\n\n.expand svg {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.checkbox {\n margin: 0;\n flex: none;\n accent-color: var(--l-color-bg-fill-brand, Highlight);\n cursor: pointer;\n inline-size: 1rem;\n block-size: 1rem;\n}\n\n/* Checkbox is only rendered when the parent tree enables multi-selection */\n:host(:not(:state(checkbox))) .checkbox {\n display: none;\n}\n\n.label {\n flex: 1;\n min-inline-size: 0;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.label ::slotted(*) {\n min-inline-size: 0;\n}\n\n/* Wrapper around the content slot + children — anchor for the indent guide. */\n.branch {\n position: relative;\n}\n\n/* Content slot — block area between the row and the children.\n Aligned under the label text: same left offset as the row's label\n (depth indent + row padding + chevron + gap). Visible for leaves (no\n children) and for expanded branches; hidden when a branch is collapsed\n (mirrors the children visibility). */\n.content {\n display: block;\n padding-inline-start: calc(\n var(--indent-size) * var(--_depth, 0) + var(--row-padding-inline) + var(--chevron-size) +\n var(--item-gap)\n );\n padding-inline-end: var(--row-padding-inline);\n}\n\n:host(:state(has-children):not([expanded])) .content {\n display: none;\n}\n\n.children {\n display: none;\n}\n\n:host([expanded]) .children {\n display: block;\n}\n\n/* Vertical indent guide — spans the content + children block, starting\n right below the row so it never overlaps the chevron/avatar.\n The guide's visual centre sits exactly on the parent chevron's centre. */\n.branch::before {\n content: '';\n position: absolute;\n inset-block: 0;\n inset-inline-start: calc(\n var(--indent-size) * var(--_depth, 0) + var(--row-padding-inline) + (var(--chevron-size) / 2) -\n (var(--indent-guide-width) / 2)\n );\n inline-size: 0;\n border-inline-start: var(--indent-guide-width) var(--indent-guide-style) var(--indent-guide-color);\n pointer-events: none;\n}\n\n/* Only render the guide for open branches that have children. */\n:host(:not([expanded])) .branch::before,\n:host(:not(:state(has-children))) .branch::before {\n display: none;\n}\n\n.spinner {\n inline-size: 0.875rem;\n block-size: 0.875rem;\n border-radius: 50%;\n border: 2px solid var(--l-color-border, currentColor);\n border-block-start-color: transparent;\n animation: spin 700ms linear infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .spinner {\n animation: none;\n }\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n","import { html, unsafeCSS, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { tagName } from '../../registry.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './tree-item.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * A node inside `<l-tree>`. Nested `<l-tree-item>` children become sub-nodes.\n *\n * @slot - Label content (kept to a single row).\n * @slot prefix - Leading content before the label (e.g. icon).\n * @slot suffix - Trailing content.\n * @slot expand-icon - Icon shown when the item is collapsed.\n * @slot collapse-icon - Icon shown when the item is expanded.\n * @slot content - Block content that belongs to the item but not to its header row (e.g. comment body, action bar). Hidden when a branch is collapsed.\n *\n * @csspart base - The item row.\n * @csspart expand-button - The chevron toggle area.\n * @csspart checkbox - The native checkbox input.\n * @csspart label - The label container.\n * @csspart branch - Wrapper around the content and children slots; carries the indent guide.\n * @csspart content - The content slot wrapper (block area between the row and the children).\n * @csspart children - The nested items container.\n *\n * @cssproperty [--_depth] - Internal depth index driving indentation. Set by `<l-tree>`.\n *\n * Layout tokens (`--chevron-size`, `--row-height`, `--row-padding-inline`, `--item-gap`) live on `<l-tree>` and cascade down — see its CSS custom properties.\n *\n * @event expand - Fired when the item is expanded.\n * @event collapse - Fired when the item is collapsed.\n * @event lazy-load - Fired when a lazy item is expanded for the first time. Consumers should append children and set `lazy=false`.\n */\nexport class TreeItem extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _internals = this.attachInternals();\n private _childObserver?: MutationObserver;\n\n /** Whether the item is expanded. */\n @property({ type: Boolean, reflect: true })\n accessor expanded = false;\n\n /** Whether the item is selected. */\n @property({ type: Boolean, reflect: true })\n accessor selected = false;\n\n /** Whether the checkbox is indeterminate (some descendants selected). */\n @property({ type: Boolean, reflect: true })\n accessor indeterminate = false;\n\n /** Whether the item is disabled. */\n @property({ type: Boolean, reflect: true })\n accessor disabled = false;\n\n /** Marks this item as having children that will be loaded on first expand. */\n @property({ type: Boolean, reflect: true })\n accessor lazy = false;\n\n /** Whether the item is currently loading (shows a spinner). */\n @property({ type: Boolean, reflect: true })\n accessor loading = false;\n\n /** Set by `<l-tree>`: whether a checkbox is shown. */\n set showCheckbox(value: boolean) {\n this._showCheckbox = value;\n this._setState('checkbox', value);\n }\n get showCheckbox(): boolean {\n return this._showCheckbox;\n }\n private _showCheckbox = false;\n\n /** Set by `<l-tree>`: depth of the item in the tree (0 = root). */\n set depth(value: number) {\n this._depth = value;\n this.style.setProperty('--_depth', String(value));\n }\n get depth(): number {\n return this._depth;\n }\n private _depth = 0;\n\n /** Whether this item has nested tree-item children. */\n get hasChildren(): boolean {\n return this._hasChildren;\n }\n private _hasChildren = false;\n\n /** Returns the child `<l-tree-item>` elements directly under this one. */\n getChildrenItems({ includeDisabled = true } = {}): TreeItem[] {\n const childTag = tagName('tree-item').toUpperCase();\n return (Array.from(this.children) as TreeItem[]).filter(\n (el) => el.tagName === childTag && (includeDisabled || !el.disabled),\n );\n }\n\n /** Returns true if this item has no expandable children. */\n isLeaf(): boolean {\n return !this.lazy && this.getChildrenItems().length === 0;\n }\n\n /** Returns the text label of this item. */\n getTextLabel(): string {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return (this.textContent ?? '').trim();\n return slot\n .assignedNodes({ flatten: true })\n .map((n) => n.textContent ?? '')\n .join('')\n .trim();\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this._internals.role = 'treeitem';\n this._childObserver = new MutationObserver(() => this._syncChildren());\n this._childObserver.observe(this, { childList: true });\n this._syncChildren();\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._childObserver?.disconnect();\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('expanded')) {\n this._internals.ariaExpanded = this.isLeaf() ? null : String(this.expanded);\n this.emit(this.expanded ? 'expand' : 'collapse');\n }\n\n if (changed.has('selected')) {\n this._internals.ariaSelected = String(this.selected);\n }\n\n if (changed.has('disabled')) {\n this._internals.ariaDisabled = this.disabled ? 'true' : null;\n }\n }\n\n private _setState(name: string, on: boolean) {\n if (!this._internals.states) return;\n if (on) this._internals.states.add(name);\n else this._internals.states.delete(name);\n }\n\n private _syncChildren() {\n // Auto-slot nested tree-items into the `children` slot so they render in the group container,\n // while label text/elements remain in the default slot.\n const childTag = tagName('tree-item').toUpperCase();\n let count = 0;\n for (const child of Array.from(this.children) as HTMLElement[]) {\n if (child.tagName === childTag) {\n count++;\n if (child.slot !== 'children') child.slot = 'children';\n }\n }\n this._hasChildren = count > 0;\n this._setState('has-children', this._hasChildren);\n if (!this._hasChildren && !this.lazy && this.expanded) {\n this.expanded = false;\n }\n this._internals.ariaExpanded = this.isLeaf() ? null : String(this.expanded);\n }\n\n /** Toggle expand state. Emits `lazy-load` the first time a lazy item opens. */\n toggle() {\n if (this.isLeaf() && !this.lazy) return;\n const next = !this.expanded;\n if (next && this.lazy) {\n this.emit('lazy-load');\n }\n this.expanded = next;\n }\n\n private _onCheckboxChange = (event: Event) => {\n event.stopPropagation();\n const input = event.target as HTMLInputElement;\n this.dispatchEvent(\n new CustomEvent('l-tree-item-toggle', {\n bubbles: true,\n composed: true,\n detail: { item: this, checked: input.checked },\n }),\n );\n };\n\n override render() {\n return html`\n <div\n class=\"item\"\n part=\"base\"\n >\n <span\n class=\"expand\"\n part=\"expand-button\"\n aria-hidden=\"true\"\n >\n ${this.loading\n ? html`<span\n class=\"spinner\"\n role=\"status\"\n ></span>`\n : this.expanded || this.isLeaf()\n ? html`<slot name=\"collapse-icon\">\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M3.5 6l4.5 5 4.5-5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>`\n : html`<slot name=\"expand-icon\">\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M6 3.5l5 4.5-5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>`}\n </span>\n\n <input\n class=\"checkbox\"\n part=\"checkbox\"\n type=\"checkbox\"\n tabindex=\"-1\"\n .checked=${this.selected}\n .indeterminate=${this.indeterminate}\n ?disabled=${this.disabled}\n @click=${(e: Event) => e.stopPropagation()}\n @change=${this._onCheckboxChange}\n />\n\n <slot name=\"prefix\"></slot>\n <span\n class=\"label\"\n part=\"label\"\n ><slot></slot\n ></span>\n <slot name=\"suffix\"></slot>\n </div>\n\n <div\n class=\"branch\"\n part=\"branch\"\n >\n <div\n class=\"content\"\n part=\"content\"\n >\n <slot name=\"content\"></slot>\n </div>\n <div\n class=\"children\"\n part=\"children\"\n role=\"group\"\n >\n <slot name=\"children\"></slot>\n </div>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tree-item.js","names":[],"sources":["../../../src/html/elements/tree-item/tree-item.css?inline","../../../src/html/elements/tree-item/tree-item.ts"],"sourcesContent":[":host {\n display: block;\n color: var(--l-color-text-primary, CanvasText);\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n:host([disabled]) {\n opacity: 0.4;\n}\n\n:host([disabled]) .item {\n cursor: not-allowed;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--item-gap);\n min-block-size: var(--row-height);\n padding-inline: var(--row-padding-inline);\n padding-inline-start: calc(var(--indent-size) * var(--_depth, 0) + var(--row-padding-inline));\n border-radius: 0.375rem;\n cursor: pointer;\n user-select: none;\n transition:\n background-color 120ms ease,\n color 120ms ease;\n position: relative;\n}\n\n.item:focus-visible,\n:host(:focus-visible) .item {\n outline: 2px solid var(--l-focus-ring, Highlight);\n outline-offset: 1px;\n}\n\n@media (hover: hover) {\n :host(:not([disabled])) .item:hover {\n background-color: var(--l-color-bg-state-hover);\n }\n}\n\n:host([selected]:not([disabled])) .item {\n background-color: var(--l-color-bg-state-selected);\n}\n\n.expand {\n inline-size: var(--chevron-size);\n block-size: var(--chevron-size);\n display: grid;\n place-items: center;\n flex: none;\n color: var(--l-color-text-secondary, CanvasText);\n border-radius: 3px;\n cursor: pointer;\n}\n\n/* Hide the DEFAULT fallback chevron SVG on a leaf — slotted content\n (user-provided icon, avatar, etc.) remains visible. */\n:host(:not(:state(has-children)):not([lazy])) .expand > svg {\n display: none;\n}\n\n.expand svg {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.checkbox {\n margin: 0;\n flex: none;\n accent-color: var(--l-color-bg-fill-brand, Highlight);\n cursor: pointer;\n inline-size: 1rem;\n block-size: 1rem;\n}\n\n/* Checkbox is only rendered when the parent tree enables multi-selection */\n:host(:not(:state(checkbox))) .checkbox {\n display: none;\n}\n\n.label {\n flex: 1;\n min-inline-size: 0;\n display: flex;\n align-items: center;\n gap: 0.375rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.label ::slotted(*) {\n min-inline-size: 0;\n}\n\n/* Wrapper around the content slot + children — anchor for the indent guide. */\n.branch {\n position: relative;\n}\n\n/* Content slot — block area between the row and the children.\n Aligned under the label text: same left offset as the row's label\n (depth indent + row padding + chevron + gap). Visible for leaves (no\n children) and for expanded branches; hidden when a branch is collapsed\n (mirrors the children visibility). */\n.content {\n display: block;\n padding-inline-start: calc(\n var(--indent-size) * var(--_depth, 0) + var(--row-padding-inline) + var(--chevron-size) +\n var(--item-gap)\n );\n padding-inline-end: var(--row-padding-inline);\n}\n\n:host(:state(has-children):not([expanded])) .content {\n display: none;\n}\n\n.children {\n display: none;\n}\n\n:host([expanded]) .children {\n display: block;\n}\n\n/* Vertical indent guide — spans the content + children block, starting\n right below the row so it never overlaps the chevron/avatar.\n The guide's visual centre sits exactly on the parent chevron's centre. */\n.branch::before {\n content: '';\n position: absolute;\n inset-block: 0;\n inset-inline-start: calc(\n var(--indent-size) * var(--_depth, 0) + var(--row-padding-inline) + (var(--chevron-size) / 2) -\n (var(--indent-guide-width) / 2)\n );\n inline-size: 0;\n border-inline-start: var(--indent-guide-width) var(--indent-guide-style) var(--indent-guide-color);\n pointer-events: none;\n}\n\n/* Only render the guide for open branches that have children. */\n:host(:not([expanded])) .branch::before,\n:host(:not(:state(has-children))) .branch::before {\n display: none;\n}\n\n.spinner {\n inline-size: 0.875rem;\n block-size: 0.875rem;\n border-radius: 50%;\n border: 2px solid var(--l-color-border, currentColor);\n border-block-start-color: transparent;\n animation: spin 700ms linear infinite;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .spinner {\n animation: none;\n }\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n","import { html, unsafeCSS, type PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { tagName } from '../../registry.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './tree-item.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * A node inside `<l-tree>`. Nested `<l-tree-item>` children become sub-nodes.\n *\n * @slot - Label content (kept to a single row).\n * @slot prefix - Leading content before the label (e.g. icon).\n * @slot suffix - Trailing content.\n * @slot expand-icon - Icon shown when the item is collapsed.\n * @slot collapse-icon - Icon shown when the item is expanded.\n * @slot content - Block content that belongs to the item but not to its header row (e.g. comment body, action bar). Hidden when a branch is collapsed.\n *\n * @csspart base - The item row.\n * @csspart expand-button - The chevron toggle area.\n * @csspart checkbox - The native checkbox input.\n * @csspart label - The label container.\n * @csspart branch - Wrapper around the content and children slots; carries the indent guide.\n * @csspart content - The content slot wrapper (block area between the row and the children).\n * @csspart children - The nested items container.\n *\n * @cssproperty [--_depth] - Internal depth index driving indentation. Set by `<l-tree>`.\n *\n * Layout tokens (`--chevron-size`, `--row-height`, `--row-padding-inline`, `--item-gap`) live on `<l-tree>` and cascade down — see its CSS custom properties.\n *\n * @event expand - Fired when the item is expanded.\n * @event collapse - Fired when the item is collapsed.\n * @event lazy-load - Fired when a lazy item is expanded for the first time. Consumers should append children and set `lazy=false`.\n *\n * @customElement l-tree-item\n */\nexport class TreeItem extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _internals = this.attachInternals();\n private _childObserver?: MutationObserver;\n\n /** Whether the item is expanded. */\n @property({ type: Boolean, reflect: true })\n accessor expanded = false;\n\n /** Whether the item is selected. */\n @property({ type: Boolean, reflect: true })\n accessor selected = false;\n\n /** Whether the checkbox is indeterminate (some descendants selected). */\n @property({ type: Boolean, reflect: true })\n accessor indeterminate = false;\n\n /** Whether the item is disabled. */\n @property({ type: Boolean, reflect: true })\n accessor disabled = false;\n\n /** Marks this item as having children that will be loaded on first expand. */\n @property({ type: Boolean, reflect: true })\n accessor lazy = false;\n\n /** Whether the item is currently loading (shows a spinner). */\n @property({ type: Boolean, reflect: true })\n accessor loading = false;\n\n /** Set by `<l-tree>`: whether a checkbox is shown. */\n set showCheckbox(value: boolean) {\n this._showCheckbox = value;\n this._setState('checkbox', value);\n }\n get showCheckbox(): boolean {\n return this._showCheckbox;\n }\n private _showCheckbox = false;\n\n /** Set by `<l-tree>`: depth of the item in the tree (0 = root). */\n set depth(value: number) {\n this._depth = value;\n this.style.setProperty('--_depth', String(value));\n }\n get depth(): number {\n return this._depth;\n }\n private _depth = 0;\n\n /** Whether this item has nested tree-item children. */\n get hasChildren(): boolean {\n return this._hasChildren;\n }\n private _hasChildren = false;\n\n /** Returns the child `<l-tree-item>` elements directly under this one. */\n getChildrenItems({ includeDisabled = true } = {}): TreeItem[] {\n const childTag = tagName('tree-item').toUpperCase();\n return (Array.from(this.children) as TreeItem[]).filter(\n (el) => el.tagName === childTag && (includeDisabled || !el.disabled),\n );\n }\n\n /** Returns true if this item has no expandable children. */\n isLeaf(): boolean {\n return !this.lazy && this.getChildrenItems().length === 0;\n }\n\n /** Returns the text label of this item. */\n getTextLabel(): string {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return (this.textContent ?? '').trim();\n return slot\n .assignedNodes({ flatten: true })\n .map((n) => n.textContent ?? '')\n .join('')\n .trim();\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this._internals.role = 'treeitem';\n this._childObserver = new MutationObserver(() => this._syncChildren());\n this._childObserver.observe(this, { childList: true });\n this._syncChildren();\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._childObserver?.disconnect();\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('expanded')) {\n this._internals.ariaExpanded = this.isLeaf() ? null : String(this.expanded);\n this.emit(this.expanded ? 'expand' : 'collapse');\n }\n\n if (changed.has('selected')) {\n this._internals.ariaSelected = String(this.selected);\n }\n\n if (changed.has('disabled')) {\n this._internals.ariaDisabled = this.disabled ? 'true' : null;\n }\n }\n\n private _setState(name: string, on: boolean) {\n if (!this._internals.states) return;\n if (on) this._internals.states.add(name);\n else this._internals.states.delete(name);\n }\n\n private _syncChildren() {\n // Auto-slot nested tree-items into the `children` slot so they render in the group container,\n // while label text/elements remain in the default slot.\n const childTag = tagName('tree-item').toUpperCase();\n let count = 0;\n for (const child of Array.from(this.children) as HTMLElement[]) {\n if (child.tagName === childTag) {\n count++;\n if (child.slot !== 'children') child.slot = 'children';\n }\n }\n this._hasChildren = count > 0;\n this._setState('has-children', this._hasChildren);\n if (!this._hasChildren && !this.lazy && this.expanded) {\n this.expanded = false;\n }\n this._internals.ariaExpanded = this.isLeaf() ? null : String(this.expanded);\n }\n\n /** Toggle expand state. Emits `lazy-load` the first time a lazy item opens. */\n toggle() {\n if (this.isLeaf() && !this.lazy) return;\n const next = !this.expanded;\n if (next && this.lazy) {\n this.emit('lazy-load');\n }\n this.expanded = next;\n }\n\n private _onCheckboxChange = (event: Event) => {\n event.stopPropagation();\n const input = event.target as HTMLInputElement;\n this.dispatchEvent(\n new CustomEvent('l-tree-item-toggle', {\n bubbles: true,\n composed: true,\n detail: { item: this, checked: input.checked },\n }),\n );\n };\n\n override render() {\n return html`\n <div\n class=\"item\"\n part=\"base\"\n >\n <span\n class=\"expand\"\n part=\"expand-button\"\n aria-hidden=\"true\"\n >\n ${this.loading\n ? html`<span\n class=\"spinner\"\n role=\"status\"\n ></span>`\n : this.expanded || this.isLeaf()\n ? html`<slot name=\"collapse-icon\">\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M3.5 6l4.5 5 4.5-5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>`\n : html`<slot name=\"expand-icon\">\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M6 3.5l5 4.5-5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>`}\n </span>\n\n <input\n class=\"checkbox\"\n part=\"checkbox\"\n type=\"checkbox\"\n tabindex=\"-1\"\n .checked=${this.selected}\n .indeterminate=${this.indeterminate}\n ?disabled=${this.disabled}\n @click=${(e: Event) => e.stopPropagation()}\n @change=${this._onCheckboxChange}\n />\n\n <slot name=\"prefix\"></slot>\n <span\n class=\"label\"\n part=\"label\"\n ><slot></slot\n ></span>\n <slot name=\"suffix\"></slot>\n </div>\n\n <div\n class=\"branch\"\n part=\"branch\"\n >\n <div\n class=\"content\"\n part=\"content\"\n >\n <slot name=\"content\"></slot>\n </div>\n <div\n class=\"children\"\n part=\"children\"\n role=\"group\"\n >\n <slot name=\"children\"></slot>\n </div>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
|
package/cdn/registry.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Every component base name the library ships. */
|
|
2
|
-
export type ElementBaseName = 'avatar' | 'badge' | 'carousel' | 'carousel-item' | 'dialog' | 'divider' | 'drawer' | 'dropdown' | 'dropdown-item' | 'icon' | 'input-otp' | 'input-stepper' | 'popover' | 'skeleton' | 'spinner' | 'rating' | 'sticky-bar' | 'stories' | 'story' | 'stories-viewer' | 'tabs' | 'toast' | 'toast-item' | 'tooltip' | 'tree' | 'tree-item';
|
|
2
|
+
export type ElementBaseName = 'avatar' | 'badge' | 'carousel' | 'carousel-item' | 'dialog' | 'divider' | 'drawer' | 'dropdown' | 'dropdown-item' | 'icon' | 'input-otp' | 'input-stepper' | 'popover' | 'prose-editor' | 'skeleton' | 'spinner' | 'rating' | 'sticky-bar' | 'stories' | 'story' | 'stories-viewer' | 'tabs' | 'toast' | 'toast-item' | 'tooltip' | 'tree' | 'tree-item';
|
|
3
3
|
/** Set the global prefix. Must be called before defining elements. */
|
|
4
4
|
export declare function setPrefix(prefix: {
|
|
5
5
|
element: string;
|
package/cdn/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/html/registry.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,OAAO,GACP,UAAU,GACV,eAAe,GACf,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,eAAe,GACf,MAAM,GACN,WAAW,GACX,eAAe,GACf,SAAS,GACT,UAAU,GACV,SAAS,GACT,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,OAAO,GACP,gBAAgB,GAChB,MAAM,GACN,OAAO,GACP,YAAY,GACZ,SAAS,GACT,MAAM,GACN,WAAW,CAAC;AAMhB,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGxE;AAED,gCAAgC;AAChC,wBAAgB,SAAS,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAE5D;AAED,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAEzD;AAED,sEAAsE;AACtE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExC;AAID,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAE/D;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAE9D"}
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/html/registry.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,OAAO,GACP,UAAU,GACV,eAAe,GACf,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,UAAU,GACV,eAAe,GACf,MAAM,GACN,WAAW,GACX,eAAe,GACf,SAAS,GACT,cAAc,GACd,UAAU,GACV,SAAS,GACT,QAAQ,GACR,YAAY,GACZ,SAAS,GACT,OAAO,GACP,gBAAgB,GAChB,MAAM,GACN,OAAO,GACP,YAAY,GACZ,SAAS,GACT,MAAM,GACN,WAAW,CAAC;AAMhB,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAGxE;AAED,gCAAgC;AAChC,wBAAgB,SAAS,IAAI;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAE5D;AAED,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAEzD;AAED,sEAAsE;AACtE,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExC;AAID,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAE/D;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAE9D"}
|
package/cdn/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","names":[],"sources":["../src/html/registry.ts"],"sourcesContent":["/** Every component base name the library ships. */\nexport type ElementBaseName =\n | 'avatar'\n | 'badge'\n | 'carousel'\n | 'carousel-item'\n | 'dialog'\n | 'divider'\n | 'drawer'\n | 'dropdown'\n | 'dropdown-item'\n | 'icon'\n | 'input-otp'\n | 'input-stepper'\n | 'popover'\n | 'skeleton'\n | 'spinner'\n | 'rating'\n | 'sticky-bar'\n | 'stories'\n | 'story'\n | 'stories-viewer'\n | 'tabs'\n | 'toast'\n | 'toast-item'\n | 'tooltip'\n | 'tree'\n | 'tree-item';\n\nlet _elementPrefix = 'l';\nlet _cssPrefix = 'l';\nconst _registered = new Set<ElementBaseName>();\n\n/** Set the global prefix. Must be called before defining elements. */\nexport function setPrefix(prefix: { element: string; css: string }): void {\n _elementPrefix = prefix.element;\n _cssPrefix = prefix.css;\n}\n\n/** Get the current prefixes. */\nexport function getPrefix(): { element: string; css: string } {\n return { element: _elementPrefix, css: _cssPrefix };\n}\n\n/** Derive the full tag name from element prefix + base name. */\nexport function tagName(baseName: ElementBaseName): string {\n return `${_elementPrefix}-${baseName}`;\n}\n\n/** Prefix a CSS class name. `cls('toast-icon')` → `'l-toast-icon'` */\nexport function cls(name: string): string {\n return `${_cssPrefix}-${name}`;\n}\n\n/** Generate a globally unique prefixed ID. `uniqueId('toast')` → `'l:toast:1'` */\nlet _uid = 0;\nexport function uniqueId(base: string): string {\n return `${_cssPrefix}:${base}:${++_uid}`;\n}\n\n/** Check if a base name is already registered. */\nexport function isRegistered(baseName: ElementBaseName): boolean {\n return _registered.has(baseName);\n}\n\n/** Mark a base name as registered. Called internally by define(). */\nexport function markRegistered(baseName: ElementBaseName): void {\n _registered.add(baseName);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.js","names":[],"sources":["../src/html/registry.ts"],"sourcesContent":["/** Every component base name the library ships. */\nexport type ElementBaseName =\n | 'avatar'\n | 'badge'\n | 'carousel'\n | 'carousel-item'\n | 'dialog'\n | 'divider'\n | 'drawer'\n | 'dropdown'\n | 'dropdown-item'\n | 'icon'\n | 'input-otp'\n | 'input-stepper'\n | 'popover'\n | 'prose-editor'\n | 'skeleton'\n | 'spinner'\n | 'rating'\n | 'sticky-bar'\n | 'stories'\n | 'story'\n | 'stories-viewer'\n | 'tabs'\n | 'toast'\n | 'toast-item'\n | 'tooltip'\n | 'tree'\n | 'tree-item';\n\nlet _elementPrefix = 'l';\nlet _cssPrefix = 'l';\nconst _registered = new Set<ElementBaseName>();\n\n/** Set the global prefix. Must be called before defining elements. */\nexport function setPrefix(prefix: { element: string; css: string }): void {\n _elementPrefix = prefix.element;\n _cssPrefix = prefix.css;\n}\n\n/** Get the current prefixes. */\nexport function getPrefix(): { element: string; css: string } {\n return { element: _elementPrefix, css: _cssPrefix };\n}\n\n/** Derive the full tag name from element prefix + base name. */\nexport function tagName(baseName: ElementBaseName): string {\n return `${_elementPrefix}-${baseName}`;\n}\n\n/** Prefix a CSS class name. `cls('toast-icon')` → `'l-toast-icon'` */\nexport function cls(name: string): string {\n return `${_cssPrefix}-${name}`;\n}\n\n/** Generate a globally unique prefixed ID. `uniqueId('toast')` → `'l:toast:1'` */\nlet _uid = 0;\nexport function uniqueId(base: string): string {\n return `${_cssPrefix}:${base}:${++_uid}`;\n}\n\n/** Check if a base name is already registered. */\nexport function isRegistered(baseName: ElementBaseName): boolean {\n return _registered.has(baseName);\n}\n\n/** Mark a base name as registered. Called internally by define(). */\nexport function markRegistered(baseName: ElementBaseName): void {\n _registered.add(baseName);\n}\n"],"mappings":"AA8BA,IAAI,EAAiB,IACjB,EAAa,IACX,EAAc,IAAI,IAcxB,SAAgB,EAAQ,EAAmC,CACzD,MAAO,GAAG,EAAe,GAAG,IAI9B,SAAgB,EAAI,EAAsB,CACxC,MAAO,GAAG,EAAW,GAAG,IAI1B,IAAI,EAAO,EACX,SAAgB,EAAS,EAAsB,CAC7C,MAAO,GAAG,EAAW,GAAG,EAAK,GAAG,EAAE,IAIpC,SAAgB,EAAa,EAAoC,CAC/D,OAAO,EAAY,IAAI,EAAS,CAIlC,SAAgB,EAAe,EAAiC,CAC9D,EAAY,IAAI,EAAS"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Reactive controller that tracks whether one or more slots have content, and
|
|
4
|
+
* requests a host update whenever that changes. Lets a template react to empty
|
|
5
|
+
* slots — e.g. collapse a footer row when nothing is slotted into it.
|
|
6
|
+
*
|
|
7
|
+
* Drives this off `slotchange` rather than a CSS selector because
|
|
8
|
+
* `:host(:has(> [slot='name']))` is invalid (`:has()` can't be nested inside
|
|
9
|
+
* `:host()`, so browsers drop the whole rule). Pair it with a data-attribute:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* private _slots = new HasSlotController(this, 'footer');
|
|
13
|
+
*
|
|
14
|
+
* render() {
|
|
15
|
+
* return html`
|
|
16
|
+
* <footer part="footer" ?data-empty=${!this._slots.test('footer')}>
|
|
17
|
+
* <slot name="footer"></slot>
|
|
18
|
+
* </footer>
|
|
19
|
+
* `;
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* Pass `'[default]'` to test the default (unnamed) slot.
|
|
24
|
+
*/
|
|
25
|
+
export declare class HasSlotController implements ReactiveController {
|
|
26
|
+
private host;
|
|
27
|
+
private slotNames;
|
|
28
|
+
constructor(host: ReactiveControllerHost & Element, ...slotNames: string[]);
|
|
29
|
+
/** Whether the given slot currently has content. Use `'[default]'` for the default slot. */
|
|
30
|
+
test(slotName: string): boolean;
|
|
31
|
+
private hasNamedSlot;
|
|
32
|
+
private hasDefaultSlot;
|
|
33
|
+
private handleSlotChange;
|
|
34
|
+
hostConnected(): void;
|
|
35
|
+
hostDisconnected(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=has-slot-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"has-slot-controller.d.ts","sourceRoot":"","sources":["../../../src/html/shared/controllers/has-slot-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,KAAK,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,iBAAkB,YAAW,kBAAkB;IAC1D,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,SAAS,CAAW;gBAEhB,IAAI,EAAE,sBAAsB,GAAG,OAAO,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE;IAM1E,4FAA4F;IAC5F,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAM/B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,gBAAgB,CAMtB;IAEF,aAAa;IAIb,gBAAgB;CAGjB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=class{constructor(e,...t){this.handleSlotChange=e=>{let t=e.target;(t.name?this.slotNames.includes(t.name):this.slotNames.includes(`[default]`))&&this.host.requestUpdate()},this.host=e,this.slotNames=t,e.addController(this)}test(e){return e===`[default]`?this.hasDefaultSlot():this.hasNamedSlot(e)}hasNamedSlot(e){return this.host.querySelector(`:scope > [slot="${e}"]`)!==null}hasDefaultSlot(){return[...this.host.childNodes].some(e=>e.nodeType===Node.TEXT_NODE?(e.textContent??``).trim()!==``:e.nodeType===Node.ELEMENT_NODE?!e.hasAttribute(`slot`):!1)}hostConnected(){this.host.shadowRoot?.addEventListener(`slotchange`,this.handleSlotChange)}hostDisconnected(){this.host.shadowRoot?.removeEventListener(`slotchange`,this.handleSlotChange)}};export{e as HasSlotController};
|
|
2
|
+
//# sourceMappingURL=has-slot-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"has-slot-controller.js","names":[],"sources":["../../../src/html/shared/controllers/has-slot-controller.ts"],"sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\n/**\n * Reactive controller that tracks whether one or more slots have content, and\n * requests a host update whenever that changes. Lets a template react to empty\n * slots — e.g. collapse a footer row when nothing is slotted into it.\n *\n * Drives this off `slotchange` rather than a CSS selector because\n * `:host(:has(> [slot='name']))` is invalid (`:has()` can't be nested inside\n * `:host()`, so browsers drop the whole rule). Pair it with a data-attribute:\n *\n * ```ts\n * private _slots = new HasSlotController(this, 'footer');\n *\n * render() {\n * return html`\n * <footer part=\"footer\" ?data-empty=${!this._slots.test('footer')}>\n * <slot name=\"footer\"></slot>\n * </footer>\n * `;\n * }\n * ```\n *\n * Pass `'[default]'` to test the default (unnamed) slot.\n */\nexport class HasSlotController implements ReactiveController {\n private host: ReactiveControllerHost & Element;\n private slotNames: string[];\n\n constructor(host: ReactiveControllerHost & Element, ...slotNames: string[]) {\n this.host = host;\n this.slotNames = slotNames;\n host.addController(this);\n }\n\n /** Whether the given slot currently has content. Use `'[default]'` for the default slot. */\n test(slotName: string): boolean {\n return slotName === '[default]' ? this.hasDefaultSlot() : this.hasNamedSlot(slotName);\n }\n\n // A direct child projected into the named slot. `:scope >` keeps it to direct\n // children, so a nested `[slot=\"name\"]` inside slotted content can't match.\n private hasNamedSlot(name: string): boolean {\n return this.host.querySelector(`:scope > [slot=\"${name}\"]`) !== null;\n }\n\n // Any non-whitespace text node or any element without a `slot` attribute\n // counts as default-slot content.\n private hasDefaultSlot(): boolean {\n return [...this.host.childNodes].some((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n return (node.textContent ?? '').trim() !== '';\n }\n if (node.nodeType === Node.ELEMENT_NODE) {\n return !(node as HTMLElement).hasAttribute('slot');\n }\n return false;\n });\n }\n\n private handleSlotChange = (event: Event) => {\n const slot = event.target as HTMLSlotElement;\n const watched = slot.name\n ? this.slotNames.includes(slot.name)\n : this.slotNames.includes('[default]');\n if (watched) this.host.requestUpdate();\n };\n\n hostConnected() {\n this.host.shadowRoot?.addEventListener('slotchange', this.handleSlotChange);\n }\n\n hostDisconnected() {\n this.host.shadowRoot?.removeEventListener('slotchange', this.handleSlotChange);\n }\n}\n"],"mappings":"AAyBA,IAAa,EAAb,KAA6D,CAI3D,YAAY,EAAwC,GAAG,EAAqB,uBA+BhD,GAAiB,CAC3C,IAAM,EAAO,EAAM,QACH,EAAK,KACjB,KAAK,UAAU,SAAS,EAAK,KAAK,CAClC,KAAK,UAAU,SAAS,YAAY,GAC3B,KAAK,KAAK,eAAe,EAnCtC,KAAK,KAAO,EACZ,KAAK,UAAY,EACjB,EAAK,cAAc,KAAK,CAI1B,KAAK,EAA2B,CAC9B,OAAO,IAAa,YAAc,KAAK,gBAAgB,CAAG,KAAK,aAAa,EAAS,CAKvF,aAAqB,EAAuB,CAC1C,OAAO,KAAK,KAAK,cAAc,mBAAmB,EAAK,IAAI,GAAK,KAKlE,gBAAkC,CAChC,MAAO,CAAC,GAAG,KAAK,KAAK,WAAW,CAAC,KAAM,GACjC,EAAK,WAAa,KAAK,WACjB,EAAK,aAAe,IAAI,MAAM,GAAK,GAEzC,EAAK,WAAa,KAAK,aAClB,CAAE,EAAqB,aAAa,OAAO,CAE7C,GACP,CAWJ,eAAgB,CACd,KAAK,KAAK,YAAY,iBAAiB,aAAc,KAAK,iBAAiB,CAG7E,kBAAmB,CACjB,KAAK,KAAK,YAAY,oBAAoB,aAAc,KAAK,iBAAiB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=Math.min,t=Math.max,n=Math.round,r=Math.floor,i=e=>({x:e,y:e}),a={left:`right`,right:`left`,bottom:`top`,top:`bottom`};function o(n,r,i){return t(n,e(r,i))}function s(e,t){return typeof e==`function`?e(t):e}function c(e){return e.split(`-`)[0]}function l(e){return e.split(`-`)[1]}function u(e){return e===`x`?`y`:`x`}function d(e){return e===`y`?`height`:`width`}function f(e){let t=e[0];return t===`t`||t===`b`?`y`:`x`}function p(e){return u(f(e))}function m(e,t,n){n===void 0&&(n=!1);let r=l(e),i=p(e),a=d(i),o=i===`x`?r===(n?`end`:`start`)?`right`:`left`:r===`start`?`bottom`:`top`;return t.reference[a]>t.floating[a]&&(o=C(o)),[o,C(o)]}function h(e){let t=C(e);return[g(e),t,g(t)]}function g(e){return e.includes(`start`)?e.replace(`start`,`end`):e.replace(`end`,`start`)}var _=[`left`,`right`],v=[`right`,`left`],y=[`top`,`bottom`],b=[`bottom`,`top`];function x(e,t,n){switch(e){case`top`:case`bottom`:return n?t?v:_:t?_:v;case`left`:case`right`:return t?y:b;default:return[]}}function S(e,t,n,r){let i=l(e),a=x(c(e),n===`start`,r);return i&&(a=a.map(e=>e+`-`+i),t&&(a=a.concat(a.map(g)))),a}function C(e){let t=c(e);return a[t]+e.slice(t.length)}function w(e){return{top:0,right:0,bottom:0,left:0,...e}}function ee(e){return typeof e==`number`?{top:e,right:e,bottom:e,left:e}:w(e)}function T(e){let{x:t,y:n,width:r,height:i}=e;return{width:r,height:i,top:n,left:t,right:t+r,bottom:n+i,x:t,y:n}}function E(e,t,n){let{reference:r,floating:i}=e,a=f(t),o=p(t),s=d(o),u=c(t),m=a===`y`,h=r.x+r.width/2-i.width/2,g=r.y+r.height/2-i.height/2,_=r[s]/2-i[s]/2,v;switch(u){case`top`:v={x:h,y:r.y-i.height};break;case`bottom`:v={x:h,y:r.y+r.height};break;case`right`:v={x:r.x+r.width,y:g};break;case`left`:v={x:r.x-i.width,y:g};break;default:v={x:r.x,y:r.y}}switch(l(t)){case`start`:v[o]-=_*(n&&m?-1:1);break;case`end`:v[o]+=_*(n&&m?-1:1);break}return v}async function D(e,t){t===void 0&&(t={});let{x:n,y:r,platform:i,rects:a,elements:o,strategy:c}=e,{boundary:l=`clippingAncestors`,rootBoundary:u=`viewport`,elementContext:d=`floating`,altBoundary:f=!1,padding:p=0}=s(t,e),m=ee(p),h=o[f?d===`floating`?`reference`:`floating`:d],g=T(await i.getClippingRect({element:await(i.isElement==null?void 0:i.isElement(h))??!0?h:h.contextElement||await(i.getDocumentElement==null?void 0:i.getDocumentElement(o.floating)),boundary:l,rootBoundary:u,strategy:c})),_=d===`floating`?{x:n,y:r,width:a.floating.width,height:a.floating.height}:a.reference,v=await(i.getOffsetParent==null?void 0:i.getOffsetParent(o.floating)),y=await(i.isElement==null?void 0:i.isElement(v))&&await(i.getScale==null?void 0:i.getScale(v))||{x:1,y:1},b=T(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:o,rect:_,offsetParent:v,strategy:c}):_);return{top:(g.top-b.top+m.top)/y.y,bottom:(b.bottom-g.bottom+m.bottom)/y.y,left:(g.left-b.left+m.left)/y.x,right:(b.right-g.right+m.right)/y.x}}var O=50,k=async(e,t,n)=>{let{placement:r=`bottom`,strategy:i=`absolute`,middleware:a=[],platform:o}=n,s=o.detectOverflow?o:{...o,detectOverflow:D},c=await(o.isRTL==null?void 0:o.isRTL(t)),l=await o.getElementRects({reference:e,floating:t,strategy:i}),{x:u,y:d}=E(l,r,c),f=r,p=0,m={};for(let n=0;n<a.length;n++){let h=a[n];if(!h)continue;let{name:g,fn:_}=h,{x:v,y,data:b,reset:x}=await _({x:u,y:d,initialPlacement:r,placement:f,strategy:i,middlewareData:m,rects:l,platform:s,elements:{reference:e,floating:t}});u=v??u,d=y??d,m[g]={...m[g],...b},x&&p<O&&(p++,typeof x==`object`&&(x.placement&&(f=x.placement),x.rects&&(l=x.rects===!0?await o.getElementRects({reference:e,floating:t,strategy:i}):x.rects),{x:u,y:d}=E(l,f,c)),n=-1)}return{x:u,y:d,placement:f,strategy:i,middlewareData:m}},A=t=>({name:`arrow`,options:t,async fn(n){let{x:r,y:i,placement:a,rects:c,platform:u,elements:f,middlewareData:m}=n,{element:h,padding:g=0}=s(t,n)||{};if(h==null)return{};let _=ee(g),v={x:r,y:i},y=p(a),b=d(y),x=await u.getDimensions(h),S=y===`y`,C=S?`top`:`left`,w=S?`bottom`:`right`,T=S?`clientHeight`:`clientWidth`,E=c.reference[b]+c.reference[y]-v[y]-c.floating[b],D=v[y]-c.reference[y],O=await(u.getOffsetParent==null?void 0:u.getOffsetParent(h)),k=O?O[T]:0;(!k||!await(u.isElement==null?void 0:u.isElement(O)))&&(k=f.floating[T]||c.floating[b]);let A=E/2-D/2,j=k/2-x[b]/2-1,M=e(_[C],j),N=e(_[w],j),P=M,te=k-x[b]-N,F=k/2-x[b]/2+A,I=o(P,F,te),L=!m.arrow&&l(a)!=null&&F!==I&&c.reference[b]/2-(F<P?M:N)-x[b]/2<0,R=L?F<P?F-P:F-te:0;return{[y]:v[y]+R,data:{[y]:I,centerOffset:F-I-R,...L&&{alignmentOffset:R}},reset:L}}}),j=function(e){return e===void 0&&(e={}),{name:`flip`,options:e,async fn(t){var n;let{placement:r,middlewareData:i,rects:a,initialPlacement:o,platform:l,elements:u}=t,{mainAxis:d=!0,crossAxis:p=!0,fallbackPlacements:g,fallbackStrategy:_=`bestFit`,fallbackAxisSideDirection:v=`none`,flipAlignment:y=!0,...b}=s(e,t);if((n=i.arrow)!=null&&n.alignmentOffset)return{};let x=c(r),w=f(o),ee=c(o)===o,T=await(l.isRTL==null?void 0:l.isRTL(u.floating)),E=g||(ee||!y?[C(o)]:h(o)),D=v!==`none`;!g&&D&&E.push(...S(o,y,v,T));let O=[o,...E],k=await l.detectOverflow(t,b),A=[],j=i.flip?.overflows||[];if(d&&A.push(k[x]),p){let e=m(r,a,T);A.push(k[e[0]],k[e[1]])}if(j=[...j,{placement:r,overflows:A}],!A.every(e=>e<=0)){let e=(i.flip?.index||0)+1,t=O[e];if(t&&(!(p===`alignment`&&w!==f(t))||j.every(e=>f(e.placement)===w?e.overflows[0]>0:!0)))return{data:{index:e,overflows:j},reset:{placement:t}};let n=j.filter(e=>e.overflows[0]<=0).sort((e,t)=>e.overflows[1]-t.overflows[1])[0]?.placement;if(!n)switch(_){case`bestFit`:{let e=j.filter(e=>{if(D){let t=f(e.placement);return t===w||t===`y`}return!0}).map(e=>[e.placement,e.overflows.filter(e=>e>0).reduce((e,t)=>e+t,0)]).sort((e,t)=>e[1]-t[1])[0]?.[0];e&&(n=e);break}case`initialPlacement`:n=o;break}if(r!==n)return{reset:{placement:n}}}return{}}}},M=new Set([`left`,`top`]);async function N(e,t){let{placement:n,platform:r,elements:i}=e,a=await(r.isRTL==null?void 0:r.isRTL(i.floating)),o=c(n),u=l(n),d=f(n)===`y`,p=M.has(o)?-1:1,m=a&&d?-1:1,h=s(t,e),{mainAxis:g,crossAxis:_,alignmentAxis:v}=typeof h==`number`?{mainAxis:h,crossAxis:0,alignmentAxis:null}:{mainAxis:h.mainAxis||0,crossAxis:h.crossAxis||0,alignmentAxis:h.alignmentAxis};return u&&typeof v==`number`&&(_=u===`end`?v*-1:v),d?{x:_*m,y:g*p}:{x:g*p,y:_*m}}var P=function(e){return e===void 0&&(e=0),{name:`offset`,options:e,async fn(t){var n;let{x:r,y:i,placement:a,middlewareData:o}=t,s=await N(t,e);return a===o.offset?.placement&&(n=o.arrow)!=null&&n.alignmentOffset?{}:{x:r+s.x,y:i+s.y,data:{...s,placement:a}}}}},te=function(e){return e===void 0&&(e={}),{name:`shift`,options:e,async fn(t){let{x:n,y:r,placement:i,platform:a}=t,{mainAxis:l=!0,crossAxis:d=!1,limiter:p={fn:e=>{let{x:t,y:n}=e;return{x:t,y:n}}},...m}=s(e,t),h={x:n,y:r},g=await a.detectOverflow(t,m),_=f(c(i)),v=u(_),y=h[v],b=h[_];if(l){let e=v===`y`?`top`:`left`,t=v===`y`?`bottom`:`right`,n=y+g[e],r=y-g[t];y=o(n,y,r)}if(d){let e=_===`y`?`top`:`left`,t=_===`y`?`bottom`:`right`,n=b+g[e],r=b-g[t];b=o(n,b,r)}let x=p.fn({...t,[v]:y,[_]:b});return{...x,data:{x:x.x-n,y:x.y-r,enabled:{[v]:l,[_]:d}}}}}};function F(){return typeof window<`u`}function I(e){return ne(e)?(e.nodeName||``).toLowerCase():`#document`}function L(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t.defaultView)||window}function R(e){return((ne(e)?e.ownerDocument:e.document)||window.document)?.documentElement}function ne(e){return F()?e instanceof Node||e instanceof L(e).Node:!1}function z(e){return F()?e instanceof Element||e instanceof L(e).Element:!1}function B(e){return F()?e instanceof HTMLElement||e instanceof L(e).HTMLElement:!1}function re(e){return!F()||typeof ShadowRoot>`u`?!1:e instanceof ShadowRoot||e instanceof L(e).ShadowRoot}function V(e){let{overflow:t,overflowX:n,overflowY:r,display:i}=q(e);return/auto|scroll|overlay|hidden|clip/.test(t+r+n)&&i!==`inline`&&i!==`contents`}function ie(e){return/^(table|td|th)$/.test(I(e))}function H(e){try{if(e.matches(`:popover-open`))return!0}catch{}try{return e.matches(`:modal`)}catch{return!1}}var ae=/transform|translate|scale|rotate|perspective|filter/,oe=/paint|layout|strict|content/,U=e=>!!e&&e!==`none`,se;function W(e){let t=z(e)?q(e):e;return U(t.transform)||U(t.translate)||U(t.scale)||U(t.rotate)||U(t.perspective)||!G()&&(U(t.backdropFilter)||U(t.filter))||ae.test(t.willChange||``)||oe.test(t.contain||``)}function ce(e){let t=Y(e);for(;B(t)&&!K(t);){if(W(t))return t;if(H(t))return null;t=Y(t)}return null}function G(){return se??=typeof CSS<`u`&&CSS.supports&&CSS.supports(`-webkit-backdrop-filter`,`none`),se}function K(e){return/^(html|body|#document)$/.test(I(e))}function q(e){return L(e).getComputedStyle(e)}function J(e){return z(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function Y(e){if(I(e)===`html`)return e;let t=e.assignedSlot||e.parentNode||re(e)&&e.host||R(e);return re(t)?t.host:t}function le(e){let t=Y(e);return K(t)?e.ownerDocument?e.ownerDocument.body:e.body:B(t)&&V(t)?t:le(t)}function X(e,t,n){t===void 0&&(t=[]),n===void 0&&(n=!0);let r=le(e),i=r===e.ownerDocument?.body,a=L(r);if(i){let e=ue(a);return t.concat(a,a.visualViewport||[],V(r)?r:[],e&&n?X(e):[])}else return t.concat(r,X(r,[],n))}function ue(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}function de(e){let t=q(e),r=parseFloat(t.width)||0,i=parseFloat(t.height)||0,a=B(e),o=a?e.offsetWidth:r,s=a?e.offsetHeight:i,c=n(r)!==o||n(i)!==s;return c&&(r=o,i=s),{width:r,height:i,$:c}}function fe(e){return z(e)?e:e.contextElement}function Z(e){let t=fe(e);if(!B(t))return i(1);let r=t.getBoundingClientRect(),{width:a,height:o,$:s}=de(t),c=(s?n(r.width):r.width)/a,l=(s?n(r.height):r.height)/o;return(!c||!Number.isFinite(c))&&(c=1),(!l||!Number.isFinite(l))&&(l=1),{x:c,y:l}}var pe=i(0);function me(e){let t=L(e);return!G()||!t.visualViewport?pe:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function he(e,t,n){return t===void 0&&(t=!1),!n||t&&n!==L(e)?!1:t}function Q(e,t,n,r){t===void 0&&(t=!1),n===void 0&&(n=!1);let a=e.getBoundingClientRect(),o=fe(e),s=i(1);t&&(r?z(r)&&(s=Z(r)):s=Z(e));let c=he(o,n,r)?me(o):i(0),l=(a.left+c.x)/s.x,u=(a.top+c.y)/s.y,d=a.width/s.x,f=a.height/s.y;if(o){let e=L(o),t=r&&z(r)?L(r):r,n=e,i=ue(n);for(;i&&r&&t!==n;){let e=Z(i),t=i.getBoundingClientRect(),r=q(i),a=t.left+(i.clientLeft+parseFloat(r.paddingLeft))*e.x,o=t.top+(i.clientTop+parseFloat(r.paddingTop))*e.y;l*=e.x,u*=e.y,d*=e.x,f*=e.y,l+=a,u+=o,n=L(i),i=ue(n)}}return T({width:d,height:f,x:l,y:u})}function $(e,t){let n=J(e).scrollLeft;return t?t.left+n:Q(R(e)).left+n}function ge(e,t){let n=e.getBoundingClientRect();return{x:n.left+t.scrollLeft-$(e,n),y:n.top+t.scrollTop}}function _e(e){let{elements:t,rect:n,offsetParent:r,strategy:a}=e,o=a===`fixed`,s=R(r),c=t?H(t.floating):!1;if(r===s||c&&o)return n;let l={scrollLeft:0,scrollTop:0},u=i(1),d=i(0),f=B(r);if((f||!f&&!o)&&((I(r)!==`body`||V(s))&&(l=J(r)),f)){let e=Q(r);u=Z(r),d.x=e.x+r.clientLeft,d.y=e.y+r.clientTop}let p=s&&!f&&!o?ge(s,l):i(0);return{width:n.width*u.x,height:n.height*u.y,x:n.x*u.x-l.scrollLeft*u.x+d.x+p.x,y:n.y*u.y-l.scrollTop*u.y+d.y+p.y}}function ve(e){return Array.from(e.getClientRects())}function ye(e){let n=R(e),r=J(e),i=e.ownerDocument.body,a=t(n.scrollWidth,n.clientWidth,i.scrollWidth,i.clientWidth),o=t(n.scrollHeight,n.clientHeight,i.scrollHeight,i.clientHeight),s=-r.scrollLeft+$(e),c=-r.scrollTop;return q(i).direction===`rtl`&&(s+=t(n.clientWidth,i.clientWidth)-a),{width:a,height:o,x:s,y:c}}var be=25;function xe(e,t){let n=L(e),r=R(e),i=n.visualViewport,a=r.clientWidth,o=r.clientHeight,s=0,c=0;if(i){a=i.width,o=i.height;let e=G();(!e||e&&t===`fixed`)&&(s=i.offsetLeft,c=i.offsetTop)}let l=$(r);if(l<=0){let e=r.ownerDocument,t=e.body,n=getComputedStyle(t),i=e.compatMode===`CSS1Compat`&&parseFloat(n.marginLeft)+parseFloat(n.marginRight)||0,o=Math.abs(r.clientWidth-t.clientWidth-i);o<=be&&(a-=o)}else l<=be&&(a+=l);return{width:a,height:o,x:s,y:c}}function Se(e,t){let n=Q(e,!0,t===`fixed`),r=n.top+e.clientTop,a=n.left+e.clientLeft,o=B(e)?Z(e):i(1);return{width:e.clientWidth*o.x,height:e.clientHeight*o.y,x:a*o.x,y:r*o.y}}function Ce(e,t,n){let r;if(t===`viewport`)r=xe(e,n);else if(t===`document`)r=ye(R(e));else if(z(t))r=Se(t,n);else{let n=me(e);r={x:t.x-n.x,y:t.y-n.y,width:t.width,height:t.height}}return T(r)}function we(e,t){let n=Y(e);return n===t||!z(n)||K(n)?!1:q(n).position===`fixed`||we(n,t)}function Te(e,t){let n=t.get(e);if(n)return n;let r=X(e,[],!1).filter(e=>z(e)&&I(e)!==`body`),i=null,a=q(e).position===`fixed`,o=a?Y(e):e;for(;z(o)&&!K(o);){let t=q(o),n=W(o);!n&&t.position===`fixed`&&(i=null),(a?!n&&!i:!n&&t.position===`static`&&i&&(i.position===`absolute`||i.position===`fixed`)||V(o)&&!n&&we(e,o))?r=r.filter(e=>e!==o):i=t,o=Y(o)}return t.set(e,r),r}function Ee(n){let{element:r,boundary:i,rootBoundary:a,strategy:o}=n,s=[...i===`clippingAncestors`?H(r)?[]:Te(r,this._c):[].concat(i),a],c=Ce(r,s[0],o),l=c.top,u=c.right,d=c.bottom,f=c.left;for(let n=1;n<s.length;n++){let i=Ce(r,s[n],o);l=t(i.top,l),u=e(i.right,u),d=e(i.bottom,d),f=t(i.left,f)}return{width:u-f,height:d-l,x:f,y:l}}function De(e){let{width:t,height:n}=de(e);return{width:t,height:n}}function Oe(e,t,n){let r=B(t),a=R(t),o=n===`fixed`,s=Q(e,!0,o,t),c={scrollLeft:0,scrollTop:0},l=i(0);function u(){l.x=$(a)}if(r||!r&&!o)if((I(t)!==`body`||V(a))&&(c=J(t)),r){let e=Q(t,!0,o,t);l.x=e.x+t.clientLeft,l.y=e.y+t.clientTop}else a&&u();o&&!r&&a&&u();let d=a&&!r&&!o?ge(a,c):i(0);return{x:s.left+c.scrollLeft-l.x-d.x,y:s.top+c.scrollTop-l.y-d.y,width:s.width,height:s.height}}function ke(e){return q(e).position===`static`}function Ae(e,t){if(!B(e)||q(e).position===`fixed`)return null;if(t)return t(e);let n=e.offsetParent;return R(e)===n&&(n=n.ownerDocument.body),n}function je(e,t){let n=L(e);if(H(e))return n;if(!B(e)){let t=Y(e);for(;t&&!K(t);){if(z(t)&&!ke(t))return t;t=Y(t)}return n}let r=Ae(e,t);for(;r&&ie(r)&&ke(r);)r=Ae(r,t);return r&&K(r)&&ke(r)&&!W(r)?n:r||ce(e)||n}var Me=async function(e){let t=this.getOffsetParent||je,n=this.getDimensions,r=await n(e.floating);return{reference:Oe(e.reference,await t(e.floating),e.strategy),floating:{x:0,y:0,width:r.width,height:r.height}}};function Ne(e){return q(e).direction===`rtl`}var Pe={convertOffsetParentRelativeRectToViewportRelativeRect:_e,getDocumentElement:R,getClippingRect:Ee,getOffsetParent:je,getElementRects:Me,getClientRects:ve,getDimensions:De,getScale:Z,isElement:z,isRTL:Ne};function Fe(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}function Ie(n,i){let a=null,o,s=R(n);function c(){var e;clearTimeout(o),(e=a)==null||e.disconnect(),a=null}function l(u,d){u===void 0&&(u=!1),d===void 0&&(d=1),c();let f=n.getBoundingClientRect(),{left:p,top:m,width:h,height:g}=f;if(u||i(),!h||!g)return;let _=r(m),v=r(s.clientWidth-(p+h)),y=r(s.clientHeight-(m+g)),b=r(p),x={rootMargin:-_+`px `+-v+`px `+-y+`px `+-b+`px`,threshold:t(0,e(1,d))||1},S=!0;function C(e){let t=e[0].intersectionRatio;if(t!==d){if(!S)return l();t?l(!1,t):o=setTimeout(()=>{l(!1,1e-7)},1e3)}t===1&&!Fe(f,n.getBoundingClientRect())&&l(),S=!1}try{a=new IntersectionObserver(C,{...x,root:s.ownerDocument})}catch{a=new IntersectionObserver(C,x)}a.observe(n)}return l(!0),c}function Le(e,t,n,r){r===void 0&&(r={});let{ancestorScroll:i=!0,ancestorResize:a=!0,elementResize:o=typeof ResizeObserver==`function`,layoutShift:s=typeof IntersectionObserver==`function`,animationFrame:c=!1}=r,l=fe(e),u=i||a?[...l?X(l):[],...t?X(t):[]]:[];u.forEach(e=>{i&&e.addEventListener(`scroll`,n,{passive:!0}),a&&e.addEventListener(`resize`,n)});let d=l&&s?Ie(l,n):null,f=-1,p=null;o&&(p=new ResizeObserver(e=>{let[r]=e;r&&r.target===l&&p&&t&&(p.unobserve(t),cancelAnimationFrame(f),f=requestAnimationFrame(()=>{var e;(e=p)==null||e.observe(t)})),n()}),l&&!c&&p.observe(l),t&&p.observe(t));let m,h=c?Q(e):null;c&&g();function g(){let t=Q(e);h&&!Fe(h,t)&&n(),h=t,m=requestAnimationFrame(g)}return n(),()=>{var e;u.forEach(e=>{i&&e.removeEventListener(`scroll`,n),a&&e.removeEventListener(`resize`,n)}),d?.(),(e=p)==null||e.disconnect(),p=null,c&&cancelAnimationFrame(m)}}var Re=P,ze=te,Be=j,Ve=A,He=(e,t,n)=>{let r=new Map,i={platform:Pe,...n},a={...i.platform,_c:r};return k(e,t,{...i,platform:a})};function Ue([e,t],n){let r=!1;for(let i=0,a=n.length-1;i<n.length;a=i++){let[o,s]=n[i],[c,l]=n[a];s>=t!=l>=t&&e<=(c-o)*(t-s)/(l-s)+o&&(r=!r)}return r}function We([e,t],n){return e>=n.left&&e<=n.right&&t>=n.top&&t<=n.bottom}function Ge(e,t,n,r,i){let a=i.split(`-`)[0],o=n.width>r.width,s=n.height>r.height,c=e>n.right-n.width/2,l=t>n.bottom-n.height/2;switch(a){case`top`:return[[o?e+2/2:c?e+8:e-8,t+2+1],[o?e-2/2:c?e+8:e-8,t+2+1],[n.left,c||o?n.bottom-2:n.top],[n.right,c?o?n.bottom-2:n.top:n.bottom-2]];case`bottom`:return[[o?e+2/2:c?e+8:e-8,t-2],[o?e-2/2:c?e+8:e-8,t-2],[n.left,c||o?n.top+2:n.bottom],[n.right,c?o?n.top+2:n.bottom:n.top+2]];case`left`:{let r=[e+2+1,s?t+2/2:l?t+8:t-8],i=[e+2+1,s?t-2/2:l?t+8:t-8];return[[l||s?n.right-2:n.left,n.top],[l?s?n.right-2:n.left:n.right-2,n.bottom],r,i]}case`right`:{let r=[e-2,s?t+2/2:l?t+8:t-8],i=[e-2,s?t-2/2:l?t+8:t-8];return[[l||s?n.left+2:n.right,n.top],[l?s?n.left+2:n.right:n.left+2,n.bottom],r,i]}default:return[]}}var Ke={top:`bottom`,right:`left`,bottom:`top`,left:`right`},qe=typeof window<`u`?window.matchMedia(`(prefers-reduced-motion: reduce)`):void 0,Je=class{constructor(e,t){this._currentPlacement=``,this._host=e,this._config=t,e.addController(this)}hostConnected(){}hostDisconnected(){this.stopPositioning(),this.cleanupSafePolygon(),this.removeTriggerListeners()}get currentPlacement(){return this._currentPlacement}async updatePosition(e){let t=this._config.getTriggerElement(),n=this._config.getFloatingElement(),r=this._config.getArrowElement();if(!t||!n)return;let i=[Re(e.distance),Be(),ze(),...r?[Ve({element:r,padding:8})]:[]],{x:a,y:o,placement:s,middlewareData:c}=await He(t,n,{placement:e.placement,strategy:`fixed`,middleware:i});if(Object.assign(n.style,{position:`fixed`,left:e.fullWidth?`0px`:`${a}px`,top:`${o}px`,width:e.fullWidth?`100vw`:``}),s!==this._currentPlacement&&(this._currentPlacement=s,this._config.onPlacementChange?.(s)),c.arrow&&r){let{x:e,y:t}=c.arrow,n=Ke[s.split(`-`)[0]];Object.assign(r.style,{left:e==null?``:`${e}px`,top:t==null?``:`${t}px`,[n]:`${-r.offsetWidth/2}px`})}}startPositioning(e){let t=this._config.getTriggerElement(),n=this._config.getFloatingElement();!t||!n||(this._cleanupAutoUpdate?.(),this._cleanupAutoUpdate=Le(t,n,()=>this.updatePosition(e)))}stopPositioning(){this._cleanupAutoUpdate?.(),this._cleanupAutoUpdate=void 0}handlePointerLeave(e,t){let n=this._config.getFloatingElement(),r=this._config.getTriggerElement();if(!n||!r){t();return}let i=e.clientX,a=e.clientY,o=e=>{let{clientX:o,clientY:c}=e,l=[o,c],u=n.getBoundingClientRect(),d=r.getBoundingClientRect(),f=this._currentPlacement.split(`-`)[0];if(!We(l,u)&&!We(l,d)){if(f===`top`&&a>=d.bottom-1||f===`bottom`&&a<=d.top+1||f===`left`&&i>=d.right-1||f===`right`&&i<=d.left+1){s(),t();return}Ue(l,Ge(i,a,u,d,this._currentPlacement))||(s(),t())}},s=()=>{document.removeEventListener(`pointermove`,o)};document.addEventListener(`pointermove`,o),this._cleanupSafePolygon?.(),this._cleanupSafePolygon=s}cleanupSafePolygon(){this._cleanupSafePolygon?.(),this._cleanupSafePolygon=void 0}addTriggerListeners(e){let t=this._config.getTriggerElement();t&&(this._handlers=e,this._triggerElement=t,e.onPointerEnter&&t.addEventListener(`pointerenter`,e.onPointerEnter),e.onPointerLeave&&t.addEventListener(`pointerleave`,e.onPointerLeave),e.onFocusIn&&t.addEventListener(`focusin`,e.onFocusIn),e.onFocusOut&&t.addEventListener(`focusout`,e.onFocusOut),e.onClick&&t.addEventListener(`click`,e.onClick),e.onKeyDown&&t.addEventListener(`keydown`,e.onKeyDown))}removeTriggerListeners(e){let t=e??this._triggerElement,n=this._handlers;!t||!n||(n.onPointerEnter&&t.removeEventListener(`pointerenter`,n.onPointerEnter),n.onPointerLeave&&t.removeEventListener(`pointerleave`,n.onPointerLeave),n.onFocusIn&&t.removeEventListener(`focusin`,n.onFocusIn),n.onFocusOut&&t.removeEventListener(`focusout`,n.onFocusOut),n.onClick&&t.removeEventListener(`click`,n.onClick),n.onKeyDown&&t.removeEventListener(`keydown`,n.onKeyDown),e||(this._handlers=void 0,this._triggerElement=void 0))}async animateShow(e,t,n){let r=qe?.matches?0:t;e.getAnimations().forEach(e=>e.cancel()),e.animate(n??[{opacity:0,scale:.96},{opacity:1,scale:1}],{duration:r,fill:`forwards`})}async animateHide(e,t,n){let r=qe?.matches?0:t;await e.animate(n??[{opacity:1,scale:1},{opacity:0,scale:.96}],{duration:r,fill:`forwards`}).finished}};export{Je as PopoverController};
|
|
1
|
+
import{a as e,i as t,n,o as r,r as i,t as a}from"../../chunks/floating-ui.dom.js";function o([e,t],n){let r=!1;for(let i=0,a=n.length-1;i<n.length;a=i++){let[o,s]=n[i],[c,l]=n[a];s>=t!=l>=t&&e<=(c-o)*(t-s)/(l-s)+o&&(r=!r)}return r}function s([e,t],n){return e>=n.left&&e<=n.right&&t>=n.top&&t<=n.bottom}function c(e,t,n,r,i){let a=i.split(`-`)[0],o=n.width>r.width,s=n.height>r.height,c=e>n.right-n.width/2,l=t>n.bottom-n.height/2;switch(a){case`top`:return[[o?e+2/2:c?e+8:e-8,t+2+1],[o?e-2/2:c?e+8:e-8,t+2+1],[n.left,c||o?n.bottom-2:n.top],[n.right,c?o?n.bottom-2:n.top:n.bottom-2]];case`bottom`:return[[o?e+2/2:c?e+8:e-8,t-2],[o?e-2/2:c?e+8:e-8,t-2],[n.left,c||o?n.top+2:n.bottom],[n.right,c?o?n.top+2:n.bottom:n.top+2]];case`left`:{let r=[e+2+1,s?t+2/2:l?t+8:t-8],i=[e+2+1,s?t-2/2:l?t+8:t-8];return[[l||s?n.right-2:n.left,n.top],[l?s?n.right-2:n.left:n.right-2,n.bottom],r,i]}case`right`:{let r=[e-2,s?t+2/2:l?t+8:t-8],i=[e-2,s?t-2/2:l?t+8:t-8];return[[l||s?n.left+2:n.right,n.top],[l?s?n.left+2:n.right:n.left+2,n.bottom],r,i]}default:return[]}}var l={top:`bottom`,right:`left`,bottom:`top`,left:`right`},u=typeof window<`u`?window.matchMedia(`(prefers-reduced-motion: reduce)`):void 0,d=class{constructor(e,t){this._currentPlacement=``,this._host=e,this._config=t,e.addController(this)}hostConnected(){}hostDisconnected(){this.stopPositioning(),this.cleanupSafePolygon(),this.removeTriggerListeners()}get currentPlacement(){return this._currentPlacement}async updatePosition(n){let o=this._config.getTriggerElement(),s=this._config.getFloatingElement(),c=this._config.getArrowElement();if(!o||!s)return;let u=[e(n.distance),t(),r(),...c?[a({element:c,padding:8})]:[]],{x:d,y:f,placement:p,middlewareData:m}=await i(o,s,{placement:n.placement,strategy:`fixed`,middleware:u});if(Object.assign(s.style,{position:`fixed`,left:n.fullWidth?`0px`:`${d}px`,top:`${f}px`,width:n.fullWidth?`100vw`:``}),p!==this._currentPlacement&&(this._currentPlacement=p,this._config.onPlacementChange?.(p)),m.arrow&&c){let{x:e,y:t}=m.arrow,n=l[p.split(`-`)[0]];Object.assign(c.style,{left:e==null?``:`${e}px`,top:t==null?``:`${t}px`,[n]:`${-c.offsetWidth/2}px`})}}startPositioning(e){let t=this._config.getTriggerElement(),r=this._config.getFloatingElement();!t||!r||(this._cleanupAutoUpdate?.(),this._cleanupAutoUpdate=n(t,r,()=>this.updatePosition(e)))}stopPositioning(){this._cleanupAutoUpdate?.(),this._cleanupAutoUpdate=void 0}handlePointerLeave(e,t){let n=this._config.getFloatingElement(),r=this._config.getTriggerElement();if(!n||!r){t();return}let i=e.clientX,a=e.clientY,l=e=>{let{clientX:l,clientY:d}=e,f=[l,d],p=n.getBoundingClientRect(),m=r.getBoundingClientRect(),h=this._currentPlacement.split(`-`)[0];if(!s(f,p)&&!s(f,m)){if(h===`top`&&a>=m.bottom-1||h===`bottom`&&a<=m.top+1||h===`left`&&i>=m.right-1||h===`right`&&i<=m.left+1){u(),t();return}o(f,c(i,a,p,m,this._currentPlacement))||(u(),t())}},u=()=>{document.removeEventListener(`pointermove`,l)};document.addEventListener(`pointermove`,l),this._cleanupSafePolygon?.(),this._cleanupSafePolygon=u}cleanupSafePolygon(){this._cleanupSafePolygon?.(),this._cleanupSafePolygon=void 0}addTriggerListeners(e){let t=this._config.getTriggerElement();t&&(this._handlers=e,this._triggerElement=t,e.onPointerEnter&&t.addEventListener(`pointerenter`,e.onPointerEnter),e.onPointerLeave&&t.addEventListener(`pointerleave`,e.onPointerLeave),e.onFocusIn&&t.addEventListener(`focusin`,e.onFocusIn),e.onFocusOut&&t.addEventListener(`focusout`,e.onFocusOut),e.onClick&&t.addEventListener(`click`,e.onClick),e.onKeyDown&&t.addEventListener(`keydown`,e.onKeyDown))}removeTriggerListeners(e){let t=e??this._triggerElement,n=this._handlers;!t||!n||(n.onPointerEnter&&t.removeEventListener(`pointerenter`,n.onPointerEnter),n.onPointerLeave&&t.removeEventListener(`pointerleave`,n.onPointerLeave),n.onFocusIn&&t.removeEventListener(`focusin`,n.onFocusIn),n.onFocusOut&&t.removeEventListener(`focusout`,n.onFocusOut),n.onClick&&t.removeEventListener(`click`,n.onClick),n.onKeyDown&&t.removeEventListener(`keydown`,n.onKeyDown),e||(this._handlers=void 0,this._triggerElement=void 0))}async animateShow(e,t,n){let r=u?.matches?0:t;e.getAnimations().forEach(e=>e.cancel()),e.animate(n??[{opacity:0,scale:.96},{opacity:1,scale:1}],{duration:r,fill:`forwards`})}async animateHide(e,t,n){let r=u?.matches?0:t;await e.animate(n??[{opacity:1,scale:1},{opacity:0,scale:.96}],{duration:r,fill:`forwards`}).finished}};export{d as PopoverController};
|
|
2
2
|
//# sourceMappingURL=popover.js.map
|