@axzydev/axzy_ui_system 1.4.8 → 1.5.1

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 (223) hide show
  1. package/README.md +2 -11
  2. package/dist/index.cjs +1826 -1351
  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 +115 -14
  7. package/dist/index.d.ts +115 -14
  8. package/dist/index.js +1481 -1010
  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.tsx +30 -28
  39. package/src/components/molecules/time-picker/timePicker.tsx +8 -6
  40. package/src/components/molecules/wysiwyg/wysiwyg.tsx +23 -12
  41. package/src/components/organisms/confirm-dialog/confirm-dialog.props.ts +4 -4
  42. package/src/components/organisms/confirm-dialog/confirm-dialog.tsx +16 -8
  43. package/src/components/organisms/data-table/dataTable.tsx +31 -25
  44. package/src/components/organisms/dialog/dialog.tsx +3 -0
  45. package/src/components/organisms/drawer/drawer.tsx +3 -0
  46. package/src/components/organisms/dropfile/dropfile.tsx +19 -17
  47. package/src/components/organisms/form-builder/fieldRenderer.tsx +4 -2
  48. package/src/components/organisms/navbar/navbar.tsx +4 -2
  49. package/src/components/organisms/page-header/page-header.tsx +3 -1
  50. package/src/components/organisms/searchTable/components/PaginationControls.tsx +8 -6
  51. package/src/components/organisms/searchTable/components/PaginationInfo.tsx +3 -1
  52. package/src/components/organisms/searchTable/components/SearchAndSortBar.tsx +7 -5
  53. package/src/components/organisms/searchTable/components/SearchInput.tsx +4 -2
  54. package/src/components/organisms/searchTable/components/SortButton.tsx +13 -11
  55. package/src/components/organisms/searchTable/components/TableEmptyState.tsx +4 -2
  56. package/src/components/organisms/searchTable/components/TableRow.tsx +6 -4
  57. package/src/components/organisms/searchTable/searchTable.tsx +4 -2
  58. package/src/components/organisms/sidebar/sidebar.props.ts +1 -1
  59. package/src/components/organisms/sidebar/sidebar.tsx +9 -4
  60. package/src/components/organisms/toast/toast.tsx +3 -1
  61. package/src/components/organisms/topbar/topbar.tsx +4 -2
  62. package/src/components/templates/page/page.props.ts +4 -4
  63. package/src/components/templates/page/page.tsx +6 -4
  64. package/src/components/theme-provider/themeProvider.tsx +28 -17
  65. package/src/dev.css +61 -2
  66. package/src/global.d.ts +10 -0
  67. package/src/i18n/context.ts +9 -0
  68. package/src/i18n/index.ts +22 -0
  69. package/src/i18n/locales/en.ts +163 -0
  70. package/src/i18n/locales/es.ts +165 -0
  71. package/src/i18n/provider.tsx +44 -0
  72. package/src/i18n/translator.ts +82 -0
  73. package/src/i18n/types.ts +54 -0
  74. package/src/i18n/useITTranslation.ts +20 -0
  75. package/src/index.css +0 -1
  76. package/src/index.ts +7 -1
  77. package/src/sandbox/LandingShowcase.tsx +224 -580
  78. package/src/sandbox/NotFoundShowcase.tsx +51 -36
  79. package/src/sandbox/TopbarSearch.tsx +6 -4
  80. package/src/sandbox/controls.tsx +180 -0
  81. package/src/sandbox/i18n.ts +1939 -0
  82. package/src/sandbox/icons.tsx +25 -0
  83. package/src/sandbox/locale.tsx +72 -0
  84. package/src/sandbox/ui.tsx +474 -0
  85. package/src/sandbox/useHashRoute.ts +46 -10
  86. package/src/showcases/DataShowcases.tsx +103 -87
  87. package/src/showcases/FeedbackShowcases.tsx +37 -30
  88. package/src/showcases/FormShowcases.tsx +303 -215
  89. package/src/showcases/GettingStartedShowcase.tsx +151 -145
  90. package/src/showcases/HelpShowcase.tsx +126 -128
  91. package/src/showcases/HomeShowcase.tsx +678 -482
  92. package/src/showcases/LayoutPrimitivesShowcases.tsx +129 -114
  93. package/src/showcases/NavigationShowcases.tsx +45 -37
  94. package/src/showcases/PageShowcases.tsx +171 -152
  95. package/src/showcases/ProductoDetalle.tsx +272 -129
  96. package/src/showcases/ShowcaseLayout.tsx +256 -219
  97. package/src/showcases/SizesShowcase.tsx +123 -64
  98. package/src/showcases/StructureShowcases.tsx +203 -138
  99. package/src/showcases/portfolioUi.tsx +153 -0
  100. package/src/showcases/techIcons.ts +3 -0
  101. package/src/utils/table.utils.ts +10 -2
  102. package/src/components/atoms/avatar/avatar.doc.mdx +0 -48
  103. package/src/components/atoms/avatar/avatar.stories.tsx +0 -64
  104. package/src/components/atoms/badget/badget.doc.mdx +0 -46
  105. package/src/components/atoms/badget/badget.stories.tsx +0 -75
  106. package/src/components/atoms/button/button.doc.mdx +0 -59
  107. package/src/components/atoms/button/button.stories.tsx +0 -173
  108. package/src/components/atoms/checkbox/checkbox.doc.mdx +0 -54
  109. package/src/components/atoms/checkbox/checkbox.stories.tsx +0 -53
  110. package/src/components/atoms/chip/chip.doc.mdx +0 -47
  111. package/src/components/atoms/chip/chip.stories.tsx +0 -64
  112. package/src/components/atoms/divider/divider.doc.mdx +0 -42
  113. package/src/components/atoms/divider/divider.stories.tsx +0 -33
  114. package/src/components/atoms/flex/flex.doc.mdx +0 -59
  115. package/src/components/atoms/flex/flex.stories.tsx +0 -70
  116. package/src/components/atoms/grid/grid.doc.mdx +0 -54
  117. package/src/components/atoms/grid/grid.stories.tsx +0 -71
  118. package/src/components/atoms/image/image.doc.mdx +0 -44
  119. package/src/components/atoms/image/image.stories.tsx +0 -48
  120. package/src/components/atoms/input/input.doc.mdx +0 -70
  121. package/src/components/atoms/input/input.stories.tsx +0 -113
  122. package/src/components/atoms/input-number/input-number.doc.mdx +0 -74
  123. package/src/components/atoms/input-number/input-number.stories.tsx +0 -111
  124. package/src/components/atoms/loader/loader.doc.mdx +0 -43
  125. package/src/components/atoms/loader/loader.stories.tsx +0 -104
  126. package/src/components/atoms/popover/popover.doc.mdx +0 -53
  127. package/src/components/atoms/popover/popover.stories.tsx +0 -24
  128. package/src/components/atoms/progress/progress.doc.mdx +0 -48
  129. package/src/components/atoms/progress/progress.stories.tsx +0 -39
  130. package/src/components/atoms/radio/radio.doc.mdx +0 -62
  131. package/src/components/atoms/radio/radio.stories.tsx +0 -48
  132. package/src/components/atoms/segmented-control/segmented-control.doc.mdx +0 -60
  133. package/src/components/atoms/segmented-control/segmented-control.stories.tsx +0 -62
  134. package/src/components/atoms/skeleton/skeleton.doc.mdx +0 -43
  135. package/src/components/atoms/skeleton/skeleton.stories.tsx +0 -29
  136. package/src/components/atoms/slide/slide.doc.mdx +0 -46
  137. package/src/components/atoms/slide/slide.stories.tsx +0 -120
  138. package/src/components/atoms/slider/slider.doc.mdx +0 -49
  139. package/src/components/atoms/slider/slider.stories.tsx +0 -29
  140. package/src/components/atoms/stack/stack.doc.mdx +0 -126
  141. package/src/components/atoms/stack/stack.stories.tsx +0 -283
  142. package/src/components/atoms/text/text.doc.mdx +0 -41
  143. package/src/components/atoms/text/text.stories.tsx +0 -66
  144. package/src/components/atoms/textarea/textarea.doc.mdx +0 -64
  145. package/src/components/atoms/textarea/textarea.stories.tsx +0 -26
  146. package/src/components/atoms/tooltip/tooltip.doc.mdx +0 -47
  147. package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -19
  148. package/src/components/isolation/isolation.stories.tsx +0 -202
  149. package/src/components/molecules/accordion/accordion.doc.mdx +0 -47
  150. package/src/components/molecules/accordion/accordion.stories.tsx +0 -68
  151. package/src/components/molecules/alert/alert.doc.mdx +0 -48
  152. package/src/components/molecules/alert/alert.stories.tsx +0 -40
  153. package/src/components/molecules/breadcrumbs/breadcrumbs.doc.mdx +0 -57
  154. package/src/components/molecules/breadcrumbs/breadcrumbs.stories.tsx +0 -20
  155. package/src/components/molecules/calendar/calendar.doc.mdx +0 -76
  156. package/src/components/molecules/calendar/calendar.stories.tsx +0 -90
  157. package/src/components/molecules/card/card.doc.mdx +0 -54
  158. package/src/components/molecules/card/card.stories.tsx +0 -57
  159. package/src/components/molecules/chip-input/chip-input.doc.mdx +0 -44
  160. package/src/components/molecules/chip-input/chip-input.stories.tsx +0 -52
  161. package/src/components/molecules/date-picker/date-picker.doc.mdx +0 -65
  162. package/src/components/molecules/date-picker/date-picker.stories.tsx +0 -88
  163. package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +0 -46
  164. package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +0 -41
  165. package/src/components/molecules/empty-state/empty-state.doc.mdx +0 -50
  166. package/src/components/molecules/empty-state/empty-state.stories.tsx +0 -19
  167. package/src/components/molecules/field/field.doc.mdx +0 -43
  168. package/src/components/molecules/field/field.stories.tsx +0 -42
  169. package/src/components/molecules/form-header/form-header.doc.mdx +0 -38
  170. package/src/components/molecules/form-header/form-header.stories.tsx +0 -52
  171. package/src/components/molecules/masked-input/masked-input.doc.mdx +0 -78
  172. package/src/components/molecules/masked-input/masked-input.stories.tsx +0 -126
  173. package/src/components/molecules/multi-select/multi-select.doc.mdx +0 -55
  174. package/src/components/molecules/multi-select/multi-select.stories.tsx +0 -59
  175. package/src/components/molecules/pagination/pagination.doc.mdx +0 -62
  176. package/src/components/molecules/pagination/pagination.stories.tsx +0 -110
  177. package/src/components/molecules/search-select/search-select.doc.mdx +0 -77
  178. package/src/components/molecules/search-select/search-select.stories.tsx +0 -146
  179. package/src/components/molecules/select/select.doc.mdx +0 -75
  180. package/src/components/molecules/select/select.stories.tsx +0 -85
  181. package/src/components/molecules/stat-card/stat-card.doc.mdx +0 -48
  182. package/src/components/molecules/stat-card/stat-card.stories.tsx +0 -40
  183. package/src/components/molecules/stepper/stepper.doc.mdx +0 -54
  184. package/src/components/molecules/stepper/stepper.stories.tsx +0 -154
  185. package/src/components/molecules/table/table.doc.mdx +0 -140
  186. package/src/components/molecules/table/table.stories.tsx +0 -402
  187. package/src/components/molecules/tabs/tabs.doc.mdx +0 -52
  188. package/src/components/molecules/tabs/tabs.stories.tsx +0 -31
  189. package/src/components/molecules/time-picker/timePicker.doc.mdx +0 -68
  190. package/src/components/molecules/time-picker/timePicker.stories.tsx +0 -130
  191. package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +0 -95
  192. package/src/components/organisms/confirm-dialog/confirm-dialog.doc.mdx +0 -60
  193. package/src/components/organisms/confirm-dialog/confirm-dialog.stories.tsx +0 -32
  194. package/src/components/organisms/data-table/ITDataTable.doc.mdx +0 -132
  195. package/src/components/organisms/data-table/ITDataTable.stories.tsx +0 -353
  196. package/src/components/organisms/dialog/dialog.doc.mdx +0 -54
  197. package/src/components/organisms/dialog/dialog.stories.tsx +0 -126
  198. package/src/components/organisms/drawer/drawer.doc.mdx +0 -59
  199. package/src/components/organisms/drawer/drawer.stories.tsx +0 -40
  200. package/src/components/organisms/dropfile/dropfile.doc.mdx +0 -74
  201. package/src/components/organisms/dropfile/dropfile.stories.tsx +0 -93
  202. package/src/components/organisms/form-builder/formBuilder.doc.mdx +0 -251
  203. package/src/components/organisms/form-builder/formBuilder.stories.tsx +0 -914
  204. package/src/components/organisms/navbar/navbar.doc.mdx +0 -77
  205. package/src/components/organisms/navbar/navbar.stories.tsx +0 -83
  206. package/src/components/organisms/page-header/page-header.doc.mdx +0 -54
  207. package/src/components/organisms/page-header/page-header.stories.tsx +0 -74
  208. package/src/components/organisms/searchTable/searchTable.doc.mdx +0 -79
  209. package/src/components/organisms/searchTable/searchTable.stories.tsx +0 -73
  210. package/src/components/organisms/sidebar/sidebar.doc.mdx +0 -176
  211. package/src/components/organisms/sidebar/sidebar.stories.tsx +0 -234
  212. package/src/components/organisms/toast/toast.doc.mdx +0 -50
  213. package/src/components/organisms/toast/toast.stories.tsx +0 -137
  214. package/src/components/organisms/topbar/topbar.doc.mdx +0 -72
  215. package/src/components/organisms/topbar/topbar.stories.tsx +0 -79
  216. package/src/components/organisms/triple-filter/tripleFilter.doc.mdx +0 -62
  217. package/src/components/organisms/triple-filter/tripleFilter.stories.tsx +0 -31
  218. package/src/components/templates/layout/layout.doc.mdx +0 -53
  219. package/src/components/templates/layout/layout.stories.tsx +0 -113
  220. package/src/components/templates/page/page.doc.mdx +0 -86
  221. package/src/components/templates/page/page.stories.tsx +0 -97
  222. package/src/components/theme-provider/themeProvider.doc.mdx +0 -85
  223. 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 />