🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@ginxjs/core

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ginxjs/core - npm Package Compare versions

Comparing version
0.0.1
to
0.0.4
+1348
dist/collection.cjs
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_utils = require("./utils-Bd5iPRBt.cjs");
//#region src/shared/collection/list-collection.ts
const fallback = {
itemToValue(item) {
if (typeof item === "string") return item;
if (require_utils.isObject(item) && require_utils.hasProp(item, "value")) return item.value;
return "";
},
itemToString(item) {
if (typeof item === "string") return item;
if (require_utils.isObject(item) && require_utils.hasProp(item, "label")) return item.label;
return fallback.itemToValue(item);
},
isItemDisabled(item) {
if (require_utils.isObject(item) && require_utils.hasProp(item, "disabled")) return !!item.disabled;
return false;
}
};
var ListCollection = class ListCollection {
options;
items;
indexMap = null;
constructor(options) {
this.options = options;
this.items = [...options.items];
}
copy = (items) => {
return new ListCollection({
...this.options,
items: items ?? [...this.items]
});
};
isEqual = (other) => {
return require_utils.isEqual(this.items, other.items);
};
setItems = (items) => {
return this.copy(items);
};
getValues = (items = this.items) => {
const values = [];
for (const item of items) {
const value = this.getItemValue(item);
if (value != null) values.push(value);
}
return values;
};
find = (value) => {
if (value == null) return null;
const index = this.indexOf(value);
return index !== -1 ? this.at(index) : null;
};
findMany = (values) => {
const result = [];
for (const value of values) {
const item = this.find(value);
if (item != null) result.push(item);
}
return result;
};
at = (index) => {
if (!this.options.groupBy && !this.options.groupSort) return this.items[index] ?? null;
let idx = 0;
const groups = this.group();
for (const [, items] of groups) for (const item of items) {
if (idx === index) return item;
idx++;
}
return null;
};
sortFn = (valueA, valueB) => {
const indexA = this.indexOf(valueA);
const indexB = this.indexOf(valueB);
return (indexA ?? 0) - (indexB ?? 0);
};
sort = (values) => {
return [...values].sort(this.sortFn.bind(this));
};
getItemValue = (item) => {
if (item == null) return null;
return this.options.itemToValue?.(item) ?? fallback.itemToValue(item);
};
getItemDisabled = (item) => {
if (item == null) return false;
return this.options.isItemDisabled?.(item) ?? fallback.isItemDisabled(item);
};
stringifyItem = (item) => {
if (item == null) return null;
return this.options.itemToString?.(item) ?? fallback.itemToString(item);
};
stringify = (value) => {
if (value == null) return null;
return this.stringifyItem(this.find(value));
};
stringifyItems = (items, separator = ", ") => {
const strs = [];
for (const item of items) {
const str = this.stringifyItem(item);
if (str != null) strs.push(str);
}
return strs.join(separator);
};
stringifyMany = (value, separator) => {
return this.stringifyItems(this.findMany(value), separator);
};
has = (value) => {
return this.indexOf(value) !== -1;
};
hasItem = (item) => {
if (item == null) return false;
return this.has(this.getItemValue(item));
};
get size() {
return this.items.length;
}
group = () => {
const { groupBy, groupSort } = this.options;
if (!groupBy) return [["", [...this.items]]];
const groups = /* @__PURE__ */ new Map();
this.items.forEach((item, index) => {
const groupKey = groupBy(item, index);
if (!groups.has(groupKey)) groups.set(groupKey, []);
groups.get(groupKey).push(item);
});
let entries = Array.from(groups.entries());
if (groupSort) entries.sort(([a], [b]) => {
if (typeof groupSort === "function") return groupSort(a, b);
if (Array.isArray(groupSort)) {
const indexA = groupSort.indexOf(a);
const indexB = groupSort.indexOf(b);
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
}
if (groupSort === "asc") return a.localeCompare(b);
if (groupSort === "desc") return b.localeCompare(a);
return 0;
});
return entries;
};
get firstValue() {
let index = 0;
while (this.getItemDisabled(this.at(index))) index++;
return this.getItemValue(this.at(index));
}
get lastValue() {
let index = this.size - 1;
while (this.getItemDisabled(this.at(index))) index--;
return this.getItemValue(this.at(index));
}
getNextValue = (value, step = 1, clamp = false) => {
let index = this.indexOf(value);
if (index === -1) return null;
index = clamp ? Math.min(index + step, this.size - 1) : index + step;
while (index <= this.size && this.getItemDisabled(this.at(index))) index++;
return this.getItemValue(this.at(index));
};
getPreviousValue = (value, step = 1, clamp = false) => {
let index = this.indexOf(value);
if (index === -1) return null;
index = clamp ? Math.max(index - step, 0) : index - step;
while (index >= 0 && this.getItemDisabled(this.at(index))) index--;
return this.getItemValue(this.at(index));
};
indexOf = (value) => {
if (value == null) return -1;
if (!this.options.groupBy && !this.options.groupSort) return this.items.findIndex((item) => this.getItemValue(item) === value);
if (!this.indexMap) {
this.indexMap = /* @__PURE__ */ new Map();
let idx = 0;
const groups = this.group();
for (const [, items] of groups) for (const item of items) {
const itemValue = this.getItemValue(item);
if (itemValue != null) this.indexMap.set(itemValue, idx);
idx++;
}
}
return this.indexMap.get(value) ?? -1;
};
getByText = (text, current) => {
const currentIndex = current != null ? this.indexOf(current) : -1;
const isSingleKey = text.length === 1;
for (let i = 0; i < this.items.length; i++) {
const item = this.items[(currentIndex + i + 1) % this.items.length];
if (isSingleKey && this.getItemValue(item) === current) continue;
if (this.getItemDisabled(item)) continue;
if (match(this.stringifyItem(item), text)) return item;
}
};
search = (queryString, options) => {
const { state, currentValue, timeout = 350 } = options;
const search = state.keysSoFar + queryString;
const query = search.length > 1 && Array.from(search).every((char) => char === search[0]) ? search[0] : search;
const item = this.getByText(query, currentValue);
const value = this.getItemValue(item);
function cleanup() {
clearTimeout(state.timer);
state.timer = -1;
}
function update(value) {
state.keysSoFar = value;
cleanup();
if (value !== "") state.timer = +setTimeout(() => {
update("");
cleanup();
}, timeout);
}
update(search);
return value;
};
*[Symbol.iterator]() {
yield* this.items;
}
update = (value, item) => {
let index = this.indexOf(value);
if (index === -1) return this;
return this.copy([
...this.items.slice(0, index),
item,
...this.items.slice(index + 1)
]);
};
upsert = (value, item, mode = "append") => {
let index = this.indexOf(value);
if (index === -1) return (mode === "append" ? this.append : this.prepend)(item);
return this.copy([
...this.items.slice(0, index),
item,
...this.items.slice(index + 1)
]);
};
insert = (index, ...items) => {
return this.copy(insert$1(this.items, index, ...items));
};
insertBefore = (value, ...items) => {
let toIndex = this.indexOf(value);
if (toIndex === -1) if (this.items.length === 0) toIndex = 0;
else return this;
return this.copy(insert$1(this.items, toIndex, ...items));
};
insertAfter = (value, ...items) => {
let toIndex = this.indexOf(value);
if (toIndex === -1) if (this.items.length === 0) toIndex = 0;
else return this;
return this.copy(insert$1(this.items, toIndex + 1, ...items));
};
prepend = (...items) => {
return this.copy(insert$1(this.items, 0, ...items));
};
append = (...items) => {
return this.copy(insert$1(this.items, this.items.length, ...items));
};
filter = (fn) => {
const filteredItems = this.items.filter((item, index) => fn(this.stringifyItem(item), index, item));
return this.copy(filteredItems);
};
remove = (...itemsOrValues) => {
const values = itemsOrValues.map((itemOrValue) => typeof itemOrValue === "string" ? itemOrValue : this.getItemValue(itemOrValue));
return this.copy(this.items.filter((item) => {
const value = this.getItemValue(item);
if (value == null) return false;
return !values.includes(value);
}));
};
move = (value, toIndex) => {
const fromIndex = this.indexOf(value);
if (fromIndex === -1) return this;
return this.copy(move$1(this.items, [fromIndex], toIndex));
};
moveBefore = (value, ...values) => {
let toIndex = this.items.findIndex((item) => this.getItemValue(item) === value);
if (toIndex === -1) return this;
let indices = values.map((value) => this.items.findIndex((item) => this.getItemValue(item) === value)).sort((a, b) => a - b);
return this.copy(move$1(this.items, indices, toIndex));
};
moveAfter = (value, ...values) => {
let toIndex = this.items.findIndex((item) => this.getItemValue(item) === value);
if (toIndex === -1) return this;
let indices = values.map((value) => this.items.findIndex((item) => this.getItemValue(item) === value)).sort((a, b) => a - b);
return this.copy(move$1(this.items, indices, toIndex + 1));
};
reorder = (fromIndex, toIndex) => {
return this.copy(move$1(this.items, [fromIndex], toIndex));
};
compareValue = (a, b) => {
const indexA = this.indexOf(a);
const indexB = this.indexOf(b);
if (indexA < indexB) return -1;
if (indexA > indexB) return 1;
return 0;
};
range = (from, to) => {
let keys = [];
let key = from;
while (key != null) {
if (this.find(key)) keys.push(key);
if (key === to) return keys;
key = this.getNextValue(key);
}
return [];
};
getValueRange = (from, to) => {
if (from && to) {
if (this.compareValue(from, to) <= 0) return this.range(from, to);
return this.range(to, from);
}
return [];
};
toString = () => {
let result = "";
for (const item of this.items) {
const itemString = [
this.getItemValue(item),
this.stringifyItem(item),
this.getItemDisabled(item)
].filter(Boolean).join(":");
result += itemString + ",";
}
return result;
};
toJSON = () => {
return {
size: this.size,
first: this.firstValue,
last: this.lastValue
};
};
};
const match = (label, query) => {
return !!label?.toLowerCase().startsWith(query.toLowerCase());
};
function isListCollection(v) {
return v instanceof ListCollection;
}
function insert$1(items, index, ...values) {
return [
...items.slice(0, index),
...values,
...items.slice(index)
];
}
function move$1(items, indices, toIndex) {
indices = [...indices].sort((a, b) => a - b);
const itemsToMove = indices.map((i) => items[i]);
for (let i = indices.length - 1; i >= 0; i--) items = [...items.slice(0, indices[i]), ...items.slice(indices[i] + 1)];
toIndex = Math.max(0, toIndex - indices.filter((i) => i < toIndex).length);
return [
...items.slice(0, toIndex),
...itemsToMove,
...items.slice(toIndex)
];
}
//#endregion
//#region src/shared/collection/grid-collection.ts
var GridCollection = class extends ListCollection {
columnCount;
rows = null;
constructor(options) {
const { columnCount } = options;
super(options);
this.columnCount = columnCount;
}
getRows = () => {
if (!this.rows) this.rows = require_utils.chunk([...this.items], this.columnCount);
return this.rows;
};
getRowCount = () => {
return Math.ceil(this.items.length / this.columnCount);
};
getCellIndex = (row, column) => {
return row * this.columnCount + column;
};
getCell = (row, column) => {
return this.at(this.getCellIndex(row, column));
};
getValueCell = (value) => {
const index = this.indexOf(value);
if (index === -1) return null;
return {
row: Math.floor(index / this.columnCount),
column: index % this.columnCount
};
};
getLastEnabledColumnIndex = (row) => {
for (let col = this.columnCount - 1; col >= 0; col--) {
const cell = this.getCell(row, col);
if (cell && !this.getItemDisabled(cell)) return col;
}
return null;
};
getFirstEnabledColumnIndex = (row) => {
for (let col = 0; col < this.columnCount; col++) {
const cell = this.getCell(row, col);
if (cell && !this.getItemDisabled(cell)) return col;
}
return null;
};
getPreviousRowValue = (value, loop = false) => {
const currentCell = this.getValueCell(value);
if (currentCell === null) return null;
const rows = this.getRows();
const rowCount = rows.length;
let prevRowIndex = currentCell.row;
let prevColumnIndex = currentCell.column;
for (let i = 1; i <= rowCount; i++) {
prevRowIndex = require_utils.prevIndex(rows, prevRowIndex, { loop });
const prevRow = rows[prevRowIndex];
if (!prevRow) continue;
if (!prevRow[prevColumnIndex]) {
const lastColumnIndex = this.getLastEnabledColumnIndex(prevRowIndex);
if (lastColumnIndex != null) prevColumnIndex = lastColumnIndex;
}
const cell = this.getCell(prevRowIndex, prevColumnIndex);
if (!this.getItemDisabled(cell)) return this.getItemValue(cell);
}
return this.firstValue;
};
getNextRowValue = (value, loop = false) => {
const currentCell = this.getValueCell(value);
if (currentCell === null) return null;
const rows = this.getRows();
const rowCount = rows.length;
let nextRowIndex = currentCell.row;
let nextColumnIndex = currentCell.column;
for (let i = 1; i <= rowCount; i++) {
nextRowIndex = require_utils.nextIndex(rows, nextRowIndex, { loop });
const nextRow = rows[nextRowIndex];
if (!nextRow) continue;
if (!nextRow[nextColumnIndex]) {
const lastColumnIndex = this.getLastEnabledColumnIndex(nextRowIndex);
if (lastColumnIndex != null) nextColumnIndex = lastColumnIndex;
}
const cell = this.getCell(nextRowIndex, nextColumnIndex);
if (!this.getItemDisabled(cell)) return this.getItemValue(cell);
}
return this.lastValue;
};
};
function isGridCollection(v) {
return require_utils.hasProp(v, "columnCount") && require_utils.hasProp(v, "getRows");
}
//#endregion
//#region src/shared/collection/selection-map.ts
function resolveSelectedItems({ values, collection, selectedItemMap }) {
const result = [];
for (const value of values) {
const item = collection.find(value) ?? selectedItemMap.get(value);
if (item != null) result.push(item);
}
return result;
}
function updateSelectedItemMap({ selectedItemMap, values, selectedItems, collection }) {
const nextMap = new Map(selectedItemMap);
for (const item of selectedItems) {
const value = collection.getItemValue(item);
if (value != null) nextMap.set(value, item);
}
const allowedValues = new Set(values);
for (const value of nextMap.keys()) if (!allowedValues.has(value)) nextMap.delete(value);
return nextMap;
}
function deriveSelectionState({ values, collection, selectedItemMap }) {
const selectedItems = resolveSelectedItems({
values,
collection,
selectedItemMap
});
return {
selectedItems,
nextSelectedItemMap: updateSelectedItemMap({
selectedItemMap,
values,
selectedItems,
collection
})
};
}
function createSelectedItemMap({ selectedItems, collection }) {
return updateSelectedItemMap({
selectedItemMap: /* @__PURE__ */ new Map(),
values: selectedItems.map((item) => collection.getItemValue(item)).filter(Boolean),
selectedItems,
collection
});
}
//#endregion
//#region src/shared/collection/selection.ts
var Selection = class Selection extends Set {
selectionMode = "single";
deselectable = true;
constructor(values = []) {
super(values);
}
copy = () => {
const clone = new Selection([...this]);
return this.sync(clone);
};
sync = (other) => {
other.selectionMode = this.selectionMode;
other.deselectable = this.deselectable;
return other;
};
isEmpty = () => {
return this.size === 0;
};
isSelected = (value) => {
if (this.selectionMode === "none" || value == null) return false;
return this.has(value);
};
canSelect = (collection, value) => {
return this.selectionMode !== "none" || !collection.getItemDisabled(collection.find(value));
};
firstSelectedValue = (collection) => {
let firstValue = null;
for (let value of this) if (!firstValue || collection.compareValue(value, firstValue) < 0) firstValue = value;
return firstValue;
};
lastSelectedValue = (collection) => {
let lastValue = null;
for (let value of this) if (!lastValue || collection.compareValue(value, lastValue) > 0) lastValue = value;
return lastValue;
};
extendSelection = (collection, anchorValue, targetValue) => {
if (this.selectionMode === "none") return this;
if (this.selectionMode === "single") return this.replaceSelection(collection, targetValue);
const selection = this.copy();
const lastSelected = Array.from(this).pop();
for (let key of collection.getValueRange(anchorValue, lastSelected ?? targetValue)) selection.delete(key);
for (let key of collection.getValueRange(targetValue, anchorValue)) if (this.canSelect(collection, key)) selection.add(key);
return selection;
};
toggleSelection = (collection, value) => {
if (this.selectionMode === "none") return this;
if (this.selectionMode === "single" && !this.isSelected(value)) return this.replaceSelection(collection, value);
const selection = this.copy();
if (selection.has(value)) selection.delete(value);
else if (selection.canSelect(collection, value)) selection.add(value);
return selection;
};
replaceSelection = (collection, value) => {
if (this.selectionMode === "none") return this;
if (value == null) return this;
if (!this.canSelect(collection, value)) return this;
const selection = new Selection([value]);
return this.sync(selection);
};
setSelection = (values) => {
if (this.selectionMode === "none") return this;
let selection = new Selection();
for (let value of values) if (value != null) {
selection.add(value);
if (this.selectionMode === "single") break;
}
return this.sync(selection);
};
clearSelection = () => {
const selection = this.copy();
if (selection.deselectable && selection.size > 0) selection.clear();
return selection;
};
select = (collection, value, forceToggle) => {
if (this.selectionMode === "none") return this;
if (this.selectionMode === "single") if (this.isSelected(value) && this.deselectable) return this.toggleSelection(collection, value);
else return this.replaceSelection(collection, value);
else if (this.selectionMode === "multiple" || forceToggle) return this.toggleSelection(collection, value);
else return this.replaceSelection(collection, value);
};
deselect = (value) => {
const selection = this.copy();
selection.delete(value);
return selection;
};
isEqual = (other) => {
return require_utils.isEqual(Array.from(this), Array.from(other));
};
};
//#endregion
//#region src/shared/collection/tree-visit.ts
function access(node, indexPath, options) {
for (let i = 0; i < indexPath.length; i++) node = options.getChildren(node, indexPath.slice(i + 1))[indexPath[i]];
return node;
}
function ancestorIndexPaths(indexPaths) {
const sortedPaths = sortIndexPaths(indexPaths);
const result = [];
const seen = /* @__PURE__ */ new Set();
for (const indexPath of sortedPaths) {
const key = indexPath.join();
if (!seen.has(key)) {
seen.add(key);
result.push(indexPath);
}
}
return result;
}
function compareIndexPaths(a, b) {
for (let i = 0; i < Math.min(a.length, b.length); i++) {
if (a[i] < b[i]) return -1;
if (a[i] > b[i]) return 1;
}
return a.length - b.length;
}
function sortIndexPaths(indexPaths) {
return indexPaths.sort(compareIndexPaths);
}
function find(node, options) {
let found;
visit(node, {
...options,
onEnter: (child, indexPath) => {
if (options.predicate(child, indexPath)) {
found = child;
return "stop";
}
}
});
return found;
}
function findAll(node, options) {
const found = [];
visit(node, {
onEnter: (child, indexPath) => {
if (options.predicate(child, indexPath)) found.push(child);
},
getChildren: options.getChildren
});
return found;
}
function findIndexPath(node, options) {
let found;
visit(node, {
onEnter: (child, indexPath) => {
if (options.predicate(child, indexPath)) {
found = [...indexPath];
return "stop";
}
},
getChildren: options.getChildren
});
return found;
}
function reduce(node, options) {
let result = options.initialResult;
visit(node, {
...options,
onEnter: (child, indexPath) => {
result = options.nextResult(result, child, indexPath);
}
});
return result;
}
function flatMap(node, options) {
return reduce(node, {
...options,
initialResult: [],
nextResult: (result, child, indexPath) => {
result.push(...options.transform(child, indexPath));
return result;
}
});
}
function filter(node, options) {
const { predicate, create, getChildren } = options;
const filterRecursive = (node, indexPath) => {
const children = getChildren(node, indexPath);
const filteredChildren = [];
children.forEach((child, index) => {
const filteredChild = filterRecursive(child, [...indexPath, index]);
if (filteredChild) filteredChildren.push(filteredChild);
});
const isRoot = indexPath.length === 0;
const nodeMatches = predicate(node, indexPath);
const hasFilteredChildren = filteredChildren.length > 0;
if (isRoot || nodeMatches || hasFilteredChildren) return create(node, filteredChildren, indexPath);
return null;
};
return filterRecursive(node, []) || create(node, [], []);
}
function flatten(rootNode, options) {
const nodes = [];
let idx = 0;
const idxMap = /* @__PURE__ */ new Map();
const parentMap = /* @__PURE__ */ new Map();
visit(rootNode, {
getChildren: options.getChildren,
onEnter: (node, indexPath) => {
if (!idxMap.has(node)) idxMap.set(node, idx++);
const children = options.getChildren(node, indexPath);
children.forEach((child) => {
if (!parentMap.has(child)) parentMap.set(child, node);
if (!idxMap.has(child)) idxMap.set(child, idx++);
});
const _children = children.length > 0 ? children.map((child) => idxMap.get(child)) : void 0;
const parent = parentMap.get(node);
const _parent = parent ? idxMap.get(parent) : void 0;
const _index = idxMap.get(node);
nodes.push({
...node,
_children,
_parent,
_index
});
}
});
return nodes;
}
function insertOperation(index, nodes) {
return {
type: "insert",
index,
nodes
};
}
function removeOperation(indexes) {
return {
type: "remove",
indexes
};
}
function replaceOperation() {
return { type: "replace" };
}
function splitIndexPath(indexPath) {
return [indexPath.slice(0, -1), indexPath[indexPath.length - 1]];
}
function getInsertionOperations(indexPath, nodes, operations = /* @__PURE__ */ new Map()) {
const [parentIndexPath, index] = splitIndexPath(indexPath);
for (let i = parentIndexPath.length - 1; i >= 0; i--) {
const parentKey = parentIndexPath.slice(0, i).join();
switch (operations.get(parentKey)?.type) {
case "remove": continue;
}
operations.set(parentKey, replaceOperation());
}
const operation = operations.get(parentIndexPath.join());
switch (operation?.type) {
case "remove":
operations.set(parentIndexPath.join(), {
type: "removeThenInsert",
removeIndexes: operation.indexes,
insertIndex: index,
insertNodes: nodes
});
break;
default: operations.set(parentIndexPath.join(), insertOperation(index, nodes));
}
return operations;
}
function getRemovalOperations(indexPaths) {
const operations = /* @__PURE__ */ new Map();
const indexesToRemove = /* @__PURE__ */ new Map();
for (const indexPath of indexPaths) {
const parentKey = indexPath.slice(0, -1).join();
const value = indexesToRemove.get(parentKey) ?? [];
value.push(indexPath[indexPath.length - 1]);
indexesToRemove.set(parentKey, value.sort((a, b) => a - b));
}
for (const indexPath of indexPaths) for (let i = indexPath.length - 2; i >= 0; i--) {
const parentKey = indexPath.slice(0, i).join();
if (!operations.has(parentKey)) operations.set(parentKey, replaceOperation());
}
for (const [parentKey, indexes] of indexesToRemove) operations.set(parentKey, removeOperation(indexes));
return operations;
}
function getReplaceOperations(indexPath, node) {
const operations = /* @__PURE__ */ new Map();
const [parentIndexPath, index] = splitIndexPath(indexPath);
for (let i = parentIndexPath.length - 1; i >= 0; i--) {
const parentKey = parentIndexPath.slice(0, i).join();
operations.set(parentKey, replaceOperation());
}
operations.set(parentIndexPath.join(), {
type: "removeThenInsert",
removeIndexes: [index],
insertIndex: index,
insertNodes: [node]
});
return operations;
}
function mutate(node, operations, options) {
return map(node, {
...options,
getChildren: (node, indexPath) => {
const key = indexPath.join();
switch (operations.get(key)?.type) {
case "replace":
case "remove":
case "removeThenInsert":
case "insert": return options.getChildren(node, indexPath);
default: return [];
}
},
transform: (node, children, indexPath) => {
const key = indexPath.join();
const operation = operations.get(key);
switch (operation?.type) {
case "remove": return options.create(node, children.filter((_, index) => !operation.indexes.includes(index)), indexPath);
case "removeThenInsert":
const updatedChildren = children.filter((_, index) => !operation.removeIndexes.includes(index));
const adjustedIndex = operation.removeIndexes.reduce((index, removedIndex) => removedIndex < index ? index - 1 : index, operation.insertIndex);
return options.create(node, splice(updatedChildren, adjustedIndex, 0, ...operation.insertNodes), indexPath);
case "insert": return options.create(node, splice(children, operation.index, 0, ...operation.nodes), indexPath);
case "replace": return options.create(node, children, indexPath);
default: return node;
}
}
});
}
function splice(array, start, deleteCount, ...items) {
return [
...array.slice(0, start),
...items,
...array.slice(start + deleteCount)
];
}
function map(node, options) {
const childrenMap = {};
visit(node, {
...options,
onLeave: (child, indexPath) => {
const keyIndexPath = [0, ...indexPath];
const key = keyIndexPath.join();
const transformed = options.transform(child, childrenMap[key] ?? [], indexPath);
const parentKey = keyIndexPath.slice(0, -1).join();
const parentChildren = childrenMap[parentKey] ?? [];
parentChildren.push(transformed);
childrenMap[parentKey] = parentChildren;
}
});
return childrenMap[""][0];
}
function insert(node, options) {
const { nodes, at } = options;
if (at.length === 0) throw new Error(`Can't insert nodes at the root`);
return mutate(node, getInsertionOperations(at, nodes), options);
}
function replace(node, options) {
if (options.at.length === 0) return options.node;
return mutate(node, getReplaceOperations(options.at, options.node), options);
}
function remove(node, options) {
if (options.indexPaths.length === 0) return node;
for (const indexPath of options.indexPaths) if (indexPath.length === 0) throw new Error(`Can't remove the root node`);
return mutate(node, getRemovalOperations(options.indexPaths), options);
}
function move(node, options) {
if (options.indexPaths.length === 0) return node;
for (const indexPath of options.indexPaths) if (indexPath.length === 0) throw new Error(`Can't move the root node`);
if (options.to.length === 0) throw new Error(`Can't move nodes to the root`);
const _ancestorIndexPaths = ancestorIndexPaths(options.indexPaths);
const nodesToInsert = _ancestorIndexPaths.map((indexPath) => access(node, indexPath, options));
return mutate(node, getInsertionOperations(options.to, nodesToInsert, getRemovalOperations(_ancestorIndexPaths)), options);
}
function visit(node, options) {
const { onEnter, onLeave, getChildren } = options;
let indexPath = [];
let stack = [{ node }];
const getIndexPath = options.reuseIndexPath ? () => indexPath : () => indexPath.slice();
while (stack.length > 0) {
let wrapper = stack[stack.length - 1];
if (wrapper.state === void 0) {
const enterResult = onEnter?.(wrapper.node, getIndexPath());
if (enterResult === "stop") return;
wrapper.state = enterResult === "skip" ? -1 : 0;
}
const children = wrapper.children || getChildren(wrapper.node, getIndexPath());
wrapper.children ||= children;
if (wrapper.state !== -1) {
if (wrapper.state < children.length) {
let currentIndex = wrapper.state;
indexPath.push(currentIndex);
stack.push({ node: children[currentIndex] });
wrapper.state = currentIndex + 1;
continue;
}
if (onLeave?.(wrapper.node, getIndexPath()) === "stop") return;
}
indexPath.pop();
stack.pop();
}
}
//#endregion
//#region src/shared/collection/tree-collection.ts
var TreeCollection = class TreeCollection {
options;
rootNode;
constructor(options) {
this.options = options;
this.rootNode = options.rootNode;
}
isEqual = (other) => {
return require_utils.isEqual(this.rootNode, other.rootNode);
};
getNodeChildren = (node) => {
return this.options.nodeToChildren?.(node) ?? fallbackMethods.nodeToChildren(node) ?? [];
};
resolveIndexPath = (valueOrIndexPath) => {
return typeof valueOrIndexPath === "string" ? this.getIndexPath(valueOrIndexPath) : valueOrIndexPath;
};
resolveNode = (valueOrIndexPath) => {
const indexPath = this.resolveIndexPath(valueOrIndexPath);
return indexPath ? this.at(indexPath) : void 0;
};
getNodeChildrenCount = (node) => {
return this.options.nodeToChildrenCount?.(node) ?? fallbackMethods.nodeToChildrenCount(node);
};
getNodeValue = (node) => {
return this.options.nodeToValue?.(node) ?? fallbackMethods.nodeToValue(node);
};
getNodeDisabled = (node) => {
return this.options.isNodeDisabled?.(node) ?? fallbackMethods.isNodeDisabled(node);
};
stringify = (value) => {
const node = this.findNode(value);
if (!node) return null;
return this.stringifyNode(node);
};
stringifyNode = (node) => {
return this.options.nodeToString?.(node) ?? fallbackMethods.nodeToString(node);
};
getFirstNode = (rootNode = this.rootNode, opts = {}) => {
let firstChild;
visit(rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isSameNode(node, rootNode)) return;
if (opts.skip?.({
value: this.getNodeValue(node),
node,
indexPath
})) return "skip";
if (!firstChild && indexPath.length > 0 && !this.getNodeDisabled(node)) {
firstChild = node;
return "stop";
}
}
});
return firstChild;
};
getLastNode = (rootNode = this.rootNode, opts = {}) => {
let lastChild;
visit(rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isSameNode(node, rootNode)) return;
if (opts.skip?.({
value: this.getNodeValue(node),
node,
indexPath
})) return "skip";
if (indexPath.length > 0 && !this.getNodeDisabled(node)) lastChild = node;
}
});
return lastChild;
};
at = (indexPath) => {
return access(this.rootNode, indexPath, { getChildren: this.getNodeChildren });
};
findNode = (value, rootNode = this.rootNode) => {
return find(rootNode, {
getChildren: this.getNodeChildren,
predicate: (node) => this.getNodeValue(node) === value
});
};
findNodes = (values, rootNode = this.rootNode) => {
const v = new Set(values.filter((v) => v != null));
return findAll(rootNode, {
getChildren: this.getNodeChildren,
predicate: (node) => v.has(this.getNodeValue(node))
});
};
sort = (values) => {
return values.reduce((acc, value) => {
const indexPath = this.getIndexPath(value);
if (indexPath) acc.push({
value,
indexPath
});
return acc;
}, []).sort((a, b) => compareIndexPaths(a.indexPath, b.indexPath)).map(({ value }) => value);
};
getIndexPath(valueOrValuePath) {
if (Array.isArray(valueOrValuePath)) {
if (valueOrValuePath.length === 0) return [];
const indexPath = [];
let currentChildren = this.getNodeChildren(this.rootNode);
for (let i = 0; i < valueOrValuePath.length; i++) {
const currentValue = valueOrValuePath[i];
const matchingChildIndex = currentChildren.findIndex((child) => this.getNodeValue(child) === currentValue);
if (matchingChildIndex === -1) break;
indexPath.push(matchingChildIndex);
if (i < valueOrValuePath.length - 1) {
const currentNode = currentChildren[matchingChildIndex];
currentChildren = this.getNodeChildren(currentNode);
}
}
return indexPath;
} else return findIndexPath(this.rootNode, {
getChildren: this.getNodeChildren,
predicate: (node) => this.getNodeValue(node) === valueOrValuePath
});
}
getValue = (indexPath) => {
const node = this.at(indexPath);
return node ? this.getNodeValue(node) : void 0;
};
getValuePath = (indexPath) => {
if (!indexPath) return [];
const valuePath = [];
let currentPath = [...indexPath];
while (currentPath.length > 0) {
const node = this.at(currentPath);
if (node) valuePath.unshift(this.getNodeValue(node));
currentPath.pop();
}
return valuePath;
};
getDepth = (value) => {
return findIndexPath(this.rootNode, {
getChildren: this.getNodeChildren,
predicate: (node) => this.getNodeValue(node) === value
})?.length ?? 0;
};
isSameNode = (node, other) => {
return this.getNodeValue(node) === this.getNodeValue(other);
};
isRootNode = (node) => {
return this.isSameNode(node, this.rootNode);
};
contains = (parentIndexPath, valueIndexPath) => {
if (!parentIndexPath || !valueIndexPath) return false;
return valueIndexPath.slice(0, parentIndexPath.length).every((_, i) => parentIndexPath[i] === valueIndexPath[i]);
};
getNextNode = (value, opts = {}) => {
let found = false;
let nextNode;
visit(this.rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isRootNode(node)) return;
const nodeValue = this.getNodeValue(node);
if (opts.skip?.({
value: nodeValue,
node,
indexPath
})) {
if (nodeValue === value) found = true;
return "skip";
}
if (found && !this.getNodeDisabled(node)) {
nextNode = node;
return "stop";
}
if (nodeValue === value) found = true;
}
});
return nextNode;
};
getPreviousNode = (value, opts = {}) => {
let previousNode;
let found = false;
visit(this.rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isRootNode(node)) return;
const nodeValue = this.getNodeValue(node);
if (opts.skip?.({
value: nodeValue,
node,
indexPath
})) return "skip";
if (nodeValue === value) {
found = true;
return "stop";
}
if (!this.getNodeDisabled(node)) previousNode = node;
}
});
return found ? previousNode : void 0;
};
getParentNodes = (valueOrIndexPath) => {
const indexPath = this.resolveIndexPath(valueOrIndexPath)?.slice();
if (!indexPath) return [];
const result = [];
while (indexPath.length > 0) {
indexPath.pop();
const parentNode = this.at(indexPath);
if (parentNode && !this.isRootNode(parentNode)) result.unshift(parentNode);
}
return result;
};
getDescendantNodes = (valueOrIndexPath, options) => {
const parentNode = this.resolveNode(valueOrIndexPath);
if (!parentNode) return [];
const result = [];
visit(parentNode, {
getChildren: this.getNodeChildren,
onEnter: (node, nodeIndexPath) => {
if (nodeIndexPath.length === 0) return;
if (!options?.withBranch && this.isBranchNode(node)) return;
result.push(node);
}
});
return result;
};
getDescendantValues = (valueOrIndexPath, options) => {
return this.getDescendantNodes(valueOrIndexPath, options).map((child) => this.getNodeValue(child));
};
getParentIndexPath = (indexPath) => {
return indexPath.slice(0, -1);
};
getParentNode = (valueOrIndexPath) => {
const indexPath = this.resolveIndexPath(valueOrIndexPath);
return indexPath ? this.at(this.getParentIndexPath(indexPath)) : void 0;
};
visit = (opts) => {
const { skip, ...rest } = opts;
visit(this.rootNode, {
...rest,
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isRootNode(node)) return;
if (skip?.({
value: this.getNodeValue(node),
node,
indexPath
})) return "skip";
return rest.onEnter?.(node, indexPath);
}
});
};
getPreviousSibling = (indexPath) => {
const parentNode = this.getParentNode(indexPath);
if (!parentNode) return;
const siblings = this.getNodeChildren(parentNode);
let idx = indexPath[indexPath.length - 1];
while (--idx >= 0) {
const sibling = siblings[idx];
if (!this.getNodeDisabled(sibling)) return sibling;
}
};
getNextSibling = (indexPath) => {
const parentNode = this.getParentNode(indexPath);
if (!parentNode) return;
const siblings = this.getNodeChildren(parentNode);
let idx = indexPath[indexPath.length - 1];
while (++idx < siblings.length) {
const sibling = siblings[idx];
if (!this.getNodeDisabled(sibling)) return sibling;
}
};
getSiblingNodes = (indexPath) => {
const parentNode = this.getParentNode(indexPath);
return parentNode ? this.getNodeChildren(parentNode) : [];
};
getValues = (rootNode = this.rootNode) => {
return flatMap(rootNode, {
getChildren: this.getNodeChildren,
transform: (node) => [this.getNodeValue(node)]
}).slice(1);
};
isValidDepth = (indexPath, depth) => {
if (depth == null) return true;
if (typeof depth === "function") return depth(indexPath.length);
return indexPath.length === depth;
};
isBranchNode = (node) => {
return this.getNodeChildren(node).length > 0 || this.getNodeChildrenCount(node) != null;
};
getBranchValues = (rootNode = this.rootNode, opts = {}) => {
let values = [];
visit(rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (indexPath.length === 0) return;
const nodeValue = this.getNodeValue(node);
if (opts.skip?.({
value: nodeValue,
node,
indexPath
})) return "skip";
if (this.isBranchNode(node) && this.isValidDepth(indexPath, opts.depth)) values.push(this.getNodeValue(node));
}
});
return values;
};
flatten = (rootNode = this.rootNode) => {
return flatten(rootNode, { getChildren: this.getNodeChildren });
};
_create = (node, children) => {
if (this.getNodeChildren(node).length > 0 || children.length > 0) return {
...node,
children
};
return { ...node };
};
_insert = (rootNode, indexPath, nodes) => {
return this.copy(insert(rootNode, {
at: indexPath,
nodes,
getChildren: this.getNodeChildren,
create: this._create
}));
};
copy = (rootNode) => {
return new TreeCollection({
...this.options,
rootNode
});
};
_replace = (rootNode, indexPath, node) => {
return this.copy(replace(rootNode, {
at: indexPath,
node,
getChildren: this.getNodeChildren,
create: this._create
}));
};
_move = (rootNode, indexPaths, to) => {
return this.copy(move(rootNode, {
indexPaths,
to,
getChildren: this.getNodeChildren,
create: this._create
}));
};
_remove = (rootNode, indexPaths) => {
return this.copy(remove(rootNode, {
indexPaths,
getChildren: this.getNodeChildren,
create: this._create
}));
};
replace = (indexPath, node) => {
return this._replace(this.rootNode, indexPath, node);
};
remove = (indexPaths) => {
return this._remove(this.rootNode, indexPaths);
};
insertBefore = (indexPath, nodes) => {
return this.getParentNode(indexPath) ? this._insert(this.rootNode, indexPath, nodes) : void 0;
};
insertAfter = (indexPath, nodes) => {
if (!this.getParentNode(indexPath)) return;
const nextIndex = [...indexPath.slice(0, -1), indexPath[indexPath.length - 1] + 1];
return this._insert(this.rootNode, nextIndex, nodes);
};
move = (fromIndexPaths, toIndexPath) => {
return this._move(this.rootNode, fromIndexPaths, toIndexPath);
};
filter = (predicate) => {
const filteredRoot = filter(this.rootNode, {
predicate,
getChildren: this.getNodeChildren,
create: this._create
});
return this.copy(filteredRoot);
};
toJSON = () => {
return this.getValues(this.rootNode);
};
};
function flattenedToTree(nodes, options = fallbackMethods) {
if (nodes.length === 0) throw new Error("[ginxjs/tree] Cannot create tree from empty flattened array");
const rootFlatNode = nodes.find((node) => node._parent === void 0);
if (!rootFlatNode) throw new Error("[ginxjs/tree] No root node found in flattened data");
const nodeMap = /* @__PURE__ */ new Map();
nodes.forEach((node) => {
nodeMap.set(node._index, node);
});
const buildNode = (idx) => {
const flatNode = nodeMap.get(idx);
if (!flatNode) return {};
const { _children, _parent, _index, ...cleanNode } = flatNode;
const children = [];
_children?.forEach((childIndex) => {
children.push(buildNode(childIndex));
});
return {
...cleanNode,
...children.length > 0 && { children }
};
};
const rootNode = buildNode(rootFlatNode._index);
return new TreeCollection({
...options,
rootNode
});
}
function filePathToTree(paths) {
const rootNode = {
label: "",
value: "ROOT",
children: []
};
paths.forEach((path) => {
const parts = path.split("/");
let currentNode = rootNode;
parts.forEach((part, index) => {
let childNode = currentNode.children?.find((child) => child.label === part);
if (!childNode) {
childNode = {
value: parts.slice(0, index + 1).join("/"),
label: part
};
currentNode.children ||= [];
currentNode.children.push(childNode);
}
currentNode = childNode;
});
});
return new TreeCollection({ rootNode });
}
const fallbackMethods = {
nodeToValue(node) {
if (typeof node === "string") return node;
if (require_utils.isObject(node) && require_utils.hasProp(node, "value")) return node.value;
return "";
},
nodeToString(node) {
if (typeof node === "string") return node;
if (require_utils.isObject(node) && require_utils.hasProp(node, "label")) return node.label;
return fallbackMethods.nodeToValue(node);
},
isNodeDisabled(node) {
if (require_utils.isObject(node) && require_utils.hasProp(node, "disabled")) return !!node.disabled;
return false;
},
nodeToChildren(node) {
return node.children;
},
nodeToChildrenCount(node) {
if (require_utils.isObject(node) && require_utils.hasProp(node, "childrenCount")) return node.childrenCount;
}
};
//#endregion
exports.GridCollection = GridCollection;
exports.ListCollection = ListCollection;
exports.Selection = Selection;
exports.TreeCollection = TreeCollection;
exports.createSelectedItemMap = createSelectedItemMap;
exports.deriveSelectionState = deriveSelectionState;
exports.filePathToTree = filePathToTree;
exports.flattenedToTree = flattenedToTree;
exports.isGridCollection = isGridCollection;
exports.isListCollection = isListCollection;
exports.resolveSelectedItems = resolveSelectedItems;
exports.updateSelectedItemMap = updateSelectedItemMap;
//#region src/shared/collection/types.d.ts
interface CollectionSearchState {
keysSoFar: string;
timer: number;
}
interface CollectionSearchOptions {
state: CollectionSearchState;
currentValue: string | null;
timeout?: number | undefined;
}
type CollectionItem = any;
interface CollectionMethods<T extends CollectionItem = CollectionItem> {
itemToValue: (item: T) => string;
itemToString: (item: T) => string;
isItemDisabled: (item: T) => boolean;
}
interface CollectionOptions<T extends CollectionItem = CollectionItem> extends Partial<CollectionMethods<T>> {
items: Iterable<T> | Readonly<Iterable<T>>;
groupBy?: ((item: T, index: number) => string) | undefined;
groupSort?: ((a: string, b: string) => number) | string[] | "asc" | "desc" | undefined;
}
type IndexPath = number[];
type ValuePath = string[];
interface TreeCollectionMethods<T> {
isNodeDisabled: (node: T) => boolean;
nodeToValue: (node: T) => string;
nodeToString: (node: T) => string;
nodeToChildren: (node: T) => any[];
nodeToChildrenCount: (node: T) => number | undefined;
}
interface TreeCollectionOptions<T> extends Partial<TreeCollectionMethods<T>> {
rootNode: T;
}
type TreeNode = any;
type FilePathTreeNode<T = TreeNode> = T & {
children?: FilePathTreeNode<T>[] | undefined;
};
interface FlatTreeNodeMeta {
_children: number[] | undefined;
_parent: number | undefined;
_index: number;
}
type FlatTreeNode<T = TreeNode> = T & FlatTreeNodeMeta;
interface TreeSkipFnArgs<T> {
value: string;
node: T;
indexPath: number[];
}
type TreeSkipFn<T> = (args: TreeSkipFnArgs<T>) => boolean | void;
interface TreeSkipOptions<T> {
skip?: TreeSkipFn<T> | undefined;
}
interface DescendantOptions {
withBranch?: boolean;
}
//#endregion
//#region src/shared/collection/list-collection.d.ts
declare class ListCollection<T extends CollectionItem = CollectionItem> {
private options;
items: T[];
private indexMap;
constructor(options: CollectionOptions<T>);
copy: (items?: T[]) => ListCollection<T>;
isEqual: (other: ListCollection<T>) => boolean;
setItems: (items: T[]) => ListCollection<T>;
getValues: (items?: T[]) => string[];
find: (value: string | null | undefined) => T | null;
findMany: (values: string[]) => T[];
at: (index: number) => T | null;
private sortFn;
sort: (values: string[]) => string[];
getItemValue: (item: T | null | undefined) => string | null;
getItemDisabled: (item: T | null) => boolean;
stringifyItem: (item: T | null) => string | null;
stringify: (value: string | null) => string | null;
stringifyItems: (items: T[], separator?: string) => string;
stringifyMany: (value: string[], separator?: string) => string;
has: (value: string | null) => boolean;
hasItem: (item: T | null) => boolean;
get size(): number;
group: () => [string, T[]][];
get firstValue(): string | null;
get lastValue(): string | null;
getNextValue: (value: string, step?: number, clamp?: boolean) => string | null;
getPreviousValue: (value: string, step?: number, clamp?: boolean) => string | null;
indexOf: (value: string | null) => number;
private getByText;
search: (queryString: string, options: CollectionSearchOptions) => string | null;
[Symbol.iterator](): Generator<T, void, unknown>;
update: (value: string, item: T) => ListCollection<T>;
upsert: (value: string, item: T, mode?: "append" | "prepend") => ListCollection<T>;
insert: (index: number, ...items: T[]) => ListCollection<T>;
insertBefore: (value: string, ...items: T[]) => ListCollection<T>;
insertAfter: (value: string, ...items: T[]) => ListCollection<T>;
prepend: (...items: T[]) => ListCollection<T>;
append: (...items: T[]) => ListCollection<T>;
filter: (fn: (itemString: string, index: number, item: T) => boolean) => ListCollection<T>;
remove: (...itemsOrValues: Array<T | string>) => ListCollection<T>;
move: (value: string, toIndex: number) => ListCollection<T>;
moveBefore: (value: string, ...values: string[]) => ListCollection<T>;
moveAfter: (value: string, ...values: string[]) => ListCollection<T>;
reorder: (fromIndex: number, toIndex: number) => ListCollection<T>;
compareValue: (a: string, b: string) => 1 | 0 | -1;
private range;
getValueRange: (from: string | null, to: string | null) => string[];
toString: () => string;
toJSON: () => {
size: number;
first: string | null;
last: string | null;
};
}
declare function isListCollection(v: unknown): v is ListCollection<any>;
//#endregion
//#region src/shared/collection/grid-collection.d.ts
interface GridCollectionOptions<T> extends CollectionOptions<T> {
columnCount: number;
}
declare class GridCollection<T extends CollectionItem = CollectionItem> extends ListCollection<T> {
columnCount: number;
private rows;
constructor(options: GridCollectionOptions<T>);
getRows: () => T[][];
getRowCount: () => number;
getCellIndex: (row: number, column: number) => number;
getCell: (row: number, column: number) => T | null;
getValueCell: (value: string) => {
row: number;
column: number;
} | null;
getLastEnabledColumnIndex: (row: number) => number | null;
getFirstEnabledColumnIndex: (row: number) => number | null;
getPreviousRowValue: (value: string, loop?: boolean) => string | null;
getNextRowValue: (value: string, loop?: boolean) => string | null;
}
declare function isGridCollection(v: any): v is GridCollection<any>;
//#endregion
//#region src/shared/collection/selection-map.d.ts
interface SelectionMapCollection<T extends CollectionItem = CollectionItem> {
find: (value: string | null | undefined) => T | null;
getItemValue: (item: T | null | undefined) => string | null;
}
declare function resolveSelectedItems<T extends CollectionItem>({
values,
collection,
selectedItemMap
}: {
values: string[];
collection: SelectionMapCollection<T>;
selectedItemMap: Map<string, T>;
}): T[];
declare function updateSelectedItemMap<T extends CollectionItem>({
selectedItemMap,
values,
selectedItems,
collection
}: {
selectedItemMap: Map<string, T>;
values: string[];
selectedItems: T[];
collection: SelectionMapCollection<T>;
}): Map<string, T>;
declare function deriveSelectionState<T extends CollectionItem>({
values,
collection,
selectedItemMap
}: {
values: string[];
collection: SelectionMapCollection<T>;
selectedItemMap: Map<string, T>;
}): {
selectedItems: T[];
nextSelectedItemMap: Map<string, T>;
};
declare function createSelectedItemMap<T extends CollectionItem>({
selectedItems,
collection
}: {
selectedItems: T[];
collection: SelectionMapCollection<T>;
}): Map<string, T>;
//#endregion
//#region src/shared/collection/selection.d.ts
type SelectionMode = "single" | "multiple" | "none" | "extended";
declare class Selection extends Set<string> {
selectionMode: SelectionMode;
deselectable: boolean;
constructor(values?: Iterable<string>);
copy: () => Selection;
private sync;
isEmpty: () => boolean;
isSelected: (value: string | null) => boolean;
canSelect: (collection: ListCollection, value: string) => boolean;
firstSelectedValue: (collection: ListCollection) => string | null;
lastSelectedValue: (collection: ListCollection) => string | null;
extendSelection: (collection: ListCollection, anchorValue: string, targetValue: string) => Selection;
toggleSelection: (collection: ListCollection, value: string) => Selection;
replaceSelection: (collection: ListCollection, value: string | null) => Selection;
setSelection: (values: Iterable<string>) => Selection;
clearSelection: () => Selection;
select: (collection: ListCollection, value: string, forceToggle?: boolean) => Selection;
deselect: (value: string) => Selection;
isEqual: (other: Selection) => boolean;
}
//#endregion
//#region src/shared/collection/tree-visit.d.ts
interface BaseOptions<T> {
getChildren: (node: T, indexPath: IndexPath) => T[];
reuseIndexPath?: boolean | undefined;
}
type TreeVisitEnterReturnValue = void | "skip" | "stop";
type TreeVisitLeaveReturnValue = void | "stop";
interface TreeVisitOptions<T> extends BaseOptions<T> {
onEnter?(node: T, indexPath: IndexPath): TreeVisitEnterReturnValue;
onLeave?(node: T, indexPath: IndexPath): TreeVisitLeaveReturnValue;
}
//#endregion
//#region src/shared/collection/tree-collection.d.ts
declare class TreeCollection<T = TreeNode> {
private options;
rootNode: T;
constructor(options: TreeCollectionOptions<T>);
isEqual: (other: TreeCollection<T>) => boolean;
getNodeChildren: (node: T) => T[];
private resolveIndexPath;
private resolveNode;
getNodeChildrenCount: (node: T) => number | undefined;
getNodeValue: (node: T) => string;
getNodeDisabled: (node: T) => boolean;
stringify: (value: string) => string | null;
stringifyNode: (node: T) => string;
getFirstNode: (rootNode?: T, opts?: TreeSkipOptions<T>) => T | undefined;
getLastNode: (rootNode?: T, opts?: TreeSkipOptions<T>) => T | undefined;
at: (indexPath: IndexPath) => T | undefined;
findNode: (value: string, rootNode?: T) => T | undefined;
findNodes: (values: string[], rootNode?: T) => T[];
sort: (values: string[]) => string[];
getIndexPath(value: string): IndexPath | undefined;
getIndexPath(valuePath: string[]): IndexPath;
getValue: (indexPath: IndexPath) => string | undefined;
getValuePath: (indexPath: IndexPath | undefined) => string[];
getDepth: (value: string) => number;
isSameNode: (node: T, other: T) => boolean;
isRootNode: (node: T) => boolean;
contains: (parentIndexPath: IndexPath, valueIndexPath: IndexPath) => boolean;
getNextNode: (value: string, opts?: TreeSkipOptions<T>) => T | undefined;
getPreviousNode: (value: string, opts?: TreeSkipOptions<T>) => T | undefined;
getParentNodes: (valueOrIndexPath: string | IndexPath) => T[];
getDescendantNodes: (valueOrIndexPath: string | IndexPath, options?: DescendantOptions) => T[];
getDescendantValues: (valueOrIndexPath: string | IndexPath, options?: DescendantOptions) => string[];
private getParentIndexPath;
getParentNode: (valueOrIndexPath: string | IndexPath) => T | undefined;
visit: (opts: Omit<TreeVisitOptions<T>, "getChildren"> & TreeSkipOptions<T>) => void;
getPreviousSibling: (indexPath: IndexPath) => T | undefined;
getNextSibling: (indexPath: IndexPath) => T | undefined;
getSiblingNodes: (indexPath: IndexPath) => T[];
getValues: (rootNode?: T) => string[];
private isValidDepth;
isBranchNode: (node: T) => boolean;
getBranchValues: (rootNode?: T, opts?: TreeSkipOptions<T> & {
depth?: number | ((nodeDepth: number) => boolean) | undefined;
}) => string[];
flatten: (rootNode?: T) => Array<FlatTreeNode<T>>;
private _create;
private _insert;
copy: (rootNode: T) => TreeCollection<T>;
private _replace;
private _move;
private _remove;
replace: (indexPath: IndexPath, node: T) => TreeCollection<T>;
remove: (indexPaths: IndexPath[]) => TreeCollection<T>;
insertBefore: (indexPath: IndexPath, nodes: T[]) => TreeCollection<T> | undefined;
insertAfter: (indexPath: IndexPath, nodes: T[]) => TreeCollection<T> | undefined;
move: (fromIndexPaths: IndexPath[], toIndexPath: IndexPath) => TreeCollection<T>;
filter: (predicate: (node: T, indexPath: IndexPath) => boolean) => TreeCollection<T>;
toJSON: () => string[];
}
declare function flattenedToTree<T>(nodes: Array<FlatTreeNode<T>>, options?: TreeCollectionMethods<T>): TreeCollection<T>;
declare function filePathToTree(paths: string[]): TreeCollection<FilePathTreeNode>;
//#endregion
export { CollectionItem, CollectionMethods, CollectionOptions, CollectionSearchOptions, CollectionSearchState, FilePathTreeNode, FlatTreeNode, FlatTreeNodeMeta, GridCollection, GridCollectionOptions, IndexPath, ListCollection, Selection, SelectionMapCollection, SelectionMode, TreeCollection, TreeCollectionMethods, TreeCollectionOptions, TreeNode, TreeSkipFn, ValuePath, createSelectedItemMap, deriveSelectionState, filePathToTree, flattenedToTree, isGridCollection, isListCollection, resolveSelectedItems, updateSelectedItemMap };
//#region src/shared/collection/types.d.ts
interface CollectionSearchState {
keysSoFar: string;
timer: number;
}
interface CollectionSearchOptions {
state: CollectionSearchState;
currentValue: string | null;
timeout?: number | undefined;
}
type CollectionItem = any;
interface CollectionMethods<T extends CollectionItem = CollectionItem> {
itemToValue: (item: T) => string;
itemToString: (item: T) => string;
isItemDisabled: (item: T) => boolean;
}
interface CollectionOptions<T extends CollectionItem = CollectionItem> extends Partial<CollectionMethods<T>> {
items: Iterable<T> | Readonly<Iterable<T>>;
groupBy?: ((item: T, index: number) => string) | undefined;
groupSort?: ((a: string, b: string) => number) | string[] | "asc" | "desc" | undefined;
}
type IndexPath = number[];
type ValuePath = string[];
interface TreeCollectionMethods<T> {
isNodeDisabled: (node: T) => boolean;
nodeToValue: (node: T) => string;
nodeToString: (node: T) => string;
nodeToChildren: (node: T) => any[];
nodeToChildrenCount: (node: T) => number | undefined;
}
interface TreeCollectionOptions<T> extends Partial<TreeCollectionMethods<T>> {
rootNode: T;
}
type TreeNode = any;
type FilePathTreeNode<T = TreeNode> = T & {
children?: FilePathTreeNode<T>[] | undefined;
};
interface FlatTreeNodeMeta {
_children: number[] | undefined;
_parent: number | undefined;
_index: number;
}
type FlatTreeNode<T = TreeNode> = T & FlatTreeNodeMeta;
interface TreeSkipFnArgs<T> {
value: string;
node: T;
indexPath: number[];
}
type TreeSkipFn<T> = (args: TreeSkipFnArgs<T>) => boolean | void;
interface TreeSkipOptions<T> {
skip?: TreeSkipFn<T> | undefined;
}
interface DescendantOptions {
withBranch?: boolean;
}
//#endregion
//#region src/shared/collection/list-collection.d.ts
declare class ListCollection<T extends CollectionItem = CollectionItem> {
private options;
items: T[];
private indexMap;
constructor(options: CollectionOptions<T>);
copy: (items?: T[]) => ListCollection<T>;
isEqual: (other: ListCollection<T>) => boolean;
setItems: (items: T[]) => ListCollection<T>;
getValues: (items?: T[]) => string[];
find: (value: string | null | undefined) => T | null;
findMany: (values: string[]) => T[];
at: (index: number) => T | null;
private sortFn;
sort: (values: string[]) => string[];
getItemValue: (item: T | null | undefined) => string | null;
getItemDisabled: (item: T | null) => boolean;
stringifyItem: (item: T | null) => string | null;
stringify: (value: string | null) => string | null;
stringifyItems: (items: T[], separator?: string) => string;
stringifyMany: (value: string[], separator?: string) => string;
has: (value: string | null) => boolean;
hasItem: (item: T | null) => boolean;
get size(): number;
group: () => [string, T[]][];
get firstValue(): string | null;
get lastValue(): string | null;
getNextValue: (value: string, step?: number, clamp?: boolean) => string | null;
getPreviousValue: (value: string, step?: number, clamp?: boolean) => string | null;
indexOf: (value: string | null) => number;
private getByText;
search: (queryString: string, options: CollectionSearchOptions) => string | null;
[Symbol.iterator](): Generator<T, void, unknown>;
update: (value: string, item: T) => ListCollection<T>;
upsert: (value: string, item: T, mode?: "append" | "prepend") => ListCollection<T>;
insert: (index: number, ...items: T[]) => ListCollection<T>;
insertBefore: (value: string, ...items: T[]) => ListCollection<T>;
insertAfter: (value: string, ...items: T[]) => ListCollection<T>;
prepend: (...items: T[]) => ListCollection<T>;
append: (...items: T[]) => ListCollection<T>;
filter: (fn: (itemString: string, index: number, item: T) => boolean) => ListCollection<T>;
remove: (...itemsOrValues: Array<T | string>) => ListCollection<T>;
move: (value: string, toIndex: number) => ListCollection<T>;
moveBefore: (value: string, ...values: string[]) => ListCollection<T>;
moveAfter: (value: string, ...values: string[]) => ListCollection<T>;
reorder: (fromIndex: number, toIndex: number) => ListCollection<T>;
compareValue: (a: string, b: string) => 1 | 0 | -1;
private range;
getValueRange: (from: string | null, to: string | null) => string[];
toString: () => string;
toJSON: () => {
size: number;
first: string | null;
last: string | null;
};
}
declare function isListCollection(v: unknown): v is ListCollection<any>;
//#endregion
//#region src/shared/collection/grid-collection.d.ts
interface GridCollectionOptions<T> extends CollectionOptions<T> {
columnCount: number;
}
declare class GridCollection<T extends CollectionItem = CollectionItem> extends ListCollection<T> {
columnCount: number;
private rows;
constructor(options: GridCollectionOptions<T>);
getRows: () => T[][];
getRowCount: () => number;
getCellIndex: (row: number, column: number) => number;
getCell: (row: number, column: number) => T | null;
getValueCell: (value: string) => {
row: number;
column: number;
} | null;
getLastEnabledColumnIndex: (row: number) => number | null;
getFirstEnabledColumnIndex: (row: number) => number | null;
getPreviousRowValue: (value: string, loop?: boolean) => string | null;
getNextRowValue: (value: string, loop?: boolean) => string | null;
}
declare function isGridCollection(v: any): v is GridCollection<any>;
//#endregion
//#region src/shared/collection/selection-map.d.ts
interface SelectionMapCollection<T extends CollectionItem = CollectionItem> {
find: (value: string | null | undefined) => T | null;
getItemValue: (item: T | null | undefined) => string | null;
}
declare function resolveSelectedItems<T extends CollectionItem>({
values,
collection,
selectedItemMap
}: {
values: string[];
collection: SelectionMapCollection<T>;
selectedItemMap: Map<string, T>;
}): T[];
declare function updateSelectedItemMap<T extends CollectionItem>({
selectedItemMap,
values,
selectedItems,
collection
}: {
selectedItemMap: Map<string, T>;
values: string[];
selectedItems: T[];
collection: SelectionMapCollection<T>;
}): Map<string, T>;
declare function deriveSelectionState<T extends CollectionItem>({
values,
collection,
selectedItemMap
}: {
values: string[];
collection: SelectionMapCollection<T>;
selectedItemMap: Map<string, T>;
}): {
selectedItems: T[];
nextSelectedItemMap: Map<string, T>;
};
declare function createSelectedItemMap<T extends CollectionItem>({
selectedItems,
collection
}: {
selectedItems: T[];
collection: SelectionMapCollection<T>;
}): Map<string, T>;
//#endregion
//#region src/shared/collection/selection.d.ts
type SelectionMode = "single" | "multiple" | "none" | "extended";
declare class Selection extends Set<string> {
selectionMode: SelectionMode;
deselectable: boolean;
constructor(values?: Iterable<string>);
copy: () => Selection;
private sync;
isEmpty: () => boolean;
isSelected: (value: string | null) => boolean;
canSelect: (collection: ListCollection, value: string) => boolean;
firstSelectedValue: (collection: ListCollection) => string | null;
lastSelectedValue: (collection: ListCollection) => string | null;
extendSelection: (collection: ListCollection, anchorValue: string, targetValue: string) => Selection;
toggleSelection: (collection: ListCollection, value: string) => Selection;
replaceSelection: (collection: ListCollection, value: string | null) => Selection;
setSelection: (values: Iterable<string>) => Selection;
clearSelection: () => Selection;
select: (collection: ListCollection, value: string, forceToggle?: boolean) => Selection;
deselect: (value: string) => Selection;
isEqual: (other: Selection) => boolean;
}
//#endregion
//#region src/shared/collection/tree-visit.d.ts
interface BaseOptions<T> {
getChildren: (node: T, indexPath: IndexPath) => T[];
reuseIndexPath?: boolean | undefined;
}
type TreeVisitEnterReturnValue = void | "skip" | "stop";
type TreeVisitLeaveReturnValue = void | "stop";
interface TreeVisitOptions<T> extends BaseOptions<T> {
onEnter?(node: T, indexPath: IndexPath): TreeVisitEnterReturnValue;
onLeave?(node: T, indexPath: IndexPath): TreeVisitLeaveReturnValue;
}
//#endregion
//#region src/shared/collection/tree-collection.d.ts
declare class TreeCollection<T = TreeNode> {
private options;
rootNode: T;
constructor(options: TreeCollectionOptions<T>);
isEqual: (other: TreeCollection<T>) => boolean;
getNodeChildren: (node: T) => T[];
private resolveIndexPath;
private resolveNode;
getNodeChildrenCount: (node: T) => number | undefined;
getNodeValue: (node: T) => string;
getNodeDisabled: (node: T) => boolean;
stringify: (value: string) => string | null;
stringifyNode: (node: T) => string;
getFirstNode: (rootNode?: T, opts?: TreeSkipOptions<T>) => T | undefined;
getLastNode: (rootNode?: T, opts?: TreeSkipOptions<T>) => T | undefined;
at: (indexPath: IndexPath) => T | undefined;
findNode: (value: string, rootNode?: T) => T | undefined;
findNodes: (values: string[], rootNode?: T) => T[];
sort: (values: string[]) => string[];
getIndexPath(value: string): IndexPath | undefined;
getIndexPath(valuePath: string[]): IndexPath;
getValue: (indexPath: IndexPath) => string | undefined;
getValuePath: (indexPath: IndexPath | undefined) => string[];
getDepth: (value: string) => number;
isSameNode: (node: T, other: T) => boolean;
isRootNode: (node: T) => boolean;
contains: (parentIndexPath: IndexPath, valueIndexPath: IndexPath) => boolean;
getNextNode: (value: string, opts?: TreeSkipOptions<T>) => T | undefined;
getPreviousNode: (value: string, opts?: TreeSkipOptions<T>) => T | undefined;
getParentNodes: (valueOrIndexPath: string | IndexPath) => T[];
getDescendantNodes: (valueOrIndexPath: string | IndexPath, options?: DescendantOptions) => T[];
getDescendantValues: (valueOrIndexPath: string | IndexPath, options?: DescendantOptions) => string[];
private getParentIndexPath;
getParentNode: (valueOrIndexPath: string | IndexPath) => T | undefined;
visit: (opts: Omit<TreeVisitOptions<T>, "getChildren"> & TreeSkipOptions<T>) => void;
getPreviousSibling: (indexPath: IndexPath) => T | undefined;
getNextSibling: (indexPath: IndexPath) => T | undefined;
getSiblingNodes: (indexPath: IndexPath) => T[];
getValues: (rootNode?: T) => string[];
private isValidDepth;
isBranchNode: (node: T) => boolean;
getBranchValues: (rootNode?: T, opts?: TreeSkipOptions<T> & {
depth?: number | ((nodeDepth: number) => boolean) | undefined;
}) => string[];
flatten: (rootNode?: T) => Array<FlatTreeNode<T>>;
private _create;
private _insert;
copy: (rootNode: T) => TreeCollection<T>;
private _replace;
private _move;
private _remove;
replace: (indexPath: IndexPath, node: T) => TreeCollection<T>;
remove: (indexPaths: IndexPath[]) => TreeCollection<T>;
insertBefore: (indexPath: IndexPath, nodes: T[]) => TreeCollection<T> | undefined;
insertAfter: (indexPath: IndexPath, nodes: T[]) => TreeCollection<T> | undefined;
move: (fromIndexPaths: IndexPath[], toIndexPath: IndexPath) => TreeCollection<T>;
filter: (predicate: (node: T, indexPath: IndexPath) => boolean) => TreeCollection<T>;
toJSON: () => string[];
}
declare function flattenedToTree<T>(nodes: Array<FlatTreeNode<T>>, options?: TreeCollectionMethods<T>): TreeCollection<T>;
declare function filePathToTree(paths: string[]): TreeCollection<FilePathTreeNode>;
//#endregion
export { CollectionItem, CollectionMethods, CollectionOptions, CollectionSearchOptions, CollectionSearchState, FilePathTreeNode, FlatTreeNode, FlatTreeNodeMeta, GridCollection, GridCollectionOptions, IndexPath, ListCollection, Selection, SelectionMapCollection, SelectionMode, TreeCollection, TreeCollectionMethods, TreeCollectionOptions, TreeNode, TreeSkipFn, ValuePath, createSelectedItemMap, deriveSelectionState, filePathToTree, flattenedToTree, isGridCollection, isListCollection, resolveSelectedItems, updateSelectedItemMap };
import { Et as nextIndex, ct as isObject, ft as isEqual, ht as chunk, kt as prevIndex, tt as hasProp } from "./utils-CeIB7ETu.mjs";
//#region src/shared/collection/list-collection.ts
const fallback = {
itemToValue(item) {
if (typeof item === "string") return item;
if (isObject(item) && hasProp(item, "value")) return item.value;
return "";
},
itemToString(item) {
if (typeof item === "string") return item;
if (isObject(item) && hasProp(item, "label")) return item.label;
return fallback.itemToValue(item);
},
isItemDisabled(item) {
if (isObject(item) && hasProp(item, "disabled")) return !!item.disabled;
return false;
}
};
var ListCollection = class ListCollection {
options;
items;
indexMap = null;
constructor(options) {
this.options = options;
this.items = [...options.items];
}
copy = (items) => {
return new ListCollection({
...this.options,
items: items ?? [...this.items]
});
};
isEqual = (other) => {
return isEqual(this.items, other.items);
};
setItems = (items) => {
return this.copy(items);
};
getValues = (items = this.items) => {
const values = [];
for (const item of items) {
const value = this.getItemValue(item);
if (value != null) values.push(value);
}
return values;
};
find = (value) => {
if (value == null) return null;
const index = this.indexOf(value);
return index !== -1 ? this.at(index) : null;
};
findMany = (values) => {
const result = [];
for (const value of values) {
const item = this.find(value);
if (item != null) result.push(item);
}
return result;
};
at = (index) => {
if (!this.options.groupBy && !this.options.groupSort) return this.items[index] ?? null;
let idx = 0;
const groups = this.group();
for (const [, items] of groups) for (const item of items) {
if (idx === index) return item;
idx++;
}
return null;
};
sortFn = (valueA, valueB) => {
const indexA = this.indexOf(valueA);
const indexB = this.indexOf(valueB);
return (indexA ?? 0) - (indexB ?? 0);
};
sort = (values) => {
return [...values].sort(this.sortFn.bind(this));
};
getItemValue = (item) => {
if (item == null) return null;
return this.options.itemToValue?.(item) ?? fallback.itemToValue(item);
};
getItemDisabled = (item) => {
if (item == null) return false;
return this.options.isItemDisabled?.(item) ?? fallback.isItemDisabled(item);
};
stringifyItem = (item) => {
if (item == null) return null;
return this.options.itemToString?.(item) ?? fallback.itemToString(item);
};
stringify = (value) => {
if (value == null) return null;
return this.stringifyItem(this.find(value));
};
stringifyItems = (items, separator = ", ") => {
const strs = [];
for (const item of items) {
const str = this.stringifyItem(item);
if (str != null) strs.push(str);
}
return strs.join(separator);
};
stringifyMany = (value, separator) => {
return this.stringifyItems(this.findMany(value), separator);
};
has = (value) => {
return this.indexOf(value) !== -1;
};
hasItem = (item) => {
if (item == null) return false;
return this.has(this.getItemValue(item));
};
get size() {
return this.items.length;
}
group = () => {
const { groupBy, groupSort } = this.options;
if (!groupBy) return [["", [...this.items]]];
const groups = /* @__PURE__ */ new Map();
this.items.forEach((item, index) => {
const groupKey = groupBy(item, index);
if (!groups.has(groupKey)) groups.set(groupKey, []);
groups.get(groupKey).push(item);
});
let entries = Array.from(groups.entries());
if (groupSort) entries.sort(([a], [b]) => {
if (typeof groupSort === "function") return groupSort(a, b);
if (Array.isArray(groupSort)) {
const indexA = groupSort.indexOf(a);
const indexB = groupSort.indexOf(b);
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
}
if (groupSort === "asc") return a.localeCompare(b);
if (groupSort === "desc") return b.localeCompare(a);
return 0;
});
return entries;
};
get firstValue() {
let index = 0;
while (this.getItemDisabled(this.at(index))) index++;
return this.getItemValue(this.at(index));
}
get lastValue() {
let index = this.size - 1;
while (this.getItemDisabled(this.at(index))) index--;
return this.getItemValue(this.at(index));
}
getNextValue = (value, step = 1, clamp = false) => {
let index = this.indexOf(value);
if (index === -1) return null;
index = clamp ? Math.min(index + step, this.size - 1) : index + step;
while (index <= this.size && this.getItemDisabled(this.at(index))) index++;
return this.getItemValue(this.at(index));
};
getPreviousValue = (value, step = 1, clamp = false) => {
let index = this.indexOf(value);
if (index === -1) return null;
index = clamp ? Math.max(index - step, 0) : index - step;
while (index >= 0 && this.getItemDisabled(this.at(index))) index--;
return this.getItemValue(this.at(index));
};
indexOf = (value) => {
if (value == null) return -1;
if (!this.options.groupBy && !this.options.groupSort) return this.items.findIndex((item) => this.getItemValue(item) === value);
if (!this.indexMap) {
this.indexMap = /* @__PURE__ */ new Map();
let idx = 0;
const groups = this.group();
for (const [, items] of groups) for (const item of items) {
const itemValue = this.getItemValue(item);
if (itemValue != null) this.indexMap.set(itemValue, idx);
idx++;
}
}
return this.indexMap.get(value) ?? -1;
};
getByText = (text, current) => {
const currentIndex = current != null ? this.indexOf(current) : -1;
const isSingleKey = text.length === 1;
for (let i = 0; i < this.items.length; i++) {
const item = this.items[(currentIndex + i + 1) % this.items.length];
if (isSingleKey && this.getItemValue(item) === current) continue;
if (this.getItemDisabled(item)) continue;
if (match(this.stringifyItem(item), text)) return item;
}
};
search = (queryString, options) => {
const { state, currentValue, timeout = 350 } = options;
const search = state.keysSoFar + queryString;
const query = search.length > 1 && Array.from(search).every((char) => char === search[0]) ? search[0] : search;
const item = this.getByText(query, currentValue);
const value = this.getItemValue(item);
function cleanup() {
clearTimeout(state.timer);
state.timer = -1;
}
function update(value) {
state.keysSoFar = value;
cleanup();
if (value !== "") state.timer = +setTimeout(() => {
update("");
cleanup();
}, timeout);
}
update(search);
return value;
};
*[Symbol.iterator]() {
yield* this.items;
}
update = (value, item) => {
let index = this.indexOf(value);
if (index === -1) return this;
return this.copy([
...this.items.slice(0, index),
item,
...this.items.slice(index + 1)
]);
};
upsert = (value, item, mode = "append") => {
let index = this.indexOf(value);
if (index === -1) return (mode === "append" ? this.append : this.prepend)(item);
return this.copy([
...this.items.slice(0, index),
item,
...this.items.slice(index + 1)
]);
};
insert = (index, ...items) => {
return this.copy(insert$1(this.items, index, ...items));
};
insertBefore = (value, ...items) => {
let toIndex = this.indexOf(value);
if (toIndex === -1) if (this.items.length === 0) toIndex = 0;
else return this;
return this.copy(insert$1(this.items, toIndex, ...items));
};
insertAfter = (value, ...items) => {
let toIndex = this.indexOf(value);
if (toIndex === -1) if (this.items.length === 0) toIndex = 0;
else return this;
return this.copy(insert$1(this.items, toIndex + 1, ...items));
};
prepend = (...items) => {
return this.copy(insert$1(this.items, 0, ...items));
};
append = (...items) => {
return this.copy(insert$1(this.items, this.items.length, ...items));
};
filter = (fn) => {
const filteredItems = this.items.filter((item, index) => fn(this.stringifyItem(item), index, item));
return this.copy(filteredItems);
};
remove = (...itemsOrValues) => {
const values = itemsOrValues.map((itemOrValue) => typeof itemOrValue === "string" ? itemOrValue : this.getItemValue(itemOrValue));
return this.copy(this.items.filter((item) => {
const value = this.getItemValue(item);
if (value == null) return false;
return !values.includes(value);
}));
};
move = (value, toIndex) => {
const fromIndex = this.indexOf(value);
if (fromIndex === -1) return this;
return this.copy(move$1(this.items, [fromIndex], toIndex));
};
moveBefore = (value, ...values) => {
let toIndex = this.items.findIndex((item) => this.getItemValue(item) === value);
if (toIndex === -1) return this;
let indices = values.map((value) => this.items.findIndex((item) => this.getItemValue(item) === value)).sort((a, b) => a - b);
return this.copy(move$1(this.items, indices, toIndex));
};
moveAfter = (value, ...values) => {
let toIndex = this.items.findIndex((item) => this.getItemValue(item) === value);
if (toIndex === -1) return this;
let indices = values.map((value) => this.items.findIndex((item) => this.getItemValue(item) === value)).sort((a, b) => a - b);
return this.copy(move$1(this.items, indices, toIndex + 1));
};
reorder = (fromIndex, toIndex) => {
return this.copy(move$1(this.items, [fromIndex], toIndex));
};
compareValue = (a, b) => {
const indexA = this.indexOf(a);
const indexB = this.indexOf(b);
if (indexA < indexB) return -1;
if (indexA > indexB) return 1;
return 0;
};
range = (from, to) => {
let keys = [];
let key = from;
while (key != null) {
if (this.find(key)) keys.push(key);
if (key === to) return keys;
key = this.getNextValue(key);
}
return [];
};
getValueRange = (from, to) => {
if (from && to) {
if (this.compareValue(from, to) <= 0) return this.range(from, to);
return this.range(to, from);
}
return [];
};
toString = () => {
let result = "";
for (const item of this.items) {
const itemString = [
this.getItemValue(item),
this.stringifyItem(item),
this.getItemDisabled(item)
].filter(Boolean).join(":");
result += itemString + ",";
}
return result;
};
toJSON = () => {
return {
size: this.size,
first: this.firstValue,
last: this.lastValue
};
};
};
const match = (label, query) => {
return !!label?.toLowerCase().startsWith(query.toLowerCase());
};
function isListCollection(v) {
return v instanceof ListCollection;
}
function insert$1(items, index, ...values) {
return [
...items.slice(0, index),
...values,
...items.slice(index)
];
}
function move$1(items, indices, toIndex) {
indices = [...indices].sort((a, b) => a - b);
const itemsToMove = indices.map((i) => items[i]);
for (let i = indices.length - 1; i >= 0; i--) items = [...items.slice(0, indices[i]), ...items.slice(indices[i] + 1)];
toIndex = Math.max(0, toIndex - indices.filter((i) => i < toIndex).length);
return [
...items.slice(0, toIndex),
...itemsToMove,
...items.slice(toIndex)
];
}
//#endregion
//#region src/shared/collection/grid-collection.ts
var GridCollection = class extends ListCollection {
columnCount;
rows = null;
constructor(options) {
const { columnCount } = options;
super(options);
this.columnCount = columnCount;
}
getRows = () => {
if (!this.rows) this.rows = chunk([...this.items], this.columnCount);
return this.rows;
};
getRowCount = () => {
return Math.ceil(this.items.length / this.columnCount);
};
getCellIndex = (row, column) => {
return row * this.columnCount + column;
};
getCell = (row, column) => {
return this.at(this.getCellIndex(row, column));
};
getValueCell = (value) => {
const index = this.indexOf(value);
if (index === -1) return null;
return {
row: Math.floor(index / this.columnCount),
column: index % this.columnCount
};
};
getLastEnabledColumnIndex = (row) => {
for (let col = this.columnCount - 1; col >= 0; col--) {
const cell = this.getCell(row, col);
if (cell && !this.getItemDisabled(cell)) return col;
}
return null;
};
getFirstEnabledColumnIndex = (row) => {
for (let col = 0; col < this.columnCount; col++) {
const cell = this.getCell(row, col);
if (cell && !this.getItemDisabled(cell)) return col;
}
return null;
};
getPreviousRowValue = (value, loop = false) => {
const currentCell = this.getValueCell(value);
if (currentCell === null) return null;
const rows = this.getRows();
const rowCount = rows.length;
let prevRowIndex = currentCell.row;
let prevColumnIndex = currentCell.column;
for (let i = 1; i <= rowCount; i++) {
prevRowIndex = prevIndex(rows, prevRowIndex, { loop });
const prevRow = rows[prevRowIndex];
if (!prevRow) continue;
if (!prevRow[prevColumnIndex]) {
const lastColumnIndex = this.getLastEnabledColumnIndex(prevRowIndex);
if (lastColumnIndex != null) prevColumnIndex = lastColumnIndex;
}
const cell = this.getCell(prevRowIndex, prevColumnIndex);
if (!this.getItemDisabled(cell)) return this.getItemValue(cell);
}
return this.firstValue;
};
getNextRowValue = (value, loop = false) => {
const currentCell = this.getValueCell(value);
if (currentCell === null) return null;
const rows = this.getRows();
const rowCount = rows.length;
let nextRowIndex = currentCell.row;
let nextColumnIndex = currentCell.column;
for (let i = 1; i <= rowCount; i++) {
nextRowIndex = nextIndex(rows, nextRowIndex, { loop });
const nextRow = rows[nextRowIndex];
if (!nextRow) continue;
if (!nextRow[nextColumnIndex]) {
const lastColumnIndex = this.getLastEnabledColumnIndex(nextRowIndex);
if (lastColumnIndex != null) nextColumnIndex = lastColumnIndex;
}
const cell = this.getCell(nextRowIndex, nextColumnIndex);
if (!this.getItemDisabled(cell)) return this.getItemValue(cell);
}
return this.lastValue;
};
};
function isGridCollection(v) {
return hasProp(v, "columnCount") && hasProp(v, "getRows");
}
//#endregion
//#region src/shared/collection/selection-map.ts
function resolveSelectedItems({ values, collection, selectedItemMap }) {
const result = [];
for (const value of values) {
const item = collection.find(value) ?? selectedItemMap.get(value);
if (item != null) result.push(item);
}
return result;
}
function updateSelectedItemMap({ selectedItemMap, values, selectedItems, collection }) {
const nextMap = new Map(selectedItemMap);
for (const item of selectedItems) {
const value = collection.getItemValue(item);
if (value != null) nextMap.set(value, item);
}
const allowedValues = new Set(values);
for (const value of nextMap.keys()) if (!allowedValues.has(value)) nextMap.delete(value);
return nextMap;
}
function deriveSelectionState({ values, collection, selectedItemMap }) {
const selectedItems = resolveSelectedItems({
values,
collection,
selectedItemMap
});
return {
selectedItems,
nextSelectedItemMap: updateSelectedItemMap({
selectedItemMap,
values,
selectedItems,
collection
})
};
}
function createSelectedItemMap({ selectedItems, collection }) {
return updateSelectedItemMap({
selectedItemMap: /* @__PURE__ */ new Map(),
values: selectedItems.map((item) => collection.getItemValue(item)).filter(Boolean),
selectedItems,
collection
});
}
//#endregion
//#region src/shared/collection/selection.ts
var Selection = class Selection extends Set {
selectionMode = "single";
deselectable = true;
constructor(values = []) {
super(values);
}
copy = () => {
const clone = new Selection([...this]);
return this.sync(clone);
};
sync = (other) => {
other.selectionMode = this.selectionMode;
other.deselectable = this.deselectable;
return other;
};
isEmpty = () => {
return this.size === 0;
};
isSelected = (value) => {
if (this.selectionMode === "none" || value == null) return false;
return this.has(value);
};
canSelect = (collection, value) => {
return this.selectionMode !== "none" || !collection.getItemDisabled(collection.find(value));
};
firstSelectedValue = (collection) => {
let firstValue = null;
for (let value of this) if (!firstValue || collection.compareValue(value, firstValue) < 0) firstValue = value;
return firstValue;
};
lastSelectedValue = (collection) => {
let lastValue = null;
for (let value of this) if (!lastValue || collection.compareValue(value, lastValue) > 0) lastValue = value;
return lastValue;
};
extendSelection = (collection, anchorValue, targetValue) => {
if (this.selectionMode === "none") return this;
if (this.selectionMode === "single") return this.replaceSelection(collection, targetValue);
const selection = this.copy();
const lastSelected = Array.from(this).pop();
for (let key of collection.getValueRange(anchorValue, lastSelected ?? targetValue)) selection.delete(key);
for (let key of collection.getValueRange(targetValue, anchorValue)) if (this.canSelect(collection, key)) selection.add(key);
return selection;
};
toggleSelection = (collection, value) => {
if (this.selectionMode === "none") return this;
if (this.selectionMode === "single" && !this.isSelected(value)) return this.replaceSelection(collection, value);
const selection = this.copy();
if (selection.has(value)) selection.delete(value);
else if (selection.canSelect(collection, value)) selection.add(value);
return selection;
};
replaceSelection = (collection, value) => {
if (this.selectionMode === "none") return this;
if (value == null) return this;
if (!this.canSelect(collection, value)) return this;
const selection = new Selection([value]);
return this.sync(selection);
};
setSelection = (values) => {
if (this.selectionMode === "none") return this;
let selection = new Selection();
for (let value of values) if (value != null) {
selection.add(value);
if (this.selectionMode === "single") break;
}
return this.sync(selection);
};
clearSelection = () => {
const selection = this.copy();
if (selection.deselectable && selection.size > 0) selection.clear();
return selection;
};
select = (collection, value, forceToggle) => {
if (this.selectionMode === "none") return this;
if (this.selectionMode === "single") if (this.isSelected(value) && this.deselectable) return this.toggleSelection(collection, value);
else return this.replaceSelection(collection, value);
else if (this.selectionMode === "multiple" || forceToggle) return this.toggleSelection(collection, value);
else return this.replaceSelection(collection, value);
};
deselect = (value) => {
const selection = this.copy();
selection.delete(value);
return selection;
};
isEqual = (other) => {
return isEqual(Array.from(this), Array.from(other));
};
};
//#endregion
//#region src/shared/collection/tree-visit.ts
function access(node, indexPath, options) {
for (let i = 0; i < indexPath.length; i++) node = options.getChildren(node, indexPath.slice(i + 1))[indexPath[i]];
return node;
}
function ancestorIndexPaths(indexPaths) {
const sortedPaths = sortIndexPaths(indexPaths);
const result = [];
const seen = /* @__PURE__ */ new Set();
for (const indexPath of sortedPaths) {
const key = indexPath.join();
if (!seen.has(key)) {
seen.add(key);
result.push(indexPath);
}
}
return result;
}
function compareIndexPaths(a, b) {
for (let i = 0; i < Math.min(a.length, b.length); i++) {
if (a[i] < b[i]) return -1;
if (a[i] > b[i]) return 1;
}
return a.length - b.length;
}
function sortIndexPaths(indexPaths) {
return indexPaths.sort(compareIndexPaths);
}
function find(node, options) {
let found;
visit(node, {
...options,
onEnter: (child, indexPath) => {
if (options.predicate(child, indexPath)) {
found = child;
return "stop";
}
}
});
return found;
}
function findAll(node, options) {
const found = [];
visit(node, {
onEnter: (child, indexPath) => {
if (options.predicate(child, indexPath)) found.push(child);
},
getChildren: options.getChildren
});
return found;
}
function findIndexPath(node, options) {
let found;
visit(node, {
onEnter: (child, indexPath) => {
if (options.predicate(child, indexPath)) {
found = [...indexPath];
return "stop";
}
},
getChildren: options.getChildren
});
return found;
}
function reduce(node, options) {
let result = options.initialResult;
visit(node, {
...options,
onEnter: (child, indexPath) => {
result = options.nextResult(result, child, indexPath);
}
});
return result;
}
function flatMap(node, options) {
return reduce(node, {
...options,
initialResult: [],
nextResult: (result, child, indexPath) => {
result.push(...options.transform(child, indexPath));
return result;
}
});
}
function filter(node, options) {
const { predicate, create, getChildren } = options;
const filterRecursive = (node, indexPath) => {
const children = getChildren(node, indexPath);
const filteredChildren = [];
children.forEach((child, index) => {
const filteredChild = filterRecursive(child, [...indexPath, index]);
if (filteredChild) filteredChildren.push(filteredChild);
});
const isRoot = indexPath.length === 0;
const nodeMatches = predicate(node, indexPath);
const hasFilteredChildren = filteredChildren.length > 0;
if (isRoot || nodeMatches || hasFilteredChildren) return create(node, filteredChildren, indexPath);
return null;
};
return filterRecursive(node, []) || create(node, [], []);
}
function flatten(rootNode, options) {
const nodes = [];
let idx = 0;
const idxMap = /* @__PURE__ */ new Map();
const parentMap = /* @__PURE__ */ new Map();
visit(rootNode, {
getChildren: options.getChildren,
onEnter: (node, indexPath) => {
if (!idxMap.has(node)) idxMap.set(node, idx++);
const children = options.getChildren(node, indexPath);
children.forEach((child) => {
if (!parentMap.has(child)) parentMap.set(child, node);
if (!idxMap.has(child)) idxMap.set(child, idx++);
});
const _children = children.length > 0 ? children.map((child) => idxMap.get(child)) : void 0;
const parent = parentMap.get(node);
const _parent = parent ? idxMap.get(parent) : void 0;
const _index = idxMap.get(node);
nodes.push({
...node,
_children,
_parent,
_index
});
}
});
return nodes;
}
function insertOperation(index, nodes) {
return {
type: "insert",
index,
nodes
};
}
function removeOperation(indexes) {
return {
type: "remove",
indexes
};
}
function replaceOperation() {
return { type: "replace" };
}
function splitIndexPath(indexPath) {
return [indexPath.slice(0, -1), indexPath[indexPath.length - 1]];
}
function getInsertionOperations(indexPath, nodes, operations = /* @__PURE__ */ new Map()) {
const [parentIndexPath, index] = splitIndexPath(indexPath);
for (let i = parentIndexPath.length - 1; i >= 0; i--) {
const parentKey = parentIndexPath.slice(0, i).join();
switch (operations.get(parentKey)?.type) {
case "remove": continue;
}
operations.set(parentKey, replaceOperation());
}
const operation = operations.get(parentIndexPath.join());
switch (operation?.type) {
case "remove":
operations.set(parentIndexPath.join(), {
type: "removeThenInsert",
removeIndexes: operation.indexes,
insertIndex: index,
insertNodes: nodes
});
break;
default: operations.set(parentIndexPath.join(), insertOperation(index, nodes));
}
return operations;
}
function getRemovalOperations(indexPaths) {
const operations = /* @__PURE__ */ new Map();
const indexesToRemove = /* @__PURE__ */ new Map();
for (const indexPath of indexPaths) {
const parentKey = indexPath.slice(0, -1).join();
const value = indexesToRemove.get(parentKey) ?? [];
value.push(indexPath[indexPath.length - 1]);
indexesToRemove.set(parentKey, value.sort((a, b) => a - b));
}
for (const indexPath of indexPaths) for (let i = indexPath.length - 2; i >= 0; i--) {
const parentKey = indexPath.slice(0, i).join();
if (!operations.has(parentKey)) operations.set(parentKey, replaceOperation());
}
for (const [parentKey, indexes] of indexesToRemove) operations.set(parentKey, removeOperation(indexes));
return operations;
}
function getReplaceOperations(indexPath, node) {
const operations = /* @__PURE__ */ new Map();
const [parentIndexPath, index] = splitIndexPath(indexPath);
for (let i = parentIndexPath.length - 1; i >= 0; i--) {
const parentKey = parentIndexPath.slice(0, i).join();
operations.set(parentKey, replaceOperation());
}
operations.set(parentIndexPath.join(), {
type: "removeThenInsert",
removeIndexes: [index],
insertIndex: index,
insertNodes: [node]
});
return operations;
}
function mutate(node, operations, options) {
return map(node, {
...options,
getChildren: (node, indexPath) => {
const key = indexPath.join();
switch (operations.get(key)?.type) {
case "replace":
case "remove":
case "removeThenInsert":
case "insert": return options.getChildren(node, indexPath);
default: return [];
}
},
transform: (node, children, indexPath) => {
const key = indexPath.join();
const operation = operations.get(key);
switch (operation?.type) {
case "remove": return options.create(node, children.filter((_, index) => !operation.indexes.includes(index)), indexPath);
case "removeThenInsert":
const updatedChildren = children.filter((_, index) => !operation.removeIndexes.includes(index));
const adjustedIndex = operation.removeIndexes.reduce((index, removedIndex) => removedIndex < index ? index - 1 : index, operation.insertIndex);
return options.create(node, splice(updatedChildren, adjustedIndex, 0, ...operation.insertNodes), indexPath);
case "insert": return options.create(node, splice(children, operation.index, 0, ...operation.nodes), indexPath);
case "replace": return options.create(node, children, indexPath);
default: return node;
}
}
});
}
function splice(array, start, deleteCount, ...items) {
return [
...array.slice(0, start),
...items,
...array.slice(start + deleteCount)
];
}
function map(node, options) {
const childrenMap = {};
visit(node, {
...options,
onLeave: (child, indexPath) => {
const keyIndexPath = [0, ...indexPath];
const key = keyIndexPath.join();
const transformed = options.transform(child, childrenMap[key] ?? [], indexPath);
const parentKey = keyIndexPath.slice(0, -1).join();
const parentChildren = childrenMap[parentKey] ?? [];
parentChildren.push(transformed);
childrenMap[parentKey] = parentChildren;
}
});
return childrenMap[""][0];
}
function insert(node, options) {
const { nodes, at } = options;
if (at.length === 0) throw new Error(`Can't insert nodes at the root`);
return mutate(node, getInsertionOperations(at, nodes), options);
}
function replace(node, options) {
if (options.at.length === 0) return options.node;
return mutate(node, getReplaceOperations(options.at, options.node), options);
}
function remove(node, options) {
if (options.indexPaths.length === 0) return node;
for (const indexPath of options.indexPaths) if (indexPath.length === 0) throw new Error(`Can't remove the root node`);
return mutate(node, getRemovalOperations(options.indexPaths), options);
}
function move(node, options) {
if (options.indexPaths.length === 0) return node;
for (const indexPath of options.indexPaths) if (indexPath.length === 0) throw new Error(`Can't move the root node`);
if (options.to.length === 0) throw new Error(`Can't move nodes to the root`);
const _ancestorIndexPaths = ancestorIndexPaths(options.indexPaths);
const nodesToInsert = _ancestorIndexPaths.map((indexPath) => access(node, indexPath, options));
return mutate(node, getInsertionOperations(options.to, nodesToInsert, getRemovalOperations(_ancestorIndexPaths)), options);
}
function visit(node, options) {
const { onEnter, onLeave, getChildren } = options;
let indexPath = [];
let stack = [{ node }];
const getIndexPath = options.reuseIndexPath ? () => indexPath : () => indexPath.slice();
while (stack.length > 0) {
let wrapper = stack[stack.length - 1];
if (wrapper.state === void 0) {
const enterResult = onEnter?.(wrapper.node, getIndexPath());
if (enterResult === "stop") return;
wrapper.state = enterResult === "skip" ? -1 : 0;
}
const children = wrapper.children || getChildren(wrapper.node, getIndexPath());
wrapper.children ||= children;
if (wrapper.state !== -1) {
if (wrapper.state < children.length) {
let currentIndex = wrapper.state;
indexPath.push(currentIndex);
stack.push({ node: children[currentIndex] });
wrapper.state = currentIndex + 1;
continue;
}
if (onLeave?.(wrapper.node, getIndexPath()) === "stop") return;
}
indexPath.pop();
stack.pop();
}
}
//#endregion
//#region src/shared/collection/tree-collection.ts
var TreeCollection = class TreeCollection {
options;
rootNode;
constructor(options) {
this.options = options;
this.rootNode = options.rootNode;
}
isEqual = (other) => {
return isEqual(this.rootNode, other.rootNode);
};
getNodeChildren = (node) => {
return this.options.nodeToChildren?.(node) ?? fallbackMethods.nodeToChildren(node) ?? [];
};
resolveIndexPath = (valueOrIndexPath) => {
return typeof valueOrIndexPath === "string" ? this.getIndexPath(valueOrIndexPath) : valueOrIndexPath;
};
resolveNode = (valueOrIndexPath) => {
const indexPath = this.resolveIndexPath(valueOrIndexPath);
return indexPath ? this.at(indexPath) : void 0;
};
getNodeChildrenCount = (node) => {
return this.options.nodeToChildrenCount?.(node) ?? fallbackMethods.nodeToChildrenCount(node);
};
getNodeValue = (node) => {
return this.options.nodeToValue?.(node) ?? fallbackMethods.nodeToValue(node);
};
getNodeDisabled = (node) => {
return this.options.isNodeDisabled?.(node) ?? fallbackMethods.isNodeDisabled(node);
};
stringify = (value) => {
const node = this.findNode(value);
if (!node) return null;
return this.stringifyNode(node);
};
stringifyNode = (node) => {
return this.options.nodeToString?.(node) ?? fallbackMethods.nodeToString(node);
};
getFirstNode = (rootNode = this.rootNode, opts = {}) => {
let firstChild;
visit(rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isSameNode(node, rootNode)) return;
if (opts.skip?.({
value: this.getNodeValue(node),
node,
indexPath
})) return "skip";
if (!firstChild && indexPath.length > 0 && !this.getNodeDisabled(node)) {
firstChild = node;
return "stop";
}
}
});
return firstChild;
};
getLastNode = (rootNode = this.rootNode, opts = {}) => {
let lastChild;
visit(rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isSameNode(node, rootNode)) return;
if (opts.skip?.({
value: this.getNodeValue(node),
node,
indexPath
})) return "skip";
if (indexPath.length > 0 && !this.getNodeDisabled(node)) lastChild = node;
}
});
return lastChild;
};
at = (indexPath) => {
return access(this.rootNode, indexPath, { getChildren: this.getNodeChildren });
};
findNode = (value, rootNode = this.rootNode) => {
return find(rootNode, {
getChildren: this.getNodeChildren,
predicate: (node) => this.getNodeValue(node) === value
});
};
findNodes = (values, rootNode = this.rootNode) => {
const v = new Set(values.filter((v) => v != null));
return findAll(rootNode, {
getChildren: this.getNodeChildren,
predicate: (node) => v.has(this.getNodeValue(node))
});
};
sort = (values) => {
return values.reduce((acc, value) => {
const indexPath = this.getIndexPath(value);
if (indexPath) acc.push({
value,
indexPath
});
return acc;
}, []).sort((a, b) => compareIndexPaths(a.indexPath, b.indexPath)).map(({ value }) => value);
};
getIndexPath(valueOrValuePath) {
if (Array.isArray(valueOrValuePath)) {
if (valueOrValuePath.length === 0) return [];
const indexPath = [];
let currentChildren = this.getNodeChildren(this.rootNode);
for (let i = 0; i < valueOrValuePath.length; i++) {
const currentValue = valueOrValuePath[i];
const matchingChildIndex = currentChildren.findIndex((child) => this.getNodeValue(child) === currentValue);
if (matchingChildIndex === -1) break;
indexPath.push(matchingChildIndex);
if (i < valueOrValuePath.length - 1) {
const currentNode = currentChildren[matchingChildIndex];
currentChildren = this.getNodeChildren(currentNode);
}
}
return indexPath;
} else return findIndexPath(this.rootNode, {
getChildren: this.getNodeChildren,
predicate: (node) => this.getNodeValue(node) === valueOrValuePath
});
}
getValue = (indexPath) => {
const node = this.at(indexPath);
return node ? this.getNodeValue(node) : void 0;
};
getValuePath = (indexPath) => {
if (!indexPath) return [];
const valuePath = [];
let currentPath = [...indexPath];
while (currentPath.length > 0) {
const node = this.at(currentPath);
if (node) valuePath.unshift(this.getNodeValue(node));
currentPath.pop();
}
return valuePath;
};
getDepth = (value) => {
return findIndexPath(this.rootNode, {
getChildren: this.getNodeChildren,
predicate: (node) => this.getNodeValue(node) === value
})?.length ?? 0;
};
isSameNode = (node, other) => {
return this.getNodeValue(node) === this.getNodeValue(other);
};
isRootNode = (node) => {
return this.isSameNode(node, this.rootNode);
};
contains = (parentIndexPath, valueIndexPath) => {
if (!parentIndexPath || !valueIndexPath) return false;
return valueIndexPath.slice(0, parentIndexPath.length).every((_, i) => parentIndexPath[i] === valueIndexPath[i]);
};
getNextNode = (value, opts = {}) => {
let found = false;
let nextNode;
visit(this.rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isRootNode(node)) return;
const nodeValue = this.getNodeValue(node);
if (opts.skip?.({
value: nodeValue,
node,
indexPath
})) {
if (nodeValue === value) found = true;
return "skip";
}
if (found && !this.getNodeDisabled(node)) {
nextNode = node;
return "stop";
}
if (nodeValue === value) found = true;
}
});
return nextNode;
};
getPreviousNode = (value, opts = {}) => {
let previousNode;
let found = false;
visit(this.rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isRootNode(node)) return;
const nodeValue = this.getNodeValue(node);
if (opts.skip?.({
value: nodeValue,
node,
indexPath
})) return "skip";
if (nodeValue === value) {
found = true;
return "stop";
}
if (!this.getNodeDisabled(node)) previousNode = node;
}
});
return found ? previousNode : void 0;
};
getParentNodes = (valueOrIndexPath) => {
const indexPath = this.resolveIndexPath(valueOrIndexPath)?.slice();
if (!indexPath) return [];
const result = [];
while (indexPath.length > 0) {
indexPath.pop();
const parentNode = this.at(indexPath);
if (parentNode && !this.isRootNode(parentNode)) result.unshift(parentNode);
}
return result;
};
getDescendantNodes = (valueOrIndexPath, options) => {
const parentNode = this.resolveNode(valueOrIndexPath);
if (!parentNode) return [];
const result = [];
visit(parentNode, {
getChildren: this.getNodeChildren,
onEnter: (node, nodeIndexPath) => {
if (nodeIndexPath.length === 0) return;
if (!options?.withBranch && this.isBranchNode(node)) return;
result.push(node);
}
});
return result;
};
getDescendantValues = (valueOrIndexPath, options) => {
return this.getDescendantNodes(valueOrIndexPath, options).map((child) => this.getNodeValue(child));
};
getParentIndexPath = (indexPath) => {
return indexPath.slice(0, -1);
};
getParentNode = (valueOrIndexPath) => {
const indexPath = this.resolveIndexPath(valueOrIndexPath);
return indexPath ? this.at(this.getParentIndexPath(indexPath)) : void 0;
};
visit = (opts) => {
const { skip, ...rest } = opts;
visit(this.rootNode, {
...rest,
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (this.isRootNode(node)) return;
if (skip?.({
value: this.getNodeValue(node),
node,
indexPath
})) return "skip";
return rest.onEnter?.(node, indexPath);
}
});
};
getPreviousSibling = (indexPath) => {
const parentNode = this.getParentNode(indexPath);
if (!parentNode) return;
const siblings = this.getNodeChildren(parentNode);
let idx = indexPath[indexPath.length - 1];
while (--idx >= 0) {
const sibling = siblings[idx];
if (!this.getNodeDisabled(sibling)) return sibling;
}
};
getNextSibling = (indexPath) => {
const parentNode = this.getParentNode(indexPath);
if (!parentNode) return;
const siblings = this.getNodeChildren(parentNode);
let idx = indexPath[indexPath.length - 1];
while (++idx < siblings.length) {
const sibling = siblings[idx];
if (!this.getNodeDisabled(sibling)) return sibling;
}
};
getSiblingNodes = (indexPath) => {
const parentNode = this.getParentNode(indexPath);
return parentNode ? this.getNodeChildren(parentNode) : [];
};
getValues = (rootNode = this.rootNode) => {
return flatMap(rootNode, {
getChildren: this.getNodeChildren,
transform: (node) => [this.getNodeValue(node)]
}).slice(1);
};
isValidDepth = (indexPath, depth) => {
if (depth == null) return true;
if (typeof depth === "function") return depth(indexPath.length);
return indexPath.length === depth;
};
isBranchNode = (node) => {
return this.getNodeChildren(node).length > 0 || this.getNodeChildrenCount(node) != null;
};
getBranchValues = (rootNode = this.rootNode, opts = {}) => {
let values = [];
visit(rootNode, {
getChildren: this.getNodeChildren,
onEnter: (node, indexPath) => {
if (indexPath.length === 0) return;
const nodeValue = this.getNodeValue(node);
if (opts.skip?.({
value: nodeValue,
node,
indexPath
})) return "skip";
if (this.isBranchNode(node) && this.isValidDepth(indexPath, opts.depth)) values.push(this.getNodeValue(node));
}
});
return values;
};
flatten = (rootNode = this.rootNode) => {
return flatten(rootNode, { getChildren: this.getNodeChildren });
};
_create = (node, children) => {
if (this.getNodeChildren(node).length > 0 || children.length > 0) return {
...node,
children
};
return { ...node };
};
_insert = (rootNode, indexPath, nodes) => {
return this.copy(insert(rootNode, {
at: indexPath,
nodes,
getChildren: this.getNodeChildren,
create: this._create
}));
};
copy = (rootNode) => {
return new TreeCollection({
...this.options,
rootNode
});
};
_replace = (rootNode, indexPath, node) => {
return this.copy(replace(rootNode, {
at: indexPath,
node,
getChildren: this.getNodeChildren,
create: this._create
}));
};
_move = (rootNode, indexPaths, to) => {
return this.copy(move(rootNode, {
indexPaths,
to,
getChildren: this.getNodeChildren,
create: this._create
}));
};
_remove = (rootNode, indexPaths) => {
return this.copy(remove(rootNode, {
indexPaths,
getChildren: this.getNodeChildren,
create: this._create
}));
};
replace = (indexPath, node) => {
return this._replace(this.rootNode, indexPath, node);
};
remove = (indexPaths) => {
return this._remove(this.rootNode, indexPaths);
};
insertBefore = (indexPath, nodes) => {
return this.getParentNode(indexPath) ? this._insert(this.rootNode, indexPath, nodes) : void 0;
};
insertAfter = (indexPath, nodes) => {
if (!this.getParentNode(indexPath)) return;
const nextIndex = [...indexPath.slice(0, -1), indexPath[indexPath.length - 1] + 1];
return this._insert(this.rootNode, nextIndex, nodes);
};
move = (fromIndexPaths, toIndexPath) => {
return this._move(this.rootNode, fromIndexPaths, toIndexPath);
};
filter = (predicate) => {
const filteredRoot = filter(this.rootNode, {
predicate,
getChildren: this.getNodeChildren,
create: this._create
});
return this.copy(filteredRoot);
};
toJSON = () => {
return this.getValues(this.rootNode);
};
};
function flattenedToTree(nodes, options = fallbackMethods) {
if (nodes.length === 0) throw new Error("[ginxjs/tree] Cannot create tree from empty flattened array");
const rootFlatNode = nodes.find((node) => node._parent === void 0);
if (!rootFlatNode) throw new Error("[ginxjs/tree] No root node found in flattened data");
const nodeMap = /* @__PURE__ */ new Map();
nodes.forEach((node) => {
nodeMap.set(node._index, node);
});
const buildNode = (idx) => {
const flatNode = nodeMap.get(idx);
if (!flatNode) return {};
const { _children, _parent, _index, ...cleanNode } = flatNode;
const children = [];
_children?.forEach((childIndex) => {
children.push(buildNode(childIndex));
});
return {
...cleanNode,
...children.length > 0 && { children }
};
};
const rootNode = buildNode(rootFlatNode._index);
return new TreeCollection({
...options,
rootNode
});
}
function filePathToTree(paths) {
const rootNode = {
label: "",
value: "ROOT",
children: []
};
paths.forEach((path) => {
const parts = path.split("/");
let currentNode = rootNode;
parts.forEach((part, index) => {
let childNode = currentNode.children?.find((child) => child.label === part);
if (!childNode) {
childNode = {
value: parts.slice(0, index + 1).join("/"),
label: part
};
currentNode.children ||= [];
currentNode.children.push(childNode);
}
currentNode = childNode;
});
});
return new TreeCollection({ rootNode });
}
const fallbackMethods = {
nodeToValue(node) {
if (typeof node === "string") return node;
if (isObject(node) && hasProp(node, "value")) return node.value;
return "";
},
nodeToString(node) {
if (typeof node === "string") return node;
if (isObject(node) && hasProp(node, "label")) return node.label;
return fallbackMethods.nodeToValue(node);
},
isNodeDisabled(node) {
if (isObject(node) && hasProp(node, "disabled")) return !!node.disabled;
return false;
},
nodeToChildren(node) {
return node.children;
},
nodeToChildrenCount(node) {
if (isObject(node) && hasProp(node, "childrenCount")) return node.childrenCount;
}
};
//#endregion
export { GridCollection, ListCollection, Selection, TreeCollection, createSelectedItemMap, deriveSelectionState, filePathToTree, flattenedToTree, isGridCollection, isListCollection, resolveSelectedItems, updateSelectedItemMap };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
require("./stringify-state.cjs");
let _internationalized_date = require("@internationalized/date");
//#region src/shared/date-utils/constrain.ts
function alignCenter(date, duration, locale, min, max) {
const halfDuration = {};
for (let prop in duration) {
const key = prop;
const value = duration[key];
if (value == null) continue;
halfDuration[key] = Math.floor(value / 2);
if (halfDuration[key] > 0 && value % 2 === 0) halfDuration[key]--;
}
return constrainStart(date, alignStart(date, duration, locale).subtract(halfDuration), duration, locale, min, max);
}
function alignStart(date, duration, locale, min, max) {
let aligned = date;
if (duration.years) aligned = (0, _internationalized_date.startOfYear)(date);
else if (duration.months) aligned = (0, _internationalized_date.startOfMonth)(date);
else if (duration.weeks) aligned = (0, _internationalized_date.startOfWeek)(date, locale);
return constrainStart(date, aligned, duration, locale, min, max);
}
function alignEnd(date, duration, locale, min, max) {
let d = { ...duration };
if (d.days) d.days--;
else if (d.weeks) d.weeks--;
else if (d.months) d.months--;
else if (d.years) d.years--;
return constrainStart(date, alignStart(date, duration, locale).subtract(d), duration, locale, min, max);
}
function constrainStart(date, aligned, duration, locale, min, max) {
if (min && date.compare(min) >= 0) aligned = (0, _internationalized_date.maxDate)(aligned, alignStart((0, _internationalized_date.toCalendarDate)(min), duration, locale));
if (max && date.compare(max) <= 0) aligned = (0, _internationalized_date.minDate)(aligned, alignEnd((0, _internationalized_date.toCalendarDate)(max), duration, locale));
return aligned;
}
function constrainValue(date, minValue, maxValue) {
const dateOnly = (0, _internationalized_date.toCalendarDate)(date);
const minOnly = minValue ? (0, _internationalized_date.toCalendarDate)(minValue) : void 0;
const maxOnly = maxValue ? (0, _internationalized_date.toCalendarDate)(maxValue) : void 0;
let constrainedDateOnly = dateOnly;
if (minOnly) constrainedDateOnly = (0, _internationalized_date.maxDate)(constrainedDateOnly, minOnly);
if (maxOnly) constrainedDateOnly = (0, _internationalized_date.minDate)(constrainedDateOnly, maxOnly);
if (constrainedDateOnly.compare(dateOnly) === 0) return date;
if ("hour" in date) return date.set({
year: constrainedDateOnly.year,
month: constrainedDateOnly.month,
day: constrainedDateOnly.day
});
return constrainedDateOnly;
}
function constrainSegments(date, minValue, maxValue) {
const dateOnly = (0, _internationalized_date.toCalendarDate)(date);
const minOnly = minValue ? (0, _internationalized_date.toCalendarDate)(minValue) : void 0;
const maxOnly = maxValue ? (0, _internationalized_date.toCalendarDate)(maxValue) : void 0;
let result = dateOnly;
if (minOnly && result.compare(minOnly) < 0) {
if (result.year < minOnly.year) result = result.set({ year: minOnly.year });
if (result.compare(minOnly) < 0 && result.month < minOnly.month) result = result.set({ month: minOnly.month });
if (result.compare(minOnly) < 0 && result.day < minOnly.day) result = result.set({ day: minOnly.day });
}
if (maxOnly && result.compare(maxOnly) > 0) {
if (result.year > maxOnly.year) result = result.set({ year: maxOnly.year });
if (result.compare(maxOnly) > 0 && result.month > maxOnly.month) result = result.set({ month: maxOnly.month });
if (result.compare(maxOnly) > 0 && result.day > maxOnly.day) result = result.set({ day: maxOnly.day });
}
if (result.compare(dateOnly) === 0) return date;
if ("hour" in date) return date.set({
year: result.year,
month: result.month,
day: result.day
});
return result;
}
//#endregion
//#region src/shared/date-utils/align.ts
function alignDate(date, alignment, duration, locale, min, max) {
switch (alignment) {
case "start": return alignStart(date, duration, locale, min, max);
case "end": return alignEnd(date, duration, locale, min, max);
default: return alignCenter(date, duration, locale, min, max);
}
}
function alignStartDate(date, startDate, endDate, duration, locale, min, max) {
if (date.compare(startDate) < 0) return alignEnd(date, duration, locale, min, max);
if (date.compare(endDate) > 0) return alignStart(date, duration, locale, min, max);
return startDate;
}
//#endregion
//#region src/shared/date-utils/assertion.ts
function isDateEqual(dateA, dateB) {
if (dateA == null || dateB == null) return dateA === dateB;
if (!("hour" in dateA) && !("hour" in dateB)) return (0, _internationalized_date.isSameDay)(dateA, dateB);
return (0, _internationalized_date.toCalendarDateTime)(dateA).compare((0, _internationalized_date.toCalendarDateTime)(dateB)) === 0;
}
function isDateUnavailable(date, isUnavailable, locale, minValue, maxValue) {
if (!date) return false;
if (isUnavailable?.(date, locale)) return true;
return isDateOutsideRange(date, minValue, maxValue);
}
function isDateOutsideRange(date, startDate, endDate) {
return startDate != null && date.compare(startDate) < 0 || endDate != null && date.compare(endDate) > 0;
}
function isPreviousRangeInvalid(startDate, minValue, maxValue) {
const prevDate = startDate.subtract({ days: 1 });
return (0, _internationalized_date.isSameDay)(prevDate, startDate) || isDateOutsideRange(prevDate, minValue, maxValue);
}
function isNextRangeInvalid(endDate, minValue, maxValue) {
const nextDate = endDate.add({ days: 1 });
return (0, _internationalized_date.isSameDay)(nextDate, endDate) || isDateOutsideRange(nextDate, minValue, maxValue);
}
//#endregion
//#region src/shared/date-utils/duration.ts
function getUnitDuration(duration) {
let clone = { ...duration };
for (let key in clone) clone[key] = 1;
return clone;
}
function getEndDate(startDate, duration) {
let clone = { ...duration };
if (clone.days) clone.days--;
else clone.days = -1;
return startDate.add(clone);
}
//#endregion
//#region src/shared/date-utils/get-era-format.ts
function getEraFormat(date) {
if (!date) return void 0;
const id = date.calendar.identifier;
if (id === "gregory" || id === "iso8601") return date.era === "BC" ? "short" : void 0;
return "short";
}
//#endregion
//#region src/shared/date-utils/formatter.ts
function getDayFormatter(locale, timeZone, referenceDate) {
const date = referenceDate ?? (0, _internationalized_date.toCalendarDateTime)((0, _internationalized_date.today)(timeZone));
return new _internationalized_date.DateFormatter(locale, {
weekday: "long",
month: "long",
year: "numeric",
day: "numeric",
era: getEraFormat(date),
calendar: date.calendar.identifier,
timeZone
});
}
function getMonthFormatter(locale, timeZone, referenceDate) {
const date = referenceDate ?? (0, _internationalized_date.today)(timeZone);
return new _internationalized_date.DateFormatter(locale, {
month: "long",
year: "numeric",
era: getEraFormat(date),
calendar: date.calendar.identifier,
timeZone
});
}
//#endregion
//#region src/shared/date-utils/format.ts
function formatRange(startDate, endDate, formatter, toString, timeZone) {
let parts = formatter.formatRangeToParts(startDate.toDate(timeZone), endDate.toDate(timeZone));
let separatorIndex = -1;
for (let i = 0; i < parts.length; i++) {
let part = parts[i];
if (part.source === "shared" && part.type === "literal") separatorIndex = i;
else if (part.source === "endRange") break;
}
let start = "";
let end = "";
for (let i = 0; i < parts.length; i++) if (i < separatorIndex) start += parts[i].value;
else if (i > separatorIndex) end += parts[i].value;
return toString(start, end);
}
function formatSelectedDate(startDate, endDate, locale, timeZone) {
if (!startDate) return "";
let start = startDate;
let end = endDate ?? startDate;
let formatter = getDayFormatter(locale, timeZone);
if ((0, _internationalized_date.isSameDay)(start, end)) return formatter.format(start.toDate(timeZone));
return formatRange(start, end, formatter, (start, end) => `${start} – ${end}`, timeZone);
}
function formatVisibleRange(startDate, endDate, locale, timeZone) {
const start = startDate;
const end = endDate ?? startDate;
const dayFormatter = getDayFormatter(locale, timeZone);
if (!(0, _internationalized_date.isSameDay)(start, (0, _internationalized_date.startOfMonth)(start))) return dayFormatter.formatRange(start.toDate(timeZone), end.toDate(timeZone));
const monthFormatter = getMonthFormatter(locale, timeZone);
if ((0, _internationalized_date.isSameDay)(end, (0, _internationalized_date.endOfMonth)(start))) return monthFormatter.format(start.toDate(timeZone));
if ((0, _internationalized_date.isSameDay)(end, (0, _internationalized_date.endOfMonth)(end))) return monthFormatter.formatRange(start.toDate(timeZone), end.toDate(timeZone));
return "";
}
//#endregion
//#region src/shared/date-utils/date-month.ts
const daysOfTheWeek = [
"sun",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat"
];
function normalizeFirstDayOfWeek(firstDayOfWeek) {
return firstDayOfWeek != null ? daysOfTheWeek[firstDayOfWeek] : void 0;
}
function getStartOfWeek(date, locale, firstDayOfWeek) {
return (0, _internationalized_date.startOfWeek)(date, locale, normalizeFirstDayOfWeek(firstDayOfWeek));
}
function getEndOfWeek(date, locale, firstDayOfWeek = 0) {
return (0, _internationalized_date.endOfWeek)(date, locale, normalizeFirstDayOfWeek(firstDayOfWeek));
}
function getDaysInWeek(weekIndex, from, locale, firstDayOfWeek) {
const weekDate = from.add({ weeks: weekIndex });
const dates = [];
let date = getStartOfWeek(weekDate, locale, firstDayOfWeek);
while (dates.length < 7) {
dates.push(date);
let nextDate = date.add({ days: 1 });
if ((0, _internationalized_date.isSameDay)(date, nextDate)) break;
date = nextDate;
}
return dates;
}
function getMonthDays(from, locale, numOfWeeks, firstDayOfWeek) {
const firstDay = normalizeFirstDayOfWeek(firstDayOfWeek);
const monthWeeks = numOfWeeks ?? (0, _internationalized_date.getWeeksInMonth)(from, locale, firstDay);
return [...new Array(monthWeeks).keys()].map((week) => getDaysInWeek(week, from, locale, firstDayOfWeek));
}
function getWeekdayFormats(locale, timeZone) {
const longFormat = new _internationalized_date.DateFormatter(locale, {
weekday: "long",
timeZone
});
const shortFormat = new _internationalized_date.DateFormatter(locale, {
weekday: "short",
timeZone
});
const narrowFormat = new _internationalized_date.DateFormatter(locale, {
weekday: "narrow",
timeZone
});
return (value) => {
const date = value instanceof Date ? value : value.toDate(timeZone);
return {
value,
short: shortFormat.format(date),
long: longFormat.format(date),
narrow: narrowFormat.format(date)
};
};
}
function getWeekDays(date, startOfWeekProp, timeZone, locale) {
const firstDayOfWeek = getStartOfWeek(date, locale, startOfWeekProp);
const weeks = [...new Array(7).keys()];
const format = getWeekdayFormats(locale, timeZone);
return weeks.map((index) => format(firstDayOfWeek.add({ days: index })));
}
function getMonthNames(locale, format = "long", referenceDate) {
if (!referenceDate || referenceDate.calendar.identifier === "gregory" || referenceDate.calendar.identifier === "iso8601") {
const date = new Date(2021, 0, 1);
const monthNames = [];
for (let i = 0; i < 12; i++) {
monthNames.push(date.toLocaleString(locale, { month: format }));
date.setMonth(date.getMonth() + 1);
}
return monthNames;
}
const monthCount = referenceDate.calendar.getMonthsInYear(referenceDate);
const formatter = new _internationalized_date.DateFormatter(locale, {
month: format,
calendar: referenceDate.calendar.identifier
});
const monthNames = [];
for (let month = 1; month <= monthCount; month++) {
const d = referenceDate.set({ month });
monthNames.push(formatter.format(d.toDate("UTC")));
}
return monthNames;
}
function getWeekOfYear(date, locale) {
const mondayOfWeek = (0, _internationalized_date.startOfWeek)(date, locale, "mon");
const year = mondayOfWeek.year;
const week1Monday = (0, _internationalized_date.startOfWeek)(mondayOfWeek.set({
month: 1,
day: 4
}), locale, "mon");
const julianMonday = mondayOfWeek.calendar.toJulianDay(mondayOfWeek);
const julianWeek1 = week1Monday.calendar.toJulianDay(week1Monday);
if (julianMonday >= julianWeek1) return 1 + Math.floor((julianMonday - julianWeek1) / 7);
const prevWeek1Monday = (0, _internationalized_date.startOfWeek)(mondayOfWeek.set({
year: year - 1,
month: 1,
day: 4
}), locale, "mon");
const julianPrevWeek1 = prevWeek1Monday.calendar.toJulianDay(prevWeek1Monday);
return 1 + Math.floor((julianMonday - julianPrevWeek1) / 7);
}
//#endregion
//#region src/shared/date-utils/date-year.ts
function getYearsRange(range) {
const years = [];
for (let year = range.from; year <= range.to; year += 1) years.push(year);
return years;
}
const DEFAULT_MIN_YEAR = 1900;
const DEFAULT_MAX_YEAR = 2099;
function getDefaultYearRange(referenceDate, min, max) {
const calendar = referenceDate.calendar;
return {
from: min?.year ?? (0, _internationalized_date.toCalendar)(new _internationalized_date.CalendarDate(DEFAULT_MIN_YEAR, 1, 1), calendar).year,
to: max?.year ?? (0, _internationalized_date.toCalendar)(new _internationalized_date.CalendarDate(DEFAULT_MAX_YEAR, 12, 31), calendar).year
};
}
const FUTURE_YEAR_COERCION = 10;
function normalizeYear(year) {
if (!year) return;
if (year.length === 3) return year.padEnd(4, "0");
if (year.length === 2) {
const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
const fullYear = Math.floor(currentYear / 100) * 100 + parseInt(year.slice(-2), 10);
return fullYear > currentYear + FUTURE_YEAR_COERCION ? (fullYear - 100).toString() : fullYear.toString();
}
return year;
}
function getDecadeRange(year, opts) {
const chunkSize = opts?.strict ? 10 : 12;
const computedYear = year - year % 10;
const years = [];
for (let i = 0; i < chunkSize; i += 1) {
const value = computedYear + i;
years.push(value);
}
return years;
}
//#endregion
//#region src/shared/date-utils/mutation.ts
function getTodayDate(timeZone, calendar) {
const tod = (0, _internationalized_date.today)(timeZone ?? (0, _internationalized_date.getLocalTimeZone)());
if (calendar) return (0, _internationalized_date.toCalendar)(tod, calendar);
return tod;
}
function setCalendar(date, calendar) {
return (0, _internationalized_date.toCalendar)((0, _internationalized_date.toCalendarDateTime)(date), calendar);
}
function setDate(date, startDate, isDateUnavailable, locale, minValue, maxValue) {
let result;
result = constrainValue(date, minValue, maxValue);
result = getPreviousAvailableDate(date, startDate, locale, isDateUnavailable);
return result;
}
function getPreviousAvailableDate(date, minValue, locale, isDateUnavailable) {
if (!isDateUnavailable) return date;
while (date.compare(minValue) >= 0 && isDateUnavailable(date, locale)) date = date.subtract({ days: 1 });
if (date.compare(minValue) >= 0) return date;
}
//#endregion
//#region src/shared/date-utils/pagination.ts
function getAdjustedDateFn(visibleDuration, locale, minValue, maxValue) {
return function getDate(options) {
const { startDate, focusedDate } = options;
const endDate = getEndDate(startDate, visibleDuration);
if (isDateOutsideRange(focusedDate, minValue, maxValue)) return {
startDate,
focusedDate: constrainValue(focusedDate, minValue, maxValue),
endDate
};
if (focusedDate.compare(startDate) < 0) return {
startDate: alignEnd(focusedDate, visibleDuration, locale, minValue, maxValue),
focusedDate: constrainValue(focusedDate, minValue, maxValue),
endDate
};
if (focusedDate.compare(endDate) > 0) return {
startDate: alignStart(focusedDate, visibleDuration, locale, minValue, maxValue),
endDate,
focusedDate: constrainValue(focusedDate, minValue, maxValue)
};
return {
startDate,
endDate,
focusedDate: constrainValue(focusedDate, minValue, maxValue)
};
};
}
function getNextPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
const start = startDate.add(visibleDuration);
return adjust({
focusedDate: focusedDate.add(visibleDuration),
startDate: alignStart(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue), visibleDuration, locale)
});
}
function getPreviousPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
let start = startDate.subtract(visibleDuration);
return adjust({
focusedDate: focusedDate.subtract(visibleDuration),
startDate: alignStart(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue), visibleDuration, locale)
});
}
function getNextRow(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (visibleDuration.days) return getNextPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue);
if (visibleDuration.weeks || visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: focusedDate.add({ weeks: 1 }),
startDate
});
}
function getPreviousRow(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (visibleDuration.days) return getPreviousPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue);
if (visibleDuration.weeks || visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: focusedDate.subtract({ weeks: 1 }),
startDate
});
}
function getSectionStart(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (visibleDuration.days) return adjust({
focusedDate: startDate,
startDate
});
if (visibleDuration.weeks) return adjust({
focusedDate: (0, _internationalized_date.startOfWeek)(focusedDate, locale),
startDate
});
if (visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: (0, _internationalized_date.startOfMonth)(focusedDate),
startDate
});
}
function getSectionEnd(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
const endDate = getEndDate(startDate, visibleDuration);
if (visibleDuration.days) return adjust({
focusedDate: endDate,
startDate
});
if (visibleDuration.weeks) return adjust({
focusedDate: (0, _internationalized_date.endOfWeek)(focusedDate, locale),
startDate
});
if (visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: (0, _internationalized_date.endOfMonth)(focusedDate),
startDate
});
}
function getNextSection(focusedDate, startDate, larger, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (!larger && !visibleDuration.days) return adjust({
focusedDate: focusedDate.add(getUnitDuration(visibleDuration)),
startDate
});
if (visibleDuration.days) return getNextPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue);
if (visibleDuration.weeks) return adjust({
focusedDate: focusedDate.add({ months: 1 }),
startDate
});
if (visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: focusedDate.add({ years: 1 }),
startDate
});
}
function getPreviousSection(focusedDate, startDate, larger, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (!larger && !visibleDuration.days) return adjust({
focusedDate: focusedDate.subtract(getUnitDuration(visibleDuration)),
startDate
});
if (visibleDuration.days) return getPreviousPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue);
if (visibleDuration.weeks) return adjust({
focusedDate: focusedDate.subtract({ months: 1 }),
startDate
});
if (visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: focusedDate.subtract({ years: 1 }),
startDate
});
}
//#endregion
//#region src/shared/date-utils/locale.ts
const isValidCharacter = (char, separator) => {
if (!char) return true;
return /\d/.test(char) || separator.includes(char) || char.length !== 1;
};
const ensureValidCharacters = (value, separator) => {
return value.split("").filter((char) => isValidCharacter(char, separator)).join("");
};
const separatorCache = /* @__PURE__ */ new Map();
function getLocaleSeparator(locale) {
let separator = separatorCache.get(locale);
if (separator != null) return separator;
const literal = new Intl.DateTimeFormat(locale).formatToParts(/* @__PURE__ */ new Date()).find((part) => part.type === "literal");
separator = literal ? literal.value : "/";
separatorCache.set(locale, separator);
return separator;
}
//#endregion
//#region src/shared/date-utils/parse-date.ts
const isValidYear = (year) => year != null && year.length === 4;
const isValidMonth = (month) => month != null && parseFloat(month) <= 12;
const isValidDay = (day) => day != null && parseFloat(day) <= 31;
function parseDateString(date, locale, timeZone) {
let { year, month, day } = extract(createRegex(locale, timeZone), date) ?? {};
if (year != null || month != null || day != null) {
const curr = /* @__PURE__ */ new Date();
year ||= curr.getFullYear().toString();
month ||= (curr.getMonth() + 1).toString();
day ||= curr.getDate().toString();
}
if (!isValidYear(year)) year = normalizeYear(year);
if (isValidYear(year) && isValidMonth(month) && isValidDay(day)) return new _internationalized_date.CalendarDate(+year, +month, +day);
const time = Date.parse(date);
if (!isNaN(time)) {
const date = new Date(time);
return new _internationalized_date.CalendarDate(date.getFullYear(), date.getMonth() + 1, date.getDate());
}
}
function createRegex(locale, timeZone) {
return new _internationalized_date.DateFormatter(locale, {
day: "numeric",
month: "numeric",
year: "numeric",
timeZone
}).formatToParts(new Date(2e3, 11, 25)).map(({ type, value }) => type === "literal" ? `${value}?` : `((?!=<${type}>)\\d+)?`).join("");
}
function extract(pattern, str) {
const matches = str.match(pattern);
return pattern.toString().match(/<(.+?)>/g)?.map((group) => {
const groupMatches = group.match(/<(.+)>/);
if (!groupMatches || groupMatches.length <= 0) return null;
return group.match(/<(.+)>/)?.[1];
}).reduce((acc, curr, index) => {
if (!curr) return acc;
if (matches && matches.length > index) acc[curr] = matches[index + 1];
else acc[curr] = null;
return acc;
}, {});
}
//#endregion
//#region src/shared/date-utils/preset.ts
function getDateRangePreset(preset, locale, timeZone) {
const today = (0, _internationalized_date.toCalendarDate)((0, _internationalized_date.now)(timeZone));
switch (preset) {
case "thisWeek": return [(0, _internationalized_date.startOfWeek)(today, locale), (0, _internationalized_date.endOfWeek)(today, locale)];
case "thisMonth": return [(0, _internationalized_date.startOfMonth)(today), today];
case "thisQuarter": return [(0, _internationalized_date.startOfMonth)(today).add({ months: -((today.month - 1) % 3) }), today];
case "thisYear": return [(0, _internationalized_date.startOfYear)(today), today];
case "last3Days": return [today.add({ days: -2 }), today];
case "last7Days": return [today.add({ days: -6 }), today];
case "last14Days": return [today.add({ days: -13 }), today];
case "last30Days": return [today.add({ days: -29 }), today];
case "last90Days": return [today.add({ days: -89 }), today];
case "lastMonth": return [(0, _internationalized_date.startOfMonth)(today.add({ months: -1 })), (0, _internationalized_date.endOfMonth)(today.add({ months: -1 }))];
case "lastQuarter": return [(0, _internationalized_date.startOfMonth)(today.add({ months: -((today.month - 1) % 3) - 3 })), (0, _internationalized_date.endOfMonth)(today.add({ months: -((today.month - 1) % 3) - 1 }))];
case "lastWeek": return [(0, _internationalized_date.startOfWeek)(today, locale).add({ weeks: -1 }), (0, _internationalized_date.endOfWeek)(today, locale).add({ weeks: -1 })];
case "lastYear": return [(0, _internationalized_date.startOfYear)(today.add({ years: -1 })), (0, _internationalized_date.endOfYear)(today.add({ years: -1 }))];
default: throw new Error(`Invalid date range preset: ${preset}`);
}
}
//#endregion
exports.alignCenter = alignCenter;
exports.alignDate = alignDate;
exports.alignEnd = alignEnd;
exports.alignStart = alignStart;
exports.alignStartDate = alignStartDate;
exports.constrainSegments = constrainSegments;
exports.constrainStart = constrainStart;
exports.constrainValue = constrainValue;
exports.ensureValidCharacters = ensureValidCharacters;
exports.formatRange = formatRange;
exports.formatSelectedDate = formatSelectedDate;
exports.formatVisibleRange = formatVisibleRange;
exports.getAdjustedDateFn = getAdjustedDateFn;
exports.getDateRangePreset = getDateRangePreset;
exports.getDayFormatter = getDayFormatter;
exports.getDaysInWeek = getDaysInWeek;
exports.getDecadeRange = getDecadeRange;
exports.getDefaultYearRange = getDefaultYearRange;
exports.getEndDate = getEndDate;
exports.getEndOfWeek = getEndOfWeek;
exports.getLocaleSeparator = getLocaleSeparator;
exports.getMonthDays = getMonthDays;
exports.getMonthFormatter = getMonthFormatter;
exports.getMonthNames = getMonthNames;
exports.getNextPage = getNextPage;
exports.getNextRow = getNextRow;
exports.getNextSection = getNextSection;
exports.getPreviousAvailableDate = getPreviousAvailableDate;
exports.getPreviousPage = getPreviousPage;
exports.getPreviousRow = getPreviousRow;
exports.getPreviousSection = getPreviousSection;
exports.getSectionEnd = getSectionEnd;
exports.getSectionStart = getSectionStart;
exports.getStartOfWeek = getStartOfWeek;
exports.getTodayDate = getTodayDate;
exports.getUnitDuration = getUnitDuration;
exports.getWeekDays = getWeekDays;
exports.getWeekOfYear = getWeekOfYear;
exports.getWeekdayFormats = getWeekdayFormats;
exports.getYearsRange = getYearsRange;
exports.isDateEqual = isDateEqual;
exports.isDateOutsideRange = isDateOutsideRange;
exports.isDateUnavailable = isDateUnavailable;
exports.isNextRangeInvalid = isNextRangeInvalid;
exports.isPreviousRangeInvalid = isPreviousRangeInvalid;
exports.isValidCharacter = isValidCharacter;
exports.normalizeYear = normalizeYear;
exports.parseDateString = parseDateString;
exports.setCalendar = setCalendar;
exports.setDate = setDate;
import * as _$_internationalized_date0 from "@internationalized/date";
import { Calendar, CalendarDate, CalendarDateTime, DateDuration, DateFormatter, DateValue as DateValue$1, ZonedDateTime } from "@internationalized/date";
//#region src/shared/date-utils/types.d.ts
type DateValue = CalendarDate | CalendarDateTime | ZonedDateTime;
type DateGranularity = "day" | "hour" | "minute" | "second";
type DateAlignment = "start" | "end" | "center";
type DateAvailableFn = (date: DateValue, locale: string) => boolean;
type DateAdjustFn = (options: {
startDate: DateValue;
focusedDate: DateValue;
}) => {
startDate: DateValue;
focusedDate: DateValue;
endDate: DateValue;
};
type DateRangePreset = "thisWeek" | "lastWeek" | "thisMonth" | "lastMonth" | "thisQuarter" | "lastQuarter" | "thisYear" | "lastYear" | "last3Days" | "last7Days" | "last14Days" | "last30Days" | "last90Days";
//#endregion
//#region src/shared/date-utils/align.d.ts
declare function alignDate(date: DateValue, alignment: DateAlignment, duration: DateDuration, locale: string, min?: DateValue | undefined, max?: DateValue | undefined): _$_internationalized_date0.DateValue;
declare function alignStartDate(date: DateValue, startDate: DateValue, endDate: DateValue, duration: DateDuration, locale: string, min?: DateValue | undefined, max?: DateValue | undefined): _$_internationalized_date0.CalendarDate | _$_internationalized_date0.CalendarDateTime | _$_internationalized_date0.ZonedDateTime;
//#endregion
//#region src/shared/date-utils/assertion.d.ts
declare function isDateEqual(dateA: DateValue | null | undefined, dateB?: DateValue | null): boolean;
declare function isDateUnavailable(date: DateValue | null, isUnavailable: DateAvailableFn | undefined, locale: string, minValue?: DateValue | null, maxValue?: DateValue | null): boolean;
declare function isDateOutsideRange(date: DateValue, startDate?: DateValue | null, endDate?: DateValue | null): boolean;
declare function isPreviousRangeInvalid(startDate: DateValue, minValue?: DateValue | null, maxValue?: DateValue | null): boolean;
declare function isNextRangeInvalid(endDate: DateValue, minValue?: DateValue | null, maxValue?: DateValue | null): boolean;
//#endregion
//#region src/shared/date-utils/constrain.d.ts
declare function alignCenter(date: DateValue$1, duration: DateDuration, locale: string, min?: DateValue$1, max?: DateValue$1): DateValue$1;
declare function alignStart(date: DateValue$1, duration: DateDuration, locale: string, min?: DateValue$1, max?: DateValue$1): DateValue$1;
declare function alignEnd(date: DateValue$1, duration: DateDuration, locale: string, min?: DateValue$1, max?: DateValue$1): DateValue$1;
declare function constrainStart(date: DateValue$1, aligned: DateValue$1, duration: DateDuration, locale: string, min?: DateValue$1, max?: DateValue$1): DateValue$1;
declare function constrainValue<T extends DateValue$1>(date: T, minValue?: DateValue$1, maxValue?: DateValue$1): T;
declare function constrainSegments<T extends DateValue$1>(date: T, minValue?: DateValue$1, maxValue?: DateValue$1): T;
//#endregion
//#region src/shared/date-utils/duration.d.ts
declare function getUnitDuration(duration: DateDuration): {
years?: number;
months?: number;
weeks?: number;
days?: number;
};
declare function getEndDate(startDate: DateValue, duration: DateDuration): _$_internationalized_date0.CalendarDate | _$_internationalized_date0.CalendarDateTime | _$_internationalized_date0.ZonedDateTime;
//#endregion
//#region src/shared/date-utils/format.d.ts
declare function formatRange(startDate: DateValue, endDate: DateValue, formatter: DateFormatter, toString: (start: string, end: string) => string, timeZone: string): string;
declare function formatSelectedDate(startDate: DateValue | null | undefined, endDate: DateValue | null, locale: string, timeZone: string): string;
declare function formatVisibleRange(startDate: DateValue, endDate: DateValue | null, locale: string, timeZone: string): string;
//#endregion
//#region src/shared/date-utils/formatter.d.ts
declare function getDayFormatter(locale: string, timeZone: string, referenceDate?: DateValue$1): DateFormatter;
declare function getMonthFormatter(locale: string, timeZone: string, referenceDate?: DateValue$1): DateFormatter;
//#endregion
//#region src/shared/date-utils/date-month.d.ts
declare function getStartOfWeek(date: DateValue$1, locale: string, firstDayOfWeek?: number): DateValue$1;
declare function getEndOfWeek(date: DateValue$1, locale: string, firstDayOfWeek?: number): DateValue$1;
declare function getDaysInWeek(weekIndex: number, from: DateValue$1, locale: string, firstDayOfWeek?: number): DateValue$1[];
declare function getMonthDays(from: DateValue$1, locale: string, numOfWeeks?: number, firstDayOfWeek?: number): DateValue$1[][];
declare function getWeekdayFormats(locale: string, timeZone: string): <T extends DateValue$1 | Date>(value: T) => {
value: T;
short: string;
long: string;
narrow: string;
};
declare function getWeekDays(date: DateValue$1, startOfWeekProp: number | undefined, timeZone: string, locale: string): {
value: _$_internationalized_date0.CalendarDate | _$_internationalized_date0.CalendarDateTime | _$_internationalized_date0.ZonedDateTime;
short: string;
long: string;
narrow: string;
}[];
declare function getMonthNames(locale: string, format?: Intl.DateTimeFormatOptions["month"], referenceDate?: DateValue$1): string[];
declare function getWeekOfYear(date: DateValue$1, locale: string): number;
//#endregion
//#region src/shared/date-utils/date-year.d.ts
interface YearsRange {
from: number;
to: number;
}
declare function getYearsRange(range: YearsRange): number[];
declare function getDefaultYearRange(referenceDate: DateValue$1, min?: DateValue$1, max?: DateValue$1): YearsRange;
declare function normalizeYear(year: string | null | undefined): string | undefined;
declare function getDecadeRange(year: number, opts?: {
strict?: boolean;
}): number[];
//#endregion
//#region src/shared/date-utils/mutation.d.ts
declare function getTodayDate(timeZone?: string, calendar?: Calendar): _$_internationalized_date0.CalendarDate;
declare function setCalendar(date: DateValue$1, calendar: Calendar): _$_internationalized_date0.CalendarDateTime;
declare function setDate(date: DateValue$1, startDate: DateValue$1, isDateUnavailable: DateAvailableFn, locale: string, minValue: DateValue$1, maxValue: DateValue$1): DateValue$1 | undefined;
declare function getPreviousAvailableDate(date: DateValue$1, minValue: DateValue$1, locale: string, isDateUnavailable?: DateAvailableFn): DateValue$1 | undefined;
//#endregion
//#region src/shared/date-utils/pagination.d.ts
interface AdjustDateParams {
startDate: DateValue;
focusedDate: DateValue;
}
interface AdjustDateReturn extends AdjustDateParams {
endDate: DateValue;
}
declare function getAdjustedDateFn(visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): (options: AdjustDateParams) => AdjustDateReturn;
declare function getNextPage(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn;
declare function getPreviousPage(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn;
declare function getNextRow(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getPreviousRow(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getSectionStart(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getSectionEnd(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getNextSection(focusedDate: DateValue, startDate: DateValue, larger: boolean, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getPreviousSection(focusedDate: DateValue, startDate: DateValue, larger: boolean, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
//#endregion
//#region src/shared/date-utils/locale.d.ts
declare const isValidCharacter: (char: string | null, separator: string) => boolean;
declare const ensureValidCharacters: (value: string, separator: string) => string;
declare function getLocaleSeparator(locale: string): string;
//#endregion
//#region src/shared/date-utils/parse-date.d.ts
declare function parseDateString(date: string, locale: string, timeZone: string): DateValue | undefined;
//#endregion
//#region src/shared/date-utils/preset.d.ts
declare function getDateRangePreset(preset: DateRangePreset, locale: string, timeZone: string): [DateValue$1, DateValue$1];
//#endregion
export { AdjustDateParams, AdjustDateReturn, type DateAdjustFn, type DateGranularity, type DateRangePreset, type DateValue, YearsRange, alignCenter, alignDate, alignEnd, alignStart, alignStartDate, constrainSegments, constrainStart, constrainValue, ensureValidCharacters, formatRange, formatSelectedDate, formatVisibleRange, getAdjustedDateFn, getDateRangePreset, getDayFormatter, getDaysInWeek, getDecadeRange, getDefaultYearRange, getEndDate, getEndOfWeek, getLocaleSeparator, getMonthDays, getMonthFormatter, getMonthNames, getNextPage, getNextRow, getNextSection, getPreviousAvailableDate, getPreviousPage, getPreviousRow, getPreviousSection, getSectionEnd, getSectionStart, getStartOfWeek, getTodayDate, getUnitDuration, getWeekDays, getWeekOfYear, getWeekdayFormats, getYearsRange, isDateEqual, isDateOutsideRange, isDateUnavailable, isNextRangeInvalid, isPreviousRangeInvalid, isValidCharacter, normalizeYear, parseDateString, setCalendar, setDate };
import * as _$_internationalized_date0 from "@internationalized/date";
import { Calendar, CalendarDate, CalendarDateTime, DateDuration, DateFormatter, DateValue as DateValue$1, ZonedDateTime } from "@internationalized/date";
//#region src/shared/date-utils/types.d.ts
type DateValue = CalendarDate | CalendarDateTime | ZonedDateTime;
type DateGranularity = "day" | "hour" | "minute" | "second";
type DateAlignment = "start" | "end" | "center";
type DateAvailableFn = (date: DateValue, locale: string) => boolean;
type DateAdjustFn = (options: {
startDate: DateValue;
focusedDate: DateValue;
}) => {
startDate: DateValue;
focusedDate: DateValue;
endDate: DateValue;
};
type DateRangePreset = "thisWeek" | "lastWeek" | "thisMonth" | "lastMonth" | "thisQuarter" | "lastQuarter" | "thisYear" | "lastYear" | "last3Days" | "last7Days" | "last14Days" | "last30Days" | "last90Days";
//#endregion
//#region src/shared/date-utils/align.d.ts
declare function alignDate(date: DateValue, alignment: DateAlignment, duration: DateDuration, locale: string, min?: DateValue | undefined, max?: DateValue | undefined): _$_internationalized_date0.DateValue;
declare function alignStartDate(date: DateValue, startDate: DateValue, endDate: DateValue, duration: DateDuration, locale: string, min?: DateValue | undefined, max?: DateValue | undefined): _$_internationalized_date0.CalendarDate | _$_internationalized_date0.CalendarDateTime | _$_internationalized_date0.ZonedDateTime;
//#endregion
//#region src/shared/date-utils/assertion.d.ts
declare function isDateEqual(dateA: DateValue | null | undefined, dateB?: DateValue | null): boolean;
declare function isDateUnavailable(date: DateValue | null, isUnavailable: DateAvailableFn | undefined, locale: string, minValue?: DateValue | null, maxValue?: DateValue | null): boolean;
declare function isDateOutsideRange(date: DateValue, startDate?: DateValue | null, endDate?: DateValue | null): boolean;
declare function isPreviousRangeInvalid(startDate: DateValue, minValue?: DateValue | null, maxValue?: DateValue | null): boolean;
declare function isNextRangeInvalid(endDate: DateValue, minValue?: DateValue | null, maxValue?: DateValue | null): boolean;
//#endregion
//#region src/shared/date-utils/constrain.d.ts
declare function alignCenter(date: DateValue$1, duration: DateDuration, locale: string, min?: DateValue$1, max?: DateValue$1): DateValue$1;
declare function alignStart(date: DateValue$1, duration: DateDuration, locale: string, min?: DateValue$1, max?: DateValue$1): DateValue$1;
declare function alignEnd(date: DateValue$1, duration: DateDuration, locale: string, min?: DateValue$1, max?: DateValue$1): DateValue$1;
declare function constrainStart(date: DateValue$1, aligned: DateValue$1, duration: DateDuration, locale: string, min?: DateValue$1, max?: DateValue$1): DateValue$1;
declare function constrainValue<T extends DateValue$1>(date: T, minValue?: DateValue$1, maxValue?: DateValue$1): T;
declare function constrainSegments<T extends DateValue$1>(date: T, minValue?: DateValue$1, maxValue?: DateValue$1): T;
//#endregion
//#region src/shared/date-utils/duration.d.ts
declare function getUnitDuration(duration: DateDuration): {
years?: number;
months?: number;
weeks?: number;
days?: number;
};
declare function getEndDate(startDate: DateValue, duration: DateDuration): _$_internationalized_date0.CalendarDate | _$_internationalized_date0.CalendarDateTime | _$_internationalized_date0.ZonedDateTime;
//#endregion
//#region src/shared/date-utils/format.d.ts
declare function formatRange(startDate: DateValue, endDate: DateValue, formatter: DateFormatter, toString: (start: string, end: string) => string, timeZone: string): string;
declare function formatSelectedDate(startDate: DateValue | null | undefined, endDate: DateValue | null, locale: string, timeZone: string): string;
declare function formatVisibleRange(startDate: DateValue, endDate: DateValue | null, locale: string, timeZone: string): string;
//#endregion
//#region src/shared/date-utils/formatter.d.ts
declare function getDayFormatter(locale: string, timeZone: string, referenceDate?: DateValue$1): DateFormatter;
declare function getMonthFormatter(locale: string, timeZone: string, referenceDate?: DateValue$1): DateFormatter;
//#endregion
//#region src/shared/date-utils/date-month.d.ts
declare function getStartOfWeek(date: DateValue$1, locale: string, firstDayOfWeek?: number): DateValue$1;
declare function getEndOfWeek(date: DateValue$1, locale: string, firstDayOfWeek?: number): DateValue$1;
declare function getDaysInWeek(weekIndex: number, from: DateValue$1, locale: string, firstDayOfWeek?: number): DateValue$1[];
declare function getMonthDays(from: DateValue$1, locale: string, numOfWeeks?: number, firstDayOfWeek?: number): DateValue$1[][];
declare function getWeekdayFormats(locale: string, timeZone: string): <T extends DateValue$1 | Date>(value: T) => {
value: T;
short: string;
long: string;
narrow: string;
};
declare function getWeekDays(date: DateValue$1, startOfWeekProp: number | undefined, timeZone: string, locale: string): {
value: _$_internationalized_date0.CalendarDate | _$_internationalized_date0.CalendarDateTime | _$_internationalized_date0.ZonedDateTime;
short: string;
long: string;
narrow: string;
}[];
declare function getMonthNames(locale: string, format?: Intl.DateTimeFormatOptions["month"], referenceDate?: DateValue$1): string[];
declare function getWeekOfYear(date: DateValue$1, locale: string): number;
//#endregion
//#region src/shared/date-utils/date-year.d.ts
interface YearsRange {
from: number;
to: number;
}
declare function getYearsRange(range: YearsRange): number[];
declare function getDefaultYearRange(referenceDate: DateValue$1, min?: DateValue$1, max?: DateValue$1): YearsRange;
declare function normalizeYear(year: string | null | undefined): string | undefined;
declare function getDecadeRange(year: number, opts?: {
strict?: boolean;
}): number[];
//#endregion
//#region src/shared/date-utils/mutation.d.ts
declare function getTodayDate(timeZone?: string, calendar?: Calendar): _$_internationalized_date0.CalendarDate;
declare function setCalendar(date: DateValue$1, calendar: Calendar): _$_internationalized_date0.CalendarDateTime;
declare function setDate(date: DateValue$1, startDate: DateValue$1, isDateUnavailable: DateAvailableFn, locale: string, minValue: DateValue$1, maxValue: DateValue$1): DateValue$1 | undefined;
declare function getPreviousAvailableDate(date: DateValue$1, minValue: DateValue$1, locale: string, isDateUnavailable?: DateAvailableFn): DateValue$1 | undefined;
//#endregion
//#region src/shared/date-utils/pagination.d.ts
interface AdjustDateParams {
startDate: DateValue;
focusedDate: DateValue;
}
interface AdjustDateReturn extends AdjustDateParams {
endDate: DateValue;
}
declare function getAdjustedDateFn(visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): (options: AdjustDateParams) => AdjustDateReturn;
declare function getNextPage(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn;
declare function getPreviousPage(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn;
declare function getNextRow(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getPreviousRow(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getSectionStart(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getSectionEnd(focusedDate: DateValue, startDate: DateValue, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getNextSection(focusedDate: DateValue, startDate: DateValue, larger: boolean, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
declare function getPreviousSection(focusedDate: DateValue, startDate: DateValue, larger: boolean, visibleDuration: DateDuration, locale: string, minValue?: DateValue, maxValue?: DateValue): AdjustDateReturn | undefined;
//#endregion
//#region src/shared/date-utils/locale.d.ts
declare const isValidCharacter: (char: string | null, separator: string) => boolean;
declare const ensureValidCharacters: (value: string, separator: string) => string;
declare function getLocaleSeparator(locale: string): string;
//#endregion
//#region src/shared/date-utils/parse-date.d.ts
declare function parseDateString(date: string, locale: string, timeZone: string): DateValue | undefined;
//#endregion
//#region src/shared/date-utils/preset.d.ts
declare function getDateRangePreset(preset: DateRangePreset, locale: string, timeZone: string): [DateValue$1, DateValue$1];
//#endregion
export { AdjustDateParams, AdjustDateReturn, type DateAdjustFn, type DateGranularity, type DateRangePreset, type DateValue, YearsRange, alignCenter, alignDate, alignEnd, alignStart, alignStartDate, constrainSegments, constrainStart, constrainValue, ensureValidCharacters, formatRange, formatSelectedDate, formatVisibleRange, getAdjustedDateFn, getDateRangePreset, getDayFormatter, getDaysInWeek, getDecadeRange, getDefaultYearRange, getEndDate, getEndOfWeek, getLocaleSeparator, getMonthDays, getMonthFormatter, getMonthNames, getNextPage, getNextRow, getNextSection, getPreviousAvailableDate, getPreviousPage, getPreviousRow, getPreviousSection, getSectionEnd, getSectionStart, getStartOfWeek, getTodayDate, getUnitDuration, getWeekDays, getWeekOfYear, getWeekdayFormats, getYearsRange, isDateEqual, isDateOutsideRange, isDateUnavailable, isNextRangeInvalid, isPreviousRangeInvalid, isValidCharacter, normalizeYear, parseDateString, setCalendar, setDate };
import { CalendarDate, DateFormatter, endOfMonth, endOfWeek, endOfYear, getLocalTimeZone, getWeeksInMonth, isSameDay, maxDate, minDate, now, startOfMonth, startOfWeek, startOfYear, toCalendar, toCalendarDate, toCalendarDateTime, today } from "@internationalized/date";
//#region src/shared/date-utils/constrain.ts
function alignCenter(date, duration, locale, min, max) {
const halfDuration = {};
for (let prop in duration) {
const key = prop;
const value = duration[key];
if (value == null) continue;
halfDuration[key] = Math.floor(value / 2);
if (halfDuration[key] > 0 && value % 2 === 0) halfDuration[key]--;
}
return constrainStart(date, alignStart(date, duration, locale).subtract(halfDuration), duration, locale, min, max);
}
function alignStart(date, duration, locale, min, max) {
let aligned = date;
if (duration.years) aligned = startOfYear(date);
else if (duration.months) aligned = startOfMonth(date);
else if (duration.weeks) aligned = startOfWeek(date, locale);
return constrainStart(date, aligned, duration, locale, min, max);
}
function alignEnd(date, duration, locale, min, max) {
let d = { ...duration };
if (d.days) d.days--;
else if (d.weeks) d.weeks--;
else if (d.months) d.months--;
else if (d.years) d.years--;
return constrainStart(date, alignStart(date, duration, locale).subtract(d), duration, locale, min, max);
}
function constrainStart(date, aligned, duration, locale, min, max) {
if (min && date.compare(min) >= 0) aligned = maxDate(aligned, alignStart(toCalendarDate(min), duration, locale));
if (max && date.compare(max) <= 0) aligned = minDate(aligned, alignEnd(toCalendarDate(max), duration, locale));
return aligned;
}
function constrainValue(date, minValue, maxValue) {
const dateOnly = toCalendarDate(date);
const minOnly = minValue ? toCalendarDate(minValue) : void 0;
const maxOnly = maxValue ? toCalendarDate(maxValue) : void 0;
let constrainedDateOnly = dateOnly;
if (minOnly) constrainedDateOnly = maxDate(constrainedDateOnly, minOnly);
if (maxOnly) constrainedDateOnly = minDate(constrainedDateOnly, maxOnly);
if (constrainedDateOnly.compare(dateOnly) === 0) return date;
if ("hour" in date) return date.set({
year: constrainedDateOnly.year,
month: constrainedDateOnly.month,
day: constrainedDateOnly.day
});
return constrainedDateOnly;
}
function constrainSegments(date, minValue, maxValue) {
const dateOnly = toCalendarDate(date);
const minOnly = minValue ? toCalendarDate(minValue) : void 0;
const maxOnly = maxValue ? toCalendarDate(maxValue) : void 0;
let result = dateOnly;
if (minOnly && result.compare(minOnly) < 0) {
if (result.year < minOnly.year) result = result.set({ year: minOnly.year });
if (result.compare(minOnly) < 0 && result.month < minOnly.month) result = result.set({ month: minOnly.month });
if (result.compare(minOnly) < 0 && result.day < minOnly.day) result = result.set({ day: minOnly.day });
}
if (maxOnly && result.compare(maxOnly) > 0) {
if (result.year > maxOnly.year) result = result.set({ year: maxOnly.year });
if (result.compare(maxOnly) > 0 && result.month > maxOnly.month) result = result.set({ month: maxOnly.month });
if (result.compare(maxOnly) > 0 && result.day > maxOnly.day) result = result.set({ day: maxOnly.day });
}
if (result.compare(dateOnly) === 0) return date;
if ("hour" in date) return date.set({
year: result.year,
month: result.month,
day: result.day
});
return result;
}
//#endregion
//#region src/shared/date-utils/align.ts
function alignDate(date, alignment, duration, locale, min, max) {
switch (alignment) {
case "start": return alignStart(date, duration, locale, min, max);
case "end": return alignEnd(date, duration, locale, min, max);
default: return alignCenter(date, duration, locale, min, max);
}
}
function alignStartDate(date, startDate, endDate, duration, locale, min, max) {
if (date.compare(startDate) < 0) return alignEnd(date, duration, locale, min, max);
if (date.compare(endDate) > 0) return alignStart(date, duration, locale, min, max);
return startDate;
}
//#endregion
//#region src/shared/date-utils/assertion.ts
function isDateEqual(dateA, dateB) {
if (dateA == null || dateB == null) return dateA === dateB;
if (!("hour" in dateA) && !("hour" in dateB)) return isSameDay(dateA, dateB);
return toCalendarDateTime(dateA).compare(toCalendarDateTime(dateB)) === 0;
}
function isDateUnavailable(date, isUnavailable, locale, minValue, maxValue) {
if (!date) return false;
if (isUnavailable?.(date, locale)) return true;
return isDateOutsideRange(date, minValue, maxValue);
}
function isDateOutsideRange(date, startDate, endDate) {
return startDate != null && date.compare(startDate) < 0 || endDate != null && date.compare(endDate) > 0;
}
function isPreviousRangeInvalid(startDate, minValue, maxValue) {
const prevDate = startDate.subtract({ days: 1 });
return isSameDay(prevDate, startDate) || isDateOutsideRange(prevDate, minValue, maxValue);
}
function isNextRangeInvalid(endDate, minValue, maxValue) {
const nextDate = endDate.add({ days: 1 });
return isSameDay(nextDate, endDate) || isDateOutsideRange(nextDate, minValue, maxValue);
}
//#endregion
//#region src/shared/date-utils/duration.ts
function getUnitDuration(duration) {
let clone = { ...duration };
for (let key in clone) clone[key] = 1;
return clone;
}
function getEndDate(startDate, duration) {
let clone = { ...duration };
if (clone.days) clone.days--;
else clone.days = -1;
return startDate.add(clone);
}
//#endregion
//#region src/shared/date-utils/get-era-format.ts
function getEraFormat(date) {
if (!date) return void 0;
const id = date.calendar.identifier;
if (id === "gregory" || id === "iso8601") return date.era === "BC" ? "short" : void 0;
return "short";
}
//#endregion
//#region src/shared/date-utils/formatter.ts
function getDayFormatter(locale, timeZone, referenceDate) {
const date = referenceDate ?? toCalendarDateTime(today(timeZone));
return new DateFormatter(locale, {
weekday: "long",
month: "long",
year: "numeric",
day: "numeric",
era: getEraFormat(date),
calendar: date.calendar.identifier,
timeZone
});
}
function getMonthFormatter(locale, timeZone, referenceDate) {
const date = referenceDate ?? today(timeZone);
return new DateFormatter(locale, {
month: "long",
year: "numeric",
era: getEraFormat(date),
calendar: date.calendar.identifier,
timeZone
});
}
//#endregion
//#region src/shared/date-utils/format.ts
function formatRange(startDate, endDate, formatter, toString, timeZone) {
let parts = formatter.formatRangeToParts(startDate.toDate(timeZone), endDate.toDate(timeZone));
let separatorIndex = -1;
for (let i = 0; i < parts.length; i++) {
let part = parts[i];
if (part.source === "shared" && part.type === "literal") separatorIndex = i;
else if (part.source === "endRange") break;
}
let start = "";
let end = "";
for (let i = 0; i < parts.length; i++) if (i < separatorIndex) start += parts[i].value;
else if (i > separatorIndex) end += parts[i].value;
return toString(start, end);
}
function formatSelectedDate(startDate, endDate, locale, timeZone) {
if (!startDate) return "";
let start = startDate;
let end = endDate ?? startDate;
let formatter = getDayFormatter(locale, timeZone);
if (isSameDay(start, end)) return formatter.format(start.toDate(timeZone));
return formatRange(start, end, formatter, (start, end) => `${start} – ${end}`, timeZone);
}
function formatVisibleRange(startDate, endDate, locale, timeZone) {
const start = startDate;
const end = endDate ?? startDate;
const dayFormatter = getDayFormatter(locale, timeZone);
if (!isSameDay(start, startOfMonth(start))) return dayFormatter.formatRange(start.toDate(timeZone), end.toDate(timeZone));
const monthFormatter = getMonthFormatter(locale, timeZone);
if (isSameDay(end, endOfMonth(start))) return monthFormatter.format(start.toDate(timeZone));
if (isSameDay(end, endOfMonth(end))) return monthFormatter.formatRange(start.toDate(timeZone), end.toDate(timeZone));
return "";
}
//#endregion
//#region src/shared/date-utils/date-month.ts
const daysOfTheWeek = [
"sun",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat"
];
function normalizeFirstDayOfWeek(firstDayOfWeek) {
return firstDayOfWeek != null ? daysOfTheWeek[firstDayOfWeek] : void 0;
}
function getStartOfWeek(date, locale, firstDayOfWeek) {
return startOfWeek(date, locale, normalizeFirstDayOfWeek(firstDayOfWeek));
}
function getEndOfWeek(date, locale, firstDayOfWeek = 0) {
return endOfWeek(date, locale, normalizeFirstDayOfWeek(firstDayOfWeek));
}
function getDaysInWeek(weekIndex, from, locale, firstDayOfWeek) {
const weekDate = from.add({ weeks: weekIndex });
const dates = [];
let date = getStartOfWeek(weekDate, locale, firstDayOfWeek);
while (dates.length < 7) {
dates.push(date);
let nextDate = date.add({ days: 1 });
if (isSameDay(date, nextDate)) break;
date = nextDate;
}
return dates;
}
function getMonthDays(from, locale, numOfWeeks, firstDayOfWeek) {
const firstDay = normalizeFirstDayOfWeek(firstDayOfWeek);
const monthWeeks = numOfWeeks ?? getWeeksInMonth(from, locale, firstDay);
return [...new Array(monthWeeks).keys()].map((week) => getDaysInWeek(week, from, locale, firstDayOfWeek));
}
function getWeekdayFormats(locale, timeZone) {
const longFormat = new DateFormatter(locale, {
weekday: "long",
timeZone
});
const shortFormat = new DateFormatter(locale, {
weekday: "short",
timeZone
});
const narrowFormat = new DateFormatter(locale, {
weekday: "narrow",
timeZone
});
return (value) => {
const date = value instanceof Date ? value : value.toDate(timeZone);
return {
value,
short: shortFormat.format(date),
long: longFormat.format(date),
narrow: narrowFormat.format(date)
};
};
}
function getWeekDays(date, startOfWeekProp, timeZone, locale) {
const firstDayOfWeek = getStartOfWeek(date, locale, startOfWeekProp);
const weeks = [...new Array(7).keys()];
const format = getWeekdayFormats(locale, timeZone);
return weeks.map((index) => format(firstDayOfWeek.add({ days: index })));
}
function getMonthNames(locale, format = "long", referenceDate) {
if (!referenceDate || referenceDate.calendar.identifier === "gregory" || referenceDate.calendar.identifier === "iso8601") {
const date = new Date(2021, 0, 1);
const monthNames = [];
for (let i = 0; i < 12; i++) {
monthNames.push(date.toLocaleString(locale, { month: format }));
date.setMonth(date.getMonth() + 1);
}
return monthNames;
}
const monthCount = referenceDate.calendar.getMonthsInYear(referenceDate);
const formatter = new DateFormatter(locale, {
month: format,
calendar: referenceDate.calendar.identifier
});
const monthNames = [];
for (let month = 1; month <= monthCount; month++) {
const d = referenceDate.set({ month });
monthNames.push(formatter.format(d.toDate("UTC")));
}
return monthNames;
}
function getWeekOfYear(date, locale) {
const mondayOfWeek = startOfWeek(date, locale, "mon");
const year = mondayOfWeek.year;
const week1Monday = startOfWeek(mondayOfWeek.set({
month: 1,
day: 4
}), locale, "mon");
const julianMonday = mondayOfWeek.calendar.toJulianDay(mondayOfWeek);
const julianWeek1 = week1Monday.calendar.toJulianDay(week1Monday);
if (julianMonday >= julianWeek1) return 1 + Math.floor((julianMonday - julianWeek1) / 7);
const prevWeek1Monday = startOfWeek(mondayOfWeek.set({
year: year - 1,
month: 1,
day: 4
}), locale, "mon");
const julianPrevWeek1 = prevWeek1Monday.calendar.toJulianDay(prevWeek1Monday);
return 1 + Math.floor((julianMonday - julianPrevWeek1) / 7);
}
//#endregion
//#region src/shared/date-utils/date-year.ts
function getYearsRange(range) {
const years = [];
for (let year = range.from; year <= range.to; year += 1) years.push(year);
return years;
}
const DEFAULT_MIN_YEAR = 1900;
const DEFAULT_MAX_YEAR = 2099;
function getDefaultYearRange(referenceDate, min, max) {
const calendar = referenceDate.calendar;
return {
from: min?.year ?? toCalendar(new CalendarDate(DEFAULT_MIN_YEAR, 1, 1), calendar).year,
to: max?.year ?? toCalendar(new CalendarDate(DEFAULT_MAX_YEAR, 12, 31), calendar).year
};
}
const FUTURE_YEAR_COERCION = 10;
function normalizeYear(year) {
if (!year) return;
if (year.length === 3) return year.padEnd(4, "0");
if (year.length === 2) {
const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
const fullYear = Math.floor(currentYear / 100) * 100 + parseInt(year.slice(-2), 10);
return fullYear > currentYear + FUTURE_YEAR_COERCION ? (fullYear - 100).toString() : fullYear.toString();
}
return year;
}
function getDecadeRange(year, opts) {
const chunkSize = opts?.strict ? 10 : 12;
const computedYear = year - year % 10;
const years = [];
for (let i = 0; i < chunkSize; i += 1) {
const value = computedYear + i;
years.push(value);
}
return years;
}
//#endregion
//#region src/shared/date-utils/mutation.ts
function getTodayDate(timeZone, calendar) {
const tod = today(timeZone ?? getLocalTimeZone());
if (calendar) return toCalendar(tod, calendar);
return tod;
}
function setCalendar(date, calendar) {
return toCalendar(toCalendarDateTime(date), calendar);
}
function setDate(date, startDate, isDateUnavailable, locale, minValue, maxValue) {
let result;
result = constrainValue(date, minValue, maxValue);
result = getPreviousAvailableDate(date, startDate, locale, isDateUnavailable);
return result;
}
function getPreviousAvailableDate(date, minValue, locale, isDateUnavailable) {
if (!isDateUnavailable) return date;
while (date.compare(minValue) >= 0 && isDateUnavailable(date, locale)) date = date.subtract({ days: 1 });
if (date.compare(minValue) >= 0) return date;
}
//#endregion
//#region src/shared/date-utils/pagination.ts
function getAdjustedDateFn(visibleDuration, locale, minValue, maxValue) {
return function getDate(options) {
const { startDate, focusedDate } = options;
const endDate = getEndDate(startDate, visibleDuration);
if (isDateOutsideRange(focusedDate, minValue, maxValue)) return {
startDate,
focusedDate: constrainValue(focusedDate, minValue, maxValue),
endDate
};
if (focusedDate.compare(startDate) < 0) return {
startDate: alignEnd(focusedDate, visibleDuration, locale, minValue, maxValue),
focusedDate: constrainValue(focusedDate, minValue, maxValue),
endDate
};
if (focusedDate.compare(endDate) > 0) return {
startDate: alignStart(focusedDate, visibleDuration, locale, minValue, maxValue),
endDate,
focusedDate: constrainValue(focusedDate, minValue, maxValue)
};
return {
startDate,
endDate,
focusedDate: constrainValue(focusedDate, minValue, maxValue)
};
};
}
function getNextPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
const start = startDate.add(visibleDuration);
return adjust({
focusedDate: focusedDate.add(visibleDuration),
startDate: alignStart(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue), visibleDuration, locale)
});
}
function getPreviousPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
let start = startDate.subtract(visibleDuration);
return adjust({
focusedDate: focusedDate.subtract(visibleDuration),
startDate: alignStart(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue), visibleDuration, locale)
});
}
function getNextRow(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (visibleDuration.days) return getNextPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue);
if (visibleDuration.weeks || visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: focusedDate.add({ weeks: 1 }),
startDate
});
}
function getPreviousRow(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (visibleDuration.days) return getPreviousPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue);
if (visibleDuration.weeks || visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: focusedDate.subtract({ weeks: 1 }),
startDate
});
}
function getSectionStart(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (visibleDuration.days) return adjust({
focusedDate: startDate,
startDate
});
if (visibleDuration.weeks) return adjust({
focusedDate: startOfWeek(focusedDate, locale),
startDate
});
if (visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: startOfMonth(focusedDate),
startDate
});
}
function getSectionEnd(focusedDate, startDate, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
const endDate = getEndDate(startDate, visibleDuration);
if (visibleDuration.days) return adjust({
focusedDate: endDate,
startDate
});
if (visibleDuration.weeks) return adjust({
focusedDate: endOfWeek(focusedDate, locale),
startDate
});
if (visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: endOfMonth(focusedDate),
startDate
});
}
function getNextSection(focusedDate, startDate, larger, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (!larger && !visibleDuration.days) return adjust({
focusedDate: focusedDate.add(getUnitDuration(visibleDuration)),
startDate
});
if (visibleDuration.days) return getNextPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue);
if (visibleDuration.weeks) return adjust({
focusedDate: focusedDate.add({ months: 1 }),
startDate
});
if (visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: focusedDate.add({ years: 1 }),
startDate
});
}
function getPreviousSection(focusedDate, startDate, larger, visibleDuration, locale, minValue, maxValue) {
const adjust = getAdjustedDateFn(visibleDuration, locale, minValue, maxValue);
if (!larger && !visibleDuration.days) return adjust({
focusedDate: focusedDate.subtract(getUnitDuration(visibleDuration)),
startDate
});
if (visibleDuration.days) return getPreviousPage(focusedDate, startDate, visibleDuration, locale, minValue, maxValue);
if (visibleDuration.weeks) return adjust({
focusedDate: focusedDate.subtract({ months: 1 }),
startDate
});
if (visibleDuration.months || visibleDuration.years) return adjust({
focusedDate: focusedDate.subtract({ years: 1 }),
startDate
});
}
//#endregion
//#region src/shared/date-utils/locale.ts
const isValidCharacter = (char, separator) => {
if (!char) return true;
return /\d/.test(char) || separator.includes(char) || char.length !== 1;
};
const ensureValidCharacters = (value, separator) => {
return value.split("").filter((char) => isValidCharacter(char, separator)).join("");
};
const separatorCache = /* @__PURE__ */ new Map();
function getLocaleSeparator(locale) {
let separator = separatorCache.get(locale);
if (separator != null) return separator;
const literal = new Intl.DateTimeFormat(locale).formatToParts(/* @__PURE__ */ new Date()).find((part) => part.type === "literal");
separator = literal ? literal.value : "/";
separatorCache.set(locale, separator);
return separator;
}
//#endregion
//#region src/shared/date-utils/parse-date.ts
const isValidYear = (year) => year != null && year.length === 4;
const isValidMonth = (month) => month != null && parseFloat(month) <= 12;
const isValidDay = (day) => day != null && parseFloat(day) <= 31;
function parseDateString(date, locale, timeZone) {
let { year, month, day } = extract(createRegex(locale, timeZone), date) ?? {};
if (year != null || month != null || day != null) {
const curr = /* @__PURE__ */ new Date();
year ||= curr.getFullYear().toString();
month ||= (curr.getMonth() + 1).toString();
day ||= curr.getDate().toString();
}
if (!isValidYear(year)) year = normalizeYear(year);
if (isValidYear(year) && isValidMonth(month) && isValidDay(day)) return new CalendarDate(+year, +month, +day);
const time = Date.parse(date);
if (!isNaN(time)) {
const date = new Date(time);
return new CalendarDate(date.getFullYear(), date.getMonth() + 1, date.getDate());
}
}
function createRegex(locale, timeZone) {
return new DateFormatter(locale, {
day: "numeric",
month: "numeric",
year: "numeric",
timeZone
}).formatToParts(new Date(2e3, 11, 25)).map(({ type, value }) => type === "literal" ? `${value}?` : `((?!=<${type}>)\\d+)?`).join("");
}
function extract(pattern, str) {
const matches = str.match(pattern);
return pattern.toString().match(/<(.+?)>/g)?.map((group) => {
const groupMatches = group.match(/<(.+)>/);
if (!groupMatches || groupMatches.length <= 0) return null;
return group.match(/<(.+)>/)?.[1];
}).reduce((acc, curr, index) => {
if (!curr) return acc;
if (matches && matches.length > index) acc[curr] = matches[index + 1];
else acc[curr] = null;
return acc;
}, {});
}
//#endregion
//#region src/shared/date-utils/preset.ts
function getDateRangePreset(preset, locale, timeZone) {
const today = toCalendarDate(now(timeZone));
switch (preset) {
case "thisWeek": return [startOfWeek(today, locale), endOfWeek(today, locale)];
case "thisMonth": return [startOfMonth(today), today];
case "thisQuarter": return [startOfMonth(today).add({ months: -((today.month - 1) % 3) }), today];
case "thisYear": return [startOfYear(today), today];
case "last3Days": return [today.add({ days: -2 }), today];
case "last7Days": return [today.add({ days: -6 }), today];
case "last14Days": return [today.add({ days: -13 }), today];
case "last30Days": return [today.add({ days: -29 }), today];
case "last90Days": return [today.add({ days: -89 }), today];
case "lastMonth": return [startOfMonth(today.add({ months: -1 })), endOfMonth(today.add({ months: -1 }))];
case "lastQuarter": return [startOfMonth(today.add({ months: -((today.month - 1) % 3) - 3 })), endOfMonth(today.add({ months: -((today.month - 1) % 3) - 1 }))];
case "lastWeek": return [startOfWeek(today, locale).add({ weeks: -1 }), endOfWeek(today, locale).add({ weeks: -1 })];
case "lastYear": return [startOfYear(today.add({ years: -1 })), endOfYear(today.add({ years: -1 }))];
default: throw new Error(`Invalid date range preset: ${preset}`);
}
}
//#endregion
export { alignCenter, alignDate, alignEnd, alignStart, alignStartDate, constrainSegments, constrainStart, constrainValue, ensureValidCharacters, formatRange, formatSelectedDate, formatVisibleRange, getAdjustedDateFn, getDateRangePreset, getDayFormatter, getDaysInWeek, getDecadeRange, getDefaultYearRange, getEndDate, getEndOfWeek, getLocaleSeparator, getMonthDays, getMonthFormatter, getMonthNames, getNextPage, getNextRow, getNextSection, getPreviousAvailableDate, getPreviousPage, getPreviousRow, getPreviousSection, getSectionEnd, getSectionStart, getStartOfWeek, getTodayDate, getUnitDuration, getWeekDays, getWeekOfYear, getWeekdayFormats, getYearsRange, isDateEqual, isDateOutsideRange, isDateUnavailable, isNextRangeInvalid, isPreviousRangeInvalid, isValidCharacter, normalizeYear, parseDateString, setCalendar, setDate };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/shared/highlight-word/normalize-span.ts
const normalizeSpan = (spans, len) => {
const result = [];
const append = (start, end, match) => {
if (end - start > 0) result.push({
start,
end,
match
});
};
if (spans.length === 0) append(0, len, false);
else {
let lastIndex = 0;
for (const chunk of spans) {
append(lastIndex, chunk.start, false);
append(chunk.start, chunk.end, true);
lastIndex = chunk.end;
}
append(lastIndex, len, false);
}
return result;
};
//#endregion
//#region src/shared/highlight-word/escape-regex.ts
const escapeRegex = (term) => term.replace(/[|\\{}()[\]^$+*?.-]/g, (char) => `\\${char}`);
//#endregion
//#region src/shared/highlight-word/highlight-first.ts
function highlightFirst(props) {
const { text, query, ignoreCase, exactMatch } = props;
if (exactMatch) {
const escapedQuery = escapeRegex(query);
const regex = new RegExp(`\\b(${escapedQuery})\\b`, ignoreCase ? "i" : "");
const match = text.match(regex);
if (!match || match.index === void 0) return [{
text,
match: false
}];
const start = match.index;
return normalizeSpan([{
start,
end: start + match[0].length
}], text.length).map((chunk) => ({
text: text.slice(chunk.start, chunk.end),
match: !!chunk.match
}));
}
const searchText = ignoreCase ? text.toLowerCase() : text;
const searchQuery = ignoreCase ? typeof query === "string" ? query.toLowerCase() : query : query;
const start = typeof searchText === "string" ? searchText.indexOf(searchQuery) : -1;
if (start === -1) return [{
text,
match: false
}];
return normalizeSpan([{
start,
end: start + searchQuery.length
}], text.length).map((chunk) => ({
text: text.slice(chunk.start, chunk.end),
match: !!chunk.match
}));
}
//#endregion
//#region src/shared/highlight-word/highlight-multiple.ts
const buildRegex = (queryProp, flags, exactMatch) => {
const query = queryProp.filter(Boolean).map((text) => escapeRegex(text));
const pattern = exactMatch ? `\\b(${query.join("|")})\\b` : `(${query.join("|")})`;
return new RegExp(pattern, flags);
};
const getRegexFlags = (ignoreCase, matchAll = true) => `${ignoreCase ? "i" : ""}${matchAll ? "g" : ""}`;
function highlightMultiple(props) {
const { text, query, ignoreCase, matchAll, exactMatch } = props;
if (query.length === 0) return [{
text,
match: false
}];
const flags = getRegexFlags(ignoreCase, matchAll);
const regex = buildRegex(Array.isArray(query) ? query : [query], flags, exactMatch);
return normalizeSpan([...text.matchAll(regex)].map((match) => ({
start: match.index || 0,
end: (match.index || 0) + match[0].length
})), props.text.length).map((chunk) => ({
text: props.text.slice(chunk.start, chunk.end),
match: !!chunk.match
}));
}
//#endregion
//#region src/shared/highlight-word/highlight.ts
const highlightWord = (props) => {
if (props.matchAll == null) props.matchAll = Array.isArray(props.query);
if (!props.matchAll && Array.isArray(props.query)) throw new Error("matchAll must be true when using multiple queries");
return props.matchAll ? highlightMultiple(props) : highlightFirst(props);
};
//#endregion
exports.highlightWord = highlightWord;
//#region src/shared/highlight-word/types.d.ts
interface HighlightRegexOptions {
ignoreCase?: boolean | undefined;
matchAll?: boolean | undefined;
exactMatch?: boolean | undefined;
}
interface HighlightWordProps extends HighlightRegexOptions {
text: string;
query: string | string[];
}
interface HighlightChunk {
text: string;
match: boolean;
}
interface HighlightSpan {
start: number;
end: number;
match?: boolean | undefined;
}
//#endregion
//#region src/shared/highlight-word/highlight.d.ts
declare const highlightWord: (props: HighlightWordProps) => HighlightChunk[];
//#endregion
export { HighlightChunk, HighlightSpan, HighlightWordProps, highlightWord };
//#region src/shared/highlight-word/types.d.ts
interface HighlightRegexOptions {
ignoreCase?: boolean | undefined;
matchAll?: boolean | undefined;
exactMatch?: boolean | undefined;
}
interface HighlightWordProps extends HighlightRegexOptions {
text: string;
query: string | string[];
}
interface HighlightChunk {
text: string;
match: boolean;
}
interface HighlightSpan {
start: number;
end: number;
match?: boolean | undefined;
}
//#endregion
//#region src/shared/highlight-word/highlight.d.ts
declare const highlightWord: (props: HighlightWordProps) => HighlightChunk[];
//#endregion
export { HighlightChunk, HighlightSpan, HighlightWordProps, highlightWord };
//#region src/shared/highlight-word/normalize-span.ts
const normalizeSpan = (spans, len) => {
const result = [];
const append = (start, end, match) => {
if (end - start > 0) result.push({
start,
end,
match
});
};
if (spans.length === 0) append(0, len, false);
else {
let lastIndex = 0;
for (const chunk of spans) {
append(lastIndex, chunk.start, false);
append(chunk.start, chunk.end, true);
lastIndex = chunk.end;
}
append(lastIndex, len, false);
}
return result;
};
//#endregion
//#region src/shared/highlight-word/escape-regex.ts
const escapeRegex = (term) => term.replace(/[|\\{}()[\]^$+*?.-]/g, (char) => `\\${char}`);
//#endregion
//#region src/shared/highlight-word/highlight-first.ts
function highlightFirst(props) {
const { text, query, ignoreCase, exactMatch } = props;
if (exactMatch) {
const escapedQuery = escapeRegex(query);
const regex = new RegExp(`\\b(${escapedQuery})\\b`, ignoreCase ? "i" : "");
const match = text.match(regex);
if (!match || match.index === void 0) return [{
text,
match: false
}];
const start = match.index;
return normalizeSpan([{
start,
end: start + match[0].length
}], text.length).map((chunk) => ({
text: text.slice(chunk.start, chunk.end),
match: !!chunk.match
}));
}
const searchText = ignoreCase ? text.toLowerCase() : text;
const searchQuery = ignoreCase ? typeof query === "string" ? query.toLowerCase() : query : query;
const start = typeof searchText === "string" ? searchText.indexOf(searchQuery) : -1;
if (start === -1) return [{
text,
match: false
}];
return normalizeSpan([{
start,
end: start + searchQuery.length
}], text.length).map((chunk) => ({
text: text.slice(chunk.start, chunk.end),
match: !!chunk.match
}));
}
//#endregion
//#region src/shared/highlight-word/highlight-multiple.ts
const buildRegex = (queryProp, flags, exactMatch) => {
const query = queryProp.filter(Boolean).map((text) => escapeRegex(text));
const pattern = exactMatch ? `\\b(${query.join("|")})\\b` : `(${query.join("|")})`;
return new RegExp(pattern, flags);
};
const getRegexFlags = (ignoreCase, matchAll = true) => `${ignoreCase ? "i" : ""}${matchAll ? "g" : ""}`;
function highlightMultiple(props) {
const { text, query, ignoreCase, matchAll, exactMatch } = props;
if (query.length === 0) return [{
text,
match: false
}];
const flags = getRegexFlags(ignoreCase, matchAll);
const regex = buildRegex(Array.isArray(query) ? query : [query], flags, exactMatch);
return normalizeSpan([...text.matchAll(regex)].map((match) => ({
start: match.index || 0,
end: (match.index || 0) + match[0].length
})), props.text.length).map((chunk) => ({
text: props.text.slice(chunk.start, chunk.end),
match: !!chunk.match
}));
}
//#endregion
//#region src/shared/highlight-word/highlight.ts
const highlightWord = (props) => {
if (props.matchAll == null) props.matchAll = Array.isArray(props.query);
if (!props.matchAll && Array.isArray(props.query)) throw new Error("matchAll must be true when using multiple queries");
return props.matchAll ? highlightMultiple(props) : highlightFirst(props);
};
//#endregion
export { highlightWord };
export { };
export { };
export {};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let json_format_highlight = require("json-format-highlight");
json_format_highlight = __toESM(json_format_highlight, 1);
//#region src/shared/stringify-state/index.ts
const pick = (obj, keys) => Object.fromEntries(keys.filter((key) => key in obj).map((key) => [key, obj[key]]));
const hasProp = (v, prop) => Object.prototype.hasOwnProperty.call(v, prop);
const isTimeObject = (v) => hasProp(v, "hour") && hasProp(v, "minute") && hasProp(v, "second");
const isMachine = (v) => [
"state",
"context",
"scope"
].every((prop) => hasProp(v, prop));
function stringifyState(state, omit) {
return JSON.stringify(state, (key, value) => {
try {
if (hasProp(value, "target") && hasProp(value, "timeStamp")) return pick(value, [
"type",
"target",
"currentTarget",
"relatedTarget"
]);
if (omit?.includes(key)) return;
if (hasProp(value, "calendar") || isTimeObject(value)) return value.toString();
if (typeof value?.json === "function") return value.json();
if (typeof value?.toJSON === "function") return value.toJSON();
if (Number.isNaN(value)) return "NaN";
if (value instanceof File) return value.name;
if (value instanceof Set) return Array.from(value);
if (isMachine(value)) return `Machine: ${value.scope.id}`;
switch (value?.toString()) {
case "[object ShadowRoot]": return "#shadow-root";
case "[object HTMLDocument]": return "#document";
case "[object Window]": return "#window";
case "[object AbortController]": return "#abort-controller";
default: return value !== null && typeof value === "object" && value.nodeType === 1 ? value.tagName : value;
}
} catch {
return value;
}
}, 4);
}
function highlightState(state, omit) {
return (0, json_format_highlight.default)(stringifyState(state, omit));
}
//#endregion
exports.__toESM = __toESM;
exports.highlightState = highlightState;
exports.stringifyState = stringifyState;
//#region src/shared/stringify-state/index.d.ts
interface Dict {
[key: string]: any;
}
declare function stringifyState(state: Dict, omit?: string[]): string;
declare function highlightState(state: Dict, omit?: string[]): any;
//#endregion
export { highlightState, stringifyState };
//#region src/shared/stringify-state/index.d.ts
interface Dict {
[key: string]: any;
}
declare function stringifyState(state: Dict, omit?: string[]): string;
declare function highlightState(state: Dict, omit?: string[]): any;
//#endregion
export { highlightState, stringifyState };
import formatHighlight from "json-format-highlight";
//#region src/shared/stringify-state/index.ts
const pick = (obj, keys) => Object.fromEntries(keys.filter((key) => key in obj).map((key) => [key, obj[key]]));
const hasProp = (v, prop) => Object.prototype.hasOwnProperty.call(v, prop);
const isTimeObject = (v) => hasProp(v, "hour") && hasProp(v, "minute") && hasProp(v, "second");
const isMachine = (v) => [
"state",
"context",
"scope"
].every((prop) => hasProp(v, prop));
function stringifyState(state, omit) {
return JSON.stringify(state, (key, value) => {
try {
if (hasProp(value, "target") && hasProp(value, "timeStamp")) return pick(value, [
"type",
"target",
"currentTarget",
"relatedTarget"
]);
if (omit?.includes(key)) return;
if (hasProp(value, "calendar") || isTimeObject(value)) return value.toString();
if (typeof value?.json === "function") return value.json();
if (typeof value?.toJSON === "function") return value.toJSON();
if (Number.isNaN(value)) return "NaN";
if (value instanceof File) return value.name;
if (value instanceof Set) return Array.from(value);
if (isMachine(value)) return `Machine: ${value.scope.id}`;
switch (value?.toString()) {
case "[object ShadowRoot]": return "#shadow-root";
case "[object HTMLDocument]": return "#document";
case "[object Window]": return "#window";
case "[object AbortController]": return "#abort-controller";
default: return value !== null && typeof value === "object" && value.nodeType === 1 ? value.tagName : value;
}
} catch {
return value;
}
}, 4);
}
function highlightState(state, omit) {
return formatHighlight(stringifyState(state, omit));
}
//#endregion
export { highlightState, stringifyState };
//#region src/shared/utils/array.ts
function toArray(v) {
if (v == null) return [];
return Array.isArray(v) ? v : [v];
}
const fromLength = (length) => Array.from(Array(length).keys());
const first = (v) => v[0];
const last = (v) => v[v.length - 1];
const isEmpty = (v) => v.length === 0;
const has = (v, t) => v.indexOf(t) !== -1;
const add = (v, ...items) => v.concat(items);
const remove = (v, ...items) => v.filter((t) => !items.includes(t));
const removeAt = (v, i) => v.filter((_, idx) => idx !== i);
const insertAt = (v, i, ...items) => [
...v.slice(0, i),
...items,
...v.slice(i)
];
const uniq = (v) => Array.from(new Set(v));
const diff = (a, b) => {
const set = new Set(b);
return a.filter((t) => !set.has(t));
};
const addOrRemove = (v, item) => has(v, item) ? remove(v, item) : add(v, item);
function clear(v) {
while (v.length > 0) v.pop();
return v;
}
function nextIndex(v, idx, opts = {}) {
const { step = 1, loop = true } = opts;
const next = idx + step;
const len = v.length;
const last = len - 1;
if (idx === -1) return step > 0 ? 0 : last;
if (next < 0) return loop ? last : 0;
if (next >= len) return loop ? 0 : idx > len ? len : idx;
return next;
}
function next(v, idx, opts = {}) {
return v[nextIndex(v, idx, opts)];
}
function prevIndex(v, idx, opts = {}) {
const { step = 1, loop = true } = opts;
return nextIndex(v, idx, {
step: -step,
loop
});
}
function prev(v, index, opts = {}) {
return v[prevIndex(v, index, opts)];
}
function chunk(v, size) {
return v.reduce((rows, value, index) => {
if (index % size === 0) rows.push([value]);
else last(rows)?.push(value);
return rows;
}, []);
}
function flatArray(arr) {
return arr.reduce((flat, item) => {
if (Array.isArray(item)) return flat.concat(flatArray(item));
return flat.concat(item);
}, []);
}
function partition(arr, fn) {
return arr.reduce(([pass, fail], value) => {
if (fn(value)) pass.push(value);
else fail.push(value);
return [pass, fail];
}, [[], []]);
}
//#endregion
//#region src/shared/utils/equal.ts
const isArrayLike = (value) => value?.constructor.name === "Array";
const isArrayEqual = (a, b) => {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) if (!isEqual(a[i], b[i])) return false;
return true;
};
const isEqual = (a, b) => {
if (Object.is(a, b)) return true;
if (a == null && b != null || a != null && b == null) return false;
if (typeof a?.isEqual === "function" && typeof b?.isEqual === "function") return a.isEqual(b);
if (typeof a === "function" && typeof b === "function") return a.toString() === b.toString();
if (isArrayLike(a) && isArrayLike(b)) return isArrayEqual(Array.from(a), Array.from(b));
if (!(typeof a === "object") || !(typeof b === "object")) return false;
const keys = Object.keys(b ?? Object.create(null));
const length = keys.length;
for (let i = 0; i < length; i++) if (!Reflect.has(a, keys[i])) return false;
for (let i = 0; i < length; i++) {
const key = keys[i];
if (!isEqual(a[key], b[key])) return false;
}
return true;
};
//#endregion
//#region src/shared/utils/guard.ts
const isDev = () => process.env.NODE_ENV !== "production";
const isArray = (v) => Array.isArray(v);
const isBoolean = (v) => v === true || v === false;
const isObjectLike = (v) => v != null && typeof v === "object";
const isObject = (v) => isObjectLike(v) && !isArray(v);
const isNumber = (v) => typeof v === "number" && !Number.isNaN(v);
const isString = (v) => typeof v === "string";
const isFunction = (v) => typeof v === "function";
const isNull = (v) => v == null;
const hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
const baseGetTag = (v) => Object.prototype.toString.call(v);
const fnToString = Function.prototype.toString;
const objectCtorString = fnToString.call(Object);
const isPlainObject = (v) => {
if (!isObjectLike(v) || baseGetTag(v) != "[object Object]" || isFrameworkElement(v)) return false;
const proto = Object.getPrototypeOf(v);
if (proto === null) return true;
const Ctor = hasProp(proto, "constructor") && proto.constructor;
return typeof Ctor == "function" && Ctor instanceof Ctor && fnToString.call(Ctor) == objectCtorString;
};
const isReactElement = (x) => typeof x === "object" && x !== null && "$$typeof" in x && "props" in x;
const isVueElement = (x) => typeof x === "object" && x !== null && "__v_isVNode" in x;
const isFrameworkElement = (x) => isReactElement(x) || isVueElement(x);
//#endregion
//#region src/shared/utils/functions.ts
const runIfFn = (v, ...a) => {
return (typeof v === "function" ? v(...a) : v) ?? void 0;
};
const cast = (v) => v;
const identity = (v) => v();
const noop = () => {};
const callAll = (...fns) => (...a) => {
fns.forEach(function(fn) {
fn?.(...a);
});
};
const uuid = (() => {
let id = 0;
return () => {
id++;
return id.toString(36);
};
})();
function match(key, record, ...args) {
if (key in record) {
const fn = record[key];
return isFunction(fn) ? fn(...args) : fn;
}
const error = /* @__PURE__ */ new Error(`No matching key: ${JSON.stringify(key)} in ${JSON.stringify(Object.keys(record))}`);
Error.captureStackTrace?.(error, match);
throw error;
}
const tryCatch = (fn, fallback) => {
try {
return fn();
} catch (error) {
if (error instanceof Error) Error.captureStackTrace?.(error, tryCatch);
return fallback?.();
}
};
function throttle(fn, wait = 0) {
let lastCall = 0;
let timeout = null;
return ((...args) => {
const now = Date.now();
const timeSinceLastCall = now - lastCall;
if (timeSinceLastCall >= wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
fn(...args);
lastCall = now;
} else if (!timeout) timeout = setTimeout(() => {
fn(...args);
lastCall = Date.now();
timeout = null;
}, wait - timeSinceLastCall);
});
}
function debounce(fn, wait = 0) {
let timeout = null;
return ((...args) => {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
timeout = setTimeout(() => {
fn(...args);
}, wait);
});
}
const toChar = (code) => String.fromCharCode(code + (code > 25 ? 39 : 97));
function toName(code) {
let name = "";
let x;
for (x = Math.abs(code); x > 52; x = x / 52 | 0) name = toChar(x % 52) + name;
return toChar(x % 52) + name;
}
function toPhash(h, x) {
let i = x.length;
while (i) h = h * 33 ^ x.charCodeAt(--i);
return h;
}
const hash = (value) => toName(toPhash(5381, value) >>> 0);
//#endregion
//#region src/shared/utils/number.ts
const { floor, abs, round, min, max, pow, sign } = Math;
const isNaN = (v) => Number.isNaN(v);
const nan = (v) => isNaN(v) ? 0 : v;
const mod = (v, m) => (v % m + m) % m;
const wrap = (v, vmax) => (v % vmax + vmax) % vmax;
const getMinValueAtIndex = (i, v, vmin) => i === 0 ? vmin : v[i - 1];
const getMaxValueAtIndex = (i, v, vmax) => i === v.length - 1 ? vmax : v[i + 1];
const isValueAtMax = (v, vmax) => nan(v) >= vmax;
const isValueAtMin = (v, vmin) => nan(v) <= vmin;
const isValueWithinRange = (v, vmin, vmax) => {
const value = nan(v);
return (vmin == null || value >= vmin) && (vmax == null || value <= vmax);
};
const roundValue = (v, vmin, step) => round((nan(v) - vmin) / step) * step + vmin;
const clampValue = (v, vmin, vmax) => min(max(nan(v), vmin), vmax);
const clampPercent = (v) => clampValue(v, 0, 1);
const getValuePercent = (v, vmin, vmax) => (nan(v) - vmin) / (vmax - vmin);
const getPercentValue = (p, vmin, vmax, step) => clampValue(roundValue(p * (vmax - vmin) + vmin, vmin, step), vmin, vmax);
const roundToStepPrecision = (v, step) => {
let rv = v;
let ss = step.toString();
let pi = ss.indexOf(".");
let p = pi >= 0 ? ss.length - pi : 0;
if (p > 0) {
let pw = pow(10, p);
rv = round(rv * pw) / pw;
}
return rv;
};
const roundToDpr = (v, dpr) => typeof dpr === "number" ? floor(v * dpr + .5) / dpr : round(v);
const snapValueToStep = (v, vmin, vmax, step) => {
const min = vmin != null ? Number(vmin) : 0;
const max = Number(vmax);
const remainder = (v - min) % step;
let snapped = abs(remainder) * 2 >= step ? v + sign(remainder) * (step - abs(remainder)) : v - remainder;
snapped = roundToStepPrecision(snapped, step);
if (!isNaN(min) && snapped < min) snapped = min;
else if (!isNaN(max) && snapped > max) {
const stepsInRange = floor((max - min) / step);
const largestValidStep = min + stepsInRange * step;
snapped = stepsInRange <= 0 || largestValidStep < min ? max : largestValidStep;
}
return roundToStepPrecision(snapped, step);
};
const setValueAtIndex = (vs, i, v) => {
if (vs[i] === v) return vs;
return [
...vs.slice(0, i),
v,
...vs.slice(i + 1)
];
};
function getValueSetterAtIndex(index, ctx) {
const minValueAtIndex = getMinValueAtIndex(index, ctx.values, ctx.min);
const maxValueAtIndex = getMaxValueAtIndex(index, ctx.values, ctx.max);
let nextValues = ctx.values.slice();
return function setValue(value) {
let nextValue = snapValueToStep(value, minValueAtIndex, maxValueAtIndex, ctx.step);
nextValues = setValueAtIndex(nextValues, index, value);
nextValues[index] = nextValue;
return nextValues;
};
}
function getNextStepValue(index, ctx) {
const nextValue = ctx.values[index] + ctx.step;
return getValueSetterAtIndex(index, ctx)(nextValue);
}
function getPreviousStepValue(index, ctx) {
const nextValue = ctx.values[index] - ctx.step;
return getValueSetterAtIndex(index, ctx)(nextValue);
}
const getClosestValueIndex = (vs, t) => {
let i = vs.findIndex((v) => t - v < 0);
if (i === 0) return i;
if (i === -1) return vs.length - 1;
let vLeft = vs[i - 1];
let vRight = vs[i];
if (abs(vLeft - t) < abs(vRight - t)) return i - 1;
return i;
};
const getClosestValue = (vs, t) => vs[getClosestValueIndex(vs, t)];
const getValueRanges = (vs, vmin, vmax, gap) => vs.map((v, i) => ({
min: i === 0 ? vmin : vs[i - 1] + gap,
max: i === vs.length - 1 ? vmax : vs[i + 1] - gap,
value: v
}));
const getValueTransformer = (va, vb) => {
const [a, b] = va;
const [c, d] = vb;
return (v) => a === b || c === d ? c : c + (d - c) / (b - a) * (v - a);
};
const toFixedNumber = (v, d = 0, b = 10) => {
const pow = Math.pow(b, d);
return round(v * pow) / pow;
};
const countDecimals = (value) => {
if (!Number.isFinite(value)) return 0;
let e = 1, p = 0;
while (Math.round(value * e) / e !== value) {
e *= 10;
p += 1;
}
return p;
};
const decimalOp = (a, op, b) => {
let result = op === "+" ? a + b : a - b;
if (a % 1 !== 0 || b % 1 !== 0) {
const multiplier = 10 ** Math.max(countDecimals(a), countDecimals(b));
a = Math.round(a * multiplier);
b = Math.round(b * multiplier);
result = op === "+" ? a + b : a - b;
result /= multiplier;
}
return result;
};
const incrementValue = (v, s) => decimalOp(nan(v), "+", s);
const decrementValue = (v, s) => decimalOp(nan(v), "-", s);
const toPx = (v) => typeof v === "number" ? `${v}px` : v;
//#endregion
//#region src/shared/utils/object.ts
function compact(obj) {
if (!isPlainObject(obj) || obj === void 0) return obj;
const keys = Reflect.ownKeys(obj).filter((key) => typeof key === "string");
const filtered = {};
for (const key of keys) {
const value = obj[key];
if (value !== void 0) filtered[key] = compact(value);
}
return filtered;
}
const json = (v) => JSON.parse(JSON.stringify(v));
function pick(obj, keys) {
const filtered = {};
for (const key of keys) {
const value = obj[key];
if (value !== void 0) filtered[key] = value;
}
return filtered;
}
function splitProps(props, keys) {
const rest = {};
const result = {};
const keySet = new Set(keys);
const ownKeys = Reflect.ownKeys(props);
for (const key of ownKeys) if (keySet.has(key)) result[key] = props[key];
else rest[key] = props[key];
return [result, rest];
}
const createSplitProps = (keys) => {
return function split(props) {
return splitProps(props, keys);
};
};
function omit(obj, keys) {
return createSplitProps(keys)(obj)[1];
}
//#endregion
//#region src/shared/utils/store.ts
function createStore(initialState, compare = Object.is) {
let state = { ...initialState };
const listeners = /* @__PURE__ */ new Set();
const subscribe = (listener) => {
listeners.add(listener);
return () => listeners.delete(listener);
};
const publish = () => {
listeners.forEach((listener) => listener());
};
const get = (key) => {
return state[key];
};
const set = (key, value) => {
if (!compare(state[key], value)) {
state[key] = value;
publish();
}
};
const update = (updates) => {
let hasChanges = false;
for (const key in updates) {
const value = updates[key];
if (value !== void 0 && !compare(state[key], value)) {
state[key] = value;
hasChanges = true;
}
}
if (hasChanges) publish();
};
const snapshot = () => ({ ...state });
return {
subscribe,
get,
set,
update,
snapshot
};
}
//#endregion
//#region src/shared/utils/timers.ts
const currentTime = () => performance.now();
var Timer = class {
onTick;
frameId = null;
pausedAtMs = null;
context;
constructor(onTick) {
this.onTick = onTick;
this.context = {
now: 0,
startMs: currentTime(),
deltaMs: 0
};
}
cancelFrame = () => {
if (this.frameId === null) return;
cancelAnimationFrame(this.frameId);
this.frameId = null;
};
setStartMs = (startMs) => {
this.context.startMs = startMs;
};
get elapsedMs() {
if (this.pausedAtMs !== null) return this.pausedAtMs - this.context.startMs;
return currentTime() - this.context.startMs;
}
start = () => {
if (this.frameId !== null) return;
const now = currentTime();
if (this.pausedAtMs !== null) {
this.context.startMs += now - this.pausedAtMs;
this.pausedAtMs = null;
} else this.context.startMs = now;
this.frameId = requestAnimationFrame(this.#tick);
};
pause = () => {
if (this.frameId === null) return;
this.cancelFrame();
this.pausedAtMs = currentTime();
};
stop = () => {
if (this.frameId === null) return;
this.cancelFrame();
this.pausedAtMs = null;
};
#tick = (now) => {
this.context.now = now;
this.context.deltaMs = now - this.context.startMs;
if (this.onTick(this.context) === false) {
this.stop();
return;
}
this.frameId = requestAnimationFrame(this.#tick);
};
};
function setRafInterval(fn, intervalMs) {
const timer = new Timer(({ now, deltaMs }) => {
if (deltaMs >= intervalMs) {
const startMs = intervalMs > 0 ? now - deltaMs % intervalMs : now;
timer.setStartMs(startMs);
fn({
startMs,
deltaMs
});
}
});
timer.start();
return () => timer.stop();
}
function setRafTimeout(fn, delayMs) {
const timer = new Timer(({ deltaMs }) => {
if (deltaMs >= delayMs) {
fn();
return false;
}
});
timer.start();
return () => timer.stop();
}
//#endregion
//#region src/shared/utils/warning.ts
function warn(...a) {
const m = a.length === 1 ? a[0] : a[1];
if ((a.length === 2 ? a[0] : true) && process.env.NODE_ENV !== "production") console.warn(m);
}
function invariant(...a) {
const m = a.length === 1 ? a[0] : a[1];
if ((a.length === 2 ? a[0] : true) && process.env.NODE_ENV !== "production") throw new Error(m);
}
function ensure(c, m) {
if (c == null) throw new Error(m());
}
function ensureProps(props, keys, scope) {
let missingKeys = [];
for (const key of keys) if (props[key] == null) missingKeys.push(key);
if (missingKeys.length > 0) throw new Error(`[ginxjs${scope ? ` > ${scope}` : ""}] missing required props: ${missingKeys.join(", ")}`);
}
//#endregion
Object.defineProperty(exports, "Timer", {
enumerable: true,
get: function() {
return Timer;
}
});
Object.defineProperty(exports, "add", {
enumerable: true,
get: function() {
return add;
}
});
Object.defineProperty(exports, "addOrRemove", {
enumerable: true,
get: function() {
return addOrRemove;
}
});
Object.defineProperty(exports, "callAll", {
enumerable: true,
get: function() {
return callAll;
}
});
Object.defineProperty(exports, "cast", {
enumerable: true,
get: function() {
return cast;
}
});
Object.defineProperty(exports, "chunk", {
enumerable: true,
get: function() {
return chunk;
}
});
Object.defineProperty(exports, "clampPercent", {
enumerable: true,
get: function() {
return clampPercent;
}
});
Object.defineProperty(exports, "clampValue", {
enumerable: true,
get: function() {
return clampValue;
}
});
Object.defineProperty(exports, "clear", {
enumerable: true,
get: function() {
return clear;
}
});
Object.defineProperty(exports, "compact", {
enumerable: true,
get: function() {
return compact;
}
});
Object.defineProperty(exports, "createSplitProps", {
enumerable: true,
get: function() {
return createSplitProps;
}
});
Object.defineProperty(exports, "createStore", {
enumerable: true,
get: function() {
return createStore;
}
});
Object.defineProperty(exports, "debounce", {
enumerable: true,
get: function() {
return debounce;
}
});
Object.defineProperty(exports, "decrementValue", {
enumerable: true,
get: function() {
return decrementValue;
}
});
Object.defineProperty(exports, "diff", {
enumerable: true,
get: function() {
return diff;
}
});
Object.defineProperty(exports, "ensure", {
enumerable: true,
get: function() {
return ensure;
}
});
Object.defineProperty(exports, "ensureProps", {
enumerable: true,
get: function() {
return ensureProps;
}
});
Object.defineProperty(exports, "first", {
enumerable: true,
get: function() {
return first;
}
});
Object.defineProperty(exports, "flatArray", {
enumerable: true,
get: function() {
return flatArray;
}
});
Object.defineProperty(exports, "fromLength", {
enumerable: true,
get: function() {
return fromLength;
}
});
Object.defineProperty(exports, "getClosestValue", {
enumerable: true,
get: function() {
return getClosestValue;
}
});
Object.defineProperty(exports, "getClosestValueIndex", {
enumerable: true,
get: function() {
return getClosestValueIndex;
}
});
Object.defineProperty(exports, "getMaxValueAtIndex", {
enumerable: true,
get: function() {
return getMaxValueAtIndex;
}
});
Object.defineProperty(exports, "getMinValueAtIndex", {
enumerable: true,
get: function() {
return getMinValueAtIndex;
}
});
Object.defineProperty(exports, "getNextStepValue", {
enumerable: true,
get: function() {
return getNextStepValue;
}
});
Object.defineProperty(exports, "getPercentValue", {
enumerable: true,
get: function() {
return getPercentValue;
}
});
Object.defineProperty(exports, "getPreviousStepValue", {
enumerable: true,
get: function() {
return getPreviousStepValue;
}
});
Object.defineProperty(exports, "getValuePercent", {
enumerable: true,
get: function() {
return getValuePercent;
}
});
Object.defineProperty(exports, "getValueRanges", {
enumerable: true,
get: function() {
return getValueRanges;
}
});
Object.defineProperty(exports, "getValueSetterAtIndex", {
enumerable: true,
get: function() {
return getValueSetterAtIndex;
}
});
Object.defineProperty(exports, "getValueTransformer", {
enumerable: true,
get: function() {
return getValueTransformer;
}
});
Object.defineProperty(exports, "has", {
enumerable: true,
get: function() {
return has;
}
});
Object.defineProperty(exports, "hasProp", {
enumerable: true,
get: function() {
return hasProp;
}
});
Object.defineProperty(exports, "hash", {
enumerable: true,
get: function() {
return hash;
}
});
Object.defineProperty(exports, "identity", {
enumerable: true,
get: function() {
return identity;
}
});
Object.defineProperty(exports, "incrementValue", {
enumerable: true,
get: function() {
return incrementValue;
}
});
Object.defineProperty(exports, "insertAt", {
enumerable: true,
get: function() {
return insertAt;
}
});
Object.defineProperty(exports, "invariant", {
enumerable: true,
get: function() {
return invariant;
}
});
Object.defineProperty(exports, "isArray", {
enumerable: true,
get: function() {
return isArray;
}
});
Object.defineProperty(exports, "isBoolean", {
enumerable: true,
get: function() {
return isBoolean;
}
});
Object.defineProperty(exports, "isDev", {
enumerable: true,
get: function() {
return isDev;
}
});
Object.defineProperty(exports, "isEmpty", {
enumerable: true,
get: function() {
return isEmpty;
}
});
Object.defineProperty(exports, "isEqual", {
enumerable: true,
get: function() {
return isEqual;
}
});
Object.defineProperty(exports, "isFunction", {
enumerable: true,
get: function() {
return isFunction;
}
});
Object.defineProperty(exports, "isNaN", {
enumerable: true,
get: function() {
return isNaN;
}
});
Object.defineProperty(exports, "isNull", {
enumerable: true,
get: function() {
return isNull;
}
});
Object.defineProperty(exports, "isNumber", {
enumerable: true,
get: function() {
return isNumber;
}
});
Object.defineProperty(exports, "isObject", {
enumerable: true,
get: function() {
return isObject;
}
});
Object.defineProperty(exports, "isObjectLike", {
enumerable: true,
get: function() {
return isObjectLike;
}
});
Object.defineProperty(exports, "isPlainObject", {
enumerable: true,
get: function() {
return isPlainObject;
}
});
Object.defineProperty(exports, "isString", {
enumerable: true,
get: function() {
return isString;
}
});
Object.defineProperty(exports, "isValueAtMax", {
enumerable: true,
get: function() {
return isValueAtMax;
}
});
Object.defineProperty(exports, "isValueAtMin", {
enumerable: true,
get: function() {
return isValueAtMin;
}
});
Object.defineProperty(exports, "isValueWithinRange", {
enumerable: true,
get: function() {
return isValueWithinRange;
}
});
Object.defineProperty(exports, "json", {
enumerable: true,
get: function() {
return json;
}
});
Object.defineProperty(exports, "last", {
enumerable: true,
get: function() {
return last;
}
});
Object.defineProperty(exports, "match", {
enumerable: true,
get: function() {
return match;
}
});
Object.defineProperty(exports, "mod", {
enumerable: true,
get: function() {
return mod;
}
});
Object.defineProperty(exports, "nan", {
enumerable: true,
get: function() {
return nan;
}
});
Object.defineProperty(exports, "next", {
enumerable: true,
get: function() {
return next;
}
});
Object.defineProperty(exports, "nextIndex", {
enumerable: true,
get: function() {
return nextIndex;
}
});
Object.defineProperty(exports, "noop", {
enumerable: true,
get: function() {
return noop;
}
});
Object.defineProperty(exports, "omit", {
enumerable: true,
get: function() {
return omit;
}
});
Object.defineProperty(exports, "partition", {
enumerable: true,
get: function() {
return partition;
}
});
Object.defineProperty(exports, "pick", {
enumerable: true,
get: function() {
return pick;
}
});
Object.defineProperty(exports, "prev", {
enumerable: true,
get: function() {
return prev;
}
});
Object.defineProperty(exports, "prevIndex", {
enumerable: true,
get: function() {
return prevIndex;
}
});
Object.defineProperty(exports, "remove", {
enumerable: true,
get: function() {
return remove;
}
});
Object.defineProperty(exports, "removeAt", {
enumerable: true,
get: function() {
return removeAt;
}
});
Object.defineProperty(exports, "roundToDpr", {
enumerable: true,
get: function() {
return roundToDpr;
}
});
Object.defineProperty(exports, "roundToStepPrecision", {
enumerable: true,
get: function() {
return roundToStepPrecision;
}
});
Object.defineProperty(exports, "roundValue", {
enumerable: true,
get: function() {
return roundValue;
}
});
Object.defineProperty(exports, "runIfFn", {
enumerable: true,
get: function() {
return runIfFn;
}
});
Object.defineProperty(exports, "setRafInterval", {
enumerable: true,
get: function() {
return setRafInterval;
}
});
Object.defineProperty(exports, "setRafTimeout", {
enumerable: true,
get: function() {
return setRafTimeout;
}
});
Object.defineProperty(exports, "setValueAtIndex", {
enumerable: true,
get: function() {
return setValueAtIndex;
}
});
Object.defineProperty(exports, "snapValueToStep", {
enumerable: true,
get: function() {
return snapValueToStep;
}
});
Object.defineProperty(exports, "splitProps", {
enumerable: true,
get: function() {
return splitProps;
}
});
Object.defineProperty(exports, "throttle", {
enumerable: true,
get: function() {
return throttle;
}
});
Object.defineProperty(exports, "toArray", {
enumerable: true,
get: function() {
return toArray;
}
});
Object.defineProperty(exports, "toFixedNumber", {
enumerable: true,
get: function() {
return toFixedNumber;
}
});
Object.defineProperty(exports, "toPx", {
enumerable: true,
get: function() {
return toPx;
}
});
Object.defineProperty(exports, "tryCatch", {
enumerable: true,
get: function() {
return tryCatch;
}
});
Object.defineProperty(exports, "uniq", {
enumerable: true,
get: function() {
return uniq;
}
});
Object.defineProperty(exports, "uuid", {
enumerable: true,
get: function() {
return uuid;
}
});
Object.defineProperty(exports, "warn", {
enumerable: true,
get: function() {
return warn;
}
});
Object.defineProperty(exports, "wrap", {
enumerable: true,
get: function() {
return wrap;
}
});
//#region src/shared/utils/array.ts
function toArray(v) {
if (v == null) return [];
return Array.isArray(v) ? v : [v];
}
const fromLength = (length) => Array.from(Array(length).keys());
const first = (v) => v[0];
const last = (v) => v[v.length - 1];
const isEmpty = (v) => v.length === 0;
const has = (v, t) => v.indexOf(t) !== -1;
const add = (v, ...items) => v.concat(items);
const remove = (v, ...items) => v.filter((t) => !items.includes(t));
const removeAt = (v, i) => v.filter((_, idx) => idx !== i);
const insertAt = (v, i, ...items) => [
...v.slice(0, i),
...items,
...v.slice(i)
];
const uniq = (v) => Array.from(new Set(v));
const diff = (a, b) => {
const set = new Set(b);
return a.filter((t) => !set.has(t));
};
const addOrRemove = (v, item) => has(v, item) ? remove(v, item) : add(v, item);
function clear(v) {
while (v.length > 0) v.pop();
return v;
}
function nextIndex(v, idx, opts = {}) {
const { step = 1, loop = true } = opts;
const next = idx + step;
const len = v.length;
const last = len - 1;
if (idx === -1) return step > 0 ? 0 : last;
if (next < 0) return loop ? last : 0;
if (next >= len) return loop ? 0 : idx > len ? len : idx;
return next;
}
function next(v, idx, opts = {}) {
return v[nextIndex(v, idx, opts)];
}
function prevIndex(v, idx, opts = {}) {
const { step = 1, loop = true } = opts;
return nextIndex(v, idx, {
step: -step,
loop
});
}
function prev(v, index, opts = {}) {
return v[prevIndex(v, index, opts)];
}
function chunk(v, size) {
return v.reduce((rows, value, index) => {
if (index % size === 0) rows.push([value]);
else last(rows)?.push(value);
return rows;
}, []);
}
function flatArray(arr) {
return arr.reduce((flat, item) => {
if (Array.isArray(item)) return flat.concat(flatArray(item));
return flat.concat(item);
}, []);
}
function partition(arr, fn) {
return arr.reduce(([pass, fail], value) => {
if (fn(value)) pass.push(value);
else fail.push(value);
return [pass, fail];
}, [[], []]);
}
//#endregion
//#region src/shared/utils/equal.ts
const isArrayLike = (value) => value?.constructor.name === "Array";
const isArrayEqual = (a, b) => {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) if (!isEqual(a[i], b[i])) return false;
return true;
};
const isEqual = (a, b) => {
if (Object.is(a, b)) return true;
if (a == null && b != null || a != null && b == null) return false;
if (typeof a?.isEqual === "function" && typeof b?.isEqual === "function") return a.isEqual(b);
if (typeof a === "function" && typeof b === "function") return a.toString() === b.toString();
if (isArrayLike(a) && isArrayLike(b)) return isArrayEqual(Array.from(a), Array.from(b));
if (!(typeof a === "object") || !(typeof b === "object")) return false;
const keys = Object.keys(b ?? Object.create(null));
const length = keys.length;
for (let i = 0; i < length; i++) if (!Reflect.has(a, keys[i])) return false;
for (let i = 0; i < length; i++) {
const key = keys[i];
if (!isEqual(a[key], b[key])) return false;
}
return true;
};
//#endregion
//#region src/shared/utils/guard.ts
const isDev = () => process.env.NODE_ENV !== "production";
const isArray = (v) => Array.isArray(v);
const isBoolean = (v) => v === true || v === false;
const isObjectLike = (v) => v != null && typeof v === "object";
const isObject = (v) => isObjectLike(v) && !isArray(v);
const isNumber = (v) => typeof v === "number" && !Number.isNaN(v);
const isString = (v) => typeof v === "string";
const isFunction = (v) => typeof v === "function";
const isNull = (v) => v == null;
const hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
const baseGetTag = (v) => Object.prototype.toString.call(v);
const fnToString = Function.prototype.toString;
const objectCtorString = fnToString.call(Object);
const isPlainObject = (v) => {
if (!isObjectLike(v) || baseGetTag(v) != "[object Object]" || isFrameworkElement(v)) return false;
const proto = Object.getPrototypeOf(v);
if (proto === null) return true;
const Ctor = hasProp(proto, "constructor") && proto.constructor;
return typeof Ctor == "function" && Ctor instanceof Ctor && fnToString.call(Ctor) == objectCtorString;
};
const isReactElement = (x) => typeof x === "object" && x !== null && "$$typeof" in x && "props" in x;
const isVueElement = (x) => typeof x === "object" && x !== null && "__v_isVNode" in x;
const isFrameworkElement = (x) => isReactElement(x) || isVueElement(x);
//#endregion
//#region src/shared/utils/functions.ts
const runIfFn = (v, ...a) => {
return (typeof v === "function" ? v(...a) : v) ?? void 0;
};
const cast = (v) => v;
const identity = (v) => v();
const noop = () => {};
const callAll = (...fns) => (...a) => {
fns.forEach(function(fn) {
fn?.(...a);
});
};
const uuid = (() => {
let id = 0;
return () => {
id++;
return id.toString(36);
};
})();
function match(key, record, ...args) {
if (key in record) {
const fn = record[key];
return isFunction(fn) ? fn(...args) : fn;
}
const error = /* @__PURE__ */ new Error(`No matching key: ${JSON.stringify(key)} in ${JSON.stringify(Object.keys(record))}`);
Error.captureStackTrace?.(error, match);
throw error;
}
const tryCatch = (fn, fallback) => {
try {
return fn();
} catch (error) {
if (error instanceof Error) Error.captureStackTrace?.(error, tryCatch);
return fallback?.();
}
};
function throttle(fn, wait = 0) {
let lastCall = 0;
let timeout = null;
return ((...args) => {
const now = Date.now();
const timeSinceLastCall = now - lastCall;
if (timeSinceLastCall >= wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
fn(...args);
lastCall = now;
} else if (!timeout) timeout = setTimeout(() => {
fn(...args);
lastCall = Date.now();
timeout = null;
}, wait - timeSinceLastCall);
});
}
function debounce(fn, wait = 0) {
let timeout = null;
return ((...args) => {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
timeout = setTimeout(() => {
fn(...args);
}, wait);
});
}
const toChar = (code) => String.fromCharCode(code + (code > 25 ? 39 : 97));
function toName(code) {
let name = "";
let x;
for (x = Math.abs(code); x > 52; x = x / 52 | 0) name = toChar(x % 52) + name;
return toChar(x % 52) + name;
}
function toPhash(h, x) {
let i = x.length;
while (i) h = h * 33 ^ x.charCodeAt(--i);
return h;
}
const hash = (value) => toName(toPhash(5381, value) >>> 0);
//#endregion
//#region src/shared/utils/number.ts
const { floor, abs, round, min, max, pow, sign } = Math;
const isNaN = (v) => Number.isNaN(v);
const nan = (v) => isNaN(v) ? 0 : v;
const mod = (v, m) => (v % m + m) % m;
const wrap = (v, vmax) => (v % vmax + vmax) % vmax;
const getMinValueAtIndex = (i, v, vmin) => i === 0 ? vmin : v[i - 1];
const getMaxValueAtIndex = (i, v, vmax) => i === v.length - 1 ? vmax : v[i + 1];
const isValueAtMax = (v, vmax) => nan(v) >= vmax;
const isValueAtMin = (v, vmin) => nan(v) <= vmin;
const isValueWithinRange = (v, vmin, vmax) => {
const value = nan(v);
return (vmin == null || value >= vmin) && (vmax == null || value <= vmax);
};
const roundValue = (v, vmin, step) => round((nan(v) - vmin) / step) * step + vmin;
const clampValue = (v, vmin, vmax) => min(max(nan(v), vmin), vmax);
const clampPercent = (v) => clampValue(v, 0, 1);
const getValuePercent = (v, vmin, vmax) => (nan(v) - vmin) / (vmax - vmin);
const getPercentValue = (p, vmin, vmax, step) => clampValue(roundValue(p * (vmax - vmin) + vmin, vmin, step), vmin, vmax);
const roundToStepPrecision = (v, step) => {
let rv = v;
let ss = step.toString();
let pi = ss.indexOf(".");
let p = pi >= 0 ? ss.length - pi : 0;
if (p > 0) {
let pw = pow(10, p);
rv = round(rv * pw) / pw;
}
return rv;
};
const roundToDpr = (v, dpr) => typeof dpr === "number" ? floor(v * dpr + .5) / dpr : round(v);
const snapValueToStep = (v, vmin, vmax, step) => {
const min = vmin != null ? Number(vmin) : 0;
const max = Number(vmax);
const remainder = (v - min) % step;
let snapped = abs(remainder) * 2 >= step ? v + sign(remainder) * (step - abs(remainder)) : v - remainder;
snapped = roundToStepPrecision(snapped, step);
if (!isNaN(min) && snapped < min) snapped = min;
else if (!isNaN(max) && snapped > max) {
const stepsInRange = floor((max - min) / step);
const largestValidStep = min + stepsInRange * step;
snapped = stepsInRange <= 0 || largestValidStep < min ? max : largestValidStep;
}
return roundToStepPrecision(snapped, step);
};
const setValueAtIndex = (vs, i, v) => {
if (vs[i] === v) return vs;
return [
...vs.slice(0, i),
v,
...vs.slice(i + 1)
];
};
function getValueSetterAtIndex(index, ctx) {
const minValueAtIndex = getMinValueAtIndex(index, ctx.values, ctx.min);
const maxValueAtIndex = getMaxValueAtIndex(index, ctx.values, ctx.max);
let nextValues = ctx.values.slice();
return function setValue(value) {
let nextValue = snapValueToStep(value, minValueAtIndex, maxValueAtIndex, ctx.step);
nextValues = setValueAtIndex(nextValues, index, value);
nextValues[index] = nextValue;
return nextValues;
};
}
function getNextStepValue(index, ctx) {
const nextValue = ctx.values[index] + ctx.step;
return getValueSetterAtIndex(index, ctx)(nextValue);
}
function getPreviousStepValue(index, ctx) {
const nextValue = ctx.values[index] - ctx.step;
return getValueSetterAtIndex(index, ctx)(nextValue);
}
const getClosestValueIndex = (vs, t) => {
let i = vs.findIndex((v) => t - v < 0);
if (i === 0) return i;
if (i === -1) return vs.length - 1;
let vLeft = vs[i - 1];
let vRight = vs[i];
if (abs(vLeft - t) < abs(vRight - t)) return i - 1;
return i;
};
const getClosestValue = (vs, t) => vs[getClosestValueIndex(vs, t)];
const getValueRanges = (vs, vmin, vmax, gap) => vs.map((v, i) => ({
min: i === 0 ? vmin : vs[i - 1] + gap,
max: i === vs.length - 1 ? vmax : vs[i + 1] - gap,
value: v
}));
const getValueTransformer = (va, vb) => {
const [a, b] = va;
const [c, d] = vb;
return (v) => a === b || c === d ? c : c + (d - c) / (b - a) * (v - a);
};
const toFixedNumber = (v, d = 0, b = 10) => {
const pow = Math.pow(b, d);
return round(v * pow) / pow;
};
const countDecimals = (value) => {
if (!Number.isFinite(value)) return 0;
let e = 1, p = 0;
while (Math.round(value * e) / e !== value) {
e *= 10;
p += 1;
}
return p;
};
const decimalOp = (a, op, b) => {
let result = op === "+" ? a + b : a - b;
if (a % 1 !== 0 || b % 1 !== 0) {
const multiplier = 10 ** Math.max(countDecimals(a), countDecimals(b));
a = Math.round(a * multiplier);
b = Math.round(b * multiplier);
result = op === "+" ? a + b : a - b;
result /= multiplier;
}
return result;
};
const incrementValue = (v, s) => decimalOp(nan(v), "+", s);
const decrementValue = (v, s) => decimalOp(nan(v), "-", s);
const toPx = (v) => typeof v === "number" ? `${v}px` : v;
//#endregion
//#region src/shared/utils/object.ts
function compact(obj) {
if (!isPlainObject(obj) || obj === void 0) return obj;
const keys = Reflect.ownKeys(obj).filter((key) => typeof key === "string");
const filtered = {};
for (const key of keys) {
const value = obj[key];
if (value !== void 0) filtered[key] = compact(value);
}
return filtered;
}
const json = (v) => JSON.parse(JSON.stringify(v));
function pick(obj, keys) {
const filtered = {};
for (const key of keys) {
const value = obj[key];
if (value !== void 0) filtered[key] = value;
}
return filtered;
}
function splitProps(props, keys) {
const rest = {};
const result = {};
const keySet = new Set(keys);
const ownKeys = Reflect.ownKeys(props);
for (const key of ownKeys) if (keySet.has(key)) result[key] = props[key];
else rest[key] = props[key];
return [result, rest];
}
const createSplitProps = (keys) => {
return function split(props) {
return splitProps(props, keys);
};
};
function omit(obj, keys) {
return createSplitProps(keys)(obj)[1];
}
//#endregion
//#region src/shared/utils/store.ts
function createStore(initialState, compare = Object.is) {
let state = { ...initialState };
const listeners = /* @__PURE__ */ new Set();
const subscribe = (listener) => {
listeners.add(listener);
return () => listeners.delete(listener);
};
const publish = () => {
listeners.forEach((listener) => listener());
};
const get = (key) => {
return state[key];
};
const set = (key, value) => {
if (!compare(state[key], value)) {
state[key] = value;
publish();
}
};
const update = (updates) => {
let hasChanges = false;
for (const key in updates) {
const value = updates[key];
if (value !== void 0 && !compare(state[key], value)) {
state[key] = value;
hasChanges = true;
}
}
if (hasChanges) publish();
};
const snapshot = () => ({ ...state });
return {
subscribe,
get,
set,
update,
snapshot
};
}
//#endregion
//#region src/shared/utils/timers.ts
const currentTime = () => performance.now();
var Timer = class {
onTick;
frameId = null;
pausedAtMs = null;
context;
constructor(onTick) {
this.onTick = onTick;
this.context = {
now: 0,
startMs: currentTime(),
deltaMs: 0
};
}
cancelFrame = () => {
if (this.frameId === null) return;
cancelAnimationFrame(this.frameId);
this.frameId = null;
};
setStartMs = (startMs) => {
this.context.startMs = startMs;
};
get elapsedMs() {
if (this.pausedAtMs !== null) return this.pausedAtMs - this.context.startMs;
return currentTime() - this.context.startMs;
}
start = () => {
if (this.frameId !== null) return;
const now = currentTime();
if (this.pausedAtMs !== null) {
this.context.startMs += now - this.pausedAtMs;
this.pausedAtMs = null;
} else this.context.startMs = now;
this.frameId = requestAnimationFrame(this.#tick);
};
pause = () => {
if (this.frameId === null) return;
this.cancelFrame();
this.pausedAtMs = currentTime();
};
stop = () => {
if (this.frameId === null) return;
this.cancelFrame();
this.pausedAtMs = null;
};
#tick = (now) => {
this.context.now = now;
this.context.deltaMs = now - this.context.startMs;
if (this.onTick(this.context) === false) {
this.stop();
return;
}
this.frameId = requestAnimationFrame(this.#tick);
};
};
function setRafInterval(fn, intervalMs) {
const timer = new Timer(({ now, deltaMs }) => {
if (deltaMs >= intervalMs) {
const startMs = intervalMs > 0 ? now - deltaMs % intervalMs : now;
timer.setStartMs(startMs);
fn({
startMs,
deltaMs
});
}
});
timer.start();
return () => timer.stop();
}
function setRafTimeout(fn, delayMs) {
const timer = new Timer(({ deltaMs }) => {
if (deltaMs >= delayMs) {
fn();
return false;
}
});
timer.start();
return () => timer.stop();
}
//#endregion
//#region src/shared/utils/warning.ts
function warn(...a) {
const m = a.length === 1 ? a[0] : a[1];
if ((a.length === 2 ? a[0] : true) && process.env.NODE_ENV !== "production") console.warn(m);
}
function invariant(...a) {
const m = a.length === 1 ? a[0] : a[1];
if ((a.length === 2 ? a[0] : true) && process.env.NODE_ENV !== "production") throw new Error(m);
}
function ensure(c, m) {
if (c == null) throw new Error(m());
}
function ensureProps(props, keys, scope) {
let missingKeys = [];
for (const key of keys) if (props[key] == null) missingKeys.push(key);
if (missingKeys.length > 0) throw new Error(`[ginxjs${scope ? ` > ${scope}` : ""}] missing required props: ${missingKeys.join(", ")}`);
}
//#endregion
export { tryCatch as $, isNaN as A, remove as At, snapValueToStep as B, getPercentValue as C, isEmpty as Ct, getValueSetterAtIndex as D, partition as Dt, getValueRanges as E, nextIndex as Et, nan as F, cast as G, toPx as H, roundToDpr as I, identity as J, debounce as K, roundToStepPrecision as L, isValueAtMin as M, toArray as Mt, isValueWithinRange as N, uniq as Nt, getValueTransformer as O, prev as Ot, mod as P, throttle as Q, roundValue as R, getNextStepValue as S, insertAt as St, getValuePercent as T, next as Tt, wrap as U, toFixedNumber as V, callAll as W, noop as X, match as Y, runIfFn as Z, decrementValue as _, diff as _t, Timer as a, isFunction as at, getMaxValueAtIndex as b, fromLength as bt, createStore as c, isObject as ct, json as d, isString as dt, uuid as et, omit as f, isEqual as ft, clampValue as g, clear as gt, clampPercent as h, chunk as ht, warn as i, isDev as it, isValueAtMax as j, removeAt as jt, incrementValue as k, prevIndex as kt, compact as l, isObjectLike as lt, splitProps as m, addOrRemove as mt, ensureProps as n, isArray as nt, setRafInterval as o, isNull as ot, pick as p, add as pt, hash as q, invariant as r, isBoolean as rt, setRafTimeout as s, isNumber as st, ensure as t, hasProp as tt, createSplitProps as u, isPlainObject as ut, getClosestValue as v, first as vt, getPreviousStepValue as w, last as wt, getMinValueAtIndex as x, has as xt, getClosestValueIndex as y, flatArray as yt, setValueAtIndex as z };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_utils = require("./utils-Bd5iPRBt.cjs");
exports.Timer = require_utils.Timer;
exports.add = require_utils.add;
exports.addOrRemove = require_utils.addOrRemove;
exports.callAll = require_utils.callAll;
exports.cast = require_utils.cast;
exports.chunk = require_utils.chunk;
exports.clampPercent = require_utils.clampPercent;
exports.clampValue = require_utils.clampValue;
exports.clear = require_utils.clear;
exports.compact = require_utils.compact;
exports.createSplitProps = require_utils.createSplitProps;
exports.createStore = require_utils.createStore;
exports.debounce = require_utils.debounce;
exports.decrementValue = require_utils.decrementValue;
exports.diff = require_utils.diff;
exports.ensure = require_utils.ensure;
exports.ensureProps = require_utils.ensureProps;
exports.first = require_utils.first;
exports.flatArray = require_utils.flatArray;
exports.fromLength = require_utils.fromLength;
exports.getClosestValue = require_utils.getClosestValue;
exports.getClosestValueIndex = require_utils.getClosestValueIndex;
exports.getMaxValueAtIndex = require_utils.getMaxValueAtIndex;
exports.getMinValueAtIndex = require_utils.getMinValueAtIndex;
exports.getNextStepValue = require_utils.getNextStepValue;
exports.getPercentValue = require_utils.getPercentValue;
exports.getPreviousStepValue = require_utils.getPreviousStepValue;
exports.getValuePercent = require_utils.getValuePercent;
exports.getValueRanges = require_utils.getValueRanges;
exports.getValueSetterAtIndex = require_utils.getValueSetterAtIndex;
exports.getValueTransformer = require_utils.getValueTransformer;
exports.has = require_utils.has;
exports.hasProp = require_utils.hasProp;
exports.hash = require_utils.hash;
exports.identity = require_utils.identity;
exports.incrementValue = require_utils.incrementValue;
exports.insertAt = require_utils.insertAt;
exports.invariant = require_utils.invariant;
exports.isArray = require_utils.isArray;
exports.isBoolean = require_utils.isBoolean;
exports.isDev = require_utils.isDev;
exports.isEmpty = require_utils.isEmpty;
exports.isEqual = require_utils.isEqual;
exports.isFunction = require_utils.isFunction;
exports.isNaN = require_utils.isNaN;
exports.isNull = require_utils.isNull;
exports.isNumber = require_utils.isNumber;
exports.isObject = require_utils.isObject;
exports.isObjectLike = require_utils.isObjectLike;
exports.isPlainObject = require_utils.isPlainObject;
exports.isString = require_utils.isString;
exports.isValueAtMax = require_utils.isValueAtMax;
exports.isValueAtMin = require_utils.isValueAtMin;
exports.isValueWithinRange = require_utils.isValueWithinRange;
exports.json = require_utils.json;
exports.last = require_utils.last;
exports.match = require_utils.match;
exports.mod = require_utils.mod;
exports.nan = require_utils.nan;
exports.next = require_utils.next;
exports.nextIndex = require_utils.nextIndex;
exports.noop = require_utils.noop;
exports.omit = require_utils.omit;
exports.partition = require_utils.partition;
exports.pick = require_utils.pick;
exports.prev = require_utils.prev;
exports.prevIndex = require_utils.prevIndex;
exports.remove = require_utils.remove;
exports.removeAt = require_utils.removeAt;
exports.roundToDpr = require_utils.roundToDpr;
exports.roundToStepPrecision = require_utils.roundToStepPrecision;
exports.roundValue = require_utils.roundValue;
exports.runIfFn = require_utils.runIfFn;
exports.setRafInterval = require_utils.setRafInterval;
exports.setRafTimeout = require_utils.setRafTimeout;
exports.setValueAtIndex = require_utils.setValueAtIndex;
exports.snapValueToStep = require_utils.snapValueToStep;
exports.splitProps = require_utils.splitProps;
exports.throttle = require_utils.throttle;
exports.toArray = require_utils.toArray;
exports.toFixedNumber = require_utils.toFixedNumber;
exports.toPx = require_utils.toPx;
exports.tryCatch = require_utils.tryCatch;
exports.uniq = require_utils.uniq;
exports.uuid = require_utils.uuid;
exports.warn = require_utils.warn;
exports.wrap = require_utils.wrap;
//#region src/shared/utils/array.d.ts
declare function toArray<T>(v: T | T[] | undefined | null): T[];
declare const fromLength: (length: number) => number[];
declare const first: <T>(v: T[]) => T | undefined;
declare const last: <T>(v: T[]) => T | undefined;
declare const isEmpty: <T>(v: T[]) => boolean;
declare const has: <T>(v: T[], t: T) => boolean;
declare const add: <T>(v: T[], ...items: T[]) => T[];
declare const remove: <T>(v: T[], ...items: T[]) => T[];
declare const removeAt: <T>(v: T[], i: number) => T[];
declare const insertAt: <T>(v: T[], i: number, ...items: T[]) => T[];
declare const uniq: <T>(v: T[]) => T[];
declare const diff: <T>(a: T[], b: T[]) => T[];
declare const addOrRemove: <T>(v: T[], item: T) => T[];
declare function clear<T>(v: T[]): T[];
type IndexOptions = {
step?: number | undefined;
loop?: boolean | undefined;
};
declare function nextIndex<T>(v: T[], idx: number, opts?: IndexOptions): number;
declare function next<T>(v: T[], idx: number, opts?: IndexOptions): T | undefined;
declare function prevIndex<T>(v: T[], idx: number, opts?: IndexOptions): number;
declare function prev<T>(v: T[], index: number, opts?: IndexOptions): T | undefined;
declare function chunk<T>(v: T[], size: number): T[][];
declare function flatArray<T>(arr: T[]): T[];
declare function partition<T>(arr: T[], fn: (value: T) => boolean): [T[], T[]];
//#endregion
//#region src/shared/utils/equal.d.ts
declare const isEqual: (a: any, b: any) => boolean;
//#endregion
//#region src/shared/utils/functions.d.ts
type VoidFunction = () => void;
type MaybeFunction<T> = T | (() => T);
type Nullable<T> = T | null | undefined;
declare const runIfFn: <T>(v: T | undefined, ...a: T extends ((...a: any[]) => void) ? Parameters<T> : never) => T extends ((...a: any[]) => void) ? NonNullable<ReturnType<T>> : NonNullable<T>;
declare const cast: <T>(v: unknown) => T;
declare const identity: (v: VoidFunction) => void;
declare const noop: () => void;
declare const callAll: <T extends (...a: any[]) => void>(...fns: (T | null | undefined)[]) => (...a: Parameters<T>) => void;
declare const uuid: () => string;
declare function match<V extends string | number = string, R = unknown>(key: V, record: Record<V, R | ((...args: any[]) => R)>, ...args: any[]): R;
declare const tryCatch: <R>(fn: () => R, fallback: () => R) => R;
declare function throttle<T extends (...args: any[]) => void>(fn: T, wait?: number): T;
declare function debounce<T extends (...args: any[]) => void>(fn: T, wait?: number): T;
declare const hash: (value: string) => string;
//#endregion
//#region src/shared/utils/guard.d.ts
type AnyFunction = (...args: any[]) => any;
declare const isDev: () => boolean;
declare const isArray: (v: any) => v is any[];
declare const isBoolean: (v: any) => v is boolean;
declare const isObjectLike: (v: any) => v is Record<string, any>;
declare const isObject: (v: any) => v is Record<string, any>;
declare const isNumber: (v: any) => v is number;
declare const isString: (v: any) => v is string;
declare const isFunction: (v: any) => v is AnyFunction;
declare const isNull: (v: any) => v is null | undefined;
declare const hasProp: <T extends string>(obj: any, prop: T) => obj is Record<T, any>;
declare const isPlainObject: (v: any) => boolean;
//#endregion
//#region src/shared/utils/number.d.ts
declare const isNaN: (v: number) => boolean;
declare const nan: (v: number) => number;
declare const mod: (v: number, m: number) => number;
declare const wrap: (v: number, vmax: number) => number;
declare const getMinValueAtIndex: (i: number, v: number[], vmin: number) => number;
declare const getMaxValueAtIndex: (i: number, v: number[], vmax: number) => number;
declare const isValueAtMax: (v: number, vmax: number) => boolean;
declare const isValueAtMin: (v: number, vmin: number) => boolean;
declare const isValueWithinRange: (v: number, vmin: number | null | undefined, vmax: number | null | undefined) => boolean;
declare const roundValue: (v: number, vmin: number, step: number) => number;
declare const clampValue: (v: number, vmin: number, vmax: number) => number;
declare const clampPercent: (v: number) => number;
declare const getValuePercent: (v: number, vmin: number, vmax: number) => number;
declare const getPercentValue: (p: number, vmin: number, vmax: number, step: number) => number;
declare const roundToStepPrecision: (v: number, step: number) => number;
declare const roundToDpr: (v: number, dpr: unknown) => number;
declare const snapValueToStep: (v: number, vmin: number | undefined, vmax: number | undefined, step: number) => number;
declare const setValueAtIndex: <T>(vs: T[], i: number, v: T) => T[];
interface RangeContext {
min: number;
max: number;
step: number;
values: number[];
}
declare function getValueSetterAtIndex(index: number, ctx: RangeContext): (value: number) => number[];
declare function getNextStepValue(index: number, ctx: RangeContext): number[];
declare function getPreviousStepValue(index: number, ctx: RangeContext): number[];
declare const getClosestValueIndex: (vs: number[], t: number) => number;
declare const getClosestValue: (vs: number[], t: number) => number;
declare const getValueRanges: (vs: number[], vmin: number, vmax: number, gap: number) => {
min: number;
max: number;
value: number;
}[];
declare const getValueTransformer: (va: number[], vb: number[]) => (v: number) => number;
declare const toFixedNumber: (v: number, d?: number, b?: number) => number;
declare const incrementValue: (v: number, s: number) => number;
declare const decrementValue: (v: number, s: number) => number;
declare const toPx: (v: number | string | undefined) => string | undefined;
//#endregion
//#region src/shared/utils/object.d.ts
declare function compact<T extends Record<string, unknown> | undefined>(obj: T): T;
declare const json: (v: any) => any;
declare function pick<T extends Record<string, any>, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>;
type Dict = Record<string | symbol, any>;
declare function splitProps<T extends Dict>(props: T, keys: (keyof T)[]): Dict[];
declare const createSplitProps: <T extends Dict>(keys: (keyof T)[]) => <Props extends T>(props: Props) => [T, Omit<Props, keyof T>];
declare function omit<T extends Record<string, any>>(obj: T, keys: string[]): Omit<T, string | number>;
//#endregion
//#region src/shared/utils/store.d.ts
type StoreListener = VoidFunction;
type StoreCompareFn<T> = (a: T, b: T) => boolean;
declare function createStore<T extends Record<string, any>>(initialState: T, compare?: StoreCompareFn<T>): Store<T>;
interface Store<T extends Record<string, any>> {
subscribe: (listener: StoreListener) => () => void;
get: <K extends keyof T>(key: K) => T[K];
set: <K extends keyof T>(key: K, value: T[K]) => void;
update: (updates: Partial<T>) => void;
snapshot: () => T;
}
//#endregion
//#region src/shared/utils/timers.d.ts
interface TimerBaseContext {
startMs: number;
deltaMs: number;
}
interface TimerContext extends TimerBaseContext {
now: number;
}
type TimerContextFn = (ctx: TimerContext) => boolean | void;
declare class Timer {
#private;
private readonly onTick;
private frameId;
private pausedAtMs;
private context;
constructor(onTick: TimerContextFn);
private cancelFrame;
setStartMs: (startMs: number) => void;
get elapsedMs(): number;
start: () => void;
pause: () => void;
stop: () => void;
}
declare function setRafInterval(fn: (ctx: TimerBaseContext) => void, intervalMs: number): () => void;
declare function setRafTimeout(fn: () => void, delayMs: number): () => void;
//#endregion
//#region src/shared/utils/warning.d.ts
declare function warn(m: string): void;
declare function warn(c: boolean, m: string): void;
declare function invariant(m: string): void;
declare function invariant(c: boolean, m: string): void;
declare function ensure<T>(c: T | null | undefined, m: () => string): asserts c is T;
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
declare function ensureProps<T, K extends keyof T>(props: T, keys: K[], scope?: string): asserts props is T & RequiredBy<T, K>;
//#endregion
export { IndexOptions, MaybeFunction, Nullable, Store, StoreCompareFn, StoreListener, Timer, TimerBaseContext, TimerContextFn, VoidFunction, add, addOrRemove, callAll, cast, chunk, clampPercent, clampValue, clear, compact, createSplitProps, createStore, debounce, decrementValue, diff, ensure, ensureProps, first, flatArray, fromLength, getClosestValue, getClosestValueIndex, getMaxValueAtIndex, getMinValueAtIndex, getNextStepValue, getPercentValue, getPreviousStepValue, getValuePercent, getValueRanges, getValueSetterAtIndex, getValueTransformer, has, hasProp, hash, identity, incrementValue, insertAt, invariant, isArray, isBoolean, isDev, isEmpty, isEqual, isFunction, isNaN, isNull, isNumber, isObject, isObjectLike, isPlainObject, isString, isValueAtMax, isValueAtMin, isValueWithinRange, json, last, match, mod, nan, next, nextIndex, noop, omit, partition, pick, prev, prevIndex, remove, removeAt, roundToDpr, roundToStepPrecision, roundValue, runIfFn, setRafInterval, setRafTimeout, setValueAtIndex, snapValueToStep, splitProps, throttle, toArray, toFixedNumber, toPx, tryCatch, uniq, uuid, warn, wrap };
//#region src/shared/utils/array.d.ts
declare function toArray<T>(v: T | T[] | undefined | null): T[];
declare const fromLength: (length: number) => number[];
declare const first: <T>(v: T[]) => T | undefined;
declare const last: <T>(v: T[]) => T | undefined;
declare const isEmpty: <T>(v: T[]) => boolean;
declare const has: <T>(v: T[], t: T) => boolean;
declare const add: <T>(v: T[], ...items: T[]) => T[];
declare const remove: <T>(v: T[], ...items: T[]) => T[];
declare const removeAt: <T>(v: T[], i: number) => T[];
declare const insertAt: <T>(v: T[], i: number, ...items: T[]) => T[];
declare const uniq: <T>(v: T[]) => T[];
declare const diff: <T>(a: T[], b: T[]) => T[];
declare const addOrRemove: <T>(v: T[], item: T) => T[];
declare function clear<T>(v: T[]): T[];
type IndexOptions = {
step?: number | undefined;
loop?: boolean | undefined;
};
declare function nextIndex<T>(v: T[], idx: number, opts?: IndexOptions): number;
declare function next<T>(v: T[], idx: number, opts?: IndexOptions): T | undefined;
declare function prevIndex<T>(v: T[], idx: number, opts?: IndexOptions): number;
declare function prev<T>(v: T[], index: number, opts?: IndexOptions): T | undefined;
declare function chunk<T>(v: T[], size: number): T[][];
declare function flatArray<T>(arr: T[]): T[];
declare function partition<T>(arr: T[], fn: (value: T) => boolean): [T[], T[]];
//#endregion
//#region src/shared/utils/equal.d.ts
declare const isEqual: (a: any, b: any) => boolean;
//#endregion
//#region src/shared/utils/functions.d.ts
type VoidFunction = () => void;
type MaybeFunction<T> = T | (() => T);
type Nullable<T> = T | null | undefined;
declare const runIfFn: <T>(v: T | undefined, ...a: T extends ((...a: any[]) => void) ? Parameters<T> : never) => T extends ((...a: any[]) => void) ? NonNullable<ReturnType<T>> : NonNullable<T>;
declare const cast: <T>(v: unknown) => T;
declare const identity: (v: VoidFunction) => void;
declare const noop: () => void;
declare const callAll: <T extends (...a: any[]) => void>(...fns: (T | null | undefined)[]) => (...a: Parameters<T>) => void;
declare const uuid: () => string;
declare function match<V extends string | number = string, R = unknown>(key: V, record: Record<V, R | ((...args: any[]) => R)>, ...args: any[]): R;
declare const tryCatch: <R>(fn: () => R, fallback: () => R) => R;
declare function throttle<T extends (...args: any[]) => void>(fn: T, wait?: number): T;
declare function debounce<T extends (...args: any[]) => void>(fn: T, wait?: number): T;
declare const hash: (value: string) => string;
//#endregion
//#region src/shared/utils/guard.d.ts
type AnyFunction = (...args: any[]) => any;
declare const isDev: () => boolean;
declare const isArray: (v: any) => v is any[];
declare const isBoolean: (v: any) => v is boolean;
declare const isObjectLike: (v: any) => v is Record<string, any>;
declare const isObject: (v: any) => v is Record<string, any>;
declare const isNumber: (v: any) => v is number;
declare const isString: (v: any) => v is string;
declare const isFunction: (v: any) => v is AnyFunction;
declare const isNull: (v: any) => v is null | undefined;
declare const hasProp: <T extends string>(obj: any, prop: T) => obj is Record<T, any>;
declare const isPlainObject: (v: any) => boolean;
//#endregion
//#region src/shared/utils/number.d.ts
declare const isNaN: (v: number) => boolean;
declare const nan: (v: number) => number;
declare const mod: (v: number, m: number) => number;
declare const wrap: (v: number, vmax: number) => number;
declare const getMinValueAtIndex: (i: number, v: number[], vmin: number) => number;
declare const getMaxValueAtIndex: (i: number, v: number[], vmax: number) => number;
declare const isValueAtMax: (v: number, vmax: number) => boolean;
declare const isValueAtMin: (v: number, vmin: number) => boolean;
declare const isValueWithinRange: (v: number, vmin: number | null | undefined, vmax: number | null | undefined) => boolean;
declare const roundValue: (v: number, vmin: number, step: number) => number;
declare const clampValue: (v: number, vmin: number, vmax: number) => number;
declare const clampPercent: (v: number) => number;
declare const getValuePercent: (v: number, vmin: number, vmax: number) => number;
declare const getPercentValue: (p: number, vmin: number, vmax: number, step: number) => number;
declare const roundToStepPrecision: (v: number, step: number) => number;
declare const roundToDpr: (v: number, dpr: unknown) => number;
declare const snapValueToStep: (v: number, vmin: number | undefined, vmax: number | undefined, step: number) => number;
declare const setValueAtIndex: <T>(vs: T[], i: number, v: T) => T[];
interface RangeContext {
min: number;
max: number;
step: number;
values: number[];
}
declare function getValueSetterAtIndex(index: number, ctx: RangeContext): (value: number) => number[];
declare function getNextStepValue(index: number, ctx: RangeContext): number[];
declare function getPreviousStepValue(index: number, ctx: RangeContext): number[];
declare const getClosestValueIndex: (vs: number[], t: number) => number;
declare const getClosestValue: (vs: number[], t: number) => number;
declare const getValueRanges: (vs: number[], vmin: number, vmax: number, gap: number) => {
min: number;
max: number;
value: number;
}[];
declare const getValueTransformer: (va: number[], vb: number[]) => (v: number) => number;
declare const toFixedNumber: (v: number, d?: number, b?: number) => number;
declare const incrementValue: (v: number, s: number) => number;
declare const decrementValue: (v: number, s: number) => number;
declare const toPx: (v: number | string | undefined) => string | undefined;
//#endregion
//#region src/shared/utils/object.d.ts
declare function compact<T extends Record<string, unknown> | undefined>(obj: T): T;
declare const json: (v: any) => any;
declare function pick<T extends Record<string, any>, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>;
type Dict = Record<string | symbol, any>;
declare function splitProps<T extends Dict>(props: T, keys: (keyof T)[]): Dict[];
declare const createSplitProps: <T extends Dict>(keys: (keyof T)[]) => <Props extends T>(props: Props) => [T, Omit<Props, keyof T>];
declare function omit<T extends Record<string, any>>(obj: T, keys: string[]): Omit<T, string | number>;
//#endregion
//#region src/shared/utils/store.d.ts
type StoreListener = VoidFunction;
type StoreCompareFn<T> = (a: T, b: T) => boolean;
declare function createStore<T extends Record<string, any>>(initialState: T, compare?: StoreCompareFn<T>): Store<T>;
interface Store<T extends Record<string, any>> {
subscribe: (listener: StoreListener) => () => void;
get: <K extends keyof T>(key: K) => T[K];
set: <K extends keyof T>(key: K, value: T[K]) => void;
update: (updates: Partial<T>) => void;
snapshot: () => T;
}
//#endregion
//#region src/shared/utils/timers.d.ts
interface TimerBaseContext {
startMs: number;
deltaMs: number;
}
interface TimerContext extends TimerBaseContext {
now: number;
}
type TimerContextFn = (ctx: TimerContext) => boolean | void;
declare class Timer {
#private;
private readonly onTick;
private frameId;
private pausedAtMs;
private context;
constructor(onTick: TimerContextFn);
private cancelFrame;
setStartMs: (startMs: number) => void;
get elapsedMs(): number;
start: () => void;
pause: () => void;
stop: () => void;
}
declare function setRafInterval(fn: (ctx: TimerBaseContext) => void, intervalMs: number): () => void;
declare function setRafTimeout(fn: () => void, delayMs: number): () => void;
//#endregion
//#region src/shared/utils/warning.d.ts
declare function warn(m: string): void;
declare function warn(c: boolean, m: string): void;
declare function invariant(m: string): void;
declare function invariant(c: boolean, m: string): void;
declare function ensure<T>(c: T | null | undefined, m: () => string): asserts c is T;
type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
declare function ensureProps<T, K extends keyof T>(props: T, keys: K[], scope?: string): asserts props is T & RequiredBy<T, K>;
//#endregion
export { IndexOptions, MaybeFunction, Nullable, Store, StoreCompareFn, StoreListener, Timer, TimerBaseContext, TimerContextFn, VoidFunction, add, addOrRemove, callAll, cast, chunk, clampPercent, clampValue, clear, compact, createSplitProps, createStore, debounce, decrementValue, diff, ensure, ensureProps, first, flatArray, fromLength, getClosestValue, getClosestValueIndex, getMaxValueAtIndex, getMinValueAtIndex, getNextStepValue, getPercentValue, getPreviousStepValue, getValuePercent, getValueRanges, getValueSetterAtIndex, getValueTransformer, has, hasProp, hash, identity, incrementValue, insertAt, invariant, isArray, isBoolean, isDev, isEmpty, isEqual, isFunction, isNaN, isNull, isNumber, isObject, isObjectLike, isPlainObject, isString, isValueAtMax, isValueAtMin, isValueWithinRange, json, last, match, mod, nan, next, nextIndex, noop, omit, partition, pick, prev, prevIndex, remove, removeAt, roundToDpr, roundToStepPrecision, roundValue, runIfFn, setRafInterval, setRafTimeout, setValueAtIndex, snapValueToStep, splitProps, throttle, toArray, toFixedNumber, toPx, tryCatch, uniq, uuid, warn, wrap };
import { $ as tryCatch, A as isNaN, At as remove, B as snapValueToStep, C as getPercentValue, Ct as isEmpty, D as getValueSetterAtIndex, Dt as partition, E as getValueRanges, Et as nextIndex, F as nan, G as cast, H as toPx, I as roundToDpr, J as identity, K as debounce, L as roundToStepPrecision, M as isValueAtMin, Mt as toArray, N as isValueWithinRange, Nt as uniq, O as getValueTransformer, Ot as prev, P as mod, Q as throttle, R as roundValue, S as getNextStepValue, St as insertAt, T as getValuePercent, Tt as next, U as wrap, V as toFixedNumber, W as callAll, X as noop, Y as match, Z as runIfFn, _ as decrementValue, _t as diff, a as Timer, at as isFunction, b as getMaxValueAtIndex, bt as fromLength, c as createStore, ct as isObject, d as json, dt as isString, et as uuid, f as omit, ft as isEqual, g as clampValue, gt as clear, h as clampPercent, ht as chunk, i as warn, it as isDev, j as isValueAtMax, jt as removeAt, k as incrementValue, kt as prevIndex, l as compact, lt as isObjectLike, m as splitProps, mt as addOrRemove, n as ensureProps, nt as isArray, o as setRafInterval, ot as isNull, p as pick, pt as add, q as hash, r as invariant, rt as isBoolean, s as setRafTimeout, st as isNumber, t as ensure, tt as hasProp, u as createSplitProps, ut as isPlainObject, v as getClosestValue, vt as first, w as getPreviousStepValue, wt as last, x as getMinValueAtIndex, xt as has, y as getClosestValueIndex, yt as flatArray, z as setValueAtIndex } from "./utils-CeIB7ETu.mjs";
export { Timer, add, addOrRemove, callAll, cast, chunk, clampPercent, clampValue, clear, compact, createSplitProps, createStore, debounce, decrementValue, diff, ensure, ensureProps, first, flatArray, fromLength, getClosestValue, getClosestValueIndex, getMaxValueAtIndex, getMinValueAtIndex, getNextStepValue, getPercentValue, getPreviousStepValue, getValuePercent, getValueRanges, getValueSetterAtIndex, getValueTransformer, has, hasProp, hash, identity, incrementValue, insertAt, invariant, isArray, isBoolean, isDev, isEmpty, isEqual, isFunction, isNaN, isNull, isNumber, isObject, isObjectLike, isPlainObject, isString, isValueAtMax, isValueAtMin, isValueWithinRange, json, last, match, mod, nan, next, nextIndex, noop, omit, partition, pick, prev, prevIndex, remove, removeAt, roundToDpr, roundToStepPrecision, roundValue, runIfFn, setRafInterval, setRafTimeout, setValueAtIndex, snapValueToStep, splitProps, throttle, toArray, toFixedNumber, toPx, tryCatch, uniq, uuid, warn, wrap };
+60
-2
{
"name": "@ginxjs/core",
"version": "0.0.1",
"version": "0.0.4",
"description": "A set of core primitives for building user interfaces.",
"homepage": "https://github.com/ginxjs/primitives#readme",
"bugs": {
"url": "https://github.com/ginxjs/primitives/issues"
},
"license": "MIT",
"author": "ginxjs <npm@ginxjs.com>",
"repository": {
"type": "git",
"url": "git+https://github.com/ginxjs/primitives.git"
},
"files": [
"dist"
],
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.cts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./collection": {
"import": "./dist/collection.mjs",
"require": "./dist/collection.cjs"
},
"./date-utils": {
"import": "./dist/date-utils.mjs",
"require": "./dist/date-utils.cjs"
},
"./highlight-word": {
"import": "./dist/highlight-word.mjs",
"require": "./dist/highlight-word.cjs"
},
"./stringify-state": {
"import": "./dist/stringify-state.mjs",
"require": "./dist/stringify-state.cjs"
},
"./utils": {
"import": "./dist/utils.mjs",
"require": "./dist/utils.cjs"
},
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@internationalized/date": "^3.12.1",
"json-format-highlight": "^1.0.4"
},
"peerDependencies": {
"@internationalized/date": ">=3.0.0"
},
"scripts": {
"build": "tsdown",
"typecheck": "tsc --noEmit",
"lint": "oxlint",
"format": "oxfmt"
}
}
}