torch-glare 2.4.0 → 2.4.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 (318) hide show
  1. package/README.md +8 -0
  2. package/apps/lib/components/ActionButton.tsx +7 -12
  3. package/apps/lib/components/ActionsGroup.tsx +4 -15
  4. package/apps/lib/components/AlertDialog.tsx +173 -191
  5. package/apps/lib/components/Avatar.tsx +13 -16
  6. package/apps/lib/components/Badge.tsx +1 -3
  7. package/apps/lib/components/BadgeField.tsx +76 -71
  8. package/apps/lib/components/Breadcrumb.tsx +49 -85
  9. package/apps/lib/components/Button.tsx +21 -20
  10. package/apps/lib/components/ButtonGroup.tsx +31 -41
  11. package/apps/lib/components/Calendar.tsx +51 -29
  12. package/apps/lib/components/Card.tsx +40 -24
  13. package/apps/lib/components/Checkbox.tsx +9 -16
  14. package/apps/lib/components/ColorPicker.tsx +441 -0
  15. package/apps/lib/components/ConclusionHeader.tsx +148 -0
  16. package/apps/lib/components/ContextMenu.tsx +97 -96
  17. package/apps/lib/components/CountBadge.tsx +4 -6
  18. package/apps/lib/components/DataTable.tsx +196 -216
  19. package/apps/lib/components/DataViews/DataViewRadio.tsx +1 -6
  20. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +13 -47
  21. package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
  22. package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
  23. package/apps/lib/components/DataViews/FilterPanel.tsx +155 -149
  24. package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
  25. package/apps/lib/components/DataViews/InboxView.tsx +22 -68
  26. package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
  27. package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
  28. package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
  29. package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
  30. package/apps/lib/components/DataViews/TableView.tsx +8 -28
  31. package/apps/lib/components/DataViews/TreeView.tsx +12 -40
  32. package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
  33. package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
  34. package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +30 -23
  35. package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
  36. package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
  37. package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
  38. package/apps/lib/components/DataViews/index.ts +26 -26
  39. package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
  40. package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
  41. package/apps/lib/components/DataViews/types.ts +104 -115
  42. package/apps/lib/components/DatePicker.tsx +200 -196
  43. package/apps/lib/components/Dialog.tsx +92 -105
  44. package/apps/lib/components/Divider.tsx +21 -24
  45. package/apps/lib/components/Drawer.tsx +124 -142
  46. package/apps/lib/components/DropdownMenu.tsx +131 -171
  47. package/apps/lib/components/FieldHint.tsx +4 -11
  48. package/apps/lib/components/Form.tsx +146 -155
  49. package/apps/lib/components/FormBuilder/DisplayField.tsx +40 -0
  50. package/apps/lib/components/FormBuilder/context.ts +71 -0
  51. package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +65 -0
  52. package/apps/lib/components/FormBuilder/fields/ColorField.tsx +76 -0
  53. package/apps/lib/components/FormBuilder/fields/CustomField.tsx +16 -0
  54. package/apps/lib/components/FormBuilder/fields/DateField.tsx +34 -0
  55. package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +79 -0
  56. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +174 -0
  57. package/apps/lib/components/FormBuilder/fields/FileField.tsx +40 -0
  58. package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +139 -0
  59. package/apps/lib/components/FormBuilder/fields/OtpField.tsx +32 -0
  60. package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +82 -0
  61. package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +37 -0
  62. package/apps/lib/components/FormBuilder/fields/SelectField.tsx +101 -0
  63. package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +175 -0
  64. package/apps/lib/components/FormBuilder/fields/SliderField.tsx +72 -0
  65. package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +42 -0
  66. package/apps/lib/components/FormBuilder/fields/TableField.tsx +312 -0
  67. package/apps/lib/components/FormBuilder/fields/TextField.tsx +222 -0
  68. package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +49 -0
  69. package/apps/lib/components/FormBuilder/fields/countries.ts +303 -0
  70. package/apps/lib/components/FormBuilder/fields/index.ts +25 -0
  71. package/apps/lib/components/FormBuilder/form-builder.tsx +292 -0
  72. package/apps/lib/components/FormBuilder/header.tsx +105 -0
  73. package/apps/lib/components/FormBuilder/index.ts +37 -0
  74. package/apps/lib/components/FormBuilder/numberFormat.ts +16 -0
  75. package/apps/lib/components/FormBuilder/stepper.tsx +217 -0
  76. package/apps/lib/components/FormBuilder/submit.tsx +41 -0
  77. package/apps/lib/components/FormBuilder/types.ts +264 -0
  78. package/apps/lib/components/FormBuilder/viewFormat.tsx +137 -0
  79. package/apps/lib/components/FormRenderer/FormDrawer.tsx +121 -0
  80. package/apps/lib/components/FormRenderer/form-renderer.tsx +113 -0
  81. package/apps/lib/components/FormRenderer/index.ts +9 -0
  82. package/apps/lib/components/FormRenderer/types.ts +79 -0
  83. package/apps/lib/components/FormStepper.tsx +9 -39
  84. package/apps/lib/components/FormSummary.tsx +282 -0
  85. package/apps/lib/components/HeaderBar.tsx +1 -9
  86. package/apps/lib/components/ImageAttachment.tsx +106 -93
  87. package/apps/lib/components/InnerLabelField.tsx +20 -16
  88. package/apps/lib/components/Input.tsx +171 -172
  89. package/apps/lib/components/InputField.tsx +44 -45
  90. package/apps/lib/components/InputOTP.tsx +68 -69
  91. package/apps/lib/components/Label.tsx +61 -58
  92. package/apps/lib/components/LabelField.tsx +4 -5
  93. package/apps/lib/components/LabeledCheckBox.tsx +8 -12
  94. package/apps/lib/components/LabeledRadio.tsx +7 -5
  95. package/apps/lib/components/LinkButton.tsx +2 -9
  96. package/apps/lib/components/LoginButton.tsx +4 -9
  97. package/apps/lib/components/PasswordLevel.tsx +5 -5
  98. package/apps/lib/components/Popover.tsx +15 -33
  99. package/apps/lib/components/ProfileMenu.tsx +67 -72
  100. package/apps/lib/components/Radio.tsx +1 -5
  101. package/apps/lib/components/RadioCard.tsx +11 -28
  102. package/apps/lib/components/ScrollArea.tsx +45 -43
  103. package/apps/lib/components/SearchField.tsx +49 -39
  104. package/apps/lib/components/SearchableSelect.tsx +16 -16
  105. package/apps/lib/components/SearchableTable.tsx +108 -118
  106. package/apps/lib/components/SearchableTree.tsx +469 -0
  107. package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
  108. package/apps/lib/components/SectionBlock.tsx +19 -23
  109. package/apps/lib/components/Select.tsx +80 -186
  110. package/apps/lib/components/SimpleSelect.tsx +196 -187
  111. package/apps/lib/components/Skeleton.tsx +9 -12
  112. package/apps/lib/components/SlideDatePicker.tsx +215 -166
  113. package/apps/lib/components/SpinLoading.tsx +33 -49
  114. package/apps/lib/components/Stepper.tsx +13 -56
  115. package/apps/lib/components/Switch.tsx +8 -10
  116. package/apps/lib/components/TabFormItem.tsx +3 -12
  117. package/apps/lib/components/TabSwitch.tsx +7 -34
  118. package/apps/lib/components/Table.tsx +60 -75
  119. package/apps/lib/components/{ChartBlockTool.ts → TextEditor/ChartBlockTool.ts} +17 -52
  120. package/apps/lib/components/TextEditor/RichTextField.tsx +46 -0
  121. package/apps/lib/components/{TableDnDWrapper.ts → TextEditor/TableDnDWrapper.ts} +15 -48
  122. package/apps/lib/components/{TextEditor.tsx → TextEditor/TextEditor.tsx} +156 -113
  123. package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +429 -0
  124. package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +70 -0
  125. package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +50 -0
  126. package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +48 -0
  127. package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +98 -0
  128. package/apps/lib/{types → components/TextEditor}/editorjs.d.ts +19 -0
  129. package/apps/lib/components/TextEditor/index.ts +7 -0
  130. package/apps/lib/{utils → components/TextEditor}/markdownParser.ts +2 -7
  131. package/apps/lib/components/Textarea.tsx +9 -13
  132. package/apps/lib/components/Timeline.tsx +21 -41
  133. package/apps/lib/components/Toast.tsx +83 -83
  134. package/apps/lib/components/Toggle.tsx +112 -114
  135. package/apps/lib/components/ToggleButton.tsx +1 -1
  136. package/apps/lib/components/Tooltip.tsx +24 -19
  137. package/apps/lib/components/TransparentLabel.tsx +61 -62
  138. package/apps/lib/components/TreeDropDown.tsx +86 -52
  139. package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
  140. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
  141. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
  142. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
  143. package/apps/lib/components/TreeFolder/icons.tsx +14 -17
  144. package/apps/lib/components/TreeFolder/index.ts +15 -8
  145. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
  146. package/apps/lib/components/TreeFolder/types.ts +32 -32
  147. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
  148. package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
  149. package/apps/lib/hooks/useClickOutside.ts +21 -20
  150. package/apps/lib/hooks/useDataViewsState.ts +86 -80
  151. package/apps/lib/hooks/useIsMobile.ts +12 -12
  152. package/apps/lib/hooks/useResize.ts +54 -65
  153. package/apps/lib/hooks/useTagSelection.ts +201 -201
  154. package/apps/lib/layouts/CNLayout.tsx +181 -140
  155. package/apps/lib/layouts/DataViewCard.tsx +4 -18
  156. package/apps/lib/layouts/FieldSection.tsx +2 -6
  157. package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
  158. package/apps/lib/providers/ThemeProvider.tsx +8 -23
  159. package/apps/lib/registry.json +997 -0
  160. package/apps/lib/tsconfig.json +9 -0
  161. package/apps/lib/tsconfig.tsbuildinfo +1 -0
  162. package/apps/lib/utils/cn.ts +1 -1
  163. package/apps/lib/utils/color.ts +175 -0
  164. package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
  165. package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
  166. package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
  167. package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
  168. package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
  169. package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
  170. package/apps/lib/utils/dateFormat.ts +64 -54
  171. package/apps/lib/utils/resize.ts +21 -25
  172. package/apps/lib/utils/types.ts +13 -13
  173. package/dist/bin/index.js +8 -2
  174. package/dist/bin/index.js.map +1 -1
  175. package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
  176. package/dist/src/shared/getAvailableFiles.js +6 -1
  177. package/dist/src/shared/getAvailableFiles.js.map +1 -1
  178. package/dist/src/shared/loadRegistry.d.ts +7 -0
  179. package/dist/src/shared/loadRegistry.d.ts.map +1 -0
  180. package/dist/src/shared/loadRegistry.js +31 -0
  181. package/dist/src/shared/loadRegistry.js.map +1 -0
  182. package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
  183. package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
  184. package/dist/src/shared/resolveInstallPlan.js +39 -0
  185. package/dist/src/shared/resolveInstallPlan.js.map +1 -0
  186. package/dist/src/types/main.d.ts +24 -0
  187. package/dist/src/types/main.d.ts.map +1 -1
  188. package/docs/README.md +10 -2
  189. package/docs/components/action-button.md +30 -24
  190. package/docs/components/actions-group.md +26 -20
  191. package/docs/components/alert-dialog.md +45 -45
  192. package/docs/components/avatar.md +6 -2
  193. package/docs/components/badge-field.md +6 -2
  194. package/docs/components/badge.md +7 -1
  195. package/docs/components/breadcrumb.md +15 -40
  196. package/docs/components/button-group.md +13 -10
  197. package/docs/components/button.md +58 -33
  198. package/docs/components/calendar.md +26 -19
  199. package/docs/components/card.md +23 -18
  200. package/docs/components/chart-block-tool.md +129 -0
  201. package/docs/components/checkbox.md +16 -8
  202. package/docs/components/cn-layout.md +7 -1
  203. package/docs/components/color-picker.md +101 -0
  204. package/docs/components/conclusion-header.md +80 -0
  205. package/docs/components/context-menu.md +18 -25
  206. package/docs/components/count-badge.md +7 -1
  207. package/docs/components/data-table.md +45 -33
  208. package/docs/components/data-views-config-panel.md +15 -11
  209. package/docs/components/data-views-layout.md +13 -16
  210. package/docs/components/date-picker.md +30 -23
  211. package/docs/components/dialog.md +43 -42
  212. package/docs/components/divider.md +10 -4
  213. package/docs/components/drawer.md +161 -135
  214. package/docs/components/dropdown-menu.md +25 -34
  215. package/docs/components/field-hint.md +37 -25
  216. package/docs/components/field-section.md +9 -3
  217. package/docs/components/form-builder.md +270 -0
  218. package/docs/components/form-renderer.md +228 -0
  219. package/docs/components/form-stepper.md +6 -0
  220. package/docs/components/form-summary.md +123 -0
  221. package/docs/components/form.md +17 -20
  222. package/docs/components/header-bar.md +6 -0
  223. package/docs/components/image-attachment.md +43 -45
  224. package/docs/components/inbox-view.md +16 -5
  225. package/docs/components/inner-label-field.md +34 -24
  226. package/docs/components/input-field.md +18 -10
  227. package/docs/components/input-otp.md +14 -11
  228. package/docs/components/input.md +22 -16
  229. package/docs/components/kanban-view.md +15 -5
  230. package/docs/components/label-field.md +32 -22
  231. package/docs/components/label.md +43 -32
  232. package/docs/components/labeled-check-box.md +16 -8
  233. package/docs/components/labeled-radio.md +18 -11
  234. package/docs/components/link-button.md +7 -1
  235. package/docs/components/login-button.md +8 -2
  236. package/docs/components/password-level.md +37 -24
  237. package/docs/components/popover.md +26 -23
  238. package/docs/components/profile-menu.md +38 -27
  239. package/docs/components/radio-card.md +16 -9
  240. package/docs/components/radio.md +16 -8
  241. package/docs/components/scroll-area.md +6 -2
  242. package/docs/components/search-field.md +14 -6
  243. package/docs/components/searchable-select.md +19 -14
  244. package/docs/components/searchable-table.md +18 -13
  245. package/docs/components/searchable-tree-dialog.md +190 -0
  246. package/docs/components/searchable-tree.md +200 -0
  247. package/docs/components/section-block.md +12 -4
  248. package/docs/components/select.md +23 -18
  249. package/docs/components/simple-select.md +14 -10
  250. package/docs/components/skeleton.md +43 -33
  251. package/docs/components/slide-date-picker.md +37 -29
  252. package/docs/components/spin-loading.md +32 -23
  253. package/docs/components/stepper.md +6 -0
  254. package/docs/components/switch.md +14 -6
  255. package/docs/components/tab-form-item.md +7 -1
  256. package/docs/components/tab-switch.md +13 -6
  257. package/docs/components/table-dnd-wrapper.md +107 -0
  258. package/docs/components/table-view.md +15 -5
  259. package/docs/components/table.md +28 -28
  260. package/docs/components/text-editor.md +37 -13
  261. package/docs/components/textarea.md +15 -7
  262. package/docs/components/timeline.md +6 -0
  263. package/docs/components/toast.md +35 -26
  264. package/docs/components/toggle-button.md +24 -21
  265. package/docs/components/toggle.md +23 -15
  266. package/docs/components/tooltip.md +42 -30
  267. package/docs/components/transparent-label.md +29 -20
  268. package/docs/components/tree-drop-down.md +31 -23
  269. package/docs/components/tree-sub-layout.md +6 -2
  270. package/docs/components/tree-view.md +16 -5
  271. package/docs/explanation/architecture.md +54 -0
  272. package/docs/explanation/design-system.md +52 -0
  273. package/docs/how-to/data-views-from-backend-response.md +6 -4
  274. package/docs/how-to/form-and-list-recipes.md +26 -19
  275. package/docs/how-to/forms-with-form-builder.md +408 -0
  276. package/docs/how-to/guides.md +177 -197
  277. package/docs/migration/changelog.md +38 -0
  278. package/docs/reference/cli.md +87 -0
  279. package/docs/reference/components.md +11 -12
  280. package/docs/reference/hooks.md +8 -8
  281. package/docs/reference/providers.md +22 -22
  282. package/docs/reference/tailwind-plugins.md +2 -2
  283. package/docs/reference/theme.md +85 -0
  284. package/docs/reference/types.md +4 -4
  285. package/docs/reference/utilities.md +19 -26
  286. package/docs/tutorials/building-first-form.md +170 -172
  287. package/docs/tutorials/component-composition.md +34 -50
  288. package/docs/tutorials/getting-started.md +2 -2
  289. package/docs/tutorials/theming-basics.md +13 -10
  290. package/package.json +31 -3
  291. package/dist/src/commands/block.d.ts +0 -5
  292. package/dist/src/commands/block.d.ts.map +0 -1
  293. package/dist/src/commands/block.js +0 -255
  294. package/dist/src/commands/block.js.map +0 -1
  295. package/dist/src/shared/configureFonts.d.ts +0 -6
  296. package/dist/src/shared/configureFonts.d.ts.map +0 -1
  297. package/dist/src/shared/configureFonts.js +0 -106
  298. package/dist/src/shared/configureFonts.js.map +0 -1
  299. package/dist/src/shared/configureGlobalCss.d.ts +0 -6
  300. package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
  301. package/dist/src/shared/configureGlobalCss.js +0 -154
  302. package/dist/src/shared/configureGlobalCss.js.map +0 -1
  303. package/dist/src/shared/configureTailwind.d.ts +0 -7
  304. package/dist/src/shared/configureTailwind.d.ts.map +0 -1
  305. package/dist/src/shared/configureTailwind.js +0 -163
  306. package/dist/src/shared/configureTailwind.js.map +0 -1
  307. package/dist/src/shared/detectFramework.d.ts +0 -23
  308. package/dist/src/shared/detectFramework.d.ts.map +0 -1
  309. package/dist/src/shared/detectFramework.js +0 -119
  310. package/dist/src/shared/detectFramework.js.map +0 -1
  311. package/dist/src/shared/installBaseUtils.d.ts +0 -5
  312. package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
  313. package/dist/src/shared/installBaseUtils.js +0 -79
  314. package/dist/src/shared/installBaseUtils.js.map +0 -1
  315. package/dist/src/shared/resolveAliases.d.ts +0 -24
  316. package/dist/src/shared/resolveAliases.d.ts.map +0 -1
  317. package/dist/src/shared/resolveAliases.js +0 -98
  318. package/dist/src/shared/resolveAliases.js.map +0 -1
