@health-samurai/react-components 0.0.0-alpha.18 → 0.0.0-alpha.20
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/LICENSE +21 -0
- package/dist/bundle.css +51 -33
- package/dist/src/components/code-editor/fhir-autocomplete.d.ts +70 -0
- package/dist/src/components/code-editor/fhir-autocomplete.d.ts.map +1 -0
- package/dist/src/components/code-editor/fhir-autocomplete.js +1849 -0
- package/dist/src/components/code-editor/fhir-autocomplete.js.map +1 -0
- package/dist/src/components/code-editor/fhir-autocomplete.test.js +1099 -0
- package/dist/src/components/code-editor/fhir-autocomplete.test.js.map +1 -0
- package/dist/src/components/code-editor/http/index.d.ts +9 -1
- package/dist/src/components/code-editor/http/index.d.ts.map +1 -1
- package/dist/src/components/code-editor/http/index.js +423 -3
- package/dist/src/components/code-editor/http/index.js.map +1 -1
- package/dist/src/components/code-editor/index.d.ts +13 -4
- package/dist/src/components/code-editor/index.d.ts.map +1 -1
- package/dist/src/components/code-editor/index.js +505 -96
- package/dist/src/components/code-editor/index.js.map +1 -1
- package/dist/src/components/code-editor/json-ast.d.ts +46 -0
- package/dist/src/components/code-editor/json-ast.d.ts.map +1 -0
- package/dist/src/components/code-editor/json-ast.js +465 -0
- package/dist/src/components/code-editor/json-ast.js.map +1 -0
- package/dist/src/components/code-editor/json-ast.test.js +206 -0
- package/dist/src/components/code-editor/json-ast.test.js.map +1 -0
- package/dist/src/components/code-editor/sql-completion.d.ts +22 -0
- package/dist/src/components/code-editor/sql-completion.d.ts.map +1 -0
- package/dist/src/components/code-editor/sql-completion.js +895 -0
- package/dist/src/components/code-editor/sql-completion.js.map +1 -0
- package/dist/src/components/date-picker-input.d.ts +10 -0
- package/dist/src/components/date-picker-input.d.ts.map +1 -0
- package/dist/src/components/date-picker-input.js +90 -0
- package/dist/src/components/date-picker-input.js.map +1 -0
- package/dist/src/components/date-picker-input.stories.js +76 -0
- package/dist/src/components/date-picker-input.stories.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/shadcn/components/ui/alert-dialog.d.ts +1 -1
- package/dist/src/shadcn/components/ui/calendar.d.ts +1 -1
- package/dist/src/shadcn/components/ui/carousel.d.ts +1 -1
- package/dist/src/shadcn/components/ui/chart.d.ts +3 -3
- package/dist/src/shadcn/components/ui/chart.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/chart.js +1 -1
- package/dist/src/shadcn/components/ui/chart.js.map +1 -1
- package/dist/src/shadcn/components/ui/command.d.ts +1 -1
- package/dist/src/shadcn/components/ui/pagination.d.ts +1 -1
- package/dist/src/shadcn/components/ui/resizable.stories.js +2 -2
- package/dist/src/shadcn/components/ui/resizable.stories.js.map +1 -1
- package/dist/src/shadcn/components/ui/sidebar.d.ts +4 -4
- package/dist/src/shadcn/components/ui/tabs.d.ts +3 -1
- package/dist/src/shadcn/components/ui/tabs.d.ts.map +1 -1
- package/dist/src/shadcn/components/ui/tabs.js +129 -2
- package/dist/src/shadcn/components/ui/tabs.js.map +1 -1
- package/dist/src/shadcn/components/ui/tabs.stories.js +1 -1
- package/dist/src/shadcn/components/ui/tabs.stories.js.map +1 -1
- package/dist/src/shadcn/components/ui/toggle-group.d.ts +1 -1
- package/dist/src/typography.css +1 -1
- package/package.json +24 -19
- package/src/components/code-editor/fhir-autocomplete.test.ts +993 -0
- package/src/components/code-editor/fhir-autocomplete.ts +2321 -0
- package/src/components/code-editor/http/index.ts +339 -2
- package/src/components/code-editor/index.tsx +593 -102
- package/src/components/code-editor/json-ast.test.ts +230 -0
- package/src/components/code-editor/json-ast.ts +590 -0
- package/src/components/code-editor/sql-completion.ts +1105 -0
- package/src/components/date-picker-input.stories.tsx +79 -0
- package/src/components/date-picker-input.tsx +104 -0
- package/src/index.tsx +1 -0
- package/src/shadcn/components/ui/chart.tsx +6 -3
- package/src/shadcn/components/ui/resizable.stories.tsx +2 -2
- package/src/shadcn/components/ui/tabs.stories.tsx +1 -1
- package/src/shadcn/components/ui/tabs.tsx +160 -2
- package/src/typography.css +1 -1
- package/dist/src/components/code-editor/http/grammar/http.test.d.ts +0 -2
- package/dist/src/components/code-editor/http/grammar/http.test.d.ts.map +0 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { DatePickerInput } from "./date-picker-input";
|
|
4
|
+
|
|
5
|
+
function DatePickerInputWrapper(props: {
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}) {
|
|
9
|
+
const [value, setValue] = useState("");
|
|
10
|
+
return (
|
|
11
|
+
<div className="w-48">
|
|
12
|
+
<DatePickerInput value={value} onChange={setValue} {...props} />
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function DatePickerInputPrefilledWrapper() {
|
|
18
|
+
const [value, setValue] = useState("15.06.2025");
|
|
19
|
+
return (
|
|
20
|
+
<div className="w-48">
|
|
21
|
+
<DatePickerInput value={value} onChange={setValue} />
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function DatePickerRangeWrapper() {
|
|
27
|
+
const [from, setFrom] = useState("");
|
|
28
|
+
const [to, setTo] = useState("");
|
|
29
|
+
return (
|
|
30
|
+
<div className="flex items-center gap-2">
|
|
31
|
+
<DatePickerInput
|
|
32
|
+
value={from}
|
|
33
|
+
onChange={setFrom}
|
|
34
|
+
className="w-40"
|
|
35
|
+
placeholder="From"
|
|
36
|
+
/>
|
|
37
|
+
<span className="text-text-secondary">—</span>
|
|
38
|
+
<DatePickerInput
|
|
39
|
+
value={to}
|
|
40
|
+
onChange={setTo}
|
|
41
|
+
className="w-40"
|
|
42
|
+
placeholder="To"
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const meta = {
|
|
49
|
+
title: "Component/DatePickerInput",
|
|
50
|
+
component: DatePickerInputWrapper,
|
|
51
|
+
parameters: {
|
|
52
|
+
layout: "centered",
|
|
53
|
+
},
|
|
54
|
+
} satisfies Meta<typeof DatePickerInputWrapper>;
|
|
55
|
+
|
|
56
|
+
export default meta;
|
|
57
|
+
type Story = StoryObj<typeof meta>;
|
|
58
|
+
|
|
59
|
+
export const Default: Story = {};
|
|
60
|
+
|
|
61
|
+
export const WithPlaceholder: Story = {
|
|
62
|
+
args: {
|
|
63
|
+
placeholder: "Select a date...",
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const Disabled: Story = {
|
|
68
|
+
args: {
|
|
69
|
+
disabled: true,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const Prefilled: StoryObj = {
|
|
74
|
+
render: () => <DatePickerInputPrefilledWrapper />,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const DateRange: StoryObj = {
|
|
78
|
+
render: () => <DatePickerRangeWrapper />,
|
|
79
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { CalendarIcon } from "lucide-react";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Button } from "#shadcn/components/ui/button";
|
|
4
|
+
import { Calendar } from "#shadcn/components/ui/calendar";
|
|
5
|
+
import { Input } from "#shadcn/components/ui/input";
|
|
6
|
+
import {
|
|
7
|
+
Popover,
|
|
8
|
+
PopoverContent,
|
|
9
|
+
PopoverTrigger,
|
|
10
|
+
} from "#shadcn/components/ui/popover";
|
|
11
|
+
import { cn } from "#shadcn/lib/utils";
|
|
12
|
+
|
|
13
|
+
function formatDate(date: Date | undefined): string {
|
|
14
|
+
if (!date) return "";
|
|
15
|
+
const d = date.getDate().toString().padStart(2, "0");
|
|
16
|
+
const m = (date.getMonth() + 1).toString().padStart(2, "0");
|
|
17
|
+
const y = date.getFullYear();
|
|
18
|
+
return `${d}.${m}.${y}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function parseDate(value: string): Date | undefined {
|
|
22
|
+
if (!value) return undefined;
|
|
23
|
+
const parts = value.split(".");
|
|
24
|
+
if (parts.length === 3) {
|
|
25
|
+
const [d, m, y] = parts;
|
|
26
|
+
const date = new Date(`${y}-${m}-${d}`);
|
|
27
|
+
if (!Number.isNaN(date.getTime())) return date;
|
|
28
|
+
}
|
|
29
|
+
const date = new Date(value);
|
|
30
|
+
if (!Number.isNaN(date.getTime())) return date;
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface DatePickerInputProps {
|
|
35
|
+
value: string;
|
|
36
|
+
onChange: (value: string) => void;
|
|
37
|
+
placeholder?: string;
|
|
38
|
+
className?: string;
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function DatePickerInput({
|
|
43
|
+
value,
|
|
44
|
+
onChange,
|
|
45
|
+
placeholder = "dd.mm.yyyy",
|
|
46
|
+
className,
|
|
47
|
+
disabled,
|
|
48
|
+
}: DatePickerInputProps) {
|
|
49
|
+
const [open, setOpen] = React.useState(false);
|
|
50
|
+
const selectedDate = parseDate(value);
|
|
51
|
+
const [month, setMonth] = React.useState<Date>(selectedDate ?? new Date());
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div className={cn("relative", className)}>
|
|
55
|
+
<Input
|
|
56
|
+
type="text"
|
|
57
|
+
placeholder={placeholder}
|
|
58
|
+
value={value}
|
|
59
|
+
disabled={disabled}
|
|
60
|
+
onChange={(e) => onChange(e.target.value)}
|
|
61
|
+
onKeyDown={(e) => {
|
|
62
|
+
if (e.key === "ArrowDown") {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
setOpen(true);
|
|
65
|
+
}
|
|
66
|
+
}}
|
|
67
|
+
rightSlot={
|
|
68
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
69
|
+
<PopoverTrigger asChild>
|
|
70
|
+
<Button
|
|
71
|
+
variant="ghost"
|
|
72
|
+
size="small"
|
|
73
|
+
className="p-0 size-5"
|
|
74
|
+
aria-label="Select date"
|
|
75
|
+
disabled={disabled}
|
|
76
|
+
onClick={(e) => {
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
setOpen((o) => !o);
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
<CalendarIcon className="size-3.5" />
|
|
82
|
+
</Button>
|
|
83
|
+
</PopoverTrigger>
|
|
84
|
+
<PopoverContent className="w-auto p-0" align="end" sideOffset={10}>
|
|
85
|
+
<Calendar
|
|
86
|
+
mode="single"
|
|
87
|
+
selected={selectedDate}
|
|
88
|
+
month={month}
|
|
89
|
+
onMonthChange={(m) => setMonth(m)}
|
|
90
|
+
onSelect={(date) => {
|
|
91
|
+
onChange(formatDate(date));
|
|
92
|
+
if (date) setMonth(date);
|
|
93
|
+
setOpen(false);
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
</PopoverContent>
|
|
97
|
+
</Popover>
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { DatePickerInput, type DatePickerInputProps };
|
package/src/index.tsx
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./components/button-dropdown";
|
|
|
4
4
|
export * from "./components/code-editor";
|
|
5
5
|
export * from "./components/copy-icon";
|
|
6
6
|
export * from "./components/data-table";
|
|
7
|
+
export * from "./components/date-picker-input";
|
|
7
8
|
export * from "./components/fhir-structure-view";
|
|
8
9
|
export * from "./components/icon-button";
|
|
9
10
|
export * from "./components/operation-outcome-view";
|
|
@@ -118,7 +118,7 @@ function ChartTooltipContent({
|
|
|
118
118
|
color,
|
|
119
119
|
nameKey,
|
|
120
120
|
labelKey,
|
|
121
|
-
}:
|
|
121
|
+
}: RechartsPrimitive.TooltipContentProps &
|
|
122
122
|
React.ComponentProps<"div"> & {
|
|
123
123
|
hideLabel?: boolean;
|
|
124
124
|
hideIndicator?: boolean;
|
|
@@ -186,7 +186,7 @@ function ChartTooltipContent({
|
|
|
186
186
|
|
|
187
187
|
return (
|
|
188
188
|
<div
|
|
189
|
-
key={item.dataKey}
|
|
189
|
+
key={String(item.dataKey ?? index)}
|
|
190
190
|
className={cn(
|
|
191
191
|
"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
|
|
192
192
|
indicator === "dot" && "items-center",
|
|
@@ -257,7 +257,10 @@ function ChartLegendContent({
|
|
|
257
257
|
verticalAlign = "bottom",
|
|
258
258
|
nameKey,
|
|
259
259
|
}: React.ComponentProps<"div"> &
|
|
260
|
-
Pick<
|
|
260
|
+
Pick<
|
|
261
|
+
RechartsPrimitive.DefaultLegendContentProps,
|
|
262
|
+
"payload" | "verticalAlign"
|
|
263
|
+
> & {
|
|
261
264
|
hideIcon?: boolean;
|
|
262
265
|
nameKey?: string;
|
|
263
266
|
}) {
|
|
@@ -15,7 +15,7 @@ type Story = StoryObj<typeof meta>;
|
|
|
15
15
|
export const Demo = {
|
|
16
16
|
render: () => (
|
|
17
17
|
<ResizablePanelGroup
|
|
18
|
-
|
|
18
|
+
orientation="horizontal"
|
|
19
19
|
className="max-w-md rounded-lg border md:min-w-[450px]"
|
|
20
20
|
>
|
|
21
21
|
<ResizablePanel defaultSize={50}>
|
|
@@ -25,7 +25,7 @@ export const Demo = {
|
|
|
25
25
|
</ResizablePanel>
|
|
26
26
|
<ResizableHandle />
|
|
27
27
|
<ResizablePanel defaultSize={50}>
|
|
28
|
-
<ResizablePanelGroup
|
|
28
|
+
<ResizablePanelGroup orientation="vertical">
|
|
29
29
|
<ResizablePanel defaultSize={25}>
|
|
30
30
|
<div className="flex h-full items-center justify-center p-6">
|
|
31
31
|
<span className="font-semibold">Two</span>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Controls, Primary, Title } from "@storybook/addon-docs/blocks";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
|
-
import { action } from "storybook/
|
|
3
|
+
import { action } from "storybook/actions";
|
|
4
4
|
import {
|
|
5
5
|
Tabs,
|
|
6
6
|
TabsAddButton,
|
|
@@ -443,17 +443,175 @@ function TabScrollRightButton({
|
|
|
443
443
|
);
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
+
type DragState = {
|
|
447
|
+
index: number;
|
|
448
|
+
startX: number;
|
|
449
|
+
offsetX: number;
|
|
450
|
+
currentIndex: number;
|
|
451
|
+
widths: number[];
|
|
452
|
+
lefts: number[];
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
const DRAG_THRESHOLD = 5;
|
|
456
|
+
|
|
457
|
+
function useTabReorder(
|
|
458
|
+
onReorder: ((fromIndex: number, toIndex: number) => void) | undefined,
|
|
459
|
+
) {
|
|
460
|
+
const [drag, setDrag] = React.useState<DragState | null>(null);
|
|
461
|
+
const dragRef = React.useRef<DragState | null>(null);
|
|
462
|
+
const pendingRef = React.useRef(false);
|
|
463
|
+
const itemsRef = React.useRef<(HTMLDivElement | null)[]>([]);
|
|
464
|
+
|
|
465
|
+
const handlePointerDown = React.useCallback(
|
|
466
|
+
(e: React.PointerEvent, index: number) => {
|
|
467
|
+
if (!onReorder || e.button !== 0) return;
|
|
468
|
+
const items = itemsRef.current;
|
|
469
|
+
const widths = items.map((el) => el?.offsetWidth ?? 0);
|
|
470
|
+
const lefts: number[] = [];
|
|
471
|
+
let acc = 0;
|
|
472
|
+
for (const w of widths) {
|
|
473
|
+
lefts.push(acc);
|
|
474
|
+
acc += w;
|
|
475
|
+
}
|
|
476
|
+
dragRef.current = {
|
|
477
|
+
index,
|
|
478
|
+
startX: e.clientX,
|
|
479
|
+
offsetX: 0,
|
|
480
|
+
currentIndex: index,
|
|
481
|
+
widths,
|
|
482
|
+
lefts,
|
|
483
|
+
};
|
|
484
|
+
pendingRef.current = true;
|
|
485
|
+
(e.target as HTMLElement).setPointerCapture(e.pointerId);
|
|
486
|
+
},
|
|
487
|
+
[onReorder],
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
const handlePointerMove = React.useCallback((e: React.PointerEvent) => {
|
|
491
|
+
const d = dragRef.current;
|
|
492
|
+
if (!d) return;
|
|
493
|
+
const dx = e.clientX - d.startX;
|
|
494
|
+
if (pendingRef.current) {
|
|
495
|
+
if (Math.abs(dx) < DRAG_THRESHOLD) return;
|
|
496
|
+
pendingRef.current = false;
|
|
497
|
+
}
|
|
498
|
+
const draggedLeft = d.lefts[d.index] ?? 0;
|
|
499
|
+
const draggedWidth = d.widths[d.index] ?? 0;
|
|
500
|
+
const draggedRightEdge = draggedLeft + draggedWidth + dx;
|
|
501
|
+
const draggedLeftEdge = draggedLeft + dx;
|
|
502
|
+
let newIndex = d.index;
|
|
503
|
+
const TRIGGER_RATIO = 0.3;
|
|
504
|
+
for (let i = 0; i < d.lefts.length; i++) {
|
|
505
|
+
if (i === d.index) continue;
|
|
506
|
+
const left = d.lefts[i] ?? 0;
|
|
507
|
+
const width = d.widths[i] ?? 0;
|
|
508
|
+
if (i > d.index) {
|
|
509
|
+
// Dragging right: trigger when right edge enters 30% of target
|
|
510
|
+
if (draggedRightEdge > left + width * TRIGGER_RATIO) newIndex = i;
|
|
511
|
+
} else {
|
|
512
|
+
// Dragging left: trigger when left edge enters 30% from right
|
|
513
|
+
if (draggedLeftEdge < left + width * (1 - TRIGGER_RATIO))
|
|
514
|
+
newIndex = Math.min(newIndex, i);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
const next: DragState = { ...d, offsetX: dx, currentIndex: newIndex };
|
|
518
|
+
dragRef.current = next;
|
|
519
|
+
setDrag(next);
|
|
520
|
+
}, []);
|
|
521
|
+
|
|
522
|
+
const handlePointerUp = React.useCallback(() => {
|
|
523
|
+
const d = dragRef.current;
|
|
524
|
+
if (d && !pendingRef.current && d.index !== d.currentIndex) {
|
|
525
|
+
onReorder?.(d.index, d.currentIndex);
|
|
526
|
+
}
|
|
527
|
+
dragRef.current = null;
|
|
528
|
+
pendingRef.current = false;
|
|
529
|
+
setDrag(null);
|
|
530
|
+
}, [onReorder]);
|
|
531
|
+
|
|
532
|
+
const getTransform = React.useCallback(
|
|
533
|
+
(index: number): React.CSSProperties => {
|
|
534
|
+
if (!drag || pendingRef.current) return {};
|
|
535
|
+
if (index === drag.index) {
|
|
536
|
+
return {
|
|
537
|
+
transform: `translateX(${drag.offsetX}px)`,
|
|
538
|
+
zIndex: 10,
|
|
539
|
+
position: "relative",
|
|
540
|
+
background: "var(--color-bg-primary)",
|
|
541
|
+
borderLeft: "1px solid var(--color-border-default)",
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
const from = drag.index;
|
|
545
|
+
const to = drag.currentIndex;
|
|
546
|
+
const draggedWidth = drag.widths[from] ?? 0;
|
|
547
|
+
if (from < to && index > from && index <= to) {
|
|
548
|
+
return {
|
|
549
|
+
transform: `translateX(${-draggedWidth}px)`,
|
|
550
|
+
transition: "transform 200ms ease",
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
if (from > to && index >= to && index < from) {
|
|
554
|
+
return {
|
|
555
|
+
transform: `translateX(${draggedWidth}px)`,
|
|
556
|
+
transition: "transform 200ms ease",
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
return { transition: "transform 200ms ease" };
|
|
560
|
+
},
|
|
561
|
+
[drag],
|
|
562
|
+
);
|
|
563
|
+
|
|
564
|
+
return {
|
|
565
|
+
drag,
|
|
566
|
+
itemsRef,
|
|
567
|
+
handlePointerDown,
|
|
568
|
+
handlePointerMove,
|
|
569
|
+
handlePointerUp,
|
|
570
|
+
getTransform,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
|
|
446
574
|
function TabsBrowserList({
|
|
447
575
|
className,
|
|
448
576
|
children,
|
|
577
|
+
onReorder,
|
|
449
578
|
...props
|
|
450
|
-
}: React.ComponentProps<typeof TabsPrimitive.List>
|
|
579
|
+
}: React.ComponentProps<typeof TabsPrimitive.List> & {
|
|
580
|
+
onReorder?: (fromIndex: number, toIndex: number) => void;
|
|
581
|
+
}) {
|
|
451
582
|
const tabsListRef = React.useRef<HTMLDivElement | null>(null);
|
|
452
583
|
|
|
453
584
|
const [showScrollButtons, setShowScrollButtons] = React.useState(false);
|
|
454
585
|
const [canScrollLeft, setCanScrollLeft] = React.useState(false);
|
|
455
586
|
const [canScrollRight, setCanScrollRight] = React.useState(false);
|
|
456
587
|
|
|
588
|
+
const {
|
|
589
|
+
drag,
|
|
590
|
+
itemsRef,
|
|
591
|
+
handlePointerDown,
|
|
592
|
+
handlePointerMove,
|
|
593
|
+
handlePointerUp,
|
|
594
|
+
getTransform,
|
|
595
|
+
} = useTabReorder(onReorder);
|
|
596
|
+
|
|
597
|
+
const wrappedChildren =
|
|
598
|
+
onReorder && React.Children.count(children) > 1
|
|
599
|
+
? React.Children.map(children, (child, index) => (
|
|
600
|
+
<div
|
|
601
|
+
ref={(el) => {
|
|
602
|
+
itemsRef.current[index] = el;
|
|
603
|
+
}}
|
|
604
|
+
style={getTransform(index)}
|
|
605
|
+
onPointerDown={(e) => handlePointerDown(e, index)}
|
|
606
|
+
onPointerMove={handlePointerMove}
|
|
607
|
+
onPointerUp={handlePointerUp}
|
|
608
|
+
className={cn(drag?.index === index && "cursor-grabbing")}
|
|
609
|
+
>
|
|
610
|
+
{child}
|
|
611
|
+
</div>
|
|
612
|
+
))
|
|
613
|
+
: children;
|
|
614
|
+
|
|
457
615
|
return (
|
|
458
616
|
<React.Fragment>
|
|
459
617
|
{showScrollButtons && (
|
|
@@ -506,7 +664,7 @@ function TabsBrowserList({
|
|
|
506
664
|
{...props}
|
|
507
665
|
ref={tabsListRef}
|
|
508
666
|
>
|
|
509
|
-
{
|
|
667
|
+
{wrappedChildren}
|
|
510
668
|
</TabsList>
|
|
511
669
|
|
|
512
670
|
{showScrollButtons && (
|
package/src/typography.css
CHANGED
|
@@ -46,7 +46,7 @@ body {
|
|
|
46
46
|
font-size: var(--font-size-xs);
|
|
47
47
|
font-family: var(--font-family-sans);
|
|
48
48
|
font-weight: var(--font-weight-normal);
|
|
49
|
-
line-height: var(--font-leading-
|
|
49
|
+
line-height: var(--font-leading-4);
|
|
50
50
|
}
|
|
51
51
|
.typo-label-xs {
|
|
52
52
|
font-size: var(--font-size-xs);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"http.test.d.ts","sourceRoot":"","sources":["../../../../../../src/components/code-editor/http/grammar/http.test.ts"],"names":[],"mappings":""}
|