@zauru-sdk/components 6.18.1 → 6.19.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 (47) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/build/assets/Alerts.stories-CSBQ8R_t.js +1 -0
  3. package/build/assets/Button-HdDVNit0.js +1 -0
  4. package/build/assets/Button.stories-4PbdRo1_.js +1 -0
  5. package/build/assets/Card.stories-QwjOcKTY.js +1 -0
  6. package/build/assets/Container.stories-pWk2cF23.js +1 -0
  7. package/build/assets/Form.stories-lVdn9hAH.js +1 -0
  8. package/build/assets/Icons-DjqYUpg9.js +10 -0
  9. package/build/assets/Labels.stories-FX8D89vw.js +1 -0
  10. package/build/assets/Matrix.stories-Cxd7sZW4.js +1 -0
  11. package/build/assets/Modal.stories-CgG40zUJ.js +1 -0
  12. package/build/assets/NavBar.stories-BPC2tPzi.js +1 -0
  13. package/build/assets/SidePanel.stories-Atykcy9h.js +1 -0
  14. package/build/assets/Tab.stories-qL5aJzJZ.js +365 -0
  15. package/build/assets/Table.stories-JhlKDwAx.js +416 -0
  16. package/build/assets/Titles.stories-BIaWnH29.js +1 -0
  17. package/build/assets/Tooltip.stories-iBejLWUg.js +1 -0
  18. package/build/assets/activestorage.esm-ByWQ3T27.js +1 -0
  19. package/build/assets/axe-VDwKxXpa.js +30 -0
  20. package/build/assets/components-TO4aWqdC.js +46 -0
  21. package/build/assets/favicon-gjFwcFbF.svg +22 -0
  22. package/build/assets/index-CraKZ-Fr.css +1 -0
  23. package/build/assets/index-DxYjnckq.js +152 -0
  24. package/build/assets/index-TgOqmrBM.js +1 -0
  25. package/build/assets/manifest-B-VxemCC.webmanifest +7 -0
  26. package/build/assets/proxy-DgkUxN7K.js +9 -0
  27. package/build/assets/touch-icon-ByyUZD7t.png +0 -0
  28. package/build/index.html +28 -0
  29. package/build/meta.json +416 -0
  30. package/dist/Matrix/CheckMatrixCards.d.ts +27 -0
  31. package/dist/Matrix/ResponsiveCheckMatrix.d.ts +7 -0
  32. package/dist/Matrix/index.d.ts +2 -0
  33. package/dist/SidePanel/index.d.ts +4 -2
  34. package/dist/esm/Matrix/CheckMatrixCards.js +25 -0
  35. package/dist/esm/Matrix/ResponsiveCheckMatrix.js +11 -0
  36. package/dist/esm/Matrix/index.js +2 -0
  37. package/dist/esm/SidePanel/index.js +47 -10
  38. package/dist/esm/index.js +1 -0
  39. package/dist/index.d.ts +1 -0
  40. package/package.json +9 -9
  41. package/src/Matrix/CheckMatrixCards.tsx +137 -0
  42. package/src/Matrix/ResponsiveCheckMatrix.tsx +32 -0
  43. package/src/Matrix/index.ts +2 -0
  44. package/src/SidePanel/index.tsx +96 -12
  45. package/src/index.ts +1 -0
  46. package/stories/Matrix.stories.tsx +75 -0
  47. package/stories/SidePanel.stories.tsx +21 -0
