@dododog/ui 0.14.1 → 0.16.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.
Files changed (73) hide show
  1. package/dist/chunk-5KOWMIWK.mjs +110 -0
  2. package/dist/{chunk-MCF3EQTV.js → chunk-73BHQJW6.js} +13 -1
  3. package/dist/{chunk-U3XWNFHH.js → chunk-A3M3XQ35.js} +96 -29
  4. package/dist/chunk-CPBDDGRX.mjs +572 -0
  5. package/dist/chunk-DJTFRMRY.js +595 -0
  6. package/dist/{chunk-NHB2TI2B.js → chunk-FHAWYXPX.js} +1 -1
  7. package/dist/{chunk-5UNG2O64.js → chunk-FR46MMNP.js} +7 -1
  8. package/dist/{chunk-I4S3R6C6.js → chunk-JUB3NGJR.js} +51 -6
  9. package/dist/chunk-JWQ2OUEG.js +132 -0
  10. package/dist/{chunk-EEIPCJQ2.mjs → chunk-KWQKC5TG.mjs} +1 -1
  11. package/dist/{chunk-IJIUUBFT.js → chunk-OUN5BU4Z.js} +1 -1
  12. package/dist/{chunk-DMCMWOBJ.mjs → chunk-PBXH4I5N.mjs} +51 -6
  13. package/dist/{chunk-ERL3WXNY.mjs → chunk-PZZWQ6IG.mjs} +5 -5
  14. package/dist/{chunk-L7OYR6U3.js → chunk-R4G5LFPN.js} +1 -1
  15. package/dist/{chunk-F2BUMJYW.mjs → chunk-RBVTV3LA.mjs} +1 -1
  16. package/dist/{chunk-B47HQHX3.mjs → chunk-RGZHSI2G.mjs} +1 -1
  17. package/dist/{chunk-GXKON34B.js → chunk-RTI25IBR.js} +1 -1
  18. package/dist/{chunk-GBWVIY3C.mjs → chunk-UJEIFKSK.mjs} +96 -29
  19. package/dist/{chunk-3R7PT3JG.js → chunk-USJDHMKS.js} +40 -6
  20. package/dist/{chunk-333YD5QI.mjs → chunk-WNBZXXFA.mjs} +40 -6
  21. package/dist/chunk-WY24TZ4R.mjs +94 -0
  22. package/dist/{chunk-JWOV5H6G.mjs → chunk-X53C3IQC.mjs} +7 -1
  23. package/dist/chunk-XBNIHUSG.js +116 -0
  24. package/dist/{chunk-TDGU5Y2P.js → chunk-XOFTU3T7.js} +5 -5
  25. package/dist/{chunk-NZ7GF6RF.mjs → chunk-YOMOULLR.mjs} +13 -1
  26. package/dist/{chunk-ZZ4EWC53.mjs → chunk-Z7CF7EQJ.mjs} +1 -1
  27. package/dist/components/Accordion/index.js +2 -2
  28. package/dist/components/Accordion/index.mjs +1 -1
  29. package/dist/components/Autocomplete/index.js +3 -3
  30. package/dist/components/Autocomplete/index.mjs +1 -1
  31. package/dist/components/Checkbox/index.js +2 -2
  32. package/dist/components/Checkbox/index.mjs +1 -1
  33. package/dist/components/Counter/index.d.mts +12 -0
  34. package/dist/components/Counter/index.d.ts +12 -0
  35. package/dist/components/Counter/index.js +2 -2
  36. package/dist/components/Counter/index.mjs +1 -1
  37. package/dist/components/DateRangePicker/index.d.mts +7 -1
  38. package/dist/components/DateRangePicker/index.d.ts +7 -1
  39. package/dist/components/DateRangePicker/index.js +3 -3
  40. package/dist/components/DateRangePicker/index.mjs +1 -1
  41. package/dist/components/Drawer/index.d.mts +21 -1
  42. package/dist/components/Drawer/index.d.ts +21 -1
  43. package/dist/components/Drawer/index.js +2 -2
  44. package/dist/components/Drawer/index.mjs +1 -1
  45. package/dist/components/DualRangeSlider/index.js +2 -2
  46. package/dist/components/DualRangeSlider/index.mjs +1 -1
  47. package/dist/components/Input/index.js +3 -3
  48. package/dist/components/Input/index.mjs +1 -1
  49. package/dist/components/Lightbox/index.d.mts +2 -0
  50. package/dist/components/Lightbox/index.d.ts +2 -0
  51. package/dist/components/Lightbox/index.js +2 -2
  52. package/dist/components/Lightbox/index.mjs +1 -1
  53. package/dist/components/RadioGroup/index.js +2 -2
  54. package/dist/components/RadioGroup/index.mjs +1 -1
  55. package/dist/components/Select/index.d.mts +8 -0
  56. package/dist/components/Select/index.d.ts +8 -0
  57. package/dist/components/Select/index.js +3 -3
  58. package/dist/components/Select/index.mjs +1 -1
  59. package/dist/components/Switch/index.d.mts +41 -1
  60. package/dist/components/Switch/index.d.ts +41 -1
  61. package/dist/components/Switch/index.js +4 -4
  62. package/dist/components/Switch/index.mjs +1 -1
  63. package/dist/components/Textarea/index.js +3 -3
  64. package/dist/components/Textarea/index.mjs +1 -1
  65. package/dist/index.js +81 -81
  66. package/dist/index.mjs +20 -20
  67. package/package.json +1 -1
  68. package/dist/chunk-AIA3NHCK.js +0 -373
  69. package/dist/chunk-FL3GD5FJ.mjs +0 -350
  70. package/dist/chunk-LRNSVRUN.mjs +0 -55
  71. package/dist/chunk-T4AT3YCT.js +0 -77
  72. package/dist/chunk-VWFY24XF.js +0 -89
  73. package/dist/chunk-ZLF7IL3Y.mjs +0 -67