@@ -16,9 +16,19 @@ related:
16
16
 
17
17
  Learn how to build complete, production-ready forms with TORCH Glare. This tutorial covers everything from basic inputs to validation and error handling.
18
18
 
19
+ > **Build real forms with `FormBuilder`.** In an actual app, do **not** hand-wire fields with
20
+ > `useState` + `LabelField`/`InputField` rows as this tutorial does — that boilerplate is exactly
21
+ > what [`FormBuilder`](../components/form-builder.md) removes. With `FormBuilder` each field is one
22
+ > JSX child (`<FormBuilder.Text name="…" label="…" required />`) and validation comes from a
23
+ > react-hook-form resolver. Add [`FormRenderer`](../components/form-renderer.md) for page/drawer
24
+ > chrome + an `actions` slot for the Save, and [`FormSummary`](../components/form-summary.md) for live totals.
25
+ > See the **[Forms with FormBuilder](../how-to/forms-with-form-builder.md)** guide. The manual
26
+ > approach below is kept only to show what `FormBuilder` does under the hood.
27
+
19
28
  ## What You'll Build
20
29
 
21
30
  A user registration form with:
31
+
22
32
  - Multiple input types (text, email, password)
23
33
  - Form validation
24
34
  - Error handling and display
@@ -40,29 +50,27 @@ Let's start with a basic form structure:
40
50
 
