hazo_ui 1.0.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +229 -31
- package/dist/index.cjs +336 -0
- 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 +336 -2
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
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 });
|
|
@@ -670,6 +674,9 @@ function MultiFilterDialog({
|
|
|
670
674
|
setFilterFields(initialFilters);
|
|
671
675
|
setIsOpen(false);
|
|
672
676
|
};
|
|
677
|
+
const handleClearAll = () => {
|
|
678
|
+
setFilterFields([]);
|
|
679
|
+
};
|
|
673
680
|
const availableFieldsToAdd = availableFields.filter(
|
|
674
681
|
(af) => !filterFields.some((ff) => ff.field === af.value)
|
|
675
682
|
);
|
|
@@ -796,6 +803,333 @@ function MultiFilterDialog({
|
|
|
796
803
|
}) }) : /* @__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.' })
|
|
797
804
|
] }),
|
|
798
805
|
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
806
|
+
filterFields.length > 0 && /* @__PURE__ */ jsxs(
|
|
807
|
+
Button,
|
|
808
|
+
{
|
|
809
|
+
variant: "outline",
|
|
810
|
+
onClick: handleClearAll,
|
|
811
|
+
className: "cls_clear_all_btn",
|
|
812
|
+
children: [
|
|
813
|
+
/* @__PURE__ */ jsx(X, { className: "cls_clear_all_icon h-4 w-4 mr-2" }),
|
|
814
|
+
"Clear All"
|
|
815
|
+
]
|
|
816
|
+
}
|
|
817
|
+
),
|
|
818
|
+
/* @__PURE__ */ jsx(
|
|
819
|
+
Button,
|
|
820
|
+
{
|
|
821
|
+
onClick: handleApply,
|
|
822
|
+
className: "cls_apply_btn",
|
|
823
|
+
children: "Apply"
|
|
824
|
+
}
|
|
825
|
+
),
|
|
826
|
+
/* @__PURE__ */ jsx(
|
|
827
|
+
Button,
|
|
828
|
+
{
|
|
829
|
+
variant: "outline",
|
|
830
|
+
onClick: handleCancel,
|
|
831
|
+
className: "cls_cancel_btn",
|
|
832
|
+
children: "Cancel"
|
|
833
|
+
}
|
|
834
|
+
)
|
|
835
|
+
] })
|
|
836
|
+
] })
|
|
837
|
+
] });
|
|
838
|
+
}
|
|
839
|
+
var Switch = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
840
|
+
SwitchPrimitives.Root,
|
|
841
|
+
{
|
|
842
|
+
className: cn(
|
|
843
|
+
"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",
|
|
844
|
+
className
|
|
845
|
+
),
|
|
846
|
+
...props,
|
|
847
|
+
ref,
|
|
848
|
+
children: /* @__PURE__ */ jsx(
|
|
849
|
+
SwitchPrimitives.Thumb,
|
|
850
|
+
{
|
|
851
|
+
className: cn(
|
|
852
|
+
"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"
|
|
853
|
+
)
|
|
854
|
+
}
|
|
855
|
+
)
|
|
856
|
+
}
|
|
857
|
+
));
|
|
858
|
+
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
859
|
+
var Label2 = React6.forwardRef(
|
|
860
|
+
({ className, ...props }, ref) => {
|
|
861
|
+
return /* @__PURE__ */ jsx(
|
|
862
|
+
"label",
|
|
863
|
+
{
|
|
864
|
+
ref,
|
|
865
|
+
className: cn(
|
|
866
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
867
|
+
className
|
|
868
|
+
),
|
|
869
|
+
...props
|
|
870
|
+
}
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
);
|
|
874
|
+
Label2.displayName = "Label";
|
|
875
|
+
function SortableSortFieldItem({
|
|
876
|
+
sortConfig,
|
|
877
|
+
fieldLabel,
|
|
878
|
+
onDirectionChange,
|
|
879
|
+
onDelete
|
|
880
|
+
}) {
|
|
881
|
+
const {
|
|
882
|
+
attributes,
|
|
883
|
+
listeners,
|
|
884
|
+
setNodeRef,
|
|
885
|
+
transform,
|
|
886
|
+
transition,
|
|
887
|
+
isDragging
|
|
888
|
+
} = useSortable({ id: sortConfig.field });
|
|
889
|
+
const style = {
|
|
890
|
+
transform: CSS.Transform.toString(transform),
|
|
891
|
+
transition,
|
|
892
|
+
opacity: isDragging ? 0.5 : 1
|
|
893
|
+
};
|
|
894
|
+
return /* @__PURE__ */ jsxs(
|
|
895
|
+
"div",
|
|
896
|
+
{
|
|
897
|
+
ref: setNodeRef,
|
|
898
|
+
style,
|
|
899
|
+
className: "cls_sortable_sort_field_item flex items-center gap-3 p-3 border rounded-md bg-card",
|
|
900
|
+
children: [
|
|
901
|
+
/* @__PURE__ */ jsx(
|
|
902
|
+
"div",
|
|
903
|
+
{
|
|
904
|
+
...attributes,
|
|
905
|
+
...listeners,
|
|
906
|
+
className: "cls_drag_handle cursor-grab active:cursor-grabbing text-muted-foreground hover:text-foreground",
|
|
907
|
+
children: /* @__PURE__ */ jsx(GripVertical, { className: "cls_drag_icon h-4 w-4" })
|
|
908
|
+
}
|
|
909
|
+
),
|
|
910
|
+
/* @__PURE__ */ jsx("span", { className: "cls_field_label flex-1 text-sm font-medium", children: fieldLabel }),
|
|
911
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_direction_control flex items-center gap-2", children: [
|
|
912
|
+
/* @__PURE__ */ jsx(Label2, { htmlFor: `switch-${sortConfig.field}`, className: "cls_direction_label text-xs text-muted-foreground", children: sortConfig.direction === "asc" ? "Ascending" : "Descending" }),
|
|
913
|
+
/* @__PURE__ */ jsx(
|
|
914
|
+
Switch,
|
|
915
|
+
{
|
|
916
|
+
id: `switch-${sortConfig.field}`,
|
|
917
|
+
checked: sortConfig.direction === "desc",
|
|
918
|
+
onCheckedChange: (checked) => onDirectionChange(checked ? "desc" : "asc"),
|
|
919
|
+
"aria-label": `Toggle sort direction for ${fieldLabel}`
|
|
920
|
+
}
|
|
921
|
+
)
|
|
922
|
+
] }),
|
|
923
|
+
/* @__PURE__ */ jsx(
|
|
924
|
+
Button,
|
|
925
|
+
{
|
|
926
|
+
variant: "ghost",
|
|
927
|
+
size: "sm",
|
|
928
|
+
onClick: onDelete,
|
|
929
|
+
className: "cls_delete_btn h-8 w-8 p-0 text-destructive hover:text-destructive",
|
|
930
|
+
"aria-label": `Remove ${fieldLabel} from sort`,
|
|
931
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "cls_delete_icon h-4 w-4" })
|
|
932
|
+
}
|
|
933
|
+
)
|
|
934
|
+
]
|
|
935
|
+
}
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
function MultiSortDialog({
|
|
939
|
+
availableFields,
|
|
940
|
+
onSortChange,
|
|
941
|
+
initialSortFields = []
|
|
942
|
+
}) {
|
|
943
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
944
|
+
const [sortFields, setSortFields] = useState(initialSortFields);
|
|
945
|
+
const [isComboboxOpen, setIsComboboxOpen] = useState(false);
|
|
946
|
+
const sensors = useSensors(
|
|
947
|
+
useSensor(PointerSensor),
|
|
948
|
+
useSensor(KeyboardSensor, {
|
|
949
|
+
coordinateGetter: sortableKeyboardCoordinates
|
|
950
|
+
})
|
|
951
|
+
);
|
|
952
|
+
useEffect(() => {
|
|
953
|
+
if (isOpen) {
|
|
954
|
+
setSortFields(initialSortFields);
|
|
955
|
+
}
|
|
956
|
+
}, [isOpen, initialSortFields]);
|
|
957
|
+
const handleAddField = (fieldValue) => {
|
|
958
|
+
if (sortFields.some((sf) => sf.field === fieldValue)) {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
const newField = {
|
|
962
|
+
field: fieldValue,
|
|
963
|
+
direction: "asc"
|
|
964
|
+
};
|
|
965
|
+
setSortFields([...sortFields, newField]);
|
|
966
|
+
setIsComboboxOpen(false);
|
|
967
|
+
};
|
|
968
|
+
const handleDeleteField = (fieldValue) => {
|
|
969
|
+
setSortFields(sortFields.filter((sf) => sf.field !== fieldValue));
|
|
970
|
+
};
|
|
971
|
+
const handleDirectionChange = (fieldValue, direction) => {
|
|
972
|
+
setSortFields(
|
|
973
|
+
sortFields.map(
|
|
974
|
+
(sf) => sf.field === fieldValue ? { ...sf, direction } : sf
|
|
975
|
+
)
|
|
976
|
+
);
|
|
977
|
+
};
|
|
978
|
+
const handleDragEnd = (event) => {
|
|
979
|
+
const { active, over } = event;
|
|
980
|
+
if (!over || active.id === over.id) {
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
const oldIndex = sortFields.findIndex((sf) => sf.field === active.id);
|
|
984
|
+
const newIndex = sortFields.findIndex((sf) => sf.field === over.id);
|
|
985
|
+
if (oldIndex !== -1 && newIndex !== -1) {
|
|
986
|
+
setSortFields(arrayMove(sortFields, oldIndex, newIndex));
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
const handleApply = () => {
|
|
990
|
+
onSortChange([...sortFields]);
|
|
991
|
+
setIsOpen(false);
|
|
992
|
+
};
|
|
993
|
+
const handleCancel = () => {
|
|
994
|
+
setSortFields(initialSortFields);
|
|
995
|
+
setIsOpen(false);
|
|
996
|
+
};
|
|
997
|
+
const handleClearAll = () => {
|
|
998
|
+
setSortFields([]);
|
|
999
|
+
};
|
|
1000
|
+
const availableFieldsToAdd = availableFields.filter(
|
|
1001
|
+
(af) => !sortFields.some((sf) => sf.field === af.value)
|
|
1002
|
+
);
|
|
1003
|
+
const getFieldLabel = (fieldValue) => {
|
|
1004
|
+
return availableFields.find((af) => af.value === fieldValue)?.label || fieldValue;
|
|
1005
|
+
};
|
|
1006
|
+
const hasActiveSorts = initialSortFields.length > 0;
|
|
1007
|
+
const tooltipContent = hasActiveSorts ? /* @__PURE__ */ jsxs("div", { className: "cls_sort_tooltip_content space-y-1", children: [
|
|
1008
|
+
/* @__PURE__ */ jsx("div", { className: "cls_tooltip_title text-xs font-semibold mb-1", children: "Active Sorts:" }),
|
|
1009
|
+
initialSortFields.map((sortConfig, index) => /* @__PURE__ */ jsxs("div", { className: "cls_tooltip_item text-xs", children: [
|
|
1010
|
+
index + 1,
|
|
1011
|
+
". ",
|
|
1012
|
+
getFieldLabel(sortConfig.field),
|
|
1013
|
+
" (",
|
|
1014
|
+
sortConfig.direction === "asc" ? "Asc" : "Desc",
|
|
1015
|
+
")"
|
|
1016
|
+
] }, sortConfig.field))
|
|
1017
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "cls_sort_tooltip_content text-xs", children: "No active sorts" });
|
|
1018
|
+
return /* @__PURE__ */ jsxs(Dialog, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
1019
|
+
/* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
1020
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1021
|
+
Button,
|
|
1022
|
+
{
|
|
1023
|
+
variant: "outline",
|
|
1024
|
+
size: "sm",
|
|
1025
|
+
className: "cls_sort_button",
|
|
1026
|
+
"aria-label": "Open sort dialog",
|
|
1027
|
+
children: [
|
|
1028
|
+
/* @__PURE__ */ jsx(
|
|
1029
|
+
ArrowUpDown,
|
|
1030
|
+
{
|
|
1031
|
+
className: cn(
|
|
1032
|
+
"cls_sort_icon h-4 w-4 mr-2",
|
|
1033
|
+
hasActiveSorts && "text-blue-600"
|
|
1034
|
+
)
|
|
1035
|
+
}
|
|
1036
|
+
),
|
|
1037
|
+
"Sort"
|
|
1038
|
+
]
|
|
1039
|
+
}
|
|
1040
|
+
) }) }),
|
|
1041
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: tooltipContent })
|
|
1042
|
+
] }) }),
|
|
1043
|
+
/* @__PURE__ */ jsxs(DialogContent, { className: "cls_sort_dialog_content max-w-lg", children: [
|
|
1044
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
1045
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Sort Images" }),
|
|
1046
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: "Add multiple fields to sort by and reorder them. Use the switch to toggle between ascending and descending." })
|
|
1047
|
+
] }),
|
|
1048
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_sort_dialog_body space-y-4 py-4", children: [
|
|
1049
|
+
/* @__PURE__ */ jsx("div", { className: "cls_add_field_section", children: /* @__PURE__ */ jsxs(Popover, { open: isComboboxOpen, onOpenChange: setIsComboboxOpen, children: [
|
|
1050
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1051
|
+
Button,
|
|
1052
|
+
{
|
|
1053
|
+
variant: "outline",
|
|
1054
|
+
role: "combobox",
|
|
1055
|
+
"aria-expanded": isComboboxOpen,
|
|
1056
|
+
className: "cls_add_field_combobox w-full justify-between",
|
|
1057
|
+
children: [
|
|
1058
|
+
/* @__PURE__ */ jsxs("div", { className: "cls_combobox_content flex items-center", children: [
|
|
1059
|
+
/* @__PURE__ */ jsx(Plus, { className: "cls_plus_icon h-4 w-4 mr-2" }),
|
|
1060
|
+
/* @__PURE__ */ jsx("span", { children: "Add field" })
|
|
1061
|
+
] }),
|
|
1062
|
+
/* @__PURE__ */ jsx(ChevronsUpDown, { className: "cls_chevron_icon ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
1063
|
+
]
|
|
1064
|
+
}
|
|
1065
|
+
) }),
|
|
1066
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "cls_combobox_popover w-full p-0", children: /* @__PURE__ */ jsxs(Command, { children: [
|
|
1067
|
+
/* @__PURE__ */ jsx(CommandInput, { placeholder: "Search fields...", className: "cls_command_input" }),
|
|
1068
|
+
/* @__PURE__ */ jsxs(CommandList, { children: [
|
|
1069
|
+
/* @__PURE__ */ jsx(CommandEmpty, { children: "No fields found." }),
|
|
1070
|
+
/* @__PURE__ */ jsx(CommandGroup, { children: availableFieldsToAdd.map((field) => /* @__PURE__ */ jsxs(
|
|
1071
|
+
CommandItem,
|
|
1072
|
+
{
|
|
1073
|
+
value: field.value,
|
|
1074
|
+
onSelect: () => handleAddField(field.value),
|
|
1075
|
+
className: "cls_command_item",
|
|
1076
|
+
children: [
|
|
1077
|
+
/* @__PURE__ */ jsx(
|
|
1078
|
+
Check,
|
|
1079
|
+
{
|
|
1080
|
+
className: cn(
|
|
1081
|
+
"cls_check_icon mr-2 h-4 w-4",
|
|
1082
|
+
"opacity-0"
|
|
1083
|
+
)
|
|
1084
|
+
}
|
|
1085
|
+
),
|
|
1086
|
+
field.label
|
|
1087
|
+
]
|
|
1088
|
+
},
|
|
1089
|
+
field.value
|
|
1090
|
+
)) })
|
|
1091
|
+
] })
|
|
1092
|
+
] }) })
|
|
1093
|
+
] }) }),
|
|
1094
|
+
sortFields.length > 0 ? /* @__PURE__ */ jsx("div", { className: "cls_sort_fields_list space-y-2", children: /* @__PURE__ */ jsx(
|
|
1095
|
+
DndContext,
|
|
1096
|
+
{
|
|
1097
|
+
sensors,
|
|
1098
|
+
collisionDetection: closestCenter,
|
|
1099
|
+
onDragEnd: handleDragEnd,
|
|
1100
|
+
children: /* @__PURE__ */ jsx(
|
|
1101
|
+
SortableContext,
|
|
1102
|
+
{
|
|
1103
|
+
items: sortFields.map((sf) => sf.field),
|
|
1104
|
+
strategy: verticalListSortingStrategy,
|
|
1105
|
+
children: sortFields.map((sortConfig) => /* @__PURE__ */ jsx(
|
|
1106
|
+
SortableSortFieldItem,
|
|
1107
|
+
{
|
|
1108
|
+
sortConfig,
|
|
1109
|
+
fieldLabel: getFieldLabel(sortConfig.field),
|
|
1110
|
+
onDirectionChange: (direction) => handleDirectionChange(sortConfig.field, direction),
|
|
1111
|
+
onDelete: () => handleDeleteField(sortConfig.field)
|
|
1112
|
+
},
|
|
1113
|
+
sortConfig.field
|
|
1114
|
+
))
|
|
1115
|
+
}
|
|
1116
|
+
)
|
|
1117
|
+
}
|
|
1118
|
+
) }) : /* @__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.' })
|
|
1119
|
+
] }),
|
|
1120
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
1121
|
+
sortFields.length > 0 && /* @__PURE__ */ jsxs(
|
|
1122
|
+
Button,
|
|
1123
|
+
{
|
|
1124
|
+
variant: "outline",
|
|
1125
|
+
onClick: handleClearAll,
|
|
1126
|
+
className: "cls_clear_all_btn",
|
|
1127
|
+
children: [
|
|
1128
|
+
/* @__PURE__ */ jsx(Trash2, { className: "cls_clear_all_icon h-4 w-4 mr-2" }),
|
|
1129
|
+
"Clear All"
|
|
1130
|
+
]
|
|
1131
|
+
}
|
|
1132
|
+
),
|
|
799
1133
|
/* @__PURE__ */ jsx(
|
|
800
1134
|
Button,
|
|
801
1135
|
{
|
|
@@ -818,6 +1152,6 @@ function MultiFilterDialog({
|
|
|
818
1152
|
] });
|
|
819
1153
|
}
|
|
820
1154
|
|
|
821
|
-
export { ExampleComponent, MultiFilterDialog };
|
|
1155
|
+
export { ExampleComponent, MultiFilterDialog, MultiSortDialog };
|
|
822
1156
|
//# sourceMappingURL=index.js.map
|
|
823
1157
|
//# sourceMappingURL=index.js.map
|