torch-glare 2.5.6 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/README.md +4 -3
  2. package/dist/bin/index.js +9 -24
  3. package/dist/bin/index.js.map +1 -1
  4. package/dist/src/commands/add.d.ts +2 -2
  5. package/dist/src/commands/add.d.ts.map +1 -1
  6. package/dist/src/commands/add.js +4 -70
  7. package/dist/src/commands/add.js.map +1 -1
  8. package/dist/src/commands/hook.d.ts +5 -4
  9. package/dist/src/commands/hook.d.ts.map +1 -1
  10. package/dist/src/commands/hook.js +7 -75
  11. package/dist/src/commands/hook.js.map +1 -1
  12. package/dist/src/commands/init.js +1 -1
  13. package/dist/src/commands/init.js.map +1 -1
  14. package/dist/src/commands/layout.d.ts +5 -4
  15. package/dist/src/commands/layout.d.ts.map +1 -1
  16. package/dist/src/commands/layout.js +7 -75
  17. package/dist/src/commands/layout.js.map +1 -1
  18. package/dist/src/commands/provider.d.ts +5 -4
  19. package/dist/src/commands/provider.d.ts.map +1 -1
  20. package/dist/src/commands/provider.js +7 -75
  21. package/dist/src/commands/provider.js.map +1 -1
  22. package/dist/src/commands/update.d.ts.map +1 -1
  23. package/dist/src/commands/update.js +78 -43
  24. package/dist/src/commands/update.js.map +1 -1
  25. package/dist/src/commands/utils.d.ts +5 -4
  26. package/dist/src/commands/utils.d.ts.map +1 -1
  27. package/dist/src/commands/utils.js +7 -80
  28. package/dist/src/commands/utils.js.map +1 -1
  29. package/dist/src/shared/addFromRegistry.d.ts +16 -0
  30. package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
  31. package/dist/src/shared/addFromRegistry.js +88 -0
  32. package/dist/src/shared/addFromRegistry.js.map +1 -0
  33. package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
  34. package/dist/src/shared/getInstallCommand.js +5 -0
  35. package/dist/src/shared/getInstallCommand.js.map +1 -1
  36. package/dist/src/shared/installDependencies.d.ts +0 -10
  37. package/dist/src/shared/installDependencies.d.ts.map +1 -1
  38. package/dist/src/shared/installDependencies.js +0 -17
  39. package/dist/src/shared/installDependencies.js.map +1 -1
  40. package/dist/src/shared/installFromPlan.d.ts +7 -5
  41. package/dist/src/shared/installFromPlan.d.ts.map +1 -1
  42. package/dist/src/shared/installFromPlan.js +103 -36
  43. package/dist/src/shared/installFromPlan.js.map +1 -1
  44. package/dist/src/shared/loadRegistry.d.ts +12 -3
  45. package/dist/src/shared/loadRegistry.d.ts.map +1 -1
  46. package/dist/src/shared/loadRegistry.js +19 -20
  47. package/dist/src/shared/loadRegistry.js.map +1 -1
  48. package/dist/src/shared/registryClient.d.ts +19 -0
  49. package/dist/src/shared/registryClient.d.ts.map +1 -0
  50. package/dist/src/shared/registryClient.js +128 -0
  51. package/dist/src/shared/registryClient.js.map +1 -0
  52. package/dist/src/shared/resolveEntry.d.ts +10 -7
  53. package/dist/src/shared/resolveEntry.d.ts.map +1 -1
  54. package/dist/src/shared/resolveEntry.js +18 -13
  55. package/dist/src/shared/resolveEntry.js.map +1 -1
  56. package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
  57. package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
  58. package/dist/src/shared/suggestOtherCommand.js +29 -23
  59. package/dist/src/shared/suggestOtherCommand.js.map +1 -1
  60. package/dist/src/types/main.d.ts +31 -2
  61. package/dist/src/types/main.d.ts.map +1 -1
  62. package/package.json +6 -11
  63. package/apps/lib/components/ActionButton.tsx +0 -93
  64. package/apps/lib/components/ActionsGroup.tsx +0 -27
  65. package/apps/lib/components/AlertDialog.tsx +0 -204
  66. package/apps/lib/components/Avatar.tsx +0 -46
  67. package/apps/lib/components/Badge.tsx +0 -250
  68. package/apps/lib/components/BadgeField.tsx +0 -403
  69. package/apps/lib/components/Breadcrumb.tsx +0 -280
  70. package/apps/lib/components/Button.tsx +0 -325
  71. package/apps/lib/components/ButtonGroup.tsx +0 -190
  72. package/apps/lib/components/Calendar.tsx +0 -115
  73. package/apps/lib/components/Card.tsx +0 -95
  74. package/apps/lib/components/Checkbox.tsx +0 -42
  75. package/apps/lib/components/ColorPicker.tsx +0 -441
  76. package/apps/lib/components/ConclusionHeader.tsx +0 -148
  77. package/apps/lib/components/ContextMenu.tsx +0 -571
  78. package/apps/lib/components/CountBadge.tsx +0 -52
  79. package/apps/lib/components/DataTable.tsx +0 -213
  80. package/apps/lib/components/DataViews/badge.ts +0 -49
  81. package/apps/lib/components/DataViews/cell.tsx +0 -324
  82. package/apps/lib/components/DataViews/context.ts +0 -144
  83. package/apps/lib/components/DataViews/data-views.tsx +0 -395
  84. package/apps/lib/components/DataViews/filters/children.tsx +0 -98
  85. package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
  86. package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
  87. package/apps/lib/components/DataViews/filters/index.ts +0 -4
  88. package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
  89. package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
  90. package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
  91. package/apps/lib/components/DataViews/filters/values.ts +0 -173
  92. package/apps/lib/components/DataViews/header.tsx +0 -220
  93. package/apps/lib/components/DataViews/hooks/index.ts +0 -5
  94. package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
  95. package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
  96. package/apps/lib/components/DataViews/index.ts +0 -88
  97. package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
  98. package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
  99. package/apps/lib/components/DataViews/panel/index.ts +0 -3
  100. package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
  101. package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
  102. package/apps/lib/components/DataViews/panel/section.tsx +0 -81
  103. package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
  104. package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
  105. package/apps/lib/components/DataViews/slots.ts +0 -72
  106. package/apps/lib/components/DataViews/states.tsx +0 -73
  107. package/apps/lib/components/DataViews/types.ts +0 -510
  108. package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
  109. package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
  110. package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
  111. package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
  112. package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
  113. package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
  114. package/apps/lib/components/DatePicker.tsx +0 -232
  115. package/apps/lib/components/Dialog.tsx +0 -116
  116. package/apps/lib/components/Divider.tsx +0 -28
  117. package/apps/lib/components/Drawer.tsx +0 -451
  118. package/apps/lib/components/DropdownMenu.tsx +0 -554
  119. package/apps/lib/components/FieldHint.tsx +0 -69
  120. package/apps/lib/components/Form.tsx +0 -182
  121. package/apps/lib/components/FormBuilder/context.ts +0 -85
  122. package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
  123. package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
  124. package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
  125. package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
  126. package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
  127. package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
  128. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -168
  129. package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
  130. package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
  131. package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
  132. package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
  133. package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
  134. package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -114
  135. package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
  136. package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
  137. package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
  138. package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
  139. package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
  140. package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
  141. package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
  142. package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
  143. package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
  144. package/apps/lib/components/FormBuilder/index.ts +0 -31
  145. package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
  146. package/apps/lib/components/FormBuilder/submit.tsx +0 -67
  147. package/apps/lib/components/FormBuilder/types.ts +0 -316
  148. package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -250
  149. package/apps/lib/components/FormRenderer/detail.tsx +0 -256
  150. package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -358
  151. package/apps/lib/components/FormRenderer/header.tsx +0 -88
  152. package/apps/lib/components/FormRenderer/index.ts +0 -17
  153. package/apps/lib/components/FormRenderer/notch-action.tsx +0 -64
  154. package/apps/lib/components/FormRenderer/section.tsx +0 -39
  155. package/apps/lib/components/FormRenderer/stepper.tsx +0 -393
  156. package/apps/lib/components/FormRenderer/types.ts +0 -115
  157. package/apps/lib/components/FormSummary.tsx +0 -282
  158. package/apps/lib/components/HeaderBar.tsx +0 -117
  159. package/apps/lib/components/ImageAttachment.tsx +0 -209
  160. package/apps/lib/components/InnerLabelField.tsx +0 -154
  161. package/apps/lib/components/Input.tsx +0 -224
  162. package/apps/lib/components/InputField.tsx +0 -147
  163. package/apps/lib/components/InputOTP.tsx +0 -84
  164. package/apps/lib/components/Label.tsx +0 -129
  165. package/apps/lib/components/LabelField.tsx +0 -76
  166. package/apps/lib/components/LabeledCheckBox.tsx +0 -51
  167. package/apps/lib/components/LabeledRadio.tsx +0 -51
  168. package/apps/lib/components/LinkButton.tsx +0 -94
  169. package/apps/lib/components/LoginButton.tsx +0 -51
  170. package/apps/lib/components/PasswordLevel.tsx +0 -58
  171. package/apps/lib/components/Popover.tsx +0 -312
  172. package/apps/lib/components/ProfileMenu.tsx +0 -85
  173. package/apps/lib/components/Radio.tsx +0 -59
  174. package/apps/lib/components/RadioCard.tsx +0 -50
  175. package/apps/lib/components/ScrollArea.tsx +0 -54
  176. package/apps/lib/components/SearchField.tsx +0 -62
  177. package/apps/lib/components/SearchableSelect.tsx +0 -318
  178. package/apps/lib/components/SearchableTable.tsx +0 -344
  179. package/apps/lib/components/SearchableTree.tsx +0 -485
  180. package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
  181. package/apps/lib/components/SectionBlock.tsx +0 -168
  182. package/apps/lib/components/Select.tsx +0 -347
  183. package/apps/lib/components/SimpleSelect.tsx +0 -225
  184. package/apps/lib/components/Skeleton.tsx +0 -12
  185. package/apps/lib/components/SlideDatePicker.tsx +0 -255
  186. package/apps/lib/components/SpinLoading.tsx +0 -174
  187. package/apps/lib/components/Stepper.tsx +0 -480
  188. package/apps/lib/components/Switch.tsx +0 -82
  189. package/apps/lib/components/TabFormItem.tsx +0 -153
  190. package/apps/lib/components/TabSwitch.tsx +0 -172
  191. package/apps/lib/components/Table.tsx +0 -597
  192. package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
  193. package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
  194. package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
  195. package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
  196. package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
  197. package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
  198. package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
  199. package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
  200. package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
  201. package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
  202. package/apps/lib/components/TextEditor/index.ts +0 -7
  203. package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
  204. package/apps/lib/components/Textarea.tsx +0 -117
  205. package/apps/lib/components/Timeline.tsx +0 -263
  206. package/apps/lib/components/Toast.tsx +0 -87
  207. package/apps/lib/components/Toggle.tsx +0 -125
  208. package/apps/lib/components/ToggleButton.tsx +0 -140
  209. package/apps/lib/components/Tooltip.tsx +0 -116
  210. package/apps/lib/components/TransparentLabel.tsx +0 -71
  211. package/apps/lib/components/TreeDropDown.tsx +0 -115
  212. package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
  213. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
  214. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
  215. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
  216. package/apps/lib/components/TreeFolder/icons.tsx +0 -60
  217. package/apps/lib/components/TreeFolder/index.ts +0 -24
  218. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
  219. package/apps/lib/components/TreeFolder/types.ts +0 -77
  220. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
  221. package/apps/lib/hooks/useActiveTreeItem.ts +0 -61
  222. package/apps/lib/hooks/useClickOutside.ts +0 -27
  223. package/apps/lib/hooks/useDragDrop.tsx +0 -365
  224. package/apps/lib/hooks/useHtmlDir.ts +0 -31
  225. package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
  226. package/apps/lib/hooks/useIsMobile.ts +0 -21
  227. package/apps/lib/hooks/useResize.ts +0 -67
  228. package/apps/lib/hooks/useTagSelection.ts +0 -300
  229. package/apps/lib/layouts/CNLayout.tsx +0 -372
  230. package/apps/lib/layouts/DataViewCard.tsx +0 -62
  231. package/apps/lib/layouts/FieldSection.tsx +0 -91
  232. package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
  233. package/apps/lib/providers/ThemeProvider.tsx +0 -84
  234. package/apps/lib/registry.json +0 -1217
  235. package/apps/lib/tsconfig.json +0 -9
  236. package/apps/lib/tsconfig.tsbuildinfo +0 -1
  237. package/apps/lib/utils/cn.ts +0 -6
  238. package/apps/lib/utils/color.ts +0 -175
  239. package/apps/lib/utils/dataViews/path.ts +0 -67
  240. package/apps/lib/utils/dataViews/query.ts +0 -73
  241. package/apps/lib/utils/dataViews/types.ts +0 -187
  242. package/apps/lib/utils/dateFormat.ts +0 -108
  243. package/apps/lib/utils/resize.ts +0 -31
  244. package/apps/lib/utils/scroller.ts +0 -26
  245. package/apps/lib/utils/types.ts +0 -16
  246. package/docs/BLOCKS.md +0 -129
  247. package/docs/CHANGELOG-1.1.16.md +0 -108
  248. package/docs/Cover.png +0 -0
  249. package/docs/README.md +0 -215
  250. package/docs/components/action-button.md +0 -638
  251. package/docs/components/actions-group.md +0 -708
  252. package/docs/components/alert-dialog.md +0 -920
  253. package/docs/components/avatar.md +0 -709
  254. package/docs/components/badge-field.md +0 -738
  255. package/docs/components/badge.md +0 -301
  256. package/docs/components/breadcrumb.md +0 -930
  257. package/docs/components/button-group.md +0 -650
  258. package/docs/components/button.md +0 -639
  259. package/docs/components/calendar.md +0 -555
  260. package/docs/components/card.md +0 -622
  261. package/docs/components/chart-block-tool.md +0 -129
  262. package/docs/components/checkbox.md +0 -699
  263. package/docs/components/cn-layout.md +0 -854
  264. package/docs/components/color-picker.md +0 -101
  265. package/docs/components/conclusion-header.md +0 -80
  266. package/docs/components/context-menu.md +0 -483
  267. package/docs/components/count-badge.md +0 -560
  268. package/docs/components/data-table.md +0 -854
  269. package/docs/components/data-views/backend-response.md +0 -324
  270. package/docs/components/data-views/examples/a11y-rtl.md +0 -250
  271. package/docs/components/data-views/examples/api-orders-route.md +0 -130
  272. package/docs/components/data-views/examples/fields.md +0 -362
  273. package/docs/components/data-views/examples/filters.md +0 -307
  274. package/docs/components/data-views/examples/inbox-routing.md +0 -218
  275. package/docs/components/data-views/examples/index.md +0 -29
  276. package/docs/components/data-views/examples/overview.md +0 -244
  277. package/docs/components/data-views/examples/panel.md +0 -212
  278. package/docs/components/data-views/examples/scale.md +0 -231
  279. package/docs/components/data-views/examples/server-side.md +0 -210
  280. package/docs/components/data-views/examples/state.md +0 -250
  281. package/docs/components/data-views/examples/tree-custom.md +0 -388
  282. package/docs/components/data-views/examples/view-registry.md +0 -313
  283. package/docs/components/data-views/examples/views.md +0 -534
  284. package/docs/components/data-views/guide.md +0 -405
  285. package/docs/components/data-views/index.md +0 -1521
  286. package/docs/components/data-views/migration.md +0 -81
  287. package/docs/components/date-picker.md +0 -857
  288. package/docs/components/dialog.md +0 -929
  289. package/docs/components/divider.md +0 -766
  290. package/docs/components/drawer.md +0 -654
  291. package/docs/components/dropdown-menu.md +0 -668
  292. package/docs/components/field-hint.md +0 -898
  293. package/docs/components/field-section.md +0 -781
  294. package/docs/components/form-builder.md +0 -284
  295. package/docs/components/form-renderer.md +0 -396
  296. package/docs/components/form-summary.md +0 -138
  297. package/docs/components/form.md +0 -785
  298. package/docs/components/header-bar.md +0 -188
  299. package/docs/components/image-attachment.md +0 -906
  300. package/docs/components/inner-label-field.md +0 -819
  301. package/docs/components/input-field.md +0 -623
  302. package/docs/components/input-otp.md +0 -756
  303. package/docs/components/input.md +0 -634
  304. package/docs/components/label-field.md +0 -770
  305. package/docs/components/label.md +0 -761
  306. package/docs/components/labeled-check-box.md +0 -642
  307. package/docs/components/labeled-radio.md +0 -796
  308. package/docs/components/link-button.md +0 -685
  309. package/docs/components/login-button.md +0 -872
  310. package/docs/components/password-level.md +0 -803
  311. package/docs/components/popover.md +0 -649
  312. package/docs/components/profile-menu.md +0 -656
  313. package/docs/components/radio-card.md +0 -801
  314. package/docs/components/radio.md +0 -735
  315. package/docs/components/scroll-area.md +0 -691
  316. package/docs/components/search-field.md +0 -702
  317. package/docs/components/searchable-select.md +0 -368
  318. package/docs/components/searchable-table.md +0 -438
  319. package/docs/components/searchable-tree-dialog.md +0 -190
  320. package/docs/components/searchable-tree.md +0 -200
  321. package/docs/components/section-block.md +0 -483
  322. package/docs/components/select.md +0 -709
  323. package/docs/components/simple-select.md +0 -741
  324. package/docs/components/skeleton.md +0 -706
  325. package/docs/components/slide-date-picker.md +0 -837
  326. package/docs/components/spin-loading.md +0 -696
  327. package/docs/components/stepper.md +0 -316
  328. package/docs/components/switch.md +0 -770
  329. package/docs/components/tab-form-item.md +0 -773
  330. package/docs/components/tab-switch.md +0 -170
  331. package/docs/components/table-dnd-wrapper.md +0 -107
  332. package/docs/components/table.md +0 -1088
  333. package/docs/components/text-editor.md +0 -735
  334. package/docs/components/textarea.md +0 -681
  335. package/docs/components/timeline.md +0 -254
  336. package/docs/components/toast.md +0 -773
  337. package/docs/components/toggle-button.md +0 -643
  338. package/docs/components/toggle.md +0 -882
  339. package/docs/components/tooltip.md +0 -513
  340. package/docs/components/transparent-label.md +0 -721
  341. package/docs/components/tree-drop-down.md +0 -740
  342. package/docs/components/tree-folder.md +0 -110
  343. package/docs/components/tree-sub-layout.md +0 -707
  344. package/docs/explanation/architecture.md +0 -54
  345. package/docs/explanation/design-system.md +0 -52
  346. package/docs/how-to/form-and-list-recipes.md +0 -386
  347. package/docs/how-to/forms-with-form-builder.md +0 -472
  348. package/docs/how-to/guides.md +0 -1027
  349. package/docs/migration/changelog.md +0 -60
  350. package/docs/migration/form-builder-2.5.2.md +0 -113
  351. package/docs/reference/cli.md +0 -112
  352. package/docs/reference/components.md +0 -572
  353. package/docs/reference/hooks.md +0 -1523
  354. package/docs/reference/providers.md +0 -866
  355. package/docs/reference/tailwind-plugins.md +0 -942
  356. package/docs/reference/theme.md +0 -85
  357. package/docs/reference/types.md +0 -1016
  358. package/docs/reference/utilities.md +0 -726
  359. package/docs/tutorials/building-first-form.md +0 -846
  360. package/docs/tutorials/component-composition.md +0 -882
  361. package/docs/tutorials/getting-started.md +0 -302
  362. package/docs/tutorials/theming-basics.md +0 -785
