@axzydev/axzy_ui_system 1.4.7 → 1.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.
Files changed (226) hide show
  1. package/README.md +2 -11
  2. package/dist/index.cjs +2174 -1570
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.css +1 -1
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.cts +232 -19
  7. package/dist/index.d.ts +232 -19
  8. package/dist/index.js +1838 -1238
  9. package/dist/index.js.map +1 -1
  10. package/dist/layered.css +1 -1
  11. package/package.json +3 -16
  12. package/src/App.tsx +90 -73
  13. package/src/components/atoms/badget/badget.tsx +23 -5
  14. package/src/components/atoms/chip/chip.tsx +3 -1
  15. package/src/components/atoms/image/image.tsx +3 -1
  16. package/src/components/atoms/input/input.tsx +8 -5
  17. package/src/components/atoms/loader/loader.tsx +3 -1
  18. package/src/components/atoms/slide/slide.props.ts +12 -0
  19. package/src/components/atoms/slide/slide.tsx +3 -0
  20. package/src/components/molecules/alert/alert.tsx +3 -1
  21. package/src/components/molecules/breadcrumbs/breadcrumbs.tsx +3 -1
  22. package/src/components/molecules/calendar/calendar.tsx +9 -6
  23. package/src/components/molecules/card/card.tsx +5 -2
  24. package/src/components/molecules/chip-input/chip-input.tsx +9 -7
  25. package/src/components/molecules/date-picker/datePicker.tsx +9 -9
  26. package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +1 -1
  27. package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +6 -3
  28. package/src/components/molecules/field/field.tsx +3 -1
  29. package/src/components/molecules/form-header/form-header.tsx +3 -1
  30. package/src/components/molecules/line-bar-chart/line-bar-chart.props.ts +2 -2
  31. package/src/components/molecules/line-bar-chart/line-bar-chart.tsx +20 -15
  32. package/src/components/molecules/masked-input/masked-input.tsx +3 -1
  33. package/src/components/molecules/multi-select/multi-select.tsx +12 -9
  34. package/src/components/molecules/pagination/pagination.tsx +11 -5
  35. package/src/components/molecules/search-select/search-select.tsx +11 -9
  36. package/src/components/molecules/select/select.tsx +6 -4
  37. package/src/components/molecules/stepper/stepper.tsx +6 -4
  38. package/src/components/molecules/table/table.props.ts +10 -2
  39. package/src/components/molecules/table/table.tsx +163 -114
  40. package/src/components/molecules/time-picker/timePicker.tsx +8 -6
  41. package/src/components/molecules/wysiwyg/wysiwyg.tsx +23 -12
  42. package/src/components/organisms/confirm-dialog/confirm-dialog.props.ts +4 -4
  43. package/src/components/organisms/confirm-dialog/confirm-dialog.tsx +16 -8
  44. package/src/components/organisms/data-table/dataTable.props.ts +3 -2
  45. package/src/components/organisms/data-table/dataTable.tsx +149 -81
  46. package/src/components/organisms/dialog/dialog.tsx +3 -0
  47. package/src/components/organisms/drawer/drawer.tsx +3 -0
  48. package/src/components/organisms/dropfile/dropfile.tsx +19 -17
  49. package/src/components/organisms/form-builder/fieldRenderer.tsx +4 -2
  50. package/src/components/organisms/navbar/navbar.tsx +4 -2
  51. package/src/components/organisms/page-header/page-header.tsx +3 -1
  52. package/src/components/organisms/searchTable/components/PaginationControls.tsx +8 -6
  53. package/src/components/organisms/searchTable/components/PaginationInfo.tsx +3 -1
  54. package/src/components/organisms/searchTable/components/SearchAndSortBar.tsx +7 -5
  55. package/src/components/organisms/searchTable/components/SearchInput.tsx +4 -2
  56. package/src/components/organisms/searchTable/components/SortButton.tsx +13 -11
  57. package/src/components/organisms/searchTable/components/TableEmptyState.tsx +4 -2
  58. package/src/components/organisms/searchTable/components/TableRow.tsx +6 -4
  59. package/src/components/organisms/searchTable/searchTable.tsx +4 -2
  60. package/src/components/organisms/sidebar/sidebar.props.ts +1 -1
  61. package/src/components/organisms/sidebar/sidebar.tsx +9 -4
  62. package/src/components/organisms/toast/toast.tsx +3 -1
  63. package/src/components/organisms/topbar/topbar.tsx +4 -2
  64. package/src/components/templates/page/page.props.ts +4 -4
  65. package/src/components/templates/page/page.tsx +6 -4
  66. package/src/components/theme-provider/themeProvider.tsx +28 -17
  67. package/src/dev.css +77 -2
  68. package/src/global.d.ts +10 -0
  69. package/src/i18n/context.ts +9 -0
  70. package/src/i18n/index.ts +22 -0
  71. package/src/i18n/locales/en.ts +163 -0
  72. package/src/i18n/locales/es.ts +165 -0
  73. package/src/i18n/provider.tsx +44 -0
  74. package/src/i18n/translator.ts +82 -0
  75. package/src/i18n/types.ts +54 -0
  76. package/src/i18n/useITTranslation.ts +20 -0
  77. package/src/index.css +0 -1
  78. package/src/index.ts +9 -3
  79. package/src/sandbox/LandingShowcase.tsx +224 -580
  80. package/src/sandbox/NotFoundShowcase.tsx +51 -36
  81. package/src/sandbox/TopbarSearch.tsx +6 -4
  82. package/src/sandbox/controls.tsx +180 -0
  83. package/src/sandbox/i18n.ts +1929 -0
  84. package/src/sandbox/icons.tsx +25 -0
  85. package/src/sandbox/locale.tsx +72 -0
  86. package/src/sandbox/ui.tsx +377 -0
  87. package/src/sandbox/useHashRoute.ts +46 -10
  88. package/src/showcases/DataShowcases.tsx +201 -80
  89. package/src/showcases/FeedbackShowcases.tsx +37 -30
  90. package/src/showcases/FormShowcases.tsx +302 -214
  91. package/src/showcases/GettingStartedShowcase.tsx +151 -145
  92. package/src/showcases/HelpShowcase.tsx +126 -128
  93. package/src/showcases/HomeShowcase.tsx +678 -482
  94. package/src/showcases/LayoutPrimitivesShowcases.tsx +129 -114
  95. package/src/showcases/NavigationShowcases.tsx +45 -37
  96. package/src/showcases/PageShowcases.tsx +171 -152
  97. package/src/showcases/ProductoDetalle.tsx +272 -129
  98. package/src/showcases/ShowcaseLayout.tsx +270 -216
  99. package/src/showcases/SizesShowcase.tsx +123 -64
  100. package/src/showcases/StructureShowcases.tsx +157 -131
  101. package/src/showcases/portfolioUi.tsx +153 -0
  102. package/src/showcases/techIcons.ts +3 -0
  103. package/src/types/table.types.ts +110 -0
  104. package/src/utils/table.utils.ts +10 -2
  105. package/src/components/atoms/avatar/avatar.doc.mdx +0 -48
  106. package/src/components/atoms/avatar/avatar.stories.tsx +0 -64
  107. package/src/components/atoms/badget/badget.doc.mdx +0 -46
  108. package/src/components/atoms/badget/badget.stories.tsx +0 -75
  109. package/src/components/atoms/button/button.doc.mdx +0 -59
  110. package/src/components/atoms/button/button.stories.tsx +0 -173
  111. package/src/components/atoms/checkbox/checkbox.doc.mdx +0 -54
  112. package/src/components/atoms/checkbox/checkbox.stories.tsx +0 -53
  113. package/src/components/atoms/chip/chip.doc.mdx +0 -47
  114. package/src/components/atoms/chip/chip.stories.tsx +0 -64
  115. package/src/components/atoms/divider/divider.doc.mdx +0 -42
  116. package/src/components/atoms/divider/divider.stories.tsx +0 -33
  117. package/src/components/atoms/flex/flex.doc.mdx +0 -59
  118. package/src/components/atoms/flex/flex.stories.tsx +0 -70
  119. package/src/components/atoms/grid/grid.doc.mdx +0 -54
  120. package/src/components/atoms/grid/grid.stories.tsx +0 -71
  121. package/src/components/atoms/image/image.doc.mdx +0 -44
  122. package/src/components/atoms/image/image.stories.tsx +0 -48
  123. package/src/components/atoms/input/input.doc.mdx +0 -70
  124. package/src/components/atoms/input/input.stories.tsx +0 -113
  125. package/src/components/atoms/input-number/input-number.doc.mdx +0 -74
  126. package/src/components/atoms/input-number/input-number.stories.tsx +0 -111
  127. package/src/components/atoms/loader/loader.doc.mdx +0 -43
  128. package/src/components/atoms/loader/loader.stories.tsx +0 -104
  129. package/src/components/atoms/popover/popover.doc.mdx +0 -53
  130. package/src/components/atoms/popover/popover.stories.tsx +0 -24
  131. package/src/components/atoms/progress/progress.doc.mdx +0 -48
  132. package/src/components/atoms/progress/progress.stories.tsx +0 -39
  133. package/src/components/atoms/radio/radio.doc.mdx +0 -62
  134. package/src/components/atoms/radio/radio.stories.tsx +0 -48
  135. package/src/components/atoms/segmented-control/segmented-control.doc.mdx +0 -60
  136. package/src/components/atoms/segmented-control/segmented-control.stories.tsx +0 -62
  137. package/src/components/atoms/skeleton/skeleton.doc.mdx +0 -43
  138. package/src/components/atoms/skeleton/skeleton.stories.tsx +0 -29
  139. package/src/components/atoms/slide/slide.doc.mdx +0 -46
  140. package/src/components/atoms/slide/slide.stories.tsx +0 -120
  141. package/src/components/atoms/slider/slider.doc.mdx +0 -49
  142. package/src/components/atoms/slider/slider.stories.tsx +0 -29
  143. package/src/components/atoms/stack/stack.doc.mdx +0 -126
  144. package/src/components/atoms/stack/stack.stories.tsx +0 -283
  145. package/src/components/atoms/text/text.doc.mdx +0 -41
  146. package/src/components/atoms/text/text.stories.tsx +0 -66
  147. package/src/components/atoms/textarea/textarea.doc.mdx +0 -64
  148. package/src/components/atoms/textarea/textarea.stories.tsx +0 -26
  149. package/src/components/atoms/tooltip/tooltip.doc.mdx +0 -47
  150. package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -19
  151. package/src/components/isolation/isolation.stories.tsx +0 -202
  152. package/src/components/molecules/accordion/accordion.doc.mdx +0 -47
  153. package/src/components/molecules/accordion/accordion.stories.tsx +0 -68
  154. package/src/components/molecules/alert/alert.doc.mdx +0 -48
  155. package/src/components/molecules/alert/alert.stories.tsx +0 -40
  156. package/src/components/molecules/breadcrumbs/breadcrumbs.doc.mdx +0 -57
  157. package/src/components/molecules/breadcrumbs/breadcrumbs.stories.tsx +0 -20
  158. package/src/components/molecules/calendar/calendar.doc.mdx +0 -76
  159. package/src/components/molecules/calendar/calendar.stories.tsx +0 -90
  160. package/src/components/molecules/card/card.doc.mdx +0 -54
  161. package/src/components/molecules/card/card.stories.tsx +0 -57
  162. package/src/components/molecules/chip-input/chip-input.doc.mdx +0 -44
  163. package/src/components/molecules/chip-input/chip-input.stories.tsx +0 -52
  164. package/src/components/molecules/date-picker/date-picker.doc.mdx +0 -65
  165. package/src/components/molecules/date-picker/date-picker.stories.tsx +0 -88
  166. package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +0 -46
  167. package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +0 -41
  168. package/src/components/molecules/empty-state/empty-state.doc.mdx +0 -50
  169. package/src/components/molecules/empty-state/empty-state.stories.tsx +0 -19
  170. package/src/components/molecules/field/field.doc.mdx +0 -43
  171. package/src/components/molecules/field/field.stories.tsx +0 -42
  172. package/src/components/molecules/form-header/form-header.doc.mdx +0 -38
  173. package/src/components/molecules/form-header/form-header.stories.tsx +0 -52
  174. package/src/components/molecules/masked-input/masked-input.doc.mdx +0 -78
  175. package/src/components/molecules/masked-input/masked-input.stories.tsx +0 -126
  176. package/src/components/molecules/multi-select/multi-select.doc.mdx +0 -55
  177. package/src/components/molecules/multi-select/multi-select.stories.tsx +0 -59
  178. package/src/components/molecules/pagination/pagination.doc.mdx +0 -62
  179. package/src/components/molecules/pagination/pagination.stories.tsx +0 -110
  180. package/src/components/molecules/search-select/search-select.doc.mdx +0 -77
  181. package/src/components/molecules/search-select/search-select.stories.tsx +0 -146
  182. package/src/components/molecules/select/select.doc.mdx +0 -75
  183. package/src/components/molecules/select/select.stories.tsx +0 -85
  184. package/src/components/molecules/stat-card/stat-card.doc.mdx +0 -48
  185. package/src/components/molecules/stat-card/stat-card.stories.tsx +0 -40
  186. package/src/components/molecules/stepper/stepper.doc.mdx +0 -54
  187. package/src/components/molecules/stepper/stepper.stories.tsx +0 -154
  188. package/src/components/molecules/table/table.doc.mdx +0 -123
  189. package/src/components/molecules/table/table.stories.tsx +0 -402
  190. package/src/components/molecules/tabs/tabs.doc.mdx +0 -52
  191. package/src/components/molecules/tabs/tabs.stories.tsx +0 -31
  192. package/src/components/molecules/time-picker/timePicker.doc.mdx +0 -68
  193. package/src/components/molecules/time-picker/timePicker.stories.tsx +0 -130
  194. package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +0 -95
  195. package/src/components/organisms/confirm-dialog/confirm-dialog.doc.mdx +0 -60
  196. package/src/components/organisms/confirm-dialog/confirm-dialog.stories.tsx +0 -32
  197. package/src/components/organisms/data-table/ITDataTable.doc.mdx +0 -115
  198. package/src/components/organisms/data-table/ITDataTable.stories.tsx +0 -353
  199. package/src/components/organisms/dialog/dialog.doc.mdx +0 -54
  200. package/src/components/organisms/dialog/dialog.stories.tsx +0 -126
  201. package/src/components/organisms/drawer/drawer.doc.mdx +0 -59
  202. package/src/components/organisms/drawer/drawer.stories.tsx +0 -40
  203. package/src/components/organisms/dropfile/dropfile.doc.mdx +0 -74
  204. package/src/components/organisms/dropfile/dropfile.stories.tsx +0 -93
  205. package/src/components/organisms/form-builder/formBuilder.doc.mdx +0 -251
  206. package/src/components/organisms/form-builder/formBuilder.stories.tsx +0 -914
  207. package/src/components/organisms/navbar/navbar.doc.mdx +0 -77
  208. package/src/components/organisms/navbar/navbar.stories.tsx +0 -83
  209. package/src/components/organisms/page-header/page-header.doc.mdx +0 -54
  210. package/src/components/organisms/page-header/page-header.stories.tsx +0 -74
  211. package/src/components/organisms/searchTable/searchTable.doc.mdx +0 -79
  212. package/src/components/organisms/searchTable/searchTable.stories.tsx +0 -73
  213. package/src/components/organisms/sidebar/sidebar.doc.mdx +0 -176
  214. package/src/components/organisms/sidebar/sidebar.stories.tsx +0 -234
  215. package/src/components/organisms/toast/toast.doc.mdx +0 -50
  216. package/src/components/organisms/toast/toast.stories.tsx +0 -137
  217. package/src/components/organisms/topbar/topbar.doc.mdx +0 -72
  218. package/src/components/organisms/topbar/topbar.stories.tsx +0 -79
  219. package/src/components/organisms/triple-filter/tripleFilter.doc.mdx +0 -62
  220. package/src/components/organisms/triple-filter/tripleFilter.stories.tsx +0 -31
  221. package/src/components/templates/layout/layout.doc.mdx +0 -53
  222. package/src/components/templates/layout/layout.stories.tsx +0 -113
  223. package/src/components/templates/page/page.doc.mdx +0 -86
  224. package/src/components/templates/page/page.stories.tsx +0 -97
  225. package/src/components/theme-provider/themeProvider.doc.mdx +0 -85
  226. package/src/components/theme-provider/themeProvider.stories.tsx +0 -58
