xiod-ui 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/LICENSE +73 -0
- package/README.md +167 -0
- package/dist/components/accordion.d.ts +9 -0
- package/dist/components/accordion.js +46 -0
- package/dist/components/agent-steps.d.ts +47 -0
- package/dist/components/agent-steps.js +223 -0
- package/dist/components/alert-dialog.d.ts +21 -0
- package/dist/components/alert-dialog.js +74 -0
- package/dist/components/alert.d.ts +12 -0
- package/dist/components/alert.js +45 -0
- package/dist/components/aspect-ratio.d.ts +9 -0
- package/dist/components/aspect-ratio.js +22 -0
- package/dist/components/autocomplete.d.ts +35 -0
- package/dist/components/autocomplete.js +160 -0
- package/dist/components/avatar.d.ts +17 -0
- package/dist/components/avatar.js +65 -0
- package/dist/components/badge.d.ts +15 -0
- package/dist/components/badge.js +46 -0
- package/dist/components/breadcrumb.d.ts +12 -0
- package/dist/components/breadcrumb.js +75 -0
- package/dist/components/button-group.d.ts +14 -0
- package/dist/components/button-group.js +45 -0
- package/dist/components/button-split.d.ts +19 -0
- package/dist/components/button-split.js +73 -0
- package/dist/components/button.d.ts +15 -0
- package/dist/components/button.js +54 -0
- package/dist/components/calendar.d.ts +63 -0
- package/dist/components/calendar.js +425 -0
- package/dist/components/card.d.ts +17 -0
- package/dist/components/card.js +139 -0
- package/dist/components/carousel.d.ts +59 -0
- package/dist/components/carousel.js +503 -0
- package/dist/components/checkbox.d.ts +16 -0
- package/dist/components/checkbox.js +86 -0
- package/dist/components/circular-progress.d.ts +28 -0
- package/dist/components/circular-progress.js +127 -0
- package/dist/components/collapsible.d.ts +8 -0
- package/dist/components/collapsible.js +27 -0
- package/dist/components/color-picker.d.ts +159 -0
- package/dist/components/color-picker.js +1589 -0
- package/dist/components/combobox.d.ts +46 -0
- package/dist/components/combobox.js +237 -0
- package/dist/components/command.d.ts +22 -0
- package/dist/components/command.js +129 -0
- package/dist/components/context-menu.d.ts +38 -0
- package/dist/components/context-menu.js +164 -0
- package/dist/components/copy-to-clipboard.d.ts +32 -0
- package/dist/components/copy-to-clipboard.js +83 -0
- package/dist/components/corner-badge.d.ts +22 -0
- package/dist/components/corner-badge.js +84 -0
- package/dist/components/dashboard-grid.d.ts +83 -0
- package/dist/components/dashboard-grid.js +486 -0
- package/dist/components/date-picker.d.ts +29 -0
- package/dist/components/date-picker.js +261 -0
- package/dist/components/dialog.d.ts +26 -0
- package/dist/components/dialog.js +97 -0
- package/dist/components/dot-matrix.d.ts +32 -0
- package/dist/components/dot-matrix.js +707 -0
- package/dist/components/draggable.d.ts +42 -0
- package/dist/components/draggable.js +346 -0
- package/dist/components/drawer.d.ts +66 -0
- package/dist/components/drawer.js +304 -0
- package/dist/components/empty.d.ts +14 -0
- package/dist/components/empty.js +75 -0
- package/dist/components/field.d.ts +12 -0
- package/dist/components/field.js +44 -0
- package/dist/components/fieldset.d.ts +7 -0
- package/dist/components/fieldset.js +21 -0
- package/dist/components/file-upload.d.ts +61 -0
- package/dist/components/file-upload.js +482 -0
- package/dist/components/form.d.ts +6 -0
- package/dist/components/form.js +14 -0
- package/dist/components/frame.d.ts +10 -0
- package/dist/components/frame.js +47 -0
- package/dist/components/gauge.d.ts +27 -0
- package/dist/components/gauge.js +74 -0
- package/dist/components/grid.d.ts +26 -0
- package/dist/components/grid.js +204 -0
- package/dist/components/group.d.ts +19 -0
- package/dist/components/group.js +45 -0
- package/dist/components/input-group.d.ts +15 -0
- package/dist/components/input-group.js +61 -0
- package/dist/components/input-otp.d.ts +24 -0
- package/dist/components/input-otp.js +50 -0
- package/dist/components/input-payment.d.ts +131 -0
- package/dist/components/input-payment.js +1140 -0
- package/dist/components/input-phone.d.ts +70 -0
- package/dist/components/input-phone.js +657 -0
- package/dist/components/input-sensitive.d.ts +12 -0
- package/dist/components/input-sensitive.js +169 -0
- package/dist/components/input.d.ts +13 -0
- package/dist/components/input.js +26 -0
- package/dist/components/kbd.d.ts +6 -0
- package/dist/components/kbd.js +19 -0
- package/dist/components/kinetic-click.d.ts +48 -0
- package/dist/components/kinetic-click.js +1184 -0
- package/dist/components/label.d.ts +6 -0
- package/dist/components/label.js +18 -0
- package/dist/components/list-box.d.ts +20 -0
- package/dist/components/list-box.js +148 -0
- package/dist/components/loader.d.ts +13 -0
- package/dist/components/loader.js +430 -0
- package/dist/components/marker.d.ts +15 -0
- package/dist/components/marker.js +59 -0
- package/dist/components/menu.d.ts +42 -0
- package/dist/components/menu.js +186 -0
- package/dist/components/menubar.d.ts +40 -0
- package/dist/components/menubar.js +107 -0
- package/dist/components/message.d.ts +33 -0
- package/dist/components/message.js +112 -0
- package/dist/components/meter.d.ts +10 -0
- package/dist/components/meter.js +42 -0
- package/dist/components/morphic-toast.d.ts +61 -0
- package/dist/components/morphic-toast.js +916 -0
- package/dist/components/navigation-menu.d.ts +26 -0
- package/dist/components/navigation-menu.js +116 -0
- package/dist/components/number-field.d.ts +15 -0
- package/dist/components/number-field.js +86 -0
- package/dist/components/option-picker.d.ts +18 -0
- package/dist/components/option-picker.js +89 -0
- package/dist/components/orb.d.ts +38 -0
- package/dist/components/orb.js +1413 -0
- package/dist/components/pagination.d.ts +25 -0
- package/dist/components/pagination.js +147 -0
- package/dist/components/popover.d.ts +22 -0
- package/dist/components/popover.js +79 -0
- package/dist/components/preview-card.d.ts +16 -0
- package/dist/components/preview-card.js +60 -0
- package/dist/components/progress.d.ts +21 -0
- package/dist/components/progress.js +139 -0
- package/dist/components/radio.d.ts +16 -0
- package/dist/components/radio.js +68 -0
- package/dist/components/resizable.d.ts +58 -0
- package/dist/components/resizable.js +964 -0
- package/dist/components/ruler-picker.d.ts +27 -0
- package/dist/components/ruler-picker.js +253 -0
- package/dist/components/scroll-area.d.ts +13 -0
- package/dist/components/scroll-area.js +34 -0
- package/dist/components/scroll-bar.d.ts +13 -0
- package/dist/components/scroll-bar.js +47 -0
- package/dist/components/select.d.ts +29 -0
- package/dist/components/select.js +140 -0
- package/dist/components/separator.d.ts +6 -0
- package/dist/components/separator.js +15 -0
- package/dist/components/sidebar.d.ts +65 -0
- package/dist/components/sidebar.js +408 -0
- package/dist/components/skeleton.d.ts +5 -0
- package/dist/components/skeleton.js +12 -0
- package/dist/components/slider.d.ts +12 -0
- package/dist/components/slider.js +96 -0
- package/dist/components/sortable.d.ts +44 -0
- package/dist/components/sortable.js +327 -0
- package/dist/components/switch.d.ts +15 -0
- package/dist/components/switch.js +63 -0
- package/dist/components/table.d.ts +12 -0
- package/dist/components/table.js +65 -0
- package/dist/components/tabs.d.ts +12 -0
- package/dist/components/tabs.js +39 -0
- package/dist/components/text.d.ts +14 -0
- package/dist/components/text.js +69 -0
- package/dist/components/textarea.d.ts +9 -0
- package/dist/components/textarea.js +20 -0
- package/dist/components/theme-provider.d.ts +52 -0
- package/dist/components/theme-provider.js +148 -0
- package/dist/components/timeline.d.ts +34 -0
- package/dist/components/timeline.js +147 -0
- package/dist/components/toast.d.ts +17 -0
- package/dist/components/toast.js +161 -0
- package/dist/components/toggle-group.d.ts +14 -0
- package/dist/components/toggle-group.js +53 -0
- package/dist/components/toggle.d.ts +11 -0
- package/dist/components/toggle.js +36 -0
- package/dist/components/toolbar.d.ts +11 -0
- package/dist/components/toolbar.js +49 -0
- package/dist/components/tooltip.d.ts +17 -0
- package/dist/components/tooltip.js +56 -0
- package/dist/components/waveform.d.ts +61 -0
- package/dist/components/waveform.js +500 -0
- package/dist/components/wheel-picker.d.ts +44 -0
- package/dist/components/wheel-picker.js +771 -0
- package/dist/hooks/use-copy-to-clipboard.d.ts +9 -0
- package/dist/hooks/use-copy-to-clipboard.js +36 -0
- package/dist/hooks/use-media-query.d.ts +21 -0
- package/dist/hooks/use-media-query.js +58 -0
- package/dist/styles.css +202 -0
- package/dist/themes/afterglow.css +89 -0
- package/dist/themes/afterglow.scoped.css +90 -0
- package/dist/themes/blacklight.css +89 -0
- package/dist/themes/blacklight.scoped.css +90 -0
- package/dist/themes/cathode.css +89 -0
- package/dist/themes/cathode.scoped.css +90 -0
- package/dist/themes/cel.css +89 -0
- package/dist/themes/cel.scoped.css +90 -0
- package/dist/themes/cinder.css +89 -0
- package/dist/themes/cinder.scoped.css +90 -0
- package/dist/themes/clay.css +89 -0
- package/dist/themes/clay.scoped.css +90 -0
- package/dist/themes/cobalt.css +89 -0
- package/dist/themes/cobalt.scoped.css +90 -0
- package/dist/themes/crimson.css +89 -0
- package/dist/themes/crimson.scoped.css +90 -0
- package/dist/themes/ion.css +89 -0
- package/dist/themes/ion.scoped.css +90 -0
- package/dist/themes/iris.css +89 -0
- package/dist/themes/iris.scoped.css +90 -0
- package/dist/themes/lagoon.css +89 -0
- package/dist/themes/lagoon.scoped.css +90 -0
- package/dist/themes/mochi.css +89 -0
- package/dist/themes/mochi.scoped.css +90 -0
- package/dist/themes/riso.css +89 -0
- package/dist/themes/riso.scoped.css +90 -0
- package/dist/themes/roast.css +89 -0
- package/dist/themes/roast.scoped.css +90 -0
- package/dist/themes/sage.css +89 -0
- package/dist/themes/sage.scoped.css +90 -0
- package/dist/themes/sepia.css +89 -0
- package/dist/themes/sepia.scoped.css +90 -0
- package/dist/themes/sorbet.css +89 -0
- package/dist/themes/sorbet.scoped.css +90 -0
- package/dist/themes/taffy.css +89 -0
- package/dist/themes/taffy.scoped.css +90 -0
- package/dist/themes/toxin.css +89 -0
- package/dist/themes/toxin.scoped.css +90 -0
- package/package.json +140 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "cn";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import * as React$1 from "react";
|
|
6
|
+
import { Cancel } from "xiod-icons/icons/Cancel";
|
|
7
|
+
import { mergeProps } from "@base-ui/react/merge-props";
|
|
8
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
9
|
+
import { GripVertical } from "xiod-icons/icons/GripVertical";
|
|
10
|
+
//#region src/components/dashboard-grid.tsx
|
|
11
|
+
const defaultBreakpoints = {
|
|
12
|
+
lg: 1200,
|
|
13
|
+
md: 996,
|
|
14
|
+
sm: 768,
|
|
15
|
+
xs: 480,
|
|
16
|
+
xxs: 0
|
|
17
|
+
};
|
|
18
|
+
const defaultCols = {
|
|
19
|
+
lg: 12,
|
|
20
|
+
md: 10,
|
|
21
|
+
sm: 6,
|
|
22
|
+
xs: 4,
|
|
23
|
+
xxs: 2
|
|
24
|
+
};
|
|
25
|
+
const dashboardGridVariants = cva("relative w-full overflow-hidden select-none transition-colors duration-200 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
26
|
+
variants: { variant: {
|
|
27
|
+
default: "bg-background/40 border border-border/40 rounded-xl p-3 backdrop-blur-xs",
|
|
28
|
+
ghost: "bg-transparent border-0 p-0",
|
|
29
|
+
bordered: "bg-card border border-border rounded-2xl p-4 shadow-xs/5",
|
|
30
|
+
canvas: "bg-muted/10 border border-border/60 rounded-2xl p-4 shadow-inner"
|
|
31
|
+
} },
|
|
32
|
+
defaultVariants: { variant: "default" }
|
|
33
|
+
});
|
|
34
|
+
const dashboardTileVariants = cva("absolute flex flex-col rounded-xl border bg-card text-card-foreground shadow-xs/5 transition-[transform,width,height,opacity,border-color,box-shadow] duration-150 group overflow-hidden touch-none", {
|
|
35
|
+
variants: {
|
|
36
|
+
variant: {
|
|
37
|
+
default: "border-border/80 bg-card hover:border-foreground/20 shadow-xs/5",
|
|
38
|
+
expressive: "border-primary/30 bg-card/95 shadow-primary/5 hover:border-primary/50",
|
|
39
|
+
flat: "border-border/40 bg-muted/30 shadow-none"
|
|
40
|
+
},
|
|
41
|
+
isDragging: {
|
|
42
|
+
true: "z-30 shadow-2xl/25 opacity-90 scale-[1.01] border-primary transition-none cursor-grabbing ring-2 ring-primary/20",
|
|
43
|
+
false: ""
|
|
44
|
+
},
|
|
45
|
+
isResizing: {
|
|
46
|
+
true: "z-30 shadow-xl/20 opacity-95 border-primary transition-none ring-2 ring-primary/20",
|
|
47
|
+
false: ""
|
|
48
|
+
},
|
|
49
|
+
isStatic: {
|
|
50
|
+
true: "border-dashed border-border/60 bg-muted/20 opacity-80 cursor-default",
|
|
51
|
+
false: ""
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
defaultVariants: {
|
|
55
|
+
variant: "default",
|
|
56
|
+
isDragging: false,
|
|
57
|
+
isResizing: false,
|
|
58
|
+
isStatic: false
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
function collides(l1, l2) {
|
|
62
|
+
if (l1.i === l2.i) return false;
|
|
63
|
+
if (l1.x + l1.w <= l2.x) return false;
|
|
64
|
+
if (l1.x >= l2.x + l2.w) return false;
|
|
65
|
+
if (l1.y + l1.h <= l2.y) return false;
|
|
66
|
+
if (l1.y >= l2.y + l2.h) return false;
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
function getFirstCollision(layout, item) {
|
|
70
|
+
return layout.find((other) => collides(other, item));
|
|
71
|
+
}
|
|
72
|
+
function sortLayout(layout, compactType) {
|
|
73
|
+
return layout.toSorted((a, b) => {
|
|
74
|
+
if (compactType === "horizontal") {
|
|
75
|
+
if (a.x > b.x || a.x === b.x && a.y > b.y) return 1;
|
|
76
|
+
return -1;
|
|
77
|
+
}
|
|
78
|
+
if (a.y > b.y || a.y === b.y && a.x > b.x) return 1;
|
|
79
|
+
return -1;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function compactItem(compareWith, l, compactType, cols) {
|
|
83
|
+
const item = { ...l };
|
|
84
|
+
if (compactType === "vertical") {
|
|
85
|
+
item.y = Math.min(item.y, Math.max(0, ...compareWith.map((c) => c.y + c.h)));
|
|
86
|
+
while (item.y > 0 && !getFirstCollision(compareWith, item)) item.y--;
|
|
87
|
+
let collision = getFirstCollision(compareWith, item);
|
|
88
|
+
while (collision) {
|
|
89
|
+
item.y = collision.y + collision.h;
|
|
90
|
+
collision = getFirstCollision(compareWith, item);
|
|
91
|
+
}
|
|
92
|
+
} else if (compactType === "horizontal") {
|
|
93
|
+
while (item.x > 0 && !getFirstCollision(compareWith, item)) item.x--;
|
|
94
|
+
let collision = getFirstCollision(compareWith, item);
|
|
95
|
+
while (collision) {
|
|
96
|
+
item.x = collision.x + collision.w;
|
|
97
|
+
collision = getFirstCollision(compareWith, item);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
item.x = Math.max(0, Math.min(cols - item.w, item.x));
|
|
101
|
+
item.y = Math.max(0, item.y);
|
|
102
|
+
return item;
|
|
103
|
+
}
|
|
104
|
+
function compactLayout(layout, compactType, cols) {
|
|
105
|
+
const compareWith = [];
|
|
106
|
+
const sorted = sortLayout(layout, compactType);
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const item of sorted) {
|
|
109
|
+
let compacted = { ...item };
|
|
110
|
+
if (!compacted.static && compactType) compacted = compactItem(compareWith, compacted, compactType, cols);
|
|
111
|
+
compareWith.push(compacted);
|
|
112
|
+
out.push(compacted);
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
function moveElement(layout, item, x, y, preventCollision, cols, compactType) {
|
|
117
|
+
if (item.static) return layout;
|
|
118
|
+
const nx = Math.max(0, Math.min(cols - item.w, x));
|
|
119
|
+
const ny = Math.max(0, y);
|
|
120
|
+
const movedItem = {
|
|
121
|
+
...item,
|
|
122
|
+
x: nx,
|
|
123
|
+
y: ny
|
|
124
|
+
};
|
|
125
|
+
if (preventCollision) {
|
|
126
|
+
if (getFirstCollision(layout.filter((l) => l.i !== item.i), movedItem)) return layout;
|
|
127
|
+
}
|
|
128
|
+
return compactLayout(layout.map((l) => l.i === item.i ? movedItem : { ...l }), compactType, cols);
|
|
129
|
+
}
|
|
130
|
+
function getColsForWidth(width, breakpoints = defaultBreakpoints, cols = defaultCols) {
|
|
131
|
+
if (typeof cols === "number") return cols;
|
|
132
|
+
const mergedBreakpoints = {
|
|
133
|
+
...defaultBreakpoints,
|
|
134
|
+
...breakpoints
|
|
135
|
+
};
|
|
136
|
+
const mergedCols = {
|
|
137
|
+
...defaultCols,
|
|
138
|
+
...cols
|
|
139
|
+
};
|
|
140
|
+
if (width >= mergedBreakpoints.lg) return mergedCols.lg;
|
|
141
|
+
if (width >= mergedBreakpoints.md) return mergedCols.md;
|
|
142
|
+
if (width >= mergedBreakpoints.sm) return mergedCols.sm;
|
|
143
|
+
if (width >= mergedBreakpoints.xs) return mergedCols.xs;
|
|
144
|
+
return mergedCols.xxs;
|
|
145
|
+
}
|
|
146
|
+
const DashboardGridContext = React$1.createContext(null);
|
|
147
|
+
const DEFAULT_GRID_MARGIN = [12, 12];
|
|
148
|
+
const DEFAULT_CONTAINER_PADDING = [12, 12];
|
|
149
|
+
function DashboardGrid({ className, variant, layout: externalLayout, cols: colsProp = 12, breakpoints = defaultBreakpoints, rowHeight = 60, margin = DEFAULT_GRID_MARGIN, containerPadding = DEFAULT_CONTAINER_PADDING, compactType = "vertical", preventCollision = false, isDraggable = true, isResizable = true, showGridLines = false, onLayoutChange, onTileRemove, render, children, ...props }) {
|
|
150
|
+
const containerRef = React$1.useRef(null);
|
|
151
|
+
const [containerWidth, setContainerWidth] = React$1.useState(0);
|
|
152
|
+
const currentCols = React$1.useMemo(() => {
|
|
153
|
+
return getColsForWidth(containerWidth || 1200, breakpoints, colsProp);
|
|
154
|
+
}, [
|
|
155
|
+
containerWidth,
|
|
156
|
+
breakpoints,
|
|
157
|
+
colsProp
|
|
158
|
+
]);
|
|
159
|
+
const [layout, setLayout] = React$1.useState(() => compactLayout(externalLayout, compactType, currentCols));
|
|
160
|
+
const [dragItem, setDragItem] = React$1.useState(null);
|
|
161
|
+
const [resizeItem, setResizeItem] = React$1.useState(null);
|
|
162
|
+
const layoutRef = React$1.useRef(layout);
|
|
163
|
+
const currentColsRef = React$1.useRef(currentCols);
|
|
164
|
+
const compactTypeRef = React$1.useRef(compactType);
|
|
165
|
+
const preventCollisionRef = React$1.useRef(preventCollision);
|
|
166
|
+
const onLayoutChangeRef = React$1.useRef(onLayoutChange);
|
|
167
|
+
React$1.useEffect(() => {
|
|
168
|
+
layoutRef.current = layout;
|
|
169
|
+
currentColsRef.current = currentCols;
|
|
170
|
+
compactTypeRef.current = compactType;
|
|
171
|
+
preventCollisionRef.current = preventCollision;
|
|
172
|
+
onLayoutChangeRef.current = onLayoutChange;
|
|
173
|
+
});
|
|
174
|
+
React$1.useEffect(() => {
|
|
175
|
+
setLayout(compactLayout(externalLayout, compactType, currentCols));
|
|
176
|
+
}, [
|
|
177
|
+
externalLayout,
|
|
178
|
+
compactType,
|
|
179
|
+
currentCols
|
|
180
|
+
]);
|
|
181
|
+
React$1.useEffect(() => {
|
|
182
|
+
const el = containerRef.current;
|
|
183
|
+
if (!el) return;
|
|
184
|
+
const observer = new ResizeObserver((entries) => {
|
|
185
|
+
for (const entry of entries) setContainerWidth(entry.contentRect.width);
|
|
186
|
+
});
|
|
187
|
+
observer.observe(el);
|
|
188
|
+
setContainerWidth(el.clientWidth);
|
|
189
|
+
return () => observer.disconnect();
|
|
190
|
+
}, []);
|
|
191
|
+
const colWidth = React$1.useMemo(() => {
|
|
192
|
+
if (!containerWidth) return 0;
|
|
193
|
+
const availableWidth = containerWidth - containerPadding[0] * 2 - margin[0] * (currentCols - 1);
|
|
194
|
+
return Math.max(10, availableWidth / currentCols);
|
|
195
|
+
}, [
|
|
196
|
+
containerWidth,
|
|
197
|
+
containerPadding,
|
|
198
|
+
margin,
|
|
199
|
+
currentCols
|
|
200
|
+
]);
|
|
201
|
+
const maxRows = React$1.useMemo(() => {
|
|
202
|
+
return Math.max(4, ...layout.map((item) => item.y + item.h));
|
|
203
|
+
}, [layout]);
|
|
204
|
+
const containerHeight = React$1.useMemo(() => {
|
|
205
|
+
return maxRows * rowHeight + (maxRows - 1) * margin[1] + containerPadding[1] * 2;
|
|
206
|
+
}, [
|
|
207
|
+
maxRows,
|
|
208
|
+
rowHeight,
|
|
209
|
+
margin,
|
|
210
|
+
containerPadding
|
|
211
|
+
]);
|
|
212
|
+
const handlePointerStart = React$1.useCallback((id, mode, e) => {
|
|
213
|
+
const targetItem = layoutRef.current.find((l) => l.i === id);
|
|
214
|
+
if (!targetItem || targetItem.static) return;
|
|
215
|
+
e.preventDefault();
|
|
216
|
+
e.stopPropagation();
|
|
217
|
+
const startX = e.clientX;
|
|
218
|
+
const startY = e.clientY;
|
|
219
|
+
const initialItem = { ...targetItem };
|
|
220
|
+
if (mode === "drag") setDragItem(initialItem);
|
|
221
|
+
else setResizeItem(initialItem);
|
|
222
|
+
const onPointerMove = (moveEvent) => {
|
|
223
|
+
const deltaX = moveEvent.clientX - startX;
|
|
224
|
+
const deltaY = moveEvent.clientY - startY;
|
|
225
|
+
const activeCols = currentColsRef.current;
|
|
226
|
+
const activeCompactType = compactTypeRef.current;
|
|
227
|
+
const activePreventCollision = preventCollisionRef.current;
|
|
228
|
+
if (mode === "drag") {
|
|
229
|
+
const gridDeltaX = Math.round(deltaX / (colWidth + margin[0]));
|
|
230
|
+
const gridDeltaY = Math.round(deltaY / (rowHeight + margin[1]));
|
|
231
|
+
const newX = initialItem.x + gridDeltaX;
|
|
232
|
+
const newY = initialItem.y + gridDeltaY;
|
|
233
|
+
setLayout((prev) => {
|
|
234
|
+
const next = moveElement(prev, initialItem, newX, newY, activePreventCollision, activeCols, activeCompactType);
|
|
235
|
+
const active = next.find((item) => item.i === id);
|
|
236
|
+
if (active) setDragItem(active);
|
|
237
|
+
return next;
|
|
238
|
+
});
|
|
239
|
+
} else {
|
|
240
|
+
const gridDeltaW = Math.round(deltaX / (colWidth + margin[0]));
|
|
241
|
+
const gridDeltaH = Math.round(deltaY / (rowHeight + margin[1]));
|
|
242
|
+
const minW = initialItem.minW ?? 1;
|
|
243
|
+
const maxW = initialItem.maxW ?? activeCols;
|
|
244
|
+
const minH = initialItem.minH ?? 1;
|
|
245
|
+
const maxH = initialItem.maxH ?? 20;
|
|
246
|
+
const newW = Math.max(minW, Math.min(maxW, Math.min(activeCols - initialItem.x, initialItem.w + gridDeltaW)));
|
|
247
|
+
const newH = Math.max(minH, Math.min(maxH, initialItem.h + gridDeltaH));
|
|
248
|
+
setLayout((prev) => {
|
|
249
|
+
const updatedItem = {
|
|
250
|
+
...initialItem,
|
|
251
|
+
w: newW,
|
|
252
|
+
h: newH
|
|
253
|
+
};
|
|
254
|
+
const next = compactLayout(prev.map((item) => item.i === id ? updatedItem : item), activeCompactType, activeCols);
|
|
255
|
+
const active = next.find((item) => item.i === id);
|
|
256
|
+
if (active) setResizeItem(active);
|
|
257
|
+
return next;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
const onPointerUp = () => {
|
|
262
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
263
|
+
window.removeEventListener("pointerup", onPointerUp);
|
|
264
|
+
setDragItem(null);
|
|
265
|
+
setResizeItem(null);
|
|
266
|
+
setLayout((finalLayout) => {
|
|
267
|
+
const compacted = compactLayout(finalLayout, compactTypeRef.current, currentColsRef.current);
|
|
268
|
+
queueMicrotask(() => {
|
|
269
|
+
onLayoutChangeRef.current?.(compacted);
|
|
270
|
+
});
|
|
271
|
+
return compacted;
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
window.addEventListener("pointermove", onPointerMove);
|
|
275
|
+
window.addEventListener("pointerup", onPointerUp);
|
|
276
|
+
}, [
|
|
277
|
+
colWidth,
|
|
278
|
+
margin,
|
|
279
|
+
rowHeight
|
|
280
|
+
]);
|
|
281
|
+
const handleTileDragStart = React$1.useCallback((id, e) => handlePointerStart(id, "drag", e), [handlePointerStart]);
|
|
282
|
+
const handleTileResizeStart = React$1.useCallback((id, e) => handlePointerStart(id, "resize", e), [handlePointerStart]);
|
|
283
|
+
const contextValue = React$1.useMemo(() => ({
|
|
284
|
+
cols: currentCols,
|
|
285
|
+
rowHeight,
|
|
286
|
+
margin,
|
|
287
|
+
containerPadding,
|
|
288
|
+
layout,
|
|
289
|
+
dragItem,
|
|
290
|
+
resizeItem,
|
|
291
|
+
isDraggable,
|
|
292
|
+
isResizable,
|
|
293
|
+
onTileDragStart: handleTileDragStart,
|
|
294
|
+
onTileResizeStart: handleTileResizeStart,
|
|
295
|
+
onTileRemove
|
|
296
|
+
}), [
|
|
297
|
+
currentCols,
|
|
298
|
+
rowHeight,
|
|
299
|
+
margin,
|
|
300
|
+
containerPadding,
|
|
301
|
+
layout,
|
|
302
|
+
dragItem,
|
|
303
|
+
resizeItem,
|
|
304
|
+
isDraggable,
|
|
305
|
+
isResizable,
|
|
306
|
+
handleTileDragStart,
|
|
307
|
+
handleTileResizeStart,
|
|
308
|
+
onTileRemove
|
|
309
|
+
]);
|
|
310
|
+
const activeGhost = dragItem || resizeItem;
|
|
311
|
+
const defaultProps = {
|
|
312
|
+
ref: containerRef,
|
|
313
|
+
className: cn(dashboardGridVariants({
|
|
314
|
+
variant,
|
|
315
|
+
className
|
|
316
|
+
})),
|
|
317
|
+
style: { height: containerHeight },
|
|
318
|
+
"data-slot": "dashboard-grid",
|
|
319
|
+
children: /* @__PURE__ */ jsxs(DashboardGridContext.Provider, {
|
|
320
|
+
value: contextValue,
|
|
321
|
+
children: [
|
|
322
|
+
showGridLines && /* @__PURE__ */ jsx("div", {
|
|
323
|
+
className: "absolute inset-0 pointer-events-none opacity-20 bg-[linear-gradient(to_right,var(--border)_1px,transparent_1px),linear-gradient(to_bottom,var(--border)_1px,transparent_1px)]",
|
|
324
|
+
style: {
|
|
325
|
+
backgroundSize: `${colWidth + margin[0]}px ${rowHeight + margin[1]}px`,
|
|
326
|
+
backgroundPosition: `${containerPadding[0]}px ${containerPadding[1]}px`
|
|
327
|
+
}
|
|
328
|
+
}),
|
|
329
|
+
children,
|
|
330
|
+
activeGhost && /* @__PURE__ */ jsx("div", {
|
|
331
|
+
className: "absolute rounded-xl border-2 border-dashed border-primary bg-primary/10 transition-[left,top,width,height] duration-75 pointer-events-none z-10",
|
|
332
|
+
"data-slot": "dashboard-grid-placeholder",
|
|
333
|
+
style: {
|
|
334
|
+
left: containerPadding[0] + activeGhost.x * (colWidth + margin[0]),
|
|
335
|
+
top: containerPadding[1] + activeGhost.y * (rowHeight + margin[1]),
|
|
336
|
+
width: activeGhost.w * colWidth + (activeGhost.w - 1) * margin[0],
|
|
337
|
+
height: activeGhost.h * rowHeight + (activeGhost.h - 1) * margin[1]
|
|
338
|
+
}
|
|
339
|
+
})
|
|
340
|
+
]
|
|
341
|
+
})
|
|
342
|
+
};
|
|
343
|
+
return useRender({
|
|
344
|
+
defaultTagName: "div",
|
|
345
|
+
props: mergeProps(defaultProps, props),
|
|
346
|
+
render
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
function DashboardTile({ className, variant, id, render, children, ...props }) {
|
|
350
|
+
const context = React$1.useContext(DashboardGridContext);
|
|
351
|
+
const tileData = context?.layout.find((item) => item.i === id);
|
|
352
|
+
const isDragging = context?.dragItem?.i === id;
|
|
353
|
+
const isResizing = context?.resizeItem?.i === id;
|
|
354
|
+
const top = context && tileData ? context.containerPadding[1] + tileData.y * (context.rowHeight + context.margin[1]) : 0;
|
|
355
|
+
const defaultProps = {
|
|
356
|
+
className: cn(dashboardTileVariants({
|
|
357
|
+
variant,
|
|
358
|
+
isDragging,
|
|
359
|
+
isResizing,
|
|
360
|
+
isStatic: tileData?.static,
|
|
361
|
+
className
|
|
362
|
+
})),
|
|
363
|
+
style: context && tileData ? {
|
|
364
|
+
transform: `translate3d(${tileData.x * 100}%, ${top}px, 0)`,
|
|
365
|
+
width: `calc(${tileData.w * (100 / context.cols)}% - ${context.margin[0]}px)`,
|
|
366
|
+
height: tileData.h * context.rowHeight + (tileData.h - 1) * context.margin[1]
|
|
367
|
+
} : void 0,
|
|
368
|
+
"data-slot": "dashboard-tile",
|
|
369
|
+
"data-tile-id": id,
|
|
370
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [children, context?.isResizable && !tileData?.static && /* @__PURE__ */ jsx(DashboardTileResizeHandle, { onPointerDown: (e) => context?.onTileResizeStart(id, e) })] })
|
|
371
|
+
};
|
|
372
|
+
const renderedElement = useRender({
|
|
373
|
+
defaultTagName: "div",
|
|
374
|
+
props: mergeProps(defaultProps, props),
|
|
375
|
+
render
|
|
376
|
+
});
|
|
377
|
+
if (!context || !tileData) return null;
|
|
378
|
+
return renderedElement;
|
|
379
|
+
}
|
|
380
|
+
function DashboardTileHeader({ className, id, render, children, ...props }) {
|
|
381
|
+
const context = React$1.useContext(DashboardGridContext);
|
|
382
|
+
const handlePointerDown = React$1.useCallback((e) => {
|
|
383
|
+
if (id && context?.isDraggable) context.onTileDragStart(id, e);
|
|
384
|
+
}, [id, context]);
|
|
385
|
+
const defaultProps = {
|
|
386
|
+
className: cn("flex items-center justify-between gap-2 px-3 py-2 border-b border-border/40 bg-muted/30 cursor-grab active:cursor-grabbing select-none text-xs font-medium text-foreground shrink-0", className),
|
|
387
|
+
onPointerDown: handlePointerDown,
|
|
388
|
+
"data-slot": "dashboard-tile-header",
|
|
389
|
+
children: children || /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
390
|
+
className: "flex items-center gap-1.5 truncate",
|
|
391
|
+
children: [/* @__PURE__ */ jsx(GripVertical, { className: "size-3.5 text-muted-foreground/60 shrink-0" }), /* @__PURE__ */ jsx(DashboardTileTitle, {})]
|
|
392
|
+
}), /* @__PURE__ */ jsx(DashboardTileControls, { id })] })
|
|
393
|
+
};
|
|
394
|
+
return useRender({
|
|
395
|
+
defaultTagName: "div",
|
|
396
|
+
props: mergeProps(defaultProps, props),
|
|
397
|
+
render
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function DashboardTileTitle({ className, render, children, ...props }) {
|
|
401
|
+
const defaultProps = {
|
|
402
|
+
className: cn("font-semibold truncate text-xs text-foreground", className),
|
|
403
|
+
"data-slot": "dashboard-tile-title",
|
|
404
|
+
children: children || "Widget Tile"
|
|
405
|
+
};
|
|
406
|
+
return useRender({
|
|
407
|
+
defaultTagName: "span",
|
|
408
|
+
props: mergeProps(defaultProps, props),
|
|
409
|
+
render
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
function DashboardTileControls({ className, id, render, children, ...props }) {
|
|
413
|
+
const context = React$1.useContext(DashboardGridContext);
|
|
414
|
+
const defaultProps = {
|
|
415
|
+
className: cn("flex items-center gap-1 shrink-0", className),
|
|
416
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
417
|
+
"data-slot": "dashboard-tile-controls",
|
|
418
|
+
children: children || id && context?.onTileRemove && /* @__PURE__ */ jsx("button", {
|
|
419
|
+
type: "button",
|
|
420
|
+
onClick: () => context.onTileRemove?.(id),
|
|
421
|
+
className: "p-1 rounded text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors pointer-coarse:after:absolute pointer-coarse:after:size-11",
|
|
422
|
+
"aria-label": "Remove Widget",
|
|
423
|
+
children: /* @__PURE__ */ jsx(Cancel, { className: "size-3" })
|
|
424
|
+
})
|
|
425
|
+
};
|
|
426
|
+
return useRender({
|
|
427
|
+
defaultTagName: "div",
|
|
428
|
+
props: mergeProps(defaultProps, props),
|
|
429
|
+
render
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
function DashboardTileHandle({ className, id, render, ...props }) {
|
|
433
|
+
const context = React$1.useContext(DashboardGridContext);
|
|
434
|
+
const handlePointerDown = React$1.useCallback((e) => {
|
|
435
|
+
if (id && context?.isDraggable) context.onTileDragStart(id, e);
|
|
436
|
+
}, [id, context]);
|
|
437
|
+
const defaultProps = {
|
|
438
|
+
className: cn("flex items-center gap-1.5 px-2.5 py-1.5 rounded-md border border-border/40 bg-muted/40 cursor-grab active:cursor-grabbing select-none text-xs font-medium text-muted-foreground hover:text-foreground", className),
|
|
439
|
+
onPointerDown: handlePointerDown,
|
|
440
|
+
"data-slot": "dashboard-tile-handle",
|
|
441
|
+
children: /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(GripVertical, { className: "size-3.5 opacity-60 shrink-0" }), /* @__PURE__ */ jsx("span", {
|
|
442
|
+
className: "truncate flex-1",
|
|
443
|
+
children: "Drag Handle"
|
|
444
|
+
})] })
|
|
445
|
+
};
|
|
446
|
+
return useRender({
|
|
447
|
+
defaultTagName: "div",
|
|
448
|
+
props: mergeProps(defaultProps, props),
|
|
449
|
+
render
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
function DashboardTileResizeHandle({ className, render, ...props }) {
|
|
453
|
+
const defaultProps = {
|
|
454
|
+
className: cn("absolute bottom-1 right-1 size-4 cursor-se-resize flex items-center justify-center opacity-40 hover:opacity-100 transition-opacity touch-none pointer-coarse:after:absolute pointer-coarse:after:size-8", className),
|
|
455
|
+
"data-slot": "dashboard-tile-resize-handle",
|
|
456
|
+
children: /* @__PURE__ */ jsxs("svg", {
|
|
457
|
+
className: "size-3 text-muted-foreground",
|
|
458
|
+
viewBox: "0 0 6 6",
|
|
459
|
+
fill: "currentColor",
|
|
460
|
+
children: [
|
|
461
|
+
/* @__PURE__ */ jsx("circle", {
|
|
462
|
+
cx: "5",
|
|
463
|
+
cy: "5",
|
|
464
|
+
r: "1"
|
|
465
|
+
}),
|
|
466
|
+
/* @__PURE__ */ jsx("circle", {
|
|
467
|
+
cx: "5",
|
|
468
|
+
cy: "2",
|
|
469
|
+
r: "1"
|
|
470
|
+
}),
|
|
471
|
+
/* @__PURE__ */ jsx("circle", {
|
|
472
|
+
cx: "2",
|
|
473
|
+
cy: "5",
|
|
474
|
+
r: "1"
|
|
475
|
+
})
|
|
476
|
+
]
|
|
477
|
+
})
|
|
478
|
+
};
|
|
479
|
+
return useRender({
|
|
480
|
+
defaultTagName: "div",
|
|
481
|
+
props: mergeProps(defaultProps, props),
|
|
482
|
+
render
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
//#endregion
|
|
486
|
+
export { DashboardGrid, DashboardTile, DashboardTileControls, DashboardTileHandle, DashboardTileHeader, DashboardTileResizeHandle, DashboardTileTitle, compactLayout, dashboardGridVariants, dashboardTileVariants, defaultBreakpoints, defaultCols };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { DateRange } from "./calendar.js";
|
|
2
|
+
import * as React$1 from "react";
|
|
3
|
+
//#region src/components/date-picker.d.ts
|
|
4
|
+
export interface DatePickerProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "onSelect" | "defaultValue"> {
|
|
5
|
+
mode?: "single" | "range";
|
|
6
|
+
triggerType?: "button" | "input";
|
|
7
|
+
defaultValue?: Date | DateRange;
|
|
8
|
+
value?: Date | DateRange;
|
|
9
|
+
onSelect?: (value: Date | DateRange | undefined) => void;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
formatStr?: "PPP" | "LLL dd, y" | "yyyy-MM-dd";
|
|
12
|
+
minDate?: Date;
|
|
13
|
+
maxDate?: Date;
|
|
14
|
+
disabled?: boolean | Date | Date[] | ((date: Date) => boolean);
|
|
15
|
+
numberOfMonths?: number;
|
|
16
|
+
fixedWeeks?: boolean;
|
|
17
|
+
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
18
|
+
showOutsideDays?: boolean;
|
|
19
|
+
disableOutsideDays?: boolean;
|
|
20
|
+
triggerClassName?: string;
|
|
21
|
+
triggerVariant?: "default" | "outline" | "ghost" | "secondary";
|
|
22
|
+
triggerSize?: "default" | "sm" | "lg" | "xs";
|
|
23
|
+
}
|
|
24
|
+
declare function DatePicker({ className, mode, triggerType, defaultValue, value, onSelect, placeholder, formatStr, minDate, maxDate, disabled, numberOfMonths, fixedWeeks, weekStartsOn, showOutsideDays, disableOutsideDays, triggerClassName, triggerVariant, triggerSize, ...props }: DatePickerProps): React$1.JSX.Element;
|
|
25
|
+
declare namespace DatePicker {
|
|
26
|
+
var displayName: string;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { DatePicker };
|