@@ -0,0 +1,416 @@
1
+ {
2
+ "about": {
3
+ "homepage": "https://www.ladle.dev",
4
+ "github": "https://github.com/tajo/ladle",
5
+ "version": 1
6
+ },
7
+ "stories": {
8
+ "alerts--info": {
9
+ "name": "Info",
10
+ "levels": [
11
+ "Alerts"
12
+ ],
13
+ "locStart": 3,
14
+ "locEnd": 5,
15
+ "filePath": "stories/Alerts.stories.tsx",
16
+ "namedExport": "Info",
17
+ "meta": {}
18
+ },
19
+ "alerts--success": {
20
+ "name": "Success",
21
+ "levels": [
22
+ "Alerts"
23
+ ],
24
+ "locStart": 7,
25
+ "locEnd": 9,
26
+ "filePath": "stories/Alerts.stories.tsx",
27
+ "namedExport": "Success",
28
+ "meta": {}
29
+ },
30
+ "alerts--warning": {
31
+ "name": "Warning",
32
+ "levels": [
33
+ "Alerts"
34
+ ],
35
+ "locStart": 11,
36
+ "locEnd": 17,
37
+ "filePath": "stories/Alerts.stories.tsx",
38
+ "namedExport": "Warning",
39
+ "meta": {}
40
+ },
41
+ "button--actions": {
42
+ "name": "Actions",
43
+ "levels": [
44
+ "Button"
45
+ ],
46
+ "locStart": 33,
47
+ "locEnd": 52,
48
+ "filePath": "stories/Button.stories.tsx",
49
+ "namedExport": "Actions",
50
+ "meta": {}
51
+ },
52
+ "button--colors": {
53
+ "name": "Colors",
54
+ "levels": [
55
+ "Button"
56
+ ],
57
+ "locStart": 12,
58
+ "locEnd": 20,
59
+ "filePath": "stories/Button.stories.tsx",
60
+ "namedExport": "Colors",
61
+ "meta": {}
62
+ },
63
+ "button--default": {
64
+ "name": "Default",
65
+ "levels": [
66
+ "Button"
67
+ ],
68
+ "locStart": 4,
69
+ "locEnd": 4,
70
+ "filePath": "stories/Button.stories.tsx",
71
+ "namedExport": "Default",
72
+ "meta": {}
73
+ },
74
+ "button--disabled": {
75
+ "name": "Disabled",
76
+ "levels": [
77
+ "Button"
78
+ ],
79
+ "locStart": 10,
80
+ "locEnd": 10,
81
+ "filePath": "stories/Button.stories.tsx",
82
+ "namedExport": "Disabled",
83
+ "meta": {}
84
+ },
85
+ "button--dropdown": {
86
+ "name": "Dropdown",
87
+ "levels": [
88
+ "Button"
89
+ ],
90
+ "locStart": 22,
91
+ "locEnd": 31,
92
+ "filePath": "stories/Button.stories.tsx",
93
+ "namedExport": "Dropdown",
94
+ "meta": {}
95
+ },
96
+ "button--loading": {
97
+ "name": "Loading",
98
+ "levels": [
99
+ "Button"
100
+ ],
101
+ "locStart": 6,
102
+ "locEnd": 8,
103
+ "filePath": "stories/Button.stories.tsx",
104
+ "namedExport": "Loading",
105
+ "meta": {}
106
+ },
107
+ "card--default": {
108
+ "name": "Default",
109
+ "levels": [
110
+ "Card"
111
+ ],
112
+ "locStart": 3,
113
+ "locEnd": 7,
114
+ "filePath": "stories/Card.stories.tsx",
115
+ "namedExport": "Default",
116
+ "meta": {}
117
+ },
118
+ "container--collapsible": {
119
+ "name": "Collapsible",
120
+ "levels": [
121
+ "Container"
122
+ ],
123
+ "locStart": 20,
124
+ "locEnd": 24,
125
+ "filePath": "stories/Container.stories.tsx",
126
+ "namedExport": "Collapsible",
127
+ "meta": {}
128
+ },
129
+ "container--default": {
130
+ "name": "Default",
131
+ "levels": [
132
+ "Container"
133
+ ],
134
+ "locStart": 4,
135
+ "locEnd": 8,
136
+ "filePath": "stories/Container.stories.tsx",
137
+ "namedExport": "Default",
138
+ "meta": {}
139
+ },
140
+ "container--with-right-content": {
141
+ "name": "With right content",
142
+ "levels": [
143
+ "Container"
144
+ ],
145
+ "locStart": 10,
146
+ "locEnd": 18,
147
+ "filePath": "stories/Container.stories.tsx",
148
+ "namedExport": "WithRightContent",
149
+ "meta": {}
150
+ },
151
+ "form--checkbox": {
152
+ "name": "Checkbox",
153
+ "levels": [
154
+ "Form"
155
+ ],
156
+ "locStart": 26,
157
+ "locEnd": 28,
158
+ "filePath": "stories/Form.stories.tsx",
159
+ "namedExport": "Checkbox",
160
+ "meta": {}
161
+ },
162
+ "form--date-picker": {
163
+ "name": "Date picker",
164
+ "levels": [
165
+ "Form"
166
+ ],
167
+ "locStart": 30,
168
+ "locEnd": 32,
169
+ "filePath": "stories/Form.stories.tsx",
170
+ "namedExport": "DatePicker",
171
+ "meta": {}
172
+ },
173
+ "form--file-upload": {
174
+ "name": "File upload",
175
+ "levels": [
176
+ "Form"
177
+ ],
178
+ "locStart": 34,
179
+ "locEnd": 36,
180
+ "filePath": "stories/Form.stories.tsx",
181
+ "namedExport": "FileUpload",
182
+ "meta": {}
183
+ },
184
+ "form--layout": {
185
+ "name": "Layout",
186
+ "levels": [
187
+ "Form"
188
+ ],
189
+ "locStart": 38,
190
+ "locEnd": 46,
191
+ "filePath": "stories/Form.stories.tsx",
192
+ "namedExport": "Layout",
193
+ "meta": {}
194
+ },
195
+ "form--radios": {
196
+ "name": "Radios",
197
+ "levels": [
198
+ "Form"
199
+ ],
200
+ "locStart": 48,
201
+ "locEnd": 58,
202
+ "filePath": "stories/Form.stories.tsx",
203
+ "namedExport": "Radios",
204
+ "meta": {}
205
+ },
206
+ "form--select": {
207
+ "name": "Select",
208
+ "levels": [
209
+ "Form"
210
+ ],
211
+ "locStart": 14,
212
+ "locEnd": 24,
213
+ "filePath": "stories/Form.stories.tsx",
214
+ "namedExport": "Select",
215
+ "meta": {}
216
+ },
217
+ "form--text": {
218
+ "name": "Text",
219
+ "levels": [
220
+ "Form"
221
+ ],
222
+ "locStart": 10,
223
+ "locEnd": 12,
224
+ "filePath": "stories/Form.stories.tsx",
225
+ "namedExport": "Text",
226
+ "meta": {}
227
+ },
228
+ "labels--filters": {
229
+ "name": "Filters",
230
+ "levels": [
231
+ "Labels"
232
+ ],
233
+ "locStart": 8,
234
+ "locEnd": 15,
235
+ "filePath": "stories/Labels.stories.tsx",
236
+ "namedExport": "Filters",
237
+ "meta": {}
238
+ },
239
+ "labels--filters-empty": {
240
+ "name": "Filters empty",
241
+ "levels": [
242
+ "Labels"
243
+ ],
244
+ "locStart": 17,
245
+ "locEnd": 17,
246
+ "filePath": "stories/Labels.stories.tsx",
247
+ "namedExport": "FiltersEmpty",
248
+ "meta": {}
249
+ },
250
+ "labels--info": {
251
+ "name": "Info",
252
+ "levels": [
253
+ "Labels"
254
+ ],
255
+ "locStart": 4,
256
+ "locEnd": 6,
257
+ "filePath": "stories/Labels.stories.tsx",
258
+ "namedExport": "Info",
259
+ "meta": {}
260
+ },
261
+ "matrix--responsive": {
262
+ "name": "Responsive",
263
+ "levels": [
264
+ "Matrix"
265
+ ],
266
+ "locStart": 14,
267
+ "locEnd": 75,
268
+ "filePath": "stories/Matrix.stories.tsx",
269
+ "namedExport": "Responsive",
270
+ "meta": {}
271
+ },
272
+ "modal--progress": {
273
+ "name": "Progress",
274
+ "levels": [
275
+ "Modal"
276
+ ],
277
+ "locStart": 5,
278
+ "locEnd": 21,
279
+ "filePath": "stories/Modal.stories.tsx",
280
+ "namedExport": "Progress",
281
+ "meta": {}
282
+ },
283
+ "nav-bar--calidad-yellow": {
284
+ "name": "Calidad yellow",
285
+ "levels": [
286
+ "Nav bar"
287
+ ],
288
+ "locStart": 56,
289
+ "locEnd": 67,
290
+ "filePath": "stories/NavBar.stories.tsx",
291
+ "namedExport": "CalidadYellow",
292
+ "meta": {}
293
+ },
294
+ "nav-bar--costos-green": {
295
+ "name": "Costos green",
296
+ "levels": [
297
+ "Nav bar"
298
+ ],
299
+ "locStart": 44,
300
+ "locEnd": 54,
301
+ "filePath": "stories/NavBar.stories.tsx",
302
+ "namedExport": "CostosGreen",
303
+ "meta": {}
304
+ },
305
+ "nav-bar--envios-red": {
306
+ "name": "Envios red",
307
+ "levels": [
308
+ "Nav bar"
309
+ ],
310
+ "locStart": 81,
311
+ "locEnd": 92,
312
+ "filePath": "stories/NavBar.stories.tsx",
313
+ "namedExport": "EnviosRed",
314
+ "meta": {}
315
+ },
316
+ "nav-bar--laboratorio-sky": {
317
+ "name": "Laboratorio sky",
318
+ "levels": [
319
+ "Nav bar"
320
+ ],
321
+ "locStart": 69,
322
+ "locEnd": 79,
323
+ "filePath": "stories/NavBar.stories.tsx",
324
+ "namedExport": "LaboratorioSky",
325
+ "meta": {}
326
+ },
327
+ "nav-bar--recepciones-slate": {
328
+ "name": "Recepciones slate",
329
+ "levels": [
330
+ "Nav bar"
331
+ ],
332
+ "locStart": 31,
333
+ "locEnd": 42,
334
+ "filePath": "stories/NavBar.stories.tsx",
335
+ "namedExport": "RecepcionesSlate",
336
+ "meta": {}
337
+ },
338
+ "side-panel--filters": {
339
+ "name": "Filters",
340
+ "levels": [
341
+ "Side panel"
342
+ ],
343
+ "locStart": 3,
344
+ "locEnd": 21,
345
+ "filePath": "stories/SidePanel.stories.tsx",
346
+ "namedExport": "Filters",
347
+ "meta": {}
348
+ },
349
+ "tab--default": {
350
+ "name": "Default",
351
+ "levels": [
352
+ "Tab"
353
+ ],
354
+ "locStart": 3,
355
+ "locEnd": 10,
356
+ "filePath": "stories/Tab.stories.tsx",
357
+ "namedExport": "Default",
358
+ "meta": {}
359
+ },
360
+ "table--data-table": {
361
+ "name": "Data table",
362
+ "levels": [
363
+ "Table"
364
+ ],
365
+ "locStart": 23,
366
+ "locEnd": 37,
367
+ "filePath": "stories/Table.stories.tsx",
368
+ "namedExport": "DataTable",
369
+ "meta": {}
370
+ },
371
+ "table--dynamic": {
372
+ "name": "Dynamic",
373
+ "levels": [
374
+ "Table"
375
+ ],
376
+ "locStart": 4,
377
+ "locEnd": 21,
378
+ "filePath": "stories/Table.stories.tsx",
379
+ "namedExport": "Dynamic",
380
+ "meta": {}
381
+ },
382
+ "titles--hierarchy": {
383
+ "name": "Hierarchy",
384
+ "levels": [
385
+ "Titles"
386
+ ],
387
+ "locStart": 5,
388
+ "locEnd": 11,
389
+ "filePath": "stories/Titles.stories.tsx",
390
+ "namedExport": "Hierarchy",
391
+ "meta": {}
392
+ },
393
+ "tooltip--css-tooltip": {
394
+ "name": "Css tooltip",
395
+ "levels": [
396
+ "Tooltip"
397
+ ],
398
+ "locStart": 11,
399
+ "locEnd": 15,
400
+ "filePath": "stories/Tooltip.stories.tsx",
401
+ "namedExport": "CssTooltip",
402
+ "meta": {}
403
+ },
404
+ "tooltip--hover-tooltip": {
405
+ "name": "Hover tooltip",
406
+ "levels": [
407
+ "Tooltip"
408
+ ],
409
+ "locStart": 5,
410
+ "locEnd": 9,
411
+ "filePath": "stories/Tooltip.stories.tsx",
412
+ "namedExport": "HoverTooltip",
413
+ "meta": {}
414
+ }
415
+ }
416
+ }
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from "react";
2
+ export type CheckMatrixColumn = {
3
+ key: string;
4
+ label: ReactNode;
5
+ };
6
+ export type CheckMatrixRow = {
7
+ key: string;
8
+ label: ReactNode;
9
+ description?: ReactNode;
10
+ };
11
+ export interface CheckMatrixCardsProps {
12
+ rows: CheckMatrixRow[];
13
+ columns: CheckMatrixColumn[];
14
+ isChecked: (rowKey: string, columnKey: string) => boolean;
15
+ isPending?: (rowKey: string, columnKey: string) => boolean;
16
+ onToggle: (rowKey: string, columnKey: string, checked: boolean) => void;
17
+ disabled?: boolean;
18
+ renderRowAction?: (row: CheckMatrixRow) => ReactNode;
19
+ checkedLabel?: string;
20
+ uncheckedLabel?: string;
21
+ pendingLabel?: string;
22
+ emptyText?: string;
23
+ pageSize?: number;
24
+ showMoreLabel?: string;
25
+ className?: string;
26
+ }
27
+ export declare const CheckMatrixCards: ({ rows, columns, isChecked, isPending, onToggle, disabled, renderRowAction, checkedLabel, uncheckedLabel, pendingLabel, emptyText, pageSize, showMoreLabel, className, }: CheckMatrixCardsProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from "react";
2
+ import { CheckMatrixCardsProps } from "./CheckMatrixCards.js";
3
+ export interface ResponsiveCheckMatrixProps extends CheckMatrixCardsProps {
4
+ desktop: ReactNode;
5
+ desktopBreakpoint?: "sm" | "md" | "lg";
6
+ }
7
+ export declare const ResponsiveCheckMatrix: ({ desktop, desktopBreakpoint, ...cardProps }: ResponsiveCheckMatrixProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export * from "./CheckMatrixCards.js";
2
+ export * from "./ResponsiveCheckMatrix.js";
@@ -11,11 +11,13 @@ import React, { ReactNode } from "react";
11
11
  *
12
12
  * @returns A toggleable side panel component.
13
13
  */
14
- interface SidePanelProps {
14
+ export interface SidePanelProps {
15
15
  children: ReactNode;
16
16
  closeOnClickOutside?: boolean;
17
17
  widthPercentage?: number;
18
18
  buttonIcon?: "chevron" | "filter" | ReactNode;
19
+ ariaLabel?: string;
20
+ openButtonLabel?: string;
21
+ closeButtonLabel?: string;
19
22
  }
20
23
  export declare const SidePanel: React.FC<SidePanelProps>;
21
- export {};
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ export const CheckMatrixCards = ({ rows, columns, isChecked, isPending = () => false, onToggle, disabled = false, renderRowAction, checkedLabel = "Marcado", uncheckedLabel = "Sin marcar", pendingLabel = "Guardando…", emptyText = "No hay filas para mostrar.", pageSize = 20, showMoreLabel = "Mostrar más", className = "", }) => {
4
+ const safePageSize = Math.max(1, pageSize);
5
+ const [visibleCount, setVisibleCount] = useState(safePageSize);
6
+ useEffect(() => {
7
+ setVisibleCount(safePageSize);
8
+ }, [rows, safePageSize]);
9
+ if (rows.length === 0) {
10
+ return _jsx("p", { className: `p-4 text-sm text-gray-600 ${className}`, children: emptyText });
11
+ }
12
+ const visibleRows = rows.slice(0, visibleCount);
13
+ return (_jsxs("div", { className: `space-y-3 ${className}`, children: [visibleRows.map((row) => (_jsxs("fieldset", { className: "min-w-0 rounded-lg border border-gray-200 bg-white p-3 shadow-sm", children: [_jsxs("div", { className: "mb-3 flex min-w-0 items-start justify-between gap-3", children: [_jsxs("legend", { className: "min-w-0 flex-1 px-0 text-sm font-semibold text-gray-900", children: [_jsx("span", { className: "block break-words", children: row.label }), row.description ? (_jsx("span", { className: "mt-0.5 block break-words text-xs font-normal text-gray-600", children: row.description })) : null] }), renderRowAction ? (_jsx("div", { className: "shrink-0", children: renderRowAction(row) })) : null] }), _jsx("div", { className: "grid gap-2 sm:grid-cols-2", children: columns.map((column) => {
14
+ const checked = isChecked(row.key, column.key);
15
+ const pending = isPending(row.key, column.key);
16
+ const inputId = `check-matrix-${encodeURIComponent(row.key)}-${encodeURIComponent(column.key)}`;
17
+ return (_jsxs("label", { htmlFor: inputId, className: `flex min-h-11 cursor-pointer items-center gap-3 rounded-md border px-3 py-2 text-sm focus-within:ring-2 focus-within:ring-indigo-500 focus-within:ring-offset-1 ${checked
18
+ ? "border-indigo-200 bg-indigo-50 text-indigo-950"
19
+ : "border-gray-200 bg-gray-50 text-gray-800"} ${pending || disabled ? "cursor-not-allowed opacity-70" : "hover:border-indigo-300"}`, children: [_jsx("input", { id: inputId, type: "checkbox", checked: checked, disabled: disabled || pending, onChange: (event) => onToggle(row.key, column.key, event.target.checked), className: "h-5 w-5 shrink-0 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" }), _jsx("span", { className: "min-w-0 flex-1 break-words font-medium", children: column.label }), _jsx("span", { className: `shrink-0 text-xs font-medium ${checked ? "text-indigo-700" : "text-gray-600"}`, "aria-live": pending ? "polite" : undefined, children: pending
20
+ ? pendingLabel
21
+ : checked
22
+ ? checkedLabel
23
+ : uncheckedLabel })] }, column.key));
24
+ }) })] }, row.key))), visibleCount < rows.length ? (_jsxs("button", { type: "button", onClick: () => setVisibleCount((count) => count + safePageSize), className: "min-h-11 w-full cursor-pointer rounded-md border border-indigo-300 bg-white px-4 py-2 text-sm font-semibold text-indigo-700 hover:bg-indigo-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2", children: [showMoreLabel, " (", rows.length - visibleCount, ")"] })) : null] }));
25
+ };
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CheckMatrixCards, } from "./CheckMatrixCards.js";
3
+ const visibilityClasses = {
4
+ sm: { mobile: "sm:hidden", desktop: "hidden sm:block" },
5
+ md: { mobile: "md:hidden", desktop: "hidden md:block" },
6
+ lg: { mobile: "lg:hidden", desktop: "hidden lg:block" },
7
+ };
8
+ export const ResponsiveCheckMatrix = ({ desktop, desktopBreakpoint = "md", ...cardProps }) => {
9
+ const visibility = visibilityClasses[desktopBreakpoint];
10
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: visibility.mobile, children: _jsx(CheckMatrixCards, { ...cardProps }) }), _jsx("div", { className: visibility.desktop, children: desktop })] }));
11
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./CheckMatrixCards.js";
2
+ export * from "./ResponsiveCheckMatrix.js";
@@ -1,21 +1,27 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState, useEffect, useRef } from "react";
3
- import { motion, AnimatePresence } from "framer-motion";
2
+ import { useState, useEffect, useId, useRef, } from "react";
3
+ import { motion, AnimatePresence, useReducedMotion } from "framer-motion";
4
4
  // SVG icon for the left-pointing chevron
