@ark-ui/solid
Version:
A collection of unstyled, accessible UI components for Solid, utilizing state machines for seamless interaction.
205 lines (202 loc) • 7.35 kB
JavaScript
import { GridCollection, ListCollection, TreeCollection, filePathToTree, Selection } from '@zag-js/collection';
import { createMemo, splitProps, createSignal, createEffect, on } from 'solid-js';
// src/components/collection/grid-collection.ts
var createGridCollection = (options) => new GridCollection(options);
var createListCollection = (options) => new ListCollection(options);
var createTreeCollection = (options) => new TreeCollection(options);
var createFileTreeCollection = (paths) => filePathToTree(paths);
function useListCollection(props) {
const splittedProps = createMemo(() => {
const rawProps = typeof props === "function" ? props() : props;
return splitProps(rawProps, ["initialItems", "filter", "limit"]);
});
const init = () => {
const [localProps] = splittedProps();
return localProps.initialItems;
};
const [items, setItemsImpl] = createSignal(init());
const [filterText, setFilterText] = createSignal("");
const setItems = (newItems) => {
setItemsImpl(newItems);
setFilterText("");
};
const create = (itemsToCreate) => {
const [, collectionOptions] = splittedProps();
return createListCollection({ ...collectionOptions, items: itemsToCreate });
};
const collection = createMemo(() => {
const [localProps, collectionOptions] = splittedProps();
const filter = localProps.filter;
let activeItems = items();
if (filterText() && filter) {
activeItems = create(items()).filter((itemString, _index, item) => filter(itemString, filterText(), item)).items;
}
const limitedItems = localProps.limit == null ? activeItems : activeItems.slice(0, localProps.limit);
return createListCollection({ ...collectionOptions, items: limitedItems });
});
return {
collection,
filter: (inputValue = "") => {
setFilterText(inputValue);
},
set: (newItems) => {
setItems(newItems);
},
reset: () => {
const [localProps] = splittedProps();
setItems(localProps.initialItems);
},
clear: () => {
setItems([]);
},
insert: (index, ...itemsToInsert) => {
const newItems = create(items()).insert(index, ...itemsToInsert).items;
setItems(newItems);
},
insertBefore: (value, ...itemsToInsert) => {
const newItems = create(items()).insertBefore(value, ...itemsToInsert).items;
setItems(newItems);
},
insertAfter: (value, ...itemsToInsert) => {
const newItems = create(items()).insertAfter(value, ...itemsToInsert).items;
setItems(newItems);
},
remove: (...itemOrValues) => {
const newItems = create(items()).remove(...itemOrValues).items;
setItems(newItems);
},
move: (value, to) => {
const newItems = create(items()).move(value, to).items;
setItems(newItems);
},
moveBefore: (value, ...values) => {
const newItems = create(items()).moveBefore(value, ...values).items;
setItems(newItems);
},
moveAfter: (value, ...values) => {
const newItems = create(items()).moveAfter(value, ...values).items;
setItems(newItems);
},
reorder: (from, to) => {
const newItems = create(items()).reorder(from, to).items;
setItems(newItems);
},
append: (...itemsToAppend) => {
const newItems = create(items()).append(...itemsToAppend).items;
setItems(newItems);
},
upsert: (value, item, mode = "append") => {
const newItems = create(items()).upsert(value, item, mode).items;
setItems(newItems);
},
prepend: (...itemsToPrepend) => {
const newItems = create(items()).prepend(...itemsToPrepend).items;
setItems(newItems);
},
update: (value, item) => {
const newItems = create(items()).update(value, item).items;
setItems(newItems);
}
};
}
function useListSelection(props) {
const splittedProps = createMemo(() => {
const rawProps = typeof props === "function" ? props() : props;
return splitProps(rawProps, [
"collection",
"selectionMode",
"deselectable",
"initialSelectedValues",
"resetOnCollectionChange"
]);
});
const createSelection = (values = []) => {
const [localProps] = splittedProps();
const selection2 = new Selection(values);
selection2.selectionMode = localProps.selectionMode ?? "single";
selection2.deselectable = localProps.deselectable ?? true;
return selection2;
};
const init = () => {
const [localProps] = splittedProps();
return createSelection(localProps.initialSelectedValues ?? []);
};
const [selection, setSelection] = createSignal(init());
const watchDeps = () => {
const [{ collection, resetOnCollectionChange }] = splittedProps();
return [collection.getValues(), resetOnCollectionChange];
};
createEffect(
on(
watchDeps,
([, resetOnCollectionChange]) => {
if (resetOnCollectionChange) {
setSelection(createSelection());
}
},
{ defer: true }
)
);
const selectedValues = createMemo(() => Array.from(selection()));
const isEmpty = createMemo(() => selection().isEmpty());
const firstSelectedValue = createMemo(() => {
const [localProps] = splittedProps();
return selection().firstSelectedValue(localProps.collection);
});
const lastSelectedValue = createMemo(() => {
const [localProps] = splittedProps();
return selection().lastSelectedValue(localProps.collection);
});
return {
selectedValues,
isEmpty,
firstSelectedValue,
lastSelectedValue,
isSelected: (value) => {
return selection().isSelected(value);
},
isAllSelected: () => {
const [localProps] = splittedProps();
const allValues = localProps.collection.getValues();
return allValues.length > 0 && allValues.every((value) => selection().isSelected(value));
},
isSomeSelected: () => {
const [localProps] = splittedProps();
const allValues = localProps.collection.getValues();
return allValues.some((value) => selection().isSelected(value));
},
canSelect: (value) => {
const [localProps] = splittedProps();
return selection().canSelect(localProps.collection, value);
},
select: (value, forceToggle) => {
const [localProps] = splittedProps();
setSelection(selection().select(localProps.collection, value, forceToggle));
},
deselect: (value) => {
setSelection(selection().deselect(value));
},
toggle: (value) => {
const [localProps] = splittedProps();
setSelection(selection().toggleSelection(localProps.collection, value));
},
replace: (value) => {
const [localProps] = splittedProps();
setSelection(selection().replaceSelection(localProps.collection, value));
},
extend: (anchorValue, targetValue) => {
const [localProps] = splittedProps();
setSelection(selection().extendSelection(localProps.collection, anchorValue, targetValue));
},
setSelectedValues: (values) => {
setSelection(selection().setSelection(values));
},
clear: () => {
setSelection(selection().clearSelection());
},
resetSelection: () => {
setSelection(createSelection());
}
};
}
export { createFileTreeCollection, createGridCollection, createListCollection, createTreeCollection, useListCollection, useListSelection };