@kobalte/core
Version:
Unstyled components and primitives for building accessible web apps and design systems with SolidJS.
431 lines (418 loc) • 12.7 kB
JSX
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
};