@sia-ui/react-web 0.4.0 → 0.5.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/CHANGELOG.md +53 -0
- package/README.md +129 -74
- package/dist/index.cjs +472 -363
- package/dist/index.css +303 -233
- package/dist/index.d.cts +81 -9
- package/dist/index.d.ts +81 -9
- package/dist/index.js +473 -366
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { createContext, forwardRef, useRef, useImperativeHandle, useEffect, memo, useContext, useState, useId, useMemo, useCallback, useLayoutEffect, Children, isValidElement, cloneElement, Fragment as Fragment$1 } from 'react';
|
|
3
|
-
import { cn, toneClass, formatCurrency, parseCurrency, formatTimeAgo, formatDate, normalizeIdentifier, truncate, formatDateTime, formatNumber } from '@sia-ui/utils';
|
|
4
|
-
import { useDisclosureState, overlayStack, navContains, useHoverIntent, navLeaves, navSome, useComponentDefaults, useSiaLocale, computeFloatingPosition, useAccordionState, navPath, filterNavTree, navKeyForPath, paginationItems, useTableQuery, useSliderState, useLocalForm, useSession, useToasts, toastStore, toast, useRovingIndex } from '@sia-ui/headless';
|
|
3
|
+
import { cn, toneClass, looseIncludes, formatCurrency, parseCurrency, formatTimeAgo, formatDate, normalizeIdentifier, truncate, formatDateTime, formatNumber } from '@sia-ui/utils';
|
|
4
|
+
import { useDisclosureState, overlayStack, navContains, useHoverIntent, navLeaves, navSome, useComponentDefaults, useSiaLocale, computeFloatingPosition, useAccordionState, navPath, filterNavTree, navKeyForPath, paginationItems, useTableQuery, useSliderState, useLocalForm, hasFormErrors, useSession, useToasts, toastStore, toast, readSubmitError, useRovingIndex } from '@sia-ui/headless';
|
|
5
5
|
export { toast, toastStore } from '@sia-ui/headless';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
import { useOutsideClick, Portal, useMediaQuery, usePortal, useControllableState } from '@sia-ui/react';
|
|
@@ -276,7 +276,8 @@ var Drawer = forwardRef(
|
|
|
276
276
|
isOpen,
|
|
277
277
|
phase: state,
|
|
278
278
|
open: doOpen,
|
|
279
|
-
close: doClose
|
|
279
|
+
close: doClose,
|
|
280
|
+
toggle
|
|
280
281
|
} = useDisclosureState({
|
|
281
282
|
...open !== void 0 ? { open } : {},
|
|
282
283
|
defaultOpen,
|
|
@@ -285,15 +286,17 @@ var Drawer = forwardRef(
|
|
|
285
286
|
});
|
|
286
287
|
const drawerRef = useRef(null);
|
|
287
288
|
const zIndexRef = useRef(null);
|
|
289
|
+
const fermer = useRef(doClose);
|
|
290
|
+
fermer.current = doClose;
|
|
288
291
|
useImperativeHandle(
|
|
289
292
|
ref,
|
|
290
293
|
() => ({
|
|
291
294
|
open: doOpen,
|
|
292
295
|
close: doClose,
|
|
293
|
-
toggle
|
|
296
|
+
toggle,
|
|
294
297
|
isOpen: () => isOpen
|
|
295
298
|
}),
|
|
296
|
-
[isOpen,
|
|
299
|
+
[isOpen, doOpen, doClose, toggle]
|
|
297
300
|
);
|
|
298
301
|
useEffect(() => {
|
|
299
302
|
if (!isOpen) return;
|
|
@@ -310,7 +313,7 @@ var Drawer = forwardRef(
|
|
|
310
313
|
const onKeyDown = (e) => {
|
|
311
314
|
if (!closeOnEsc || e.key !== "Escape") return;
|
|
312
315
|
if (overlayStack.isTop(zIndexRef.current)) {
|
|
313
|
-
|
|
316
|
+
fermer.current();
|
|
314
317
|
}
|
|
315
318
|
};
|
|
316
319
|
window.addEventListener("keydown", onKeyDown);
|
|
@@ -2020,9 +2023,9 @@ function Calendar({
|
|
|
2020
2023
|
if (mode === void 0) setPanelMode(next);
|
|
2021
2024
|
onPanelChange?.(monthIso(controlledMonth), next);
|
|
2022
2025
|
};
|
|
2023
|
-
const isDisabled = (date) => Boolean(
|
|
2026
|
+
const isDisabled = useCallback((date) => Boolean(
|
|
2024
2027
|
disabledDate?.(date) || validRange && (date < validRange[0] || date > validRange[1])
|
|
2025
|
-
);
|
|
2028
|
+
), [disabledDate, validRange]);
|
|
2026
2029
|
const selectDate = (date) => {
|
|
2027
2030
|
if (isDisabled(date)) return;
|
|
2028
2031
|
if (selectionMode === "range") {
|
|
@@ -2056,7 +2059,7 @@ function Calendar({
|
|
|
2056
2059
|
...rangeEdge ? { rangeEdge } : {}
|
|
2057
2060
|
};
|
|
2058
2061
|
});
|
|
2059
|
-
}, [year, monthIndex, firstDayOfWeek,
|
|
2062
|
+
}, [year, monthIndex, firstDayOfWeek, isDisabled, currentValue, currentRange.start, currentRange.end]);
|
|
2060
2063
|
const weekdays = Array.from({ length: 7 }, (_, index) => new Intl.DateTimeFormat(locale, { weekday: "short" }).format(new Date(2024, 0, 7 + firstDayOfWeek + index)));
|
|
2061
2064
|
const monthName = new Intl.DateTimeFormat(locale, { month: "long" }).format(controlledMonth);
|
|
2062
2065
|
const updateFromString = (next) => setMonth(parseMonth(next));
|
|
@@ -2703,6 +2706,8 @@ function Timer({ duration = 6e4, initialValue = 0, direction = "down", running =
|
|
|
2703
2706
|
const initial = direction === "down" ? duration : initialValue;
|
|
2704
2707
|
const [value, setValue] = useState(initial);
|
|
2705
2708
|
const finishCalled = useRef(false);
|
|
2709
|
+
const latest = useRef({ value, onChange, onFinish });
|
|
2710
|
+
latest.current = { value, onChange, onFinish };
|
|
2706
2711
|
useEffect(() => {
|
|
2707
2712
|
setValue(direction === "down" ? duration : initialValue);
|
|
2708
2713
|
finishCalled.current = false;
|
|
@@ -2710,15 +2715,15 @@ function Timer({ duration = 6e4, initialValue = 0, direction = "down", running =
|
|
|
2710
2715
|
useEffect(() => {
|
|
2711
2716
|
if (!running) return;
|
|
2712
2717
|
const startedAt = Date.now();
|
|
2713
|
-
const base = value;
|
|
2718
|
+
const base = latest.current.value;
|
|
2714
2719
|
const update = () => {
|
|
2715
2720
|
const elapsed = Date.now() - startedAt;
|
|
2716
2721
|
const next = direction === "down" ? Math.max(0, base - elapsed) : base + elapsed;
|
|
2717
2722
|
setValue(next);
|
|
2718
|
-
onChange?.(next);
|
|
2723
|
+
latest.current.onChange?.(next);
|
|
2719
2724
|
if (direction === "down" && next === 0 && !finishCalled.current) {
|
|
2720
2725
|
finishCalled.current = true;
|
|
2721
|
-
onFinish?.();
|
|
2726
|
+
latest.current.onFinish?.();
|
|
2722
2727
|
}
|
|
2723
2728
|
};
|
|
2724
2729
|
update();
|
|
@@ -2740,6 +2745,270 @@ function PageHeader({ title, description, eyebrow, actions, className }) {
|
|
|
2740
2745
|
actions && /* @__PURE__ */ jsx("div", { className: "sia-page-header__actions", children: actions })
|
|
2741
2746
|
] });
|
|
2742
2747
|
}
|
|
2748
|
+
function optionsFromChildren(children) {
|
|
2749
|
+
return Children.toArray(children).flatMap((child) => {
|
|
2750
|
+
if (!isValidElement(child))
|
|
2751
|
+
return [];
|
|
2752
|
+
const value = child.props.value;
|
|
2753
|
+
if (value === void 0) return [];
|
|
2754
|
+
return [{
|
|
2755
|
+
value: String(value),
|
|
2756
|
+
label: child.props.children,
|
|
2757
|
+
...child.props.disabled !== void 0 ? { disabled: child.props.disabled } : {}
|
|
2758
|
+
}];
|
|
2759
|
+
});
|
|
2760
|
+
}
|
|
2761
|
+
function optionText(option) {
|
|
2762
|
+
return [option.label, option.description, ...option.keywords ?? []].map((value) => typeof value === "string" || typeof value === "number" ? String(value) : "").join(" ");
|
|
2763
|
+
}
|
|
2764
|
+
var Select = forwardRef(function Select2({
|
|
2765
|
+
id,
|
|
2766
|
+
name,
|
|
2767
|
+
options,
|
|
2768
|
+
children,
|
|
2769
|
+
value,
|
|
2770
|
+
defaultValue = "",
|
|
2771
|
+
onValueChange,
|
|
2772
|
+
placeholder = "S\xE9lectionner",
|
|
2773
|
+
searchable = false,
|
|
2774
|
+
searchPlaceholder = "Rechercher...",
|
|
2775
|
+
fetcher,
|
|
2776
|
+
debounce = 250,
|
|
2777
|
+
loadingText = "Chargement des options...",
|
|
2778
|
+
emptyText = "Aucun r\xE9sultat",
|
|
2779
|
+
errorText = "Impossible de charger les options",
|
|
2780
|
+
clearable = false,
|
|
2781
|
+
disabled = false,
|
|
2782
|
+
invalid = false,
|
|
2783
|
+
required = false,
|
|
2784
|
+
placement = "bottom-start",
|
|
2785
|
+
renderValue,
|
|
2786
|
+
variant = "default",
|
|
2787
|
+
className,
|
|
2788
|
+
"aria-invalid": ariaInvalid,
|
|
2789
|
+
"aria-required": ariaRequired,
|
|
2790
|
+
...ariaProps
|
|
2791
|
+
}, forwardedRef) {
|
|
2792
|
+
const generatedId = useId();
|
|
2793
|
+
const controlId = id ?? `sia-select-${generatedId.replace(/:/g, "")}`;
|
|
2794
|
+
const listboxId = `${controlId}-listbox`;
|
|
2795
|
+
const triggerRef = useRef(null);
|
|
2796
|
+
const searchRef = useRef(null);
|
|
2797
|
+
const staticOptions = useMemo(
|
|
2798
|
+
() => options ?? optionsFromChildren(children),
|
|
2799
|
+
[children, options]
|
|
2800
|
+
);
|
|
2801
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
2802
|
+
const [open, setOpen] = useState(false);
|
|
2803
|
+
const [query, setQuery] = useState("");
|
|
2804
|
+
const [remoteOptions, setRemoteOptions] = useState([]);
|
|
2805
|
+
const [selectedRemoteOption, setSelectedRemoteOption] = useState();
|
|
2806
|
+
const [loading, setLoading] = useState(false);
|
|
2807
|
+
const [loadError, setLoadError] = useState(false);
|
|
2808
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
2809
|
+
const currentValue = value ?? internalValue;
|
|
2810
|
+
const sourceOptions = fetcher ? remoteOptions : staticOptions;
|
|
2811
|
+
const visibleOptions = useMemo(() => {
|
|
2812
|
+
if (fetcher) return sourceOptions;
|
|
2813
|
+
const needle = query.trim();
|
|
2814
|
+
return needle ? sourceOptions.filter((option) => looseIncludes(optionText(option), needle)) : sourceOptions;
|
|
2815
|
+
}, [fetcher, query, sourceOptions]);
|
|
2816
|
+
const selectedOption = [...staticOptions, ...remoteOptions].find(
|
|
2817
|
+
(option) => option.value === currentValue
|
|
2818
|
+
) ?? (selectedRemoteOption?.value === currentValue ? selectedRemoteOption : void 0);
|
|
2819
|
+
useEffect(() => {
|
|
2820
|
+
if (!open || !fetcher) return;
|
|
2821
|
+
const controller = new AbortController();
|
|
2822
|
+
const timeout = window.setTimeout(async () => {
|
|
2823
|
+
setLoading(true);
|
|
2824
|
+
setLoadError(false);
|
|
2825
|
+
try {
|
|
2826
|
+
const nextOptions = await fetcher(query, controller.signal);
|
|
2827
|
+
if (!controller.signal.aborted) setRemoteOptions(nextOptions);
|
|
2828
|
+
} catch {
|
|
2829
|
+
if (!controller.signal.aborted) setLoadError(true);
|
|
2830
|
+
} finally {
|
|
2831
|
+
if (!controller.signal.aborted) setLoading(false);
|
|
2832
|
+
}
|
|
2833
|
+
}, debounce);
|
|
2834
|
+
return () => {
|
|
2835
|
+
window.clearTimeout(timeout);
|
|
2836
|
+
controller.abort();
|
|
2837
|
+
};
|
|
2838
|
+
}, [debounce, fetcher, open, query]);
|
|
2839
|
+
useEffect(() => {
|
|
2840
|
+
if (!open) return;
|
|
2841
|
+
const selected = visibleOptions.findIndex((option) => option.value === currentValue);
|
|
2842
|
+
setActiveIndex(selected >= 0 ? selected : visibleOptions.findIndex((option) => !option.disabled));
|
|
2843
|
+
if (searchable || fetcher) window.setTimeout(() => searchRef.current?.focus(), 0);
|
|
2844
|
+
}, [currentValue, fetcher, open, searchable, visibleOptions]);
|
|
2845
|
+
const setTriggerRef = (node) => {
|
|
2846
|
+
triggerRef.current = node;
|
|
2847
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
2848
|
+
else if (forwardedRef) forwardedRef.current = node;
|
|
2849
|
+
};
|
|
2850
|
+
const changeValue = (nextValue, option) => {
|
|
2851
|
+
if (value === void 0) setInternalValue(nextValue);
|
|
2852
|
+
onValueChange?.(nextValue, option);
|
|
2853
|
+
};
|
|
2854
|
+
const choose = (option) => {
|
|
2855
|
+
if (option.disabled) return;
|
|
2856
|
+
if (fetcher) setSelectedRemoteOption(option);
|
|
2857
|
+
changeValue(option.value, option);
|
|
2858
|
+
setOpen(false);
|
|
2859
|
+
setQuery("");
|
|
2860
|
+
window.setTimeout(() => triggerRef.current?.focus(), 0);
|
|
2861
|
+
};
|
|
2862
|
+
const moveActive = (direction) => {
|
|
2863
|
+
if (!visibleOptions.length) return;
|
|
2864
|
+
let next = activeIndex;
|
|
2865
|
+
for (let count = 0; count < visibleOptions.length; count += 1) {
|
|
2866
|
+
next = (next + direction + visibleOptions.length) % visibleOptions.length;
|
|
2867
|
+
if (!visibleOptions[next]?.disabled) break;
|
|
2868
|
+
}
|
|
2869
|
+
setActiveIndex(next);
|
|
2870
|
+
};
|
|
2871
|
+
const handleKeyDown = (event) => {
|
|
2872
|
+
if (["ArrowDown", "ArrowUp"].includes(event.key)) {
|
|
2873
|
+
event.preventDefault();
|
|
2874
|
+
if (!open) setOpen(true);
|
|
2875
|
+
else moveActive(event.key === "ArrowDown" ? 1 : -1);
|
|
2876
|
+
return;
|
|
2877
|
+
}
|
|
2878
|
+
if (event.key === "Home" && open) {
|
|
2879
|
+
event.preventDefault();
|
|
2880
|
+
setActiveIndex(visibleOptions.findIndex((option) => !option.disabled));
|
|
2881
|
+
} else if (event.key === "End" && open) {
|
|
2882
|
+
event.preventDefault();
|
|
2883
|
+
for (let index = visibleOptions.length - 1; index >= 0; index -= 1) {
|
|
2884
|
+
if (!visibleOptions[index]?.disabled) {
|
|
2885
|
+
setActiveIndex(index);
|
|
2886
|
+
break;
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
} else if (event.key === "Enter" && open && activeIndex >= 0) {
|
|
2890
|
+
event.preventDefault();
|
|
2891
|
+
const active = visibleOptions[activeIndex];
|
|
2892
|
+
if (active) choose(active);
|
|
2893
|
+
} else if (event.key === "Escape" && open) {
|
|
2894
|
+
event.preventDefault();
|
|
2895
|
+
setOpen(false);
|
|
2896
|
+
triggerRef.current?.focus();
|
|
2897
|
+
} else if (!open && clearable && currentValue && ["Backspace", "Delete"].includes(event.key)) {
|
|
2898
|
+
event.preventDefault();
|
|
2899
|
+
changeValue("");
|
|
2900
|
+
}
|
|
2901
|
+
};
|
|
2902
|
+
const showSearch = searchable || Boolean(fetcher);
|
|
2903
|
+
const activeOption = activeIndex >= 0 ? visibleOptions[activeIndex] : void 0;
|
|
2904
|
+
return /* @__PURE__ */ jsxs(
|
|
2905
|
+
"div",
|
|
2906
|
+
{
|
|
2907
|
+
className: cn(
|
|
2908
|
+
"sia-select",
|
|
2909
|
+
variant === "embedded" && "sia-select--embedded",
|
|
2910
|
+
disabled && "sia-select--disabled",
|
|
2911
|
+
className
|
|
2912
|
+
),
|
|
2913
|
+
children: [
|
|
2914
|
+
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: currentValue }),
|
|
2915
|
+
/* @__PURE__ */ jsxs(
|
|
2916
|
+
"button",
|
|
2917
|
+
{
|
|
2918
|
+
ref: setTriggerRef,
|
|
2919
|
+
id: controlId,
|
|
2920
|
+
type: "button",
|
|
2921
|
+
className: cn("sia-select__trigger", invalid && "sia-select__trigger--invalid"),
|
|
2922
|
+
role: "combobox",
|
|
2923
|
+
"aria-haspopup": "listbox",
|
|
2924
|
+
"aria-expanded": open,
|
|
2925
|
+
"aria-controls": listboxId,
|
|
2926
|
+
"aria-activedescendant": open && activeOption ? `${listboxId}-${activeIndex}` : void 0,
|
|
2927
|
+
"aria-invalid": ariaInvalid ?? (invalid || void 0),
|
|
2928
|
+
"aria-required": ariaRequired ?? (required || void 0),
|
|
2929
|
+
disabled,
|
|
2930
|
+
onClick: () => setOpen((current) => !current),
|
|
2931
|
+
onKeyDown: handleKeyDown,
|
|
2932
|
+
...ariaProps,
|
|
2933
|
+
children: [
|
|
2934
|
+
/* @__PURE__ */ jsx("span", { className: cn("sia-select__value", !selectedOption && "sia-select__placeholder"), children: renderValue ? renderValue(selectedOption) : selectedOption?.label ?? placeholder }),
|
|
2935
|
+
/* @__PURE__ */ jsxs("span", { className: "sia-select__actions", children: [
|
|
2936
|
+
clearable && currentValue && !disabled && /* @__PURE__ */ jsx(
|
|
2937
|
+
"span",
|
|
2938
|
+
{
|
|
2939
|
+
className: "sia-select__clear",
|
|
2940
|
+
"aria-hidden": "true",
|
|
2941
|
+
title: "Effacer la s\xE9lection",
|
|
2942
|
+
onClick: (event) => {
|
|
2943
|
+
event.stopPropagation();
|
|
2944
|
+
changeValue("");
|
|
2945
|
+
},
|
|
2946
|
+
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
2947
|
+
}
|
|
2948
|
+
),
|
|
2949
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "sia-select__chevron", "aria-hidden": "true" })
|
|
2950
|
+
] })
|
|
2951
|
+
]
|
|
2952
|
+
}
|
|
2953
|
+
),
|
|
2954
|
+
/* @__PURE__ */ jsx(
|
|
2955
|
+
Overlay,
|
|
2956
|
+
{
|
|
2957
|
+
open,
|
|
2958
|
+
anchorRef: triggerRef,
|
|
2959
|
+
onOpenChange: setOpen,
|
|
2960
|
+
placement,
|
|
2961
|
+
matchAnchorWidth: true,
|
|
2962
|
+
className: "sia-select__overlay",
|
|
2963
|
+
children: /* @__PURE__ */ jsxs("div", { className: "sia-select__panel", onKeyDown: handleKeyDown, children: [
|
|
2964
|
+
showSearch && /* @__PURE__ */ jsxs("div", { className: "sia-select__search-wrap", children: [
|
|
2965
|
+
/* @__PURE__ */ jsx(SearchIcon, { "aria-hidden": "true" }),
|
|
2966
|
+
/* @__PURE__ */ jsx(
|
|
2967
|
+
"input",
|
|
2968
|
+
{
|
|
2969
|
+
ref: searchRef,
|
|
2970
|
+
className: "sia-select__search",
|
|
2971
|
+
value: query,
|
|
2972
|
+
placeholder: searchPlaceholder,
|
|
2973
|
+
"aria-label": searchPlaceholder,
|
|
2974
|
+
onChange: (event) => setQuery(event.target.value)
|
|
2975
|
+
}
|
|
2976
|
+
),
|
|
2977
|
+
loading && /* @__PURE__ */ jsx(Spinner, { size: "xs", label: "Chargement" })
|
|
2978
|
+
] }),
|
|
2979
|
+
/* @__PURE__ */ jsx("div", { id: listboxId, role: "listbox", "aria-busy": loading || void 0, className: "sia-select__options", children: loading && !visibleOptions.length ? /* @__PURE__ */ jsx("div", { className: "sia-select__status", children: loadingText }) : loadError ? /* @__PURE__ */ jsx("div", { className: "sia-select__status sia-select__status--error", children: errorText }) : !visibleOptions.length ? /* @__PURE__ */ jsx("div", { className: "sia-select__status", children: emptyText }) : visibleOptions.map((option, index) => /* @__PURE__ */ jsxs(
|
|
2980
|
+
"button",
|
|
2981
|
+
{
|
|
2982
|
+
id: `${listboxId}-${index}`,
|
|
2983
|
+
type: "button",
|
|
2984
|
+
role: "option",
|
|
2985
|
+
"aria-selected": currentValue === option.value,
|
|
2986
|
+
disabled: option.disabled,
|
|
2987
|
+
className: cn(
|
|
2988
|
+
"sia-select__option",
|
|
2989
|
+
index === activeIndex && "sia-select__option--active"
|
|
2990
|
+
),
|
|
2991
|
+
onMouseEnter: () => setActiveIndex(index),
|
|
2992
|
+
onClick: () => choose(option),
|
|
2993
|
+
children: [
|
|
2994
|
+
/* @__PURE__ */ jsxs("span", { className: "sia-select__option-content", children: [
|
|
2995
|
+
/* @__PURE__ */ jsx("span", { children: option.label }),
|
|
2996
|
+
option.description && /* @__PURE__ */ jsx("small", { children: option.description })
|
|
2997
|
+
] }),
|
|
2998
|
+
currentValue === option.value && /* @__PURE__ */ jsx(CheckIcon, { "aria-hidden": "true" })
|
|
2999
|
+
]
|
|
3000
|
+
},
|
|
3001
|
+
option.value
|
|
3002
|
+
)) })
|
|
3003
|
+
] })
|
|
3004
|
+
}
|
|
3005
|
+
)
|
|
3006
|
+
]
|
|
3007
|
+
}
|
|
3008
|
+
);
|
|
3009
|
+
});
|
|
3010
|
+
Select.displayName = "Select";
|
|
3011
|
+
var DEFAULT_PAGE_SIZE_OPTIONS = [10, 20, 50, 100];
|
|
2743
3012
|
function Pagination({
|
|
2744
3013
|
page,
|
|
2745
3014
|
totalPages,
|
|
@@ -2750,6 +3019,11 @@ function Pagination({
|
|
|
2750
3019
|
jumpTo = false,
|
|
2751
3020
|
showTotal = false,
|
|
2752
3021
|
compact = false,
|
|
3022
|
+
pageSize,
|
|
3023
|
+
onPageSizeChange,
|
|
3024
|
+
pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS,
|
|
3025
|
+
pageSizeLabel,
|
|
3026
|
+
renderPageSize,
|
|
2753
3027
|
ariaLabel,
|
|
2754
3028
|
className
|
|
2755
3029
|
}) {
|
|
@@ -2760,8 +3034,17 @@ function Pagination({
|
|
|
2760
3034
|
const current = Math.min(Math.max(page, 1), Math.max(totalPages, 1));
|
|
2761
3035
|
const [draft, setDraft] = useState(String(current));
|
|
2762
3036
|
useEffect(() => setDraft(String(current)), [current]);
|
|
2763
|
-
|
|
2764
|
-
|
|
3037
|
+
const tailles = useMemo(() => {
|
|
3038
|
+
if (pageSize === void 0 || pageSizeOptions.includes(pageSize)) {
|
|
3039
|
+
return pageSizeOptions;
|
|
3040
|
+
}
|
|
3041
|
+
return [...pageSizeOptions, pageSize].sort((a, b) => a - b);
|
|
3042
|
+
}, [pageSize, pageSizeOptions]);
|
|
3043
|
+
const choixTaille = pageSize !== void 0 && onPageSizeChange && tailles.length > 0;
|
|
3044
|
+
const plusieursPages = totalPages > 1;
|
|
3045
|
+
const tailleLibelle = pageSizeLabel ?? locale.perPage;
|
|
3046
|
+
if (!plusieursPages && !choixTaille) return null;
|
|
3047
|
+
const items = plusieursPages ? paginationItems(current, totalPages, siblingCount) : [];
|
|
2765
3048
|
const jump = (event) => {
|
|
2766
3049
|
event.preventDefault();
|
|
2767
3050
|
const asked = Number(draft);
|
|
@@ -2781,71 +3064,97 @@ function Pagination({
|
|
|
2781
3064
|
),
|
|
2782
3065
|
"aria-label": ariaLabel ?? "Pagination",
|
|
2783
3066
|
children: [
|
|
2784
|
-
/* @__PURE__ */ jsxs(
|
|
2785
|
-
|
|
2786
|
-
{
|
|
2787
|
-
type: "button",
|
|
2788
|
-
className: "sia-pagination__step",
|
|
2789
|
-
disabled: current === 1,
|
|
2790
|
-
"aria-label": previousLabel,
|
|
2791
|
-
onClick: () => onPageChange(current - 1),
|
|
2792
|
-
children: [
|
|
2793
|
-
/* @__PURE__ */ jsx(ChevronLeftIcon, {}),
|
|
2794
|
-
!compact && /* @__PURE__ */ jsx("span", { children: previousLabel })
|
|
2795
|
-
]
|
|
2796
|
-
}
|
|
2797
|
-
),
|
|
2798
|
-
items.map(
|
|
2799
|
-
(item) => typeof item === "number" ? /* @__PURE__ */ jsx(
|
|
3067
|
+
plusieursPages && /* @__PURE__ */ jsxs("div", { className: "sia-pagination__pages", children: [
|
|
3068
|
+
/* @__PURE__ */ jsxs(
|
|
2800
3069
|
"button",
|
|
2801
3070
|
{
|
|
2802
3071
|
type: "button",
|
|
2803
|
-
className: "sia-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
/* @__PURE__ */ jsxs(
|
|
2812
|
-
"button",
|
|
2813
|
-
{
|
|
2814
|
-
type: "button",
|
|
2815
|
-
className: "sia-pagination__step",
|
|
2816
|
-
disabled: current === totalPages,
|
|
2817
|
-
"aria-label": nextLabel,
|
|
2818
|
-
onClick: () => onPageChange(current + 1),
|
|
2819
|
-
children: [
|
|
2820
|
-
!compact && /* @__PURE__ */ jsx("span", { children: nextLabel }),
|
|
2821
|
-
/* @__PURE__ */ jsx(ChevronRightIcon, {})
|
|
2822
|
-
]
|
|
2823
|
-
}
|
|
2824
|
-
),
|
|
2825
|
-
showTotal && /* @__PURE__ */ jsxs("span", { className: "sia-pagination__total", children: [
|
|
2826
|
-
locale.page,
|
|
2827
|
-
" ",
|
|
2828
|
-
current,
|
|
2829
|
-
" / ",
|
|
2830
|
-
totalPages
|
|
2831
|
-
] }),
|
|
2832
|
-
jumpTo && /* @__PURE__ */ jsxs("form", { className: "sia-pagination__jump", onSubmit: jump, children: [
|
|
2833
|
-
/* @__PURE__ */ jsx("label", { htmlFor: jumpId, children: locale.goToPage }),
|
|
2834
|
-
/* @__PURE__ */ jsx(
|
|
2835
|
-
"input",
|
|
2836
|
-
{
|
|
2837
|
-
id: jumpId,
|
|
2838
|
-
type: "text",
|
|
2839
|
-
inputMode: "numeric",
|
|
2840
|
-
value: draft,
|
|
2841
|
-
"aria-label": locale.goToPage,
|
|
2842
|
-
onChange: (event) => setDraft(event.target.value.replace(/\D/g, "")),
|
|
2843
|
-
onBlur: jump
|
|
3072
|
+
className: "sia-pagination__step",
|
|
3073
|
+
disabled: current === 1,
|
|
3074
|
+
"aria-label": previousLabel,
|
|
3075
|
+
onClick: () => onPageChange(current - 1),
|
|
3076
|
+
children: [
|
|
3077
|
+
/* @__PURE__ */ jsx(ChevronLeftIcon, {}),
|
|
3078
|
+
!compact && /* @__PURE__ */ jsx("span", { children: previousLabel })
|
|
3079
|
+
]
|
|
2844
3080
|
}
|
|
2845
3081
|
),
|
|
2846
|
-
|
|
2847
|
-
"
|
|
3082
|
+
items.map(
|
|
3083
|
+
(item) => typeof item === "number" ? /* @__PURE__ */ jsx(
|
|
3084
|
+
"button",
|
|
3085
|
+
{
|
|
3086
|
+
type: "button",
|
|
3087
|
+
className: "sia-pagination__page",
|
|
3088
|
+
"aria-current": item === current ? "page" : void 0,
|
|
3089
|
+
onClick: () => onPageChange(item),
|
|
3090
|
+
children: item
|
|
3091
|
+
},
|
|
3092
|
+
item
|
|
3093
|
+
) : /* @__PURE__ */ jsx("span", { className: "sia-pagination__gap", "aria-hidden": "true", children: "\u2026" }, item)
|
|
3094
|
+
),
|
|
3095
|
+
/* @__PURE__ */ jsxs(
|
|
3096
|
+
"button",
|
|
3097
|
+
{
|
|
3098
|
+
type: "button",
|
|
3099
|
+
className: "sia-pagination__step",
|
|
3100
|
+
disabled: current === totalPages,
|
|
3101
|
+
"aria-label": nextLabel,
|
|
3102
|
+
onClick: () => onPageChange(current + 1),
|
|
3103
|
+
children: [
|
|
3104
|
+
!compact && /* @__PURE__ */ jsx("span", { children: nextLabel }),
|
|
3105
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, {})
|
|
3106
|
+
]
|
|
3107
|
+
}
|
|
3108
|
+
)
|
|
3109
|
+
] }),
|
|
3110
|
+
(choixTaille || plusieursPages && (showTotal || jumpTo)) && /* @__PURE__ */ jsxs("div", { className: "sia-pagination__settings", children: [
|
|
3111
|
+
plusieursPages && showTotal && /* @__PURE__ */ jsxs("span", { className: "sia-pagination__total", children: [
|
|
3112
|
+
locale.page,
|
|
3113
|
+
" ",
|
|
3114
|
+
current,
|
|
3115
|
+
" / ",
|
|
2848
3116
|
totalPages
|
|
3117
|
+
] }),
|
|
3118
|
+
choixTaille && /* @__PURE__ */ jsx("div", { className: "sia-pagination__size", children: renderPageSize ? renderPageSize({
|
|
3119
|
+
pageSize,
|
|
3120
|
+
options: tailles,
|
|
3121
|
+
onChange: onPageSizeChange,
|
|
3122
|
+
label: tailleLibelle
|
|
3123
|
+
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3124
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: tailleLibelle }),
|
|
3125
|
+
/* @__PURE__ */ jsx(
|
|
3126
|
+
Select,
|
|
3127
|
+
{
|
|
3128
|
+
variant: "embedded",
|
|
3129
|
+
"aria-label": tailleLibelle,
|
|
3130
|
+
placement: "top-end",
|
|
3131
|
+
value: String(pageSize),
|
|
3132
|
+
options: tailles.map((taille) => ({
|
|
3133
|
+
value: String(taille),
|
|
3134
|
+
label: String(taille)
|
|
3135
|
+
})),
|
|
3136
|
+
onValueChange: (valeur) => onPageSizeChange(Number(valeur))
|
|
3137
|
+
}
|
|
3138
|
+
)
|
|
3139
|
+
] }) }),
|
|
3140
|
+
plusieursPages && jumpTo && /* @__PURE__ */ jsxs("form", { className: "sia-pagination__jump", onSubmit: jump, children: [
|
|
3141
|
+
/* @__PURE__ */ jsx("label", { htmlFor: jumpId, children: locale.goToPage }),
|
|
3142
|
+
/* @__PURE__ */ jsx(
|
|
3143
|
+
"input",
|
|
3144
|
+
{
|
|
3145
|
+
id: jumpId,
|
|
3146
|
+
type: "text",
|
|
3147
|
+
inputMode: "numeric",
|
|
3148
|
+
value: draft,
|
|
3149
|
+
"aria-label": locale.goToPage,
|
|
3150
|
+
onChange: (event) => setDraft(event.target.value.replace(/\D/g, "")),
|
|
3151
|
+
onBlur: jump
|
|
3152
|
+
}
|
|
3153
|
+
),
|
|
3154
|
+
/* @__PURE__ */ jsxs("span", { className: "sia-pagination__jump-total", "aria-hidden": "true", children: [
|
|
3155
|
+
"/ ",
|
|
3156
|
+
totalPages
|
|
3157
|
+
] })
|
|
2849
3158
|
] })
|
|
2850
3159
|
] })
|
|
2851
3160
|
]
|
|
@@ -3131,6 +3440,7 @@ function DataTable({
|
|
|
3131
3440
|
searchKeys,
|
|
3132
3441
|
searchPlaceholder,
|
|
3133
3442
|
onSearch,
|
|
3443
|
+
searchDelay = 0,
|
|
3134
3444
|
layout = "auto",
|
|
3135
3445
|
maxHeight,
|
|
3136
3446
|
stickyHeader = false,
|
|
@@ -3249,9 +3559,10 @@ function DataTable({
|
|
|
3249
3559
|
{
|
|
3250
3560
|
value: recherche,
|
|
3251
3561
|
placeholder: searchPlaceholder ?? locale.search,
|
|
3562
|
+
...onSearch && searchDelay > 0 ? { onSearch, searchDelay } : {},
|
|
3252
3563
|
onValueChange: (v) => {
|
|
3253
3564
|
setRecherche(v);
|
|
3254
|
-
onSearch?.(v);
|
|
3565
|
+
if (searchDelay <= 0) onSearch?.(v);
|
|
3255
3566
|
}
|
|
3256
3567
|
}
|
|
3257
3568
|
),
|
|
@@ -4044,255 +4355,6 @@ function DateTimePicker({ value, defaultValue = { date: "", time: "" }, onValueC
|
|
|
4044
4355
|
/* @__PURE__ */ jsx(TimePicker, { ...timeProps, value: current.time, minuteStep, secondStep, showSeconds, hourFormat, needConfirm, tone, ...stateProps, "aria-label": "Heure", onValueChange: (time) => update({ ...current, time }) })
|
|
4045
4356
|
] });
|
|
4046
4357
|
}
|
|
4047
|
-
function optionsFromChildren(children) {
|
|
4048
|
-
return Children.toArray(children).flatMap((child) => {
|
|
4049
|
-
if (!isValidElement(child))
|
|
4050
|
-
return [];
|
|
4051
|
-
const value = child.props.value;
|
|
4052
|
-
if (value === void 0) return [];
|
|
4053
|
-
return [{
|
|
4054
|
-
value: String(value),
|
|
4055
|
-
label: child.props.children,
|
|
4056
|
-
...child.props.disabled !== void 0 ? { disabled: child.props.disabled } : {}
|
|
4057
|
-
}];
|
|
4058
|
-
});
|
|
4059
|
-
}
|
|
4060
|
-
function optionText(option) {
|
|
4061
|
-
return [option.label, option.description, ...option.keywords ?? []].map((value) => typeof value === "string" || typeof value === "number" ? String(value) : "").join(" ").toLocaleLowerCase();
|
|
4062
|
-
}
|
|
4063
|
-
var Select = forwardRef(function Select2({
|
|
4064
|
-
id,
|
|
4065
|
-
name,
|
|
4066
|
-
options,
|
|
4067
|
-
children,
|
|
4068
|
-
value,
|
|
4069
|
-
defaultValue = "",
|
|
4070
|
-
onValueChange,
|
|
4071
|
-
placeholder = "S\xE9lectionner",
|
|
4072
|
-
searchable = false,
|
|
4073
|
-
searchPlaceholder = "Rechercher...",
|
|
4074
|
-
fetcher,
|
|
4075
|
-
debounce = 250,
|
|
4076
|
-
loadingText = "Chargement des options...",
|
|
4077
|
-
emptyText = "Aucun r\xE9sultat",
|
|
4078
|
-
errorText = "Impossible de charger les options",
|
|
4079
|
-
clearable = false,
|
|
4080
|
-
disabled = false,
|
|
4081
|
-
invalid = false,
|
|
4082
|
-
required = false,
|
|
4083
|
-
placement = "bottom-start",
|
|
4084
|
-
className,
|
|
4085
|
-
"aria-invalid": ariaInvalid,
|
|
4086
|
-
"aria-required": ariaRequired,
|
|
4087
|
-
...ariaProps
|
|
4088
|
-
}, forwardedRef) {
|
|
4089
|
-
const generatedId = useId();
|
|
4090
|
-
const controlId = id ?? `sia-select-${generatedId.replace(/:/g, "")}`;
|
|
4091
|
-
const listboxId = `${controlId}-listbox`;
|
|
4092
|
-
const triggerRef = useRef(null);
|
|
4093
|
-
const searchRef = useRef(null);
|
|
4094
|
-
const staticOptions = useMemo(
|
|
4095
|
-
() => options ?? optionsFromChildren(children),
|
|
4096
|
-
[children, options]
|
|
4097
|
-
);
|
|
4098
|
-
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
4099
|
-
const [open, setOpen] = useState(false);
|
|
4100
|
-
const [query, setQuery] = useState("");
|
|
4101
|
-
const [remoteOptions, setRemoteOptions] = useState([]);
|
|
4102
|
-
const [selectedRemoteOption, setSelectedRemoteOption] = useState();
|
|
4103
|
-
const [loading, setLoading] = useState(false);
|
|
4104
|
-
const [loadError, setLoadError] = useState(false);
|
|
4105
|
-
const [activeIndex, setActiveIndex] = useState(-1);
|
|
4106
|
-
const currentValue = value ?? internalValue;
|
|
4107
|
-
const sourceOptions = fetcher ? remoteOptions : staticOptions;
|
|
4108
|
-
const visibleOptions = useMemo(() => {
|
|
4109
|
-
if (fetcher) return sourceOptions;
|
|
4110
|
-
const needle = query.trim().toLocaleLowerCase();
|
|
4111
|
-
return needle ? sourceOptions.filter((option) => optionText(option).includes(needle)) : sourceOptions;
|
|
4112
|
-
}, [fetcher, query, sourceOptions]);
|
|
4113
|
-
const selectedOption = [...staticOptions, ...remoteOptions].find(
|
|
4114
|
-
(option) => option.value === currentValue
|
|
4115
|
-
) ?? (selectedRemoteOption?.value === currentValue ? selectedRemoteOption : void 0);
|
|
4116
|
-
useEffect(() => {
|
|
4117
|
-
if (!open || !fetcher) return;
|
|
4118
|
-
const controller = new AbortController();
|
|
4119
|
-
const timeout = window.setTimeout(async () => {
|
|
4120
|
-
setLoading(true);
|
|
4121
|
-
setLoadError(false);
|
|
4122
|
-
try {
|
|
4123
|
-
const nextOptions = await fetcher(query, controller.signal);
|
|
4124
|
-
if (!controller.signal.aborted) setRemoteOptions(nextOptions);
|
|
4125
|
-
} catch {
|
|
4126
|
-
if (!controller.signal.aborted) setLoadError(true);
|
|
4127
|
-
} finally {
|
|
4128
|
-
if (!controller.signal.aborted) setLoading(false);
|
|
4129
|
-
}
|
|
4130
|
-
}, debounce);
|
|
4131
|
-
return () => {
|
|
4132
|
-
window.clearTimeout(timeout);
|
|
4133
|
-
controller.abort();
|
|
4134
|
-
};
|
|
4135
|
-
}, [debounce, fetcher, open, query]);
|
|
4136
|
-
useEffect(() => {
|
|
4137
|
-
if (!open) return;
|
|
4138
|
-
setActiveIndex(visibleOptions.findIndex((option) => option.value === currentValue));
|
|
4139
|
-
if (searchable || fetcher) window.setTimeout(() => searchRef.current?.focus(), 0);
|
|
4140
|
-
}, [currentValue, fetcher, open, searchable, visibleOptions]);
|
|
4141
|
-
const setTriggerRef = (node) => {
|
|
4142
|
-
triggerRef.current = node;
|
|
4143
|
-
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
4144
|
-
else if (forwardedRef) forwardedRef.current = node;
|
|
4145
|
-
};
|
|
4146
|
-
const changeValue = (nextValue, option) => {
|
|
4147
|
-
if (value === void 0) setInternalValue(nextValue);
|
|
4148
|
-
onValueChange?.(nextValue, option);
|
|
4149
|
-
};
|
|
4150
|
-
const choose = (option) => {
|
|
4151
|
-
if (option.disabled) return;
|
|
4152
|
-
if (fetcher) setSelectedRemoteOption(option);
|
|
4153
|
-
changeValue(option.value, option);
|
|
4154
|
-
setOpen(false);
|
|
4155
|
-
setQuery("");
|
|
4156
|
-
window.setTimeout(() => triggerRef.current?.focus(), 0);
|
|
4157
|
-
};
|
|
4158
|
-
const moveActive = (direction) => {
|
|
4159
|
-
if (!visibleOptions.length) return;
|
|
4160
|
-
let next = activeIndex;
|
|
4161
|
-
for (let count = 0; count < visibleOptions.length; count += 1) {
|
|
4162
|
-
next = (next + direction + visibleOptions.length) % visibleOptions.length;
|
|
4163
|
-
if (!visibleOptions[next]?.disabled) break;
|
|
4164
|
-
}
|
|
4165
|
-
setActiveIndex(next);
|
|
4166
|
-
};
|
|
4167
|
-
const handleKeyDown = (event) => {
|
|
4168
|
-
if (["ArrowDown", "ArrowUp"].includes(event.key)) {
|
|
4169
|
-
event.preventDefault();
|
|
4170
|
-
if (!open) setOpen(true);
|
|
4171
|
-
else moveActive(event.key === "ArrowDown" ? 1 : -1);
|
|
4172
|
-
return;
|
|
4173
|
-
}
|
|
4174
|
-
if (event.key === "Home" && open) {
|
|
4175
|
-
event.preventDefault();
|
|
4176
|
-
setActiveIndex(visibleOptions.findIndex((option) => !option.disabled));
|
|
4177
|
-
} else if (event.key === "End" && open) {
|
|
4178
|
-
event.preventDefault();
|
|
4179
|
-
for (let index = visibleOptions.length - 1; index >= 0; index -= 1) {
|
|
4180
|
-
if (!visibleOptions[index]?.disabled) {
|
|
4181
|
-
setActiveIndex(index);
|
|
4182
|
-
break;
|
|
4183
|
-
}
|
|
4184
|
-
}
|
|
4185
|
-
} else if (event.key === "Enter" && open && activeIndex >= 0) {
|
|
4186
|
-
event.preventDefault();
|
|
4187
|
-
const active = visibleOptions[activeIndex];
|
|
4188
|
-
if (active) choose(active);
|
|
4189
|
-
} else if (event.key === "Escape" && open) {
|
|
4190
|
-
event.preventDefault();
|
|
4191
|
-
setOpen(false);
|
|
4192
|
-
triggerRef.current?.focus();
|
|
4193
|
-
} else if (!open && clearable && currentValue && ["Backspace", "Delete"].includes(event.key)) {
|
|
4194
|
-
event.preventDefault();
|
|
4195
|
-
changeValue("");
|
|
4196
|
-
}
|
|
4197
|
-
};
|
|
4198
|
-
const showSearch = searchable || Boolean(fetcher);
|
|
4199
|
-
const activeOption = activeIndex >= 0 ? visibleOptions[activeIndex] : void 0;
|
|
4200
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("sia-select", disabled && "sia-select--disabled", className), children: [
|
|
4201
|
-
name && /* @__PURE__ */ jsx("input", { type: "hidden", name, value: currentValue }),
|
|
4202
|
-
/* @__PURE__ */ jsxs(
|
|
4203
|
-
"button",
|
|
4204
|
-
{
|
|
4205
|
-
ref: setTriggerRef,
|
|
4206
|
-
id: controlId,
|
|
4207
|
-
type: "button",
|
|
4208
|
-
className: cn("sia-select__trigger", invalid && "sia-select__trigger--invalid"),
|
|
4209
|
-
role: "combobox",
|
|
4210
|
-
"aria-haspopup": "listbox",
|
|
4211
|
-
"aria-expanded": open,
|
|
4212
|
-
"aria-controls": listboxId,
|
|
4213
|
-
"aria-activedescendant": open && activeOption ? `${listboxId}-${activeIndex}` : void 0,
|
|
4214
|
-
"aria-invalid": ariaInvalid ?? (invalid || void 0),
|
|
4215
|
-
"aria-required": ariaRequired ?? (required || void 0),
|
|
4216
|
-
disabled,
|
|
4217
|
-
onClick: () => setOpen((current) => !current),
|
|
4218
|
-
onKeyDown: handleKeyDown,
|
|
4219
|
-
...ariaProps,
|
|
4220
|
-
children: [
|
|
4221
|
-
/* @__PURE__ */ jsx("span", { className: cn("sia-select__value", !selectedOption && "sia-select__placeholder"), children: selectedOption?.label ?? placeholder }),
|
|
4222
|
-
/* @__PURE__ */ jsxs("span", { className: "sia-select__actions", children: [
|
|
4223
|
-
clearable && currentValue && !disabled && /* @__PURE__ */ jsx(
|
|
4224
|
-
"span",
|
|
4225
|
-
{
|
|
4226
|
-
className: "sia-select__clear",
|
|
4227
|
-
"aria-hidden": "true",
|
|
4228
|
-
title: "Effacer la s\xE9lection",
|
|
4229
|
-
onClick: (event) => {
|
|
4230
|
-
event.stopPropagation();
|
|
4231
|
-
changeValue("");
|
|
4232
|
-
},
|
|
4233
|
-
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
4234
|
-
}
|
|
4235
|
-
),
|
|
4236
|
-
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "sia-select__chevron", "aria-hidden": "true" })
|
|
4237
|
-
] })
|
|
4238
|
-
]
|
|
4239
|
-
}
|
|
4240
|
-
),
|
|
4241
|
-
/* @__PURE__ */ jsx(
|
|
4242
|
-
Overlay,
|
|
4243
|
-
{
|
|
4244
|
-
open,
|
|
4245
|
-
anchorRef: triggerRef,
|
|
4246
|
-
onOpenChange: setOpen,
|
|
4247
|
-
placement,
|
|
4248
|
-
matchAnchorWidth: true,
|
|
4249
|
-
className: "sia-select__overlay",
|
|
4250
|
-
children: /* @__PURE__ */ jsxs("div", { className: "sia-select__panel", onKeyDown: handleKeyDown, children: [
|
|
4251
|
-
showSearch && /* @__PURE__ */ jsxs("div", { className: "sia-select__search-wrap", children: [
|
|
4252
|
-
/* @__PURE__ */ jsx(SearchIcon, { "aria-hidden": "true" }),
|
|
4253
|
-
/* @__PURE__ */ jsx(
|
|
4254
|
-
"input",
|
|
4255
|
-
{
|
|
4256
|
-
ref: searchRef,
|
|
4257
|
-
className: "sia-select__search",
|
|
4258
|
-
value: query,
|
|
4259
|
-
placeholder: searchPlaceholder,
|
|
4260
|
-
"aria-label": searchPlaceholder,
|
|
4261
|
-
onChange: (event) => setQuery(event.target.value)
|
|
4262
|
-
}
|
|
4263
|
-
),
|
|
4264
|
-
loading && /* @__PURE__ */ jsx(Spinner, { size: "xs", label: "Chargement" })
|
|
4265
|
-
] }),
|
|
4266
|
-
/* @__PURE__ */ jsx("div", { id: listboxId, role: "listbox", "aria-busy": loading || void 0, className: "sia-select__options", children: loading && !visibleOptions.length ? /* @__PURE__ */ jsx("div", { className: "sia-select__status", children: loadingText }) : loadError ? /* @__PURE__ */ jsx("div", { className: "sia-select__status sia-select__status--error", children: errorText }) : !visibleOptions.length ? /* @__PURE__ */ jsx("div", { className: "sia-select__status", children: emptyText }) : visibleOptions.map((option, index) => /* @__PURE__ */ jsxs(
|
|
4267
|
-
"button",
|
|
4268
|
-
{
|
|
4269
|
-
id: `${listboxId}-${index}`,
|
|
4270
|
-
type: "button",
|
|
4271
|
-
role: "option",
|
|
4272
|
-
"aria-selected": currentValue === option.value,
|
|
4273
|
-
disabled: option.disabled,
|
|
4274
|
-
className: cn(
|
|
4275
|
-
"sia-select__option",
|
|
4276
|
-
index === activeIndex && "sia-select__option--active"
|
|
4277
|
-
),
|
|
4278
|
-
onMouseEnter: () => setActiveIndex(index),
|
|
4279
|
-
onClick: () => choose(option),
|
|
4280
|
-
children: [
|
|
4281
|
-
/* @__PURE__ */ jsxs("span", { className: "sia-select__option-content", children: [
|
|
4282
|
-
/* @__PURE__ */ jsx("span", { children: option.label }),
|
|
4283
|
-
option.description && /* @__PURE__ */ jsx("small", { children: option.description })
|
|
4284
|
-
] }),
|
|
4285
|
-
currentValue === option.value && /* @__PURE__ */ jsx(CheckIcon, { "aria-hidden": "true" })
|
|
4286
|
-
]
|
|
4287
|
-
},
|
|
4288
|
-
option.value
|
|
4289
|
-
)) })
|
|
4290
|
-
] })
|
|
4291
|
-
}
|
|
4292
|
-
)
|
|
4293
|
-
] });
|
|
4294
|
-
});
|
|
4295
|
-
Select.displayName = "Select";
|
|
4296
4358
|
function MultiSelect({
|
|
4297
4359
|
id,
|
|
4298
4360
|
options,
|
|
@@ -5279,6 +5341,14 @@ function Field(rawProps) {
|
|
|
5279
5341
|
function isGroup(entry) {
|
|
5280
5342
|
return "group" in entry;
|
|
5281
5343
|
}
|
|
5344
|
+
function formFieldNames(fields) {
|
|
5345
|
+
const noms = [];
|
|
5346
|
+
for (const entree of fields) {
|
|
5347
|
+
if (isGroup(entree)) noms.push(...entree.fields.map((f) => f.name));
|
|
5348
|
+
else noms.push(entree.name);
|
|
5349
|
+
}
|
|
5350
|
+
return noms;
|
|
5351
|
+
}
|
|
5282
5352
|
var VIDE = {};
|
|
5283
5353
|
function Form({
|
|
5284
5354
|
fields,
|
|
@@ -5303,6 +5373,26 @@ function Form({
|
|
|
5303
5373
|
...onSubmit ? { onSubmit } : {}
|
|
5304
5374
|
});
|
|
5305
5375
|
const form = adapter ?? interne;
|
|
5376
|
+
const locale = useSiaLocale();
|
|
5377
|
+
const [echec, setEchec] = useState(null);
|
|
5378
|
+
const envoyer = () => {
|
|
5379
|
+
setEchec(null);
|
|
5380
|
+
form.submit().catch((error) => {
|
|
5381
|
+
const { fields: erreurs, message } = readSubmitError(error);
|
|
5382
|
+
const connus = new Set(formFieldNames(fields));
|
|
5383
|
+
const sousLesChamps = {};
|
|
5384
|
+
const ailleurs = [];
|
|
5385
|
+
for (const [nom, texte] of Object.entries(erreurs)) {
|
|
5386
|
+
if (connus.has(nom)) sousLesChamps[nom] = texte;
|
|
5387
|
+
else ailleurs.push(texte);
|
|
5388
|
+
}
|
|
5389
|
+
form.setErrors(sousLesChamps);
|
|
5390
|
+
if (ailleurs.length > 0) setEchec(ailleurs.join(" "));
|
|
5391
|
+
else if (Object.keys(sousLesChamps).length === 0) {
|
|
5392
|
+
setEchec(message ?? locale.submitError);
|
|
5393
|
+
}
|
|
5394
|
+
});
|
|
5395
|
+
};
|
|
5306
5396
|
const busy = loading || form.state.isSubmitting;
|
|
5307
5397
|
const submitDisabled = busy || requireDirty && !form.state.isDirty || requireValid && !form.state.isValid;
|
|
5308
5398
|
const grille = (nombre) => ({
|
|
@@ -5338,7 +5428,7 @@ function Form({
|
|
|
5338
5428
|
noValidate: true,
|
|
5339
5429
|
onSubmit: (event) => {
|
|
5340
5430
|
event.preventDefault();
|
|
5341
|
-
|
|
5431
|
+
envoyer();
|
|
5342
5432
|
},
|
|
5343
5433
|
children: [
|
|
5344
5434
|
/* @__PURE__ */ jsx("div", { className: "sia-form-grid", style: grille(columns), children: fields.map(
|
|
@@ -5357,6 +5447,15 @@ function Form({
|
|
|
5357
5447
|
)
|
|
5358
5448
|
] }, entry.group) : rendre(entry)
|
|
5359
5449
|
) }),
|
|
5450
|
+
echec && /* @__PURE__ */ jsx(
|
|
5451
|
+
Alert,
|
|
5452
|
+
{
|
|
5453
|
+
tone: "danger",
|
|
5454
|
+
className: "sia-form-error",
|
|
5455
|
+
onDismiss: () => setEchec(null),
|
|
5456
|
+
children: echec
|
|
5457
|
+
}
|
|
5458
|
+
),
|
|
5360
5459
|
actions ?? /* @__PURE__ */ jsxs("div", { className: "sia-form-actions", children: [
|
|
5361
5460
|
showClear && /* @__PURE__ */ jsx(
|
|
5362
5461
|
Button,
|
|
@@ -5392,23 +5491,15 @@ function Descriptions({ items, title, columns = 2, bordered = false, className }
|
|
|
5392
5491
|
] }, item.key)) })
|
|
5393
5492
|
] });
|
|
5394
5493
|
}
|
|
5395
|
-
function nomsDeChamps(fields) {
|
|
5396
|
-
const noms = [];
|
|
5397
|
-
for (const entree of fields) {
|
|
5398
|
-
if ("group" in entree) noms.push(...entree.fields.map((f) => f.name));
|
|
5399
|
-
else noms.push(entree.name);
|
|
5400
|
-
}
|
|
5401
|
-
return noms;
|
|
5402
|
-
}
|
|
5403
5494
|
function valeursVides(fields) {
|
|
5404
5495
|
const valeurs = {};
|
|
5405
|
-
for (const nom of
|
|
5496
|
+
for (const nom of formFieldNames(fields)) valeurs[nom] = "";
|
|
5406
5497
|
return valeurs;
|
|
5407
5498
|
}
|
|
5408
5499
|
function valeursDeLigne(row, fields) {
|
|
5409
5500
|
const source = row;
|
|
5410
5501
|
const valeurs = {};
|
|
5411
|
-
for (const nom of
|
|
5502
|
+
for (const nom of formFieldNames(fields)) {
|
|
5412
5503
|
const valeur = source[nom];
|
|
5413
5504
|
valeurs[nom] = typeof valeur === "string" || typeof valeur === "number" || typeof valeur === "boolean" || Array.isArray(valeur) ? valeur : "";
|
|
5414
5505
|
}
|
|
@@ -5453,11 +5544,12 @@ function CrudDialogs({
|
|
|
5453
5544
|
submitText: dialog?.submitText ?? (creation ? "Cr\xE9er" : "Enregistrer"),
|
|
5454
5545
|
requireDirty: modification,
|
|
5455
5546
|
onSubmit: async (values) => {
|
|
5456
|
-
await onSubmit?.(values, {
|
|
5547
|
+
const resultat = await onSubmit?.(values, {
|
|
5457
5548
|
mode: creation ? "create" : "edit",
|
|
5458
5549
|
...state?.row !== void 0 ? { row: state.row } : {},
|
|
5459
5550
|
...state?.index !== void 0 ? { index: state.index } : {}
|
|
5460
5551
|
});
|
|
5552
|
+
if (hasFormErrors(resultat)) return resultat;
|
|
5461
5553
|
onClose();
|
|
5462
5554
|
}
|
|
5463
5555
|
},
|
|
@@ -5541,6 +5633,7 @@ function CrudPage({
|
|
|
5541
5633
|
searchKeys: clesDeRecherche,
|
|
5542
5634
|
searchPlaceholder,
|
|
5543
5635
|
onSearch,
|
|
5636
|
+
searchDelay,
|
|
5544
5637
|
loading = false,
|
|
5545
5638
|
error,
|
|
5546
5639
|
onRetry,
|
|
@@ -5548,6 +5641,9 @@ function CrudPage({
|
|
|
5548
5641
|
page,
|
|
5549
5642
|
totalPages,
|
|
5550
5643
|
onPageChange,
|
|
5644
|
+
pageSize,
|
|
5645
|
+
onPageSizeChange,
|
|
5646
|
+
pageSizeOptions,
|
|
5551
5647
|
table,
|
|
5552
5648
|
children,
|
|
5553
5649
|
className
|
|
@@ -5627,9 +5723,12 @@ function CrudPage({
|
|
|
5627
5723
|
if (!extraRowActions) {
|
|
5628
5724
|
return actionsDeLigne.length > 0 ? actionsDeLigne : void 0;
|
|
5629
5725
|
}
|
|
5726
|
+
const suppression = actionsDeLigne.filter((a) => a.key === "delete");
|
|
5727
|
+
const autres = actionsDeLigne.filter((a) => a.key !== "delete");
|
|
5630
5728
|
return (row, index) => [
|
|
5631
|
-
...
|
|
5632
|
-
...typeof extraRowActions === "function" ? extraRowActions(row, index) : extraRowActions
|
|
5729
|
+
...autres,
|
|
5730
|
+
...typeof extraRowActions === "function" ? extraRowActions(row, index) : extraRowActions,
|
|
5731
|
+
...suppression
|
|
5633
5732
|
];
|
|
5634
5733
|
}, [actionsDeLigne, extraRowActions]);
|
|
5635
5734
|
const creation = operations?.create === false ? null : operations?.create ?? {};
|
|
@@ -5663,6 +5762,7 @@ function CrudPage({
|
|
|
5663
5762
|
...searchKeys ? { searchKeys } : {},
|
|
5664
5763
|
...searchPlaceholder ? { searchPlaceholder } : {},
|
|
5665
5764
|
...onSearch ? { onSearch } : {},
|
|
5765
|
+
...searchDelay !== void 0 ? { searchDelay } : {},
|
|
5666
5766
|
...toutesLesActions ? { rowActions: toutesLesActions } : {},
|
|
5667
5767
|
...can ? { can } : {},
|
|
5668
5768
|
loading,
|
|
@@ -5725,7 +5825,10 @@ function CrudPage({
|
|
|
5725
5825
|
page,
|
|
5726
5826
|
totalPages,
|
|
5727
5827
|
onPageChange,
|
|
5728
|
-
showTotal: true
|
|
5828
|
+
showTotal: true,
|
|
5829
|
+
...pageSize !== void 0 ? { pageSize } : {},
|
|
5830
|
+
...onPageSizeChange ? { onPageSizeChange } : {},
|
|
5831
|
+
...pageSizeOptions ? { pageSizeOptions } : {}
|
|
5729
5832
|
}
|
|
5730
5833
|
)
|
|
5731
5834
|
] });
|
|
@@ -6188,6 +6291,14 @@ var PhoneInput = forwardRef(
|
|
|
6188
6291
|
[countries, initial, picked, value]
|
|
6189
6292
|
);
|
|
6190
6293
|
const national = value.startsWith(country.dial) ? value.slice(country.dial.length) : digitsOnly(value);
|
|
6294
|
+
const options = useMemo(
|
|
6295
|
+
() => countries.map((entry) => ({
|
|
6296
|
+
value: entry.code,
|
|
6297
|
+
label: `${entry.flag} ${entry.label} (${entry.dial})`,
|
|
6298
|
+
keywords: [entry.code]
|
|
6299
|
+
})),
|
|
6300
|
+
[countries]
|
|
6301
|
+
);
|
|
6191
6302
|
const commit = (next) => {
|
|
6192
6303
|
if (!controlled) setInternal(next);
|
|
6193
6304
|
onValueChange?.(next);
|
|
@@ -6209,35 +6320,31 @@ var PhoneInput = forwardRef(
|
|
|
6209
6320
|
if (country.digits) next = next.slice(0, country.digits);
|
|
6210
6321
|
commit(next ? `${country.dial}${next}` : "");
|
|
6211
6322
|
},
|
|
6212
|
-
left: /* @__PURE__ */ jsxs("span", { className: "sia-phone__country", children: [
|
|
6323
|
+
left: lockCountry ? /* @__PURE__ */ jsxs("span", { className: "sia-phone__country", children: [
|
|
6213
6324
|
/* @__PURE__ */ jsx("span", { className: "sia-phone__flag", "aria-hidden": "true", children: country.flag }),
|
|
6214
|
-
/* @__PURE__ */ jsx("span", { className: "sia-phone__dial", children: country.dial })
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
" (",
|
|
6235
|
-
entry.dial,
|
|
6236
|
-
")"
|
|
6237
|
-
] }, entry.code))
|
|
6325
|
+
/* @__PURE__ */ jsx("span", { className: "sia-phone__dial", children: country.dial })
|
|
6326
|
+
] }) : /* @__PURE__ */ jsx(
|
|
6327
|
+
Select,
|
|
6328
|
+
{
|
|
6329
|
+
variant: "embedded",
|
|
6330
|
+
searchable: true,
|
|
6331
|
+
className: "sia-phone__country",
|
|
6332
|
+
"aria-label": locale.countryCode,
|
|
6333
|
+
options,
|
|
6334
|
+
value: country.code,
|
|
6335
|
+
disabled: disabled ?? false,
|
|
6336
|
+
renderValue: () => /* @__PURE__ */ jsxs("span", { className: "sia-phone__value", children: [
|
|
6337
|
+
/* @__PURE__ */ jsx("span", { className: "sia-phone__flag", "aria-hidden": "true", children: country.flag }),
|
|
6338
|
+
/* @__PURE__ */ jsx("span", { className: "sia-phone__dial", children: country.dial })
|
|
6339
|
+
] }),
|
|
6340
|
+
onValueChange: (code) => {
|
|
6341
|
+
const next = countries.find((entry) => entry.code === code);
|
|
6342
|
+
if (!next) return;
|
|
6343
|
+
setPicked(next.code);
|
|
6344
|
+
commit(national ? `${next.dial}${national}` : "");
|
|
6238
6345
|
}
|
|
6239
|
-
|
|
6240
|
-
|
|
6346
|
+
}
|
|
6347
|
+
)
|
|
6241
6348
|
}
|
|
6242
6349
|
);
|
|
6243
6350
|
}
|
|
@@ -7189,4 +7296,4 @@ function YearPicker({ value, defaultValue = (/* @__PURE__ */ new Date()).getFull
|
|
|
7189
7296
|
return /* @__PURE__ */ jsx("select", { className: cn("sia-year-picker", className), value, defaultValue: value === void 0 ? defaultValue : void 0, onChange: (event) => onValueChange?.(Number(event.target.value)), children: years.map((year) => /* @__PURE__ */ jsx("option", { value: year, children: year }, year)) });
|
|
7190
7297
|
}
|
|
7191
7298
|
|
|
7192
|
-
export { Accordion, Alert, AlertCircleIcon, AmountDisplay, AppShell, AppShellBrand, AppShellRailItem, ArrowRightIcon, AspectRatio, AsyncState, AuditMeta, AuthLayout, Autocomplete, Avatar, AvatarGroup, Badge, BottomTabs, Breadcrumb, Button, Calendar, CalendarIcon, Can, Card, CardBody, CardFooter, CardHeader, Chart, CheckIcon, Checkbox, CheckboxGroup, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ClockIcon, Collapse, ColorPicker, CommandPalette, ConfirmDialog, Container, ContextMenu, Countdown, CrudDialogs, CrudPage, CurrencyInput, DEFAULT_COUNTRIES, DataTable, DatePicker, DateRangeFilter, DateRangePicker, DateTimePicker, Descriptions, Divider, Drawer, DrawerBody, DrawerClose, DrawerFooter, DrawerHeader, DrawerTitle, DropdownMenu, DurationDisplay, EmptyState, EntityMeta, ErrorState, EventCalendar, EyeIcon, EyeOffIcon, Field, FileUpload, FiltersBar, Form, Field as FormField, Heading, HoverCard, IconButton, ImageUpload, InfoIcon, InlineCode, Input, InputNumber, JsonEditor, KpiGrid, Label, MarkdownEditor, MenuList, MiniCalendar, MinusIcon, Modal, MonthPicker, MoreHorizontalIcon, MultiSelect, OtpInput, Overlay, PageHeader, Pagination, PasswordInput, PermissionGate, PhoneInput, PlusIcon, Popover, Progress, QRCode, Radio, RadioButton, RadioGroup, Rating, ReferenceSelect, RelativeTime, RequireSession, ResizablePanel, RichTextEditor, ScrollArea, SearchIcon, SearchInput, Select, SettingsIcon, Sidebar, Skeleton, Slider, Sparkline, Spinner, Stack, StarIcon, StatCard, Statistic, Steps, Switch, Tabs, TabsContent, TabsList, TabsTrigger, TagsInput, Text, Textarea, TimePicker, TimeRangePicker, Timeline, Timer, ToastProvider, Toaster, Toggle, ToggleGroup, Tooltip, Tour, Transfer, TrashIcon, Tree, TreeSelect, UnsavedChangesGuard, UploadIcon, WeekPicker, XIcon, YearPicker, confirmUnsavedNavigation, createUrlTableStorage, defineResource, formatDuration, formatTimeValue, initialsOf, parseTimeValue, resourceColumns, resourceDefaults, resourceDetailColumns, resourceFormFields, resourcePermissions, resourceRowKey, resourceSearchKeys, resourceValidator, tintForName, useDataTableQuery, useToast };
|
|
7299
|
+
export { Accordion, Alert, AlertCircleIcon, AmountDisplay, AppShell, AppShellBrand, AppShellRailItem, ArrowRightIcon, AspectRatio, AsyncState, AuditMeta, AuthLayout, Autocomplete, Avatar, AvatarGroup, Badge, BottomTabs, Breadcrumb, Button, Calendar, CalendarIcon, Can, Card, CardBody, CardFooter, CardHeader, Chart, CheckIcon, Checkbox, CheckboxGroup, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, ClockIcon, Collapse, ColorPicker, CommandPalette, ConfirmDialog, Container, ContextMenu, Countdown, CrudDialogs, CrudPage, CurrencyInput, DEFAULT_COUNTRIES, DEFAULT_PAGE_SIZE_OPTIONS, DataTable, DatePicker, DateRangeFilter, DateRangePicker, DateTimePicker, Descriptions, Divider, Drawer, DrawerBody, DrawerClose, DrawerFooter, DrawerHeader, DrawerTitle, DropdownMenu, DurationDisplay, EmptyState, EntityMeta, ErrorState, EventCalendar, EyeIcon, EyeOffIcon, Field, FileUpload, FiltersBar, Form, Field as FormField, Heading, HoverCard, IconButton, ImageUpload, InfoIcon, InlineCode, Input, InputNumber, JsonEditor, KpiGrid, Label, MarkdownEditor, MenuList, MiniCalendar, MinusIcon, Modal, MonthPicker, MoreHorizontalIcon, MultiSelect, OtpInput, Overlay, PageHeader, Pagination, PasswordInput, PermissionGate, PhoneInput, PlusIcon, Popover, Progress, QRCode, Radio, RadioButton, RadioGroup, Rating, ReferenceSelect, RelativeTime, RequireSession, ResizablePanel, RichTextEditor, ScrollArea, SearchIcon, SearchInput, Select, SettingsIcon, Sidebar, Skeleton, Slider, Sparkline, Spinner, Stack, StarIcon, StatCard, Statistic, Steps, Switch, Tabs, TabsContent, TabsList, TabsTrigger, TagsInput, Text, Textarea, TimePicker, TimeRangePicker, Timeline, Timer, ToastProvider, Toaster, Toggle, ToggleGroup, Tooltip, Tour, Transfer, TrashIcon, Tree, TreeSelect, UnsavedChangesGuard, UploadIcon, WeekPicker, XIcon, YearPicker, confirmUnsavedNavigation, createUrlTableStorage, defineResource, formFieldNames, formatDuration, formatTimeValue, initialsOf, parseTimeValue, resourceColumns, resourceDefaults, resourceDetailColumns, resourceFormFields, resourcePermissions, resourceRowKey, resourceSearchKeys, resourceValidator, tintForName, useDataTableQuery, useToast };
|