@djangocfg/ui-tools 2.1.314 → 2.1.315
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/TreeRoot-DO33TIS5.mjs +4 -0
- package/dist/TreeRoot-DO33TIS5.mjs.map +1 -0
- package/dist/TreeRoot-NJOZ2DMV.cjs +19 -0
- package/dist/TreeRoot-NJOZ2DMV.cjs.map +1 -0
- package/dist/chunk-E5BP4IXF.mjs +1231 -0
- package/dist/chunk-E5BP4IXF.mjs.map +1 -0
- package/dist/chunk-MA552EWC.cjs +1282 -0
- package/dist/chunk-MA552EWC.cjs.map +1 -0
- package/dist/index.cjs +186 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +435 -2
- package/dist/index.d.ts +435 -2
- package/dist/index.mjs +60 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -6
- package/src/index.ts +4 -0
- package/src/tools/Tree/README.md +220 -0
- package/src/tools/Tree/Tree.story.tsx +536 -0
- package/src/tools/Tree/TreeRoot.tsx +157 -0
- package/src/tools/Tree/components/TreeChevron.tsx +39 -0
- package/src/tools/Tree/components/TreeContent.tsx +48 -0
- package/src/tools/Tree/components/TreeEmpty.tsx +21 -0
- package/src/tools/Tree/components/TreeError.tsx +24 -0
- package/src/tools/Tree/components/TreeIcon.tsx +29 -0
- package/src/tools/Tree/components/TreeIndentGuides.tsx +33 -0
- package/src/tools/Tree/components/TreeLabel.tsx +24 -0
- package/src/tools/Tree/components/TreeRow.tsx +173 -0
- package/src/tools/Tree/components/TreeSearchInput.tsx +50 -0
- package/src/tools/Tree/components/TreeSkeleton.tsx +22 -0
- package/src/tools/Tree/components/index.ts +22 -0
- package/src/tools/Tree/context/TreeContext.tsx +538 -0
- package/src/tools/Tree/context/hooks.ts +110 -0
- package/src/tools/Tree/context/index.ts +13 -0
- package/src/tools/Tree/data/appearance.ts +175 -0
- package/src/tools/Tree/data/childCache.ts +43 -0
- package/src/tools/Tree/data/createDemoTree.ts +42 -0
- package/src/tools/Tree/data/flatten.ts +51 -0
- package/src/tools/Tree/data/index.ts +24 -0
- package/src/tools/Tree/data/persist.ts +62 -0
- package/src/tools/Tree/hooks/index.ts +6 -0
- package/src/tools/Tree/hooks/useTreeKeyboard.ts +137 -0
- package/src/tools/Tree/hooks/useTreeTypeAhead.ts +100 -0
- package/src/tools/Tree/index.tsx +99 -0
- package/src/tools/Tree/lazy.tsx +14 -0
- package/src/tools/Tree/types.ts +136 -0
- package/src/tools/index.ts +75 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Decomposed shadcn-style tree component.
|
|
5
|
+
*
|
|
6
|
+
* Two usage patterns:
|
|
7
|
+
*
|
|
8
|
+
* 1) High-level (most cases):
|
|
9
|
+
* <TreeRoot data={...} getItemName={...} onSelectionChange={...} />
|
|
10
|
+
*
|
|
11
|
+
* 2) Composition (full control):
|
|
12
|
+
* <TreeProvider data={...} getItemName={...}>
|
|
13
|
+
* <TreeSearchInput />
|
|
14
|
+
* <TreeContent />
|
|
15
|
+
* </TreeProvider>
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export { TreeRoot, TreeRoot as Tree, default as default } from './TreeRoot';
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
TreeProvider,
|
|
22
|
+
useTreeContext,
|
|
23
|
+
useTreeLabels,
|
|
24
|
+
useTreeRows,
|
|
25
|
+
useTreeSelection,
|
|
26
|
+
useTreeExpansion,
|
|
27
|
+
useTreeFocus,
|
|
28
|
+
useTreeSearch,
|
|
29
|
+
useTreeActions,
|
|
30
|
+
} from './context';
|
|
31
|
+
export type { TreeProviderProps, TreeContextValue } from './context';
|
|
32
|
+
|
|
33
|
+
export { useTreeTypeAhead, useTreeKeyboard } from './hooks';
|
|
34
|
+
export type { UseTreeTypeAheadOptions, UseTreeKeyboardOptions } from './hooks';
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
TreeContent,
|
|
38
|
+
TreeRow,
|
|
39
|
+
TreeChevron,
|
|
40
|
+
TreeIcon,
|
|
41
|
+
TreeLabel,
|
|
42
|
+
TreeSearchInput,
|
|
43
|
+
TreeEmpty,
|
|
44
|
+
TreeSkeleton,
|
|
45
|
+
TreeError,
|
|
46
|
+
TreeIndentGuides,
|
|
47
|
+
} from './components';
|
|
48
|
+
export type {
|
|
49
|
+
TreeContentProps,
|
|
50
|
+
TreeRowProps,
|
|
51
|
+
TreeChevronProps,
|
|
52
|
+
TreeIconProps,
|
|
53
|
+
TreeLabelProps,
|
|
54
|
+
TreeSearchInputProps,
|
|
55
|
+
TreeEmptyProps,
|
|
56
|
+
TreeSkeletonProps,
|
|
57
|
+
TreeErrorProps,
|
|
58
|
+
TreeIndentGuidesProps,
|
|
59
|
+
} from './components';
|
|
60
|
+
|
|
61
|
+
export {
|
|
62
|
+
createChildCache,
|
|
63
|
+
resolveChildren,
|
|
64
|
+
flattenTree,
|
|
65
|
+
loadTreeState,
|
|
66
|
+
saveTreeState,
|
|
67
|
+
clearTreeState,
|
|
68
|
+
createDemoTree,
|
|
69
|
+
DEFAULT_TREE_APPEARANCE,
|
|
70
|
+
resolveAppearance,
|
|
71
|
+
appearanceToStyle,
|
|
72
|
+
} from './data';
|
|
73
|
+
export type {
|
|
74
|
+
ChildCache,
|
|
75
|
+
ChildEntry,
|
|
76
|
+
ChildEntryStatus,
|
|
77
|
+
FlattenInput,
|
|
78
|
+
PersistedTreeState,
|
|
79
|
+
DemoNode,
|
|
80
|
+
TreeAppearance,
|
|
81
|
+
ResolvedAppearance,
|
|
82
|
+
TreeDensity,
|
|
83
|
+
TreeAccentIntensity,
|
|
84
|
+
TreeRadius,
|
|
85
|
+
} from './data';
|
|
86
|
+
|
|
87
|
+
export { DEFAULT_TREE_LABELS } from './types';
|
|
88
|
+
export type {
|
|
89
|
+
TreeRootProps,
|
|
90
|
+
TreeNode,
|
|
91
|
+
TreeItemId,
|
|
92
|
+
TreeLabels,
|
|
93
|
+
TreeSelectionMode,
|
|
94
|
+
TreeRowRenderProps,
|
|
95
|
+
TreeRowSlot,
|
|
96
|
+
TreeContextMenuSlot,
|
|
97
|
+
TreeLoadChildren,
|
|
98
|
+
FlatRow,
|
|
99
|
+
} from './types';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createLazyComponent, LoadingFallback } from '../../components/lazy-wrapper';
|
|
4
|
+
import type { TreeRootProps } from './types';
|
|
5
|
+
|
|
6
|
+
export const LazyTree = createLazyComponent<TreeRootProps<unknown>>(
|
|
7
|
+
() => import('./TreeRoot'),
|
|
8
|
+
{
|
|
9
|
+
displayName: 'LazyTree',
|
|
10
|
+
fallback: <LoadingFallback minHeight={200} text="Loading tree…" />,
|
|
11
|
+
},
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export type { TreeRootProps };
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
import type { TreeAppearance } from './data/appearance';
|
|
6
|
+
|
|
7
|
+
export type TreeItemId = string;
|
|
8
|
+
|
|
9
|
+
/** A single node in the consumer's tree data. Generic over your payload. */
|
|
10
|
+
export interface TreeNode<T = unknown> {
|
|
11
|
+
id: TreeItemId;
|
|
12
|
+
data: T;
|
|
13
|
+
/** Inline children. Omit (and provide a `loadChildren`) for async loading. */
|
|
14
|
+
children?: TreeNode<T>[];
|
|
15
|
+
/**
|
|
16
|
+
* Set to `true` to mark a node as a folder even when its `children` array
|
|
17
|
+
* is empty (e.g. an unloaded async folder). Default: derived from
|
|
18
|
+
* `Array.isArray(children)`.
|
|
19
|
+
*/
|
|
20
|
+
isFolder?: boolean;
|
|
21
|
+
/** Disable interaction. */
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TreeLabels {
|
|
26
|
+
loading: string;
|
|
27
|
+
empty: string;
|
|
28
|
+
error: string;
|
|
29
|
+
searchPlaceholder: string;
|
|
30
|
+
searchMatches: (count: number) => string;
|
|
31
|
+
ariaLabel: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const DEFAULT_TREE_LABELS: TreeLabels = {
|
|
35
|
+
loading: 'Loading…',
|
|
36
|
+
empty: 'Nothing to show',
|
|
37
|
+
error: 'Failed to load',
|
|
38
|
+
searchPlaceholder: 'Search…',
|
|
39
|
+
searchMatches: (n) => `${n} match${n === 1 ? '' : 'es'}`,
|
|
40
|
+
ariaLabel: 'Tree',
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type TreeSelectionMode = 'none' | 'single' | 'multiple';
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Async loader: called the first time a folder is expanded with no inline
|
|
47
|
+
* `children`. Result is cached; concurrent expansions are de-duplicated.
|
|
48
|
+
*/
|
|
49
|
+
export type TreeLoadChildren<T> = (
|
|
50
|
+
node: TreeNode<T>,
|
|
51
|
+
) => Promise<TreeNode<T>[]>;
|
|
52
|
+
|
|
53
|
+
export interface TreeRowRenderProps<T> {
|
|
54
|
+
node: TreeNode<T>;
|
|
55
|
+
level: number;
|
|
56
|
+
isSelected: boolean;
|
|
57
|
+
isExpanded: boolean;
|
|
58
|
+
isFocused: boolean;
|
|
59
|
+
isFolder: boolean;
|
|
60
|
+
isLoading: boolean;
|
|
61
|
+
isMatchingSearch: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type TreeRowSlot<T> = (props: TreeRowRenderProps<T>) => ReactNode;
|
|
65
|
+
|
|
66
|
+
export type TreeContextMenuSlot<T> = (
|
|
67
|
+
props: TreeRowRenderProps<T>,
|
|
68
|
+
trigger: ReactNode,
|
|
69
|
+
) => ReactNode;
|
|
70
|
+
|
|
71
|
+
export interface TreeRootProps<T> {
|
|
72
|
+
/** Root nodes. Top-level items are rendered directly (no synthetic root). */
|
|
73
|
+
data: TreeNode<T>[];
|
|
74
|
+
/** Returns the human-readable name for a node (used by search/type-ahead). */
|
|
75
|
+
getItemName: (node: TreeNode<T>) => string;
|
|
76
|
+
|
|
77
|
+
/** Async loader for folders without inline `children`. */
|
|
78
|
+
loadChildren?: TreeLoadChildren<T>;
|
|
79
|
+
|
|
80
|
+
/** Selection behaviour. Default: `'single'`. */
|
|
81
|
+
selectionMode?: TreeSelectionMode;
|
|
82
|
+
/** Initially expanded ids. */
|
|
83
|
+
initialExpandedIds?: TreeItemId[];
|
|
84
|
+
/** Initially selected ids. */
|
|
85
|
+
initialSelectedIds?: TreeItemId[];
|
|
86
|
+
/** Pixels of indent per nesting level. Default: 16. (Shortcut for `appearance.indent`.) */
|
|
87
|
+
indent?: number;
|
|
88
|
+
/** Cosmetic configuration: density, sizes, accent intensity, radius. */
|
|
89
|
+
appearance?: TreeAppearance;
|
|
90
|
+
|
|
91
|
+
/** Triggered when selection changes. */
|
|
92
|
+
onSelectionChange?: (selectedIds: TreeItemId[]) => void;
|
|
93
|
+
/** Triggered when expanded set changes. */
|
|
94
|
+
onExpansionChange?: (expandedIds: TreeItemId[]) => void;
|
|
95
|
+
/** Enter / dblclick on a node. */
|
|
96
|
+
onActivate?: (node: TreeNode<T>) => void;
|
|
97
|
+
|
|
98
|
+
/** Show built-in search input. Default: false. */
|
|
99
|
+
enableSearch?: boolean;
|
|
100
|
+
/** Type printable letters to jump to a matching name. Default: true. */
|
|
101
|
+
enableTypeAhead?: boolean;
|
|
102
|
+
/** Render vertical indent guides under expanded folders. Default: false. */
|
|
103
|
+
showIndentGuides?: boolean;
|
|
104
|
+
|
|
105
|
+
/** Custom row renderer. Falls back to the default <TreeRow />. */
|
|
106
|
+
renderRow?: TreeRowSlot<T>;
|
|
107
|
+
/** Replace default folder/file icon. */
|
|
108
|
+
renderIcon?: TreeRowSlot<T>;
|
|
109
|
+
/** Replace default label rendering. */
|
|
110
|
+
renderLabel?: TreeRowSlot<T>;
|
|
111
|
+
/** Right-side actions slot (per row). */
|
|
112
|
+
renderActions?: TreeRowSlot<T>;
|
|
113
|
+
/** Wrap each row in a context menu (right-click). Receives the row meta + trigger element. */
|
|
114
|
+
renderContextMenu?: TreeContextMenuSlot<T>;
|
|
115
|
+
|
|
116
|
+
/** Override built-in copy in your locale. */
|
|
117
|
+
labels?: Partial<TreeLabels>;
|
|
118
|
+
/** Persist expanded + (optional) selected ids in localStorage under this key. */
|
|
119
|
+
persistKey?: string;
|
|
120
|
+
/** Persist selection alongside expansion. Default: false. */
|
|
121
|
+
persistSelection?: boolean;
|
|
122
|
+
|
|
123
|
+
className?: string;
|
|
124
|
+
style?: React.CSSProperties;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Internal flat-row representation used by the renderer + keyboard nav. */
|
|
128
|
+
export interface FlatRow<T> {
|
|
129
|
+
node: TreeNode<T>;
|
|
130
|
+
level: number;
|
|
131
|
+
parentId: TreeItemId | null;
|
|
132
|
+
isFolder: boolean;
|
|
133
|
+
isExpanded: boolean;
|
|
134
|
+
isLoading: boolean;
|
|
135
|
+
hasError: boolean;
|
|
136
|
+
}
|
package/src/tools/index.ts
CHANGED
|
@@ -162,6 +162,81 @@ export type {
|
|
|
162
162
|
MentionMarkdownRenderer,
|
|
163
163
|
} from './MarkdownEditor';
|
|
164
164
|
|
|
165
|
+
// Export Tree (decomposed shadcn-style tree, our own engine)
|
|
166
|
+
export {
|
|
167
|
+
TreeRoot,
|
|
168
|
+
Tree,
|
|
169
|
+
TreeProvider,
|
|
170
|
+
useTreeContext,
|
|
171
|
+
useTreeLabels,
|
|
172
|
+
useTreeRows,
|
|
173
|
+
useTreeSelection,
|
|
174
|
+
useTreeExpansion,
|
|
175
|
+
useTreeFocus,
|
|
176
|
+
useTreeSearch,
|
|
177
|
+
useTreeActions,
|
|
178
|
+
useTreeTypeAhead,
|
|
179
|
+
useTreeKeyboard,
|
|
180
|
+
TreeContent,
|
|
181
|
+
TreeRow,
|
|
182
|
+
TreeChevron,
|
|
183
|
+
TreeIcon,
|
|
184
|
+
TreeLabel,
|
|
185
|
+
TreeSearchInput,
|
|
186
|
+
TreeEmpty,
|
|
187
|
+
TreeSkeleton,
|
|
188
|
+
TreeError,
|
|
189
|
+
TreeIndentGuides,
|
|
190
|
+
createChildCache,
|
|
191
|
+
resolveChildren,
|
|
192
|
+
flattenTree,
|
|
193
|
+
loadTreeState,
|
|
194
|
+
saveTreeState,
|
|
195
|
+
clearTreeState,
|
|
196
|
+
createDemoTree,
|
|
197
|
+
DEFAULT_TREE_LABELS,
|
|
198
|
+
DEFAULT_TREE_APPEARANCE,
|
|
199
|
+
resolveAppearance,
|
|
200
|
+
appearanceToStyle,
|
|
201
|
+
} from './Tree';
|
|
202
|
+
export type {
|
|
203
|
+
TreeRootProps,
|
|
204
|
+
TreeProviderProps,
|
|
205
|
+
TreeContextValue,
|
|
206
|
+
TreeContextMenuSlot,
|
|
207
|
+
TreeContentProps,
|
|
208
|
+
TreeRowProps,
|
|
209
|
+
TreeChevronProps,
|
|
210
|
+
TreeIconProps,
|
|
211
|
+
TreeLabelProps,
|
|
212
|
+
TreeSearchInputProps,
|
|
213
|
+
TreeEmptyProps,
|
|
214
|
+
TreeSkeletonProps,
|
|
215
|
+
TreeErrorProps,
|
|
216
|
+
TreeIndentGuidesProps,
|
|
217
|
+
TreeNode,
|
|
218
|
+
TreeItemId,
|
|
219
|
+
TreeLabels,
|
|
220
|
+
TreeSelectionMode,
|
|
221
|
+
TreeRowRenderProps,
|
|
222
|
+
TreeRowSlot,
|
|
223
|
+
TreeLoadChildren,
|
|
224
|
+
FlatRow,
|
|
225
|
+
ChildCache,
|
|
226
|
+
ChildEntry,
|
|
227
|
+
ChildEntryStatus,
|
|
228
|
+
FlattenInput,
|
|
229
|
+
PersistedTreeState,
|
|
230
|
+
UseTreeTypeAheadOptions,
|
|
231
|
+
UseTreeKeyboardOptions,
|
|
232
|
+
DemoNode,
|
|
233
|
+
TreeAppearance,
|
|
234
|
+
ResolvedAppearance,
|
|
235
|
+
TreeDensity,
|
|
236
|
+
TreeAccentIntensity,
|
|
237
|
+
TreeRadius,
|
|
238
|
+
} from './Tree';
|
|
239
|
+
|
|
165
240
|
// Export Media Cache Store
|
|
166
241
|
export {
|
|
167
242
|
useMediaCacheStore,
|