luxen-ui 0.24.0 → 0.26.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/README.md +1 -0
- package/bin/cli.mjs +16 -1
- package/cdn/custom-elements.json +295 -169
- package/cdn/elements/alert-dialog/alert-dialog.d.ts +3 -2
- package/cdn/elements/alert-dialog/alert-dialog.d.ts.map +1 -1
- package/cdn/elements/alert-dialog/alert-dialog.js.map +1 -1
- package/cdn/elements/avatar/avatar.js +1 -1
- package/cdn/elements/avatar/avatar.js.map +1 -1
- package/cdn/elements/carousel/carousel.js +1 -1
- package/cdn/elements/carousel/carousel.js.map +1 -1
- package/cdn/elements/combobox/combobox.d.ts.map +1 -1
- package/cdn/elements/combobox/combobox.js +2 -1
- package/cdn/elements/combobox/combobox.js.map +1 -1
- package/cdn/elements/dialog/dialog.d.ts +2 -1
- package/cdn/elements/dialog/dialog.d.ts.map +1 -1
- 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/drawer/drawer.d.ts +7 -7
- package/cdn/elements/drawer/drawer.js +1 -1
- package/cdn/elements/drawer/drawer.js.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/input-otp/input-otp.d.ts +2 -2
- package/cdn/elements/input-otp/input-otp.js.map +1 -1
- package/cdn/elements/prose-editor/prose-editor.js +1 -1
- package/cdn/elements/prose-editor/prose-editor.js.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.d.ts.map +1 -1
- package/cdn/elements/select/select.js +2 -1
- package/cdn/elements/select/select.js.map +1 -1
- package/cdn/elements/slider/slider.js +1 -1
- package/cdn/elements/slider/slider.js.map +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.js +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.js.map +1 -1
- package/cdn/elements/table/table.meta.d.ts +55 -0
- package/cdn/elements/table/table.meta.d.ts.map +1 -0
- package/cdn/elements/table/table.meta.js +0 -0
- package/cdn/elements/tag/tag.js +1 -1
- package/cdn/elements/tag/tag.js.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.js +1 -1
- package/cdn/elements/tree-item/tree-item.js.map +1 -1
- package/cdn/shared/controllers/listbox-nav.d.ts +7 -0
- package/cdn/shared/controllers/listbox-nav.d.ts.map +1 -1
- package/cdn/shared/controllers/listbox-nav.js +1 -1
- package/cdn/shared/controllers/listbox-nav.js.map +1 -1
- package/cdn/shared/styles/button-core.styles.js +1 -1
- package/cdn/shared/styles/button-core.styles.js.map +1 -1
- package/cdn/shared/styles/checkbox-appearance.styles.js +1 -1
- package/cdn/shared/styles/checkbox-appearance.styles.js.map +1 -1
- package/cdn/shared/styles/picker-core.styles.js +1 -1
- package/cdn/shared/styles/picker-core.styles.js.map +1 -1
- package/cdn/standalone.css +392 -86
- package/cdn/standalone.js +38 -28
- package/cdn/standalone.js.map +1 -1
- package/cdn/styles/base.css +11 -0
- package/cdn/styles/elements/breadcrumb.css +2 -2
- package/cdn/styles/elements/button.css +2 -2
- package/cdn/styles/elements/checkbox.css +2 -2
- package/cdn/styles/elements/close-button/circle.css +2 -2
- package/cdn/styles/elements/close-button/ring.css +2 -2
- package/cdn/styles/elements/close-button/square.css +2 -2
- package/cdn/styles/elements/disclosure.css +2 -2
- package/cdn/styles/elements/input-otp.css +20 -4
- package/cdn/styles/elements/input-stepper/default.css +2 -2
- package/cdn/styles/elements/input-stepper/pill.css +2 -2
- package/cdn/styles/elements/input-stepper/rounded.css +2 -2
- package/cdn/styles/elements/input.css +50 -17
- package/cdn/styles/elements/prose-editor.css +26 -11
- package/cdn/styles/elements/radio-group.css +2 -2
- package/cdn/styles/elements/radio.css +2 -2
- package/cdn/styles/elements/segmented-control.css +2 -2
- package/cdn/styles/elements/select.css +26 -5
- package/cdn/styles/elements/story.css +2 -2
- package/cdn/styles/elements/switch.css +2 -2
- package/cdn/styles/elements/table.css +186 -0
- package/cdn/styles/elements/tabs/enclosed.css +4 -4
- package/cdn/styles/elements/tabs/line.css +4 -4
- package/cdn/styles/elements/textarea.css +23 -9
- package/cdn/styles/preset.css +21 -2
- package/cdn/styles/tokens/aliases.css +6 -2
- package/cdn/styles/tokens/forms.css +4 -0
- package/cdn/styles/tokens.css +10 -2
- package/dist/css/base.css +11 -0
- package/dist/css/elements/breadcrumb.css +2 -2
- package/dist/css/elements/button.css +2 -2
- package/dist/css/elements/checkbox.css +2 -2
- package/dist/css/elements/close-button/circle.css +2 -2
- package/dist/css/elements/close-button/ring.css +2 -2
- package/dist/css/elements/close-button/square.css +2 -2
- package/dist/css/elements/disclosure.css +2 -2
- package/dist/css/elements/input-otp.css +20 -4
- package/dist/css/elements/input-stepper/default.css +2 -2
- package/dist/css/elements/input-stepper/pill.css +2 -2
- package/dist/css/elements/input-stepper/rounded.css +2 -2
- package/dist/css/elements/input.css +50 -17
- package/dist/css/elements/prose-editor.css +26 -11
- package/dist/css/elements/radio-group.css +2 -2
- package/dist/css/elements/radio.css +2 -2
- package/dist/css/elements/segmented-control.css +2 -2
- package/dist/css/elements/select.css +26 -5
- package/dist/css/elements/story.css +2 -2
- package/dist/css/elements/switch.css +2 -2
- package/dist/css/elements/table.css +186 -0
- package/dist/css/elements/tabs/enclosed.css +4 -4
- package/dist/css/elements/tabs/line.css +4 -4
- package/dist/css/elements/textarea.css +23 -9
- package/dist/css/preset.css +21 -2
- package/dist/css/tokens/aliases.css +6 -2
- package/dist/css/tokens/forms.css +4 -0
- package/dist/css/tokens.css +10 -2
- package/dist/custom-elements.json +295 -169
- package/dist/elements/alert-dialog/alert-dialog.d.ts +3 -2
- package/dist/elements/alert-dialog/alert-dialog.d.ts.map +1 -1
- package/dist/elements/alert-dialog/alert-dialog.js +3 -2
- package/dist/elements/avatar/avatar.css +2 -2
- package/dist/elements/carousel/carousel.css +18 -0
- package/dist/elements/combobox/combobox.css +9 -0
- package/dist/elements/combobox/combobox.d.ts.map +1 -1
- package/dist/elements/combobox/combobox.js +1 -0
- package/dist/elements/dialog/dialog.css +12 -0
- package/dist/elements/dialog/dialog.d.ts +2 -1
- package/dist/elements/dialog/dialog.d.ts.map +1 -1
- package/dist/elements/dialog/dialog.js +2 -1
- package/dist/elements/drawer/drawer.css +11 -1
- package/dist/elements/drawer/drawer.d.ts +7 -7
- package/dist/elements/drawer/drawer.js +7 -7
- package/dist/elements/dropdown-item/dropdown-item.css +5 -4
- package/dist/elements/input-otp/input-otp.d.ts +2 -2
- package/dist/elements/input-otp/input-otp.js +2 -2
- package/dist/elements/prose-editor/prose-editor.css +5 -3
- package/dist/elements/rating/rating.css +9 -10
- package/dist/elements/select/select.css +10 -9
- package/dist/elements/select/select.d.ts.map +1 -1
- package/dist/elements/select/select.js +1 -0
- package/dist/elements/slider/slider.css +5 -1
- package/dist/elements/stories-viewer/stories-viewer.css +10 -2
- package/dist/elements/table/table.meta.d.ts +55 -0
- package/dist/elements/table/table.meta.d.ts.map +1 -0
- package/dist/elements/table/table.meta.js +65 -0
- package/dist/elements/tag/tag.css +4 -4
- package/dist/elements/tree/tree.css +3 -3
- package/dist/elements/tree-item/tree-item.css +5 -3
- package/dist/metadata/alert-dialog.json +90 -85
- package/dist/metadata/alert.json +22 -22
- package/dist/metadata/avatar.json +26 -26
- package/dist/metadata/badge.json +13 -13
- package/dist/metadata/breadcrumb.json +9 -9
- package/dist/metadata/button.json +40 -40
- package/dist/metadata/carousel.json +133 -133
- package/dist/metadata/checkbox.json +13 -13
- package/dist/metadata/close-button.json +15 -15
- package/dist/metadata/color-scheme-icon.json +13 -13
- package/dist/metadata/combobox.json +77 -94
- package/dist/metadata/dialog.json +49 -44
- package/dist/metadata/disclosure.json +17 -17
- package/dist/metadata/divider.json +12 -12
- package/dist/metadata/drawer.json +61 -61
- package/dist/metadata/dropdown-item.json +50 -50
- package/dist/metadata/dropdown.json +32 -32
- package/dist/metadata/form-field.json +15 -15
- package/dist/metadata/icon.json +8 -8
- package/dist/metadata/index.json +1761 -1765
- package/dist/metadata/input-group.json +5 -5
- package/dist/metadata/input-otp.json +17 -17
- package/dist/metadata/input-stepper.json +24 -24
- package/dist/metadata/input.json +31 -31
- package/dist/metadata/popover.json +49 -49
- package/dist/metadata/progress.json +15 -15
- package/dist/metadata/prose-editor.json +110 -116
- package/dist/metadata/radio.json +15 -15
- package/dist/metadata/rating.json +25 -47
- package/dist/metadata/segmented-control.json +24 -46
- package/dist/metadata/select.json +81 -98
- package/dist/metadata/skeleton.json +12 -12
- package/dist/metadata/slider.json +60 -78
- package/dist/metadata/spinner.json +5 -5
- package/dist/metadata/sticky-bar.json +13 -13
- package/dist/metadata/stories-viewer.json +105 -105
- package/dist/metadata/stories.json +17 -17
- package/dist/metadata/story.json +41 -41
- package/dist/metadata/switch.json +9 -9
- package/dist/metadata/table.json +88 -0
- package/dist/metadata/tabs.json +26 -26
- package/dist/metadata/tag.json +50 -50
- package/dist/metadata/textarea.json +28 -28
- package/dist/metadata/toast.json +16 -16
- package/dist/metadata/tooltip.json +49 -49
- package/dist/metadata/tree-item.json +73 -73
- package/dist/metadata/tree.json +39 -39
- package/dist/shared/controllers/listbox-nav.d.ts +7 -0
- package/dist/shared/controllers/listbox-nav.d.ts.map +1 -1
- package/dist/shared/controllers/listbox-nav.js +12 -0
- package/dist/shared/styles/button-core.css +2 -2
- package/dist/shared/styles/checkbox-appearance.css +2 -2
- package/dist/shared/styles/picker-core.css +31 -7
- package/dist/templates/elements/alert-dialog.md +19 -18
- package/dist/templates/elements/alert.md +4 -4
- package/dist/templates/elements/avatar.md +9 -9
- package/dist/templates/elements/badge.md +4 -4
- package/dist/templates/elements/breadcrumb.md +4 -4
- package/dist/templates/elements/button.md +8 -8
- package/dist/templates/elements/carousel.md +32 -32
- package/dist/templates/elements/checkbox.md +4 -4
- package/dist/templates/elements/close-button.md +2 -2
- package/dist/templates/elements/color-scheme-icon.md +13 -13
- package/dist/templates/elements/combobox.md +19 -19
- package/dist/templates/elements/dialog.md +11 -10
- package/dist/templates/elements/disclosure.md +3 -3
- package/dist/templates/elements/divider.md +2 -2
- package/dist/templates/elements/drawer.md +15 -15
- package/dist/templates/elements/dropdown.md +15 -15
- package/dist/templates/elements/form-field.md +3 -3
- package/dist/templates/elements/icon.md +1 -1
- package/dist/templates/elements/input-otp.md +5 -5
- package/dist/templates/elements/input-stepper.md +4 -4
- package/dist/templates/elements/input.md +15 -8
- package/dist/templates/elements/popover.md +8 -8
- package/dist/templates/elements/progress.md +3 -3
- package/dist/templates/elements/prose-editor.md +38 -39
- package/dist/templates/elements/radio.md +6 -6
- package/dist/templates/elements/rating.md +5 -13
- package/dist/templates/elements/segmented-control.md +4 -4
- package/dist/templates/elements/select.md +23 -23
- package/dist/templates/elements/skeleton.md +2 -2
- package/dist/templates/elements/slider.md +13 -13
- package/dist/templates/elements/spinner.md +1 -1
- package/dist/templates/elements/sticky-bar.md +2 -2
- package/dist/templates/elements/stories-viewer.md +29 -29
- package/dist/templates/elements/stories.md +4 -4
- package/dist/templates/elements/story.md +11 -11
- package/dist/templates/elements/switch.md +5 -5
- package/dist/templates/elements/table.md +210 -0
- package/dist/templates/elements/tabs.md +4 -4
- package/dist/templates/elements/tag.md +14 -14
- package/dist/templates/elements/textarea.md +8 -8
- package/dist/templates/elements/toast.md +4 -4
- package/dist/templates/elements/tooltip.md +9 -9
- package/dist/templates/elements/tree-item.md +18 -18
- package/dist/templates/elements/tree.md +13 -13
- package/dist/templates/foundations/focus.md +303 -0
- package/elements.json +9 -0
- package/package.json +1 -1
- package/postcss-plugin-prefix.js +2 -2
- package/templates/SKILL.md.tpl +1 -0
- package/templates/choosing-elements.md.tpl +1 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e}from"../../chunks/lit.js";import{r as t,t as n}from"../../chunks/decorate.js";import{a as r,t as i}from"../../chunks/lit-html.js";import{LuxenFormAssociatedElement as a}from"../../shared/luxen-form-associated-element.js";import o from"../../shared/styles/host.styles.js";var s=e(`:host{--icon-size:20px;--active-color:gold;--inactive-color:#ddd;--spacing:0px;--_icon:var(--icon,url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='2 2 20 19.02'><path d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/></svg>"));align-items:center;display:inline-flex}.rating{height:var(--icon-size);background:linear-gradient(to right, var(--active-color) var(--_fill,0%), var(--inactive-color) var(--_fill,0%));-webkit-mask-size:var(--icon-size) var(--icon-size);mask-size:var(--icon-size) var(--icon-size);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.rating-edit{gap:var(--spacing);display:inline-flex}.icon-wrapper{cursor:pointer}.icon-wrapper input{clip:rect(0, 0, 0, 0);border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.icon{width:var(--icon-size);height:var(--icon-size);-webkit-mask-image:var(--_icon);mask-image:var(--_icon);background:var(--inactive-color);pointer-events:none;transition:scale .2s;display:block;-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.icon.active{background:var(--active-color)}.icon-wrapper:hover .icon{scale:1.2}.icon-wrapper:has(input:focus-visible)
|
|
1
|
+
import{i as e}from"../../chunks/lit.js";import{r as t,t as n}from"../../chunks/decorate.js";import{a as r,t as i}from"../../chunks/lit-html.js";import{LuxenFormAssociatedElement as a}from"../../shared/luxen-form-associated-element.js";import o from"../../shared/styles/host.styles.js";var s=e(`:host{--icon-size:20px;--active-color:gold;--inactive-color:#ddd;--spacing:0px;--_icon:var(--icon,url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='2 2 20 19.02'><path d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/></svg>"));align-items:center;display:inline-flex}.rating{height:var(--icon-size);background:linear-gradient(to right, var(--active-color) var(--_fill,0%), var(--inactive-color) var(--_fill,0%));-webkit-mask-size:var(--icon-size) var(--icon-size);mask-size:var(--icon-size) var(--icon-size);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.rating-edit{gap:var(--spacing);display:inline-flex}.icon-wrapper{border-radius:var(--l-radius-sm);cursor:pointer;display:block}.icon-wrapper input{clip:rect(0, 0, 0, 0);border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.icon{width:var(--icon-size);height:var(--icon-size);-webkit-mask-image:var(--_icon);mask-image:var(--_icon);background:var(--inactive-color);pointer-events:none;transition:scale .2s;display:block;-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.icon.active{background:var(--active-color)}.icon-wrapper:hover .icon{scale:1.2}.icon-wrapper:has(input:focus-visible){outline:var(--l-focus-ring-width) solid var(--l-focus-ring-color);outline-offset:var(--l-focus-ring-offset)}:host([disabled]){opacity:.5;pointer-events:none}.wrapper{white-space:nowrap;align-items:center;display:flex}.rating-label{flex:1;margin-inline-start:8px;font-size:1rem;line-height:1}`),c=class extends Event{constructor(e){super(`change`,{bubbles:!0,composed:!1,cancelable:!1}),this.name=e.name,this.value=e.value,this.checked=e.checked,this.sourceEvent=e.sourceEvent}},l=class extends a{constructor(...e){super(...e),this.currentLabel=``,this.previewedValue=0,this.#e=!1,this.#t=[],this.#n=0,this.#r=5,this.previewValue=e=>{this.previewedValue=e,this.setLabelForValue(e)},this.clearPreview=e=>{if(e){let t=e.relatedTarget;if(t&&this.shadowRoot?.contains(t))return}this.previewedValue=0,this.setLabelForValue(this.value)},this.onClick=e=>{let t=e.currentTarget,n=Number(t.value);this.value=n===this.value?0:n,this.hasInteracted=!0,this._syncFormValue(String(this.value)),this.dispatchEvent(new c({name:this.name,value:String(this.value),checked:this.value>0,sourceEvent:e}))}}static{this.styles=[o,s]}#e;get editMode(){return this.#e}set editMode(e){this.#e=e}#t;get labels(){return this.#t}set labels(e){this.#t=e}#n;get value(){return this.#n}set value(e){this.#n=e}#r;get length(){return this.#r}set length(e){this.#r=e}connectedCallback(){super.connectedCallback(),this._defaultFormValue=String(this.value),this._syncFormValue(this._defaultFormValue)}formResetCallback(){this.value=Number(this._defaultFormValue),super.formResetCallback()}formStateRestoreCallback(e,t){this.value=Number(e),this._syncFormValue(e)}willUpdate(e){if((e.has(`value`)||e.has(`labels`))&&!this.previewedValue){let e=this.value;this.currentLabel=e?this.labels?.[e-1]??``:``}}setLabelForValue(e){let t=typeof e==`string`?parseInt(e,10):e;this.currentLabel=t?this.labels?.[t-1]??``:``,this.requestUpdate()}getRatingStyle(){let e=this.length,t=e>0?this.value/e*100:0,n=Array.from({length:e},(e,t)=>this.getIcon?.(t+1)??`var(--_icon)`),r=Array.from({length:e},(e,t)=>t===0?`0 0`:`calc(${t} * calc(var(--icon-size) + var(--spacing))) 0`);return[`width: calc(${e} * var(--icon-size) + ${e-1} * var(--spacing))`,`--_fill: ${t}%`,`mask-image: ${n.join(`, `)}`,`mask-position: ${r.join(`, `)}`].join(`; `)}render(){if(!this.editMode)return r`<div
|
|
2
2
|
class="rating"
|
|
3
3
|
style=${this.getRatingStyle()}
|
|
4
4
|
></div>`;let e=this.previewedValue||this.value;return r`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rating.js","names":["unsafeCSS","rawStyles","hostStyles","nothing","_decorate","property","r","n","__decorate","b","A","host_styles_default","styles","RatingChangeEvent","detail","Rating","LuxenFormAssociatedElement","_args","#_editMode_accessor_storage","#_labels_accessor_storage","#_value_accessor_storage","#_length_accessor_storage","value","event","related","target","clickedValue","state","changed","v","intValue","max","fillPct","icons","i","positions","activeCount","icon"],"sources":["../../../src/html/elements/rating/rating.css?inline","../../../src/html/elements/rating/rating.ts"],"sourcesContent":[":host {\n --icon-size: 20px;\n --active-color: gold;\n --inactive-color: #ddd;\n --spacing: 0px;\n --_icon: var(\n --icon,\n url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='2 2 20 19.02'><path d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/></svg>\")\n );\n\n display: inline-flex;\n align-items: center;\n}\n\n/* — Read-only mode — */\n\n.rating {\n height: var(--icon-size);\n background: linear-gradient(\n to right,\n var(--active-color) var(--_fill, 0%),\n var(--inactive-color) var(--_fill, 0%)\n );\n mask-size: var(--icon-size) var(--icon-size);\n mask-repeat: no-repeat;\n}\n\n/* — Edit mode — */\n\n.rating-edit {\n display: inline-flex;\n gap: var(--spacing);\n}\n\n.icon-wrapper {\n cursor: pointer;\n}\n\n.icon-wrapper input {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n\n.icon {\n display: block;\n width: var(--icon-size);\n height: var(--icon-size);\n mask-image: var(--_icon);\n mask-size: contain;\n mask-repeat: no-repeat;\n background: var(--inactive-color);\n transition: scale 0.2s ease;\n pointer-events: none;\n}\n\n.icon.active {\n background: var(--active-color);\n}\n\n.icon-wrapper:hover .icon {\n scale: 1.2;\n}\n\n.icon-wrapper:has(input:focus-visible) .icon {\n outline: 2px solid var(--active-color);\n outline-offset: 2px;\n border-radius: 2px;\n}\n\n:host([edit-mode]) .wrapper:focus-within {\n outline: 2px solid var(--active-color);\n outline-offset: 2px;\n border-radius: 2px;\n}\n\n/* — Disabled — */\n\n:host([disabled]) {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* — Label — */\n\n.wrapper {\n display: flex;\n align-items: center;\n white-space: nowrap;\n}\n\n.rating-label {\n margin-inline-start: 8px;\n flex: 1;\n font-size: 1rem;\n line-height: 1;\n}\n","import { html, nothing, unsafeCSS } from 'lit';\nimport type { PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { LuxenFormAssociatedElement } from '../../shared/luxen-form-associated-element.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './rating.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/** Fired when the rating value changes in edit mode. Bubbles; not composed. */\nexport class RatingChangeEvent extends Event {\n readonly name: string | undefined;\n readonly value: string;\n readonly checked: boolean;\n readonly sourceEvent: Event;\n constructor(detail: {\n name: string | undefined;\n value: string;\n checked: boolean;\n sourceEvent: Event;\n }) {\n super('change', { bubbles: true, composed: false, cancelable: false });\n this.name = detail.name;\n this.value = detail.value;\n this.checked = detail.checked;\n this.sourceEvent = detail.sourceEvent;\n }\n}\n\ninterface RatingEventMap {\n change: RatingChangeEvent;\n}\n\n/**\n * A star rating component using CSS mask-image.\n *\n * @summary Displays a star rating, optionally interactive.\n *\n * @csspart label - The label element shown in edit mode.\n *\n * @cssproperty --icon-size - The size of each icon. Defaults to `20px`.\n * @cssproperty --active-color - The fill color for rated icons. Defaults to `gold`.\n * @cssproperty --inactive-color - The fill color for empty icons. Defaults to `#ddd`.\n * @cssproperty --spacing - The spacing between icons. Defaults to `0px`.\n * @cssproperty --icon - Custom SVG shape as a `url()`. Defaults to a 5-pointed star.\n *\n * @event change - Emitted when the rating value changes in edit mode. Bubbles. Properties: `name: string`, `value: string`, `checked: boolean`, `sourceEvent: Event`.\n *\n * @customElement l-rating\n */\n// oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- typed addEventListener overloads merged below; no uninitialized properties.\nexport class Rating extends LuxenFormAssociatedElement {\n static override styles = [hostStyles, styles];\n\n private currentLabel = '';\n private previewedValue = 0;\n\n @property({ type: Boolean, reflect: true, attribute: 'edit-mode' })\n accessor editMode = false;\n\n @property({\n type: Array,\n reflect: true,\n converter: {\n fromAttribute: (value: string) => value.split('|'),\n toAttribute: (value: string[]) => (value.length ? value.join('|') : null),\n },\n })\n accessor labels: string[] = [];\n\n @property({ type: Number, reflect: true })\n accessor value = 0;\n\n @property({ type: Number, reflect: true })\n accessor length = 5;\n\n /** Optional callback returning a CSS `url()` string for a given position (1-based). */\n getIcon?: (value: number) => string;\n\n override connectedCallback() {\n super.connectedCallback();\n this._defaultFormValue = String(this.value);\n this._syncFormValue(this._defaultFormValue);\n }\n\n override formResetCallback() {\n this.value = Number(this._defaultFormValue);\n super.formResetCallback();\n }\n\n override formStateRestoreCallback(state: string, _mode: 'restore' | 'autocomplete') {\n this.value = Number(state);\n this._syncFormValue(state);\n }\n\n override willUpdate(changed: PropertyValues<this>) {\n // Derive the label inside the update cycle (Lit-sanctioned) instead of\n // requestUpdate()-ing from firstUpdated — see PRs #39/#45 for the pattern.\n // Only sync from `value` when not previewing, so hover/focus previews win.\n if ((changed.has('value') || changed.has('labels')) && !this.previewedValue) {\n const v = this.value;\n this.currentLabel = v ? (this.labels?.[v - 1] ?? '') : '';\n }\n }\n\n private setLabelForValue(value: number | string) {\n const intValue = typeof value === 'string' ? parseInt(value, 10) : value;\n this.currentLabel = intValue ? (this.labels?.[intValue - 1] ?? '') : '';\n this.requestUpdate();\n }\n\n private getRatingStyle() {\n const max = this.length;\n const fillPct = max > 0 ? (this.value / max) * 100 : 0;\n const step = 'calc(var(--icon-size) + var(--spacing))';\n\n const icons = Array.from({ length: max }, (_, i) => this.getIcon?.(i + 1) ?? 'var(--_icon)');\n const positions = Array.from({ length: max }, (_, i) =>\n i === 0 ? '0 0' : `calc(${i} * ${step}) 0`,\n );\n\n return [\n `width: calc(${max} * var(--icon-size) + ${max - 1} * var(--spacing))`,\n `--_fill: ${fillPct}%`,\n `mask-image: ${icons.join(', ')}`,\n `mask-position: ${positions.join(', ')}`,\n ].join('; ');\n }\n\n override render() {\n if (!this.editMode) {\n return html`<div\n class=\"rating\"\n style=${this.getRatingStyle()}\n ></div>`;\n }\n\n const activeCount = this.previewedValue || this.value;\n\n return html`\n <div\n class=\"wrapper\"\n @focusout=${this.clearPreview}\n >\n <div class=\"rating-edit\">\n ${Array.from({ length: this.length }, (_, i) => {\n const v = i + 1;\n const icon = this.getIcon?.(v);\n return html`\n <label\n class=\"icon-wrapper\"\n @pointerover=${() => this.previewValue(v)}\n @pointerout=${this.clearPreview}\n >\n <input\n type=\"radio\"\n name=${this.name ?? nothing}\n value=\"${v}\"\n aria-label=\"${this.labels?.[i] ?? `${v} ${v === 1 ? 'star' : 'stars'}`}\"\n ?checked=\"${this.value === v}\"\n ?disabled=\"${this.disabled}\"\n @click=${this.onClick}\n @focusin=${() => this.previewValue(v)}\n />\n <span\n class=\"icon ${v <= activeCount ? 'active' : ''}\"\n style=${icon ? `mask-image: ${icon}` : nothing}\n ></span>\n </label>\n `;\n })}\n </div>\n ${\n this.labels?.length\n ? html`<div\n class=\"rating-label\"\n part=\"label\"\n >\n ${this.currentLabel}\n </div>`\n : nothing\n }\n </div>\n `;\n }\n\n private previewValue = (value: number) => {\n this.previewedValue = value;\n this.setLabelForValue(value);\n };\n\n private clearPreview = (event?: FocusEvent) => {\n if (event) {\n const related = event.relatedTarget as Node | null;\n if (related && this.shadowRoot?.contains(related)) return;\n }\n this.previewedValue = 0;\n this.setLabelForValue(this.value);\n };\n\n private onClick = (event: Event) => {\n const target = event.currentTarget as HTMLInputElement;\n const clickedValue = Number(target.value);\n this.value = clickedValue === this.value ? 0 : clickedValue;\n this.hasInteracted = true;\n this._syncFormValue(String(this.value));\n\n this.dispatchEvent(\n new RatingChangeEvent({\n name: this.name,\n value: String(this.value),\n checked: this.value > 0,\n sourceEvent: event,\n }),\n );\n };\n}\n\n// Types `addEventListener('change', …)` as `RatingChangeEvent` on this element\n// (the global event map can't be augmented for the colliding name `change`).\n// See the Tabs interface in tabs.ts for the full rationale and the gotchas.\nexport interface Rating {\n addEventListener<K extends keyof RatingEventMap>(\n type: K,\n listener: (this: Rating, ev: RatingEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener<K extends keyof RatingEventMap>(\n type: K,\n listener: (this: Rating, ev: RatingEventMap[K]) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n}\n"],"mappings":"A,6RCOA,IAAMY,EAASZ,EAAUC,kmDAAS,EAGrBY,EAAb,cAAuC,KAAM,CAK3C,YAAY,EAKT,CACD,MAAM,SAAU,CAAE,QAAS,GAAM,SAAU,GAAO,WAAY,EAAM,CAAC,EACrE,KAAK,KAAOC,EAAO,KACnB,KAAK,MAAQA,EAAO,MACpB,KAAK,QAAUA,EAAO,QACtB,KAAK,YAAcA,EAAO,WAC5B,CACF,EAwBaC,EAAb,cAA4BC,CAA2B,C,8BAG9B,KAAA,aAAA,GACE,KAAA,eAAA,EAGL,KAAAE,GAAA,GAUQ,KAAAC,GAAA,CAAC,EAGZ,KAAAC,GAAA,EAGC,KAAAC,GAAA,EAgHM,KAAA,aAAA,GAAkB,CACxC,KAAK,eAAiBC,EACtB,KAAK,iBAAiBA,CAAK,CAC7B,EAEwB,KAAA,aAAA,GAAuB,CAC7C,GAAIC,EAAO,CACT,IAAMC,EAAUD,EAAM,cACtB,GAAIC,GAAW,KAAK,YAAY,SAASA,CAAO,EAAG,MACrD,CACA,KAAK,eAAiB,EACtB,KAAK,iBAAiB,KAAK,KAAK,CAClC,EAEmB,KAAA,QAAA,GAAiB,CAClC,IAAMC,EAASF,EAAM,cACfG,EAAe,OAAOD,EAAO,KAAK,EACxC,KAAK,MAAQC,IAAiB,KAAK,MAAQ,EAAIA,EAC/C,KAAK,cAAgB,GACrB,KAAK,eAAe,OAAO,KAAK,KAAK,CAAC,EAEtC,KAAK,cACH,IAAIb,EAAkB,CACpB,KAAM,KAAK,KACX,MAAO,OAAO,KAAK,KAAK,EACxB,QAAS,KAAK,MAAQ,EACtB,YAAaU,CACf,CAAC,CACH,CACF,C,QAnKyB,KAAA,OAAA,CAACrB,EAAYU,CAAM,C,IAMnC,IAAA,UAAA,C,4CAUA,IAAA,QAAA,C,0CAGA,IAAA,OAAA,C,yCAGA,IAAA,QAAA,C,uCAKT,mBAA6B,CAC3B,MAAM,kBAAkB,EACxB,KAAK,kBAAoB,OAAO,KAAK,KAAK,EAC1C,KAAK,eAAe,KAAK,iBAAiB,CAC5C,CAEA,mBAA6B,CAC3B,KAAK,MAAQ,OAAO,KAAK,iBAAiB,EAC1C,MAAM,kBAAkB,CAC1B,CAEA,yBAAkC,EAAe,EAAmC,CAClF,KAAK,MAAQ,OAAOe,CAAK,EACzB,KAAK,eAAeA,CAAK,CAC3B,CAEA,WAAoB,EAA+B,CAIjD,IAAKC,EAAQ,IAAI,OAAO,GAAKA,EAAQ,IAAI,QAAQ,IAAM,CAAC,KAAK,eAAgB,CAC3E,IAAMC,EAAI,KAAK,MACf,KAAK,aAAeA,EAAK,KAAK,SAASA,EAAI,IAAM,GAAM,EACzD,CACF,CAEA,iBAAyB,EAAwB,CAC/C,IAAMC,EAAW,OAAOR,GAAU,SAAW,SAASA,EAAO,EAAE,EAAIA,EACnE,KAAK,aAAeQ,EAAY,KAAK,SAASA,EAAW,IAAM,GAAM,GACrE,KAAK,cAAc,CACrB,CAEA,gBAAyB,CACvB,IAAMC,EAAM,KAAK,OACXC,EAAUD,EAAM,EAAK,KAAK,MAAQA,EAAO,IAAM,EAG/CE,EAAQ,MAAM,KAAK,CAAE,OAAQF,CAAI,GAAI,EAAG,IAAM,KAAK,UAAUG,EAAI,CAAC,GAAK,cAAc,EACrFC,EAAY,MAAM,KAAK,CAAE,OAAQJ,CAAI,GAAI,EAAG,IAChDG,IAAM,EAAI,MAAQ,QAAQA,EAAE,8CAC9B,EAEA,MAAO,CACL,eAAeH,EAAI,wBAAwBA,EAAM,EAAE,oBACnD,YAAYC,EAAQ,GACpB,eAAeC,EAAM,KAAK,IAAI,IAC9B,kBAAkBE,EAAU,KAAK,IAAI,GACvC,CAAC,CAAC,KAAK,IAAI,CACb,CAEA,QAAkB,CAChB,GAAI,CAAC,KAAK,SACR,MAAO,EAAI;;gBAED,KAAK,eAAe,EAAE;eAIlC,IAAMC,EAAc,KAAK,gBAAkB,KAAK,MAEhD,MAAO,EAAI;;;oBAGK,KAAK,aAAa;;;YAG1B,MAAM,KAAK,CAAE,OAAQ,KAAK,MAAO,GAAI,EAAG,IAAM,CAC9C,IAAMP,EAAIK,EAAI,EACRG,EAAO,KAAK,UAAUR,CAAC,EAC7B,MAAO,EAAI;;;mCAGc,KAAK,aAAaA,CAAC,EAAE;8BAC5B,KAAK,aAAa;;;;yBAIvB,KAAK,MAAQ1B,EAAQ;2BACnB0B,EAAE;gCACG,KAAK,SAASK,IAAM,GAAGL,EAAE,GAAGA,IAAM,EAAI,OAAS,UAAU;8BAC3D,KAAK,QAAUA,EAAE;+BAChB,KAAK,SAAS;2BAClB,KAAK,QAAQ;iCACL,KAAK,aAAaA,CAAC,EAAE;;;gCAGxBA,GAAKO,EAAc,SAAW,GAAG;0BACvCC,EAAO,eAAeA,IAASlC,EAAQ;;;aAIvD,CAAC,EAAE;;UAGH,KAAK,QAAQ,OACT,CAAI;;;;kBAIA,KAAK,aAAa;sBAEtBA,EACL;;KAGP,CAgCF,EA/JGC,EAAA,CAAAC,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,UAAW,WAAY,CAAC,CAAA,EAAAU,EAAA,UAAA,WAAA,IAAA,EAGjEX,EAAA,CAAAC,EAAS,CACR,KAAM,MACN,QAAS,GACT,UAAW,CACT,cAAgB,GAAkBiB,EAAM,MAAM,GAAG,EACjD,YAAc,GAAqBA,EAAM,OAASA,EAAM,KAAK,GAAG,EAAI,IACtE,CACF,CAAC,CAAA,EAAAP,EAAA,UAAA,SAAA,IAAA,EAGAX,EAAA,CAAAC,EAAS,CAAE,KAAM,OAAQ,QAAS,EAAK,CAAC,CAAA,EAAAU,EAAA,UAAA,QAAA,IAAA,EAGxCX,EAAA,CAAAC,EAAS,CAAE,KAAM,OAAQ,QAAS,EAAK,CAAC,CAAA,EAAAU,EAAA,UAAA,SAAA,IAAA,E"}
|
|
1
|
+
{"version":3,"file":"rating.js","names":["unsafeCSS","rawStyles","hostStyles","nothing","_decorate","property","r","n","__decorate","b","A","host_styles_default","styles","RatingChangeEvent","detail","Rating","LuxenFormAssociatedElement","_args","#_editMode_accessor_storage","#_labels_accessor_storage","#_value_accessor_storage","#_length_accessor_storage","value","event","related","target","clickedValue","state","changed","v","intValue","max","fillPct","icons","i","positions","activeCount","icon"],"sources":["../../../src/html/elements/rating/rating.css?inline","../../../src/html/elements/rating/rating.ts"],"sourcesContent":[":host {\n --icon-size: 20px;\n --active-color: gold;\n --inactive-color: #ddd;\n --spacing: 0px;\n --_icon: var(\n --icon,\n url(\"data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='2 2 20 19.02'><path d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/></svg>\")\n );\n\n display: inline-flex;\n align-items: center;\n}\n\n/* — Read-only mode — */\n\n.rating {\n height: var(--icon-size);\n background: linear-gradient(\n to right,\n var(--active-color) var(--_fill, 0%),\n var(--inactive-color) var(--_fill, 0%)\n );\n mask-size: var(--icon-size) var(--icon-size);\n mask-repeat: no-repeat;\n}\n\n/* — Edit mode — */\n\n.rating-edit {\n display: inline-flex;\n gap: var(--spacing);\n}\n\n.icon-wrapper {\n display: block;\n border-radius: var(--l-radius-sm);\n cursor: pointer;\n}\n\n.icon-wrapper input {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n\n.icon {\n display: block;\n width: var(--icon-size);\n height: var(--icon-size);\n mask-image: var(--_icon);\n mask-size: contain;\n mask-repeat: no-repeat;\n background: var(--inactive-color);\n transition: scale 0.2s ease;\n pointer-events: none;\n}\n\n.icon.active {\n background: var(--active-color);\n}\n\n.icon-wrapper:hover .icon {\n scale: 1.2;\n}\n\n/* One ring, around the focused star — the radio the keyboard is on. On the\n label, not the star: the star is drawn by a mask, which would clip its own\n outline away. The global ring color, not --active-color: gold is ~1.6:1 on\n white, under the 3:1 a focus indicator needs (WCAG 1.4.11). */\n.icon-wrapper:has(input:focus-visible) {\n outline: var(--l-focus-ring-width) solid var(--l-focus-ring-color);\n outline-offset: var(--l-focus-ring-offset);\n}\n\n/* — Disabled — */\n\n:host([disabled]) {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* — Label — */\n\n.wrapper {\n display: flex;\n align-items: center;\n white-space: nowrap;\n}\n\n.rating-label {\n margin-inline-start: 8px;\n flex: 1;\n font-size: 1rem;\n line-height: 1;\n}\n","import { html, nothing, unsafeCSS } from 'lit';\nimport type { PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { LuxenFormAssociatedElement } from '../../shared/luxen-form-associated-element.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './rating.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/** Fired when the rating value changes in edit mode. Bubbles; not composed. */\nexport class RatingChangeEvent extends Event {\n readonly name: string | undefined;\n readonly value: string;\n readonly checked: boolean;\n readonly sourceEvent: Event;\n constructor(detail: {\n name: string | undefined;\n value: string;\n checked: boolean;\n sourceEvent: Event;\n }) {\n super('change', { bubbles: true, composed: false, cancelable: false });\n this.name = detail.name;\n this.value = detail.value;\n this.checked = detail.checked;\n this.sourceEvent = detail.sourceEvent;\n }\n}\n\ninterface RatingEventMap {\n change: RatingChangeEvent;\n}\n\n/**\n * A star rating component using CSS mask-image.\n *\n * @summary Displays a star rating, optionally interactive.\n *\n * @csspart label - The label element shown in edit mode.\n *\n * @cssproperty --icon-size - The size of each icon. Defaults to `20px`.\n * @cssproperty --active-color - The fill color for rated icons. Defaults to `gold`.\n * @cssproperty --inactive-color - The fill color for empty icons. Defaults to `#ddd`.\n * @cssproperty --spacing - The spacing between icons. Defaults to `0px`.\n * @cssproperty --icon - Custom SVG shape as a `url()`. Defaults to a 5-pointed star.\n *\n * @event change - Emitted when the rating value changes in edit mode. Bubbles. Properties: `name: string`, `value: string`, `checked: boolean`, `sourceEvent: Event`.\n *\n * @customElement l-rating\n */\n// oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- typed addEventListener overloads merged below; no uninitialized properties.\nexport class Rating extends LuxenFormAssociatedElement {\n static override styles = [hostStyles, styles];\n\n private currentLabel = '';\n private previewedValue = 0;\n\n @property({ type: Boolean, reflect: true, attribute: 'edit-mode' })\n accessor editMode = false;\n\n @property({\n type: Array,\n reflect: true,\n converter: {\n fromAttribute: (value: string) => value.split('|'),\n toAttribute: (value: string[]) => (value.length ? value.join('|') : null),\n },\n })\n accessor labels: string[] = [];\n\n @property({ type: Number, reflect: true })\n accessor value = 0;\n\n @property({ type: Number, reflect: true })\n accessor length = 5;\n\n /** Optional callback returning a CSS `url()` string for a given position (1-based). */\n getIcon?: (value: number) => string;\n\n override connectedCallback() {\n super.connectedCallback();\n this._defaultFormValue = String(this.value);\n this._syncFormValue(this._defaultFormValue);\n }\n\n override formResetCallback() {\n this.value = Number(this._defaultFormValue);\n super.formResetCallback();\n }\n\n override formStateRestoreCallback(state: string, _mode: 'restore' | 'autocomplete') {\n this.value = Number(state);\n this._syncFormValue(state);\n }\n\n override willUpdate(changed: PropertyValues<this>) {\n // Derive the label inside the update cycle (Lit-sanctioned) instead of\n // requestUpdate()-ing from firstUpdated — see PRs #39/#45 for the pattern.\n // Only sync from `value` when not previewing, so hover/focus previews win.\n if ((changed.has('value') || changed.has('labels')) && !this.previewedValue) {\n const v = this.value;\n this.currentLabel = v ? (this.labels?.[v - 1] ?? '') : '';\n }\n }\n\n private setLabelForValue(value: number | string) {\n const intValue = typeof value === 'string' ? parseInt(value, 10) : value;\n this.currentLabel = intValue ? (this.labels?.[intValue - 1] ?? '') : '';\n this.requestUpdate();\n }\n\n private getRatingStyle() {\n const max = this.length;\n const fillPct = max > 0 ? (this.value / max) * 100 : 0;\n const step = 'calc(var(--icon-size) + var(--spacing))';\n\n const icons = Array.from({ length: max }, (_, i) => this.getIcon?.(i + 1) ?? 'var(--_icon)');\n const positions = Array.from({ length: max }, (_, i) =>\n i === 0 ? '0 0' : `calc(${i} * ${step}) 0`,\n );\n\n return [\n `width: calc(${max} * var(--icon-size) + ${max - 1} * var(--spacing))`,\n `--_fill: ${fillPct}%`,\n `mask-image: ${icons.join(', ')}`,\n `mask-position: ${positions.join(', ')}`,\n ].join('; ');\n }\n\n override render() {\n if (!this.editMode) {\n return html`<div\n class=\"rating\"\n style=${this.getRatingStyle()}\n ></div>`;\n }\n\n const activeCount = this.previewedValue || this.value;\n\n return html`\n <div\n class=\"wrapper\"\n @focusout=${this.clearPreview}\n >\n <div class=\"rating-edit\">\n ${Array.from({ length: this.length }, (_, i) => {\n const v = i + 1;\n const icon = this.getIcon?.(v);\n return html`\n <label\n class=\"icon-wrapper\"\n @pointerover=${() => this.previewValue(v)}\n @pointerout=${this.clearPreview}\n >\n <input\n type=\"radio\"\n name=${this.name ?? nothing}\n value=\"${v}\"\n aria-label=\"${this.labels?.[i] ?? `${v} ${v === 1 ? 'star' : 'stars'}`}\"\n ?checked=\"${this.value === v}\"\n ?disabled=\"${this.disabled}\"\n @click=${this.onClick}\n @focusin=${() => this.previewValue(v)}\n />\n <span\n class=\"icon ${v <= activeCount ? 'active' : ''}\"\n style=${icon ? `mask-image: ${icon}` : nothing}\n ></span>\n </label>\n `;\n })}\n </div>\n ${\n this.labels?.length\n ? html`<div\n class=\"rating-label\"\n part=\"label\"\n >\n ${this.currentLabel}\n </div>`\n : nothing\n }\n </div>\n `;\n }\n\n private previewValue = (value: number) => {\n this.previewedValue = value;\n this.setLabelForValue(value);\n };\n\n private clearPreview = (event?: FocusEvent) => {\n if (event) {\n const related = event.relatedTarget as Node | null;\n if (related && this.shadowRoot?.contains(related)) return;\n }\n this.previewedValue = 0;\n this.setLabelForValue(this.value);\n };\n\n private onClick = (event: Event) => {\n const target = event.currentTarget as HTMLInputElement;\n const clickedValue = Number(target.value);\n this.value = clickedValue === this.value ? 0 : clickedValue;\n this.hasInteracted = true;\n this._syncFormValue(String(this.value));\n\n this.dispatchEvent(\n new RatingChangeEvent({\n name: this.name,\n value: String(this.value),\n checked: this.value > 0,\n sourceEvent: event,\n }),\n );\n };\n}\n\n// Types `addEventListener('change', …)` as `RatingChangeEvent` on this element\n// (the global event map can't be augmented for the colliding name `change`).\n// See the Tabs interface in tabs.ts for the full rationale and the gotchas.\nexport interface Rating {\n addEventListener<K extends keyof RatingEventMap>(\n type: K,\n listener: (this: Rating, ev: RatingEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener<K extends keyof RatingEventMap>(\n type: K,\n listener: (this: Rating, ev: RatingEventMap[K]) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/html/elements/select/select.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/html/elements/select/select.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/static-html.js";import{n as r,r as i,t as a}from"../../chunks/decorate.js";import{a as o,t as s}from"../../chunks/lit-html.js";import{t as c}from"../../chunks/unsafe-html.js";import{LuxenFormAssociatedElement as l}from"../../shared/luxen-form-associated-element.js";import{PopoverController as u}from"../../shared/controllers/popover.js";import{ListboxNavController as d}from"../../shared/controllers/listbox-nav.js";import{DatalistObserverController as f}from"../../shared/controllers/datalist-observer.js";import{LocalizeController as p}from"../../shared/localize.js";import{RichHighlighter as m,highlightText as h,normalize as g}from"../../shared/highlight.js";import{cls as _,tagName as v,uniqueId as y}from"../../registry.js";import{adoptRichContentStyles as b,richOptionLabel as x}from"../../shared/rich-option.js";import S from"../../shared/styles/host.styles.js";import C from"../../shared/styles/visually-hidden.styles.js";import w from"../../shared/styles/select-item-suffix.styles.js";import T from"../../shared/styles/picker-core.styles.js";import E from"../../shared/styles/select-item.styles.js";var D=e(`.trigger{inline-size:100%;min-block-size:var(--height);color:var(--l-form-control-value-color);font:inherit;text-align:start;cursor:pointer;gap:.5rem;padding-block:.25rem}:host([multiple]) .trigger{padding-inline-start:.375rem}.
|
|
1
|
+
import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/static-html.js";import{n as r,r as i,t as a}from"../../chunks/decorate.js";import{a as o,t as s}from"../../chunks/lit-html.js";import{t as c}from"../../chunks/unsafe-html.js";import{LuxenFormAssociatedElement as l}from"../../shared/luxen-form-associated-element.js";import{PopoverController as u}from"../../shared/controllers/popover.js";import{ListboxNavController as d}from"../../shared/controllers/listbox-nav.js";import{DatalistObserverController as f}from"../../shared/controllers/datalist-observer.js";import{LocalizeController as p}from"../../shared/localize.js";import{RichHighlighter as m,highlightText as h,normalize as g}from"../../shared/highlight.js";import{cls as _,tagName as v,uniqueId as y}from"../../registry.js";import{adoptRichContentStyles as b,richOptionLabel as x}from"../../shared/rich-option.js";import S from"../../shared/styles/host.styles.js";import C from"../../shared/styles/visually-hidden.styles.js";import w from"../../shared/styles/select-item-suffix.styles.js";import T from"../../shared/styles/picker-core.styles.js";import E from"../../shared/styles/select-item.styles.js";var D=e(`.trigger{inline-size:100%;min-block-size:var(--height);color:var(--l-form-control-value-color);font:inherit;text-align:start;cursor:pointer;gap:.5rem;padding-block:.25rem}:host([multiple]) .trigger{padding-inline-start:.375rem}.value{flex-wrap:wrap;flex:1;align-items:center;gap:.25rem;min-inline-size:0;display:flex;overflow:hidden}.value-text{text-overflow:ellipsis;white-space:nowrap;min-inline-size:0;overflow:hidden}[part=tag]{--height:initial;--border-radius:initial}.placeholder{color:var(--l-form-control-placeholder-color)}.clear-button{margin-block:auto;position:absolute;inset-block:0;inset-inline-end:calc(var(--l-form-control-border-width) + var(--_action-size))}.base:has(>.clear-button) .chevron{margin-inline-start:var(--_action-size)}.value .l-select-item-title{font-weight:inherit}.value .l-select-item-description,.value .l-select-item-suffix{display:none}.search-row{border-block-end:1px solid var(--l-color-border-overlay);padding:.375rem}.search{inline-size:100%;block-size:var(--l-size-control-sm);border:var(--l-form-control-border-width) solid var(--l-form-control-border-color);border-radius:calc(var(--border-radius) - 2px);background-color:var(--l-form-control-background-color);color:var(--l-form-control-value-color);font:inherit;padding-inline:.5rem}.search::placeholder{color:var(--l-form-control-placeholder-color)}.option[data-active]{background-color:var(--l-color-bg-state-hover)}.listbox[data-nav=keyboard] .option[data-active]{outline:var(--l-focus-ring-width) solid var(--l-focus-ring-color);outline-offset:calc(var(--l-focus-ring-width) * -1)}.option[data-current]:after{content:"";inline-size:1rem;block-size:calc(var(--l-popover-font-size) * var(--l-popover-line-height));-webkit-mask:var(--_check-icon) center / 1rem no-repeat;mask:var(--_check-icon) center / 1rem no-repeat;background-color:currentColor;position:absolute;inset-block-start:var(--_row-padding-block);inset-inline-start:.5rem}.l-select-item-media{align-items:center;font-size:1.25em;display:inline-flex}`),O=(e,t)=>{if(!t)return!0;let n=g(e.label);return g(t).split(/\s+/).filter(Boolean).every(e=>n.includes(e))},k=class extends Event{constructor(e){super(`change`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},A=class extends Event{constructor(e){super(`input`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},j=class extends l{constructor(...e){super(...e),this._localize=new p(this),this._listId=y(`select-list`),this._richHighlighter=new m,this._floating=new u(this,{getTriggerElement:()=>this._triggerEl,getFloatingElement:()=>this._panelEl,getArrowElement:()=>null}),this._nav=new d(this,{listboxId:this._listId,getCount:()=>this._filtered.length,isDisabled:e=>this._filtered[e]?.disabled??!1,isOpen:()=>this._open,open:()=>this.show(),getOptionElements:()=>this.shadowRoot?.querySelectorAll(`.option`)}),this._options=new f(this,()=>this._syncItems()),this.#e=``,this.#t=``,this.#n=`md`,this.#r=!1,this.#i=!1,this.#a=`bottom-start`,this.#o=!1,this.filter=O,this.#s=[],this.#c=!1,this.#l=``,this.#u=[],this._defaultValues=[],this._onDocumentPointerDown=e=>{e.composedPath().includes(this)||(this.hasInteracted=!0,this._updateValidity(),this.hide({focusTrigger:!1}))},this._onTriggerKeyDown=e=>{this._open||(e.key===`ArrowDown`||e.key===`ArrowUp`||e.key===`Enter`||e.key===` `)&&(e.preventDefault(),this.show())},this._onPanelKeyDown=e=>{if(!this._nav.onKeyDown(e))switch(e.key){case`Enter`:{e.preventDefault();let t=this._filtered[this._nav.activeIndex];t&&this._select(t);break}case`Escape`:e.preventDefault(),this.hide();break;case`Tab`:this.hide({focusTrigger:!1})}},this._onSearchInput=e=>{this._query=e.target.value,this._nav.reset(),this.dispatchEvent(new A(this._query))}}static{this.styles=[S,C,w,E,T,D]}#e;get placeholder(){return this.#e}set placeholder(e){this.#e=e}#t;get label(){return this.#t}set label(e){this.#t=e}#n;get size(){return this.#n}set size(e){this.#n=e}#r;get searchable(){return this.#r}set searchable(e){this.#r=e}#i;get withClear(){return this.#i}set withClear(e){this.#i=e}#a;get placement(){return this.#a}set placement(e){this.#a=e}#o;get multiple(){return this.#o}set multiple(e){this.#o=e}#s;get _values(){return this.#s}set _values(e){this.#s=e}#c;get _open(){return this.#c}set _open(e){this.#c=e}#l;get _query(){return this.#l}set _query(e){this.#l=e}#u;get _items(){return this.#u}set _items(e){this.#u=e}get value(){return this.multiple?[...this._values]:this._values[0]??``}set value(e){this._values=Array.isArray(e)?[...e]:e?[e]:[]}get _triggerEl(){return this.shadowRoot?.querySelector(`.trigger`)??null}get _panelEl(){return this.shadowRoot?.querySelector(`.panel`)??null}get _searchEl(){return this.shadowRoot?.querySelector(`.search`)??null}get validationTarget(){return this._triggerEl??void 0}connectedCallback(){if(super.connectedCallback(),this._readItems(),this._values.length===0){let e=this.getAttribute(`value`);if(e)this._values=[e];else{let e=this._items.filter(e=>e.selected).map(e=>e.value);this._values=this.multiple?e:e.slice(0,1)}}this._defaultValues=[...this._values],this._syncForm()}updated(e){(e.has(`_values`)||e.has(`multiple`))&&(this._syncForm(),this._updateValidity())}formResetCallback(){this._values=[...this._defaultValues],this._query=``,this._nav.reset(),super.formResetCallback(),this._syncForm()}formStateRestoreCallback(e){this.value=e,this._syncForm()}_readItems(){let e=this.querySelector(`datalist`),t=e?Array.from(e.options):[];this._items=t.map(e=>{let t=e.childElementCount>0,n=x(e);return{value:e.value,label:n,disabled:e.disabled,selected:e.hasAttribute(`selected`),html:t?e.innerHTML:void 0}}),b(this.shadowRoot,this._items)}_syncItems(){let e=this._open?this._filtered[this._nav.activeIndex]:void 0;this._readItems(),this._open&&this._nav.setActive(e?this._filtered.findIndex(t=>t.value===e.value):-1)}_itemFor(e){return this._items.find(t=>t.value===e)}get _filtered(){return this._items.filter(e=>this.filter(e,this._query))}_syncForm(){if(this.multiple){let e=new FormData;for(let t of this._values)e.append(this.name,t);this._internals.setFormValue(e)}else this._internals.setFormValue(this._values[0]??``)}_updateValidity(){this.required&&this._values.length===0?this.setValidity({valueMissing:!0},this._localize.term(`selectOption`),this._triggerEl??void 0):this.setValidity({})}show(){this._open||this.disabled||(this._readItems(),this.dispatchEvent(new Event(`show`,{cancelable:!0}))&&(this._open=!0,this._query=``,this._values.length&&this._nav.setActive(this._filtered.findIndex(e=>e.value===this._values[0])),this.updateComplete.then(()=>{this._panelEl?.showPopover?.(),this._floating.startPositioning({placement:this.placement,distance:4,minWidth:`trigger`}),(this._searchEl??this._panelEl?.querySelector(`.listbox`))?.focus(),document.addEventListener(`pointerdown`,this._onDocumentPointerDown,!0)})))}hide({focusTrigger:e=!0}={}){if(!this._open||!this.dispatchEvent(new Event(`hide`,{cancelable:!0})))return;this._open=!1,this._query=``,this._nav.reset();let t=this._panelEl;t?.matches?.(`:popover-open`)&&t.hidePopover?.(),this._floating.stopPositioning(),document.removeEventListener(`pointerdown`,this._onDocumentPointerDown,!0),e&&this._triggerEl?.focus()}_select(e){e.disabled||(this.hasInteracted=!0,this.multiple?(this._values=this._values.includes(e.value)?this._values.filter(t=>t!==e.value):[...this._values,e.value],this.dispatchEvent(new k(this.value)),this._searchEl?.focus()):(this._values=[e.value],this.dispatchEvent(new k(this.value)),this.hide()))}_removeValue(e){this._values=this._values.filter(t=>t!==e),this.hasInteracted=!0,this.dispatchEvent(new k(this.value))}_clear(e){e?.stopPropagation(),this._values=[],this.hasInteracted=!0,this.dispatchEvent(new k(this.value)),this._triggerEl?.focus()}_renderSingleValue(){let e=this._itemFor(this._values[0]);return e?e.html?o`${c(e.html)}`:o`<span class="value-text">${e.label}</span>`:o`<span class="value-text placeholder">${this.placeholder}</span>`}_renderChips(){if(this._values.length===0)return o`<span class="value-text placeholder">${this.placeholder}</span>`;let e=t(v(`tag`));return this._values.map(t=>{let r=this._itemFor(t);return n`<${e}
|
|
2
2
|
size="sm"
|
|
3
3
|
removable
|
|
4
4
|
part="tag"
|
|
@@ -91,6 +91,7 @@ import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/s
|
|
|
91
91
|
aria-label=${this.label||this._localize.term(`suggestions`)}
|
|
92
92
|
aria-multiselectable=${this.multiple?`true`:s}
|
|
93
93
|
aria-activedescendant=${this.searchable?s:t??s}
|
|
94
|
+
data-nav=${this._nav.keyboard?`keyboard`:`pointer`}
|
|
94
95
|
@pointermove=${this._nav.onPointerMove}
|
|
95
96
|
@pointerleave=${this._nav.onPointerLeave}
|
|
96
97
|
>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","names":["unsafeCSS","rawStyles","hostStyles","visuallyHiddenStyles","suffixStyles","selectItemStyles","pickerCoreStyles","unsafeHTML","unsafeStatic","nothing","_decorate","property","state","r","s","u","r$1","n","__decorate","b","A","o","host_styles_default","visually_hidden_styles_default","select_item_suffix_styles_default","picker_core_styles_default","select_item_styles_default","styles","defaultFilter","query","label","normalize","item","kw","SelectChangeEvent","value","SelectInputEvent","Select","LuxenFormAssociatedElement","_args","LocalizeController","uniqueId","RichHighlighter","PopoverController","ListboxNavController","i","DatalistObserverController","#_placeholder_accessor_storage","#_label_accessor_storage","#_size_accessor_storage","#_searchable_accessor_storage","#_withClear_accessor_storage","#_placement_accessor_storage","#_multiple_accessor_storage","#__values_accessor_storage","#__open_accessor_storage","#__query_accessor_storage","#__items_accessor_storage","active","v","attr","selected","changed","state","list","opts","rich","richOptionLabel","adoptRichContentStyles","data","panel","focusTrigger","chip","tagName","inner","onClick","invalid","filtered","activeId","activeIndex","hasValue","status","highlightText","cls"],"sources":["../../../src/html/elements/select/select.css?inline","../../../src/html/elements/select/select.ts"],"sourcesContent":["/* Knobs, size scale, field frame, chevron, clear, listbox popover and the\n shared option bits come from shared/styles/picker-core.css; the option row\n and rich-option content from shared/styles/select-item.css (also used by the\n native `.l-select` picker). This file holds what is specific to l-select. */\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆃🆁🅸🅶🅶🅴🆁 (button, opens the listbox popover)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n*/\n\n.trigger {\n gap: 0.5rem;\n inline-size: 100%;\n min-block-size: var(--height);\n padding-block: 0.25rem;\n color: var(--l-form-control-value-color);\n font: inherit;\n text-align: start;\n cursor: pointer;\n}\n\n/* The form-control inline padding is tuned for text; before a chip row it reads\n as too much, so tighten the start edge in multiple mode (the chips bring their\n own spacing). */\n:host([multiple]) .trigger {\n padding-inline-start: 0.375rem;\n}\n\n.trigger:focus-visible {\n outline: none;\n}\n\n/* Selection display fills the trigger; the chevron (and overlaid clear) sit at the end. */\n.value {\n flex: 1;\n min-inline-size: 0;\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 0.25rem;\n overflow: hidden;\n}\n\n.value-text {\n min-inline-size: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* This element's public knobs and the chip's share two names — `--height` and\n `--border-radius` — and custom properties inherit straight through a shadow\n boundary. Left alone, every chip in the trigger renders at the *select's*\n height and corner rather than its own: a 36px chip with a 6px corner, when\n `size=\"sm\"` asked for a 24px pill. `initial` is the guaranteed-invalid value,\n so each `var(--x, …)` inside the chip falls back to its own default. Matched\n on the part, not on the tag name, so a renamed `elementPrefix` can't miss it.\n\n The fill used to collide too, back when the chip read `--background`; it now\n reads `--background-color`, which this element does not expose. */\n[part='tag'] {\n --height: initial;\n --border-radius: initial;\n}\n\n.placeholder {\n color: var(--l-form-control-placeholder-color);\n}\n\n/* The clear button is a SIBLING of the trigger (not a child — no nested buttons),\n * overlaid on the trigger's end, square against the chevron's square — which\n * sits flush against the border (picker-core.css). */\n.clear-button {\n position: absolute;\n inset-block: 0;\n inset-inline-end: calc(var(--l-form-control-border-width) + var(--_action-size));\n margin-block: auto;\n}\n\n/* Keep the value (text or chips) clear of the overlaid button. */\n.base:has(> .clear-button) .chevron {\n margin-inline-start: var(--_action-size);\n}\n\n/* Rich content in the trigger takes the row styles (select-item.css), then\n mirrors the native trigger: only the media and title, at the value's weight —\n the secondary description and the trailing suffix are dropped so the selected\n value stays compact and consistent across options. */\n.value .l-select-item-title {\n font-weight: inherit;\n}\n.value .l-select-item-description,\n.value .l-select-item-suffix {\n display: none;\n}\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🅿🅰🅽🅴🅻 (popover: search + listbox)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n*/\n\n.search-row {\n padding: 0.375rem;\n border-block-end: 1px solid var(--l-color-border-overlay);\n}\n\n.search {\n inline-size: 100%;\n block-size: var(--l-size-control-sm);\n padding-inline: 0.5rem;\n border: var(--l-form-control-border-width) solid var(--l-form-control-border-color);\n border-radius: calc(var(--border-radius) - 2px);\n background-color: var(--l-form-control-background-color);\n color: var(--l-form-control-value-color);\n font: inherit;\n}\n\n.search:focus-visible {\n outline: none;\n border-color: var(--l-focus-ring);\n}\n\n.search::placeholder {\n color: var(--l-form-control-placeholder-color);\n}\n\n/* Keyboard-active row (moves with Arrow keys) — same tint as hover. */\n.option[data-active] {\n background-color: var(--l-color-bg-state-hover);\n}\n\n/* Selected indicator in the reserved inline-start column, pinned to the first\n * line so a wrapping description never shifts it (matches the native\n * `::checkmark` in src/css/elements/select.css). */\n.option[data-current]::after {\n content: '';\n position: absolute;\n inset-inline-start: 0.5rem;\n inset-block-start: var(--_row-padding-block);\n inline-size: 1rem;\n block-size: calc(var(--l-popover-font-size) * var(--l-popover-line-height));\n background-color: currentColor;\n mask: var(--_check-icon) center / 1rem no-repeat;\n}\n\n/* Rich content, rows and trigger alike: the shared layout (select-item.css)\n plus what only this tier needs — media may be an emoji or icon rather than an\n image, so it is centred and sized by font. */\n.l-select-item-media {\n display: inline-flex;\n align-items: center;\n font-size: 1.25em;\n}\n","import { html, nothing, unsafeCSS } from 'lit';\nimport { html as staticHtml, unsafeStatic } from 'lit/static-html.js';\nimport { property, state } from 'lit/decorators.js';\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\nimport type { Placement } from '@floating-ui/dom';\nimport { LuxenFormAssociatedElement } from '../../shared/luxen-form-associated-element.js';\nimport { PopoverController } from '../../shared/controllers/popover.js';\nimport { ListboxNavController } from '../../shared/controllers/listbox-nav.js';\nimport { DatalistObserverController } from '../../shared/controllers/datalist-observer.js';\nimport { LocalizeController } from '../../shared/localize.js';\nimport { RichHighlighter, highlightText, normalize } from '../../shared/highlight.js';\nimport { cls, tagName, uniqueId } from '../../registry.js';\nimport { adoptRichContentStyles, richOptionLabel } from '../../shared/rich-option.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport visuallyHiddenStyles from '../../shared/styles/visually-hidden.styles.js';\nimport suffixStyles from '../../shared/styles/select-item-suffix.styles.js';\nimport pickerCoreStyles from '../../shared/styles/picker-core.styles.js';\nimport selectItemStyles from '../../shared/styles/select-item.styles.js';\nimport rawStyles from './select.css?inline';\n// Registers the chip element used to render selected values in multiple mode.\nimport '../tag/index.js';\n\nconst styles = unsafeCSS(rawStyles);\n\nexport type SelectSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\n/** A single option read from the `<datalist>`. */\nexport interface SelectItem {\n value: string;\n /** Plain text used for filtering and the trigger display. */\n label: string;\n disabled: boolean;\n /** Authored `selected` attribute — seeds the initial value. */\n selected: boolean;\n /** Rich inner markup (from a non-empty `<option>`), projected into the row. */\n html?: string;\n}\n\n/** Default filter: accent/case-insensitive, every space-separated keyword must match. */\nexport type SelectFilter = (item: SelectItem, query: string) => boolean;\n\nconst defaultFilter: SelectFilter = (item, query) => {\n if (!query) return true;\n const label = normalize(item.label);\n return normalize(query)\n .split(/\\s+/)\n .filter(Boolean)\n .every((kw) => label.includes(kw));\n};\n\n/** Fired when the selection changes. Bubbles; not composed. */\nexport class SelectChangeEvent extends Event {\n /** The selected value (single mode) or values (multiple mode). */\n readonly value: string | string[];\n constructor(value: string | string[]) {\n super('change', { bubbles: true, composed: false, cancelable: false });\n this.value = value;\n }\n}\n\n/** Fired as the user types in the search box. Bubbles; not composed. */\nexport class SelectInputEvent extends Event {\n /** The current query text. */\n readonly value: string;\n constructor(value: string) {\n super('input', { bubbles: true, composed: false, cancelable: false });\n this.value = value;\n }\n}\n\ninterface SelectEventMap {\n change: SelectChangeEvent;\n input: SelectInputEvent;\n}\n\n/**\n * A button-triggered, searchable select. A trigger shows the current selection,\n * opening a popover with a search box and a `role=\"listbox\"` of options authored\n * as a native `<datalist>` of `<option>` — the same authoring surface as\n * `l-combobox` and the native `.l-select`. Form-associated.\n *\n * @summary A searchable select with a button trigger and a popover listbox.\n *\n * @example\n * ```html\n * <l-select label=\"Country\" name=\"country\" placeholder=\"Select a country…\">\n * <datalist>\n * <option value=\"us\">United States</option>\n * <option value=\"fr\" selected>France</option>\n * </datalist>\n * </l-select>\n * ```\n *\n * @event change - Fired when the selection changes. Bubbles. Not cancelable. Properties: `value: string | string[]`.\n * @event input - Fired as the user types in the search box. Bubbles. Not cancelable. Properties: `value: string` (the query).\n * @event show - Fired before the listbox opens. Cancelable.\n * @event hide - Fired before the listbox closes. Cancelable.\n *\n * @csspart base - The host wrapper.\n * @csspart trigger - The button that opens the listbox.\n * @csspart value - The selection display inside the trigger.\n * @csspart chevron - The trigger chevron.\n * @csspart clear - The clear button.\n * @csspart panel - The floating popover panel.\n * @csspart search - The search input.\n * @csspart listbox - The options container.\n * @csspart option - Each option row.\n * @csspart empty - The \"no results\" message.\n *\n * @cssproperty [--height=var(--l-form-control-height)] - Control height. The clear button and the chevron\n * each take a square of this height (borders excluded), so their hit area and spacing follow it.\n * @cssproperty [--l-form-control-icon-size=1em] - Glyph size of the clear button and the chevron (global form-control\n * token; set it here or on any ancestor). Changes the glyph only — the hit area follows `--height`.\n * @cssproperty --chevron-icon - Chevron glyph as a `url()`. Masked, so its color comes from the control, not the image.\n * @cssproperty --clear-icon - Clear button glyph as a `url()`.\n * @cssproperty [--border-radius] - Trigger + panel radius.\n * @cssproperty [--background] - Panel background.\n *\n * @cssClass .l-select-item-media - Rich option: leading image or icon.\n * @cssClass .l-select-item-text - Rich option: column holding the title and the description.\n * @cssClass .l-select-item-title - Rich option: title, truncated with an ellipsis. Used as the label when the option has no `label`.\n * @cssClass .l-select-item-description - Rich option: secondary line, shown in the listbox only.\n * @cssClass .l-select-item-suffix - Rich option: trailing badge, count or status icon on the title's line. Kept out of the trigger, the chips and the search.\n *\n * @customElement l-select\n */\n// oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- typed addEventListener overloads merged below; no uninitialized properties.\nexport class Select extends LuxenFormAssociatedElement {\n // Rich option markup is copied into the shadow root, out of reach of the\n // global stylesheets: suffixStyles lays out the `.l-select-item-suffix` zone,\n // and `_readItems` adopts the styles of the light-DOM elements (l-badge) the\n // options actually contain. selectItemStyles (row + rich content, shared with\n // the native picker) loads before pickerCoreStyles so the shared disabled-row\n // rule wins over the row's `cursor: pointer`.\n static override styles = [\n hostStyles,\n visuallyHiddenStyles,\n suffixStyles,\n selectItemStyles,\n pickerCoreStyles,\n styles,\n ];\n\n private _localize = new LocalizeController(this);\n private readonly _listId = uniqueId('select-list');\n private readonly _richHighlighter = new RichHighlighter();\n\n private _floating = new PopoverController(this, {\n getTriggerElement: () => this._triggerEl,\n getFloatingElement: () => this._panelEl,\n getArrowElement: () => null,\n });\n\n private _nav = new ListboxNavController(this, {\n listboxId: this._listId,\n getCount: () => this._filtered.length,\n isDisabled: (i) => this._filtered[i]?.disabled ?? false,\n isOpen: () => this._open,\n open: () => this.show(),\n getOptionElements: () => this.shadowRoot?.querySelectorAll<HTMLElement>('.option'),\n });\n\n // The `<datalist>` is light DOM the consumer owns and rewrites in place;\n // re-read it so the closed trigger tracks the options it was given.\n private _options = new DatalistObserverController(this, () => this._syncItems());\n\n /** Placeholder shown in the trigger when nothing is selected. */\n @property()\n accessor placeholder = '';\n\n /** Accessible label for the trigger. */\n @property()\n accessor label = '';\n\n /** Control size. */\n @property({ reflect: true })\n accessor size: SelectSize = 'md';\n\n /** Show a filter box inside the popover (opt-in, for long lists). */\n @property({ type: Boolean, reflect: true })\n accessor searchable = false;\n\n /** Show a button to clear the value. */\n @property({ type: Boolean, reflect: true, attribute: 'with-clear' })\n accessor withClear = false;\n\n /** Panel placement relative to the trigger. */\n @property()\n accessor placement: Placement = 'bottom-start';\n\n /** Allow selecting multiple values — renders chips and submits one entry per value. */\n @property({ type: Boolean, reflect: true })\n accessor multiple = false;\n\n /** Override the option filter. `(item, query) => boolean`. */\n filter: SelectFilter = defaultFilter;\n\n @state() private accessor _values: string[] = [];\n @state() private accessor _open = false;\n @state() private accessor _query = '';\n @state() private accessor _items: SelectItem[] = [];\n\n private _defaultValues: string[] = [];\n\n /** The selected value (single mode) or array of values (multiple mode). */\n get value(): string | string[] {\n return this.multiple ? [...this._values] : (this._values[0] ?? '');\n }\n set value(v: string | string[]) {\n this._values = Array.isArray(v) ? [...v] : v ? [v] : [];\n }\n\n private get _triggerEl() {\n return this.shadowRoot?.querySelector<HTMLElement>('.trigger') ?? null;\n }\n private get _panelEl() {\n return this.shadowRoot?.querySelector<HTMLElement>('.panel') ?? null;\n }\n private get _searchEl() {\n return this.shadowRoot?.querySelector<HTMLInputElement>('.search') ?? null;\n }\n\n override get validationTarget() {\n return this._triggerEl ?? undefined;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this._readItems();\n // Seed the initial selection: an explicit `value` attribute wins, else the\n // authored `<option selected>` (declarative pre-selection — markup-driven).\n if (this._values.length === 0) {\n const attr = this.getAttribute('value');\n if (attr) {\n this._values = [attr];\n } else {\n const selected = this._items.filter((i) => i.selected).map((i) => i.value);\n this._values = this.multiple ? selected : selected.slice(0, 1);\n }\n }\n this._defaultValues = [...this._values];\n this._syncForm();\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('_values') || changed.has('multiple')) {\n this._syncForm();\n this._updateValidity();\n }\n }\n\n override formResetCallback() {\n this._values = [...this._defaultValues];\n this._query = '';\n this._nav.reset();\n super.formResetCallback();\n this._syncForm();\n }\n\n override formStateRestoreCallback(state: string) {\n this.value = state;\n this._syncForm();\n }\n\n // --- Items (read from the light-DOM <datalist>) ---\n\n private _readItems() {\n const list = this.querySelector('datalist');\n const opts = list ? Array.from(list.options) : [];\n this._items = opts.map((o) => {\n const rich = o.childElementCount > 0;\n const label = richOptionLabel(o);\n return {\n value: o.value,\n label,\n disabled: o.disabled,\n selected: o.hasAttribute('selected'),\n html: rich ? o.innerHTML : undefined,\n };\n });\n adoptRichContentStyles(this.shadowRoot, this._items);\n }\n\n /**\n * Re-read the options after the light DOM changed underneath us. The active\n * option is addressed by position in `_filtered`, so a list that grows or\n * shrinks while the listbox is open would silently move the keyboard\n * selection onto a different row (or off the end, leaving Enter dead).\n * Re-anchor it on the option the user had highlighted, and drop it when that\n * option is gone.\n */\n private _syncItems() {\n const active = this._open ? this._filtered[this._nav.activeIndex] : undefined;\n this._readItems();\n if (!this._open) return;\n this._nav.setActive(active ? this._filtered.findIndex((i) => i.value === active.value) : -1);\n }\n\n private _itemFor(value: string): SelectItem | undefined {\n return this._items.find((i) => i.value === value);\n }\n\n private get _filtered(): SelectItem[] {\n return this._items.filter((i) => this.filter(i, this._query));\n }\n\n // --- Validity ---\n\n /** Push the current selection to the form (single value, or one entry per value). */\n private _syncForm() {\n if (this.multiple) {\n const data = new FormData();\n for (const v of this._values) data.append(this.name, v);\n this._internals.setFormValue(data);\n } else {\n this._internals.setFormValue(this._values[0] ?? '');\n }\n }\n\n private _updateValidity() {\n if (this.required && this._values.length === 0) {\n this.setValidity(\n { valueMissing: true },\n this._localize.term('selectOption'),\n this._triggerEl ?? undefined,\n );\n } else {\n this.setValidity({});\n }\n }\n\n // --- Open / close ---\n\n show() {\n if (this._open || this.disabled) return;\n this._readItems();\n if (!this.dispatchEvent(new Event('show', { cancelable: true }))) return;\n this._open = true;\n this._query = '';\n // Pre-activate the (first) chosen option so a screen reader announces it on open.\n if (this._values.length) {\n this._nav.setActive(this._filtered.findIndex((i) => i.value === this._values[0]));\n }\n void this.updateComplete.then(() => {\n const panel = this._panelEl;\n panel?.showPopover?.();\n this._floating.startPositioning({\n placement: this.placement,\n distance: 4,\n minWidth: 'trigger',\n });\n // Move focus into the search box (or the listbox when not searchable).\n (this._searchEl ?? this._panelEl?.querySelector<HTMLElement>('.listbox'))?.focus();\n document.addEventListener('pointerdown', this._onDocumentPointerDown, true);\n });\n }\n\n hide({ focusTrigger = true } = {}) {\n if (!this._open) return;\n if (!this.dispatchEvent(new Event('hide', { cancelable: true }))) return;\n this._open = false;\n this._query = '';\n this._nav.reset();\n const panel = this._panelEl;\n if (panel?.matches?.(':popover-open')) panel.hidePopover?.();\n this._floating.stopPositioning();\n document.removeEventListener('pointerdown', this._onDocumentPointerDown, true);\n if (focusTrigger) this._triggerEl?.focus();\n }\n\n private _onDocumentPointerDown = (e: PointerEvent) => {\n // popover=\"manual\" does not light-dismiss; do it ourselves.\n const path = e.composedPath();\n if (path.includes(this)) return;\n this.hasInteracted = true;\n this._updateValidity();\n this.hide({ focusTrigger: false });\n };\n\n // --- Selection ---\n\n /** Single: set the value and close. Multiple: toggle the value and stay open. */\n private _select(item: SelectItem) {\n if (item.disabled) return;\n this.hasInteracted = true;\n if (this.multiple) {\n this._values = this._values.includes(item.value)\n ? this._values.filter((v) => v !== item.value)\n : [...this._values, item.value];\n this.dispatchEvent(new SelectChangeEvent(this.value));\n this._searchEl?.focus();\n } else {\n this._values = [item.value];\n this.dispatchEvent(new SelectChangeEvent(this.value));\n this.hide();\n }\n }\n\n /** Deselect a single value (chip remove, multiple mode). */\n private _removeValue(value: string) {\n this._values = this._values.filter((v) => v !== value);\n this.hasInteracted = true;\n this.dispatchEvent(new SelectChangeEvent(this.value));\n }\n\n private _clear(e?: Event) {\n e?.stopPropagation();\n this._values = [];\n this.hasInteracted = true;\n this.dispatchEvent(new SelectChangeEvent(this.value));\n this._triggerEl?.focus();\n }\n\n // --- Keyboard ---\n\n private _onTriggerKeyDown = (e: KeyboardEvent) => {\n if (this._open) return;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.show();\n }\n };\n\n private _onPanelKeyDown = (e: KeyboardEvent) => {\n if (this._nav.onKeyDown(e)) return;\n switch (e.key) {\n case 'Enter': {\n e.preventDefault();\n const active = this._filtered[this._nav.activeIndex];\n if (active) this._select(active);\n break;\n }\n case 'Escape':\n e.preventDefault();\n this.hide();\n break;\n case 'Tab':\n this.hide({ focusTrigger: false });\n break;\n default:\n break;\n }\n };\n\n private _onSearchInput = (e: Event) => {\n this._query = (e.target as HTMLInputElement).value;\n this._nav.reset();\n this.dispatchEvent(new SelectInputEvent(this._query));\n };\n\n // --- Render ---\n\n private _renderSingleValue() {\n const selected = this._itemFor(this._values[0]);\n if (!selected) {\n return html`<span class=\"value-text placeholder\">${this.placeholder}</span>`;\n }\n return selected.html\n ? html`${unsafeHTML(selected.html)}`\n : html`<span class=\"value-text\">${selected.label}</span>`;\n }\n\n private _renderChips() {\n if (this._values.length === 0) {\n return html`<span class=\"value-text placeholder\">${this.placeholder}</span>`;\n }\n // The chip tag is the renameable `l-tag`; it's a Shadow-DOM element so its\n // remove button renders correctly inside this element's shadow root.\n const chip = unsafeStatic(tagName('tag'));\n return this._values.map((value) => {\n const item = this._itemFor(value);\n return staticHtml`<${chip}\n size=\"sm\"\n removable\n part=\"tag\"\n @remove=${(e: Event) => {\n e.preventDefault();\n this._removeValue(value);\n }}\n @click=${(e: Event) => e.stopPropagation()}\n >${item?.label ?? value}</${chip}\n >`;\n });\n }\n\n private _renderTrigger(invalid: boolean) {\n const inner = html`\n <span\n class=\"value\"\n part=\"value\"\n >${this.multiple ? this._renderChips() : this._renderSingleValue()}</span\n >\n <span\n class=\"chevron\"\n part=\"chevron\"\n aria-hidden=\"true\"\n ></span>\n `;\n const onClick = () => (this._open ? this.hide() : this.show());\n // Both modes expose role=\"combobox\" (APG select-only combobox). A combobox\n // doesn't take its name from its content, so `label` stays the accessible\n // name while the shown value is announced as the value. A plain button would\n // let `aria-label` hide the chosen value from screen readers (WCAG 2.5.3).\n // Multiple mode uses a focusable div so the chips' remove buttons are valid\n // interactive children — a <button> trigger can't nest them.\n return this.multiple\n ? html`<div\n class=\"trigger\"\n part=\"trigger\"\n role=\"combobox\"\n tabindex=${this.disabled ? -1 : 0}\n aria-haspopup=\"listbox\"\n aria-expanded=${this._open ? 'true' : 'false'}\n aria-controls=${this._listId}\n aria-label=${this.label || nothing}\n aria-required=${this.required ? 'true' : nothing}\n aria-invalid=${invalid ? 'true' : nothing}\n @click=${onClick}\n @keydown=${this._onTriggerKeyDown}\n >\n ${inner}\n </div>`\n : html`<button\n class=\"trigger\"\n part=\"trigger\"\n type=\"button\"\n role=\"combobox\"\n ?disabled=${this.disabled}\n aria-haspopup=\"listbox\"\n aria-expanded=${this._open ? 'true' : 'false'}\n aria-controls=${this._listId}\n aria-label=${this.label || nothing}\n aria-required=${this.required ? 'true' : nothing}\n aria-invalid=${invalid ? 'true' : nothing}\n @click=${onClick}\n @keydown=${this._onTriggerKeyDown}\n >\n ${inner}\n </button>`;\n }\n\n override render() {\n const filtered = this._filtered;\n const activeId = this._nav.activeDescendant;\n const activeIndex = this._nav.activeIndex;\n const invalid = this.required && this._values.length === 0 && this.hasInteracted;\n const hasValue = this._values.length > 0;\n const status = !this._open\n ? ''\n : filtered.length === 0\n ? this._localize.term('noResults')\n : `${filtered.length} ${this._localize.term('suggestions')}`;\n\n return html`\n <div\n class=\"base\"\n part=\"base\"\n >\n ${this._renderTrigger(invalid)}\n ${\n this.withClear && hasValue\n ? html`<button\n class=\"clear-button\"\n part=\"clear\"\n type=\"button\"\n aria-label=${this._localize.term('clear')}\n @click=${this._clear}\n ></button>`\n : nothing\n }\n\n <div\n class=\"panel\"\n part=\"panel\"\n popover=\"manual\"\n @keydown=${this._onPanelKeyDown}\n >\n ${\n this.searchable\n ? html`<div class=\"search-row\">\n <input\n class=\"search\"\n part=\"search\"\n type=\"text\"\n role=\"searchbox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n .placeholder=${this._localize.term('search') ?? ''}\n aria-controls=${this._listId}\n aria-activedescendant=${activeId ?? nothing}\n @input=${this._onSearchInput}\n />\n </div>`\n : nothing\n }\n\n <ul\n class=\"listbox\"\n part=\"listbox\"\n role=\"listbox\"\n id=${this._listId}\n tabindex=${this.searchable ? nothing : '0'}\n aria-label=${this.label || this._localize.term('suggestions')}\n aria-multiselectable=${this.multiple ? 'true' : nothing}\n aria-activedescendant=${!this.searchable ? (activeId ?? nothing) : nothing}\n @pointermove=${this._nav.onPointerMove}\n @pointerleave=${this._nav.onPointerLeave}\n >\n ${filtered.map(\n (item, i) =>\n html`<li\n class=\"option\"\n part=\"option\"\n id=${this._nav.optionId(i)}\n role=\"option\"\n aria-selected=${this._values.includes(item.value) ? 'true' : 'false'}\n aria-disabled=${item.disabled ? 'true' : nothing}\n data-active=${i === activeIndex ? '' : nothing}\n data-current=${this._values.includes(item.value) ? '' : nothing}\n @pointerdown=${(e: Event) => e.preventDefault()}\n @click=${() => this._select(item)}\n >\n ${\n item.html\n ? unsafeHTML(this._richHighlighter.highlight(item.html, this._query))\n : html`<span class=\"option-label\"\n >${highlightText(item.label, this._query)}</span\n >`\n }\n </li>`,\n )}\n </ul>\n ${\n filtered.length === 0\n ? html`<div\n class=\"empty\"\n part=\"empty\"\n >\n ${this._localize.term('noResults')}\n </div>`\n : nothing\n }\n </div>\n\n <div\n class=${cls('visually-hidden')}\n aria-live=\"polite\"\n >\n ${status}\n </div>\n </div>\n `;\n }\n}\n\n// Typed addEventListener for the colliding `change` / `input` names.\nexport interface Select {\n addEventListener<K extends keyof SelectEventMap>(\n type: K,\n listener: (this: Select, ev: SelectEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener<K extends keyof SelectEventMap>(\n type: K,\n listener: (this: Select, ev: SelectEventMap[K]) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"select.js","names":["unsafeCSS","rawStyles","hostStyles","visuallyHiddenStyles","suffixStyles","selectItemStyles","pickerCoreStyles","unsafeHTML","unsafeStatic","nothing","_decorate","property","state","r","s","u","r$1","n","__decorate","b","A","o","host_styles_default","visually_hidden_styles_default","select_item_suffix_styles_default","picker_core_styles_default","select_item_styles_default","styles","defaultFilter","query","label","normalize","item","kw","SelectChangeEvent","value","SelectInputEvent","Select","LuxenFormAssociatedElement","_args","LocalizeController","uniqueId","RichHighlighter","PopoverController","ListboxNavController","i","DatalistObserverController","#_placeholder_accessor_storage","#_label_accessor_storage","#_size_accessor_storage","#_searchable_accessor_storage","#_withClear_accessor_storage","#_placement_accessor_storage","#_multiple_accessor_storage","#__values_accessor_storage","#__open_accessor_storage","#__query_accessor_storage","#__items_accessor_storage","active","v","attr","selected","changed","state","list","opts","rich","richOptionLabel","adoptRichContentStyles","data","panel","focusTrigger","chip","tagName","inner","onClick","invalid","filtered","activeId","activeIndex","hasValue","status","highlightText","cls"],"sources":["../../../src/html/elements/select/select.css?inline","../../../src/html/elements/select/select.ts"],"sourcesContent":["/* Knobs, size scale, field frame, chevron, clear, listbox popover and the\n shared option bits come from shared/styles/picker-core.css; the option row\n and rich-option content from shared/styles/select-item.css (also used by the\n native `.l-select` picker). This file holds what is specific to l-select. */\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆃🆁🅸🅶🅶🅴🆁 (button, opens the listbox popover)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n*/\n\n.trigger {\n gap: 0.5rem;\n inline-size: 100%;\n min-block-size: var(--height);\n padding-block: 0.25rem;\n color: var(--l-form-control-value-color);\n font: inherit;\n text-align: start;\n cursor: pointer;\n}\n\n/* The form-control inline padding is tuned for text; before a chip row it reads\n as too much, so tighten the start edge in multiple mode (the chips bring their\n own spacing). */\n:host([multiple]) .trigger {\n padding-inline-start: 0.375rem;\n}\n\n/* Selection display fills the trigger; the chevron (and overlaid clear) sit at the end. */\n.value {\n flex: 1;\n min-inline-size: 0;\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 0.25rem;\n overflow: hidden;\n}\n\n.value-text {\n min-inline-size: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* This element's public knobs and the chip's share two names — `--height` and\n `--border-radius` — and custom properties inherit straight through a shadow\n boundary. Left alone, every chip in the trigger renders at the *select's*\n height and corner rather than its own: a 36px chip with a 6px corner, when\n `size=\"sm\"` asked for a 24px pill. `initial` is the guaranteed-invalid value,\n so each `var(--x, …)` inside the chip falls back to its own default. Matched\n on the part, not on the tag name, so a renamed `elementPrefix` can't miss it.\n\n The fill used to collide too, back when the chip read `--background`; it now\n reads `--background-color`, which this element does not expose. */\n[part='tag'] {\n --height: initial;\n --border-radius: initial;\n}\n\n.placeholder {\n color: var(--l-form-control-placeholder-color);\n}\n\n/* The clear button is a SIBLING of the trigger (not a child — no nested buttons),\n * overlaid on the trigger's end, square against the chevron's square — which\n * sits flush against the border (picker-core.css). */\n.clear-button {\n position: absolute;\n inset-block: 0;\n inset-inline-end: calc(var(--l-form-control-border-width) + var(--_action-size));\n margin-block: auto;\n}\n\n/* Keep the value (text or chips) clear of the overlaid button. */\n.base:has(> .clear-button) .chevron {\n margin-inline-start: var(--_action-size);\n}\n\n/* Rich content in the trigger takes the row styles (select-item.css), then\n mirrors the native trigger: only the media and title, at the value's weight —\n the secondary description and the trailing suffix are dropped so the selected\n value stays compact and consistent across options. */\n.value .l-select-item-title {\n font-weight: inherit;\n}\n.value .l-select-item-description,\n.value .l-select-item-suffix {\n display: none;\n}\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🅿🅰🅽🅴🅻 (popover: search + listbox)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n*/\n\n.search-row {\n padding: 0.375rem;\n border-block-end: 1px solid var(--l-color-border-overlay);\n}\n\n.search {\n inline-size: 100%;\n block-size: var(--l-size-control-sm);\n padding-inline: 0.5rem;\n border: var(--l-form-control-border-width) solid var(--l-form-control-border-color);\n border-radius: calc(var(--border-radius) - 2px);\n background-color: var(--l-form-control-background-color);\n color: var(--l-form-control-value-color);\n font: inherit;\n}\n\n.search::placeholder {\n color: var(--l-form-control-placeholder-color);\n}\n\n/* Keyboard-active row (moves with Arrow keys) — same tint as hover. */\n.option[data-active] {\n background-color: var(--l-color-bg-state-hover);\n}\n\n/* Moved there with the arrow keys: the active option is where the keyboard\n is, though DOM focus stays on the search box or the listbox\n (aria-activedescendant), so it draws the focus ring itself — inside, like a\n menu item. A tint alone is the hover look, barely 1.1:1, and forced colors\n drops it. */\n.listbox[data-nav='keyboard'] .option[data-active] {\n outline: var(--l-focus-ring-width) solid var(--l-focus-ring-color);\n outline-offset: calc(var(--l-focus-ring-width) * -1);\n}\n\n/* Selected indicator in the reserved inline-start column, pinned to the first\n * line so a wrapping description never shifts it (matches the native\n * `::checkmark` in src/css/elements/select.css). */\n.option[data-current]::after {\n content: '';\n position: absolute;\n inset-inline-start: 0.5rem;\n inset-block-start: var(--_row-padding-block);\n inline-size: 1rem;\n block-size: calc(var(--l-popover-font-size) * var(--l-popover-line-height));\n background-color: currentColor;\n mask: var(--_check-icon) center / 1rem no-repeat;\n}\n\n/* Rich content, rows and trigger alike: the shared layout (select-item.css)\n plus what only this tier needs — media may be an emoji or icon rather than an\n image, so it is centred and sized by font. */\n.l-select-item-media {\n display: inline-flex;\n align-items: center;\n font-size: 1.25em;\n}\n","import { html, nothing, unsafeCSS } from 'lit';\nimport { html as staticHtml, unsafeStatic } from 'lit/static-html.js';\nimport { property, state } from 'lit/decorators.js';\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\nimport type { Placement } from '@floating-ui/dom';\nimport { LuxenFormAssociatedElement } from '../../shared/luxen-form-associated-element.js';\nimport { PopoverController } from '../../shared/controllers/popover.js';\nimport { ListboxNavController } from '../../shared/controllers/listbox-nav.js';\nimport { DatalistObserverController } from '../../shared/controllers/datalist-observer.js';\nimport { LocalizeController } from '../../shared/localize.js';\nimport { RichHighlighter, highlightText, normalize } from '../../shared/highlight.js';\nimport { cls, tagName, uniqueId } from '../../registry.js';\nimport { adoptRichContentStyles, richOptionLabel } from '../../shared/rich-option.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport visuallyHiddenStyles from '../../shared/styles/visually-hidden.styles.js';\nimport suffixStyles from '../../shared/styles/select-item-suffix.styles.js';\nimport pickerCoreStyles from '../../shared/styles/picker-core.styles.js';\nimport selectItemStyles from '../../shared/styles/select-item.styles.js';\nimport rawStyles from './select.css?inline';\n// Registers the chip element used to render selected values in multiple mode.\nimport '../tag/index.js';\n\nconst styles = unsafeCSS(rawStyles);\n\nexport type SelectSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\n/** A single option read from the `<datalist>`. */\nexport interface SelectItem {\n value: string;\n /** Plain text used for filtering and the trigger display. */\n label: string;\n disabled: boolean;\n /** Authored `selected` attribute — seeds the initial value. */\n selected: boolean;\n /** Rich inner markup (from a non-empty `<option>`), projected into the row. */\n html?: string;\n}\n\n/** Default filter: accent/case-insensitive, every space-separated keyword must match. */\nexport type SelectFilter = (item: SelectItem, query: string) => boolean;\n\nconst defaultFilter: SelectFilter = (item, query) => {\n if (!query) return true;\n const label = normalize(item.label);\n return normalize(query)\n .split(/\\s+/)\n .filter(Boolean)\n .every((kw) => label.includes(kw));\n};\n\n/** Fired when the selection changes. Bubbles; not composed. */\nexport class SelectChangeEvent extends Event {\n /** The selected value (single mode) or values (multiple mode). */\n readonly value: string | string[];\n constructor(value: string | string[]) {\n super('change', { bubbles: true, composed: false, cancelable: false });\n this.value = value;\n }\n}\n\n/** Fired as the user types in the search box. Bubbles; not composed. */\nexport class SelectInputEvent extends Event {\n /** The current query text. */\n readonly value: string;\n constructor(value: string) {\n super('input', { bubbles: true, composed: false, cancelable: false });\n this.value = value;\n }\n}\n\ninterface SelectEventMap {\n change: SelectChangeEvent;\n input: SelectInputEvent;\n}\n\n/**\n * A button-triggered, searchable select. A trigger shows the current selection,\n * opening a popover with a search box and a `role=\"listbox\"` of options authored\n * as a native `<datalist>` of `<option>` — the same authoring surface as\n * `l-combobox` and the native `.l-select`. Form-associated.\n *\n * @summary A searchable select with a button trigger and a popover listbox.\n *\n * @example\n * ```html\n * <l-select label=\"Country\" name=\"country\" placeholder=\"Select a country…\">\n * <datalist>\n * <option value=\"us\">United States</option>\n * <option value=\"fr\" selected>France</option>\n * </datalist>\n * </l-select>\n * ```\n *\n * @event change - Fired when the selection changes. Bubbles. Not cancelable. Properties: `value: string | string[]`.\n * @event input - Fired as the user types in the search box. Bubbles. Not cancelable. Properties: `value: string` (the query).\n * @event show - Fired before the listbox opens. Cancelable.\n * @event hide - Fired before the listbox closes. Cancelable.\n *\n * @csspart base - The host wrapper.\n * @csspart trigger - The button that opens the listbox.\n * @csspart value - The selection display inside the trigger.\n * @csspart chevron - The trigger chevron.\n * @csspart clear - The clear button.\n * @csspart panel - The floating popover panel.\n * @csspart search - The search input.\n * @csspart listbox - The options container.\n * @csspart option - Each option row.\n * @csspart empty - The \"no results\" message.\n *\n * @cssproperty [--height=var(--l-form-control-height)] - Control height. The clear button and the chevron\n * each take a square of this height (borders excluded), so their hit area and spacing follow it.\n * @cssproperty [--l-form-control-icon-size=1em] - Glyph size of the clear button and the chevron (global form-control\n * token; set it here or on any ancestor). Changes the glyph only — the hit area follows `--height`.\n * @cssproperty --chevron-icon - Chevron glyph as a `url()`. Masked, so its color comes from the control, not the image.\n * @cssproperty --clear-icon - Clear button glyph as a `url()`.\n * @cssproperty [--border-radius] - Trigger + panel radius.\n * @cssproperty [--background] - Panel background.\n *\n * @cssClass .l-select-item-media - Rich option: leading image or icon.\n * @cssClass .l-select-item-text - Rich option: column holding the title and the description.\n * @cssClass .l-select-item-title - Rich option: title, truncated with an ellipsis. Used as the label when the option has no `label`.\n * @cssClass .l-select-item-description - Rich option: secondary line, shown in the listbox only.\n * @cssClass .l-select-item-suffix - Rich option: trailing badge, count or status icon on the title's line. Kept out of the trigger, the chips and the search.\n *\n * @customElement l-select\n */\n// oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- typed addEventListener overloads merged below; no uninitialized properties.\nexport class Select extends LuxenFormAssociatedElement {\n // Rich option markup is copied into the shadow root, out of reach of the\n // global stylesheets: suffixStyles lays out the `.l-select-item-suffix` zone,\n // and `_readItems` adopts the styles of the light-DOM elements (l-badge) the\n // options actually contain. selectItemStyles (row + rich content, shared with\n // the native picker) loads before pickerCoreStyles so the shared disabled-row\n // rule wins over the row's `cursor: pointer`.\n static override styles = [\n hostStyles,\n visuallyHiddenStyles,\n suffixStyles,\n selectItemStyles,\n pickerCoreStyles,\n styles,\n ];\n\n private _localize = new LocalizeController(this);\n private readonly _listId = uniqueId('select-list');\n private readonly _richHighlighter = new RichHighlighter();\n\n private _floating = new PopoverController(this, {\n getTriggerElement: () => this._triggerEl,\n getFloatingElement: () => this._panelEl,\n getArrowElement: () => null,\n });\n\n private _nav = new ListboxNavController(this, {\n listboxId: this._listId,\n getCount: () => this._filtered.length,\n isDisabled: (i) => this._filtered[i]?.disabled ?? false,\n isOpen: () => this._open,\n open: () => this.show(),\n getOptionElements: () => this.shadowRoot?.querySelectorAll<HTMLElement>('.option'),\n });\n\n // The `<datalist>` is light DOM the consumer owns and rewrites in place;\n // re-read it so the closed trigger tracks the options it was given.\n private _options = new DatalistObserverController(this, () => this._syncItems());\n\n /** Placeholder shown in the trigger when nothing is selected. */\n @property()\n accessor placeholder = '';\n\n /** Accessible label for the trigger. */\n @property()\n accessor label = '';\n\n /** Control size. */\n @property({ reflect: true })\n accessor size: SelectSize = 'md';\n\n /** Show a filter box inside the popover (opt-in, for long lists). */\n @property({ type: Boolean, reflect: true })\n accessor searchable = false;\n\n /** Show a button to clear the value. */\n @property({ type: Boolean, reflect: true, attribute: 'with-clear' })\n accessor withClear = false;\n\n /** Panel placement relative to the trigger. */\n @property()\n accessor placement: Placement = 'bottom-start';\n\n /** Allow selecting multiple values — renders chips and submits one entry per value. */\n @property({ type: Boolean, reflect: true })\n accessor multiple = false;\n\n /** Override the option filter. `(item, query) => boolean`. */\n filter: SelectFilter = defaultFilter;\n\n @state() private accessor _values: string[] = [];\n @state() private accessor _open = false;\n @state() private accessor _query = '';\n @state() private accessor _items: SelectItem[] = [];\n\n private _defaultValues: string[] = [];\n\n /** The selected value (single mode) or array of values (multiple mode). */\n get value(): string | string[] {\n return this.multiple ? [...this._values] : (this._values[0] ?? '');\n }\n set value(v: string | string[]) {\n this._values = Array.isArray(v) ? [...v] : v ? [v] : [];\n }\n\n private get _triggerEl() {\n return this.shadowRoot?.querySelector<HTMLElement>('.trigger') ?? null;\n }\n private get _panelEl() {\n return this.shadowRoot?.querySelector<HTMLElement>('.panel') ?? null;\n }\n private get _searchEl() {\n return this.shadowRoot?.querySelector<HTMLInputElement>('.search') ?? null;\n }\n\n override get validationTarget() {\n return this._triggerEl ?? undefined;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n this._readItems();\n // Seed the initial selection: an explicit `value` attribute wins, else the\n // authored `<option selected>` (declarative pre-selection — markup-driven).\n if (this._values.length === 0) {\n const attr = this.getAttribute('value');\n if (attr) {\n this._values = [attr];\n } else {\n const selected = this._items.filter((i) => i.selected).map((i) => i.value);\n this._values = this.multiple ? selected : selected.slice(0, 1);\n }\n }\n this._defaultValues = [...this._values];\n this._syncForm();\n }\n\n override updated(changed: Map<string, unknown>) {\n if (changed.has('_values') || changed.has('multiple')) {\n this._syncForm();\n this._updateValidity();\n }\n }\n\n override formResetCallback() {\n this._values = [...this._defaultValues];\n this._query = '';\n this._nav.reset();\n super.formResetCallback();\n this._syncForm();\n }\n\n override formStateRestoreCallback(state: string) {\n this.value = state;\n this._syncForm();\n }\n\n // --- Items (read from the light-DOM <datalist>) ---\n\n private _readItems() {\n const list = this.querySelector('datalist');\n const opts = list ? Array.from(list.options) : [];\n this._items = opts.map((o) => {\n const rich = o.childElementCount > 0;\n const label = richOptionLabel(o);\n return {\n value: o.value,\n label,\n disabled: o.disabled,\n selected: o.hasAttribute('selected'),\n html: rich ? o.innerHTML : undefined,\n };\n });\n adoptRichContentStyles(this.shadowRoot, this._items);\n }\n\n /**\n * Re-read the options after the light DOM changed underneath us. The active\n * option is addressed by position in `_filtered`, so a list that grows or\n * shrinks while the listbox is open would silently move the keyboard\n * selection onto a different row (or off the end, leaving Enter dead).\n * Re-anchor it on the option the user had highlighted, and drop it when that\n * option is gone.\n */\n private _syncItems() {\n const active = this._open ? this._filtered[this._nav.activeIndex] : undefined;\n this._readItems();\n if (!this._open) return;\n this._nav.setActive(active ? this._filtered.findIndex((i) => i.value === active.value) : -1);\n }\n\n private _itemFor(value: string): SelectItem | undefined {\n return this._items.find((i) => i.value === value);\n }\n\n private get _filtered(): SelectItem[] {\n return this._items.filter((i) => this.filter(i, this._query));\n }\n\n // --- Validity ---\n\n /** Push the current selection to the form (single value, or one entry per value). */\n private _syncForm() {\n if (this.multiple) {\n const data = new FormData();\n for (const v of this._values) data.append(this.name, v);\n this._internals.setFormValue(data);\n } else {\n this._internals.setFormValue(this._values[0] ?? '');\n }\n }\n\n private _updateValidity() {\n if (this.required && this._values.length === 0) {\n this.setValidity(\n { valueMissing: true },\n this._localize.term('selectOption'),\n this._triggerEl ?? undefined,\n );\n } else {\n this.setValidity({});\n }\n }\n\n // --- Open / close ---\n\n show() {\n if (this._open || this.disabled) return;\n this._readItems();\n if (!this.dispatchEvent(new Event('show', { cancelable: true }))) return;\n this._open = true;\n this._query = '';\n // Pre-activate the (first) chosen option so a screen reader announces it on open.\n if (this._values.length) {\n this._nav.setActive(this._filtered.findIndex((i) => i.value === this._values[0]));\n }\n void this.updateComplete.then(() => {\n const panel = this._panelEl;\n panel?.showPopover?.();\n this._floating.startPositioning({\n placement: this.placement,\n distance: 4,\n minWidth: 'trigger',\n });\n // Move focus into the search box (or the listbox when not searchable).\n (this._searchEl ?? this._panelEl?.querySelector<HTMLElement>('.listbox'))?.focus();\n document.addEventListener('pointerdown', this._onDocumentPointerDown, true);\n });\n }\n\n hide({ focusTrigger = true } = {}) {\n if (!this._open) return;\n if (!this.dispatchEvent(new Event('hide', { cancelable: true }))) return;\n this._open = false;\n this._query = '';\n this._nav.reset();\n const panel = this._panelEl;\n if (panel?.matches?.(':popover-open')) panel.hidePopover?.();\n this._floating.stopPositioning();\n document.removeEventListener('pointerdown', this._onDocumentPointerDown, true);\n if (focusTrigger) this._triggerEl?.focus();\n }\n\n private _onDocumentPointerDown = (e: PointerEvent) => {\n // popover=\"manual\" does not light-dismiss; do it ourselves.\n const path = e.composedPath();\n if (path.includes(this)) return;\n this.hasInteracted = true;\n this._updateValidity();\n this.hide({ focusTrigger: false });\n };\n\n // --- Selection ---\n\n /** Single: set the value and close. Multiple: toggle the value and stay open. */\n private _select(item: SelectItem) {\n if (item.disabled) return;\n this.hasInteracted = true;\n if (this.multiple) {\n this._values = this._values.includes(item.value)\n ? this._values.filter((v) => v !== item.value)\n : [...this._values, item.value];\n this.dispatchEvent(new SelectChangeEvent(this.value));\n this._searchEl?.focus();\n } else {\n this._values = [item.value];\n this.dispatchEvent(new SelectChangeEvent(this.value));\n this.hide();\n }\n }\n\n /** Deselect a single value (chip remove, multiple mode). */\n private _removeValue(value: string) {\n this._values = this._values.filter((v) => v !== value);\n this.hasInteracted = true;\n this.dispatchEvent(new SelectChangeEvent(this.value));\n }\n\n private _clear(e?: Event) {\n e?.stopPropagation();\n this._values = [];\n this.hasInteracted = true;\n this.dispatchEvent(new SelectChangeEvent(this.value));\n this._triggerEl?.focus();\n }\n\n // --- Keyboard ---\n\n private _onTriggerKeyDown = (e: KeyboardEvent) => {\n if (this._open) return;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.show();\n }\n };\n\n private _onPanelKeyDown = (e: KeyboardEvent) => {\n if (this._nav.onKeyDown(e)) return;\n switch (e.key) {\n case 'Enter': {\n e.preventDefault();\n const active = this._filtered[this._nav.activeIndex];\n if (active) this._select(active);\n break;\n }\n case 'Escape':\n e.preventDefault();\n this.hide();\n break;\n case 'Tab':\n this.hide({ focusTrigger: false });\n break;\n default:\n break;\n }\n };\n\n private _onSearchInput = (e: Event) => {\n this._query = (e.target as HTMLInputElement).value;\n this._nav.reset();\n this.dispatchEvent(new SelectInputEvent(this._query));\n };\n\n // --- Render ---\n\n private _renderSingleValue() {\n const selected = this._itemFor(this._values[0]);\n if (!selected) {\n return html`<span class=\"value-text placeholder\">${this.placeholder}</span>`;\n }\n return selected.html\n ? html`${unsafeHTML(selected.html)}`\n : html`<span class=\"value-text\">${selected.label}</span>`;\n }\n\n private _renderChips() {\n if (this._values.length === 0) {\n return html`<span class=\"value-text placeholder\">${this.placeholder}</span>`;\n }\n // The chip tag is the renameable `l-tag`; it's a Shadow-DOM element so its\n // remove button renders correctly inside this element's shadow root.\n const chip = unsafeStatic(tagName('tag'));\n return this._values.map((value) => {\n const item = this._itemFor(value);\n return staticHtml`<${chip}\n size=\"sm\"\n removable\n part=\"tag\"\n @remove=${(e: Event) => {\n e.preventDefault();\n this._removeValue(value);\n }}\n @click=${(e: Event) => e.stopPropagation()}\n >${item?.label ?? value}</${chip}\n >`;\n });\n }\n\n private _renderTrigger(invalid: boolean) {\n const inner = html`\n <span\n class=\"value\"\n part=\"value\"\n >${this.multiple ? this._renderChips() : this._renderSingleValue()}</span\n >\n <span\n class=\"chevron\"\n part=\"chevron\"\n aria-hidden=\"true\"\n ></span>\n `;\n const onClick = () => (this._open ? this.hide() : this.show());\n // Both modes expose role=\"combobox\" (APG select-only combobox). A combobox\n // doesn't take its name from its content, so `label` stays the accessible\n // name while the shown value is announced as the value. A plain button would\n // let `aria-label` hide the chosen value from screen readers (WCAG 2.5.3).\n // Multiple mode uses a focusable div so the chips' remove buttons are valid\n // interactive children — a <button> trigger can't nest them.\n return this.multiple\n ? html`<div\n class=\"trigger\"\n part=\"trigger\"\n role=\"combobox\"\n tabindex=${this.disabled ? -1 : 0}\n aria-haspopup=\"listbox\"\n aria-expanded=${this._open ? 'true' : 'false'}\n aria-controls=${this._listId}\n aria-label=${this.label || nothing}\n aria-required=${this.required ? 'true' : nothing}\n aria-invalid=${invalid ? 'true' : nothing}\n @click=${onClick}\n @keydown=${this._onTriggerKeyDown}\n >\n ${inner}\n </div>`\n : html`<button\n class=\"trigger\"\n part=\"trigger\"\n type=\"button\"\n role=\"combobox\"\n ?disabled=${this.disabled}\n aria-haspopup=\"listbox\"\n aria-expanded=${this._open ? 'true' : 'false'}\n aria-controls=${this._listId}\n aria-label=${this.label || nothing}\n aria-required=${this.required ? 'true' : nothing}\n aria-invalid=${invalid ? 'true' : nothing}\n @click=${onClick}\n @keydown=${this._onTriggerKeyDown}\n >\n ${inner}\n </button>`;\n }\n\n override render() {\n const filtered = this._filtered;\n const activeId = this._nav.activeDescendant;\n const activeIndex = this._nav.activeIndex;\n const invalid = this.required && this._values.length === 0 && this.hasInteracted;\n const hasValue = this._values.length > 0;\n const status = !this._open\n ? ''\n : filtered.length === 0\n ? this._localize.term('noResults')\n : `${filtered.length} ${this._localize.term('suggestions')}`;\n\n return html`\n <div\n class=\"base\"\n part=\"base\"\n >\n ${this._renderTrigger(invalid)}\n ${\n this.withClear && hasValue\n ? html`<button\n class=\"clear-button\"\n part=\"clear\"\n type=\"button\"\n aria-label=${this._localize.term('clear')}\n @click=${this._clear}\n ></button>`\n : nothing\n }\n\n <div\n class=\"panel\"\n part=\"panel\"\n popover=\"manual\"\n @keydown=${this._onPanelKeyDown}\n >\n ${\n this.searchable\n ? html`<div class=\"search-row\">\n <input\n class=\"search\"\n part=\"search\"\n type=\"text\"\n role=\"searchbox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n .placeholder=${this._localize.term('search') ?? ''}\n aria-controls=${this._listId}\n aria-activedescendant=${activeId ?? nothing}\n @input=${this._onSearchInput}\n />\n </div>`\n : nothing\n }\n\n <ul\n class=\"listbox\"\n part=\"listbox\"\n role=\"listbox\"\n id=${this._listId}\n tabindex=${this.searchable ? nothing : '0'}\n aria-label=${this.label || this._localize.term('suggestions')}\n aria-multiselectable=${this.multiple ? 'true' : nothing}\n aria-activedescendant=${!this.searchable ? (activeId ?? nothing) : nothing}\n data-nav=${this._nav.keyboard ? 'keyboard' : 'pointer'}\n @pointermove=${this._nav.onPointerMove}\n @pointerleave=${this._nav.onPointerLeave}\n >\n ${filtered.map(\n (item, i) =>\n html`<li\n class=\"option\"\n part=\"option\"\n id=${this._nav.optionId(i)}\n role=\"option\"\n aria-selected=${this._values.includes(item.value) ? 'true' : 'false'}\n aria-disabled=${item.disabled ? 'true' : nothing}\n data-active=${i === activeIndex ? '' : nothing}\n data-current=${this._values.includes(item.value) ? '' : nothing}\n @pointerdown=${(e: Event) => e.preventDefault()}\n @click=${() => this._select(item)}\n >\n ${\n item.html\n ? unsafeHTML(this._richHighlighter.highlight(item.html, this._query))\n : html`<span class=\"option-label\"\n >${highlightText(item.label, this._query)}</span\n >`\n }\n </li>`,\n )}\n </ul>\n ${\n filtered.length === 0\n ? html`<div\n class=\"empty\"\n part=\"empty\"\n >\n ${this._localize.term('noResults')}\n </div>`\n : nothing\n }\n </div>\n\n <div\n class=${cls('visually-hidden')}\n aria-live=\"polite\"\n >\n ${status}\n </div>\n </div>\n `;\n }\n}\n\n// Typed addEventListener for the colliding `change` / `input` names.\nexport interface Select {\n addEventListener<K extends keyof SelectEventMap>(\n type: K,\n listener: (this: Select, ev: SelectEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener<K extends keyof SelectEventMap>(\n type: K,\n listener: (this: Select, ev: SelectEventMap[K]) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e}from"../../chunks/lit.js";import{n as t,r as n,t as r}from"../../chunks/decorate.js";import{a as i,t as a}from"../../chunks/lit-html.js";import{LuxenFormAssociatedElement as o}from"../../shared/luxen-form-associated-element.js";import{LocalizeController as s}from"../../shared/localize.js";import c from"../../shared/styles/host.styles.js";var l=e(`:host{--track-size:.375rem;--thumb-size:1.125rem;--_thumb-hit:1.5rem;--track-color:var(--l-color-bg-fill-neutral-subtle);--indicator-color:var(--l-form-control-activated-color);--thumb-color:var(--l-color-surface);inline-size:100%;display:block}:host([size=xs]){--track-size:.25rem;--thumb-size:.875rem}:host([size=sm]){--track-size:.3125rem;--thumb-size:1rem}:host([size=lg]){--track-size:.4375rem;--thumb-size:1.25rem}:host([size=xl]){--track-size:.5rem;--thumb-size:1.5rem}:host([disabled]){opacity:.5;pointer-events:none}.base{inline-size:100%;min-block-size:var(--_thumb-hit);touch-action:none;align-items:center;display:flex;position:relative}.track{inline-size:100%;block-size:var(--track-size);background-color:var(--track-color);border-radius:999px;position:relative}.indicator{background-color:var(--indicator-color);border-radius:inherit;position:absolute;inset-block:0;inset-inline-start:var(--start,0%);inset-inline-end:calc(100% - var(--end,0%))}.thumb{inline-size:var(--_thumb-hit);block-size:var(--_thumb-hit);cursor:grab;touch-action:none;place-items:center;display:grid;position:absolute;inset-block-start:50%;inset-inline-start:var(--pos,0%);translate:-50% -50%}.thumb:before{content:"";inline-size:var(--thumb-size);block-size:var(--thumb-size);background-color:var(--thumb-color);border:2px solid var(--indicator-color);box-shadow:var(--l-shadow-sm);border-radius:50%;transition:box-shadow .15s,scale .1s}.thumb:active{cursor:grabbing}.thumb:focus-visible{outline:none}.thumb:focus-visible:before{
|
|
1
|
+
import{i as e}from"../../chunks/lit.js";import{n as t,r as n,t as r}from"../../chunks/decorate.js";import{a as i,t as a}from"../../chunks/lit-html.js";import{LuxenFormAssociatedElement as o}from"../../shared/luxen-form-associated-element.js";import{LocalizeController as s}from"../../shared/localize.js";import c from"../../shared/styles/host.styles.js";var l=e(`:host{--track-size:.375rem;--thumb-size:1.125rem;--_thumb-hit:1.5rem;--track-color:var(--l-color-bg-fill-neutral-subtle);--indicator-color:var(--l-form-control-activated-color);--thumb-color:var(--l-color-surface);inline-size:100%;display:block}:host([size=xs]){--track-size:.25rem;--thumb-size:.875rem}:host([size=sm]){--track-size:.3125rem;--thumb-size:1rem}:host([size=lg]){--track-size:.4375rem;--thumb-size:1.25rem}:host([size=xl]){--track-size:.5rem;--thumb-size:1.5rem}:host([disabled]){opacity:.5;pointer-events:none}.base{inline-size:100%;min-block-size:var(--_thumb-hit);touch-action:none;align-items:center;display:flex;position:relative}.track{inline-size:100%;block-size:var(--track-size);background-color:var(--track-color);border-radius:999px;position:relative}.indicator{background-color:var(--indicator-color);border-radius:inherit;position:absolute;inset-block:0;inset-inline-start:var(--start,0%);inset-inline-end:calc(100% - var(--end,0%))}.thumb{inline-size:var(--_thumb-hit);block-size:var(--_thumb-hit);cursor:grab;touch-action:none;place-items:center;display:grid;position:absolute;inset-block-start:50%;inset-inline-start:var(--pos,0%);translate:-50% -50%}.thumb:before{content:"";inline-size:var(--thumb-size);block-size:var(--thumb-size);background-color:var(--thumb-color);border:2px solid var(--indicator-color);box-shadow:var(--l-shadow-sm);border-radius:50%;transition:box-shadow .15s,scale .1s}.thumb:active{cursor:grabbing}.thumb:focus-visible{outline:none}.thumb:focus-visible:before{outline:var(--l-focus-ring-width) solid var(--l-focus-ring-color);outline-offset:var(--l-focus-ring-offset)}.tooltip{background:var(--l-tooltip-background-color);color:oklch(from var(--l-tooltip-background-color) calc(.59 - .41 * sign(l - .5)) 0 0);font-variant-numeric:tabular-nums;white-space:nowrap;pointer-events:none;opacity:0;border-radius:4px;padding:.125rem .4rem;font-size:.75rem;line-height:1.5;transition:opacity .12s,scale .12s;position:absolute;inset-block-end:calc(100% + .25rem);inset-inline-start:50%;translate:-50%;scale:.85}@supports (color:contrast-color(red vs black, white)){.tooltip{color:contrast-color(var(--l-tooltip-background-color) vs #111827, #fff to AA)}}.tooltip:after{content:"";border:4px solid #0000;border-block-start-color:var(--l-tooltip-background-color);position:absolute;inset-block-start:100%;inset-inline-start:50%;translate:-50% -1px}:host([with-tooltip]) .thumb:focus-visible .tooltip,:host([with-tooltip]) .thumb[data-active] .tooltip{opacity:1;scale:1}@media (prefers-reduced-motion:reduce){.tooltip{transition-duration:0s}}:host([orientation=vertical]){--length:11rem;inline-size:auto;display:inline-block}:host([orientation=vertical]) .base{inline-size:var(--_thumb-hit);min-inline-size:var(--_thumb-hit);block-size:var(--length);flex-direction:column}:host([orientation=vertical]) .track{inline-size:var(--track-size);block-size:100%}:host([orientation=vertical]) .indicator{inset-block:auto;inset-inline:0;inset-block-start:calc(100% - var(--end,0%));inset-block-end:var(--start,0%)}:host([orientation=vertical]) .thumb{inset-block-start:auto;inset-block-end:var(--pos,0%);inset-inline-start:50%;translate:-50% 50%}:host([orientation=vertical]) .tooltip{inset-block:50% auto;inset-inline:auto calc(100% + .25rem);translate:0 -50%}:host([orientation=vertical]) .tooltip:after{border-block-start-color:#0000;border-inline-start-color:var(--l-tooltip-background-color);inset-block-start:50%;inset-inline-start:100%;translate:-1px -50%}@media (hover:hover){.thumb:hover:before{scale:1.08}}@media (prefers-reduced-motion:reduce){.thumb:before{transition-duration:0s}}`),u=class extends Event{constructor(e){super(`input`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e[0]??0,this.values=e}},d=class extends Event{constructor(e){super(`change`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e[0]??0,this.values=e}},f=class extends o{constructor(...e){super(...e),this._localize=new s(this),this.#e=0,this.#t=100,this.#n=1,this.#r=0,this.#i=!1,this.#a=0,this.#o=100,this.#s=``,this.#c=`md`,this.#l=`horizontal`,this.#u=!1,this.#d=null}static{this.styles=[c,l]}#e;get min(){return this.#e}set min(e){this.#e=e}#t;get max(){return this.#t}set max(e){this.#t=e}#n;get step(){return this.#n}set step(e){this.#n=e}#r;get value(){return this.#r}set value(e){this.#r=e}#i;get range(){return this.#i}set range(e){this.#i=e}#a;get minValue(){return this.#a}set minValue(e){this.#a=e}#o;get maxValue(){return this.#o}set maxValue(e){this.#o=e}#s;get label(){return this.#s}set label(e){this.#s=e}#c;get size(){return this.#c}set size(e){this.#c=e}#l;get orientation(){return this.#l}set orientation(e){this.#l=e}#u;get withTooltip(){return this.#u}set withTooltip(e){this.#u=e}#d;get _activeThumb(){return this.#d}set _activeThumb(e){this.#d=e}connectedCallback(){super.connectedCallback(),this._defaultFormValue=this._serialize(),this._syncForm()}willUpdate(e){(e.has(`min`)||e.has(`max`)||e.has(`value`)||e.has(`minValue`)||e.has(`maxValue`)||e.has(`range`))&&(this.range?(this.minValue=this._clamp(this.minValue),this.maxValue=this._clamp(this.maxValue),this.minValue>this.maxValue&&(this._activeThumb===`max`?this.maxValue=this.minValue:this.minValue=this.maxValue)):this.value=this._clamp(this.value))}updated(){this._syncForm()}formResetCallback(){let[e,t]=this._parse(this._defaultFormValue);this.range?(this.minValue=e,this.maxValue=t):this.value=e,super.formResetCallback()}formStateRestoreCallback(e){let[t,n]=this._parse(e);this.range?(this.minValue=t,this.maxValue=n):this.value=t}_clamp(e){let t=this.min,n=this.max,r=this.step>0?this.step:1,i=Math.round((e-t)/r)*r+t;return Math.min(Math.max(i,t),n)}_percent(e){let t=this.max-this.min;return t>0?(e-this.min)/t*100:0}get values(){return this.range?[this.minValue,this.maxValue]:[this.value]}_serialize(){return this.range?`${this.minValue},${this.maxValue}`:String(this.value)}_parse(e){let t=e.split(`,`).map(Number);return[t[0]??this.min,t[1]??this.max]}_syncForm(){if(this.range){let e=new FormData;this.name&&(e.append(this.name,String(this.minValue)),e.append(this.name,String(this.maxValue))),this._internals.setFormValue(e)}else this._syncFormValue(String(this.value))}_set(e,t,n){let r=this._clamp(t);e===`min`?this.minValue=Math.min(r,this.maxValue):e===`max`?this.maxValue=Math.max(r,this.minValue):this.value=r,this.hasInteracted=!0,this.dispatchEvent(new u(this.values)),n&&this.dispatchEvent(new d(this.values))}_valueOf(e){return e===`min`?this.minValue:e===`max`?this.maxValue:this.value}_format(e){return this.valueFormatter?this.valueFormatter(e):String(e)}_onKeyDown(e,t){if(this.disabled)return;let n=this.step>0?this.step:1,r=Math.max(n,(this.max-this.min)/10),i=this._valueOf(e),a;switch(t.key){case`ArrowRight`:case`ArrowUp`:a=i+n;break;case`ArrowLeft`:case`ArrowDown`:a=i-n;break;case`PageUp`:a=i+r;break;case`PageDown`:a=i-r;break;case`Home`:a=this.min;break;case`End`:a=this.max;break;default:return}t.preventDefault(),this._set(e,a,!0)}_onPointerDown(e){if(this.disabled||e.button!==0)return;let t=this.shadowRoot?.querySelector(`.track`);if(!t)return;let n=this._valueFromPointer(t,e),r=this.range?Math.abs(n-this.minValue)<=Math.abs(n-this.maxValue)?`min`:`max`:`value`;this._activeThumb=r,this._set(r,n,!1),this._focusThumb(r);let i=e=>this._set(r,this._valueFromPointer(t,e),!1),a=()=>{window.removeEventListener(`pointermove`,i),window.removeEventListener(`pointerup`,a),this._activeThumb=null,this.dispatchEvent(new d(this.values))};window.addEventListener(`pointermove`,i),window.addEventListener(`pointerup`,a)}_valueFromPointer(e,t){let n=e.getBoundingClientRect(),r=this.orientation===`vertical`?n.height>0?(n.bottom-t.clientY)/n.height:0:n.width>0?(t.clientX-n.left)/n.width:0;return this.min+r*(this.max-this.min)}_focusThumb(e){let t=e===`value`?`.thumb`:`.thumb[data-thumb="${e}"]`;(this.shadowRoot?.querySelector(t))?.focus()}_renderThumb(e,t){let n=this._valueOf(e);return i`<span
|
|
2
2
|
class="thumb"
|
|
3
3
|
part="thumb"
|
|
4
4
|
data-thumb=${e}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slider.js","names":["unsafeCSS","rawStyles","hostStyles","nothing","_decorate","property","state","r","r$1","__decorate","b","A","host_styles_default","styles","SliderInputEvent","values","SliderChangeEvent","Slider","LuxenFormAssociatedElement","_args","LocalizeController","#_min_accessor_storage","#_max_accessor_storage","#_step_accessor_storage","#_value_accessor_storage","#_range_accessor_storage","#_minValue_accessor_storage","#_maxValue_accessor_storage","#_label_accessor_storage","#_size_accessor_storage","#_orientation_accessor_storage","#_withTooltip_accessor_storage","#__activeThumb_accessor_storage","value","changed","lo","hi","state","min","max","step","stepped","v","span","parts","s","data","next","raw","thumb","commit","big","current","e","track","valueAt","move","ev","up","rect","ratio","sel","ariaLabel","start","end","thumbLabel","term"],"sources":["../../../src/html/elements/slider/slider.css?inline","../../../src/html/elements/slider/slider.ts"],"sourcesContent":["/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆂🅻🅸🅳🅴🆁 (shadow)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n- https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/\n\nshadcn-flavoured: a thin neutral rail, a high-contrast (primary) filled\nindicator, and circular white thumbs with a primary border + focus ring. The\nthumb's hit box is ≥24px (WCAG 2.5.8) while the visible disc stays smaller.\n*/\n\n:host {\n --track-size: 0.375rem;\n --thumb-size: 1.125rem;\n /* The hit target never drops below 24px even though the disc is smaller. */\n --_thumb-hit: 1.5rem;\n\n --track-color: var(--l-color-bg-fill-neutral-subtle);\n /* The active fill reads the shared form-control accent — same token the\n switch / checkbox / radio use — so the slider stays consistent and\n responds to a themed `--l-form-control-activated-color`. */\n --indicator-color: var(--l-form-control-activated-color);\n --thumb-color: var(--l-color-surface);\n\n display: block;\n inline-size: 100%;\n}\n\n:host([size='xs']) {\n --track-size: 0.25rem;\n --thumb-size: 0.875rem;\n}\n:host([size='sm']) {\n --track-size: 0.3125rem;\n --thumb-size: 1rem;\n}\n:host([size='lg']) {\n --track-size: 0.4375rem;\n --thumb-size: 1.25rem;\n}\n:host([size='xl']) {\n --track-size: 0.5rem;\n --thumb-size: 1.5rem;\n}\n\n/* Disabled: faded, like the checked checkbox and the on switch. The thumb is a\n disc ringed in the accent sitting on an accent-filled indicator — a mark on a\n fill, which is the case the fade is for. Repainting it in neutral tokens keeps\n the thumb crisper, but a grey bar across the full width reads as a styled,\n still-live control, and it drops the accent tint every other faded control\n keeps. Consistency wins here: see checkbox-appearance.css for the trade. */\n:host([disabled]) {\n opacity: 0.5;\n pointer-events: none;\n}\n\n.base {\n position: relative;\n display: flex;\n align-items: center;\n inline-size: 100%;\n min-block-size: var(--_thumb-hit);\n touch-action: none;\n}\n\n.track {\n position: relative;\n inline-size: 100%;\n block-size: var(--track-size);\n background-color: var(--track-color);\n border-radius: 999px;\n}\n\n.indicator {\n position: absolute;\n inset-block: 0;\n inset-inline-start: var(--start, 0%);\n inset-inline-end: calc(100% - var(--end, 0%));\n background-color: var(--indicator-color);\n border-radius: inherit;\n}\n\n.thumb {\n position: absolute;\n inset-inline-start: var(--pos, 0%);\n inset-block-start: 50%;\n inline-size: var(--_thumb-hit);\n block-size: var(--_thumb-hit);\n translate: -50% -50%;\n display: grid;\n place-items: center;\n cursor: grab;\n touch-action: none;\n}\n\n.thumb::before {\n content: '';\n inline-size: var(--thumb-size);\n block-size: var(--thumb-size);\n border-radius: 50%;\n background-color: var(--thumb-color);\n border: 2px solid var(--indicator-color);\n box-shadow: var(--l-shadow-sm);\n transition:\n box-shadow 0.15s ease,\n scale 0.1s ease;\n}\n\n.thumb:active {\n cursor: grabbing;\n}\n\n.thumb:focus-visible {\n outline: none;\n}\n\n.thumb:focus-visible::before {\n box-shadow: 0 0 0 3px color-mix(in oklab, var(--l-focus-ring) 45%, transparent);\n}\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆃🅾🅾🅻🆃🅸🅿 (with-tooltip)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\nReuses the l-tooltip bubble tokens. Shown only when the host has `with-tooltip`\nand the thumb is keyboard-focused or being dragged (`[data-active]`).\n*/\n\n.tooltip {\n position: absolute;\n inset-block-end: calc(100% + 0.25rem);\n inset-inline-start: 50%;\n translate: -50% 0;\n padding: 0.125rem 0.4rem;\n border-radius: 4px;\n background: var(--l-tooltip-background-color);\n color: oklch(from var(--l-tooltip-background-color) calc(0.59 - 0.41 * sign(l - 0.5)) 0 0);\n font-size: 0.75rem;\n line-height: 1.5;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n scale: 0.85;\n transition:\n opacity 0.12s ease,\n scale 0.12s ease;\n}\n\n@supports (color: contrast-color(red vs black, white)) {\n .tooltip {\n color: contrast-color(var(--l-tooltip-background-color) vs #111827, #fff to AA);\n }\n}\n\n/* Little caret under the bubble. */\n.tooltip::after {\n content: '';\n position: absolute;\n inset-block-start: 100%;\n inset-inline-start: 50%;\n translate: -50% -1px;\n border: 4px solid transparent;\n border-block-start-color: var(--l-tooltip-background-color);\n}\n\n:host([with-tooltip]) .thumb:focus-visible .tooltip,\n:host([with-tooltip]) .thumb[data-active] .tooltip {\n opacity: 1;\n scale: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tooltip {\n transition-duration: 0ms;\n }\n}\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆅🅴🆁🆃🅸🅲🅰🅻\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\nThe same `--start` / `--end` / `--pos` percentages (low→high) drive the block\naxis instead of the inline axis; the value increases upward. Height defaults to\n`--length` (override per instance).\n*/\n\n:host([orientation='vertical']) {\n --length: 11rem;\n display: inline-block;\n inline-size: auto;\n}\n\n:host([orientation='vertical']) .base {\n flex-direction: column;\n inline-size: var(--_thumb-hit);\n min-inline-size: var(--_thumb-hit);\n block-size: var(--length);\n}\n\n:host([orientation='vertical']) .track {\n inline-size: var(--track-size);\n block-size: 100%;\n}\n\n:host([orientation='vertical']) .indicator {\n inset-block: auto;\n inset-inline: 0;\n inset-block-end: var(--start, 0%);\n inset-block-start: calc(100% - var(--end, 0%));\n}\n\n:host([orientation='vertical']) .thumb {\n inset-inline-start: 50%;\n inset-block-start: auto;\n inset-block-end: var(--pos, 0%);\n translate: -50% 50%;\n}\n\n/* In vertical mode the bubble sits to the inline-start with a side caret. */\n:host([orientation='vertical']) .tooltip {\n inset-block-end: auto;\n inset-block-start: 50%;\n inset-inline-start: auto;\n inset-inline-end: calc(100% + 0.25rem);\n translate: 0 -50%;\n}\n\n:host([orientation='vertical']) .tooltip::after {\n inset-block-start: 50%;\n inset-inline-start: 100%;\n translate: -1px -50%;\n border-block-start-color: transparent;\n border-inline-start-color: var(--l-tooltip-background-color);\n}\n\n@media (hover: hover) {\n .thumb:hover::before {\n scale: 1.08;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .thumb::before {\n transition-duration: 0ms;\n }\n}\n","import { html, nothing, unsafeCSS } from 'lit';\nimport type { PropertyValues } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { LuxenFormAssociatedElement } from '../../shared/luxen-form-associated-element.js';\nimport { LocalizeController } from '../../shared/localize.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './slider.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\nexport type SliderSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\nexport type SliderOrientation = 'horizontal' | 'vertical';\n\ntype Thumb = 'min' | 'max' | 'value';\n\n/** Fired continuously while a thumb is dragged or stepped. Bubbles; not composed. */\nexport class SliderInputEvent extends Event {\n /** Value of the (first) thumb. */\n readonly value: number;\n /** All thumb values, low to high. One entry in single mode, two in range mode. */\n readonly values: number[];\n constructor(values: number[]) {\n super('input', { bubbles: true, composed: false, cancelable: false });\n this.value = values[0] ?? 0;\n this.values = values;\n }\n}\n\n/** Fired when a thumb is released after a change. Bubbles; not composed. */\nexport class SliderChangeEvent extends Event {\n /** Value of the (first) thumb. */\n readonly value: number;\n /** All thumb values, low to high. One entry in single mode, two in range mode. */\n readonly values: number[];\n constructor(values: number[]) {\n super('change', { bubbles: true, composed: false, cancelable: false });\n this.value = values[0] ?? 0;\n this.values = values;\n }\n}\n\ninterface SliderEventMap {\n input: SliderInputEvent;\n change: SliderChangeEvent;\n}\n\n/**\n * A single- or dual-thumb range slider. Pick a numeric value, or a min–max\n * range with `range`. Form-associated: the value is submitted under `name`\n * (range mode submits the low and high values as two entries).\n *\n * @summary Pick a numeric value or a min–max range by dragging a thumb.\n *\n * @example\n * ```html\n * <l-slider label=\"Volume\" min=\"0\" max=\"100\" value=\"40\" name=\"volume\"></l-slider>\n * ```\n *\n * @example Range (min–max)\n * ```html\n * <l-slider label=\"Price\" range min=\"0\" max=\"100\" min-value=\"20\" max-value=\"70\" name=\"price\"></l-slider>\n * ```\n *\n * @event input - Fired continuously while a thumb moves. Bubbles. Not cancelable. Properties: `value: number`, `values: number[]`.\n * @event change - Fired when a thumb is released. Bubbles. Not cancelable. Properties: `value: number`, `values: number[]`.\n *\n * @csspart base - The slider container.\n * @csspart track - The full-width rail.\n * @csspart indicator - The filled portion of the rail.\n * @csspart thumb - Each draggable thumb.\n * @csspart tooltip - The value tooltip shown above a thumb when `with-tooltip` is set.\n *\n * @cssproperty [--track-size] - Thickness of the rail.\n * @cssproperty [--thumb-size] - Diameter of each thumb.\n * @cssproperty [--track-color] - Color of the unfilled rail.\n * @cssproperty [--indicator-color] - Color of the filled portion.\n * @cssproperty [--thumb-color] - Background color of the thumbs.\n *\n * @customElement l-slider\n */\n// oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- typed addEventListener overloads merged below; no uninitialized properties.\nexport class Slider extends LuxenFormAssociatedElement {\n static override styles = [hostStyles, styles];\n\n private _localize = new LocalizeController(this);\n\n /** Minimum value. */\n @property({ type: Number, reflect: true })\n accessor min = 0;\n\n /** Maximum value. */\n @property({ type: Number, reflect: true })\n accessor max = 100;\n\n /** Step increment. */\n @property({ type: Number, reflect: true })\n accessor step = 1;\n\n /** Single-thumb value. */\n @property({ type: Number, reflect: true })\n accessor value = 0;\n\n /** Enable a two-thumb min–max range. */\n @property({ type: Boolean, reflect: true })\n accessor range = false;\n\n /** Lower value (range mode). */\n @property({ type: Number, reflect: true, attribute: 'min-value' })\n accessor minValue = 0;\n\n /** Upper value (range mode). */\n @property({ type: Number, reflect: true, attribute: 'max-value' })\n accessor maxValue = 100;\n\n /** Accessible label for the slider (and base for the range thumbs' names). */\n @property()\n accessor label = '';\n\n /** Control size. */\n @property({ reflect: true })\n accessor size: SliderSize = 'md';\n\n /** Layout axis. Vertical sliders increase upward. */\n @property({ reflect: true })\n accessor orientation: SliderOrientation = 'horizontal';\n\n /** Show a tooltip with the current value while a thumb is focused or dragged. */\n @property({ type: Boolean, reflect: true, attribute: 'with-tooltip' })\n accessor withTooltip = false;\n\n /**\n * Formats a value for the tooltip and the `aria-valuetext` announcement.\n * Assign a function `(value: number) => string`, e.g. to add a unit or currency.\n */\n valueFormatter?: (value: number) => string;\n\n /** The thumb currently being dragged, or null. */\n @state() private accessor _activeThumb: Thumb | null = null;\n\n override connectedCallback() {\n super.connectedCallback();\n this._defaultFormValue = this._serialize();\n this._syncForm();\n }\n\n override willUpdate(changed: PropertyValues<this>) {\n // Keep values inside [min, max] and, in range mode, ordered low ≤ high.\n if (\n changed.has('min') ||\n changed.has('max') ||\n changed.has('value') ||\n changed.has('minValue') ||\n changed.has('maxValue') ||\n changed.has('range')\n ) {\n if (this.range) {\n this.minValue = this._clamp(this.minValue);\n this.maxValue = this._clamp(this.maxValue);\n if (this.minValue > this.maxValue) {\n // The thumb the user is NOT dragging holds its ground.\n if (this._activeThumb === 'max') this.maxValue = this.minValue;\n else this.minValue = this.maxValue;\n }\n } else {\n this.value = this._clamp(this.value);\n }\n }\n }\n\n override updated() {\n this._syncForm();\n }\n\n override formResetCallback() {\n const [lo, hi] = this._parse(this._defaultFormValue);\n if (this.range) {\n this.minValue = lo;\n this.maxValue = hi;\n } else {\n this.value = lo;\n }\n super.formResetCallback();\n }\n\n override formStateRestoreCallback(state: string) {\n const [lo, hi] = this._parse(state);\n if (this.range) {\n this.minValue = lo;\n this.maxValue = hi;\n } else {\n this.value = lo;\n }\n }\n\n // --- Value helpers ---\n\n private _clamp(v: number): number {\n const min = this.min;\n const max = this.max;\n const step = this.step > 0 ? this.step : 1;\n const stepped = Math.round((v - min) / step) * step + min;\n return Math.min(Math.max(stepped, min), max);\n }\n\n private _percent(v: number): number {\n const span = this.max - this.min;\n return span > 0 ? ((v - this.min) / span) * 100 : 0;\n }\n\n /** Current thumb values, low to high. */\n get values(): number[] {\n return this.range ? [this.minValue, this.maxValue] : [this.value];\n }\n\n private _serialize(): string {\n return this.range ? `${this.minValue},${this.maxValue}` : String(this.value);\n }\n\n private _parse(s: string): [number, number] {\n const parts = s.split(',').map(Number);\n return [parts[0] ?? this.min, parts[1] ?? this.max];\n }\n\n private _syncForm() {\n if (this.range) {\n const data = new FormData();\n if (this.name) {\n data.append(this.name, String(this.minValue));\n data.append(this.name, String(this.maxValue));\n }\n this._internals.setFormValue(data);\n } else {\n this._syncFormValue(String(this.value));\n }\n }\n\n // --- Mutations ---\n\n private _set(thumb: Thumb, raw: number, commit: boolean) {\n const next = this._clamp(raw);\n if (thumb === 'min') {\n this.minValue = Math.min(next, this.maxValue);\n } else if (thumb === 'max') {\n this.maxValue = Math.max(next, this.minValue);\n } else {\n this.value = next;\n }\n this.hasInteracted = true;\n this.dispatchEvent(new SliderInputEvent(this.values));\n if (commit) this.dispatchEvent(new SliderChangeEvent(this.values));\n }\n\n private _valueOf(thumb: Thumb): number {\n if (thumb === 'min') return this.minValue;\n if (thumb === 'max') return this.maxValue;\n return this.value;\n }\n\n private _format(v: number): string {\n return this.valueFormatter ? this.valueFormatter(v) : String(v);\n }\n\n // --- Keyboard (APG slider pattern) ---\n\n private _onKeyDown(thumb: Thumb, e: KeyboardEvent) {\n if (this.disabled) return;\n const step = this.step > 0 ? this.step : 1;\n const big = Math.max(step, (this.max - this.min) / 10);\n const current = this._valueOf(thumb);\n let next: number | undefined;\n\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + step;\n break;\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - step;\n break;\n case 'PageUp':\n next = current + big;\n break;\n case 'PageDown':\n next = current - big;\n break;\n case 'Home':\n next = this.min;\n break;\n case 'End':\n next = this.max;\n break;\n default:\n return;\n }\n e.preventDefault();\n this._set(thumb, next, true);\n }\n\n // --- Pointer drag ---\n\n private _onPointerDown(e: PointerEvent) {\n if (this.disabled || e.button !== 0) return;\n const track = this.shadowRoot?.querySelector('.track') as HTMLElement | undefined;\n if (!track) return;\n\n const valueAt = this._valueFromPointer(track, e);\n const thumb: Thumb = this.range\n ? Math.abs(valueAt - this.minValue) <= Math.abs(valueAt - this.maxValue)\n ? 'min'\n : 'max'\n : 'value';\n\n this._activeThumb = thumb;\n this._set(thumb, valueAt, false);\n this._focusThumb(thumb);\n\n const move = (ev: PointerEvent) => this._set(thumb, this._valueFromPointer(track, ev), false);\n const up = () => {\n window.removeEventListener('pointermove', move);\n window.removeEventListener('pointerup', up);\n this._activeThumb = null;\n this.dispatchEvent(new SliderChangeEvent(this.values));\n };\n window.addEventListener('pointermove', move);\n window.addEventListener('pointerup', up);\n }\n\n private _valueFromPointer(track: HTMLElement, e: PointerEvent): number {\n const rect = track.getBoundingClientRect();\n // Vertical sliders increase upward: top edge is max, bottom edge is min.\n const ratio =\n this.orientation === 'vertical'\n ? rect.height > 0\n ? (rect.bottom - e.clientY) / rect.height\n : 0\n : rect.width > 0\n ? (e.clientX - rect.left) / rect.width\n : 0;\n return this.min + ratio * (this.max - this.min);\n }\n\n private _focusThumb(thumb: Thumb) {\n const sel = thumb === 'value' ? '.thumb' : `.thumb[data-thumb=\"${thumb}\"]`;\n (this.shadowRoot?.querySelector(sel) as HTMLElement | undefined)?.focus();\n }\n\n // --- Render ---\n\n private _renderThumb(thumb: Thumb, ariaLabel: string) {\n const v = this._valueOf(thumb);\n return html`<span\n class=\"thumb\"\n part=\"thumb\"\n data-thumb=${thumb}\n role=\"slider\"\n tabindex=${this.disabled ? -1 : 0}\n aria-label=${ariaLabel || nothing}\n aria-valuemin=${this.min}\n aria-valuemax=${this.max}\n aria-valuenow=${v}\n aria-valuetext=${this.valueFormatter ? this._format(v) : nothing}\n aria-orientation=${this.orientation}\n aria-disabled=${this.disabled ? 'true' : nothing}\n ?data-active=${this._activeThumb === thumb}\n style=\"--pos:${this._percent(v)}%\"\n @keydown=${(e: KeyboardEvent) => this._onKeyDown(thumb, e)}\n >\n <span\n class=\"tooltip\"\n part=\"tooltip\"\n aria-hidden=\"true\"\n >${this._format(v)}</span\n >\n </span>`;\n }\n\n override render() {\n const start = this.range ? this._percent(this.minValue) : 0;\n const end = this.range ? this._percent(this.maxValue) : this._percent(this.value);\n const thumbLabel = (term: 'rangeMinimum' | 'rangeMaximum') =>\n this.label ? `${this.label} ${this._localize.term(term)}` : this._localize.term(term);\n\n return html`\n <div\n class=\"base\"\n part=\"base\"\n role=\"group\"\n aria-label=${this.label || nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n @pointerdown=${this._onPointerDown}\n >\n <div\n class=\"track\"\n part=\"track\"\n >\n <div\n class=\"indicator\"\n part=\"indicator\"\n style=\"--start:${start}%;--end:${end}%\"\n ></div>\n </div>\n ${\n this.range\n ? html`${this._renderThumb('min', thumbLabel('rangeMinimum'))}${this._renderThumb(\n 'max',\n thumbLabel('rangeMaximum'),\n )}`\n : this._renderThumb('value', this.label)\n }\n </div>\n `;\n }\n}\n\n// Types `addEventListener('input' | 'change', …)` on this element (the global\n// event map can't be augmented for the colliding names). See input-stepper.ts\n// for the full rationale.\nexport interface Slider {\n addEventListener<K extends keyof SliderEventMap>(\n type: K,\n listener: (this: Slider, ev: SliderEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener<K extends keyof SliderEventMap>(\n type: K,\n listener: (this: Slider, ev: SliderEventMap[K]) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"slider.js","names":["unsafeCSS","rawStyles","hostStyles","nothing","_decorate","property","state","r","r$1","__decorate","b","A","host_styles_default","styles","SliderInputEvent","values","SliderChangeEvent","Slider","LuxenFormAssociatedElement","_args","LocalizeController","#_min_accessor_storage","#_max_accessor_storage","#_step_accessor_storage","#_value_accessor_storage","#_range_accessor_storage","#_minValue_accessor_storage","#_maxValue_accessor_storage","#_label_accessor_storage","#_size_accessor_storage","#_orientation_accessor_storage","#_withTooltip_accessor_storage","#__activeThumb_accessor_storage","value","changed","lo","hi","state","min","max","step","stepped","v","span","parts","s","data","next","raw","thumb","commit","big","current","e","track","valueAt","move","ev","up","rect","ratio","sel","ariaLabel","start","end","thumbLabel","term"],"sources":["../../../src/html/elements/slider/slider.css?inline","../../../src/html/elements/slider/slider.ts"],"sourcesContent":["/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆂🅻🅸🅳🅴🆁 (shadow)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n- https://www.w3.org/WAI/ARIA/apg/patterns/slider-multithumb/\n\nshadcn-flavoured: a thin neutral rail, a high-contrast (primary) filled\nindicator, and circular white thumbs with a primary border + focus ring. The\nthumb's hit box is ≥24px (WCAG 2.5.8) while the visible disc stays smaller.\n*/\n\n:host {\n --track-size: 0.375rem;\n --thumb-size: 1.125rem;\n /* The hit target never drops below 24px even though the disc is smaller. */\n --_thumb-hit: 1.5rem;\n\n --track-color: var(--l-color-bg-fill-neutral-subtle);\n /* The active fill reads the shared form-control accent — same token the\n switch / checkbox / radio use — so the slider stays consistent and\n responds to a themed `--l-form-control-activated-color`. */\n --indicator-color: var(--l-form-control-activated-color);\n --thumb-color: var(--l-color-surface);\n\n display: block;\n inline-size: 100%;\n}\n\n:host([size='xs']) {\n --track-size: 0.25rem;\n --thumb-size: 0.875rem;\n}\n:host([size='sm']) {\n --track-size: 0.3125rem;\n --thumb-size: 1rem;\n}\n:host([size='lg']) {\n --track-size: 0.4375rem;\n --thumb-size: 1.25rem;\n}\n:host([size='xl']) {\n --track-size: 0.5rem;\n --thumb-size: 1.5rem;\n}\n\n/* Disabled: faded, like the checked checkbox and the on switch. The thumb is a\n disc ringed in the accent sitting on an accent-filled indicator — a mark on a\n fill, which is the case the fade is for. Repainting it in neutral tokens keeps\n the thumb crisper, but a grey bar across the full width reads as a styled,\n still-live control, and it drops the accent tint every other faded control\n keeps. Consistency wins here: see checkbox-appearance.css for the trade. */\n:host([disabled]) {\n opacity: 0.5;\n pointer-events: none;\n}\n\n.base {\n position: relative;\n display: flex;\n align-items: center;\n inline-size: 100%;\n min-block-size: var(--_thumb-hit);\n touch-action: none;\n}\n\n.track {\n position: relative;\n inline-size: 100%;\n block-size: var(--track-size);\n background-color: var(--track-color);\n border-radius: 999px;\n}\n\n.indicator {\n position: absolute;\n inset-block: 0;\n inset-inline-start: var(--start, 0%);\n inset-inline-end: calc(100% - var(--end, 0%));\n background-color: var(--indicator-color);\n border-radius: inherit;\n}\n\n.thumb {\n position: absolute;\n inset-inline-start: var(--pos, 0%);\n inset-block-start: 50%;\n inline-size: var(--_thumb-hit);\n block-size: var(--_thumb-hit);\n translate: -50% -50%;\n display: grid;\n place-items: center;\n cursor: grab;\n touch-action: none;\n}\n\n.thumb::before {\n content: '';\n inline-size: var(--thumb-size);\n block-size: var(--thumb-size);\n border-radius: 50%;\n background-color: var(--thumb-color);\n border: 2px solid var(--indicator-color);\n box-shadow: var(--l-shadow-sm);\n transition:\n box-shadow 0.15s ease,\n scale 0.1s ease;\n}\n\n.thumb:active {\n cursor: grabbing;\n}\n\n.thumb:focus-visible {\n outline: none;\n}\n\n/* The ring goes on the visible disc, not on the larger hit box. An outline, not\n a box-shadow halo: it keeps full contrast and survives forced colors, where\n box-shadows are dropped. */\n.thumb:focus-visible::before {\n outline: var(--l-focus-ring-width) solid var(--l-focus-ring-color);\n outline-offset: var(--l-focus-ring-offset);\n}\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆃🅾🅾🅻🆃🅸🅿 (with-tooltip)\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\nReuses the l-tooltip bubble tokens. Shown only when the host has `with-tooltip`\nand the thumb is keyboard-focused or being dragged (`[data-active]`).\n*/\n\n.tooltip {\n position: absolute;\n inset-block-end: calc(100% + 0.25rem);\n inset-inline-start: 50%;\n translate: -50% 0;\n padding: 0.125rem 0.4rem;\n border-radius: 4px;\n background: var(--l-tooltip-background-color);\n color: oklch(from var(--l-tooltip-background-color) calc(0.59 - 0.41 * sign(l - 0.5)) 0 0);\n font-size: 0.75rem;\n line-height: 1.5;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n scale: 0.85;\n transition:\n opacity 0.12s ease,\n scale 0.12s ease;\n}\n\n@supports (color: contrast-color(red vs black, white)) {\n .tooltip {\n color: contrast-color(var(--l-tooltip-background-color) vs #111827, #fff to AA);\n }\n}\n\n/* Little caret under the bubble. */\n.tooltip::after {\n content: '';\n position: absolute;\n inset-block-start: 100%;\n inset-inline-start: 50%;\n translate: -50% -1px;\n border: 4px solid transparent;\n border-block-start-color: var(--l-tooltip-background-color);\n}\n\n:host([with-tooltip]) .thumb:focus-visible .tooltip,\n:host([with-tooltip]) .thumb[data-active] .tooltip {\n opacity: 1;\n scale: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .tooltip {\n transition-duration: 0ms;\n }\n}\n\n/*\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\n 🆅🅴🆁🆃🅸🅲🅰🅻\n▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬\nThe same `--start` / `--end` / `--pos` percentages (low→high) drive the block\naxis instead of the inline axis; the value increases upward. Height defaults to\n`--length` (override per instance).\n*/\n\n:host([orientation='vertical']) {\n --length: 11rem;\n display: inline-block;\n inline-size: auto;\n}\n\n:host([orientation='vertical']) .base {\n flex-direction: column;\n inline-size: var(--_thumb-hit);\n min-inline-size: var(--_thumb-hit);\n block-size: var(--length);\n}\n\n:host([orientation='vertical']) .track {\n inline-size: var(--track-size);\n block-size: 100%;\n}\n\n:host([orientation='vertical']) .indicator {\n inset-block: auto;\n inset-inline: 0;\n inset-block-end: var(--start, 0%);\n inset-block-start: calc(100% - var(--end, 0%));\n}\n\n:host([orientation='vertical']) .thumb {\n inset-inline-start: 50%;\n inset-block-start: auto;\n inset-block-end: var(--pos, 0%);\n translate: -50% 50%;\n}\n\n/* In vertical mode the bubble sits to the inline-start with a side caret. */\n:host([orientation='vertical']) .tooltip {\n inset-block-end: auto;\n inset-block-start: 50%;\n inset-inline-start: auto;\n inset-inline-end: calc(100% + 0.25rem);\n translate: 0 -50%;\n}\n\n:host([orientation='vertical']) .tooltip::after {\n inset-block-start: 50%;\n inset-inline-start: 100%;\n translate: -1px -50%;\n border-block-start-color: transparent;\n border-inline-start-color: var(--l-tooltip-background-color);\n}\n\n@media (hover: hover) {\n .thumb:hover::before {\n scale: 1.08;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .thumb::before {\n transition-duration: 0ms;\n }\n}\n","import { html, nothing, unsafeCSS } from 'lit';\nimport type { PropertyValues } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { LuxenFormAssociatedElement } from '../../shared/luxen-form-associated-element.js';\nimport { LocalizeController } from '../../shared/localize.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './slider.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\nexport type SliderSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\nexport type SliderOrientation = 'horizontal' | 'vertical';\n\ntype Thumb = 'min' | 'max' | 'value';\n\n/** Fired continuously while a thumb is dragged or stepped. Bubbles; not composed. */\nexport class SliderInputEvent extends Event {\n /** Value of the (first) thumb. */\n readonly value: number;\n /** All thumb values, low to high. One entry in single mode, two in range mode. */\n readonly values: number[];\n constructor(values: number[]) {\n super('input', { bubbles: true, composed: false, cancelable: false });\n this.value = values[0] ?? 0;\n this.values = values;\n }\n}\n\n/** Fired when a thumb is released after a change. Bubbles; not composed. */\nexport class SliderChangeEvent extends Event {\n /** Value of the (first) thumb. */\n readonly value: number;\n /** All thumb values, low to high. One entry in single mode, two in range mode. */\n readonly values: number[];\n constructor(values: number[]) {\n super('change', { bubbles: true, composed: false, cancelable: false });\n this.value = values[0] ?? 0;\n this.values = values;\n }\n}\n\ninterface SliderEventMap {\n input: SliderInputEvent;\n change: SliderChangeEvent;\n}\n\n/**\n * A single- or dual-thumb range slider. Pick a numeric value, or a min–max\n * range with `range`. Form-associated: the value is submitted under `name`\n * (range mode submits the low and high values as two entries).\n *\n * @summary Pick a numeric value or a min–max range by dragging a thumb.\n *\n * @example\n * ```html\n * <l-slider label=\"Volume\" min=\"0\" max=\"100\" value=\"40\" name=\"volume\"></l-slider>\n * ```\n *\n * @example Range (min–max)\n * ```html\n * <l-slider label=\"Price\" range min=\"0\" max=\"100\" min-value=\"20\" max-value=\"70\" name=\"price\"></l-slider>\n * ```\n *\n * @event input - Fired continuously while a thumb moves. Bubbles. Not cancelable. Properties: `value: number`, `values: number[]`.\n * @event change - Fired when a thumb is released. Bubbles. Not cancelable. Properties: `value: number`, `values: number[]`.\n *\n * @csspart base - The slider container.\n * @csspart track - The full-width rail.\n * @csspart indicator - The filled portion of the rail.\n * @csspart thumb - Each draggable thumb.\n * @csspart tooltip - The value tooltip shown above a thumb when `with-tooltip` is set.\n *\n * @cssproperty [--track-size] - Thickness of the rail.\n * @cssproperty [--thumb-size] - Diameter of each thumb.\n * @cssproperty [--track-color] - Color of the unfilled rail.\n * @cssproperty [--indicator-color] - Color of the filled portion.\n * @cssproperty [--thumb-color] - Background color of the thumbs.\n *\n * @customElement l-slider\n */\n// oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- typed addEventListener overloads merged below; no uninitialized properties.\nexport class Slider extends LuxenFormAssociatedElement {\n static override styles = [hostStyles, styles];\n\n private _localize = new LocalizeController(this);\n\n /** Minimum value. */\n @property({ type: Number, reflect: true })\n accessor min = 0;\n\n /** Maximum value. */\n @property({ type: Number, reflect: true })\n accessor max = 100;\n\n /** Step increment. */\n @property({ type: Number, reflect: true })\n accessor step = 1;\n\n /** Single-thumb value. */\n @property({ type: Number, reflect: true })\n accessor value = 0;\n\n /** Enable a two-thumb min–max range. */\n @property({ type: Boolean, reflect: true })\n accessor range = false;\n\n /** Lower value (range mode). */\n @property({ type: Number, reflect: true, attribute: 'min-value' })\n accessor minValue = 0;\n\n /** Upper value (range mode). */\n @property({ type: Number, reflect: true, attribute: 'max-value' })\n accessor maxValue = 100;\n\n /** Accessible label for the slider (and base for the range thumbs' names). */\n @property()\n accessor label = '';\n\n /** Control size. */\n @property({ reflect: true })\n accessor size: SliderSize = 'md';\n\n /** Layout axis. Vertical sliders increase upward. */\n @property({ reflect: true })\n accessor orientation: SliderOrientation = 'horizontal';\n\n /** Show a tooltip with the current value while a thumb is focused or dragged. */\n @property({ type: Boolean, reflect: true, attribute: 'with-tooltip' })\n accessor withTooltip = false;\n\n /**\n * Formats a value for the tooltip and the `aria-valuetext` announcement.\n * Assign a function `(value: number) => string`, e.g. to add a unit or currency.\n */\n valueFormatter?: (value: number) => string;\n\n /** The thumb currently being dragged, or null. */\n @state() private accessor _activeThumb: Thumb | null = null;\n\n override connectedCallback() {\n super.connectedCallback();\n this._defaultFormValue = this._serialize();\n this._syncForm();\n }\n\n override willUpdate(changed: PropertyValues<this>) {\n // Keep values inside [min, max] and, in range mode, ordered low ≤ high.\n if (\n changed.has('min') ||\n changed.has('max') ||\n changed.has('value') ||\n changed.has('minValue') ||\n changed.has('maxValue') ||\n changed.has('range')\n ) {\n if (this.range) {\n this.minValue = this._clamp(this.minValue);\n this.maxValue = this._clamp(this.maxValue);\n if (this.minValue > this.maxValue) {\n // The thumb the user is NOT dragging holds its ground.\n if (this._activeThumb === 'max') this.maxValue = this.minValue;\n else this.minValue = this.maxValue;\n }\n } else {\n this.value = this._clamp(this.value);\n }\n }\n }\n\n override updated() {\n this._syncForm();\n }\n\n override formResetCallback() {\n const [lo, hi] = this._parse(this._defaultFormValue);\n if (this.range) {\n this.minValue = lo;\n this.maxValue = hi;\n } else {\n this.value = lo;\n }\n super.formResetCallback();\n }\n\n override formStateRestoreCallback(state: string) {\n const [lo, hi] = this._parse(state);\n if (this.range) {\n this.minValue = lo;\n this.maxValue = hi;\n } else {\n this.value = lo;\n }\n }\n\n // --- Value helpers ---\n\n private _clamp(v: number): number {\n const min = this.min;\n const max = this.max;\n const step = this.step > 0 ? this.step : 1;\n const stepped = Math.round((v - min) / step) * step + min;\n return Math.min(Math.max(stepped, min), max);\n }\n\n private _percent(v: number): number {\n const span = this.max - this.min;\n return span > 0 ? ((v - this.min) / span) * 100 : 0;\n }\n\n /** Current thumb values, low to high. */\n get values(): number[] {\n return this.range ? [this.minValue, this.maxValue] : [this.value];\n }\n\n private _serialize(): string {\n return this.range ? `${this.minValue},${this.maxValue}` : String(this.value);\n }\n\n private _parse(s: string): [number, number] {\n const parts = s.split(',').map(Number);\n return [parts[0] ?? this.min, parts[1] ?? this.max];\n }\n\n private _syncForm() {\n if (this.range) {\n const data = new FormData();\n if (this.name) {\n data.append(this.name, String(this.minValue));\n data.append(this.name, String(this.maxValue));\n }\n this._internals.setFormValue(data);\n } else {\n this._syncFormValue(String(this.value));\n }\n }\n\n // --- Mutations ---\n\n private _set(thumb: Thumb, raw: number, commit: boolean) {\n const next = this._clamp(raw);\n if (thumb === 'min') {\n this.minValue = Math.min(next, this.maxValue);\n } else if (thumb === 'max') {\n this.maxValue = Math.max(next, this.minValue);\n } else {\n this.value = next;\n }\n this.hasInteracted = true;\n this.dispatchEvent(new SliderInputEvent(this.values));\n if (commit) this.dispatchEvent(new SliderChangeEvent(this.values));\n }\n\n private _valueOf(thumb: Thumb): number {\n if (thumb === 'min') return this.minValue;\n if (thumb === 'max') return this.maxValue;\n return this.value;\n }\n\n private _format(v: number): string {\n return this.valueFormatter ? this.valueFormatter(v) : String(v);\n }\n\n // --- Keyboard (APG slider pattern) ---\n\n private _onKeyDown(thumb: Thumb, e: KeyboardEvent) {\n if (this.disabled) return;\n const step = this.step > 0 ? this.step : 1;\n const big = Math.max(step, (this.max - this.min) / 10);\n const current = this._valueOf(thumb);\n let next: number | undefined;\n\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowUp':\n next = current + step;\n break;\n case 'ArrowLeft':\n case 'ArrowDown':\n next = current - step;\n break;\n case 'PageUp':\n next = current + big;\n break;\n case 'PageDown':\n next = current - big;\n break;\n case 'Home':\n next = this.min;\n break;\n case 'End':\n next = this.max;\n break;\n default:\n return;\n }\n e.preventDefault();\n this._set(thumb, next, true);\n }\n\n // --- Pointer drag ---\n\n private _onPointerDown(e: PointerEvent) {\n if (this.disabled || e.button !== 0) return;\n const track = this.shadowRoot?.querySelector('.track') as HTMLElement | undefined;\n if (!track) return;\n\n const valueAt = this._valueFromPointer(track, e);\n const thumb: Thumb = this.range\n ? Math.abs(valueAt - this.minValue) <= Math.abs(valueAt - this.maxValue)\n ? 'min'\n : 'max'\n : 'value';\n\n this._activeThumb = thumb;\n this._set(thumb, valueAt, false);\n this._focusThumb(thumb);\n\n const move = (ev: PointerEvent) => this._set(thumb, this._valueFromPointer(track, ev), false);\n const up = () => {\n window.removeEventListener('pointermove', move);\n window.removeEventListener('pointerup', up);\n this._activeThumb = null;\n this.dispatchEvent(new SliderChangeEvent(this.values));\n };\n window.addEventListener('pointermove', move);\n window.addEventListener('pointerup', up);\n }\n\n private _valueFromPointer(track: HTMLElement, e: PointerEvent): number {\n const rect = track.getBoundingClientRect();\n // Vertical sliders increase upward: top edge is max, bottom edge is min.\n const ratio =\n this.orientation === 'vertical'\n ? rect.height > 0\n ? (rect.bottom - e.clientY) / rect.height\n : 0\n : rect.width > 0\n ? (e.clientX - rect.left) / rect.width\n : 0;\n return this.min + ratio * (this.max - this.min);\n }\n\n private _focusThumb(thumb: Thumb) {\n const sel = thumb === 'value' ? '.thumb' : `.thumb[data-thumb=\"${thumb}\"]`;\n (this.shadowRoot?.querySelector(sel) as HTMLElement | undefined)?.focus();\n }\n\n // --- Render ---\n\n private _renderThumb(thumb: Thumb, ariaLabel: string) {\n const v = this._valueOf(thumb);\n return html`<span\n class=\"thumb\"\n part=\"thumb\"\n data-thumb=${thumb}\n role=\"slider\"\n tabindex=${this.disabled ? -1 : 0}\n aria-label=${ariaLabel || nothing}\n aria-valuemin=${this.min}\n aria-valuemax=${this.max}\n aria-valuenow=${v}\n aria-valuetext=${this.valueFormatter ? this._format(v) : nothing}\n aria-orientation=${this.orientation}\n aria-disabled=${this.disabled ? 'true' : nothing}\n ?data-active=${this._activeThumb === thumb}\n style=\"--pos:${this._percent(v)}%\"\n @keydown=${(e: KeyboardEvent) => this._onKeyDown(thumb, e)}\n >\n <span\n class=\"tooltip\"\n part=\"tooltip\"\n aria-hidden=\"true\"\n >${this._format(v)}</span\n >\n </span>`;\n }\n\n override render() {\n const start = this.range ? this._percent(this.minValue) : 0;\n const end = this.range ? this._percent(this.maxValue) : this._percent(this.value);\n const thumbLabel = (term: 'rangeMinimum' | 'rangeMaximum') =>\n this.label ? `${this.label} ${this._localize.term(term)}` : this._localize.term(term);\n\n return html`\n <div\n class=\"base\"\n part=\"base\"\n role=\"group\"\n aria-label=${this.label || nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n @pointerdown=${this._onPointerDown}\n >\n <div\n class=\"track\"\n part=\"track\"\n >\n <div\n class=\"indicator\"\n part=\"indicator\"\n style=\"--start:${start}%;--end:${end}%\"\n ></div>\n </div>\n ${\n this.range\n ? html`${this._renderThumb('min', thumbLabel('rangeMinimum'))}${this._renderThumb(\n 'max',\n thumbLabel('rangeMaximum'),\n )}`\n : this._renderThumb('value', this.label)\n }\n </div>\n `;\n }\n}\n\n// Types `addEventListener('input' | 'change', …)` on this element (the global\n// event map can't be augmented for the colliding names). See input-stepper.ts\n// for the full rationale.\nexport interface Slider {\n addEventListener<K extends keyof SliderEventMap>(\n type: K,\n listener: (this: Slider, ev: SliderEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ): void;\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n removeEventListener<K extends keyof SliderEventMap>(\n type: K,\n listener: (this: Slider, ev: SliderEventMap[K]) => void,\n options?: boolean | EventListenerOptions,\n ): void;\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n}\n"],"mappings":"A,kWCQA,IAAMa,EAASb,EAAUC,gjHAAS,EAQrBa,EAAb,cAAsC,KAAM,CAK1C,YAAY,EAAkB,CAC5B,MAAM,QAAS,CAAE,QAAS,GAAM,SAAU,GAAO,WAAY,EAAM,CAAC,EACpE,KAAK,MAAQC,EAAO,IAAM,EAC1B,KAAK,OAASA,CAChB,CACF,EAGaC,EAAb,cAAuC,KAAM,CAK3C,YAAY,EAAkB,CAC5B,MAAM,SAAU,CAAE,QAAS,GAAM,SAAU,GAAO,WAAY,EAAM,CAAC,EACrE,KAAK,MAAQD,EAAO,IAAM,EAC1B,KAAK,OAASA,CAChB,CACF,EA0CaE,EAAb,cAA4BC,CAA2B,C,8BAGjC,KAAA,UAAA,IAAIE,EAAmB,IAAI,EAIhC,KAAAC,GAAA,EAIA,KAAAC,GAAA,IAIC,KAAAC,GAAA,EAIC,KAAAC,GAAA,EAIA,KAAAC,GAAA,GAIG,KAAAC,GAAA,EAIA,KAAAC,GAAA,IAIH,KAAAC,GAAA,GAIW,KAAAC,GAAA,KAIc,KAAAC,GAAA,aAInB,KAAAC,GAAA,GASgC,KAAAC,GAAA,I,QAvD9B,KAAA,OAAA,CAAC9B,EAAYW,CAAM,C,IAMnC,IAAA,KAAA,C,uCAIA,IAAA,KAAA,C,uCAIA,IAAA,MAAA,C,wCAIA,IAAA,OAAA,C,yCAIA,IAAA,OAAA,C,yCAIA,IAAA,UAAA,C,4CAIA,IAAA,UAAA,C,4CAIA,IAAA,OAAA,C,yCAIA,IAAA,MAAA,C,wCAIA,IAAA,aAAA,C,+CAIA,IAAA,aAAA,C,+CASiB,IAAA,cAAA,C,6CAE1B,mBAA6B,CAC3B,MAAM,kBAAkB,EACxB,KAAK,kBAAoB,KAAK,WAAW,EACzC,KAAK,UAAU,CACjB,CAEA,WAAoB,EAA+B,EAG/CqB,EAAQ,IAAI,KAAK,GACjBA,EAAQ,IAAI,KAAK,GACjBA,EAAQ,IAAI,OAAO,GACnBA,EAAQ,IAAI,UAAU,GACtBA,EAAQ,IAAI,UAAU,GACtBA,EAAQ,IAAI,OAAO,KAEf,KAAK,OACP,KAAK,SAAW,KAAK,OAAO,KAAK,QAAQ,EACzC,KAAK,SAAW,KAAK,OAAO,KAAK,QAAQ,EACrC,KAAK,SAAW,KAAK,WAEnB,KAAK,eAAiB,MAAO,KAAK,SAAW,KAAK,SACjD,KAAK,SAAW,KAAK,WAG5B,KAAK,MAAQ,KAAK,OAAO,KAAK,KAAK,EAGzC,CAEA,SAAmB,CACjB,KAAK,UAAU,CACjB,CAEA,mBAA6B,CAC3B,GAAM,CAACC,EAAIC,GAAM,KAAK,OAAO,KAAK,iBAAiB,EAC/C,KAAK,OACP,KAAK,SAAWD,EAChB,KAAK,SAAWC,GAEhB,KAAK,MAAQD,EAEf,MAAM,kBAAkB,CAC1B,CAEA,yBAAkC,EAAe,CAC/C,GAAM,CAACA,EAAIC,GAAM,KAAK,OAAOC,CAAK,EAC9B,KAAK,OACP,KAAK,SAAWF,EAChB,KAAK,SAAWC,GAEhB,KAAK,MAAQD,CAEjB,CAIA,OAAe,EAAmB,CAChC,IAAMG,EAAM,KAAK,IACXC,EAAM,KAAK,IACXC,EAAO,KAAK,KAAO,EAAI,KAAK,KAAO,EACnCC,EAAU,KAAK,OAAOC,EAAIJ,GAAOE,CAAI,EAAIA,EAAOF,EACtD,OAAO,KAAK,IAAI,KAAK,IAAIG,EAASH,CAAG,EAAGC,CAAG,CAC7C,CAEA,SAAiB,EAAmB,CAClC,IAAMI,EAAO,KAAK,IAAM,KAAK,IAC7B,OAAOA,EAAO,GAAMD,EAAI,KAAK,KAAOC,EAAQ,IAAM,CACpD,CAGA,IAAI,QAAmB,CACrB,OAAO,KAAK,MAAQ,CAAC,KAAK,SAAU,KAAK,QAAQ,EAAI,CAAC,KAAK,KAAK,CAClE,CAEA,YAA6B,CAC3B,OAAO,KAAK,MAAQ,GAAG,KAAK,SAAS,GAAG,KAAK,WAAa,OAAO,KAAK,KAAK,CAC7E,CAEA,OAAe,EAA6B,CAC1C,IAAMC,EAAQC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,EACrC,MAAO,CAACD,EAAM,IAAM,KAAK,IAAKA,EAAM,IAAM,KAAK,GAAG,CACpD,CAEA,WAAoB,CAClB,GAAI,KAAK,MAAO,CACd,IAAME,EAAO,IAAI,SACb,KAAK,OACPA,EAAK,OAAO,KAAK,KAAM,OAAO,KAAK,QAAQ,CAAC,EAC5CA,EAAK,OAAO,KAAK,KAAM,OAAO,KAAK,QAAQ,CAAC,GAE9C,KAAK,WAAW,aAAaA,CAAI,CACnC,MACE,KAAK,eAAe,OAAO,KAAK,KAAK,CAAC,CAE1C,CAIA,KAAa,EAAc,EAAa,EAAiB,CACvD,IAAMC,EAAO,KAAK,OAAOC,CAAG,EACxBC,IAAU,MACZ,KAAK,SAAW,KAAK,IAAIF,EAAM,KAAK,QAAQ,EACnCE,IAAU,MACnB,KAAK,SAAW,KAAK,IAAIF,EAAM,KAAK,QAAQ,EAE5C,KAAK,MAAQA,EAEf,KAAK,cAAgB,GACrB,KAAK,cAAc,IAAIjC,EAAiB,KAAK,MAAM,CAAC,EAChDoC,GAAQ,KAAK,cAAc,IAAIlC,EAAkB,KAAK,MAAM,CAAC,CACnE,CAEA,SAAiB,EAAsB,CAGrC,OAFIiC,IAAU,MAAc,KAAK,SAC7BA,IAAU,MAAc,KAAK,SAC1B,KAAK,KACd,CAEA,QAAgB,EAAmB,CACjC,OAAO,KAAK,eAAiB,KAAK,eAAeP,CAAC,EAAI,OAAOA,CAAC,CAChE,CAIA,WAAmB,EAAc,EAAkB,CACjD,GAAI,KAAK,SAAU,OACnB,IAAMF,EAAO,KAAK,KAAO,EAAI,KAAK,KAAO,EACnCW,EAAM,KAAK,IAAIX,GAAO,KAAK,IAAM,KAAK,KAAO,EAAE,EAC/CY,EAAU,KAAK,SAASH,CAAK,EAC/BF,EAEJ,OAAQM,EAAE,IAAV,CACE,IAAK,aACL,IAAK,UACH,EAAOD,EAAUZ,EACjB,MACF,IAAK,YACL,IAAK,YACH,EAAOY,EAAUZ,EACjB,MACF,IAAK,SACH,EAAOY,EAAUD,EACjB,MACF,IAAK,WACH,EAAOC,EAAUD,EACjB,MACF,IAAK,OACH,EAAO,KAAK,IACZ,MACF,IAAK,MACH,EAAO,KAAK,IACZ,MACF,QACE,MACJ,CACAE,EAAE,eAAe,EACjB,KAAK,KAAKJ,EAAOF,EAAM,EAAI,CAC7B,CAIA,eAAuB,EAAiB,CACtC,GAAI,KAAK,UAAY,EAAE,SAAW,EAAG,OACrC,IAAMO,EAAQ,KAAK,YAAY,cAAc,QAAQ,EACrD,GAAI,CAACA,EAAO,OAEZ,IAAMC,EAAU,KAAK,kBAAkBD,EAAO,CAAC,EACzCL,EAAe,KAAK,MACtB,KAAK,IAAIM,EAAU,KAAK,QAAQ,GAAK,KAAK,IAAIA,EAAU,KAAK,QAAQ,EACnE,MACA,MACF,QAEJ,KAAK,aAAeN,EACpB,KAAK,KAAKA,EAAOM,EAAS,EAAK,EAC/B,KAAK,YAAYN,CAAK,EAEtB,IAAMO,EAAQ,GAAqB,KAAK,KAAKP,EAAO,KAAK,kBAAkBK,EAAOG,CAAE,EAAG,EAAK,EACtFC,MAAW,CACf,OAAO,oBAAoB,cAAeF,CAAI,EAC9C,OAAO,oBAAoB,YAAaE,CAAE,EAC1C,KAAK,aAAe,KACpB,KAAK,cAAc,IAAI1C,EAAkB,KAAK,MAAM,CAAC,CACvD,EACA,OAAO,iBAAiB,cAAewC,CAAI,EAC3C,OAAO,iBAAiB,YAAaE,CAAE,CACzC,CAEA,kBAA0B,EAAoB,EAAyB,CACrE,IAAMC,EAAOL,EAAM,sBAAsB,EAEnCM,EACJ,KAAK,cAAgB,WACjBD,EAAK,OAAS,GACXA,EAAK,OAASN,EAAE,SAAWM,EAAK,OACjC,EACFA,EAAK,MAAQ,GACVN,EAAE,QAAUM,EAAK,MAAQA,EAAK,MAC/B,EACR,OAAO,KAAK,IAAMC,GAAS,KAAK,IAAM,KAAK,IAC7C,CAEA,YAAoB,EAAc,CAChC,IAAMC,EAAMZ,IAAU,QAAU,SAAW,sBAAsBA,EAAM,KACtE,KAAK,YAAY,cAAcY,CAAG,EAAA,EAA+B,MAAM,CAC1E,CAIA,aAAqB,EAAc,EAAmB,CACpD,IAAMnB,EAAI,KAAK,SAASO,CAAK,EAC7B,MAAO,EAAI;;;mBAGIA,EAAM;;iBAER,KAAK,SAAW,GAAK,EAAE;mBACrBa,GAAa3D,EAAQ;sBAClB,KAAK,IAAI;sBACT,KAAK,IAAI;sBACTuC,EAAE;uBACD,KAAK,eAAiB,KAAK,QAAQA,CAAC,EAAIvC,EAAQ;yBAC9C,KAAK,YAAY;sBACpB,KAAK,SAAW,OAASA,EAAQ;qBAClC,KAAK,eAAiB8C,EAAM;qBAC5B,KAAK,SAASP,CAAC,EAAE;iBACpB,GAAqB,KAAK,WAAWO,EAAOI,CAAC,EAAE;;;;;;WAMtD,KAAK,QAAQX,CAAC,EAAE;;YAGzB,CAEA,QAAkB,CAChB,IAAMqB,EAAQ,KAAK,MAAQ,KAAK,SAAS,KAAK,QAAQ,EAAI,EACpDC,EAAM,KAAK,MAAQ,KAAK,SAAS,KAAK,QAAQ,EAAI,KAAK,SAAS,KAAK,KAAK,EAC1EC,EAAc,GAClB,KAAK,MAAQ,GAAG,KAAK,MAAM,GAAG,KAAK,UAAU,KAAKC,CAAI,IAAM,KAAK,UAAU,KAAKA,CAAI,EAEtF,MAAO,EAAI;;;;;qBAKM,KAAK,OAAS/D,EAAQ;wBACnB,KAAK,SAAW,OAASA,EAAQ;uBAClC,KAAK,eAAe;;;;;;;;;6BASd4D,EAAM,UAAUC,EAAI;;;UAIvC,KAAK,MACD,CAAI,GAAG,KAAK,aAAa,MAAOC,EAAW,cAAc,CAAC,IAAI,KAAK,aACjE,MACAA,EAAW,cAAc,CAC3B,IACA,KAAK,aAAa,QAAS,KAAK,KAAK,EAC1C;;KAGP,CACF,EAtUG7D,EAAA,CAAAC,EAAS,CAAE,KAAM,OAAQ,QAAS,EAAK,CAAC,CAAA,EAAAY,EAAA,UAAA,MAAA,IAAA,EAIxCb,EAAA,CAAAC,EAAS,CAAE,KAAM,OAAQ,QAAS,EAAK,CAAC,CAAA,EAAAY,EAAA,UAAA,MAAA,IAAA,EAIxCb,EAAA,CAAAC,EAAS,CAAE,KAAM,OAAQ,QAAS,EAAK,CAAC,CAAA,EAAAY,EAAA,UAAA,OAAA,IAAA,EAIxCb,EAAA,CAAAC,EAAS,CAAE,KAAM,OAAQ,QAAS,EAAK,CAAC,CAAA,EAAAY,EAAA,UAAA,QAAA,IAAA,EAIxCb,EAAA,CAAAC,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAAY,EAAA,UAAA,QAAA,IAAA,EAIzCb,EAAA,CAAAC,EAAS,CAAE,KAAM,OAAQ,QAAS,GAAM,UAAW,WAAY,CAAC,CAAA,EAAAY,EAAA,UAAA,WAAA,IAAA,EAIhEb,EAAA,CAAAC,EAAS,CAAE,KAAM,OAAQ,QAAS,GAAM,UAAW,WAAY,CAAC,CAAA,EAAAY,EAAA,UAAA,WAAA,IAAA,EAIhEb,EAAA,CAAAC,EAAS,CAAA,EAAAY,EAAA,UAAA,QAAA,IAAA,EAITb,EAAA,CAAAC,EAAS,CAAE,QAAS,EAAK,CAAC,CAAA,EAAAY,EAAA,UAAA,OAAA,IAAA,EAI1Bb,EAAA,CAAAC,EAAS,CAAE,QAAS,EAAK,CAAC,CAAA,EAAAY,EAAA,UAAA,cAAA,IAAA,EAI1Bb,EAAA,CAAAC,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,UAAW,cAAe,CAAC,CAAA,EAAAY,EAAA,UAAA,cAAA,IAAA,EAUpEb,EAAA,CAAAE,EAAM,CAAA,EAAAW,EAAA,UAAA,eAAA,IAAA,E"}
|