41
51
  ```tsx
42
52
  // components/RegistrationForm.tsx
43
- 'use client';
53
+ "use client";
44
54
 
45
- import { useState } from 'react';
46
- import { Button } from '@torch-ai/torch-glare';
55
+ import { useState } from "react";
56
+ import { Button } from "@/components/Button";
47
57
 
48
58
  export default function RegistrationForm() {
49
59
  const [formData, setFormData] = useState({
50
- fullName: '',
51
- email: '',
52
- password: '',
53
- confirmPassword: '',
60
+ fullName: "",
61
+ email: "",
62
+ password: "",
63
+ confirmPassword: "",
54
64
  });
55
65
 
56
66
  const handleSubmit = (e: React.FormEvent) => {
57
67
  e.preventDefault();
58
- console.log('Form submitted:', formData);
68
+ console.log("Form submitted:", formData);
59
69
  };
60
70
 
61
71
  return (
62
72
  <form onSubmit={handleSubmit} className="max-w-md mx-auto p-6">
63
- <h2 className="typography-display-medium-bold mb-6">
64
- Create Account
65
- </h2>
73
+ <h2 className="typography-display-medium-bold mb-6">Create Account</h2>
66
74
 
67
75
  {/* We'll add fields here */}
68
76
 
@@ -83,36 +91,35 @@ export default function RegistrationForm() {
83
91
  `LabelField` combines a label and input field with built-in styling:
84
92
 
85
93
  ```tsx
