UNPKG

@kobalte/core

Version:

Unstyled components and primitives for building accessible web apps and design systems with SolidJS.

431 lines (418 loc) 12.7 kB
import { getItemCount } from "./FINWO3A5.jsx"; import { createSelectableList } from "./N3GAC5SS.jsx"; import { createListState, createSelectableItem } from "./QZDH5R5B.jsx"; import { createRegisterId } from "./JNCCF6MP.jsx"; import { Polymorphic } from "./FLVHQV4A.jsx"; import { __export } from "./5WXHJDCZ.jsx"; // src/listbox/index.tsx var listbox_exports = {}; __export(listbox_exports, { Item: () => ListboxItem, ItemDescription: () => ListboxItemDescription, ItemIndicator: () => ListboxItemIndicator, ItemLabel: () => ListboxItemLabel, Listbox: () => Listbox, Root: () => ListboxRoot, Section: () => ListboxSection, useListboxContext: () => useListboxContext }); // src/listbox/listbox-item.tsx import { callHandler, composeEventHandlers, createGenerateId, focusWithoutScrolling, isMac, isWebKit, mergeDefaultProps, mergeRefs } from "@kobalte/utils"; import { createMemo, createSignal, createUniqueId, splitProps } from "solid-js"; // src/listbox/listbox-context.tsx import { createContext, useContext } from "solid-js"; var ListboxContext = createContext(); function useListboxContext() { const context = useContext(ListboxContext); if (context === void 0) { throw new Error( "[kobalte]: `useListboxContext` must be used within a `Listbox` component" ); } return context; } // src/listbox/listbox-item-context.tsx import { createContext as createContext2, useContext as useContext2 } from "solid-js"; var ListboxItemContext = createContext2(); function useListboxItemContext() { const context = useContext2(ListboxItemContext); if (context === void 0) { throw new Error( "[kobalte]: `useListboxItemContext` must be used within a `Listbox.Item` component" ); } return context; } // src/listbox/listbox-item.tsx function ListboxItem(props) { let ref; const listBoxContext = useListboxContext(); const defaultId = `${listBoxContext.generateId("item")}-${createUniqueId()}`; const mergedProps = mergeDefaultProps( { id: defaultId }, props ); const [local, others] = splitProps(mergedProps, [ "ref", "item", "aria-label", "aria-labelledby", "aria-describedby", "onPointerMove", "onPointerDown", "onPointerUp", "onClick", "onKeyDown", "onMouseDown", "onFocus" ]); const [labelId, setLabelId] = createSignal(); const [descriptionId, setDescriptionId] = createSignal(); const selectionManager = () => listBoxContext.listState().selectionManager(); const isHighlighted = () => selectionManager().focusedKey() === local.item.key; const selectableItem = createSelectableItem( { key: () => local.item.key, selectionManager, shouldSelectOnPressUp: listBoxContext.shouldSelectOnPressUp, allowsDifferentPressOrigin: () => { return listBoxContext.shouldSelectOnPressUp() && listBoxContext.shouldFocusOnHover(); }, shouldUseVirtualFocus: listBoxContext.shouldUseVirtualFocus, disabled: () => local.item.disabled }, () => ref ); const ariaSelected = () => { if (selectionManager().selectionMode() === "none") { return void 0; } return selectableItem.isSelected(); }; const isNotSafariMacOS = createMemo(() => !(isMac() && isWebKit())); const ariaLabel = () => isNotSafariMacOS() ? local["aria-label"] : void 0; const ariaLabelledBy = () => isNotSafariMacOS() ? labelId() : void 0; const ariaDescribedBy = () => isNotSafariMacOS() ? descriptionId() : void 0; const ariaPosInSet = () => { if (!listBoxContext.isVirtualized()) { return void 0; } const index = listBoxContext.listState().collection().getItem(local.item.key)?.index; return index != null ? index + 1 : void 0; }; const ariaSetSize = () => { if (!listBoxContext.isVirtualized()) { return void 0; } return getItemCount(listBoxContext.listState().collection()); }; const onPointerMove = (e) => { callHandler(e, local.onPointerMove); if (e.pointerType !== "mouse") { return; } if (!selectableItem.isDisabled() && listBoxContext.shouldFocusOnHover()) { focusWithoutScrolling(e.currentTarget); selectionManager().setFocused(true); selectionManager().setFocusedKey(local.item.key); } }; const dataset = createMemo(() => ({ "data-disabled": selectableItem.isDisabled() ? "" : void 0, "data-selected": selectableItem.isSelected() ? "" : void 0, "data-highlighted": isHighlighted() ? "" : void 0 })); const context = { isSelected: selectableItem.isSelected, dataset, generateId: createGenerateId(() => others.id), registerLabelId: createRegisterId(setLabelId), registerDescriptionId: createRegisterId(setDescriptionId) }; return <ListboxItemContext.Provider value={context}><Polymorphic as="li" ref={mergeRefs((el) => ref = el, local.ref)} role="option" tabIndex={selectableItem.tabIndex()} aria-disabled={selectableItem.isDisabled()} aria-selected={ariaSelected()} aria-label={ariaLabel()} aria-labelledby={ariaLabelledBy()} aria-describedby={ariaDescribedBy()} aria-posinset={ariaPosInSet()} aria-setsize={ariaSetSize()} data-key={selectableItem.dataKey()} onPointerDown={composeEventHandlers([ local.onPointerDown, selectableItem.onPointerDown ])} onPointerUp={composeEventHandlers([ local.onPointerUp, selectableItem.onPointerUp ])} onClick={composeEventHandlers([local.onClick, selectableItem.onClick])} onKeyDown={composeEventHandlers([ local.onKeyDown, selectableItem.onKeyDown ])} onMouseDown={composeEventHandlers([ local.onMouseDown, selectableItem.onMouseDown ])} onFocus={composeEventHandlers([local.onFocus, selectableItem.onFocus])} onPointerMove={onPointerMove} {...dataset()} {...others} /></ListboxItemContext.Provider>; } // src/listbox/listbox-item-description.tsx import { mergeDefaultProps as mergeDefaultProps2 } from "@kobalte/utils"; import { createEffect, onCleanup } from "solid-js"; function ListboxItemDescription(props) { const context = useListboxItemContext(); const mergedProps = mergeDefaultProps2( { id: context.generateId("description") }, props ); createEffect(() => onCleanup(context.registerDescriptionId(mergedProps.id))); return <Polymorphic as="div" {...context.dataset()} {...mergedProps} />; } // src/listbox/listbox-item-indicator.tsx import { mergeDefaultProps as mergeDefaultProps3 } from "@kobalte/utils"; import { Show, splitProps as splitProps2 } from "solid-js"; function ListboxItemIndicator(props) { const context = useListboxItemContext(); const mergedProps = mergeDefaultProps3( { id: context.generateId("indicator") }, props ); const [local, others] = splitProps2(mergedProps, ["forceMount"]); return <Show when={local.forceMount || context.isSelected()}><Polymorphic as="div" aria-hidden="true" {...context.dataset()} {...others} /></Show>; } // src/listbox/listbox-item-label.tsx import { mergeDefaultProps as mergeDefaultProps4 } from "@kobalte/utils"; import { createEffect as createEffect2, onCleanup as onCleanup2 } from "solid-js"; function ListboxItemLabel(props) { const context = useListboxItemContext(); const mergedProps = mergeDefaultProps4( { id: context.generateId("label") }, props ); createEffect2(() => onCleanup2(context.registerLabelId(mergedProps.id))); return <Polymorphic as="div" {...context.dataset()} {...mergedProps} />; } // src/listbox/listbox-root.tsx import { Key, access, composeEventHandlers as composeEventHandlers2, createGenerateId as createGenerateId2, mergeDefaultProps as mergeDefaultProps5, mergeRefs as mergeRefs2 } from "@kobalte/utils"; import { Match, Show as Show2, Switch, createMemo as createMemo2, createUniqueId as createUniqueId2, splitProps as splitProps4 } from "solid-js"; function ListboxRoot(props) { let ref; const defaultId = `listbox-${createUniqueId2()}`; const mergedProps = mergeDefaultProps5( { id: defaultId, selectionMode: "single", virtualized: false }, props ); const [local, others] = splitProps4(mergedProps, [ "ref", "children", "renderItem", "renderSection", "value", "defaultValue", "onChange", "options", "optionValue", "optionTextValue", "optionDisabled", "optionGroupChildren", "state", "keyboardDelegate", "autoFocus", "selectionMode", "shouldFocusWrap", "shouldUseVirtualFocus", "shouldSelectOnPressUp", "shouldFocusOnHover", "allowDuplicateSelectionEvents", "disallowEmptySelection", "selectionBehavior", "selectOnFocus", "disallowTypeAhead", "allowsTabNavigation", "virtualized", "scrollToItem", "scrollRef", "onKeyDown", "onMouseDown", "onFocusIn", "onFocusOut" ]); const listState = createMemo2(() => { if (local.state) { return local.state; } return createListState({ selectedKeys: () => local.value, defaultSelectedKeys: () => local.defaultValue, onSelectionChange: local.onChange, allowDuplicateSelectionEvents: () => access(local.allowDuplicateSelectionEvents), disallowEmptySelection: () => access(local.disallowEmptySelection), selectionBehavior: () => access(local.selectionBehavior), selectionMode: () => access(local.selectionMode), dataSource: () => local.options ?? [], getKey: () => local.optionValue, getTextValue: () => local.optionTextValue, getDisabled: () => local.optionDisabled, getSectionChildren: () => local.optionGroupChildren }); }); const selectableList = createSelectableList( { selectionManager: () => listState().selectionManager(), collection: () => listState().collection(), autoFocus: () => access(local.autoFocus), shouldFocusWrap: () => access(local.shouldFocusWrap), keyboardDelegate: () => local.keyboardDelegate, disallowEmptySelection: () => access(local.disallowEmptySelection), selectOnFocus: () => access(local.selectOnFocus), disallowTypeAhead: () => access(local.disallowTypeAhead), shouldUseVirtualFocus: () => access(local.shouldUseVirtualFocus), allowsTabNavigation: () => access(local.allowsTabNavigation), isVirtualized: () => local.virtualized, scrollToKey: () => local.scrollToItem }, () => ref, () => local.scrollRef?.() ); const context = { listState, generateId: createGenerateId2(() => others.id), shouldUseVirtualFocus: () => mergedProps.shouldUseVirtualFocus, shouldSelectOnPressUp: () => mergedProps.shouldSelectOnPressUp, shouldFocusOnHover: () => mergedProps.shouldFocusOnHover, isVirtualized: () => local.virtualized }; return <ListboxContext.Provider value={context}><Polymorphic as="ul" ref={mergeRefs2((el) => ref = el, local.ref)} role="listbox" tabIndex={selectableList.tabIndex()} aria-multiselectable={listState().selectionManager().selectionMode() === "multiple" ? true : void 0} onKeyDown={composeEventHandlers2([ local.onKeyDown, selectableList.onKeyDown ])} onMouseDown={composeEventHandlers2([ local.onMouseDown, selectableList.onMouseDown ])} onFocusIn={composeEventHandlers2([ local.onFocusIn, selectableList.onFocusIn ])} onFocusOut={composeEventHandlers2([ local.onFocusOut, selectableList.onFocusOut ])} {...others} ><Show2 when={!local.virtualized} fallback={local.children?.(listState().collection)} ><Key each={[...listState().collection()]} by="key">{(item) => <Switch> <Match when={item().type === "section"}>{local.renderSection?.(item())}</Match> <Match when={item().type === "item"}>{local.renderItem?.(item())}</Match> </Switch>}</Key></Show2></Polymorphic></ListboxContext.Provider>; } // src/listbox/listbox-section.tsx function ListboxSection(props) { return <Polymorphic as="li" role="presentation" {...props} />; } // src/listbox/index.tsx var Listbox = Object.assign(ListboxRoot, { Item: ListboxItem, ItemDescription: ListboxItemDescription, ItemIndicator: ListboxItemIndicator, ItemLabel: ListboxItemLabel, Section: ListboxSection }); export { useListboxContext, ListboxItem, ListboxItemDescription, ListboxItemIndicator, ListboxItemLabel, ListboxRoot, ListboxSection, Listbox, listbox_exports };