@dimaan/ui 0.0.24 → 0.0.26
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 +128 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.js +128 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2948,37 +2948,130 @@ function hasActiveFilters(filters, values) {
|
|
|
2948
2948
|
}
|
|
2949
2949
|
return false;
|
|
2950
2950
|
}
|
|
2951
|
+
function DebouncedFilterInput({
|
|
2952
|
+
value,
|
|
2953
|
+
onChange,
|
|
2954
|
+
debounceMs,
|
|
2955
|
+
ariaLabel,
|
|
2956
|
+
placeholder,
|
|
2957
|
+
wrapperClassName,
|
|
2958
|
+
disabled
|
|
2959
|
+
}) {
|
|
2960
|
+
const [local, setLocal] = react.useState(value);
|
|
2961
|
+
const timerRef = react.useRef(null);
|
|
2962
|
+
const onChangeRef = react.useRef(onChange);
|
|
2963
|
+
onChangeRef.current = onChange;
|
|
2964
|
+
react.useEffect(() => {
|
|
2965
|
+
setLocal(value);
|
|
2966
|
+
if (timerRef.current) {
|
|
2967
|
+
clearTimeout(timerRef.current);
|
|
2968
|
+
timerRef.current = null;
|
|
2969
|
+
}
|
|
2970
|
+
}, [value]);
|
|
2971
|
+
react.useEffect(
|
|
2972
|
+
() => () => {
|
|
2973
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
2974
|
+
},
|
|
2975
|
+
[]
|
|
2976
|
+
);
|
|
2977
|
+
const handleChange = (next) => {
|
|
2978
|
+
setLocal(next);
|
|
2979
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
2980
|
+
if (debounceMs <= 0) {
|
|
2981
|
+
onChangeRef.current(next);
|
|
2982
|
+
return;
|
|
2983
|
+
}
|
|
2984
|
+
timerRef.current = setTimeout(() => {
|
|
2985
|
+
timerRef.current = null;
|
|
2986
|
+
onChangeRef.current(next);
|
|
2987
|
+
}, debounceMs);
|
|
2988
|
+
};
|
|
2989
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2990
|
+
Input,
|
|
2991
|
+
{
|
|
2992
|
+
type: "search",
|
|
2993
|
+
"aria-label": ariaLabel,
|
|
2994
|
+
placeholder,
|
|
2995
|
+
value: local,
|
|
2996
|
+
onChange: (e) => handleChange(e.target.value),
|
|
2997
|
+
leadingIcon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "size-4" }),
|
|
2998
|
+
wrapperClassName,
|
|
2999
|
+
disabled
|
|
3000
|
+
}
|
|
3001
|
+
);
|
|
3002
|
+
}
|
|
3003
|
+
var DEFAULT_TEXT_DEBOUNCE_MS = 400;
|
|
2951
3004
|
function ListPageFilterBar({
|
|
2952
3005
|
filters,
|
|
2953
3006
|
values,
|
|
2954
3007
|
onChange,
|
|
2955
3008
|
disabled = false,
|
|
3009
|
+
mode = "live",
|
|
2956
3010
|
labels
|
|
2957
3011
|
}) {
|
|
3012
|
+
const manual = mode === "manual";
|
|
2958
3013
|
const active = hasActiveFilters(filters, values);
|
|
3014
|
+
const appliedKey = JSON.stringify(values ?? {});
|
|
3015
|
+
const [draft, setDraft] = react.useState(values ?? {});
|
|
3016
|
+
react.useEffect(() => {
|
|
3017
|
+
if (manual) setDraft(values ?? {});
|
|
3018
|
+
}, [appliedKey, manual]);
|
|
3019
|
+
const effectiveValues = manual ? draft : values ?? {};
|
|
3020
|
+
const handleChange = (key, value) => {
|
|
3021
|
+
if (manual) {
|
|
3022
|
+
setDraft((prev) => ({ ...prev, [key]: value }));
|
|
3023
|
+
} else {
|
|
3024
|
+
onChange?.(key, value);
|
|
3025
|
+
}
|
|
3026
|
+
};
|
|
3027
|
+
const dirty = manual && (filters ?? []).some((filter) => {
|
|
3028
|
+
const next = draft[filter.key] ?? filterDefaultValue(filter);
|
|
3029
|
+
const current = values?.[filter.key] ?? filterDefaultValue(filter);
|
|
3030
|
+
return next !== current;
|
|
3031
|
+
});
|
|
3032
|
+
const apply = (event) => {
|
|
3033
|
+
event.preventDefault();
|
|
3034
|
+
for (const filter of filters ?? []) {
|
|
3035
|
+
const next = draft[filter.key] ?? filterDefaultValue(filter);
|
|
3036
|
+
const current = values?.[filter.key] ?? filterDefaultValue(filter);
|
|
3037
|
+
if (next !== current) onChange?.(filter.key, next);
|
|
3038
|
+
}
|
|
3039
|
+
};
|
|
2959
3040
|
const reset = () => {
|
|
2960
3041
|
for (const filter of filters ?? []) {
|
|
2961
3042
|
onChange?.(filter.key, filterDefaultValue(filter));
|
|
2962
3043
|
}
|
|
2963
3044
|
};
|
|
3045
|
+
const controls = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3", children: filters?.map((filter) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3046
|
+
FilterControl,
|
|
3047
|
+
{
|
|
3048
|
+
filter,
|
|
3049
|
+
value: effectiveValues[filter.key],
|
|
3050
|
+
onChange: handleChange,
|
|
3051
|
+
disabled,
|
|
3052
|
+
mode
|
|
3053
|
+
},
|
|
3054
|
+
filter.key
|
|
3055
|
+
)) });
|
|
3056
|
+
const resetButton = active && !disabled ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: reset, children: [
|
|
3057
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "size-4" }),
|
|
3058
|
+
labels.reset
|
|
3059
|
+
] }) : null;
|
|
3060
|
+
if (manual) {
|
|
3061
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("form", { "data-slot": "list-page-filter-bar", className: "space-y-3", onSubmit: apply, children: [
|
|
3062
|
+
controls,
|
|
3063
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
3064
|
+
resetButton,
|
|
3065
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", size: "sm", disabled: disabled || !dirty, children: labels.apply ?? "Apply" })
|
|
3066
|
+
] })
|
|
3067
|
+
] });
|
|
3068
|
+
}
|
|
2964
3069
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "list-page-filter-bar", className: "space-y-3", children: [
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
{
|
|
2968
|
-
filter,
|
|
2969
|
-
value: values?.[filter.key],
|
|
2970
|
-
onChange,
|
|
2971
|
-
disabled
|
|
2972
|
-
},
|
|
2973
|
-
filter.key
|
|
2974
|
-
)) }),
|
|
2975
|
-
active && !disabled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "ghost", size: "sm", onClick: reset, children: [
|
|
2976
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "size-4" }),
|
|
2977
|
-
labels.reset
|
|
2978
|
-
] }) }) : null
|
|
3070
|
+
controls,
|
|
3071
|
+
resetButton ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end", children: resetButton }) : null
|
|
2979
3072
|
] });
|
|
2980
3073
|
}
|
|
2981
|
-
function FilterControl({ filter, value, onChange, disabled }) {
|
|
3074
|
+
function FilterControl({ filter, value, onChange, disabled, mode }) {
|
|
2982
3075
|
const spanClass = FILTER_SPAN_CLASS[filter.width ?? "default"];
|
|
2983
3076
|
const ariaLabel = typeof filter.label === "string" ? filter.label : filter.key;
|
|
2984
3077
|
switch (filter.type) {
|
|
@@ -2996,14 +3089,13 @@ function FilterControl({ filter, value, onChange, disabled }) {
|
|
|
2996
3089
|
);
|
|
2997
3090
|
case "text":
|
|
2998
3091
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2999
|
-
|
|
3092
|
+
DebouncedFilterInput,
|
|
3000
3093
|
{
|
|
3001
|
-
type: "search",
|
|
3002
|
-
"aria-label": ariaLabel,
|
|
3003
|
-
placeholder: filter.placeholder,
|
|
3004
3094
|
value: value ?? "",
|
|
3005
|
-
onChange: (
|
|
3006
|
-
|
|
3095
|
+
onChange: (v) => onChange?.(filter.key, v),
|
|
3096
|
+
debounceMs: mode === "live" ? filter.debounceMs ?? DEFAULT_TEXT_DEBOUNCE_MS : 0,
|
|
3097
|
+
ariaLabel,
|
|
3098
|
+
placeholder: filter.placeholder,
|
|
3007
3099
|
wrapperClassName: spanClass,
|
|
3008
3100
|
disabled
|
|
3009
3101
|
}
|
|
@@ -3035,13 +3127,22 @@ function FilterControl({ filter, value, onChange, disabled }) {
|
|
|
3035
3127
|
);
|
|
3036
3128
|
}
|
|
3037
3129
|
}
|
|
3038
|
-
var
|
|
3130
|
+
var EN_LABELS2 = {
|
|
3039
3131
|
reset: "Reset filters",
|
|
3132
|
+
apply: "Apply",
|
|
3040
3133
|
emptyTitle: "No results",
|
|
3041
3134
|
emptyDescription: "Try clearing the search or adjusting the filters.",
|
|
3042
3135
|
noDataTitle: "No data yet",
|
|
3043
3136
|
noDataDescription: "Nothing has been added here so far."
|
|
3044
3137
|
};
|
|
3138
|
+
var AR_LABELS2 = {
|
|
3139
|
+
reset: "\u0625\u0639\u0627\u062F\u0629 \u062A\u0639\u064A\u064A\u0646 \u0627\u0644\u0641\u0644\u0627\u062A\u0631",
|
|
3140
|
+
apply: "\u062A\u0637\u0628\u064A\u0642",
|
|
3141
|
+
emptyTitle: "\u0644\u0627 \u062A\u0648\u062C\u062F \u0646\u062A\u0627\u0626\u062C",
|
|
3142
|
+
emptyDescription: "\u062C\u0631\u0651\u0628 \u0645\u0633\u062D \u0627\u0644\u0628\u062D\u062B \u0623\u0648 \u062A\u0639\u062F\u064A\u0644 \u0627\u0644\u0641\u0644\u0627\u062A\u0631.",
|
|
3143
|
+
noDataTitle: "\u0644\u0627 \u062A\u0648\u062C\u062F \u0628\u064A\u0627\u0646\u0627\u062A \u0628\u0639\u062F",
|
|
3144
|
+
noDataDescription: "\u0644\u0645 \u062A\u062A\u0645 \u0625\u0636\u0627\u0641\u0629 \u0623\u064A \u0634\u064A\u0621 \u0647\u0646\u0627 \u062D\u062A\u0649 \u0627\u0644\u0622\u0646."
|
|
3145
|
+
};
|
|
3045
3146
|
function ListPage({
|
|
3046
3147
|
title,
|
|
3047
3148
|
description,
|
|
@@ -3055,6 +3156,7 @@ function ListPage({
|
|
|
3055
3156
|
filters,
|
|
3056
3157
|
filterValues,
|
|
3057
3158
|
onFilterChange,
|
|
3159
|
+
filterMode = "manual",
|
|
3058
3160
|
enableRowSelection,
|
|
3059
3161
|
bulkActions,
|
|
3060
3162
|
pagination,
|
|
@@ -3066,7 +3168,8 @@ function ListPage({
|
|
|
3066
3168
|
labels: labelsProp,
|
|
3067
3169
|
className
|
|
3068
3170
|
}) {
|
|
3069
|
-
const
|
|
3171
|
+
const dir = useDirection();
|
|
3172
|
+
const labels = { ...dir === "rtl" ? AR_LABELS2 : EN_LABELS2, ...labelsProp };
|
|
3070
3173
|
const showFilterBar = Boolean(filters?.length);
|
|
3071
3174
|
const hasActiveQuery = react.useMemo(
|
|
3072
3175
|
() => hasActiveFilters(filters, filterValues),
|
|
@@ -3086,8 +3189,8 @@ function ListPage({
|
|
|
3086
3189
|
filters,
|
|
3087
3190
|
values: filterValues,
|
|
3088
3191
|
onChange: onFilterChange,
|
|
3089
|
-
|
|
3090
|
-
labels: { reset: labels.reset }
|
|
3192
|
+
mode: filterMode,
|
|
3193
|
+
labels: { reset: labels.reset, apply: labels.apply }
|
|
3091
3194
|
}
|
|
3092
3195
|
) : null,
|
|
3093
3196
|
tableMode === "loading" || tableMode === "rows" ? /* @__PURE__ */ jsxRuntime.jsx(
|