azamat-ui-kit-cli 0.2.2

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 (213) hide show
  1. package/README.md +8 -0
  2. package/dist/index.js +432 -0
  3. package/package.json +34 -0
  4. package/vendor/package.json +4 -0
  5. package/vendor/src/components/actions/action-bar.tsx +35 -0
  6. package/vendor/src/components/actions/action-menu.tsx +120 -0
  7. package/vendor/src/components/actions/button-group.tsx +47 -0
  8. package/vendor/src/components/actions/copy-button.tsx +91 -0
  9. package/vendor/src/components/actions/copy-field.tsx +31 -0
  10. package/vendor/src/components/actions/floating-action-button.tsx +33 -0
  11. package/vendor/src/components/actions/index.ts +7 -0
  12. package/vendor/src/components/actions/public.ts +5 -0
  13. package/vendor/src/components/actions/quick-action-grid.tsx +162 -0
  14. package/vendor/src/components/calendar/calendar.tsx +328 -0
  15. package/vendor/src/components/calendar/date-picker.tsx +78 -0
  16. package/vendor/src/components/calendar/date-range-picker.tsx +96 -0
  17. package/vendor/src/components/calendar/date-utils.ts +89 -0
  18. package/vendor/src/components/calendar/index.ts +4 -0
  19. package/vendor/src/components/charts/charts.tsx +275 -0
  20. package/vendor/src/components/charts/horizontal-bar-chart.tsx +46 -0
  21. package/vendor/src/components/charts/index.ts +4 -0
  22. package/vendor/src/components/charts/kpi.tsx +68 -0
  23. package/vendor/src/components/charts/progress-ring.tsx +45 -0
  24. package/vendor/src/components/charts/public.ts +1 -0
  25. package/vendor/src/components/command/command-palette.tsx +375 -0
  26. package/vendor/src/components/command/index.ts +1 -0
  27. package/vendor/src/components/data-table/data-table-actions-column.tsx +58 -0
  28. package/vendor/src/components/data-table/data-table-bulk-actions.tsx +84 -0
  29. package/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +79 -0
  30. package/vendor/src/components/data-table/data-table-pagination.tsx +91 -0
  31. package/vendor/src/components/data-table/data-table-row-actions.tsx +48 -0
  32. package/vendor/src/components/data-table/data-table-select-column.tsx +59 -0
  33. package/vendor/src/components/data-table/data-table-sortable-header.tsx +45 -0
  34. package/vendor/src/components/data-table/data-table-toolbar.tsx +76 -0
  35. package/vendor/src/components/data-table/data-table-view-presets.tsx +128 -0
  36. package/vendor/src/components/data-table/data-table.tsx +507 -0
  37. package/vendor/src/components/data-table/index.ts +12 -0
  38. package/vendor/src/components/data-table/public.ts +10 -0
  39. package/vendor/src/components/data-table/table-export-menu.tsx +56 -0
  40. package/vendor/src/components/data-table/table-import-button.tsx +43 -0
  41. package/vendor/src/components/display/activity-feed.tsx +97 -0
  42. package/vendor/src/components/display/avatar.tsx +131 -0
  43. package/vendor/src/components/display/code-block.tsx +33 -0
  44. package/vendor/src/components/display/data-state.tsx +63 -0
  45. package/vendor/src/components/display/description-list.tsx +119 -0
  46. package/vendor/src/components/display/descriptions.tsx +83 -0
  47. package/vendor/src/components/display/entity-card.tsx +53 -0
  48. package/vendor/src/components/display/file-card.tsx +54 -0
  49. package/vendor/src/components/display/index.ts +30 -0
  50. package/vendor/src/components/display/kanban.tsx +104 -0
  51. package/vendor/src/components/display/keyboard-shortcut.tsx +31 -0
  52. package/vendor/src/components/display/list.tsx +100 -0
  53. package/vendor/src/components/display/metric-grid.tsx +86 -0
  54. package/vendor/src/components/display/progress.tsx +162 -0
  55. package/vendor/src/components/display/property-grid.tsx +54 -0
  56. package/vendor/src/components/display/result.tsx +90 -0
  57. package/vendor/src/components/display/smart-card.tsx +168 -0
  58. package/vendor/src/components/display/statistic.tsx +107 -0
  59. package/vendor/src/components/display/status-legend.tsx +108 -0
  60. package/vendor/src/components/display/tag-list.tsx +52 -0
  61. package/vendor/src/components/display/timeline.tsx +132 -0
  62. package/vendor/src/components/display/tree-view.tsx +116 -0
  63. package/vendor/src/components/feedback/alert.tsx +69 -0
  64. package/vendor/src/components/feedback/empty-state.tsx +56 -0
  65. package/vendor/src/components/feedback/index.ts +5 -0
  66. package/vendor/src/components/feedback/loading-state.tsx +39 -0
  67. package/vendor/src/components/feedback/page-state.tsx +69 -0
  68. package/vendor/src/components/feedback/status-badge.tsx +62 -0
  69. package/vendor/src/components/filters/filter-bar.tsx +89 -0
  70. package/vendor/src/components/filters/filter-chips.tsx +69 -0
  71. package/vendor/src/components/filters/index.ts +2 -0
  72. package/vendor/src/components/form/form-actions.tsx +53 -0
  73. package/vendor/src/components/form/form-async-select.tsx +26 -0
  74. package/vendor/src/components/form/form-date-input.tsx +19 -0
  75. package/vendor/src/components/form/form-date-picker.tsx +54 -0
  76. package/vendor/src/components/form/form-date-range-input.tsx +79 -0
  77. package/vendor/src/components/form/form-date-range-picker.tsx +57 -0
  78. package/vendor/src/components/form/form-field-shell.tsx +191 -0
  79. package/vendor/src/components/form/form-input.tsx +480 -0
  80. package/vendor/src/components/form/form-number-input.tsx +19 -0
  81. package/vendor/src/components/form/form-password-input.tsx +19 -0
  82. package/vendor/src/components/form/form-phone-input.tsx +22 -0
  83. package/vendor/src/components/form/form-search-input.tsx +19 -0
  84. package/vendor/src/components/form/form-section.tsx +29 -0
  85. package/vendor/src/components/form/form-select.tsx +194 -0
  86. package/vendor/src/components/form/form-switch.tsx +145 -0
  87. package/vendor/src/components/form/form-textarea.tsx +103 -0
  88. package/vendor/src/components/form/index.ts +17 -0
  89. package/vendor/src/components/form/public.ts +14 -0
  90. package/vendor/src/components/form/smart-form-shell.tsx +59 -0
  91. package/vendor/src/components/inputs/async-select.tsx +1143 -0
  92. package/vendor/src/components/inputs/clearable-input.tsx +78 -0
  93. package/vendor/src/components/inputs/color-input.tsx +47 -0
  94. package/vendor/src/components/inputs/combobox.tsx +89 -0
  95. package/vendor/src/components/inputs/date-input.tsx +32 -0
  96. package/vendor/src/components/inputs/date-range-input.tsx +67 -0
  97. package/vendor/src/components/inputs/index.ts +19 -0
  98. package/vendor/src/components/inputs/input-chrome.tsx +37 -0
  99. package/vendor/src/components/inputs/input-decorator.tsx +64 -0
  100. package/vendor/src/components/inputs/input-value.ts +42 -0
  101. package/vendor/src/components/inputs/masked-input.tsx +51 -0
  102. package/vendor/src/components/inputs/money-input.tsx +73 -0
  103. package/vendor/src/components/inputs/number-input.tsx +87 -0
  104. package/vendor/src/components/inputs/numeric-value.ts +39 -0
  105. package/vendor/src/components/inputs/otp-input.tsx +102 -0
  106. package/vendor/src/components/inputs/password-input.tsx +85 -0
  107. package/vendor/src/components/inputs/phone-input.tsx +46 -0
  108. package/vendor/src/components/inputs/quantity-input.tsx +116 -0
  109. package/vendor/src/components/inputs/quantity-stepper.tsx +49 -0
  110. package/vendor/src/components/inputs/rating.tsx +98 -0
  111. package/vendor/src/components/inputs/search-input.tsx +26 -0
  112. package/vendor/src/components/inputs/simple-select.tsx +72 -0
  113. package/vendor/src/components/inputs/slider.tsx +149 -0
  114. package/vendor/src/components/inputs/tag-input.tsx +104 -0
  115. package/vendor/src/components/layout/app-header.tsx +46 -0
  116. package/vendor/src/components/layout/app-shell.tsx +243 -0
  117. package/vendor/src/components/layout/app-sidebar.tsx +179 -0
  118. package/vendor/src/components/layout/breadcrumbs.tsx +72 -0
  119. package/vendor/src/components/layout/index.ts +11 -0
  120. package/vendor/src/components/layout/page-container.tsx +30 -0
  121. package/vendor/src/components/layout/page-header.tsx +60 -0
  122. package/vendor/src/components/layout/public.ts +10 -0
  123. package/vendor/src/components/layout/section.tsx +76 -0
  124. package/vendor/src/components/layout/sidebar-nav.tsx +147 -0
  125. package/vendor/src/components/layout/stat-card.tsx +88 -0
  126. package/vendor/src/components/layout/sticky-footer-bar.tsx +23 -0
  127. package/vendor/src/components/layout/workspace-shell.tsx +50 -0
  128. package/vendor/src/components/navigation/anchor-nav.tsx +44 -0
  129. package/vendor/src/components/navigation/index.ts +4 -0
  130. package/vendor/src/components/navigation/page-tabs.tsx +67 -0
  131. package/vendor/src/components/navigation/pagination.tsx +179 -0
  132. package/vendor/src/components/navigation/stepper-tabs.tsx +67 -0
  133. package/vendor/src/components/notifications/index.ts +1 -0
  134. package/vendor/src/components/notifications/toast.tsx +259 -0
  135. package/vendor/src/components/overlay/confirm-dialog.tsx +66 -0
  136. package/vendor/src/components/overlay/dialog-actions.tsx +68 -0
  137. package/vendor/src/components/overlay/index.ts +4 -0
  138. package/vendor/src/components/overlay/modal-shell.tsx +93 -0
  139. package/vendor/src/components/overlay/sheet-shell.tsx +212 -0
  140. package/vendor/src/components/patterns/action-system.tsx +116 -0
  141. package/vendor/src/components/patterns/crud-system.tsx +53 -0
  142. package/vendor/src/components/patterns/data-view.tsx +84 -0
  143. package/vendor/src/components/patterns/entity-details.tsx +66 -0
  144. package/vendor/src/components/patterns/filter-builder.tsx +113 -0
  145. package/vendor/src/components/patterns/form-builder-presets.ts +131 -0
  146. package/vendor/src/components/patterns/form-builder.tsx +334 -0
  147. package/vendor/src/components/patterns/index.ts +12 -0
  148. package/vendor/src/components/patterns/public.ts +4 -0
  149. package/vendor/src/components/patterns/resource-detail-page.tsx +160 -0
  150. package/vendor/src/components/patterns/resource-page.tsx +159 -0
  151. package/vendor/src/components/patterns/resource-system.tsx +61 -0
  152. package/vendor/src/components/patterns/settings-section.tsx +46 -0
  153. package/vendor/src/components/patterns/status-system.tsx +89 -0
  154. package/vendor/src/components/theme-provider.tsx +51 -0
  155. package/vendor/src/components/ui/badge.tsx +52 -0
  156. package/vendor/src/components/ui/button.tsx +61 -0
  157. package/vendor/src/components/ui/card.tsx +103 -0
  158. package/vendor/src/components/ui/checkbox.tsx +82 -0
  159. package/vendor/src/components/ui/collapse.tsx +126 -0
  160. package/vendor/src/components/ui/command.tsx +194 -0
  161. package/vendor/src/components/ui/dialog.tsx +160 -0
  162. package/vendor/src/components/ui/divider.tsx +46 -0
  163. package/vendor/src/components/ui/dropdown-menu.tsx +266 -0
  164. package/vendor/src/components/ui/input-group.tsx +158 -0
  165. package/vendor/src/components/ui/input.tsx +20 -0
  166. package/vendor/src/components/ui/popover.tsx +90 -0
  167. package/vendor/src/components/ui/segmented-control.tsx +78 -0
  168. package/vendor/src/components/ui/select.tsx +201 -0
  169. package/vendor/src/components/ui/skeleton.tsx +75 -0
  170. package/vendor/src/components/ui/spinner.tsx +50 -0
  171. package/vendor/src/components/ui/switch.tsx +71 -0
  172. package/vendor/src/components/ui/table.tsx +114 -0
  173. package/vendor/src/components/ui/tabs.tsx +55 -0
  174. package/vendor/src/components/ui/textarea.tsx +18 -0
  175. package/vendor/src/components/ui/tooltip.tsx +38 -0
  176. package/vendor/src/components/upload/file-upload.tsx +483 -0
  177. package/vendor/src/components/upload/image-upload.tsx +118 -0
  178. package/vendor/src/components/upload/index.ts +2 -0
  179. package/vendor/src/components/wizard/index.ts +2 -0
  180. package/vendor/src/components/wizard/stepper.tsx +53 -0
  181. package/vendor/src/components/wizard/wizard.tsx +60 -0
  182. package/vendor/src/families/card-family.ts +28 -0
  183. package/vendor/src/families/catalog.ts +96 -0
  184. package/vendor/src/families/data-table-family.ts +31 -0
  185. package/vendor/src/families/docs-adoption.ts +103 -0
  186. package/vendor/src/families/docs-groups.ts +209 -0
  187. package/vendor/src/families/docs-queries.ts +84 -0
  188. package/vendor/src/families/docs-routing.ts +89 -0
  189. package/vendor/src/families/form-family.ts +45 -0
  190. package/vendor/src/families/index.ts +17 -0
  191. package/vendor/src/families/input-family.ts +61 -0
  192. package/vendor/src/families/member-metadata.ts +466 -0
  193. package/vendor/src/families/member-queries.ts +28 -0
  194. package/vendor/src/families/member-snippet-queries.ts +54 -0
  195. package/vendor/src/families/member-snippets.ts +673 -0
  196. package/vendor/src/families/migration-map.ts +79 -0
  197. package/vendor/src/families/queries.ts +63 -0
  198. package/vendor/src/families/select-family.ts +33 -0
  199. package/vendor/src/families/views.ts +81 -0
  200. package/vendor/src/hooks/index.ts +6 -0
  201. package/vendor/src/hooks/use-before-unload-when-dirty.ts +21 -0
  202. package/vendor/src/hooks/use-data-table-view-state.ts +122 -0
  203. package/vendor/src/hooks/use-debounce.ts +52 -0
  204. package/vendor/src/hooks/use-disclosure.ts +38 -0
  205. package/vendor/src/hooks/use-is-mobile.ts +28 -0
  206. package/vendor/src/hooks/use-session-storage-state.ts +85 -0
  207. package/vendor/src/index.ts +38 -0
  208. package/vendor/src/lib/utils.ts +6 -0
  209. package/vendor/templates/components/button.tsx +0 -0
  210. package/vendor/templates/components/data-table.tsx +0 -0
  211. package/vendor/templates/components/input.tsx +0 -0
  212. package/vendor/templates/lib/utils.ts +0 -0
  213. package/vendor/templates/styles/globals.css +0 -0
