@wordrhyme/auto-crud 1.1.5 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +445 -280
- package/dist/index.d.cts +55 -9
- package/dist/index.d.ts +71 -25
- package/dist/index.js +445 -280
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -59,8 +59,6 @@ let __pixpilot_formily_shadcn = require("@pixpilot/formily-shadcn");
|
|
|
59
59
|
__pixpilot_formily_shadcn = __toESM(__pixpilot_formily_shadcn);
|
|
60
60
|
let __formily_react = require("@formily/react");
|
|
61
61
|
__formily_react = __toESM(__formily_react);
|
|
62
|
-
let __pixpilot_shadcn_ui = require("@pixpilot/shadcn-ui");
|
|
63
|
-
__pixpilot_shadcn_ui = __toESM(__pixpilot_shadcn_ui);
|
|
64
62
|
let sonner = require("sonner");
|
|
65
63
|
sonner = __toESM(sonner);
|
|
66
64
|
|
|
@@ -1459,6 +1457,7 @@ function DataTableFilterList({ table, debounceMs = DEBOUNCE_MS$2, throttleMs = T
|
|
|
1459
1457
|
const descriptionId = react.useId();
|
|
1460
1458
|
const [open, setOpen] = react.useState(false);
|
|
1461
1459
|
const addButtonRef = react.useRef(null);
|
|
1460
|
+
const columnDefs = table.options.columns;
|
|
1462
1461
|
const columns = react.useMemo(() => {
|
|
1463
1462
|
return table.getAllColumns().filter((column) => {
|
|
1464
1463
|
if (!column.getCanFilter()) return false;
|
|
@@ -1466,7 +1465,7 @@ function DataTableFilterList({ table, debounceMs = DEBOUNCE_MS$2, throttleMs = T
|
|
|
1466
1465
|
if (modes && !modes.includes("advanced")) return false;
|
|
1467
1466
|
return true;
|
|
1468
1467
|
});
|
|
1469
|
-
}, [table]);
|
|
1468
|
+
}, [table, columnDefs]);
|
|
1470
1469
|
const [filters, setFilters] = useReadableFilters(columns, { debounceMs });
|
|
1471
1470
|
const debouncedSetFilters = useDebouncedCallback(setFilters, debounceMs);
|
|
1472
1471
|
const [joinOperator, setJoinOperator] = useQueryState(table.options.meta?.queryKeys?.joinOperator ?? "", parseAsStringEnum(["and", "or"]).withDefault("and"));
|
|
@@ -1944,7 +1943,7 @@ const DEBOUNCE_MS$1 = 300;
|
|
|
1944
1943
|
const THROTTLE_MS$1 = 50;
|
|
1945
1944
|
const FILTER_SHORTCUT_KEY = "f";
|
|
1946
1945
|
const REMOVE_FILTER_SHORTCUTS = ["backspace", "delete"];
|
|
1947
|
-
function getOptionCommandValue
|
|
1946
|
+
function getOptionCommandValue(option) {
|
|
1948
1947
|
return [
|
|
1949
1948
|
option.value,
|
|
1950
1949
|
option.label,
|
|
@@ -1953,6 +1952,7 @@ function getOptionCommandValue$2(option) {
|
|
|
1953
1952
|
}
|
|
1954
1953
|
function DataTableFilterMenu({ table, debounceMs = DEBOUNCE_MS$1, throttleMs = THROTTLE_MS$1, shallow = true, disabled,...props }) {
|
|
1955
1954
|
const id = react.useId();
|
|
1955
|
+
const columnDefs = table.options.columns;
|
|
1956
1956
|
const columns = react.useMemo(() => {
|
|
1957
1957
|
return table.getAllColumns().filter((column) => {
|
|
1958
1958
|
if (!column.columnDef.enableColumnFilter) return false;
|
|
@@ -1960,7 +1960,7 @@ function DataTableFilterMenu({ table, debounceMs = DEBOUNCE_MS$1, throttleMs = T
|
|
|
1960
1960
|
if (modes && !modes.includes("command")) return false;
|
|
1961
1961
|
return true;
|
|
1962
1962
|
});
|
|
1963
|
-
}, [table]);
|
|
1963
|
+
}, [table, columnDefs]);
|
|
1964
1964
|
const [open, setOpen] = react.useState(false);
|
|
1965
1965
|
const [selectedColumn, setSelectedColumn] = react.useState(null);
|
|
1966
1966
|
const [inputValue, setInputValue] = react.useState("");
|
|
@@ -2229,7 +2229,7 @@ function FilterValueSelector({ column, value, onSelect }) {
|
|
|
2229
2229
|
})] });
|
|
2230
2230
|
case "select":
|
|
2231
2231
|
case "multiSelect": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandGroup, { children: column.columnDef.meta?.options?.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandItem, {
|
|
2232
|
-
value: getOptionCommandValue
|
|
2232
|
+
value: getOptionCommandValue(option),
|
|
2233
2233
|
onSelect: () => onSelect(option.value),
|
|
2234
2234
|
children: [
|
|
2235
2235
|
option.icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(option.icon, {}),
|
|
@@ -2356,7 +2356,7 @@ function onFilterInputRender({ filter, column, inputId, onFilterUpdate, showValu
|
|
|
2356
2356
|
align: "start",
|
|
2357
2357
|
className: "w-48 p-0",
|
|
2358
2358
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Command, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandInput, { placeholder: "Search options..." }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandList, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandEmpty, { children: "No options found." }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandGroup, { children: options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandItem, {
|
|
2359
|
-
value: getOptionCommandValue
|
|
2359
|
+
value: getOptionCommandValue(option),
|
|
2360
2360
|
onSelect: () => {
|
|
2361
2361
|
const value = filter.variant === "multiSelect" ? selectedValues.includes(option.value) ? selectedValues.filter((v) => v !== option.value) : [...selectedValues, option.value] : option.value;
|
|
2362
2362
|
onFilterUpdate(filter.filterId, { value });
|
|
@@ -2713,9 +2713,209 @@ function DataTableViewOptions({ table, disabled,...props }) {
|
|
|
2713
2713
|
})] });
|
|
2714
2714
|
}
|
|
2715
2715
|
|
|
2716
|
+
//#endregion
|
|
2717
|
+
//#region src/components/ui/multi-combobox.tsx
|
|
2718
|
+
const DEFAULT_OPTIONS = [];
|
|
2719
|
+
const SCROLLABLE_COMMAND_GROUP_STYLE = {
|
|
2720
|
+
maxHeight: "300px",
|
|
2721
|
+
overscrollBehavior: "contain",
|
|
2722
|
+
overflowX: "hidden",
|
|
2723
|
+
overflowY: "auto"
|
|
2724
|
+
};
|
|
2725
|
+
function getWheelDeltaY(event) {
|
|
2726
|
+
if (event.deltaMode === 1) return event.deltaY * 16;
|
|
2727
|
+
if (event.deltaMode === 2) return event.deltaY * event.currentTarget.clientHeight;
|
|
2728
|
+
return event.deltaY;
|
|
2729
|
+
}
|
|
2730
|
+
function handleScrollableCommandGroupWheel(event) {
|
|
2731
|
+
const target = event.currentTarget;
|
|
2732
|
+
if (target.scrollHeight <= target.clientHeight) return;
|
|
2733
|
+
const maxScrollTop = target.scrollHeight - target.clientHeight;
|
|
2734
|
+
const nextScrollTop = Math.max(0, Math.min(target.scrollTop + getWheelDeltaY(event), maxScrollTop));
|
|
2735
|
+
if (nextScrollTop === target.scrollTop) return;
|
|
2736
|
+
event.preventDefault();
|
|
2737
|
+
event.stopPropagation();
|
|
2738
|
+
target.scrollTop = nextScrollTop;
|
|
2739
|
+
}
|
|
2740
|
+
function collectSearchText(...parts) {
|
|
2741
|
+
const texts = [];
|
|
2742
|
+
for (const part of parts) {
|
|
2743
|
+
if (!part) continue;
|
|
2744
|
+
if (Array.isArray(part)) texts.push(...part.map(String));
|
|
2745
|
+
else if (typeof part === "object") texts.push(...Object.values(part).filter(Boolean).map(String));
|
|
2746
|
+
else texts.push(String(part));
|
|
2747
|
+
}
|
|
2748
|
+
return texts.join(" ");
|
|
2749
|
+
}
|
|
2750
|
+
function getOptionKeywords(option) {
|
|
2751
|
+
return collectSearchText(typeof option.label === "string" || typeof option.label === "number" ? option.label : void 0, option.searchText, option.keywords).split(/\s+/).filter(Boolean);
|
|
2752
|
+
}
|
|
2753
|
+
function getOptionText(option) {
|
|
2754
|
+
if (typeof option.label === "string" || typeof option.label === "number") return String(option.label);
|
|
2755
|
+
return option.value;
|
|
2756
|
+
}
|
|
2757
|
+
function createNextValue(currentValue, optionValue, isSelected, selectionMode) {
|
|
2758
|
+
if (selectionMode === "single") return isSelected ? [] : [optionValue];
|
|
2759
|
+
return isSelected ? currentValue.filter((value) => value !== optionValue) : [...currentValue, optionValue];
|
|
2760
|
+
}
|
|
2761
|
+
function DefaultMultiComboboxTrigger({ open, selectedOptions, selectedValues, clearSelection, disabled, readOnly, placeholder, selectedText, className,...buttonProps }) {
|
|
2762
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Button, {
|
|
2763
|
+
...buttonProps,
|
|
2764
|
+
type: "button",
|
|
2765
|
+
variant: "outline",
|
|
2766
|
+
role: "combobox",
|
|
2767
|
+
"aria-expanded": open,
|
|
2768
|
+
disabled,
|
|
2769
|
+
className: (0, __pixpilot_shadcn.cn)("w-full justify-between", className),
|
|
2770
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2771
|
+
className: "flex min-w-0 flex-1 items-center gap-1 overflow-hidden",
|
|
2772
|
+
children: selectedValues.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2773
|
+
className: "truncate text-muted-foreground",
|
|
2774
|
+
children: placeholder
|
|
2775
|
+
}) : selectedOptions.length <= 2 ? selectedOptions.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
2776
|
+
variant: "secondary",
|
|
2777
|
+
className: "max-w-[8rem] rounded-sm px-1 font-normal",
|
|
2778
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2779
|
+
className: "truncate",
|
|
2780
|
+
children: option.label
|
|
2781
|
+
})
|
|
2782
|
+
}, option.value)) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Badge, {
|
|
2783
|
+
variant: "secondary",
|
|
2784
|
+
className: "rounded-sm px-1 font-normal",
|
|
2785
|
+
children: [
|
|
2786
|
+
selectedValues.length,
|
|
2787
|
+
" ",
|
|
2788
|
+
selectedText
|
|
2789
|
+
]
|
|
2790
|
+
})
|
|
2791
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2792
|
+
className: "ml-2 flex shrink-0 items-center gap-1",
|
|
2793
|
+
children: [selectedValues.length > 0 && !readOnly && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2794
|
+
role: "button",
|
|
2795
|
+
"aria-label": "Clear selection",
|
|
2796
|
+
tabIndex: 0,
|
|
2797
|
+
className: "rounded-sm px-1 text-muted-foreground opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2798
|
+
onClick: clearSelection,
|
|
2799
|
+
onKeyDown: (event) => {
|
|
2800
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
2801
|
+
event.preventDefault();
|
|
2802
|
+
clearSelection(event);
|
|
2803
|
+
}
|
|
2804
|
+
},
|
|
2805
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "size-3" })
|
|
2806
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronsUpDown, { className: "h-4 w-4 opacity-50" })]
|
|
2807
|
+
})]
|
|
2808
|
+
});
|
|
2809
|
+
}
|
|
2810
|
+
const MultiCombobox = ({ value, defaultValue, onChange, options = DEFAULT_OPTIONS, placeholder = "Select options...", searchPlaceholder = "Search...", emptyText = "No options found.", clearText = "Clear selection", selectedText = "selected", selectionMode = "multiple", disabled, readOnly, className, contentClassName, triggerClassName, matchTriggerWidth = true, renderTrigger, filter,...commandProps }) => {
|
|
2811
|
+
const [open, setOpen] = react.useState(false);
|
|
2812
|
+
const [internalValue, setInternalValue] = react.useState(defaultValue ?? []);
|
|
2813
|
+
const selectedValues = value ?? internalValue;
|
|
2814
|
+
const selectedValueSet = react.useMemo(() => new Set(selectedValues), [selectedValues]);
|
|
2815
|
+
const selectedOptions = react.useMemo(() => options.filter((option) => selectedValueSet.has(option.value)), [options, selectedValueSet]);
|
|
2816
|
+
const commitChange = react.useCallback((nextValue) => {
|
|
2817
|
+
if (value === void 0) setInternalValue(nextValue);
|
|
2818
|
+
onChange?.(nextValue);
|
|
2819
|
+
}, [onChange, value]);
|
|
2820
|
+
const clearSelection = react.useCallback((event) => {
|
|
2821
|
+
event?.preventDefault();
|
|
2822
|
+
event?.stopPropagation();
|
|
2823
|
+
if (readOnly) return;
|
|
2824
|
+
commitChange([]);
|
|
2825
|
+
}, [commitChange, readOnly]);
|
|
2826
|
+
const onItemSelect = react.useCallback((option) => {
|
|
2827
|
+
if (option.disabled || readOnly) return;
|
|
2828
|
+
const isSelected = selectedValueSet.has(option.value);
|
|
2829
|
+
commitChange(createNextValue(selectedValues, option.value, isSelected, selectionMode));
|
|
2830
|
+
if (selectionMode === "single") setOpen(false);
|
|
2831
|
+
}, [
|
|
2832
|
+
commitChange,
|
|
2833
|
+
readOnly,
|
|
2834
|
+
selectedValues,
|
|
2835
|
+
selectedValueSet,
|
|
2836
|
+
selectionMode
|
|
2837
|
+
]);
|
|
2838
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Popover, {
|
|
2839
|
+
open,
|
|
2840
|
+
onOpenChange: setOpen,
|
|
2841
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.PopoverTrigger, {
|
|
2842
|
+
asChild: true,
|
|
2843
|
+
children: renderTrigger ? renderTrigger({
|
|
2844
|
+
open,
|
|
2845
|
+
selectedOptions,
|
|
2846
|
+
selectedValues,
|
|
2847
|
+
clearSelection,
|
|
2848
|
+
disabled,
|
|
2849
|
+
readOnly
|
|
2850
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultMultiComboboxTrigger, {
|
|
2851
|
+
open,
|
|
2852
|
+
selectedOptions,
|
|
2853
|
+
selectedValues,
|
|
2854
|
+
clearSelection,
|
|
2855
|
+
disabled,
|
|
2856
|
+
readOnly,
|
|
2857
|
+
placeholder,
|
|
2858
|
+
selectedText,
|
|
2859
|
+
className: triggerClassName
|
|
2860
|
+
})
|
|
2861
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.PopoverContent, {
|
|
2862
|
+
className: (0, __pixpilot_shadcn.cn)("w-full p-0", contentClassName),
|
|
2863
|
+
style: matchTriggerWidth ? { width: "var(--radix-popover-trigger-width)" } : void 0,
|
|
2864
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Command, {
|
|
2865
|
+
className,
|
|
2866
|
+
filter,
|
|
2867
|
+
...commandProps,
|
|
2868
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandInput, { placeholder: searchPlaceholder }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandList, {
|
|
2869
|
+
className: "max-h-full",
|
|
2870
|
+
children: [
|
|
2871
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandEmpty, { children: emptyText }),
|
|
2872
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandGroup, {
|
|
2873
|
+
className: "max-h-[300px] scroll-py-1 overflow-y-auto overflow-x-hidden",
|
|
2874
|
+
onWheelCapture: handleScrollableCommandGroupWheel,
|
|
2875
|
+
style: SCROLLABLE_COMMAND_GROUP_STYLE,
|
|
2876
|
+
children: options.map((option) => {
|
|
2877
|
+
const isSelected = selectedValueSet.has(option.value);
|
|
2878
|
+
const Icon = option.icon;
|
|
2879
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandItem, {
|
|
2880
|
+
value: option.value,
|
|
2881
|
+
keywords: getOptionKeywords(option),
|
|
2882
|
+
disabled: option.disabled,
|
|
2883
|
+
onSelect: () => onItemSelect(option),
|
|
2884
|
+
children: [
|
|
2885
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2886
|
+
className: (0, __pixpilot_shadcn.cn)("flex size-4 items-center justify-center rounded-sm border border-primary", isSelected ? "bg-primary text-primary-foreground" : "opacity-50 [&_svg]:invisible"),
|
|
2887
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, {})
|
|
2888
|
+
}),
|
|
2889
|
+
Icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "size-4" }),
|
|
2890
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2891
|
+
className: "truncate",
|
|
2892
|
+
children: getOptionText(option)
|
|
2893
|
+
}),
|
|
2894
|
+
option.count !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2895
|
+
className: "ml-auto font-mono text-xs",
|
|
2896
|
+
children: option.count
|
|
2897
|
+
})
|
|
2898
|
+
]
|
|
2899
|
+
}, option.value);
|
|
2900
|
+
})
|
|
2901
|
+
}),
|
|
2902
|
+
selectedValues.length > 0 && !readOnly && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandSeparator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandGroup, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandItem, {
|
|
2903
|
+
onSelect: () => commitChange([]),
|
|
2904
|
+
className: "justify-center text-center",
|
|
2905
|
+
children: clearText
|
|
2906
|
+
}) })] })
|
|
2907
|
+
]
|
|
2908
|
+
})]
|
|
2909
|
+
})
|
|
2910
|
+
})]
|
|
2911
|
+
});
|
|
2912
|
+
};
|
|
2913
|
+
MultiCombobox.displayName = "MultiCombobox";
|
|
2914
|
+
|
|
2716
2915
|
//#endregion
|
|
2717
2916
|
//#region src/components/auto-crud/auto-table-simple-filters.tsx
|
|
2718
2917
|
function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilters, onFiltersChange, leading }) {
|
|
2918
|
+
const columnDefs = table.options.columns;
|
|
2719
2919
|
const columns = react.useMemo(() => table.getAllColumns().filter((col) => col.getCanFilter()).sort((a, b) => {
|
|
2720
2920
|
const readOrder = (column) => {
|
|
2721
2921
|
const metaIndex = column.columnDef.meta?.index;
|
|
@@ -2725,7 +2925,7 @@ function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilte
|
|
|
2725
2925
|
const orderDiff = readOrder(a) - readOrder(b);
|
|
2726
2926
|
if (orderDiff !== 0) return orderDiff;
|
|
2727
2927
|
return a.getIndex() - b.getIndex();
|
|
2728
|
-
}), [table]);
|
|
2928
|
+
}), [table, columnDefs]);
|
|
2729
2929
|
const queryStateOptions = table.options.meta?.queryStateOptions;
|
|
2730
2930
|
const [queryFilters, setQueryFilters] = useReadableFilters(columns, {
|
|
2731
2931
|
...queryStateOptions,
|
|
@@ -2959,120 +3159,60 @@ function AutoTableSimpleFilters({ table, shallow = false, filters: externalFilte
|
|
|
2959
3159
|
]
|
|
2960
3160
|
});
|
|
2961
3161
|
}
|
|
2962
|
-
function getOptionCommandValue$1(option) {
|
|
2963
|
-
return [
|
|
2964
|
-
option.value,
|
|
2965
|
-
option.label,
|
|
2966
|
-
option.searchText
|
|
2967
|
-
].filter(Boolean).join(" ");
|
|
2968
|
-
}
|
|
2969
3162
|
function SimpleFacetedFilter({ title, options, multiple, value, onChange }) {
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
onKeyDown: (e) => {
|
|
3003
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
3004
|
-
e.preventDefault();
|
|
3005
|
-
onReset(e);
|
|
3006
|
-
}
|
|
3007
|
-
},
|
|
3008
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.XCircle, {})
|
|
3009
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.PlusCircle, {}),
|
|
3010
|
-
title,
|
|
3011
|
-
selectedValues.size > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3012
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Separator, {
|
|
3013
|
-
orientation: "vertical",
|
|
3014
|
-
className: "mx-0.5 h-4"
|
|
3015
|
-
}),
|
|
3016
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
3017
|
-
variant: "secondary",
|
|
3018
|
-
className: "rounded-sm px-1 font-normal lg:hidden",
|
|
3019
|
-
children: selectedValues.size
|
|
3020
|
-
}),
|
|
3021
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3022
|
-
className: "hidden items-center gap-1 lg:flex",
|
|
3023
|
-
children: selectedValues.size > 2 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Badge, {
|
|
3024
|
-
variant: "secondary",
|
|
3025
|
-
className: "rounded-sm px-1 font-normal",
|
|
3026
|
-
children: [selectedValues.size, " selected"]
|
|
3027
|
-
}) : options.filter((o) => selectedValues.has(o.value)).map((o) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
3028
|
-
variant: "secondary",
|
|
3029
|
-
className: "rounded-sm px-1 font-normal",
|
|
3030
|
-
children: o.label
|
|
3031
|
-
}, o.value))
|
|
3032
|
-
})
|
|
3033
|
-
] })
|
|
3034
|
-
]
|
|
3035
|
-
})
|
|
3036
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.PopoverContent, {
|
|
3037
|
-
className: "w-50 p-0",
|
|
3038
|
-
align: "start",
|
|
3039
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Command, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandInput, { placeholder: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandList, {
|
|
3040
|
-
className: "max-h-full",
|
|
3041
|
-
children: [
|
|
3042
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandEmpty, { children: "No results found." }),
|
|
3043
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandGroup, {
|
|
3044
|
-
className: "max-h-[300px] overflow-y-auto",
|
|
3045
|
-
children: options.map((option) => {
|
|
3046
|
-
const isSelected = selectedValues.has(option.value);
|
|
3047
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandItem, {
|
|
3048
|
-
value: getOptionCommandValue$1(option),
|
|
3049
|
-
onSelect: () => onItemSelect(option, isSelected),
|
|
3050
|
-
children: [
|
|
3051
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3052
|
-
className: cn("flex size-4 items-center justify-center rounded-sm border border-primary", isSelected ? "bg-primary" : "opacity-50 [&_svg]:invisible"),
|
|
3053
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, {})
|
|
3054
|
-
}),
|
|
3055
|
-
option.icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(option.icon, {}),
|
|
3056
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3057
|
-
className: "truncate",
|
|
3058
|
-
children: option.label
|
|
3059
|
-
}),
|
|
3060
|
-
option.count && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3061
|
-
className: "ml-auto font-mono text-xs",
|
|
3062
|
-
children: option.count
|
|
3063
|
-
})
|
|
3064
|
-
]
|
|
3065
|
-
}, option.value);
|
|
3066
|
-
})
|
|
3163
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiCombobox, {
|
|
3164
|
+
value,
|
|
3165
|
+
onChange,
|
|
3166
|
+
options,
|
|
3167
|
+
selectionMode: multiple ? "multiple" : "single",
|
|
3168
|
+
searchPlaceholder: title,
|
|
3169
|
+
contentClassName: "w-50",
|
|
3170
|
+
matchTriggerWidth: false,
|
|
3171
|
+
clearText: "Clear filters",
|
|
3172
|
+
renderTrigger: ({ selectedOptions, selectedValues, clearSelection }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Button, {
|
|
3173
|
+
variant: "outline",
|
|
3174
|
+
size: "sm",
|
|
3175
|
+
className: "border-dashed font-normal",
|
|
3176
|
+
children: [
|
|
3177
|
+
selectedValues.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3178
|
+
role: "button",
|
|
3179
|
+
tabIndex: 0,
|
|
3180
|
+
className: "rounded-sm opacity-70 hover:opacity-100",
|
|
3181
|
+
onClick: clearSelection,
|
|
3182
|
+
onKeyDown: (e) => {
|
|
3183
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
3184
|
+
e.preventDefault();
|
|
3185
|
+
clearSelection(e);
|
|
3186
|
+
}
|
|
3187
|
+
},
|
|
3188
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.XCircle, {})
|
|
3189
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.PlusCircle, {}),
|
|
3190
|
+
title,
|
|
3191
|
+
selectedValues.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3192
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Separator, {
|
|
3193
|
+
orientation: "vertical",
|
|
3194
|
+
className: "mx-0.5 h-4"
|
|
3067
3195
|
}),
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
className: "
|
|
3071
|
-
children:
|
|
3072
|
-
})
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3196
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
3197
|
+
variant: "secondary",
|
|
3198
|
+
className: "rounded-sm px-1 font-normal lg:hidden",
|
|
3199
|
+
children: selectedValues.length
|
|
3200
|
+
}),
|
|
3201
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3202
|
+
className: "hidden items-center gap-1 lg:flex",
|
|
3203
|
+
children: selectedValues.length > 2 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Badge, {
|
|
3204
|
+
variant: "secondary",
|
|
3205
|
+
className: "rounded-sm px-1 font-normal",
|
|
3206
|
+
children: [selectedValues.length, " selected"]
|
|
3207
|
+
}) : selectedOptions.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
3208
|
+
variant: "secondary",
|
|
3209
|
+
className: "rounded-sm px-1 font-normal",
|
|
3210
|
+
children: option.label
|
|
3211
|
+
}, option.value))
|
|
3212
|
+
})
|
|
3213
|
+
] })
|
|
3214
|
+
]
|
|
3215
|
+
})
|
|
3076
3216
|
});
|
|
3077
3217
|
}
|
|
3078
3218
|
function SimpleSliderFilter({ title, range, unit, value, onChange }) {
|
|
@@ -3983,11 +4123,32 @@ function parseZodField(schema) {
|
|
|
3983
4123
|
/**
|
|
3984
4124
|
* 渲染单元格内容
|
|
3985
4125
|
*/
|
|
3986
|
-
function renderCell(value, type) {
|
|
4126
|
+
function renderCell(value, type, options) {
|
|
3987
4127
|
if (value === null || value === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3988
4128
|
className: "text-muted-foreground",
|
|
3989
4129
|
children: "-"
|
|
3990
4130
|
});
|
|
4131
|
+
const formatOptionValue = (optionValue) => {
|
|
4132
|
+
const stringValue = String(optionValue);
|
|
4133
|
+
return options?.find((option) => option.value === stringValue)?.label ?? stringValue;
|
|
4134
|
+
};
|
|
4135
|
+
if (options && options.length > 0) {
|
|
4136
|
+
if (Array.isArray(value)) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4137
|
+
className: "flex gap-1 flex-wrap",
|
|
4138
|
+
children: [value.slice(0, 3).map((v, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
4139
|
+
variant: "secondary",
|
|
4140
|
+
children: formatOptionValue(v)
|
|
4141
|
+
}, i)), value.length > 3 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Badge, {
|
|
4142
|
+
variant: "outline",
|
|
4143
|
+
children: ["+", value.length - 3]
|
|
4144
|
+
})]
|
|
4145
|
+
});
|
|
4146
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
4147
|
+
variant: "outline",
|
|
4148
|
+
className: "capitalize",
|
|
4149
|
+
children: formatOptionValue(value)
|
|
4150
|
+
});
|
|
4151
|
+
}
|
|
3991
4152
|
switch (type) {
|
|
3992
4153
|
case "boolean": return value ? "✓" : "✗";
|
|
3993
4154
|
case "date": return formatDate(value);
|
|
@@ -4060,7 +4221,7 @@ function createTableSchema(schema, options) {
|
|
|
4060
4221
|
column,
|
|
4061
4222
|
label
|
|
4062
4223
|
}),
|
|
4063
|
-
cell: ({ row }) => renderCell(row.getValue(key), parsed.type),
|
|
4224
|
+
cell: ({ row }) => renderCell(row.getValue(key), parsed.type, meta.options),
|
|
4064
4225
|
enableColumnFilter: true,
|
|
4065
4226
|
enableSorting: true,
|
|
4066
4227
|
meta,
|
|
@@ -4757,25 +4918,27 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
|
|
|
4757
4918
|
clearOnDefault: true
|
|
4758
4919
|
});
|
|
4759
4920
|
const searchConfig = search && typeof search === "object" ? search : {};
|
|
4921
|
+
const enableAdvancedFilter = true;
|
|
4922
|
+
const columns = (0, react.useMemo)(() => {
|
|
4923
|
+
const dataColumns = createTableSchema(schema, {
|
|
4924
|
+
overrides,
|
|
4925
|
+
exclude
|
|
4926
|
+
});
|
|
4927
|
+
const result = enableRowSelection ? [createSelectColumn(), ...dataColumns] : dataColumns;
|
|
4928
|
+
if (actions) result.push(createActionsColumn(actions));
|
|
4929
|
+
return result;
|
|
4930
|
+
}, [
|
|
4931
|
+
schema,
|
|
4932
|
+
overrides,
|
|
4933
|
+
enableRowSelection,
|
|
4934
|
+
exclude,
|
|
4935
|
+
actions
|
|
4936
|
+
]);
|
|
4760
4937
|
const { table, shallow, debounceMs, throttleMs } = useDataTable({
|
|
4761
4938
|
data,
|
|
4762
|
-
columns
|
|
4763
|
-
const dataColumns = createTableSchema(schema, {
|
|
4764
|
-
overrides,
|
|
4765
|
-
exclude
|
|
4766
|
-
});
|
|
4767
|
-
const result = enableRowSelection ? [createSelectColumn(), ...dataColumns] : dataColumns;
|
|
4768
|
-
if (actions) result.push(createActionsColumn(actions));
|
|
4769
|
-
return result;
|
|
4770
|
-
}, [
|
|
4771
|
-
schema,
|
|
4772
|
-
overrides,
|
|
4773
|
-
enableRowSelection,
|
|
4774
|
-
exclude,
|
|
4775
|
-
actions
|
|
4776
|
-
]),
|
|
4939
|
+
columns,
|
|
4777
4940
|
pageCount,
|
|
4778
|
-
enableAdvancedFilter
|
|
4941
|
+
enableAdvancedFilter,
|
|
4779
4942
|
initialState: (0, react.useMemo)(() => ({
|
|
4780
4943
|
sorting: initialSorting,
|
|
4781
4944
|
columnPinning: pinnedColumns ?? {
|
|
@@ -4861,6 +5024,7 @@ function AutoTable({ schema, data, pageCount = 1, overrides, enableRowSelection
|
|
|
4861
5024
|
}, [
|
|
4862
5025
|
currentMode,
|
|
4863
5026
|
table,
|
|
5027
|
+
columns,
|
|
4864
5028
|
shallow,
|
|
4865
5029
|
searchInput,
|
|
4866
5030
|
debounceMs,
|
|
@@ -5076,37 +5240,31 @@ const FormilySwitch = (0, __formily_react.connect)(__pixpilot_shadcn.Switch, (0,
|
|
|
5076
5240
|
onInput: "onCheckedChange"
|
|
5077
5241
|
}));
|
|
5078
5242
|
const FormilyCombobox = (0, __formily_react.connect)(AutoCrudCombobox, (0, __formily_react.mapProps)({ dataSource: "options" }));
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
return
|
|
5243
|
+
const FormilyMultiCombobox = (0, __formily_react.connect)(AutoCrudMultiCombobox, (0, __formily_react.mapProps)({
|
|
5244
|
+
dataSource: "options",
|
|
5245
|
+
onInput: "onChange"
|
|
5246
|
+
}, (props, field) => {
|
|
5247
|
+
const fieldValue = field.value;
|
|
5248
|
+
return {
|
|
5249
|
+
...props,
|
|
5250
|
+
value: Array.isArray(fieldValue) ? fieldValue.map(String) : []
|
|
5251
|
+
};
|
|
5252
|
+
}));
|
|
5253
|
+
function AutoCrudCombobox({ options = [], className, value, onChange,...props }) {
|
|
5254
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiCombobox, {
|
|
5085
5255
|
...props,
|
|
5256
|
+
value: value ? [value] : [],
|
|
5086
5257
|
options,
|
|
5087
|
-
|
|
5258
|
+
selectionMode: "single",
|
|
5259
|
+
onChange: (nextValues) => onChange?.(nextValues[0] ?? ""),
|
|
5088
5260
|
className: (0, __pixpilot_shadcn.cn)(COMBOBOX_LIST_CLASS, className)
|
|
5089
5261
|
});
|
|
5090
5262
|
}
|
|
5091
|
-
function
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
const searchText = collectSearchText(searchTextByValue.get(value), keywords).toLocaleLowerCase();
|
|
5097
|
-
if (searchText === query) return 2;
|
|
5098
|
-
return searchText.includes(query) ? 1 : 0;
|
|
5099
|
-
};
|
|
5100
|
-
}
|
|
5101
|
-
function collectSearchText(...parts) {
|
|
5102
|
-
const texts = [];
|
|
5103
|
-
for (const part of parts) {
|
|
5104
|
-
if (!part) continue;
|
|
5105
|
-
if (Array.isArray(part)) texts.push(...part.map(String));
|
|
5106
|
-
else if (typeof part === "object") texts.push(...Object.values(part).filter(Boolean).map(String));
|
|
5107
|
-
else texts.push(String(part));
|
|
5108
|
-
}
|
|
5109
|
-
return texts.join(" ");
|
|
5263
|
+
function AutoCrudMultiCombobox({ options = [],...props }) {
|
|
5264
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiCombobox, {
|
|
5265
|
+
...props,
|
|
5266
|
+
options
|
|
5267
|
+
});
|
|
5110
5268
|
}
|
|
5111
5269
|
function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides, mode = "create", loading = false, gridColumns = 1, labelAlign = "top", labelWidth, showSubmitButton = true }, ref) {
|
|
5112
5270
|
const form = (0, react.useMemo)(() => (0, __formily_core.createForm)({ initialValues }), [JSON.stringify(initialValues)]);
|
|
@@ -5137,6 +5295,10 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
|
|
|
5137
5295
|
component: FormilyCombobox,
|
|
5138
5296
|
decorator: "FormItem"
|
|
5139
5297
|
},
|
|
5298
|
+
MultiCombobox: {
|
|
5299
|
+
component: FormilyMultiCombobox,
|
|
5300
|
+
decorator: "FormItem"
|
|
5301
|
+
},
|
|
5140
5302
|
Switch: {
|
|
5141
5303
|
component: FormilySwitch,
|
|
5142
5304
|
decorator: "FormItem"
|
|
@@ -5954,6 +6116,7 @@ function mergeFieldConfig(base, override) {
|
|
|
5954
6116
|
return {
|
|
5955
6117
|
...base,
|
|
5956
6118
|
...override,
|
|
6119
|
+
enum: override?.enum ?? base?.enum,
|
|
5957
6120
|
table: mergeFieldPart(base?.table, override?.table),
|
|
5958
6121
|
filter: mergeFieldPart(base?.filter, override?.filter),
|
|
5959
6122
|
form: mergeFieldPart(base?.form, override?.form)
|
|
@@ -5964,6 +6127,32 @@ function mergeFields(base, override) {
|
|
|
5964
6127
|
const keys = new Set([...Object.keys(base ?? {}), ...Object.keys(override ?? {})]);
|
|
5965
6128
|
return Object.fromEntries(Array.from(keys).map((key) => [key, mergeFieldConfig(base?.[key], override?.[key])]));
|
|
5966
6129
|
}
|
|
6130
|
+
function normalizeFieldOptions(options) {
|
|
6131
|
+
if (!options || options.length === 0) return void 0;
|
|
6132
|
+
return options.map((option) => ({
|
|
6133
|
+
...option,
|
|
6134
|
+
value: String(option.value)
|
|
6135
|
+
}));
|
|
6136
|
+
}
|
|
6137
|
+
function toTableOptions(options) {
|
|
6138
|
+
return options?.map(({ label, value, searchText, count, icon }) => ({
|
|
6139
|
+
label,
|
|
6140
|
+
value,
|
|
6141
|
+
searchText: Array.isArray(searchText) ? searchText.join(" ") : searchText,
|
|
6142
|
+
count,
|
|
6143
|
+
icon
|
|
6144
|
+
}));
|
|
6145
|
+
}
|
|
6146
|
+
function toBatchOptions(options) {
|
|
6147
|
+
return options?.map(({ label, value }) => ({
|
|
6148
|
+
label,
|
|
6149
|
+
value
|
|
6150
|
+
}));
|
|
6151
|
+
}
|
|
6152
|
+
function getOptionLabel(value, options) {
|
|
6153
|
+
const stringValue = String(value);
|
|
6154
|
+
return options?.find((option) => option.value === stringValue)?.label ?? stringValue;
|
|
6155
|
+
}
|
|
5967
6156
|
/**
|
|
5968
6157
|
* 从统一配置生成表格 overrides
|
|
5969
6158
|
* 当 filter 配置存在时,合并到 meta 中(不影响列隐藏)
|
|
@@ -5971,7 +6160,12 @@ function mergeFields(base, override) {
|
|
|
5971
6160
|
function buildTableOverrides(fields, legacyOverrides) {
|
|
5972
6161
|
const result = { ...legacyOverrides };
|
|
5973
6162
|
if (fields) for (const [key, config] of Object.entries(fields)) {
|
|
6163
|
+
const tableOptions = toTableOptions(normalizeFieldOptions(config.enum));
|
|
5974
6164
|
const tableMeta = config.table !== false && typeof config.table === "object" ? config.table.meta : void 0;
|
|
6165
|
+
const fieldEnumMeta = tableOptions ? {
|
|
6166
|
+
options: tableOptions,
|
|
6167
|
+
variant: "multiSelect"
|
|
6168
|
+
} : void 0;
|
|
5975
6169
|
let filterMeta;
|
|
5976
6170
|
if (config.filter && typeof config.filter === "object") {
|
|
5977
6171
|
if (config.filter.enabled !== false && config.filter.hidden !== true) {
|
|
@@ -5989,10 +6183,11 @@ function buildTableOverrides(fields, legacyOverrides) {
|
|
|
5989
6183
|
enableColumnFilter: false
|
|
5990
6184
|
};
|
|
5991
6185
|
}
|
|
5992
|
-
if (tableMeta || filterMeta) result[key] = {
|
|
6186
|
+
if (fieldEnumMeta || tableMeta || filterMeta) result[key] = {
|
|
5993
6187
|
...result[key],
|
|
5994
6188
|
meta: {
|
|
5995
6189
|
...result[key]?.meta ?? {},
|
|
6190
|
+
...fieldEnumMeta ?? {},
|
|
5996
6191
|
...tableMeta ?? {},
|
|
5997
6192
|
...filterMeta ?? {}
|
|
5998
6193
|
}
|
|
@@ -6030,6 +6225,7 @@ function buildFormOverrides(fields, legacyOverrides, denyFields) {
|
|
|
6030
6225
|
"x-hidden": true
|
|
6031
6226
|
};
|
|
6032
6227
|
if (fields) for (const [key, config] of Object.entries(fields)) {
|
|
6228
|
+
const fieldOptions = normalizeFieldOptions(config.enum);
|
|
6033
6229
|
if (config.label) result[key] = {
|
|
6034
6230
|
...result[key],
|
|
6035
6231
|
title: config.label
|
|
@@ -6038,6 +6234,10 @@ function buildFormOverrides(fields, legacyOverrides, denyFields) {
|
|
|
6038
6234
|
...result[key],
|
|
6039
6235
|
"x-hidden": true
|
|
6040
6236
|
};
|
|
6237
|
+
if (fieldOptions) result[key] = {
|
|
6238
|
+
...result[key],
|
|
6239
|
+
enum: fieldOptions
|
|
6240
|
+
};
|
|
6041
6241
|
if (config.form === false) result[key] = {
|
|
6042
6242
|
...result[key],
|
|
6043
6243
|
"x-hidden": true
|
|
@@ -6080,6 +6280,12 @@ function buildBatchUpdateFields(schema, batchFields, fields) {
|
|
|
6080
6280
|
}
|
|
6081
6281
|
const parsed = parseZodField(fieldSchema);
|
|
6082
6282
|
const label = fields?.[field]?.label ?? humanize(field);
|
|
6283
|
+
const batchOptions = toBatchOptions(normalizeFieldOptions(fields?.[field]?.enum));
|
|
6284
|
+
if (batchOptions) return {
|
|
6285
|
+
field,
|
|
6286
|
+
label,
|
|
6287
|
+
options: batchOptions
|
|
6288
|
+
};
|
|
6083
6289
|
if (parsed.type === "enum" && parsed.enumValues) return {
|
|
6084
6290
|
field,
|
|
6085
6291
|
label,
|
|
@@ -6099,11 +6305,28 @@ function buildBatchUpdateFields(schema, batchFields, fields) {
|
|
|
6099
6305
|
/**
|
|
6100
6306
|
* 渲染字段值
|
|
6101
6307
|
*/
|
|
6102
|
-
function renderFieldValue(value, type, booleanLocale) {
|
|
6308
|
+
function renderFieldValue(value, type, booleanLocale, options) {
|
|
6103
6309
|
if (value === null || value === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6104
6310
|
className: "text-muted-foreground",
|
|
6105
6311
|
children: "-"
|
|
6106
6312
|
});
|
|
6313
|
+
if (options && options.length > 0) {
|
|
6314
|
+
if (Array.isArray(value)) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6315
|
+
className: "flex gap-1 flex-wrap",
|
|
6316
|
+
children: [value.slice(0, 5).map((v, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
6317
|
+
variant: "secondary",
|
|
6318
|
+
children: getOptionLabel(v, options)
|
|
6319
|
+
}, i)), value.length > 5 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Badge, {
|
|
6320
|
+
variant: "outline",
|
|
6321
|
+
children: ["+", value.length - 5]
|
|
6322
|
+
})]
|
|
6323
|
+
});
|
|
6324
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
6325
|
+
variant: "outline",
|
|
6326
|
+
className: "capitalize",
|
|
6327
|
+
children: getOptionLabel(value, options)
|
|
6328
|
+
});
|
|
6329
|
+
}
|
|
6107
6330
|
switch (type) {
|
|
6108
6331
|
case "boolean": return value ? booleanLocale.true : booleanLocale.false;
|
|
6109
6332
|
case "date": return formatDate(value);
|
|
@@ -6141,6 +6364,7 @@ function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldCon
|
|
|
6141
6364
|
const parsed = parseZodField(fieldSchema);
|
|
6142
6365
|
const label = fieldConfig?.[key]?.label ?? humanize(key);
|
|
6143
6366
|
const value = data[key];
|
|
6367
|
+
const options = normalizeFieldOptions(fieldConfig?.[key]?.enum);
|
|
6144
6368
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6145
6369
|
className: "grid grid-cols-3 items-start gap-4",
|
|
6146
6370
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", {
|
|
@@ -6148,7 +6372,7 @@ function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldCon
|
|
|
6148
6372
|
children: label
|
|
6149
6373
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
|
|
6150
6374
|
className: "col-span-2 text-sm",
|
|
6151
|
-
children: renderFieldValue(value, parsed.type, locale.boolean)
|
|
6375
|
+
children: renderFieldValue(value, parsed.type, locale.boolean, options)
|
|
6152
6376
|
})]
|
|
6153
6377
|
}, key);
|
|
6154
6378
|
})
|
|
@@ -6580,122 +6804,62 @@ function DataTableAdvancedToolbar({ table, children, className,...props }) {
|
|
|
6580
6804
|
|
|
6581
6805
|
//#endregion
|
|
6582
6806
|
//#region src/components/data-table/data-table-faceted-filter.tsx
|
|
6583
|
-
function getOptionCommandValue(option) {
|
|
6584
|
-
return [
|
|
6585
|
-
option.value,
|
|
6586
|
-
option.label,
|
|
6587
|
-
option.searchText
|
|
6588
|
-
].filter(Boolean).join(" ");
|
|
6589
|
-
}
|
|
6590
6807
|
function DataTableFacetedFilter({ column, title, options, multiple }) {
|
|
6591
|
-
const [open, setOpen] = react.useState(false);
|
|
6592
6808
|
const columnFilterValue = column?.getFilterValue();
|
|
6593
|
-
const selectedValues =
|
|
6594
|
-
const
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
role: "button",
|
|
6627
|
-
"aria-label": `Clear ${title} filter`,
|
|
6628
|
-
tabIndex: 0,
|
|
6629
|
-
className: "rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
6630
|
-
onClick: onReset,
|
|
6631
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.XCircle, {})
|
|
6632
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.PlusCircle, {}),
|
|
6633
|
-
title,
|
|
6634
|
-
selectedValues?.size > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6635
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Separator, {
|
|
6636
|
-
orientation: "vertical",
|
|
6637
|
-
className: "mx-0.5 data-[orientation=vertical]:h-4"
|
|
6638
|
-
}),
|
|
6639
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
6640
|
-
variant: "secondary",
|
|
6641
|
-
className: "rounded-sm px-1 font-normal lg:hidden",
|
|
6642
|
-
children: selectedValues.size
|
|
6643
|
-
}),
|
|
6644
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6645
|
-
className: "hidden items-center gap-1 lg:flex",
|
|
6646
|
-
children: selectedValues.size > 2 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Badge, {
|
|
6647
|
-
variant: "secondary",
|
|
6648
|
-
className: "rounded-sm px-1 font-normal",
|
|
6649
|
-
children: [selectedValues.size, " selected"]
|
|
6650
|
-
}) : options.filter((option) => selectedValues.has(option.value)).map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
6651
|
-
variant: "secondary",
|
|
6652
|
-
className: "rounded-sm px-1 font-normal",
|
|
6653
|
-
children: option.label
|
|
6654
|
-
}, option.value))
|
|
6655
|
-
})
|
|
6656
|
-
] })
|
|
6657
|
-
]
|
|
6658
|
-
})
|
|
6659
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.PopoverContent, {
|
|
6660
|
-
className: "w-50 p-0",
|
|
6661
|
-
align: "start",
|
|
6662
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Command, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandInput, { placeholder: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandList, {
|
|
6663
|
-
className: "max-h-full",
|
|
6664
|
-
children: [
|
|
6665
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandEmpty, { children: "No results found." }),
|
|
6666
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.CommandGroup, {
|
|
6667
|
-
className: "max-h-[300px] scroll-py-1 overflow-y-auto overflow-x-hidden",
|
|
6668
|
-
children: options.map((option) => {
|
|
6669
|
-
const isSelected = selectedValues.has(option.value);
|
|
6670
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.CommandItem, {
|
|
6671
|
-
value: getOptionCommandValue(option),
|
|
6672
|
-
onSelect: () => onItemSelect(option, isSelected),
|
|
6673
|
-
children: [
|
|
6674
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6675
|
-
className: cn("flex size-4 items-center justify-center rounded-sm border border-primary", isSelected ? "bg-primary" : "opacity-50 [&_svg]:invisible"),
|
|
6676
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, {})
|
|
6677
|
-
}),
|
|
6678
|
-
option.icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(option.icon, {}),
|
|
6679
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6680
|
-
className: "truncate",
|
|
6681
|
-
children: option.label
|
|
6682
|
-
}),
|
|
6683
|
-
option.count && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6684
|
-
className: "ml-auto font-mono text-xs",
|
|
6685
|
-
children: option.count
|
|
6686
|
-
})
|
|
6687
|
-
]
|
|
6688
|
-
}, option.value);
|
|
6689
|
-
})
|
|
6809
|
+
const selectedValues = Array.isArray(columnFilterValue) ? columnFilterValue.filter((value) => typeof value === "string") : [];
|
|
6810
|
+
const onChange = (nextValues) => {
|
|
6811
|
+
column?.setFilterValue(nextValues.length ? nextValues : void 0);
|
|
6812
|
+
};
|
|
6813
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiCombobox, {
|
|
6814
|
+
value: selectedValues,
|
|
6815
|
+
onChange,
|
|
6816
|
+
options,
|
|
6817
|
+
selectionMode: multiple ? "multiple" : "single",
|
|
6818
|
+
searchPlaceholder: title,
|
|
6819
|
+
contentClassName: "w-50",
|
|
6820
|
+
matchTriggerWidth: false,
|
|
6821
|
+
clearText: "Clear filters",
|
|
6822
|
+
renderTrigger: ({ selectedOptions, selectedValues: selectedValues$1, clearSelection }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Button, {
|
|
6823
|
+
type: "button",
|
|
6824
|
+
variant: "outline",
|
|
6825
|
+
size: "sm",
|
|
6826
|
+
className: "border-dashed font-normal",
|
|
6827
|
+
disabled: !column,
|
|
6828
|
+
children: [
|
|
6829
|
+
selectedValues$1.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6830
|
+
role: "button",
|
|
6831
|
+
"aria-label": `Clear ${title} filter`,
|
|
6832
|
+
tabIndex: 0,
|
|
6833
|
+
className: "rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
6834
|
+
onClick: clearSelection,
|
|
6835
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.XCircle, {})
|
|
6836
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.PlusCircle, {}),
|
|
6837
|
+
title,
|
|
6838
|
+
selectedValues$1.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6839
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Separator, {
|
|
6840
|
+
orientation: "vertical",
|
|
6841
|
+
className: "mx-0.5 data-[orientation=vertical]:h-4"
|
|
6690
6842
|
}),
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
className: "
|
|
6694
|
-
children:
|
|
6695
|
-
})
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6843
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
6844
|
+
variant: "secondary",
|
|
6845
|
+
className: "rounded-sm px-1 font-normal lg:hidden",
|
|
6846
|
+
children: selectedValues$1.length
|
|
6847
|
+
}),
|
|
6848
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6849
|
+
className: "hidden items-center gap-1 lg:flex",
|
|
6850
|
+
children: selectedValues$1.length > 2 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Badge, {
|
|
6851
|
+
variant: "secondary",
|
|
6852
|
+
className: "rounded-sm px-1 font-normal",
|
|
6853
|
+
children: [selectedValues$1.length, " selected"]
|
|
6854
|
+
}) : selectedOptions.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
|
|
6855
|
+
variant: "secondary",
|
|
6856
|
+
className: "rounded-sm px-1 font-normal",
|
|
6857
|
+
children: option.label
|
|
6858
|
+
}, option.value))
|
|
6859
|
+
})
|
|
6860
|
+
] })
|
|
6861
|
+
]
|
|
6862
|
+
})
|
|
6699
6863
|
});
|
|
6700
6864
|
}
|
|
6701
6865
|
|
|
@@ -7929,6 +8093,7 @@ exports.DataTableToolbar = DataTableToolbar;
|
|
|
7929
8093
|
exports.DataTableViewOptions = DataTableViewOptions;
|
|
7930
8094
|
exports.ExportDialog = ExportDialog;
|
|
7931
8095
|
exports.ImportDialog = ImportDialog;
|
|
8096
|
+
exports.MultiCombobox = MultiCombobox;
|
|
7932
8097
|
exports.SchemaAdapter = SchemaAdapter;
|
|
7933
8098
|
exports.cn = cn;
|
|
7934
8099
|
exports.coerceRowValues = coerceRowValues;
|