@classic-homes/theme-react 0.1.50 → 0.1.52
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.css +141 -0
- package/dist/index.d.mts +134 -7
- package/dist/index.d.ts +134 -7
- package/dist/index.js +1007 -46
- package/dist/index.mjs +1022 -45
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -110,21 +110,91 @@ var Input = React3.forwardRef(
|
|
|
110
110
|
);
|
|
111
111
|
Input.displayName = "Input";
|
|
112
112
|
|
|
113
|
-
// src/components/
|
|
113
|
+
// src/components/PasswordInput.tsx
|
|
114
114
|
import * as React4 from "react";
|
|
115
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
116
|
+
var EyeIcon = () => /* @__PURE__ */ jsxs(
|
|
117
|
+
"svg",
|
|
118
|
+
{
|
|
119
|
+
width: 18,
|
|
120
|
+
height: 18,
|
|
121
|
+
viewBox: "0 0 24 24",
|
|
122
|
+
fill: "none",
|
|
123
|
+
stroke: "currentColor",
|
|
124
|
+
strokeWidth: 2,
|
|
125
|
+
strokeLinecap: "round",
|
|
126
|
+
strokeLinejoin: "round",
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsx4("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
|
|
129
|
+
/* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "3" })
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
var EyeOffIcon = () => /* @__PURE__ */ jsx4(
|
|
134
|
+
"svg",
|
|
135
|
+
{
|
|
136
|
+
width: 18,
|
|
137
|
+
height: 18,
|
|
138
|
+
viewBox: "0 0 24 24",
|
|
139
|
+
fill: "none",
|
|
140
|
+
stroke: "currentColor",
|
|
141
|
+
strokeWidth: 2,
|
|
142
|
+
strokeLinecap: "round",
|
|
143
|
+
strokeLinejoin: "round",
|
|
144
|
+
children: /* @__PURE__ */ jsx4("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24M1 1l22 22" })
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
var PasswordInput = React4.forwardRef(
|
|
148
|
+
({ className, disabled, showLabel = "Show password", hideLabel = "Hide password", ...props }, ref) => {
|
|
149
|
+
const [showPassword, setShowPassword] = React4.useState(false);
|
|
150
|
+
const toggleVisibility = () => {
|
|
151
|
+
setShowPassword((prev) => !prev);
|
|
152
|
+
};
|
|
153
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
154
|
+
/* @__PURE__ */ jsx4(
|
|
155
|
+
"input",
|
|
156
|
+
{
|
|
157
|
+
type: showPassword ? "text" : "password",
|
|
158
|
+
className: cn(
|
|
159
|
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 pr-10 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
160
|
+
className
|
|
161
|
+
),
|
|
162
|
+
disabled,
|
|
163
|
+
ref,
|
|
164
|
+
...props
|
|
165
|
+
}
|
|
166
|
+
),
|
|
167
|
+
/* @__PURE__ */ jsx4(
|
|
168
|
+
"button",
|
|
169
|
+
{
|
|
170
|
+
type: "button",
|
|
171
|
+
className: "absolute right-0 top-0 h-10 w-10 flex items-center justify-center text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-r-md disabled:pointer-events-none disabled:opacity-50",
|
|
172
|
+
onClick: toggleVisibility,
|
|
173
|
+
disabled,
|
|
174
|
+
"aria-label": showPassword ? hideLabel : showLabel,
|
|
175
|
+
children: showPassword ? /* @__PURE__ */ jsx4(EyeOffIcon, {}) : /* @__PURE__ */ jsx4(EyeIcon, {})
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
] });
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
PasswordInput.displayName = "PasswordInput";
|
|
182
|
+
|
|
183
|
+
// src/components/Label.tsx
|
|
184
|
+
import * as React5 from "react";
|
|
115
185
|
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
116
186
|
import { cva as cva2 } from "class-variance-authority";
|
|
117
|
-
import { jsx as
|
|
187
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
118
188
|
var labelVariants = cva2(
|
|
119
189
|
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
120
190
|
);
|
|
121
|
-
var Label =
|
|
191
|
+
var Label = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(LabelPrimitive.Root, { ref, className: cn(labelVariants(), className), ...props }));
|
|
122
192
|
Label.displayName = LabelPrimitive.Root.displayName;
|
|
123
193
|
|
|
124
194
|
// src/components/Badge.tsx
|
|
125
|
-
import * as
|
|
195
|
+
import * as React6 from "react";
|
|
126
196
|
import { cva as cva3 } from "class-variance-authority";
|
|
127
|
-
import { jsx as
|
|
197
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
128
198
|
var badgeVariants = cva3(
|
|
129
199
|
"inline-flex items-center rounded-full border border-border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
130
200
|
{
|
|
@@ -141,9 +211,9 @@ var badgeVariants = cva3(
|
|
|
141
211
|
}
|
|
142
212
|
}
|
|
143
213
|
);
|
|
144
|
-
var Badge =
|
|
214
|
+
var Badge = React6.forwardRef(
|
|
145
215
|
({ className, variant, ...props }, ref) => {
|
|
146
|
-
return /* @__PURE__ */
|
|
216
|
+
return /* @__PURE__ */ jsx6(
|
|
147
217
|
"div",
|
|
148
218
|
{
|
|
149
219
|
ref,
|
|
@@ -157,10 +227,10 @@ var Badge = React5.forwardRef(
|
|
|
157
227
|
Badge.displayName = "Badge";
|
|
158
228
|
|
|
159
229
|
// src/components/Separator.tsx
|
|
160
|
-
import * as
|
|
230
|
+
import * as React7 from "react";
|
|
161
231
|
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
162
|
-
import { jsx as
|
|
163
|
-
var Separator =
|
|
232
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
233
|
+
var Separator = React7.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx7(
|
|
164
234
|
SeparatorPrimitive.Root,
|
|
165
235
|
{
|
|
166
236
|
ref,
|
|
@@ -177,12 +247,14 @@ var Separator = React6.forwardRef(({ className, orientation = "horizontal", deco
|
|
|
177
247
|
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
|
178
248
|
|
|
179
249
|
// src/components/Switch.tsx
|
|
180
|
-
import * as
|
|
250
|
+
import * as React8 from "react";
|
|
181
251
|
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
|
182
|
-
import { jsx as
|
|
183
|
-
var
|
|
184
|
-
|
|
185
|
-
|
|
252
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
253
|
+
var SwitchRoot = SwitchPrimitives.Root;
|
|
254
|
+
var SwitchThumb = SwitchPrimitives.Thumb;
|
|
255
|
+
var Switch = React8.forwardRef(
|
|
256
|
+
({ className, size = "default", ...props }, ref) => /* @__PURE__ */ jsx8(
|
|
257
|
+
SwitchRoot,
|
|
186
258
|
{
|
|
187
259
|
className: cn(
|
|
188
260
|
"peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
|
@@ -190,10 +262,10 @@ var Switch = React7.forwardRef(
|
|
|
190
262
|
size === "sm" && "h-5 w-9",
|
|
191
263
|
className
|
|
192
264
|
),
|
|
193
|
-
...props,
|
|
194
265
|
ref,
|
|
195
|
-
|
|
196
|
-
|
|
266
|
+
...props,
|
|
267
|
+
children: /* @__PURE__ */ jsx8(
|
|
268
|
+
SwitchThumb,
|
|
197
269
|
{
|
|
198
270
|
className: cn(
|
|
199
271
|
"pointer-events-none block rounded-full bg-background shadow-lg ring-0 transition-transform",
|
|
@@ -208,10 +280,10 @@ var Switch = React7.forwardRef(
|
|
|
208
280
|
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
209
281
|
|
|
210
282
|
// src/components/Avatar.tsx
|
|
211
|
-
import * as
|
|
283
|
+
import * as React9 from "react";
|
|
212
284
|
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
213
|
-
import { jsx as
|
|
214
|
-
var Avatar =
|
|
285
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
286
|
+
var Avatar = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
|
|
215
287
|
AvatarPrimitive.Root,
|
|
216
288
|
{
|
|
217
289
|
ref,
|
|
@@ -220,7 +292,7 @@ var Avatar = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
220
292
|
}
|
|
221
293
|
));
|
|
222
294
|
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
223
|
-
var AvatarImage =
|
|
295
|
+
var AvatarImage = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
|
|
224
296
|
AvatarPrimitive.Image,
|
|
225
297
|
{
|
|
226
298
|
ref,
|
|
@@ -229,7 +301,7 @@ var AvatarImage = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
229
301
|
}
|
|
230
302
|
));
|
|
231
303
|
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
232
|
-
var AvatarFallback =
|
|
304
|
+
var AvatarFallback = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
|
|
233
305
|
AvatarPrimitive.Fallback,
|
|
234
306
|
{
|
|
235
307
|
ref,
|
|
@@ -243,15 +315,19 @@ var AvatarFallback = React8.forwardRef(({ className, ...props }, ref) => /* @__P
|
|
|
243
315
|
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
244
316
|
|
|
245
317
|
// src/components/Dialog.tsx
|
|
246
|
-
import * as
|
|
318
|
+
import * as React10 from "react";
|
|
247
319
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
248
|
-
import { jsx as
|
|
320
|
+
import { jsx as jsx10, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
321
|
+
var PrimitiveOverlay = DialogPrimitive.Overlay;
|
|
322
|
+
var PrimitiveContent = DialogPrimitive.Content;
|
|
323
|
+
var PrimitiveTitle = DialogPrimitive.Title;
|
|
324
|
+
var PrimitiveDescription = DialogPrimitive.Description;
|
|
249
325
|
var Dialog = DialogPrimitive.Root;
|
|
250
326
|
var DialogTrigger = DialogPrimitive.Trigger;
|
|
251
327
|
var DialogPortal = DialogPrimitive.Portal;
|
|
252
328
|
var DialogClose = DialogPrimitive.Close;
|
|
253
|
-
var DialogOverlay =
|
|
254
|
-
|
|
329
|
+
var DialogOverlay = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
|
|
330
|
+
PrimitiveOverlay,
|
|
255
331
|
{
|
|
256
332
|
ref,
|
|
257
333
|
className: cn(
|
|
@@ -262,10 +338,10 @@ var DialogOverlay = React9.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
262
338
|
}
|
|
263
339
|
));
|
|
264
340
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
265
|
-
var DialogContent =
|
|
266
|
-
/* @__PURE__ */
|
|
267
|
-
/* @__PURE__ */
|
|
268
|
-
|
|
341
|
+
var DialogContent = React10.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs2(DialogPortal, { children: [
|
|
342
|
+
/* @__PURE__ */ jsx10(DialogOverlay, {}),
|
|
343
|
+
/* @__PURE__ */ jsx10(
|
|
344
|
+
PrimitiveContent,
|
|
269
345
|
{
|
|
270
346
|
ref,
|
|
271
347
|
className: cn(
|
|
@@ -278,9 +354,9 @@ var DialogContent = React9.forwardRef(({ className, children, ...props }, ref) =
|
|
|
278
354
|
)
|
|
279
355
|
] }));
|
|
280
356
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
281
|
-
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */
|
|
357
|
+
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx10("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
|
|
282
358
|
DialogHeader.displayName = "DialogHeader";
|
|
283
|
-
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */
|
|
359
|
+
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx10(
|
|
284
360
|
"div",
|
|
285
361
|
{
|
|
286
362
|
className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
|
|
@@ -288,8 +364,8 @@ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx9(
|
|
|
288
364
|
}
|
|
289
365
|
);
|
|
290
366
|
DialogFooter.displayName = "DialogFooter";
|
|
291
|
-
var DialogTitle =
|
|
292
|
-
|
|
367
|
+
var DialogTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
|
|
368
|
+
PrimitiveTitle,
|
|
293
369
|
{
|
|
294
370
|
ref,
|
|
295
371
|
className: cn("text-lg font-semibold leading-none tracking-tight", className),
|
|
@@ -297,8 +373,8 @@ var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
297
373
|
}
|
|
298
374
|
));
|
|
299
375
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
300
|
-
var DialogDescription =
|
|
301
|
-
|
|
376
|
+
var DialogDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
|
|
377
|
+
PrimitiveDescription,
|
|
302
378
|
{
|
|
303
379
|
ref,
|
|
304
380
|
className: cn("text-sm text-muted-foreground", className),
|
|
@@ -308,9 +384,9 @@ var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
308
384
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
309
385
|
|
|
310
386
|
// src/components/PageHeader.tsx
|
|
311
|
-
import * as
|
|
387
|
+
import * as React11 from "react";
|
|
312
388
|
import { cva as cva4 } from "class-variance-authority";
|
|
313
|
-
import { jsx as
|
|
389
|
+
import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
314
390
|
var pageHeaderContainerVariants = cva4("", {
|
|
315
391
|
variants: {
|
|
316
392
|
variant: {
|
|
@@ -359,22 +435,916 @@ var pageHeaderActionsVariants = cva4("flex gap-4", {
|
|
|
359
435
|
variant: "default"
|
|
360
436
|
}
|
|
361
437
|
});
|
|
362
|
-
var PageHeader =
|
|
363
|
-
({ className, variant, title, subtitle, actions, ...props }, ref) => /* @__PURE__ */
|
|
438
|
+
var PageHeader = React11.forwardRef(
|
|
439
|
+
({ className, variant, title, subtitle, actions, ...props }, ref) => /* @__PURE__ */ jsxs3(
|
|
364
440
|
"header",
|
|
365
441
|
{
|
|
366
442
|
ref,
|
|
367
443
|
className: cn(pageHeaderContainerVariants({ variant }), className),
|
|
368
444
|
...props,
|
|
369
445
|
children: [
|
|
370
|
-
/* @__PURE__ */
|
|
371
|
-
subtitle && /* @__PURE__ */
|
|
372
|
-
actions && /* @__PURE__ */
|
|
446
|
+
/* @__PURE__ */ jsx11("h1", { className: pageHeaderTitleVariants({ variant }), children: title }),
|
|
447
|
+
subtitle && /* @__PURE__ */ jsx11("p", { className: pageHeaderSubtitleVariants({ variant }), children: subtitle }),
|
|
448
|
+
actions && /* @__PURE__ */ jsx11("div", { className: pageHeaderActionsVariants({ variant }), children: actions })
|
|
373
449
|
]
|
|
374
450
|
}
|
|
375
451
|
)
|
|
376
452
|
);
|
|
377
453
|
PageHeader.displayName = "PageHeader";
|
|
454
|
+
|
|
455
|
+
// src/components/DataPanel.tsx
|
|
456
|
+
import * as React12 from "react";
|
|
457
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
458
|
+
import {
|
|
459
|
+
DEFAULT_PANEL_STATE,
|
|
460
|
+
DEFAULT_CONSTRAINTS,
|
|
461
|
+
loadPanelState,
|
|
462
|
+
savePanelState,
|
|
463
|
+
getPointerPosition,
|
|
464
|
+
calculateDragPosition,
|
|
465
|
+
calculateResize,
|
|
466
|
+
getResizeCursor,
|
|
467
|
+
getPinnedResizeHandle,
|
|
468
|
+
constrainSize,
|
|
469
|
+
constrainPosition,
|
|
470
|
+
constrainPinnedWidth,
|
|
471
|
+
constrainPinnedHeight,
|
|
472
|
+
detectEdgeSnap,
|
|
473
|
+
getPinnedPositionStyles,
|
|
474
|
+
getDetachedPositionStyles,
|
|
475
|
+
getInitialDetachedPosition,
|
|
476
|
+
isHorizontalEdge,
|
|
477
|
+
calculateDetachDistance,
|
|
478
|
+
calculatePullOffset,
|
|
479
|
+
calculateDetachedPositionFromPinned,
|
|
480
|
+
getPinnedPullTransform
|
|
481
|
+
} from "@classic-homes/data-panel-core";
|
|
482
|
+
import { Fragment, jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
483
|
+
var DropdownTrigger = DropdownMenuPrimitive.Trigger;
|
|
484
|
+
var DropdownContent = DropdownMenuPrimitive.Content;
|
|
485
|
+
var DropdownLabel = DropdownMenuPrimitive.Label;
|
|
486
|
+
var DropdownItem = DropdownMenuPrimitive.Item;
|
|
487
|
+
var DropdownSeparator = DropdownMenuPrimitive.Separator;
|
|
488
|
+
function useDataPanel(options = {}) {
|
|
489
|
+
const {
|
|
490
|
+
persistKey,
|
|
491
|
+
initialMode = DEFAULT_PANEL_STATE.mode,
|
|
492
|
+
initialEdge = DEFAULT_PANEL_STATE.edge,
|
|
493
|
+
initialExpanded = DEFAULT_PANEL_STATE.isExpanded,
|
|
494
|
+
constraints = {}
|
|
495
|
+
} = options;
|
|
496
|
+
const resolvedConstraints = { ...DEFAULT_CONSTRAINTS, ...constraints };
|
|
497
|
+
const [persistedState] = React12.useState(() => {
|
|
498
|
+
if (persistKey && typeof window !== "undefined") {
|
|
499
|
+
return loadPanelState(persistKey);
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
502
|
+
});
|
|
503
|
+
const [mode, setMode] = React12.useState(persistedState?.mode ?? initialMode);
|
|
504
|
+
const [edge, setEdge] = React12.useState(persistedState?.edge ?? initialEdge);
|
|
505
|
+
const [isExpanded, setIsExpanded] = React12.useState(
|
|
506
|
+
persistedState?.isExpanded ?? initialExpanded
|
|
507
|
+
);
|
|
508
|
+
const [detachedPosition, setDetachedPosition] = React12.useState(
|
|
509
|
+
persistedState?.detachedPosition ?? DEFAULT_PANEL_STATE.detachedPosition
|
|
510
|
+
);
|
|
511
|
+
const [detachedSize, setDetachedSize] = React12.useState(
|
|
512
|
+
persistedState?.detachedSize ?? DEFAULT_PANEL_STATE.detachedSize
|
|
513
|
+
);
|
|
514
|
+
const [pinnedSize, setPinnedSize] = React12.useState(
|
|
515
|
+
persistedState?.pinnedSize ?? DEFAULT_PANEL_STATE.pinnedSize
|
|
516
|
+
);
|
|
517
|
+
const saveTimeoutRef = React12.useRef(null);
|
|
518
|
+
const debouncedSave = React12.useCallback(() => {
|
|
519
|
+
if (!persistKey) return;
|
|
520
|
+
if (saveTimeoutRef.current) {
|
|
521
|
+
clearTimeout(saveTimeoutRef.current);
|
|
522
|
+
}
|
|
523
|
+
saveTimeoutRef.current = setTimeout(() => {
|
|
524
|
+
savePanelState(persistKey, {
|
|
525
|
+
mode,
|
|
526
|
+
variant: "full",
|
|
527
|
+
edge,
|
|
528
|
+
isExpanded,
|
|
529
|
+
detachedPosition,
|
|
530
|
+
detachedSize,
|
|
531
|
+
pinnedSize,
|
|
532
|
+
cardSnapIndex: 0
|
|
533
|
+
});
|
|
534
|
+
}, 300);
|
|
535
|
+
}, [persistKey, mode, edge, isExpanded, detachedPosition, detachedSize, pinnedSize]);
|
|
536
|
+
const handleSetMode = React12.useCallback(
|
|
537
|
+
(newMode) => {
|
|
538
|
+
setMode(newMode);
|
|
539
|
+
if (newMode === "detached" && typeof window !== "undefined" && detachedPosition.x === DEFAULT_PANEL_STATE.detachedPosition.x && detachedPosition.y === DEFAULT_PANEL_STATE.detachedPosition.y) {
|
|
540
|
+
setDetachedPosition(
|
|
541
|
+
getInitialDetachedPosition(detachedSize, window.innerWidth, window.innerHeight)
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
[detachedPosition, detachedSize]
|
|
546
|
+
);
|
|
547
|
+
const handleSetDetachedPosition = React12.useCallback(
|
|
548
|
+
(position) => {
|
|
549
|
+
if (typeof window === "undefined") {
|
|
550
|
+
setDetachedPosition(position);
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
setDetachedPosition(
|
|
554
|
+
constrainPosition(position, detachedSize, window.innerWidth, window.innerHeight)
|
|
555
|
+
);
|
|
556
|
+
},
|
|
557
|
+
[detachedSize]
|
|
558
|
+
);
|
|
559
|
+
const handleSetDetachedSize = React12.useCallback(
|
|
560
|
+
(size) => {
|
|
561
|
+
setDetachedSize(constrainSize(size, resolvedConstraints));
|
|
562
|
+
},
|
|
563
|
+
[resolvedConstraints]
|
|
564
|
+
);
|
|
565
|
+
const handleSetPinnedSize = React12.useCallback(
|
|
566
|
+
(size) => {
|
|
567
|
+
if (typeof window === "undefined") {
|
|
568
|
+
setPinnedSize(size);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
if (isHorizontalEdge(edge)) {
|
|
572
|
+
setPinnedSize(constrainPinnedWidth(size, resolvedConstraints, window.innerWidth));
|
|
573
|
+
} else {
|
|
574
|
+
setPinnedSize(constrainPinnedHeight(size, resolvedConstraints, window.innerHeight));
|
|
575
|
+
}
|
|
576
|
+
},
|
|
577
|
+
[edge, resolvedConstraints]
|
|
578
|
+
);
|
|
579
|
+
React12.useEffect(() => {
|
|
580
|
+
debouncedSave();
|
|
581
|
+
}, [debouncedSave]);
|
|
582
|
+
return {
|
|
583
|
+
mode,
|
|
584
|
+
setMode: handleSetMode,
|
|
585
|
+
edge,
|
|
586
|
+
setEdge,
|
|
587
|
+
isExpanded,
|
|
588
|
+
setIsExpanded,
|
|
589
|
+
detachedPosition,
|
|
590
|
+
setDetachedPosition: handleSetDetachedPosition,
|
|
591
|
+
detachedSize,
|
|
592
|
+
setDetachedSize: handleSetDetachedSize,
|
|
593
|
+
pinnedSize,
|
|
594
|
+
setPinnedSize: handleSetPinnedSize
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
var ChevronUpIcon = () => /* @__PURE__ */ jsx12(
|
|
598
|
+
"svg",
|
|
599
|
+
{
|
|
600
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
601
|
+
width: "16",
|
|
602
|
+
height: "16",
|
|
603
|
+
viewBox: "0 0 24 24",
|
|
604
|
+
fill: "none",
|
|
605
|
+
stroke: "currentColor",
|
|
606
|
+
strokeWidth: "2",
|
|
607
|
+
strokeLinecap: "round",
|
|
608
|
+
strokeLinejoin: "round",
|
|
609
|
+
children: /* @__PURE__ */ jsx12("path", { d: "m18 15-6-6-6 6" })
|
|
610
|
+
}
|
|
611
|
+
);
|
|
612
|
+
var MoreVerticalIcon = () => /* @__PURE__ */ jsxs4(
|
|
613
|
+
"svg",
|
|
614
|
+
{
|
|
615
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
616
|
+
width: "16",
|
|
617
|
+
height: "16",
|
|
618
|
+
viewBox: "0 0 24 24",
|
|
619
|
+
fill: "none",
|
|
620
|
+
stroke: "currentColor",
|
|
621
|
+
strokeWidth: "2",
|
|
622
|
+
strokeLinecap: "round",
|
|
623
|
+
strokeLinejoin: "round",
|
|
624
|
+
children: [
|
|
625
|
+
/* @__PURE__ */ jsx12("circle", { cx: "12", cy: "12", r: "1" }),
|
|
626
|
+
/* @__PURE__ */ jsx12("circle", { cx: "12", cy: "5", r: "1" }),
|
|
627
|
+
/* @__PURE__ */ jsx12("circle", { cx: "12", cy: "19", r: "1" })
|
|
628
|
+
]
|
|
629
|
+
}
|
|
630
|
+
);
|
|
631
|
+
var CloseIcon = () => /* @__PURE__ */ jsxs4(
|
|
632
|
+
"svg",
|
|
633
|
+
{
|
|
634
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
635
|
+
width: "16",
|
|
636
|
+
height: "16",
|
|
637
|
+
viewBox: "0 0 24 24",
|
|
638
|
+
fill: "none",
|
|
639
|
+
stroke: "currentColor",
|
|
640
|
+
strokeWidth: "2",
|
|
641
|
+
strokeLinecap: "round",
|
|
642
|
+
strokeLinejoin: "round",
|
|
643
|
+
children: [
|
|
644
|
+
/* @__PURE__ */ jsx12("path", { d: "M18 6 6 18" }),
|
|
645
|
+
/* @__PURE__ */ jsx12("path", { d: "m6 6 12 12" })
|
|
646
|
+
]
|
|
647
|
+
}
|
|
648
|
+
);
|
|
649
|
+
var edgeLabels = {
|
|
650
|
+
left: "Pin to left",
|
|
651
|
+
right: "Pin to right",
|
|
652
|
+
top: "Pin to top",
|
|
653
|
+
bottom: "Pin to bottom"
|
|
654
|
+
};
|
|
655
|
+
var DataPanelHeader = React12.forwardRef(
|
|
656
|
+
({
|
|
657
|
+
title,
|
|
658
|
+
subtitle,
|
|
659
|
+
mode,
|
|
660
|
+
edge,
|
|
661
|
+
isExpanded,
|
|
662
|
+
onModeChange,
|
|
663
|
+
onEdgeChange,
|
|
664
|
+
onExpandedChange,
|
|
665
|
+
onClose,
|
|
666
|
+
disableClose = false,
|
|
667
|
+
disableModeSwitch = false,
|
|
668
|
+
headerContent,
|
|
669
|
+
headerActions,
|
|
670
|
+
className,
|
|
671
|
+
draggable = false
|
|
672
|
+
}, ref) => {
|
|
673
|
+
return /* @__PURE__ */ jsxs4(
|
|
674
|
+
"div",
|
|
675
|
+
{
|
|
676
|
+
ref,
|
|
677
|
+
className: cn(
|
|
678
|
+
"flex items-center justify-between gap-2 border-b border-border bg-muted/30 px-4 py-3",
|
|
679
|
+
draggable && "cursor-grab active:cursor-grabbing",
|
|
680
|
+
className
|
|
681
|
+
),
|
|
682
|
+
"data-panel-header": true,
|
|
683
|
+
children: [
|
|
684
|
+
/* @__PURE__ */ jsx12("div", { className: "flex flex-col min-w-0 flex-1", children: headerContent ? headerContent : /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
685
|
+
title && /* @__PURE__ */ jsx12("h3", { className: "text-sm font-semibold leading-none truncate", children: title }),
|
|
686
|
+
subtitle && /* @__PURE__ */ jsx12("p", { className: "text-xs text-muted-foreground mt-1 truncate", children: subtitle })
|
|
687
|
+
] }) }),
|
|
688
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
689
|
+
headerActions,
|
|
690
|
+
/* @__PURE__ */ jsx12(
|
|
691
|
+
"button",
|
|
692
|
+
{
|
|
693
|
+
type: "button",
|
|
694
|
+
className: "flex h-8 w-8 items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
695
|
+
onClick: () => onExpandedChange?.(!isExpanded),
|
|
696
|
+
"aria-label": isExpanded ? "Collapse panel" : "Expand panel",
|
|
697
|
+
"aria-expanded": isExpanded,
|
|
698
|
+
children: /* @__PURE__ */ jsx12("span", { className: cn("transition-transform", !isExpanded && "rotate-180"), children: /* @__PURE__ */ jsx12(ChevronUpIcon, {}) })
|
|
699
|
+
}
|
|
700
|
+
),
|
|
701
|
+
!disableModeSwitch && /* @__PURE__ */ jsxs4(DropdownMenuPrimitive.Root, { children: [
|
|
702
|
+
/* @__PURE__ */ jsx12(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsx12(
|
|
703
|
+
"button",
|
|
704
|
+
{
|
|
705
|
+
type: "button",
|
|
706
|
+
className: "flex h-8 w-8 items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
707
|
+
"aria-label": "Panel options",
|
|
708
|
+
children: /* @__PURE__ */ jsx12(MoreVerticalIcon, {})
|
|
709
|
+
}
|
|
710
|
+
) }),
|
|
711
|
+
/* @__PURE__ */ jsx12(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsxs4(
|
|
712
|
+
DropdownContent,
|
|
713
|
+
{
|
|
714
|
+
className: "z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95",
|
|
715
|
+
sideOffset: 4,
|
|
716
|
+
align: "end",
|
|
717
|
+
children: [
|
|
718
|
+
/* @__PURE__ */ jsx12(DropdownLabel, { className: "px-2 py-1.5 text-sm font-semibold", children: "Panel Position" }),
|
|
719
|
+
["left", "right", "top", "bottom"].map((e) => /* @__PURE__ */ jsxs4(
|
|
720
|
+
DropdownItem,
|
|
721
|
+
{
|
|
722
|
+
className: "relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
723
|
+
onSelect: () => {
|
|
724
|
+
onModeChange?.("pinned");
|
|
725
|
+
onEdgeChange?.(e);
|
|
726
|
+
},
|
|
727
|
+
children: [
|
|
728
|
+
edgeLabels[e],
|
|
729
|
+
mode === "pinned" && edge === e && /* @__PURE__ */ jsx12("span", { className: "ml-auto text-xs", children: "\u2713" })
|
|
730
|
+
]
|
|
731
|
+
},
|
|
732
|
+
e
|
|
733
|
+
)),
|
|
734
|
+
/* @__PURE__ */ jsx12(DropdownSeparator, { className: "-mx-1 my-1 h-px bg-muted" }),
|
|
735
|
+
/* @__PURE__ */ jsxs4(
|
|
736
|
+
DropdownItem,
|
|
737
|
+
{
|
|
738
|
+
className: "relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground",
|
|
739
|
+
onSelect: () => onModeChange?.("detached"),
|
|
740
|
+
children: [
|
|
741
|
+
"Detach",
|
|
742
|
+
mode === "detached" && /* @__PURE__ */ jsx12("span", { className: "ml-auto text-xs", children: "\u2713" })
|
|
743
|
+
]
|
|
744
|
+
}
|
|
745
|
+
)
|
|
746
|
+
]
|
|
747
|
+
}
|
|
748
|
+
) })
|
|
749
|
+
] }),
|
|
750
|
+
!disableClose && /* @__PURE__ */ jsx12(
|
|
751
|
+
"button",
|
|
752
|
+
{
|
|
753
|
+
type: "button",
|
|
754
|
+
className: "flex h-8 w-8 items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
755
|
+
onClick: onClose,
|
|
756
|
+
"aria-label": "Close panel",
|
|
757
|
+
children: /* @__PURE__ */ jsx12(CloseIcon, {})
|
|
758
|
+
}
|
|
759
|
+
)
|
|
760
|
+
] })
|
|
761
|
+
]
|
|
762
|
+
}
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
);
|
|
766
|
+
DataPanelHeader.displayName = "DataPanelHeader";
|
|
767
|
+
var DataPanelContent = React12.forwardRef(
|
|
768
|
+
({ children, className }, ref) => {
|
|
769
|
+
return /* @__PURE__ */ jsx12("div", { ref, className: cn("flex-1 overflow-auto p-4", className), children });
|
|
770
|
+
}
|
|
771
|
+
);
|
|
772
|
+
DataPanelContent.displayName = "DataPanelContent";
|
|
773
|
+
var DataPanelFooter = React12.forwardRef(
|
|
774
|
+
({ actions = [], footerContent, footerActions, className }, ref) => {
|
|
775
|
+
if (!footerContent && actions.length === 0 && !footerActions) {
|
|
776
|
+
return null;
|
|
777
|
+
}
|
|
778
|
+
const mapVariant = (variant) => {
|
|
779
|
+
if (variant === "primary") return "default";
|
|
780
|
+
return variant ?? "default";
|
|
781
|
+
};
|
|
782
|
+
return /* @__PURE__ */ jsx12(
|
|
783
|
+
"div",
|
|
784
|
+
{
|
|
785
|
+
ref,
|
|
786
|
+
className: cn(
|
|
787
|
+
"flex items-center justify-end gap-2 border-t border-border bg-muted/30 px-4 py-3",
|
|
788
|
+
className
|
|
789
|
+
),
|
|
790
|
+
children: footerContent ? footerContent : /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
791
|
+
footerActions,
|
|
792
|
+
actions.map((action, index) => /* @__PURE__ */ jsx12(
|
|
793
|
+
Button,
|
|
794
|
+
{
|
|
795
|
+
variant: mapVariant(action.variant),
|
|
796
|
+
size: "sm",
|
|
797
|
+
disabled: action.disabled,
|
|
798
|
+
onClick: action.onClick,
|
|
799
|
+
children: action.label
|
|
800
|
+
},
|
|
801
|
+
index
|
|
802
|
+
))
|
|
803
|
+
] })
|
|
804
|
+
}
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
);
|
|
808
|
+
DataPanelFooter.displayName = "DataPanelFooter";
|
|
809
|
+
var DataPanelTab = React12.forwardRef(
|
|
810
|
+
({ title = "Panel", edge, onClick, className }, ref) => {
|
|
811
|
+
const positionClasses = {
|
|
812
|
+
left: "left-0 top-1/2 -translate-y-1/2 rounded-r-md border-l-0",
|
|
813
|
+
right: "right-0 top-1/2 -translate-y-1/2 rounded-l-md border-r-0",
|
|
814
|
+
top: "top-0 left-1/2 -translate-x-1/2 rounded-b-md border-t-0",
|
|
815
|
+
bottom: "bottom-0 left-1/2 -translate-x-1/2 rounded-t-md border-b-0"
|
|
816
|
+
}[edge];
|
|
817
|
+
const isVertical = edge === "left" || edge === "right";
|
|
818
|
+
const iconRotation = {
|
|
819
|
+
left: "rotate-90",
|
|
820
|
+
right: "-rotate-90",
|
|
821
|
+
top: "rotate-180",
|
|
822
|
+
bottom: ""
|
|
823
|
+
}[edge];
|
|
824
|
+
return /* @__PURE__ */ jsxs4(
|
|
825
|
+
"button",
|
|
826
|
+
{
|
|
827
|
+
ref,
|
|
828
|
+
type: "button",
|
|
829
|
+
className: cn(
|
|
830
|
+
"fixed z-40 flex items-center justify-center gap-2 border border-border bg-background px-3 py-2 text-sm font-medium shadow-md transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
831
|
+
positionClasses,
|
|
832
|
+
isVertical && "[writing-mode:vertical-rl]",
|
|
833
|
+
className
|
|
834
|
+
),
|
|
835
|
+
onClick,
|
|
836
|
+
"aria-label": `Expand ${title} panel`,
|
|
837
|
+
children: [
|
|
838
|
+
/* @__PURE__ */ jsx12("span", { className: cn("shrink-0", iconRotation), children: /* @__PURE__ */ jsx12(ChevronUpIcon, {}) }),
|
|
839
|
+
/* @__PURE__ */ jsx12("span", { className: cn(isVertical && "rotate-180"), children: title })
|
|
840
|
+
]
|
|
841
|
+
}
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
);
|
|
845
|
+
DataPanelTab.displayName = "DataPanelTab";
|
|
846
|
+
var DataPanel = React12.forwardRef(
|
|
847
|
+
({
|
|
848
|
+
open: controlledOpen,
|
|
849
|
+
onOpenChange,
|
|
850
|
+
mode: controlledMode,
|
|
851
|
+
onModeChange,
|
|
852
|
+
edge: controlledEdge,
|
|
853
|
+
onEdgeChange,
|
|
854
|
+
expanded: controlledExpanded,
|
|
855
|
+
onExpandedChange,
|
|
856
|
+
title,
|
|
857
|
+
subtitle,
|
|
858
|
+
children,
|
|
859
|
+
actions = [],
|
|
860
|
+
constraints = {},
|
|
861
|
+
disableClose = false,
|
|
862
|
+
disableResize = false,
|
|
863
|
+
disableDrag = false,
|
|
864
|
+
disableModeSwitch = false,
|
|
865
|
+
persistKey,
|
|
866
|
+
snapThreshold = 20,
|
|
867
|
+
detachThreshold = 40,
|
|
868
|
+
headerContent,
|
|
869
|
+
headerActions,
|
|
870
|
+
footerContent,
|
|
871
|
+
footerActions,
|
|
872
|
+
className
|
|
873
|
+
}, ref) => {
|
|
874
|
+
const resolvedConstraints = { ...DEFAULT_CONSTRAINTS, ...constraints };
|
|
875
|
+
const [internalOpen, setInternalOpen] = React12.useState(true);
|
|
876
|
+
const [internalMode, setInternalMode] = React12.useState(DEFAULT_PANEL_STATE.mode);
|
|
877
|
+
const [internalEdge, setInternalEdge] = React12.useState(DEFAULT_PANEL_STATE.edge);
|
|
878
|
+
const [internalExpanded, setInternalExpanded] = React12.useState(
|
|
879
|
+
DEFAULT_PANEL_STATE.isExpanded
|
|
880
|
+
);
|
|
881
|
+
const [detachedPosition, setDetachedPosition] = React12.useState(
|
|
882
|
+
DEFAULT_PANEL_STATE.detachedPosition
|
|
883
|
+
);
|
|
884
|
+
const [detachedSize, setDetachedSize] = React12.useState(DEFAULT_PANEL_STATE.detachedSize);
|
|
885
|
+
const [pinnedSize, setPinnedSize] = React12.useState(DEFAULT_PANEL_STATE.pinnedSize);
|
|
886
|
+
const [isDragging, setIsDragging] = React12.useState(false);
|
|
887
|
+
const [isResizing, setIsResizing] = React12.useState(false);
|
|
888
|
+
const [snapPreview, setSnapPreview] = React12.useState(null);
|
|
889
|
+
const [isPinnedDragging, setIsPinnedDragging] = React12.useState(false);
|
|
890
|
+
const [pullOffset, setPullOffset] = React12.useState(0);
|
|
891
|
+
const dragStateRef = React12.useRef({
|
|
892
|
+
startPosition: { x: 0, y: 0 },
|
|
893
|
+
startPanelPosition: { x: 0, y: 0 }
|
|
894
|
+
});
|
|
895
|
+
const pinnedDragStateRef = React12.useRef({
|
|
896
|
+
startPosition: { x: 0, y: 0 },
|
|
897
|
+
hasDetached: false
|
|
898
|
+
});
|
|
899
|
+
const resizeStateRef = React12.useRef({
|
|
900
|
+
handle: null,
|
|
901
|
+
startPosition: { x: 0, y: 0 },
|
|
902
|
+
startSize: { width: 0, height: 0 },
|
|
903
|
+
startPanelPosition: { x: 0, y: 0 }
|
|
904
|
+
});
|
|
905
|
+
const open = controlledOpen ?? internalOpen;
|
|
906
|
+
const mode = controlledMode ?? internalMode;
|
|
907
|
+
const edge = controlledEdge ?? internalEdge;
|
|
908
|
+
const isExpanded = controlledExpanded ?? internalExpanded;
|
|
909
|
+
const saveTimeoutRef = React12.useRef(null);
|
|
910
|
+
const debouncedSave = React12.useCallback(() => {
|
|
911
|
+
if (!persistKey) return;
|
|
912
|
+
if (saveTimeoutRef.current) {
|
|
913
|
+
clearTimeout(saveTimeoutRef.current);
|
|
914
|
+
}
|
|
915
|
+
saveTimeoutRef.current = setTimeout(() => {
|
|
916
|
+
savePanelState(persistKey, {
|
|
917
|
+
mode: internalMode,
|
|
918
|
+
variant: "full",
|
|
919
|
+
edge: internalEdge,
|
|
920
|
+
isExpanded: internalExpanded,
|
|
921
|
+
detachedPosition,
|
|
922
|
+
detachedSize,
|
|
923
|
+
pinnedSize,
|
|
924
|
+
cardSnapIndex: 0
|
|
925
|
+
});
|
|
926
|
+
}, 300);
|
|
927
|
+
}, [
|
|
928
|
+
persistKey,
|
|
929
|
+
internalMode,
|
|
930
|
+
internalEdge,
|
|
931
|
+
internalExpanded,
|
|
932
|
+
detachedPosition,
|
|
933
|
+
detachedSize,
|
|
934
|
+
pinnedSize
|
|
935
|
+
]);
|
|
936
|
+
React12.useEffect(() => {
|
|
937
|
+
if (!persistKey) return;
|
|
938
|
+
const persisted = loadPanelState(persistKey);
|
|
939
|
+
if (persisted) {
|
|
940
|
+
if (controlledMode === void 0 && persisted.mode) setInternalMode(persisted.mode);
|
|
941
|
+
if (controlledEdge === void 0 && persisted.edge) setInternalEdge(persisted.edge);
|
|
942
|
+
if (controlledExpanded === void 0 && persisted.isExpanded !== void 0)
|
|
943
|
+
setInternalExpanded(persisted.isExpanded);
|
|
944
|
+
if (persisted.detachedPosition) setDetachedPosition(persisted.detachedPosition);
|
|
945
|
+
if (persisted.detachedSize) setDetachedSize(persisted.detachedSize);
|
|
946
|
+
if (persisted.pinnedSize) setPinnedSize(persisted.pinnedSize);
|
|
947
|
+
}
|
|
948
|
+
}, [persistKey, controlledMode, controlledEdge, controlledExpanded]);
|
|
949
|
+
React12.useEffect(() => {
|
|
950
|
+
if (mode === "detached" && detachedPosition.x === DEFAULT_PANEL_STATE.detachedPosition.x && detachedPosition.y === DEFAULT_PANEL_STATE.detachedPosition.y) {
|
|
951
|
+
setDetachedPosition(
|
|
952
|
+
getInitialDetachedPosition(detachedSize, window.innerWidth, window.innerHeight)
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
}, [mode, detachedPosition, detachedSize]);
|
|
956
|
+
const handleOpenChange = (newOpen) => {
|
|
957
|
+
if (controlledOpen === void 0) {
|
|
958
|
+
setInternalOpen(newOpen);
|
|
959
|
+
}
|
|
960
|
+
onOpenChange?.(newOpen);
|
|
961
|
+
};
|
|
962
|
+
const handleModeChange = (newMode) => {
|
|
963
|
+
if (controlledMode === void 0) {
|
|
964
|
+
setInternalMode(newMode);
|
|
965
|
+
}
|
|
966
|
+
onModeChange?.(newMode);
|
|
967
|
+
debouncedSave();
|
|
968
|
+
};
|
|
969
|
+
const handleEdgeChange = (newEdge) => {
|
|
970
|
+
if (controlledEdge === void 0) {
|
|
971
|
+
setInternalEdge(newEdge);
|
|
972
|
+
}
|
|
973
|
+
onEdgeChange?.(newEdge);
|
|
974
|
+
debouncedSave();
|
|
975
|
+
};
|
|
976
|
+
const handleExpandedChange = (newExpanded) => {
|
|
977
|
+
if (controlledExpanded === void 0) {
|
|
978
|
+
setInternalExpanded(newExpanded);
|
|
979
|
+
}
|
|
980
|
+
onExpandedChange?.(newExpanded);
|
|
981
|
+
debouncedSave();
|
|
982
|
+
};
|
|
983
|
+
const handleDragStart = (e) => {
|
|
984
|
+
if (disableDrag) return;
|
|
985
|
+
const target = e.target;
|
|
986
|
+
if (!target.closest("[data-panel-header]")) return;
|
|
987
|
+
const pos = getPointerPosition(e.nativeEvent);
|
|
988
|
+
if (mode === "detached") {
|
|
989
|
+
setIsDragging(true);
|
|
990
|
+
dragStateRef.current = {
|
|
991
|
+
startPosition: pos,
|
|
992
|
+
startPanelPosition: { ...detachedPosition }
|
|
993
|
+
};
|
|
994
|
+
document.body.style.cursor = "grabbing";
|
|
995
|
+
document.body.style.userSelect = "none";
|
|
996
|
+
} else if (mode === "pinned" && detachThreshold > 0) {
|
|
997
|
+
setIsPinnedDragging(true);
|
|
998
|
+
pinnedDragStateRef.current = {
|
|
999
|
+
startPosition: pos,
|
|
1000
|
+
hasDetached: false
|
|
1001
|
+
};
|
|
1002
|
+
setPullOffset(0);
|
|
1003
|
+
document.body.style.cursor = "grab";
|
|
1004
|
+
document.body.style.userSelect = "none";
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
const handleDragMove = React12.useCallback(
|
|
1008
|
+
(e) => {
|
|
1009
|
+
if (!isDragging) return;
|
|
1010
|
+
const currentPos = getPointerPosition(e);
|
|
1011
|
+
const newPosition = calculateDragPosition(
|
|
1012
|
+
{
|
|
1013
|
+
isDragging: true,
|
|
1014
|
+
startPosition: dragStateRef.current.startPosition,
|
|
1015
|
+
startPanelPosition: dragStateRef.current.startPanelPosition,
|
|
1016
|
+
currentPosition: currentPos
|
|
1017
|
+
},
|
|
1018
|
+
currentPos
|
|
1019
|
+
);
|
|
1020
|
+
const snap = detectEdgeSnap(
|
|
1021
|
+
newPosition,
|
|
1022
|
+
detachedSize,
|
|
1023
|
+
window.innerWidth,
|
|
1024
|
+
window.innerHeight,
|
|
1025
|
+
snapThreshold
|
|
1026
|
+
);
|
|
1027
|
+
setSnapPreview(snap.shouldSnap ? snap.edge : null);
|
|
1028
|
+
setDetachedPosition(
|
|
1029
|
+
constrainPosition(newPosition, detachedSize, window.innerWidth, window.innerHeight)
|
|
1030
|
+
);
|
|
1031
|
+
},
|
|
1032
|
+
[isDragging, detachedSize, snapThreshold]
|
|
1033
|
+
);
|
|
1034
|
+
const handleDragEnd = React12.useCallback(() => {
|
|
1035
|
+
if (!isDragging) return;
|
|
1036
|
+
setIsDragging(false);
|
|
1037
|
+
document.body.style.cursor = "";
|
|
1038
|
+
document.body.style.userSelect = "";
|
|
1039
|
+
if (snapPreview) {
|
|
1040
|
+
handleModeChange("pinned");
|
|
1041
|
+
handleEdgeChange(snapPreview);
|
|
1042
|
+
setSnapPreview(null);
|
|
1043
|
+
} else {
|
|
1044
|
+
debouncedSave();
|
|
1045
|
+
}
|
|
1046
|
+
}, [isDragging, snapPreview, handleModeChange, handleEdgeChange, debouncedSave]);
|
|
1047
|
+
const handlePinnedDragMove = React12.useCallback(
|
|
1048
|
+
(e) => {
|
|
1049
|
+
if (!isPinnedDragging) return;
|
|
1050
|
+
const currentPos = getPointerPosition(e);
|
|
1051
|
+
const distance = calculateDetachDistance(
|
|
1052
|
+
pinnedDragStateRef.current.startPosition,
|
|
1053
|
+
currentPos,
|
|
1054
|
+
edge
|
|
1055
|
+
);
|
|
1056
|
+
if (distance >= detachThreshold && !pinnedDragStateRef.current.hasDetached) {
|
|
1057
|
+
pinnedDragStateRef.current.hasDetached = true;
|
|
1058
|
+
setIsPinnedDragging(false);
|
|
1059
|
+
setPullOffset(0);
|
|
1060
|
+
const newPosition = calculateDetachedPositionFromPinned(
|
|
1061
|
+
currentPos,
|
|
1062
|
+
pinnedSize,
|
|
1063
|
+
detachedSize,
|
|
1064
|
+
edge,
|
|
1065
|
+
window.innerWidth,
|
|
1066
|
+
window.innerHeight
|
|
1067
|
+
);
|
|
1068
|
+
setDetachedPosition(newPosition);
|
|
1069
|
+
handleModeChange("detached");
|
|
1070
|
+
setIsDragging(true);
|
|
1071
|
+
dragStateRef.current = {
|
|
1072
|
+
startPosition: currentPos,
|
|
1073
|
+
startPanelPosition: newPosition
|
|
1074
|
+
};
|
|
1075
|
+
document.body.style.cursor = "grabbing";
|
|
1076
|
+
} else if (!pinnedDragStateRef.current.hasDetached) {
|
|
1077
|
+
const pull = calculatePullOffset(distance, detachThreshold);
|
|
1078
|
+
setPullOffset(pull);
|
|
1079
|
+
}
|
|
1080
|
+
},
|
|
1081
|
+
[isPinnedDragging, edge, detachThreshold, pinnedSize, detachedSize, handleModeChange]
|
|
1082
|
+
);
|
|
1083
|
+
const handlePinnedDragEnd = React12.useCallback(() => {
|
|
1084
|
+
if (!isPinnedDragging) return;
|
|
1085
|
+
setIsPinnedDragging(false);
|
|
1086
|
+
setPullOffset(0);
|
|
1087
|
+
document.body.style.cursor = "";
|
|
1088
|
+
document.body.style.userSelect = "";
|
|
1089
|
+
}, [isPinnedDragging]);
|
|
1090
|
+
const handleResizeStart = (e, handle) => {
|
|
1091
|
+
if (disableResize) return;
|
|
1092
|
+
e.preventDefault();
|
|
1093
|
+
e.stopPropagation();
|
|
1094
|
+
setIsResizing(true);
|
|
1095
|
+
const pos = getPointerPosition(e.nativeEvent);
|
|
1096
|
+
resizeStateRef.current = {
|
|
1097
|
+
handle,
|
|
1098
|
+
startPosition: pos,
|
|
1099
|
+
startSize: mode === "detached" ? { ...detachedSize } : { width: pinnedSize, height: pinnedSize },
|
|
1100
|
+
startPanelPosition: { ...detachedPosition }
|
|
1101
|
+
};
|
|
1102
|
+
document.body.style.cursor = getResizeCursor(handle);
|
|
1103
|
+
document.body.style.userSelect = "none";
|
|
1104
|
+
};
|
|
1105
|
+
const handleResizeMove = React12.useCallback(
|
|
1106
|
+
(e) => {
|
|
1107
|
+
if (!isResizing || !resizeStateRef.current.handle) return;
|
|
1108
|
+
const currentPos = getPointerPosition(e);
|
|
1109
|
+
const { handle, startPosition, startSize, startPanelPosition } = resizeStateRef.current;
|
|
1110
|
+
if (mode === "detached") {
|
|
1111
|
+
const result = calculateResize(
|
|
1112
|
+
{
|
|
1113
|
+
isResizing: true,
|
|
1114
|
+
handle,
|
|
1115
|
+
startPosition,
|
|
1116
|
+
startSize,
|
|
1117
|
+
startPanelPosition
|
|
1118
|
+
},
|
|
1119
|
+
currentPos
|
|
1120
|
+
);
|
|
1121
|
+
const constrainedSize = constrainSize(result.size, resolvedConstraints);
|
|
1122
|
+
const constrainedPosition = constrainPosition(
|
|
1123
|
+
result.position,
|
|
1124
|
+
constrainedSize,
|
|
1125
|
+
window.innerWidth,
|
|
1126
|
+
window.innerHeight
|
|
1127
|
+
);
|
|
1128
|
+
setDetachedSize(constrainedSize);
|
|
1129
|
+
setDetachedPosition(constrainedPosition);
|
|
1130
|
+
} else {
|
|
1131
|
+
const delta = isHorizontalEdge(edge) ? currentPos.x - startPosition.x : currentPos.y - startPosition.y;
|
|
1132
|
+
const direction = edge === "left" || edge === "top" ? 1 : -1;
|
|
1133
|
+
const newSize = startSize.width + delta * direction;
|
|
1134
|
+
if (isHorizontalEdge(edge)) {
|
|
1135
|
+
setPinnedSize(constrainPinnedWidth(newSize, resolvedConstraints, window.innerWidth));
|
|
1136
|
+
} else {
|
|
1137
|
+
setPinnedSize(constrainPinnedHeight(newSize, resolvedConstraints, window.innerHeight));
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
[isResizing, mode, edge, resolvedConstraints]
|
|
1142
|
+
);
|
|
1143
|
+
const handleResizeEnd = React12.useCallback(() => {
|
|
1144
|
+
if (!isResizing) return;
|
|
1145
|
+
setIsResizing(false);
|
|
1146
|
+
resizeStateRef.current.handle = null;
|
|
1147
|
+
document.body.style.cursor = "";
|
|
1148
|
+
document.body.style.userSelect = "";
|
|
1149
|
+
debouncedSave();
|
|
1150
|
+
}, [isResizing, debouncedSave]);
|
|
1151
|
+
React12.useEffect(() => {
|
|
1152
|
+
if (isDragging) {
|
|
1153
|
+
window.addEventListener("pointermove", handleDragMove);
|
|
1154
|
+
window.addEventListener("pointerup", handleDragEnd);
|
|
1155
|
+
return () => {
|
|
1156
|
+
window.removeEventListener("pointermove", handleDragMove);
|
|
1157
|
+
window.removeEventListener("pointerup", handleDragEnd);
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
}, [isDragging, handleDragMove, handleDragEnd]);
|
|
1161
|
+
React12.useEffect(() => {
|
|
1162
|
+
if (isPinnedDragging) {
|
|
1163
|
+
window.addEventListener("pointermove", handlePinnedDragMove);
|
|
1164
|
+
window.addEventListener("pointerup", handlePinnedDragEnd);
|
|
1165
|
+
return () => {
|
|
1166
|
+
window.removeEventListener("pointermove", handlePinnedDragMove);
|
|
1167
|
+
window.removeEventListener("pointerup", handlePinnedDragEnd);
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
}, [isPinnedDragging, handlePinnedDragMove, handlePinnedDragEnd]);
|
|
1171
|
+
React12.useEffect(() => {
|
|
1172
|
+
if (isResizing) {
|
|
1173
|
+
window.addEventListener("pointermove", handleResizeMove);
|
|
1174
|
+
window.addEventListener("pointerup", handleResizeEnd);
|
|
1175
|
+
return () => {
|
|
1176
|
+
window.removeEventListener("pointermove", handleResizeMove);
|
|
1177
|
+
window.removeEventListener("pointerup", handleResizeEnd);
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
}, [isResizing, handleResizeMove, handleResizeEnd]);
|
|
1181
|
+
const panelStyles = React12.useMemo(() => {
|
|
1182
|
+
if (mode === "pinned") {
|
|
1183
|
+
const baseStyles = getPinnedPositionStyles(edge, pinnedSize);
|
|
1184
|
+
if (pullOffset > 0) {
|
|
1185
|
+
const transform = getPinnedPullTransform(pullOffset, edge);
|
|
1186
|
+
return { ...baseStyles, transform };
|
|
1187
|
+
}
|
|
1188
|
+
return baseStyles;
|
|
1189
|
+
}
|
|
1190
|
+
return getDetachedPositionStyles(detachedPosition, detachedSize);
|
|
1191
|
+
}, [mode, edge, pinnedSize, detachedPosition, detachedSize, pullOffset]);
|
|
1192
|
+
const pinnedClasses = {
|
|
1193
|
+
left: "left-0 top-0 bottom-0 border-r",
|
|
1194
|
+
right: "right-0 top-0 bottom-0 border-l",
|
|
1195
|
+
top: "top-0 left-0 right-0 border-b",
|
|
1196
|
+
bottom: "bottom-0 left-0 right-0 border-t"
|
|
1197
|
+
}[edge];
|
|
1198
|
+
const animationClass = mode === "pinned" ? {
|
|
1199
|
+
left: "animate-slide-right",
|
|
1200
|
+
right: "animate-slide-left",
|
|
1201
|
+
top: "animate-slide-down",
|
|
1202
|
+
bottom: "animate-slide-up"
|
|
1203
|
+
}[edge] : "animate-scale-in";
|
|
1204
|
+
if (!open) return null;
|
|
1205
|
+
if (!isExpanded && mode === "pinned") {
|
|
1206
|
+
return /* @__PURE__ */ jsx12(DataPanelTab, { title, edge, onClick: () => handleExpandedChange(true) });
|
|
1207
|
+
}
|
|
1208
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1209
|
+
snapPreview && /* @__PURE__ */ jsx12(
|
|
1210
|
+
"div",
|
|
1211
|
+
{
|
|
1212
|
+
className: cn(
|
|
1213
|
+
"fixed z-40 bg-primary/20 border-2 border-primary border-dashed transition-all",
|
|
1214
|
+
snapPreview === "left" && "left-0 top-0 bottom-0 w-80",
|
|
1215
|
+
snapPreview === "right" && "right-0 top-0 bottom-0 w-80",
|
|
1216
|
+
snapPreview === "top" && "top-0 left-0 right-0 h-64",
|
|
1217
|
+
snapPreview === "bottom" && "bottom-0 left-0 right-0 h-64"
|
|
1218
|
+
)
|
|
1219
|
+
}
|
|
1220
|
+
),
|
|
1221
|
+
/* @__PURE__ */ jsxs4(
|
|
1222
|
+
"div",
|
|
1223
|
+
{
|
|
1224
|
+
ref,
|
|
1225
|
+
className: cn(
|
|
1226
|
+
"fixed z-50 flex flex-col bg-background border border-border shadow-lg overflow-hidden",
|
|
1227
|
+
mode === "pinned" && pinnedClasses,
|
|
1228
|
+
mode === "detached" && "rounded-lg",
|
|
1229
|
+
isPinnedDragging && pullOffset > 0 && "shadow-2xl",
|
|
1230
|
+
animationClass,
|
|
1231
|
+
className
|
|
1232
|
+
),
|
|
1233
|
+
style: panelStyles,
|
|
1234
|
+
role: mode === "detached" ? "dialog" : void 0,
|
|
1235
|
+
"aria-modal": mode === "detached" ? "true" : void 0,
|
|
1236
|
+
"aria-labelledby": title ? "data-panel-title" : void 0,
|
|
1237
|
+
onPointerDown: handleDragStart,
|
|
1238
|
+
children: [
|
|
1239
|
+
/* @__PURE__ */ jsx12(
|
|
1240
|
+
DataPanelHeader,
|
|
1241
|
+
{
|
|
1242
|
+
title,
|
|
1243
|
+
subtitle,
|
|
1244
|
+
mode,
|
|
1245
|
+
edge,
|
|
1246
|
+
isExpanded,
|
|
1247
|
+
onModeChange: handleModeChange,
|
|
1248
|
+
onEdgeChange: handleEdgeChange,
|
|
1249
|
+
onExpandedChange: handleExpandedChange,
|
|
1250
|
+
onClose: () => handleOpenChange(false),
|
|
1251
|
+
disableClose,
|
|
1252
|
+
disableModeSwitch,
|
|
1253
|
+
headerContent,
|
|
1254
|
+
headerActions,
|
|
1255
|
+
draggable: !disableDrag && (mode === "detached" || mode === "pinned" && detachThreshold > 0)
|
|
1256
|
+
}
|
|
1257
|
+
),
|
|
1258
|
+
/* @__PURE__ */ jsx12(DataPanelContent, { children }),
|
|
1259
|
+
/* @__PURE__ */ jsx12(
|
|
1260
|
+
DataPanelFooter,
|
|
1261
|
+
{
|
|
1262
|
+
actions,
|
|
1263
|
+
footerContent,
|
|
1264
|
+
footerActions
|
|
1265
|
+
}
|
|
1266
|
+
),
|
|
1267
|
+
!disableResize && /* @__PURE__ */ jsx12(Fragment, { children: mode === "detached" ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1268
|
+
/* @__PURE__ */ jsx12(
|
|
1269
|
+
"div",
|
|
1270
|
+
{
|
|
1271
|
+
className: "resize-handle resize-handle--horizontal resize-handle--top",
|
|
1272
|
+
onPointerDown: (e) => handleResizeStart(e, "top")
|
|
1273
|
+
}
|
|
1274
|
+
),
|
|
1275
|
+
/* @__PURE__ */ jsx12(
|
|
1276
|
+
"div",
|
|
1277
|
+
{
|
|
1278
|
+
className: "resize-handle resize-handle--horizontal resize-handle--bottom",
|
|
1279
|
+
onPointerDown: (e) => handleResizeStart(e, "bottom")
|
|
1280
|
+
}
|
|
1281
|
+
),
|
|
1282
|
+
/* @__PURE__ */ jsx12(
|
|
1283
|
+
"div",
|
|
1284
|
+
{
|
|
1285
|
+
className: "resize-handle resize-handle--vertical resize-handle--left",
|
|
1286
|
+
onPointerDown: (e) => handleResizeStart(e, "left")
|
|
1287
|
+
}
|
|
1288
|
+
),
|
|
1289
|
+
/* @__PURE__ */ jsx12(
|
|
1290
|
+
"div",
|
|
1291
|
+
{
|
|
1292
|
+
className: "resize-handle resize-handle--vertical resize-handle--right",
|
|
1293
|
+
onPointerDown: (e) => handleResizeStart(e, "right")
|
|
1294
|
+
}
|
|
1295
|
+
),
|
|
1296
|
+
/* @__PURE__ */ jsx12(
|
|
1297
|
+
"div",
|
|
1298
|
+
{
|
|
1299
|
+
className: "resize-handle resize-handle--corner resize-handle--top-left",
|
|
1300
|
+
style: { "--handle-radius": "6px" },
|
|
1301
|
+
onPointerDown: (e) => handleResizeStart(e, "top-left")
|
|
1302
|
+
}
|
|
1303
|
+
),
|
|
1304
|
+
/* @__PURE__ */ jsx12(
|
|
1305
|
+
"div",
|
|
1306
|
+
{
|
|
1307
|
+
className: "resize-handle resize-handle--corner resize-handle--top-right",
|
|
1308
|
+
style: { "--handle-radius": "6px" },
|
|
1309
|
+
onPointerDown: (e) => handleResizeStart(e, "top-right")
|
|
1310
|
+
}
|
|
1311
|
+
),
|
|
1312
|
+
/* @__PURE__ */ jsx12(
|
|
1313
|
+
"div",
|
|
1314
|
+
{
|
|
1315
|
+
className: "resize-handle resize-handle--corner resize-handle--bottom-left",
|
|
1316
|
+
style: { "--handle-radius": "6px" },
|
|
1317
|
+
onPointerDown: (e) => handleResizeStart(e, "bottom-left")
|
|
1318
|
+
}
|
|
1319
|
+
),
|
|
1320
|
+
/* @__PURE__ */ jsx12(
|
|
1321
|
+
"div",
|
|
1322
|
+
{
|
|
1323
|
+
className: "resize-handle resize-handle--corner resize-handle--bottom-right",
|
|
1324
|
+
style: { "--handle-radius": "6px" },
|
|
1325
|
+
onPointerDown: (e) => handleResizeStart(e, "bottom-right")
|
|
1326
|
+
}
|
|
1327
|
+
)
|
|
1328
|
+
] }) : /* @__PURE__ */ jsx12(
|
|
1329
|
+
"div",
|
|
1330
|
+
{
|
|
1331
|
+
className: cn(
|
|
1332
|
+
"resize-handle",
|
|
1333
|
+
edge === "left" && "resize-handle--vertical resize-handle--right",
|
|
1334
|
+
edge === "right" && "resize-handle--vertical resize-handle--left",
|
|
1335
|
+
edge === "top" && "resize-handle--horizontal resize-handle--bottom",
|
|
1336
|
+
edge === "bottom" && "resize-handle--horizontal resize-handle--top"
|
|
1337
|
+
),
|
|
1338
|
+
onPointerDown: (e) => handleResizeStart(e, getPinnedResizeHandle(edge))
|
|
1339
|
+
}
|
|
1340
|
+
) })
|
|
1341
|
+
]
|
|
1342
|
+
}
|
|
1343
|
+
)
|
|
1344
|
+
] });
|
|
1345
|
+
}
|
|
1346
|
+
);
|
|
1347
|
+
DataPanel.displayName = "DataPanel";
|
|
378
1348
|
export {
|
|
379
1349
|
Avatar,
|
|
380
1350
|
AvatarFallback,
|
|
@@ -387,6 +1357,11 @@ export {
|
|
|
387
1357
|
CardFooter,
|
|
388
1358
|
CardHeader,
|
|
389
1359
|
CardTitle,
|
|
1360
|
+
DataPanel,
|
|
1361
|
+
DataPanelContent,
|
|
1362
|
+
DataPanelFooter,
|
|
1363
|
+
DataPanelHeader,
|
|
1364
|
+
DataPanelTab,
|
|
390
1365
|
Dialog,
|
|
391
1366
|
DialogClose,
|
|
392
1367
|
DialogContent,
|
|
@@ -400,6 +1375,7 @@ export {
|
|
|
400
1375
|
Input,
|
|
401
1376
|
Label,
|
|
402
1377
|
PageHeader,
|
|
1378
|
+
PasswordInput,
|
|
403
1379
|
Separator,
|
|
404
1380
|
Switch,
|
|
405
1381
|
badgeVariants,
|
|
@@ -408,5 +1384,6 @@ export {
|
|
|
408
1384
|
pageHeaderActionsVariants,
|
|
409
1385
|
pageHeaderContainerVariants,
|
|
410
1386
|
pageHeaderSubtitleVariants,
|
|
411
|
-
pageHeaderTitleVariants
|
|
1387
|
+
pageHeaderTitleVariants,
|
|
1388
|
+
useDataPanel
|
|
412
1389
|
};
|