@@ -0,0 +1,480 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import * as React from "react"
3
+ import { Controller, type Control, type FieldPath, type FieldValues } from "react-hook-form"
4
+
5
+ import { DateInput, type DateInputProps } from "@/components/inputs/date-input"
6
+ import { NumberInput, type NumberInputProps } from "@/components/inputs/number-input"
7
+ import {
8
+ PhoneInput,
9
+ formatPhoneDigits,
10
+ type PhoneInputProps,
11
+ } from "@/components/inputs/phone-input"
12
+ import { PasswordInput, type PasswordInputProps } from "@/components/inputs/password-input"
13
+ import { SearchInput, type SearchInputProps } from "@/components/inputs/search-input"
14
+ import {
15
+ FormFieldShell,
16
+ type FormFieldShellControlProps,
17
+ } from "@/components/form/form-field-shell"
18
+ import { Input } from "@/components/ui/input"
19
+
20
+ export type FormInputKind = "text" | "search" | "password" | "number" | "phone" | "date"
21
+ export type FormPhoneInputValueMode = "raw" | "masked"
22
+
23
+ type FormControlledFieldProps<
24
+ TFieldValues extends FieldValues,
25
+ TName extends FieldPath<TFieldValues>,
26
+ > = FormFieldShellControlProps & {
27
+ control: Control<TFieldValues>
28
+ name: TName
29
+ fieldClassName?: string
30
+ id?: string
31
+ }
32
+
33
+ export type FormTextInputProps<
34
+ TFieldValues extends FieldValues = FieldValues,
35
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
36
+ > = Omit<React.ComponentProps<typeof Input>, "name" | "value" | "defaultValue"> &
37
+ FormControlledFieldProps<TFieldValues, TName> & {
38
+ kind?: "text"
39
+ transformIn?: (value: unknown) => string | number | readonly string[] | undefined
40
+ transformOut?: (event: React.ChangeEvent<HTMLInputElement>) => unknown
41
+ }
42
+
43
+ export type FormInputSearchVariantProps<
44
+ TFieldValues extends FieldValues = FieldValues,
45
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
46
+ > = Omit<SearchInputProps, "name" | "value" | "defaultValue" | "onValueChange"> &
47
+ FormControlledFieldProps<TFieldValues, TName> & {
48
+ kind: "search"
49
+ onValueChange?: (value: string) => void
50
+ }
51
+
52
+ export type FormInputPasswordVariantProps<
53
+ TFieldValues extends FieldValues = FieldValues,
54
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
55
+ > = Omit<PasswordInputProps, "name" | "value" | "defaultValue" | "onValueChange"> &
56
+ FormControlledFieldProps<TFieldValues, TName> & {
57
+ kind: "password"
58
+ onValueChange?: (value: string) => void
59
+ }
60
+
61
+ export type FormInputNumberVariantProps<
62
+ TFieldValues extends FieldValues = FieldValues,
63
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
64
+ > = Omit<NumberInputProps, "name" | "value" | "defaultValue" | "onNumberChange"> &
65
+ FormControlledFieldProps<TFieldValues, TName> & {
66
+ kind: "number"
67
+ emptyValue?: unknown
68
+ onNumberChange?: (value: number | null) => void
69
+ }
70
+
71
+ export type FormInputPhoneVariantProps<
72
+ TFieldValues extends FieldValues = FieldValues,
73
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
74
+ > = Omit<PhoneInputProps, "name" | "value" | "defaultValue" | "onValueChange"> &
75
+ FormControlledFieldProps<TFieldValues, TName> & {
76
+ kind: "phone"
77
+ valueMode?: FormPhoneInputValueMode
78
+ onValueChange?: (value: string, rawValue: string, maskedValue: string) => void
79
+ }
80
+
81
+ export type FormInputDateVariantProps<
82
+ TFieldValues extends FieldValues = FieldValues,
83
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
84
+ > = Omit<DateInputProps, "name" | "value" | "defaultValue" | "onValueChange"> &
85
+ FormControlledFieldProps<TFieldValues, TName> & {
86
+ kind: "date"
87
+ emptyValue?: unknown
88
+ onValueChange?: (value: string) => void
89
+ }
90
+
91
+ export type FormInputProps<
92
+ TFieldValues extends FieldValues = FieldValues,
93
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
94
+ > =
95
+ | FormTextInputProps<TFieldValues, TName>
96
+ | FormInputSearchVariantProps<TFieldValues, TName>
97
+ | FormInputPasswordVariantProps<TFieldValues, TName>
98
+ | FormInputNumberVariantProps<TFieldValues, TName>
99
+ | FormInputPhoneVariantProps<TFieldValues, TName>
100
+ | FormInputDateVariantProps<TFieldValues, TName>
101
+
102
+ function buildShellProps<
103
+ TFieldValues extends FieldValues,
104
+ TName extends FieldPath<TFieldValues>,
105
+ >(props: FormInputProps<TFieldValues, TName>) {
106
+ return {
107
+ label: props.label,
108
+ description: props.description,
109
+ required: props.required,
110
+ className: props.className,
111
+ layout: props.layout,
112
+ descriptionPosition: props.descriptionPosition,
113
+ labelAction: props.labelAction,
114
+ requiredIndicator: props.requiredIndicator,
115
+ errorIcon: props.errorIcon,
116
+ showErrorIcon: props.showErrorIcon,
117
+ disabled: props.disabled,
118
+ readOnly: props.readOnly,
119
+ labelClassName: props.labelClassName,
120
+ labelRowClassName: props.labelRowClassName,
121
+ descriptionClassName: props.descriptionClassName,
122
+ errorClassName: props.errorClassName,
123
+ contentClassName: props.contentClassName,
124
+ } satisfies FormFieldShellControlProps
125
+ }
126
+
127
+ function FormInput<
128
+ TFieldValues extends FieldValues = FieldValues,
129
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
130
+ >(props: FormInputProps<TFieldValues, TName>) {
131
+ const inputId = props.id ?? props.name
132
+ const shellProps = buildShellProps(props)
133
+ const kind = props.kind ?? "text"
134
+
135
+ return (
136
+ <Controller
137
+ control={props.control}
138
+ name={props.name}
139
+ render={({ field, fieldState }) => {
140
+ const error = fieldState.error?.message
141
+
142
+ if (kind === "search") {
143
+ const {
144
+ control: _control,
145
+ name: _name,
146
+ label: _label,
147
+ description: _description,
148
+ required: _required,
149
+ className: _className,
150
+ layout: _layout,
151
+ descriptionPosition: _descriptionPosition,
152
+ labelAction: _labelAction,
153
+ requiredIndicator: _requiredIndicator,
154
+ errorIcon: _errorIcon,
155
+ showErrorIcon: _showErrorIcon,
156
+ disabled,
157
+ readOnly: _readOnly,
158
+ labelClassName: _labelClassName,
159
+ labelRowClassName: _labelRowClassName,
160
+ descriptionClassName: _descriptionClassName,
161
+ errorClassName: _errorClassName,
162
+ contentClassName: _contentClassName,
163
+ fieldClassName,
164
+ id,
165
+ kind: _kind,
166
+ onValueChange,
167
+ onBlur,
168
+ ...searchProps
169
+ } = props as FormInputSearchVariantProps<TFieldValues, TName>
170
+
171
+ return (
172
+ <FormFieldShell {...shellProps} error={error} htmlFor={id ?? inputId}>
173
+ <SearchInput
174
+ {...searchProps}
175
+ id={id ?? inputId}
176
+ name={field.name}
177
+ ref={field.ref}
178
+ value={field.value ?? ""}
179
+ disabled={disabled}
180
+ inputClassName={fieldClassName}
181
+ aria-invalid={fieldState.invalid || undefined}
182
+ onBlur={(event) => {
183
+ field.onBlur()
184
+ onBlur?.(event)
185
+ }}
186
+ onValueChange={(value) => {
187
+ field.onChange(value)
188
+ onValueChange?.(value)
189
+ }}
190
+ />
191
+ </FormFieldShell>
192
+ )
193
+ }
194
+
195
+ if (kind === "password") {
196
+ const {
197
+ control: _control,
198
+ name: _name,
199
+ label: _label,
200
+ description: _description,
201
+ required: _required,
202
+ className: _className,
203
+ layout: _layout,
204
+ descriptionPosition: _descriptionPosition,
205
+ labelAction: _labelAction,
206
+ requiredIndicator: _requiredIndicator,
207
+ errorIcon: _errorIcon,
208
+ showErrorIcon: _showErrorIcon,
209
+ disabled,
210
+ readOnly: _readOnly,
211
+ labelClassName: _labelClassName,
212
+ labelRowClassName: _labelRowClassName,
213
+ descriptionClassName: _descriptionClassName,
214
+ errorClassName: _errorClassName,
215
+ contentClassName: _contentClassName,
216
+ fieldClassName,
217
+ id,
218
+ kind: _kind,
219
+ onValueChange,
220
+ onBlur,
221
+ ...passwordProps
222
+ } = props as FormInputPasswordVariantProps<TFieldValues, TName>
223
+
224
+ return (
225
+ <FormFieldShell {...shellProps} error={error} htmlFor={id ?? inputId}>
226
+ <PasswordInput
227
+ {...passwordProps}
228
+ id={id ?? inputId}
229
+ name={field.name}
230
+ ref={field.ref}
231
+ value={field.value ?? ""}
232
+ disabled={disabled}
233
+ inputClassName={fieldClassName}
234
+ aria-invalid={fieldState.invalid || undefined}
235
+ onBlur={(event) => {
236
+ field.onBlur()
237
+ onBlur?.(event)
238
+ }}
239
+ onValueChange={(value) => {
240
+ field.onChange(value)
241
+ onValueChange?.(value)
242
+ }}
243
+ />
244
+ </FormFieldShell>
245
+ )
246
+ }
247
+
248
+ if (kind === "number") {
249
+ const {
250
+ control: _control,
251
+ name: _name,
252
+ label: _label,
253
+ description: _description,
254
+ required: _required,
255
+ className: _className,
256
+ layout: _layout,
257
+ descriptionPosition: _descriptionPosition,
258
+ labelAction: _labelAction,
259
+ requiredIndicator: _requiredIndicator,
260
+ errorIcon: _errorIcon,
261
+ showErrorIcon: _showErrorIcon,
262
+ disabled,
263
+ readOnly: _readOnly,
264
+ labelClassName: _labelClassName,
265
+ labelRowClassName: _labelRowClassName,
266
+ descriptionClassName: _descriptionClassName,
267
+ errorClassName: _errorClassName,
268
+ contentClassName: _contentClassName,
269
+ fieldClassName,
270
+ id,
271
+ kind: _kind,
272
+ emptyValue = null,
273
+ onNumberChange,
274
+ onBlur,
275
+ ...numberProps
276
+ } = props as FormInputNumberVariantProps<TFieldValues, TName>
277
+
278
+ return (
279
+ <FormFieldShell {...shellProps} error={error} htmlFor={id ?? inputId}>
280
+ <NumberInput
281
+ {...numberProps}
282
+ id={id ?? inputId}
283
+ name={field.name}
284
+ ref={field.ref}
285
+ value={field.value ?? ""}
286
+ disabled={disabled}
287
+ readOnly={props.readOnly}
288
+ className={fieldClassName}
289
+ aria-invalid={fieldState.invalid || undefined}
290
+ onBlur={(event) => {
291
+ field.onBlur()
292
+ onBlur?.(event)
293
+ }}
294
+ onNumberChange={(value) => {
295
+ field.onChange(value ?? emptyValue)
296
+ onNumberChange?.(value)
297
+ }}
298
+ />
299
+ </FormFieldShell>
300
+ )
301
+ }
302
+
303
+ if (kind === "phone") {
304
+ const {
305
+ control: _control,
306
+ name: _name,
307
+ label: _label,
308
+ description: _description,
309
+ required: _required,
310
+ className: _className,
311
+ layout: _layout,
312
+ descriptionPosition: _descriptionPosition,
313
+ labelAction: _labelAction,
314
+ requiredIndicator: _requiredIndicator,
315
+ errorIcon: _errorIcon,
316
+ showErrorIcon: _showErrorIcon,
317
+ disabled,
318
+ readOnly: _readOnly,
319
+ labelClassName: _labelClassName,
320
+ labelRowClassName: _labelRowClassName,
321
+ descriptionClassName: _descriptionClassName,
322
+ errorClassName: _errorClassName,
323
+ contentClassName: _contentClassName,
324
+ fieldClassName,
325
+ id,
326
+ kind: _kind,
327
+ valueMode = "raw",
328
+ countryCode = "+998",
329
+ maxDigits = 12,
330
+ onValueChange,
331
+ onBlur,
332
+ ...phoneProps
333
+ } = props as FormInputPhoneVariantProps<TFieldValues, TName>
334
+
335
+ const fieldValue = field.value == null ? "" : String(field.value)
336
+ const displayValue =
337
+ valueMode === "raw" ? formatPhoneDigits(fieldValue, countryCode, maxDigits) : fieldValue
338
+
339
+ return (
340
+ <FormFieldShell {...shellProps} error={error} htmlFor={id ?? inputId}>
341
+ <PhoneInput
342
+ {...phoneProps}
343
+ id={id ?? inputId}
344
+ name={field.name}
345
+ ref={field.ref}
346
+ value={displayValue}
347
+ disabled={disabled}
348
+ readOnly={props.readOnly}
349
+ countryCode={countryCode}
350
+ maxDigits={maxDigits}
351
+ className={fieldClassName}
352
+ aria-invalid={fieldState.invalid || undefined}
353
+ onBlur={(event) => {
354
+ field.onBlur()
355
+ onBlur?.(event)
356
+ }}
357
+ onValueChange={(maskedValue, rawValue) => {
358
+ const nextValue = valueMode === "raw" ? rawValue : maskedValue
359
+ field.onChange(nextValue)
360
+ onValueChange?.(nextValue, rawValue, maskedValue)
361
+ }}
362
+ />
363
+ </FormFieldShell>
364
+ )
365
+ }
366
+
367
+ if (kind === "date") {
368
+ const {
369
+ control: _control,
370
+ name: _name,
371
+ label: _label,
372
+ description: _description,
373
+ required: _required,
374
+ className: _className,
375
+ layout: _layout,
376
+ descriptionPosition: _descriptionPosition,
377
+ labelAction: _labelAction,
378
+ requiredIndicator: _requiredIndicator,
379
+ errorIcon: _errorIcon,
380
+ showErrorIcon: _showErrorIcon,
381
+ disabled,
382
+ readOnly: _readOnly,
383
+ labelClassName: _labelClassName,
384
+ labelRowClassName: _labelRowClassName,
385
+ descriptionClassName: _descriptionClassName,
386
+ errorClassName: _errorClassName,
387
+ contentClassName: _contentClassName,
388
+ fieldClassName,
389
+ id,
390
+ kind: _kind,
391
+ emptyValue = "",
392
+ onValueChange,
393
+ onBlur,
394
+ ...dateProps
395
+ } = props as FormInputDateVariantProps<TFieldValues, TName>
396
+
397
+ return (
398
+ <FormFieldShell {...shellProps} error={error} htmlFor={id ?? inputId}>
399
+ <DateInput
400
+ {...dateProps}
401
+ id={id ?? inputId}
402
+ name={field.name}
403
+ ref={field.ref}
404
+ value={field.value ?? ""}
405
+ disabled={disabled}
406
+ readOnly={props.readOnly}
407
+ className={fieldClassName}
408
+ aria-invalid={fieldState.invalid || undefined}
409
+ onBlur={(event) => {
410
+ field.onBlur()
411
+ onBlur?.(event)
412
+ }}
413
+ onValueChange={(value) => {
414
+ field.onChange(value || emptyValue)
415
+ onValueChange?.(value)
416
+ }}
417
+ />
418
+ </FormFieldShell>
419
+ )
420
+ }
421
+
422
+ const {
423
+ control: _control,
424
+ name: _name,
425
+ label: _label,
426
+ description: _description,
427
+ required: _required,
428
+ className: _className,
429
+ layout: _layout,
430
+ descriptionPosition: _descriptionPosition,
431
+ labelAction: _labelAction,
432
+ requiredIndicator: _requiredIndicator,
433
+ errorIcon: _errorIcon,
434
+ showErrorIcon: _showErrorIcon,
435
+ disabled,
436
+ readOnly,
437
+ labelClassName: _labelClassName,
438
+ labelRowClassName: _labelRowClassName,
439
+ descriptionClassName: _descriptionClassName,
440
+ errorClassName: _errorClassName,
441
+ contentClassName: _contentClassName,
442
+ fieldClassName,
443
+ transformIn,
444
+ transformOut,
445
+ id,
446
+ kind: _kind,
447
+ onChange,
448
+ onBlur,
449
+ ...inputProps
450
+ } = props as FormTextInputProps<TFieldValues, TName>
451
+
452
+ return (
453
+ <FormFieldShell {...shellProps} error={error} htmlFor={id ?? inputId}>
454
+ <Input
455
+ {...inputProps}
456
+ id={id ?? inputId}
457
+ ref={field.ref}
458
+ name={field.name}
459
+ value={transformIn ? transformIn(field.value) : field.value ?? ""}
460
+ disabled={disabled}
461
+ readOnly={readOnly}
462
+ onBlur={(event) => {
463
+ field.onBlur()
464
+ onBlur?.(event)
465
+ }}
466
+ onChange={(event) => {
467
+ field.onChange(transformOut ? transformOut(event) : event)
468
+ onChange?.(event)
469
+ }}
470
+ aria-invalid={fieldState.invalid || undefined}
471
+ className={fieldClassName}
472
+ />
473
+ </FormFieldShell>
474
+ )
475
+ }}
476
+ />
477
+ )
478
+ }
479
+
480
+ export { FormInput }
@@ -0,0 +1,19 @@
1
+ import {
2
+ FormInput,
3
+ type FormInputNumberVariantProps as BaseFormNumberInputProps,
4
+ } from "@/components/form/form-input"
5
+ import type { FieldPath, FieldValues } from "react-hook-form"
6
+
7
+ export type FormNumberInputProps<
8
+ TFieldValues extends FieldValues = FieldValues,
9
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
10
+ > = Omit<BaseFormNumberInputProps<TFieldValues, TName>, "kind">
11
+
12
+ function FormNumberInput<
13
+ TFieldValues extends FieldValues = FieldValues,
14
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
15
+ >(props: FormNumberInputProps<TFieldValues, TName>) {
16
+ return <FormInput {...props} kind="number" />
17
+ }
18
+
19
+ export { FormNumberInput }
@@ -0,0 +1,19 @@
1
+ import {
2
+ FormInput,
3
+ type FormInputPasswordVariantProps as BaseFormPasswordInputProps,
4
+ } from "@/components/form/form-input"
5
+ import type { FieldPath, FieldValues } from "react-hook-form"
6
+
7
+ export type FormPasswordInputProps<
8
+ TFieldValues extends FieldValues = FieldValues,
9
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
10
+ > = Omit<BaseFormPasswordInputProps<TFieldValues, TName>, "kind">
11
+
12
+ function FormPasswordInput<
13
+ TFieldValues extends FieldValues = FieldValues,
14
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
15
+ >(props: FormPasswordInputProps<TFieldValues, TName>) {
16
+ return <FormInput {...props} kind="password" />
17
+ }
18
+
19
+ export { FormPasswordInput }
@@ -0,0 +1,22 @@
1
+ import {
2
+ FormInput,
3
+ type FormInputPhoneVariantProps as BaseFormPhoneInputProps,
4
+ type FormPhoneInputValueMode,
5
+ } from "@/components/form/form-input"
6
+ import type { FieldPath, FieldValues } from "react-hook-form"
7
+
8
+ export type { FormPhoneInputValueMode }
9
+
10
+ export type FormPhoneInputProps<
11
+ TFieldValues extends FieldValues = FieldValues,
12
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
13
+ > = Omit<BaseFormPhoneInputProps<TFieldValues, TName>, "kind">
14
+
15
+ function FormPhoneInput<
16
+ TFieldValues extends FieldValues = FieldValues,
17
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
18
+ >(props: FormPhoneInputProps<TFieldValues, TName>) {
19
+ return <FormInput {...props} kind="phone" />
20
+ }
21
+
22
+ export { FormPhoneInput }
@@ -0,0 +1,19 @@
1
+ import {
2
+ FormInput,
3
+ type FormInputSearchVariantProps as BaseFormSearchInputProps,
4
+ } from "@/components/form/form-input"
5
+ import type { FieldPath, FieldValues } from "react-hook-form"
6
+
7
+ export type FormSearchInputProps<
8
+ TFieldValues extends FieldValues = FieldValues,
9
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
10
+ > = Omit<BaseFormSearchInputProps<TFieldValues, TName>, "kind">
11
+
12
+ function FormSearchInput<
13
+ TFieldValues extends FieldValues = FieldValues,
14
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
15
+ >(props: FormSearchInputProps<TFieldValues, TName>) {
16
+ return <FormInput {...props} kind="search" />
17
+ }
18
+
19
+ export { FormSearchInput }
@@ -0,0 +1,29 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ export type FormSectionProps = Omit<React.ComponentProps<"section">, "title"> & {
6
+ title?: React.ReactNode
7
+ description?: React.ReactNode
8
+ actions?: React.ReactNode
9
+ columns?: 1 | 2 | 3
10
+ }
11
+
12
+ function FormSection({ title, description, actions, columns = 1, className, children, ...props }: FormSectionProps) {
13
+ return (
14
+ <section data-slot="form-section" className={cn("grid gap-4 rounded-lg border bg-card p-4", className)} {...props}>
15
+ {(title || description || actions) && (
16
+ <div className="flex flex-wrap items-start justify-between gap-3">
17
+ <div className="grid gap-1">
18
+ {title && <h3 className="text-base font-semibold text-foreground">{title}</h3>}
19
+ {description && <p className="text-sm text-muted-foreground">{description}</p>}
20
+ </div>
21
+ {actions}
22
+ </div>
23
+ )}
24
+ <div className={cn("grid gap-4", columns === 2 && "sm:grid-cols-2", columns === 3 && "sm:grid-cols-2 lg:grid-cols-3")}>{children}</div>
25
+ </section>
26
+ )
27
+ }
28
+
29
+ export { FormSection }