@@ -1,353 +0,0 @@
1
- import React, { useState, useCallback, useMemo } from 'react';
2
- import { Meta, StoryObj } from '@storybook/react';
3
- import { startOfDay, endOfDay } from 'date-fns';
4
- import ITDataTable from './dataTable';
5
- import { ITDataTableFetchParams, ITDataTableResponse } from './dataTable.props';
6
- import ITCard from '@/components/molecules/card/card';
7
- import ITBadget from '@/components/atoms/badget/badget';
8
- import ITDatePicker from '@/components/molecules/date-picker/datePicker';
9
-
10
- const meta: Meta<typeof ITDataTable> = {
11
- title: 'Data Display/ITDataTable',
12
- component: ITDataTable,
13
- decorators: [
14
- (Story) => (
15
- <div className="p-8 bg-gray-50 min-h-screen">
16
- <Story />
17
- </div>
18
- ),
19
- ],
20
- };
21
-
22
- export default meta;
23
- type Story = StoryObj<typeof ITDataTable>;
24
-
25
- // --- MOCK CONSTANTS ---
26
- const ROLES = ['ADMIN', 'CAJERO', 'TECNICO', 'SUPERVISOR'];
27
- const MOCK_DATA = Array.from({ length: 100 }).map((_, i) => ({
28
- id: i + 1,
29
- username: `user_${i + 1}`,
30
- name: `Nombre ${i + 1}`,
31
- role: ROLES[i % ROLES.length],
32
- active: i % 3 !== 0,
33
- createdAt: new Date(Date.now() - i * 86400000).toISOString(),
34
- }));
35
-
36
- // --- MOCK FETCH FUNCTION ---
37
- const mockFetchItems = async (
38
- params: ITDataTableFetchParams
39
- ): Promise<ITDataTableResponse<any>> => {
40
- console.log('Fetching with params:', params);
41
-
42
- // Simulate network delay
43
- await new Promise((resolve) => setTimeout(resolve, 800));
44
-
45
- let filtered = [...MOCK_DATA];
46
-
47
- // Apply filters
48
- Object.entries(params.filters).forEach(([key, value]) => {
49
- if (value === undefined || value === '') return;
50
-
51
- if (key === 'username') {
52
- filtered = filtered.filter(item =>
53
- item.username.toLowerCase().includes(String(value).toLowerCase())
54
- );
55
- } else if (key === 'role') {
56
- filtered = filtered.filter(item => item.role === value);
57
- } else if (key === 'active') {
58
- filtered = filtered.filter(item => item.active === value);
59
- }
60
- });
61
-
62
- // Apply sorting
63
- if (params.sort) {
64
- const { key, direction } = params.sort;
65
- filtered.sort((a: any, b: any) => {
66
- if (a[key] < b[key]) return direction === 'asc' ? -1 : 1;
67
- if (a[key] > b[key]) return direction === 'asc' ? 1 : -1;
68
- return 0;
69
- });
70
- }
71
-
72
- // Apply pagination
73
- const start = (params.page - 1) * params.limit;
74
- const end = start + params.limit;
75
- const data = filtered.slice(start, end);
76
-
77
- return {
78
- data,
79
- total: filtered.length,
80
- };
81
- };
82
-
83
- const columns = [
84
- {
85
- key: 'id',
86
- label: 'ID',
87
- type: 'number' as const,
88
- sortable: true,
89
- },
90
- {
91
- key: 'username',
92
- label: 'Usuario',
93
- type: 'string' as const,
94
- filter: true,
95
- sortable: true,
96
- },
97
- {
98
- key: 'name',
99
- label: 'Nombre Completo',
100
- type: 'string' as const,
101
- filter: true,
102
- },
103
- {
104
- key: 'role',
105
- label: 'Rol',
106
- type: 'string' as const,
107
- filter: 'catalog' as const,
108
- catalogOptions: {
109
- loading: false,
110
- data: [
111
- { id: 'ADMIN', name: 'Administrador' },
112
- { id: 'CAJERO', name: 'Cajero' },
113
- { id: 'TECNICO', name: 'Técnico' },
114
- { id: 'SUPERVISOR', name: 'Supervisor' },
115
- ],
116
- },
117
- render: (row: any) => (
118
- <ITBadget
119
- label={row.role}
120
- color={
121
- row.role === 'ADMIN' ? 'primary' :
122
- row.role === 'CAJERO' ? 'success' :
123
- row.role === 'TECNICO' ? 'warning' : 'secondary'
124
- }
125
- />
126
- )
127
- },
128
- {
129
- key: 'active',
130
- label: 'Estado',
131
- type: 'boolean' as const,
132
- filter: true,
133
- sortable: true,
134
- },
135
- ];
136
-
137
- export const Default: Story = {
138
- args: {
139
- title: 'Gestión de Usuarios',
140
- columns,
141
- fetchData: mockFetchItems,
142
- defaultItemsPerPage: 10,
143
- },
144
- };
145
-
146
- // Column widths keep the fixed layout from forcing horizontal scroll.
147
- const fixedColumns = columns.map((col, i) => ({
148
- ...col,
149
- width: [64, '28%', '34%', '22%', '16%'][i],
150
- truncate: col.type === 'string' || col.type === 'catalog',
151
- })) as any;
152
-
153
- export const FixedLayoutCompact: Story = {
154
- args: {
155
- title: 'Compact fixed layout',
156
- columns: fixedColumns,
157
- fetchData: mockFetchItems,
158
- defaultItemsPerPage: 10,
159
- layout: 'fixed',
160
- density: 'compact',
161
- },
162
- };
163
-
164
- // Pixel widths push the total past the 520px wrapper: the first column stays
165
- // frozen left and the last one frozen right while the middle scrolls sideways.
166
- const pinnedColumns = columns.map((col, i) => ({
167
- ...col,
168
- width: [72, 240, 280, 160, 120][i],
169
- pinned: i === 0 ? 'left' : i === columns.length - 1 ? 'right' : undefined,
170
- truncate: col.type === 'string' || col.type === 'catalog',
171
- })) as any;
172
-
173
- export const PinnedColumns: Story = {
174
- render: (args) => (
175
- <div style={{ width: 520 }}>
176
- <ITDataTable {...args} />
177
- </div>
178
- ),
179
- args: {
180
- title: 'Pinned left & right columns',
181
- columns: pinnedColumns,
182
- fetchData: mockFetchItems,
183
- defaultItemsPerPage: 10,
184
- layout: 'fixed',
185
- density: 'compact',
186
- },
187
- };
188
-
189
- export const VirtualizedLargeDataset: Story = {
190
- args: {
191
- title: 'Virtualized · 100 rows',
192
- columns: fixedColumns,
193
- fetchData: mockFetchItems,
194
- defaultItemsPerPage: 100,
195
- itemsPerPageOptions: [10, 50, 100],
196
- virtualized: true,
197
- stickyHeader: true,
198
- layout: 'fixed',
199
- density: 'compact',
200
- virtualizedMaxHeight: 360,
201
- },
202
- };
203
-
204
- export const RemoteWithExternalFilters: Story = {
205
- render: () => {
206
- const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);
207
- const [dateRange, setDateRange] = useState<[Date | null, Date | null]>([null, null]);
208
-
209
- // Stable references for ITDataTable
210
- const memoizedFetch = useCallback(mockFetchItems, []);
211
- const memoizedColumns = useMemo(() => columns, []);
212
- const externalFilters = useMemo(() => ({
213
- date: selectedDate,
214
- startDate: dateRange[0],
215
- endDate: dateRange[1]
216
- }), [selectedDate, dateRange]);
217
-
218
- return (
219
- <div className="space-y-6">
220
- <ITCard title="Filtros Globales de Negocio" className="bg-white">
221
- <div className="flex flex-wrap gap-4 items-end">
222
- <div className="w-64">
223
- <ITDatePicker
224
- name="single"
225
- label="Fecha Específica"
226
- value={selectedDate}
227
- onChange={(e: any) => setSelectedDate(e.target.value)}
228
- placeholder="Seleccionar..."
229
- />
230
- </div>
231
- <div className="w-80">
232
- <ITDatePicker
233
- range
234
- name="range"
235
- label="Rango de Auditoría"
236
- value={dateRange}
237
- onChange={(e: any) => setDateRange(e.target.value)}
238
- placeholder="Seleccionar rango..."
239
- />
240
- </div>
241
- <button
242
- onClick={() => { setSelectedDate(undefined); setDateRange([null, null]); }}
243
- className="px-4 py-2 text-sm text-primary-600 hover:text-primary-700 font-medium"
244
- >
245
- Resetear Filtros
246
- </button>
247
- </div>
248
- </ITCard>
249
-
250
- <ITDataTable
251
- title="Resultados Filtrados"
252
- columns={memoizedColumns}
253
- fetchData={memoizedFetch}
254
- externalFilters={externalFilters}
255
- defaultItemsPerPage={5}
256
- />
257
- </div>
258
- );
259
- }
260
- };
261
-
262
- export const WithRowClick: Story = {
263
- args: {
264
- title: 'Filas clickeables',
265
- columns,
266
- fetchData: mockFetchItems,
267
- defaultItemsPerPage: 10,
268
- onRowClick: (row: any) => console.log('Row clicked:', row),
269
- },
270
- };
271
-
272
- export const WithSearchAndDateFilters: Story = {
273
- render: () => {
274
- const searchDateFetch = useCallback(
275
- async (params: ITDataTableFetchParams): Promise<ITDataTableResponse<any>> => {
276
- await new Promise((r) => setTimeout(r, 400));
277
- let filtered = [...MOCK_DATA];
278
-
279
- Object.entries(params.filters).forEach(([key, value]) => {
280
- if (value === undefined || value === '') return;
281
-
282
- if (key === 'role') {
283
- filtered = filtered.filter((item) => item.role === value);
284
- } else if (key === 'createdAt') {
285
- if (Array.isArray(value)) {
286
- const [rangeStart, rangeEnd] = value as [Date | null, Date | null];
287
- if (!rangeStart && !rangeEnd) return;
288
- filtered = filtered.filter((item) => {
289
- const time = new Date(item.createdAt).getTime();
290
- if (rangeStart && time < startOfDay(rangeStart).getTime()) return false;
291
- if (rangeEnd && time > endOfDay(rangeEnd).getTime()) return false;
292
- return true;
293
- });
294
- } else if (value instanceof Date) {
295
- filtered = filtered.filter(
296
- (item) => new Date(item.createdAt).toDateString() === value.toDateString()
297
- );
298
- }
299
- }
300
- });
301
-
302
- const start = (params.page - 1) * params.limit;
303
- return { data: filtered.slice(start, start + params.limit), total: filtered.length };
304
- },
305
- []
306
- );
307
-
308
- const filterColumns = useMemo(
309
- () => [
310
- { key: 'username', label: 'Usuario', type: 'string' as const, filter: true, sortable: true },
311
- {
312
- key: 'role',
313
- label: 'Rol (ITSearchSelect)',
314
- type: 'string' as const,
315
- filter: 'search' as const,
316
- sortable: true,
317
- catalogOptions: { data: ROLES.map((role) => ({ id: role, name: role })) },
318
- render: (row: any) => <ITBadget label={row.role} />,
319
- },
320
- {
321
- key: 'createdAt',
322
- label: 'Alta (ITDatePicker range)',
323
- type: 'date' as const,
324
- filter: 'date-range' as const,
325
- sortable: true,
326
- dateFilterOptions: { maxDate: new Date() },
327
- render: (row: any) => new Date(row.createdAt).toLocaleDateString('es-MX'),
328
- },
329
- ],
330
- []
331
- );
332
-
333
- return (
334
- <ITDataTable
335
- title="Filtros: ITSearchSelect + ITDatePicker (rango)"
336
- columns={filterColumns as any}
337
- fetchData={searchDateFetch}
338
- defaultItemsPerPage={8}
339
- />
340
- );
341
- },
342
- };
343
-
344
- export const SkeletonLoading: Story = {
345
- args: {
346
- title: 'Cargando Datos...',
347
- columns,
348
- fetchData: async () => {
349
- await new Promise(r => setTimeout(r, 10000));
350
- return { data: [], total: 0 };
351
- },
352
- },
353
- };
@@ -1,54 +0,0 @@
1
- import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
2
- import * as StoriesData from './dialog.stories';
3
-
4
- <Meta of={StoriesData} />
5
-
6
- # ITDialog
7
-
8
- Modal dialog rendered via a React portal with a semi-transparent overlay backdrop. Supports optional title bar (plain or ITFormHeader), Escape-key dismissal, and a full-screen variant.
9
-
10
- ## Props
11
-
12
- | Prop | Type | Default | Description |
13
- |------|------|---------|-------------|
14
- | `isOpen` | `boolean` | — | Controls dialog visibility. |
15
- | `onClose` | `() => void` | — | Called on overlay click, close button, or Escape key. |
16
- | `children` | `ReactNode` | — | Content rendered in the dialog body. |
17
- | `className` | `string` | — | CSS classes for the dialog panel (e.g., `"w-96"` for width). |
18
- | `title` | `string` | — | Optional heading at the top of the dialog. |
19
- | `useFormHeader` | `boolean` | `false` | When true and `title` is set, renders an ITFormHeader with colored styling. |
20
- | `fullScreen` | `boolean` | `false` | Makes the dialog fill the entire viewport. |
21
-
22
- ## Usage
23
-
24
- ```tsx
25
- import { ITDialog } from '@axzydev/axzy_ui_system';
26
-
27
- <ITDialog
28
- isOpen={open}
29
- onClose={() => setOpen(false)}
30
- title="User Details"
31
- useFormHeader
32
- className="w-[500px]"
33
- >
34
- <UserForm />
35
- </ITDialog>
36
-
37
- <ITDialog isOpen={open} onClose={close} fullScreen>
38
- <FullPageEditor />
39
- </ITDialog>
40
- ```
41
-
42
- ## Notes
43
-
44
- - Content is portaled to `document.body` via `createPortal`, ensuring it renders above all page layers.
45
- - Click outside the dialog panel or pressing Escape dismisses it.
46
- - When `useFormHeader` is true, the header uses the ITFormHeader design pattern with brand coloring.
47
- - Control the dialog width via the `className` prop (e.g., `"w-96"`, `"w-[600px]"`).
48
- - The overlay uses `bg-black/50` for a darkened backdrop effect.
49
-
50
- ## Stories
51
-
52
- <Primary />
53
- <Controls />
54
- <Stories />
@@ -1,126 +0,0 @@
1
- import type { Meta } from '@storybook/react';
2
- import ITDialog from '@/components/organisms/dialog/dialog';
3
- import ITSearchSelect from '@/components/molecules/search-select/search-select';
4
- import { useState } from 'react';
5
- import { expect, userEvent, within } from 'storybook/test';
6
- import ITButton from '@/components/atoms/button/button';
7
-
8
- const meta = {
9
- title: 'Components/Feedback/ITDialog',
10
- component: ITDialog,
11
- parameters: {
12
- layout: 'centered',
13
- },
14
- argTypes: {
15
- isOpen: { control: 'boolean' },
16
- onClose: { action: 'closed' },
17
- title: { control: 'text' },
18
- useFormHeader: { control: 'boolean' },
19
- },
20
- } satisfies Meta<typeof ITDialog>;
21
-
22
- export default meta;
23
-
24
- // Wrapper to handle open/close state
25
- const DialogWrapper = (args: any) => {
26
- const [isOpen, setIsOpen] = useState(false);
27
-
28
- return (
29
- <div>
30
- <ITButton onClick={() => setIsOpen(true)}>Open Dialog</ITButton>
31
- <ITDialog {...args} isOpen={isOpen} onClose={() => setIsOpen(false)}>
32
- {args.children}
33
- </ITDialog>
34
- </div>
35
- );
36
- };
37
-
38
- export const Default: any = {
39
- render: (args) => <DialogWrapper {...args} />,
40
- args: {
41
- title: 'Basic Dialog',
42
- children: <p className="text-gray-600">This is a simple dialog usage standard headers.</p>,
43
- useFormHeader: false,
44
- className: 'w-96',
45
- } as any,
46
- };
47
-
48
- export const WithFormHeader: any = {
49
- render: (args) => <DialogWrapper {...args} />,
50
- args: {
51
- title: 'Form Header Dialog',
52
- children: (
53
- <div className="space-y-4">
54
- <p className="text-gray-600">This dialog uses the standard form header styling.</p>
55
- <div className="flex justify-end">
56
- <ITButton variant="primary">Confirm</ITButton>
57
- </div>
58
- </div>
59
- ),
60
- useFormHeader: true,
61
- className: 'w-[500px]',
62
- } as any,
63
- };
64
-
65
- export const LongContent: any = {
66
- render: (args) => <DialogWrapper {...args} />,
67
- args: {
68
- title: 'Terms of Service',
69
- children: (
70
- <div className="h-64 overflow-y-auto text-sm text-gray-600">
71
- <p className="mb-4">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
72
- <p className="mb-4">Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
73
- <p className="mb-4">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
74
- <p className="mb-4">Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>
75
- </div>
76
- ),
77
- useFormHeader: true,
78
- className: 'w-[600px]',
79
- } as any,
80
- };
81
-
82
- // Dialog opened on mount but controlled, so an unexpected close is observable.
83
- const DialogWithSearchSelect = () => {
84
- const [fruit, setFruit] = useState('');
85
- const [isOpen, setIsOpen] = useState(true);
86
-
87
- return (
88
- <ITDialog isOpen={isOpen} onClose={() => setIsOpen(false)} title="Fruta favorita">
89
- <ITSearchSelect
90
- label="Fruta"
91
- placeholder="Busca una fruta..."
92
- options={[
93
- { value: 'apple', label: 'Apple' },
94
- { value: 'banana', label: 'Banana' },
95
- ]}
96
- value={fruit}
97
- onChange={(next) => setFruit(String(next))}
98
- />
99
- </ITDialog>
100
- );
101
- };
102
-
103
- /**
104
- * Regression test: floating panels (selects, pickers, menus) are portaled to
105
- * `<body>`, so they live outside the dialog DOM. Picking an option there must
106
- * not count as a click outside the dialog.
107
- *
108
- * Note the whole dialog and its dropdown are portaled, so they are queried
109
- * from `document.body` instead of the story canvas.
110
- */
111
- export const FloatingPanelInsideDialog: any = {
112
- render: () => <DialogWithSearchSelect />,
113
- play: async () => {
114
- const view = within(document.body);
115
-
116
- const input = await view.findByPlaceholderText('Busca una fruta...');
117
- await userEvent.click(input);
118
-
119
- await userEvent.click(await view.findByText('Banana'));
120
-
121
- // The dialog must still be mounted after picking an option.
122
- await expect(view.getByText('Fruta favorita')).toBeVisible();
123
- await expect((input as HTMLInputElement).value).toBe('Banana');
124
- },
125
- };
126
-
@@ -1,59 +0,0 @@
1
- import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
2
- import * as StoriesData from './drawer.stories';
3
-
4
- <Meta of={StoriesData} />
5
-
6
- # ITDrawer
7
-
8
- A sliding panel that emerges from the left or right edge with a backdrop overlay. Includes an optional title bar with close button and a scrollable body. Ideal for side panels, navigation menus, filters, and detail views.
9
-
10
- ## Props
11
-
12
- | Prop | Type | Default | Description |
13
- |------|------|---------|-------------|
14
- | `isOpen` | `boolean` | — | Controls drawer visibility. |
15
- | `onClose` | `() => void` | — | Called on overlay click or close button press. |
16
- | `position` | `"left" \| "right"` | `"right"` | Screen edge the drawer attaches to. |
17
- | `size` | `string` | `"w-80"` | Tailwind width class (e.g., `"w-72"`, `"w-96"`). |
18
- | `title` | `ReactNode` | — | Optional heading in the drawer header. |
19
- | `children` | `ReactNode` | — | Content displayed in the drawer body. |
20
- | `className` | `string` | — | Additional CSS classes for the drawer panel. |
21
- | `style` | `CSSProperties` | — | Inline styles for the drawer panel. |
22
-
23
- ## Usage
24
-
25
- ```tsx
26
- import { ITDrawer } from '@axzydev/axzy_ui_system';
27
-
28
- <ITDrawer
29
- isOpen={menuOpen}
30
- onClose={() => setMenuOpen(false)}
31
- title="Navigation"
32
- position="left"
33
- size="w-72"
34
- >
35
- <NavMenu />
36
- </ITDrawer>
37
-
38
- <ITDrawer
39
- isOpen={filterOpen}
40
- onClose={() => setFilterOpen(false)}
41
- title="Filters"
42
- >
43
- <FilterPanel />
44
- </ITDrawer>
45
- ```
46
-
47
- ## Notes
48
-
49
- - The overlay uses `bg-black/40 backdrop-blur-sm` for a blurred background effect.
50
- - Overlay click outside the panel dismisses the drawer via `useClickOutside`.
51
- - The body area scrolls independently (`overflow-y-auto`), keeping the header fixed.
52
- - Default size `w-80` (320px); adjust with any Tailwind width class like `w-96` (384px) or `w-[400px]`.
53
- - No built-in footer slot — add buttons or actions directly in the children content.
54
-
55
- ## Stories
56
-
57
- <Primary />
58
- <Controls />
59
- <Stories />
@@ -1,40 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/react";
2
- import { useState } from "react";
3
- import ITDrawer from "@/components/organisms/drawer/drawer";
4
- import ITButton from "@/components/atoms/button/button";
5
-
6
- const meta: Meta<typeof ITDrawer> = {
7
- title: "Components/Overlay/ITDrawer",
8
- component: ITDrawer,
9
- };
10
-
11
- export default meta;
12
- type Story = StoryObj<typeof ITDrawer>;
13
-
14
- export const Default: Story = {
15
- render: () => {
16
- const [open, setOpen] = useState(false);
17
- return (
18
- <>
19
- <ITButton label="Abrir Drawer" onClick={() => setOpen(true)} />
20
- <ITDrawer isOpen={open} onClose={() => setOpen(false)} title="Panel Lateral">
21
- <p className="text-sm text-slate-600 dark:text-slate-300">Contenido del drawer.</p>
22
- </ITDrawer>
23
- </>
24
- );
25
- },
26
- };
27
-
28
- export const PositionLeft: Story = {
29
- render: () => {
30
- const [open, setOpen] = useState(false);
31
- return (
32
- <>
33
- <ITButton label="Abrir Izquierda" onClick={() => setOpen(true)} />
34
- <ITDrawer isOpen={open} onClose={() => setOpen(false)} position="left" title="Menú">
35
- <p className="text-sm text-slate-600">Drawer desde la izquierda.</p>
36
- </ITDrawer>
37
- </>
38
- );
39
- },
40
- };