5
- const ChevronLeftIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "h-6 w-6", children: _jsx("path", { fillRule: "evenodd", d: "M7.72 12.53a.75.75 0 010-1.06l7.5-7.5a.75.75 0 111.06 1.06L9.31 12l6.97 6.97a.75.75 0 11-1.06 1.06l-7.5-7.5z", clipRule: "evenodd" }) }));
5
+ const ChevronLeftIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "h-6 w-6", "aria-hidden": "true", focusable: "false", children: _jsx("path", { fillRule: "evenodd", d: "M7.72 12.53a.75.75 0 010-1.06l7.5-7.5a.75.75 0 111.06 1.06L9.31 12l6.97 6.97a.75.75 0 11-1.06 1.06l-7.5-7.5z", clipRule: "evenodd" }) }));
6
6
  // SVG icon for the right-pointing chevron
7
- const ChevronRightIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "h-6 w-6", children: _jsx("path", { fillRule: "evenodd", d: "M16.28 11.47a.75.75 0 010 1.06l-7.5 7.5a.75.75 0 01-1.06-1.06L14.69 12 7.72 5.03a.75.75 0 011.06-1.06l7.5 7.5z", clipRule: "evenodd" }) }));
7
+ const ChevronRightIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "h-6 w-6", "aria-hidden": "true", focusable: "false", children: _jsx("path", { fillRule: "evenodd", d: "M16.28 11.47a.75.75 0 010 1.06l-7.5 7.5a.75.75 0 01-1.06-1.06L14.69 12 7.72 5.03a.75.75 0 011.06-1.06l7.5 7.5z", clipRule: "evenodd" }) }));
8
8
  // SVG icon for the filter (bars filter icon)
