@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,74 +0,0 @@
1
- import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
2
- import * as StoriesData from './dropfile.stories';
3
-
4
- <Meta of={StoriesData} />
5
-
6
- # ITDropfile
7
-
8
- A drag-and-drop file upload zone with preview support for images. Tracks upload lifecycle with status enumeration and provides confirm/cancel actions. Configurable accepted file types limit which formats are allowed.
9
-
10
- ## Props
11
-
12
- | Prop | Type | Default | Description |
13
- |------|------|---------|-------------|
14
- | `onFileSelect` | `(file: File \| null) => void` | — | Called when a file is selected or cleared. |
15
- | `onCancel` | `() => void` | — | Called when the user cancels the current selection. |
16
- | `onSubmit` | `(file: File) => void` | — | Called when the user confirms and submits the file. |
17
- | `acceptedFileTypes` | `FileTypeEnum[]` | — | List of accepted MIME types (PDF, XLS, CSV, PNG, JPG, etc.). |
18
- | `contentClassName` | `string` | — | CSS classes for the preview/content area. |
19
- | `containerClassName` | `string` | — | CSS classes for the outermost container. |
20
- | `showStatusBadge` | `boolean` | — | Whether to show the status badge (pending/uploading/uploaded/error). |
21
- | `uploadStatus` | `UploadStatus` | — | Externally controlled upload status. |
22
- | `onStatusChange` | `(status: UploadStatus) => void` | — | Callback when upload status changes. |
23
- | `initialPreviewUrl` | `string \| null` | — | Initial preview URL shown before any file is selected (e.g., editing an existing entry). |
24
- | `view` | `"drop" \| "button"` | `"drop"` | `"drop"` renders the dropzone/preview inline. `"button"` renders a compact trigger button that opens the same UI inside an `ITDialog` modal. |
25
- | `buttonLabel` | `string` | `"Subir archivo"` | Label for the trigger button when `view="button"` and no file is selected yet. |
26
- | `modalTitle` | `string` | `buttonLabel` | Title of the modal opened when `view="button"`. |
27
-
28
- ### Enums
29
-
30
- | Enum | Values |
31
- |------|--------|
32
- | `UploadStatus` | `PENDING` (`"pendiente"`), `UPLOADING` (`"subiendo"`), `UPLOADED` (`"subido"`), `ERROR` (`"error"`) |
33
- | `FileTypeEnum` | `PDF`, `XLS`, `XLSX`, `CSV`, `PNG`, `JPG`, `JPEG` |
34
-
35
- ## Usage
36
-
37
- ```tsx
38
- import { ITDropfile, UploadStatus, FileTypeEnum } from '@axzydev/axzy_ui_system';
39
-
40
- <ITDropfile
41
- onFileSelect={(file) => setSelectedFile(file)}
42
- onSubmit={(file) => uploadFile(file)}
43
- onCancel={() => clearFile()}
44
- acceptedFileTypes={[FileTypeEnum.PNG, FileTypeEnum.JPG, FileTypeEnum.PDF]}
45
- uploadStatus={UploadStatus.PENDING}
46
- showStatusBadge
47
- />
48
- ```
49
-
50
- ### `view="button"`
51
-
52
- ```tsx
53
- <ITDropfile
54
- view="button"
55
- buttonLabel="Subir archivos"
56
- onFileSelect={(file) => setSelectedFile(file)}
57
- />
58
- ```
59
-
60
- Use this when you'd otherwise write your own button + modal wrapper around `ITDropfile` — it's built in. The button shows the picked file's name (and status badge, if `showStatusBadge`) once one is selected, and reopens the same dropzone/preview to change it. ~900ms after a successful confirm the modal closes **and the selection resets**, so the button goes back to `buttonLabel`, ready to upload another file — this mode is built for repeated uploads (e.g. an attachments list), replacing the old pattern of remounting `ITDropfile` with a changing `key` after each upload.
61
-
62
- ## Notes
63
-
64
- - Displays image preview for image file types; shows a file icon for non-image types.
65
- - The `uploadStatus` and `showStatusBadge` props enable external lifecycle control and visual feedback.
66
- - `initialPreviewUrl` is useful for edit forms where an existing file is already associated.
67
- - Only one file at a time is supported — selecting a new file replaces the current one.
68
- - The confirm/cancel flow gives users a chance to review their selection before submission.
69
-
70
- ## Stories
71
-
72
- <Primary />
73
- <Controls />
74
- <Stories />
@@ -1,93 +0,0 @@
1
- import type { Meta } from '@storybook/react';
2
- import ITDropfile, { UploadStatus } from '@/components/organisms/dropfile/dropfile';
3
-
4
- const meta = {
5
- title: 'Components/Actions/ITDropfile',
6
- component: ITDropfile,
7
- parameters: {
8
- layout: 'centered',
9
- },
10
- argTypes: {
11
- onFileSelect: { action: 'file selected' },
12
- onCancel: { action: 'cancelled' },
13
- onSubmit: { action: 'submitted' },
14
- showStatusBadge: { control: 'boolean' },
15
- uploadStatus: {
16
- control: 'select',
17
- options: Object.values(UploadStatus),
18
- },
19
- view: {
20
- control: 'radio',
21
- options: ['drop', 'button'],
22
- },
23
- },
24
- } satisfies Meta<typeof ITDropfile>;
25
-
26
- export default meta;
27
-
28
- // Wrapper for stateful file handling in story
29
- const DropfileWrapper = (args: any) => {
30
- return <ITDropfile {...args} className="w-[500px]" />;
31
- }
32
-
33
- export const Default: any = {
34
- render: (args) => <DropfileWrapper {...args} />,
35
- args: {
36
- showStatusBadge: true,
37
- containerClassName: 'w-[400px]',
38
- },
39
- };
40
-
41
- export const WithImage: any = {
42
- render: (args) => <DropfileWrapper {...args} />,
43
- args: {
44
- showStatusBadge: true,
45
- initialPreviewUrl: 'https://images.unsplash.com/photo-1575936123452-b67c3203c357?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80',
46
- uploadStatus: UploadStatus.UPLOADED,
47
- containerClassName: 'w-[400px]',
48
- },
49
- parameters: {
50
- docs: {
51
- description: {
52
- story: 'Simulates a pre-loaded image (e.g., editing an existing entry).'
53
- }
54
- }
55
- }
56
- };
57
-
58
- export const Uploading: any = {
59
- render: (args) => <DropfileWrapper {...args} />,
60
- args: {
61
- showStatusBadge: true,
62
- initialPreviewUrl: 'https://images.unsplash.com/photo-1575936123452-b67c3203c357?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80',
63
- uploadStatus: UploadStatus.UPLOADING,
64
- containerClassName: 'w-[400px]',
65
- },
66
- };
67
-
68
- export const ButtonView: any = {
69
- render: (args) => <DropfileWrapper {...args} />,
70
- args: {
71
- view: 'button',
72
- buttonLabel: 'Subir archivos',
73
- showStatusBadge: true,
74
- },
75
- parameters: {
76
- docs: {
77
- description: {
78
- story:
79
- 'Compact trigger button that opens the dropzone/preview inside a modal (`ITDialog`) — use this instead of wrapping `ITDropfile` in your own "open a modal" button.',
80
- },
81
- },
82
- },
83
- };
84
-
85
- export const ErrorState: any = {
86
- render: (args) => <DropfileWrapper {...args} />,
87
- args: {
88
- showStatusBadge: true,
89
- initialPreviewUrl: 'https://images.unsplash.com/photo-1575936123452-b67c3203c357?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80',
90
- uploadStatus: UploadStatus.ERROR,
91
- containerClassName: 'w-[400px]',
92
- },
93
- };
@@ -1,251 +0,0 @@
1
- import { Meta, Title, Description, Primary, Controls, Stories } from '@storybook/blocks';
2
- import * as StoriesData from './formBuilder.stories';
3
-
4
- <Meta of={StoriesData} />
5
-
6
- # ITFormBuilder
7
-
8
- Dynamic form generator that renders fields from a JSON-like array. Integrates with
9
- Formik + Yup, supports both a backward-compatible V1 (`fields`) and the powerful
10
- Enterprise V2 (`config`) API, and exposes a `useFormBuilder()` hook for building
11
- custom submit buttons, progress meters, and dirty-state indicators.
12
-
13
- ## When to use
14
-
15
- - You want to drive a form from a declarative config (server-driven forms, CMS schemas).
16
- - You need conditional fields (`renderWhen`), derived values (`onChangeAction`),
17
- dynamic props (`dynamicProps`), or cascading selects.
18
- - You need to render a custom React component as a field (`type: "custom"`).
19
-
20
- ## Props
21
-
22
- | Prop | Type | Default | Required | Description |
23
- |------|------|---------|----------|-------------|
24
- | `fields` | `FieldConfig[]` | — | No | Legacy V1 field definitions. Kept for backward compatibility. |
25
- | `config` | `FieldConfigV2[]` | — | No | V2 field configuration. Recommended. Shadows `fields` when both supplied. |
26
- | `columns` | `number` | `12` | No | Grid column count (1–12). |
27
- | `values` | `Record<string, unknown>` | — | Yes | Current form values keyed by field `name`. |
28
- | `handleChange` | `(event) => void` | — | Yes | Change handler — pass Formik's `handleChange` directly. |
29
- | `handleBlur` | `(event) => void` | — | Yes | Blur handler — pass Formik's `handleBlur` directly. |
30
- | `touched` | `Record<string, boolean>` | — | Yes | Touch state keyed by field `name`. |
31
- | `errors` | `Record<string, string>` | — | Yes | Errors keyed by field `name`. |
32
- | `setFieldValue` | `(field, value, shouldValidate?) => Promise` | no-op | No | Required for V2 `onChangeAction` and `dynamicProps` side effects. |
33
- | `setFieldTouched` | `(field, touched?, shouldValidate?) => Promise` | no-op | No | Programmatic touch. |
34
- | `setFieldError` | `(field, message?) => void` | no-op | No | Programmatic field-level error. |
35
- | `isSubmitting` | `boolean` | `false` | No | Surface submit state to the context. |
36
-
37
- When both `config` and `fields` are supplied, `config` wins. When neither is supplied the
38
- component renders an empty grid.
39
-
40
- ## FieldConfigV2 reference
41
-
42
- | Field | Type | Description |
43
- |-------|------|-------------|
44
- | `type` | `"text" \| "number" \| "password" \| "email" \| "select" \| "date" \| "time" \| "section" \| "custom" \| "array"` | Field kind. |
45
- | `name` | `string` | Matches the key in `values` / `errors` / `touched`. |
46
- | `label` | `string` | Text rendered above the field (or as the section heading). |
47
- | `column` | `number \| { sm?, md?, lg?, xl? }` | Grid span. Responsive object or single number. |
48
- | `dependsOn` | `string[]` | Sibling field names watched by `renderWhen`/`dynamicProps`. |
49
- | `renderWhen` | `(values) => boolean` | Hide this field when returns `false`. |
50
- | `dynamicProps` | `(values) => Partial<FieldConfigV2>` | Compute per-render overrides (e.g. toggle `disabled`). |
51
- | `validation` | `Yup.AnySchema` | Per-field Yup schema. |
52
- | `asyncValidation` | `(value, values) => Promise<string \| null>` | Async validator returning an error message or `null`. |
53
- | `onChangeAction` | `(value, context) => void \| Promise<void>` | Side-effect fired on change. Use to compute derived fields. |
54
- | `options` | `Array \| () => Promise<Array>` | Sync or async options for `select`. Async → renders `ITSearchSelect`. |
55
- | `component` | `React.ComponentType` | Renderer for `type: "custom"`. |
56
- | `fields` | `FieldConfigV2[]` | Nested fields for `type: "section"` (or `array` placeholder). |
57
- | `placeholder` | `string` | Placeholder text. |
58
- | `required` | `boolean \| (values) => boolean` | Required flag. |
59
- | `disabled` | `boolean \| (values) => boolean` | Disabled flag. |
60
- | `readOnly` | `boolean` | Read-only flag. |
61
- | `defaultValue` | `any` | Initial value. |
62
- | `valueField` / `labelField` | `string` | Keys read off each option object. |
63
- | `leftIcon` / `rightIcon` | `React.ReactNode` | Icon adornments. |
64
- | `className` | `string` | Extra classes for the field's container. |
65
- | `maxLength` / `minLength` | `number` | Length bounds for text/textarea. |
66
- | `rows` | `number` | Rows for textarea-style inputs. |
67
- | `formatNumber` | `boolean` | Apply thousand-separator formatting as the user types. |
68
- | `currencyFormat` | `boolean` | Render a `$`-style currency treatment on numeric input. |
69
- | `showHintLength` | `boolean` | Show a live character counter. |
70
-
71
- ## FieldConfig (V1) reference (legacy)
72
-
73
- | Field | Type | Description |
74
- |-------|------|-------------|
75
- | `name` | `string` | Key in `values`/`errors`/`touched`. |
76
- | `label` | `string` | Field label. |
77
- | `type` | `"text" \| "number" \| "password" \| "select" \| "date"` | Input kind. |
78
- | `placeholder` | `string` | Placeholder text. |
79
- | `required` | `boolean` | Required flag. |
80
- | `disabled` | `boolean` | Disabled flag. |
81
- | `column` | `number` | Grid span. |
82
- | `options` | `{ value, label }[]` | Options for `select`. |
83
- | `leftIcon` / `rightIcon` | `React.ReactNode` | Icon adornments. |
84
- | `valueField` / `labelField` | `string` | Keys read off each option object. |
85
- | `maxLength` / `minLength` | `number` | Length bounds. |
86
- | `rows` | `number` | Rows for multi-line inputs. |
87
- | `formatNumber` | `boolean` | Thousand-separator formatting. |
88
- | `currencyFormat` | `boolean` | Currency-style numeric input. |
89
- | `showHintLength` | `boolean` | Live character counter. |
90
- | `validation` | `Yup.AnySchema` | Per-field Yup schema. |
91
- | `onChangeAction` | `(value, setFieldValue) => void` | Side-effect fired on change. |
92
-
93
- ## Usage
94
-
95
- ### 1. Minimal Formik + Yup form (V2)
96
-
97
- ```tsx
98
- import { Formik } from "formik";
99
- import * as Yup from "yup";
100
- import { ITFormBuilder } from "@axzydev/axzy_ui_system";
101
- import type { FieldConfigV2 } from "@axzydev/axzy_ui_system";
102
-
103
- const schema = Yup.object({
104
- email: Yup.string().email().required(),
105
- password: Yup.string().min(8).required(),
106
- });
107
-
108
- const config: FieldConfigV2[] = [
109
- { name: "email", label: "Email", type: "email", required: true, column: 6 },
110
- { name: "password", label: "Password", type: "password", required: true, column: 6 },
111
- ];
112
-
113
- <Formik
114
- initialValues={{ email: "", password: "" }}
115
- validationSchema={schema}
116
- onSubmit={(values) => console.log(values)}
117
- >
118
- {(p) => (
119
- <form onSubmit={p.handleSubmit}>
120
- <ITFormBuilder
121
- config={config}
122
- values={p.values}
123
- handleChange={p.handleChange}
124
- handleBlur={p.handleBlur}
125
- touched={p.touched}
126
- errors={p.errors}
127
- setFieldValue={p.setFieldValue}
128
- />
129
- <button type="submit">Submit</button>
130
- </form>
131
- )}
132
- </Formik>
133
- ```
134
-
135
- ### 2. Conditional + derived fields
136
-
137
- ```tsx
138
- const config: FieldConfigV2[] = [
139
- {
140
- name: "country",
141
- label: "País",
142
- type: "select",
143
- required: true,
144
- options: [{ value: "MX", label: "México" }, { value: "US", label: "USA" }],
145
- },
146
- {
147
- name: "rfc",
148
- label: "RFC",
149
- type: "text",
150
- required: true,
151
- dependsOn: ["country"],
152
- renderWhen: (v) => v.country === "MX",
153
- },
154
- {
155
- name: "subtotal",
156
- label: "Subtotal",
157
- type: "number",
158
- currencyFormat: true,
159
- onChangeAction: (val, ctx) => {
160
- const n = parseFloat(String(val).replace(/,/g, "")) || 0;
161
- ctx.setFieldValue("total", (n * 1.16).toFixed(2));
162
- },
163
- },
164
- { name: "total", label: "Total", type: "number", disabled: true, currencyFormat: true },
165
- ];
166
- ```
167
-
168
- ### 3. Async / cascading options
169
-
170
- ```tsx
171
- {
172
- name: "city",
173
- label: "Ciudad",
174
- type: "select",
175
- options: async () => {
176
- const res = await fetch(`/api/cities?country=${values.country}`);
177
- return res.json();
178
- },
179
- }
180
- ```
181
-
182
- Async option lists use `ITSearchSelect` underneath and render a spinner fallback
183
- while loading (`data-testid="field-loading-{name}"`).
184
-
185
- ### 4. Custom component
186
-
187
- ```tsx
188
- const ConfirmToggle = ({ value, onChange, label }) => (
189
- <label>
190
- <input type="checkbox" checked={!!value} onChange={(e) => onChange(e.target.checked)} />
191
- {label}
192
- </label>
193
- );
194
-
195
- {
196
- name: "confirm",
197
- label: "Acepto términos",
198
- type: "custom",
199
- component: ConfirmToggle,
200
- defaultValue: false,
201
- }
202
- ```
203
-
204
- ### 5. Section grouping
205
-
206
- ```tsx
207
- {
208
- name: "identity",
209
- label: "Personal Information",
210
- type: "section",
211
- fields: [
212
- { name: "firstName", label: "First Name", type: "text" },
213
- { name: "lastName", label: "Last Name", type: "text" },
214
- ],
215
- }
216
- ```
217
-
218
- ### 6. Custom submit button via `useFormBuilder`
219
-
220
- ```tsx
221
- import { useFormBuilder } from "@axzydev/axzy_ui_system";
222
-
223
- const SubmitButton = () => {
224
- const { progress, isSubmitting } = useFormBuilder();
225
- return (
226
- <button type="submit" disabled={progress < 100 || isSubmitting}>
227
- {isSubmitting ? "Saving…" : `Submit (${progress}%)`}
228
- </button>
229
- );
230
- };
231
- ```
232
-
233
- `useFormBuilder` must be rendered inside the `<ITFormBuilder>` subtree (so the
234
- V2 provider must be active). It throws a clear error if used outside.
235
-
236
- ## Notes
237
-
238
- - The component is fully controlled — it does not own form state. Pass values
239
- and handlers from Formik (or any state holder of your choice).
240
- - V1 and V2 can coexist on a single page; mixing both on the same `<ITFormBuilder>`
241
- is not supported — `config` wins.
242
- - The V2 registry of registered fields is exposed via `useFormBuilder` and via
243
- `useITFormBuilderContext().getAllFieldConfigs()`.
244
- - `validation`/`asyncValidation` are NOT applied automatically — wire them to
245
- Yup at the Formik root, or run them manually inside `onChangeAction`.
246
-
247
- ## Stories
248
-
249
- <Primary />
250
- <Controls />
251
- <Stories />