hazo_ui 1.1.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +229 -31
- package/dist/index.cjs +339 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +339 -26
- package/dist/index.js.map +1 -1
- package/package.json +9 -5
package/dist/index.js
CHANGED
|
@@ -6,12 +6,16 @@ import { cva } from 'class-variance-authority';
|
|
|
6
6
|
import { clsx } from 'clsx';
|
|
7
7
|
import { twMerge } from 'tailwind-merge';
|
|
8
8
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
9
|
-
import { X, ChevronDown, ChevronUp, Check, Filter, Plus, ChevronsUpDown, Trash2, Calendar as Calendar$1, ChevronRight, ChevronLeft } from 'lucide-react';
|
|
9
|
+
import { X, ChevronDown, ChevronUp, Check, Filter, Plus, ChevronsUpDown, ArrowUpDown, Trash2, GripVertical, Calendar as Calendar$1, ChevronRight, ChevronLeft } from 'lucide-react';
|
|
10
10
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
11
11
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
12
12
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
13
13
|
import { DayPicker } from 'react-day-picker';
|
|
14
14
|
import { format } from 'date-fns';
|
|
15
|
+
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
16
|
+
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from '@dnd-kit/core';
|
|
17
|
+
import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, arrayMove, useSortable } from '@dnd-kit/sortable';
|
|
18
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
15
19
|
|
|
16
20
|
var ExampleComponent = ({ children, className = "" }) => {
|
|
17
21
|
return /* @__PURE__ */ jsx("div", { className: `cls_example_component ${className}`, children });
|
|
@@ -756,30 +760,27 @@ function MultiFilterDialog({
|
|
|
756
760
|
) }),
|
|
757
761
|
/* @__PURE__ */ jsx(PopoverContent, { className: "cls_combobox_popover w-full p-0", children: /* @__PURE__ */ jsxs(Command, { children: [
|
|
758
762
|
/* @__PURE__ */ jsx(CommandInput, { placeholder: "Search fields...", className: "cls_command_input" }),
|
|
759
|
-
/* @__PURE__ */
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
field.value
|
|
781
|
-
)) })
|
|
782
|
-
] })
|
|
763
|
+
/* @__PURE__ */ jsx(CommandList, { children: availableFieldsToAdd.length === 0 ? /* @__PURE__ */ jsx(CommandEmpty, { children: "No fields found." }) : /* @__PURE__ */ jsx(CommandGroup, { children: availableFieldsToAdd.map((field) => /* @__PURE__ */ jsxs(
|
|
764
|
+
CommandItem,
|
|
765
|
+
{
|
|
766
|
+
value: field.label,
|
|
767
|
+
onSelect: () => handleAddField(field.value),
|
|
768
|
+
className: "cls_command_item",
|
|
769
|
+
children: [
|
|
770
|
+
/* @__PURE__ */ jsx(
|
|
771
|
+
Check,
|
|
772
|
+
{
|
|
773
|
+
className: cn(
|
|
774
|
+
"cls_check_icon mr-2 h-4 w-4",
|
|
775
|
+
"opacity-0"
|
|
776
|
+
)
|
|
777
|
+
}
|
|
778
|
+
),
|
|
779
|
+
field.label
|
|
780
|
+
]
|
|
781
|
+
},
|
|
782
|
+
field.value
|
|
783
|
+
)) }) })
|
|
783
784
|
] }) })
|
|
784
785
|
] }) }),
|
|
785
786
|
filterFields.length > 0 ? /* @__PURE__ */ jsx("div", { className: "cls_filter_fields_list space-y-2", children: filterFields.map((filterConfig) => {
|
|
@@ -832,7 +833,319 @@ function MultiFilterDialog({
|
|
|
832
833
|
] })
|
|
833
834
|
] });
|
|
834
835
|
}
|
|
836
|
+
var Switch = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
837
|
+
SwitchPrimitives.Root,
|
|
838
|
+
{
|
|
839
|
+
className: cn(
|
|
840
|
+
"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",
|
|
841
|
+
className
|
|
842
|
+
),
|
|
843
|
+
...props,
|
|
844
|
+
ref,
|
|
845
|
+
children: /* @__PURE__ */ jsx(
|
|
846
|
+
SwitchPrimitives.Thumb,
|
|
847
|
+
{
|
|
848
|
+
className: cn(
|
|
849
|
+
"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"
|
|
850
|
+
)
|
|
851
|
+
}
|
|
852
|
+
)
|
|
853
|
+
}
|
|
854
|
+
));
|
|
855
|
+
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
856
|
+
var Label2 = React6.forwardRef(
|
|
857
|
+
({ className, ...props }, ref) => {
|
|
858
|
+
return /* @__PURE__ */ jsx(
|
|
859
|
+
"label",
|
|
860
|
+
{
|
|
861
|
+
ref,
|
|
862
|
+
className: cn(
|
|
863
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
864
|
+
className
|
|
865
|
+
),
|
|
866
|
+
...props
|
|
867
|
+
}
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
);
|
|
871
|
+
Label2.displayName = "Label";
|
|
872
|
+
function SortableSortFieldItem({
|
|
873
|
+
sortConfig,
|
|
874
|
+
fieldLabel,
|
|
875
|
+
onDirectionChange,
|
|
876
|
+
onDelete
|
|
877
|
+
}) {
|
|
878
|
+
const {
|
|
879
|
+
attributes,
|
|
880
|
+
listeners,
|
|
881
|
+
setNodeRef,
|
|
882
|
+
transform,
|
|
883
|
+
transition,
|
|
884
|
+
isDragging
|
|
885
|
+
} = useSortable({ id: sortConfig.field });
|
|
886
|
+
const style = {
|
|
887
|
+
transform: CSS.Transform.toString(transform),
|
|
888
|
+
transition,
|
|
889
|
+
opacity: isDragging ? 0.5 : 1
|
|
890
|
+
};
|
|
891
|
+
return /* @__PURE__ */ jsxs(
|
|
892
|
+
"div",
|
|
893
|
+
{
|
|
894
|
+
ref: setNodeRef,
|
|
895
|
+
style,
|
|
896
|
+
className: "cls_sortable_sort_field_item flex items-center gap-3 p-3 border rounded-md bg-card",
|
|
897
|
+
children: [
|
|
898
|
+
/* @__PURE__ */ jsx(
|
|
899
|
+
"div",
|
|
900
|
+
{
|
|
901
|
+
...attributes,
|
|
902
|
+
...listeners,
|
|
903
|
+
className: "cls_drag_handle cursor-grab active:cursor-grabbing text-muted-foreground hover:text-foreground",
|
|
904
|
+
children: /* @__PURE__ */ jsx(GripVertical, { className: "cls_drag_icon h-4 w-4" })
|
|
905
|
+
}
|
|
906
|
+
),
|
|
907
|
+
/* @__PURE__ */ jsx("span", { className: "cls_field_label flex-1 text-sm font-medium", children: fieldLabel }),
|
|
908
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_direction_control flex items-center gap-2", children: [
|
|
909
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: `switch-${sortConfig.field}`, className: "cls_direction_label text-xs text-muted-foreground", children: sortConfig.direction === "asc" ? "Ascending" : "Descending" }),
|
|
910
|
+
/* @__PURE__ */ jsx(
|
|
911
|
+
Switch,
|
|
912
|
+
{
|
|
913
|
+
id: `switch-${sortConfig.field}`,
|
|
914
|
+
checked: sortConfig.direction === "desc",
|
|
915
|
+
onCheckedChange: (checked) => onDirectionChange(checked ? "desc" : "asc"),
|
|
916
|
+
"aria-label": `Toggle sort direction for ${fieldLabel}`
|
|
917
|
+
}
|
|
918
|
+
)
|
|
919
|
+
] }),
|
|
920
|
+
/* @__PURE__ */ jsx(
|
|
921
|
+
Button,
|
|
922
|
+
{
|
|
923
|
+
variant: "ghost",
|
|
924
|
+
size: "sm",
|
|
925
|
+
onClick: onDelete,
|
|
926
|
+
className: "cls_delete_btn h-8 w-8 p-0 text-destructive hover:text-destructive",
|
|
927
|
+
"aria-label": `Remove ${fieldLabel} from sort`,
|
|
928
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "cls_delete_icon h-4 w-4" })
|
|
929
|
+
}
|
|
930
|
+
)
|
|
931
|
+
]
|
|
932
|
+
}
|
|
933
|
+
);
|
|
934
|
+
}
|
|
935
|
+
function MultiSortDialog({
|
|
936
|
+
availableFields,
|
|
937
|
+
onSortChange,
|
|
938
|
+
initialSortFields = []
|
|
939
|
+
}) {
|
|
940
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
941
|
+
const [sortFields, setSortFields] = useState(initialSortFields);
|
|
942
|
+
const [isComboboxOpen, setIsComboboxOpen] = useState(false);
|
|
943
|
+
const sensors = useSensors(
|
|
944
|
+
useSensor(PointerSensor),
|
|
945
|
+
useSensor(KeyboardSensor, {
|
|
946
|
+
coordinateGetter: sortableKeyboardCoordinates
|
|
947
|
+
})
|
|
948
|
+
);
|
|
949
|
+
useEffect(() => {
|
|
950
|
+
if (isOpen) {
|
|
951
|
+
setSortFields(initialSortFields);
|
|
952
|
+
}
|
|
953
|
+
}, [isOpen, initialSortFields]);
|
|
954
|
+
const handleAddField = (fieldValue) => {
|
|
955
|
+
if (sortFields.some((sf) => sf.field === fieldValue)) {
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
const newField = {
|
|
959
|
+
field: fieldValue,
|
|
960
|
+
direction: "asc"
|
|
961
|
+
};
|
|
962
|
+
setSortFields([...sortFields, newField]);
|
|
963
|
+
setIsComboboxOpen(false);
|
|
964
|
+
};
|
|
965
|
+
const handleDeleteField = (fieldValue) => {
|
|
966
|
+
setSortFields(sortFields.filter((sf) => sf.field !== fieldValue));
|
|
967
|
+
};
|
|
968
|
+
const handleDirectionChange = (fieldValue, direction) => {
|
|
969
|
+
setSortFields(
|
|
970
|
+
sortFields.map(
|
|
971
|
+
(sf) => sf.field === fieldValue ? { ...sf, direction } : sf
|
|
972
|
+
)
|
|
973
|
+
);
|
|
974
|
+
};
|
|
975
|
+
const handleDragEnd = (event) => {
|
|
976
|
+
const { active, over } = event;
|
|
977
|
+
if (!over || active.id === over.id) {
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
const oldIndex = sortFields.findIndex((sf) => sf.field === active.id);
|
|
981
|
+
const newIndex = sortFields.findIndex((sf) => sf.field === over.id);
|
|
982
|
+
if (oldIndex !== -1 && newIndex !== -1) {
|
|
983
|
+
setSortFields(arrayMove(sortFields, oldIndex, newIndex));
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
const handleApply = () => {
|
|
987
|
+
onSortChange([...sortFields]);
|
|
988
|
+
setIsOpen(false);
|
|
989
|
+
};
|
|
990
|
+
const handleCancel = () => {
|
|
991
|
+
setSortFields(initialSortFields);
|
|
992
|
+
setIsOpen(false);
|
|
993
|
+
};
|
|
994
|
+
const handleClearAll = () => {
|
|
995
|
+
setSortFields([]);
|
|
996
|
+
};
|
|
997
|
+
const availableFieldsToAdd = availableFields.filter(
|
|
998
|
+
(af) => !sortFields.some((sf) => sf.field === af.value)
|
|
999
|
+
);
|
|
1000
|
+
const getFieldLabel = (fieldValue) => {
|
|
1001
|
+
return availableFields.find((af) => af.value === fieldValue)?.label || fieldValue;
|
|
1002
|
+
};
|
|
1003
|
+
const hasActiveSorts = initialSortFields.length > 0;
|
|
1004
|
+
const tooltipContent = hasActiveSorts ? /* @__PURE__ */ jsxs("div", { className: "cls_sort_tooltip_content space-y-1", children: [
|
|
1005
|
+
/* @__PURE__ */ jsx("div", { className: "cls_tooltip_title text-xs font-semibold mb-1", children: "Active Sorts:" }),
|
|
1006
|
+
initialSortFields.map((sortConfig, index) => /* @__PURE__ */ jsxs("div", { className: "cls_tooltip_item text-xs", children: [
|
|
1007
|
+
index + 1,
|
|
1008
|
+
". ",
|
|
1009
|
+
getFieldLabel(sortConfig.field),
|
|
1010
|
+
" (",
|
|
1011
|
+
sortConfig.direction === "asc" ? "Asc" : "Desc",
|
|
1012
|
+
")"
|
|
1013
|
+
] }, sortConfig.field))
|
|
1014
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "cls_sort_tooltip_content text-xs", children: "No active sorts" });
|
|
1015
|
+
return /* @__PURE__ */ jsxs(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
1016
|
+
/* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
1017
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1018
|
+
Button,
|
|
1019
|
+
{
|
|
1020
|
+
variant: "outline",
|
|
1021
|
+
size: "sm",
|
|
1022
|
+
className: "cls_sort_button",
|
|
1023
|
+
"aria-label": "Open sort dialog",
|
|
1024
|
+
children: [
|
|
1025
|
+
/* @__PURE__ */ jsx(
|
|
1026
|
+
ArrowUpDown,
|
|
1027
|
+
{
|
|
1028
|
+
className: cn(
|
|
1029
|
+
"cls_sort_icon h-4 w-4 mr-2",
|
|
1030
|
+
hasActiveSorts && "text-blue-600"
|
|
1031
|
+
)
|
|
1032
|
+
}
|
|
1033
|
+
),
|
|
1034
|
+
"Sort"
|
|
1035
|
+
]
|
|
1036
|
+
}
|
|
1037
|
+
) }) }),
|
|
1038
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: tooltipContent })
|
|
1039
|
+
] }) }),
|
|
1040
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "cls_sort_dialog_content max-w-lg", children: [
|
|
1041
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
1042
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Sort Images" }),
|
|
1043
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: "Add multiple fields to sort by and reorder them. Use the switch to toggle between ascending and descending." })
|
|
1044
|
+
] }),
|
|
1045
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_sort_dialog_body space-y-4 py-4", children: [
|
|
1046
|
+
/* @__PURE__ */ jsx("div", { className: "cls_add_field_section", children: /* @__PURE__ */ jsxs(Popover, { open: isComboboxOpen, onOpenChange: setIsComboboxOpen, children: [
|
|
1047
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1048
|
+
Button,
|
|
1049
|
+
{
|
|
1050
|
+
variant: "outline",
|
|
1051
|
+
role: "combobox",
|
|
1052
|
+
"aria-expanded": isComboboxOpen,
|
|
1053
|
+
className: "cls_add_field_combobox w-full justify-between",
|
|
1054
|
+
children: [
|
|
1055
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_combobox_content flex items-center", children: [
|
|
1056
|
+
/* @__PURE__ */ jsx(Plus, { className: "cls_plus_icon h-4 w-4 mr-2" }),
|
|
1057
|
+
/* @__PURE__ */ jsx("span", { children: "Add field" })
|
|
1058
|
+
] }),
|
|
1059
|
+
/* @__PURE__ */ jsx(ChevronsUpDown, { className: "cls_chevron_icon ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
1060
|
+
]
|
|
1061
|
+
}
|
|
1062
|
+
) }),
|
|
1063
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "cls_combobox_popover w-full p-0", children: /* @__PURE__ */ jsxs(Command, { children: [
|
|
1064
|
+
/* @__PURE__ */ jsx(CommandInput, { placeholder: "Search fields...", className: "cls_command_input" }),
|
|
1065
|
+
/* @__PURE__ */ jsx(CommandList, { children: availableFieldsToAdd.length === 0 ? /* @__PURE__ */ jsx(CommandEmpty, { children: "No fields found." }) : /* @__PURE__ */ jsx(CommandGroup, { children: availableFieldsToAdd.map((field) => /* @__PURE__ */ jsxs(
|
|
1066
|
+
CommandItem,
|
|
1067
|
+
{
|
|
1068
|
+
value: field.label,
|
|
1069
|
+
onSelect: () => handleAddField(field.value),
|
|
1070
|
+
className: "cls_command_item",
|
|
1071
|
+
children: [
|
|
1072
|
+
/* @__PURE__ */ jsx(
|
|
1073
|
+
Check,
|
|
1074
|
+
{
|
|
1075
|
+
className: cn(
|
|
1076
|
+
"cls_check_icon mr-2 h-4 w-4",
|
|
1077
|
+
"opacity-0"
|
|
1078
|
+
)
|
|
1079
|
+
}
|
|
1080
|
+
),
|
|
1081
|
+
field.label
|
|
1082
|
+
]
|
|
1083
|
+
},
|
|
1084
|
+
field.value
|
|
1085
|
+
)) }) })
|
|
1086
|
+
] }) })
|
|
1087
|
+
] }) }),
|
|
1088
|
+
sortFields.length > 0 ? /* @__PURE__ */ jsx("div", { className: "cls_sort_fields_list space-y-2", children: /* @__PURE__ */ jsx(
|
|
1089
|
+
DndContext,
|
|
1090
|
+
{
|
|
1091
|
+
sensors,
|
|
1092
|
+
collisionDetection: closestCenter,
|
|
1093
|
+
onDragEnd: handleDragEnd,
|
|
1094
|
+
children: /* @__PURE__ */ jsx(
|
|
1095
|
+
SortableContext,
|
|
1096
|
+
{
|
|
1097
|
+
items: sortFields.map((sf) => sf.field),
|
|
1098
|
+
strategy: verticalListSortingStrategy,
|
|
1099
|
+
children: sortFields.map((sortConfig) => /* @__PURE__ */ jsx(
|
|
1100
|
+
SortableSortFieldItem,
|
|
1101
|
+
{
|
|
1102
|
+
sortConfig,
|
|
1103
|
+
fieldLabel: getFieldLabel(sortConfig.field),
|
|
1104
|
+
onDirectionChange: (direction) => handleDirectionChange(sortConfig.field, direction),
|
|
1105
|
+
onDelete: () => handleDeleteField(sortConfig.field)
|
|
1106
|
+
},
|
|
1107
|
+
sortConfig.field
|
|
1108
|
+
))
|
|
1109
|
+
}
|
|
1110
|
+
)
|
|
1111
|
+
}
|
|
1112
|
+
) }) : /* @__PURE__ */ jsx("div", { className: "cls_empty_sort_fields text-center py-8 text-sm text-muted-foreground", children: 'No sort fields added. Click "Add field" to add sorting criteria.' })
|
|
1113
|
+
] }),
|
|
1114
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
1115
|
+
sortFields.length > 0 && /* @__PURE__ */ jsxs(
|
|
1116
|
+
Button,
|
|
1117
|
+
{
|
|
1118
|
+
variant: "outline",
|
|
1119
|
+
onClick: handleClearAll,
|
|
1120
|
+
className: "cls_clear_all_btn",
|
|
1121
|
+
children: [
|
|
1122
|
+
/* @__PURE__ */ jsx(Trash2, { className: "cls_clear_all_icon h-4 w-4 mr-2" }),
|
|
1123
|
+
"Clear All"
|
|
1124
|
+
]
|
|
1125
|
+
}
|
|
1126
|
+
),
|
|
1127
|
+
/* @__PURE__ */ jsx(
|
|
1128
|
+
Button,
|
|
1129
|
+
{
|
|
1130
|
+
onClick: handleApply,
|
|
1131
|
+
className: "cls_apply_btn",
|
|
1132
|
+
children: "Apply"
|
|
1133
|
+
}
|
|
1134
|
+
),
|
|
1135
|
+
/* @__PURE__ */ jsx(
|
|
1136
|
+
Button,
|
|
1137
|
+
{
|
|
1138
|
+
variant: "outline",
|
|
1139
|
+
onClick: handleCancel,
|
|
1140
|
+
className: "cls_cancel_btn",
|
|
1141
|
+
children: "Cancel"
|
|
1142
|
+
}
|
|
1143
|
+
)
|
|
1144
|
+
] })
|
|
1145
|
+
] })
|
|
1146
|
+
] });
|
|
1147
|
+
}
|
|
835
1148
|
|
|
836
|
-
export { ExampleComponent, MultiFilterDialog };
|
|
1149
|
+
export { ExampleComponent, MultiFilterDialog, MultiSortDialog };
|
|
837
1150
|
//# sourceMappingURL=index.js.map
|
|
838
1151
|
//# sourceMappingURL=index.js.map
|