9
- const FilterIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "h-6 w-6", children: _jsx("path", { fillRule: "evenodd", d: "M3 6a1 1 0 011-1h16a1 1 0 110 2H4a1 1 0 01-1-1zm0 6a1 1 0 011-1h10a1 1 0 110 2H4a1 1 0 01-1-1zm0 6a1 1 0 011-1h4a1 1 0 110 2H4a1 1 0 01-1-1z", clipRule: "evenodd" }) }));
10
- export const SidePanel = ({ children, closeOnClickOutside = true, widthPercentage = 25, buttonIcon = "chevron", }) => {
9
+ const FilterIcon = () => (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "h-6 w-6", "aria-hidden": "true", focusable: "false", children: _jsx("path", { fillRule: "evenodd", d: "M3 6a1 1 0 011-1h16a1 1 0 110 2H4a1 1 0 01-1-1zm0 6a1 1 0 011-1h10a1 1 0 110 2H4a1 1 0 01-1-1zm0 6a1 1 0 011-1h4a1 1 0 110 2H4a1 1 0 01-1-1z", clipRule: "evenodd" }) }));
10
+ export const SidePanel = ({ children, closeOnClickOutside = true, widthPercentage = 25, buttonIcon = "chevron", ariaLabel = "Panel lateral", openButtonLabel = "Abrir panel", closeButtonLabel = "Cerrar panel", }) => {
11
11
  const [isOpen, setIsOpen] = useState(false);
12
12
  const panelRef = useRef(null);
13
+ const closeButtonRef = useRef(null);
14
+ const triggerButtonRef = useRef(null);
15
+ const wasOpenRef = useRef(false);
16
+ const panelId = useId();
17
+ const shouldReduceMotion = useReducedMotion();
13
18
  const togglePanel = () => {
14
- setIsOpen(!isOpen);
19
+ setIsOpen((open) => !open);
15
20
  };
16
21
  useEffect(() => {
17
22
  const handleClickOutside = (event) => {
18
- if (closeOnClickOutside &&
23
+ if (isOpen &&
24
+ closeOnClickOutside &&
19
25
  panelRef.current &&
20
26
  !panelRef.current.contains(event.target)) {
21
27
  setIsOpen(false);
@@ -25,7 +31,34 @@ export const SidePanel = ({ children, closeOnClickOutside = true, widthPercentag
25
31
  return () => {
26
32
  document.removeEventListener("mousedown", handleClickOutside);
27
33
  };
28
- }, [closeOnClickOutside]);
34
+ }, [closeOnClickOutside, isOpen]);
35
+ useEffect(() => {
36
+ if (!isOpen)
37
+ return;
38
+ const handleEscape = (event) => {
39
+ if (event.key === "Escape")
40
+ setIsOpen(false);
41
+ };
42
+ document.addEventListener("keydown", handleEscape);
43
+ return () => document.removeEventListener("keydown", handleEscape);
44
+ }, [isOpen]);
45
+ useEffect(() => {
46
+ if (isOpen) {
47
+ wasOpenRef.current = true;
48
+ closeButtonRef.current?.focus();
49
+ const previousOverflow = document.body.style.overflow;
50
+ if (window.matchMedia("(max-width: 767px)").matches) {
51
+ document.body.style.overflow = "hidden";
52
+ }
53
+ return () => {
54
+ document.body.style.overflow = previousOverflow;
55
+ };
56
+ }
57
+ if (wasOpenRef.current) {
58
+ wasOpenRef.current = false;
59
+ triggerButtonRef.current?.focus();
60
+ }
61
+ }, [isOpen]);
29
62
  const renderIcon = () => {
30
63
  if (typeof buttonIcon === "string") {
31
64
  switch (buttonIcon) {
@@ -41,5 +74,9 @@ export const SidePanel = ({ children, closeOnClickOutside = true, widthPercentag
41
74
  return buttonIcon;
42
75
  }
43
76
  };
44
- return (_jsxs(_Fragment, { children: [_jsxs(motion.div, { ref: panelRef, initial: { x: "100%" }, animate: { x: isOpen ? 0 : "100%" }, transition: { type: "spring", stiffness: 300, damping: 30 }, className: `fixed top-0 right-0 h-full bg-white shadow-lg z-[9999] overflow-y-auto`, style: { width: `${widthPercentage}%` }, children: [_jsx("button", { onClick: togglePanel, className: "absolute top-4 left-4 p-2 rounded-full bg-gray-200 hover:bg-gray-300 transition-colors", children: _jsx(ChevronRightIcon, {}) }), _jsx("div", { className: "p-6 mt-16", children: children })] }), _jsx(AnimatePresence, { children: !isOpen && (_jsx(motion.button, { initial: { opacity: 0, x: 20 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: 20 }, transition: { duration: 0.2 }, onClick: togglePanel, className: `fixed top-1/2 right-0 transform -translate-y-1/2 bg-indigo-600 text-white p-3 rounded-l-lg shadow-md hover:bg-indigo-700 transition-colors z-[10000]`, children: renderIcon() })) })] }));
77
+ return (_jsxs(_Fragment, { children: [_jsxs(motion.div, { id: panelId, ref: panelRef, role: "dialog", "aria-modal": isOpen ? "true" : undefined, "aria-label": ariaLabel, "aria-hidden": !isOpen, initial: { x: "100%" }, animate: { x: isOpen ? 0 : "100%" }, transition: shouldReduceMotion
78
+ ? { duration: 0 }
79
+ : { type: "spring", stiffness: 300, damping: 30 }, className: "fixed right-0 top-0 z-[9999] h-full w-[calc(100%-1rem)] overflow-y-auto bg-white shadow-lg sm:w-[min(28rem,calc(100%-2rem))] md:w-[var(--side-panel-width)]", style: {
80
+ "--side-panel-width": `${widthPercentage}%`,
81
+ }, children: [_jsx("button", { ref: closeButtonRef, type: "button", onClick: togglePanel, "aria-label": closeButtonLabel, className: "absolute left-4 top-4 min-h-11 min-w-11 cursor-pointer rounded-full bg-gray-200 p-2 transition-colors hover:bg-gray-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 md:min-h-0 md:min-w-0", children: _jsx(ChevronRightIcon, {}) }), _jsx("div", { className: "mt-16 p-4 sm:p-6", children: children })] }), _jsxs(AnimatePresence, { children: [isOpen && closeOnClickOutside ? (_jsx(motion.button, { type: "button", "aria-label": closeButtonLabel, initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: shouldReduceMotion ? 0 : 0.15 }, onClick: () => setIsOpen(false), className: "fixed inset-0 z-[9998] cursor-default bg-black/30 md:hidden" })) : null, !isOpen && (_jsx(motion.button, { ref: triggerButtonRef, type: "button", "aria-label": openButtonLabel, "aria-expanded": isOpen, "aria-controls": panelId, initial: { opacity: 0, x: 20 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: 20 }, transition: { duration: shouldReduceMotion ? 0 : 0.2 }, onClick: togglePanel, className: "fixed right-0 top-1/2 z-[10000] min-h-11 min-w-11 -translate-y-1/2 cursor-pointer rounded-l-lg bg-indigo-600 p-3 text-white shadow-md transition-colors hover:bg-indigo-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2", children: renderIcon() }))] })] }));
45
82
  };
package/dist/esm/index.js CHANGED
@@ -3,6 +3,7 @@ export * from "./AccessControl/index.js";
3
3
  export * from "./BlockUI/index.js";
4
4
  export * from "./Buttons/index.js";
5
5
  export * from "./Card/index.js";
6
+ export * from "./Matrix/index.js";
6
7
  export * from "./ConnectionState/index.js";
7
8
  export * from "./Chat/index.js";
8
9
  export * from "./Containers/index.js";
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./AccessControl/index.js";
3
3
  export * from "./BlockUI/index.js";
4
4
  export * from "./Buttons/index.js";
5
5
  export * from "./Card/index.js";
6
+ export * from "./Matrix/index.js";
6
7
  export * from "./ConnectionState/index.js";
7
8
  export * from "./Chat/index.js";
8
9
  export * from "./Containers/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zauru-sdk/components",
3
- "version": "6.18.1",
3
+ "version": "6.19.0",
4
4
  "description": "Componentes reutilizables en las WebApps de Zauru.",
5
5
  "main": "./dist/esm/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -27,8 +27,8 @@
27
27
  "@tailwindcss/forms": "^0.5.7",
28
28
  "@types/jsonwebtoken": "^9.0.2",
29
29
  "@types/rails__activestorage": "^7.1.1",
30
- "@types/react": "^19.0.0",
31
- "@types/react-dom": "^19.0.0",
30
+ "@types/react": "^18.2.20",
31
+ "@types/react-dom": "^18.2.7",
32
32
  "@types/styled-components": "^5.1.34",
33
33
  "autoprefixer": "^10.6.0",
34
34
  "postcss": "^8.4.35",
@@ -44,12 +44,12 @@
44
44
  "@reduxjs/toolkit": "^2.2.1",
45
45
  "@remix-run/node": "^2.8.1",
46
46
  "@remix-run/react": "^2.8.1",
47
- "@zauru-sdk/common": "^6.14.1",
48
- "@zauru-sdk/hooks": "^6.4.3",
47
+ "@zauru-sdk/common": "^6.14.2",
48
+ "@zauru-sdk/hooks": "^6.4.4",
49
49
  "@zauru-sdk/icons": "^6.2.0",
50
- "@zauru-sdk/redux": "^6.8.3",
51
- "@zauru-sdk/types": "^6.30.0",
52
- "@zauru-sdk/utils": "^6.30.1",
50
+ "@zauru-sdk/redux": "^6.8.4",
51
+ "@zauru-sdk/types": "^6.30.2",
52
+ "@zauru-sdk/utils": "^6.30.3",
53
53
  "browser-image-compression": "^2.0.2",
54
54
  "framer-motion": "^12.0.0",
55
55
  "jsonwebtoken": "^9.0.2",
@@ -62,5 +62,5 @@
62
62
  "styled-components": "^5.3.5",
63
63
  "zod": "^3.23.8"
64
64
  },
65
- "gitHead": "dc5f6e04a2c4254710cbd86cb7016beefd84b9be"
65
+ "gitHead": "c0b80c26ce1e4788cb7683fb6514ad449b46ac59"
66
66
  }