hazo_ui 2.9.0 → 2.16.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/CHANGE_LOG.md +500 -0
- package/README.md +539 -0
- package/SETUP_CHECKLIST.md +418 -0
- package/dist/index.cjs +2522 -499
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +534 -1
- package/dist/index.d.ts +534 -1
- package/dist/index.js +2461 -468
- package/dist/index.js.map +1 -1
- package/dist/styles.css +40 -0
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
2
|
+
import * as React25 from 'react';
|
|
3
|
+
import React25__default, { useRef, useState, useCallback, useEffect, useMemo, Fragment } from 'react';
|
|
4
4
|
import { Slot } from '@radix-ui/react-slot';
|
|
5
5
|
import { cva } from 'class-variance-authority';
|
|
6
6
|
import { clsx } from 'clsx';
|
|
7
7
|
import { twMerge } from 'tailwind-merge';
|
|
8
8
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
9
9
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
10
|
-
import { X, ChevronDown, ChevronUp, Check, Circle, ChevronRight, ChevronLeft, Filter, Plus,
|
|
10
|
+
import { X, ChevronDown, ChevronUp, Check, Circle, ChevronRight, ChevronLeft, Filter, Plus, ArrowUpDown, Loader2, AlertTriangle, OctagonAlert, CheckCircle2, ChevronsUpDown, GripVertical, ArrowUp, ArrowDown, Pencil, Calendar as Calendar$1 } from 'lucide-react';
|
|
11
11
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
12
12
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
13
13
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
14
14
|
import { DayPicker } from 'react-day-picker';
|
|
15
15
|
import { format } from 'date-fns';
|
|
16
|
-
import
|
|
17
|
-
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from '@dnd-kit/core';
|
|
16
|
+
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter, closestCorners, DragOverlay, useDroppable } from '@dnd-kit/core';
|
|
18
17
|
import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, arrayMove, useSortable } from '@dnd-kit/sortable';
|
|
19
18
|
import { CSS } from '@dnd-kit/utilities';
|
|
20
19
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
@@ -61,12 +60,15 @@ import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
|
61
60
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
62
61
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
63
62
|
import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
|
|
63
|
+
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
64
64
|
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
65
65
|
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
66
66
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
67
67
|
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
68
68
|
import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
69
69
|
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
70
|
+
import { Toaster, toast } from 'sonner';
|
|
71
|
+
export { toast as rawToast } from 'sonner';
|
|
70
72
|
|
|
71
73
|
var __create = Object.create;
|
|
72
74
|
var __defProp = Object.defineProperty;
|
|
@@ -186,26 +188,26 @@ var buttonVariants = cva(
|
|
|
186
188
|
);
|
|
187
189
|
var variant_styles = {
|
|
188
190
|
default: {
|
|
189
|
-
backgroundColor: "var(--primary)",
|
|
190
|
-
color: "var(--primary-foreground)",
|
|
191
|
-
border: "1px solid var(--primary)"
|
|
191
|
+
backgroundColor: "hsl(var(--primary))",
|
|
192
|
+
color: "hsl(var(--primary-foreground))",
|
|
193
|
+
border: "1px solid hsl(var(--primary))"
|
|
192
194
|
},
|
|
193
195
|
destructive: {
|
|
194
|
-
backgroundColor: "var(--destructive)",
|
|
195
|
-
color: "
|
|
196
|
-
border: "1px solid var(--destructive)"
|
|
196
|
+
backgroundColor: "hsl(var(--destructive))",
|
|
197
|
+
color: "hsl(var(--destructive-foreground))",
|
|
198
|
+
border: "1px solid hsl(var(--destructive))"
|
|
197
199
|
},
|
|
198
200
|
outline: {
|
|
199
|
-
backgroundColor: "var(--background)",
|
|
200
|
-
color: "var(--foreground)",
|
|
201
|
-
border: "1px solid var(--border)"
|
|
201
|
+
backgroundColor: "hsl(var(--background))",
|
|
202
|
+
color: "hsl(var(--foreground))",
|
|
203
|
+
border: "1px solid hsl(var(--border))"
|
|
202
204
|
},
|
|
203
205
|
secondary: {
|
|
204
|
-
backgroundColor: "var(--secondary)",
|
|
205
|
-
color: "var(--secondary-foreground)"
|
|
206
|
+
backgroundColor: "hsl(var(--secondary))",
|
|
207
|
+
color: "hsl(var(--secondary-foreground))"
|
|
206
208
|
}
|
|
207
209
|
};
|
|
208
|
-
var Button =
|
|
210
|
+
var Button = React25.forwardRef(
|
|
209
211
|
({ className, variant, size, asChild = false, style, ...props }, ref) => {
|
|
210
212
|
const Comp = asChild ? Slot : "button";
|
|
211
213
|
const fallback_styles = variant_styles[variant ?? "default"] ?? {};
|
|
@@ -225,7 +227,7 @@ var Dialog = DialogPrimitive.Root;
|
|
|
225
227
|
var DialogTrigger = DialogPrimitive.Trigger;
|
|
226
228
|
var DialogPortal = DialogPrimitive.Portal;
|
|
227
229
|
var DialogClose = DialogPrimitive.Close;
|
|
228
|
-
var DialogOverlay =
|
|
230
|
+
var DialogOverlay = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
229
231
|
DialogPrimitive.Overlay,
|
|
230
232
|
{
|
|
231
233
|
ref,
|
|
@@ -237,14 +239,14 @@ var DialogOverlay = React27.forwardRef(({ className, ...props }, ref) => /* @__P
|
|
|
237
239
|
}
|
|
238
240
|
));
|
|
239
241
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
240
|
-
var DialogContent =
|
|
242
|
+
var DialogContent = React25.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
241
243
|
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
242
244
|
/* @__PURE__ */ jsxs(
|
|
243
245
|
DialogPrimitive.Content,
|
|
244
246
|
{
|
|
245
247
|
ref,
|
|
246
248
|
className: cn(
|
|
247
|
-
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95
|
|
249
|
+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-lg",
|
|
248
250
|
className
|
|
249
251
|
),
|
|
250
252
|
...props,
|
|
@@ -287,7 +289,7 @@ var DialogFooter = ({
|
|
|
287
289
|
}
|
|
288
290
|
);
|
|
289
291
|
DialogFooter.displayName = "DialogFooter";
|
|
290
|
-
var DialogTitle =
|
|
292
|
+
var DialogTitle = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
291
293
|
DialogPrimitive.Title,
|
|
292
294
|
{
|
|
293
295
|
ref,
|
|
@@ -300,7 +302,7 @@ var DialogTitle = React27.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
300
302
|
}
|
|
301
303
|
));
|
|
302
304
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
303
|
-
var DialogDescription =
|
|
305
|
+
var DialogDescription = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
304
306
|
DialogPrimitive.Description,
|
|
305
307
|
{
|
|
306
308
|
ref,
|
|
@@ -309,7 +311,7 @@ var DialogDescription = React27.forwardRef(({ className, ...props }, ref) => /*
|
|
|
309
311
|
}
|
|
310
312
|
));
|
|
311
313
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
312
|
-
var Command =
|
|
314
|
+
var Command = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
313
315
|
"div",
|
|
314
316
|
{
|
|
315
317
|
ref,
|
|
@@ -321,7 +323,7 @@ var Command = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
321
323
|
}
|
|
322
324
|
));
|
|
323
325
|
Command.displayName = "Command";
|
|
324
|
-
var CommandInput =
|
|
326
|
+
var CommandInput = React25.forwardRef(({ className, onValueChange, onChange, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
325
327
|
"input",
|
|
326
328
|
{
|
|
327
329
|
ref,
|
|
@@ -337,7 +339,7 @@ var CommandInput = React27.forwardRef(({ className, onValueChange, onChange, ...
|
|
|
337
339
|
}
|
|
338
340
|
));
|
|
339
341
|
CommandInput.displayName = "CommandInput";
|
|
340
|
-
var CommandList =
|
|
342
|
+
var CommandList = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
341
343
|
"div",
|
|
342
344
|
{
|
|
343
345
|
ref,
|
|
@@ -346,7 +348,7 @@ var CommandList = React27.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
346
348
|
}
|
|
347
349
|
));
|
|
348
350
|
CommandList.displayName = "CommandList";
|
|
349
|
-
var CommandEmpty =
|
|
351
|
+
var CommandEmpty = React25.forwardRef((props, ref) => /* @__PURE__ */ jsx(
|
|
350
352
|
"div",
|
|
351
353
|
{
|
|
352
354
|
ref,
|
|
@@ -355,7 +357,7 @@ var CommandEmpty = React27.forwardRef((props, ref) => /* @__PURE__ */ jsx(
|
|
|
355
357
|
}
|
|
356
358
|
));
|
|
357
359
|
CommandEmpty.displayName = "CommandEmpty";
|
|
358
|
-
var CommandGroup =
|
|
360
|
+
var CommandGroup = React25.forwardRef(({ className, heading, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
359
361
|
"div",
|
|
360
362
|
{
|
|
361
363
|
ref,
|
|
@@ -371,7 +373,7 @@ var CommandGroup = React27.forwardRef(({ className, heading, children, ...props
|
|
|
371
373
|
}
|
|
372
374
|
));
|
|
373
375
|
CommandGroup.displayName = "CommandGroup";
|
|
374
|
-
var CommandItem =
|
|
376
|
+
var CommandItem = React25.forwardRef(({ className, onSelect, value, selected, style, ...props }, ref) => {
|
|
375
377
|
const handleClick = () => {
|
|
376
378
|
if (onSelect && value) {
|
|
377
379
|
onSelect(value);
|
|
@@ -402,7 +404,7 @@ var CommandItem = React27.forwardRef(({ className, onSelect, value, selected, st
|
|
|
402
404
|
CommandItem.displayName = "CommandItem";
|
|
403
405
|
var Popover = PopoverPrimitive.Root;
|
|
404
406
|
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
405
|
-
var PopoverContent =
|
|
407
|
+
var PopoverContent = React25.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
406
408
|
PopoverPrimitive.Content,
|
|
407
409
|
{
|
|
408
410
|
ref,
|
|
@@ -416,7 +418,7 @@ var PopoverContent = React27.forwardRef(({ className, align = "center", sideOffs
|
|
|
416
418
|
}
|
|
417
419
|
) }));
|
|
418
420
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
419
|
-
var Input =
|
|
421
|
+
var Input = React25.forwardRef(
|
|
420
422
|
({ className, type, ...props }, ref) => {
|
|
421
423
|
return /* @__PURE__ */ jsx(
|
|
422
424
|
"input",
|
|
@@ -436,7 +438,7 @@ Input.displayName = "Input";
|
|
|
436
438
|
var Select = SelectPrimitive.Root;
|
|
437
439
|
var SelectGroup = SelectPrimitive.Group;
|
|
438
440
|
var SelectValue = SelectPrimitive.Value;
|
|
439
|
-
var SelectTrigger =
|
|
441
|
+
var SelectTrigger = React25.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
440
442
|
SelectPrimitive.Trigger,
|
|
441
443
|
{
|
|
442
444
|
ref,
|
|
@@ -452,7 +454,7 @@ var SelectTrigger = React27.forwardRef(({ className, children, ...props }, ref)
|
|
|
452
454
|
}
|
|
453
455
|
));
|
|
454
456
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
455
|
-
var SelectScrollUpButton =
|
|
457
|
+
var SelectScrollUpButton = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
456
458
|
SelectPrimitive.ScrollUpButton,
|
|
457
459
|
{
|
|
458
460
|
ref,
|
|
@@ -465,7 +467,7 @@ var SelectScrollUpButton = React27.forwardRef(({ className, ...props }, ref) =>
|
|
|
465
467
|
}
|
|
466
468
|
));
|
|
467
469
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
468
|
-
var SelectScrollDownButton =
|
|
470
|
+
var SelectScrollDownButton = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
469
471
|
SelectPrimitive.ScrollDownButton,
|
|
470
472
|
{
|
|
471
473
|
ref,
|
|
@@ -478,7 +480,7 @@ var SelectScrollDownButton = React27.forwardRef(({ className, ...props }, ref) =
|
|
|
478
480
|
}
|
|
479
481
|
));
|
|
480
482
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
481
|
-
var SelectContent =
|
|
483
|
+
var SelectContent = React25.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
482
484
|
SelectPrimitive.Content,
|
|
483
485
|
{
|
|
484
486
|
ref,
|
|
@@ -506,7 +508,7 @@ var SelectContent = React27.forwardRef(({ className, children, position = "poppe
|
|
|
506
508
|
}
|
|
507
509
|
) }));
|
|
508
510
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
509
|
-
var SelectLabel =
|
|
511
|
+
var SelectLabel = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
510
512
|
SelectPrimitive.Label,
|
|
511
513
|
{
|
|
512
514
|
ref,
|
|
@@ -515,7 +517,7 @@ var SelectLabel = React27.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
515
517
|
}
|
|
516
518
|
));
|
|
517
519
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
518
|
-
var SelectItem =
|
|
520
|
+
var SelectItem = React25.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
519
521
|
SelectPrimitive.Item,
|
|
520
522
|
{
|
|
521
523
|
ref,
|
|
@@ -531,7 +533,7 @@ var SelectItem = React27.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
531
533
|
}
|
|
532
534
|
));
|
|
533
535
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
534
|
-
var SelectSeparator =
|
|
536
|
+
var SelectSeparator = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
535
537
|
SelectPrimitive.Separator,
|
|
536
538
|
{
|
|
537
539
|
ref,
|
|
@@ -543,7 +545,7 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
|
543
545
|
var TooltipProvider = TooltipPrimitive.Provider;
|
|
544
546
|
var Tooltip = TooltipPrimitive.Root;
|
|
545
547
|
var TooltipTrigger = TooltipPrimitive.Trigger;
|
|
546
|
-
var TooltipContent =
|
|
548
|
+
var TooltipContent = React25.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
547
549
|
TooltipPrimitive.Content,
|
|
548
550
|
{
|
|
549
551
|
ref,
|
|
@@ -630,27 +632,27 @@ function FilterFieldItem({
|
|
|
630
632
|
placeholder: "Enter text...",
|
|
631
633
|
minLength: fieldConfig.textConfig?.minLength,
|
|
632
634
|
maxLength: fieldConfig.textConfig?.maxLength,
|
|
633
|
-
className: "cls_filter_text_input w-full min-w-0"
|
|
635
|
+
className: "cls_filter_text_input h-8 w-full min-w-0 text-sm"
|
|
634
636
|
}
|
|
635
637
|
);
|
|
636
|
-
case "number":
|
|
638
|
+
case "number": {
|
|
637
639
|
const numberOperators = [
|
|
638
|
-
{ value: "equals", label: "
|
|
639
|
-
{ value: "not_equals", label: "
|
|
640
|
-
{ value: "greater_than", label: "
|
|
641
|
-
{ value: "less_than", label: "
|
|
642
|
-
{ value: "greater_equal", label: "
|
|
643
|
-
{ value: "less_equal", label: "
|
|
640
|
+
{ value: "equals", label: "=" },
|
|
641
|
+
{ value: "not_equals", label: "\u2260" },
|
|
642
|
+
{ value: "greater_than", label: ">" },
|
|
643
|
+
{ value: "less_than", label: "<" },
|
|
644
|
+
{ value: "greater_equal", label: "\u2265" },
|
|
645
|
+
{ value: "less_equal", label: "\u2264" }
|
|
644
646
|
];
|
|
645
|
-
return /* @__PURE__ */ jsxs("div", { className: "cls_number_filter_container flex
|
|
647
|
+
return /* @__PURE__ */ jsxs("div", { className: "cls_number_filter_container flex w-full items-center gap-1.5", children: [
|
|
646
648
|
/* @__PURE__ */ jsxs(
|
|
647
649
|
Select,
|
|
648
650
|
{
|
|
649
651
|
value: filterConfig.operator || "equals",
|
|
650
652
|
onValueChange: (value) => onOperatorChange?.(value),
|
|
651
653
|
children: [
|
|
652
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "cls_operator_select
|
|
653
|
-
/* @__PURE__ */ jsx(SelectContent, { children: numberOperators.map((op) => /* @__PURE__ */ jsx(SelectItem, { value: op.value, children: op.label }, op.value)) })
|
|
654
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "cls_operator_select h-8 w-[60px] shrink-0 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
655
|
+
/* @__PURE__ */ jsx(SelectContent, { children: numberOperators.map((op) => /* @__PURE__ */ jsx(SelectItem, { value: op.value, children: /* @__PURE__ */ jsx("span", { className: "font-mono", children: op.label }) }, op.value)) })
|
|
654
656
|
]
|
|
655
657
|
}
|
|
656
658
|
),
|
|
@@ -666,14 +668,10 @@ function FilterFieldItem({
|
|
|
666
668
|
return;
|
|
667
669
|
}
|
|
668
670
|
let numValue = fieldConfig.numberConfig?.allowDecimal ? parseFloat(value) : parseInt(value, 10);
|
|
669
|
-
if (isNaN(numValue))
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
671
|
+
if (isNaN(numValue)) return;
|
|
672
672
|
if (fieldConfig.numberConfig?.allowDecimal && fieldConfig.numberConfig?.decimalLength) {
|
|
673
673
|
const decimalPlaces = value.split(".")[1]?.length || 0;
|
|
674
|
-
if (decimalPlaces > fieldConfig.numberConfig.decimalLength)
|
|
675
|
-
return;
|
|
676
|
-
}
|
|
674
|
+
if (decimalPlaces > fieldConfig.numberConfig.decimalLength) return;
|
|
677
675
|
}
|
|
678
676
|
if (fieldConfig.numberConfig?.min !== void 0 && numValue < fieldConfig.numberConfig.min) {
|
|
679
677
|
numValue = fieldConfig.numberConfig.min;
|
|
@@ -683,14 +681,15 @@ function FilterFieldItem({
|
|
|
683
681
|
}
|
|
684
682
|
onValueChange(numValue);
|
|
685
683
|
},
|
|
686
|
-
placeholder: "
|
|
684
|
+
placeholder: "Value",
|
|
687
685
|
min: fieldConfig.numberConfig?.min,
|
|
688
686
|
max: fieldConfig.numberConfig?.max,
|
|
689
687
|
step: fieldConfig.numberConfig?.allowDecimal ? 0.01 : 1,
|
|
690
|
-
className: "cls_filter_number_input flex-1 min-w-0"
|
|
688
|
+
className: "cls_filter_number_input h-8 flex-1 min-w-0 text-sm tabular-nums"
|
|
691
689
|
}
|
|
692
690
|
)
|
|
693
691
|
] });
|
|
692
|
+
}
|
|
694
693
|
case "combobox":
|
|
695
694
|
return /* @__PURE__ */ jsxs(
|
|
696
695
|
Select,
|
|
@@ -698,12 +697,12 @@ function FilterFieldItem({
|
|
|
698
697
|
value: filterConfig.value || "",
|
|
699
698
|
onValueChange: (value) => onValueChange(value),
|
|
700
699
|
children: [
|
|
701
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "cls_filter_combobox_select w-full min-w-0", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select option..." }) }),
|
|
700
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "cls_filter_combobox_select h-8 w-full min-w-0 text-sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select option..." }) }),
|
|
702
701
|
/* @__PURE__ */ jsx(SelectContent, { children: fieldConfig.comboboxOptions?.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
703
702
|
]
|
|
704
703
|
}
|
|
705
704
|
);
|
|
706
|
-
case "boolean":
|
|
705
|
+
case "boolean": {
|
|
707
706
|
const trueLabel = fieldConfig.booleanLabels?.trueLabel || "On";
|
|
708
707
|
const falseLabel = fieldConfig.booleanLabels?.falseLabel || "Off";
|
|
709
708
|
return /* @__PURE__ */ jsxs(
|
|
@@ -712,7 +711,7 @@ function FilterFieldItem({
|
|
|
712
711
|
value: filterConfig.value !== void 0 && filterConfig.value !== null ? String(filterConfig.value) : "",
|
|
713
712
|
onValueChange: (value) => onValueChange(value === "true"),
|
|
714
713
|
children: [
|
|
715
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "cls_filter_boolean_select w-full min-w-0", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select..." }) }),
|
|
714
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "cls_filter_boolean_select h-8 w-full min-w-0 text-sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select..." }) }),
|
|
716
715
|
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
717
716
|
/* @__PURE__ */ jsx(SelectItem, { value: "true", children: trueLabel }),
|
|
718
717
|
/* @__PURE__ */ jsx(SelectItem, { value: "false", children: falseLabel })
|
|
@@ -720,25 +719,26 @@ function FilterFieldItem({
|
|
|
720
719
|
]
|
|
721
720
|
}
|
|
722
721
|
);
|
|
723
|
-
|
|
722
|
+
}
|
|
723
|
+
case "date": {
|
|
724
724
|
const dateOperators = [
|
|
725
|
-
{ value: "equals", label: "
|
|
726
|
-
{ value: "not_equals", label: "
|
|
727
|
-
{ value: "greater_than", label: "
|
|
728
|
-
{ value: "less_than", label: "
|
|
729
|
-
{ value: "greater_equal", label: "
|
|
730
|
-
{ value: "less_equal", label: "
|
|
725
|
+
{ value: "equals", label: "=" },
|
|
726
|
+
{ value: "not_equals", label: "\u2260" },
|
|
727
|
+
{ value: "greater_than", label: ">" },
|
|
728
|
+
{ value: "less_than", label: "<" },
|
|
729
|
+
{ value: "greater_equal", label: "\u2265" },
|
|
730
|
+
{ value: "less_equal", label: "\u2264" }
|
|
731
731
|
];
|
|
732
732
|
const selectedDate = filterConfig.value ? typeof filterConfig.value === "string" ? new Date(filterConfig.value) : filterConfig.value : void 0;
|
|
733
|
-
return /* @__PURE__ */ jsxs("div", { className: "cls_date_filter_container flex
|
|
733
|
+
return /* @__PURE__ */ jsxs("div", { className: "cls_date_filter_container flex w-full items-center gap-1.5", children: [
|
|
734
734
|
/* @__PURE__ */ jsxs(
|
|
735
735
|
Select,
|
|
736
736
|
{
|
|
737
737
|
value: filterConfig.operator || "equals",
|
|
738
738
|
onValueChange: (value) => onOperatorChange?.(value),
|
|
739
739
|
children: [
|
|
740
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "cls_operator_select
|
|
741
|
-
/* @__PURE__ */ jsx(SelectContent, { children: dateOperators.map((op) => /* @__PURE__ */ jsx(SelectItem, { value: op.value, children: op.label }, op.value)) })
|
|
740
|
+
/* @__PURE__ */ jsx(SelectTrigger, { className: "cls_operator_select h-8 w-[60px] shrink-0 text-sm", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
741
|
+
/* @__PURE__ */ jsx(SelectContent, { children: dateOperators.map((op) => /* @__PURE__ */ jsx(SelectItem, { value: op.value, children: /* @__PURE__ */ jsx("span", { className: "font-mono", children: op.label }) }, op.value)) })
|
|
742
742
|
]
|
|
743
743
|
}
|
|
744
744
|
),
|
|
@@ -748,11 +748,11 @@ function FilterFieldItem({
|
|
|
748
748
|
{
|
|
749
749
|
variant: "outline",
|
|
750
750
|
className: cn(
|
|
751
|
-
"cls_date_picker_trigger
|
|
751
|
+
"cls_date_picker_trigger h-8 flex-1 justify-start gap-2 px-2.5 text-left text-sm font-normal min-w-0",
|
|
752
752
|
!selectedDate && "text-muted-foreground"
|
|
753
753
|
),
|
|
754
754
|
children: [
|
|
755
|
-
/* @__PURE__ */ jsx(Calendar$1, { className: "cls_calendar_icon
|
|
755
|
+
/* @__PURE__ */ jsx(Calendar$1, { className: "cls_calendar_icon h-3.5 w-3.5 shrink-0" }),
|
|
756
756
|
/* @__PURE__ */ jsx("span", { className: "cls_date_text truncate", children: selectedDate ? format(selectedDate, "MMM d, yyyy") : "Pick a date" })
|
|
757
757
|
]
|
|
758
758
|
}
|
|
@@ -771,24 +771,27 @@ function FilterFieldItem({
|
|
|
771
771
|
) })
|
|
772
772
|
] })
|
|
773
773
|
] });
|
|
774
|
+
}
|
|
774
775
|
default:
|
|
775
776
|
return null;
|
|
776
777
|
}
|
|
777
778
|
};
|
|
778
|
-
return /* @__PURE__ */ jsxs("div", { className: "cls_filter_field_item flex flex-col
|
|
779
|
-
/* @__PURE__ */ jsx("span", { className: "cls_field_label text-
|
|
780
|
-
/* @__PURE__ */
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
779
|
+
return /* @__PURE__ */ jsxs("div", { className: "cls_filter_field_item group flex flex-col gap-2 rounded-lg border border-border/70 bg-card px-3 py-2.5 transition-colors hover:border-border sm:flex-row sm:items-center sm:gap-3", children: [
|
|
780
|
+
/* @__PURE__ */ jsx("span", { className: "cls_field_label w-full shrink-0 truncate text-xs font-semibold uppercase tracking-wide text-muted-foreground sm:w-[110px] sm:text-sm sm:normal-case sm:font-medium sm:text-foreground sm:tracking-normal", children: fieldConfig.label }),
|
|
781
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_field_input_container flex min-w-0 flex-1 items-center gap-2", children: [
|
|
782
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: renderInput() }),
|
|
783
|
+
/* @__PURE__ */ jsx(
|
|
784
|
+
Button,
|
|
785
|
+
{
|
|
786
|
+
variant: "ghost",
|
|
787
|
+
size: "sm",
|
|
788
|
+
onClick: onDelete,
|
|
789
|
+
className: "cls_delete_btn h-7 w-7 shrink-0 p-0 text-muted-foreground/60 hover:bg-destructive/10 hover:text-destructive",
|
|
790
|
+
"aria-label": `Remove ${fieldConfig.label} filter`,
|
|
791
|
+
children: /* @__PURE__ */ jsx(X, { className: "cls_delete_icon h-3.5 w-3.5" })
|
|
792
|
+
}
|
|
793
|
+
)
|
|
794
|
+
] })
|
|
792
795
|
] });
|
|
793
796
|
}
|
|
794
797
|
function HazoUiMultiFilterDialog({
|
|
@@ -796,7 +799,7 @@ function HazoUiMultiFilterDialog({
|
|
|
796
799
|
onFilterChange,
|
|
797
800
|
initialFilters = [],
|
|
798
801
|
title = "Filter",
|
|
799
|
-
description = "Add
|
|
802
|
+
description = "Add fields to filter by. Select a field and set its value.",
|
|
800
803
|
headerBackgroundColor,
|
|
801
804
|
headerTextColor,
|
|
802
805
|
submitButtonBackgroundColor,
|
|
@@ -846,13 +849,9 @@ function HazoUiMultiFilterDialog({
|
|
|
846
849
|
}
|
|
847
850
|
}, [isOpen, initialFilters]);
|
|
848
851
|
const handleAddField = (fieldValue) => {
|
|
849
|
-
if (filterFields.some((ff) => ff.field === fieldValue))
|
|
850
|
-
return;
|
|
851
|
-
}
|
|
852
|
+
if (filterFields.some((ff) => ff.field === fieldValue)) return;
|
|
852
853
|
const fieldConfig = availableFields.find((af) => af.value === fieldValue);
|
|
853
|
-
if (!fieldConfig)
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
854
|
+
if (!fieldConfig) return;
|
|
856
855
|
let defaultValue = "";
|
|
857
856
|
if (fieldConfig.type === "boolean") {
|
|
858
857
|
defaultValue = false;
|
|
@@ -905,7 +904,7 @@ function HazoUiMultiFilterDialog({
|
|
|
905
904
|
};
|
|
906
905
|
const hasActiveFilters = initialFilters.length > 0;
|
|
907
906
|
const tooltipContent = hasActiveFilters ? /* @__PURE__ */ jsxs("div", { className: "cls_filter_tooltip_content space-y-1", children: [
|
|
908
|
-
/* @__PURE__ */ jsx("div", { className: "cls_tooltip_title text-xs font-semibold mb-1", children: "Active
|
|
907
|
+
/* @__PURE__ */ jsx("div", { className: "cls_tooltip_title text-xs font-semibold mb-1", children: "Active filters" }),
|
|
909
908
|
initialFilters.map((filterConfig) => {
|
|
910
909
|
const fieldConfig = getFieldConfig(filterConfig.field);
|
|
911
910
|
if (!fieldConfig) return null;
|
|
@@ -949,152 +948,114 @@ function HazoUiMultiFilterDialog({
|
|
|
949
948
|
)
|
|
950
949
|
}
|
|
951
950
|
),
|
|
952
|
-
"Filter"
|
|
951
|
+
"Filter",
|
|
952
|
+
hasActiveFilters && /* @__PURE__ */ jsx("span", { className: "cls_filter_count ml-2 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-blue-600 px-1 text-[10px] font-semibold text-white", children: initialFilters.length })
|
|
953
953
|
]
|
|
954
954
|
}
|
|
955
955
|
) }) }),
|
|
956
956
|
/* @__PURE__ */ jsx(TooltipContent, { children: tooltipContent })
|
|
957
957
|
] }) }),
|
|
958
|
-
/* @__PURE__ */ jsxs(DialogContent, { className: "cls_filter_dialog_content max-w-lg
|
|
959
|
-
/* @__PURE__ */ jsxs(
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
958
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "cls_filter_dialog_content max-w-lg gap-0 p-0 sm:rounded-xl max-h-[90vh]", children: [
|
|
959
|
+
/* @__PURE__ */ jsxs(
|
|
960
|
+
DialogHeader,
|
|
961
|
+
{
|
|
962
|
+
className: "cls_filter_dialog_header space-y-1 border-b px-5 py-4 text-left",
|
|
963
|
+
style: headerStyles,
|
|
964
|
+
children: [
|
|
965
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "text-base font-semibold", children: title }),
|
|
966
|
+
/* @__PURE__ */ jsx(DialogDescription, { className: "text-xs leading-relaxed text-muted-foreground", children: description })
|
|
967
|
+
]
|
|
968
|
+
}
|
|
969
|
+
),
|
|
970
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_filter_dialog_body space-y-3 overflow-y-auto px-5 py-4", children: [
|
|
971
|
+
filterFields.length > 0 ? /* @__PURE__ */ jsx("div", { className: "cls_filter_fields_list space-y-1.5", children: filterFields.map((filterConfig) => {
|
|
972
|
+
const fieldConfig = getFieldConfig(filterConfig.field);
|
|
973
|
+
if (!fieldConfig) return null;
|
|
974
|
+
return /* @__PURE__ */ jsx(
|
|
975
|
+
FilterFieldItem,
|
|
976
|
+
{
|
|
977
|
+
filterConfig,
|
|
978
|
+
fieldConfig,
|
|
979
|
+
onValueChange: (value) => handleValueChange(filterConfig.field, value),
|
|
980
|
+
onOperatorChange: (operator) => handleOperatorChange(filterConfig.field, operator),
|
|
981
|
+
onDelete: () => handleDeleteField(filterConfig.field)
|
|
982
|
+
},
|
|
983
|
+
filterConfig.field
|
|
984
|
+
);
|
|
985
|
+
}) }) : /* @__PURE__ */ jsx("div", { className: "cls_empty_filter_fields rounded-lg border border-dashed border-border/70 bg-muted/20 px-4 py-6 text-center text-xs text-muted-foreground", children: "No filters yet. Add one below to narrow down the results." }),
|
|
964
986
|
/* @__PURE__ */ jsx("div", { className: "cls_add_field_section", children: /* @__PURE__ */ jsxs(Popover, { open: isComboboxOpen, onOpenChange: setIsComboboxOpen, children: [
|
|
965
987
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
966
988
|
Button,
|
|
967
989
|
{
|
|
968
|
-
variant: "
|
|
990
|
+
variant: "ghost",
|
|
969
991
|
role: "combobox",
|
|
970
992
|
"aria-expanded": isComboboxOpen,
|
|
971
|
-
|
|
993
|
+
disabled: availableFieldsToAdd.length === 0,
|
|
994
|
+
className: "cls_add_field_combobox w-full justify-start gap-2 border border-dashed border-border/70 text-sm font-medium text-muted-foreground hover:border-border hover:bg-muted/40 hover:text-foreground",
|
|
972
995
|
children: [
|
|
973
|
-
/* @__PURE__ */
|
|
974
|
-
|
|
975
|
-
/* @__PURE__ */ jsx("span", { children: "Add field" })
|
|
976
|
-
] }),
|
|
977
|
-
/* @__PURE__ */ jsx(ChevronsUpDown, { className: "cls_chevron_icon ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
996
|
+
/* @__PURE__ */ jsx(Plus, { className: "cls_plus_icon h-4 w-4" }),
|
|
997
|
+
/* @__PURE__ */ jsx("span", { children: availableFieldsToAdd.length === 0 ? "All fields added" : "Add filter field" })
|
|
978
998
|
]
|
|
979
999
|
}
|
|
980
1000
|
) }),
|
|
981
|
-
/* @__PURE__ */ jsx(PopoverContent, { className: "cls_combobox_popover w-
|
|
1001
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "cls_combobox_popover w-[var(--radix-popover-trigger-width)] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
|
|
982
1002
|
/* @__PURE__ */ jsx(CommandInput, { placeholder: "Search fields...", className: "cls_command_input" }),
|
|
983
|
-
/* @__PURE__ */ jsx(CommandList, { children: availableFieldsToAdd.length === 0 ? /* @__PURE__ */ jsx(CommandEmpty, { children: "No fields
|
|
1003
|
+
/* @__PURE__ */ jsx(CommandList, { children: availableFieldsToAdd.length === 0 ? /* @__PURE__ */ jsx(CommandEmpty, { children: "No fields available." }) : /* @__PURE__ */ jsx(CommandGroup, { children: availableFieldsToAdd.map((field) => /* @__PURE__ */ jsx(
|
|
984
1004
|
CommandItem,
|
|
985
1005
|
{
|
|
986
1006
|
value: field.label,
|
|
987
1007
|
onSelect: () => handleAddField(field.value),
|
|
988
1008
|
className: "cls_command_item",
|
|
989
|
-
children:
|
|
990
|
-
/* @__PURE__ */ jsx(
|
|
991
|
-
Check,
|
|
992
|
-
{
|
|
993
|
-
className: cn(
|
|
994
|
-
"cls_check_icon mr-2 h-4 w-4",
|
|
995
|
-
"opacity-0"
|
|
996
|
-
)
|
|
997
|
-
}
|
|
998
|
-
),
|
|
999
|
-
field.label
|
|
1000
|
-
]
|
|
1009
|
+
children: field.label
|
|
1001
1010
|
},
|
|
1002
1011
|
field.value
|
|
1003
1012
|
)) }) })
|
|
1004
1013
|
] }) })
|
|
1005
|
-
] }) })
|
|
1006
|
-
filterFields.length > 0 ? /* @__PURE__ */ jsx("div", { className: "cls_filter_fields_list space-y-2", children: filterFields.map((filterConfig) => {
|
|
1007
|
-
const fieldConfig = getFieldConfig(filterConfig.field);
|
|
1008
|
-
if (!fieldConfig) return null;
|
|
1009
|
-
return /* @__PURE__ */ jsx(
|
|
1010
|
-
FilterFieldItem,
|
|
1011
|
-
{
|
|
1012
|
-
filterConfig,
|
|
1013
|
-
fieldConfig,
|
|
1014
|
-
onValueChange: (value) => handleValueChange(filterConfig.field, value),
|
|
1015
|
-
onOperatorChange: (operator) => handleOperatorChange(filterConfig.field, operator),
|
|
1016
|
-
onDelete: () => handleDeleteField(filterConfig.field)
|
|
1017
|
-
},
|
|
1018
|
-
filterConfig.field
|
|
1019
|
-
);
|
|
1020
|
-
}) }) : /* @__PURE__ */ jsx("div", { className: "cls_empty_filter_fields text-center py-8 text-sm text-muted-foreground", children: 'No filter fields added. Click "Add field" to add filtering criteria.' })
|
|
1014
|
+
] }) })
|
|
1021
1015
|
] }),
|
|
1022
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
1023
|
-
filterFields.length > 0 && /* @__PURE__ */
|
|
1016
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "cls_filter_dialog_footer flex flex-row items-center justify-between gap-2 border-t bg-muted/20 px-5 py-3 sm:justify-between sm:space-x-0", children: [
|
|
1017
|
+
/* @__PURE__ */ jsx("div", { className: "cls_footer_left", children: filterFields.length > 0 && /* @__PURE__ */ jsx(
|
|
1024
1018
|
Button,
|
|
1025
1019
|
{
|
|
1026
|
-
variant: "
|
|
1020
|
+
variant: "ghost",
|
|
1021
|
+
size: "sm",
|
|
1027
1022
|
onClick: handleClearAll,
|
|
1028
|
-
className: "cls_clear_all_btn",
|
|
1023
|
+
className: "cls_clear_all_btn text-muted-foreground hover:text-foreground",
|
|
1029
1024
|
style: clearButtonStyles,
|
|
1030
|
-
children:
|
|
1031
|
-
/* @__PURE__ */ jsx(X, { className: "cls_clear_all_icon h-4 w-4 mr-2" }),
|
|
1032
|
-
"Clear All"
|
|
1033
|
-
]
|
|
1034
|
-
}
|
|
1035
|
-
),
|
|
1036
|
-
/* @__PURE__ */ jsx(
|
|
1037
|
-
Button,
|
|
1038
|
-
{
|
|
1039
|
-
onClick: handleApply,
|
|
1040
|
-
className: "cls_apply_btn",
|
|
1041
|
-
style: submitButtonStyles,
|
|
1042
|
-
children: "Apply"
|
|
1043
|
-
}
|
|
1044
|
-
),
|
|
1045
|
-
/* @__PURE__ */ jsx(
|
|
1046
|
-
Button,
|
|
1047
|
-
{
|
|
1048
|
-
variant: "outline",
|
|
1049
|
-
onClick: handleCancel,
|
|
1050
|
-
className: "cls_cancel_btn",
|
|
1051
|
-
style: cancelButtonStyles,
|
|
1052
|
-
children: "Cancel"
|
|
1025
|
+
children: "Clear all"
|
|
1053
1026
|
}
|
|
1054
|
-
)
|
|
1027
|
+
) }),
|
|
1028
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_footer_right flex items-center gap-2", children: [
|
|
1029
|
+
/* @__PURE__ */ jsx(
|
|
1030
|
+
Button,
|
|
1031
|
+
{
|
|
1032
|
+
variant: "outline",
|
|
1033
|
+
size: "sm",
|
|
1034
|
+
onClick: handleCancel,
|
|
1035
|
+
className: "cls_cancel_btn",
|
|
1036
|
+
style: cancelButtonStyles,
|
|
1037
|
+
children: "Cancel"
|
|
1038
|
+
}
|
|
1039
|
+
),
|
|
1040
|
+
/* @__PURE__ */ jsx(
|
|
1041
|
+
Button,
|
|
1042
|
+
{
|
|
1043
|
+
size: "sm",
|
|
1044
|
+
onClick: handleApply,
|
|
1045
|
+
className: "cls_apply_btn",
|
|
1046
|
+
style: submitButtonStyles,
|
|
1047
|
+
children: "Apply"
|
|
1048
|
+
}
|
|
1049
|
+
)
|
|
1050
|
+
] })
|
|
1055
1051
|
] })
|
|
1056
1052
|
] })
|
|
1057
1053
|
] });
|
|
1058
1054
|
}
|
|
1059
|
-
var Switch = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1060
|
-
SwitchPrimitives.Root,
|
|
1061
|
-
{
|
|
1062
|
-
className: cn(
|
|
1063
|
-
"peer inline-flex h-6 w-11 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",
|
|
1064
|
-
className
|
|
1065
|
-
),
|
|
1066
|
-
...props,
|
|
1067
|
-
ref,
|
|
1068
|
-
children: /* @__PURE__ */ jsx(
|
|
1069
|
-
SwitchPrimitives.Thumb,
|
|
1070
|
-
{
|
|
1071
|
-
className: cn(
|
|
1072
|
-
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
|
|
1073
|
-
)
|
|
1074
|
-
}
|
|
1075
|
-
)
|
|
1076
|
-
}
|
|
1077
|
-
));
|
|
1078
|
-
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
1079
|
-
var Label2 = React27.forwardRef(
|
|
1080
|
-
({ className, ...props }, ref) => {
|
|
1081
|
-
return /* @__PURE__ */ jsx(
|
|
1082
|
-
"label",
|
|
1083
|
-
{
|
|
1084
|
-
ref,
|
|
1085
|
-
className: cn(
|
|
1086
|
-
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
1087
|
-
className
|
|
1088
|
-
),
|
|
1089
|
-
...props
|
|
1090
|
-
}
|
|
1091
|
-
);
|
|
1092
|
-
}
|
|
1093
|
-
);
|
|
1094
|
-
Label2.displayName = "Label";
|
|
1095
1055
|
function SortableSortFieldItem({
|
|
1096
1056
|
sortConfig,
|
|
1097
1057
|
fieldLabel,
|
|
1058
|
+
priority,
|
|
1098
1059
|
onDirectionChange,
|
|
1099
1060
|
onDelete
|
|
1100
1061
|
}) {
|
|
@@ -1109,46 +1070,88 @@ function SortableSortFieldItem({
|
|
|
1109
1070
|
const style = {
|
|
1110
1071
|
transform: CSS.Transform.toString(transform),
|
|
1111
1072
|
transition,
|
|
1112
|
-
opacity: isDragging ? 0.
|
|
1073
|
+
opacity: isDragging ? 0.6 : 1,
|
|
1074
|
+
zIndex: isDragging ? 10 : void 0
|
|
1113
1075
|
};
|
|
1114
1076
|
return /* @__PURE__ */ jsxs(
|
|
1115
1077
|
"div",
|
|
1116
1078
|
{
|
|
1117
1079
|
ref: setNodeRef,
|
|
1118
1080
|
style,
|
|
1119
|
-
className:
|
|
1081
|
+
className: cn(
|
|
1082
|
+
"cls_sortable_sort_field_item group flex items-center gap-2.5 rounded-lg border border-border/70 bg-card pl-1.5 pr-2 py-2 transition-shadow",
|
|
1083
|
+
isDragging ? "shadow-md" : "hover:border-border"
|
|
1084
|
+
),
|
|
1120
1085
|
children: [
|
|
1121
1086
|
/* @__PURE__ */ jsx(
|
|
1122
|
-
"
|
|
1087
|
+
"button",
|
|
1123
1088
|
{
|
|
1089
|
+
type: "button",
|
|
1124
1090
|
...attributes,
|
|
1125
1091
|
...listeners,
|
|
1126
|
-
className: "cls_drag_handle cursor-grab
|
|
1092
|
+
className: "cls_drag_handle flex h-7 w-5 shrink-0 cursor-grab items-center justify-center rounded text-muted-foreground/60 hover:text-foreground active:cursor-grabbing",
|
|
1093
|
+
"aria-label": `Reorder ${fieldLabel}`,
|
|
1127
1094
|
children: /* @__PURE__ */ jsx(GripVertical, { className: "cls_drag_icon h-4 w-4" })
|
|
1128
1095
|
}
|
|
1129
1096
|
),
|
|
1130
|
-
/* @__PURE__ */ jsx(
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1097
|
+
/* @__PURE__ */ jsx(
|
|
1098
|
+
"span",
|
|
1099
|
+
{
|
|
1100
|
+
className: "cls_priority_badge inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-muted text-[10px] font-semibold tabular-nums text-muted-foreground",
|
|
1101
|
+
"aria-label": `Sort priority ${priority}`,
|
|
1102
|
+
children: priority
|
|
1103
|
+
}
|
|
1104
|
+
),
|
|
1105
|
+
/* @__PURE__ */ jsx("span", { className: "cls_field_label flex-1 truncate text-sm font-medium text-foreground", children: fieldLabel }),
|
|
1106
|
+
/* @__PURE__ */ jsxs(
|
|
1107
|
+
"div",
|
|
1108
|
+
{
|
|
1109
|
+
role: "radiogroup",
|
|
1110
|
+
"aria-label": `Sort direction for ${fieldLabel}`,
|
|
1111
|
+
className: "cls_direction_control inline-flex shrink-0 items-center rounded-md border border-border/70 bg-muted/40 p-0.5",
|
|
1112
|
+
children: [
|
|
1113
|
+
/* @__PURE__ */ jsxs(
|
|
1114
|
+
"button",
|
|
1115
|
+
{
|
|
1116
|
+
type: "button",
|
|
1117
|
+
role: "radio",
|
|
1118
|
+
"aria-checked": sortConfig.direction === "asc",
|
|
1119
|
+
"data-active": sortConfig.direction === "asc",
|
|
1120
|
+
onClick: () => onDirectionChange("asc"),
|
|
1121
|
+
className: "cls_dir_asc inline-flex items-center gap-1 rounded px-2 py-1 text-xs font-medium text-muted-foreground transition-colors data-[active=true]:bg-background data-[active=true]:text-foreground data-[active=true]:shadow-sm hover:text-foreground",
|
|
1122
|
+
children: [
|
|
1123
|
+
/* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3" }),
|
|
1124
|
+
"Asc"
|
|
1125
|
+
]
|
|
1126
|
+
}
|
|
1127
|
+
),
|
|
1128
|
+
/* @__PURE__ */ jsxs(
|
|
1129
|
+
"button",
|
|
1130
|
+
{
|
|
1131
|
+
type: "button",
|
|
1132
|
+
role: "radio",
|
|
1133
|
+
"aria-checked": sortConfig.direction === "desc",
|
|
1134
|
+
"data-active": sortConfig.direction === "desc",
|
|
1135
|
+
onClick: () => onDirectionChange("desc"),
|
|
1136
|
+
className: "cls_dir_desc inline-flex items-center gap-1 rounded px-2 py-1 text-xs font-medium text-muted-foreground transition-colors data-[active=true]:bg-background data-[active=true]:text-foreground data-[active=true]:shadow-sm hover:text-foreground",
|
|
1137
|
+
children: [
|
|
1138
|
+
/* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3" }),
|
|
1139
|
+
"Desc"
|
|
1140
|
+
]
|
|
1141
|
+
}
|
|
1142
|
+
)
|
|
1143
|
+
]
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1143
1146
|
/* @__PURE__ */ jsx(
|
|
1144
1147
|
Button,
|
|
1145
1148
|
{
|
|
1146
1149
|
variant: "ghost",
|
|
1147
1150
|
size: "sm",
|
|
1148
1151
|
onClick: onDelete,
|
|
1149
|
-
className: "cls_delete_btn h-
|
|
1152
|
+
className: "cls_delete_btn h-7 w-7 shrink-0 p-0 text-muted-foreground/60 hover:bg-destructive/10 hover:text-destructive",
|
|
1150
1153
|
"aria-label": `Remove ${fieldLabel} from sort`,
|
|
1151
|
-
children: /* @__PURE__ */ jsx(
|
|
1154
|
+
children: /* @__PURE__ */ jsx(X, { className: "cls_delete_icon h-3.5 w-3.5" })
|
|
1152
1155
|
}
|
|
1153
1156
|
)
|
|
1154
1157
|
]
|
|
@@ -1160,7 +1163,7 @@ function HazoUiMultiSortDialog({
|
|
|
1160
1163
|
onSortChange,
|
|
1161
1164
|
initialSortFields = [],
|
|
1162
1165
|
title = "Sort",
|
|
1163
|
-
description = "Add
|
|
1166
|
+
description = "Add fields to sort by, drag to reorder, toggle ascending or descending.",
|
|
1164
1167
|
headerBackgroundColor,
|
|
1165
1168
|
headerTextColor,
|
|
1166
1169
|
submitButtonBackgroundColor,
|
|
@@ -1205,7 +1208,7 @@ function HazoUiMultiSortDialog({
|
|
|
1205
1208
|
const [sortFields, setSortFields] = useState(initialSortFields);
|
|
1206
1209
|
const [isComboboxOpen, setIsComboboxOpen] = useState(false);
|
|
1207
1210
|
const sensors = useSensors(
|
|
1208
|
-
useSensor(PointerSensor),
|
|
1211
|
+
useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),
|
|
1209
1212
|
useSensor(KeyboardSensor, {
|
|
1210
1213
|
coordinateGetter: sortableKeyboardCoordinates
|
|
1211
1214
|
})
|
|
@@ -1219,11 +1222,7 @@ function HazoUiMultiSortDialog({
|
|
|
1219
1222
|
if (sortFields.some((sf) => sf.field === fieldValue)) {
|
|
1220
1223
|
return;
|
|
1221
1224
|
}
|
|
1222
|
-
|
|
1223
|
-
field: fieldValue,
|
|
1224
|
-
direction: "asc"
|
|
1225
|
-
};
|
|
1226
|
-
setSortFields([...sortFields, newField]);
|
|
1225
|
+
setSortFields([...sortFields, { field: fieldValue, direction: "asc" }]);
|
|
1227
1226
|
setIsComboboxOpen(false);
|
|
1228
1227
|
};
|
|
1229
1228
|
const handleDeleteField = (fieldValue) => {
|
|
@@ -1238,9 +1237,7 @@ function HazoUiMultiSortDialog({
|
|
|
1238
1237
|
};
|
|
1239
1238
|
const handleDragEnd = (event) => {
|
|
1240
1239
|
const { active, over } = event;
|
|
1241
|
-
if (!over || active.id === over.id)
|
|
1242
|
-
return;
|
|
1243
|
-
}
|
|
1240
|
+
if (!over || active.id === over.id) return;
|
|
1244
1241
|
const oldIndex = sortFields.findIndex((sf) => sf.field === active.id);
|
|
1245
1242
|
const newIndex = sortFields.findIndex((sf) => sf.field === over.id);
|
|
1246
1243
|
if (oldIndex !== -1 && newIndex !== -1) {
|
|
@@ -1266,7 +1263,7 @@ function HazoUiMultiSortDialog({
|
|
|
1266
1263
|
};
|
|
1267
1264
|
const hasActiveSorts = initialSortFields.length > 0;
|
|
1268
1265
|
const tooltipContent = hasActiveSorts ? /* @__PURE__ */ jsxs("div", { className: "cls_sort_tooltip_content space-y-1", children: [
|
|
1269
|
-
/* @__PURE__ */ jsx("div", { className: "cls_tooltip_title text-xs font-semibold mb-1", children: "Active
|
|
1266
|
+
/* @__PURE__ */ jsx("div", { className: "cls_tooltip_title text-xs font-semibold mb-1", children: "Active sorts" }),
|
|
1270
1267
|
initialSortFields.map((sortConfig, index) => /* @__PURE__ */ jsxs("div", { className: "cls_tooltip_item text-xs", children: [
|
|
1271
1268
|
index + 1,
|
|
1272
1269
|
". ",
|
|
@@ -1295,61 +1292,27 @@ function HazoUiMultiSortDialog({
|
|
|
1295
1292
|
)
|
|
1296
1293
|
}
|
|
1297
1294
|
),
|
|
1298
|
-
"Sort"
|
|
1295
|
+
"Sort",
|
|
1296
|
+
hasActiveSorts && /* @__PURE__ */ jsx("span", { className: "cls_sort_count ml-2 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-blue-600 px-1 text-[10px] font-semibold text-white", children: initialSortFields.length })
|
|
1299
1297
|
]
|
|
1300
1298
|
}
|
|
1301
1299
|
) }) }),
|
|
1302
1300
|
/* @__PURE__ */ jsx(TooltipContent, { children: tooltipContent })
|
|
1303
1301
|
] }) }),
|
|
1304
|
-
/* @__PURE__ */ jsxs(DialogContent, { className: "cls_sort_dialog_content max-w-lg", children: [
|
|
1305
|
-
/* @__PURE__ */ jsxs(
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
children: [
|
|
1319
|
-
/* @__PURE__ */ jsxs("div", { className: "cls_combobox_content flex items-center", children: [
|
|
1320
|
-
/* @__PURE__ */ jsx(Plus, { className: "cls_plus_icon h-4 w-4 mr-2" }),
|
|
1321
|
-
/* @__PURE__ */ jsx("span", { children: "Add field" })
|
|
1322
|
-
] }),
|
|
1323
|
-
/* @__PURE__ */ jsx(ChevronsUpDown, { className: "cls_chevron_icon ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
1324
|
-
]
|
|
1325
|
-
}
|
|
1326
|
-
) }),
|
|
1327
|
-
/* @__PURE__ */ jsx(PopoverContent, { className: "cls_combobox_popover w-full p-0", children: /* @__PURE__ */ jsxs(Command, { children: [
|
|
1328
|
-
/* @__PURE__ */ jsx(CommandInput, { placeholder: "Search fields...", className: "cls_command_input" }),
|
|
1329
|
-
/* @__PURE__ */ jsx(CommandList, { children: availableFieldsToAdd.length === 0 ? /* @__PURE__ */ jsx(CommandEmpty, { children: "No fields found." }) : /* @__PURE__ */ jsx(CommandGroup, { children: availableFieldsToAdd.map((field) => /* @__PURE__ */ jsxs(
|
|
1330
|
-
CommandItem,
|
|
1331
|
-
{
|
|
1332
|
-
value: field.label,
|
|
1333
|
-
onSelect: () => handleAddField(field.value),
|
|
1334
|
-
className: "cls_command_item",
|
|
1335
|
-
children: [
|
|
1336
|
-
/* @__PURE__ */ jsx(
|
|
1337
|
-
Check,
|
|
1338
|
-
{
|
|
1339
|
-
className: cn(
|
|
1340
|
-
"cls_check_icon mr-2 h-4 w-4",
|
|
1341
|
-
"opacity-0"
|
|
1342
|
-
)
|
|
1343
|
-
}
|
|
1344
|
-
),
|
|
1345
|
-
field.label
|
|
1346
|
-
]
|
|
1347
|
-
},
|
|
1348
|
-
field.value
|
|
1349
|
-
)) }) })
|
|
1350
|
-
] }) })
|
|
1351
|
-
] }) }),
|
|
1352
|
-
sortFields.length > 0 ? /* @__PURE__ */ jsx("div", { className: "cls_sort_fields_list space-y-2", children: /* @__PURE__ */ jsx(
|
|
1302
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "cls_sort_dialog_content max-w-lg gap-0 p-0 sm:rounded-xl", children: [
|
|
1303
|
+
/* @__PURE__ */ jsxs(
|
|
1304
|
+
DialogHeader,
|
|
1305
|
+
{
|
|
1306
|
+
className: "cls_sort_dialog_header space-y-1 border-b px-5 py-4 text-left",
|
|
1307
|
+
style: headerStyles,
|
|
1308
|
+
children: [
|
|
1309
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "text-base font-semibold", children: title }),
|
|
1310
|
+
/* @__PURE__ */ jsx(DialogDescription, { className: "text-xs leading-relaxed text-muted-foreground", children: description })
|
|
1311
|
+
]
|
|
1312
|
+
}
|
|
1313
|
+
),
|
|
1314
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_sort_dialog_body space-y-3 px-5 py-4", children: [
|
|
1315
|
+
sortFields.length > 0 ? /* @__PURE__ */ jsx("div", { className: "cls_sort_fields_list space-y-1.5", children: /* @__PURE__ */ jsx(
|
|
1353
1316
|
DndContext,
|
|
1354
1317
|
{
|
|
1355
1318
|
sensors,
|
|
@@ -1360,11 +1323,12 @@ function HazoUiMultiSortDialog({
|
|
|
1360
1323
|
{
|
|
1361
1324
|
items: sortFields.map((sf) => sf.field),
|
|
1362
1325
|
strategy: verticalListSortingStrategy,
|
|
1363
|
-
children: sortFields.map((sortConfig) => /* @__PURE__ */ jsx(
|
|
1326
|
+
children: sortFields.map((sortConfig, idx) => /* @__PURE__ */ jsx(
|
|
1364
1327
|
SortableSortFieldItem,
|
|
1365
1328
|
{
|
|
1366
1329
|
sortConfig,
|
|
1367
1330
|
fieldLabel: getFieldLabel(sortConfig.field),
|
|
1331
|
+
priority: idx + 1,
|
|
1368
1332
|
onDirectionChange: (direction) => handleDirectionChange(sortConfig.field, direction),
|
|
1369
1333
|
onDelete: () => handleDeleteField(sortConfig.field)
|
|
1370
1334
|
},
|
|
@@ -1373,46 +1337,77 @@ function HazoUiMultiSortDialog({
|
|
|
1373
1337
|
}
|
|
1374
1338
|
)
|
|
1375
1339
|
}
|
|
1376
|
-
) }) : /* @__PURE__ */ jsx("div", { className: "cls_empty_sort_fields
|
|
1340
|
+
) }) : /* @__PURE__ */ jsx("div", { className: "cls_empty_sort_fields rounded-lg border border-dashed border-border/70 bg-muted/20 px-4 py-6 text-center text-xs text-muted-foreground", children: "No sort fields yet. Add one below to start ordering rows." }),
|
|
1341
|
+
/* @__PURE__ */ jsx("div", { className: "cls_add_field_section", children: /* @__PURE__ */ jsxs(Popover, { open: isComboboxOpen, onOpenChange: setIsComboboxOpen, children: [
|
|
1342
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1343
|
+
Button,
|
|
1344
|
+
{
|
|
1345
|
+
variant: "ghost",
|
|
1346
|
+
role: "combobox",
|
|
1347
|
+
"aria-expanded": isComboboxOpen,
|
|
1348
|
+
disabled: availableFieldsToAdd.length === 0,
|
|
1349
|
+
className: "cls_add_field_combobox w-full justify-start gap-2 border border-dashed border-border/70 text-sm font-medium text-muted-foreground hover:border-border hover:bg-muted/40 hover:text-foreground",
|
|
1350
|
+
children: [
|
|
1351
|
+
/* @__PURE__ */ jsx(Plus, { className: "cls_plus_icon h-4 w-4" }),
|
|
1352
|
+
/* @__PURE__ */ jsx("span", { children: availableFieldsToAdd.length === 0 ? "All fields added" : "Add sort field" })
|
|
1353
|
+
]
|
|
1354
|
+
}
|
|
1355
|
+
) }),
|
|
1356
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "cls_combobox_popover w-[var(--radix-popover-trigger-width)] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
|
|
1357
|
+
/* @__PURE__ */ jsx(CommandInput, { placeholder: "Search fields...", className: "cls_command_input" }),
|
|
1358
|
+
/* @__PURE__ */ jsx(CommandList, { children: availableFieldsToAdd.length === 0 ? /* @__PURE__ */ jsx(CommandEmpty, { children: "No fields available." }) : /* @__PURE__ */ jsx(CommandGroup, { children: availableFieldsToAdd.map((field) => /* @__PURE__ */ jsx(
|
|
1359
|
+
CommandItem,
|
|
1360
|
+
{
|
|
1361
|
+
value: field.label,
|
|
1362
|
+
onSelect: () => handleAddField(field.value),
|
|
1363
|
+
className: "cls_command_item",
|
|
1364
|
+
children: field.label
|
|
1365
|
+
},
|
|
1366
|
+
field.value
|
|
1367
|
+
)) }) })
|
|
1368
|
+
] }) })
|
|
1369
|
+
] }) })
|
|
1377
1370
|
] }),
|
|
1378
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
1379
|
-
sortFields.length > 0 && /* @__PURE__ */
|
|
1371
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "cls_sort_dialog_footer flex flex-row items-center justify-between gap-2 border-t bg-muted/20 px-5 py-3 sm:justify-between sm:space-x-0", children: [
|
|
1372
|
+
/* @__PURE__ */ jsx("div", { className: "cls_footer_left", children: sortFields.length > 0 && /* @__PURE__ */ jsx(
|
|
1380
1373
|
Button,
|
|
1381
1374
|
{
|
|
1382
|
-
variant: "
|
|
1375
|
+
variant: "ghost",
|
|
1376
|
+
size: "sm",
|
|
1383
1377
|
onClick: handleClearAll,
|
|
1384
|
-
className: "cls_clear_all_btn",
|
|
1378
|
+
className: "cls_clear_all_btn text-muted-foreground hover:text-foreground",
|
|
1385
1379
|
style: clearButtonStyles,
|
|
1386
|
-
children:
|
|
1387
|
-
/* @__PURE__ */ jsx(Trash2, { className: "cls_clear_all_icon h-4 w-4 mr-2" }),
|
|
1388
|
-
"Clear All"
|
|
1389
|
-
]
|
|
1390
|
-
}
|
|
1391
|
-
),
|
|
1392
|
-
/* @__PURE__ */ jsx(
|
|
1393
|
-
Button,
|
|
1394
|
-
{
|
|
1395
|
-
onClick: handleApply,
|
|
1396
|
-
className: "cls_apply_btn",
|
|
1397
|
-
style: submitButtonStyles,
|
|
1398
|
-
children: "Apply"
|
|
1399
|
-
}
|
|
1400
|
-
),
|
|
1401
|
-
/* @__PURE__ */ jsx(
|
|
1402
|
-
Button,
|
|
1403
|
-
{
|
|
1404
|
-
variant: "outline",
|
|
1405
|
-
onClick: handleCancel,
|
|
1406
|
-
className: "cls_cancel_btn",
|
|
1407
|
-
style: cancelButtonStyles,
|
|
1408
|
-
children: "Cancel"
|
|
1380
|
+
children: "Clear all"
|
|
1409
1381
|
}
|
|
1410
|
-
)
|
|
1382
|
+
) }),
|
|
1383
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_footer_right flex items-center gap-2", children: [
|
|
1384
|
+
/* @__PURE__ */ jsx(
|
|
1385
|
+
Button,
|
|
1386
|
+
{
|
|
1387
|
+
variant: "outline",
|
|
1388
|
+
size: "sm",
|
|
1389
|
+
onClick: handleCancel,
|
|
1390
|
+
className: "cls_cancel_btn",
|
|
1391
|
+
style: cancelButtonStyles,
|
|
1392
|
+
children: "Cancel"
|
|
1393
|
+
}
|
|
1394
|
+
),
|
|
1395
|
+
/* @__PURE__ */ jsx(
|
|
1396
|
+
Button,
|
|
1397
|
+
{
|
|
1398
|
+
size: "sm",
|
|
1399
|
+
onClick: handleApply,
|
|
1400
|
+
className: "cls_apply_btn",
|
|
1401
|
+
style: submitButtonStyles,
|
|
1402
|
+
children: "Apply"
|
|
1403
|
+
}
|
|
1404
|
+
)
|
|
1405
|
+
] })
|
|
1411
1406
|
] })
|
|
1412
1407
|
] })
|
|
1413
1408
|
] });
|
|
1414
1409
|
}
|
|
1415
|
-
var RadioGroup =
|
|
1410
|
+
var RadioGroup = React25.forwardRef(({ className, ...props }, ref) => {
|
|
1416
1411
|
return /* @__PURE__ */ jsx(
|
|
1417
1412
|
RadioGroupPrimitive.Root,
|
|
1418
1413
|
{
|
|
@@ -1423,7 +1418,7 @@ var RadioGroup = React27.forwardRef(({ className, ...props }, ref) => {
|
|
|
1423
1418
|
);
|
|
1424
1419
|
});
|
|
1425
1420
|
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
1426
|
-
var RadioGroupItem =
|
|
1421
|
+
var RadioGroupItem = React25.forwardRef(({ className, ...props }, ref) => {
|
|
1427
1422
|
return /* @__PURE__ */ jsx(
|
|
1428
1423
|
RadioGroupPrimitive.Item,
|
|
1429
1424
|
{
|
|
@@ -1880,7 +1875,7 @@ function filterInputValue(value, input_type, num_decimals) {
|
|
|
1880
1875
|
}
|
|
1881
1876
|
}
|
|
1882
1877
|
}
|
|
1883
|
-
var HazoUiFlexInput =
|
|
1878
|
+
var HazoUiFlexInput = React25.forwardRef(
|
|
1884
1879
|
({
|
|
1885
1880
|
className,
|
|
1886
1881
|
input_type = "mixed",
|
|
@@ -1897,13 +1892,13 @@ var HazoUiFlexInput = React27.forwardRef(
|
|
|
1897
1892
|
onBlur,
|
|
1898
1893
|
...props
|
|
1899
1894
|
}, ref) => {
|
|
1900
|
-
const [internalValue, setInternalValue] =
|
|
1895
|
+
const [internalValue, setInternalValue] = React25.useState(
|
|
1901
1896
|
typeof controlledValue === "string" ? controlledValue : typeof controlledValue === "number" ? String(controlledValue) : ""
|
|
1902
1897
|
);
|
|
1903
|
-
const [errorMessage, setErrorMessage] =
|
|
1898
|
+
const [errorMessage, setErrorMessage] = React25.useState();
|
|
1904
1899
|
const isControlled = controlledValue !== void 0;
|
|
1905
1900
|
const currentValue = isControlled ? typeof controlledValue === "string" ? controlledValue : String(controlledValue || "") : internalValue;
|
|
1906
|
-
|
|
1901
|
+
React25.useEffect(() => {
|
|
1907
1902
|
if (isControlled) {
|
|
1908
1903
|
const newValue = typeof controlledValue === "string" ? controlledValue : String(controlledValue || "");
|
|
1909
1904
|
if (newValue !== internalValue) {
|
|
@@ -1983,7 +1978,7 @@ var HazoUiFlexInput = React27.forwardRef(
|
|
|
1983
1978
|
}
|
|
1984
1979
|
);
|
|
1985
1980
|
HazoUiFlexInput.displayName = "HazoUiFlexInput";
|
|
1986
|
-
var ToolbarButton =
|
|
1981
|
+
var ToolbarButton = React25.forwardRef(
|
|
1987
1982
|
({ onClick, is_active = false, disabled = false, tooltip, className, children }, ref) => {
|
|
1988
1983
|
const button = /* @__PURE__ */ jsx(
|
|
1989
1984
|
"button",
|
|
@@ -2302,7 +2297,7 @@ var getRelativePosition = (node, event) => {
|
|
|
2302
2297
|
};
|
|
2303
2298
|
};
|
|
2304
2299
|
var _excluded = ["prefixCls", "className", "onMove", "onDown"];
|
|
2305
|
-
var Interactive = /* @__PURE__ */
|
|
2300
|
+
var Interactive = /* @__PURE__ */ React25__default.forwardRef((props, ref) => {
|
|
2306
2301
|
var {
|
|
2307
2302
|
prefixCls = "w-color-interactive",
|
|
2308
2303
|
className,
|
|
@@ -2401,7 +2396,7 @@ var Pointer = (_ref) => {
|
|
|
2401
2396
|
}), [top, left, color2, className, prefixCls]);
|
|
2402
2397
|
};
|
|
2403
2398
|
var _excluded2 = ["prefixCls", "radius", "pointer", "className", "hue", "style", "hsva", "onChange"];
|
|
2404
|
-
var Saturation = /* @__PURE__ */
|
|
2399
|
+
var Saturation = /* @__PURE__ */ React25__default.forwardRef((props, ref) => {
|
|
2405
2400
|
var _hsva$h;
|
|
2406
2401
|
var {
|
|
2407
2402
|
prefixCls = "w-color-saturation",
|
|
@@ -2553,7 +2548,7 @@ var Pointer2 = (_ref) => {
|
|
|
2553
2548
|
};
|
|
2554
2549
|
var _excluded4 = ["prefixCls", "className", "hsva", "background", "bgProps", "innerProps", "pointerProps", "radius", "width", "height", "direction", "style", "onChange", "pointer"];
|
|
2555
2550
|
var BACKGROUND_IMG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==";
|
|
2556
|
-
var Alpha = /* @__PURE__ */
|
|
2551
|
+
var Alpha = /* @__PURE__ */ React25__default.forwardRef((props, ref) => {
|
|
2557
2552
|
var {
|
|
2558
2553
|
prefixCls = "w-color-alpha",
|
|
2559
2554
|
className,
|
|
@@ -2687,7 +2682,7 @@ var import_objectWithoutPropertiesLoose5 = __toESM(require_objectWithoutProperti
|
|
|
2687
2682
|
var _excluded5 = ["prefixCls", "placement", "label", "value", "className", "style", "labelStyle", "inputStyle", "onChange", "onBlur", "renderInput"];
|
|
2688
2683
|
var validHex2 = (hex) => /^#?([A-Fa-f0-9]{3,4}){1,2}$/.test(hex);
|
|
2689
2684
|
var getNumberValue = (value) => Number(String(value).replace(/%/g, ""));
|
|
2690
|
-
var EditableInput = /* @__PURE__ */
|
|
2685
|
+
var EditableInput = /* @__PURE__ */ React25__default.forwardRef((props, ref) => {
|
|
2691
2686
|
var {
|
|
2692
2687
|
prefixCls = "w-color-editable-input",
|
|
2693
2688
|
placement = "bottom",
|
|
@@ -2792,7 +2787,7 @@ var esm_default4 = EditableInput;
|
|
|
2792
2787
|
var import_extends7 = __toESM(require_extends());
|
|
2793
2788
|
var import_objectWithoutPropertiesLoose6 = __toESM(require_objectWithoutPropertiesLoose());
|
|
2794
2789
|
var _excluded6 = ["prefixCls", "hsva", "placement", "rProps", "gProps", "bProps", "aProps", "className", "style", "onChange"];
|
|
2795
|
-
var EditableInputRGBA = /* @__PURE__ */
|
|
2790
|
+
var EditableInputRGBA = /* @__PURE__ */ React25__default.forwardRef((props, ref) => {
|
|
2796
2791
|
var {
|
|
2797
2792
|
prefixCls = "w-color-editable-input-rgba",
|
|
2798
2793
|
hsva,
|
|
@@ -2915,7 +2910,7 @@ var esm_default5 = EditableInputRGBA;
|
|
|
2915
2910
|
var import_extends8 = __toESM(require_extends());
|
|
2916
2911
|
var import_objectWithoutPropertiesLoose7 = __toESM(require_objectWithoutPropertiesLoose());
|
|
2917
2912
|
var _excluded7 = ["prefixCls", "className", "hue", "onChange", "direction"];
|
|
2918
|
-
var Hue = /* @__PURE__ */
|
|
2913
|
+
var Hue = /* @__PURE__ */ React25__default.forwardRef((props, ref) => {
|
|
2919
2914
|
var {
|
|
2920
2915
|
prefixCls = "w-color-hue",
|
|
2921
2916
|
className,
|
|
@@ -2949,7 +2944,7 @@ var esm_default6 = Hue;
|
|
|
2949
2944
|
var import_extends9 = __toESM(require_extends());
|
|
2950
2945
|
var import_objectWithoutPropertiesLoose8 = __toESM(require_objectWithoutPropertiesLoose());
|
|
2951
2946
|
var _excluded8 = ["prefixCls", "className", "color", "colors", "style", "rectProps", "onChange", "addonAfter", "addonBefore", "rectRender"];
|
|
2952
|
-
var Swatch = /* @__PURE__ */
|
|
2947
|
+
var Swatch = /* @__PURE__ */ React25__default.forwardRef((props, ref) => {
|
|
2953
2948
|
var {
|
|
2954
2949
|
prefixCls = "w-color-swatch",
|
|
2955
2950
|
className,
|
|
@@ -2986,7 +2981,7 @@ var Swatch = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
|
|
|
2986
2981
|
flexWrap: "wrap",
|
|
2987
2982
|
position: "relative"
|
|
2988
2983
|
}, style),
|
|
2989
|
-
children: [addonBefore && /* @__PURE__ */
|
|
2984
|
+
children: [addonBefore && /* @__PURE__ */ React25__default.isValidElement(addonBefore) && addonBefore, colors && Array.isArray(colors) && colors.map((item, idx) => {
|
|
2990
2985
|
var title = "";
|
|
2991
2986
|
var background = "";
|
|
2992
2987
|
if (typeof item === "string") {
|
|
@@ -3012,7 +3007,7 @@ var Swatch = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
|
|
|
3012
3007
|
children: render
|
|
3013
3008
|
}, idx);
|
|
3014
3009
|
}
|
|
3015
|
-
var child = rectProps.children && /* @__PURE__ */
|
|
3010
|
+
var child = rectProps.children && /* @__PURE__ */ React25__default.isValidElement(rectProps.children) ? /* @__PURE__ */ React25__default.cloneElement(rectProps.children, {
|
|
3016
3011
|
color: background,
|
|
3017
3012
|
checked
|
|
3018
3013
|
}) : null;
|
|
@@ -3026,7 +3021,7 @@ var Swatch = /* @__PURE__ */ React27__default.forwardRef((props, ref) => {
|
|
|
3026
3021
|
background
|
|
3027
3022
|
})
|
|
3028
3023
|
}), idx);
|
|
3029
|
-
}), addonAfter && /* @__PURE__ */
|
|
3024
|
+
}), addonAfter && /* @__PURE__ */ React25__default.isValidElement(addonAfter) && addonAfter]
|
|
3030
3025
|
}));
|
|
3031
3026
|
});
|
|
3032
3027
|
Swatch.displayName = "Swatch";
|
|
@@ -3045,7 +3040,7 @@ var Bar = (props) => /* @__PURE__ */ jsx("div", {
|
|
|
3045
3040
|
backgroundColor: "#fff"
|
|
3046
3041
|
}
|
|
3047
3042
|
});
|
|
3048
|
-
var Sketch = /* @__PURE__ */
|
|
3043
|
+
var Sketch = /* @__PURE__ */ React25__default.forwardRef((props, ref) => {
|
|
3049
3044
|
var {
|
|
3050
3045
|
prefixCls = "w-color-sketch",
|
|
3051
3046
|
className,
|
|
@@ -3296,19 +3291,19 @@ var Toolbar = ({
|
|
|
3296
3291
|
on_attachments_change,
|
|
3297
3292
|
disabled = false
|
|
3298
3293
|
}) => {
|
|
3299
|
-
const [link_url, set_link_url] =
|
|
3300
|
-
const [link_popover_open, set_link_popover_open] =
|
|
3301
|
-
const [text_color_open, set_text_color_open] =
|
|
3302
|
-
const [highlight_color_open, set_highlight_color_open] =
|
|
3303
|
-
const [variables_menu_open, set_variables_menu_open] =
|
|
3304
|
-
const [table_menu_open, set_table_menu_open] =
|
|
3305
|
-
const [text_color, set_text_color] =
|
|
3306
|
-
const [highlight_color, set_highlight_color] =
|
|
3307
|
-
const [table_rows, set_table_rows] =
|
|
3308
|
-
const [table_cols, set_table_cols] =
|
|
3309
|
-
const [hovered_cell, set_hovered_cell] =
|
|
3310
|
-
const file_input_ref =
|
|
3311
|
-
const image_input_ref =
|
|
3294
|
+
const [link_url, set_link_url] = React25.useState("https://");
|
|
3295
|
+
const [link_popover_open, set_link_popover_open] = React25.useState(false);
|
|
3296
|
+
const [text_color_open, set_text_color_open] = React25.useState(false);
|
|
3297
|
+
const [highlight_color_open, set_highlight_color_open] = React25.useState(false);
|
|
3298
|
+
const [variables_menu_open, set_variables_menu_open] = React25.useState(false);
|
|
3299
|
+
const [table_menu_open, set_table_menu_open] = React25.useState(false);
|
|
3300
|
+
const [text_color, set_text_color] = React25.useState("#000000");
|
|
3301
|
+
const [highlight_color, set_highlight_color] = React25.useState("#ffff00");
|
|
3302
|
+
const [table_rows, set_table_rows] = React25.useState(3);
|
|
3303
|
+
const [table_cols, set_table_cols] = React25.useState(3);
|
|
3304
|
+
const [hovered_cell, set_hovered_cell] = React25.useState(null);
|
|
3305
|
+
const file_input_ref = React25.useRef(null);
|
|
3306
|
+
const image_input_ref = React25.useRef(null);
|
|
3312
3307
|
if (!editor) {
|
|
3313
3308
|
return null;
|
|
3314
3309
|
}
|
|
@@ -4241,7 +4236,7 @@ var VariableExtension = Node.create({
|
|
|
4241
4236
|
}
|
|
4242
4237
|
});
|
|
4243
4238
|
var Tabs = TabsPrimitive.Root;
|
|
4244
|
-
var TabsList =
|
|
4239
|
+
var TabsList = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
4245
4240
|
TabsPrimitive.List,
|
|
4246
4241
|
{
|
|
4247
4242
|
ref,
|
|
@@ -4253,7 +4248,7 @@ var TabsList = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
4253
4248
|
}
|
|
4254
4249
|
));
|
|
4255
4250
|
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
4256
|
-
var TabsTrigger =
|
|
4251
|
+
var TabsTrigger = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
4257
4252
|
TabsPrimitive.Trigger,
|
|
4258
4253
|
{
|
|
4259
4254
|
ref,
|
|
@@ -4265,7 +4260,7 @@ var TabsTrigger = React27.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
4265
4260
|
}
|
|
4266
4261
|
));
|
|
4267
4262
|
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
4268
|
-
var TabsContent =
|
|
4263
|
+
var TabsContent = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
4269
4264
|
TabsPrimitive.Content,
|
|
4270
4265
|
{
|
|
4271
4266
|
ref,
|
|
@@ -4300,14 +4295,14 @@ var HazoUiRte = ({
|
|
|
4300
4295
|
className,
|
|
4301
4296
|
show_output_viewer = false
|
|
4302
4297
|
}) => {
|
|
4303
|
-
const [attachments, set_attachments] =
|
|
4298
|
+
const [attachments, set_attachments] = React25.useState(
|
|
4304
4299
|
initial_attachments
|
|
4305
4300
|
);
|
|
4306
|
-
const [active_tab, set_active_tab] =
|
|
4301
|
+
const [active_tab, set_active_tab] = React25.useState("html");
|
|
4307
4302
|
const is_view_only = active_tab !== "html";
|
|
4308
|
-
const attachments_ref =
|
|
4303
|
+
const attachments_ref = React25.useRef(attachments);
|
|
4309
4304
|
attachments_ref.current = attachments;
|
|
4310
|
-
const debounced_on_change =
|
|
4305
|
+
const debounced_on_change = React25.useMemo(
|
|
4311
4306
|
() => debounce_fn((output) => {
|
|
4312
4307
|
if (on_change) {
|
|
4313
4308
|
on_change(output);
|
|
@@ -4406,7 +4401,7 @@ var HazoUiRte = ({
|
|
|
4406
4401
|
debounced_on_change(output);
|
|
4407
4402
|
}
|
|
4408
4403
|
});
|
|
4409
|
-
|
|
4404
|
+
React25.useEffect(() => {
|
|
4410
4405
|
if (editor && html !== void 0) {
|
|
4411
4406
|
const current_html = editor.getHTML();
|
|
4412
4407
|
if (html !== current_html && !editor.isFocused) {
|
|
@@ -4414,21 +4409,21 @@ var HazoUiRte = ({
|
|
|
4414
4409
|
}
|
|
4415
4410
|
}
|
|
4416
4411
|
}, [html, editor]);
|
|
4417
|
-
|
|
4412
|
+
React25.useEffect(() => {
|
|
4418
4413
|
if (editor) {
|
|
4419
4414
|
editor.setEditable(!disabled);
|
|
4420
4415
|
}
|
|
4421
4416
|
}, [disabled, editor]);
|
|
4422
|
-
const attachments_from_props_ref =
|
|
4423
|
-
const prev_initial_attachments_ref =
|
|
4424
|
-
|
|
4417
|
+
const attachments_from_props_ref = React25.useRef(false);
|
|
4418
|
+
const prev_initial_attachments_ref = React25.useRef(initial_attachments);
|
|
4419
|
+
React25.useEffect(() => {
|
|
4425
4420
|
if (JSON.stringify(initial_attachments) !== JSON.stringify(prev_initial_attachments_ref.current)) {
|
|
4426
4421
|
prev_initial_attachments_ref.current = initial_attachments;
|
|
4427
4422
|
attachments_from_props_ref.current = true;
|
|
4428
4423
|
set_attachments(initial_attachments);
|
|
4429
4424
|
}
|
|
4430
4425
|
}, [initial_attachments]);
|
|
4431
|
-
|
|
4426
|
+
React25.useEffect(() => {
|
|
4432
4427
|
if (attachments_from_props_ref.current) {
|
|
4433
4428
|
attachments_from_props_ref.current = false;
|
|
4434
4429
|
return;
|
|
@@ -4930,12 +4925,12 @@ var CommandPopover = ({
|
|
|
4930
4925
|
on_selection_change: _on_selection_change,
|
|
4931
4926
|
prefix_color
|
|
4932
4927
|
}) => {
|
|
4933
|
-
const container_ref =
|
|
4934
|
-
const grouped_commands =
|
|
4928
|
+
const container_ref = React25.useRef(null);
|
|
4929
|
+
const grouped_commands = React25.useMemo(
|
|
4935
4930
|
() => group_commands(commands),
|
|
4936
4931
|
[commands]
|
|
4937
4932
|
);
|
|
4938
|
-
|
|
4933
|
+
React25.useEffect(() => {
|
|
4939
4934
|
const handle_click_outside = (e) => {
|
|
4940
4935
|
if (container_ref.current && !container_ref.current.contains(e.target)) {
|
|
4941
4936
|
on_close();
|
|
@@ -4948,8 +4943,8 @@ var CommandPopover = ({
|
|
|
4948
4943
|
};
|
|
4949
4944
|
}
|
|
4950
4945
|
}, [is_open, on_close]);
|
|
4951
|
-
const [mounted, set_mounted] =
|
|
4952
|
-
|
|
4946
|
+
const [mounted, set_mounted] = React25.useState(false);
|
|
4947
|
+
React25.useEffect(() => {
|
|
4953
4948
|
set_mounted(true);
|
|
4954
4949
|
}, []);
|
|
4955
4950
|
if (!is_open || !mounted) return null;
|
|
@@ -5259,21 +5254,21 @@ var HazoUiTextbox = ({
|
|
|
5259
5254
|
on_command_change,
|
|
5260
5255
|
on_command_remove
|
|
5261
5256
|
}) => {
|
|
5262
|
-
const generated_instance_id =
|
|
5257
|
+
const generated_instance_id = React25.useId();
|
|
5263
5258
|
const instance_id = provided_instance_id || generated_instance_id;
|
|
5264
|
-
const [suggestion_state, set_suggestion_state] =
|
|
5265
|
-
const [selected_index, set_selected_index] =
|
|
5266
|
-
const [popover_position, set_popover_position] =
|
|
5267
|
-
const [edit_context, set_edit_context] =
|
|
5268
|
-
const [edit_selected_index, set_edit_selected_index] =
|
|
5259
|
+
const [suggestion_state, set_suggestion_state] = React25.useState(null);
|
|
5260
|
+
const [selected_index, set_selected_index] = React25.useState(0);
|
|
5261
|
+
const [popover_position, set_popover_position] = React25.useState({ top: 0, left: 0 });
|
|
5262
|
+
const [edit_context, set_edit_context] = React25.useState(null);
|
|
5263
|
+
const [edit_selected_index, set_edit_selected_index] = React25.useState(0);
|
|
5269
5264
|
const is_controlled = value !== void 0;
|
|
5270
|
-
const editor_container_ref =
|
|
5271
|
-
const edit_popover_ref =
|
|
5272
|
-
const [mounted, set_mounted] =
|
|
5273
|
-
|
|
5265
|
+
const editor_container_ref = React25.useRef(null);
|
|
5266
|
+
const edit_popover_ref = React25.useRef(null);
|
|
5267
|
+
const [mounted, set_mounted] = React25.useState(false);
|
|
5268
|
+
React25.useEffect(() => {
|
|
5274
5269
|
set_mounted(true);
|
|
5275
5270
|
}, []);
|
|
5276
|
-
const suggestion_extensions =
|
|
5271
|
+
const suggestion_extensions = React25.useMemo(() => {
|
|
5277
5272
|
return create_command_suggestion_extension({
|
|
5278
5273
|
prefixes,
|
|
5279
5274
|
instance_id,
|
|
@@ -5324,7 +5319,7 @@ var HazoUiTextbox = ({
|
|
|
5324
5319
|
}
|
|
5325
5320
|
}
|
|
5326
5321
|
});
|
|
5327
|
-
|
|
5322
|
+
React25.useEffect(() => {
|
|
5328
5323
|
if (suggestion_state?.is_active && editor) {
|
|
5329
5324
|
requestAnimationFrame(() => {
|
|
5330
5325
|
const { from } = suggestion_state.range;
|
|
@@ -5348,7 +5343,7 @@ var HazoUiTextbox = ({
|
|
|
5348
5343
|
});
|
|
5349
5344
|
}
|
|
5350
5345
|
}, [suggestion_state, editor]);
|
|
5351
|
-
|
|
5346
|
+
React25.useEffect(() => {
|
|
5352
5347
|
if (is_controlled && editor && !editor.isFocused) {
|
|
5353
5348
|
const current_text = editor.getText();
|
|
5354
5349
|
if (value !== current_text) {
|
|
@@ -5357,12 +5352,12 @@ var HazoUiTextbox = ({
|
|
|
5357
5352
|
}
|
|
5358
5353
|
}
|
|
5359
5354
|
}, [value, editor, is_controlled, prefixes, pill_variant]);
|
|
5360
|
-
|
|
5355
|
+
React25.useEffect(() => {
|
|
5361
5356
|
if (editor) {
|
|
5362
5357
|
editor.setEditable(!disabled);
|
|
5363
5358
|
}
|
|
5364
5359
|
}, [disabled, editor]);
|
|
5365
|
-
const handle_command_select =
|
|
5360
|
+
const handle_command_select = React25.useCallback(
|
|
5366
5361
|
(command) => {
|
|
5367
5362
|
if (!editor || !suggestion_state) return;
|
|
5368
5363
|
const prefix_config = prefixes.find((p) => p.char === suggestion_state.prefix);
|
|
@@ -5382,15 +5377,15 @@ var HazoUiTextbox = ({
|
|
|
5382
5377
|
},
|
|
5383
5378
|
[editor, suggestion_state, pill_variant, on_command_insert, prefixes]
|
|
5384
5379
|
);
|
|
5385
|
-
const handle_popover_close =
|
|
5380
|
+
const handle_popover_close = React25.useCallback(() => {
|
|
5386
5381
|
set_suggestion_state(null);
|
|
5387
5382
|
editor?.commands.focus();
|
|
5388
5383
|
}, [editor]);
|
|
5389
|
-
const handle_edit_close =
|
|
5384
|
+
const handle_edit_close = React25.useCallback(() => {
|
|
5390
5385
|
set_edit_context(null);
|
|
5391
5386
|
editor?.commands.focus();
|
|
5392
5387
|
}, [editor]);
|
|
5393
|
-
const handle_command_update =
|
|
5388
|
+
const handle_command_update = React25.useCallback(
|
|
5394
5389
|
(new_command) => {
|
|
5395
5390
|
if (!editor || !edit_context) return;
|
|
5396
5391
|
const old_command = edit_context.command;
|
|
@@ -5406,7 +5401,7 @@ var HazoUiTextbox = ({
|
|
|
5406
5401
|
},
|
|
5407
5402
|
[editor, edit_context, on_command_change]
|
|
5408
5403
|
);
|
|
5409
|
-
const handle_command_remove =
|
|
5404
|
+
const handle_command_remove = React25.useCallback(() => {
|
|
5410
5405
|
if (!editor || !edit_context) return;
|
|
5411
5406
|
const command = edit_context.command;
|
|
5412
5407
|
editor.state.doc.descendants((node, pos) => {
|
|
@@ -5420,7 +5415,7 @@ var HazoUiTextbox = ({
|
|
|
5420
5415
|
}
|
|
5421
5416
|
set_edit_context(null);
|
|
5422
5417
|
}, [editor, edit_context, on_command_remove]);
|
|
5423
|
-
const filtered_commands =
|
|
5418
|
+
const filtered_commands = React25.useMemo(() => {
|
|
5424
5419
|
if (!suggestion_state) return [];
|
|
5425
5420
|
const query = suggestion_state.query.toLowerCase();
|
|
5426
5421
|
if (!query) return suggestion_state.commands;
|
|
@@ -5428,7 +5423,7 @@ var HazoUiTextbox = ({
|
|
|
5428
5423
|
(cmd) => cmd.action_label.toLowerCase().includes(query) || cmd.action.toLowerCase().includes(query) || cmd.action_description?.toLowerCase().includes(query)
|
|
5429
5424
|
);
|
|
5430
5425
|
}, [suggestion_state]);
|
|
5431
|
-
|
|
5426
|
+
React25.useEffect(() => {
|
|
5432
5427
|
if (!suggestion_state?.is_active) return;
|
|
5433
5428
|
const handle_keydown = (e) => {
|
|
5434
5429
|
switch (e.key) {
|
|
@@ -5463,7 +5458,7 @@ var HazoUiTextbox = ({
|
|
|
5463
5458
|
handle_command_select,
|
|
5464
5459
|
handle_popover_close
|
|
5465
5460
|
]);
|
|
5466
|
-
|
|
5461
|
+
React25.useEffect(() => {
|
|
5467
5462
|
if (!edit_context) return;
|
|
5468
5463
|
const handle_click_outside = (e) => {
|
|
5469
5464
|
if (edit_popover_ref.current && !edit_popover_ref.current.contains(e.target)) {
|
|
@@ -5478,12 +5473,12 @@ var HazoUiTextbox = ({
|
|
|
5478
5473
|
document.removeEventListener("mousedown", handle_click_outside);
|
|
5479
5474
|
};
|
|
5480
5475
|
}, [edit_context]);
|
|
5481
|
-
const edit_commands =
|
|
5476
|
+
const edit_commands = React25.useMemo(() => {
|
|
5482
5477
|
if (!edit_context) return [];
|
|
5483
5478
|
const prefix_config = prefixes.find((p) => p.char === edit_context.command.prefix);
|
|
5484
5479
|
return prefix_config?.commands || [];
|
|
5485
5480
|
}, [edit_context, prefixes]);
|
|
5486
|
-
|
|
5481
|
+
React25.useEffect(() => {
|
|
5487
5482
|
if (!edit_context) return;
|
|
5488
5483
|
const handle_keydown = (e) => {
|
|
5489
5484
|
switch (e.key) {
|
|
@@ -5521,7 +5516,7 @@ var HazoUiTextbox = ({
|
|
|
5521
5516
|
handle_command_remove,
|
|
5522
5517
|
handle_edit_close
|
|
5523
5518
|
]);
|
|
5524
|
-
|
|
5519
|
+
React25.useEffect(() => {
|
|
5525
5520
|
const handle_pill_click = (e) => {
|
|
5526
5521
|
const detail = e.detail;
|
|
5527
5522
|
const { id, prefix, action, action_label, node_pos } = detail;
|
|
@@ -5804,22 +5799,22 @@ var HazoUiTextarea = ({
|
|
|
5804
5799
|
on_command_change,
|
|
5805
5800
|
on_command_remove
|
|
5806
5801
|
}) => {
|
|
5807
|
-
const generated_instance_id =
|
|
5802
|
+
const generated_instance_id = React25.useId();
|
|
5808
5803
|
const instance_id = provided_instance_id || generated_instance_id;
|
|
5809
|
-
const [suggestion_state, set_suggestion_state] =
|
|
5810
|
-
const [selected_index, set_selected_index] =
|
|
5811
|
-
const [popover_position, set_popover_position] =
|
|
5812
|
-
const [edit_context, set_edit_context] =
|
|
5813
|
-
const [edit_selected_index, set_edit_selected_index] =
|
|
5804
|
+
const [suggestion_state, set_suggestion_state] = React25.useState(null);
|
|
5805
|
+
const [selected_index, set_selected_index] = React25.useState(0);
|
|
5806
|
+
const [popover_position, set_popover_position] = React25.useState({ top: 0, left: 0 });
|
|
5807
|
+
const [edit_context, set_edit_context] = React25.useState(null);
|
|
5808
|
+
const [edit_selected_index, set_edit_selected_index] = React25.useState(0);
|
|
5814
5809
|
const is_controlled = value !== void 0;
|
|
5815
|
-
const editor_container_ref =
|
|
5816
|
-
const edit_popover_ref =
|
|
5817
|
-
const [mounted, set_mounted] =
|
|
5818
|
-
|
|
5810
|
+
const editor_container_ref = React25.useRef(null);
|
|
5811
|
+
const edit_popover_ref = React25.useRef(null);
|
|
5812
|
+
const [mounted, set_mounted] = React25.useState(false);
|
|
5813
|
+
React25.useEffect(() => {
|
|
5819
5814
|
set_mounted(true);
|
|
5820
5815
|
}, []);
|
|
5821
5816
|
const calculated_min_height = rows ? `${rows * 1.5}em` : min_height;
|
|
5822
|
-
const suggestion_extensions =
|
|
5817
|
+
const suggestion_extensions = React25.useMemo(() => {
|
|
5823
5818
|
return create_command_suggestion_extension({
|
|
5824
5819
|
prefixes,
|
|
5825
5820
|
instance_id,
|
|
@@ -5868,7 +5863,7 @@ var HazoUiTextarea = ({
|
|
|
5868
5863
|
}
|
|
5869
5864
|
}
|
|
5870
5865
|
});
|
|
5871
|
-
|
|
5866
|
+
React25.useEffect(() => {
|
|
5872
5867
|
if (suggestion_state?.is_active && editor) {
|
|
5873
5868
|
requestAnimationFrame(() => {
|
|
5874
5869
|
const { from } = suggestion_state.range;
|
|
@@ -5892,7 +5887,7 @@ var HazoUiTextarea = ({
|
|
|
5892
5887
|
});
|
|
5893
5888
|
}
|
|
5894
5889
|
}, [suggestion_state, editor]);
|
|
5895
|
-
|
|
5890
|
+
React25.useEffect(() => {
|
|
5896
5891
|
if (is_controlled && editor && !editor.isFocused) {
|
|
5897
5892
|
const current_text = editor.getText();
|
|
5898
5893
|
if (value !== current_text) {
|
|
@@ -5905,12 +5900,12 @@ var HazoUiTextarea = ({
|
|
|
5905
5900
|
}
|
|
5906
5901
|
}
|
|
5907
5902
|
}, [value, editor, is_controlled, prefixes, pill_variant]);
|
|
5908
|
-
|
|
5903
|
+
React25.useEffect(() => {
|
|
5909
5904
|
if (editor) {
|
|
5910
5905
|
editor.setEditable(!disabled);
|
|
5911
5906
|
}
|
|
5912
5907
|
}, [disabled, editor]);
|
|
5913
|
-
const handle_command_select =
|
|
5908
|
+
const handle_command_select = React25.useCallback(
|
|
5914
5909
|
(command) => {
|
|
5915
5910
|
if (!editor || !suggestion_state) return;
|
|
5916
5911
|
const prefix_config = prefixes.find((p) => p.char === suggestion_state.prefix);
|
|
@@ -5930,15 +5925,15 @@ var HazoUiTextarea = ({
|
|
|
5930
5925
|
},
|
|
5931
5926
|
[editor, suggestion_state, pill_variant, on_command_insert, prefixes]
|
|
5932
5927
|
);
|
|
5933
|
-
const handle_popover_close =
|
|
5928
|
+
const handle_popover_close = React25.useCallback(() => {
|
|
5934
5929
|
set_suggestion_state(null);
|
|
5935
5930
|
editor?.commands.focus();
|
|
5936
5931
|
}, [editor]);
|
|
5937
|
-
const handle_edit_close =
|
|
5932
|
+
const handle_edit_close = React25.useCallback(() => {
|
|
5938
5933
|
set_edit_context(null);
|
|
5939
5934
|
editor?.commands.focus();
|
|
5940
5935
|
}, [editor]);
|
|
5941
|
-
const handle_command_update =
|
|
5936
|
+
const handle_command_update = React25.useCallback(
|
|
5942
5937
|
(new_command) => {
|
|
5943
5938
|
if (!editor || !edit_context) return;
|
|
5944
5939
|
const old_command = edit_context.command;
|
|
@@ -5954,7 +5949,7 @@ var HazoUiTextarea = ({
|
|
|
5954
5949
|
},
|
|
5955
5950
|
[editor, edit_context, on_command_change]
|
|
5956
5951
|
);
|
|
5957
|
-
const handle_command_remove =
|
|
5952
|
+
const handle_command_remove = React25.useCallback(() => {
|
|
5958
5953
|
if (!editor || !edit_context) return;
|
|
5959
5954
|
const command = edit_context.command;
|
|
5960
5955
|
editor.state.doc.descendants((node, pos) => {
|
|
@@ -5968,7 +5963,7 @@ var HazoUiTextarea = ({
|
|
|
5968
5963
|
}
|
|
5969
5964
|
set_edit_context(null);
|
|
5970
5965
|
}, [editor, edit_context, on_command_remove]);
|
|
5971
|
-
const filtered_commands =
|
|
5966
|
+
const filtered_commands = React25.useMemo(() => {
|
|
5972
5967
|
if (!suggestion_state) return [];
|
|
5973
5968
|
const query = suggestion_state.query.toLowerCase();
|
|
5974
5969
|
if (!query) return suggestion_state.commands;
|
|
@@ -5976,7 +5971,7 @@ var HazoUiTextarea = ({
|
|
|
5976
5971
|
(cmd) => cmd.action_label.toLowerCase().includes(query) || cmd.action.toLowerCase().includes(query) || cmd.action_description?.toLowerCase().includes(query)
|
|
5977
5972
|
);
|
|
5978
5973
|
}, [suggestion_state]);
|
|
5979
|
-
|
|
5974
|
+
React25.useEffect(() => {
|
|
5980
5975
|
if (!suggestion_state?.is_active) return;
|
|
5981
5976
|
const handle_keydown = (e) => {
|
|
5982
5977
|
switch (e.key) {
|
|
@@ -6011,7 +6006,7 @@ var HazoUiTextarea = ({
|
|
|
6011
6006
|
handle_command_select,
|
|
6012
6007
|
handle_popover_close
|
|
6013
6008
|
]);
|
|
6014
|
-
|
|
6009
|
+
React25.useEffect(() => {
|
|
6015
6010
|
if (!edit_context) return;
|
|
6016
6011
|
const handle_click_outside = (e) => {
|
|
6017
6012
|
if (edit_popover_ref.current && !edit_popover_ref.current.contains(e.target)) {
|
|
@@ -6026,12 +6021,12 @@ var HazoUiTextarea = ({
|
|
|
6026
6021
|
document.removeEventListener("mousedown", handle_click_outside);
|
|
6027
6022
|
};
|
|
6028
6023
|
}, [edit_context]);
|
|
6029
|
-
const edit_commands =
|
|
6024
|
+
const edit_commands = React25.useMemo(() => {
|
|
6030
6025
|
if (!edit_context) return [];
|
|
6031
6026
|
const prefix_config = prefixes.find((p) => p.char === edit_context.command.prefix);
|
|
6032
6027
|
return prefix_config?.commands || [];
|
|
6033
6028
|
}, [edit_context, prefixes]);
|
|
6034
|
-
|
|
6029
|
+
React25.useEffect(() => {
|
|
6035
6030
|
if (!edit_context) return;
|
|
6036
6031
|
const handle_keydown = (e) => {
|
|
6037
6032
|
switch (e.key) {
|
|
@@ -6069,7 +6064,7 @@ var HazoUiTextarea = ({
|
|
|
6069
6064
|
handle_command_remove,
|
|
6070
6065
|
handle_edit_close
|
|
6071
6066
|
]);
|
|
6072
|
-
|
|
6067
|
+
React25.useEffect(() => {
|
|
6073
6068
|
const handle_pill_click = (e) => {
|
|
6074
6069
|
const detail = e.detail;
|
|
6075
6070
|
const { id, prefix, action, action_label, node_pos } = detail;
|
|
@@ -6616,7 +6611,7 @@ function HazoUiConfirmDialog({
|
|
|
6616
6611
|
openAnimation = "zoom",
|
|
6617
6612
|
closeAnimation = "zoom"
|
|
6618
6613
|
}) {
|
|
6619
|
-
const [internal_loading, set_internal_loading] =
|
|
6614
|
+
const [internal_loading, set_internal_loading] = React25.useState(false);
|
|
6620
6615
|
const config = get_hazo_ui_config();
|
|
6621
6616
|
const variant_preset = variant !== "default" ? CONFIRM_VARIANT_PRESETS[variant] : void 0;
|
|
6622
6617
|
const is_loading = external_loading ?? internal_loading;
|
|
@@ -6653,7 +6648,7 @@ function HazoUiConfirmDialog({
|
|
|
6653
6648
|
onCancel?.();
|
|
6654
6649
|
onOpenChange(false);
|
|
6655
6650
|
};
|
|
6656
|
-
const cancel_ref =
|
|
6651
|
+
const cancel_ref = React25.useRef(null);
|
|
6657
6652
|
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
6658
6653
|
/* @__PURE__ */ jsx(
|
|
6659
6654
|
DialogOverlay,
|
|
@@ -6738,7 +6733,7 @@ Drawer.displayName = "Drawer";
|
|
|
6738
6733
|
var DrawerTrigger = Drawer$1.Trigger;
|
|
6739
6734
|
var DrawerPortal = Drawer$1.Portal;
|
|
6740
6735
|
var DrawerClose = Drawer$1.Close;
|
|
6741
|
-
var DrawerOverlay =
|
|
6736
|
+
var DrawerOverlay = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6742
6737
|
Drawer$1.Overlay,
|
|
6743
6738
|
{
|
|
6744
6739
|
ref,
|
|
@@ -6750,7 +6745,7 @@ var DrawerOverlay = React27.forwardRef(({ className, ...props }, ref) => /* @__P
|
|
|
6750
6745
|
}
|
|
6751
6746
|
));
|
|
6752
6747
|
DrawerOverlay.displayName = "DrawerOverlay";
|
|
6753
|
-
var DrawerContent =
|
|
6748
|
+
var DrawerContent = React25.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DrawerPortal, { children: [
|
|
6754
6749
|
/* @__PURE__ */ jsx(DrawerOverlay, {}),
|
|
6755
6750
|
/* @__PURE__ */ jsxs(
|
|
6756
6751
|
Drawer$1.Content,
|
|
@@ -6791,7 +6786,7 @@ var DrawerFooter = ({
|
|
|
6791
6786
|
}
|
|
6792
6787
|
);
|
|
6793
6788
|
DrawerFooter.displayName = "DrawerFooter";
|
|
6794
|
-
var DrawerTitle =
|
|
6789
|
+
var DrawerTitle = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6795
6790
|
Drawer$1.Title,
|
|
6796
6791
|
{
|
|
6797
6792
|
ref,
|
|
@@ -6803,7 +6798,7 @@ var DrawerTitle = React27.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
6803
6798
|
}
|
|
6804
6799
|
));
|
|
6805
6800
|
DrawerTitle.displayName = "DrawerTitle";
|
|
6806
|
-
var DrawerDescription =
|
|
6801
|
+
var DrawerDescription = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6807
6802
|
Drawer$1.Description,
|
|
6808
6803
|
{
|
|
6809
6804
|
ref,
|
|
@@ -6813,14 +6808,14 @@ var DrawerDescription = React27.forwardRef(({ className, ...props }, ref) => /*
|
|
|
6813
6808
|
));
|
|
6814
6809
|
DrawerDescription.displayName = "DrawerDescription";
|
|
6815
6810
|
function useMediaQuery(query) {
|
|
6816
|
-
const get_match =
|
|
6811
|
+
const get_match = React25.useCallback(() => {
|
|
6817
6812
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
6818
6813
|
return false;
|
|
6819
6814
|
}
|
|
6820
6815
|
return window.matchMedia(query).matches;
|
|
6821
6816
|
}, [query]);
|
|
6822
|
-
const [matches, set_matches] =
|
|
6823
|
-
|
|
6817
|
+
const [matches, set_matches] = React25.useState(false);
|
|
6818
|
+
React25.useEffect(() => {
|
|
6824
6819
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
6825
6820
|
return;
|
|
6826
6821
|
}
|
|
@@ -6837,7 +6832,7 @@ function useMediaQuery(query) {
|
|
|
6837
6832
|
return matches;
|
|
6838
6833
|
}
|
|
6839
6834
|
var Accordion = AccordionPrimitive.Root;
|
|
6840
|
-
var AccordionItem =
|
|
6835
|
+
var AccordionItem = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6841
6836
|
AccordionPrimitive.Item,
|
|
6842
6837
|
{
|
|
6843
6838
|
ref,
|
|
@@ -6846,7 +6841,7 @@ var AccordionItem = React27.forwardRef(({ className, ...props }, ref) => /* @__P
|
|
|
6846
6841
|
}
|
|
6847
6842
|
));
|
|
6848
6843
|
AccordionItem.displayName = "AccordionItem";
|
|
6849
|
-
var AccordionTrigger =
|
|
6844
|
+
var AccordionTrigger = React25.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(AccordionPrimitive.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
|
|
6850
6845
|
AccordionPrimitive.Trigger,
|
|
6851
6846
|
{
|
|
6852
6847
|
ref,
|
|
@@ -6862,7 +6857,7 @@ var AccordionTrigger = React27.forwardRef(({ className, children, ...props }, re
|
|
|
6862
6857
|
}
|
|
6863
6858
|
) }));
|
|
6864
6859
|
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
|
|
6865
|
-
var AccordionContent =
|
|
6860
|
+
var AccordionContent = React25.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6866
6861
|
AccordionPrimitive.Content,
|
|
6867
6862
|
{
|
|
6868
6863
|
ref,
|
|
@@ -6872,7 +6867,7 @@ var AccordionContent = React27.forwardRef(({ className, children, ...props }, re
|
|
|
6872
6867
|
}
|
|
6873
6868
|
));
|
|
6874
6869
|
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
|
|
6875
|
-
var Checkbox =
|
|
6870
|
+
var Checkbox = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6876
6871
|
CheckboxPrimitive.Root,
|
|
6877
6872
|
{
|
|
6878
6873
|
ref,
|
|
@@ -6897,7 +6892,7 @@ var DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
|
6897
6892
|
var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
6898
6893
|
var DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
6899
6894
|
var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
6900
|
-
var DropdownMenuSubTrigger =
|
|
6895
|
+
var DropdownMenuSubTrigger = React25.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
6901
6896
|
DropdownMenuPrimitive.SubTrigger,
|
|
6902
6897
|
{
|
|
6903
6898
|
ref,
|
|
@@ -6914,7 +6909,7 @@ var DropdownMenuSubTrigger = React27.forwardRef(({ className, inset, children, .
|
|
|
6914
6909
|
}
|
|
6915
6910
|
));
|
|
6916
6911
|
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
|
|
6917
|
-
var DropdownMenuSubContent =
|
|
6912
|
+
var DropdownMenuSubContent = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6918
6913
|
DropdownMenuPrimitive.SubContent,
|
|
6919
6914
|
{
|
|
6920
6915
|
ref,
|
|
@@ -6926,7 +6921,7 @@ var DropdownMenuSubContent = React27.forwardRef(({ className, ...props }, ref) =
|
|
|
6926
6921
|
}
|
|
6927
6922
|
));
|
|
6928
6923
|
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
|
|
6929
|
-
var DropdownMenuContent =
|
|
6924
|
+
var DropdownMenuContent = React25.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
6930
6925
|
DropdownMenuPrimitive.Content,
|
|
6931
6926
|
{
|
|
6932
6927
|
ref,
|
|
@@ -6939,7 +6934,7 @@ var DropdownMenuContent = React27.forwardRef(({ className, sideOffset = 4, ...pr
|
|
|
6939
6934
|
}
|
|
6940
6935
|
) }));
|
|
6941
6936
|
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
6942
|
-
var DropdownMenuItem =
|
|
6937
|
+
var DropdownMenuItem = React25.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6943
6938
|
DropdownMenuPrimitive.Item,
|
|
6944
6939
|
{
|
|
6945
6940
|
ref,
|
|
@@ -6952,7 +6947,7 @@ var DropdownMenuItem = React27.forwardRef(({ className, inset, ...props }, ref)
|
|
|
6952
6947
|
}
|
|
6953
6948
|
));
|
|
6954
6949
|
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
6955
|
-
var DropdownMenuCheckboxItem =
|
|
6950
|
+
var DropdownMenuCheckboxItem = React25.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
6956
6951
|
DropdownMenuPrimitive.CheckboxItem,
|
|
6957
6952
|
{
|
|
6958
6953
|
ref,
|
|
@@ -6969,7 +6964,7 @@ var DropdownMenuCheckboxItem = React27.forwardRef(({ className, children, checke
|
|
|
6969
6964
|
}
|
|
6970
6965
|
));
|
|
6971
6966
|
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
|
|
6972
|
-
var DropdownMenuRadioItem =
|
|
6967
|
+
var DropdownMenuRadioItem = React25.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
6973
6968
|
DropdownMenuPrimitive.RadioItem,
|
|
6974
6969
|
{
|
|
6975
6970
|
ref,
|
|
@@ -6985,7 +6980,7 @@ var DropdownMenuRadioItem = React27.forwardRef(({ className, children, ...props
|
|
|
6985
6980
|
}
|
|
6986
6981
|
));
|
|
6987
6982
|
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
|
6988
|
-
var DropdownMenuLabel =
|
|
6983
|
+
var DropdownMenuLabel = React25.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6989
6984
|
DropdownMenuPrimitive.Label,
|
|
6990
6985
|
{
|
|
6991
6986
|
ref,
|
|
@@ -6998,7 +6993,7 @@ var DropdownMenuLabel = React27.forwardRef(({ className, inset, ...props }, ref)
|
|
|
6998
6993
|
}
|
|
6999
6994
|
));
|
|
7000
6995
|
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
|
7001
|
-
var DropdownMenuSeparator =
|
|
6996
|
+
var DropdownMenuSeparator = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7002
6997
|
DropdownMenuPrimitive.Separator,
|
|
7003
6998
|
{
|
|
7004
6999
|
ref,
|
|
@@ -7022,7 +7017,7 @@ var DropdownMenuShortcut = ({
|
|
|
7022
7017
|
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
|
7023
7018
|
var HoverCard = HoverCardPrimitive.Root;
|
|
7024
7019
|
var HoverCardTrigger = HoverCardPrimitive.Trigger;
|
|
7025
|
-
var HoverCardContent =
|
|
7020
|
+
var HoverCardContent = React25.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7026
7021
|
HoverCardPrimitive.Content,
|
|
7027
7022
|
{
|
|
7028
7023
|
ref,
|
|
@@ -7036,34 +7031,70 @@ var HoverCardContent = React27.forwardRef(({ className, align = "center", sideOf
|
|
|
7036
7031
|
}
|
|
7037
7032
|
));
|
|
7038
7033
|
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
|
|
7039
|
-
var
|
|
7034
|
+
var Label3 = React25.forwardRef(
|
|
7040
7035
|
({ className, ...props }, ref) => {
|
|
7041
7036
|
return /* @__PURE__ */ jsx(
|
|
7042
|
-
"
|
|
7037
|
+
"label",
|
|
7043
7038
|
{
|
|
7039
|
+
ref,
|
|
7044
7040
|
className: cn(
|
|
7045
|
-
"
|
|
7046
|
-
"text-sm ring-offset-background",
|
|
7047
|
-
"placeholder:text-muted-foreground",
|
|
7048
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
7049
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
7041
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
7050
7042
|
className
|
|
7051
7043
|
),
|
|
7052
|
-
ref,
|
|
7053
7044
|
...props
|
|
7054
7045
|
}
|
|
7055
7046
|
);
|
|
7056
7047
|
}
|
|
7057
7048
|
);
|
|
7058
|
-
|
|
7059
|
-
var
|
|
7060
|
-
|
|
7049
|
+
Label3.displayName = "Label";
|
|
7050
|
+
var Switch = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7051
|
+
SwitchPrimitives.Root,
|
|
7061
7052
|
{
|
|
7062
|
-
ref,
|
|
7063
|
-
decorative,
|
|
7064
|
-
orientation,
|
|
7065
7053
|
className: cn(
|
|
7066
|
-
"shrink-0 bg-
|
|
7054
|
+
"peer inline-flex h-6 w-11 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",
|
|
7055
|
+
className
|
|
7056
|
+
),
|
|
7057
|
+
...props,
|
|
7058
|
+
ref,
|
|
7059
|
+
children: /* @__PURE__ */ jsx(
|
|
7060
|
+
SwitchPrimitives.Thumb,
|
|
7061
|
+
{
|
|
7062
|
+
className: cn(
|
|
7063
|
+
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
|
|
7064
|
+
)
|
|
7065
|
+
}
|
|
7066
|
+
)
|
|
7067
|
+
}
|
|
7068
|
+
));
|
|
7069
|
+
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
7070
|
+
var Textarea = React25.forwardRef(
|
|
7071
|
+
({ className, ...props }, ref) => {
|
|
7072
|
+
return /* @__PURE__ */ jsx(
|
|
7073
|
+
"textarea",
|
|
7074
|
+
{
|
|
7075
|
+
className: cn(
|
|
7076
|
+
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2",
|
|
7077
|
+
"text-sm ring-offset-background",
|
|
7078
|
+
"placeholder:text-muted-foreground",
|
|
7079
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
7080
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
7081
|
+
className
|
|
7082
|
+
),
|
|
7083
|
+
ref,
|
|
7084
|
+
...props
|
|
7085
|
+
}
|
|
7086
|
+
);
|
|
7087
|
+
}
|
|
7088
|
+
);
|
|
7089
|
+
Textarea.displayName = "Textarea";
|
|
7090
|
+
var Separator3 = React25.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7091
|
+
SeparatorPrimitive.Root,
|
|
7092
|
+
{
|
|
7093
|
+
ref,
|
|
7094
|
+
decorative,
|
|
7095
|
+
orientation,
|
|
7096
|
+
className: cn(
|
|
7097
|
+
"shrink-0 bg-border",
|
|
7067
7098
|
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
7068
7099
|
className
|
|
7069
7100
|
),
|
|
@@ -7074,7 +7105,7 @@ Separator3.displayName = SeparatorPrimitive.Root.displayName;
|
|
|
7074
7105
|
var Collapsible = CollapsiblePrimitive.Root;
|
|
7075
7106
|
var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
|
|
7076
7107
|
var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
|
|
7077
|
-
var ScrollArea =
|
|
7108
|
+
var ScrollArea = React25.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
7078
7109
|
ScrollAreaPrimitive.Root,
|
|
7079
7110
|
{
|
|
7080
7111
|
ref,
|
|
@@ -7088,7 +7119,7 @@ var ScrollArea = React27.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
7088
7119
|
}
|
|
7089
7120
|
));
|
|
7090
7121
|
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
7091
|
-
var ScrollBar =
|
|
7122
|
+
var ScrollBar = React25.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7092
7123
|
ScrollAreaPrimitive.ScrollAreaScrollbar,
|
|
7093
7124
|
{
|
|
7094
7125
|
ref,
|
|
@@ -7104,27 +7135,27 @@ var ScrollBar = React27.forwardRef(({ className, orientation = "vertical", ...pr
|
|
|
7104
7135
|
}
|
|
7105
7136
|
));
|
|
7106
7137
|
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
7107
|
-
var Card =
|
|
7138
|
+
var Card = React25.forwardRef(
|
|
7108
7139
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("rounded-lg border bg-card text-card-foreground shadow-sm", className), ...props })
|
|
7109
7140
|
);
|
|
7110
7141
|
Card.displayName = "Card";
|
|
7111
|
-
var CardHeader =
|
|
7142
|
+
var CardHeader = React25.forwardRef(
|
|
7112
7143
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props })
|
|
7113
7144
|
);
|
|
7114
7145
|
CardHeader.displayName = "CardHeader";
|
|
7115
|
-
var CardTitle =
|
|
7146
|
+
var CardTitle = React25.forwardRef(
|
|
7116
7147
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("h3", { ref, className: cn("text-2xl font-semibold leading-none tracking-tight", className), ...props })
|
|
7117
7148
|
);
|
|
7118
7149
|
CardTitle.displayName = "CardTitle";
|
|
7119
|
-
var CardDescription =
|
|
7150
|
+
var CardDescription = React25.forwardRef(
|
|
7120
7151
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props })
|
|
7121
7152
|
);
|
|
7122
7153
|
CardDescription.displayName = "CardDescription";
|
|
7123
|
-
var CardContent =
|
|
7154
|
+
var CardContent = React25.forwardRef(
|
|
7124
7155
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props })
|
|
7125
7156
|
);
|
|
7126
7157
|
CardContent.displayName = "CardContent";
|
|
7127
|
-
var CardFooter =
|
|
7158
|
+
var CardFooter = React25.forwardRef(
|
|
7128
7159
|
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center p-6 pt-0", className), ...props })
|
|
7129
7160
|
);
|
|
7130
7161
|
CardFooter.displayName = "CardFooter";
|
|
@@ -7157,16 +7188,16 @@ var toggleVariants = cva(
|
|
|
7157
7188
|
defaultVariants: { variant: "default", size: "default" }
|
|
7158
7189
|
}
|
|
7159
7190
|
);
|
|
7160
|
-
var Toggle =
|
|
7191
|
+
var Toggle = React25.forwardRef(({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx(TogglePrimitive.Root, { ref, className: cn(toggleVariants({ variant, size, className })), ...props }));
|
|
7161
7192
|
Toggle.displayName = TogglePrimitive.Root.displayName;
|
|
7162
|
-
var ToggleGroupContext =
|
|
7193
|
+
var ToggleGroupContext = React25.createContext({
|
|
7163
7194
|
size: "default",
|
|
7164
7195
|
variant: "default"
|
|
7165
7196
|
});
|
|
7166
|
-
var ToggleGroup =
|
|
7197
|
+
var ToggleGroup = React25.forwardRef(({ className, variant, size, children, ...props }, ref) => /* @__PURE__ */ jsx(ToggleGroupPrimitive.Root, { ref, className: cn("flex items-center justify-center gap-1", className), ...props, children: /* @__PURE__ */ jsx(ToggleGroupContext.Provider, { value: { variant, size }, children }) }));
|
|
7167
7198
|
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
|
|
7168
|
-
var ToggleGroupItem =
|
|
7169
|
-
const context =
|
|
7199
|
+
var ToggleGroupItem = React25.forwardRef(({ className, children, variant, size, ...props }, ref) => {
|
|
7200
|
+
const context = React25.useContext(ToggleGroupContext);
|
|
7170
7201
|
return /* @__PURE__ */ jsx(
|
|
7171
7202
|
ToggleGroupPrimitive.Item,
|
|
7172
7203
|
{
|
|
@@ -7181,7 +7212,7 @@ ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
|
7181
7212
|
var AlertDialog = AlertDialogPrimitive.Root;
|
|
7182
7213
|
var AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
|
7183
7214
|
var AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
7184
|
-
var AlertDialogOverlay =
|
|
7215
|
+
var AlertDialogOverlay = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7185
7216
|
AlertDialogPrimitive.Overlay,
|
|
7186
7217
|
{
|
|
7187
7218
|
ref,
|
|
@@ -7190,7 +7221,7 @@ var AlertDialogOverlay = React27.forwardRef(({ className, ...props }, ref) => /*
|
|
|
7190
7221
|
}
|
|
7191
7222
|
));
|
|
7192
7223
|
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
|
|
7193
|
-
var AlertDialogContent =
|
|
7224
|
+
var AlertDialogContent = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [
|
|
7194
7225
|
/* @__PURE__ */ jsx(AlertDialogOverlay, {}),
|
|
7195
7226
|
/* @__PURE__ */ jsx(
|
|
7196
7227
|
AlertDialogPrimitive.Content,
|
|
@@ -7206,13 +7237,13 @@ var AlertDialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div",
|
|
|
7206
7237
|
AlertDialogHeader.displayName = "AlertDialogHeader";
|
|
7207
7238
|
var AlertDialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props });
|
|
7208
7239
|
AlertDialogFooter.displayName = "AlertDialogFooter";
|
|
7209
|
-
var AlertDialogTitle =
|
|
7240
|
+
var AlertDialogTitle = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(AlertDialogPrimitive.Title, { ref, className: cn("text-lg font-semibold", className), ...props }));
|
|
7210
7241
|
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
|
|
7211
|
-
var AlertDialogDescription =
|
|
7242
|
+
var AlertDialogDescription = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(AlertDialogPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
|
|
7212
7243
|
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
|
|
7213
|
-
var AlertDialogAction =
|
|
7244
|
+
var AlertDialogAction = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(AlertDialogPrimitive.Action, { ref, className: cn(buttonVariants(), className), ...props }));
|
|
7214
7245
|
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
|
|
7215
|
-
var AlertDialogCancel =
|
|
7246
|
+
var AlertDialogCancel = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(AlertDialogPrimitive.Cancel, { ref, className: cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className), ...props }));
|
|
7216
7247
|
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
|
|
7217
7248
|
var buttonGroupVariants = cva(
|
|
7218
7249
|
"flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10",
|
|
@@ -7240,7 +7271,1969 @@ function ButtonGroupText({ className, asChild = false, ...props }) {
|
|
|
7240
7271
|
function ButtonGroupSeparator({ className, orientation = "vertical", ...props }) {
|
|
7241
7272
|
return /* @__PURE__ */ jsx(Separator3, { orientation, className: cn("bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto", className), ...props });
|
|
7242
7273
|
}
|
|
7274
|
+
var SkeletonBase = React25.forwardRef(
|
|
7275
|
+
({ className, ...rest }, ref) => /* @__PURE__ */ jsx(
|
|
7276
|
+
"div",
|
|
7277
|
+
{
|
|
7278
|
+
ref,
|
|
7279
|
+
"data-hazo-skeleton": "",
|
|
7280
|
+
"aria-hidden": "true",
|
|
7281
|
+
className: cn("hazo-shimmer rounded-md", className),
|
|
7282
|
+
...rest
|
|
7283
|
+
}
|
|
7284
|
+
)
|
|
7285
|
+
);
|
|
7286
|
+
SkeletonBase.displayName = "Skeleton";
|
|
7287
|
+
var Skeleton = SkeletonBase;
|
|
7288
|
+
function SkeletonCircle({ size = 40, className }) {
|
|
7289
|
+
return /* @__PURE__ */ jsx(
|
|
7290
|
+
SkeletonBase,
|
|
7291
|
+
{
|
|
7292
|
+
className: cn("rounded-full", className),
|
|
7293
|
+
style: { width: size, height: size }
|
|
7294
|
+
}
|
|
7295
|
+
);
|
|
7296
|
+
}
|
|
7297
|
+
function SkeletonBar({ width = "100%", height = 12, className }) {
|
|
7298
|
+
return /* @__PURE__ */ jsx(
|
|
7299
|
+
SkeletonBase,
|
|
7300
|
+
{
|
|
7301
|
+
className,
|
|
7302
|
+
style: { width, height }
|
|
7303
|
+
}
|
|
7304
|
+
);
|
|
7305
|
+
}
|
|
7306
|
+
function SkeletonRect({ width = "100%", height = 96, radius = 6, className }) {
|
|
7307
|
+
return /* @__PURE__ */ jsx(
|
|
7308
|
+
SkeletonBase,
|
|
7309
|
+
{
|
|
7310
|
+
className,
|
|
7311
|
+
style: { width, height, borderRadius: radius }
|
|
7312
|
+
}
|
|
7313
|
+
);
|
|
7314
|
+
}
|
|
7315
|
+
function SkeletonGroup({ label = "Loading content", children, className, ...rest }) {
|
|
7316
|
+
return /* @__PURE__ */ jsxs(
|
|
7317
|
+
"div",
|
|
7318
|
+
{
|
|
7319
|
+
role: "status",
|
|
7320
|
+
"aria-busy": "true",
|
|
7321
|
+
"aria-label": label,
|
|
7322
|
+
className: cn("space-y-2", className),
|
|
7323
|
+
...rest,
|
|
7324
|
+
children: [
|
|
7325
|
+
children,
|
|
7326
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: label })
|
|
7327
|
+
]
|
|
7328
|
+
}
|
|
7329
|
+
);
|
|
7330
|
+
}
|
|
7331
|
+
function EmptyState({
|
|
7332
|
+
icon,
|
|
7333
|
+
title,
|
|
7334
|
+
description,
|
|
7335
|
+
action,
|
|
7336
|
+
size = "md",
|
|
7337
|
+
className
|
|
7338
|
+
}) {
|
|
7339
|
+
const sizing = {
|
|
7340
|
+
sm: { wrap: "py-6 gap-2", icon: "w-8 h-8 mb-1", title: "text-sm font-medium", desc: "text-xs" },
|
|
7341
|
+
md: { wrap: "py-10 gap-3", icon: "w-12 h-12 mb-2", title: "text-base font-semibold", desc: "text-sm" },
|
|
7342
|
+
lg: { wrap: "py-16 gap-4", icon: "w-16 h-16 mb-3", title: "text-lg font-semibold", desc: "text-base" }
|
|
7343
|
+
}[size];
|
|
7344
|
+
return /* @__PURE__ */ jsxs(
|
|
7345
|
+
"div",
|
|
7346
|
+
{
|
|
7347
|
+
className: cn(
|
|
7348
|
+
"flex flex-col items-center justify-center text-center text-muted-foreground",
|
|
7349
|
+
sizing.wrap,
|
|
7350
|
+
className
|
|
7351
|
+
),
|
|
7352
|
+
children: [
|
|
7353
|
+
icon ? /* @__PURE__ */ jsx("div", { className: cn("text-muted-foreground/60", sizing.icon), children: icon }) : null,
|
|
7354
|
+
/* @__PURE__ */ jsx("div", { className: cn("text-foreground", sizing.title), children: title }),
|
|
7355
|
+
description ? /* @__PURE__ */ jsx("div", { className: cn("max-w-md text-muted-foreground", sizing.desc), children: description }) : null,
|
|
7356
|
+
action ? /* @__PURE__ */ jsx("div", { className: "mt-2 flex items-center gap-2", children: action }) : null
|
|
7357
|
+
]
|
|
7358
|
+
}
|
|
7359
|
+
);
|
|
7360
|
+
}
|
|
7361
|
+
function ErrorBanner({
|
|
7362
|
+
severity = "error",
|
|
7363
|
+
title,
|
|
7364
|
+
message,
|
|
7365
|
+
icon,
|
|
7366
|
+
action,
|
|
7367
|
+
onDismiss,
|
|
7368
|
+
className
|
|
7369
|
+
}) {
|
|
7370
|
+
const palette = severity === "warning" ? "border-amber-300 bg-amber-50 text-amber-900 dark:border-amber-700 dark:bg-amber-950 dark:text-amber-100" : "border-destructive/40 bg-destructive/10 text-destructive-foreground";
|
|
7371
|
+
const iconColor = severity === "warning" ? "text-amber-600" : "text-destructive";
|
|
7372
|
+
const resolvedIcon = icon ?? (severity === "warning" ? /* @__PURE__ */ jsx(AlertTriangle, { className: cn("h-5 w-5", iconColor), "aria-hidden": "true" }) : /* @__PURE__ */ jsx(OctagonAlert, { className: cn("h-5 w-5", iconColor), "aria-hidden": "true" }));
|
|
7373
|
+
return /* @__PURE__ */ jsxs(
|
|
7374
|
+
"div",
|
|
7375
|
+
{
|
|
7376
|
+
role: "alert",
|
|
7377
|
+
"aria-live": severity === "error" ? "assertive" : "polite",
|
|
7378
|
+
className: cn(
|
|
7379
|
+
"flex items-start gap-3 rounded-md border px-4 py-3 text-sm",
|
|
7380
|
+
palette,
|
|
7381
|
+
className
|
|
7382
|
+
),
|
|
7383
|
+
children: [
|
|
7384
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 mt-0.5", children: resolvedIcon }),
|
|
7385
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
7386
|
+
title ? /* @__PURE__ */ jsx("div", { className: "font-semibold leading-tight", children: title }) : null,
|
|
7387
|
+
/* @__PURE__ */ jsx("div", { className: cn("leading-snug", title ? "mt-1" : ""), children: message }),
|
|
7388
|
+
action ? /* @__PURE__ */ jsx("div", { className: "mt-2 flex items-center gap-2", children: action }) : null
|
|
7389
|
+
] }),
|
|
7390
|
+
onDismiss ? /* @__PURE__ */ jsx(
|
|
7391
|
+
"button",
|
|
7392
|
+
{
|
|
7393
|
+
type: "button",
|
|
7394
|
+
onClick: onDismiss,
|
|
7395
|
+
"aria-label": "Dismiss",
|
|
7396
|
+
className: "flex-shrink-0 rounded p-1 hover:bg-black/5 focus:outline-none focus:ring-2 focus:ring-offset-2 dark:hover:bg-white/5",
|
|
7397
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
7398
|
+
}
|
|
7399
|
+
) : null
|
|
7400
|
+
]
|
|
7401
|
+
}
|
|
7402
|
+
);
|
|
7403
|
+
}
|
|
7404
|
+
function ErrorPage({
|
|
7405
|
+
title = "Something went wrong",
|
|
7406
|
+
description,
|
|
7407
|
+
errorCode,
|
|
7408
|
+
correlationId,
|
|
7409
|
+
actions,
|
|
7410
|
+
illustration,
|
|
7411
|
+
className
|
|
7412
|
+
}) {
|
|
7413
|
+
return /* @__PURE__ */ jsxs(
|
|
7414
|
+
"div",
|
|
7415
|
+
{
|
|
7416
|
+
role: "alert",
|
|
7417
|
+
"aria-live": "assertive",
|
|
7418
|
+
className: cn(
|
|
7419
|
+
"mx-auto flex max-w-md flex-col items-center justify-center gap-4 px-6 py-16 text-center",
|
|
7420
|
+
className
|
|
7421
|
+
),
|
|
7422
|
+
children: [
|
|
7423
|
+
/* @__PURE__ */ jsx("div", { className: "text-destructive", children: illustration ?? /* @__PURE__ */ jsx(OctagonAlert, { className: "h-16 w-16", "aria-hidden": "true" }) }),
|
|
7424
|
+
errorCode ? /* @__PURE__ */ jsx("div", { className: "rounded-full bg-muted px-3 py-1 text-xs font-mono uppercase tracking-wider text-muted-foreground", children: errorCode }) : null,
|
|
7425
|
+
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold text-foreground", children: title }),
|
|
7426
|
+
description ? /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: description }) : null,
|
|
7427
|
+
correlationId ? /* @__PURE__ */ jsxs("div", { className: "w-full rounded-md border bg-muted/40 px-3 py-2 text-left", children: [
|
|
7428
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wider text-muted-foreground", children: "Correlation ID" }),
|
|
7429
|
+
/* @__PURE__ */ jsx("code", { className: "break-all text-xs", children: correlationId })
|
|
7430
|
+
] }) : null,
|
|
7431
|
+
actions ? /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap items-center justify-center gap-2", children: actions }) : null
|
|
7432
|
+
]
|
|
7433
|
+
}
|
|
7434
|
+
);
|
|
7435
|
+
}
|
|
7436
|
+
function LoadingTimeout({
|
|
7437
|
+
active,
|
|
7438
|
+
children,
|
|
7439
|
+
skeleton,
|
|
7440
|
+
onRetry,
|
|
7441
|
+
thresholds,
|
|
7442
|
+
label = "content",
|
|
7443
|
+
className
|
|
7444
|
+
}) {
|
|
7445
|
+
const t = {
|
|
7446
|
+
gentle: thresholds?.gentle ?? 5e3,
|
|
7447
|
+
firm: thresholds?.firm ?? 15e3,
|
|
7448
|
+
expired: thresholds?.expired ?? 3e4
|
|
7449
|
+
};
|
|
7450
|
+
const [phase, setPhase] = React25.useState(active ? "silent" : "idle");
|
|
7451
|
+
React25.useEffect(() => {
|
|
7452
|
+
if (!active) {
|
|
7453
|
+
setPhase("idle");
|
|
7454
|
+
return;
|
|
7455
|
+
}
|
|
7456
|
+
setPhase("silent");
|
|
7457
|
+
const gentleTimer = window.setTimeout(() => setPhase("gentle"), t.gentle);
|
|
7458
|
+
const firmTimer = window.setTimeout(() => setPhase("firm"), t.firm);
|
|
7459
|
+
const expiredTimer = window.setTimeout(() => setPhase("expired"), t.expired);
|
|
7460
|
+
return () => {
|
|
7461
|
+
window.clearTimeout(gentleTimer);
|
|
7462
|
+
window.clearTimeout(firmTimer);
|
|
7463
|
+
window.clearTimeout(expiredTimer);
|
|
7464
|
+
};
|
|
7465
|
+
}, [active, t.gentle, t.firm, t.expired]);
|
|
7466
|
+
if (!active) {
|
|
7467
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
7468
|
+
}
|
|
7469
|
+
if (phase === "expired") {
|
|
7470
|
+
return /* @__PURE__ */ jsx("div", { className, role: "alert", "aria-busy": "false", children: /* @__PURE__ */ jsx(
|
|
7471
|
+
ErrorBanner,
|
|
7472
|
+
{
|
|
7473
|
+
severity: "error",
|
|
7474
|
+
title: "This is taking longer than expected",
|
|
7475
|
+
message: `We're still trying to load the ${label}. The connection may be slow.`,
|
|
7476
|
+
action: onRetry ? /* @__PURE__ */ jsx(
|
|
7477
|
+
"button",
|
|
7478
|
+
{
|
|
7479
|
+
type: "button",
|
|
7480
|
+
onClick: onRetry,
|
|
7481
|
+
className: "rounded bg-foreground/10 px-3 py-1.5 text-sm font-medium hover:bg-foreground/15",
|
|
7482
|
+
children: "Try again"
|
|
7483
|
+
}
|
|
7484
|
+
) : null
|
|
7485
|
+
}
|
|
7486
|
+
) });
|
|
7487
|
+
}
|
|
7488
|
+
return /* @__PURE__ */ jsxs("div", { className, role: "status", "aria-busy": "true", "aria-live": "polite", children: [
|
|
7489
|
+
skeleton,
|
|
7490
|
+
phase === "gentle" ? /* @__PURE__ */ jsxs("div", { className: "mt-3 text-center text-sm text-muted-foreground", children: [
|
|
7491
|
+
"Loading ",
|
|
7492
|
+
label,
|
|
7493
|
+
"\u2026"
|
|
7494
|
+
] }) : null,
|
|
7495
|
+
phase === "firm" ? /* @__PURE__ */ jsx("div", { className: "mt-3 text-center text-sm text-muted-foreground", children: "Still working on it \u2014 almost there." }) : null
|
|
7496
|
+
] });
|
|
7497
|
+
}
|
|
7498
|
+
function ProgressiveImage({
|
|
7499
|
+
src,
|
|
7500
|
+
alt,
|
|
7501
|
+
lqip,
|
|
7502
|
+
width,
|
|
7503
|
+
height,
|
|
7504
|
+
loading = "lazy",
|
|
7505
|
+
fit = "cover",
|
|
7506
|
+
className,
|
|
7507
|
+
onLoad,
|
|
7508
|
+
onError
|
|
7509
|
+
}) {
|
|
7510
|
+
const [loaded, setLoaded] = React25.useState(false);
|
|
7511
|
+
return /* @__PURE__ */ jsxs(
|
|
7512
|
+
"div",
|
|
7513
|
+
{
|
|
7514
|
+
className: cn("relative overflow-hidden bg-muted", className),
|
|
7515
|
+
style: { width, height },
|
|
7516
|
+
children: [
|
|
7517
|
+
lqip ? /* @__PURE__ */ jsx(
|
|
7518
|
+
"img",
|
|
7519
|
+
{
|
|
7520
|
+
src: lqip,
|
|
7521
|
+
alt: "",
|
|
7522
|
+
"aria-hidden": "true",
|
|
7523
|
+
className: cn(
|
|
7524
|
+
"absolute inset-0 h-full w-full object-cover blur-md scale-110 transition-opacity duration-300",
|
|
7525
|
+
loaded ? "opacity-0" : "opacity-100"
|
|
7526
|
+
)
|
|
7527
|
+
}
|
|
7528
|
+
) : null,
|
|
7529
|
+
/* @__PURE__ */ jsx(
|
|
7530
|
+
"img",
|
|
7531
|
+
{
|
|
7532
|
+
src,
|
|
7533
|
+
alt,
|
|
7534
|
+
loading,
|
|
7535
|
+
onLoad: () => {
|
|
7536
|
+
setLoaded(true);
|
|
7537
|
+
onLoad?.();
|
|
7538
|
+
},
|
|
7539
|
+
onError,
|
|
7540
|
+
className: cn(
|
|
7541
|
+
"absolute inset-0 h-full w-full transition-opacity duration-300",
|
|
7542
|
+
`object-${fit}`,
|
|
7543
|
+
loaded ? "opacity-100" : "opacity-0"
|
|
7544
|
+
)
|
|
7545
|
+
}
|
|
7546
|
+
)
|
|
7547
|
+
]
|
|
7548
|
+
}
|
|
7549
|
+
);
|
|
7550
|
+
}
|
|
7551
|
+
function HazoUiToaster({
|
|
7552
|
+
position = "bottom-right",
|
|
7553
|
+
closeButton = true,
|
|
7554
|
+
visibleToasts = 5
|
|
7555
|
+
} = {}) {
|
|
7556
|
+
return /* @__PURE__ */ jsx(
|
|
7557
|
+
Toaster,
|
|
7558
|
+
{
|
|
7559
|
+
position,
|
|
7560
|
+
closeButton,
|
|
7561
|
+
visibleToasts,
|
|
7562
|
+
theme: "system",
|
|
7563
|
+
richColors: true,
|
|
7564
|
+
toastOptions: {
|
|
7565
|
+
classNames: {
|
|
7566
|
+
toast: "group rounded-md border bg-background text-foreground shadow-lg",
|
|
7567
|
+
title: "font-medium",
|
|
7568
|
+
description: "text-muted-foreground text-sm"
|
|
7569
|
+
}
|
|
7570
|
+
}
|
|
7571
|
+
}
|
|
7572
|
+
);
|
|
7573
|
+
}
|
|
7574
|
+
function successToast({ title, description, duration = 3e3, action }) {
|
|
7575
|
+
return toast.success(title, {
|
|
7576
|
+
description,
|
|
7577
|
+
duration,
|
|
7578
|
+
icon: /* @__PURE__ */ jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-600" }),
|
|
7579
|
+
action: action ? { label: action.label, onClick: action.onClick } : void 0
|
|
7580
|
+
});
|
|
7581
|
+
}
|
|
7582
|
+
function errorToast({ title, description, duration = 5e3, action }) {
|
|
7583
|
+
return toast.error(title, {
|
|
7584
|
+
description,
|
|
7585
|
+
duration,
|
|
7586
|
+
icon: /* @__PURE__ */ jsx(OctagonAlert, { className: "h-4 w-4 text-destructive" }),
|
|
7587
|
+
action: action ? { label: action.label, onClick: action.onClick } : void 0
|
|
7588
|
+
});
|
|
7589
|
+
}
|
|
7590
|
+
function useLoadingState(initial = false) {
|
|
7591
|
+
const [isLoading, setLoading] = useState(initial);
|
|
7592
|
+
const withLoading = useCallback(async (fn) => {
|
|
7593
|
+
setLoading(true);
|
|
7594
|
+
try {
|
|
7595
|
+
return await fn();
|
|
7596
|
+
} finally {
|
|
7597
|
+
setLoading(false);
|
|
7598
|
+
}
|
|
7599
|
+
}, []);
|
|
7600
|
+
return { isLoading, setLoading, withLoading };
|
|
7601
|
+
}
|
|
7602
|
+
function useErrorDisplay() {
|
|
7603
|
+
const [error, setRaw] = useState(null);
|
|
7604
|
+
const setError = useCallback((value) => {
|
|
7605
|
+
if (value == null) {
|
|
7606
|
+
setRaw(null);
|
|
7607
|
+
return;
|
|
7608
|
+
}
|
|
7609
|
+
if (typeof value === "string") {
|
|
7610
|
+
setRaw(value);
|
|
7611
|
+
return;
|
|
7612
|
+
}
|
|
7613
|
+
if (value instanceof Error) {
|
|
7614
|
+
setRaw(value.message);
|
|
7615
|
+
return;
|
|
7616
|
+
}
|
|
7617
|
+
setRaw(String(value));
|
|
7618
|
+
}, []);
|
|
7619
|
+
const clearError = useCallback(() => setRaw(null), []);
|
|
7620
|
+
return { error, setError, clearError };
|
|
7621
|
+
}
|
|
7622
|
+
function KanbanCard({
|
|
7623
|
+
item,
|
|
7624
|
+
renderCard,
|
|
7625
|
+
dragging = false,
|
|
7626
|
+
cardClassName,
|
|
7627
|
+
showEdit = false,
|
|
7628
|
+
onEditRequest
|
|
7629
|
+
}) {
|
|
7630
|
+
const {
|
|
7631
|
+
attributes,
|
|
7632
|
+
listeners,
|
|
7633
|
+
setNodeRef,
|
|
7634
|
+
transform,
|
|
7635
|
+
transition,
|
|
7636
|
+
isDragging
|
|
7637
|
+
} = useSortable({ id: item.id, data: { columnKey: item.columnKey } });
|
|
7638
|
+
const priority_var = item.priority ? `--hazo-kanban-priority-${String(item.priority).toLowerCase()}` : null;
|
|
7639
|
+
const style = {
|
|
7640
|
+
transform: CSS.Transform.toString(transform),
|
|
7641
|
+
transition,
|
|
7642
|
+
backgroundColor: "hsl(var(--hazo-kanban-card-bg))",
|
|
7643
|
+
border: `1px solid hsl(var(--hazo-kanban-card-border))`,
|
|
7644
|
+
borderLeft: priority_var ? `4px solid hsl(var(${priority_var}))` : `1px solid hsl(var(--hazo-kanban-card-border))`,
|
|
7645
|
+
opacity: isDragging && !dragging ? 0.4 : 1,
|
|
7646
|
+
cursor: "grab"
|
|
7647
|
+
};
|
|
7648
|
+
return /* @__PURE__ */ jsxs(
|
|
7649
|
+
"div",
|
|
7650
|
+
{
|
|
7651
|
+
ref: setNodeRef,
|
|
7652
|
+
style,
|
|
7653
|
+
className: cn(
|
|
7654
|
+
"cls_hazo_kanban_card group relative rounded-md p-3 mb-2 select-none",
|
|
7655
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7656
|
+
dragging && "cls_hazo_kanban_card_overlay shadow-lg",
|
|
7657
|
+
cardClassName
|
|
7658
|
+
),
|
|
7659
|
+
...attributes,
|
|
7660
|
+
...listeners,
|
|
7661
|
+
role: "button",
|
|
7662
|
+
tabIndex: 0,
|
|
7663
|
+
"aria-roledescription": "draggable card",
|
|
7664
|
+
"aria-grabbed": isDragging,
|
|
7665
|
+
children: [
|
|
7666
|
+
showEdit && onEditRequest && !dragging && /* @__PURE__ */ jsx(
|
|
7667
|
+
"button",
|
|
7668
|
+
{
|
|
7669
|
+
type: "button",
|
|
7670
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
7671
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
7672
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
7673
|
+
onClick: (e) => {
|
|
7674
|
+
e.stopPropagation();
|
|
7675
|
+
onEditRequest(item);
|
|
7676
|
+
},
|
|
7677
|
+
"aria-label": `Edit ${item.id}`,
|
|
7678
|
+
className: cn(
|
|
7679
|
+
"cls_hazo_kanban_card_edit absolute top-1.5 right-1.5",
|
|
7680
|
+
"p-1 rounded-md text-muted-foreground hover:text-foreground hover:bg-accent",
|
|
7681
|
+
"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100",
|
|
7682
|
+
"focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7683
|
+
"transition-opacity duration-150"
|
|
7684
|
+
),
|
|
7685
|
+
tabIndex: 0,
|
|
7686
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" })
|
|
7687
|
+
}
|
|
7688
|
+
),
|
|
7689
|
+
renderCard(item)
|
|
7690
|
+
]
|
|
7691
|
+
}
|
|
7692
|
+
);
|
|
7693
|
+
}
|
|
7694
|
+
function KanbanColumn({
|
|
7695
|
+
column,
|
|
7696
|
+
items,
|
|
7697
|
+
renderCard,
|
|
7698
|
+
emptyColumn,
|
|
7699
|
+
cardClassName,
|
|
7700
|
+
showEdit,
|
|
7701
|
+
onEditRequest
|
|
7702
|
+
}) {
|
|
7703
|
+
const { setNodeRef, isOver } = useDroppable({
|
|
7704
|
+
id: `column:${column.key}`,
|
|
7705
|
+
data: { columnKey: column.key, isColumn: true }
|
|
7706
|
+
});
|
|
7707
|
+
return /* @__PURE__ */ jsxs(
|
|
7708
|
+
"div",
|
|
7709
|
+
{
|
|
7710
|
+
ref: setNodeRef,
|
|
7711
|
+
className: cn(
|
|
7712
|
+
"cls_hazo_kanban_column flex flex-col rounded-md p-2",
|
|
7713
|
+
isOver && "cls_hazo_kanban_column_over bg-accent/30 ring-2 ring-ring/40"
|
|
7714
|
+
),
|
|
7715
|
+
children: [
|
|
7716
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_hazo_kanban_column_head flex items-center justify-between mb-2 px-1 text-xs uppercase tracking-wider text-muted-foreground", children: [
|
|
7717
|
+
/* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_column_title", children: column.title }),
|
|
7718
|
+
/* @__PURE__ */ jsx("span", { className: "cls_hazo_kanban_column_count rounded-full bg-muted px-2 py-0.5 text-foreground", children: items.length })
|
|
7719
|
+
] }),
|
|
7720
|
+
/* @__PURE__ */ jsx(
|
|
7721
|
+
SortableContext,
|
|
7722
|
+
{
|
|
7723
|
+
items: items.map((i) => i.id),
|
|
7724
|
+
strategy: verticalListSortingStrategy,
|
|
7725
|
+
children: /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_column_body flex-1 min-h-[40px]", children: items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "cls_hazo_kanban_column_empty text-xs text-muted-foreground py-2 px-1", children: emptyColumn }) : items.map((item) => /* @__PURE__ */ jsx(
|
|
7726
|
+
KanbanCard,
|
|
7727
|
+
{
|
|
7728
|
+
item,
|
|
7729
|
+
renderCard,
|
|
7730
|
+
cardClassName,
|
|
7731
|
+
showEdit,
|
|
7732
|
+
onEditRequest
|
|
7733
|
+
},
|
|
7734
|
+
item.id
|
|
7735
|
+
)) })
|
|
7736
|
+
}
|
|
7737
|
+
)
|
|
7738
|
+
]
|
|
7739
|
+
}
|
|
7740
|
+
);
|
|
7741
|
+
}
|
|
7742
|
+
var DEFAULT_PRIORITIES = ["P0", "P1", "P2", "P3"];
|
|
7743
|
+
function humanize(key) {
|
|
7744
|
+
return key.replace(/[_\-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\s+/g, " ").trim().split(" ").map((w) => w ? w[0].toUpperCase() + w.slice(1) : w).join(" ");
|
|
7745
|
+
}
|
|
7746
|
+
function auto_detect_fields(item, columns) {
|
|
7747
|
+
const skip = /* @__PURE__ */ new Set(["id", "columnKey", "priority"]);
|
|
7748
|
+
const out = [];
|
|
7749
|
+
for (const [key, value] of Object.entries(item)) {
|
|
7750
|
+
if (skip.has(key)) continue;
|
|
7751
|
+
if (typeof value === "string") {
|
|
7752
|
+
out.push({ key, type: "text" });
|
|
7753
|
+
}
|
|
7754
|
+
}
|
|
7755
|
+
if (columns.length > 0) {
|
|
7756
|
+
out.push({ key: "columnKey", type: "status", label: "Status" });
|
|
7757
|
+
}
|
|
7758
|
+
return out;
|
|
7759
|
+
}
|
|
7760
|
+
function KanbanEditor({
|
|
7761
|
+
item,
|
|
7762
|
+
columns,
|
|
7763
|
+
fields,
|
|
7764
|
+
priorities,
|
|
7765
|
+
titleFn,
|
|
7766
|
+
renderBody,
|
|
7767
|
+
hideFooter = false,
|
|
7768
|
+
onSave,
|
|
7769
|
+
onClose
|
|
7770
|
+
}) {
|
|
7771
|
+
const [draft, set_draft] = React25.useState(item);
|
|
7772
|
+
const [saving, set_saving] = React25.useState(false);
|
|
7773
|
+
const [error, set_error] = React25.useState(null);
|
|
7774
|
+
const item_id = item?.id ?? null;
|
|
7775
|
+
React25.useEffect(() => {
|
|
7776
|
+
set_draft(item);
|
|
7777
|
+
set_error(null);
|
|
7778
|
+
set_saving(false);
|
|
7779
|
+
}, [item_id]);
|
|
7780
|
+
const resolved_columns = columns ?? [];
|
|
7781
|
+
const resolved_priorities = priorities ?? DEFAULT_PRIORITIES;
|
|
7782
|
+
const resolved_fields = React25.useMemo(() => {
|
|
7783
|
+
if (fields) return fields;
|
|
7784
|
+
if (!item) return [];
|
|
7785
|
+
return auto_detect_fields(item, resolved_columns);
|
|
7786
|
+
}, [fields, item, resolved_columns]);
|
|
7787
|
+
const required_keys = React25.useMemo(
|
|
7788
|
+
() => resolved_fields.filter(
|
|
7789
|
+
(f) => f.required && (f.type === "text" || f.type === "textarea" || f.type === "number")
|
|
7790
|
+
).map((f) => f.key),
|
|
7791
|
+
[resolved_fields]
|
|
7792
|
+
);
|
|
7793
|
+
const all_required_filled = React25.useMemo(() => {
|
|
7794
|
+
if (!draft) return false;
|
|
7795
|
+
for (const key of required_keys) {
|
|
7796
|
+
const v = draft[key];
|
|
7797
|
+
if (v === void 0 || v === null || v === "") return false;
|
|
7798
|
+
if (typeof v === "string" && v.trim() === "") return false;
|
|
7799
|
+
}
|
|
7800
|
+
return true;
|
|
7801
|
+
}, [draft, required_keys]);
|
|
7802
|
+
const is_dirty = React25.useMemo(() => {
|
|
7803
|
+
if (!draft || !item) return false;
|
|
7804
|
+
try {
|
|
7805
|
+
return JSON.stringify(draft) !== JSON.stringify(item);
|
|
7806
|
+
} catch {
|
|
7807
|
+
return draft !== item;
|
|
7808
|
+
}
|
|
7809
|
+
}, [draft, item]);
|
|
7810
|
+
const handle_save = React25.useCallback(async () => {
|
|
7811
|
+
if (!draft || !item) return;
|
|
7812
|
+
if (saving) return;
|
|
7813
|
+
set_error(null);
|
|
7814
|
+
if (!onSave) {
|
|
7815
|
+
onClose();
|
|
7816
|
+
return;
|
|
7817
|
+
}
|
|
7818
|
+
const result = onSave({ itemId: item.id, item, next: draft });
|
|
7819
|
+
if (result && typeof result.then === "function") {
|
|
7820
|
+
set_saving(true);
|
|
7821
|
+
try {
|
|
7822
|
+
await result;
|
|
7823
|
+
set_saving(false);
|
|
7824
|
+
onClose();
|
|
7825
|
+
} catch (err) {
|
|
7826
|
+
set_saving(false);
|
|
7827
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
7828
|
+
set_error(message);
|
|
7829
|
+
}
|
|
7830
|
+
} else {
|
|
7831
|
+
onClose();
|
|
7832
|
+
}
|
|
7833
|
+
}, [draft, item, onSave, onClose, saving]);
|
|
7834
|
+
const ctx = {
|
|
7835
|
+
draft: draft ?? item,
|
|
7836
|
+
setDraft: (next) => {
|
|
7837
|
+
set_draft((prev) => {
|
|
7838
|
+
const base = prev ?? item;
|
|
7839
|
+
if (!base) return prev;
|
|
7840
|
+
if (typeof next === "function") {
|
|
7841
|
+
return next(base);
|
|
7842
|
+
}
|
|
7843
|
+
return next;
|
|
7844
|
+
});
|
|
7845
|
+
},
|
|
7846
|
+
save: handle_save,
|
|
7847
|
+
close: onClose,
|
|
7848
|
+
saving,
|
|
7849
|
+
error,
|
|
7850
|
+
isDirty: is_dirty
|
|
7851
|
+
};
|
|
7852
|
+
const open = item !== null;
|
|
7853
|
+
const title = item && titleFn ? titleFn(item) : item ? `Edit ${item.id}` : "";
|
|
7854
|
+
const priority_var = item?.priority ? `--hazo-kanban-priority-${String(item.priority).toLowerCase()}` : null;
|
|
7855
|
+
const header_bar_color = priority_var ? `hsl(var(${priority_var}))` : void 0;
|
|
7856
|
+
const use_default_footer = !(renderBody && hideFooter);
|
|
7857
|
+
return /* @__PURE__ */ jsx(
|
|
7858
|
+
HazoUiDialog,
|
|
7859
|
+
{
|
|
7860
|
+
open,
|
|
7861
|
+
onOpenChange: (o) => {
|
|
7862
|
+
if (!o && !saving) onClose();
|
|
7863
|
+
},
|
|
7864
|
+
title,
|
|
7865
|
+
description: "Update card details below.",
|
|
7866
|
+
sizeWidth: "min(90vw, 480px)",
|
|
7867
|
+
openAnimation: "none",
|
|
7868
|
+
closeAnimation: "none",
|
|
7869
|
+
headerBar: !!priority_var,
|
|
7870
|
+
headerBarColor: header_bar_color,
|
|
7871
|
+
contentClassName: cn("cls_hazo_kanban_editor", priority_var && "pt-0"),
|
|
7872
|
+
actionButtonText: saving ? "Saving\u2026" : "Save",
|
|
7873
|
+
actionButtonIcon: saving ? void 0 : /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 mr-2" }),
|
|
7874
|
+
actionButtonLoading: saving,
|
|
7875
|
+
actionButtonDisabled: !is_dirty || !all_required_filled || saving,
|
|
7876
|
+
cancelButtonText: "Cancel",
|
|
7877
|
+
showCancelButton: true,
|
|
7878
|
+
onConfirm: handle_save,
|
|
7879
|
+
onCancel: onClose,
|
|
7880
|
+
footerContent: use_default_footer ? void 0 : /* @__PURE__ */ jsx("span", {}),
|
|
7881
|
+
children: /* @__PURE__ */ jsxs("div", { className: "cls_hazo_kanban_editor_body flex flex-col gap-4", children: [
|
|
7882
|
+
item && draft && renderBody ? renderBody(item, ctx) : draft ? resolved_fields.map((field) => /* @__PURE__ */ jsx(
|
|
7883
|
+
KanbanEditorFieldRow,
|
|
7884
|
+
{
|
|
7885
|
+
field,
|
|
7886
|
+
draft,
|
|
7887
|
+
setDraft: (updater) => set_draft(
|
|
7888
|
+
(prev) => prev ? updater(prev) : prev
|
|
7889
|
+
),
|
|
7890
|
+
priorities: resolved_priorities,
|
|
7891
|
+
columns: resolved_columns
|
|
7892
|
+
},
|
|
7893
|
+
field.key
|
|
7894
|
+
)) : null,
|
|
7895
|
+
error && /* @__PURE__ */ jsx(
|
|
7896
|
+
"div",
|
|
7897
|
+
{
|
|
7898
|
+
className: "cls_hazo_kanban_editor_error mt-1 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive",
|
|
7899
|
+
role: "alert",
|
|
7900
|
+
children: error
|
|
7901
|
+
}
|
|
7902
|
+
)
|
|
7903
|
+
] })
|
|
7904
|
+
}
|
|
7905
|
+
);
|
|
7906
|
+
}
|
|
7907
|
+
function KanbanEditorFieldRow({
|
|
7908
|
+
field,
|
|
7909
|
+
draft,
|
|
7910
|
+
setDraft,
|
|
7911
|
+
priorities,
|
|
7912
|
+
columns
|
|
7913
|
+
}) {
|
|
7914
|
+
const id = `kanban-editor-${field.key}`;
|
|
7915
|
+
const label = field.label ?? humanize(field.key);
|
|
7916
|
+
const value = draft[field.key];
|
|
7917
|
+
const set_value = (next_value) => {
|
|
7918
|
+
setDraft((prev) => ({ ...prev, [field.key]: next_value }));
|
|
7919
|
+
};
|
|
7920
|
+
const required_marker_shown = field.required && (field.type === "text" || field.type === "textarea" || field.type === "number");
|
|
7921
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("cls_hazo_kanban_editor_field flex flex-col gap-1.5"), children: [
|
|
7922
|
+
/* @__PURE__ */ jsxs(Label3, { htmlFor: id, className: "text-xs font-medium text-muted-foreground", children: [
|
|
7923
|
+
label,
|
|
7924
|
+
required_marker_shown && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-0.5", children: "*" })
|
|
7925
|
+
] }),
|
|
7926
|
+
field.type === "text" && /* @__PURE__ */ jsx(
|
|
7927
|
+
Input,
|
|
7928
|
+
{
|
|
7929
|
+
id,
|
|
7930
|
+
value: typeof value === "string" ? value : "",
|
|
7931
|
+
placeholder: field.placeholder,
|
|
7932
|
+
onChange: (e) => set_value(e.target.value)
|
|
7933
|
+
}
|
|
7934
|
+
),
|
|
7935
|
+
field.type === "textarea" && /* @__PURE__ */ jsx(
|
|
7936
|
+
Textarea,
|
|
7937
|
+
{
|
|
7938
|
+
id,
|
|
7939
|
+
value: typeof value === "string" ? value : "",
|
|
7940
|
+
placeholder: field.placeholder,
|
|
7941
|
+
rows: 3,
|
|
7942
|
+
onChange: (e) => set_value(e.target.value)
|
|
7943
|
+
}
|
|
7944
|
+
),
|
|
7945
|
+
field.type === "number" && /* @__PURE__ */ jsx(
|
|
7946
|
+
Input,
|
|
7947
|
+
{
|
|
7948
|
+
id,
|
|
7949
|
+
type: "number",
|
|
7950
|
+
value: typeof value === "number" ? value : value === "" || value == null ? "" : Number(value) || 0,
|
|
7951
|
+
placeholder: field.placeholder,
|
|
7952
|
+
onChange: (e) => set_value(e.target.value === "" ? void 0 : Number(e.target.value))
|
|
7953
|
+
}
|
|
7954
|
+
),
|
|
7955
|
+
field.type === "checkbox" && /* @__PURE__ */ jsx(
|
|
7956
|
+
Checkbox,
|
|
7957
|
+
{
|
|
7958
|
+
id,
|
|
7959
|
+
checked: !!value,
|
|
7960
|
+
onCheckedChange: (checked) => set_value(checked === true)
|
|
7961
|
+
}
|
|
7962
|
+
),
|
|
7963
|
+
field.type === "select" && /* @__PURE__ */ jsxs(
|
|
7964
|
+
Select,
|
|
7965
|
+
{
|
|
7966
|
+
value: typeof value === "string" ? value : "",
|
|
7967
|
+
onValueChange: set_value,
|
|
7968
|
+
children: [
|
|
7969
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id, children: /* @__PURE__ */ jsx(
|
|
7970
|
+
SelectValue,
|
|
7971
|
+
{
|
|
7972
|
+
placeholder: field.placeholder ?? `Select ${label}\u2026`
|
|
7973
|
+
}
|
|
7974
|
+
) }),
|
|
7975
|
+
/* @__PURE__ */ jsx(SelectContent, { children: (field.options ?? []).map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt, children: opt }, opt)) })
|
|
7976
|
+
]
|
|
7977
|
+
}
|
|
7978
|
+
),
|
|
7979
|
+
field.type === "priority" && /* @__PURE__ */ jsxs(
|
|
7980
|
+
Select,
|
|
7981
|
+
{
|
|
7982
|
+
value: typeof value === "string" ? value : "",
|
|
7983
|
+
onValueChange: set_value,
|
|
7984
|
+
children: [
|
|
7985
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id, children: /* @__PURE__ */ jsx(
|
|
7986
|
+
SelectValue,
|
|
7987
|
+
{
|
|
7988
|
+
placeholder: field.placeholder ?? "Select priority\u2026"
|
|
7989
|
+
}
|
|
7990
|
+
) }),
|
|
7991
|
+
/* @__PURE__ */ jsx(SelectContent, { children: priorities.map((p) => /* @__PURE__ */ jsx(SelectItem, { value: p, children: p }, p)) })
|
|
7992
|
+
]
|
|
7993
|
+
}
|
|
7994
|
+
),
|
|
7995
|
+
field.type === "status" && /* @__PURE__ */ jsxs(
|
|
7996
|
+
Select,
|
|
7997
|
+
{
|
|
7998
|
+
value: typeof value === "string" ? value : "",
|
|
7999
|
+
onValueChange: set_value,
|
|
8000
|
+
children: [
|
|
8001
|
+
/* @__PURE__ */ jsx(SelectTrigger, { id, children: /* @__PURE__ */ jsx(
|
|
8002
|
+
SelectValue,
|
|
8003
|
+
{
|
|
8004
|
+
placeholder: field.placeholder ?? "Select status\u2026"
|
|
8005
|
+
}
|
|
8006
|
+
) }),
|
|
8007
|
+
/* @__PURE__ */ jsx(SelectContent, { children: columns.map((col) => /* @__PURE__ */ jsx(SelectItem, { value: col.key, children: col.title }, col.key)) })
|
|
8008
|
+
]
|
|
8009
|
+
}
|
|
8010
|
+
)
|
|
8011
|
+
] });
|
|
8012
|
+
}
|
|
8013
|
+
var EMPTY_FILTER = {
|
|
8014
|
+
search: "",
|
|
8015
|
+
categories: [],
|
|
8016
|
+
priority: null
|
|
8017
|
+
};
|
|
8018
|
+
function HazoUiKanbanFilter({
|
|
8019
|
+
search = true,
|
|
8020
|
+
searchPlaceholder = "Search...",
|
|
8021
|
+
categories,
|
|
8022
|
+
priorities,
|
|
8023
|
+
value,
|
|
8024
|
+
defaultValue,
|
|
8025
|
+
onChange,
|
|
8026
|
+
className
|
|
8027
|
+
}) {
|
|
8028
|
+
const is_controlled = value !== void 0;
|
|
8029
|
+
const [internal, set_internal] = React25.useState(
|
|
8030
|
+
defaultValue ?? EMPTY_FILTER
|
|
8031
|
+
);
|
|
8032
|
+
const current = is_controlled ? value : internal;
|
|
8033
|
+
const update = React25.useCallback(
|
|
8034
|
+
(next) => {
|
|
8035
|
+
if (!is_controlled) set_internal(next);
|
|
8036
|
+
onChange?.(next);
|
|
8037
|
+
},
|
|
8038
|
+
[is_controlled, onChange]
|
|
8039
|
+
);
|
|
8040
|
+
const has_active = current.search.length > 0 || current.categories.length > 0 || current.priority !== null;
|
|
8041
|
+
return /* @__PURE__ */ jsxs(
|
|
8042
|
+
"div",
|
|
8043
|
+
{
|
|
8044
|
+
className: cn(
|
|
8045
|
+
"cls_hazo_kanban_filter flex flex-wrap items-center gap-3 p-2",
|
|
8046
|
+
className
|
|
8047
|
+
),
|
|
8048
|
+
children: [
|
|
8049
|
+
search && /* @__PURE__ */ jsx(
|
|
8050
|
+
Input,
|
|
8051
|
+
{
|
|
8052
|
+
value: current.search,
|
|
8053
|
+
onChange: (e) => update({ ...current, search: e.target.value }),
|
|
8054
|
+
placeholder: searchPlaceholder,
|
|
8055
|
+
className: "cls_hazo_kanban_filter_search w-full sm:w-64"
|
|
8056
|
+
}
|
|
8057
|
+
),
|
|
8058
|
+
categories && categories.length > 0 && /* @__PURE__ */ jsx(
|
|
8059
|
+
ToggleGroup,
|
|
8060
|
+
{
|
|
8061
|
+
type: "multiple",
|
|
8062
|
+
value: current.categories,
|
|
8063
|
+
onValueChange: (cats) => update({ ...current, categories: cats }),
|
|
8064
|
+
className: "cls_hazo_kanban_filter_categories flex flex-wrap gap-1",
|
|
8065
|
+
children: categories.map((cat) => /* @__PURE__ */ jsx(
|
|
8066
|
+
ToggleGroupItem,
|
|
8067
|
+
{
|
|
8068
|
+
value: cat,
|
|
8069
|
+
size: "sm",
|
|
8070
|
+
className: "cls_hazo_kanban_filter_category_chip",
|
|
8071
|
+
children: cat
|
|
8072
|
+
},
|
|
8073
|
+
cat
|
|
8074
|
+
))
|
|
8075
|
+
}
|
|
8076
|
+
),
|
|
8077
|
+
priorities && priorities.length > 0 && /* @__PURE__ */ jsx(
|
|
8078
|
+
ToggleGroup,
|
|
8079
|
+
{
|
|
8080
|
+
type: "single",
|
|
8081
|
+
value: current.priority ?? "",
|
|
8082
|
+
onValueChange: (p) => update({
|
|
8083
|
+
...current,
|
|
8084
|
+
priority: p ? p : null
|
|
8085
|
+
}),
|
|
8086
|
+
className: "cls_hazo_kanban_filter_priority flex gap-1",
|
|
8087
|
+
children: priorities.map((p) => /* @__PURE__ */ jsx(
|
|
8088
|
+
ToggleGroupItem,
|
|
8089
|
+
{
|
|
8090
|
+
value: p,
|
|
8091
|
+
size: "sm",
|
|
8092
|
+
className: "cls_hazo_kanban_filter_priority_chip",
|
|
8093
|
+
children: p
|
|
8094
|
+
},
|
|
8095
|
+
p
|
|
8096
|
+
))
|
|
8097
|
+
}
|
|
8098
|
+
),
|
|
8099
|
+
has_active && /* @__PURE__ */ jsxs(
|
|
8100
|
+
Button,
|
|
8101
|
+
{
|
|
8102
|
+
variant: "ghost",
|
|
8103
|
+
size: "sm",
|
|
8104
|
+
onClick: () => update(EMPTY_FILTER),
|
|
8105
|
+
className: "cls_hazo_kanban_filter_clear",
|
|
8106
|
+
children: [
|
|
8107
|
+
/* @__PURE__ */ jsx(X, { className: "h-4 w-4 mr-1" }),
|
|
8108
|
+
"Clear"
|
|
8109
|
+
]
|
|
8110
|
+
}
|
|
8111
|
+
)
|
|
8112
|
+
]
|
|
8113
|
+
}
|
|
8114
|
+
);
|
|
8115
|
+
}
|
|
8116
|
+
|
|
8117
|
+
// src/components/hazo_ui_kanban/apply_kanban_filter.ts
|
|
8118
|
+
function applyKanbanFilter(items, filter) {
|
|
8119
|
+
const search = filter.search.trim().toLowerCase();
|
|
8120
|
+
return items.filter((item) => {
|
|
8121
|
+
if (filter.priority && item.priority !== filter.priority) {
|
|
8122
|
+
return false;
|
|
8123
|
+
}
|
|
8124
|
+
if (filter.categories.length > 0) {
|
|
8125
|
+
const cat = item.category;
|
|
8126
|
+
if (typeof cat !== "string" || !filter.categories.includes(cat)) {
|
|
8127
|
+
return false;
|
|
8128
|
+
}
|
|
8129
|
+
}
|
|
8130
|
+
if (search) {
|
|
8131
|
+
const haystack = Object.values(item).filter((v) => typeof v === "string").join(" ").toLowerCase();
|
|
8132
|
+
if (!haystack.includes(search)) {
|
|
8133
|
+
return false;
|
|
8134
|
+
}
|
|
8135
|
+
}
|
|
8136
|
+
return true;
|
|
8137
|
+
});
|
|
8138
|
+
}
|
|
8139
|
+
function default_announcements(itemLabel) {
|
|
8140
|
+
return {
|
|
8141
|
+
onDragStart: ({ item, fromColumn }) => `Picked up ${itemLabel(item)}. Currently in ${fromColumn}. Use arrow keys to choose a different column. Press space to drop, escape to cancel.`,
|
|
8142
|
+
onDragOver: ({ item, overColumn }) => overColumn ? `${itemLabel(item)} over ${overColumn}.` : "",
|
|
8143
|
+
onDragEnd: ({ item, fromColumn, toColumn, newIndex }) => fromColumn === toColumn ? `${itemLabel(item)} reordered to position ${newIndex + 1} in ${toColumn}.` : `${itemLabel(item)} dropped in ${toColumn}, position ${newIndex + 1}.`,
|
|
8144
|
+
onDragCancel: ({ item, fromColumn }) => `Movement cancelled. ${itemLabel(item)} returned to ${fromColumn}.`
|
|
8145
|
+
};
|
|
8146
|
+
}
|
|
8147
|
+
function group_items_by_column(items, overlay, columns) {
|
|
8148
|
+
const out = /* @__PURE__ */ new Map();
|
|
8149
|
+
for (const col of columns) out.set(col.key, []);
|
|
8150
|
+
const overlay_inserts = /* @__PURE__ */ new Map();
|
|
8151
|
+
for (const col of columns) overlay_inserts.set(col.key, []);
|
|
8152
|
+
for (const item of items) {
|
|
8153
|
+
const ov = overlay.get(item.id);
|
|
8154
|
+
if (ov) {
|
|
8155
|
+
const bucket = overlay_inserts.get(ov.columnKey);
|
|
8156
|
+
if (bucket) {
|
|
8157
|
+
bucket.push({ item, index: ov.index });
|
|
8158
|
+
}
|
|
8159
|
+
} else {
|
|
8160
|
+
const bucket = out.get(item.columnKey);
|
|
8161
|
+
if (bucket) bucket.push(item);
|
|
8162
|
+
}
|
|
8163
|
+
}
|
|
8164
|
+
for (const col of columns) {
|
|
8165
|
+
const inserts = overlay_inserts.get(col.key) ?? [];
|
|
8166
|
+
inserts.sort((a, b) => a.index - b.index);
|
|
8167
|
+
const arr = out.get(col.key) ?? [];
|
|
8168
|
+
for (const { item, index } of inserts) {
|
|
8169
|
+
const at = Math.max(0, Math.min(index, arr.length));
|
|
8170
|
+
arr.splice(at, 0, item);
|
|
8171
|
+
}
|
|
8172
|
+
out.set(col.key, arr);
|
|
8173
|
+
}
|
|
8174
|
+
return out;
|
|
8175
|
+
}
|
|
8176
|
+
function HazoUiKanban({
|
|
8177
|
+
columns,
|
|
8178
|
+
items,
|
|
8179
|
+
renderCard,
|
|
8180
|
+
onMove,
|
|
8181
|
+
onReorder,
|
|
8182
|
+
mobileBreakpoint = 640,
|
|
8183
|
+
announcements,
|
|
8184
|
+
emptyColumn = "\u2014",
|
|
8185
|
+
className,
|
|
8186
|
+
cardClassName,
|
|
8187
|
+
itemLabel,
|
|
8188
|
+
editorFields,
|
|
8189
|
+
editorPriorities,
|
|
8190
|
+
editorTitle,
|
|
8191
|
+
renderCardEditor,
|
|
8192
|
+
hideEditorFooter,
|
|
8193
|
+
onCardSave,
|
|
8194
|
+
disableEdit = false
|
|
8195
|
+
}) {
|
|
8196
|
+
const label_fn = React25.useCallback(
|
|
8197
|
+
(item) => itemLabel ? itemLabel(item) : item.id,
|
|
8198
|
+
[itemLabel]
|
|
8199
|
+
);
|
|
8200
|
+
const dnd_context_id = React25.useId();
|
|
8201
|
+
const [overlay, set_overlay] = React25.useState(
|
|
8202
|
+
/* @__PURE__ */ new Map()
|
|
8203
|
+
);
|
|
8204
|
+
const [active_id, set_active_id] = React25.useState(null);
|
|
8205
|
+
const [active_tab, set_active_tab] = React25.useState(columns[0]?.key ?? "");
|
|
8206
|
+
const [editing_item, set_editing_item] = React25.useState(null);
|
|
8207
|
+
const show_edit = !disableEdit && typeof onCardSave === "function";
|
|
8208
|
+
const handle_edit_request = React25.useCallback(
|
|
8209
|
+
(it) => {
|
|
8210
|
+
const typed = items.find((x) => x.id === it.id);
|
|
8211
|
+
if (typed) set_editing_item(typed);
|
|
8212
|
+
},
|
|
8213
|
+
[items]
|
|
8214
|
+
);
|
|
8215
|
+
const handle_editor_close = React25.useCallback(() => {
|
|
8216
|
+
set_editing_item(null);
|
|
8217
|
+
}, []);
|
|
8218
|
+
React25.useEffect(() => {
|
|
8219
|
+
if (overlay.size === 0) return;
|
|
8220
|
+
set_overlay((prev) => {
|
|
8221
|
+
let changed = false;
|
|
8222
|
+
const next = new Map(prev);
|
|
8223
|
+
for (const [item_id, pos] of prev.entries()) {
|
|
8224
|
+
const item = items.find((i) => i.id === item_id);
|
|
8225
|
+
if (item && item.columnKey === pos.columnKey) {
|
|
8226
|
+
next.delete(item_id);
|
|
8227
|
+
changed = true;
|
|
8228
|
+
}
|
|
8229
|
+
}
|
|
8230
|
+
return changed ? next : prev;
|
|
8231
|
+
});
|
|
8232
|
+
}, [items, overlay]);
|
|
8233
|
+
const grouped = React25.useMemo(
|
|
8234
|
+
() => group_items_by_column(items, overlay, columns),
|
|
8235
|
+
[items, overlay, columns]
|
|
8236
|
+
);
|
|
8237
|
+
const find_item = React25.useCallback(
|
|
8238
|
+
(id) => items.find((i) => i.id === id),
|
|
8239
|
+
[items]
|
|
8240
|
+
);
|
|
8241
|
+
const sensors = useSensors(
|
|
8242
|
+
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
|
|
8243
|
+
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
|
8244
|
+
);
|
|
8245
|
+
const merged_announcements = React25.useMemo(() => {
|
|
8246
|
+
const defaults = default_announcements(label_fn);
|
|
8247
|
+
return {
|
|
8248
|
+
onDragStart: announcements?.onDragStart ?? defaults.onDragStart,
|
|
8249
|
+
onDragOver: announcements?.onDragOver ?? defaults.onDragOver,
|
|
8250
|
+
onDragEnd: announcements?.onDragEnd ?? defaults.onDragEnd,
|
|
8251
|
+
onDragCancel: announcements?.onDragCancel ?? defaults.onDragCancel
|
|
8252
|
+
};
|
|
8253
|
+
}, [announcements, label_fn]);
|
|
8254
|
+
const dnd_announcements = React25.useMemo(
|
|
8255
|
+
() => ({
|
|
8256
|
+
onDragStart({ active }) {
|
|
8257
|
+
const id = String(active.id);
|
|
8258
|
+
const item = find_item(id);
|
|
8259
|
+
if (!item) return "";
|
|
8260
|
+
const col = columns.find((c) => c.key === item.columnKey);
|
|
8261
|
+
return merged_announcements.onDragStart({
|
|
8262
|
+
item,
|
|
8263
|
+
fromColumn: col?.title ?? item.columnKey
|
|
8264
|
+
});
|
|
8265
|
+
},
|
|
8266
|
+
onDragOver({
|
|
8267
|
+
active,
|
|
8268
|
+
over
|
|
8269
|
+
}) {
|
|
8270
|
+
const id = String(active.id);
|
|
8271
|
+
const item = find_item(id);
|
|
8272
|
+
if (!item) return "";
|
|
8273
|
+
const over_col_key = over ? over.data?.current?.columnKey ?? String(over.id).replace(/^column:/, "") : null;
|
|
8274
|
+
const col = over_col_key ? columns.find((c) => c.key === over_col_key) : null;
|
|
8275
|
+
return merged_announcements.onDragOver({
|
|
8276
|
+
item,
|
|
8277
|
+
overColumn: col?.title ?? null
|
|
8278
|
+
});
|
|
8279
|
+
},
|
|
8280
|
+
onDragEnd({
|
|
8281
|
+
active,
|
|
8282
|
+
over
|
|
8283
|
+
}) {
|
|
8284
|
+
const id = String(active.id);
|
|
8285
|
+
const item = find_item(id);
|
|
8286
|
+
if (!item) return "";
|
|
8287
|
+
const from_col = columns.find((c) => c.key === item.columnKey);
|
|
8288
|
+
const over_col_key = over ? over.data?.current?.columnKey ?? String(over.id).replace(/^column:/, "") : null;
|
|
8289
|
+
const to_col = over_col_key ? columns.find((c) => c.key === over_col_key) ?? from_col : from_col;
|
|
8290
|
+
const target = over_col_key ? grouped.get(over_col_key) ?? [] : grouped.get(item.columnKey) ?? [];
|
|
8291
|
+
const new_index = over && String(over.id) !== `column:${over_col_key}` ? target.findIndex((it) => it.id === String(over.id)) : target.length;
|
|
8292
|
+
return merged_announcements.onDragEnd({
|
|
8293
|
+
item,
|
|
8294
|
+
fromColumn: from_col?.title ?? item.columnKey,
|
|
8295
|
+
toColumn: to_col?.title ?? item.columnKey,
|
|
8296
|
+
newIndex: Math.max(0, new_index)
|
|
8297
|
+
});
|
|
8298
|
+
},
|
|
8299
|
+
onDragCancel({ active }) {
|
|
8300
|
+
const id = String(active.id);
|
|
8301
|
+
const item = find_item(id);
|
|
8302
|
+
if (!item) return "";
|
|
8303
|
+
const col = columns.find((c) => c.key === item.columnKey);
|
|
8304
|
+
return merged_announcements.onDragCancel({
|
|
8305
|
+
item,
|
|
8306
|
+
fromColumn: col?.title ?? item.columnKey
|
|
8307
|
+
});
|
|
8308
|
+
}
|
|
8309
|
+
}),
|
|
8310
|
+
[find_item, columns, grouped, merged_announcements]
|
|
8311
|
+
);
|
|
8312
|
+
const handle_drag_start = React25.useCallback((event) => {
|
|
8313
|
+
set_active_id(String(event.active.id));
|
|
8314
|
+
}, []);
|
|
8315
|
+
const make_revert_handle = React25.useCallback(
|
|
8316
|
+
(item_id) => ({
|
|
8317
|
+
revert: () => {
|
|
8318
|
+
set_overlay((prev) => {
|
|
8319
|
+
if (!prev.has(item_id)) return prev;
|
|
8320
|
+
const next = new Map(prev);
|
|
8321
|
+
next.delete(item_id);
|
|
8322
|
+
return next;
|
|
8323
|
+
});
|
|
8324
|
+
}
|
|
8325
|
+
}),
|
|
8326
|
+
[]
|
|
8327
|
+
);
|
|
8328
|
+
const handle_drag_end = React25.useCallback(
|
|
8329
|
+
(event) => {
|
|
8330
|
+
const active_id_str = String(event.active.id);
|
|
8331
|
+
set_active_id(null);
|
|
8332
|
+
const item = find_item(active_id_str);
|
|
8333
|
+
if (!item) return;
|
|
8334
|
+
if (!event.over) return;
|
|
8335
|
+
const over_id = String(event.over.id);
|
|
8336
|
+
const over_data = event.over.data?.current;
|
|
8337
|
+
const dest_column_key = over_data?.columnKey ?? over_id.replace(/^column:/, "");
|
|
8338
|
+
const dest_column = columns.find((c) => c.key === dest_column_key);
|
|
8339
|
+
if (!dest_column) return;
|
|
8340
|
+
if (dest_column.accepts && !dest_column.accepts(item)) return;
|
|
8341
|
+
const dest_items_pre_overlay = grouped.get(dest_column_key) ?? [];
|
|
8342
|
+
let new_index;
|
|
8343
|
+
if (over_data?.isColumn) {
|
|
8344
|
+
new_index = dest_items_pre_overlay.length;
|
|
8345
|
+
} else {
|
|
8346
|
+
const idx = dest_items_pre_overlay.findIndex((i) => i.id === over_id);
|
|
8347
|
+
new_index = idx === -1 ? dest_items_pre_overlay.length : idx;
|
|
8348
|
+
}
|
|
8349
|
+
const handle = make_revert_handle(active_id_str);
|
|
8350
|
+
if (item.columnKey === dest_column_key) {
|
|
8351
|
+
if (active_id_str === over_id) return;
|
|
8352
|
+
set_overlay((prev) => {
|
|
8353
|
+
const next = new Map(prev);
|
|
8354
|
+
next.set(active_id_str, {
|
|
8355
|
+
columnKey: dest_column_key,
|
|
8356
|
+
index: new_index
|
|
8357
|
+
});
|
|
8358
|
+
return next;
|
|
8359
|
+
});
|
|
8360
|
+
const reorder_event = {
|
|
8361
|
+
itemId: active_id_str,
|
|
8362
|
+
item,
|
|
8363
|
+
columnKey: dest_column_key,
|
|
8364
|
+
newIndex: new_index,
|
|
8365
|
+
revert: handle.revert
|
|
8366
|
+
};
|
|
8367
|
+
onReorder?.(reorder_event);
|
|
8368
|
+
return;
|
|
8369
|
+
}
|
|
8370
|
+
set_overlay((prev) => {
|
|
8371
|
+
const next = new Map(prev);
|
|
8372
|
+
next.set(active_id_str, {
|
|
8373
|
+
columnKey: dest_column_key,
|
|
8374
|
+
index: new_index
|
|
8375
|
+
});
|
|
8376
|
+
return next;
|
|
8377
|
+
});
|
|
8378
|
+
const move_event = {
|
|
8379
|
+
itemId: active_id_str,
|
|
8380
|
+
item,
|
|
8381
|
+
fromColumn: item.columnKey,
|
|
8382
|
+
toColumn: dest_column_key,
|
|
8383
|
+
newIndex: new_index,
|
|
8384
|
+
revert: handle.revert
|
|
8385
|
+
};
|
|
8386
|
+
onMove?.(move_event);
|
|
8387
|
+
},
|
|
8388
|
+
[find_item, columns, grouped, onMove, onReorder, make_revert_handle]
|
|
8389
|
+
);
|
|
8390
|
+
const handle_drag_cancel = React25.useCallback(() => {
|
|
8391
|
+
set_active_id(null);
|
|
8392
|
+
}, []);
|
|
8393
|
+
const active_item = active_id ? find_item(active_id) : null;
|
|
8394
|
+
const is_custom_breakpoint = mobileBreakpoint !== 640;
|
|
8395
|
+
const is_mobile_via_query = useMediaQuery(
|
|
8396
|
+
`(max-width: ${Math.max(0, mobileBreakpoint - 1)}px)`
|
|
8397
|
+
);
|
|
8398
|
+
const mobile_classes = is_custom_breakpoint ? is_mobile_via_query ? "block" : "hidden" : "sm:hidden";
|
|
8399
|
+
const desktop_classes = is_custom_breakpoint ? is_mobile_via_query ? "hidden" : "grid" : "hidden sm:grid";
|
|
8400
|
+
return /* @__PURE__ */ jsxs(
|
|
8401
|
+
DndContext,
|
|
8402
|
+
{
|
|
8403
|
+
id: dnd_context_id,
|
|
8404
|
+
sensors,
|
|
8405
|
+
collisionDetection: closestCorners,
|
|
8406
|
+
onDragStart: handle_drag_start,
|
|
8407
|
+
onDragEnd: handle_drag_end,
|
|
8408
|
+
onDragCancel: handle_drag_cancel,
|
|
8409
|
+
accessibility: { announcements: dnd_announcements },
|
|
8410
|
+
children: [
|
|
8411
|
+
/* @__PURE__ */ jsxs("div", { className: cn("cls_hazo_kanban w-full", className), children: [
|
|
8412
|
+
/* @__PURE__ */ jsx("div", { className: cn("cls_hazo_kanban_mobile", mobile_classes), children: /* @__PURE__ */ jsxs(Tabs, { value: active_tab, onValueChange: set_active_tab, children: [
|
|
8413
|
+
/* @__PURE__ */ jsx(TabsList, { className: "grid w-full", style: { gridTemplateColumns: `repeat(${columns.length}, 1fr)` }, children: columns.map((col) => {
|
|
8414
|
+
const count = (grouped.get(col.key) ?? []).length;
|
|
8415
|
+
return /* @__PURE__ */ jsxs(TabsTrigger, { value: col.key, className: "flex flex-col gap-0.5", children: [
|
|
8416
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: col.title }),
|
|
8417
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: count })
|
|
8418
|
+
] }, col.key);
|
|
8419
|
+
}) }),
|
|
8420
|
+
columns.map((col) => /* @__PURE__ */ jsx(TabsContent, { value: col.key, className: "mt-3", children: /* @__PURE__ */ jsx(
|
|
8421
|
+
KanbanColumn,
|
|
8422
|
+
{
|
|
8423
|
+
column: col,
|
|
8424
|
+
items: grouped.get(col.key) ?? [],
|
|
8425
|
+
renderCard,
|
|
8426
|
+
emptyColumn,
|
|
8427
|
+
cardClassName,
|
|
8428
|
+
showEdit: show_edit,
|
|
8429
|
+
onEditRequest: handle_edit_request
|
|
8430
|
+
}
|
|
8431
|
+
) }, col.key))
|
|
8432
|
+
] }) }),
|
|
8433
|
+
/* @__PURE__ */ jsx(
|
|
8434
|
+
"div",
|
|
8435
|
+
{
|
|
8436
|
+
className: cn("cls_hazo_kanban_desktop gap-3", desktop_classes),
|
|
8437
|
+
style: { gridTemplateColumns: `repeat(${columns.length}, minmax(0, 1fr))` },
|
|
8438
|
+
children: columns.map((col) => /* @__PURE__ */ jsx(
|
|
8439
|
+
KanbanColumn,
|
|
8440
|
+
{
|
|
8441
|
+
column: col,
|
|
8442
|
+
items: grouped.get(col.key) ?? [],
|
|
8443
|
+
renderCard,
|
|
8444
|
+
emptyColumn,
|
|
8445
|
+
cardClassName,
|
|
8446
|
+
showEdit: show_edit,
|
|
8447
|
+
onEditRequest: handle_edit_request
|
|
8448
|
+
},
|
|
8449
|
+
col.key
|
|
8450
|
+
))
|
|
8451
|
+
}
|
|
8452
|
+
),
|
|
8453
|
+
/* @__PURE__ */ jsx(DragOverlay, { children: active_item ? /* @__PURE__ */ jsx(
|
|
8454
|
+
KanbanCard,
|
|
8455
|
+
{
|
|
8456
|
+
item: active_item,
|
|
8457
|
+
renderCard,
|
|
8458
|
+
dragging: true,
|
|
8459
|
+
cardClassName
|
|
8460
|
+
}
|
|
8461
|
+
) : null })
|
|
8462
|
+
] }),
|
|
8463
|
+
/* @__PURE__ */ jsx(
|
|
8464
|
+
KanbanEditor,
|
|
8465
|
+
{
|
|
8466
|
+
item: editing_item,
|
|
8467
|
+
columns,
|
|
8468
|
+
fields: editorFields,
|
|
8469
|
+
priorities: editorPriorities,
|
|
8470
|
+
titleFn: editorTitle,
|
|
8471
|
+
renderBody: renderCardEditor,
|
|
8472
|
+
hideFooter: hideEditorFooter,
|
|
8473
|
+
onSave: onCardSave,
|
|
8474
|
+
onClose: handle_editor_close
|
|
8475
|
+
}
|
|
8476
|
+
)
|
|
8477
|
+
]
|
|
8478
|
+
}
|
|
8479
|
+
);
|
|
8480
|
+
}
|
|
8481
|
+
var Table2 = React25.forwardRef(
|
|
8482
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "cls_table_wrap relative w-full overflow-auto", children: /* @__PURE__ */ jsx(
|
|
8483
|
+
"table",
|
|
8484
|
+
{
|
|
8485
|
+
ref,
|
|
8486
|
+
className: cn("w-full caption-bottom text-sm", className),
|
|
8487
|
+
...props
|
|
8488
|
+
}
|
|
8489
|
+
) })
|
|
8490
|
+
);
|
|
8491
|
+
Table2.displayName = "Table";
|
|
8492
|
+
var TableHeader2 = React25.forwardRef(
|
|
8493
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props })
|
|
8494
|
+
);
|
|
8495
|
+
TableHeader2.displayName = "TableHeader";
|
|
8496
|
+
var TableBody = React25.forwardRef(
|
|
8497
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
8498
|
+
"tbody",
|
|
8499
|
+
{
|
|
8500
|
+
ref,
|
|
8501
|
+
className: cn("[&_tr:last-child]:border-0", className),
|
|
8502
|
+
...props
|
|
8503
|
+
}
|
|
8504
|
+
)
|
|
8505
|
+
);
|
|
8506
|
+
TableBody.displayName = "TableBody";
|
|
8507
|
+
var TableFooter = React25.forwardRef(
|
|
8508
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
8509
|
+
"tfoot",
|
|
8510
|
+
{
|
|
8511
|
+
ref,
|
|
8512
|
+
className: cn("bg-muted/50 font-medium [&>tr]:last:border-b-0", className),
|
|
8513
|
+
...props
|
|
8514
|
+
}
|
|
8515
|
+
)
|
|
8516
|
+
);
|
|
8517
|
+
TableFooter.displayName = "TableFooter";
|
|
8518
|
+
var TableRow2 = React25.forwardRef(
|
|
8519
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
8520
|
+
"tr",
|
|
8521
|
+
{
|
|
8522
|
+
ref,
|
|
8523
|
+
className: cn(
|
|
8524
|
+
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
|
8525
|
+
className
|
|
8526
|
+
),
|
|
8527
|
+
...props
|
|
8528
|
+
}
|
|
8529
|
+
)
|
|
8530
|
+
);
|
|
8531
|
+
TableRow2.displayName = "TableRow";
|
|
8532
|
+
var TableHead = React25.forwardRef(
|
|
8533
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
8534
|
+
"th",
|
|
8535
|
+
{
|
|
8536
|
+
ref,
|
|
8537
|
+
className: cn(
|
|
8538
|
+
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
|
8539
|
+
className
|
|
8540
|
+
),
|
|
8541
|
+
...props
|
|
8542
|
+
}
|
|
8543
|
+
)
|
|
8544
|
+
);
|
|
8545
|
+
TableHead.displayName = "TableHead";
|
|
8546
|
+
var TableCell2 = React25.forwardRef(
|
|
8547
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
8548
|
+
"td",
|
|
8549
|
+
{
|
|
8550
|
+
ref,
|
|
8551
|
+
className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className),
|
|
8552
|
+
...props
|
|
8553
|
+
}
|
|
8554
|
+
)
|
|
8555
|
+
);
|
|
8556
|
+
TableCell2.displayName = "TableCell";
|
|
8557
|
+
var TableCaption = React25.forwardRef(
|
|
8558
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
8559
|
+
"caption",
|
|
8560
|
+
{
|
|
8561
|
+
ref,
|
|
8562
|
+
className: cn("mt-4 text-sm text-muted-foreground", className),
|
|
8563
|
+
...props
|
|
8564
|
+
}
|
|
8565
|
+
)
|
|
8566
|
+
);
|
|
8567
|
+
TableCaption.displayName = "TableCaption";
|
|
8568
|
+
function TableMobileCards(props) {
|
|
8569
|
+
const { columns, rows, getRowKey, onRowClick, renderCell: renderCell2 } = props;
|
|
8570
|
+
const [titleCol, ...restCols] = columns;
|
|
8571
|
+
if (!titleCol) return null;
|
|
8572
|
+
return /* @__PURE__ */ jsx("div", { className: "cls_hazo_ui_table_mobile_cards flex flex-col gap-3", children: rows.map((row, i) => {
|
|
8573
|
+
const interactionProps = onRowClick ? {
|
|
8574
|
+
role: "button",
|
|
8575
|
+
tabIndex: 0,
|
|
8576
|
+
className: "cls_hazo_ui_table_mobile_card_clickable cursor-pointer",
|
|
8577
|
+
onClick: () => onRowClick(row, i),
|
|
8578
|
+
onKeyDown: (e) => {
|
|
8579
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
8580
|
+
e.preventDefault();
|
|
8581
|
+
onRowClick(row, i);
|
|
8582
|
+
}
|
|
8583
|
+
}
|
|
8584
|
+
} : {};
|
|
8585
|
+
return /* @__PURE__ */ jsxs(
|
|
8586
|
+
Card,
|
|
8587
|
+
{
|
|
8588
|
+
...interactionProps,
|
|
8589
|
+
children: [
|
|
8590
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: renderCell2(titleCol, row, i) }) }),
|
|
8591
|
+
/* @__PURE__ */ jsx(CardContent, { className: "pt-0 space-y-1.5", children: restCols.map((c) => /* @__PURE__ */ jsxs(
|
|
8592
|
+
"div",
|
|
8593
|
+
{
|
|
8594
|
+
className: cn(
|
|
8595
|
+
"cls_hazo_ui_table_mobile_row flex items-center justify-between gap-3 text-sm"
|
|
8596
|
+
),
|
|
8597
|
+
children: [
|
|
8598
|
+
/* @__PURE__ */ jsx("span", { className: "cls_hazo_ui_table_mobile_label text-muted-foreground", children: c.label }),
|
|
8599
|
+
/* @__PURE__ */ jsx("span", { className: cn("cls_hazo_ui_table_mobile_value", c.className), children: renderCell2(c, row, i) })
|
|
8600
|
+
]
|
|
8601
|
+
},
|
|
8602
|
+
c.key
|
|
8603
|
+
)) })
|
|
8604
|
+
]
|
|
8605
|
+
},
|
|
8606
|
+
getRowKey ? getRowKey(row, i) : i
|
|
8607
|
+
);
|
|
8608
|
+
}) });
|
|
8609
|
+
}
|
|
8610
|
+
var DEFAULT_DEBOUNCE_MS = 200;
|
|
8611
|
+
function useTableState(props) {
|
|
8612
|
+
const [sortInternal, setSortInternal] = useState(
|
|
8613
|
+
() => normalizeSortProp(props.defaultSort)
|
|
8614
|
+
);
|
|
8615
|
+
const isSortControlled = props.sort !== void 0;
|
|
8616
|
+
const sort = isSortControlled ? normalizeSortProp(props.sort) : sortInternal;
|
|
8617
|
+
const setSort = useCallback(
|
|
8618
|
+
(next) => {
|
|
8619
|
+
if (!isSortControlled) setSortInternal(next);
|
|
8620
|
+
props.onSortChange?.(next);
|
|
8621
|
+
},
|
|
8622
|
+
[isSortControlled, props.onSortChange]
|
|
8623
|
+
);
|
|
8624
|
+
const cycleHeaderSort = useCallback(
|
|
8625
|
+
(key, append) => {
|
|
8626
|
+
const next = append ? cycleAppendColumn(sort, key) : cycleSingleColumn(sort, key);
|
|
8627
|
+
setSort(next);
|
|
8628
|
+
},
|
|
8629
|
+
[sort, setSort]
|
|
8630
|
+
);
|
|
8631
|
+
const [filterInternal, setFilterInternal] = useState(
|
|
8632
|
+
() => props.defaultFilter ?? {}
|
|
8633
|
+
);
|
|
8634
|
+
const isFilterControlled = props.filter !== void 0;
|
|
8635
|
+
const filter = isFilterControlled ? props.filter : filterInternal;
|
|
8636
|
+
const setFilter = useCallback(
|
|
8637
|
+
(next) => {
|
|
8638
|
+
if (!isFilterControlled) setFilterInternal(next);
|
|
8639
|
+
props.onFilterChange?.(next);
|
|
8640
|
+
},
|
|
8641
|
+
[isFilterControlled, props.onFilterChange]
|
|
8642
|
+
);
|
|
8643
|
+
const [searchDraft, setSearchDraft] = useState(
|
|
8644
|
+
filter.search ?? ""
|
|
8645
|
+
);
|
|
8646
|
+
const debounceMs = props.searchDebounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
8647
|
+
useEffect(() => {
|
|
8648
|
+
const handle = setTimeout(() => {
|
|
8649
|
+
if (searchDraft === (filter.search ?? "")) return;
|
|
8650
|
+
setFilter({ ...filter, search: searchDraft || void 0 });
|
|
8651
|
+
}, debounceMs);
|
|
8652
|
+
return () => clearTimeout(handle);
|
|
8653
|
+
}, [searchDraft, debounceMs]);
|
|
8654
|
+
const setSearch = useCallback((s) => setSearchDraft(s), []);
|
|
8655
|
+
const [pageInternal, setPageInternal] = useState(
|
|
8656
|
+
() => props.defaultPage ?? 0
|
|
8657
|
+
);
|
|
8658
|
+
const isPageControlled = props.page !== void 0;
|
|
8659
|
+
const page = isPageControlled ? props.page : pageInternal;
|
|
8660
|
+
const setPage = useCallback(
|
|
8661
|
+
(next) => {
|
|
8662
|
+
if (!isPageControlled) setPageInternal(next);
|
|
8663
|
+
props.onPageChange?.(next);
|
|
8664
|
+
},
|
|
8665
|
+
[isPageControlled, props.onPageChange]
|
|
8666
|
+
);
|
|
8667
|
+
const prevSortKey = useRef(serializeSort(sort));
|
|
8668
|
+
const prevFilterKey = useRef(serializeFilter(filter));
|
|
8669
|
+
useEffect(() => {
|
|
8670
|
+
const sk = serializeSort(sort);
|
|
8671
|
+
const fk = serializeFilter(filter);
|
|
8672
|
+
if (sk !== prevSortKey.current || fk !== prevFilterKey.current) {
|
|
8673
|
+
if (!isPageControlled) setPageInternal(0);
|
|
8674
|
+
prevSortKey.current = sk;
|
|
8675
|
+
prevFilterKey.current = fk;
|
|
8676
|
+
}
|
|
8677
|
+
}, [sort, filter, isPageControlled]);
|
|
8678
|
+
const pageSize = props.pagination && typeof props.pagination === "object" ? props.pagination.pageSize : 0;
|
|
8679
|
+
const isServerMode = typeof props.onLoad === "function";
|
|
8680
|
+
const filtered = useMemo(
|
|
8681
|
+
() => isServerMode ? props.rows : applyFilter(props.rows, filter, props.columns),
|
|
8682
|
+
[props.rows, filter, props.columns, isServerMode]
|
|
8683
|
+
);
|
|
8684
|
+
const sorted = useMemo(
|
|
8685
|
+
() => isServerMode ? filtered : applySort(filtered, sort),
|
|
8686
|
+
[filtered, sort, isServerMode]
|
|
8687
|
+
);
|
|
8688
|
+
const pagedInMemory = useMemo(() => {
|
|
8689
|
+
if (isServerMode || pageSize <= 0) return sorted;
|
|
8690
|
+
const start = page * pageSize;
|
|
8691
|
+
return sorted.slice(start, start + pageSize);
|
|
8692
|
+
}, [sorted, page, pageSize, isServerMode]);
|
|
8693
|
+
const [serverRows, setServerRows] = useState([]);
|
|
8694
|
+
const [serverTotal, setServerTotal] = useState(0);
|
|
8695
|
+
const [serverError, setServerError] = useState(null);
|
|
8696
|
+
const reqIdRef = useRef(0);
|
|
8697
|
+
useEffect(() => {
|
|
8698
|
+
if (!isServerMode) return;
|
|
8699
|
+
const myId = ++reqIdRef.current;
|
|
8700
|
+
let cancelled = false;
|
|
8701
|
+
setServerError(null);
|
|
8702
|
+
Promise.resolve(
|
|
8703
|
+
props.onLoad({ page, sort, filter })
|
|
8704
|
+
).then((res) => {
|
|
8705
|
+
if (cancelled || myId !== reqIdRef.current) return;
|
|
8706
|
+
setServerRows(res.rows);
|
|
8707
|
+
setServerTotal(res.total);
|
|
8708
|
+
}).catch((err) => {
|
|
8709
|
+
if (cancelled || myId !== reqIdRef.current) return;
|
|
8710
|
+
console.warn("[HazoUiTable] onLoad rejected:", err);
|
|
8711
|
+
setServerRows([]);
|
|
8712
|
+
setServerTotal(0);
|
|
8713
|
+
setServerError(err ?? new Error("onLoad rejected"));
|
|
8714
|
+
});
|
|
8715
|
+
return () => {
|
|
8716
|
+
cancelled = true;
|
|
8717
|
+
};
|
|
8718
|
+
}, [isServerMode, page, sort, filter, props.onLoad]);
|
|
8719
|
+
const displayed = isServerMode ? serverRows : pagedInMemory;
|
|
8720
|
+
const totalAfterFilter = isServerMode ? serverTotal : filtered.length;
|
|
8721
|
+
return {
|
|
8722
|
+
sort,
|
|
8723
|
+
setSort,
|
|
8724
|
+
cycleHeaderSort,
|
|
8725
|
+
filter,
|
|
8726
|
+
setFilter,
|
|
8727
|
+
setSearch,
|
|
8728
|
+
page,
|
|
8729
|
+
setPage,
|
|
8730
|
+
displayed,
|
|
8731
|
+
totalAfterFilter,
|
|
8732
|
+
pageSize,
|
|
8733
|
+
serverError: isServerMode ? serverError : null
|
|
8734
|
+
};
|
|
8735
|
+
}
|
|
8736
|
+
function normalizeSortProp(p) {
|
|
8737
|
+
if (!p) return [];
|
|
8738
|
+
if (Array.isArray(p)) return p;
|
|
8739
|
+
return [p];
|
|
8740
|
+
}
|
|
8741
|
+
function cycleSingleColumn(current, key) {
|
|
8742
|
+
if (current.length !== 1) return [{ key, dir: "asc" }];
|
|
8743
|
+
const only = current[0];
|
|
8744
|
+
if (only.key !== key) return [{ key, dir: "asc" }];
|
|
8745
|
+
if (only.dir === "asc") return [{ key, dir: "desc" }];
|
|
8746
|
+
return [];
|
|
8747
|
+
}
|
|
8748
|
+
function cycleAppendColumn(current, key) {
|
|
8749
|
+
const idx = current.findIndex((s) => s.key === key);
|
|
8750
|
+
if (idx === -1) return [...current, { key, dir: "asc" }];
|
|
8751
|
+
const entry = current[idx];
|
|
8752
|
+
if (entry.dir === "asc") {
|
|
8753
|
+
const next = current.slice();
|
|
8754
|
+
next[idx] = { key, dir: "desc" };
|
|
8755
|
+
return next;
|
|
8756
|
+
}
|
|
8757
|
+
return current.filter((_, i) => i !== idx);
|
|
8758
|
+
}
|
|
8759
|
+
function applyFilter(rows, filter, columns) {
|
|
8760
|
+
let result = rows;
|
|
8761
|
+
if (filter.fields && filter.fields.length > 0) {
|
|
8762
|
+
result = result.filter(
|
|
8763
|
+
(row) => filter.fields.every((f) => matchesFieldFilter(row, f, columns))
|
|
8764
|
+
);
|
|
8765
|
+
}
|
|
8766
|
+
const needle = (filter.search ?? "").trim().toLowerCase();
|
|
8767
|
+
if (needle.length > 0) {
|
|
8768
|
+
const searchKeys = columns.filter(isSearchable).map((c) => c.key);
|
|
8769
|
+
if (searchKeys.length > 0) {
|
|
8770
|
+
result = result.filter(
|
|
8771
|
+
(row) => searchKeys.some(
|
|
8772
|
+
(k) => String(row[k] ?? "").toLowerCase().includes(needle)
|
|
8773
|
+
)
|
|
8774
|
+
);
|
|
8775
|
+
}
|
|
8776
|
+
}
|
|
8777
|
+
return result;
|
|
8778
|
+
}
|
|
8779
|
+
function isSearchable(c) {
|
|
8780
|
+
if (c.searchable !== void 0) return c.searchable;
|
|
8781
|
+
switch (c.formatter) {
|
|
8782
|
+
case "number":
|
|
8783
|
+
case "currency":
|
|
8784
|
+
case "percent":
|
|
8785
|
+
case "date":
|
|
8786
|
+
return false;
|
|
8787
|
+
default:
|
|
8788
|
+
return true;
|
|
8789
|
+
}
|
|
8790
|
+
}
|
|
8791
|
+
function matchesFieldFilter(row, f, columns) {
|
|
8792
|
+
const col = columns.find((c) => c.key === f.field);
|
|
8793
|
+
if (!col || !col.filterType) return true;
|
|
8794
|
+
const value = row[f.field];
|
|
8795
|
+
const op = f.operator || "equals";
|
|
8796
|
+
switch (col.filterType) {
|
|
8797
|
+
case "text": {
|
|
8798
|
+
if (f.value === void 0 || f.value === "") return true;
|
|
8799
|
+
return String(value ?? "").toLowerCase().includes(String(f.value).toLowerCase());
|
|
8800
|
+
}
|
|
8801
|
+
case "number": {
|
|
8802
|
+
const v = Number(value);
|
|
8803
|
+
const fv = Number(f.value);
|
|
8804
|
+
if (Number.isNaN(v) || Number.isNaN(fv)) return false;
|
|
8805
|
+
return numberOp(v, fv, op);
|
|
8806
|
+
}
|
|
8807
|
+
case "date": {
|
|
8808
|
+
const v = value instanceof Date ? value : new Date(value);
|
|
8809
|
+
const fv = f.value instanceof Date ? f.value : new Date(f.value);
|
|
8810
|
+
if (Number.isNaN(v.getTime()) || Number.isNaN(fv.getTime())) return false;
|
|
8811
|
+
const ta = new Date(v).setHours(0, 0, 0, 0);
|
|
8812
|
+
const tb = new Date(fv).setHours(0, 0, 0, 0);
|
|
8813
|
+
return numberOp(ta, tb, op);
|
|
8814
|
+
}
|
|
8815
|
+
case "combobox":
|
|
8816
|
+
return String(value) === String(f.value);
|
|
8817
|
+
case "boolean":
|
|
8818
|
+
return Boolean(value) === Boolean(f.value);
|
|
8819
|
+
default:
|
|
8820
|
+
return true;
|
|
8821
|
+
}
|
|
8822
|
+
}
|
|
8823
|
+
function numberOp(a, b, op) {
|
|
8824
|
+
switch (op) {
|
|
8825
|
+
case "equals":
|
|
8826
|
+
return a === b;
|
|
8827
|
+
case "not_equals":
|
|
8828
|
+
return a !== b;
|
|
8829
|
+
case "greater_than":
|
|
8830
|
+
return a > b;
|
|
8831
|
+
case "less_than":
|
|
8832
|
+
return a < b;
|
|
8833
|
+
case "greater_equal":
|
|
8834
|
+
return a >= b;
|
|
8835
|
+
case "less_equal":
|
|
8836
|
+
return a <= b;
|
|
8837
|
+
default:
|
|
8838
|
+
return true;
|
|
8839
|
+
}
|
|
8840
|
+
}
|
|
8841
|
+
function applySort(rows, sort) {
|
|
8842
|
+
if (sort.length === 0) return rows;
|
|
8843
|
+
return [...rows].map((row, idx) => ({ row, idx })).sort((a, b) => {
|
|
8844
|
+
for (const entry of sort) {
|
|
8845
|
+
const va = a.row[entry.key];
|
|
8846
|
+
const vb = b.row[entry.key];
|
|
8847
|
+
const cmp = compareValues(va, vb);
|
|
8848
|
+
if (cmp !== 0) return entry.dir === "asc" ? cmp : -cmp;
|
|
8849
|
+
}
|
|
8850
|
+
return a.idx - b.idx;
|
|
8851
|
+
}).map((x) => x.row);
|
|
8852
|
+
}
|
|
8853
|
+
function compareValues(a, b) {
|
|
8854
|
+
if (a == null && b == null) return 0;
|
|
8855
|
+
if (a == null) return 1;
|
|
8856
|
+
if (b == null) return -1;
|
|
8857
|
+
if (a instanceof Date && b instanceof Date)
|
|
8858
|
+
return a.getTime() - b.getTime();
|
|
8859
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
8860
|
+
return String(a).localeCompare(String(b));
|
|
8861
|
+
}
|
|
8862
|
+
function serializeSort(sort) {
|
|
8863
|
+
return sort.map((s) => `${s.key}:${s.dir}`).join(",");
|
|
8864
|
+
}
|
|
8865
|
+
function serializeFilter(filter) {
|
|
8866
|
+
const fields = (filter.fields ?? []).map((f) => `${f.field}:${f.operator ?? ""}:${String(f.value)}`).join(",");
|
|
8867
|
+
return `${filter.search ?? ""}|${fields}`;
|
|
8868
|
+
}
|
|
8869
|
+
function HazoUiTable(props) {
|
|
8870
|
+
const state = useTableState(props);
|
|
8871
|
+
const { columns, rows, getRowKey, className, caption } = props;
|
|
8872
|
+
const mobileBreakpoint = props.mobileBreakpoint ?? 768;
|
|
8873
|
+
const mobileEnabled = props.mobileCardFallback !== false;
|
|
8874
|
+
const isNarrow = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);
|
|
8875
|
+
const renderAsCards = mobileEnabled && isNarrow;
|
|
8876
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("cls_hazo_ui_table_root space-y-3", className), children: [
|
|
8877
|
+
(props.enableSearch || props.enableSortDialog || props.enableFilterDialog) && /* @__PURE__ */ jsx(
|
|
8878
|
+
Toolbar2,
|
|
8879
|
+
{
|
|
8880
|
+
columns,
|
|
8881
|
+
sort: state.sort,
|
|
8882
|
+
onSortChange: state.setSort,
|
|
8883
|
+
filter: state.filter,
|
|
8884
|
+
onSearchChange: state.setSearch,
|
|
8885
|
+
onFilterFieldsChange: (fields) => state.setFilter({ ...state.filter, fields }),
|
|
8886
|
+
enableSearch: props.enableSearch,
|
|
8887
|
+
enableSortDialog: props.enableSortDialog,
|
|
8888
|
+
enableFilterDialog: props.enableFilterDialog,
|
|
8889
|
+
searchPlaceholder: props.searchPlaceholder
|
|
8890
|
+
}
|
|
8891
|
+
),
|
|
8892
|
+
renderAsCards ? props.loading ? /* @__PURE__ */ jsx("div", { className: "cls_hazo_ui_table_mobile_loading flex flex-col gap-3", children: Array.from({ length: Math.max(state.pageSize || 5, 3) }).map(
|
|
8893
|
+
(_, i) => /* @__PURE__ */ jsxs(Card, { children: [
|
|
8894
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx(SkeletonBar, { className: "w-2/3" }) }),
|
|
8895
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "pt-0 space-y-2", children: [
|
|
8896
|
+
/* @__PURE__ */ jsx(SkeletonBar, { className: "w-full" }),
|
|
8897
|
+
/* @__PURE__ */ jsx(SkeletonBar, { className: "w-1/2" })
|
|
8898
|
+
] })
|
|
8899
|
+
] }, `mloader-${i}`)
|
|
8900
|
+
) }) : state.serverError != null ? /* @__PURE__ */ jsx("div", { className: "cls_hazo_ui_table_mobile_error py-6", children: renderErrorState(props.error, state.serverError) }) : state.displayed.length === 0 ? /* @__PURE__ */ jsx("div", { className: "cls_hazo_ui_table_mobile_empty py-6", children: noActiveFilters(state.filter) && rows.length === 0 ? typeof props.empty === "string" || props.empty === void 0 ? /* @__PURE__ */ jsx(
|
|
8901
|
+
EmptyState,
|
|
8902
|
+
{
|
|
8903
|
+
title: typeof props.empty === "string" && props.empty || "No items"
|
|
8904
|
+
}
|
|
8905
|
+
) : props.empty : typeof props.noResults === "string" || props.noResults === void 0 ? /* @__PURE__ */ jsx(
|
|
8906
|
+
EmptyState,
|
|
8907
|
+
{
|
|
8908
|
+
title: typeof props.noResults === "string" && props.noResults || "No matches \u2014 adjust your filters"
|
|
8909
|
+
}
|
|
8910
|
+
) : props.noResults }) : /* @__PURE__ */ jsx(
|
|
8911
|
+
TableMobileCards,
|
|
8912
|
+
{
|
|
8913
|
+
columns,
|
|
8914
|
+
rows: state.displayed,
|
|
8915
|
+
getRowKey,
|
|
8916
|
+
onRowClick: props.onRowClick,
|
|
8917
|
+
renderCell
|
|
8918
|
+
}
|
|
8919
|
+
) : /* @__PURE__ */ jsxs(Table2, { children: [
|
|
8920
|
+
caption && /* @__PURE__ */ jsx(TableCaption, { children: caption }),
|
|
8921
|
+
/* @__PURE__ */ jsx(TableHeader2, { children: /* @__PURE__ */ jsx(TableRow2, { children: columns.map((c) => /* @__PURE__ */ jsx(
|
|
8922
|
+
TableHead,
|
|
8923
|
+
{
|
|
8924
|
+
className: cn(headerAlignClass(c), c.headerClassName),
|
|
8925
|
+
"aria-sort": ariaSortFor(state.sort, c.key),
|
|
8926
|
+
children: c.sortable ? /* @__PURE__ */ jsxs(
|
|
8927
|
+
"button",
|
|
8928
|
+
{
|
|
8929
|
+
type: "button",
|
|
8930
|
+
onClick: (e) => state.cycleHeaderSort(c.key, e.shiftKey),
|
|
8931
|
+
title: "Click to sort; shift-click to append a secondary sort",
|
|
8932
|
+
className: "cls_hazo_ui_table_sort_btn inline-flex items-center gap-1 hover:text-foreground",
|
|
8933
|
+
children: [
|
|
8934
|
+
/* @__PURE__ */ jsx("span", { children: c.label }),
|
|
8935
|
+
/* @__PURE__ */ jsx(SortIndicator, { sort: state.sort, columnKey: c.key })
|
|
8936
|
+
]
|
|
8937
|
+
}
|
|
8938
|
+
) : c.label
|
|
8939
|
+
},
|
|
8940
|
+
c.key
|
|
8941
|
+
)) }) }),
|
|
8942
|
+
/* @__PURE__ */ jsx(TableBody, { children: props.loading ? /* @__PURE__ */ jsx(
|
|
8943
|
+
LoadingRows,
|
|
8944
|
+
{
|
|
8945
|
+
columns,
|
|
8946
|
+
count: Math.max(state.pageSize || 5, 3)
|
|
8947
|
+
}
|
|
8948
|
+
) : state.serverError != null ? /* @__PURE__ */ jsx(TableRow2, { children: /* @__PURE__ */ jsx(
|
|
8949
|
+
TableCell2,
|
|
8950
|
+
{
|
|
8951
|
+
colSpan: columns.length,
|
|
8952
|
+
className: "cls_hazo_ui_table_error_cell p-0",
|
|
8953
|
+
children: /* @__PURE__ */ jsx("div", { className: "cls_hazo_ui_table_error_wrap py-6", children: renderErrorState(props.error, state.serverError) })
|
|
8954
|
+
}
|
|
8955
|
+
) }) : state.displayed.length === 0 ? /* @__PURE__ */ jsx(TableRow2, { children: /* @__PURE__ */ jsx(
|
|
8956
|
+
TableCell2,
|
|
8957
|
+
{
|
|
8958
|
+
colSpan: columns.length,
|
|
8959
|
+
className: "cls_hazo_ui_table_empty_cell p-0",
|
|
8960
|
+
children: noActiveFilters(state.filter) && rows.length === 0 ? /* @__PURE__ */ jsx("div", { className: "cls_hazo_ui_table_empty_wrap py-6", children: typeof props.empty === "string" || props.empty === void 0 ? /* @__PURE__ */ jsx(
|
|
8961
|
+
EmptyState,
|
|
8962
|
+
{
|
|
8963
|
+
title: typeof props.empty === "string" && props.empty || "No items"
|
|
8964
|
+
}
|
|
8965
|
+
) : props.empty }) : /* @__PURE__ */ jsx("div", { className: "cls_hazo_ui_table_no_results_wrap py-6", children: typeof props.noResults === "string" || props.noResults === void 0 ? /* @__PURE__ */ jsx(
|
|
8966
|
+
EmptyState,
|
|
8967
|
+
{
|
|
8968
|
+
title: typeof props.noResults === "string" && props.noResults || "No matches \u2014 adjust your filters"
|
|
8969
|
+
}
|
|
8970
|
+
) : props.noResults })
|
|
8971
|
+
}
|
|
8972
|
+
) }) : state.displayed.map((row, i) => /* @__PURE__ */ jsx(
|
|
8973
|
+
TableRow2,
|
|
8974
|
+
{
|
|
8975
|
+
...buildRowProps(row, i, props.onRowClick),
|
|
8976
|
+
children: columns.map((c) => /* @__PURE__ */ jsx(
|
|
8977
|
+
TableCell2,
|
|
8978
|
+
{
|
|
8979
|
+
className: cn(cellAlignClass(c), c.className),
|
|
8980
|
+
children: renderCell(c, row, i)
|
|
8981
|
+
},
|
|
8982
|
+
c.key
|
|
8983
|
+
))
|
|
8984
|
+
},
|
|
8985
|
+
getRowKey ? getRowKey(row, i) : i
|
|
8986
|
+
)) })
|
|
8987
|
+
] }),
|
|
8988
|
+
state.pageSize > 0 && /* @__PURE__ */ jsx(
|
|
8989
|
+
PaginationFooter,
|
|
8990
|
+
{
|
|
8991
|
+
page: state.page,
|
|
8992
|
+
pageSize: state.pageSize,
|
|
8993
|
+
total: state.totalAfterFilter,
|
|
8994
|
+
onPageChange: state.setPage
|
|
8995
|
+
}
|
|
8996
|
+
)
|
|
8997
|
+
] });
|
|
8998
|
+
}
|
|
8999
|
+
function renderCell(c, row, i) {
|
|
9000
|
+
if (c.cell) return c.cell(row, i);
|
|
9001
|
+
const raw = row[c.key];
|
|
9002
|
+
return formatValue(raw, c.formatter, c.currency, c.locale);
|
|
9003
|
+
}
|
|
9004
|
+
var DEFAULT_NUMBER_LOCALE = "en-US";
|
|
9005
|
+
function formatValue(value, formatter, currency, locale) {
|
|
9006
|
+
if (value === null || value === void 0 || value === "") return "\u2014";
|
|
9007
|
+
const lc = locale ?? DEFAULT_NUMBER_LOCALE;
|
|
9008
|
+
switch (formatter) {
|
|
9009
|
+
case "date": {
|
|
9010
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
9011
|
+
if (Number.isNaN(d.getTime())) return String(value);
|
|
9012
|
+
return format(d, "MMM d, yyyy");
|
|
9013
|
+
}
|
|
9014
|
+
case "number":
|
|
9015
|
+
return new Intl.NumberFormat(lc).format(Number(value));
|
|
9016
|
+
case "currency":
|
|
9017
|
+
return new Intl.NumberFormat(lc, {
|
|
9018
|
+
style: "currency",
|
|
9019
|
+
currency: currency ?? "USD"
|
|
9020
|
+
}).format(Number(value));
|
|
9021
|
+
case "percent":
|
|
9022
|
+
return new Intl.NumberFormat(lc, {
|
|
9023
|
+
style: "percent",
|
|
9024
|
+
maximumFractionDigits: 2
|
|
9025
|
+
}).format(Number(value));
|
|
9026
|
+
default:
|
|
9027
|
+
return String(value);
|
|
9028
|
+
}
|
|
9029
|
+
}
|
|
9030
|
+
function headerAlignClass(c) {
|
|
9031
|
+
switch (c.align) {
|
|
9032
|
+
case "right":
|
|
9033
|
+
return "text-right";
|
|
9034
|
+
case "center":
|
|
9035
|
+
return "text-center";
|
|
9036
|
+
default:
|
|
9037
|
+
return "text-left";
|
|
9038
|
+
}
|
|
9039
|
+
}
|
|
9040
|
+
function cellAlignClass(c) {
|
|
9041
|
+
switch (c.align) {
|
|
9042
|
+
case "right":
|
|
9043
|
+
return "text-right";
|
|
9044
|
+
case "center":
|
|
9045
|
+
return "text-center";
|
|
9046
|
+
default:
|
|
9047
|
+
return "";
|
|
9048
|
+
}
|
|
9049
|
+
}
|
|
9050
|
+
function ariaSortFor(sort, key) {
|
|
9051
|
+
const entry = sort.find((s) => s.key === key);
|
|
9052
|
+
if (!entry) return "none";
|
|
9053
|
+
return entry.dir === "asc" ? "ascending" : "descending";
|
|
9054
|
+
}
|
|
9055
|
+
function deriveSortFields(columns) {
|
|
9056
|
+
return columns.filter((c) => c.sortable).map((c) => ({ value: c.key, label: c.label }));
|
|
9057
|
+
}
|
|
9058
|
+
function deriveFilterFields(columns) {
|
|
9059
|
+
return columns.filter((c) => c.filterType).map((c) => ({
|
|
9060
|
+
value: c.key,
|
|
9061
|
+
label: c.label,
|
|
9062
|
+
type: c.filterType,
|
|
9063
|
+
...c.filterConfig ?? {}
|
|
9064
|
+
}));
|
|
9065
|
+
}
|
|
9066
|
+
function sortToDialogConfig(sort) {
|
|
9067
|
+
return sort.map((s) => ({ field: s.key, direction: s.dir }));
|
|
9068
|
+
}
|
|
9069
|
+
function dialogConfigToSort(configs) {
|
|
9070
|
+
return configs.map((c) => ({ key: c.field, dir: c.direction }));
|
|
9071
|
+
}
|
|
9072
|
+
function PaginationFooter({
|
|
9073
|
+
page,
|
|
9074
|
+
pageSize,
|
|
9075
|
+
total,
|
|
9076
|
+
onPageChange
|
|
9077
|
+
}) {
|
|
9078
|
+
const start = total === 0 ? 0 : page * pageSize + 1;
|
|
9079
|
+
const end = Math.min((page + 1) * pageSize, total);
|
|
9080
|
+
const lastPage = Math.max(0, Math.ceil(total / pageSize) - 1);
|
|
9081
|
+
return /* @__PURE__ */ jsxs("div", { className: "cls_hazo_ui_table_pagination flex items-center justify-between gap-3 pt-2 text-sm", children: [
|
|
9082
|
+
/* @__PURE__ */ jsxs("span", { className: "cls_hazo_ui_table_page_counter text-muted-foreground", children: [
|
|
9083
|
+
"Showing ",
|
|
9084
|
+
start,
|
|
9085
|
+
"\u2013",
|
|
9086
|
+
end,
|
|
9087
|
+
" of ",
|
|
9088
|
+
total
|
|
9089
|
+
] }),
|
|
9090
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_hazo_ui_table_page_buttons flex items-center gap-2", children: [
|
|
9091
|
+
/* @__PURE__ */ jsx(
|
|
9092
|
+
Button,
|
|
9093
|
+
{
|
|
9094
|
+
variant: "outline",
|
|
9095
|
+
size: "sm",
|
|
9096
|
+
onClick: () => onPageChange(Math.max(0, page - 1)),
|
|
9097
|
+
disabled: page === 0,
|
|
9098
|
+
"aria-label": "Previous page",
|
|
9099
|
+
children: "\u2039 Prev"
|
|
9100
|
+
}
|
|
9101
|
+
),
|
|
9102
|
+
/* @__PURE__ */ jsx(
|
|
9103
|
+
Button,
|
|
9104
|
+
{
|
|
9105
|
+
variant: "outline",
|
|
9106
|
+
size: "sm",
|
|
9107
|
+
onClick: () => onPageChange(Math.min(lastPage, page + 1)),
|
|
9108
|
+
disabled: page >= lastPage,
|
|
9109
|
+
"aria-label": "Next page",
|
|
9110
|
+
children: "Next \u203A"
|
|
9111
|
+
}
|
|
9112
|
+
)
|
|
9113
|
+
] })
|
|
9114
|
+
] });
|
|
9115
|
+
}
|
|
9116
|
+
function Toolbar2(props) {
|
|
9117
|
+
const {
|
|
9118
|
+
columns,
|
|
9119
|
+
sort,
|
|
9120
|
+
onSortChange,
|
|
9121
|
+
filter,
|
|
9122
|
+
onSearchChange,
|
|
9123
|
+
onFilterFieldsChange,
|
|
9124
|
+
enableSearch,
|
|
9125
|
+
enableSortDialog,
|
|
9126
|
+
enableFilterDialog,
|
|
9127
|
+
searchPlaceholder
|
|
9128
|
+
} = props;
|
|
9129
|
+
const sortFields = React25.useMemo(
|
|
9130
|
+
() => deriveSortFields(columns),
|
|
9131
|
+
[columns]
|
|
9132
|
+
);
|
|
9133
|
+
const filterFields = React25.useMemo(
|
|
9134
|
+
() => deriveFilterFields(columns),
|
|
9135
|
+
[columns]
|
|
9136
|
+
);
|
|
9137
|
+
const [searchValue, setSearchValue] = React25.useState(
|
|
9138
|
+
filter.search ?? ""
|
|
9139
|
+
);
|
|
9140
|
+
React25.useEffect(() => {
|
|
9141
|
+
setSearchValue(filter.search ?? "");
|
|
9142
|
+
}, [filter.search]);
|
|
9143
|
+
return /* @__PURE__ */ jsxs("div", { className: "cls_hazo_ui_table_toolbar flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
9144
|
+
enableSearch ? /* @__PURE__ */ jsx(
|
|
9145
|
+
Input,
|
|
9146
|
+
{
|
|
9147
|
+
type: "text",
|
|
9148
|
+
value: searchValue,
|
|
9149
|
+
onChange: (e) => {
|
|
9150
|
+
const v = e.target.value;
|
|
9151
|
+
setSearchValue(v);
|
|
9152
|
+
onSearchChange(v);
|
|
9153
|
+
},
|
|
9154
|
+
placeholder: searchPlaceholder ?? "Search...",
|
|
9155
|
+
className: "cls_hazo_ui_table_search w-full sm:max-w-xs"
|
|
9156
|
+
}
|
|
9157
|
+
) : /* @__PURE__ */ jsx("div", {}),
|
|
9158
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_hazo_ui_table_toolbar_right flex items-center gap-2", children: [
|
|
9159
|
+
enableFilterDialog && filterFields.length > 0 && /* @__PURE__ */ jsx(
|
|
9160
|
+
HazoUiMultiFilterDialog,
|
|
9161
|
+
{
|
|
9162
|
+
availableFields: filterFields,
|
|
9163
|
+
initialFilters: filter.fields ?? [],
|
|
9164
|
+
onFilterChange: onFilterFieldsChange
|
|
9165
|
+
}
|
|
9166
|
+
),
|
|
9167
|
+
enableSortDialog && sortFields.length > 0 && /* @__PURE__ */ jsx(
|
|
9168
|
+
HazoUiMultiSortDialog,
|
|
9169
|
+
{
|
|
9170
|
+
availableFields: sortFields,
|
|
9171
|
+
initialSortFields: sortToDialogConfig(sort),
|
|
9172
|
+
onSortChange: (configs) => onSortChange(dialogConfigToSort(configs))
|
|
9173
|
+
}
|
|
9174
|
+
)
|
|
9175
|
+
] })
|
|
9176
|
+
] });
|
|
9177
|
+
}
|
|
9178
|
+
function LoadingRows({
|
|
9179
|
+
columns,
|
|
9180
|
+
count
|
|
9181
|
+
}) {
|
|
9182
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: Array.from({ length: count }).map((_, rowIdx) => /* @__PURE__ */ jsx(TableRow2, { children: columns.map((c) => /* @__PURE__ */ jsx(TableCell2, { className: cellAlignClass(c), children: /* @__PURE__ */ jsx(
|
|
9183
|
+
SkeletonBar,
|
|
9184
|
+
{
|
|
9185
|
+
className: cn(
|
|
9186
|
+
"cls_hazo_ui_table_skeleton",
|
|
9187
|
+
c.align === "right" ? "w-16 ml-auto" : "w-full"
|
|
9188
|
+
)
|
|
9189
|
+
}
|
|
9190
|
+
) }, c.key)) }, `skeleton-${rowIdx}`)) });
|
|
9191
|
+
}
|
|
9192
|
+
function noActiveFilters(filter) {
|
|
9193
|
+
return !filter.search && (!filter.fields || filter.fields.length === 0);
|
|
9194
|
+
}
|
|
9195
|
+
function renderErrorState(error, serverError) {
|
|
9196
|
+
if (typeof error === "function") return error(serverError);
|
|
9197
|
+
if (error !== void 0 && error !== null) return error;
|
|
9198
|
+
const msg = serverError instanceof Error ? serverError.message : String(serverError);
|
|
9199
|
+
return /* @__PURE__ */ jsx(
|
|
9200
|
+
EmptyState,
|
|
9201
|
+
{
|
|
9202
|
+
title: "Couldn't load data",
|
|
9203
|
+
description: msg || "The data source rejected the request."
|
|
9204
|
+
}
|
|
9205
|
+
);
|
|
9206
|
+
}
|
|
9207
|
+
function buildRowProps(row, index, onRowClick) {
|
|
9208
|
+
if (!onRowClick) return {};
|
|
9209
|
+
return {
|
|
9210
|
+
role: "button",
|
|
9211
|
+
tabIndex: 0,
|
|
9212
|
+
className: "cls_hazo_ui_table_row_clickable cursor-pointer",
|
|
9213
|
+
onClick: () => onRowClick(row, index),
|
|
9214
|
+
onKeyDown: (e) => {
|
|
9215
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
9216
|
+
e.preventDefault();
|
|
9217
|
+
onRowClick(row, index);
|
|
9218
|
+
}
|
|
9219
|
+
}
|
|
9220
|
+
};
|
|
9221
|
+
}
|
|
9222
|
+
function SortIndicator({
|
|
9223
|
+
sort,
|
|
9224
|
+
columnKey
|
|
9225
|
+
}) {
|
|
9226
|
+
const idx = sort.findIndex((s) => s.key === columnKey);
|
|
9227
|
+
if (idx === -1) {
|
|
9228
|
+
return /* @__PURE__ */ jsx(ChevronsUpDown, { className: "cls_hazo_ui_table_sort_idle h-3.5 w-3.5 opacity-30" });
|
|
9229
|
+
}
|
|
9230
|
+
const entry = sort[idx];
|
|
9231
|
+
return /* @__PURE__ */ jsxs("span", { className: "cls_hazo_ui_table_sort_active inline-flex items-center gap-0.5", children: [
|
|
9232
|
+
entry.dir === "asc" ? /* @__PURE__ */ jsx(ChevronUp, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" }),
|
|
9233
|
+
sort.length > 1 && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-medium", children: idx + 1 })
|
|
9234
|
+
] });
|
|
9235
|
+
}
|
|
7243
9236
|
|
|
7244
|
-
export { ANIMATION_PRESETS, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, CommandNodeExtension, CommandPill, CommandPopover, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, HazoUiConfirmDialog, HazoUiDialog, DialogClose as HazoUiDialogClose, DialogContent as HazoUiDialogContent, DialogDescription as HazoUiDialogDescription, DialogFooter as HazoUiDialogFooter, DialogHeader as HazoUiDialogHeader, DialogOverlay as HazoUiDialogOverlay, DialogPortal as HazoUiDialogPortal, Dialog as HazoUiDialogRoot, DialogTitle as HazoUiDialogTitle, DialogTrigger as HazoUiDialogTrigger, HazoUiFlexInput, HazoUiFlexRadio, HazoUiMultiFilterDialog, HazoUiMultiSortDialog, HazoUiPillRadio, HazoUiRte, HazoUiTextarea, HazoUiTextbox, HoverCard, HoverCardContent, HoverCardTrigger, Input,
|
|
9237
|
+
export { ANIMATION_PRESETS, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, CommandNodeExtension, CommandPill, CommandPopover, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorBanner, ErrorPage, HazoUiConfirmDialog, HazoUiDialog, DialogClose as HazoUiDialogClose, DialogContent as HazoUiDialogContent, DialogDescription as HazoUiDialogDescription, DialogFooter as HazoUiDialogFooter, DialogHeader as HazoUiDialogHeader, DialogOverlay as HazoUiDialogOverlay, DialogPortal as HazoUiDialogPortal, Dialog as HazoUiDialogRoot, DialogTitle as HazoUiDialogTitle, DialogTrigger as HazoUiDialogTrigger, HazoUiFlexInput, HazoUiFlexRadio, HazoUiKanban, HazoUiKanbanFilter, HazoUiMultiFilterDialog, HazoUiMultiSortDialog, HazoUiPillRadio, HazoUiRte, HazoUiTable, HazoUiTextarea, HazoUiTextbox, HazoUiToaster, HoverCard, HoverCardContent, HoverCardTrigger, Input, Label3 as Label, LoadingTimeout, Popover, PopoverContent, PopoverTrigger, ProgressiveImage, RadioGroup, RadioGroupItem, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator3 as Separator, Command as ShadcnCommand, CommandEmpty as ShadcnCommandEmpty, CommandGroup as ShadcnCommandGroup, CommandInput as ShadcnCommandInput, CommandItem as ShadcnCommandItem, CommandList as ShadcnCommandList, Skeleton, SkeletonBar, SkeletonCircle, SkeletonGroup, SkeletonRect, Spinner, Switch, Table2 as Table, TableBody, TableCaption, TableCell2 as TableCell, TableFooter, TableHead, TableHeader2 as TableHeader, TableRow2 as TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, applyKanbanFilter, buttonGroupVariants, create_command_suggestion_extension, errorToast, get_hazo_ui_config, parse_commands_from_text, reset_hazo_ui_config, resolve_animation_classes, set_hazo_ui_config, successToast, text_to_tiptap_content, toggleVariants, useErrorDisplay, useLoadingState, useMediaQuery };
|
|
7245
9238
|
//# sourceMappingURL=index.js.map
|
|
7246
9239
|
//# sourceMappingURL=index.js.map
|