@@ -0,0 +1,110 @@
1
+ import { cn } from './chunk-IMKLN273.mjs';
2
+ import * as React from 'react';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ var SIDE_CLASSES = {
6
+ right: "top-0 bottom-0 right-0 w-full max-w-md",
7
+ left: "top-0 bottom-0 left-0 w-full max-w-md",
8
+ bottom: "inset-x-0 bottom-0 w-full max-h-[90dvh] rounded-t-3xl"
9
+ };
10
+ var Drawer = React.forwardRef(
11
+ ({
12
+ isOpen,
13
+ onClose,
14
+ children,
15
+ side = "right",
16
+ title,
17
+ labelledById,
18
+ className,
19
+ overlayClassName,
20
+ contentClassName,
21
+ closeLabel = "Fermer"
22
+ }, ref) => {
23
+ React.useEffect(() => {
24
+ if (!isOpen) return;
25
+ const handleKeyDown = (e) => {
26
+ if (e.key === "Escape") onClose();
27
+ };
28
+ document.addEventListener("keydown", handleKeyDown);
29
+ return () => document.removeEventListener("keydown", handleKeyDown);
30
+ }, [isOpen, onClose]);
31
+ React.useEffect(() => {
32
+ if (!isOpen) return;
33
+ const prev = document.body.style.overflow;
34
+ document.body.style.overflow = "hidden";
35
+ return () => {
36
+ document.body.style.overflow = prev;
37
+ };
38
+ }, [isOpen]);
39
+ if (!isOpen) return null;
40
+ return /* @__PURE__ */ jsxs(
41
+ "div",
42
+ {
43
+ ref,
44
+ className: cn("fixed inset-0 z-50", overlayClassName),
45
+ role: "dialog",
46
+ "aria-modal": "true",
47
+ "aria-labelledby": labelledById,
48
+ "aria-label": labelledById ? void 0 : title,
49
+ children: [
50
+ /* @__PURE__ */ jsx(
51
+ "div",
52
+ {
53
+ className: "absolute inset-0 bg-black/50 transition-opacity",
54
+ onClick: onClose,
55
+ "aria-hidden": "true"
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsxs(
59
+ "div",
60
+ {
61
+ className: cn(
62
+ "absolute bg-white shadow-xl flex flex-col overflow-hidden",
63
+ SIDE_CLASSES[side],
64
+ className
65
+ ),
66
+ children: [
67
+ /* @__PURE__ */ jsxs(
68
+ "div",
69
+ {
70
+ className: cn(
71
+ "flex items-center gap-2 px-4 h-16 shrink-0",
72
+ title ? "justify-between border-b border-gray-100" : "justify-end"
73
+ ),
74
+ children: [
75
+ title && /* @__PURE__ */ jsx("h2", { className: "text-lg font-heading font-semibold text-primary truncate", children: title }),
76
+ /* @__PURE__ */ jsx(
77
+ "button",
78
+ {
79
+ type: "button",
80
+ onClick: onClose,
81
+ className: "p-2 hover:bg-gray-100 rounded-full transition-colors shrink-0",
82
+ "aria-label": closeLabel,
83
+ children: /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
84
+ /* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
85
+ /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
86
+ ] })
87
+ }
88
+ )
89
+ ]
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsx(
93
+ "div",
94
+ {
95
+ "data-drawer-content": "",
96
+ className: cn("flex-1 overflow-y-auto overscroll-contain", contentClassName),
97
+ children
98
+ }
99
+ )
100
+ ]
101
+ }
102
+ )
103
+ ]
104
+ }
105
+ );
106
+ }
107
+ );
108
+ Drawer.displayName = "Drawer";
109
+
110
+ export { Drawer };
@@ -73,11 +73,15 @@ Accordion.displayName = "Accordion";
73
73
  function AccordionItem({ title, isOpen, onToggle, children }) {
74
74
  const contentRef = React__namespace.useRef(null);
75
75
  const [height, setHeight] = React__namespace.useState(0);
76
+ const baseId = React__namespace.useId();
77
+ const headerId = `${baseId}-header`;
78
+ const panelId = `${baseId}-panel`;
76
79
  React__namespace.useEffect(() => {
77
80
  if (contentRef.current) {
78
81
  setHeight(isOpen ? contentRef.current.scrollHeight : 0);
79
82
  }
80
83
  }, [isOpen]);
84
+ const inertProps = isOpen ? {} : { inert: "" };
81
85
  return /* @__PURE__ */ jsxRuntime.jsxs(
82
86
  "div",
83
87
  {
@@ -89,8 +93,10 @@ function AccordionItem({ title, isOpen, onToggle, children }) {
89
93
  /* @__PURE__ */ jsxRuntime.jsxs(
90
94
  "button",
91
95
  {
96
+ id: headerId,
92
97
  onClick: onToggle,
93
98
  "aria-expanded": isOpen,
99
+ "aria-controls": panelId,
94
100
  className: "w-full flex items-center justify-between py-5 px-5 text-left group",
95
101
  children: [
96
102
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -106,6 +112,7 @@ function AccordionItem({ title, isOpen, onToggle, children }) {
106
112
  /* @__PURE__ */ jsxRuntime.jsx(
107
113
  "div",
108
114
  {
115
+ "aria-hidden": "true",
109
116
  className: chunkADIDI7AJ_js.cn(
110
117
  "w-7 h-7 rounded-full flex items-center justify-center shrink-0 transition-all duration-300",
111
118
  isOpen ? "bg-secondary text-white" : "bg-gray-100 text-gray-600 group-hover:bg-secondary/10 group-hover:text-secondary"
@@ -122,7 +129,12 @@ function AccordionItem({ title, isOpen, onToggle, children }) {
122
129
  /* @__PURE__ */ jsxRuntime.jsx(
123
130
  "div",
124
131
  {
125
- style: { height },
132
+ id: panelId,
133
+ role: "region",
134
+ "aria-labelledby": headerId,
135
+ "aria-hidden": isOpen ? void 0 : true,
136
+ ...inertProps,
137
+ style: { height, visibility: isOpen ? void 0 : "hidden" },
126
138
  className: "overflow-hidden transition-all duration-500 ease-out",
127
139
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: contentRef, className: "pb-5 px-5 pr-12", children })
128
140
  }
@@ -24,10 +24,30 @@ function _interopNamespace(e) {
24
24
 
25
25
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
26
26
 
27
+ var FOCUSABLE_SELECTOR = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
27
28
  var Lightbox = React__namespace.forwardRef(
28
- ({ images, initialIndex = 0, open, onClose, className }, ref) => {
29
+ ({
30
+ images,
31
+ initialIndex = 0,
32
+ open,
33
+ onClose,
34
+ className,
35
+ "aria-label": ariaLabel = "Visionneuse d'images"
36
+ }, ref) => {
29
37
  const [current, setCurrent] = React__namespace.useState(initialIndex);
30
38
  const touchStartX = React__namespace.useRef(0);
39
+ const containerRef = React__namespace.useRef(null);
40
+ const setRefs = React__namespace.useCallback(
41
+ (node) => {
42
+ containerRef.current = node;
43
+ if (typeof ref === "function") {
44
+ ref(node);
45
+ } else if (ref) {
46
+ ref.current = node;
47
+ }
48
+ },
49
+ [ref]
50
+ );
31
51
  React__namespace.useEffect(() => {
32
52
  if (open) setCurrent(initialIndex);
33
53
  }, [open, initialIndex]);
@@ -37,6 +57,28 @@ var Lightbox = React__namespace.forwardRef(
37
57
  if (e.key === "Escape") onClose();
38
58
  if (e.key === "ArrowLeft") setCurrent((c) => (c - 1 + images.length) % images.length);
39
59
  if (e.key === "ArrowRight") setCurrent((c) => (c + 1) % images.length);
60
+ if (e.key === "Tab") {
61
+ const node = containerRef.current;
62
+ if (!node) return;
63
+ const items = Array.from(
64
+ node.querySelectorAll(FOCUSABLE_SELECTOR)
65
+ );
66
+ if (items.length === 0) {
67
+ e.preventDefault();
68
+ return;
69
+ }
70
+ const first = items[0];
71
+ const last = items[items.length - 1];
72
+ const active = document.activeElement;
73
+ const inside = active instanceof Node && node.contains(active);
74
+ if (e.shiftKey && (!inside || active === first)) {
75
+ e.preventDefault();
76
+ last.focus();
77
+ } else if (!e.shiftKey && (!inside || active === last)) {
78
+ e.preventDefault();
79
+ first.focus();
80
+ }
81
+ }
40
82
  }
41
83
  document.addEventListener("keydown", handleKeyDown);
42
84
  document.body.style.overflow = "hidden";
@@ -45,13 +87,24 @@ var Lightbox = React__namespace.forwardRef(
45
87
  document.body.style.overflow = "";
46
88
  };
47
89
  }, [open, images.length, onClose]);
90
+ React__namespace.useEffect(() => {
91
+ if (!open) return;
92
+ const previouslyFocused = document.activeElement;
93
+ const node = containerRef.current;
94
+ const target = node?.querySelector(FOCUSABLE_SELECTOR) ?? node ?? null;
95
+ target?.focus?.();
96
+ return () => {
97
+ previouslyFocused?.focus?.();
98
+ };
99
+ }, [open]);
48
100
  if (!open || images.length === 0) return null;
49
101
  const prev = () => setCurrent((c) => (c - 1 + images.length) % images.length);
50
102
  const next = () => setCurrent((c) => (c + 1) % images.length);
51
103
  return /* @__PURE__ */ jsxRuntime.jsxs(
52
104
  "div",
53
105
  {
54
- ref,
106
+ ref: setRefs,
107
+ tabIndex: -1,
55
108
  className: chunkADIDI7AJ_js.cn(
56
109
  "fixed inset-0 z-50 flex items-center justify-center bg-black/90",
57
110
  className
@@ -59,14 +112,14 @@ var Lightbox = React__namespace.forwardRef(
59
112
  onClick: onClose,
60
113
  role: "dialog",
61
114
  "aria-modal": "true",
62
- "aria-label": "Image viewer",
115
+ "aria-label": ariaLabel,
63
116
  children: [
64
117
  /* @__PURE__ */ jsxRuntime.jsx(
65
118
  "button",
66
119
  {
67
120
  onClick: onClose,
68
121
  className: "absolute top-4 right-4 z-10 w-10 h-10 rounded-full bg-white/10 backdrop-blur-sm flex items-center justify-center text-white hover:bg-white/20 transition-colors",
69
- "aria-label": "Close",
122
+ "aria-label": "Fermer la visionneuse",
70
123
  children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
71
124
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18" }),
72
125
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 6 12 12" })
@@ -74,9 +127,12 @@ var Lightbox = React__namespace.forwardRef(
74
127
  }
75
128
  ),
76
129
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-4 left-4 z-10 px-3 py-1.5 rounded-full bg-white/10 backdrop-blur-sm text-white text-sm", children: [
77
- current + 1,
78
- " / ",
79
- images.length
130
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { "aria-hidden": "true", children: [
131
+ current + 1,
132
+ " / ",
133
+ images.length
134
+ ] }),
135
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", "aria-live": "polite", "aria-atomic": "true", children: `Image ${current + 1} sur ${images.length}` })
80
136
  ] }),
81
137
  /* @__PURE__ */ jsxRuntime.jsx(
82
138
  "div",
@@ -112,7 +168,7 @@ var Lightbox = React__namespace.forwardRef(
112
168
  prev();
113
169
  },
114
170
  className: "absolute left-4 top-1/2 -translate-y-1/2 w-12 h-12 rounded-full bg-white/10 backdrop-blur-sm flex items-center justify-center text-white hover:bg-white/20 transition-colors",
115
- "aria-label": "Previous image",
171
+ "aria-label": "Image pr\xE9c\xE9dente",
116
172
  children: /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) })
117
173
  }
118
174
  ),
@@ -124,33 +180,44 @@ var Lightbox = React__namespace.forwardRef(
124
180
  next();
125
181
  },
126
182
  className: "absolute right-4 top-1/2 -translate-y-1/2 w-12 h-12 rounded-full bg-white/10 backdrop-blur-sm flex items-center justify-center text-white hover:bg-white/20 transition-colors",
127
- "aria-label": "Next image",
183
+ "aria-label": "Image suivante",
128
184
  children: /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 18 6-6-6-6" }) })
129
185
  }
130
186
  )
131
187
  ] }),
132
- images.length > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2 max-w-[80vw] overflow-x-auto px-4 py-2", children: images.map((img, i) => /* @__PURE__ */ jsxRuntime.jsx(
133
- "button",
188
+ images.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
189
+ "div",
134
190
  {
135
- onClick: (e) => {
136
- e.stopPropagation();
137
- setCurrent(i);
138
- },
139
- className: chunkADIDI7AJ_js.cn(
140
- "w-16 h-12 rounded-lg overflow-hidden flex-shrink-0 border-2 transition-all",
141
- i === current ? "border-white opacity-100" : "border-transparent opacity-50 hover:opacity-75"
142
- ),
143
- children: /* @__PURE__ */ jsxRuntime.jsx(
144
- "img",
191
+ role: "group",
192
+ "aria-label": "Vignettes des images",
193
+ className: "absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2 max-w-[80vw] overflow-x-auto px-4 py-2",
194
+ children: images.map((img, i) => /* @__PURE__ */ jsxRuntime.jsx(
195
+ "button",
145
196
  {
146
- src: img.src,
147
- alt: img.alt,
148
- className: "w-full h-full object-cover"
149
- }
150
- )
151
- },
152
- i
153
- )) })
197
+ onClick: (e) => {
198
+ e.stopPropagation();
199
+ setCurrent(i);
200
+ },
201
+ "aria-label": `Afficher l'image ${i + 1} : ${img.alt}`,
202
+ "aria-current": i === current ? "true" : void 0,
203
+ className: chunkADIDI7AJ_js.cn(
204
+ "w-16 h-12 rounded-lg overflow-hidden flex-shrink-0 border-2 transition-all",
205
+ i === current ? "border-white opacity-100" : "border-transparent opacity-50 hover:opacity-75"
206
+ ),
207
+ children: /* @__PURE__ */ jsxRuntime.jsx(
208
+ "img",
209
+ {
210
+ src: img.src,
211
+ alt: "",
212
+ "aria-hidden": "true",
213
+ className: "w-full h-full object-cover"
214
+ }
215
+ )
216
+ },
217
+ i
218
+ ))
219
+ }
220
+ )
154
221
  ]
155
222
  }
156
223
  );