@exegia/corpora-ui 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/components/blocks/auth/__tests__/auth-state-atom.test.d.ts +1 -0
- package/dist-lib/components/blocks/auth/auth-flow-atom.d.ts +77 -0
- package/dist-lib/components/blocks/auth/auth-session-atom.d.ts +28 -0
- package/dist-lib/components/blocks/auth/auth-state-type.d.ts +71 -0
- package/dist-lib/components/blocks/auth/auth-state.d.ts +9 -0
- package/dist-lib/components/blocks/auth/use-auth-state.d.ts +52 -0
- package/dist-lib/components/blocks/nav/sidebar/__tests__/ai-sidebar-atom.test.d.ts +1 -0
- package/dist-lib/components/blocks/nav/sidebar/__tests__/use-ai-sidebar.test.d.ts +1 -0
- package/dist-lib/components/blocks/nav/sidebar/ai-sidebar-atom.d.ts +217 -0
- package/dist-lib/components/blocks/nav/sidebar/ai-sidebar.d.ts +11 -2
- package/dist-lib/components/blocks/nav/sidebar/index.d.ts +3 -1
- package/dist-lib/components/blocks/nav/sidebar/sidebar-context.d.ts +3 -0
- package/dist-lib/components/blocks/nav/sidebar/sidebar-row.d.ts +3 -1
- package/dist-lib/components/blocks/nav/sidebar/type.d.ts +191 -29
- package/dist-lib/components/blocks/nav/sidebar/use-ai-sidebar-state.d.ts +29 -0
- package/dist-lib/components/blocks/nav/sidebar/use-ai-sidebar.d.ts +27 -31
- package/dist-lib/components/blocks/nav/sidebar/utils.d.ts +6 -1
- package/dist-lib/components/blocks/profile/index.d.ts +7 -0
- package/dist-lib/components/blocks/profile/profile-card-atom.d.ts +68 -0
- package/dist-lib/components/blocks/profile/profile-card-block.d.ts +28 -39
- package/dist-lib/components/blocks/profile/type.d.ts +80 -0
- package/dist-lib/components/blocks/profile/use-profile-card-state.d.ts +24 -0
- package/dist-lib/components/blocks/profile/use-profile-card.d.ts +34 -0
- package/dist-lib/components/blocks/scaffold/constants.d.ts +5 -0
- package/dist-lib/components/blocks/scaffold/scaffold-canvas.d.ts +2 -0
- package/dist-lib/components/blocks/scaffold/scaffold-panel.d.ts +1 -1
- package/dist-lib/components/blocks/scaffold/scaffold-tab.d.ts +6 -1
- package/dist-lib/components/blocks/scaffold/type.d.ts +28 -0
- package/dist-lib/components/blocks/scaffold/use-panel-visibility.d.ts +19 -0
- package/dist-lib/components/blocks/scaffold/utils.d.ts +6 -0
- package/dist-lib/components/blocks/shell/__tests__/shell-fit-atom.test.d.ts +1 -0
- package/dist-lib/components/blocks/shell/__tests__/shell-metrics.test.d.ts +1 -0
- package/dist-lib/components/blocks/shell/animated-panel-provider.d.ts +1 -1
- package/dist-lib/components/blocks/shell/animated-panel.d.ts +1 -1
- package/dist-lib/components/blocks/shell/index.d.ts +4 -0
- package/dist-lib/components/blocks/shell/shell-fit-atom.d.ts +68 -0
- package/dist-lib/components/blocks/shell/shell-metrics.d.ts +54 -0
- package/dist-lib/components/blocks/shell/type.d.ts +115 -3
- package/dist-lib/components/blocks/shell/use-shell-fit-state.d.ts +25 -0
- package/dist-lib/components/blocks/shell/use-shell-fit.d.ts +14 -0
- package/dist-lib/components/blocks/shell/use-shell-panels.d.ts +12 -1
- package/dist-lib/components/blocks/shell/utils.d.ts +32 -0
- package/dist-lib/components/composed/tree/__tests__/tree-atom.test.d.ts +1 -0
- package/dist-lib/components/composed/tree/__tests__/tree.test.d.ts +1 -0
- package/dist-lib/components/composed/tree/__tests__/use-tree.test.d.ts +1 -0
- package/dist-lib/components/composed/tree/constants.d.ts +35 -0
- package/dist-lib/components/composed/tree/index.d.ts +6 -0
- package/dist-lib/components/composed/tree/tree-atom.d.ts +160 -0
- package/dist-lib/components/composed/tree/tree-context.d.ts +4 -0
- package/dist-lib/components/composed/tree/tree-node.d.ts +12 -0
- package/dist-lib/components/composed/tree/tree.d.ts +19 -0
- package/dist-lib/components/composed/tree/type.d.ts +290 -0
- package/dist-lib/components/composed/tree/use-tree-dnd.d.ts +18 -0
- package/dist-lib/components/composed/tree/use-tree-state.d.ts +25 -0
- package/dist-lib/components/composed/tree/use-tree.d.ts +24 -0
- package/dist-lib/components/composed/tree/utils.d.ts +28 -0
- package/dist-lib/components/composed/user-avatar.d.ts +5 -28
- package/dist-lib/components/user-avatar/__tests__/user-avatar.test.d.ts +1 -0
- package/dist-lib/components/user-avatar/audio-wave.d.ts +2 -0
- package/dist-lib/components/user-avatar/component.d.ts +3 -0
- package/dist-lib/components/user-avatar/fallback.d.ts +5 -0
- package/dist-lib/components/user-avatar/index.d.ts +18 -0
- package/dist-lib/components/user-avatar/presence-badge.d.ts +16 -0
- package/dist-lib/components/user-avatar/type.d.ts +71 -0
- package/dist-lib/components/user-avatar/use-user-avatar-state.d.ts +26 -0
- package/dist-lib/components/user-avatar/use-user-avatar.d.ts +32 -0
- package/dist-lib/components/user-avatar/user-avatar-atom.d.ts +55 -0
- package/dist-lib/components/user-avatar/utils.d.ts +2 -0
- package/dist-lib/index.d.ts +6 -2
- package/dist-lib/index.js +3576 -1366
- package/dist-lib/index.js.map +1 -1
- package/dist-lib/state/exegia-provider.d.ts +51 -0
- package/dist-lib/state/index.d.ts +4 -0
- package/dist-lib/state/store.d.ts +17 -0
- package/package.json +16 -12
- package/src/components/beste/piece/browser-frame.tsx +9 -6
- package/src/components/blocks/auth/__tests__/auth-state-atom.test.tsx +247 -0
- package/src/components/blocks/auth/auth-flow-atom.ts +238 -0
- package/src/components/blocks/auth/auth-session-atom.ts +82 -0
- package/src/components/blocks/auth/auth-state-type.ts +97 -0
- package/src/components/blocks/auth/auth-state.ts +52 -0
- package/src/components/blocks/auth/use-auth-state.ts +127 -0
- package/src/components/blocks/nav/sidebar/__tests__/ai-sidebar-atom.test.tsx +325 -0
- package/src/components/blocks/nav/sidebar/__tests__/use-ai-sidebar.test.tsx +310 -0
- package/src/components/blocks/nav/sidebar/ai-sidebar-atom.ts +698 -0
- package/src/components/blocks/nav/sidebar/ai-sidebar.tsx +112 -76
- package/src/components/blocks/nav/sidebar/index.ts +53 -1
- package/src/components/blocks/nav/sidebar/sidebar-context.ts +15 -0
- package/src/components/blocks/nav/sidebar/sidebar-row.tsx +119 -50
- package/src/components/blocks/nav/sidebar/type.ts +228 -29
- package/src/components/blocks/nav/sidebar/use-ai-sidebar-state.ts +123 -0
- package/src/components/blocks/nav/sidebar/use-ai-sidebar.ts +455 -225
- package/src/components/blocks/nav/sidebar/utils.ts +29 -1
- package/src/components/blocks/profile/__tests__/profile-card-block.test.tsx +194 -0
- package/src/components/blocks/profile/index.ts +28 -0
- package/src/components/blocks/profile/profile-card-atom.ts +247 -0
- package/src/components/blocks/profile/profile-card-block.tsx +153 -74
- package/src/components/blocks/profile/type.ts +95 -0
- package/src/components/blocks/profile/use-profile-card-state.ts +67 -0
- package/src/components/blocks/profile/use-profile-card.ts +126 -0
- package/src/components/blocks/scaffold/__tests__/scaffold.test.tsx +160 -1
- package/src/components/blocks/scaffold/constants.ts +7 -0
- package/src/components/blocks/scaffold/panel-menu-button.tsx +3 -0
- package/src/components/blocks/scaffold/scaffold-canvas.tsx +48 -5
- package/src/components/blocks/scaffold/scaffold-inspector.tsx +3 -2
- package/src/components/blocks/scaffold/scaffold-main.tsx +1 -1
- package/src/components/blocks/scaffold/scaffold-panel.tsx +41 -5
- package/src/components/blocks/scaffold/scaffold-root.tsx +18 -3
- package/src/components/blocks/scaffold/scaffold-sidebar.tsx +1 -1
- package/src/components/blocks/scaffold/scaffold-tab.tsx +45 -7
- package/src/components/blocks/scaffold/type.ts +28 -0
- package/src/components/blocks/scaffold/use-panel-visibility.ts +180 -0
- package/src/components/blocks/scaffold/utils.ts +19 -0
- package/src/components/blocks/shell/__tests__/shell-fit-atom.test.tsx +360 -0
- package/src/components/blocks/shell/__tests__/shell-layout.test.tsx +192 -3
- package/src/components/blocks/shell/__tests__/shell-metrics.test.ts +108 -0
- package/src/components/blocks/shell/animated-panel-inset.tsx +5 -1
- package/src/components/blocks/shell/animated-panel-provider.tsx +77 -11
- package/src/components/blocks/shell/animated-panel-trigger.tsx +4 -0
- package/src/components/blocks/shell/animated-panel.tsx +126 -29
- package/src/components/blocks/shell/index.ts +18 -0
- package/src/components/blocks/shell/shell-fit-atom.ts +243 -0
- package/src/components/blocks/shell/shell-layout.tsx +55 -53
- package/src/components/blocks/shell/shell-metrics.ts +79 -0
- package/src/components/blocks/shell/type.ts +130 -3
- package/src/components/blocks/shell/use-shell-fit-state.ts +49 -0
- package/src/components/blocks/shell/use-shell-fit.ts +135 -0
- package/src/components/blocks/shell/use-shell-panels.ts +57 -4
- package/src/components/blocks/shell/utils.ts +44 -4
- package/src/components/composed/tree/CLAUDE.md +132 -0
- package/src/components/composed/tree/__tests__/tree-atom.test.tsx +217 -0
- package/src/components/composed/tree/__tests__/tree.test.tsx +525 -0
- package/src/components/composed/tree/__tests__/use-tree.test.tsx +333 -0
- package/src/components/composed/tree/constants.ts +60 -0
- package/src/components/composed/tree/index.ts +51 -0
- package/src/components/composed/tree/tree-atom.ts +590 -0
- package/src/components/composed/tree/tree-context.ts +13 -0
- package/src/components/composed/tree/tree-node.tsx +490 -0
- package/src/components/composed/tree/tree.tsx +286 -0
- package/src/components/composed/tree/type.ts +322 -0
- package/src/components/composed/tree/use-tree-dnd.ts +179 -0
- package/src/components/composed/tree/use-tree-state.ts +105 -0
- package/src/components/composed/tree/use-tree.ts +307 -0
- package/src/components/composed/tree/utils.ts +172 -0
- package/src/components/composed/user-avatar.tsx +11 -96
- package/src/components/docs/component-preview.tsx +11 -11
- package/src/components/user-avatar/__tests__/user-avatar.test.tsx +245 -0
- package/src/components/user-avatar/audio-wave.tsx +22 -0
- package/src/components/user-avatar/component.tsx +152 -0
- package/src/components/user-avatar/fallback.tsx +26 -0
- package/src/components/user-avatar/index.ts +34 -0
- package/src/components/user-avatar/presence-badge.tsx +56 -0
- package/src/components/user-avatar/type.ts +85 -0
- package/src/components/user-avatar/use-user-avatar-state.ts +60 -0
- package/src/components/user-avatar/use-user-avatar.ts +144 -0
- package/src/components/user-avatar/user-avatar-atom.ts +198 -0
- package/src/components/user-avatar/utils.ts +8 -0
- package/src/index.css +211 -153
- package/src/index.ts +35 -2
- package/src/state/exegia-provider.tsx +79 -0
- package/src/state/index.ts +4 -0
- package/src/state/store.ts +19 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Atom } from 'jotai';
|
|
2
|
+
import { TreeConfig, TreeDropPosition, TreeDropTarget, TreeHandlers, TreeInstanceId, TreeNode, TreeSeed, TreeState, TreeVariant } from './type';
|
|
3
|
+
/** What a tree reads as before `useTree` publishes its options. */
|
|
4
|
+
export declare const DEFAULT_TREE_CONFIG: TreeConfig;
|
|
5
|
+
/**
|
|
6
|
+
* A string-keyed atom family.
|
|
7
|
+
*
|
|
8
|
+
* `jotai/utils`' `atomFamily` is deprecated for Jotai v3, and we need only
|
|
9
|
+
* the string-keyed case with a `remove` — so this stays in-house rather than
|
|
10
|
+
* adding `jotai-family` as a second Jotai package to keep version-aligned.
|
|
11
|
+
* Dropping a key lets the store's WeakMap release that instance's state.
|
|
12
|
+
*/
|
|
13
|
+
type Family<AtomType> = ((id: TreeInstanceId) => AtomType) & {
|
|
14
|
+
remove: (id: TreeInstanceId) => void;
|
|
15
|
+
};
|
|
16
|
+
/** @internal */
|
|
17
|
+
export declare const treeConfigAtom: Family<import('jotai').PrimitiveAtom<TreeConfig> & {
|
|
18
|
+
init: TreeConfig;
|
|
19
|
+
}>;
|
|
20
|
+
/** @internal Refreshed every commit; nothing subscribes, so it is free. */
|
|
21
|
+
export declare const treeHandlersAtom: Family<import('jotai').PrimitiveAtom<TreeHandlers> & {
|
|
22
|
+
init: TreeHandlers;
|
|
23
|
+
}>;
|
|
24
|
+
/** The tree's current data — hook-owned, or the projection of a controlled
|
|
25
|
+
* `items` prop. */
|
|
26
|
+
export declare const treeItemsAtom: Family<import('jotai').PrimitiveAtom<TreeNode[]> & {
|
|
27
|
+
init: TreeNode[];
|
|
28
|
+
}>;
|
|
29
|
+
export declare const treeActiveIdAtom: Family<import('jotai').PrimitiveAtom<string | undefined> & {
|
|
30
|
+
init: string | undefined;
|
|
31
|
+
}>;
|
|
32
|
+
export declare const treeExpandedIdsAtom: Family<import('jotai').PrimitiveAtom<ReadonlySet<string>> & {
|
|
33
|
+
init: ReadonlySet<string>;
|
|
34
|
+
}>;
|
|
35
|
+
/** Raw rail fold. Read `treeCollapsedAtom` for the variant-masked value. */
|
|
36
|
+
export declare const treeRailCollapsedAtom: Family<import('jotai').PrimitiveAtom<boolean> & {
|
|
37
|
+
init: boolean;
|
|
38
|
+
}>;
|
|
39
|
+
export declare const treeRenamingIdAtom: Family<import('jotai').PrimitiveAtom<string | null> & {
|
|
40
|
+
init: string | null;
|
|
41
|
+
}>;
|
|
42
|
+
export declare const treeDraggedIdAtom: Family<import('jotai').PrimitiveAtom<string | null> & {
|
|
43
|
+
init: string | null;
|
|
44
|
+
}>;
|
|
45
|
+
export declare const treeDropTargetAtom: Family<import('jotai').PrimitiveAtom<TreeDropTarget | null> & {
|
|
46
|
+
init: TreeDropTarget | null;
|
|
47
|
+
}>;
|
|
48
|
+
/** @internal The only items atom `useTree` may subscribe to: empty while a
|
|
49
|
+
* controlled `items` prop owns the data, so the projection write never feeds
|
|
50
|
+
* back into the render that produced it. An inline `items={[…]}` array is a
|
|
51
|
+
* new reference every render, and a subscribed round-trip would loop. */
|
|
52
|
+
export declare const treeOwnedItemsAtom: Family<Atom<TreeNode[]>>;
|
|
53
|
+
/** Rail folded to icons — always `false` outside `sidebar`. */
|
|
54
|
+
export declare const treeCollapsedAtom: Family<Atom<boolean>>;
|
|
55
|
+
export declare const treeSectionedAtom: Family<Atom<boolean>>;
|
|
56
|
+
export declare const treeSectionIdsAtom: Family<Atom<string[]>>;
|
|
57
|
+
export declare const treeCanRenameAtom: Family<Atom<boolean>>;
|
|
58
|
+
export declare const treeCanMoveAtom: Family<Atom<boolean>>;
|
|
59
|
+
export declare const treeVariantAtom: Family<Atom<TreeVariant>>;
|
|
60
|
+
export declare const treeSoundAtom: Family<Atom<boolean>>;
|
|
61
|
+
/** Whether this one node's branch is open. */
|
|
62
|
+
export declare const treeNodeExpandedAtom: (id: TreeInstanceId, nodeId: string) => Atom<boolean>;
|
|
63
|
+
/** Whether this one node is the current entry. */
|
|
64
|
+
export declare const treeNodeActiveAtom: (id: TreeInstanceId, nodeId: string) => Atom<boolean>;
|
|
65
|
+
/** Whether this one node is in rename mode. */
|
|
66
|
+
export declare const treeNodeRenamingAtom: (id: TreeInstanceId, nodeId: string) => Atom<boolean>;
|
|
67
|
+
/** Whether this one node is the row in flight. */
|
|
68
|
+
export declare const treeNodeDraggingAtom: (id: TreeInstanceId, nodeId: string) => Atom<boolean>;
|
|
69
|
+
/** Where a drop on this one node would land, `null` when it is not hovered. */
|
|
70
|
+
export declare const treeNodeDropAtom: (id: TreeInstanceId, nodeId: string) => Atom<TreeDropPosition | null>;
|
|
71
|
+
/** The whole state of one tree. Components reading a single field should
|
|
72
|
+
* subscribe to that field's atom instead — this one changes on every edit. */
|
|
73
|
+
export declare const treeStateAtom: Family<Atom<TreeState>>;
|
|
74
|
+
export declare const expandTreeNodeAtom: Family<import('jotai').WritableAtom<null, [nodeId: string], void> & {
|
|
75
|
+
init: null;
|
|
76
|
+
}>;
|
|
77
|
+
export declare const collapseTreeNodeAtom: Family<import('jotai').WritableAtom<null, [nodeId: string], void> & {
|
|
78
|
+
init: null;
|
|
79
|
+
}>;
|
|
80
|
+
export declare const toggleTreeNodeAtom: Family<import('jotai').WritableAtom<null, [nodeId: string], void> & {
|
|
81
|
+
init: null;
|
|
82
|
+
}>;
|
|
83
|
+
export declare const expandAllTreeNodesAtom: Family<import('jotai').WritableAtom<null, [], void> & {
|
|
84
|
+
init: null;
|
|
85
|
+
}>;
|
|
86
|
+
export declare const collapseAllTreeNodesAtom: Family<import('jotai').WritableAtom<null, [], void> & {
|
|
87
|
+
init: null;
|
|
88
|
+
}>;
|
|
89
|
+
/** Open every ancestor of `nodeId` without touching the rest of the tree. */
|
|
90
|
+
export declare const revealTreeNodeAtom: Family<import('jotai').WritableAtom<null, [nodeId: string], void> & {
|
|
91
|
+
init: null;
|
|
92
|
+
}>;
|
|
93
|
+
/** @internal The same, silent. `useTree` runs it whenever the active id
|
|
94
|
+
* changes so a nested entry is never folded away — the hook has never
|
|
95
|
+
* reported that implicit reveal through `onExpandedChange`. */
|
|
96
|
+
export declare const revealTreeAncestorsAtom: Family<import('jotai').WritableAtom<null, [nodeId: string], void> & {
|
|
97
|
+
init: null;
|
|
98
|
+
}>;
|
|
99
|
+
export declare const setTreeCollapsedAtom: Family<import('jotai').WritableAtom<null, [collapsed: boolean], void> & {
|
|
100
|
+
init: null;
|
|
101
|
+
}>;
|
|
102
|
+
export declare const toggleTreeCollapsedAtom: Family<import('jotai').WritableAtom<null, [], void> & {
|
|
103
|
+
init: null;
|
|
104
|
+
}>;
|
|
105
|
+
/** Runs the node's own `onSelect` first, then `onNavigate` — the order a row
|
|
106
|
+
* press follows. Disabled and unknown nodes are inert. */
|
|
107
|
+
export declare const selectTreeNodeAtom: Family<import('jotai').WritableAtom<null, [nodeId: string], void> & {
|
|
108
|
+
init: null;
|
|
109
|
+
}>;
|
|
110
|
+
export declare const startTreeRenameAtom: Family<import('jotai').WritableAtom<null, [nodeId: string], void> & {
|
|
111
|
+
init: null;
|
|
112
|
+
}>;
|
|
113
|
+
export declare const cancelTreeRenameAtom: Family<import('jotai').WritableAtom<null, [], void> & {
|
|
114
|
+
init: null;
|
|
115
|
+
}>;
|
|
116
|
+
/** Commit a rename and leave rename mode. Blank or unchanged labels are
|
|
117
|
+
* dropped. */
|
|
118
|
+
export declare const renameTreeNodeAtom: Family<import('jotai').WritableAtom<null, [nodeId: string, label: string], void> & {
|
|
119
|
+
init: null;
|
|
120
|
+
}>;
|
|
121
|
+
export declare const moveTreeNodeAtom: Family<import('jotai').WritableAtom<null, [nodeId: string, parentId: string | null, index: number], void> & {
|
|
122
|
+
init: null;
|
|
123
|
+
}>;
|
|
124
|
+
/** Replace the data. Reports through `onItemsChange`; writes the atom only
|
|
125
|
+
* when no controlled `items` prop owns it. */
|
|
126
|
+
export declare const setTreeItemsAtom: Family<import('jotai').WritableAtom<null, [items: TreeNode[]], void> & {
|
|
127
|
+
init: null;
|
|
128
|
+
}>;
|
|
129
|
+
export declare const endTreeDragAtom: Family<import('jotai').WritableAtom<null, [], void> & {
|
|
130
|
+
init: null;
|
|
131
|
+
}>;
|
|
132
|
+
/** @internal Publish the latest options; seed the instance once. */
|
|
133
|
+
export declare const mountTreeAtom: Family<import('jotai').WritableAtom<null, [config: TreeConfig, seed: TreeSeed], void> & {
|
|
134
|
+
init: null;
|
|
135
|
+
}>;
|
|
136
|
+
/** @internal */
|
|
137
|
+
export declare const setTreeHandlersAtom: Family<import('jotai').WritableAtom<null, [handlers: TreeHandlers], void> & {
|
|
138
|
+
init: null;
|
|
139
|
+
}>;
|
|
140
|
+
/** @internal One-way projections of controlled props — no callbacks fire. */
|
|
141
|
+
export declare const projectTreeItemsAtom: Family<import('jotai').WritableAtom<null, [items: TreeNode[]], void> & {
|
|
142
|
+
init: null;
|
|
143
|
+
}>;
|
|
144
|
+
/** @internal */
|
|
145
|
+
export declare const projectTreeActiveIdAtom: Family<import('jotai').WritableAtom<null, [activeId: string | undefined], void> & {
|
|
146
|
+
init: null;
|
|
147
|
+
}>;
|
|
148
|
+
/** @internal */
|
|
149
|
+
export declare const projectTreeCollapsedAtom: Family<import('jotai').WritableAtom<null, [collapsed: boolean], void> & {
|
|
150
|
+
init: null;
|
|
151
|
+
}>;
|
|
152
|
+
/** Back to the values the instance mounted with. */
|
|
153
|
+
export declare const resetTreeAtom: Family<import('jotai').WritableAtom<null, [], void> & {
|
|
154
|
+
init: null;
|
|
155
|
+
}>;
|
|
156
|
+
/** Drop every atom for `id`. `useTree` calls this on unmount for trees it
|
|
157
|
+
* keyed itself; an explicit `treeId` outlives its component, so a rail's fold
|
|
158
|
+
* survives a route change. */
|
|
159
|
+
export declare function removeTreeInstance(id: TreeInstanceId): void;
|
|
160
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TreeNode } from './type';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
export interface TreeRowProps {
|
|
4
|
+
node: TreeNode;
|
|
5
|
+
depth: number;
|
|
6
|
+
}
|
|
7
|
+
declare function TreeRowImpl({ node, depth }: TreeRowProps): React.ReactElement;
|
|
8
|
+
/** Rows are memoized so a re-render of the root — a rail measurement, a new
|
|
9
|
+
* `renderTrailing` — does not walk the whole tree. Each row's own state
|
|
10
|
+
* reaches it through its atoms instead. */
|
|
11
|
+
export declare const TreeRow: React.MemoExoticComponent<typeof TreeRowImpl>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { TreeProps } from './type';
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* A nested item tree with four shapes: `navigation` (app nav — 3-level
|
|
5
|
+
* data promotes the top level to collapsible section names), `toc`
|
|
6
|
+
* (routes on top, in-page `#` anchors at the leaves), `sidebar` (a
|
|
7
|
+
* single-level rail that collapses to icons) and `files` (a compact file
|
|
8
|
+
* explorer with rename, drag-and-drop and trailing row actions).
|
|
9
|
+
*
|
|
10
|
+
* Two ways to drive it. Data-driven like the sidebar block: pass `items`,
|
|
11
|
+
* wire `onNavigate` into your router. Or hold a `useTree` controller and
|
|
12
|
+
* pass it as `tree` — same rendering, but expand, collapse, select, rename
|
|
13
|
+
* and reorder are then callable from anywhere in your app.
|
|
14
|
+
*
|
|
15
|
+
* Branches expand with a soft height morph and row stagger; the rail's
|
|
16
|
+
* labels fold away when `collapsed` flips. Arrow keys walk visible rows,
|
|
17
|
+
* expand and collapse; F2 renames in `files`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function Tree(props: TreeProps): React.ReactElement;
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
/** One node in the tree. Nesting depth carries meaning per variant — see
|
|
3
|
+
* `TreeProps["variant"]`. */
|
|
4
|
+
export interface TreeNode {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
/** Leading icon. Required in practice for `sidebar` — it is all that
|
|
8
|
+
* remains of a row while the rail is collapsed. */
|
|
9
|
+
icon?: React.ReactNode;
|
|
10
|
+
/** Route metadata for the consumer's `onNavigate` — every row renders as
|
|
11
|
+
* a button, so this is never turned into an anchor element. Read it (with
|
|
12
|
+
* `target`) off the node your handler receives. One native behaviour is
|
|
13
|
+
* kept: `toc` rows below the route level jump to `#{id}` after select
|
|
14
|
+
* (a `#hash` href overrides the id; a non-hash href disables the jump). */
|
|
15
|
+
href?: string;
|
|
16
|
+
target?: "_blank" | "_self" | "_parent" | "_top";
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
/** Start expanded. Ancestors of `activeId` expand regardless. */
|
|
19
|
+
defaultOpen?: boolean;
|
|
20
|
+
/** Trailing hint — a count, a "New" pill. */
|
|
21
|
+
badge?: React.ReactNode;
|
|
22
|
+
/** Fires on selection, before the tree-level `onNavigate`. */
|
|
23
|
+
onSelect?: () => void;
|
|
24
|
+
children?: TreeNode[];
|
|
25
|
+
}
|
|
26
|
+
export type TreeVariant = "navigation" | "toc" | "sidebar" | "files";
|
|
27
|
+
/** Where a dragged row lands relative to its drop target. */
|
|
28
|
+
export type TreeDropPosition = "before" | "after" | "inside";
|
|
29
|
+
/** Key for one tree’s state in the store. Any stable string; `useTree`
|
|
30
|
+
* generates one when you don't pass it. */
|
|
31
|
+
export type TreeInstanceId = string;
|
|
32
|
+
/** Row a drag hovers, and where the drop would land. */
|
|
33
|
+
export interface TreeDropTarget {
|
|
34
|
+
id: string;
|
|
35
|
+
position: TreeDropPosition;
|
|
36
|
+
}
|
|
37
|
+
interface TreeBaseProps {
|
|
38
|
+
items: TreeNode[];
|
|
39
|
+
/** Key this tree's state under a name your app can address —
|
|
40
|
+
* `useTreeState("app-nav")` / `useTreeActions("app-nav")` reach it from
|
|
41
|
+
* anywhere under `ExegiaProvider`. Without one the tree generates a key
|
|
42
|
+
* and its state is dropped when it unmounts. */
|
|
43
|
+
treeId?: TreeInstanceId;
|
|
44
|
+
/** Never set on the data form — `tree` selects the controller form. */
|
|
45
|
+
tree?: never;
|
|
46
|
+
/** `id` of the current entry — matches any depth. Its ancestors expand. */
|
|
47
|
+
activeId?: string;
|
|
48
|
+
/** Fires for every selection (rows and leaves alike), after the node's
|
|
49
|
+
* own `onSelect`. Rows are buttons, so this is the routing path — wire
|
|
50
|
+
* your router's navigate here. `toc` rows below the route level still jump
|
|
51
|
+
* to `#{id}` natively, after this fires. */
|
|
52
|
+
onNavigate?: (node: TreeNode) => void;
|
|
53
|
+
/** Expand/collapse cues. Silent until `bindSounds()`. */
|
|
54
|
+
sound?: boolean;
|
|
55
|
+
ariaLabel?: string;
|
|
56
|
+
className?: string;
|
|
57
|
+
}
|
|
58
|
+
interface TreeReadonlyProps {
|
|
59
|
+
collapsed?: never;
|
|
60
|
+
onMove?: never;
|
|
61
|
+
onRename?: never;
|
|
62
|
+
renderTrailing?: never;
|
|
63
|
+
}
|
|
64
|
+
/** Drive the tree from a `useTree` controller instead of raw props. The
|
|
65
|
+
* controller carries the variant, the data and every handler; only the
|
|
66
|
+
* presentational props stay here. */
|
|
67
|
+
export interface TreeControllerProps {
|
|
68
|
+
tree: TreeController;
|
|
69
|
+
items?: never;
|
|
70
|
+
ariaLabel?: string;
|
|
71
|
+
className?: string;
|
|
72
|
+
/** Row actions revealed on hover/focus (`files` only — ignored by the
|
|
73
|
+
* other variants, which the controller form cannot type-gate). */
|
|
74
|
+
renderTrailing?: (node: TreeNode) => React.ReactNode;
|
|
75
|
+
}
|
|
76
|
+
/** Either form: raw props, or a `useTree` controller via `tree`. */
|
|
77
|
+
export type TreeProps = TreeDataProps | TreeControllerProps;
|
|
78
|
+
/** The four shapes a Tree takes. Editing props only exist on `files`;
|
|
79
|
+
* `collapsed` only on `sidebar` — the union is the contract. */
|
|
80
|
+
export type TreeDataProps = TreeBaseProps & (({
|
|
81
|
+
/** Nested app navigation. With 3 levels of nodes the top level
|
|
82
|
+
* becomes collapsible section names (styled as headings, not
|
|
83
|
+
* rows); with 2 it renders plain selectable rows. */
|
|
84
|
+
variant: "navigation";
|
|
85
|
+
} & TreeReadonlyProps) | ({
|
|
86
|
+
/** Table of contents: top-level nodes are routes (handled in
|
|
87
|
+
* `onNavigate`); rows below jump to `#{id}` after select, like an
|
|
88
|
+
* anchor would. Parents select on the row and expand from a
|
|
89
|
+
* separate overlay chevron. */
|
|
90
|
+
variant: "toc";
|
|
91
|
+
} & TreeReadonlyProps) | ({
|
|
92
|
+
/** Single-level icon rail. `collapsed` shrinks rows to their
|
|
93
|
+
* leading icon; nested children are ignored. */
|
|
94
|
+
variant: "sidebar";
|
|
95
|
+
collapsed?: boolean;
|
|
96
|
+
} & Omit<TreeReadonlyProps, "collapsed">) | {
|
|
97
|
+
/** File explorer: only leaves navigate, folders toggle. Compact
|
|
98
|
+
* spacing; rename, drag-and-drop and trailing actions enabled. */
|
|
99
|
+
variant: "files";
|
|
100
|
+
/** Enables drag-and-drop. Reorder `items` yourself: `parentId`
|
|
101
|
+
* `null` means the root list, `index` is the slot among the new
|
|
102
|
+
* siblings (computed on the list without the dragged node). */
|
|
103
|
+
onMove?: (id: string, parentId: string | null, index: number) => void;
|
|
104
|
+
/** Enables inline rename (double-click or F2). */
|
|
105
|
+
onRename?: (id: string, label: string) => void;
|
|
106
|
+
/** Row actions revealed on hover/focus — a menu, a delete icon. */
|
|
107
|
+
renderTrailing?: (node: TreeNode) => React.ReactNode;
|
|
108
|
+
collapsed?: never;
|
|
109
|
+
});
|
|
110
|
+
/** Options for `useTree`. Each of `items`, `activeId` and `collapsed` is
|
|
111
|
+
* controlled when passed and hook-owned when its `default*` twin is used
|
|
112
|
+
* instead. */
|
|
113
|
+
export interface UseTreeOptions {
|
|
114
|
+
/** Key this tree's state under a name your app can address —
|
|
115
|
+
* `useTreeState("app-nav")` / `useTreeActions("app-nav")` reach it from
|
|
116
|
+
* anywhere under `ExegiaProvider`. Without one the hook generates a key
|
|
117
|
+
* and the state is dropped when the component unmounts. */
|
|
118
|
+
treeId?: TreeInstanceId;
|
|
119
|
+
/** Which shape the tree takes — gates rename/reorder (`files`) and the
|
|
120
|
+
* collapsible rail (`sidebar`). */
|
|
121
|
+
variant: TreeVariant;
|
|
122
|
+
/** Controlled data. With it, `rename`/`move` only report the edit unless
|
|
123
|
+
* you also pass `onItemsChange`. */
|
|
124
|
+
items?: TreeNode[];
|
|
125
|
+
/** Hook-owned data — `rename` and `move` apply the edit themselves. */
|
|
126
|
+
defaultItems?: TreeNode[];
|
|
127
|
+
/** Next tree after a `rename`/`move`. Also enables self-applying edits
|
|
128
|
+
* on top of controlled `items`. */
|
|
129
|
+
onItemsChange?: (items: TreeNode[]) => void;
|
|
130
|
+
/** Controlled selection. Ancestors of the active node expand. */
|
|
131
|
+
activeId?: string;
|
|
132
|
+
defaultActiveId?: string;
|
|
133
|
+
/** Fires for every selection (rows and leaves alike), after the node's
|
|
134
|
+
* own `onSelect` — wire your router's navigate here. */
|
|
135
|
+
onNavigate?: (node: TreeNode) => void;
|
|
136
|
+
/** Start with these ids expanded instead of the `defaultOpen` set. */
|
|
137
|
+
defaultExpandedIds?: Iterable<string>;
|
|
138
|
+
onExpandedChange?: (ids: string[]) => void;
|
|
139
|
+
/** Controlled rail fold (`sidebar` only). */
|
|
140
|
+
collapsed?: boolean;
|
|
141
|
+
defaultCollapsed?: boolean;
|
|
142
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
143
|
+
/** Enables rename (`files`). Not needed when the hook owns the data. */
|
|
144
|
+
onRename?: (id: string, label: string) => void;
|
|
145
|
+
/** Enables drag-and-drop (`files`). `parentId` `null` means the root
|
|
146
|
+
* list, `index` is the slot among the new siblings (computed on the list
|
|
147
|
+
* without the moved node). Not needed when the hook owns the data. */
|
|
148
|
+
onMove?: (id: string, parentId: string | null, index: number) => void;
|
|
149
|
+
/** Expand/collapse cues. Silent until `bindSounds()`. */
|
|
150
|
+
sound?: boolean;
|
|
151
|
+
}
|
|
152
|
+
/** Everything the tree can do, callable from outside the component.
|
|
153
|
+
* Returned by `useTree` and accepted by `<Tree tree={…} />`. */
|
|
154
|
+
export interface TreeController {
|
|
155
|
+
/** The key this tree's state is stored under. */
|
|
156
|
+
treeId: TreeInstanceId;
|
|
157
|
+
variant: TreeVariant;
|
|
158
|
+
items: TreeNode[];
|
|
159
|
+
/** `navigation` with 3 levels of nodes — depth 0 renders as sections. */
|
|
160
|
+
sectioned: boolean;
|
|
161
|
+
/** Ids of the section headings, empty unless `sectioned`. Pass one to
|
|
162
|
+
* `expand`/`collapse`/`toggleExpanded` to work a whole section. */
|
|
163
|
+
sectionIds: string[];
|
|
164
|
+
sound: boolean;
|
|
165
|
+
getNode: (id: string) => TreeNode | null;
|
|
166
|
+
expandedIds: ReadonlySet<string>;
|
|
167
|
+
isExpanded: (id: string) => boolean;
|
|
168
|
+
expand: (id: string) => void;
|
|
169
|
+
collapse: (id: string) => void;
|
|
170
|
+
toggleExpanded: (id: string) => void;
|
|
171
|
+
expandAll: () => void;
|
|
172
|
+
collapseAll: () => void;
|
|
173
|
+
/** Open every ancestor of `id`, leaving the rest of the tree alone. */
|
|
174
|
+
reveal: (id: string) => void;
|
|
175
|
+
/** Rail folded to icons — always `false` outside `sidebar`. */
|
|
176
|
+
collapsed: boolean;
|
|
177
|
+
setCollapsed: (collapsed: boolean) => void;
|
|
178
|
+
toggleCollapsed: () => void;
|
|
179
|
+
activeId?: string;
|
|
180
|
+
/** Select a node: runs its `onSelect`, then `onNavigate`. Inert on
|
|
181
|
+
* disabled and unknown nodes. */
|
|
182
|
+
select: (id: string) => void;
|
|
183
|
+
/** Whether rename is wired up at all (`files` + a handler or owned data). */
|
|
184
|
+
canRename: boolean;
|
|
185
|
+
/** Rename target id, `null` while idle. */
|
|
186
|
+
renamingId: string | null;
|
|
187
|
+
startRename: (id: string) => void;
|
|
188
|
+
cancelRename: () => void;
|
|
189
|
+
/** Commit a rename and leave rename mode. Blank or unchanged labels are
|
|
190
|
+
* dropped. */
|
|
191
|
+
rename: (id: string, label: string) => void;
|
|
192
|
+
/** Whether reorder is wired up at all. */
|
|
193
|
+
canMove: boolean;
|
|
194
|
+
move: (id: string, parentId: string | null, index: number) => void;
|
|
195
|
+
/** Back to the values the tree mounted with. */
|
|
196
|
+
reset: () => void;
|
|
197
|
+
dnd: TreeDndContextValue;
|
|
198
|
+
}
|
|
199
|
+
/** @internal What a row needs from the root, threaded through context so
|
|
200
|
+
* the recursive rows stay prop-light.
|
|
201
|
+
*
|
|
202
|
+
* Deliberately free of tree state. Rows read state from per-node atoms, so
|
|
203
|
+
* this value keeps its identity for the life of the tree and expanding one
|
|
204
|
+
* branch no longer re-renders every row through context. */
|
|
205
|
+
export interface TreeContextValue {
|
|
206
|
+
treeId: TreeInstanceId;
|
|
207
|
+
renderTrailing?: (node: TreeNode) => React.ReactNode;
|
|
208
|
+
dnd: TreeDndHandlers;
|
|
209
|
+
}
|
|
210
|
+
/** @internal The drag event handlers, stable for the life of the tree —
|
|
211
|
+
* they read drag state out of the store instead of closing over it, so
|
|
212
|
+
* handing them to every row costs no re-renders. */
|
|
213
|
+
export interface TreeDndHandlers {
|
|
214
|
+
enabled: boolean;
|
|
215
|
+
onRowDragStart: (event: React.DragEvent, id: string) => void;
|
|
216
|
+
onRowDragOver: (event: React.DragEvent, node: TreeNode) => void;
|
|
217
|
+
onRowDragLeave: (event: React.DragEvent) => void;
|
|
218
|
+
onRowDrop: (event: React.DragEvent, node: TreeNode) => void;
|
|
219
|
+
onRowDragEnd: () => void;
|
|
220
|
+
}
|
|
221
|
+
/** @internal Handlers plus live drag state — what `TreeController.dnd`
|
|
222
|
+
* exposes (all `null`/no-op outside `files`). */
|
|
223
|
+
export interface TreeDndContextValue extends TreeDndHandlers {
|
|
224
|
+
draggedId: string | null;
|
|
225
|
+
/** Row the pointer is over and where the drop would land. */
|
|
226
|
+
dropTarget: TreeDropTarget | null;
|
|
227
|
+
}
|
|
228
|
+
/** Everything observable about one tree, for consumers reading it by id. */
|
|
229
|
+
export interface TreeState {
|
|
230
|
+
variant: TreeVariant;
|
|
231
|
+
items: TreeNode[];
|
|
232
|
+
activeId?: string;
|
|
233
|
+
expandedIds: ReadonlySet<string>;
|
|
234
|
+
collapsed: boolean;
|
|
235
|
+
renamingId: string | null;
|
|
236
|
+
sectioned: boolean;
|
|
237
|
+
sectionIds: string[];
|
|
238
|
+
canRename: boolean;
|
|
239
|
+
canMove: boolean;
|
|
240
|
+
draggedId: string | null;
|
|
241
|
+
dropTarget: TreeDropTarget | null;
|
|
242
|
+
}
|
|
243
|
+
/** Everything doable to one tree from outside its component. */
|
|
244
|
+
export interface TreeActions {
|
|
245
|
+
expand: (id: string) => void;
|
|
246
|
+
collapse: (id: string) => void;
|
|
247
|
+
toggleExpanded: (id: string) => void;
|
|
248
|
+
expandAll: () => void;
|
|
249
|
+
collapseAll: () => void;
|
|
250
|
+
reveal: (id: string) => void;
|
|
251
|
+
setCollapsed: (collapsed: boolean) => void;
|
|
252
|
+
toggleCollapsed: () => void;
|
|
253
|
+
select: (id: string) => void;
|
|
254
|
+
startRename: (id: string) => void;
|
|
255
|
+
cancelRename: () => void;
|
|
256
|
+
rename: (id: string, label: string) => void;
|
|
257
|
+
move: (id: string, parentId: string | null, index: number) => void;
|
|
258
|
+
setItems: (items: TreeNode[]) => void;
|
|
259
|
+
reset: () => void;
|
|
260
|
+
}
|
|
261
|
+
/** @internal Projection of `useTree`'s options — primitives only, so the
|
|
262
|
+
* store write runs once per real change instead of once per render. */
|
|
263
|
+
export interface TreeConfig {
|
|
264
|
+
variant: TreeVariant;
|
|
265
|
+
sound: boolean;
|
|
266
|
+
controlsItems: boolean;
|
|
267
|
+
controlsActiveId: boolean;
|
|
268
|
+
controlsCollapsed: boolean;
|
|
269
|
+
managesItems: boolean;
|
|
270
|
+
hasRenameHandler: boolean;
|
|
271
|
+
hasMoveHandler: boolean;
|
|
272
|
+
}
|
|
273
|
+
/** @internal Latest option callbacks. Only write atoms read this, so it
|
|
274
|
+
* can be refreshed every commit without re-rendering anything. */
|
|
275
|
+
export interface TreeHandlers {
|
|
276
|
+
onNavigate?: (node: TreeNode) => void;
|
|
277
|
+
onItemsChange?: (items: TreeNode[]) => void;
|
|
278
|
+
onExpandedChange?: (ids: string[]) => void;
|
|
279
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
280
|
+
onRename?: (id: string, label: string) => void;
|
|
281
|
+
onMove?: (id: string, parentId: string | null, index: number) => void;
|
|
282
|
+
}
|
|
283
|
+
/** @internal What an instance starts from, replayed by `resetTreeAtom`. */
|
|
284
|
+
export interface TreeSeed {
|
|
285
|
+
items: TreeNode[];
|
|
286
|
+
activeId?: string;
|
|
287
|
+
collapsed: boolean;
|
|
288
|
+
expandedIds?: string[];
|
|
289
|
+
}
|
|
290
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TreeDndContextValue, TreeDndHandlers, TreeInstanceId } from './type';
|
|
2
|
+
/**
|
|
3
|
+
* The drag handlers for the `files` variant, stable for the life of the tree.
|
|
4
|
+
*
|
|
5
|
+
* Nothing here subscribes to drag state: items, the dragged id and the drop
|
|
6
|
+
* target are read out of the store when a handler runs. That is what lets
|
|
7
|
+
* every row share one handler object without re-rendering when a drag moves —
|
|
8
|
+
* and it keeps `useTree` from subscribing to data it also projects from
|
|
9
|
+
* props, which would loop on an inline `items` array.
|
|
10
|
+
*
|
|
11
|
+
* Inert unless the tree `canMove`. `dataTransfer` is set for interop but
|
|
12
|
+
* never read, so the flow also works where the store is unavailable (tests,
|
|
13
|
+
* some webviews).
|
|
14
|
+
*/
|
|
15
|
+
export declare function useTreeDndHandlers(treeId: TreeInstanceId): TreeDndHandlers;
|
|
16
|
+
/** The handlers plus live drag state, for `TreeController.dnd`. Rows take the
|
|
17
|
+
* handlers alone and read the state per node instead. */
|
|
18
|
+
export declare function useTreeDnd(treeId: TreeInstanceId): TreeDndContextValue;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { TreeActions, TreeInstanceId, TreeState } from './type';
|
|
2
|
+
/**
|
|
3
|
+
* Read the tree registered under `treeId` from anywhere below
|
|
4
|
+
* `ExegiaProvider` — no controller, no props, no provider of its own.
|
|
5
|
+
*
|
|
6
|
+
* ```tsx
|
|
7
|
+
* const { collapsed, activeId } = useTreeState("app-nav")
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* This returns the whole state object, so the caller re-renders on any
|
|
11
|
+
* change. A component that reads one field should subscribe to that field's
|
|
12
|
+
* atom instead: `useAtomValue(treeCollapsedAtom("app-nav"))`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useTreeState(treeId: TreeInstanceId): TreeState;
|
|
15
|
+
/**
|
|
16
|
+
* Drive the tree registered under `treeId` from anywhere. Writes only — the
|
|
17
|
+
* caller never re-renders when the tree changes, so this is what a command
|
|
18
|
+
* palette, a keyboard shortcut or a route guard should reach for.
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* const nav = useTreeActions("app-nav")
|
|
22
|
+
* <Button onClick={nav.collapseAll}>Collapse all</Button>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function useTreeActions(treeId: TreeInstanceId): TreeActions;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { TreeController, UseTreeOptions } from './type';
|
|
2
|
+
/**
|
|
3
|
+
* The tree's headless controller — every behaviour the component exposes,
|
|
4
|
+
* callable from outside it: expand/collapse (a node, a section, the whole
|
|
5
|
+
* tree), fold the `sidebar` rail, select a node, rename, reorder.
|
|
6
|
+
*
|
|
7
|
+
* Each piece of state is controlled-or-uncontrolled in the usual React
|
|
8
|
+
* shape: pass `items`/`activeId`/`collapsed` to own it yourself, or
|
|
9
|
+
* `defaultItems`/`defaultActiveId`/`defaultCollapsed` to let the hook. When
|
|
10
|
+
* the hook owns `items` (or you pass `onItemsChange`), `rename` and `move`
|
|
11
|
+
* apply the edit to the data themselves — otherwise they only report it
|
|
12
|
+
* through `onRename`/`onMove` and you reduce the tree yourself.
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const tree = useTree({ variant: "files", defaultItems: files })
|
|
16
|
+
* <Tree tree={tree} />
|
|
17
|
+
* <Button onClick={tree.collapseAll}>Collapse all</Button>
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* State lives in Jotai atoms keyed by `treeId`, so anything under
|
|
21
|
+
* `ExegiaProvider` can drive this tree without the controller — name it and
|
|
22
|
+
* reach for `useTreeState(treeId)` / `useTreeActions(treeId)` elsewhere.
|
|
23
|
+
*/
|
|
24
|
+
export declare function useTree(options: UseTreeOptions): TreeController;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { TreeNode } from './type';
|
|
2
|
+
/** Depth-0 nodes read as sections only when the data actually nests three
|
|
3
|
+
* levels — a two-level tree keeps its top level as plain link rows. */
|
|
4
|
+
export declare function hasThreeLevels(items: readonly TreeNode[]): boolean;
|
|
5
|
+
/** Ids of every ancestor of `id` (nearest last); empty when absent. */
|
|
6
|
+
export declare function ancestorIdsOf(items: readonly TreeNode[], id: string): string[];
|
|
7
|
+
/** Ids that start expanded: `defaultOpen` nodes plus every ancestor of the
|
|
8
|
+
* active entry, so the current location is never folded away. */
|
|
9
|
+
export declare function initialExpandedIds(items: readonly TreeNode[], activeId?: string): Set<string>;
|
|
10
|
+
/** Ids of every node that can hold children — the set `expandAll` opens.
|
|
11
|
+
* In `files` an empty `children: []` still counts (it is a folder). */
|
|
12
|
+
export declare function expandableIdsOf(items: readonly TreeNode[], filesVariant?: boolean): string[];
|
|
13
|
+
/** Immutably relabel `id`. Returns the same array reference when absent. */
|
|
14
|
+
export declare function renameNode(items: readonly TreeNode[], id: string, label: string): TreeNode[];
|
|
15
|
+
/** Whether `candidateId` is `id` itself or nests anywhere under it — the
|
|
16
|
+
* guard that keeps a folder from being dropped into its own subtree. */
|
|
17
|
+
export declare function containsNode(items: readonly TreeNode[], id: string, candidateId: string): boolean;
|
|
18
|
+
export declare function findNode(items: readonly TreeNode[], id: string): TreeNode | null;
|
|
19
|
+
/** Parent id (`null` at root) and index of `id` among its siblings. */
|
|
20
|
+
export declare function locateNode(items: readonly TreeNode[], id: string): {
|
|
21
|
+
parentId: string | null;
|
|
22
|
+
index: number;
|
|
23
|
+
} | null;
|
|
24
|
+
/** Immutably lift `id` out of the tree and reinsert it under `parentId`
|
|
25
|
+
* (`null` = root) at `index` — the standard `onMove` reducer, exported so
|
|
26
|
+
* consumers don't each rebuild it. `index` addresses the sibling list
|
|
27
|
+
* *after* the node has been lifted out. */
|
|
28
|
+
export declare function moveNode(items: readonly TreeNode[], id: string, parentId: string | null, index: number): TreeNode[];
|
|
@@ -1,30 +1,7 @@
|
|
|
1
|
-
import { AvatarPrimitive } from '../ui/avatar';
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
export interface UserAvatarProps extends Omit<AvatarPrimitive.Root.Props, "children"> {
|
|
4
|
-
/** Image URL. Without one the initials show immediately — no skeleton. */
|
|
5
|
-
src?: string;
|
|
6
|
-
/** Drives the initials, and the alt text unless `alt` overrides it. */
|
|
7
|
-
name?: string;
|
|
8
|
-
/** Overrides the initials derived from `name`. */
|
|
9
|
-
initials?: string;
|
|
10
|
-
/**
|
|
11
|
-
* Alt text for the image. Pass "" when adjacent text already names the
|
|
12
|
-
* person — the image is then decorative.
|
|
13
|
-
*/
|
|
14
|
-
alt?: string;
|
|
15
|
-
/**
|
|
16
|
-
* Force the skeleton, for when the identity itself is still being fetched.
|
|
17
|
-
* Omitted, it follows the image: a passed `src` skeletons until it resolves.
|
|
18
|
-
*/
|
|
19
|
-
loading?: boolean;
|
|
20
|
-
}
|
|
21
|
-
/** "Jenny Hamilton" → "JH", "luna" → "L". */
|
|
22
|
-
export declare function initialsFrom(name: string): string;
|
|
23
1
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* the image resolves rather than flashing initials that are about to be
|
|
28
|
-
* replaced. A failed load settles on the initials.
|
|
2
|
+
* Back-compat path. The avatar moved to `components/user-avatar/` (split
|
|
3
|
+
* into component / atoms / hooks); this module re-exports it so existing
|
|
4
|
+
* imports keep resolving to the one implementation. Prefer the new path.
|
|
29
5
|
*/
|
|
30
|
-
export
|
|
6
|
+
export { UserAvatar, initialsFrom, useUserAvatar, useUserAvatarActions, useUserAvatarState, } from '../user-avatar';
|
|
7
|
+
export type { UserAvatarProps, UserPresence } from '../user-avatar';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|