@burdenoff/microfe-bigconsole 2026.613.5 → 2026.615.1
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/bigconsole/components/dashboard/DashboardCanvas.js +163 -151
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +89 -69
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableHeader.js +89 -29
- package/dist/bigconsole/components/widgets/table/TableHeader.js.map +1 -1
- package/dist/bigconsole/components/widgets/table/TableWidget.js +218 -148
- package/dist/bigconsole/components/widgets/table/TableWidget.js.map +1 -1
- package/dist/bigconsole/hooks/index.js +1 -0
- package/dist/bigconsole/hooks/useDashboardImageExport.js +92 -1
- package/dist/bigconsole/hooks/useDashboardImageExport.js.map +1 -0
- package/dist/bigconsole/hooks/useWidgetConfigPersist.js +32 -0
- package/dist/bigconsole/hooks/useWidgetConfigPersist.js.map +1 -0
- package/dist/bigconsole/store/dashboardStore.js +2 -2
- package/dist/bigconsole/store/dashboardStore.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,129 +4,149 @@ import "../../store/index.js";
|
|
|
4
4
|
import n from "./SavedViewsDropdown/SavedViewsDropdown.js";
|
|
5
5
|
import "./SavedViewsDropdown/index.js";
|
|
6
6
|
import { memo as r, useCallback as i } from "react";
|
|
7
|
-
import { Clipboard as a, Download as o, Eye as s,
|
|
8
|
-
import { Fragment as
|
|
9
|
-
import { Button as
|
|
7
|
+
import { Clipboard as a, Download as o, Eye as s, FileText as c, Image as l, Minus as u, PanelLeft as d, PanelLeftClose as f, Pencil as p, Plus as m, RotateCcw as h, Save as g, Share2 as _ } from "lucide-react";
|
|
8
|
+
import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
9
|
+
import { Button as x, Spinner as S, Tooltip as C, TooltipContent as w, TooltipProvider as T, TooltipTrigger as E } from "@burdenoff/fe-libs/ui";
|
|
10
10
|
//#region src/bigconsole/components/dashboard/DashboardToolbar.tsx
|
|
11
|
-
var
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
}, [
|
|
15
|
-
return /* @__PURE__ */
|
|
11
|
+
var D = r(function({ dashboardId: r, title: D, onAddWidget: O, onTogglePalette: k, isPaletteOpen: A = !1, onPaste: j, onSave: M, isSaving: N = !1, onExport: P, onExportImage: F, onExportPdf: I, isExportingImage: L = !1, onShare: R }) {
|
|
12
|
+
let z = t((e) => e.viewMode === "edit"), B = t((e) => e.toggleViewMode), V = t((e) => e.zoomLevel), H = t((e) => e.setZoomLevel), U = !!e((e) => e.clipboardWidgetId), W = i(() => {
|
|
13
|
+
U && j && j();
|
|
14
|
+
}, [U, j]);
|
|
15
|
+
return /* @__PURE__ */ y(T, { children: /* @__PURE__ */ b("div", {
|
|
16
16
|
className: "flex flex-wrap items-center justify-between gap-x-4 gap-y-2 px-4 py-2 bg-background border-b",
|
|
17
17
|
children: [
|
|
18
|
-
/* @__PURE__ */
|
|
18
|
+
/* @__PURE__ */ b("div", {
|
|
19
19
|
className: "flex min-w-0 items-center gap-4",
|
|
20
|
-
children: [
|
|
20
|
+
children: [D && /* @__PURE__ */ y("h1", {
|
|
21
21
|
className: "min-w-0 truncate text-lg font-semibold",
|
|
22
|
-
title:
|
|
23
|
-
children:
|
|
24
|
-
}), r && /* @__PURE__ */
|
|
22
|
+
title: D,
|
|
23
|
+
children: D
|
|
24
|
+
}), r && /* @__PURE__ */ y(n, { dashboardId: r })]
|
|
25
25
|
}),
|
|
26
|
-
/* @__PURE__ */
|
|
26
|
+
/* @__PURE__ */ b("div", {
|
|
27
27
|
className: "flex flex-shrink-0 items-center gap-1",
|
|
28
28
|
children: [
|
|
29
|
-
/* @__PURE__ */
|
|
29
|
+
/* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
30
30
|
asChild: !0,
|
|
31
|
-
children: /* @__PURE__ */
|
|
31
|
+
children: /* @__PURE__ */ y(x, {
|
|
32
32
|
variant: "ghost",
|
|
33
33
|
size: "icon-sm",
|
|
34
|
-
onClick: () =>
|
|
35
|
-
disabled:
|
|
36
|
-
children: /* @__PURE__ */
|
|
34
|
+
onClick: () => H(Math.max(50, V - 10)),
|
|
35
|
+
disabled: V <= 50,
|
|
36
|
+
children: /* @__PURE__ */ y(u, { className: "size-4" })
|
|
37
37
|
})
|
|
38
|
-
}), /* @__PURE__ */
|
|
39
|
-
/* @__PURE__ */
|
|
38
|
+
}), /* @__PURE__ */ y(w, { children: "Zoom out" })] }),
|
|
39
|
+
/* @__PURE__ */ b("span", {
|
|
40
40
|
className: "text-sm text-muted-foreground w-12 text-center",
|
|
41
|
-
children: [
|
|
41
|
+
children: [V, "%"]
|
|
42
42
|
}),
|
|
43
|
-
/* @__PURE__ */
|
|
43
|
+
/* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
44
44
|
asChild: !0,
|
|
45
|
-
children: /* @__PURE__ */
|
|
45
|
+
children: /* @__PURE__ */ y(x, {
|
|
46
46
|
variant: "ghost",
|
|
47
47
|
size: "icon-sm",
|
|
48
|
-
onClick: () =>
|
|
49
|
-
disabled:
|
|
50
|
-
children: /* @__PURE__ */
|
|
48
|
+
onClick: () => H(Math.min(200, V + 10)),
|
|
49
|
+
disabled: V >= 200,
|
|
50
|
+
children: /* @__PURE__ */ y(m, { className: "size-4" })
|
|
51
51
|
})
|
|
52
|
-
}), /* @__PURE__ */
|
|
53
|
-
/* @__PURE__ */
|
|
52
|
+
}), /* @__PURE__ */ y(w, { children: "Zoom in" })] }),
|
|
53
|
+
/* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
54
54
|
asChild: !0,
|
|
55
|
-
children: /* @__PURE__ */
|
|
55
|
+
children: /* @__PURE__ */ b(x, {
|
|
56
56
|
variant: "ghost",
|
|
57
57
|
size: "sm",
|
|
58
|
-
onClick: () =>
|
|
59
|
-
children: [/* @__PURE__ */
|
|
58
|
+
onClick: () => H(100),
|
|
59
|
+
children: [/* @__PURE__ */ y(h, { className: "size-3.5 mr-1" }), "Reset"]
|
|
60
60
|
})
|
|
61
|
-
}), /* @__PURE__ */
|
|
61
|
+
}), /* @__PURE__ */ y(w, { children: "Reset zoom to 100%" })] })
|
|
62
62
|
]
|
|
63
63
|
}),
|
|
64
|
-
/* @__PURE__ */
|
|
64
|
+
/* @__PURE__ */ b("div", {
|
|
65
65
|
className: "flex flex-wrap items-center justify-end gap-2",
|
|
66
66
|
children: [
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
z && /* @__PURE__ */ b(v, { children: [
|
|
68
|
+
k && /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
69
69
|
asChild: !0,
|
|
70
|
-
children: /* @__PURE__ */
|
|
71
|
-
variant:
|
|
70
|
+
children: /* @__PURE__ */ b(x, {
|
|
71
|
+
variant: A ? "secondary" : "outline",
|
|
72
72
|
size: "sm",
|
|
73
|
-
onClick:
|
|
74
|
-
children: [
|
|
73
|
+
onClick: k,
|
|
74
|
+
children: [y(A ? f : d, { className: "size-4" }), "Widgets"]
|
|
75
75
|
})
|
|
76
|
-
}), /* @__PURE__ */
|
|
77
|
-
/* @__PURE__ */
|
|
76
|
+
}), /* @__PURE__ */ y(w, { children: A ? "Hide widget palette" : "Show widget palette for drag & drop" })] }),
|
|
77
|
+
/* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
78
78
|
asChild: !0,
|
|
79
|
-
children: /* @__PURE__ */
|
|
79
|
+
children: /* @__PURE__ */ b(x, {
|
|
80
80
|
variant: "ghost",
|
|
81
81
|
size: "sm",
|
|
82
|
-
onClick:
|
|
83
|
-
disabled: !
|
|
84
|
-
children: [/* @__PURE__ */
|
|
82
|
+
onClick: W,
|
|
83
|
+
disabled: !U,
|
|
84
|
+
children: [/* @__PURE__ */ y(a, { className: "size-4" }), "Paste"]
|
|
85
85
|
})
|
|
86
|
-
}), /* @__PURE__ */
|
|
87
|
-
/* @__PURE__ */
|
|
86
|
+
}), /* @__PURE__ */ y(w, { children: "Paste widget from clipboard" })] }),
|
|
87
|
+
/* @__PURE__ */ b(x, {
|
|
88
88
|
size: "sm",
|
|
89
|
-
onClick:
|
|
90
|
-
children: [/* @__PURE__ */
|
|
89
|
+
onClick: O,
|
|
90
|
+
children: [/* @__PURE__ */ y(m, { className: "size-4" }), "Add Widget"]
|
|
91
91
|
})
|
|
92
92
|
] }),
|
|
93
|
-
/* @__PURE__ */
|
|
94
|
-
variant:
|
|
93
|
+
/* @__PURE__ */ y(x, {
|
|
94
|
+
variant: z ? "secondary" : "outline",
|
|
95
95
|
size: "sm",
|
|
96
|
-
onClick:
|
|
97
|
-
children:
|
|
96
|
+
onClick: B,
|
|
97
|
+
children: z ? /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y(s, { className: "size-4" }), "Preview"] }) : /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y(p, { className: "size-4" }), "Edit"] })
|
|
98
98
|
}),
|
|
99
|
-
|
|
99
|
+
M && /* @__PURE__ */ y(x, {
|
|
100
100
|
variant: "outline",
|
|
101
101
|
size: "sm",
|
|
102
|
-
onClick:
|
|
103
|
-
disabled:
|
|
104
|
-
children:
|
|
102
|
+
onClick: M,
|
|
103
|
+
disabled: N,
|
|
104
|
+
children: N ? /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y(S, { className: "size-4" }), "Saving..."] }) : /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y(g, { className: "size-4" }), "Save"] })
|
|
105
105
|
}),
|
|
106
|
-
|
|
106
|
+
R && /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
107
107
|
asChild: !0,
|
|
108
|
-
children: /* @__PURE__ */
|
|
108
|
+
children: /* @__PURE__ */ b(x, {
|
|
109
109
|
variant: "outline",
|
|
110
110
|
size: "sm",
|
|
111
|
-
onClick:
|
|
112
|
-
children: [/* @__PURE__ */ _
|
|
111
|
+
onClick: R,
|
|
112
|
+
children: [/* @__PURE__ */ y(_, { className: "size-4" }), "Share"]
|
|
113
113
|
})
|
|
114
|
-
}), /* @__PURE__ */
|
|
115
|
-
|
|
114
|
+
}), /* @__PURE__ */ y(w, { children: "Share dashboard with others" })] }),
|
|
115
|
+
P && /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
116
116
|
asChild: !0,
|
|
117
|
-
children: /* @__PURE__ */
|
|
117
|
+
children: /* @__PURE__ */ b(x, {
|
|
118
118
|
variant: "outline",
|
|
119
119
|
size: "sm",
|
|
120
|
-
onClick:
|
|
121
|
-
children: [/* @__PURE__ */
|
|
120
|
+
onClick: P,
|
|
121
|
+
children: [/* @__PURE__ */ y(o, { className: "size-4" }), "Export"]
|
|
122
122
|
})
|
|
123
|
-
}), /* @__PURE__ */
|
|
123
|
+
}), /* @__PURE__ */ y(w, { children: "Export dashboard to JSON" })] }),
|
|
124
|
+
F && /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
125
|
+
asChild: !0,
|
|
126
|
+
children: /* @__PURE__ */ y(x, {
|
|
127
|
+
variant: "outline",
|
|
128
|
+
size: "icon-sm",
|
|
129
|
+
onClick: F,
|
|
130
|
+
disabled: L,
|
|
131
|
+
children: y(L ? S : l, { className: "size-4" })
|
|
132
|
+
})
|
|
133
|
+
}), /* @__PURE__ */ y(w, { children: "Export board as PNG image" })] }),
|
|
134
|
+
I && /* @__PURE__ */ b(C, { children: [/* @__PURE__ */ y(E, {
|
|
135
|
+
asChild: !0,
|
|
136
|
+
children: /* @__PURE__ */ y(x, {
|
|
137
|
+
variant: "outline",
|
|
138
|
+
size: "icon-sm",
|
|
139
|
+
onClick: I,
|
|
140
|
+
disabled: L,
|
|
141
|
+
children: /* @__PURE__ */ y(c, { className: "size-4" })
|
|
142
|
+
})
|
|
143
|
+
}), /* @__PURE__ */ y(w, { children: "Export board as PDF" })] })
|
|
124
144
|
]
|
|
125
145
|
})
|
|
126
146
|
]
|
|
127
147
|
}) });
|
|
128
148
|
});
|
|
129
149
|
//#endregion
|
|
130
|
-
export {
|
|
150
|
+
export { D as default };
|
|
131
151
|
|
|
132
152
|
//# sourceMappingURL=DashboardToolbar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardToolbar.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/DashboardToolbar.tsx"],"sourcesContent":["/**\n * DashboardToolbar Component\n *\n * Toolbar for dashboard actions and controls.\n * Uses fe-libs shared components for consistent styling.\n * Phase 2: Added SavedViewsDropdown and Share button.\n */\n\nimport { type FC, memo, useCallback } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport {\n Plus,\n Clipboard,\n Eye,\n Pencil,\n Save,\n Download,\n Minus,\n RotateCcw,\n Share2,\n LayoutGrid,\n PanelLeftClose,\n PanelLeft,\n} from 'lucide-react';\nimport { useDashboardStore, useWidgetStore } from '../../store';\nimport { SavedViewsDropdown } from './SavedViewsDropdown';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardToolbarProps {\n /** Dashboard ID for saved views */\n dashboardId?: string;\n /** Dashboard title */\n title?: string;\n /** Callback to add widget */\n onAddWidget: () => void;\n /** Callback to toggle widget palette */\n onTogglePalette?: () => void;\n /** Whether palette is open */\n isPaletteOpen?: boolean;\n /** Callback to paste widget */\n onPaste?: () => void;\n /** Callback to save dashboard */\n onSave?: () => void;\n /** Whether save is in progress */\n isSaving?: boolean;\n /** Callback to export dashboard */\n onExport?: () => void;\n /** Callback to open share dialog */\n onShare?: () => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const DashboardToolbar: FC<DashboardToolbarProps> = memo(function DashboardToolbar({\n dashboardId,\n title,\n onAddWidget,\n onTogglePalette,\n isPaletteOpen = false,\n onPaste,\n onSave,\n isSaving = false,\n onExport,\n onShare,\n}) {\n const isEditMode = useDashboardStore((state) => state.viewMode === 'edit');\n const toggleViewMode = useDashboardStore((state) => state.toggleViewMode);\n const zoomLevel = useDashboardStore((state) => state.zoomLevel);\n const setZoomLevel = useDashboardStore((state) => state.setZoomLevel);\n\n const clipboardWidgetId = useWidgetStore((state) => state.clipboardWidgetId);\n const hasClipboard = !!clipboardWidgetId;\n\n // Handle paste - use provided callback or fallback\n const handlePaste = useCallback(() => {\n if (hasClipboard && onPaste) {\n onPaste();\n }\n }, [hasClipboard, onPaste]);\n\n return (\n <TooltipProvider>\n <div className=\"flex flex-wrap items-center justify-between gap-x-4 gap-y-2 px-4 py-2 bg-background border-b\">\n {/* Left section */}\n <div className=\"flex min-w-0 items-center gap-4\">\n {title && (\n <h1 className=\"min-w-0 truncate text-lg font-semibold\" title={title}>\n {title}\n </h1>\n )}\n {/* Saved Views Dropdown */}\n {dashboardId && <SavedViewsDropdown dashboardId={dashboardId} />}\n </div>\n\n {/* Center section - Zoom controls */}\n <div className=\"flex flex-shrink-0 items-center gap-1\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => setZoomLevel(Math.max(50, zoomLevel - 10))}\n disabled={zoomLevel <= 50}\n >\n <Minus className=\"size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Zoom out</TooltipContent>\n </Tooltip>\n\n <span className=\"text-sm text-muted-foreground w-12 text-center\">{zoomLevel}%</span>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => setZoomLevel(Math.min(200, zoomLevel + 10))}\n disabled={zoomLevel >= 200}\n >\n <Plus className=\"size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Zoom in</TooltipContent>\n </Tooltip>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setZoomLevel(100)}>\n <RotateCcw className=\"size-3.5 mr-1\" />\n Reset\n </Button>\n </TooltipTrigger>\n <TooltipContent>Reset zoom to 100%</TooltipContent>\n </Tooltip>\n </div>\n\n {/* Right section - Actions */}\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {isEditMode && (\n <>\n {/* Widget Palette Toggle */}\n {onTogglePalette && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant={isPaletteOpen ? 'secondary' : 'outline'} size=\"sm\" onClick={onTogglePalette}>\n {isPaletteOpen ? <PanelLeftClose className=\"size-4\" /> : <PanelLeft className=\"size-4\" />}\n Widgets\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n {isPaletteOpen ? 'Hide widget palette' : 'Show widget palette for drag & drop'}\n </TooltipContent>\n </Tooltip>\n )}\n\n {/* Paste */}\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={handlePaste} disabled={!hasClipboard}>\n <Clipboard className=\"size-4\" />\n Paste\n </Button>\n </TooltipTrigger>\n <TooltipContent>Paste widget from clipboard</TooltipContent>\n </Tooltip>\n\n {/* Add Widget (Dialog) */}\n <Button size=\"sm\" onClick={onAddWidget}>\n <Plus className=\"size-4\" />\n Add Widget\n </Button>\n </>\n )}\n\n {/* Edit/View Mode Toggle */}\n <Button variant={isEditMode ? 'secondary' : 'outline'} size=\"sm\" onClick={toggleViewMode}>\n {isEditMode ? (\n <>\n <Eye className=\"size-4\" />\n Preview\n </>\n ) : (\n <>\n <Pencil className=\"size-4\" />\n Edit\n </>\n )}\n </Button>\n\n {/* Save */}\n {onSave && (\n <Button variant=\"outline\" size=\"sm\" onClick={onSave} disabled={isSaving}>\n {isSaving ? (\n <>\n <Spinner className=\"size-4\" />\n Saving...\n </>\n ) : (\n <>\n <Save className=\"size-4\" />\n Save\n </>\n )}\n </Button>\n )}\n\n {/* Share */}\n {onShare && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" onClick={onShare}>\n <Share2 className=\"size-4\" />\n Share\n </Button>\n </TooltipTrigger>\n <TooltipContent>Share dashboard with others</TooltipContent>\n </Tooltip>\n )}\n\n {/* Export */}\n {onExport && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" onClick={onExport}>\n <Download className=\"size-4\" />\n Export\n </Button>\n </TooltipTrigger>\n <TooltipContent>Export dashboard to JSON</TooltipContent>\n </Tooltip>\n )}\n </div>\n </div>\n </TooltipProvider>\n );\n});\n\nexport default DashboardToolbar;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardToolbar.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/DashboardToolbar.tsx"],"sourcesContent":["/**\n * DashboardToolbar Component\n *\n * Toolbar for dashboard actions and controls.\n * Uses fe-libs shared components for consistent styling.\n * Phase 2: Added SavedViewsDropdown and Share button.\n */\n\nimport { type FC, memo, useCallback } from 'react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport {\n Plus,\n Clipboard,\n Eye,\n Pencil,\n Save,\n Download,\n Minus,\n RotateCcw,\n Share2,\n PanelLeftClose,\n PanelLeft,\n Image as ImageIcon,\n FileText,\n} from 'lucide-react';\nimport { useDashboardStore, useWidgetStore } from '../../store';\nimport { SavedViewsDropdown } from './SavedViewsDropdown';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardToolbarProps {\n /** Dashboard ID for saved views */\n dashboardId?: string;\n /** Dashboard title */\n title?: string;\n /** Callback to add widget */\n onAddWidget: () => void;\n /** Callback to toggle widget palette */\n onTogglePalette?: () => void;\n /** Whether palette is open */\n isPaletteOpen?: boolean;\n /** Callback to paste widget */\n onPaste?: () => void;\n /** Callback to save dashboard */\n onSave?: () => void;\n /** Whether save is in progress */\n isSaving?: boolean;\n /** Callback to export dashboard (JSON console definition) */\n onExport?: () => void;\n /** Callback to export the board as a PNG image */\n onExportImage?: () => void;\n /** Callback to export the board as a PDF */\n onExportPdf?: () => void;\n /** Whether an image/PDF export is in progress */\n isExportingImage?: boolean;\n /** Callback to open share dialog */\n onShare?: () => void;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const DashboardToolbar: FC<DashboardToolbarProps> = memo(function DashboardToolbar({\n dashboardId,\n title,\n onAddWidget,\n onTogglePalette,\n isPaletteOpen = false,\n onPaste,\n onSave,\n isSaving = false,\n onExport,\n onExportImage,\n onExportPdf,\n isExportingImage = false,\n onShare,\n}) {\n const isEditMode = useDashboardStore((state) => state.viewMode === 'edit');\n const toggleViewMode = useDashboardStore((state) => state.toggleViewMode);\n const zoomLevel = useDashboardStore((state) => state.zoomLevel);\n const setZoomLevel = useDashboardStore((state) => state.setZoomLevel);\n\n const clipboardWidgetId = useWidgetStore((state) => state.clipboardWidgetId);\n const hasClipboard = !!clipboardWidgetId;\n\n // Handle paste - use provided callback or fallback\n const handlePaste = useCallback(() => {\n if (hasClipboard && onPaste) {\n onPaste();\n }\n }, [hasClipboard, onPaste]);\n\n return (\n <TooltipProvider>\n <div className=\"flex flex-wrap items-center justify-between gap-x-4 gap-y-2 px-4 py-2 bg-background border-b\">\n {/* Left section */}\n <div className=\"flex min-w-0 items-center gap-4\">\n {title && (\n <h1 className=\"min-w-0 truncate text-lg font-semibold\" title={title}>\n {title}\n </h1>\n )}\n {/* Saved Views Dropdown */}\n {dashboardId && <SavedViewsDropdown dashboardId={dashboardId} />}\n </div>\n\n {/* Center section - Zoom controls */}\n <div className=\"flex flex-shrink-0 items-center gap-1\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => setZoomLevel(Math.max(50, zoomLevel - 10))}\n disabled={zoomLevel <= 50}\n >\n <Minus className=\"size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Zoom out</TooltipContent>\n </Tooltip>\n\n <span className=\"text-sm text-muted-foreground w-12 text-center\">{zoomLevel}%</span>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => setZoomLevel(Math.min(200, zoomLevel + 10))}\n disabled={zoomLevel >= 200}\n >\n <Plus className=\"size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Zoom in</TooltipContent>\n </Tooltip>\n\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setZoomLevel(100)}>\n <RotateCcw className=\"size-3.5 mr-1\" />\n Reset\n </Button>\n </TooltipTrigger>\n <TooltipContent>Reset zoom to 100%</TooltipContent>\n </Tooltip>\n </div>\n\n {/* Right section - Actions */}\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {isEditMode && (\n <>\n {/* Widget Palette Toggle */}\n {onTogglePalette && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant={isPaletteOpen ? 'secondary' : 'outline'} size=\"sm\" onClick={onTogglePalette}>\n {isPaletteOpen ? <PanelLeftClose className=\"size-4\" /> : <PanelLeft className=\"size-4\" />}\n Widgets\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n {isPaletteOpen ? 'Hide widget palette' : 'Show widget palette for drag & drop'}\n </TooltipContent>\n </Tooltip>\n )}\n\n {/* Paste */}\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" onClick={handlePaste} disabled={!hasClipboard}>\n <Clipboard className=\"size-4\" />\n Paste\n </Button>\n </TooltipTrigger>\n <TooltipContent>Paste widget from clipboard</TooltipContent>\n </Tooltip>\n\n {/* Add Widget (Dialog) */}\n <Button size=\"sm\" onClick={onAddWidget}>\n <Plus className=\"size-4\" />\n Add Widget\n </Button>\n </>\n )}\n\n {/* Edit/View Mode Toggle */}\n <Button variant={isEditMode ? 'secondary' : 'outline'} size=\"sm\" onClick={toggleViewMode}>\n {isEditMode ? (\n <>\n <Eye className=\"size-4\" />\n Preview\n </>\n ) : (\n <>\n <Pencil className=\"size-4\" />\n Edit\n </>\n )}\n </Button>\n\n {/* Save */}\n {onSave && (\n <Button variant=\"outline\" size=\"sm\" onClick={onSave} disabled={isSaving}>\n {isSaving ? (\n <>\n <Spinner className=\"size-4\" />\n Saving...\n </>\n ) : (\n <>\n <Save className=\"size-4\" />\n Save\n </>\n )}\n </Button>\n )}\n\n {/* Share */}\n {onShare && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" onClick={onShare}>\n <Share2 className=\"size-4\" />\n Share\n </Button>\n </TooltipTrigger>\n <TooltipContent>Share dashboard with others</TooltipContent>\n </Tooltip>\n )}\n\n {/* Export — JSON definition */}\n {onExport && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" onClick={onExport}>\n <Download className=\"size-4\" />\n Export\n </Button>\n </TooltipTrigger>\n <TooltipContent>Export dashboard to JSON</TooltipContent>\n </Tooltip>\n )}\n\n {/* Export — board PNG */}\n {onExportImage && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"icon-sm\" onClick={onExportImage} disabled={isExportingImage}>\n {isExportingImage ? <Spinner className=\"size-4\" /> : <ImageIcon className=\"size-4\" />}\n </Button>\n </TooltipTrigger>\n <TooltipContent>Export board as PNG image</TooltipContent>\n </Tooltip>\n )}\n\n {/* Export — board PDF */}\n {onExportPdf && (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"outline\" size=\"icon-sm\" onClick={onExportPdf} disabled={isExportingImage}>\n <FileText className=\"size-4\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Export board as PDF</TooltipContent>\n </Tooltip>\n )}\n </div>\n </div>\n </TooltipProvider>\n );\n});\n\nexport default DashboardToolbar;\n"],"mappings":"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"}
|
|
@@ -1,45 +1,60 @@
|
|
|
1
|
-
import { memo as e, useCallback as t } from "react";
|
|
2
|
-
import {
|
|
1
|
+
import { memo as e, useCallback as t, useEffect as n, useRef as r, useState as i } from "react";
|
|
2
|
+
import { GripVertical as a } from "lucide-react";
|
|
3
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
3
4
|
//#region src/bigconsole/components/widgets/table/TableHeader.tsx
|
|
4
|
-
var
|
|
5
|
-
let
|
|
6
|
-
e.sortable !== !1 &&
|
|
7
|
-
}, [
|
|
5
|
+
var c = 60, l = e(function({ columns: e, sortState: l, onSort: u, sticky: d = !0, frozenLefts: f, editable: p = !1, onColumnResize: m, onColumnResizeEnd: h, onColumnReorder: g }) {
|
|
6
|
+
let _ = t((e) => {
|
|
7
|
+
e.sortable !== !1 && u(e.key);
|
|
8
|
+
}, [u]), v = r({}), [y, b] = i(null), [x, S] = i(null), C = r(null), w = r(null), T = t((e, t) => {
|
|
9
|
+
t.preventDefault(), t.stopPropagation();
|
|
10
|
+
let n = v.current[e], r = n ? n.offsetWidth : c, i = t.clientX;
|
|
11
|
+
b(e);
|
|
12
|
+
let a = r, o = (t) => {
|
|
13
|
+
a = Math.max(c, Math.round(r + (t.clientX - i))), m?.(e, a);
|
|
14
|
+
}, s = () => {
|
|
15
|
+
window.removeEventListener("pointermove", o), window.removeEventListener("pointerup", l), w.current = null;
|
|
16
|
+
}, l = () => {
|
|
17
|
+
s(), b(null), h?.(e, a);
|
|
18
|
+
};
|
|
19
|
+
w.current = s, window.addEventListener("pointermove", o), window.addEventListener("pointerup", l);
|
|
20
|
+
}, [m, h]);
|
|
21
|
+
n(() => () => w.current?.(), []);
|
|
22
|
+
let E = (e) => {
|
|
8
23
|
if (e.sortable === !1) return null;
|
|
9
|
-
let t =
|
|
10
|
-
return /* @__PURE__ */
|
|
24
|
+
let t = l.column === e.key ? l.direction : null;
|
|
25
|
+
return /* @__PURE__ */ s("span", {
|
|
11
26
|
className: "inline-flex ml-1",
|
|
12
27
|
children: [
|
|
13
|
-
t === "asc" && /* @__PURE__ */
|
|
28
|
+
t === "asc" && /* @__PURE__ */ o("svg", {
|
|
14
29
|
className: "w-4 h-4 text-action-primary-bg",
|
|
15
30
|
fill: "none",
|
|
16
31
|
stroke: "currentColor",
|
|
17
32
|
viewBox: "0 0 24 24",
|
|
18
|
-
children: /* @__PURE__ */
|
|
33
|
+
children: /* @__PURE__ */ o("path", {
|
|
19
34
|
strokeLinecap: "round",
|
|
20
35
|
strokeLinejoin: "round",
|
|
21
36
|
strokeWidth: 2,
|
|
22
37
|
d: "M5 15l7-7 7 7"
|
|
23
38
|
})
|
|
24
39
|
}),
|
|
25
|
-
t === "desc" && /* @__PURE__ */
|
|
40
|
+
t === "desc" && /* @__PURE__ */ o("svg", {
|
|
26
41
|
className: "w-4 h-4 text-action-primary-bg",
|
|
27
42
|
fill: "none",
|
|
28
43
|
stroke: "currentColor",
|
|
29
44
|
viewBox: "0 0 24 24",
|
|
30
|
-
children: /* @__PURE__ */
|
|
45
|
+
children: /* @__PURE__ */ o("path", {
|
|
31
46
|
strokeLinecap: "round",
|
|
32
47
|
strokeLinejoin: "round",
|
|
33
48
|
strokeWidth: 2,
|
|
34
49
|
d: "M19 9l-7 7-7-7"
|
|
35
50
|
})
|
|
36
51
|
}),
|
|
37
|
-
!t && /* @__PURE__ */
|
|
52
|
+
!t && /* @__PURE__ */ o("svg", {
|
|
38
53
|
className: "w-4 h-4 text-text-secondary opacity-0 group-hover:opacity-100",
|
|
39
54
|
fill: "none",
|
|
40
55
|
stroke: "currentColor",
|
|
41
56
|
viewBox: "0 0 24 24",
|
|
42
|
-
children: /* @__PURE__ */
|
|
57
|
+
children: /* @__PURE__ */ o("path", {
|
|
43
58
|
strokeLinecap: "round",
|
|
44
59
|
strokeLinejoin: "round",
|
|
45
60
|
strokeWidth: 2,
|
|
@@ -49,16 +64,37 @@ var i = e(function({ columns: e, sortState: i, onSort: a, sticky: o = !0, frozen
|
|
|
49
64
|
]
|
|
50
65
|
});
|
|
51
66
|
};
|
|
52
|
-
return /* @__PURE__ */
|
|
67
|
+
return /* @__PURE__ */ o("thead", {
|
|
53
68
|
className: `
|
|
54
69
|
bg-bg-muted
|
|
55
|
-
${
|
|
70
|
+
${d ? "sticky top-0 z-10" : ""}
|
|
56
71
|
`,
|
|
57
|
-
children: /* @__PURE__ */
|
|
58
|
-
let t =
|
|
59
|
-
return /* @__PURE__ */
|
|
72
|
+
children: /* @__PURE__ */ o("tr", { children: e.map((e) => {
|
|
73
|
+
let t = f?.[e.key], n = e.width, r = p && !!g && y === null, i = x === e.key && C.current !== e.key;
|
|
74
|
+
return /* @__PURE__ */ s("th", {
|
|
75
|
+
ref: (t) => {
|
|
76
|
+
v.current[e.key] = t;
|
|
77
|
+
},
|
|
78
|
+
draggable: r,
|
|
79
|
+
onDragStart: r ? (t) => {
|
|
80
|
+
C.current = e.key, t.dataTransfer.effectAllowed = "move", t.dataTransfer.setData("text/plain", e.key);
|
|
81
|
+
} : void 0,
|
|
82
|
+
onDragOver: p && g ? (t) => {
|
|
83
|
+
C.current && C.current !== e.key && (t.preventDefault(), t.dataTransfer.dropEffect = "move", x !== e.key && S(e.key));
|
|
84
|
+
} : void 0,
|
|
85
|
+
onDragLeave: p && g ? () => {
|
|
86
|
+
x === e.key && S(null);
|
|
87
|
+
} : void 0,
|
|
88
|
+
onDrop: p && g ? (t) => {
|
|
89
|
+
t.preventDefault();
|
|
90
|
+
let n = C.current;
|
|
91
|
+
C.current = null, S(null), n && n !== e.key && g(n, e.key);
|
|
92
|
+
} : void 0,
|
|
93
|
+
onDragEnd: r ? () => {
|
|
94
|
+
C.current = null, S(null);
|
|
95
|
+
} : void 0,
|
|
60
96
|
className: `
|
|
61
|
-
px-4 py-3
|
|
97
|
+
relative px-4 py-3
|
|
62
98
|
text-xs font-semibold uppercase tracking-wider
|
|
63
99
|
text-text-secondary
|
|
64
100
|
border-b border-border-default
|
|
@@ -66,27 +102,51 @@ var i = e(function({ columns: e, sortState: i, onSort: a, sticky: o = !0, frozen
|
|
|
66
102
|
${e.align === "center" ? "text-center" : ""}
|
|
67
103
|
${e.align === "right" ? "text-right" : "text-left"}
|
|
68
104
|
${t == null ? "" : "sticky z-20 bg-bg-muted"}
|
|
105
|
+
${i ? "border-l-2 border-l-action-primary-bg" : ""}
|
|
69
106
|
`,
|
|
70
|
-
style: t == null ? { width:
|
|
71
|
-
width:
|
|
107
|
+
style: t == null ? { width: n } : {
|
|
108
|
+
width: n,
|
|
72
109
|
left: t
|
|
73
110
|
},
|
|
74
|
-
onClick: () =>
|
|
111
|
+
onClick: () => _(e),
|
|
75
112
|
role: e.sortable === !1 ? void 0 : "button",
|
|
76
113
|
tabIndex: e.sortable === !1 ? void 0 : 0,
|
|
77
114
|
onKeyDown: (t) => {
|
|
78
|
-
e.sortable !== !1 && (t.key === "Enter" || t.key === " ") && (t.preventDefault(),
|
|
115
|
+
e.sortable !== !1 && (t.key === "Enter" || t.key === " ") && (t.preventDefault(), _(e));
|
|
79
116
|
},
|
|
80
|
-
"aria-sort":
|
|
81
|
-
children: /* @__PURE__ */
|
|
117
|
+
"aria-sort": l.column === e.key ? l.direction === "asc" ? "ascending" : "descending" : void 0,
|
|
118
|
+
children: [/* @__PURE__ */ s("div", {
|
|
82
119
|
className: "inline-flex items-center",
|
|
83
|
-
children: [
|
|
84
|
-
|
|
120
|
+
children: [
|
|
121
|
+
p && g && /* @__PURE__ */ o("span", {
|
|
122
|
+
className: "mr-1 -ml-1 cursor-grab text-text-tertiary opacity-0 group-hover:opacity-100",
|
|
123
|
+
onClick: (e) => e.stopPropagation(),
|
|
124
|
+
"aria-hidden": "true",
|
|
125
|
+
title: "Drag to reorder column",
|
|
126
|
+
children: /* @__PURE__ */ o(a, { className: "w-3.5 h-3.5" })
|
|
127
|
+
}),
|
|
128
|
+
e.header,
|
|
129
|
+
E(e)
|
|
130
|
+
]
|
|
131
|
+
}), p && m && /* @__PURE__ */ o("span", {
|
|
132
|
+
role: "separator",
|
|
133
|
+
"aria-orientation": "vertical",
|
|
134
|
+
"aria-label": `Resize ${e.header} column`,
|
|
135
|
+
className: `
|
|
136
|
+
absolute top-0 right-0 z-30 h-full w-1.5
|
|
137
|
+
cursor-col-resize select-none
|
|
138
|
+
hover:bg-action-primary-bg/40
|
|
139
|
+
${y === e.key ? "bg-action-primary-bg/60" : ""}
|
|
140
|
+
`,
|
|
141
|
+
onPointerDown: (t) => T(e.key, t),
|
|
142
|
+
onClick: (e) => e.stopPropagation(),
|
|
143
|
+
draggable: !1
|
|
144
|
+
})]
|
|
85
145
|
}, e.key);
|
|
86
146
|
}) })
|
|
87
147
|
});
|
|
88
148
|
});
|
|
89
149
|
//#endregion
|
|
90
|
-
export {
|
|
150
|
+
export { l as default };
|
|
91
151
|
|
|
92
152
|
//# sourceMappingURL=TableHeader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableHeader.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/table/TableHeader.tsx"],"sourcesContent":["/**\n * TableHeader Component\n *\n * Sortable table header with column definitions.\n */\n\nimport { type FC, memo, useCallback } from 'react';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ColumnDefinition {\n /** Unique key for the column */\n key: string;\n /** Display header text */\n header: string;\n /** Whether column is sortable */\n sortable?: boolean;\n /** Column width (CSS value) */\n width?: string;\n /** Text alignment */\n align?: 'left' | 'center' | 'right';\n}\n\nexport type SortDirection = 'asc' | 'desc' | null;\n\nexport interface SortState {\n column: string | null;\n direction: SortDirection;\n}\n\nexport interface TableHeaderProps {\n /** Column definitions */\n columns: ColumnDefinition[];\n /** Current sort state */\n sortState: SortState;\n /** Callback when sort changes */\n onSort: (column: string) => void;\n /** Whether header is sticky */\n sticky?: boolean;\n /** column key → sticky-left px offset for frozen leading columns */\n frozenLefts?: Record<string, number>;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const TableHeader: FC<TableHeaderProps> = memo(function TableHeader({\n columns,\n sortState,\n onSort,\n sticky = true,\n frozenLefts,\n}) {\n const handleSort = useCallback(\n (column: ColumnDefinition) => {\n if (column.sortable !== false) {\n onSort(column.key);\n }\n },\n [onSort]\n );\n\n const getSortIcon = (column: ColumnDefinition) => {\n if (column.sortable === false) return null;\n\n const isActive = sortState.column === column.key;\n const direction = isActive ? sortState.direction : null;\n\n return (\n <span className=\"inline-flex ml-1\">\n {direction === 'asc' && (\n <svg className=\"w-4 h-4 text-action-primary-bg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 15l7-7 7 7\" />\n </svg>\n )}\n {direction === 'desc' && (\n <svg className=\"w-4 h-4 text-action-primary-bg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n )}\n {!direction && (\n <svg\n className=\"w-4 h-4 text-text-secondary opacity-0 group-hover:opacity-100\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4\"\n />\n </svg>\n )}\n </span>\n );\n };\n\n return (\n <thead\n className={`\n bg-bg-muted\n ${sticky ? 'sticky top-0 z-10' : ''}\n `}\n >\n <tr>\n {columns.map((column) => {\n const frozen = frozenLefts?.[column.key];\n return (\n <th\n key={column.key}\n className={`\n px-4 py-3\n text-xs font-semibold uppercase tracking-wider\n text-text-secondary\n border-b border-border-default\n ${column.sortable !== false ? 'cursor-pointer select-none group hover:bg-bg-surface' : ''}\n ${column.align === 'center' ? 'text-center' : ''}\n ${column.align === 'right' ? 'text-right' : 'text-left'}\n ${frozen != null ? 'sticky z-20 bg-bg-muted' : ''}\n `}\n style={frozen != null ? { width: column.width, left: frozen } : { width: column.width }}\n onClick={() => handleSort(column)}\n role={column.sortable !== false ? 'button' : undefined}\n tabIndex={column.sortable !== false ? 0 : undefined}\n onKeyDown={(e) => {\n if (column.sortable !== false && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n handleSort(column);\n }\n }}\n aria-sort={\n sortState.column === column.key\n ? sortState.direction === 'asc'\n ? 'ascending'\n : 'descending'\n : undefined\n }\n >\n <div className=\"inline-flex items-center\">\n {column.header}\n {getSortIcon(column)}\n </div>\n </th>\n );\n })}\n </tr>\n </thead>\n );\n});\n\nexport default TableHeader;\n"],"mappings":";;;AAiDA,IAAa,IAAoC,EAAK,SAAqB,EACzE,YACA,cACA,WACA,YAAS,IACT,kBACC;CACD,IAAM,IAAa,GAChB,MAA6B;AAC5B,EAAI,EAAO,aAAa,MACtB,EAAO,EAAO,IAAI;IAGtB,CAAC,EAAO,CACT,EAEK,KAAe,MAA6B;AAChD,MAAI,EAAO,aAAa,GAAO,QAAO;EAGtC,IAAM,IADW,EAAU,WAAW,EAAO,MAChB,EAAU,YAAY;AAEnD,SACE,kBAAC,QAAD;GAAM,WAAU;aAAhB;IACG,MAAc,SACb,kBAAC,OAAD;KAAK,WAAU;KAAiC,MAAK;KAAO,QAAO;KAAe,SAAQ;eACxF,kBAAC,QAAD;MAAM,eAAc;MAAQ,gBAAe;MAAQ,aAAa;MAAG,GAAE;MAAkB,CAAA;KACnF,CAAA;IAEP,MAAc,UACb,kBAAC,OAAD;KAAK,WAAU;KAAiC,MAAK;KAAO,QAAO;KAAe,SAAQ;eACxF,kBAAC,QAAD;MAAM,eAAc;MAAQ,gBAAe;MAAQ,aAAa;MAAG,GAAE;MAAmB,CAAA;KACpF,CAAA;IAEP,CAAC,KACA,kBAAC,OAAD;KACE,WAAU;KACV,MAAK;KACL,QAAO;KACP,SAAQ;eAER,kBAAC,QAAD;MACE,eAAc;MACd,gBAAe;MACf,aAAa;MACb,GAAE;MACF,CAAA;KACE,CAAA;IAEH;;;AAIX,QACE,kBAAC,SAAD;EACE,WAAW;;UAEP,IAAS,sBAAsB,GAAG;;YAGtC,kBAAC,MAAD,EAAA,UACG,EAAQ,KAAK,MAAW;GACvB,IAAM,IAAS,IAAc,EAAO;AACpC,UACE,kBAAC,MAAD;IAEE,WAAW;;;;;gBAKT,EAAO,aAAa,KAAiE,KAAzD,uDAA4D;gBACxF,EAAO,UAAU,WAAW,gBAAgB,GAAG;gBAC/C,EAAO,UAAU,UAAU,eAAe,YAAY;gBACtD,KAAU,OAAmC,KAA5B,0BAA+B;;IAElD,OAAO,KAAU,OAA+C,EAAE,OAAO,EAAO,OAAO,GAA/D;KAAE,OAAO,EAAO;KAAO,MAAM;KAAQ;IAC7D,eAAe,EAAW,EAAO;IACjC,MAAM,EAAO,aAAa,KAAmB,KAAA,IAAX;IAClC,UAAU,EAAO,aAAa,KAAY,KAAA,IAAJ;IACtC,YAAY,MAAM;AAChB,KAAI,EAAO,aAAa,OAAU,EAAE,QAAQ,WAAW,EAAE,QAAQ,SAC/D,EAAE,gBAAgB,EAClB,EAAW,EAAO;;IAGtB,aACE,EAAU,WAAW,EAAO,MACxB,EAAU,cAAc,QACtB,cACA,eACF,KAAA;cAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACG,EAAO,QACP,EAAY,EAAO,CAChB;;IACH,EAjCE,EAAO,IAiCT;IAEP,EACC,CAAA;EACC,CAAA;EAEV"}
|
|
1
|
+
{"version":3,"file":"TableHeader.js","names":[],"sources":["../../../../../src/bigconsole/components/widgets/table/TableHeader.tsx"],"sourcesContent":["/**\n * TableHeader Component\n *\n * Sortable table header with column definitions. In edit mode it also supports\n * interactive column resize (drag the right border) and reorder (drag the grip\n * handle), each surfaced through callbacks the parent persists to widget config.\n */\n\nimport { type FC, memo, useCallback, useEffect, useRef, useState } from 'react';\nimport { GripVertical } from 'lucide-react';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ColumnDefinition {\n /** Unique key for the column */\n key: string;\n /** Display header text */\n header: string;\n /** Whether column is sortable */\n sortable?: boolean;\n /** Column width (CSS value) */\n width?: string;\n /** Text alignment */\n align?: 'left' | 'center' | 'right';\n}\n\nexport type SortDirection = 'asc' | 'desc' | null;\n\nexport interface SortState {\n column: string | null;\n direction: SortDirection;\n}\n\nexport interface TableHeaderProps {\n /** Column definitions */\n columns: ColumnDefinition[];\n /** Current sort state */\n sortState: SortState;\n /** Callback when sort changes */\n onSort: (column: string) => void;\n /** Whether header is sticky */\n sticky?: boolean;\n /** column key → sticky-left px offset for frozen leading columns */\n frozenLefts?: Record<string, number>;\n /** Enable interactive resize + reorder (edit mode). */\n editable?: boolean;\n /** Called on every resize move with the in-progress width (px) for live feedback. */\n onColumnResize?: (key: string, widthPx: number) => void;\n /** Called once when a resize drag ends with the final width (px) — parent persists. */\n onColumnResizeEnd?: (key: string, widthPx: number) => void;\n /** Called when a column is dropped onto another to reorder — parent persists. */\n onColumnReorder?: (sourceKey: string, targetKey: string) => void;\n}\n\nconst MIN_COLUMN_WIDTH = 60;\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const TableHeader: FC<TableHeaderProps> = memo(function TableHeader({\n columns,\n sortState,\n onSort,\n sticky = true,\n frozenLefts,\n editable = false,\n onColumnResize,\n onColumnResizeEnd,\n onColumnReorder,\n}) {\n const handleSort = useCallback(\n (column: ColumnDefinition) => {\n if (column.sortable !== false) {\n onSort(column.key);\n }\n },\n [onSort]\n );\n\n // Refs to each <th> so a resize drag can read its current rendered width.\n const thRefs = useRef<Record<string, HTMLTableCellElement | null>>({});\n // Key being resized — disabled drag-reorder while resizing, and used for cursor.\n const [resizingKey, setResizingKey] = useState<string | null>(null);\n const [dragOverKey, setDragOverKey] = useState<string | null>(null);\n const dragSourceKey = useRef<string | null>(null);\n // Removes the active resize window-listeners; set during a drag, called on\n // pointer-up and on unmount so a drag interrupted by unmount can't leak.\n const teardownResizeRef = useRef<(() => void) | null>(null);\n\n // Start a resize drag from the right-border handle. Uses window listeners so\n // the pointer can leave the (narrow) handle without dropping the gesture.\n const startResize = useCallback(\n (key: string, startEvent: React.PointerEvent) => {\n startEvent.preventDefault();\n startEvent.stopPropagation();\n const th = thRefs.current[key];\n const startWidth = th ? th.offsetWidth : MIN_COLUMN_WIDTH;\n const startX = startEvent.clientX;\n setResizingKey(key);\n\n let lastWidth = startWidth;\n const onMove = (e: PointerEvent) => {\n lastWidth = Math.max(MIN_COLUMN_WIDTH, Math.round(startWidth + (e.clientX - startX)));\n onColumnResize?.(key, lastWidth);\n };\n const teardown = () => {\n window.removeEventListener('pointermove', onMove);\n window.removeEventListener('pointerup', onUp);\n teardownResizeRef.current = null;\n };\n const onUp = () => {\n teardown();\n setResizingKey(null);\n onColumnResizeEnd?.(key, lastWidth);\n };\n teardownResizeRef.current = teardown;\n window.addEventListener('pointermove', onMove);\n window.addEventListener('pointerup', onUp);\n },\n [onColumnResize, onColumnResizeEnd]\n );\n\n // Detach any in-progress resize listeners if the header unmounts mid-drag.\n useEffect(() => () => teardownResizeRef.current?.(), []);\n\n const getSortIcon = (column: ColumnDefinition) => {\n if (column.sortable === false) return null;\n\n const isActive = sortState.column === column.key;\n const direction = isActive ? sortState.direction : null;\n\n return (\n <span className=\"inline-flex ml-1\">\n {direction === 'asc' && (\n <svg className=\"w-4 h-4 text-action-primary-bg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 15l7-7 7 7\" />\n </svg>\n )}\n {direction === 'desc' && (\n <svg className=\"w-4 h-4 text-action-primary-bg\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n )}\n {!direction && (\n <svg\n className=\"w-4 h-4 text-text-secondary opacity-0 group-hover:opacity-100\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4\"\n />\n </svg>\n )}\n </span>\n );\n };\n\n return (\n <thead\n className={`\n bg-bg-muted\n ${sticky ? 'sticky top-0 z-10' : ''}\n `}\n >\n <tr>\n {columns.map((column) => {\n const frozen = frozenLefts?.[column.key];\n // Width (incl. live resize overrides) is baked into column.width by the parent.\n const width = column.width;\n const reorderable = editable && !!onColumnReorder && resizingKey === null;\n const isDropTarget = dragOverKey === column.key && dragSourceKey.current !== column.key;\n return (\n <th\n key={column.key}\n ref={(el) => {\n thRefs.current[column.key] = el;\n }}\n draggable={reorderable}\n onDragStart={\n reorderable\n ? (e) => {\n dragSourceKey.current = column.key;\n e.dataTransfer.effectAllowed = 'move';\n // Some browsers require data to be set for a drag to start.\n e.dataTransfer.setData('text/plain', column.key);\n }\n : undefined\n }\n onDragOver={\n editable && onColumnReorder\n ? (e) => {\n if (dragSourceKey.current && dragSourceKey.current !== column.key) {\n e.preventDefault();\n e.dataTransfer.dropEffect = 'move';\n if (dragOverKey !== column.key) setDragOverKey(column.key);\n }\n }\n : undefined\n }\n onDragLeave={\n editable && onColumnReorder\n ? () => {\n if (dragOverKey === column.key) setDragOverKey(null);\n }\n : undefined\n }\n onDrop={\n editable && onColumnReorder\n ? (e) => {\n e.preventDefault();\n const source = dragSourceKey.current;\n dragSourceKey.current = null;\n setDragOverKey(null);\n if (source && source !== column.key) {\n onColumnReorder(source, column.key);\n }\n }\n : undefined\n }\n onDragEnd={\n reorderable\n ? () => {\n dragSourceKey.current = null;\n setDragOverKey(null);\n }\n : undefined\n }\n className={`\n relative px-4 py-3\n text-xs font-semibold uppercase tracking-wider\n text-text-secondary\n border-b border-border-default\n ${column.sortable !== false ? 'cursor-pointer select-none group hover:bg-bg-surface' : ''}\n ${column.align === 'center' ? 'text-center' : ''}\n ${column.align === 'right' ? 'text-right' : 'text-left'}\n ${frozen != null ? 'sticky z-20 bg-bg-muted' : ''}\n ${isDropTarget ? 'border-l-2 border-l-action-primary-bg' : ''}\n `}\n style={frozen != null ? { width, left: frozen } : { width }}\n onClick={() => handleSort(column)}\n role={column.sortable !== false ? 'button' : undefined}\n tabIndex={column.sortable !== false ? 0 : undefined}\n onKeyDown={(e) => {\n if (column.sortable !== false && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n handleSort(column);\n }\n }}\n aria-sort={\n sortState.column === column.key\n ? sortState.direction === 'asc'\n ? 'ascending'\n : 'descending'\n : undefined\n }\n >\n <div className=\"inline-flex items-center\">\n {editable && onColumnReorder && (\n // Reorder grip — its own drag surface so dragging it (not the\n // label) starts a reorder, leaving the label click free to sort.\n <span\n className=\"mr-1 -ml-1 cursor-grab text-text-tertiary opacity-0 group-hover:opacity-100\"\n onClick={(e) => e.stopPropagation()}\n aria-hidden=\"true\"\n title=\"Drag to reorder column\"\n >\n <GripVertical className=\"w-3.5 h-3.5\" />\n </span>\n )}\n {column.header}\n {getSortIcon(column)}\n </div>\n {editable && onColumnResize && (\n // Resize handle on the right border. Pointer-only; stops the sort\n // click and the reorder drag from firing.\n <span\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={`Resize ${column.header} column`}\n className={`\n absolute top-0 right-0 z-30 h-full w-1.5\n cursor-col-resize select-none\n hover:bg-action-primary-bg/40\n ${resizingKey === column.key ? 'bg-action-primary-bg/60' : ''}\n `}\n onPointerDown={(e) => startResize(column.key, e)}\n onClick={(e) => e.stopPropagation()}\n draggable={false}\n />\n )}\n </th>\n );\n })}\n </tr>\n </thead>\n );\n});\n\nexport default TableHeader;\n"],"mappings":"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"}
|