@kobalte/core
Version:
Unstyled components and primitives for building accessible web apps and design systems with SolidJS.
144 lines (141 loc) • 4.55 kB
JavaScript
import { createSelectableCollection } from './H6DSIDEC.js';
import { createCollator } from './XHJPQEZP.js';
import { access } from '@kobalte/utils';
import { createMemo } from 'solid-js';
// src/list/list-keyboard-delegate.ts
var ListKeyboardDelegate = class {
collection;
ref;
collator;
constructor(collection, ref, collator) {
this.collection = collection;
this.ref = ref;
this.collator = collator;
}
getKeyBelow(key) {
let keyAfter = this.collection().getKeyAfter(key);
while (keyAfter != null) {
const item = this.collection().getItem(keyAfter);
if (item && item.type === "item" && !item.disabled) {
return keyAfter;
}
keyAfter = this.collection().getKeyAfter(keyAfter);
}
}
getKeyAbove(key) {
let keyBefore = this.collection().getKeyBefore(key);
while (keyBefore != null) {
const item = this.collection().getItem(keyBefore);
if (item && item.type === "item" && !item.disabled) {
return keyBefore;
}
keyBefore = this.collection().getKeyBefore(keyBefore);
}
}
getFirstKey() {
let key = this.collection().getFirstKey();
while (key != null) {
const item = this.collection().getItem(key);
if (item && item.type === "item" && !item.disabled) {
return key;
}
key = this.collection().getKeyAfter(key);
}
}
getLastKey() {
let key = this.collection().getLastKey();
while (key != null) {
const item = this.collection().getItem(key);
if (item && item.type === "item" && !item.disabled) {
return key;
}
key = this.collection().getKeyBefore(key);
}
}
getItem(key) {
return this.ref?.()?.querySelector(`[data-key="${key}"]`) ?? null;
}
// TODO: not working correctly
getKeyPageAbove(key) {
const menu = this.ref?.();
let item = this.getItem(key);
if (!menu || !item) {
return;
}
const pageY = Math.max(
0,
item.offsetTop + item.offsetHeight - menu.offsetHeight
);
let keyAbove = key;
while (keyAbove && item && item.offsetTop > pageY) {
keyAbove = this.getKeyAbove(keyAbove);
item = keyAbove != null ? this.getItem(keyAbove) : null;
}
return keyAbove;
}
// TODO: not working correctly
getKeyPageBelow(key) {
const menu = this.ref?.();
let item = this.getItem(key);
if (!menu || !item) {
return;
}
const pageY = Math.min(
menu.scrollHeight,
item.offsetTop - item.offsetHeight + menu.offsetHeight
);
let keyBelow = key;
while (keyBelow && item && item.offsetTop < pageY) {
keyBelow = this.getKeyBelow(keyBelow);
item = keyBelow != null ? this.getItem(keyBelow) : null;
}
return keyBelow;
}
getKeyForSearch(search, fromKey) {
const collator = this.collator?.();
if (!collator) {
return;
}
let key = fromKey != null ? this.getKeyBelow(fromKey) : this.getFirstKey();
while (key != null) {
const item = this.collection().getItem(key);
if (item) {
const substring = item.textValue.slice(0, search.length);
if (item.textValue && collator.compare(substring, search) === 0) {
return key;
}
}
key = this.getKeyBelow(key);
}
}
};
function createSelectableList(props, ref, scrollRef) {
const collator = createCollator({ usage: "search", sensitivity: "base" });
const delegate = createMemo(() => {
const keyboardDelegate = access(props.keyboardDelegate);
if (keyboardDelegate) {
return keyboardDelegate;
}
return new ListKeyboardDelegate(props.collection, ref, collator);
});
return createSelectableCollection(
{
selectionManager: () => access(props.selectionManager),
keyboardDelegate: delegate,
autoFocus: () => access(props.autoFocus),
deferAutoFocus: () => access(props.deferAutoFocus),
shouldFocusWrap: () => access(props.shouldFocusWrap),
disallowEmptySelection: () => access(props.disallowEmptySelection),
selectOnFocus: () => access(props.selectOnFocus),
disallowTypeAhead: () => access(props.disallowTypeAhead),
shouldUseVirtualFocus: () => access(props.shouldUseVirtualFocus),
allowsTabNavigation: () => access(props.allowsTabNavigation),
isVirtualized: () => access(props.isVirtualized),
scrollToKey: (key) => access(props.scrollToKey)?.(key),
orientation: () => access(props.orientation)
},
ref,
scrollRef
);
}
export { ListKeyboardDelegate, createSelectableList };