@enonic/ui 0.26.0 → 0.27.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/enonic-ui.cjs +1 -1
- package/dist/enonic-ui.es.js +104 -93
- package/dist/styles/preset.css +1 -1
- package/dist/styles/style.css +1 -1
- package/dist/styles/tokens.css +1 -1
- package/dist/styles/utilities.css +1 -1
- package/dist/types/components/icon-button/icon-button.d.ts +1 -1
- package/dist/types/components/index.d.ts +2 -0
- package/dist/types/components/skeleton/index.d.ts +1 -0
- package/dist/types/components/skeleton/skeleton.d.ts +26 -0
- package/dist/types/components/tree-list/index.d.ts +2 -1
- package/dist/types/components/tree-list/tree-list.d.ts +141 -106
- package/dist/types/components/virtualized-tree-list/index.d.ts +2 -0
- package/dist/types/components/virtualized-tree-list/virtualized-tree-list.d.ts +195 -0
- package/dist/types/hooks/index.d.ts +1 -0
- package/dist/types/hooks/use-item-registry.d.ts +5 -0
- package/dist/types/hooks/use-virtualized-keyboard-navigation.d.ts +81 -0
- package/dist/types/icons/circle-disc.d.ts +7 -0
- package/dist/types/icons/filled-circle-alert.d.ts +8 -0
- package/dist/types/icons/filled-circle-check.d.ts +8 -0
- package/dist/types/icons/filled-circle-info.d.ts +8 -0
- package/dist/types/icons/filled-circle-x.d.ts +8 -0
- package/dist/types/icons/filled-square-check.d.ts +8 -0
- package/dist/types/icons/filled-square-minus.d.ts +8 -0
- package/dist/types/icons/index.d.ts +7 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/providers/index.d.ts +1 -0
- package/dist/types/providers/tree-list-provider.d.ts +30 -17
- package/dist/types/providers/virtualized-tree-list-provider.d.ts +26 -0
- package/package.json +11 -7
|
@@ -1,141 +1,176 @@
|
|
|
1
1
|
import { ComponentPropsWithoutRef, ReactElement, ReactNode } from 'react';
|
|
2
2
|
import { IconButtonProps } from '../icon-button';
|
|
3
|
+
import { SelectionMode } from '../../providers/tree-list-provider';
|
|
3
4
|
import { LucideIcon } from '../../types';
|
|
4
|
-
export declare const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
export type
|
|
11
|
-
nodes: Record<string, TreeData | undefined>;
|
|
12
|
-
children: Record<string, string[] | undefined>;
|
|
13
|
-
hasMore: Record<string, boolean | undefined>;
|
|
14
|
-
};
|
|
15
|
-
export type FlatTreeNode<TData extends TreeData> = {
|
|
16
|
-
id: string;
|
|
17
|
-
data: TData;
|
|
18
|
-
level: number;
|
|
19
|
-
parentId: string | null;
|
|
20
|
-
nodeType: 'node' | 'loading' | 'error';
|
|
21
|
-
};
|
|
22
|
-
export type TreeListProps<TData extends TreeData = TreeData> = {
|
|
23
|
-
className?: string;
|
|
24
|
-
fetchChildren: (parentId: string | undefined, offset: number) => Promise<{
|
|
25
|
-
items: TData[];
|
|
26
|
-
hasMore: boolean;
|
|
27
|
-
}>;
|
|
28
|
-
expanded?: ReadonlySet<string>;
|
|
29
|
-
onExpandedChange?: (expanded: ReadonlySet<string>) => void;
|
|
5
|
+
export declare const treeListRowVariants: (props?: ({
|
|
6
|
+
active?: boolean | null | undefined;
|
|
7
|
+
selected?: boolean | null | undefined;
|
|
8
|
+
disabled?: boolean | null | undefined;
|
|
9
|
+
selectable?: boolean | null | undefined;
|
|
10
|
+
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
11
|
+
export type TreeListRootProps = {
|
|
30
12
|
selection?: ReadonlySet<string>;
|
|
13
|
+
defaultSelection?: ReadonlySet<string>;
|
|
31
14
|
onSelectionChange?: (selection: ReadonlySet<string>) => void;
|
|
32
|
-
selectionMode?:
|
|
33
|
-
active?: string
|
|
15
|
+
selectionMode?: SelectionMode;
|
|
16
|
+
active?: string;
|
|
34
17
|
defaultActive?: string;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
onItemsChange?: (items: TreeItems<TData>) => void;
|
|
18
|
+
onActiveChange?: (active: string | undefined) => void;
|
|
19
|
+
loop?: boolean;
|
|
20
|
+
className?: string;
|
|
39
21
|
children?: ReactNode;
|
|
22
|
+
onActivate?: (id: string) => void;
|
|
23
|
+
getParentId?: (id: string) => string | undefined;
|
|
24
|
+
getFirstChildId?: (id: string) => string | undefined;
|
|
25
|
+
expanded?: ReadonlySet<string>;
|
|
26
|
+
onExpandedChange?: (expanded: ReadonlySet<string>) => void;
|
|
40
27
|
} & ComponentPropsWithoutRef<'div'>;
|
|
41
28
|
export type TreeListContainerProps = {
|
|
42
29
|
children?: ReactNode;
|
|
43
30
|
className?: string;
|
|
44
31
|
} & ComponentPropsWithoutRef<'div'>;
|
|
45
|
-
export type
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
children
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
32
|
+
export type TreeListRowProps = {
|
|
33
|
+
id: string;
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
selectable?: boolean;
|
|
36
|
+
/** ARIA level for tree hierarchy (1-based, optional for accessibility) */
|
|
37
|
+
level?: number;
|
|
38
|
+
/** Whether this node has children (affects aria-expanded) */
|
|
39
|
+
hasChildren?: boolean;
|
|
40
|
+
/** Whether this node is expanded (required if hasChildren=true) */
|
|
41
|
+
expanded?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Position of this item within its siblings (1-indexed).
|
|
44
|
+
* Used for `aria-posinset`. Optional - only set if you have this data.
|
|
45
|
+
*/
|
|
46
|
+
posinset?: number;
|
|
47
|
+
/**
|
|
48
|
+
* Total number of siblings at this level.
|
|
49
|
+
* Used for `aria-setsize`. Optional - only set if you have this data.
|
|
50
|
+
*/
|
|
51
|
+
setsize?: number;
|
|
57
52
|
className?: string;
|
|
58
|
-
|
|
53
|
+
children?: ReactNode;
|
|
59
54
|
} & ComponentPropsWithoutRef<'div'>;
|
|
60
|
-
export type TreeListContentProps<TData extends TreeData> = {
|
|
61
|
-
renderNode: (item: FlatTreeNode<TData>) => ReactNode;
|
|
62
|
-
renderLoading?: (item: FlatTreeNode<TData>) => ReactNode;
|
|
63
|
-
renderError?: (item: FlatTreeNode<TData>) => ReactNode;
|
|
64
|
-
};
|
|
65
55
|
export type TreeListRowLeftProps = {
|
|
66
56
|
children?: ReactNode;
|
|
67
57
|
className?: string;
|
|
68
58
|
} & ComponentPropsWithoutRef<'div'>;
|
|
59
|
+
export declare const TreeListRowLeft: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLeftProps> & {
|
|
60
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
61
|
+
}>;
|
|
69
62
|
export type TreeListRowRightProps = {
|
|
70
63
|
children?: ReactNode;
|
|
71
64
|
className?: string;
|
|
72
65
|
} & ComponentPropsWithoutRef<'div'>;
|
|
66
|
+
export declare const TreeListRowRight: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowRightProps> & {
|
|
67
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
68
|
+
}>;
|
|
69
|
+
export type TreeListRowContentProps = {
|
|
70
|
+
children?: ReactNode;
|
|
71
|
+
className?: string;
|
|
72
|
+
} & ComponentPropsWithoutRef<'div'>;
|
|
73
|
+
export declare const TreeListRowContent: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowContentProps> & {
|
|
74
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
75
|
+
}>;
|
|
76
|
+
export type TreeListActionProps = {
|
|
77
|
+
/** Interactive element to exclude from normal tab order (use F2 action mode) */
|
|
78
|
+
children: ReactElement;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Wrapper for interactive elements inside TreeList rows.
|
|
82
|
+
* Removes the element from normal tab order (tabIndex={-1}) so it's only
|
|
83
|
+
* accessible via F2 action mode.
|
|
84
|
+
*/
|
|
85
|
+
export declare const TreeListAction: {
|
|
86
|
+
({ children }: TreeListActionProps): ReactElement;
|
|
87
|
+
displayName: string;
|
|
88
|
+
};
|
|
73
89
|
export type TreeListRowLevelSpacerProps = {
|
|
74
90
|
level?: number;
|
|
75
91
|
className?: string;
|
|
76
92
|
} & ComponentPropsWithoutRef<'div'>;
|
|
77
|
-
export
|
|
78
|
-
|
|
93
|
+
export declare const TreeListRowLevelSpacer: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLevelSpacerProps> & {
|
|
94
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
95
|
+
}>;
|
|
96
|
+
export type TreeListRowExpandControlProps = {
|
|
97
|
+
/** Row ID - if provided, clicking will also set this row as active */
|
|
98
|
+
rowId?: string;
|
|
99
|
+
expanded?: boolean;
|
|
100
|
+
hasChildren?: boolean;
|
|
101
|
+
onToggle?: () => void;
|
|
79
102
|
icon?: LucideIcon;
|
|
80
|
-
|
|
81
|
-
export type TreeListRowContentProps = {
|
|
82
|
-
children?: ReactNode;
|
|
103
|
+
selected?: boolean;
|
|
83
104
|
className?: string;
|
|
84
|
-
} &
|
|
85
|
-
export
|
|
86
|
-
|
|
105
|
+
} & Omit<IconButtonProps, 'icon' | 'onClick'>;
|
|
106
|
+
export declare const TreeListRowExpandControl: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowExpandControlProps> & {
|
|
107
|
+
ref?: import('preact').Ref<HTMLButtonElement> | undefined;
|
|
108
|
+
}>;
|
|
109
|
+
export type TreeListRowSelectionControlProps = {
|
|
110
|
+
/** Row ID - required for toggle selection to work */
|
|
111
|
+
rowId: string;
|
|
112
|
+
/** Override selection state. If not provided, reads from TreeList selection context. */
|
|
113
|
+
selected?: boolean;
|
|
114
|
+
selectable?: boolean;
|
|
87
115
|
className?: string;
|
|
116
|
+
} & Omit<ComponentPropsWithoutRef<'div'>, 'onClick'>;
|
|
117
|
+
export declare const TreeListRowSelectionControl: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowSelectionControlProps> & {
|
|
118
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
119
|
+
}>;
|
|
120
|
+
export type TreeListRowLoadingProps = {
|
|
121
|
+
level?: number;
|
|
122
|
+
className?: string;
|
|
123
|
+
children?: ReactNode;
|
|
88
124
|
} & ComponentPropsWithoutRef<'div'>;
|
|
89
|
-
export
|
|
90
|
-
|
|
91
|
-
|
|
125
|
+
export declare const TreeListRowLoading: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLoadingProps> & {
|
|
126
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
127
|
+
}>;
|
|
128
|
+
export type TreeListRowPlaceholderProps = {
|
|
129
|
+
level?: number;
|
|
92
130
|
className?: string;
|
|
131
|
+
children?: ReactNode;
|
|
93
132
|
} & ComponentPropsWithoutRef<'div'>;
|
|
94
|
-
export declare const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
({
|
|
135
|
-
displayName: string;
|
|
136
|
-
};
|
|
137
|
-
RowSelectionControl: {
|
|
138
|
-
<TData extends TreeData>({ data, className, ...props }: TreeListRowSelectionControlProps<TData>): ReactElement;
|
|
133
|
+
export declare const TreeListRowPlaceholder: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowPlaceholderProps> & {
|
|
134
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
135
|
+
}>;
|
|
136
|
+
export declare const TreeList: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRootProps> & {
|
|
137
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
138
|
+
}> & {
|
|
139
|
+
Root: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRootProps> & {
|
|
140
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
141
|
+
}>;
|
|
142
|
+
Container: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListContainerProps> & {
|
|
143
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
144
|
+
}>;
|
|
145
|
+
Row: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowProps> & {
|
|
146
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
147
|
+
}>;
|
|
148
|
+
RowLeft: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLeftProps> & {
|
|
149
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
150
|
+
}>;
|
|
151
|
+
RowRight: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowRightProps> & {
|
|
152
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
153
|
+
}>;
|
|
154
|
+
RowContent: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowContentProps> & {
|
|
155
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
156
|
+
}>;
|
|
157
|
+
RowLevelSpacer: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLevelSpacerProps> & {
|
|
158
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
159
|
+
}>;
|
|
160
|
+
RowExpandControl: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowExpandControlProps> & {
|
|
161
|
+
ref?: import('preact').Ref<HTMLButtonElement> | undefined;
|
|
162
|
+
}>;
|
|
163
|
+
RowSelectionControl: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowSelectionControlProps> & {
|
|
164
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
165
|
+
}>;
|
|
166
|
+
RowLoading: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLoadingProps> & {
|
|
167
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
168
|
+
}>;
|
|
169
|
+
RowPlaceholder: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowPlaceholderProps> & {
|
|
170
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
171
|
+
}>;
|
|
172
|
+
Action: {
|
|
173
|
+
({ children }: TreeListActionProps): ReactElement;
|
|
139
174
|
displayName: string;
|
|
140
175
|
};
|
|
141
176
|
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type { FlatNode, VirtualizedTreeListItemProps, VirtualizedTreeListRenderProps, VirtualizedTreeListRootProps, VirtualizedTreeListRowContentProps, VirtualizedTreeListRowExpandControlProps, VirtualizedTreeListRowLeftProps, VirtualizedTreeListRowLevelSpacerProps, VirtualizedTreeListRowLoadingProps, VirtualizedTreeListRowPlaceholderProps, VirtualizedTreeListRowProps, VirtualizedTreeListRowRightProps, VirtualizedTreeListRowSelectionControlProps, VirtuosoHandle, } from './virtualized-tree-list';
|
|
2
|
+
export { VirtualizedTreeList } from './virtualized-tree-list';
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef, ReactElement, ReactNode, RefObject } from 'react';
|
|
2
|
+
import { IconButtonProps } from '../icon-button';
|
|
3
|
+
import { TreeListRowContentProps, TreeListRowLeftProps, TreeListRowLevelSpacerProps, TreeListRowLoadingProps, TreeListRowPlaceholderProps, TreeListRowRightProps } from '../tree-list/tree-list';
|
|
4
|
+
import { LucideIcon } from '../../types';
|
|
5
|
+
/**
|
|
6
|
+
* Flat node type for virtualized tree list.
|
|
7
|
+
* This represents a single node in a flattened tree structure.
|
|
8
|
+
*/
|
|
9
|
+
export type FlatNode<TData = unknown> = {
|
|
10
|
+
/** Unique identifier for the node */
|
|
11
|
+
id: string;
|
|
12
|
+
/** User data associated with the node */
|
|
13
|
+
data: TData;
|
|
14
|
+
/** Nesting level (1 = root level) */
|
|
15
|
+
level: number;
|
|
16
|
+
/** Parent node ID, null for root nodes */
|
|
17
|
+
parentId: string | null;
|
|
18
|
+
/** Whether the node has children */
|
|
19
|
+
hasChildren: boolean;
|
|
20
|
+
/** Whether the node is currently expanded */
|
|
21
|
+
isExpanded: boolean;
|
|
22
|
+
/** Whether the node is in a loading state */
|
|
23
|
+
isLoading?: boolean;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Props returned by getItemProps for a row item.
|
|
27
|
+
*/
|
|
28
|
+
export type VirtualizedTreeListItemProps = {
|
|
29
|
+
id: string;
|
|
30
|
+
'data-index': number;
|
|
31
|
+
role: 'treeitem';
|
|
32
|
+
'aria-selected': boolean | undefined;
|
|
33
|
+
'aria-expanded': boolean | undefined;
|
|
34
|
+
'aria-level': number;
|
|
35
|
+
onClick: (e: React.MouseEvent<HTMLElement>) => void;
|
|
36
|
+
active: boolean;
|
|
37
|
+
selected: boolean;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Props passed to the render function.
|
|
41
|
+
*/
|
|
42
|
+
export type VirtualizedTreeListRenderProps<TData> = {
|
|
43
|
+
/** The flat list of nodes to render */
|
|
44
|
+
items: readonly FlatNode<TData>[];
|
|
45
|
+
/** Function to get props for each row item */
|
|
46
|
+
getItemProps: (index: number, node: FlatNode<TData>) => VirtualizedTreeListItemProps;
|
|
47
|
+
/** Current active item index */
|
|
48
|
+
activeIndex: number | null;
|
|
49
|
+
/** Props to spread on the Virtuoso container for keyboard navigation and ARIA */
|
|
50
|
+
containerProps: {
|
|
51
|
+
role: 'tree';
|
|
52
|
+
'aria-label'?: string;
|
|
53
|
+
'aria-activedescendant': string | undefined;
|
|
54
|
+
'aria-multiselectable': boolean | undefined;
|
|
55
|
+
tabIndex: 0;
|
|
56
|
+
onKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;
|
|
57
|
+
onFocus: () => void;
|
|
58
|
+
onBlur: () => void;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Virtuoso handle type for scroll operations.
|
|
63
|
+
* This matches the VirtuosoHandle from react-virtuoso.
|
|
64
|
+
*/
|
|
65
|
+
export type VirtuosoHandle = {
|
|
66
|
+
scrollToIndex: (location: number | {
|
|
67
|
+
index: number;
|
|
68
|
+
align?: 'start' | 'center' | 'end';
|
|
69
|
+
behavior?: 'auto' | 'smooth';
|
|
70
|
+
}) => void;
|
|
71
|
+
scrollIntoView?: (location: {
|
|
72
|
+
index: number;
|
|
73
|
+
align?: 'start' | 'center' | 'end';
|
|
74
|
+
behavior?: 'auto' | 'smooth';
|
|
75
|
+
}) => void;
|
|
76
|
+
};
|
|
77
|
+
export type VirtualizedTreeListRootProps<TData = unknown> = {
|
|
78
|
+
/** Flat list of tree nodes to render */
|
|
79
|
+
items: readonly FlatNode<TData>[];
|
|
80
|
+
/** Controlled selection state */
|
|
81
|
+
selection?: ReadonlySet<string>;
|
|
82
|
+
/** Default selection for uncontrolled mode */
|
|
83
|
+
defaultSelection?: ReadonlySet<string>;
|
|
84
|
+
/** Callback when selection changes */
|
|
85
|
+
onSelectionChange?: (selection: ReadonlySet<string>) => void;
|
|
86
|
+
/** Selection mode: 'single', 'multiple', or 'none' (navigation only) */
|
|
87
|
+
selectionMode?: 'single' | 'multiple' | 'none';
|
|
88
|
+
/** Controlled active item ID (null = no active item in controlled mode) */
|
|
89
|
+
active?: string | null;
|
|
90
|
+
/** Default active item ID for uncontrolled mode */
|
|
91
|
+
defaultActive?: string;
|
|
92
|
+
/** Callback when active item changes (null = no active item) */
|
|
93
|
+
onActiveChange?: (active: string | null) => void;
|
|
94
|
+
/** Callback when a node should be expanded */
|
|
95
|
+
onExpand?: (id: string) => void;
|
|
96
|
+
/** Callback when a node should be collapsed */
|
|
97
|
+
onCollapse?: (id: string) => void;
|
|
98
|
+
/** Callback when an item is activated (Enter key or double-click) */
|
|
99
|
+
onActivate?: (id: string) => void;
|
|
100
|
+
/** Ref to Virtuoso component for scroll operations */
|
|
101
|
+
virtuosoRef?: RefObject<VirtuosoHandle | null>;
|
|
102
|
+
/** Whether navigation should loop at start/end */
|
|
103
|
+
loop?: boolean;
|
|
104
|
+
/** Accessible label for the tree */
|
|
105
|
+
'aria-label'?: string;
|
|
106
|
+
/** Render function that receives items and helper props */
|
|
107
|
+
children: (props: VirtualizedTreeListRenderProps<TData>) => ReactNode;
|
|
108
|
+
} & Omit<ComponentPropsWithoutRef<'div'>, 'children'>;
|
|
109
|
+
export type VirtualizedTreeListRowProps = {
|
|
110
|
+
/** Whether this row is the active (focused) row */
|
|
111
|
+
active?: boolean;
|
|
112
|
+
/** Whether this row is selected */
|
|
113
|
+
selected?: boolean;
|
|
114
|
+
/** Whether this row is disabled */
|
|
115
|
+
disabled?: boolean;
|
|
116
|
+
/** Whether this row is selectable */
|
|
117
|
+
selectable?: boolean;
|
|
118
|
+
/** Additional class names */
|
|
119
|
+
className?: string;
|
|
120
|
+
/** Row content */
|
|
121
|
+
children?: ReactNode;
|
|
122
|
+
} & ComponentPropsWithoutRef<'div'>;
|
|
123
|
+
export type VirtualizedTreeListActionProps = {
|
|
124
|
+
/** Interactive element to exclude from normal tab order (use F2 action mode) */
|
|
125
|
+
children: ReactElement;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Wrapper for interactive elements inside VirtualizedTreeList rows.
|
|
129
|
+
* Removes the element from normal tab order (tabIndex={-1}) so it's only
|
|
130
|
+
* accessible via F2 action mode.
|
|
131
|
+
*/
|
|
132
|
+
export declare const VirtualizedTreeListAction: {
|
|
133
|
+
({ children }: VirtualizedTreeListActionProps): ReactElement;
|
|
134
|
+
displayName: string;
|
|
135
|
+
};
|
|
136
|
+
export type VirtualizedTreeListRowExpandControlProps = {
|
|
137
|
+
/** Row ID - if provided, clicking will also set this row as active */
|
|
138
|
+
rowId?: string;
|
|
139
|
+
expanded?: boolean;
|
|
140
|
+
hasChildren?: boolean;
|
|
141
|
+
onToggle?: () => void;
|
|
142
|
+
icon?: LucideIcon;
|
|
143
|
+
selected?: boolean;
|
|
144
|
+
className?: string;
|
|
145
|
+
} & Omit<IconButtonProps, 'icon' | 'onClick'>;
|
|
146
|
+
export declare const VirtualizedTreeListRowExpandControl: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<VirtualizedTreeListRowExpandControlProps> & {
|
|
147
|
+
ref?: import('preact').Ref<HTMLButtonElement> | undefined;
|
|
148
|
+
}>;
|
|
149
|
+
export type VirtualizedTreeListRowSelectionControlProps = {
|
|
150
|
+
/** Row ID - required for toggle selection to work */
|
|
151
|
+
rowId: string;
|
|
152
|
+
/** Override selection state. If not provided, reads from VirtualizedTreeList selection context. */
|
|
153
|
+
selected?: boolean;
|
|
154
|
+
selectable?: boolean;
|
|
155
|
+
className?: string;
|
|
156
|
+
} & Omit<ComponentPropsWithoutRef<'div'>, 'onClick'>;
|
|
157
|
+
export declare const VirtualizedTreeListRowSelectionControl: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<VirtualizedTreeListRowSelectionControlProps> & {
|
|
158
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
159
|
+
}>;
|
|
160
|
+
export declare const VirtualizedTreeList: (<TData = unknown>(props: VirtualizedTreeListRootProps<TData> & {
|
|
161
|
+
ref?: React.ForwardedRef<HTMLDivElement>;
|
|
162
|
+
}) => ReactElement) & {
|
|
163
|
+
Row: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<VirtualizedTreeListRowProps> & {
|
|
164
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
165
|
+
}>;
|
|
166
|
+
RowLeft: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLeftProps> & {
|
|
167
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
168
|
+
}>;
|
|
169
|
+
RowRight: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowRightProps> & {
|
|
170
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
171
|
+
}>;
|
|
172
|
+
RowContent: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowContentProps> & {
|
|
173
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
174
|
+
}>;
|
|
175
|
+
RowLevelSpacer: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLevelSpacerProps> & {
|
|
176
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
177
|
+
}>;
|
|
178
|
+
RowExpandControl: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<VirtualizedTreeListRowExpandControlProps> & {
|
|
179
|
+
ref?: import('preact').Ref<HTMLButtonElement> | undefined;
|
|
180
|
+
}>;
|
|
181
|
+
RowSelectionControl: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<VirtualizedTreeListRowSelectionControlProps> & {
|
|
182
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
183
|
+
}>;
|
|
184
|
+
RowLoading: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowLoadingProps> & {
|
|
185
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
186
|
+
}>;
|
|
187
|
+
RowPlaceholder: import('preact').FunctionalComponent<import('preact/compat').PropsWithoutRef<TreeListRowPlaceholderProps> & {
|
|
188
|
+
ref?: import('preact').Ref<HTMLDivElement> | undefined;
|
|
189
|
+
}>;
|
|
190
|
+
Action: {
|
|
191
|
+
({ children }: VirtualizedTreeListActionProps): ReactElement;
|
|
192
|
+
displayName: string;
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
export type { TreeListRowContentProps as VirtualizedTreeListRowContentProps, TreeListRowLeftProps as VirtualizedTreeListRowLeftProps, TreeListRowLevelSpacerProps as VirtualizedTreeListRowLevelSpacerProps, TreeListRowLoadingProps as VirtualizedTreeListRowLoadingProps, TreeListRowPlaceholderProps as VirtualizedTreeListRowPlaceholderProps, TreeListRowRightProps as VirtualizedTreeListRowRightProps, };
|
|
@@ -13,3 +13,4 @@ export { useScrollLock } from './use-scroll-lock';
|
|
|
13
13
|
export { type UseSelectorKeyboardConfig, type UseSelectorKeyboardReturn, useSelectorKeyboard, } from './use-selector-keyboard';
|
|
14
14
|
export { useSyncValue } from './use-sync-value';
|
|
15
15
|
export { type UseTypeAheadConfig, type UseTypeAheadReturn, useTypeAhead } from './use-type-ahead';
|
|
16
|
+
export { type FlatNodeBase, type UseVirtualizedKeyboardNavigationReturn, useVirtualizedKeyboardNavigation, type VirtualizedKeyboardNavigationConfig, } from './use-virtualized-keyboard-navigation';
|
|
@@ -24,6 +24,11 @@ export type UseItemRegistryReturn = {
|
|
|
24
24
|
* @returns True if the item is disabled
|
|
25
25
|
*/
|
|
26
26
|
isItemDisabled: (id: string) => boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Version counter that increments when items are registered or unregistered.
|
|
29
|
+
* Use as a dependency in useEffect to react to item changes.
|
|
30
|
+
*/
|
|
31
|
+
registryVersion: number;
|
|
27
32
|
};
|
|
28
33
|
/**
|
|
29
34
|
* Hook for managing a registry of items (menu items, listbox options, etc.).
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export type FlatNodeBase = {
|
|
2
|
+
id: string;
|
|
3
|
+
level: number;
|
|
4
|
+
parentId: string | null;
|
|
5
|
+
hasChildren: boolean;
|
|
6
|
+
isExpanded: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type VirtualizedKeyboardNavigationConfig<TNode extends FlatNodeBase> = {
|
|
9
|
+
/**
|
|
10
|
+
* Flat list of all visible tree nodes
|
|
11
|
+
*/
|
|
12
|
+
items: readonly TNode[];
|
|
13
|
+
/**
|
|
14
|
+
* Currently active item index
|
|
15
|
+
*/
|
|
16
|
+
activeIndex: number | null;
|
|
17
|
+
/**
|
|
18
|
+
* Set the active item index
|
|
19
|
+
*/
|
|
20
|
+
setActiveIndex: (index: number | null) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Scroll to index using virtuoso's scrollToIndex API
|
|
23
|
+
*/
|
|
24
|
+
scrollToIndex: (index: number) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Called when user requests expand (ArrowRight on collapsed node with children)
|
|
27
|
+
*/
|
|
28
|
+
onExpand?: (id: string) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Called when user requests collapse (ArrowLeft on expanded node)
|
|
31
|
+
*/
|
|
32
|
+
onCollapse?: (id: string) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Called when user requests selection (Enter/Space)
|
|
35
|
+
*/
|
|
36
|
+
onSelect?: (id: string, index: number) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Called when user presses Escape
|
|
39
|
+
*/
|
|
40
|
+
onEscape?: () => void;
|
|
41
|
+
/**
|
|
42
|
+
* Whether to loop navigation at start/end
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
loop?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Check if an item is disabled
|
|
48
|
+
* @default () => false
|
|
49
|
+
*/
|
|
50
|
+
isItemDisabled?: (node: TNode) => boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Returns the number of items to move for PageUp/PageDown navigation.
|
|
53
|
+
* If not provided, defaults to 10.
|
|
54
|
+
*/
|
|
55
|
+
getPageSize?: () => number;
|
|
56
|
+
};
|
|
57
|
+
export type UseVirtualizedKeyboardNavigationReturn = {
|
|
58
|
+
/**
|
|
59
|
+
* Move active item by delta (1 for next, -1 for previous)
|
|
60
|
+
*/
|
|
61
|
+
moveActive: (delta: number) => void;
|
|
62
|
+
/**
|
|
63
|
+
* Keyboard event handler to attach to the container
|
|
64
|
+
*/
|
|
65
|
+
handleKeyDown: (e: React.KeyboardEvent<HTMLElement>) => void;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Hook for keyboard navigation through a virtualized tree list.
|
|
69
|
+
* Works with array indices instead of DOM IDs since items may not be in DOM.
|
|
70
|
+
*
|
|
71
|
+
* Supports:
|
|
72
|
+
* - ArrowUp/ArrowDown for moving between items
|
|
73
|
+
* - ArrowRight for expand or move to first child
|
|
74
|
+
* - ArrowLeft for collapse or move to parent
|
|
75
|
+
* - Home/End keys for jumping to first/last
|
|
76
|
+
* - Enter/Space for selection
|
|
77
|
+
* - Escape key handling
|
|
78
|
+
* - Loop navigation (optional)
|
|
79
|
+
* - Disabled item skipping
|
|
80
|
+
*/
|
|
81
|
+
export declare function useVirtualizedKeyboardNavigation<TNode extends FlatNodeBase>(config: VirtualizedKeyboardNavigationConfig<TNode>): UseVirtualizedKeyboardNavigationReturn;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
/**
|
|
3
|
+
* A filled circle with an alert sign inside.
|
|
4
|
+
* Useful for representing warning states.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FilledCircleAlert: LucideIcon;
|
|
7
|
+
/** @alias FilledCircleAlert */
|
|
8
|
+
export declare const FilledCircleAlertIcon: LucideIcon;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
/**
|
|
3
|
+
* A filled circle with a checkmark sign inside.
|
|
4
|
+
* Useful for representing success states.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FilledCircleCheck: LucideIcon;
|
|
7
|
+
/** @alias FilledCircleCheck */
|
|
8
|
+
export declare const FilledCircleCheckIcon: LucideIcon;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
/**
|
|
3
|
+
* A filled circle with an info sign inside.
|
|
4
|
+
* Useful for representing info states.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FilledCircleInfo: LucideIcon;
|
|
7
|
+
/** @alias FilledCircleInfo */
|
|
8
|
+
export declare const FilledCircleInfoIcon: LucideIcon;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
/**
|
|
3
|
+
* A filled circle with an X sign inside.
|
|
4
|
+
* Useful for representing error states.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FilledCircleX: LucideIcon;
|
|
7
|
+
/** @alias FilledCircleX */
|
|
8
|
+
export declare const FilledCircleXIcon: LucideIcon;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
/**
|
|
3
|
+
* A filled square with a checkmark inside.
|
|
4
|
+
* Useful for representing selected or checked states.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FilledSquareCheck: LucideIcon;
|
|
7
|
+
/** @alias FilledSquareCheck */
|
|
8
|
+
export declare const FilledSquareCheckIcon: LucideIcon;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LucideIcon } from 'lucide-react';
|
|
2
|
+
/**
|
|
3
|
+
* A filled square with a minus sign inside.
|
|
4
|
+
* Useful for representing indeterminate or partial selection states.
|
|
5
|
+
*/
|
|
6
|
+
export declare const FilledSquareMinus: LucideIcon;
|
|
7
|
+
/** @alias FilledSquareMinus */
|
|
8
|
+
export declare const FilledSquareMinusIcon: LucideIcon;
|