@alexgorbatchev/shadcn 0.0.16 → 0.0.18
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/README.md +3 -0
- package/dist/{chunk-5ntb7p4q.js → chunk-0qcknj5n.js} +36 -16
- package/dist/{chunk-299wvwy8.js → chunk-6aqm34nb.js} +1 -1
- package/dist/{chunk-r9mng3ws.js → chunk-c6nvc3ft.js} +1 -1
- package/dist/components/assistant-ui/native/AssistantModal.js +2 -2
- package/dist/components/assistant-ui/native/AssistantSidebar.js +2 -2
- package/dist/components/assistant-ui/native/Thread.d.ts +9 -3
- package/dist/components/assistant-ui/native/Thread.js +1 -1
- package/dist/components/assistant-ui/native/index.js +3 -3
- package/dist/components/virtual-table/VirtualTable.d.ts +23 -0
- package/dist/components/virtual-table/index.d.ts +2 -0
- package/dist/components/virtual-table/index.js +103 -0
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -52,6 +52,7 @@ Import shared controls and providers from `@alexgorbatchev/shadcn`. Import the f
|
|
|
52
52
|
| `/fonts.css` | JetBrains Mono font stylesheet | `bun add @fontsource-variable/jetbrains-mono@^5.3.0` |
|
|
53
53
|
| `/sonner` | Sonner, SonnerToaster, Toaster, toast, useSonner | No additional install; patched implementation is bundled |
|
|
54
54
|
| `/input-otp` | InputOTP components | No additional install; patched implementation is bundled |
|
|
55
|
+
| `/virtual-table` | VirtualTable and row measurement props | `@tanstack/react-virtual@3.14.13` |
|
|
55
56
|
| `/message-scroller` | MessageScroller components, hooks, and types | No additional install; patched implementation is bundled |
|
|
56
57
|
| `/questionnaire` | Questionnaire components and types | No additional install; patched implementation is bundled |
|
|
57
58
|
|
|
@@ -268,6 +269,8 @@ Compose `QuestionnaireItem`, `QuestionnaireTitle`, and answer controls inside `Q
|
|
|
268
269
|
|
|
269
270
|
`InlineEdit` mounts an edit session with a controlled `value`, `onValueChange`, `onCommit`, and `onCancel`. Mount it in place of the displayed label. Its input focuses and selects its text by default; `shouldSelectOnMount={false}` preserves the initial caret. Enter or blur commits once, Escape cancels without committing, and asynchronous saves disable the input until completion. Rejected saves display an error and allow retry.
|
|
270
271
|
|
|
272
|
+
`VirtualTable` renders a bounded, dynamically measured set of native table rows using TanStack Virtual. Supply `items`, stable `getItemKey`, `header`, `columnCount`, `label`, and `renderRow`; spread the supplied measurement props onto each native row. Optional `columns` accepts a colgroup. `maxHeight` defaults to `65vh`, `estimateRowHeight` to 80 pixels, and `overscan` to five rows. `retainedKeys` keeps editing rows mounted; the focused row is retained automatically. Filtering and selection belong to the consumer.
|
|
273
|
+
|
|
271
274
|
`StarRating` takes a controlled numeric `value` from 0 to 5, `onValueChange`, and an accessible `label`. Its native radio buttons support keyboard selection and an Unrated option to clear the rating. Set `disabled` while saving. `Avatar shape="square"` displays square artwork with matching image, fallback, and border corners.
|
|
272
275
|
|
|
273
276
|
`DialogContent size="wide"` uses a desktop maximum width of 576px; `size="narrow"` uses 192px, and the default uses 384px. Dialogs remain bounded by the viewport. `FieldGroup columns={2}` arranges fields in two columns on desktop and one on mobile.
|
|
@@ -157,7 +157,9 @@ var ThreadHistorySkeleton = () => /* @__PURE__ */ jsxs("div", {
|
|
|
157
157
|
function Thread2({
|
|
158
158
|
components = EMPTY_COMPONENTS,
|
|
159
159
|
autoFocus = true,
|
|
160
|
-
emptyComposerPosition = "center"
|
|
160
|
+
emptyComposerPosition = "center",
|
|
161
|
+
viewportProps,
|
|
162
|
+
composerInputRef
|
|
161
163
|
}) {
|
|
162
164
|
const isEmpty = useAuiState(isNewChatView);
|
|
163
165
|
return /* @__PURE__ */ jsx(ThreadComponentsContext.Provider, {
|
|
@@ -165,11 +167,19 @@ function Thread2({
|
|
|
165
167
|
children: /* @__PURE__ */ jsx(ThreadRoot, {
|
|
166
168
|
isEmpty,
|
|
167
169
|
autoFocus,
|
|
168
|
-
emptyComposerPosition
|
|
170
|
+
emptyComposerPosition,
|
|
171
|
+
viewportProps,
|
|
172
|
+
composerInputRef
|
|
169
173
|
})
|
|
170
174
|
});
|
|
171
175
|
}
|
|
172
|
-
var ThreadRoot = ({
|
|
176
|
+
var ThreadRoot = ({
|
|
177
|
+
isEmpty,
|
|
178
|
+
autoFocus,
|
|
179
|
+
emptyComposerPosition,
|
|
180
|
+
viewportProps,
|
|
181
|
+
composerInputRef
|
|
182
|
+
}) => {
|
|
173
183
|
const { Welcome = ThreadWelcome } = useContext(ThreadComponentsContext);
|
|
174
184
|
const isCentered = isEmpty && emptyComposerPosition === "center";
|
|
175
185
|
return /* @__PURE__ */ jsx(ThreadPrimitive.Root, {
|
|
@@ -178,6 +188,7 @@ var ThreadRoot = ({ isEmpty, autoFocus, emptyComposerPosition }) => {
|
|
|
178
188
|
}),
|
|
179
189
|
children: /* @__PURE__ */ jsx(ThreadPrimitive.Viewport, {
|
|
180
190
|
turnAnchor: "top",
|
|
191
|
+
...viewportProps,
|
|
181
192
|
"data-slot": "aui_thread-viewport",
|
|
182
193
|
render: /* @__PURE__ */ jsx("div", {
|
|
183
194
|
className: "relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth"
|
|
@@ -201,15 +212,20 @@ var ThreadRoot = ({ isEmpty, autoFocus, emptyComposerPosition }) => {
|
|
|
201
212
|
children: () => /* @__PURE__ */ jsx(ThreadMessage, {})
|
|
202
213
|
})
|
|
203
214
|
}),
|
|
215
|
+
/* @__PURE__ */ jsx("div", {
|
|
216
|
+
"aria-hidden": "true",
|
|
217
|
+
className: cn2(!isCentered && "flex-1")
|
|
218
|
+
}),
|
|
204
219
|
/* @__PURE__ */ jsxs(ThreadPrimitive.ViewportFooter, {
|
|
205
220
|
render: /* @__PURE__ */ jsx("div", {
|
|
206
|
-
className: cn2("aui-thread-viewport-footer bg-background sticky bottom-0 flex flex-col gap-4 overflow-visible pb-4 md:pb-6", !isCentered && "
|
|
221
|
+
className: cn2("aui-thread-viewport-footer bg-background sticky bottom-0 flex flex-col gap-4 overflow-visible pb-4 md:pb-6", !isCentered && "rounded-t-(--composer-radius)")
|
|
207
222
|
}),
|
|
208
223
|
children: [
|
|
209
224
|
/* @__PURE__ */ jsx(ThreadScrollToBottom, {}),
|
|
210
225
|
/* @__PURE__ */ jsx(ThreadFollowupSuggestions2, {}),
|
|
211
226
|
/* @__PURE__ */ jsx(Composer, {
|
|
212
|
-
autoFocus
|
|
227
|
+
autoFocus,
|
|
228
|
+
inputRef: composerInputRef
|
|
213
229
|
}),
|
|
214
230
|
/* @__PURE__ */ jsx(AuiIf, {
|
|
215
231
|
condition: (s) => isNewChatView(s) && s.composer.isEmpty,
|
|
@@ -460,7 +476,7 @@ var ThreadSuggestionItem = () => {
|
|
|
460
476
|
})
|
|
461
477
|
});
|
|
462
478
|
};
|
|
463
|
-
var Composer = ({ autoFocus }) => {
|
|
479
|
+
var Composer = ({ autoFocus, inputRef }) => {
|
|
464
480
|
return /* @__PURE__ */ jsx(ComposerPrimitive.Root, {
|
|
465
481
|
render: /* @__PURE__ */ jsx("form", {
|
|
466
482
|
className: "aui-composer-root relative flex w-full flex-col"
|
|
@@ -473,6 +489,7 @@ var Composer = ({ autoFocus }) => {
|
|
|
473
489
|
children: [
|
|
474
490
|
/* @__PURE__ */ jsx(ComposerAttachments3, {}),
|
|
475
491
|
/* @__PURE__ */ jsx(ComposerPrimitive.Input, {
|
|
492
|
+
ref: inputRef,
|
|
476
493
|
placeholder: "Send a message...",
|
|
477
494
|
rows: 1,
|
|
478
495
|
autoFocus,
|
|
@@ -488,6 +505,7 @@ var Composer = ({ autoFocus }) => {
|
|
|
488
505
|
});
|
|
489
506
|
};
|
|
490
507
|
var ComposerAction = () => {
|
|
508
|
+
const { ComposerActions } = useContext(ThreadComponentsContext);
|
|
491
509
|
const isSending = useAuiState((s) => s.composer.submission !== undefined && !(s.thread.isRunning && s.thread.capabilities.cancel));
|
|
492
510
|
return /* @__PURE__ */ jsxs("div", {
|
|
493
511
|
className: "aui-composer-action-wrapper relative flex items-center justify-between",
|
|
@@ -496,6 +514,7 @@ var ComposerAction = () => {
|
|
|
496
514
|
/* @__PURE__ */ jsxs("div", {
|
|
497
515
|
className: "flex items-center gap-1.5",
|
|
498
516
|
children: [
|
|
517
|
+
ComposerActions && /* @__PURE__ */ jsx(ComposerActions, {}),
|
|
499
518
|
/* @__PURE__ */ jsxs(AuiIf, {
|
|
500
519
|
condition: (s) => s.thread.capabilities.dictation,
|
|
501
520
|
children: [
|
|
@@ -504,11 +523,11 @@ var ComposerAction = () => {
|
|
|
504
523
|
children: /* @__PURE__ */ jsx(ComposerPrimitive.Dictate, {
|
|
505
524
|
asChild: true,
|
|
506
525
|
children: /* @__PURE__ */ jsx(TooltipIconButton2, {
|
|
507
|
-
tooltip: "Voice
|
|
526
|
+
tooltip: "Voice Input",
|
|
508
527
|
side: "bottom",
|
|
509
528
|
type: "button",
|
|
510
529
|
variant: "ghost",
|
|
511
|
-
"aria-label": "Start
|
|
530
|
+
"aria-label": "Start Voice Input",
|
|
512
531
|
children: /* @__PURE__ */ jsx(MicIcon, {
|
|
513
532
|
"aria-hidden": "true",
|
|
514
533
|
className: "size-4 shrink-0"
|
|
@@ -521,11 +540,11 @@ var ComposerAction = () => {
|
|
|
521
540
|
children: /* @__PURE__ */ jsx(ComposerPrimitive.StopDictation, {
|
|
522
541
|
asChild: true,
|
|
523
542
|
children: /* @__PURE__ */ jsx(TooltipIconButton2, {
|
|
524
|
-
tooltip: "Stop
|
|
543
|
+
tooltip: "Stop Dictation",
|
|
525
544
|
side: "bottom",
|
|
526
545
|
type: "button",
|
|
527
546
|
variant: "ghost",
|
|
528
|
-
"aria-label": "Stop
|
|
547
|
+
"aria-label": "Stop Voice Input",
|
|
529
548
|
children: /* @__PURE__ */ jsx(SquareIcon, {
|
|
530
549
|
"aria-hidden": "true",
|
|
531
550
|
className: "size-3.5 shrink-0 animate-pulse motion-reduce:animate-none"
|
|
@@ -540,11 +559,11 @@ var ComposerAction = () => {
|
|
|
540
559
|
children: /* @__PURE__ */ jsx(ComposerPrimitive.Send, {
|
|
541
560
|
asChild: true,
|
|
542
561
|
children: /* @__PURE__ */ jsx(TooltipIconButton2, {
|
|
543
|
-
tooltip: "Send
|
|
562
|
+
tooltip: "Send Message",
|
|
544
563
|
side: "bottom",
|
|
545
564
|
type: "button",
|
|
546
565
|
variant: "default",
|
|
547
|
-
"aria-label": "Send
|
|
566
|
+
"aria-label": "Send Message",
|
|
548
567
|
children: /* @__PURE__ */ jsx(ArrowUpIcon, {
|
|
549
568
|
"aria-hidden": "true",
|
|
550
569
|
className: "size-4 shrink-0"
|
|
@@ -557,11 +576,11 @@ var ComposerAction = () => {
|
|
|
557
576
|
children: /* @__PURE__ */ jsx(ComposerPrimitive.Resume, {
|
|
558
577
|
asChild: true,
|
|
559
578
|
children: /* @__PURE__ */ jsx(TooltipIconButton2, {
|
|
560
|
-
tooltip: "Resume
|
|
579
|
+
tooltip: "Resume Generating",
|
|
561
580
|
side: "bottom",
|
|
562
581
|
type: "button",
|
|
563
582
|
variant: "default",
|
|
564
|
-
"aria-label": "Resume
|
|
583
|
+
"aria-label": "Resume Generating",
|
|
565
584
|
children: /* @__PURE__ */ jsx(PlayIcon, {
|
|
566
585
|
"aria-hidden": "true",
|
|
567
586
|
className: "size-4 shrink-0"
|
|
@@ -576,7 +595,7 @@ var ComposerAction = () => {
|
|
|
576
595
|
children: /* @__PURE__ */ jsx(Button2, {
|
|
577
596
|
type: "button",
|
|
578
597
|
variant: "default",
|
|
579
|
-
"aria-label": isSending ? "Cancel
|
|
598
|
+
"aria-label": isSending ? "Cancel Sending" : "Stop Generating",
|
|
580
599
|
children: /* @__PURE__ */ jsx(SquareIcon, {
|
|
581
600
|
"aria-hidden": "true",
|
|
582
601
|
className: "size-3.5 shrink-0"
|
|
@@ -874,6 +893,7 @@ var UserImagePart = (part) => /* @__PURE__ */ jsx("div", {
|
|
|
874
893
|
})
|
|
875
894
|
});
|
|
876
895
|
var UserMessage = () => {
|
|
896
|
+
const { UserText } = useContext(ThreadComponentsContext);
|
|
877
897
|
return /* @__PURE__ */ jsxs(MessagePrimitive.Root, {
|
|
878
898
|
"data-slot": "aui_user-message-root",
|
|
879
899
|
"data-role": "user",
|
|
@@ -888,7 +908,7 @@ var UserMessage = () => {
|
|
|
888
908
|
/* @__PURE__ */ jsx("div", {
|
|
889
909
|
className: "aui-user-message-content peer bg-muted text-foreground rounded-(--composer-radius) px-4 py-2 wrap-break-word empty:hidden",
|
|
890
910
|
children: /* @__PURE__ */ jsx(MessagePrimitive.Parts, {
|
|
891
|
-
components: { File: UserFilePart, Image: UserImagePart }
|
|
911
|
+
components: { Text: UserText, File: UserFilePart, Image: UserImagePart }
|
|
892
912
|
})
|
|
893
913
|
}),
|
|
894
914
|
/* @__PURE__ */ jsx("div", {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AssistantModal2
|
|
3
|
-
} from "../../../chunk-
|
|
3
|
+
} from "../../../chunk-6aqm34nb.js";
|
|
4
4
|
import"../../../chunk-tsekdy3w.js";
|
|
5
|
-
import"../../../chunk-
|
|
5
|
+
import"../../../chunk-0qcknj5n.js";
|
|
6
6
|
import"../../../chunk-9msk1t9e.js";
|
|
7
7
|
import"../../../chunk-c2vcrwjp.js";
|
|
8
8
|
import"../../../chunk-sbrpnv8s.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AssistantSidebar2
|
|
3
|
-
} from "../../../chunk-
|
|
4
|
-
import"../../../chunk-
|
|
3
|
+
} from "../../../chunk-c6nvc3ft.js";
|
|
4
|
+
import"../../../chunk-0qcknj5n.js";
|
|
5
5
|
import"../../../chunk-9msk1t9e.js";
|
|
6
6
|
import"../../../chunk-c2vcrwjp.js";
|
|
7
7
|
import"../../../chunk-sbrpnv8s.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ReactElement } from "react";
|
|
2
|
-
import { MessagePrimitive, type ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
1
|
+
import type { ComponentPropsWithRef, ReactElement, Ref } from "react";
|
|
2
|
+
import { MessagePrimitive, ThreadPrimitive, type TextMessagePartComponent, type ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
3
3
|
import { type ComponentType, type PropsWithChildren } from "react";
|
|
4
4
|
export type ThreadGroupPart = MessagePrimitive.GroupedParts.GroupPart;
|
|
5
5
|
/**
|
|
@@ -12,6 +12,8 @@ export type ThreadGroupPart = MessagePrimitive.GroupedParts.GroupPart;
|
|
|
12
12
|
* tool group; without it they render like any other tool call.
|
|
13
13
|
*/
|
|
14
14
|
export type ThreadComponents = {
|
|
15
|
+
UserText?: TextMessagePartComponent | undefined;
|
|
16
|
+
ComposerActions?: ComponentType | undefined;
|
|
15
17
|
AssistantMessage?: ComponentType | undefined;
|
|
16
18
|
Welcome?: ComponentType | undefined;
|
|
17
19
|
ToolFallback?: ToolCallMessagePartComponent | undefined;
|
|
@@ -26,9 +28,13 @@ export type ThreadComponents = {
|
|
|
26
28
|
}> | undefined;
|
|
27
29
|
};
|
|
28
30
|
export type ThreadProps = {
|
|
31
|
+
/** Native viewport behavior and ref, including scroll restoration. */
|
|
32
|
+
viewportProps?: Omit<ComponentPropsWithRef<typeof ThreadPrimitive.Viewport>, "children" | "render"> | undefined;
|
|
33
|
+
/** Ref to the thread composer's native input. */
|
|
34
|
+
composerInputRef?: Ref<HTMLTextAreaElement> | undefined;
|
|
29
35
|
components?: ThreadComponents | undefined;
|
|
30
36
|
autoFocus?: boolean | undefined;
|
|
31
37
|
/** Place the composer at the bottom even before the first message. */
|
|
32
38
|
emptyComposerPosition?: "center" | "bottom" | undefined;
|
|
33
39
|
};
|
|
34
|
-
export declare function Thread({ components, autoFocus, emptyComposerPosition, }: ThreadProps): ReactElement;
|
|
40
|
+
export declare function Thread({ components, autoFocus, emptyComposerPosition, viewportProps, composerInputRef, }: ThreadProps): ReactElement;
|
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
import"../../../chunk-d70rcwk7.js";
|
|
65
65
|
import {
|
|
66
66
|
Thread2
|
|
67
|
-
} from "../../../chunk-
|
|
67
|
+
} from "../../../chunk-0qcknj5n.js";
|
|
68
68
|
import {
|
|
69
69
|
useThreadListGroups2,
|
|
70
70
|
ThreadList3,
|
|
@@ -77,11 +77,11 @@ import {
|
|
|
77
77
|
import"../../../chunk-59p19t57.js";
|
|
78
78
|
import {
|
|
79
79
|
AssistantModal2
|
|
80
|
-
} from "../../../chunk-
|
|
80
|
+
} from "../../../chunk-6aqm34nb.js";
|
|
81
81
|
import"../../../chunk-1x2ch0xc.js";
|
|
82
82
|
import {
|
|
83
83
|
AssistantSidebar2
|
|
84
|
-
} from "../../../chunk-
|
|
84
|
+
} from "../../../chunk-c6nvc3ft.js";
|
|
85
85
|
import {
|
|
86
86
|
ComposerQuotePreviewRoot2,
|
|
87
87
|
ComposerQuotePreviewIcon2,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ComponentProps, type Key, type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import { Table } from "../Table.js";
|
|
3
|
+
export interface IVirtualTableRowProps {
|
|
4
|
+
ref: (element: HTMLTableRowElement | null) => void;
|
|
5
|
+
"data-index": number;
|
|
6
|
+
"aria-rowindex": number;
|
|
7
|
+
}
|
|
8
|
+
interface IVirtualTableProps<T> {
|
|
9
|
+
items: readonly T[];
|
|
10
|
+
getItemKey: (item: T) => Key;
|
|
11
|
+
renderRow: (item: T, props: IVirtualTableRowProps) => ReactNode;
|
|
12
|
+
header: ReactNode;
|
|
13
|
+
columns?: ReactNode;
|
|
14
|
+
columnCount: number;
|
|
15
|
+
label: string;
|
|
16
|
+
maxHeight?: number | string;
|
|
17
|
+
estimateRowHeight?: number;
|
|
18
|
+
overscan?: number;
|
|
19
|
+
retainedKeys?: readonly Key[];
|
|
20
|
+
layout?: ComponentProps<typeof Table>["layout"];
|
|
21
|
+
}
|
|
22
|
+
export declare function VirtualTable<T>({ items, getItemKey, renderRow, header, columns, columnCount, label, maxHeight, estimateRowHeight, overscan, retainedKeys, layout, }: IVirtualTableProps<T>): ReactElement;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import"../../chunk-cp2m7y7v.js";
|
|
2
|
+
import {
|
|
3
|
+
Table2,
|
|
4
|
+
TableHeader2,
|
|
5
|
+
TableBody2
|
|
6
|
+
} from "../../chunk-0y0kqaqj.js";
|
|
7
|
+
|
|
8
|
+
// src/components/virtual-table/VirtualTable.tsx
|
|
9
|
+
import {
|
|
10
|
+
Fragment,
|
|
11
|
+
useCallback,
|
|
12
|
+
useMemo,
|
|
13
|
+
useRef,
|
|
14
|
+
useState
|
|
15
|
+
} from "react";
|
|
16
|
+
import { defaultRangeExtractor, useVirtualizer } from "@tanstack/react-virtual";
|
|
17
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
18
|
+
function VirtualTable({
|
|
19
|
+
items,
|
|
20
|
+
getItemKey,
|
|
21
|
+
renderRow,
|
|
22
|
+
header,
|
|
23
|
+
columns,
|
|
24
|
+
columnCount,
|
|
25
|
+
label,
|
|
26
|
+
maxHeight = "65vh",
|
|
27
|
+
estimateRowHeight = 80,
|
|
28
|
+
overscan = 5,
|
|
29
|
+
retainedKeys,
|
|
30
|
+
layout = "fixed"
|
|
31
|
+
}) {
|
|
32
|
+
const viewport = useRef(null);
|
|
33
|
+
const [focusedKey, setFocusedKey] = useState();
|
|
34
|
+
const retained = useMemo(() => items.flatMap((item, index) => retainedKeys?.includes(getItemKey(item)) || getItemKey(item) === focusedKey ? [index] : []), [items, retainedKeys, getItemKey, focusedKey]);
|
|
35
|
+
const rangeExtractor = useCallback((range) => [...new Set([...defaultRangeExtractor(range), ...retained])].sort((a, b) => a - b), [retained]);
|
|
36
|
+
const itemKey = useCallback((index) => getItemKey(items[index]), [items, getItemKey]);
|
|
37
|
+
const virtualizer = useVirtualizer({
|
|
38
|
+
count: items.length,
|
|
39
|
+
getScrollElement: () => viewport.current,
|
|
40
|
+
getItemKey: itemKey,
|
|
41
|
+
estimateSize: () => estimateRowHeight,
|
|
42
|
+
overscan,
|
|
43
|
+
rangeExtractor
|
|
44
|
+
});
|
|
45
|
+
const rows = virtualizer.getVirtualItems();
|
|
46
|
+
const last = rows.at(-1);
|
|
47
|
+
return /* @__PURE__ */ jsx("div", {
|
|
48
|
+
ref: viewport,
|
|
49
|
+
"data-testid": "VirtualTable",
|
|
50
|
+
role: "region",
|
|
51
|
+
"aria-label": label,
|
|
52
|
+
tabIndex: 0,
|
|
53
|
+
className: "min-w-0 overflow-auto overscroll-contain",
|
|
54
|
+
style: { maxHeight },
|
|
55
|
+
onFocusCapture: (event) => {
|
|
56
|
+
const row = event.target.closest("tr[data-index]");
|
|
57
|
+
const item = items[Number(row?.dataset.index)];
|
|
58
|
+
if (row && item)
|
|
59
|
+
setFocusedKey(getItemKey(item));
|
|
60
|
+
},
|
|
61
|
+
children: /* @__PURE__ */ jsxs(Table2, {
|
|
62
|
+
layout,
|
|
63
|
+
"aria-label": label,
|
|
64
|
+
"aria-rowcount": items.length + 1,
|
|
65
|
+
children: [
|
|
66
|
+
columns,
|
|
67
|
+
/* @__PURE__ */ jsx(TableHeader2, {
|
|
68
|
+
children: header
|
|
69
|
+
}),
|
|
70
|
+
/* @__PURE__ */ jsxs(TableBody2, {
|
|
71
|
+
children: [
|
|
72
|
+
rows.map((row, index) => /* @__PURE__ */ jsxs(Fragment, {
|
|
73
|
+
children: [
|
|
74
|
+
row.start > (rows[index - 1]?.end ?? 0) && /* @__PURE__ */ jsx("tr", {
|
|
75
|
+
"aria-hidden": "true",
|
|
76
|
+
children: /* @__PURE__ */ jsx("td", {
|
|
77
|
+
colSpan: columnCount,
|
|
78
|
+
style: { height: row.start - (rows[index - 1]?.end ?? 0), padding: 0, border: 0 }
|
|
79
|
+
})
|
|
80
|
+
}),
|
|
81
|
+
renderRow(items[row.index], {
|
|
82
|
+
ref: virtualizer.measureElement,
|
|
83
|
+
"data-index": row.index,
|
|
84
|
+
"aria-rowindex": row.index + 2
|
|
85
|
+
})
|
|
86
|
+
]
|
|
87
|
+
}, row.key)),
|
|
88
|
+
last && virtualizer.getTotalSize() > last.end && /* @__PURE__ */ jsx("tr", {
|
|
89
|
+
"aria-hidden": "true",
|
|
90
|
+
children: /* @__PURE__ */ jsx("td", {
|
|
91
|
+
colSpan: columnCount,
|
|
92
|
+
style: { height: virtualizer.getTotalSize() - last.end, padding: 0, border: 0 }
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
]
|
|
96
|
+
})
|
|
97
|
+
]
|
|
98
|
+
})
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
VirtualTable
|
|
103
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alexgorbatchev/shadcn",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "Sharp, monospace React components with compact and comfortable densities.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -988,6 +988,10 @@
|
|
|
988
988
|
"./assistant-ui/native/task-tray": {
|
|
989
989
|
"types": "./dist/components/assistant-ui/native/TaskTray.d.ts",
|
|
990
990
|
"import": "./dist/components/assistant-ui/native/TaskTray.js"
|
|
991
|
+
},
|
|
992
|
+
"./virtual-table": {
|
|
993
|
+
"types": "./dist/components/virtual-table/index.d.ts",
|
|
994
|
+
"import": "./dist/components/virtual-table/index.js"
|
|
991
995
|
}
|
|
992
996
|
},
|
|
993
997
|
"publishConfig": {
|
|
@@ -1105,6 +1109,7 @@
|
|
|
1105
1109
|
"@daypicker/persian": "^10.0.2",
|
|
1106
1110
|
"@daypicker/react": "^10.0.2",
|
|
1107
1111
|
"@fontsource-variable/jetbrains-mono": "^5.3.0",
|
|
1112
|
+
"@tanstack/react-virtual": "^3.14.13",
|
|
1108
1113
|
"anser": "2.3.5",
|
|
1109
1114
|
"beautiful-mermaid": "^1.1.3",
|
|
1110
1115
|
"cmdk": "^1.1.1",
|
|
@@ -1218,6 +1223,9 @@
|
|
|
1218
1223
|
},
|
|
1219
1224
|
"colorjs.io": {
|
|
1220
1225
|
"optional": true
|
|
1226
|
+
},
|
|
1227
|
+
"@tanstack/react-virtual": {
|
|
1228
|
+
"optional": true
|
|
1221
1229
|
}
|
|
1222
1230
|
},
|
|
1223
1231
|
"packageManager": "bun@1.4.2"
|