@data-slot/combobox 0.2.43 → 0.2.44
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
CHANGED
|
@@ -102,6 +102,7 @@ Options can be passed via JavaScript or data attributes (JS takes precedence).
|
|
|
102
102
|
| `openOnFocus` | `data-open-on-focus` | `boolean` | `true` | Open popup when input is focused |
|
|
103
103
|
| `autoHighlight` | `data-auto-highlight` | `boolean` | `true` | Auto-highlight first visible item when filtering |
|
|
104
104
|
| `filter` | - | `function` | substring | Custom filter function |
|
|
105
|
+
| `itemToStringValue` | - | `(item: HTMLElement \| null, value: string \| null) => string` | item label | Custom text resolver for selected value shown in input |
|
|
105
106
|
| `side` | `data-side` | `"top" \| "bottom"` | `"bottom"` | Popup placement |
|
|
106
107
|
| `align` | `data-align` | `"start" \| "center" \| "end"` | `"start"` | Popup alignment |
|
|
107
108
|
| `sideOffset` | `data-side-offset` | `number` | `4` | Distance from input (px) |
|
|
@@ -128,6 +129,7 @@ interface ComboboxController {
|
|
|
128
129
|
clear(): void; // Clear selection
|
|
129
130
|
open(): void; // Open the popup
|
|
130
131
|
close(): void; // Close the popup
|
|
132
|
+
setItemToStringValue(itemToStringValue: ((item: HTMLElement | null, value: string | null) => string) | null): void;
|
|
131
133
|
destroy(): void; // Cleanup
|
|
132
134
|
}
|
|
133
135
|
```
|
|
@@ -162,6 +164,11 @@ root.dispatchEvent(new CustomEvent('combobox:set', {
|
|
|
162
164
|
root.dispatchEvent(new CustomEvent('combobox:set', {
|
|
163
165
|
detail: { open: true }
|
|
164
166
|
}));
|
|
167
|
+
|
|
168
|
+
// Set runtime selected-value text formatter
|
|
169
|
+
root.dispatchEvent(new CustomEvent('combobox:set', {
|
|
170
|
+
detail: { itemToStringValue: (item, value) => value ? value.toUpperCase() : '' }
|
|
171
|
+
}));
|
|
165
172
|
```
|
|
166
173
|
|
|
167
174
|
## Keyboard Navigation
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
type Side = "top" | "bottom";
|
|
4
4
|
/** Alignment of the content relative to the input */
|
|
5
5
|
type Align = "start" | "center" | "end";
|
|
6
|
+
type ComboboxItemToStringValue = (item: HTMLElement | null, value: string | null) => string;
|
|
6
7
|
interface ComboboxOptions {
|
|
7
8
|
/** Initial selected value */
|
|
8
9
|
defaultValue?: string;
|
|
@@ -28,6 +29,8 @@ interface ComboboxOptions {
|
|
|
28
29
|
autoHighlight?: boolean;
|
|
29
30
|
/** Custom filter function. Return true to show item. */
|
|
30
31
|
filter?: (inputValue: string, itemValue: string, itemLabel: string) => boolean;
|
|
32
|
+
/** Custom text resolver for the selected value shown in the input */
|
|
33
|
+
itemToStringValue?: ComboboxItemToStringValue;
|
|
31
34
|
/** @default "bottom" */
|
|
32
35
|
side?: Side;
|
|
33
36
|
/** @default "start" */
|
|
@@ -56,6 +59,8 @@ interface ComboboxController {
|
|
|
56
59
|
open(): void;
|
|
57
60
|
/** Close the popup */
|
|
58
61
|
close(): void;
|
|
62
|
+
/** Set or clear runtime selected-value text resolver */
|
|
63
|
+
setItemToStringValue(itemToStringValue: ComboboxItemToStringValue | null): void;
|
|
59
64
|
/** Cleanup all event listeners */
|
|
60
65
|
destroy(): void;
|
|
61
66
|
}
|
|
@@ -70,7 +75,7 @@ interface ComboboxController {
|
|
|
70
75
|
* - **Outbound** `combobox:input-change` (on root): Fires when user types.
|
|
71
76
|
* `event.detail: { inputValue: string }`
|
|
72
77
|
* - **Inbound** `combobox:set` (on root): Set value, open state, or input value.
|
|
73
|
-
* `event.detail: { value?: string | null, open?: boolean, inputValue?: string }`
|
|
78
|
+
* `event.detail: { value?: string | null, open?: boolean, inputValue?: string, itemToStringValue?: ComboboxItemToStringValue | null }`
|
|
74
79
|
*/
|
|
75
80
|
declare function createCombobox(root: Element, options?: ComboboxOptions): ComboboxController;
|
|
76
81
|
/**
|
|
@@ -79,4 +84,4 @@ declare function createCombobox(root: Element, options?: ComboboxOptions): Combo
|
|
|
79
84
|
*/
|
|
80
85
|
declare function create(scope?: ParentNode): ComboboxController[];
|
|
81
86
|
//#endregion
|
|
82
|
-
export { Align, ComboboxController, ComboboxOptions, Side, create, createCombobox };
|
|
87
|
+
export { Align, ComboboxController, ComboboxItemToStringValue, ComboboxOptions, Side, create, createCombobox };
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
type Side = "top" | "bottom";
|
|
4
4
|
/** Alignment of the content relative to the input */
|
|
5
5
|
type Align = "start" | "center" | "end";
|
|
6
|
+
type ComboboxItemToStringValue = (item: HTMLElement | null, value: string | null) => string;
|
|
6
7
|
interface ComboboxOptions {
|
|
7
8
|
/** Initial selected value */
|
|
8
9
|
defaultValue?: string;
|
|
@@ -28,6 +29,8 @@ interface ComboboxOptions {
|
|
|
28
29
|
autoHighlight?: boolean;
|
|
29
30
|
/** Custom filter function. Return true to show item. */
|
|
30
31
|
filter?: (inputValue: string, itemValue: string, itemLabel: string) => boolean;
|
|
32
|
+
/** Custom text resolver for the selected value shown in the input */
|
|
33
|
+
itemToStringValue?: ComboboxItemToStringValue;
|
|
31
34
|
/** @default "bottom" */
|
|
32
35
|
side?: Side;
|
|
33
36
|
/** @default "start" */
|
|
@@ -56,6 +59,8 @@ interface ComboboxController {
|
|
|
56
59
|
open(): void;
|
|
57
60
|
/** Close the popup */
|
|
58
61
|
close(): void;
|
|
62
|
+
/** Set or clear runtime selected-value text resolver */
|
|
63
|
+
setItemToStringValue(itemToStringValue: ComboboxItemToStringValue | null): void;
|
|
59
64
|
/** Cleanup all event listeners */
|
|
60
65
|
destroy(): void;
|
|
61
66
|
}
|
|
@@ -70,7 +75,7 @@ interface ComboboxController {
|
|
|
70
75
|
* - **Outbound** `combobox:input-change` (on root): Fires when user types.
|
|
71
76
|
* `event.detail: { inputValue: string }`
|
|
72
77
|
* - **Inbound** `combobox:set` (on root): Set value, open state, or input value.
|
|
73
|
-
* `event.detail: { value?: string | null, open?: boolean, inputValue?: string }`
|
|
78
|
+
* `event.detail: { value?: string | null, open?: boolean, inputValue?: string, itemToStringValue?: ComboboxItemToStringValue | null }`
|
|
74
79
|
*/
|
|
75
80
|
declare function createCombobox(root: Element, options?: ComboboxOptions): ComboboxController;
|
|
76
81
|
/**
|
|
@@ -79,4 +84,4 @@ declare function createCombobox(root: Element, options?: ComboboxOptions): Combo
|
|
|
79
84
|
*/
|
|
80
85
|
declare function create(scope?: ParentNode): ComboboxController[];
|
|
81
86
|
//#endregion
|
|
82
|
-
export { Align, ComboboxController, ComboboxOptions, Side, create, createCombobox };
|
|
87
|
+
export { Align, ComboboxController, ComboboxItemToStringValue, ComboboxOptions, Side, create, createCombobox };
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@data-slot/core`);const t=[`top`,`bottom`],n=[`start`,`center`,`end`];function r(r,a={}){let o=(0,e.getPart)(r,`combobox-input`),s=(0,e.getPart)(r,`combobox-content`),c=(0,e.getPart)(r,`combobox-list`)??(0,e.getPart)(s??r,`combobox-list`),l=(0,e.getPart)(r,`combobox-trigger`),u=(0,e.getPart)(c??s??r,`combobox-empty`);if(!o||!s)throw Error(`Combobox requires combobox-input and combobox-content slots`);let ee=a.defaultValue??(0,e.getDataString)(r,`defaultValue`)??null,d=a.defaultOpen??(0,e.getDataBool)(r,`defaultOpen`)??!1,f=a.placeholder??(0,e.getDataString)(r,`placeholder`)??``,p=a.disabled??(0,e.getDataBool)(r,`disabled`)??!1,m=a.required??(0,e.getDataBool)(r,`required`)??!1,h=a.name??(0,e.getDataString)(r,`name`)??null,te=a.openOnFocus??(0,e.getDataBool)(r,`openOnFocus`)??!0,g=a.autoHighlight??(0,e.getDataBool)(r,`autoHighlight`)??!0,
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@data-slot/core`);const t=[`top`,`bottom`],n=[`start`,`center`,`end`];function r(r,a={}){let o=(0,e.getPart)(r,`combobox-input`),s=(0,e.getPart)(r,`combobox-content`),c=(0,e.getPart)(r,`combobox-list`)??(0,e.getPart)(s??r,`combobox-list`),l=(0,e.getPart)(r,`combobox-trigger`),u=(0,e.getPart)(c??s??r,`combobox-empty`);if(!o||!s)throw Error(`Combobox requires combobox-input and combobox-content slots`);let ee=a.defaultValue??(0,e.getDataString)(r,`defaultValue`)??null,d=a.defaultOpen??(0,e.getDataBool)(r,`defaultOpen`)??!1,f=a.placeholder??(0,e.getDataString)(r,`placeholder`)??``,p=a.disabled??(0,e.getDataBool)(r,`disabled`)??!1,m=a.required??(0,e.getDataBool)(r,`required`)??!1,h=a.name??(0,e.getDataString)(r,`name`)??null,te=a.openOnFocus??(0,e.getDataBool)(r,`openOnFocus`)??!0,g=a.autoHighlight??(0,e.getDataBool)(r,`autoHighlight`)??!0,ne=a.filter??null,re=a.onValueChange,_=a.onOpenChange,ie=a.onInputValueChange,v=a.itemToStringValue??null,ae=a.side??(0,e.getDataEnum)(s,`side`,t)??(0,e.getDataEnum)(r,`side`,t)??`bottom`,oe=a.align??(0,e.getDataEnum)(s,`align`,n)??(0,e.getDataEnum)(r,`align`,n)??`start`,se=a.sideOffset??(0,e.getDataNumber)(s,`sideOffset`)??(0,e.getDataNumber)(r,`sideOffset`)??4,y=a.alignOffset??(0,e.getDataNumber)(s,`alignOffset`)??(0,e.getDataNumber)(r,`alignOffset`)??0,ce=a.avoidCollisions??(0,e.getDataBool)(s,`avoidCollisions`)??(0,e.getDataBool)(r,`avoidCollisions`)??!0,le=a.collisionPadding??(0,e.getDataNumber)(s,`collisionPadding`)??(0,e.getDataNumber)(r,`collisionPadding`)??8,b=!1,x=ee,S=-1,C=!1,w=[],T=[],E=[],D=[],O=new Map,k=null,A=(0,e.createPortalLifecycle)({content:s,root:r,wrapperSlot:`combobox-positioner`}),j=!1,M=e=>e.hasAttribute(`disabled`)||e.hasAttribute(`data-disabled`)||e.getAttribute(`aria-disabled`)===`true`,N=e=>{if(e.dataset.label)return e.dataset.label;let t=``;for(let n of e.childNodes)n.nodeType===Node.TEXT_NODE&&(t+=n.textContent);return t.trim()||(e.textContent?.trim()??``)},P=e=>e.hasAttribute(`data-value`)?e.getAttribute(`data-value`):void 0,ue=t=>t===null?null:(0,e.getParts)(c??s,`combobox-item`).find(e=>P(e)===t)??null,F=e=>{let t=ue(e);return v?v(t,e):t?N(t):``},de=(0,e.ensureId)(o,`combobox-input`),I=c??s,L=(0,e.ensureId)(I,`combobox-list`);o.setAttribute(`role`,`combobox`),o.setAttribute(`aria-autocomplete`,`list`),o.setAttribute(`autocomplete`,`off`),o.setAttribute(`aria-controls`,L),c?c.setAttribute(`role`,`listbox`):s.setAttribute(`role`,`listbox`),l&&(l.hasAttribute(`type`)||l.setAttribute(`type`,`button`),l.tabIndex=-1,l.setAttribute(`aria-label`,`Toggle`));let R=document.querySelector(`label[for="${CSS.escape(de)}"]`);if(R){let t=(0,e.ensureId)(R,`combobox-label`),n=o.getAttribute(`aria-labelledby`);o.setAttribute(`aria-labelledby`,n?`${n} ${t}`:t),I.setAttribute(`aria-labelledby`,t)}p&&(o.setAttribute(`aria-disabled`,`true`),o.disabled=!0,l&&(l.setAttribute(`aria-disabled`,`true`),l.setAttribute(`data-disabled`,``))),m&&(o.setAttribute(`aria-required`,`true`),o.required=!0);let z=()=>{m&&o.setCustomValidity(x===null?`Please select a value`:``)};f&&(o.placeholder=f),h&&(o.name&&o.removeAttribute(`name`),k=document.createElement(`input`),k.type=`hidden`,k.name=h,k.value=x??``,r.appendChild(k));let B=ne??((e,t,n)=>n.toLowerCase().includes(e.toLowerCase())),V=()=>{let t=c??s;T=(0,e.getParts)(t,`combobox-item`);for(let t of T)t.setAttribute(`role`,`option`),(0,e.ensureId)(t,`combobox-item`),M(t)?t.setAttribute(`aria-disabled`,`true`):t.removeAttribute(`aria-disabled`),P(t)===x?((0,e.setAria)(t,`selected`,!0),t.setAttribute(`data-selected`,``)):((0,e.setAria)(t,`selected`,!1),t.removeAttribute(`data-selected`));let n=(0,e.getParts)(t,`combobox-group`);for(let t of n){t.setAttribute(`role`,`group`);let n=(0,e.getPart)(t,`combobox-label`);if(n){let r=(0,e.ensureId)(n,`combobox-label`);t.setAttribute(`aria-labelledby`,r)}}H()},H=()=>{E=T.filter(e=>!e.hidden),D=E.filter(e=>!M(e)),O=new Map(D.map((e,t)=>[e,t]))},U=(e,t)=>{let n=t===`previous`?e.previousElementSibling:e.nextElementSibling;for(;n;){if(n instanceof HTMLElement&&!n.hidden&&n.dataset.slot!==`combobox-separator`)return!0;n=t===`previous`?n.previousElementSibling:n.nextElementSibling}return!1},W=t=>{let n=c??s,r=t.trim(),i=0;for(let e of T){let t=P(e)??``,n=N(e),a=r===``||B(r,t,n);e.hidden=!a,a&&i++}let a=(0,e.getParts)(n,`combobox-group`);for(let t of a)t.hidden=!(0,e.getParts)(t,`combobox-item`).some(e=>!e.hidden);let o=(0,e.getParts)(n,`combobox-separator`);for(let e of o)e.hidden=!U(e,`previous`)||!U(e,`next`);u&&(u.hidden=i>0),i===0?s.setAttribute(`data-empty`,``):s.removeAttribute(`data-empty`),H()},G=()=>{let n=A.container,i=r.ownerDocument.defaultView??window,a=r.getBoundingClientRect();s.style.minWidth=`${a.width}px`;let o=(0,e.computeFloatingPosition)({anchorRect:a,contentRect:s.getBoundingClientRect(),side:ae,align:oe,sideOffset:se,alignOffset:y,avoidCollisions:ce,collisionPadding:le,allowedSides:t});n.style.position=`absolute`,n.style.top=`0px`,n.style.left=`0px`,n.style.transform=`translate3d(${o.x+i.scrollX}px, ${o.y+i.scrollY}px, 0)`,n.style.willChange=`transform`,n.style.margin=`0`,s.setAttribute(`data-side`,o.side),s.setAttribute(`data-align`,o.align),n!==s&&(n.setAttribute(`data-side`,o.side),n.setAttribute(`data-align`,o.align))},K=(0,e.createPositionSync)({observedElements:[r,s],isActive:()=>b,ancestorScroll:!1,onUpdate:G,ignoreScrollTarget:e=>e instanceof Node&&s.contains(e)}),fe=e=>c&&c.contains(e)&&c.scrollHeight>c.clientHeight?c:s,q=t=>{for(let n=0;n<D.length;n++){let r=D[n];n===t?(r.setAttribute(`data-highlighted`,``),o.setAttribute(`aria-activedescendant`,r.id),(0,e.ensureItemVisibleInContainer)(r,fe(r))):r.removeAttribute(`data-highlighted`)}S=t},J=()=>{for(let e of T)e.removeAttribute(`data-highlighted`);S=-1,o.removeAttribute(`aria-activedescendant`)},Y=e=>{r.setAttribute(`data-state`,e),s.setAttribute(`data-state`,e),l&&l.setAttribute(`data-state`,e),e===`open`?(r.setAttribute(`data-open`,``),s.setAttribute(`data-open`,``),l&&l.setAttribute(`data-open`,``),r.removeAttribute(`data-closed`),s.removeAttribute(`data-closed`),l&&l.removeAttribute(`data-closed`)):(r.setAttribute(`data-closed`,``),s.setAttribute(`data-closed`,``),l&&l.setAttribute(`data-closed`,``),r.removeAttribute(`data-open`),s.removeAttribute(`data-open`),l&&l.removeAttribute(`data-open`))},X=(0,e.createPresenceLifecycle)({element:s,onExitComplete:()=>{j||(A.restore(),s.hidden=!0)}}),Z=(t,n=!1)=>{if(b!==t&&!(p&&t)){if(t){b=!0,(0,e.setAria)(o,`expanded`,!0),A.mount(),s.hidden=!1,Y(`open`),X.enter(),V(),C=!1,W(o.value);let t=D.findIndex(e=>P(e)===x);t>=0?q(t):g&&D.length>0?q(0):J(),K.start(),G(),K.update(),requestAnimationFrame(()=>{b&&K.update()})}else b=!1,(0,e.setAria)(o,`expanded`,!1),Y(`closed`),J(),C=!1,K.stop(),X.exit(),o.value=F(x);(0,e.emit)(r,`combobox:open-change`,{open:b}),_?.(b)}},Q=(t,n=!1)=>{if(x===t&&!n)return;let i=x;x=t,z(),k&&(k.value=t??``),t===null?r.removeAttribute(`data-value`):r.setAttribute(`data-value`,t);let a=c??s,l=T.length>0?T:(0,e.getParts)(a,`combobox-item`);for(let n of l)P(n)===t?((0,e.setAria)(n,`selected`,!0),n.setAttribute(`data-selected`,``)):((0,e.setAria)(n,`selected`,!1),n.removeAttribute(`data-selected`));o.value=F(t),!n&&i!==t&&((0,e.emit)(r,`combobox:change`,{value:t}),re?.(t))},$=e=>{if(M(e))return;let t=P(e);t!==void 0&&(Q(t),Z(!1))};return(0,e.setAria)(o,`expanded`,!1),s.hidden=!0,Y(`closed`),Q(x,!0),w.push((0,e.on)(o,`input`,()=>{let t=o.value;(0,e.emit)(r,`combobox:input-change`,{inputValue:t}),ie?.(t),b?(W(t),g&&D.length>0?q(0):J(),K.update()):Z(!0)}),(0,e.on)(o,`keydown`,e=>{if(!p)switch(e.key){case`ArrowDown`:{if(e.preventDefault(),!b){Z(!0);return}C=!0;let t=D.length;if(t===0)return;q(S===-1?0:(S+1)%t);break}case`ArrowUp`:{if(e.preventDefault(),!b){Z(!0);return}C=!0;let t=D.length;if(t===0)return;q(S===-1?t-1:(S-1+t)%t);break}case`Home`:if(!b)return;e.preventDefault(),C=!0,D.length>0&&q(0);break;case`End`:if(!b)return;e.preventDefault(),C=!0,D.length>0&&q(D.length-1);break;case`Enter`:if(!b)return;e.preventDefault(),S>=0&&S<D.length&&$(D[S]);break;case`Escape`:b?(e.preventDefault(),Z(!1)):x!==null&&(e.preventDefault(),Q(null));break;case`Tab`:b&&Z(!1,!0);break}}),(0,e.on)(o,`focus`,()=>{p||(o.select(),te&&!b&&Z(!0))})),l&&w.push((0,e.on)(l,`click`,()=>{p||(b?Z(!1):(Z(!0),o.focus()))})),w.push((0,e.on)(s,`click`,e=>{let t=e.target.closest?.(`[data-slot="combobox-item"]`);t&&!t.hidden&&$(t)}),(0,e.on)(s,`pointermove`,e=>{let t=e.target.closest?.(`[data-slot="combobox-item"]`);if(!(C&&(C=!1,t&&O.get(t)===S)))if(t&&!M(t)&&!t.hidden){let e=O.get(t);e!==void 0&&e!==S&&q(e)}else J()}),(0,e.on)(s,`pointerleave`,()=>{C||J()}),(0,e.on)(s,`mousedown`,e=>{e.preventDefault()})),w.push((0,e.createDismissLayer)({root:r,isOpen:()=>b,onDismiss:()=>Z(!1),closeOnClickOutside:!0,closeOnEscape:!1})),w.push((0,e.on)(r,`combobox:set`,e=>{let t=e.detail;t?.value!==void 0&&Q(t.value),t?.open!==void 0&&Z(t.open),t?.inputValue!==void 0&&(o.value=t.inputValue),t?.itemToStringValue!==void 0&&(v=t.itemToStringValue,o.value=F(x))})),d&&Z(!0),{get value(){return x},get inputValue(){return o.value},get isOpen(){return b},select:e=>Q(e),clear:()=>Q(null),open:()=>Z(!0),close:()=>Z(!1),setItemToStringValue:e=>{v=e,o.value=F(x)},destroy:()=>{j=!0,K.stop(),X.cleanup(),A.cleanup(),w.forEach(e=>e()),w.length=0,k&&k.parentNode&&k.parentNode.removeChild(k),i.delete(r)}}}const i=new WeakSet;function a(t=document){let n=[];for(let a of(0,e.getRoots)(t,`combobox`))i.has(a)||(i.add(a),n.push(r(a)));return n}exports.create=a,exports.createCombobox=r;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{computeFloatingPosition as e,createDismissLayer as t,createPortalLifecycle as n,createPositionSync as r,createPresenceLifecycle as i,emit as a,ensureId as o,ensureItemVisibleInContainer as ee,getDataBool as s,getDataEnum as c,getDataNumber as l,getDataString as u,getPart as d,getParts as f,getRoots as p,on as m,setAria as h}from"@data-slot/core";const g=[`top`,`bottom`],
|
|
1
|
+
import{computeFloatingPosition as e,createDismissLayer as t,createPortalLifecycle as n,createPositionSync as r,createPresenceLifecycle as i,emit as a,ensureId as o,ensureItemVisibleInContainer as ee,getDataBool as s,getDataEnum as c,getDataNumber as l,getDataString as u,getPart as d,getParts as f,getRoots as p,on as m,setAria as h}from"@data-slot/core";const g=[`top`,`bottom`],te=[`start`,`center`,`end`];function _(p,_={}){let y=d(p,`combobox-input`),b=d(p,`combobox-content`),x=d(p,`combobox-list`)??d(b??p,`combobox-list`),S=d(p,`combobox-trigger`),ne=d(x??b??p,`combobox-empty`);if(!y||!b)throw Error(`Combobox requires combobox-input and combobox-content slots`);let re=_.defaultValue??u(p,`defaultValue`)??null,ie=_.defaultOpen??s(p,`defaultOpen`)??!1,C=_.placeholder??u(p,`placeholder`)??``,w=_.disabled??s(p,`disabled`)??!1,T=_.required??s(p,`required`)??!1,E=_.name??u(p,`name`)??null,ae=_.openOnFocus??s(p,`openOnFocus`)??!0,D=_.autoHighlight??s(p,`autoHighlight`)??!0,oe=_.filter??null,se=_.onValueChange,ce=_.onOpenChange,le=_.onInputValueChange,O=_.itemToStringValue??null,ue=_.side??c(b,`side`,g)??c(p,`side`,g)??`bottom`,de=_.align??c(b,`align`,te)??c(p,`align`,te)??`start`,fe=_.sideOffset??l(b,`sideOffset`)??l(p,`sideOffset`)??4,pe=_.alignOffset??l(b,`alignOffset`)??l(p,`alignOffset`)??0,me=_.avoidCollisions??s(b,`avoidCollisions`)??s(p,`avoidCollisions`)??!0,he=_.collisionPadding??l(b,`collisionPadding`)??l(p,`collisionPadding`)??8,k=!1,A=re,j=-1,M=!1,N=[],P=[],F=[],I=[],L=new Map,R=null,z=n({content:b,root:p,wrapperSlot:`combobox-positioner`}),B=!1,V=e=>e.hasAttribute(`disabled`)||e.hasAttribute(`data-disabled`)||e.getAttribute(`aria-disabled`)===`true`,H=e=>{if(e.dataset.label)return e.dataset.label;let t=``;for(let n of e.childNodes)n.nodeType===Node.TEXT_NODE&&(t+=n.textContent);return t.trim()||(e.textContent?.trim()??``)},U=e=>e.hasAttribute(`data-value`)?e.getAttribute(`data-value`):void 0,ge=e=>e===null?null:f(x??b,`combobox-item`).find(t=>U(t)===e)??null,W=e=>{let t=ge(e);return O?O(t,e):t?H(t):``},_e=o(y,`combobox-input`),ve=x??b,ye=o(ve,`combobox-list`);y.setAttribute(`role`,`combobox`),y.setAttribute(`aria-autocomplete`,`list`),y.setAttribute(`autocomplete`,`off`),y.setAttribute(`aria-controls`,ye),x?x.setAttribute(`role`,`listbox`):b.setAttribute(`role`,`listbox`),S&&(S.hasAttribute(`type`)||S.setAttribute(`type`,`button`),S.tabIndex=-1,S.setAttribute(`aria-label`,`Toggle`));let be=document.querySelector(`label[for="${CSS.escape(_e)}"]`);if(be){let e=o(be,`combobox-label`),t=y.getAttribute(`aria-labelledby`);y.setAttribute(`aria-labelledby`,t?`${t} ${e}`:e),ve.setAttribute(`aria-labelledby`,e)}w&&(y.setAttribute(`aria-disabled`,`true`),y.disabled=!0,S&&(S.setAttribute(`aria-disabled`,`true`),S.setAttribute(`data-disabled`,``))),T&&(y.setAttribute(`aria-required`,`true`),y.required=!0);let xe=()=>{T&&y.setCustomValidity(A===null?`Please select a value`:``)};C&&(y.placeholder=C),E&&(y.name&&y.removeAttribute(`name`),R=document.createElement(`input`),R.type=`hidden`,R.name=E,R.value=A??``,p.appendChild(R));let Se=oe??((e,t,n)=>n.toLowerCase().includes(e.toLowerCase())),Ce=()=>{let e=x??b;P=f(e,`combobox-item`);for(let e of P)e.setAttribute(`role`,`option`),o(e,`combobox-item`),V(e)?e.setAttribute(`aria-disabled`,`true`):e.removeAttribute(`aria-disabled`),U(e)===A?(h(e,`selected`,!0),e.setAttribute(`data-selected`,``)):(h(e,`selected`,!1),e.removeAttribute(`data-selected`));let t=f(e,`combobox-group`);for(let e of t){e.setAttribute(`role`,`group`);let t=d(e,`combobox-label`);if(t){let n=o(t,`combobox-label`);e.setAttribute(`aria-labelledby`,n)}}we()},we=()=>{F=P.filter(e=>!e.hidden),I=F.filter(e=>!V(e)),L=new Map(I.map((e,t)=>[e,t]))},G=(e,t)=>{let n=t===`previous`?e.previousElementSibling:e.nextElementSibling;for(;n;){if(n instanceof HTMLElement&&!n.hidden&&n.dataset.slot!==`combobox-separator`)return!0;n=t===`previous`?n.previousElementSibling:n.nextElementSibling}return!1},Te=e=>{let t=x??b,n=e.trim(),r=0;for(let e of P){let t=U(e)??``,i=H(e),a=n===``||Se(n,t,i);e.hidden=!a,a&&r++}let i=f(t,`combobox-group`);for(let e of i)e.hidden=!f(e,`combobox-item`).some(e=>!e.hidden);let a=f(t,`combobox-separator`);for(let e of a)e.hidden=!G(e,`previous`)||!G(e,`next`);ne&&(ne.hidden=r>0),r===0?b.setAttribute(`data-empty`,``):b.removeAttribute(`data-empty`),we()},Ee=()=>{let t=z.container,n=p.ownerDocument.defaultView??window,r=p.getBoundingClientRect();b.style.minWidth=`${r.width}px`;let i=e({anchorRect:r,contentRect:b.getBoundingClientRect(),side:ue,align:de,sideOffset:fe,alignOffset:pe,avoidCollisions:me,collisionPadding:he,allowedSides:g});t.style.position=`absolute`,t.style.top=`0px`,t.style.left=`0px`,t.style.transform=`translate3d(${i.x+n.scrollX}px, ${i.y+n.scrollY}px, 0)`,t.style.willChange=`transform`,t.style.margin=`0`,b.setAttribute(`data-side`,i.side),b.setAttribute(`data-align`,i.align),t!==b&&(t.setAttribute(`data-side`,i.side),t.setAttribute(`data-align`,i.align))},K=r({observedElements:[p,b],isActive:()=>k,ancestorScroll:!1,onUpdate:Ee,ignoreScrollTarget:e=>e instanceof Node&&b.contains(e)}),De=e=>x&&x.contains(e)&&x.scrollHeight>x.clientHeight?x:b,q=e=>{for(let t=0;t<I.length;t++){let n=I[t];t===e?(n.setAttribute(`data-highlighted`,``),y.setAttribute(`aria-activedescendant`,n.id),ee(n,De(n))):n.removeAttribute(`data-highlighted`)}j=e},J=()=>{for(let e of P)e.removeAttribute(`data-highlighted`);j=-1,y.removeAttribute(`aria-activedescendant`)},Y=e=>{p.setAttribute(`data-state`,e),b.setAttribute(`data-state`,e),S&&S.setAttribute(`data-state`,e),e===`open`?(p.setAttribute(`data-open`,``),b.setAttribute(`data-open`,``),S&&S.setAttribute(`data-open`,``),p.removeAttribute(`data-closed`),b.removeAttribute(`data-closed`),S&&S.removeAttribute(`data-closed`)):(p.setAttribute(`data-closed`,``),b.setAttribute(`data-closed`,``),S&&S.setAttribute(`data-closed`,``),p.removeAttribute(`data-open`),b.removeAttribute(`data-open`),S&&S.removeAttribute(`data-open`))},X=i({element:b,onExitComplete:()=>{B||(z.restore(),b.hidden=!0)}}),Z=(e,t=!1)=>{if(k!==e&&!(w&&e)){if(e){k=!0,h(y,`expanded`,!0),z.mount(),b.hidden=!1,Y(`open`),X.enter(),Ce(),M=!1,Te(y.value);let e=I.findIndex(e=>U(e)===A);e>=0?q(e):D&&I.length>0?q(0):J(),K.start(),Ee(),K.update(),requestAnimationFrame(()=>{k&&K.update()})}else k=!1,h(y,`expanded`,!1),Y(`closed`),J(),M=!1,K.stop(),X.exit(),y.value=W(A);a(p,`combobox:open-change`,{open:k}),ce?.(k)}},Q=(e,t=!1)=>{if(A===e&&!t)return;let n=A;A=e,xe(),R&&(R.value=e??``),e===null?p.removeAttribute(`data-value`):p.setAttribute(`data-value`,e);let r=x??b,i=P.length>0?P:f(r,`combobox-item`);for(let t of i)U(t)===e?(h(t,`selected`,!0),t.setAttribute(`data-selected`,``)):(h(t,`selected`,!1),t.removeAttribute(`data-selected`));y.value=W(e),!t&&n!==e&&(a(p,`combobox:change`,{value:e}),se?.(e))},$=e=>{if(V(e))return;let t=U(e);t!==void 0&&(Q(t),Z(!1))};return h(y,`expanded`,!1),b.hidden=!0,Y(`closed`),Q(A,!0),N.push(m(y,`input`,()=>{let e=y.value;a(p,`combobox:input-change`,{inputValue:e}),le?.(e),k?(Te(e),D&&I.length>0?q(0):J(),K.update()):Z(!0)}),m(y,`keydown`,e=>{if(!w)switch(e.key){case`ArrowDown`:{if(e.preventDefault(),!k){Z(!0);return}M=!0;let t=I.length;if(t===0)return;q(j===-1?0:(j+1)%t);break}case`ArrowUp`:{if(e.preventDefault(),!k){Z(!0);return}M=!0;let t=I.length;if(t===0)return;q(j===-1?t-1:(j-1+t)%t);break}case`Home`:if(!k)return;e.preventDefault(),M=!0,I.length>0&&q(0);break;case`End`:if(!k)return;e.preventDefault(),M=!0,I.length>0&&q(I.length-1);break;case`Enter`:if(!k)return;e.preventDefault(),j>=0&&j<I.length&&$(I[j]);break;case`Escape`:k?(e.preventDefault(),Z(!1)):A!==null&&(e.preventDefault(),Q(null));break;case`Tab`:k&&Z(!1,!0);break}}),m(y,`focus`,()=>{w||(y.select(),ae&&!k&&Z(!0))})),S&&N.push(m(S,`click`,()=>{w||(k?Z(!1):(Z(!0),y.focus()))})),N.push(m(b,`click`,e=>{let t=e.target.closest?.(`[data-slot="combobox-item"]`);t&&!t.hidden&&$(t)}),m(b,`pointermove`,e=>{let t=e.target.closest?.(`[data-slot="combobox-item"]`);if(!(M&&(M=!1,t&&L.get(t)===j)))if(t&&!V(t)&&!t.hidden){let e=L.get(t);e!==void 0&&e!==j&&q(e)}else J()}),m(b,`pointerleave`,()=>{M||J()}),m(b,`mousedown`,e=>{e.preventDefault()})),N.push(t({root:p,isOpen:()=>k,onDismiss:()=>Z(!1),closeOnClickOutside:!0,closeOnEscape:!1})),N.push(m(p,`combobox:set`,e=>{let t=e.detail;t?.value!==void 0&&Q(t.value),t?.open!==void 0&&Z(t.open),t?.inputValue!==void 0&&(y.value=t.inputValue),t?.itemToStringValue!==void 0&&(O=t.itemToStringValue,y.value=W(A))})),ie&&Z(!0),{get value(){return A},get inputValue(){return y.value},get isOpen(){return k},select:e=>Q(e),clear:()=>Q(null),open:()=>Z(!0),close:()=>Z(!1),setItemToStringValue:e=>{O=e,y.value=W(A)},destroy:()=>{B=!0,K.stop(),X.cleanup(),z.cleanup(),N.forEach(e=>e()),N.length=0,R&&R.parentNode&&R.parentNode.removeChild(R),v.delete(p)}}}const v=new WeakSet;function y(e=document){let t=[];for(let n of p(e,`combobox`))v.has(n)||(v.add(n),t.push(_(n)));return t}export{y as create,_ as createCombobox};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@data-slot/combobox",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.44",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -40,6 +40,6 @@
|
|
|
40
40
|
],
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@data-slot/core": "0.2.
|
|
43
|
+
"@data-slot/core": "0.2.44"
|
|
44
44
|
}
|
|
45
45
|
}
|