@optilogic/core 1.0.0-beta.8 → 1.0.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/index.cjs +1115 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +326 -1
- package/dist/index.d.ts +326 -1
- package/dist/index.js +1097 -46
- package/dist/index.js.map +1 -1
- package/dist/styles.css +22 -0
- package/dist/tailwind-preset.cjs +17 -2
- package/dist/tailwind-preset.cjs.map +1 -1
- package/dist/tailwind-preset.js +17 -2
- package/dist/tailwind-preset.js.map +1 -1
- package/package.json +15 -1
- package/src/components/autocomplete.tsx +2 -1
- package/src/components/button.tsx +10 -8
- package/src/components/calendar.tsx +7 -7
- package/src/components/data-grid/DataGrid.tsx +6 -1
- package/src/components/data-grid/components/CellEditor.tsx +3 -3
- package/src/components/data-grid/hooks/useDataGridState.ts +18 -3
- package/src/components/data-grid/types.ts +4 -0
- package/src/components/data-grid/utils/dataProcessing.ts +40 -11
- package/src/components/date-picker.tsx +2 -1
- package/src/components/dropdown-menu.tsx +1 -1
- package/src/components/file-view/FileView.tsx +147 -0
- package/src/components/file-view/components/CodeRenderer.tsx +97 -0
- package/src/components/file-view/components/CsvRenderer.tsx +127 -0
- package/src/components/file-view/components/HtmlRenderer.tsx +24 -0
- package/src/components/file-view/components/ImageRenderer.tsx +67 -0
- package/src/components/file-view/components/MarkdownRenderer.tsx +304 -0
- package/src/components/file-view/components/PlainTextRenderer.tsx +27 -0
- package/src/components/file-view/components/index.ts +4 -0
- package/src/components/file-view/hooks/index.ts +5 -0
- package/src/components/file-view/hooks/useContentType.ts +34 -0
- package/src/components/file-view/hooks/useDarkMode.ts +62 -0
- package/src/components/file-view/hooks/useHighlightedTokens.ts +83 -0
- package/src/components/file-view/hooks/useShikiHighlighter.ts +69 -0
- package/src/components/file-view/index.ts +47 -0
- package/src/components/file-view/types.ts +180 -0
- package/src/components/file-view/utils/contentTypeDetection.ts +157 -0
- package/src/components/file-view/utils/index.ts +12 -0
- package/src/components/file-view/utils/languageMapping.ts +78 -0
- package/src/components/file-view/utils/rendererRegistry.ts +42 -0
- package/src/components/input.tsx +1 -1
- package/src/components/popover.tsx +1 -1
- package/src/components/select.tsx +1 -1
- package/src/components/switch.tsx +5 -3
- package/src/components/textarea.tsx +1 -1
- package/src/index.ts +39 -0
- package/src/styles.css +22 -0
- package/src/tailwind-preset.ts +17 -1
- package/src/theme/index.ts +5 -0
- package/src/theme/presets.ts +112 -2
- package/src/theme/types.ts +35 -0
- package/src/theme/utils.ts +231 -0
package/dist/index.js
CHANGED
|
@@ -22,23 +22,25 @@ import { Toaster as Toaster$1 } from 'sonner';
|
|
|
22
22
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
23
23
|
import { format, parse, isValid, parseISO } from 'date-fns';
|
|
24
24
|
import { DayPicker } from 'react-day-picker';
|
|
25
|
+
import ReactMarkdownImport from 'react-markdown';
|
|
26
|
+
import remarkGfmImport from 'remark-gfm';
|
|
25
27
|
|
|
26
28
|
// src/utils/cn.ts
|
|
27
29
|
function cn(...inputs) {
|
|
28
30
|
return twMerge(clsx(inputs));
|
|
29
31
|
}
|
|
30
32
|
var buttonVariants = cva(
|
|
31
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none
|
|
33
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
32
34
|
{
|
|
33
35
|
variants: {
|
|
34
36
|
variant: {
|
|
35
|
-
default: "bg-muted text-
|
|
36
|
-
primary: "bg-accent text-accent-foreground shadow hover:shadow-md",
|
|
37
|
-
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90 hover:shadow-md",
|
|
38
|
-
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
39
|
-
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
40
|
-
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
41
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
37
|
+
default: "bg-muted text-foreground hover:bg-accent hover:text-accent-foreground disabled:opacity-50 disabled:text-muted-foreground",
|
|
38
|
+
primary: "bg-accent text-accent-foreground shadow hover:shadow-md disabled:opacity-50",
|
|
39
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90 hover:shadow-md disabled:opacity-50",
|
|
40
|
+
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground disabled:opacity-50 disabled:bg-muted/20 disabled:text-muted-foreground",
|
|
41
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80 disabled:opacity-50",
|
|
42
|
+
ghost: "text-foreground hover:bg-accent hover:text-accent-foreground disabled:text-muted-foreground disabled:bg-muted/30 disabled:opacity-70",
|
|
43
|
+
link: "text-primary underline-offset-4 hover:underline disabled:opacity-50 disabled:text-muted-foreground"
|
|
42
44
|
},
|
|
43
45
|
size: {
|
|
44
46
|
default: "h-9 px-4 py-2",
|
|
@@ -74,7 +76,7 @@ var Input = React20.forwardRef(
|
|
|
74
76
|
{
|
|
75
77
|
type,
|
|
76
78
|
className: cn(
|
|
77
|
-
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
79
|
+
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground hover:border-input-hover focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-input md:text-sm",
|
|
78
80
|
className
|
|
79
81
|
),
|
|
80
82
|
ref,
|
|
@@ -102,7 +104,7 @@ var Textarea = React20.forwardRef(
|
|
|
102
104
|
"textarea",
|
|
103
105
|
{
|
|
104
106
|
className: cn(
|
|
105
|
-
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
107
|
+
"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground hover:border-input-hover focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-input md:text-sm",
|
|
106
108
|
className
|
|
107
109
|
),
|
|
108
110
|
ref,
|
|
@@ -190,9 +192,11 @@ var Switch = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
|
|
|
190
192
|
// Focus styles
|
|
191
193
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
192
194
|
// Disabled styles
|
|
193
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
195
|
+
"disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-muted",
|
|
194
196
|
// Unchecked state
|
|
195
|
-
"bg-
|
|
197
|
+
"bg-toggle-track",
|
|
198
|
+
// Hover
|
|
199
|
+
"hover:bg-toggle-track/80 data-[state=checked]:hover:bg-primary/80",
|
|
196
200
|
// Checked state
|
|
197
201
|
"data-[state=checked]:bg-primary",
|
|
198
202
|
className
|
|
@@ -205,7 +209,7 @@ var Switch = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ *
|
|
|
205
209
|
className: cn(
|
|
206
210
|
// Base styles
|
|
207
211
|
"pointer-events-none block h-4 w-4 rounded-full",
|
|
208
|
-
"bg-
|
|
212
|
+
"bg-toggle-track-foreground shadow-lg ring-0",
|
|
209
213
|
"transition-transform",
|
|
210
214
|
// Position based on state
|
|
211
215
|
"data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
|
|
@@ -268,7 +272,7 @@ var SelectTrigger = React20.forwardRef(({ className, children, ...props }, ref)
|
|
|
268
272
|
{
|
|
269
273
|
ref,
|
|
270
274
|
className: cn(
|
|
271
|
-
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
275
|
+
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground hover:border-input-hover focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-input [&>span]:line-clamp-1",
|
|
272
276
|
className
|
|
273
277
|
),
|
|
274
278
|
...props,
|
|
@@ -604,7 +608,7 @@ var PopoverContent = React20.forwardRef(({ className, align = "center", sideOffs
|
|
|
604
608
|
align,
|
|
605
609
|
sideOffset,
|
|
606
610
|
className: cn(
|
|
607
|
-
"z-50 w-
|
|
611
|
+
"z-50 w-auto max-w-[90vw] rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none",
|
|
608
612
|
// Animation
|
|
609
613
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
610
614
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
@@ -665,7 +669,7 @@ var DropdownMenuContent = React20.forwardRef(({ className, sideOffset = 4, ...pr
|
|
|
665
669
|
ref,
|
|
666
670
|
sideOffset,
|
|
667
671
|
className: cn(
|
|
668
|
-
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
|
|
672
|
+
"z-50 min-w-[8rem] max-w-[90vw] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md",
|
|
669
673
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
670
674
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
671
675
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
@@ -2702,19 +2706,19 @@ function Calendar({
|
|
|
2702
2706
|
className: cn("p-3", className),
|
|
2703
2707
|
classNames: {
|
|
2704
2708
|
months: "flex flex-col sm:flex-row gap-4",
|
|
2705
|
-
month: "flex flex-col gap-
|
|
2706
|
-
month_caption: "flex justify-center pt-1
|
|
2709
|
+
month: "flex flex-col gap-2 relative px-8",
|
|
2710
|
+
month_caption: "flex justify-center pt-1 items-center h-7",
|
|
2707
2711
|
caption_label: "text-sm font-medium hidden",
|
|
2708
2712
|
nav: "flex items-center gap-1",
|
|
2709
2713
|
button_previous: cn(
|
|
2710
2714
|
buttonVariants({ variant: "outline" }),
|
|
2711
|
-
"absolute left-1 h-
|
|
2715
|
+
"absolute left-1 top-1/2 -translate-y-1/2 h-6 w-6 bg-transparent p-0 opacity-50 hover:opacity-100 z-10"
|
|
2712
2716
|
),
|
|
2713
2717
|
button_next: cn(
|
|
2714
2718
|
buttonVariants({ variant: "outline" }),
|
|
2715
|
-
"absolute right-1 h-
|
|
2719
|
+
"absolute right-1 top-1/2 -translate-y-1/2 h-6 w-6 bg-transparent p-0 opacity-50 hover:opacity-100 z-10"
|
|
2716
2720
|
),
|
|
2717
|
-
month_grid: "
|
|
2721
|
+
month_grid: "border-collapse mx-auto",
|
|
2718
2722
|
weekdays: "flex",
|
|
2719
2723
|
weekday: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
|
|
2720
2724
|
week: "flex w-full mt-2",
|
|
@@ -2739,12 +2743,12 @@ function Calendar({
|
|
|
2739
2743
|
components: {
|
|
2740
2744
|
Chevron: ({ orientation }) => {
|
|
2741
2745
|
const Icon2 = orientation === "left" ? ChevronLeft : ChevronRight;
|
|
2742
|
-
return /* @__PURE__ */ jsx(Icon2, { className: "h-
|
|
2746
|
+
return /* @__PURE__ */ jsx(Icon2, { className: "h-3.5 w-3.5" });
|
|
2743
2747
|
},
|
|
2744
2748
|
MonthCaption: ({ calendarMonth }) => {
|
|
2745
2749
|
const month = calendarMonth.date.getMonth();
|
|
2746
2750
|
const year = calendarMonth.date.getFullYear();
|
|
2747
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1
|
|
2751
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1", children: [
|
|
2748
2752
|
/* @__PURE__ */ jsxs(
|
|
2749
2753
|
Select,
|
|
2750
2754
|
{
|
|
@@ -2980,8 +2984,9 @@ function DatePickerInput({
|
|
|
2980
2984
|
{
|
|
2981
2985
|
className: cn(
|
|
2982
2986
|
"flex items-center rounded-md border border-input bg-background ring-offset-background",
|
|
2987
|
+
"hover:border-input-hover",
|
|
2983
2988
|
"focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
|
|
2984
|
-
disabled && "opacity-50 cursor-not-allowed",
|
|
2989
|
+
disabled && "opacity-50 cursor-not-allowed hover:border-input",
|
|
2985
2990
|
sizeClasses[size]
|
|
2986
2991
|
),
|
|
2987
2992
|
children: [
|
|
@@ -3613,7 +3618,7 @@ function CellEditor({
|
|
|
3613
3618
|
onKeyDown: handleKeyDown,
|
|
3614
3619
|
onBlur: handleBlur,
|
|
3615
3620
|
className: cn(
|
|
3616
|
-
"h-full w-full border-0 rounded-none
|
|
3621
|
+
"h-full w-full border-0 rounded-none bg-background focus:ring-0 text-sm px-2",
|
|
3617
3622
|
validationError && "ring-2 ring-destructive focus:ring-destructive",
|
|
3618
3623
|
className
|
|
3619
3624
|
),
|
|
@@ -3631,7 +3636,7 @@ function CellEditor({
|
|
|
3631
3636
|
onKeyDown: handleKeyDown,
|
|
3632
3637
|
onBlur: handleBlur,
|
|
3633
3638
|
className: cn(
|
|
3634
|
-
"h-full w-full border-0 rounded-none
|
|
3639
|
+
"h-full w-full border-0 rounded-none bg-background focus:ring-0 text-sm px-2",
|
|
3635
3640
|
validationError && "ring-2 ring-destructive focus:ring-destructive",
|
|
3636
3641
|
className
|
|
3637
3642
|
),
|
|
@@ -3701,7 +3706,7 @@ function CellEditor({
|
|
|
3701
3706
|
{
|
|
3702
3707
|
ref: selectRef,
|
|
3703
3708
|
className: cn(
|
|
3704
|
-
"h-full w-full border-0 rounded-none
|
|
3709
|
+
"h-full w-full border-0 rounded-none bg-background focus:ring-0 text-sm",
|
|
3705
3710
|
validationError && "ring-2 ring-destructive focus:ring-destructive",
|
|
3706
3711
|
className
|
|
3707
3712
|
),
|
|
@@ -3846,6 +3851,7 @@ function useDataGridState(options) {
|
|
|
3846
3851
|
const [internalColumnWidths, setInternalColumnWidths] = useState(defaultColumnWidths);
|
|
3847
3852
|
const [internalFocusedCell, setInternalFocusedCell] = useState(null);
|
|
3848
3853
|
const [editingCell, setEditingCell] = useState(null);
|
|
3854
|
+
const processedDataRef = useRef([]);
|
|
3849
3855
|
const sorting = isControlled.sorting ? controlledSorting : internalSorting;
|
|
3850
3856
|
const filters = isControlled.filters ? controlledFilters : internalFilters;
|
|
3851
3857
|
const focusedCell = isControlled.focusedCell ? controlledFocusedCell : internalFocusedCell;
|
|
@@ -3966,7 +3972,8 @@ function useDataGridState(options) {
|
|
|
3966
3972
|
}
|
|
3967
3973
|
const column = columns.find((c) => c.key === columnKey);
|
|
3968
3974
|
if (!column || !column.editable) return;
|
|
3969
|
-
const
|
|
3975
|
+
const resolvedData = processedDataRef.current.length > 0 ? processedDataRef.current : data;
|
|
3976
|
+
const row = resolvedData[rowIndex];
|
|
3970
3977
|
if (!row) return;
|
|
3971
3978
|
const value = getCellValue2(row, column);
|
|
3972
3979
|
setEditingCell({
|
|
@@ -3988,7 +3995,8 @@ function useDataGridState(options) {
|
|
|
3988
3995
|
const value = valueOverride !== void 0 ? valueOverride : editingCell.value;
|
|
3989
3996
|
const column = columns.find((c) => c.key === columnKey);
|
|
3990
3997
|
if (column?.validator) {
|
|
3991
|
-
const
|
|
3998
|
+
const resolvedData = processedDataRef.current.length > 0 ? processedDataRef.current : data;
|
|
3999
|
+
const row = resolvedData[rowIndex];
|
|
3992
4000
|
const validationResult = column.validator(value, row);
|
|
3993
4001
|
if (validationResult !== true && typeof validationResult === "string") {
|
|
3994
4002
|
return;
|
|
@@ -4020,6 +4028,7 @@ function useDataGridState(options) {
|
|
|
4020
4028
|
commitEdit,
|
|
4021
4029
|
cancelEdit
|
|
4022
4030
|
},
|
|
4031
|
+
processedDataRef,
|
|
4023
4032
|
isControlled
|
|
4024
4033
|
};
|
|
4025
4034
|
}
|
|
@@ -4473,16 +4482,44 @@ function applySorting(data, sorting, columns) {
|
|
|
4473
4482
|
if (aVal == null) return sort.direction === "asc" ? 1 : -1;
|
|
4474
4483
|
if (bVal == null) return sort.direction === "asc" ? -1 : 1;
|
|
4475
4484
|
let comparison = 0;
|
|
4476
|
-
if (
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
} else {
|
|
4485
|
+
if (column.dataType === "number") {
|
|
4486
|
+
const aNum = Number(aVal);
|
|
4487
|
+
const bNum = Number(bVal);
|
|
4488
|
+
if (!isNaN(aNum) && !isNaN(bNum)) {
|
|
4489
|
+
comparison = aNum - bNum;
|
|
4490
|
+
} else {
|
|
4491
|
+
comparison = String(aVal).localeCompare(String(bVal));
|
|
4492
|
+
}
|
|
4493
|
+
} else if (column.dataType === "date") {
|
|
4494
|
+
const aDate = aVal instanceof Date ? aVal : new Date(aVal);
|
|
4495
|
+
const bDate = bVal instanceof Date ? bVal : new Date(bVal);
|
|
4496
|
+
const aTime = isNaN(aDate.getTime()) ? 0 : aDate.getTime();
|
|
4497
|
+
const bTime = isNaN(bDate.getTime()) ? 0 : bDate.getTime();
|
|
4498
|
+
comparison = aTime - bTime;
|
|
4499
|
+
} else if (column.dataType === "boolean") {
|
|
4500
|
+
const aBool = aVal === true || aVal === "true" || aVal === 1;
|
|
4501
|
+
const bBool = bVal === true || bVal === "true" || bVal === 1;
|
|
4502
|
+
comparison = aBool === bBool ? 0 : aBool ? 1 : -1;
|
|
4503
|
+
} else if (column.dataType === "string") {
|
|
4485
4504
|
comparison = String(aVal).localeCompare(String(bVal));
|
|
4505
|
+
} else {
|
|
4506
|
+
if (typeof aVal === "number" && typeof bVal === "number") {
|
|
4507
|
+
comparison = aVal - bVal;
|
|
4508
|
+
} else if (aVal instanceof Date && bVal instanceof Date) {
|
|
4509
|
+
comparison = aVal.getTime() - bVal.getTime();
|
|
4510
|
+
} else if (typeof aVal === "boolean" && typeof bVal === "boolean") {
|
|
4511
|
+
comparison = aVal === bVal ? 0 : aVal ? 1 : -1;
|
|
4512
|
+
} else {
|
|
4513
|
+
const aStr = String(aVal);
|
|
4514
|
+
const bStr = String(bVal);
|
|
4515
|
+
const aNum = Number(aStr);
|
|
4516
|
+
const bNum = Number(bStr);
|
|
4517
|
+
if (!isNaN(aNum) && !isNaN(bNum) && aStr !== "" && bStr !== "") {
|
|
4518
|
+
comparison = aNum - bNum;
|
|
4519
|
+
} else {
|
|
4520
|
+
comparison = aStr.localeCompare(bStr);
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4486
4523
|
}
|
|
4487
4524
|
return sort.direction === "asc" ? comparison : -comparison;
|
|
4488
4525
|
});
|
|
@@ -4704,7 +4741,7 @@ function DataGrid({
|
|
|
4704
4741
|
},
|
|
4705
4742
|
[]
|
|
4706
4743
|
);
|
|
4707
|
-
const { state, actions, isControlled } = useDataGridState({
|
|
4744
|
+
const { state, actions, processedDataRef, isControlled } = useDataGridState({
|
|
4708
4745
|
sorting: controlledSorting,
|
|
4709
4746
|
filters: controlledFilters,
|
|
4710
4747
|
columnWidths: controlledColumnWidths,
|
|
@@ -4743,6 +4780,7 @@ function DataGrid({
|
|
|
4743
4780
|
state.sorting,
|
|
4744
4781
|
visibleColumns
|
|
4745
4782
|
]);
|
|
4783
|
+
processedDataRef.current = processedData;
|
|
4746
4784
|
const { resizingColumn, getResizeProps } = useColumnResizeManager({
|
|
4747
4785
|
columns: visibleColumns,
|
|
4748
4786
|
columnWidths: state.columnWidths,
|
|
@@ -5078,6 +5116,7 @@ function DataGrid({
|
|
|
5078
5116
|
"flex-shrink-0 px-3 py-2 text-sm overflow-hidden",
|
|
5079
5117
|
showColumnBorders && "border-r border-border last:border-r-0",
|
|
5080
5118
|
isFocused && !isEditingThisCell && "ring-2 ring-inset ring-primary",
|
|
5119
|
+
isEditingThisCell && "ring-2 ring-inset ring-primary bg-background",
|
|
5081
5120
|
column.align === "center" && "text-center",
|
|
5082
5121
|
column.align === "right" && "text-right"
|
|
5083
5122
|
),
|
|
@@ -5247,6 +5286,7 @@ function DataGrid({
|
|
|
5247
5286
|
"flex-shrink-0 px-3 py-2 text-sm overflow-hidden",
|
|
5248
5287
|
showColumnBorders && "border-r border-border last:border-r-0",
|
|
5249
5288
|
isFocused && !isEditingThisCell && "ring-2 ring-inset ring-primary",
|
|
5289
|
+
isEditingThisCell && "ring-2 ring-inset ring-primary bg-background",
|
|
5250
5290
|
column.align === "center" && "text-center",
|
|
5251
5291
|
column.align === "right" && "text-right"
|
|
5252
5292
|
),
|
|
@@ -5502,8 +5542,9 @@ function Autocomplete({
|
|
|
5502
5542
|
disabled,
|
|
5503
5543
|
className: cn(
|
|
5504
5544
|
"flex h-9 w-full items-center justify-between gap-2 whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background",
|
|
5545
|
+
"hover:border-input-hover",
|
|
5505
5546
|
"focus:outline-none focus:ring-1 focus:ring-ring",
|
|
5506
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
5547
|
+
"disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-input",
|
|
5507
5548
|
!selectedOption && "text-muted-foreground",
|
|
5508
5549
|
className
|
|
5509
5550
|
),
|
|
@@ -5734,11 +5775,21 @@ var GREEN_THEME = {
|
|
|
5734
5775
|
border: "#243630",
|
|
5735
5776
|
input: "#243630",
|
|
5736
5777
|
ring: "#6FCF97",
|
|
5778
|
+
toggleTrack: "#354840",
|
|
5779
|
+
toggleTrackForeground: "#E6F5EC",
|
|
5780
|
+
inputHover: "#6FCF97",
|
|
5737
5781
|
chart1: "#6FCF97",
|
|
5738
5782
|
chart2: "#8FE3B0",
|
|
5739
5783
|
chart3: "#9DB8A8",
|
|
5740
5784
|
chart4: "#2d4038",
|
|
5741
5785
|
chart5: "#354840",
|
|
5786
|
+
chart6: "#4CAF50",
|
|
5787
|
+
chart7: "#81C784",
|
|
5788
|
+
chart8: "#F2C94C",
|
|
5789
|
+
chart9: "#EB5757",
|
|
5790
|
+
chart10: "#56CCF2",
|
|
5791
|
+
chart11: "#BB6BD9",
|
|
5792
|
+
chart12: "#2D9CDB",
|
|
5742
5793
|
radius: "0.5rem"
|
|
5743
5794
|
};
|
|
5744
5795
|
var OPTILOGIC_LEGACY_THEME = {
|
|
@@ -5769,13 +5820,23 @@ var OPTILOGIC_LEGACY_THEME = {
|
|
|
5769
5820
|
chip: "#B8C5F9",
|
|
5770
5821
|
chipForeground: "#0C0A5A",
|
|
5771
5822
|
border: "#D0D0D0",
|
|
5772
|
-
input: "#
|
|
5823
|
+
input: "#D0D0D0",
|
|
5773
5824
|
ring: "#5766F2",
|
|
5825
|
+
toggleTrack: "#D0D0D0",
|
|
5826
|
+
toggleTrackForeground: "#FFFFFF",
|
|
5827
|
+
inputHover: "#5766F2",
|
|
5774
5828
|
chart1: "#78D237",
|
|
5775
5829
|
chart2: "#F5CF47",
|
|
5776
5830
|
chart3: "#5766F2",
|
|
5777
5831
|
chart4: "#44BD7E",
|
|
5778
5832
|
chart5: "#929BEF",
|
|
5833
|
+
chart6: "#DB2828",
|
|
5834
|
+
chart7: "#E07B39",
|
|
5835
|
+
chart8: "#2BBBAD",
|
|
5836
|
+
chart9: "#A5673F",
|
|
5837
|
+
chart10: "#00B5AD",
|
|
5838
|
+
chart11: "#6435C9",
|
|
5839
|
+
chart12: "#E03997",
|
|
5779
5840
|
radius: "0.5rem"
|
|
5780
5841
|
};
|
|
5781
5842
|
var FUTURISTIC_THEME = {
|
|
@@ -5808,11 +5869,21 @@ var FUTURISTIC_THEME = {
|
|
|
5808
5869
|
border: "#1e293b",
|
|
5809
5870
|
input: "#1e293b",
|
|
5810
5871
|
ring: "#6366f1",
|
|
5872
|
+
toggleTrack: "#334155",
|
|
5873
|
+
toggleTrackForeground: "#e0e7ff",
|
|
5874
|
+
inputHover: "#6366f1",
|
|
5811
5875
|
chart1: "#6366f1",
|
|
5812
5876
|
chart2: "#8b5cf6",
|
|
5813
5877
|
chart3: "#a855f7",
|
|
5814
5878
|
chart4: "#ec4899",
|
|
5815
5879
|
chart5: "#f43f5e",
|
|
5880
|
+
chart6: "#06b6d4",
|
|
5881
|
+
chart7: "#14b8a6",
|
|
5882
|
+
chart8: "#f97316",
|
|
5883
|
+
chart9: "#eab308",
|
|
5884
|
+
chart10: "#22c55e",
|
|
5885
|
+
chart11: "#0ea5e9",
|
|
5886
|
+
chart12: "#f43f5e",
|
|
5816
5887
|
radius: "0.5rem"
|
|
5817
5888
|
};
|
|
5818
5889
|
var NATURE_THEME = {
|
|
@@ -5845,11 +5916,21 @@ var NATURE_THEME = {
|
|
|
5845
5916
|
border: "#243824",
|
|
5846
5917
|
input: "#243824",
|
|
5847
5918
|
ring: "#4caf50",
|
|
5919
|
+
toggleTrack: "#3d5a3d",
|
|
5920
|
+
toggleTrackForeground: "#e8f5e9",
|
|
5921
|
+
inputHover: "#4caf50",
|
|
5848
5922
|
chart1: "#4caf50",
|
|
5849
5923
|
chart2: "#66bb6a",
|
|
5850
5924
|
chart3: "#81c784",
|
|
5851
5925
|
chart4: "#a5d6a7",
|
|
5852
5926
|
chart5: "#c8e6c9",
|
|
5927
|
+
chart6: "#8bc34a",
|
|
5928
|
+
chart7: "#cddc39",
|
|
5929
|
+
chart8: "#ffb74d",
|
|
5930
|
+
chart9: "#4db6ac",
|
|
5931
|
+
chart10: "#7986cb",
|
|
5932
|
+
chart11: "#e57373",
|
|
5933
|
+
chart12: "#64b5f6",
|
|
5853
5934
|
radius: "0.5rem"
|
|
5854
5935
|
};
|
|
5855
5936
|
var SCIFI_THEME = {
|
|
@@ -5882,11 +5963,21 @@ var SCIFI_THEME = {
|
|
|
5882
5963
|
border: "#30363d",
|
|
5883
5964
|
input: "#21262d",
|
|
5884
5965
|
ring: "#00d9ff",
|
|
5966
|
+
toggleTrack: "#30363d",
|
|
5967
|
+
toggleTrackForeground: "#c9d1d9",
|
|
5968
|
+
inputHover: "#00d9ff",
|
|
5885
5969
|
chart1: "#00d9ff",
|
|
5886
5970
|
chart2: "#ff00ff",
|
|
5887
5971
|
chart3: "#00ff88",
|
|
5888
5972
|
chart4: "#ffd93d",
|
|
5889
5973
|
chart5: "#58a6ff",
|
|
5974
|
+
chart6: "#ff6b6b",
|
|
5975
|
+
chart7: "#4ecdc4",
|
|
5976
|
+
chart8: "#a855f7",
|
|
5977
|
+
chart9: "#fb923c",
|
|
5978
|
+
chart10: "#38bdf8",
|
|
5979
|
+
chart11: "#f472b6",
|
|
5980
|
+
chart12: "#34d399",
|
|
5890
5981
|
radius: "0.5rem"
|
|
5891
5982
|
};
|
|
5892
5983
|
var OCEAN_THEME = {
|
|
@@ -5919,11 +6010,21 @@ var OCEAN_THEME = {
|
|
|
5919
6010
|
border: "#1e3a5f",
|
|
5920
6011
|
input: "#1e3a5f",
|
|
5921
6012
|
ring: "#2196f3",
|
|
6013
|
+
toggleTrack: "#264a6e",
|
|
6014
|
+
toggleTrackForeground: "#e3f2fd",
|
|
6015
|
+
inputHover: "#2196f3",
|
|
5922
6016
|
chart1: "#2196f3",
|
|
5923
6017
|
chart2: "#00bcd4",
|
|
5924
6018
|
chart3: "#03a9f4",
|
|
5925
6019
|
chart4: "#0288d1",
|
|
5926
6020
|
chart5: "#0277bd",
|
|
6021
|
+
chart6: "#26c6da",
|
|
6022
|
+
chart7: "#42a5f5",
|
|
6023
|
+
chart8: "#66bb6a",
|
|
6024
|
+
chart9: "#ffb74d",
|
|
6025
|
+
chart10: "#ef5350",
|
|
6026
|
+
chart11: "#ab47bc",
|
|
6027
|
+
chart12: "#78909c",
|
|
5927
6028
|
radius: "0.5rem"
|
|
5928
6029
|
};
|
|
5929
6030
|
var SUNSET_THEME = {
|
|
@@ -5956,11 +6057,21 @@ var SUNSET_THEME = {
|
|
|
5956
6057
|
border: "#241424",
|
|
5957
6058
|
input: "#241424",
|
|
5958
6059
|
ring: "#ff6b35",
|
|
6060
|
+
toggleTrack: "#3d2a3d",
|
|
6061
|
+
toggleTrackForeground: "#ffe0e6",
|
|
6062
|
+
inputHover: "#ff6b35",
|
|
5959
6063
|
chart1: "#ff6b35",
|
|
5960
6064
|
chart2: "#c44569",
|
|
5961
6065
|
chart3: "#f7931e",
|
|
5962
6066
|
chart4: "#ffb703",
|
|
5963
6067
|
chart5: "#ff8c42",
|
|
6068
|
+
chart6: "#06d6a0",
|
|
6069
|
+
chart7: "#118ab2",
|
|
6070
|
+
chart8: "#ef476f",
|
|
6071
|
+
chart9: "#ffd166",
|
|
6072
|
+
chart10: "#073b4c",
|
|
6073
|
+
chart11: "#8338ec",
|
|
6074
|
+
chart12: "#3a86ff",
|
|
5964
6075
|
radius: "0.5rem"
|
|
5965
6076
|
};
|
|
5966
6077
|
var FOREST_THEME = {
|
|
@@ -5993,11 +6104,21 @@ var FOREST_THEME = {
|
|
|
5993
6104
|
border: "#1b5e20",
|
|
5994
6105
|
input: "#1a2e1a",
|
|
5995
6106
|
ring: "#2e7d32",
|
|
6107
|
+
toggleTrack: "#2d4a2d",
|
|
6108
|
+
toggleTrackForeground: "#e8f5e9",
|
|
6109
|
+
inputHover: "#2e7d32",
|
|
5996
6110
|
chart1: "#2e7d32",
|
|
5997
6111
|
chart2: "#388e3c",
|
|
5998
6112
|
chart3: "#43a047",
|
|
5999
6113
|
chart4: "#66bb6a",
|
|
6000
6114
|
chart5: "#81c784",
|
|
6115
|
+
chart6: "#a5d6a7",
|
|
6116
|
+
chart7: "#c8e6c9",
|
|
6117
|
+
chart8: "#ffb74d",
|
|
6118
|
+
chart9: "#4db6ac",
|
|
6119
|
+
chart10: "#7986cb",
|
|
6120
|
+
chart11: "#e57373",
|
|
6121
|
+
chart12: "#64b5f6",
|
|
6001
6122
|
radius: "0.5rem"
|
|
6002
6123
|
};
|
|
6003
6124
|
var CYBERPUNK_THEME = {
|
|
@@ -6030,11 +6151,21 @@ var CYBERPUNK_THEME = {
|
|
|
6030
6151
|
border: "#1a1a2e",
|
|
6031
6152
|
input: "#16213e",
|
|
6032
6153
|
ring: "#ff00ff",
|
|
6154
|
+
toggleTrack: "#2a2a4e",
|
|
6155
|
+
toggleTrackForeground: "#f0f0f0",
|
|
6156
|
+
inputHover: "#ff00ff",
|
|
6033
6157
|
chart1: "#ff00ff",
|
|
6034
6158
|
chart2: "#00ffff",
|
|
6035
6159
|
chart3: "#00ff88",
|
|
6036
6160
|
chart4: "#ffd700",
|
|
6037
6161
|
chart5: "#ff1744",
|
|
6162
|
+
chart6: "#ff6b6b",
|
|
6163
|
+
chart7: "#4ecdc4",
|
|
6164
|
+
chart8: "#a855f7",
|
|
6165
|
+
chart9: "#fb923c",
|
|
6166
|
+
chart10: "#38bdf8",
|
|
6167
|
+
chart11: "#84cc16",
|
|
6168
|
+
chart12: "#f97316",
|
|
6038
6169
|
radius: "0.5rem"
|
|
6039
6170
|
};
|
|
6040
6171
|
var MINIMALIST_LIGHT_THEME = {
|
|
@@ -6065,13 +6196,23 @@ var MINIMALIST_LIGHT_THEME = {
|
|
|
6065
6196
|
chip: "#e9ecef",
|
|
6066
6197
|
chipForeground: "#495057",
|
|
6067
6198
|
border: "#dee2e6",
|
|
6068
|
-
input: "#
|
|
6199
|
+
input: "#dee2e6",
|
|
6069
6200
|
ring: "#000000",
|
|
6201
|
+
toggleTrack: "#ced4da",
|
|
6202
|
+
toggleTrackForeground: "#ffffff",
|
|
6203
|
+
inputHover: "#6c757d",
|
|
6070
6204
|
chart1: "#000000",
|
|
6071
6205
|
chart2: "#6c757d",
|
|
6072
6206
|
chart3: "#adb5bd",
|
|
6073
6207
|
chart4: "#dee2e6",
|
|
6074
6208
|
chart5: "#e9ecef",
|
|
6209
|
+
chart6: "#343a40",
|
|
6210
|
+
chart7: "#495057",
|
|
6211
|
+
chart8: "#868e96",
|
|
6212
|
+
chart9: "#5c6bc0",
|
|
6213
|
+
chart10: "#26a69a",
|
|
6214
|
+
chart11: "#ef5350",
|
|
6215
|
+
chart12: "#ffa726",
|
|
6075
6216
|
radius: "0.5rem"
|
|
6076
6217
|
};
|
|
6077
6218
|
var DARK_ELEGANT_THEME = {
|
|
@@ -6104,11 +6245,21 @@ var DARK_ELEGANT_THEME = {
|
|
|
6104
6245
|
border: "#2d2d2d",
|
|
6105
6246
|
input: "#1e1e1e",
|
|
6106
6247
|
ring: "#bb86fc",
|
|
6248
|
+
toggleTrack: "#3d3d3d",
|
|
6249
|
+
toggleTrackForeground: "#e0e0e0",
|
|
6250
|
+
inputHover: "#bb86fc",
|
|
6107
6251
|
chart1: "#bb86fc",
|
|
6108
6252
|
chart2: "#03dac6",
|
|
6109
6253
|
chart3: "#4caf50",
|
|
6110
6254
|
chart4: "#ff9800",
|
|
6111
6255
|
chart5: "#cf6679",
|
|
6256
|
+
chart6: "#64b5f6",
|
|
6257
|
+
chart7: "#81c784",
|
|
6258
|
+
chart8: "#ffb74d",
|
|
6259
|
+
chart9: "#e57373",
|
|
6260
|
+
chart10: "#7986cb",
|
|
6261
|
+
chart11: "#4db6ac",
|
|
6262
|
+
chart12: "#f06292",
|
|
6112
6263
|
radius: "0.5rem"
|
|
6113
6264
|
};
|
|
6114
6265
|
var PRESET_THEMES = [OPTILOGIC_LEGACY_THEME];
|
|
@@ -6194,13 +6345,32 @@ function themeToHsl(theme) {
|
|
|
6194
6345
|
border: hexToHsl(theme.border),
|
|
6195
6346
|
input: hexToHsl(theme.input),
|
|
6196
6347
|
ring: hexToHsl(theme.ring),
|
|
6348
|
+
toggleTrack: theme.toggleTrack ? hexToHsl(theme.toggleTrack) : void 0,
|
|
6349
|
+
toggleTrackForeground: theme.toggleTrackForeground ? hexToHsl(theme.toggleTrackForeground) : void 0,
|
|
6350
|
+
inputHover: theme.inputHover ? hexToHsl(theme.inputHover) : void 0,
|
|
6197
6351
|
chart1: hexToHsl(theme.chart1),
|
|
6198
6352
|
chart2: hexToHsl(theme.chart2),
|
|
6199
6353
|
chart3: hexToHsl(theme.chart3),
|
|
6200
6354
|
chart4: hexToHsl(theme.chart4),
|
|
6201
|
-
chart5: hexToHsl(theme.chart5)
|
|
6355
|
+
chart5: hexToHsl(theme.chart5),
|
|
6356
|
+
chart6: hexToHsl(theme.chart6),
|
|
6357
|
+
chart7: hexToHsl(theme.chart7),
|
|
6358
|
+
chart8: hexToHsl(theme.chart8),
|
|
6359
|
+
chart9: hexToHsl(theme.chart9),
|
|
6360
|
+
chart10: hexToHsl(theme.chart10),
|
|
6361
|
+
chart11: hexToHsl(theme.chart11),
|
|
6362
|
+
chart12: hexToHsl(theme.chart12)
|
|
6202
6363
|
};
|
|
6203
6364
|
}
|
|
6365
|
+
function deriveInputHoverHsl(hslTheme) {
|
|
6366
|
+
const parts = hslTheme.foreground.split(/\s+/);
|
|
6367
|
+
if (parts.length >= 3) {
|
|
6368
|
+
const h = parts[0];
|
|
6369
|
+
const s = parts[1];
|
|
6370
|
+
return `${h} ${s} 50%`;
|
|
6371
|
+
}
|
|
6372
|
+
return hslTheme.foreground;
|
|
6373
|
+
}
|
|
6204
6374
|
function applyTheme(theme, targetElement) {
|
|
6205
6375
|
const element = targetElement || document.documentElement;
|
|
6206
6376
|
const hslTheme = themeToHsl(theme);
|
|
@@ -6235,11 +6405,33 @@ function applyTheme(theme, targetElement) {
|
|
|
6235
6405
|
element.style.setProperty("--border", hslTheme.border);
|
|
6236
6406
|
element.style.setProperty("--input", hslTheme.input);
|
|
6237
6407
|
element.style.setProperty("--ring", hslTheme.ring);
|
|
6408
|
+
element.style.setProperty(
|
|
6409
|
+
"--toggle-track",
|
|
6410
|
+
hslTheme.toggleTrack ?? hslTheme.muted
|
|
6411
|
+
);
|
|
6412
|
+
element.style.setProperty(
|
|
6413
|
+
"--toggle-track-foreground",
|
|
6414
|
+
hslTheme.toggleTrackForeground ?? hslTheme.background
|
|
6415
|
+
);
|
|
6416
|
+
element.style.setProperty(
|
|
6417
|
+
"--input-hover",
|
|
6418
|
+
hslTheme.inputHover ?? deriveInputHoverHsl(hslTheme)
|
|
6419
|
+
);
|
|
6238
6420
|
element.style.setProperty("--chart-1", hslTheme.chart1);
|
|
6239
6421
|
element.style.setProperty("--chart-2", hslTheme.chart2);
|
|
6240
6422
|
element.style.setProperty("--chart-3", hslTheme.chart3);
|
|
6241
6423
|
element.style.setProperty("--chart-4", hslTheme.chart4);
|
|
6242
6424
|
element.style.setProperty("--chart-5", hslTheme.chart5);
|
|
6425
|
+
element.style.setProperty("--chart-6", hslTheme.chart6);
|
|
6426
|
+
element.style.setProperty("--chart-7", hslTheme.chart7);
|
|
6427
|
+
element.style.setProperty("--chart-8", hslTheme.chart8);
|
|
6428
|
+
element.style.setProperty("--chart-9", hslTheme.chart9);
|
|
6429
|
+
element.style.setProperty("--chart-10", hslTheme.chart10);
|
|
6430
|
+
element.style.setProperty("--chart-11", hslTheme.chart11);
|
|
6431
|
+
element.style.setProperty("--chart-12", hslTheme.chart12);
|
|
6432
|
+
if (theme.disabledOpacity) {
|
|
6433
|
+
element.style.setProperty("--disabled-opacity", theme.disabledOpacity);
|
|
6434
|
+
}
|
|
6243
6435
|
if (theme.radius) {
|
|
6244
6436
|
element.style.setProperty("--radius", theme.radius);
|
|
6245
6437
|
}
|
|
@@ -6282,7 +6474,14 @@ function validateTheme(theme) {
|
|
|
6282
6474
|
"chart2",
|
|
6283
6475
|
"chart3",
|
|
6284
6476
|
"chart4",
|
|
6285
|
-
"chart5"
|
|
6477
|
+
"chart5",
|
|
6478
|
+
"chart6",
|
|
6479
|
+
"chart7",
|
|
6480
|
+
"chart8",
|
|
6481
|
+
"chart9",
|
|
6482
|
+
"chart10",
|
|
6483
|
+
"chart11",
|
|
6484
|
+
"chart12"
|
|
6286
6485
|
];
|
|
6287
6486
|
for (const field of requiredFields) {
|
|
6288
6487
|
if (!(field in t)) {
|
|
@@ -6330,11 +6529,21 @@ function areThemesEqual(theme1, theme2) {
|
|
|
6330
6529
|
"border",
|
|
6331
6530
|
"input",
|
|
6332
6531
|
"ring",
|
|
6532
|
+
"toggleTrack",
|
|
6533
|
+
"toggleTrackForeground",
|
|
6534
|
+
"inputHover",
|
|
6333
6535
|
"chart1",
|
|
6334
6536
|
"chart2",
|
|
6335
6537
|
"chart3",
|
|
6336
6538
|
"chart4",
|
|
6337
|
-
"chart5"
|
|
6539
|
+
"chart5",
|
|
6540
|
+
"chart6",
|
|
6541
|
+
"chart7",
|
|
6542
|
+
"chart8",
|
|
6543
|
+
"chart9",
|
|
6544
|
+
"chart10",
|
|
6545
|
+
"chart11",
|
|
6546
|
+
"chart12"
|
|
6338
6547
|
];
|
|
6339
6548
|
for (const field of colorFields) {
|
|
6340
6549
|
if (theme1[field] !== theme2[field]) {
|
|
@@ -6768,6 +6977,848 @@ function useContextMenu() {
|
|
|
6768
6977
|
};
|
|
6769
6978
|
}
|
|
6770
6979
|
|
|
6771
|
-
|
|
6980
|
+
// src/components/file-view/utils/contentTypeDetection.ts
|
|
6981
|
+
var EXTENSION_MAP = {
|
|
6982
|
+
// Code / programming languages
|
|
6983
|
+
ts: "code",
|
|
6984
|
+
tsx: "code",
|
|
6985
|
+
js: "code",
|
|
6986
|
+
jsx: "code",
|
|
6987
|
+
mjs: "code",
|
|
6988
|
+
cjs: "code",
|
|
6989
|
+
py: "code",
|
|
6990
|
+
rb: "code",
|
|
6991
|
+
go: "code",
|
|
6992
|
+
rs: "code",
|
|
6993
|
+
java: "code",
|
|
6994
|
+
c: "code",
|
|
6995
|
+
cpp: "code",
|
|
6996
|
+
h: "code",
|
|
6997
|
+
hpp: "code",
|
|
6998
|
+
cs: "code",
|
|
6999
|
+
php: "code",
|
|
7000
|
+
swift: "code",
|
|
7001
|
+
kt: "code",
|
|
7002
|
+
scala: "code",
|
|
7003
|
+
r: "code",
|
|
7004
|
+
sql: "code",
|
|
7005
|
+
sh: "code",
|
|
7006
|
+
bash: "code",
|
|
7007
|
+
zsh: "code",
|
|
7008
|
+
ps1: "code",
|
|
7009
|
+
bat: "code",
|
|
7010
|
+
lua: "code",
|
|
7011
|
+
perl: "code",
|
|
7012
|
+
pl: "code",
|
|
7013
|
+
// Config / data (code-rendered)
|
|
7014
|
+
json: "code",
|
|
7015
|
+
yaml: "code",
|
|
7016
|
+
yml: "code",
|
|
7017
|
+
toml: "code",
|
|
7018
|
+
xml: "code",
|
|
7019
|
+
html: "html",
|
|
7020
|
+
htm: "html",
|
|
7021
|
+
css: "code",
|
|
7022
|
+
scss: "code",
|
|
7023
|
+
sass: "code",
|
|
7024
|
+
less: "code",
|
|
7025
|
+
graphql: "code",
|
|
7026
|
+
gql: "code",
|
|
7027
|
+
// Optimization / domain-specific
|
|
7028
|
+
lp: "code",
|
|
7029
|
+
dat: "code",
|
|
7030
|
+
// Markdown
|
|
7031
|
+
md: "markdown",
|
|
7032
|
+
mdx: "markdown",
|
|
7033
|
+
// Images
|
|
7034
|
+
png: "image",
|
|
7035
|
+
jpg: "image",
|
|
7036
|
+
jpeg: "image",
|
|
7037
|
+
gif: "image",
|
|
7038
|
+
svg: "image",
|
|
7039
|
+
webp: "image",
|
|
7040
|
+
ico: "image",
|
|
7041
|
+
bmp: "image",
|
|
7042
|
+
// PDF
|
|
7043
|
+
pdf: "pdf",
|
|
7044
|
+
// CSV
|
|
7045
|
+
csv: "csv",
|
|
7046
|
+
tsv: "csv",
|
|
7047
|
+
// Plain text
|
|
7048
|
+
txt: "plaintext",
|
|
7049
|
+
log: "plaintext",
|
|
7050
|
+
env: "plaintext"
|
|
7051
|
+
};
|
|
7052
|
+
var SPECIAL_FILES = {
|
|
7053
|
+
dockerfile: "code",
|
|
7054
|
+
makefile: "code",
|
|
7055
|
+
rakefile: "code",
|
|
7056
|
+
gemfile: "code",
|
|
7057
|
+
procfile: "code"
|
|
7058
|
+
};
|
|
7059
|
+
function getFileExtension(fileName) {
|
|
7060
|
+
if (!fileName) return null;
|
|
7061
|
+
const baseName = fileName.split("/").pop() || fileName;
|
|
7062
|
+
if (baseName.startsWith(".") && !baseName.slice(1).includes(".")) {
|
|
7063
|
+
return baseName.slice(1).toLowerCase();
|
|
7064
|
+
}
|
|
7065
|
+
const lastDot = baseName.lastIndexOf(".");
|
|
7066
|
+
if (lastDot === -1 || lastDot === baseName.length - 1) return null;
|
|
7067
|
+
return baseName.slice(lastDot + 1).toLowerCase();
|
|
7068
|
+
}
|
|
7069
|
+
function detectContentType(fileName) {
|
|
7070
|
+
const baseName = (fileName.split("/").pop() || fileName).toLowerCase();
|
|
7071
|
+
const specialType = SPECIAL_FILES[baseName];
|
|
7072
|
+
if (specialType) {
|
|
7073
|
+
return { type: specialType, extension: baseName };
|
|
7074
|
+
}
|
|
7075
|
+
const extension = getFileExtension(fileName);
|
|
7076
|
+
if (!extension) {
|
|
7077
|
+
return { type: "unknown", extension: null };
|
|
7078
|
+
}
|
|
7079
|
+
const type = EXTENSION_MAP[extension] ?? "unknown";
|
|
7080
|
+
return { type, extension };
|
|
7081
|
+
}
|
|
7082
|
+
function isTextContentType(contentType) {
|
|
7083
|
+
return contentType === "code" || contentType === "markdown" || contentType === "plaintext" || contentType === "csv" || contentType === "html" || contentType === "unknown";
|
|
7084
|
+
}
|
|
7085
|
+
function isUrlContentType(contentType) {
|
|
7086
|
+
return contentType === "image" || contentType === "pdf";
|
|
7087
|
+
}
|
|
7088
|
+
|
|
7089
|
+
// src/components/file-view/hooks/useContentType.ts
|
|
7090
|
+
function useContentType({
|
|
7091
|
+
fileName,
|
|
7092
|
+
contentTypeOverride
|
|
7093
|
+
}) {
|
|
7094
|
+
return useMemo(() => {
|
|
7095
|
+
if (contentTypeOverride) {
|
|
7096
|
+
return {
|
|
7097
|
+
type: contentTypeOverride,
|
|
7098
|
+
extension: null,
|
|
7099
|
+
isOverridden: true
|
|
7100
|
+
};
|
|
7101
|
+
}
|
|
7102
|
+
const detected = detectContentType(fileName);
|
|
7103
|
+
return { ...detected, isOverridden: false };
|
|
7104
|
+
}, [fileName, contentTypeOverride]);
|
|
7105
|
+
}
|
|
7106
|
+
var globalHighlighter = null;
|
|
7107
|
+
var initPromise = null;
|
|
7108
|
+
async function getOrCreateHighlighter() {
|
|
7109
|
+
if (globalHighlighter) return globalHighlighter;
|
|
7110
|
+
if (!initPromise) {
|
|
7111
|
+
initPromise = (async () => {
|
|
7112
|
+
try {
|
|
7113
|
+
const { createHighlighter } = await import('shiki');
|
|
7114
|
+
globalHighlighter = await createHighlighter({
|
|
7115
|
+
themes: ["github-light", "github-dark"],
|
|
7116
|
+
langs: []
|
|
7117
|
+
});
|
|
7118
|
+
return globalHighlighter;
|
|
7119
|
+
} catch {
|
|
7120
|
+
return null;
|
|
7121
|
+
}
|
|
7122
|
+
})();
|
|
7123
|
+
}
|
|
7124
|
+
return initPromise;
|
|
7125
|
+
}
|
|
7126
|
+
function useShikiHighlighter() {
|
|
7127
|
+
const [state, setState] = useState({
|
|
7128
|
+
highlighter: globalHighlighter,
|
|
7129
|
+
isReady: globalHighlighter !== null
|
|
7130
|
+
});
|
|
7131
|
+
useEffect(() => {
|
|
7132
|
+
if (globalHighlighter) {
|
|
7133
|
+
setState({ highlighter: globalHighlighter, isReady: true });
|
|
7134
|
+
return;
|
|
7135
|
+
}
|
|
7136
|
+
let cancelled = false;
|
|
7137
|
+
getOrCreateHighlighter().then((h) => {
|
|
7138
|
+
if (!cancelled) {
|
|
7139
|
+
setState({ highlighter: h, isReady: true });
|
|
7140
|
+
}
|
|
7141
|
+
});
|
|
7142
|
+
return () => {
|
|
7143
|
+
cancelled = true;
|
|
7144
|
+
};
|
|
7145
|
+
}, []);
|
|
7146
|
+
return state;
|
|
7147
|
+
}
|
|
7148
|
+
function getBackgroundLightness(el) {
|
|
7149
|
+
const value = getComputedStyle(el).getPropertyValue("--background").trim();
|
|
7150
|
+
if (!value) return null;
|
|
7151
|
+
const match = value.match(/(\d+(?:\.\d+)?)%\s*$/);
|
|
7152
|
+
return match ? parseFloat(match[1]) : null;
|
|
7153
|
+
}
|
|
7154
|
+
function useDarkMode() {
|
|
7155
|
+
const checkDark = useCallback(() => {
|
|
7156
|
+
if (typeof document === "undefined") return false;
|
|
7157
|
+
const lightness = getBackgroundLightness(document.documentElement);
|
|
7158
|
+
if (lightness === null) {
|
|
7159
|
+
return document.documentElement.classList.contains("dark");
|
|
7160
|
+
}
|
|
7161
|
+
return lightness < 50;
|
|
7162
|
+
}, []);
|
|
7163
|
+
const [isDark, setIsDark] = useState(checkDark);
|
|
7164
|
+
useEffect(() => {
|
|
7165
|
+
const el = document.documentElement;
|
|
7166
|
+
const update = () => {
|
|
7167
|
+
setIsDark(checkDark());
|
|
7168
|
+
};
|
|
7169
|
+
const observer = new MutationObserver(update);
|
|
7170
|
+
observer.observe(el, {
|
|
7171
|
+
attributes: true,
|
|
7172
|
+
attributeFilter: ["class", "style"]
|
|
7173
|
+
});
|
|
7174
|
+
update();
|
|
7175
|
+
return () => observer.disconnect();
|
|
7176
|
+
}, [checkDark]);
|
|
7177
|
+
return isDark;
|
|
7178
|
+
}
|
|
7179
|
+
|
|
7180
|
+
// src/components/file-view/hooks/useHighlightedTokens.ts
|
|
7181
|
+
function useHighlightedTokens(code, language) {
|
|
7182
|
+
const { highlighter, isReady } = useShikiHighlighter();
|
|
7183
|
+
const isDark = useDarkMode();
|
|
7184
|
+
const [lines, setLines] = useState(null);
|
|
7185
|
+
useEffect(() => {
|
|
7186
|
+
if (!isReady || !highlighter || !code) {
|
|
7187
|
+
setLines(null);
|
|
7188
|
+
return;
|
|
7189
|
+
}
|
|
7190
|
+
let cancelled = false;
|
|
7191
|
+
const theme = isDark ? "github-dark" : "github-light";
|
|
7192
|
+
(async () => {
|
|
7193
|
+
try {
|
|
7194
|
+
if (language !== "text") {
|
|
7195
|
+
const loadedLangs = highlighter.getLoadedLanguages();
|
|
7196
|
+
if (!loadedLangs.includes(language)) {
|
|
7197
|
+
await highlighter.loadLanguage(language);
|
|
7198
|
+
}
|
|
7199
|
+
}
|
|
7200
|
+
} catch {
|
|
7201
|
+
if (!cancelled) setLines(null);
|
|
7202
|
+
return;
|
|
7203
|
+
}
|
|
7204
|
+
if (cancelled) return;
|
|
7205
|
+
try {
|
|
7206
|
+
const result = highlighter.codeToTokens(code, {
|
|
7207
|
+
lang: language,
|
|
7208
|
+
theme
|
|
7209
|
+
});
|
|
7210
|
+
if (!cancelled) {
|
|
7211
|
+
setLines(
|
|
7212
|
+
result.tokens.map(
|
|
7213
|
+
(line) => line.map((token) => ({
|
|
7214
|
+
content: token.content,
|
|
7215
|
+
color: token.color
|
|
7216
|
+
}))
|
|
7217
|
+
)
|
|
7218
|
+
);
|
|
7219
|
+
}
|
|
7220
|
+
} catch {
|
|
7221
|
+
if (!cancelled) setLines(null);
|
|
7222
|
+
}
|
|
7223
|
+
})();
|
|
7224
|
+
return () => {
|
|
7225
|
+
cancelled = true;
|
|
7226
|
+
};
|
|
7227
|
+
}, [highlighter, isReady, code, language, isDark]);
|
|
7228
|
+
return { lines };
|
|
7229
|
+
}
|
|
7230
|
+
|
|
7231
|
+
// src/components/file-view/utils/languageMapping.ts
|
|
7232
|
+
var EXTENSION_OVERRIDES = {
|
|
7233
|
+
yml: "yaml",
|
|
7234
|
+
htm: "html",
|
|
7235
|
+
cjs: "javascript",
|
|
7236
|
+
mjs: "javascript",
|
|
7237
|
+
jsx: "jsx",
|
|
7238
|
+
tsx: "tsx",
|
|
7239
|
+
h: "c",
|
|
7240
|
+
hpp: "cpp",
|
|
7241
|
+
cs: "csharp",
|
|
7242
|
+
rb: "ruby",
|
|
7243
|
+
sh: "shellscript",
|
|
7244
|
+
bash: "shellscript",
|
|
7245
|
+
zsh: "shellscript",
|
|
7246
|
+
ps1: "powershell",
|
|
7247
|
+
bat: "bat",
|
|
7248
|
+
kt: "kotlin",
|
|
7249
|
+
rs: "rust",
|
|
7250
|
+
gql: "graphql",
|
|
7251
|
+
pl: "perl",
|
|
7252
|
+
sass: "sass",
|
|
7253
|
+
scss: "scss",
|
|
7254
|
+
less: "less",
|
|
7255
|
+
// Domain-specific / data formats without shiki support
|
|
7256
|
+
lp: "text",
|
|
7257
|
+
dat: "text",
|
|
7258
|
+
env: "shellscript"
|
|
7259
|
+
};
|
|
7260
|
+
var SPECIAL_FILE_LANGUAGES = {
|
|
7261
|
+
dockerfile: "dockerfile",
|
|
7262
|
+
makefile: "makefile",
|
|
7263
|
+
rakefile: "ruby",
|
|
7264
|
+
gemfile: "ruby",
|
|
7265
|
+
procfile: "yaml"
|
|
7266
|
+
};
|
|
7267
|
+
function getLanguageFromFileName(fileName) {
|
|
7268
|
+
const baseName = (fileName.split("/").pop() || fileName).toLowerCase();
|
|
7269
|
+
const specialLang = SPECIAL_FILE_LANGUAGES[baseName];
|
|
7270
|
+
if (specialLang) return specialLang;
|
|
7271
|
+
let ext = null;
|
|
7272
|
+
if (baseName.startsWith(".") && !baseName.slice(1).includes(".")) {
|
|
7273
|
+
ext = baseName.slice(1);
|
|
7274
|
+
} else {
|
|
7275
|
+
const lastDot = baseName.lastIndexOf(".");
|
|
7276
|
+
if (lastDot !== -1 && lastDot !== baseName.length - 1) {
|
|
7277
|
+
ext = baseName.slice(lastDot + 1);
|
|
7278
|
+
}
|
|
7279
|
+
}
|
|
7280
|
+
if (!ext) return "text";
|
|
7281
|
+
return EXTENSION_OVERRIDES[ext] ?? ext;
|
|
7282
|
+
}
|
|
7283
|
+
function CodeRenderer({
|
|
7284
|
+
content,
|
|
7285
|
+
fileName,
|
|
7286
|
+
className
|
|
7287
|
+
}) {
|
|
7288
|
+
const language = React20.useMemo(
|
|
7289
|
+
() => getLanguageFromFileName(fileName),
|
|
7290
|
+
[fileName]
|
|
7291
|
+
);
|
|
7292
|
+
const plainLines = React20.useMemo(
|
|
7293
|
+
() => (content ?? "").split("\n"),
|
|
7294
|
+
[content]
|
|
7295
|
+
);
|
|
7296
|
+
const { lines: highlightedLines } = useHighlightedTokens(
|
|
7297
|
+
content ?? "",
|
|
7298
|
+
language
|
|
7299
|
+
);
|
|
7300
|
+
const gutterWidth = React20.useMemo(
|
|
7301
|
+
() => `${Math.max(String(plainLines.length).length, 2) + 2}ch`,
|
|
7302
|
+
[plainLines.length]
|
|
7303
|
+
);
|
|
7304
|
+
return /* @__PURE__ */ jsx(
|
|
7305
|
+
"div",
|
|
7306
|
+
{
|
|
7307
|
+
className: cn(
|
|
7308
|
+
"relative h-full w-full overflow-auto rounded-md border border-border bg-background",
|
|
7309
|
+
"scrollbar-thin",
|
|
7310
|
+
className
|
|
7311
|
+
),
|
|
7312
|
+
children: /* @__PURE__ */ jsx("pre", { className: "m-0 p-0", children: /* @__PURE__ */ jsx("code", { className: "block font-mono text-sm leading-relaxed", children: highlightedLines ? highlightedLines.map((tokens, index) => /* @__PURE__ */ jsxs("div", { className: "flex", children: [
|
|
7313
|
+
/* @__PURE__ */ jsx(
|
|
7314
|
+
"span",
|
|
7315
|
+
{
|
|
7316
|
+
className: "sticky left-0 shrink-0 select-none border-r border-border bg-muted px-3 text-right text-muted-foreground",
|
|
7317
|
+
style: { minWidth: gutterWidth },
|
|
7318
|
+
children: index + 1
|
|
7319
|
+
}
|
|
7320
|
+
),
|
|
7321
|
+
/* @__PURE__ */ jsx("span", { className: "whitespace-pre px-4", children: tokens.length === 0 || tokens.length === 1 && tokens[0].content === "" ? " " : tokens.map((token, ti) => /* @__PURE__ */ jsx("span", { style: { color: token.color }, children: token.content }, ti)) })
|
|
7322
|
+
] }, index)) : plainLines.map((line, index) => /* @__PURE__ */ jsxs("div", { className: "flex", children: [
|
|
7323
|
+
/* @__PURE__ */ jsx(
|
|
7324
|
+
"span",
|
|
7325
|
+
{
|
|
7326
|
+
className: "sticky left-0 shrink-0 select-none border-r border-border bg-muted px-3 text-right text-muted-foreground",
|
|
7327
|
+
style: { minWidth: gutterWidth },
|
|
7328
|
+
children: index + 1
|
|
7329
|
+
}
|
|
7330
|
+
),
|
|
7331
|
+
/* @__PURE__ */ jsx("span", { className: "whitespace-pre px-4 text-foreground", children: line || " " })
|
|
7332
|
+
] }, index)) }) })
|
|
7333
|
+
}
|
|
7334
|
+
);
|
|
7335
|
+
}
|
|
7336
|
+
CodeRenderer.displayName = "CodeRenderer";
|
|
7337
|
+
function HighlightedCodeBlock({
|
|
7338
|
+
children,
|
|
7339
|
+
className: codeClassName,
|
|
7340
|
+
...props
|
|
7341
|
+
}) {
|
|
7342
|
+
const language = React20.useMemo(() => {
|
|
7343
|
+
if (!codeClassName) return "text";
|
|
7344
|
+
const match = codeClassName.match(/language-(\S+)/);
|
|
7345
|
+
return match ? match[1] : "text";
|
|
7346
|
+
}, [codeClassName]);
|
|
7347
|
+
const code = React20.useMemo(() => {
|
|
7348
|
+
const raw = String(children);
|
|
7349
|
+
return raw.endsWith("\n") ? raw.slice(0, -1) : raw;
|
|
7350
|
+
}, [children]);
|
|
7351
|
+
const { lines } = useHighlightedTokens(code, language);
|
|
7352
|
+
if (lines) {
|
|
7353
|
+
return /* @__PURE__ */ jsx("code", { className: cn("bg-transparent p-0", codeClassName), ...props, children: lines.map((tokens, i) => /* @__PURE__ */ jsxs(React20.Fragment, { children: [
|
|
7354
|
+
i > 0 && "\n",
|
|
7355
|
+
tokens.map((token, ti) => /* @__PURE__ */ jsx("span", { style: { color: token.color }, children: token.content }, ti))
|
|
7356
|
+
] }, i)) });
|
|
7357
|
+
}
|
|
7358
|
+
return /* @__PURE__ */ jsx("code", { className: cn("bg-transparent p-0", codeClassName), ...props, children });
|
|
7359
|
+
}
|
|
7360
|
+
function MarkdownImage({
|
|
7361
|
+
src,
|
|
7362
|
+
alt,
|
|
7363
|
+
resolveImageUrl,
|
|
7364
|
+
...props
|
|
7365
|
+
}) {
|
|
7366
|
+
const needsResolution = !!src && !!resolveImageUrl && !src.startsWith("http://") && !src.startsWith("https://") && !src.startsWith("data:");
|
|
7367
|
+
const [resolvedUrl, setResolvedUrl] = React20.useState(null);
|
|
7368
|
+
const [error, setError] = React20.useState(false);
|
|
7369
|
+
const [loading, setLoading] = React20.useState(needsResolution);
|
|
7370
|
+
React20.useEffect(() => {
|
|
7371
|
+
if (!needsResolution || !src || !resolveImageUrl) return;
|
|
7372
|
+
let cancelled = false;
|
|
7373
|
+
let blobUrl = null;
|
|
7374
|
+
setLoading(true);
|
|
7375
|
+
setError(false);
|
|
7376
|
+
setResolvedUrl(null);
|
|
7377
|
+
Promise.resolve(resolveImageUrl(src)).then((url) => {
|
|
7378
|
+
if (cancelled) {
|
|
7379
|
+
if (url.startsWith("blob:")) URL.revokeObjectURL(url);
|
|
7380
|
+
return;
|
|
7381
|
+
}
|
|
7382
|
+
if (url.startsWith("blob:")) blobUrl = url;
|
|
7383
|
+
setResolvedUrl(url);
|
|
7384
|
+
setLoading(false);
|
|
7385
|
+
}).catch(() => {
|
|
7386
|
+
if (!cancelled) {
|
|
7387
|
+
setError(true);
|
|
7388
|
+
setLoading(false);
|
|
7389
|
+
}
|
|
7390
|
+
});
|
|
7391
|
+
return () => {
|
|
7392
|
+
cancelled = true;
|
|
7393
|
+
if (blobUrl) URL.revokeObjectURL(blobUrl);
|
|
7394
|
+
};
|
|
7395
|
+
}, [needsResolution, src, resolveImageUrl]);
|
|
7396
|
+
if (!needsResolution) {
|
|
7397
|
+
return /* @__PURE__ */ jsx("img", { src, alt, className: "max-w-full rounded", ...props });
|
|
7398
|
+
}
|
|
7399
|
+
if (loading) {
|
|
7400
|
+
return /* @__PURE__ */ jsx("span", { className: "my-2 inline-block h-24 w-40 animate-pulse rounded bg-muted" });
|
|
7401
|
+
}
|
|
7402
|
+
if (error || !resolvedUrl) {
|
|
7403
|
+
return /* @__PURE__ */ jsx("img", { src, alt, className: "max-w-full rounded", ...props });
|
|
7404
|
+
}
|
|
7405
|
+
return /* @__PURE__ */ jsx(
|
|
7406
|
+
"img",
|
|
7407
|
+
{
|
|
7408
|
+
src: resolvedUrl,
|
|
7409
|
+
alt,
|
|
7410
|
+
className: "max-w-full rounded",
|
|
7411
|
+
...props
|
|
7412
|
+
}
|
|
7413
|
+
);
|
|
7414
|
+
}
|
|
7415
|
+
function MarkdownRenderer({
|
|
7416
|
+
content,
|
|
7417
|
+
className,
|
|
7418
|
+
resolveImageUrl
|
|
7419
|
+
}) {
|
|
7420
|
+
const markdownComponents = React20.useMemo(
|
|
7421
|
+
() => ({
|
|
7422
|
+
code: ({
|
|
7423
|
+
children,
|
|
7424
|
+
className: codeClassName,
|
|
7425
|
+
...props
|
|
7426
|
+
}) => {
|
|
7427
|
+
const isInline = !codeClassName;
|
|
7428
|
+
if (isInline) {
|
|
7429
|
+
return /* @__PURE__ */ jsx(
|
|
7430
|
+
"code",
|
|
7431
|
+
{
|
|
7432
|
+
className: "rounded bg-muted px-1.5 py-0.5 font-mono text-[85%]",
|
|
7433
|
+
...props,
|
|
7434
|
+
children
|
|
7435
|
+
}
|
|
7436
|
+
);
|
|
7437
|
+
}
|
|
7438
|
+
return /* @__PURE__ */ jsx(HighlightedCodeBlock, { className: codeClassName, ...props, children });
|
|
7439
|
+
},
|
|
7440
|
+
pre: ({ children, ...props }) => /* @__PURE__ */ jsx(
|
|
7441
|
+
"pre",
|
|
7442
|
+
{
|
|
7443
|
+
className: "my-4 overflow-auto rounded-md border border-border bg-muted p-4 font-mono text-sm leading-relaxed",
|
|
7444
|
+
...props,
|
|
7445
|
+
children
|
|
7446
|
+
}
|
|
7447
|
+
),
|
|
7448
|
+
blockquote: ({
|
|
7449
|
+
children,
|
|
7450
|
+
...props
|
|
7451
|
+
}) => /* @__PURE__ */ jsx(
|
|
7452
|
+
"blockquote",
|
|
7453
|
+
{
|
|
7454
|
+
className: "my-4 border-l-4 border-border pl-4 text-muted-foreground",
|
|
7455
|
+
...props,
|
|
7456
|
+
children
|
|
7457
|
+
}
|
|
7458
|
+
),
|
|
7459
|
+
a: ({
|
|
7460
|
+
children,
|
|
7461
|
+
href,
|
|
7462
|
+
...props
|
|
7463
|
+
}) => /* @__PURE__ */ jsx(
|
|
7464
|
+
"a",
|
|
7465
|
+
{
|
|
7466
|
+
href,
|
|
7467
|
+
target: "_blank",
|
|
7468
|
+
rel: "noopener noreferrer",
|
|
7469
|
+
className: "text-primary hover:underline",
|
|
7470
|
+
...props,
|
|
7471
|
+
children
|
|
7472
|
+
}
|
|
7473
|
+
),
|
|
7474
|
+
table: ({
|
|
7475
|
+
children,
|
|
7476
|
+
...props
|
|
7477
|
+
}) => /* @__PURE__ */ jsx("div", { className: "my-4 overflow-auto", children: /* @__PURE__ */ jsx(
|
|
7478
|
+
"table",
|
|
7479
|
+
{
|
|
7480
|
+
className: "w-full border-collapse border border-border text-sm",
|
|
7481
|
+
...props,
|
|
7482
|
+
children
|
|
7483
|
+
}
|
|
7484
|
+
) }),
|
|
7485
|
+
th: ({
|
|
7486
|
+
children,
|
|
7487
|
+
...props
|
|
7488
|
+
}) => /* @__PURE__ */ jsx(
|
|
7489
|
+
"th",
|
|
7490
|
+
{
|
|
7491
|
+
className: "border border-border bg-muted px-3 py-2 text-left font-semibold",
|
|
7492
|
+
...props,
|
|
7493
|
+
children
|
|
7494
|
+
}
|
|
7495
|
+
),
|
|
7496
|
+
td: ({
|
|
7497
|
+
children,
|
|
7498
|
+
...props
|
|
7499
|
+
}) => /* @__PURE__ */ jsx("td", { className: "border border-border px-3 py-2", ...props, children }),
|
|
7500
|
+
img: ({
|
|
7501
|
+
src,
|
|
7502
|
+
alt,
|
|
7503
|
+
...props
|
|
7504
|
+
}) => /* @__PURE__ */ jsx(
|
|
7505
|
+
MarkdownImage,
|
|
7506
|
+
{
|
|
7507
|
+
src,
|
|
7508
|
+
alt,
|
|
7509
|
+
resolveImageUrl,
|
|
7510
|
+
...props
|
|
7511
|
+
}
|
|
7512
|
+
)
|
|
7513
|
+
}),
|
|
7514
|
+
[resolveImageUrl]
|
|
7515
|
+
);
|
|
7516
|
+
return /* @__PURE__ */ jsx(
|
|
7517
|
+
"div",
|
|
7518
|
+
{
|
|
7519
|
+
className: cn(
|
|
7520
|
+
"h-full w-full overflow-auto bg-background p-6 text-sm leading-relaxed text-foreground",
|
|
7521
|
+
// Heading styles
|
|
7522
|
+
"[&_h1]:mb-4 [&_h1]:mt-6 [&_h1]:border-b [&_h1]:border-border [&_h1]:pb-2 [&_h1]:text-2xl [&_h1]:font-bold",
|
|
7523
|
+
"[&_h2]:mb-4 [&_h2]:mt-6 [&_h2]:border-b [&_h2]:border-border [&_h2]:pb-2 [&_h2]:text-xl [&_h2]:font-semibold",
|
|
7524
|
+
"[&_h3]:mb-3 [&_h3]:mt-5 [&_h3]:text-lg [&_h3]:font-semibold",
|
|
7525
|
+
"[&_h4]:mb-3 [&_h4]:mt-4 [&_h4]:text-base [&_h4]:font-semibold",
|
|
7526
|
+
// Paragraph and list styles
|
|
7527
|
+
"[&_p]:mb-4 [&_p]:leading-relaxed",
|
|
7528
|
+
"[&_ul]:mb-4 [&_ul]:list-disc [&_ul]:pl-6",
|
|
7529
|
+
"[&_ol]:mb-4 [&_ol]:list-decimal [&_ol]:pl-6",
|
|
7530
|
+
"[&_li]:mb-1",
|
|
7531
|
+
// Horizontal rule
|
|
7532
|
+
"[&_hr]:my-6 [&_hr]:border-border",
|
|
7533
|
+
"scrollbar-thin",
|
|
7534
|
+
className
|
|
7535
|
+
),
|
|
7536
|
+
children: /* @__PURE__ */ jsx(
|
|
7537
|
+
ReactMarkdownImport,
|
|
7538
|
+
{
|
|
7539
|
+
remarkPlugins: [remarkGfmImport],
|
|
7540
|
+
components: markdownComponents,
|
|
7541
|
+
children: content ?? ""
|
|
7542
|
+
}
|
|
7543
|
+
)
|
|
7544
|
+
}
|
|
7545
|
+
);
|
|
7546
|
+
}
|
|
7547
|
+
MarkdownRenderer.displayName = "MarkdownRenderer";
|
|
7548
|
+
function ImageRenderer({
|
|
7549
|
+
url,
|
|
7550
|
+
fileName,
|
|
7551
|
+
className
|
|
7552
|
+
}) {
|
|
7553
|
+
const [hasError, setHasError] = React20.useState(false);
|
|
7554
|
+
React20.useEffect(() => {
|
|
7555
|
+
setHasError(false);
|
|
7556
|
+
}, [url]);
|
|
7557
|
+
if (!url) {
|
|
7558
|
+
return /* @__PURE__ */ jsx(
|
|
7559
|
+
"div",
|
|
7560
|
+
{
|
|
7561
|
+
className: cn(
|
|
7562
|
+
"flex h-full w-full items-center justify-center text-sm text-muted-foreground",
|
|
7563
|
+
className
|
|
7564
|
+
),
|
|
7565
|
+
children: "No image URL provided"
|
|
7566
|
+
}
|
|
7567
|
+
);
|
|
7568
|
+
}
|
|
7569
|
+
if (hasError) {
|
|
7570
|
+
return /* @__PURE__ */ jsxs(
|
|
7571
|
+
"div",
|
|
7572
|
+
{
|
|
7573
|
+
className: cn(
|
|
7574
|
+
"flex h-full w-full flex-col items-center justify-center gap-2 text-sm text-muted-foreground",
|
|
7575
|
+
className
|
|
7576
|
+
),
|
|
7577
|
+
children: [
|
|
7578
|
+
/* @__PURE__ */ jsx("span", { children: "Failed to load image" }),
|
|
7579
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: fileName })
|
|
7580
|
+
]
|
|
7581
|
+
}
|
|
7582
|
+
);
|
|
7583
|
+
}
|
|
7584
|
+
return /* @__PURE__ */ jsx(
|
|
7585
|
+
"div",
|
|
7586
|
+
{
|
|
7587
|
+
className: cn(
|
|
7588
|
+
"flex h-full w-full items-center justify-center overflow-auto bg-background p-4",
|
|
7589
|
+
"scrollbar-thin",
|
|
7590
|
+
className
|
|
7591
|
+
),
|
|
7592
|
+
children: /* @__PURE__ */ jsx(
|
|
7593
|
+
"img",
|
|
7594
|
+
{
|
|
7595
|
+
src: url,
|
|
7596
|
+
alt: fileName,
|
|
7597
|
+
onError: () => setHasError(true),
|
|
7598
|
+
className: "max-h-full max-w-full object-contain"
|
|
7599
|
+
}
|
|
7600
|
+
)
|
|
7601
|
+
}
|
|
7602
|
+
);
|
|
7603
|
+
}
|
|
7604
|
+
ImageRenderer.displayName = "ImageRenderer";
|
|
7605
|
+
function PlainTextRenderer({ content, className }) {
|
|
7606
|
+
return /* @__PURE__ */ jsx(
|
|
7607
|
+
"div",
|
|
7608
|
+
{
|
|
7609
|
+
className: cn(
|
|
7610
|
+
"h-full w-full overflow-auto rounded-md border border-border bg-background p-4",
|
|
7611
|
+
"scrollbar-thin",
|
|
7612
|
+
className
|
|
7613
|
+
),
|
|
7614
|
+
children: /* @__PURE__ */ jsx("pre", { className: "m-0 whitespace-pre-wrap break-words font-mono text-sm leading-relaxed text-foreground", children: content ?? "" })
|
|
7615
|
+
}
|
|
7616
|
+
);
|
|
7617
|
+
}
|
|
7618
|
+
PlainTextRenderer.displayName = "PlainTextRenderer";
|
|
7619
|
+
function parseCSV(text) {
|
|
7620
|
+
const lines = text.split("\n");
|
|
7621
|
+
if (lines.length === 0) return { headers: [], rows: [] };
|
|
7622
|
+
const firstLine = lines[0] ?? "";
|
|
7623
|
+
const delimiter = firstLine.includes(" ") ? " " : ",";
|
|
7624
|
+
function parseLine(line) {
|
|
7625
|
+
const fields = [];
|
|
7626
|
+
let current = "";
|
|
7627
|
+
let inQuotes = false;
|
|
7628
|
+
let i = 0;
|
|
7629
|
+
while (i < line.length) {
|
|
7630
|
+
const char = line[i];
|
|
7631
|
+
if (inQuotes) {
|
|
7632
|
+
if (char === '"') {
|
|
7633
|
+
if (i + 1 < line.length && line[i + 1] === '"') {
|
|
7634
|
+
current += '"';
|
|
7635
|
+
i += 2;
|
|
7636
|
+
} else {
|
|
7637
|
+
inQuotes = false;
|
|
7638
|
+
i++;
|
|
7639
|
+
}
|
|
7640
|
+
} else {
|
|
7641
|
+
current += char;
|
|
7642
|
+
i++;
|
|
7643
|
+
}
|
|
7644
|
+
} else {
|
|
7645
|
+
if (char === '"') {
|
|
7646
|
+
inQuotes = true;
|
|
7647
|
+
i++;
|
|
7648
|
+
} else if (char === delimiter) {
|
|
7649
|
+
fields.push(current.trim());
|
|
7650
|
+
current = "";
|
|
7651
|
+
i++;
|
|
7652
|
+
} else {
|
|
7653
|
+
current += char;
|
|
7654
|
+
i++;
|
|
7655
|
+
}
|
|
7656
|
+
}
|
|
7657
|
+
}
|
|
7658
|
+
fields.push(current.trim());
|
|
7659
|
+
return fields;
|
|
7660
|
+
}
|
|
7661
|
+
const headers = parseLine(firstLine);
|
|
7662
|
+
const rows = [];
|
|
7663
|
+
for (let i = 1; i < lines.length; i++) {
|
|
7664
|
+
const line = lines[i];
|
|
7665
|
+
if (line.trim() === "") continue;
|
|
7666
|
+
const values = parseLine(line);
|
|
7667
|
+
const row = {};
|
|
7668
|
+
for (let j = 0; j < headers.length; j++) {
|
|
7669
|
+
row[headers[j]] = values[j] ?? "";
|
|
7670
|
+
}
|
|
7671
|
+
rows.push(row);
|
|
7672
|
+
}
|
|
7673
|
+
return { headers, rows };
|
|
7674
|
+
}
|
|
7675
|
+
function CsvRenderer({ content, className }) {
|
|
7676
|
+
const { headers, rows } = React20.useMemo(
|
|
7677
|
+
() => parseCSV(content ?? ""),
|
|
7678
|
+
[content]
|
|
7679
|
+
);
|
|
7680
|
+
const columns = React20.useMemo(
|
|
7681
|
+
() => headers.map((header) => ({
|
|
7682
|
+
key: header,
|
|
7683
|
+
header,
|
|
7684
|
+
sortable: true,
|
|
7685
|
+
filterable: true,
|
|
7686
|
+
filterType: "text"
|
|
7687
|
+
})),
|
|
7688
|
+
[headers]
|
|
7689
|
+
);
|
|
7690
|
+
if (headers.length === 0) {
|
|
7691
|
+
return /* @__PURE__ */ jsx(
|
|
7692
|
+
"div",
|
|
7693
|
+
{
|
|
7694
|
+
className: cn(
|
|
7695
|
+
"flex h-full w-full items-center justify-center text-sm text-muted-foreground",
|
|
7696
|
+
className
|
|
7697
|
+
),
|
|
7698
|
+
children: "No CSV data to display"
|
|
7699
|
+
}
|
|
7700
|
+
);
|
|
7701
|
+
}
|
|
7702
|
+
return /* @__PURE__ */ jsx("div", { className: cn("h-full w-full overflow-auto", className), children: /* @__PURE__ */ jsx(
|
|
7703
|
+
DataGrid,
|
|
7704
|
+
{
|
|
7705
|
+
data: rows,
|
|
7706
|
+
columns,
|
|
7707
|
+
getRowKey: (_, index) => String(index),
|
|
7708
|
+
resizableColumns: true
|
|
7709
|
+
}
|
|
7710
|
+
) });
|
|
7711
|
+
}
|
|
7712
|
+
CsvRenderer.displayName = "CsvRenderer";
|
|
7713
|
+
function HtmlRenderer({
|
|
7714
|
+
content,
|
|
7715
|
+
fileName,
|
|
7716
|
+
className
|
|
7717
|
+
}) {
|
|
7718
|
+
return /* @__PURE__ */ jsx(
|
|
7719
|
+
"iframe",
|
|
7720
|
+
{
|
|
7721
|
+
srcDoc: content ?? "",
|
|
7722
|
+
sandbox: "allow-scripts",
|
|
7723
|
+
title: fileName,
|
|
7724
|
+
className: cn("h-full w-full border-0", className)
|
|
7725
|
+
}
|
|
7726
|
+
);
|
|
7727
|
+
}
|
|
7728
|
+
HtmlRenderer.displayName = "HtmlRenderer";
|
|
7729
|
+
|
|
7730
|
+
// src/components/file-view/utils/rendererRegistry.ts
|
|
7731
|
+
var DEFAULT_RENDERERS = {
|
|
7732
|
+
code: CodeRenderer,
|
|
7733
|
+
markdown: MarkdownRenderer,
|
|
7734
|
+
image: ImageRenderer,
|
|
7735
|
+
plaintext: PlainTextRenderer,
|
|
7736
|
+
csv: CsvRenderer,
|
|
7737
|
+
html: HtmlRenderer
|
|
7738
|
+
};
|
|
7739
|
+
function mergeRenderers(userRenderers) {
|
|
7740
|
+
if (!userRenderers) return DEFAULT_RENDERERS;
|
|
7741
|
+
return { ...DEFAULT_RENDERERS, ...userRenderers };
|
|
7742
|
+
}
|
|
7743
|
+
function resolveRenderer(registry, contentType) {
|
|
7744
|
+
return registry[contentType] ?? registry["plaintext"] ?? PlainTextRenderer;
|
|
7745
|
+
}
|
|
7746
|
+
function DefaultEmptyState({ message }) {
|
|
7747
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center text-sm text-muted-foreground", children: message });
|
|
7748
|
+
}
|
|
7749
|
+
function DefaultLoadingState() {
|
|
7750
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", children: [
|
|
7751
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-primary/20 border-t-primary" }),
|
|
7752
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Loading file..." })
|
|
7753
|
+
] }) });
|
|
7754
|
+
}
|
|
7755
|
+
function DefaultErrorState({ error }) {
|
|
7756
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "flex max-w-sm flex-col items-center gap-3 text-center", children: [
|
|
7757
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-destructive", children: error.message }),
|
|
7758
|
+
error.onRetry && /* @__PURE__ */ jsx(
|
|
7759
|
+
"button",
|
|
7760
|
+
{
|
|
7761
|
+
onClick: error.onRetry,
|
|
7762
|
+
className: cn(
|
|
7763
|
+
"rounded-md border border-border bg-background px-3 py-1.5 text-sm text-foreground",
|
|
7764
|
+
"transition-colors hover:bg-muted"
|
|
7765
|
+
),
|
|
7766
|
+
children: "Retry"
|
|
7767
|
+
}
|
|
7768
|
+
)
|
|
7769
|
+
] }) });
|
|
7770
|
+
}
|
|
7771
|
+
function FileView({
|
|
7772
|
+
content,
|
|
7773
|
+
url = null,
|
|
7774
|
+
fileName,
|
|
7775
|
+
contentType: contentTypeOverride,
|
|
7776
|
+
renderers: userRenderers,
|
|
7777
|
+
loading = false,
|
|
7778
|
+
error = null,
|
|
7779
|
+
loadingComponent,
|
|
7780
|
+
emptyComponent,
|
|
7781
|
+
emptyMessage = "No content to display",
|
|
7782
|
+
errorComponent: ErrorComponent,
|
|
7783
|
+
className,
|
|
7784
|
+
rendererClassName,
|
|
7785
|
+
resolveImageUrl
|
|
7786
|
+
}) {
|
|
7787
|
+
const { type: resolvedType } = useContentType({
|
|
7788
|
+
fileName,
|
|
7789
|
+
contentTypeOverride
|
|
7790
|
+
});
|
|
7791
|
+
const registry = React20.useMemo(
|
|
7792
|
+
() => mergeRenderers(userRenderers),
|
|
7793
|
+
[userRenderers]
|
|
7794
|
+
);
|
|
7795
|
+
const Renderer = React20.useMemo(
|
|
7796
|
+
() => resolveRenderer(registry, resolvedType),
|
|
7797
|
+
[registry, resolvedType]
|
|
7798
|
+
);
|
|
7799
|
+
if (loading) {
|
|
7800
|
+
return /* @__PURE__ */ jsx("div", { className: cn("relative h-full w-full", className), children: loadingComponent ?? /* @__PURE__ */ jsx(DefaultLoadingState, {}) });
|
|
7801
|
+
}
|
|
7802
|
+
if (error) {
|
|
7803
|
+
return /* @__PURE__ */ jsx("div", { className: cn("relative h-full w-full", className), children: ErrorComponent ? /* @__PURE__ */ jsx(ErrorComponent, { error }) : /* @__PURE__ */ jsx(DefaultErrorState, { error }) });
|
|
7804
|
+
}
|
|
7805
|
+
if ((content == null || content === "") && url == null) {
|
|
7806
|
+
return /* @__PURE__ */ jsx("div", { className: cn("relative h-full w-full", className), children: emptyComponent ?? /* @__PURE__ */ jsx(DefaultEmptyState, { message: emptyMessage }) });
|
|
7807
|
+
}
|
|
7808
|
+
return /* @__PURE__ */ jsx("div", { className: cn("relative h-full w-full", className), children: /* @__PURE__ */ jsx(
|
|
7809
|
+
Renderer,
|
|
7810
|
+
{
|
|
7811
|
+
content,
|
|
7812
|
+
url: url ?? null,
|
|
7813
|
+
fileName,
|
|
7814
|
+
contentType: resolvedType,
|
|
7815
|
+
className: rendererClassName,
|
|
7816
|
+
resolveImageUrl
|
|
7817
|
+
}
|
|
7818
|
+
) });
|
|
7819
|
+
}
|
|
7820
|
+
FileView.displayName = "FileView";
|
|
7821
|
+
|
|
7822
|
+
export { ALL_THEMES, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Autocomplete, Badge, Board, BoardContent, BoardHeader, Button, CYBERPUNK_THEME, Calendar, Card, CardActions, CardContent, CardDescription, CardFooter, CardGrid, CardHeader, CardImage, CardList, CardTitle, CellEditor, Checkbox, Chip, CodeRenderer, ConfirmationModal, ContextMenu, CopyButton, CsvRenderer, DARK_ELEGANT_THEME, DEFAULT_RENDERERS, DataGrid, DataTable, DatePicker, DatePickerInput, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FOREST_THEME, FUTURISTIC_THEME, FileView, FilterPopover, GREEN_THEME, HeaderCell, HtmlRenderer, IconButton, ImageRenderer, Input, Label, LoadingSpinner, MINIMALIST_LIGHT_THEME, MarkdownRenderer, Modal, ModalButton, NATURE_THEME, OCEAN_THEME, OPTILOGIC_LEGACY_THEME, PRESET_THEMES, PlainTextRenderer, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, ResizablePanel, ResizeHandle, SCIFI_THEME, SUNSET_THEME, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SelectableCard, Separator, Skeleton, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, ThemePicker, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger, accordionContentVariants, accordionItemVariants, accordionTriggerVariants, applyFilterOperator, applyFilters, applySorting, applyTheme, areThemesEqual, badgeVariants, boardVariants, buttonVariants, cardActionsVariants, cardGridVariants, cardImageVariants, cardListVariants, cardVariants, cloneTheme, cn, detectContentType, exportTheme, getCellValue, getCurrentTheme, getDefaultTheme, getFileExtension, getPresetTheme, hexToHsl, iconButtonVariants, importTheme, isPresetTheme, isTextContentType, isUrlContentType, labelVariants, loadingSpinnerVariants, mergeRenderers, resolveRenderer, themeToHsl, useColumnResize, useColumnResizeManager, useConfirmation, useContentType, useContextMenu, useDataGridState, useKeyboardNavigation, validateTheme };
|
|
6772
7823
|
//# sourceMappingURL=index.js.map
|
|
6773
7824
|
//# sourceMappingURL=index.js.map
|