UNPKG

@runstack/ui

Version:

React UI components library for runstack

211 lines (200 loc) 8.91 kB
import * as react_jsx_runtime from 'react/jsx-runtime'; import * as React from 'react'; import { ReactNode } from 'react'; import { ClassValue } from 'clsx'; type DraggableItem = { sync_id: string; rank: bigint; title: string; parent_id?: string | null | undefined; }; /** * Gets all direct children of a specific item. * Returns children sorted by rank in ascending order. */ declare function getChildren<Item extends DraggableItem>(id: string, items: Item[]): Item[]; /** * Gets all siblings of a specific item (items with the same parent). * Returns siblings sorted by rank in ascending order. */ declare function getSiblings<Item extends DraggableItem>(id: string | "root", items: Item[]): Item[]; /** * Gets the previous sibling of an item. * Returns undefined if the item is the first sibling. */ declare function getPreviousSibling(id: string, items: DraggableItem[]): DraggableItem | undefined; /** * Gets all descendants (children, grandchildren, etc.) of a specific item. * Returns all descendants in depth-first order. */ declare function getAllDescendants(id: string, items: DraggableItem[]): DraggableItem[]; /** * Gets all root items (items with no parent). * Returns all root items in depth-first order. */ declare function getRootItems<Item extends DraggableItem>(items: Item[]): Item[]; /** * Calculates the updates needed to increase an item's indentation level. * Makes the item a child of its previous sibling and recalculates ranks for all affected items. * * @param item - The item to increase indentation for * @param items - Array of all items in the tree * @returns Array of items that need to be updated with new ranks and parent relationships * * @example * ```typescript * // Before: [A, B, C] -> After: [A, B -> C] * const updates = calculateIndentIncrease(itemC, allItems); * // Returns updates for itemC with new parent_id = itemB._id * ``` * * Algorithm: * 1. Finds the previous sibling of the target item * 2. If no previous sibling exists, returns empty array (can't indent) * 3. Makes the target item a child of the previous sibling * 4. Recalculates ranks for all children of the previous sibling (including new child) * 5. Uses ENTRY_GAP (100,000) spacing between ranks for efficient insertion */ declare function calculateIndentIncrease<Item extends DraggableItem>(item: Item, items?: Item[]): Item[]; /** * Calculates the updates needed to decrease an item's indentation level. * Promotes the item to be a sibling of its current parent and recalculates ranks for all affected items. * * @param item - The item to decrease indentation for * @param items - Array of all items in the tree * @returns Array of items that need to be updated with new ranks and parent relationships * * @example * ```typescript * // Before: [A -> B -> C] -> After: [A -> B, C] * const updates = calculateIndentDecrease(itemC, allItems); * // Returns updates for itemC with parent_id = itemA._id (same as itemB's parent) * ``` * * Algorithm: * 1. Finds the parent of the target item * 2. If no parent exists, returns empty array (already at root level) * 3. Promotes the item to be a sibling of its current parent * 4. Places the item immediately after its parent in the sibling order * 5. Recalculates ranks for all siblings at the parent's level * 6. Uses ENTRY_GAP (100,000) spacing between ranks for efficient insertion */ declare function calculateIndentDecrease<Item extends DraggableItem>(item: Item, items?: Item[]): Item[]; /** * Flattens a tree structure into a pre-order traversal mapping. * Used for calculating animation delays and determining render order. * * @param tree - Array of all items in the tree * @returns Record mapping item IDs to their flat index position * * @example * ```typescript * // Tree structure: A -> [B, C], D -> [E] * const flattened = flattenTreePreorder(items); * // Returns: { A: 0, B: 1, C: 2, D: 3, E: 4 } * ``` * * Algorithm: * 1. Sorts all items by rank to ensure consistent ordering * 2. Performs pre-order traversal (parent first, then children) * 3. Assigns incremental indices to each item in traversal order * 4. Returns mapping of item ID to flat index for animation calculations */ declare function flattenTreePreorder<Item extends DraggableItem>(tree: Item[]): Record<string, number>; /** * Gap between consecutive item ranks in the tree structure. * * This large gap (100,000) allows for efficient insertion of new items * between existing ones without requiring rank recalculation of many items. * * Example rank sequence: 0, 100000, 200000, 300000... * To insert between ranks 100000 and 200000, we can use 150000. */ declare const ENTRY_GAP = 100000; type DraggableListState = { index: number; level: number; focusItemId: string; updateFocusItemId: (value: string) => void; }; type AddEntryPayload<Item extends DraggableItem> = { rank: bigint; parent_id: Item["parent_id"] | null; title: string; }; type AddEntryFn<Item extends DraggableItem> = (payload: AddEntryPayload<Item>, item: Item, context: DraggableListContextType<Item>) => void; type DraggableListContextType<Item extends DraggableItem = DraggableItem> = { items: Item[]; renderProps: (item: Item, state: DraggableListState) => React.ReactNode; currentItem?: Item; hasAnimated: boolean; updateHasAnimated: (value: boolean) => void; updateTitle: (id: Item["sync_id"], title: string) => void; updateTree: (updates: DraggableItem[]) => void; onAddEntry: AddEntryFn<Item>; } & DraggableListState; declare const useDraggableListContext: <Item extends DraggableItem>() => DraggableListContextType<Item>; type DraggableListProviderProps<Item extends DraggableItem> = { children: (item: Item, state: DraggableListState, context: DraggableListContextType<Item>) => React.ReactNode; data: Item[]; onDrop?: (updates: Item[]) => void; onTitleChange?: (id: Item["sync_id"], title: string) => void; onTreeChange?: (updates: Item[]) => void; /** * onAddEntry is called with the payload and the current item being added. * This allows for more granular control over the payload and item being added. * @param payload - The payload object passed to the mutation * @param item - The current item the addEntry was triggered on * */ onAddEntry?: AddEntryFn<Item>; _animationKey?: string; }; declare const DraggableListProvider: <Item extends DraggableItem>(props: DraggableListProviderProps<Item>) => react_jsx_runtime.JSX.Element; type DraggableListMainProps = { children: React.ReactNode; className?: string; }; declare const DraggableListMain: (props: DraggableListMainProps) => react_jsx_runtime.JSX.Element; type DraggableListItemProps = { children: React.ReactNode; className?: string; }; declare const DraggableListItem: (props: DraggableListItemProps) => react_jsx_runtime.JSX.Element; type DraggableListItemStartProps = { children: React.ReactNode; className?: string; }; declare const DraggableListItemStart: (props: DraggableListItemStartProps) => react_jsx_runtime.JSX.Element; type DraggableListItemContentProps = { children: React.ReactNode; className?: string; }; declare const DraggableListItemContent: (props: DraggableListItemContentProps) => react_jsx_runtime.JSX.Element; type DraggableListItemBottomProps = { children: React.ReactNode; className?: string; }; declare const DraggableListItemBottom: (props: DraggableListItemBottomProps) => react_jsx_runtime.JSX.Element; type DraggableListItemEndProps = { children: React.ReactNode; className?: string; }; declare const DraggableListItemEnd: (props: DraggableListItemEndProps) => react_jsx_runtime.JSX.Element; type DragHandleProps = { children: React.ReactNode; }; declare const DragHandle: (props: DragHandleProps) => react_jsx_runtime.JSX.Element; type DraggableListEditableTextProps = { className?: string; placeholder?: string; placeholderBehaviour?: "showOnHover" | "alwaysShow"; }; declare const DraggableListEditableText: (props: DraggableListEditableTextProps) => react_jsx_runtime.JSX.Element; interface ButtonProps { children: ReactNode; className?: string; appName: string; } declare const Button: ({ children, className, appName }: ButtonProps) => react_jsx_runtime.JSX.Element; declare function cn(...inputs: ClassValue[]): string; export { type AddEntryPayload, Button, DragHandle, type DraggableItem, type DraggableListContextType, DraggableListEditableText, DraggableListItem, DraggableListItemBottom, DraggableListItemContent, DraggableListItemEnd, DraggableListItemStart, DraggableListMain, DraggableListProvider, ENTRY_GAP, calculateIndentDecrease, calculateIndentIncrease, cn, flattenTreePreorder, getAllDescendants, getChildren, getPreviousSibling, getRootItems, getSiblings, useDraggableListContext };