@@ -1,803 +0,0 @@
1
- ---
2
- title: PasswordLevel
3
- description: Real-time password strength indicator with visual feedback based on length, symbols, and uppercase characters
4
- group: Feedback & Status
5
- keywords: [password, strength, security, validation, indicator, level]
6
- ---
7
-
8
- # PasswordLevel
9
-
10
- > A real-time password strength indicator that visually displays password security level through a three-bar progress indicator. Evaluates password strength based on length, special characters, and uppercase letters.
11
-
12
- ## Installation
13
-
14
- TORCH Glare is a copy-in library: the CLI copies this component's source into your project
15
- (you do **not** install it from the npm package). Run `init` once, then `add`:
16
-
17
- ```bash
18
- npx torch-glare@latest init
19
- npx torch-glare@latest add PasswordLevel
20
- ```
21
-
22
- `add` also copies any components, hooks, and utilities that `PasswordLevel` depends on.
23
-
24
- ## Import
25
-
26
- Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
27
-
28
- ```tsx
29
- import { PasswordLevel } from "@/components/PasswordLevel";
30
- ```
31
-
32
- ## Quick Examples
33
-
34
- ### Basic Usage
35
-
36
- ```typescript
37
- import { PasswordLevel } from "@/components/PasswordLevel";
38
- import { InputField } from "@/components/InputField";
39
- import { useState } from 'react'
40
-
41
- function Example() {
42
- const [password, setPassword] = useState('')
43
-
44
- return (
45
- <div className="space-y-2">
46
- <InputField
47
- type="password"
48
- value={password}
49
- onChange={(e) => setPassword(e.target.value)}
50
- label="Password"
51
- />
52
- <PasswordLevel value={password} />
53
- </div>
54
- )
55
- }
56
- ```
57
-
58
- ### With Labels
59
-
60
- ```typescript
61
- import { PasswordLevel } from "@/components/PasswordLevel";
62
- import { InputField } from "@/components/InputField";
63
- import { useState } from 'react'
64
-
65
- function WithLabels() {
66
- const [password, setPassword] = useState('')
67
-
68
- const getStrengthLabel = (password: string) => {
69
- let level = 0
70
- if (password.length >= 6) level++
71
- if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) level++
72
- if (/[A-Z]/.test(password)) level++
73
-
74
- if (level === 0) return 'No password'
75
- if (level === 1) return 'Weak'
76
- if (level === 2) return 'Medium'
77
- return 'Strong'
78
- }
79
-
80
- const getStrengthColor = (password: string) => {
81
- const label = getStrengthLabel(password)
82
- if (label === 'Weak') return 'text-red-500'
83
- if (label === 'Medium') return 'text-yellow-500'
84
- if (label === 'Strong') return 'text-green-500'
85
- return 'text-gray-400'
86
- }
87
-
88
- return (
89
- <div className="space-y-2">
90
- <InputField
91
- type="password"
92
- value={password}
93
- onChange={(e) => setPassword(e.target.value)}
94
- label="Password"
95
- />
96
- <PasswordLevel value={password} />
97
- <p className={`text-sm font-medium ${getStrengthColor(password)}`}>
98
- Password strength: {getStrengthLabel(password)}
99
- </p>
100
- </div>
101
- )
102
- }
103
- ```
104
-
105
- ### Registration Form
106
-
107
- ```typescript
108
- import { PasswordLevel } from "@/components/PasswordLevel";
109
- import { Button } from "@/components/Button";
110
- import { FieldHint } from "@/components/FieldHint";
111
- import { InputField } from "@/components/InputField";
112
- import { useState } from 'react'
113
-
114
- function RegistrationForm() {
115
- const [password, setPassword] = useState('')
116
- const [confirmPassword, setConfirmPassword] = useState('')
117
-
118
- const passwordMatch = password && confirmPassword && password === confirmPassword
119
-
120
- const getPasswordLevel = (pwd: string) => {
121
- let level = 0
122
- if (pwd.length >= 6) level++
123
- if (/[!@#$%^&*(),.?":{}|<>]/.test(pwd)) level++
124
- if (/[A-Z]/.test(pwd)) level++
125
- return level
126
- }
127
-
128
- const isStrongPassword = getPasswordLevel(password) === 3
129
-
130
- return (
131
- <form className="space-y-4">
132
- <div className="space-y-2">
133
- <InputField
134
- type="password"
135
- value={password}
136
- onChange={(e) => setPassword(e.target.value)}
137
- label="Create Password"
138
- />
139
- <PasswordLevel value={password} />
140
- <FieldHint
141
- state="info"
142
- label="Password must be at least 6 characters with uppercase and symbols"
143
- />
144
- </div>
145
-
146
- <InputField
147
- type="password"
148
- value={confirmPassword}
149
- onChange={(e) => setConfirmPassword(e.target.value)}
150
- label="Confirm Password"
151
- />
152
-
153
- {confirmPassword && !passwordMatch && (
154
- <FieldHint state="error" label="Passwords do not match" />
155
- )}
156
-
157
- <Button
158
- type="submit"
159
- disabled={!isStrongPassword || !passwordMatch}
160
- >
161
- Create Account
162
- </Button>
163
- </form>
164
- )
165
- }
166
- ```
167
-
168
- ### With Requirements Checklist
169
-
170
- ```typescript
171
- import { PasswordLevel } from "@/components/PasswordLevel";
172
- import { InputField } from "@/components/InputField";
173
- import { useState } from 'react'
174
-
175
- function PasswordWithChecklist() {
176
- const [password, setPassword] = useState('')
177
-
178
- const requirements = [
179
- {
180
- label: 'At least 6 characters',
181
- met: password.length >= 6,
182
- },
183
- {
184
- label: 'Contains a special character',
185
- met: /[!@#$%^&*(),.?":{}|<>]/.test(password),
186
- },
187
- {
188
- label: 'Contains an uppercase letter',
189
- met: /[A-Z]/.test(password),
190
- },
191
- ]
192
-
193
- return (
194
- <div className="space-y-4">
195
- <InputField
196
- type="password"
197
- value={password}
198
- onChange={(e) => setPassword(e.target.value)}
199
- label="Password"
200
- />
201
-
202
- <PasswordLevel value={password} />
203
-
204
- <div className="space-y-2">
205
- <p className="text-sm font-medium">Password requirements:</p>
206
- <ul className="space-y-1">
207
- {requirements.map((req, index) => (
208
- <li key={index} className="flex items-center gap-2 text-sm">
209
- <i
210
- className={`${
211
- req.met
212
- ? 'ri-checkbox-circle-fill text-green-500'
213
- : 'ri-checkbox-blank-circle-line text-gray-400'
214
- }`}
215
- />
216
- <span className={req.met ? 'text-green-600' : 'text-gray-600'}>
217
- {req.label}
218
- </span>
219
- </li>
220
- ))}
221
- </ul>
222
- </div>
223
- </div>
224
- )
225
- }
226
- ```
227
-
228
- ### Password Change Form
229
-
230
- ```typescript
231
- import { PasswordLevel } from "@/components/PasswordLevel";
232
- import { Button } from "@/components/Button";
233
- import { InputField } from "@/components/InputField";
234
- import { useState } from 'react'
235
-
236
- function PasswordChangeForm() {
237
- const [currentPassword, setCurrentPassword] = useState('')
238
- const [newPassword, setNewPassword] = useState('')
239
- const [confirmPassword, setConfirmPassword] = useState('')
240
-
241
- const canSubmit =
242
- currentPassword &&
243
- newPassword &&
244
- newPassword === confirmPassword &&
245
- getPasswordLevel(newPassword) >= 2 // At least medium strength
246
-
247
- return (
248
- <form className="space-y-4">
249
- <InputField
250
- type="password"
251
- value={currentPassword}
252
- onChange={(e) => setCurrentPassword(e.target.value)}
253
- label="Current Password"
254
- />
255
-
256
- <div className="space-y-2">
257
- <InputField
258
- type="password"
259
- value={newPassword}
260
- onChange={(e) => setNewPassword(e.target.value)}
261
- label="New Password"
262
- />
263
- <PasswordLevel value={newPassword} />
264
- </div>
265
-
266
- <InputField
267
- type="password"
268
- value={confirmPassword}
269
- onChange={(e) => setConfirmPassword(e.target.value)}
270
- label="Confirm New Password"
271
- />
272
-
273
- <Button type="submit" disabled={!canSubmit}>
274
- Change Password
275
- </Button>
276
- </form>
277
- )
278
- }
279
- ```
280
-
281
- ### Real-time Feedback
282
-
283
- ```typescript
284
- import { PasswordLevel } from "@/components/PasswordLevel";
285
- import { InputField } from "@/components/InputField";
286
- import { useState, useEffect } from 'react'
287
-
288
- function RealTimeFeedback() {
289
- const [password, setPassword] = useState('')
290
- const [feedback, setFeedback] = useState<string[]>([])
291
-
292
- useEffect(() => {
293
- const newFeedback: string[] = []
294
-
295
- if (password.length > 0 && password.length < 6) {
296
- newFeedback.push('Password is too short')
297
- }
298
-
299
- if (password.length >= 6 && !/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
300
- newFeedback.push('Add a special character for better security')
301
- }
302
-
303
- if (password.length >= 6 && !/[A-Z]/.test(password)) {
304
- newFeedback.push('Add an uppercase letter for better security')
305
- }
306
-
307
- if (!/[0-9]/.test(password) && password.length > 0) {
308
- newFeedback.push('Consider adding a number')
309
- }
310
-
311
- setFeedback(newFeedback)
312
- }, [password])
313
-
314
- return (
315
- <div className="space-y-2">
316
- <InputField
317
- type="password"
318
- value={password}
319
- onChange={(e) => setPassword(e.target.value)}
320
- label="Password"
321
- />
322
-
323
- <PasswordLevel value={password} />
324
-
325
- {feedback.length > 0 && (
326
- <div className="space-y-1">
327
- {feedback.map((msg, index) => (
328
- <p key={index} className="text-xs text-gray-600">
329
- 💡 {msg}
330
- </p>
331
- ))}
332
- </div>
333
- )}
334
- </div>
335
- )
336
- }
337
- ```
338
-
339
- ### Different Themes
340
-
341
- ```typescript
342
- import { PasswordLevel } from "@/components/PasswordLevel";
343
- import { useState } from 'react'
344
-
345
- function ThemeExample() {
346
- const [password, setPassword] = useState('')
347
-
348
- return (
349
- <div className="space-y-4">
350
- <div className="p-4 bg-white">
351
- <input
352
- type="password"
353
- value={password}
354
- onChange={(e) => setPassword(e.target.value)}
355
- />
356
- <PasswordLevel value={password} theme="light" />
357
- </div>
358
-
359
- <div className="p-4 bg-gray-900">
360
- <input
361
- type="password"
362
- value={password}
363
- onChange={(e) => setPassword(e.target.value)}
364
- />
365
- <PasswordLevel value={password} theme="dark" />
366
- </div>
367
- </div>
368
- )
369
- }
370
- ```
371
-
372
- ### Custom Styling
373
-
374
- ```typescript
375
- import { PasswordLevel } from "@/components/PasswordLevel";
376
- import { useState } from 'react'
377
-
378
- function CustomStyling() {
379
- const [password, setPassword] = useState('')
380
-
381
- return (
382
- <div className="space-y-2">
383
- <input
384
- type="password"
385
- value={password}
386
- onChange={(e) => setPassword(e.target.value)}
387
- className="w-full border rounded p-2"
388
- />
389
-
390
- <PasswordLevel
391
- value={password}
392
- className="!rounded-[8px] !p-[6px] !gap-[6px]"
393
- />
394
- </div>
395
- )
396
- }
397
- ```
398
-
399
- ### Animated Feedback
400
-
401
- ```typescript
402
- import { PasswordLevel } from "@/components/PasswordLevel";
403
- import { InputField } from "@/components/InputField";
404
- import { useState } from 'react'
405
-
406
- function AnimatedFeedback() {
407
- const [password, setPassword] = useState('')
408
-
409
- const getLevel = (pwd: string) => {
410
- let level = 0
411
- if (pwd.length >= 6) level++
412
- if (/[!@#$%^&*(),.?":{}|<>]/.test(pwd)) level++
413
- if (/[A-Z]/.test(pwd)) level++
414
- return level
415
- }
416
-
417
- const level = getLevel(password)
418
-
419
- const messages = [
420
- 'Enter a password',
421
- 'Weak - Add more characters',
422
- 'Medium - Almost there!',
423
- 'Strong - Great password!',
424
- ]
425
-
426
- return (
427
- <div className="space-y-2">
428
- <InputField
429
- type="password"
430
- value={password}
431
- onChange={(e) => setPassword(e.target.value)}
432
- label="Password"
433
- />
434
-
435
- <PasswordLevel value={password} />
436
-
437
- <div className="transition-all duration-300">
438
- <p
439
- className={`text-sm font-medium ${
440
- level === 0
441
- ? 'text-gray-400'
442
- : level === 1
443
- ? 'text-red-500'
444
- : level === 2
445
- ? 'text-yellow-500'
446
- : 'text-green-500'
447
- }`}
448
- >
449
- {messages[level]}
450
- </p>
451
- </div>
452
- </div>
453
- )
454
- }
455
- ```
456
-
457
- ## API Reference
458
-
459
- ### PasswordLevel Props
460
-
461
- Extends all standard HTML div attributes.
462
-
463
- | Prop | Type | Default | Description |
464
- |------|------|---------|-------------|
465
- | `value` | `string` | **required** | Password string to evaluate |
466
- | `theme` | `'light' \| 'dark' \| 'default'` | - | Theme variant |
467
- | `className` | `string` | - | Additional CSS classes |
468
- | ...HTMLDivElement | - | - | All div attributes |
469
-
470
- ### Strength Calculation
471
-
472
- Password strength is calculated based on three criteria:
473
-
474
- | Level | Criteria | Color |
475
- |-------|----------|-------|
476
- | 1 | Length ≥ 6 characters | Red (Weak) |
477
- | 2 | + Contains special character | Yellow (Medium) |
478
- | 3 | + Contains uppercase letter | Green (Strong) |
479
-
480
- ### Special Characters
481
-
482
- The following characters count as special characters:
483
-
484
- ```
485
- ! @ # $ % ^ & * ( ) , . ? " : { } | < >
486
- ```
487
-
488
- ## TypeScript
489
-
490
- ### Full Type Definitions
491
-
492
- ```typescript
493
- import { HTMLAttributes } from 'react'
494
-
495
- interface PasswordLevelProps extends HTMLAttributes<HTMLDivElement> {
496
- value: string
497
- theme?: 'light' | 'dark' | 'default'
498
- }
499
-
500
- export const PasswordLevel: React.FC<PasswordLevelProps>
501
- ```
502
-
503
- ### Helper Functions
504
-
505
- ```typescript
506
- // Calculate password level
507
- function getPasswordLevel(password: string): number {
508
- const symbolRegex = /[!@#$%^&*(),.?":{}|<>]/
509
- const uppercaseRegex = /[A-Z]/
510
-
511
- let level = 0
512
- if (password.length >= 6) level++
513
- if (symbolRegex.test(password)) level++
514
- if (uppercaseRegex.test(password)) level++
515
-
516
- return level
517
- }
518
-
519
- // Get strength label
520
- function getPasswordStrength(password: string): 'weak' | 'medium' | 'strong' | 'none' {
521
- const level = getPasswordLevel(password)
522
- if (level === 0) return 'none'
523
- if (level === 1) return 'weak'
524
- if (level === 2) return 'medium'
525
- return 'strong'
526
- }
527
-
528
- // Check if password is acceptable
529
- function isPasswordAcceptable(password: string, minLevel: number = 2): boolean {
530
- return getPasswordLevel(password) >= minLevel
531
- }
532
- ```
533
-
534
- ## Common Patterns
535
-
536
- ### Validation Hook
537
-
538
- ```typescript
539
- import { PasswordLevel } from "@/components/PasswordLevel";
540
- import { useState, useMemo } from 'react'
541
-
542
- function usePasswordValidation(password: string) {
543
- const validation = useMemo(() => {
544
- const symbolRegex = /[!@#$%^&*(),.?":{}|<>]/
545
- const uppercaseRegex = /[A-Z]/
546
- const numberRegex = /[0-9]/
547
-
548
- return {
549
- hasMinLength: password.length >= 6,
550
- hasSymbol: symbolRegex.test(password),
551
- hasUppercase: uppercaseRegex.test(password),
552
- hasNumber: numberRegex.test(password),
553
- level: [
554
- password.length >= 6,
555
- symbolRegex.test(password),
556
- uppercaseRegex.test(password),
557
- ].filter(Boolean).length,
558
- isStrong: password.length >= 6 && symbolRegex.test(password) && uppercaseRegex.test(password),
559
- }
560
- }, [password])
561
-
562
- return validation
563
- }
564
-
565
- // Usage
566
- function ValidatedPasswordField() {
567
- const [password, setPassword] = useState('')
568
- const validation = usePasswordValidation(password)
569
-
570
- return (
571
- <div className="space-y-2">
572
- <InputField
573
- type="password"
574
- value={password}
575
- onChange={(e) => setPassword(e.target.value)}
576
- label="Password"
577
- />
578
- <PasswordLevel value={password} />
579
-
580
- <div className="text-xs space-y-1">
581
- <p className={validation.hasMinLength ? 'text-green-600' : 'text-gray-500'}>
582
- ✓ At least 6 characters
583
- </p>
584
- <p className={validation.hasSymbol ? 'text-green-600' : 'text-gray-500'}>
585
- ✓ Special character
586
- </p>
587
- <p className={validation.hasUppercase ? 'text-green-600' : 'text-gray-500'}>
588
- ✓ Uppercase letter
589
- </p>
590
- </div>
591
- </div>
592
- )
593
- }
594
- ```
595
-
596
- ### Password Generator
597
-
598
- ```typescript
599
- import { PasswordLevel } from "@/components/PasswordLevel";
600
- import { Button } from "@/components/Button";
601
- import { InputField } from "@/components/InputField";
602
- import { useState } from 'react'
603
-
604
- function PasswordGenerator() {
605
- const [password, setPassword] = useState('')
606
-
607
- const generatePassword = () => {
608
- const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
609
- const lowercase = 'abcdefghijklmnopqrstuvwxyz'
610
- const numbers = '0123456789'
611
- const symbols = '!@#$%^&*(),.?":{}|<>'
612
- const all = uppercase + lowercase + numbers + symbols
613
-
614
- let pwd = ''
615
- // Ensure at least one of each required type
616
- pwd += uppercase[Math.floor(Math.random() * uppercase.length)]
617
- pwd += symbols[Math.floor(Math.random() * symbols.length)]
618
-
619
- // Fill remaining characters
620
- for (let i = 0; i < 10; i++) {
621
- pwd += all[Math.floor(Math.random() * all.length)]
622
- }
623
-
624
- // Shuffle
625
- pwd = pwd.split('').sort(() => Math.random() - 0.5).join('')
626
- setPassword(pwd)
627
- }
628
-
629
- return (
630
- <div className="space-y-2">
631
- <InputField
632
- type="text"
633
- value={password}
634
- onChange={(e) => setPassword(e.target.value)}
635
- label="Password"
636
- childrenSide={
637
- <Button onClick={generatePassword} size="S">
638
- Generate
639
- </Button>
640
- }
641
- />
642
- <PasswordLevel value={password} />
643
- </div>
644
- )
645
- }
646
- ```
647
-
648
- ## Testing
649
-
650
- ### Unit Test Examples
651
-
652
- ```typescript
653
- import { render, screen } from '@testing-library/react'
654
- import { PasswordLevel } from "@/components/PasswordLevel";
655
-
656
- describe('PasswordLevel', () => {
657
- it('renders three bars', () => {
658
- const { container } = render(<PasswordLevel value="" />)
659
-
660
- const bars = container.querySelectorAll('.h-\\[4px\\]')
661
- expect(bars).toHaveLength(3)
662
- })
663
-
664
- it('shows weak password (level 1)', () => {
665
- const { container } = render(<PasswordLevel value="password" />)
666
-
667
- const bars = container.querySelectorAll('[class*="bg-border-presentation-state-negative"]')
668
- expect(bars).toHaveLength(1) // Only first bar filled
669
- })
670
-
671
- it('shows medium password (level 2)', () => {
672
- const { container } = render(<PasswordLevel value="password!" />)
673
-
674
- const negativeBars = container.querySelectorAll('[class*="negative"]')
675
- const warningBars = container.querySelectorAll('[class*="warning"]')
676
-
677
- expect(negativeBars).toHaveLength(1) // First bar
678
- expect(warningBars).toHaveLength(1) // Second bar
679
- })
680
-
681
- it('shows strong password (level 3)', () => {
682
- const { container } = render(<PasswordLevel value="Password!123" />)
683
-
684
- const negativeBars = container.querySelectorAll('[class*="negative"]')
685
- const warningBars = container.querySelectorAll('[class*="warning"]')
686
- const successBars = container.querySelectorAll('[class*="success"]')
687
-
688
- expect(negativeBars).toHaveLength(1) // First bar
689
- expect(warningBars).toHaveLength(1) // Second bar
690
- expect(successBars).toHaveLength(1) // Third bar
691
- })
692
-
693
- it('updates level when value changes', () => {
694
- const { rerender, container } = render(<PasswordLevel value="pass" />)
695
-
696
- let bars = container.querySelectorAll('[class*="negative"]')
697
- expect(bars).toHaveLength(0) // Too short
698
-
699
- rerender(<PasswordLevel value="password" />)
700
- bars = container.querySelectorAll('[class*="negative"]')
701
- expect(bars).toHaveLength(1) // Level 1
702
-
703
- rerender(<PasswordLevel value="Password!123" />)
704
- const successBars = container.querySelectorAll('[class*="success"]')
705
- expect(successBars).toHaveLength(1) // Level 3
706
- })
707
-
708
- it('applies theme correctly', () => {
709
- const { container } = render(
710
- <PasswordLevel value="test" theme="dark" />
711
- )
712
-
713
- const element = container.querySelector('[data-theme="dark"]')
714
- expect(element).toBeInTheDocument()
715
- })
716
- })
717
- ```
718
-
719
- ## Accessibility
720
-
721
- - **Visual Indicators**: Color-coded bars (red, yellow, green)
722
- - **Color Independence**: Always include text labels alongside colors
723
- - **Progressive Enhancement**: Works without JavaScript (static display)
724
- - **Screen Readers**: Add `aria-label` or `aria-describedby` for context
725
-
726
- ### Accessibility Best Practices
727
-
728
- ```typescript
729
- // Provide text alternative
730
- <div>
731
- <PasswordLevel value={password} aria-label={`Password strength: ${getStrength(password)}`} />
732
- <p className="sr-only">
733
- Password strength: {getStrength(password)}
734
- </p>
735
- </div>
736
-
737
- // Link with description
738
- <div>
739
- <InputField
740
- id="password-input"
741
- type="password"
742
- aria-describedby="password-strength"
743
- />
744
- <div id="password-strength">
745
- <PasswordLevel value={password} />
746
- <p className="text-sm">Strength: {getStrength(password)}</p>
747
- </div>
748
- </div>
749
- ```
750
-
751
- ## Performance
752
-
753
- | Metric | Value |
754
- |--------|-------|
755
- | Bundle size (minified) | ~1kb |
756
- | Bundle size (gzipped) | ~0.5kb |
757
- | Dependencies | None |
758
- | Re-renders | Only on value change |
759
- | Calculation complexity | O(n) where n is password length |
760
- | Tree-shakeable | ✅ |
761
-
762
- ### Performance Tips
763
-
764
- 1. **Debounce for real-time validation**: Avoid excessive calculations
765
- ```typescript
766
- const debouncedPassword = useDebounce(password, 300)
767
- <PasswordLevel value={debouncedPassword} />
768
- ```
769
-
770
- 2. **Memoize calculations**: Cache strength calculations
771
- ```typescript
772
- const level = useMemo(() => getPasswordLevel(password), [password])
773
- ```
774
-
775
- ## Styling
776
-
777
- ### Default Styling
778
-
779
- - Container: Rounded borders, grid layout with 3 columns
780
- - Bars: 4px height, rounded, with color transitions
781
- - Colors:
782
- - Level 0: Gray (secondary border)
783
- - Level 1: Red (negative state)
784
- - Level 2: Yellow (warning state)
785
- - Level 3: Green (success state)
786
- - Animation: 300ms ease-in-out transitions
787
-
788
- ## Best Practices
789
-
790
- 1. **Always show with password input**: Provide immediate feedback
791
- 2. **Add text labels**: Don't rely solely on colors
792
- 3. **Set minimum requirements**: Enforce at least level 2 for important accounts
793
- 4. **Provide helpful hints**: Tell users what's missing
794
- 5. **Test all levels**: Ensure all three states display correctly
795
- 6. **Consider additional criteria**: Numbers, lowercase, special patterns
796
- 7. **Validate on submit**: Client-side indicator + server-side validation
797
-
798
- ## Related Components
799
-
800
- - [InputField](./input-field.md) - Input field for password entry
801
- - [FieldHint](./field-hint.md) - Inline validation messages
802
- - [Toast](./toast.md) - Success/error notifications
803
- - [Button](./button.md) - Submit buttons with disabled states