86
- import { useState } from 'react';
87
- import { LabelField, Button } from '@torch-ai/torch-glare';
94
+ import { useState } from "react";
95
+ import { Button } from "@/components/Button";
96
+ import { LabelField } from "@/components/LabelField";
88
97
 
89
98
  export default function RegistrationForm() {
90
99
  const [formData, setFormData] = useState({
91
- fullName: '',
92
- email: '',
93
- password: '',
94
- confirmPassword: '',
100
+ fullName: "",
101
+ email: "",
102
+ password: "",
103
+ confirmPassword: "",
95
104
  });
96
105
 
97
106
  const handleChange = (field: string) => (e: React.ChangeEvent<HTMLInputElement>) => {
98
- setFormData(prev => ({
107
+ setFormData((prev) => ({
99
108
  ...prev,
100
- [field]: e.target.value
109
+ [field]: e.target.value,
101
110
  }));
102
111
  };
103
112
 
104
113
  return (
105
114
  <form onSubmit={handleSubmit} className="max-w-md mx-auto p-6 space-y-4">
106
- <h2 className="typography-display-medium-bold mb-6">
107
- Create Account
108
- </h2>
115
+ <h2 className="typography-display-medium-bold mb-6">Create Account</h2>
109
116
 
110
117
  <LabelField
111
118
  theme="light"
112
119
  label="Full Name"
113
120
  requiredLabel="*"
114
121
  value={formData.fullName}
115
- onChange={handleChange('fullName')}
122
+ onChange={handleChange("fullName")}
116
123
  placeholder="John Doe"
117
124
  />
118
125
 
@@ -122,7 +129,7 @@ export default function RegistrationForm() {
122
129
  requiredLabel="*"
123
130
  type="email"
124
131
  value={formData.email}
125
- onChange={handleChange('email')}
132
+ onChange={handleChange("email")}
126
133
  placeholder="you@example.com"
127
134
  />
128
135
 
@@ -132,7 +139,7 @@ export default function RegistrationForm() {
132
139
  requiredLabel="*"
133
140
  type="password"
134
141
  value={formData.password}
135
- onChange={handleChange('password')}
142
+ onChange={handleChange("password")}
136
143
  placeholder="••••••••"
137
144
  />
138
145
 
@@ -142,7 +149,7 @@ export default function RegistrationForm() {
142
149
  requiredLabel="*"
143
150
  type="password"
144
151
  value={formData.confirmPassword}
145
- onChange={handleChange('confirmPassword')}
152
+ onChange={handleChange("confirmPassword")}
146
153
  placeholder="••••••••"
147
154
  />
148
155
 
@@ -161,10 +168,12 @@ export default function RegistrationForm() {
161
168
  Let's add comprehensive validation:
162
169
 
163
170
  ```tsx
164
- 'use client';
171
+ "use client";
165
172
 
166
- import { useState, FormEvent } from 'react';
167
- import { LabelField, Button, FieldHint } from '@torch-ai/torch-glare';
173
+ import { useState, FormEvent } from "react";
174
+ import { Button } from "@/components/Button";
175
+ import { FieldHint } from "@/components/FieldHint";
176
+ import { LabelField } from "@/components/LabelField";
168
177
 
169
178
  interface FormErrors {
170
179
  fullName?: string;
@@ -175,10 +184,10 @@ interface FormErrors {
175
184
 
176
185
  export default function RegistrationForm() {
177
186
  const [formData, setFormData] = useState({
178
- fullName: '',
179
- email: '',
180
- password: '',
181
- confirmPassword: '',
187
+ fullName: "",
188
+ email: "",
189
+ password: "",
190
+ confirmPassword: "",
182
191
  });
183
192
 
184
193
  const [errors, setErrors] = useState<FormErrors>({});
@@ -186,49 +195,48 @@ export default function RegistrationForm() {
186
195
 
187
196
  // Validation functions
188
197
  const validateFullName = (name: string): string | undefined => {
189
- if (!name.trim()) return 'Full name is required';
190
- if (name.trim().length < 2) return 'Name must be at least 2 characters';
198
+ if (!name.trim()) return "Full name is required";
199
+ if (name.trim().length < 2) return "Name must be at least 2 characters";
191
200
  return undefined;
192
201
  };
193
202
 
194
203
  const validateEmail = (email: string): string | undefined => {
195
- if (!email) return 'Email is required';
204
+ if (!email) return "Email is required";
196
205
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
197
- if (!emailRegex.test(email)) return 'Please enter a valid email';
206
+ if (!emailRegex.test(email)) return "Please enter a valid email";
198
207
  return undefined;
199
208
  };
200
209
 
201
210
  const validatePassword = (password: string): string | undefined => {
202
- if (!password) return 'Password is required';
203
- if (password.length < 8) return 'Password must be at least 8 characters';
204
- if (!/[A-Z]/.test(password)) return 'Password must contain an uppercase letter';
205
- if (!/[a-z]/.test(password)) return 'Password must contain a lowercase letter';
206
- if (!/[0-9]/.test(password)) return 'Password must contain a number';
211
+ if (!password) return "Password is required";
212
+ if (password.length < 8) return "Password must be at least 8 characters";
213
+ if (!/[A-Z]/.test(password)) return "Password must contain an uppercase letter";
214
+ if (!/[a-z]/.test(password)) return "Password must contain a lowercase letter";
215
+ if (!/[0-9]/.test(password)) return "Password must contain a number";
207
216
  return undefined;
208
217
  };
209
218
 
210
219
  const validateConfirmPassword = (confirmPassword: string): string | undefined => {
211
- if (!confirmPassword) return 'Please confirm your password';
212
- if (confirmPassword !== formData.password) return 'Passwords do not match';
220
+ if (!confirmPassword) return "Please confirm your password";
221
+ if (confirmPassword !== formData.password) return "Passwords do not match";
213
222
  return undefined;
214
223
  };
215
224
 
216
225
  // Handle field changes
217
- const handleChange = (field: keyof typeof formData) => (
218
- e: React.ChangeEvent<HTMLInputElement>
219
- ) => {
220
- const value = e.target.value;
221
- setFormData(prev => ({ ...prev, [field]: value }));
222
-
223
- // Validate on change if field has been touched
224
- if (touched[field]) {
225
- validateField(field, value);
226
- }
227
- };
226
+ const handleChange =
227
+ (field: keyof typeof formData) => (e: React.ChangeEvent<HTMLInputElement>) => {
228
+ const value = e.target.value;
229
+ setFormData((prev) => ({ ...prev, [field]: value }));
230
+
231
+ // Validate on change if field has been touched
232
+ if (touched[field]) {
233
+ validateField(field, value);
234
+ }
235
+ };
228
236
 
229
237
  // Handle blur events
230
238
  const handleBlur = (field: keyof typeof formData) => () => {
231
- setTouched(prev => ({ ...prev, [field]: true }));
239
+ setTouched((prev) => ({ ...prev, [field]: true }));
232
240
  validateField(field, formData[field]);
233
241
  };
234
242
 
@@ -237,21 +245,21 @@ export default function RegistrationForm() {
237
245
  let error: string | undefined;
238
246
 
239
247
  switch (field) {
240
- case 'fullName':
248
+ case "fullName":
241
249
  error = validateFullName(value);
242
250
  break;
243
- case 'email':
251
+ case "email":
244
252
  error = validateEmail(value);
245
253
  break;
246
- case 'password':
254
+ case "password":
247
255
  error = validatePassword(value);
248
256
  break;
249
- case 'confirmPassword':
257
+ case "confirmPassword":
250
258
  error = validateConfirmPassword(value);
251
259
  break;
252
260
  }
253
261
 
254
- setErrors(prev => ({ ...prev, [field]: error }));
262
+ setErrors((prev) => ({ ...prev, [field]: error }));
255
263
  };
256
264
 
257
265
  // Validate all fields
@@ -271,7 +279,7 @@ export default function RegistrationForm() {
271
279
  confirmPassword: true,
272
280
  });
273
281
 
274
- return !Object.values(newErrors).some(error => error !== undefined);
282
+ return !Object.values(newErrors).some((error) => error !== undefined);
275
283
  };
276
284
 
277
285
  // Handle form submission
@@ -279,16 +287,14 @@ export default function RegistrationForm() {
279
287
  e.preventDefault();
280
288
 
281
289
  if (validateForm()) {
282
- console.log('Form is valid:', formData);
290
+ console.log("Form is valid:", formData);
283
291
  // Submit form data
284
292
  }
285
293
  };
286
294
 
287
295
  return (
288
296
  <form onSubmit={handleSubmit} className="max-w-md mx-auto p-6 space-y-4">
289
- <h2 className="typography-display-medium-bold mb-6">
290
- Create Account
291
- </h2>
297
+ <h2 className="typography-display-medium-bold mb-6">Create Account</h2>
292
298
 
293
299
  <div>
294
300
  <LabelField
@@ -296,8 +302,8 @@ export default function RegistrationForm() {
296
302
  label="Full Name"
297
303
  requiredLabel="*"
298
304
  value={formData.fullName}
299
- onChange={handleChange('fullName')}
300
- onBlur={handleBlur('fullName')}
305
+ onChange={handleChange("fullName")}
306
+ onBlur={handleBlur("fullName")}
301
307
  placeholder="John Doe"
302
308
  errorMessage={touched.fullName ? errors.fullName : undefined}
303
309
  />
@@ -310,8 +316,8 @@ export default function RegistrationForm() {
310
316
  requiredLabel="*"
311
317
  type="email"
312
318
  value={formData.email}
313
- onChange={handleChange('email')}
314
- onBlur={handleBlur('email')}
319
+ onChange={handleChange("email")}
320
+ onBlur={handleBlur("email")}
315
321
  placeholder="you@example.com"
316
322
  errorMessage={touched.email ? errors.email : undefined}
317
323
  />
@@ -324,8 +330,8 @@ export default function RegistrationForm() {
324
330
  requiredLabel="*"
325
331
  type="password"
326
332
  value={formData.password}
327
- onChange={handleChange('password')}
328
- onBlur={handleBlur('password')}
333
+ onChange={handleChange("password")}
334
+ onBlur={handleBlur("password")}
329
335
  placeholder="••••••••"
330
336
  errorMessage={touched.password ? errors.password : undefined}
331
337
  />
@@ -338,8 +344,8 @@ export default function RegistrationForm() {
338
344
  requiredLabel="*"
339
345
  type="password"
340
346
  value={formData.confirmPassword}
341
- onChange={handleChange('confirmPassword')}
342
- onBlur={handleBlur('confirmPassword')}
347
+ onChange={handleChange("confirmPassword")}
348
+ onBlur={handleBlur("confirmPassword")}
343
349
  placeholder="••••••••"
344
350
  errorMessage={touched.confirmPassword ? errors.confirmPassword : undefined}
345
351
  />
@@ -360,7 +366,9 @@ export default function RegistrationForm() {
360
366
  Use the `PasswordLevel` component to show password strength:
361
367
 
362
368
  ```tsx
363
- import { LabelField, PasswordLevel, Button } from '@torch-ai/torch-glare';
369
+ import { Button } from "@/components/Button";
370
+ import { LabelField } from "@/components/LabelField";
371
+ import { PasswordLevel } from "@/components/PasswordLevel";
364
372
 
365
373
  // Inside your form component, add this after the password field:
366
374
 
@@ -371,8 +379,8 @@ import { LabelField, PasswordLevel, Button } from '@torch-ai/torch-glare';
371
379
  requiredLabel="*"
372
380
  type="password"
373
381
  value={formData.password}
374
- onChange={handleChange('password')}
375
- onBlur={handleBlur('password')}
382
+ onChange={handleChange("password")}
383
+ onBlur={handleBlur("password")}
376
384
  placeholder="••••••••"
377
385
  errorMessage={touched.password ? errors.password : undefined}
378
386
  />
@@ -383,7 +391,7 @@ import { LabelField, PasswordLevel, Button } from '@torch-ai/torch-glare';
383
391
  <PasswordLevel theme="light" value={formData.password} />
384
392
  </div>
385
393
  )}
386
- </div>
394
+ </div>;
387
395
  ```
388
396
 
389
397
  ---
@@ -393,7 +401,9 @@ import { LabelField, PasswordLevel, Button } from '@torch-ai/torch-glare';
393
401
  Use `FieldHint` to provide helpful guidance:
394
402
 
395
403
  ```tsx
396
- import { LabelField, FieldHint, Button } from '@torch-ai/torch-glare';
404
+ import { Button } from "@/components/Button";
405
+ import { FieldHint } from "@/components/FieldHint";
406
+ import { LabelField } from "@/components/LabelField";
397
407
 
398
408
  <div>
399
409
  <LabelField
@@ -402,8 +412,8 @@ import { LabelField, FieldHint, Button } from '@torch-ai/torch-glare';
402
412
  requiredLabel="*"
403
413
  type="email"
404
414
  value={formData.email}
405
- onChange={handleChange('email')}
406
- onBlur={handleBlur('email')}
415
+ onChange={handleChange("email")}
416
+ onBlur={handleBlur("email")}
407
417
  placeholder="you@example.com"
408
418
  errorMessage={touched.email ? errors.email : undefined}
409
419
  />
@@ -416,7 +426,7 @@ import { LabelField, FieldHint, Button } from '@torch-ai/torch-glare';
416
426
  className="mt-2"
417
427
  />
418
428
  )}
419
- </div>
429
+ </div>;
420
430
  ```
421
431
 
422
432
  ---
@@ -437,12 +447,12 @@ const handleSubmit = async (e: FormEvent) => {
437
447
 
438
448
  try {
439
449
  // Simulate API call
440
- await new Promise(resolve => setTimeout(resolve, 2000));
450
+ await new Promise((resolve) => setTimeout(resolve, 2000));
441
451
 
442
- console.log('Registration successful:', formData);
452
+ console.log("Registration successful:", formData);
443
453
  // Handle success (e.g., redirect, show success message)
444
454
  } catch (error) {
445
- console.error('Registration failed:', error);
455
+ console.error("Registration failed:", error);
446
456
  // Handle error
447
457
  } finally {
448
458
  setIsSubmitting(false);
@@ -450,15 +460,9 @@ const handleSubmit = async (e: FormEvent) => {
450
460
  };
451
461
 
452
462
  // Update button
453
- <Button
454
- theme="light"
455
- variant="PrimeStyle"
456
- type="submit"
457
- className="w-full"
458
- disabled={isSubmitting}
459
- >
460
- {isSubmitting ? 'Registering...' : 'Register'}
461
- </Button>
463
+ <Button theme="light" variant="PrimeStyle" type="submit" className="w-full" disabled={isSubmitting}>
464
+ {isSubmitting ? "Registering..." : "Register"}
465
+ </Button>;
462
466
  ```
463
467
 
464
468
  ---
@@ -468,13 +472,15 @@ const handleSubmit = async (e: FormEvent) => {
468
472
  Use the `toast` function for success notifications:
469
473
 
470
474
  ```tsx
471
- import { LabelField, Button, toast } from '@torch-ai/torch-glare';
475
+ import { Button } from "@/components/Button";
476
+ import { LabelField } from "@/components/LabelField";
477
+ import { toast } from "@/components/Toast";
472
478
 
473
479
  const handleSubmit = async (e: FormEvent) => {
474
480
  e.preventDefault();
475
481
 
476
482
  if (!validateForm()) {
477
- toast.error('Please fix the errors in the form');
483
+ toast.error("Please fix the errors in the form");
478
484
  return;
479
485
  }
480
486
 
@@ -482,21 +488,21 @@ const handleSubmit = async (e: FormEvent) => {
482
488
 
483
489
  try {
484
490
  // Simulate API call
485
- await new Promise(resolve => setTimeout(resolve, 2000));
491
+ await new Promise((resolve) => setTimeout(resolve, 2000));
486
492
 
487
- toast.success('Account created successfully!');
493
+ toast.success("Account created successfully!");
488
494
 
489
495
  // Reset form
490
496
  setFormData({
491
- fullName: '',
492
- email: '',
493
- password: '',
494
- confirmPassword: '',
497
+ fullName: "",
498
+ email: "",
499
+ password: "",
500
+ confirmPassword: "",
495
501
  });
496
502
  setErrors({});
497
503
  setTouched({});
498
504
  } catch (error) {
499
- toast.error('Registration failed. Please try again.');
505
+ toast.error("Registration failed. Please try again.");
500
506
  } finally {
501
507
  setIsSubmitting(false);
502
508
  }
@@ -510,16 +516,14 @@ const handleSubmit = async (e: FormEvent) => {
510
516
  Here's the complete, production-ready form:
511
517
 
512
518
  ```tsx
513
- 'use client';
519
+ "use client";
514
520
 
515
- import { useState, FormEvent } from 'react';
516
- import {
517
- LabelField,
518
- Button,
519
- PasswordLevel,
520
- FieldHint,
521
- toast,
522
- } from '@torch-ai/torch-glare';
521
+ import { useState, FormEvent } from "react";
522
+ import { Button } from "@/components/Button";
523
+ import { FieldHint } from "@/components/FieldHint";
524
+ import { LabelField } from "@/components/LabelField";
525
+ import { PasswordLevel } from "@/components/PasswordLevel";
526
+ import { toast } from "@/components/Toast";
523
527
 
524
528
  interface FormErrors {
525
529
  fullName?: string;
@@ -530,10 +534,10 @@ interface FormErrors {
530
534
 
531
535
  export default function RegistrationForm() {
532
536
  const [formData, setFormData] = useState({
533
- fullName: '',
534
- email: '',
535
- password: '',
536
- confirmPassword: '',
537
+ fullName: "",
538
+ email: "",
539
+ password: "",
540
+ confirmPassword: "",
537
541
  });
538
542
 
539
543
  const [errors, setErrors] = useState<FormErrors>({});
@@ -542,46 +546,45 @@ export default function RegistrationForm() {
542
546
 
543
547
  // Validation functions
544
548
  const validateFullName = (name: string): string | undefined => {
545
- if (!name.trim()) return 'Full name is required';
546
- if (name.trim().length < 2) return 'Name must be at least 2 characters';
549
+ if (!name.trim()) return "Full name is required";
550
+ if (name.trim().length < 2) return "Name must be at least 2 characters";
547
551
  return undefined;
548
552
  };
549
553
 
550
554
  const validateEmail = (email: string): string | undefined => {
551
- if (!email) return 'Email is required';
555
+ if (!email) return "Email is required";
552
556
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
553
- if (!emailRegex.test(email)) return 'Please enter a valid email';
557
+ if (!emailRegex.test(email)) return "Please enter a valid email";
554
558
  return undefined;
555
559
  };
556
560
 
557
561
  const validatePassword = (password: string): string | undefined => {
558
- if (!password) return 'Password is required';
559
- if (password.length < 8) return 'Password must be at least 8 characters';
560
- if (!/[A-Z]/.test(password)) return 'Password must contain an uppercase letter';
561
- if (!/[a-z]/.test(password)) return 'Password must contain a lowercase letter';
562
- if (!/[0-9]/.test(password)) return 'Password must contain a number';
562
+ if (!password) return "Password is required";
563
+ if (password.length < 8) return "Password must be at least 8 characters";
564
+ if (!/[A-Z]/.test(password)) return "Password must contain an uppercase letter";
565
+ if (!/[a-z]/.test(password)) return "Password must contain a lowercase letter";
566
+ if (!/[0-9]/.test(password)) return "Password must contain a number";
563
567
  return undefined;
564
568
  };
565
569
 
566
570
  const validateConfirmPassword = (confirmPassword: string): string | undefined => {
567
- if (!confirmPassword) return 'Please confirm your password';
568
- if (confirmPassword !== formData.password) return 'Passwords do not match';
571
+ if (!confirmPassword) return "Please confirm your password";
572
+ if (confirmPassword !== formData.password) return "Passwords do not match";
569
573
  return undefined;
570
574
  };
571
575
 
572
- const handleChange = (field: keyof typeof formData) => (
573
- e: React.ChangeEvent<HTMLInputElement>
574
- ) => {
575
- const value = e.target.value;
576
- setFormData(prev => ({ ...prev, [field]: value }));
576
+ const handleChange =
577
+ (field: keyof typeof formData) => (e: React.ChangeEvent<HTMLInputElement>) => {
578
+ const value = e.target.value;
579
+ setFormData((prev) => ({ ...prev, [field]: value }));
577
580
 
578
- if (touched[field]) {
579
- validateField(field, value);
580
- }
581
- };
581
+ if (touched[field]) {
582
+ validateField(field, value);
583
+ }
584
+ };
582
585
 
583
586
  const handleBlur = (field: keyof typeof formData) => () => {
584
- setTouched(prev => ({ ...prev, [field]: true }));
587
+ setTouched((prev) => ({ ...prev, [field]: true }));
585
588
  validateField(field, formData[field]);
586
589
  };
587
590
 
@@ -589,21 +592,21 @@ export default function RegistrationForm() {
589
592
  let error: string | undefined;
590
593
 
591
594
  switch (field) {
592
- case 'fullName':
595
+ case "fullName":
593
596
  error = validateFullName(value);
594
597
  break;
595
- case 'email':
598
+ case "email":
596
599
  error = validateEmail(value);
597
600
  break;
598
- case 'password':
601
+ case "password":
599
602
  error = validatePassword(value);
600
603
  break;
601
- case 'confirmPassword':
604
+ case "confirmPassword":
602
605
  error = validateConfirmPassword(value);
603
606
  break;
604
607
  }
605
608
 
606
- setErrors(prev => ({ ...prev, [field]: error }));
609
+ setErrors((prev) => ({ ...prev, [field]: error }));
607
610
  };
608
611
 
609
612
  const validateForm = (): boolean => {
@@ -622,14 +625,14 @@ export default function RegistrationForm() {
622
625
  confirmPassword: true,
623
626
  });
624
627
 
625
- return !Object.values(newErrors).some(error => error !== undefined);
628
+ return !Object.values(newErrors).some((error) => error !== undefined);
626
629
  };
627
630
 
628
631
  const handleSubmit = async (e: FormEvent) => {
629
632
  e.preventDefault();
630
633
 
631
634
  if (!validateForm()) {
632
- toast.error('Please fix the errors in the form');
635
+ toast.error("Please fix the errors in the form");
633
636
  return;
634
637
  }
635
638
 
@@ -637,21 +640,21 @@ export default function RegistrationForm() {
637
640
 
638
641
  try {
639
642
  // Simulate API call
640
- await new Promise(resolve => setTimeout(resolve, 2000));
643
+ await new Promise((resolve) => setTimeout(resolve, 2000));
641
644
 
642
- toast.success('Account created successfully!');
645
+ toast.success("Account created successfully!");
643
646
 
644
647
  // Reset form
645
648
  setFormData({
646
- fullName: '',
647
- email: '',
648
- password: '',
649
- confirmPassword: '',
649
+ fullName: "",
650
+ email: "",
651
+ password: "",
652
+ confirmPassword: "",
650
653
  });
651
654
  setErrors({});
652
655
  setTouched({});
653
656
  } catch (error) {
654
- toast.error('Registration failed. Please try again.');
657
+ toast.error("Registration failed. Please try again.");
655
658
  } finally {
656
659
  setIsSubmitting(false);
657
660
  }
@@ -669,9 +672,7 @@ export default function RegistrationForm() {
669
672
  "
670
673
  >
671
674
  <div className="mb-6">
672
- <h2 className="typography-display-medium-bold mb-2">
673
- Create Account
674
- </h2>
675
+ <h2 className="typography-display-medium-bold mb-2">Create Account</h2>
675
676
  <p className="typography-body-medium-regular text-content-presentation-global-secondary">
676
677
  Join us and get started today
677
678
  </p>
@@ -683,8 +684,8 @@ export default function RegistrationForm() {
683
684
  label="Full Name"
684
685
  requiredLabel="*"
685
686
  value={formData.fullName}
686
- onChange={handleChange('fullName')}
687
- onBlur={handleBlur('fullName')}
687
+ onChange={handleChange("fullName")}
688
+ onBlur={handleBlur("fullName")}
688
689
  placeholder="John Doe"
689
690
  errorMessage={touched.fullName ? errors.fullName : undefined}
690
691
  />
@@ -697,8 +698,8 @@ export default function RegistrationForm() {
697
698
  requiredLabel="*"
698
699
  type="email"
699
700
  value={formData.email}
700
- onChange={handleChange('email')}
701
- onBlur={handleBlur('email')}
701
+ onChange={handleChange("email")}
702
+ onBlur={handleBlur("email")}
702
703
  placeholder="you@example.com"
703
704
  errorMessage={touched.email ? errors.email : undefined}
704
705
  />
@@ -719,8 +720,8 @@ export default function RegistrationForm() {
719
720
  requiredLabel="*"
720
721
  type="password"
721
722
  value={formData.password}
722
- onChange={handleChange('password')}
723
- onBlur={handleBlur('password')}
723
+ onChange={handleChange("password")}
724
+ onBlur={handleBlur("password")}
724
725
  placeholder="••••••••"
725
726
  errorMessage={touched.password ? errors.password : undefined}
726
727
  />
@@ -738,8 +739,8 @@ export default function RegistrationForm() {
738
739
  requiredLabel="*"
739
740
  type="password"
740
741
  value={formData.confirmPassword}
741
- onChange={handleChange('confirmPassword')}
742
- onBlur={handleBlur('confirmPassword')}
742
+ onChange={handleChange("confirmPassword")}
743
+ onBlur={handleBlur("confirmPassword")}
743
744
  placeholder="••••••••"
744
745
  errorMessage={touched.confirmPassword ? errors.confirmPassword : undefined}
745
746
  />
@@ -752,11 +753,11 @@ export default function RegistrationForm() {
752
753
  className="w-full"
753
754
  disabled={isSubmitting}
754
755
  >
755
- {isSubmitting ? 'Registering...' : 'Register'}
756
+ {isSubmitting ? "Registering..." : "Register"}
756
757
  </Button>
757
758
 
758
759
  <p className="typography-body-small-regular text-content-presentation-global-secondary text-center">
759
- Already have an account?{' '}
760
+ Already have an account?{" "}
760
761
  <a href="/login" className="text-content-presentation-action-light-primary">
761
762
  Sign in
762
763
  </a>
@@ -799,11 +800,8 @@ errorMessage={touched.email ? errors.email : undefined}
799
800
  ### 3. Disable Submit During Submission
800
801
 
801
802
  ```tsx
802
- <Button
803
- type="submit"
804
- disabled={isSubmitting || Object.keys(errors).length > 0}
805
- >
806
- {isSubmitting ? 'Submitting...' : 'Submit'}
803
+ <Button type="submit" disabled={isSubmitting || Object.keys(errors).length > 0}>
804
+ {isSubmitting ? "Submitting..." : "Submit"}
807
805
  </Button>
808
806
  ```
809
807
 
@@ -811,10 +809,10 @@ errorMessage={touched.email ? errors.email : undefined}
811
809
 
812
810
  ```tsx
813
811
  // ✓ Good - Specific and actionable
814
- 'Password must contain at least one uppercase letter'
812
+ "Password must contain at least one uppercase letter";
815
813
 
816
814
  // ✗ Bad - Vague
817
- 'Invalid password'
815
+ "Invalid password";
818
816
  ```
819
817
 
820
818
  ### 5. Reset Form After Success
@@ -824,7 +822,7 @@ const handleSuccess = () => {
824
822
  setFormData(initialState);
825
823
  setErrors({});
826
824
  setTouched({});
827
- toast.success('Success!');
825
+ toast.success("Success!");
828
826
  };
829
827
  ```
830
828