@tribepad/themis 1.0.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 (654) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +21 -0
  3. package/README.md +114 -0
  4. package/dist/Carousel-NTZX5TOW.js +16 -0
  5. package/dist/Carousel-NTZX5TOW.js.map +1 -0
  6. package/dist/Carousel-YH3DOQJU.mjs +7 -0
  7. package/dist/Carousel-YH3DOQJU.mjs.map +1 -0
  8. package/dist/chunk-2HIUTHMU.mjs +234 -0
  9. package/dist/chunk-2HIUTHMU.mjs.map +1 -0
  10. package/dist/chunk-34GTFTDO.js +431 -0
  11. package/dist/chunk-34GTFTDO.js.map +1 -0
  12. package/dist/chunk-3H7ASYR7.js +250 -0
  13. package/dist/chunk-3H7ASYR7.js.map +1 -0
  14. package/dist/chunk-3IEN7JOP.js +316 -0
  15. package/dist/chunk-3IEN7JOP.js.map +1 -0
  16. package/dist/chunk-3JHN4GAL.js +326 -0
  17. package/dist/chunk-3JHN4GAL.js.map +1 -0
  18. package/dist/chunk-3MJPASQU.js +232 -0
  19. package/dist/chunk-3MJPASQU.js.map +1 -0
  20. package/dist/chunk-3XD2JUL3.js +572 -0
  21. package/dist/chunk-3XD2JUL3.js.map +1 -0
  22. package/dist/chunk-3YOY2VJ6.js +189 -0
  23. package/dist/chunk-3YOY2VJ6.js.map +1 -0
  24. package/dist/chunk-4DU5JSXB.js +408 -0
  25. package/dist/chunk-4DU5JSXB.js.map +1 -0
  26. package/dist/chunk-4E4E2GSS.js +352 -0
  27. package/dist/chunk-4E4E2GSS.js.map +1 -0
  28. package/dist/chunk-4NHAP4AN.mjs +3 -0
  29. package/dist/chunk-4NHAP4AN.mjs.map +1 -0
  30. package/dist/chunk-4S33J5NY.mjs +415 -0
  31. package/dist/chunk-4S33J5NY.mjs.map +1 -0
  32. package/dist/chunk-5SMGRT3G.mjs +354 -0
  33. package/dist/chunk-5SMGRT3G.mjs.map +1 -0
  34. package/dist/chunk-5SVLJN2C.mjs +22 -0
  35. package/dist/chunk-5SVLJN2C.mjs.map +1 -0
  36. package/dist/chunk-66WTU4EB.mjs +299 -0
  37. package/dist/chunk-66WTU4EB.mjs.map +1 -0
  38. package/dist/chunk-6S25NMOT.mjs +335 -0
  39. package/dist/chunk-6S25NMOT.mjs.map +1 -0
  40. package/dist/chunk-6SP7UB3D.js +4 -0
  41. package/dist/chunk-6SP7UB3D.js.map +1 -0
  42. package/dist/chunk-6TYWWQHM.mjs +565 -0
  43. package/dist/chunk-6TYWWQHM.mjs.map +1 -0
  44. package/dist/chunk-A3YUJA6W.mjs +384 -0
  45. package/dist/chunk-A3YUJA6W.mjs.map +1 -0
  46. package/dist/chunk-A6KEDVUR.js +61 -0
  47. package/dist/chunk-A6KEDVUR.js.map +1 -0
  48. package/dist/chunk-A77RUEWL.js +730 -0
  49. package/dist/chunk-A77RUEWL.js.map +1 -0
  50. package/dist/chunk-AA4IKMPE.mjs +3 -0
  51. package/dist/chunk-AA4IKMPE.mjs.map +1 -0
  52. package/dist/chunk-AKIA6GW6.mjs +163 -0
  53. package/dist/chunk-AKIA6GW6.mjs.map +1 -0
  54. package/dist/chunk-AL6P275L.mjs +435 -0
  55. package/dist/chunk-AL6P275L.mjs.map +1 -0
  56. package/dist/chunk-AZ3RJYTB.js +37 -0
  57. package/dist/chunk-AZ3RJYTB.js.map +1 -0
  58. package/dist/chunk-B5Q4UPL6.js +32 -0
  59. package/dist/chunk-B5Q4UPL6.js.map +1 -0
  60. package/dist/chunk-B6DHPMDP.mjs +335 -0
  61. package/dist/chunk-B6DHPMDP.mjs.map +1 -0
  62. package/dist/chunk-BDXKKMBZ.mjs +184 -0
  63. package/dist/chunk-BDXKKMBZ.mjs.map +1 -0
  64. package/dist/chunk-BL6E2DLZ.mjs +52 -0
  65. package/dist/chunk-BL6E2DLZ.mjs.map +1 -0
  66. package/dist/chunk-CGFDS4XS.mjs +121 -0
  67. package/dist/chunk-CGFDS4XS.mjs.map +1 -0
  68. package/dist/chunk-CJIW5TKI.js +139 -0
  69. package/dist/chunk-CJIW5TKI.js.map +1 -0
  70. package/dist/chunk-CKNISJOQ.js +314 -0
  71. package/dist/chunk-CKNISJOQ.js.map +1 -0
  72. package/dist/chunk-D6CBOECS.mjs +1757 -0
  73. package/dist/chunk-D6CBOECS.mjs.map +1 -0
  74. package/dist/chunk-DDWEVC2S.js +166 -0
  75. package/dist/chunk-DDWEVC2S.js.map +1 -0
  76. package/dist/chunk-DZ556D2F.mjs +176 -0
  77. package/dist/chunk-DZ556D2F.mjs.map +1 -0
  78. package/dist/chunk-E2KQFV3O.mjs +10 -0
  79. package/dist/chunk-E2KQFV3O.mjs.map +1 -0
  80. package/dist/chunk-EMMLADSC.js +126 -0
  81. package/dist/chunk-EMMLADSC.js.map +1 -0
  82. package/dist/chunk-EP4WOI5D.mjs +926 -0
  83. package/dist/chunk-EP4WOI5D.mjs.map +1 -0
  84. package/dist/chunk-FJRXLJC2.mjs +160 -0
  85. package/dist/chunk-FJRXLJC2.mjs.map +1 -0
  86. package/dist/chunk-FKQI434R.js +345 -0
  87. package/dist/chunk-FKQI434R.js.map +1 -0
  88. package/dist/chunk-FPKEAJRZ.mjs +100 -0
  89. package/dist/chunk-FPKEAJRZ.mjs.map +1 -0
  90. package/dist/chunk-FWQYB22U.js +183 -0
  91. package/dist/chunk-FWQYB22U.js.map +1 -0
  92. package/dist/chunk-GD5GHTMA.js +189 -0
  93. package/dist/chunk-GD5GHTMA.js.map +1 -0
  94. package/dist/chunk-GE5XTSDZ.js +447 -0
  95. package/dist/chunk-GE5XTSDZ.js.map +1 -0
  96. package/dist/chunk-GVE47ZAX.mjs +32 -0
  97. package/dist/chunk-GVE47ZAX.mjs.map +1 -0
  98. package/dist/chunk-HK46BT5U.mjs +18 -0
  99. package/dist/chunk-HK46BT5U.mjs.map +1 -0
  100. package/dist/chunk-HQVRMR6N.js +365 -0
  101. package/dist/chunk-HQVRMR6N.js.map +1 -0
  102. package/dist/chunk-HSGBJPJO.mjs +398 -0
  103. package/dist/chunk-HSGBJPJO.mjs.map +1 -0
  104. package/dist/chunk-I3AUTOMZ.mjs +125 -0
  105. package/dist/chunk-I3AUTOMZ.mjs.map +1 -0
  106. package/dist/chunk-IEI5LD5C.mjs +1161 -0
  107. package/dist/chunk-IEI5LD5C.mjs.map +1 -0
  108. package/dist/chunk-IIPTC2X7.mjs +118 -0
  109. package/dist/chunk-IIPTC2X7.mjs.map +1 -0
  110. package/dist/chunk-J7TLHF2Q.js +4 -0
  111. package/dist/chunk-J7TLHF2Q.js.map +1 -0
  112. package/dist/chunk-JJOWXFXQ.mjs +765 -0
  113. package/dist/chunk-JJOWXFXQ.mjs.map +1 -0
  114. package/dist/chunk-JPTSS2OA.mjs +3 -0
  115. package/dist/chunk-JPTSS2OA.mjs.map +1 -0
  116. package/dist/chunk-KFXXRLTP.js +396 -0
  117. package/dist/chunk-KFXXRLTP.js.map +1 -0
  118. package/dist/chunk-KPRRBSG6.mjs +272 -0
  119. package/dist/chunk-KPRRBSG6.mjs.map +1 -0
  120. package/dist/chunk-NFSBGRDB.mjs +57 -0
  121. package/dist/chunk-NFSBGRDB.mjs.map +1 -0
  122. package/dist/chunk-NGJVCFTM.js +219 -0
  123. package/dist/chunk-NGJVCFTM.js.map +1 -0
  124. package/dist/chunk-NSQ6MZJ6.mjs +728 -0
  125. package/dist/chunk-NSQ6MZJ6.mjs.map +1 -0
  126. package/dist/chunk-NYQYHT76.mjs +296 -0
  127. package/dist/chunk-NYQYHT76.mjs.map +1 -0
  128. package/dist/chunk-OLJJGI5B.js +1193 -0
  129. package/dist/chunk-OLJJGI5B.js.map +1 -0
  130. package/dist/chunk-Q3572X2J.js +292 -0
  131. package/dist/chunk-Q3572X2J.js.map +1 -0
  132. package/dist/chunk-QH7N7D4I.mjs +210 -0
  133. package/dist/chunk-QH7N7D4I.mjs.map +1 -0
  134. package/dist/chunk-R7XUIV25.js +466 -0
  135. package/dist/chunk-R7XUIV25.js.map +1 -0
  136. package/dist/chunk-RFFO4KPM.js +135 -0
  137. package/dist/chunk-RFFO4KPM.js.map +1 -0
  138. package/dist/chunk-RFX7QKA7.mjs +180 -0
  139. package/dist/chunk-RFX7QKA7.mjs.map +1 -0
  140. package/dist/chunk-SN5LFAP3.js +940 -0
  141. package/dist/chunk-SN5LFAP3.js.map +1 -0
  142. package/dist/chunk-T4COXKQ3.js +24 -0
  143. package/dist/chunk-T4COXKQ3.js.map +1 -0
  144. package/dist/chunk-TS54QM27.js +125 -0
  145. package/dist/chunk-TS54QM27.js.map +1 -0
  146. package/dist/chunk-UE2S4PCX.mjs +220 -0
  147. package/dist/chunk-UE2S4PCX.mjs.map +1 -0
  148. package/dist/chunk-UTW3QX2A.mjs +282 -0
  149. package/dist/chunk-UTW3QX2A.mjs.map +1 -0
  150. package/dist/chunk-V74LGMAE.js +1767 -0
  151. package/dist/chunk-V74LGMAE.js.map +1 -0
  152. package/dist/chunk-VIREG536.js +12 -0
  153. package/dist/chunk-VIREG536.js.map +1 -0
  154. package/dist/chunk-VY7M7346.js +4 -0
  155. package/dist/chunk-VY7M7346.js.map +1 -0
  156. package/dist/chunk-W3TJOO7H.mjs +319 -0
  157. package/dist/chunk-W3TJOO7H.mjs.map +1 -0
  158. package/dist/chunk-WIUOB36M.js +54 -0
  159. package/dist/chunk-WIUOB36M.js.map +1 -0
  160. package/dist/chunk-WJGLM4CY.js +291 -0
  161. package/dist/chunk-WJGLM4CY.js.map +1 -0
  162. package/dist/chunk-WNURH5OO.mjs +453 -0
  163. package/dist/chunk-WNURH5OO.mjs.map +1 -0
  164. package/dist/chunk-X25TNRSD.mjs +364 -0
  165. package/dist/chunk-X25TNRSD.mjs.map +1 -0
  166. package/dist/chunk-Y3GT7ETK.js +108 -0
  167. package/dist/chunk-Y3GT7ETK.js.map +1 -0
  168. package/dist/chunk-Z4FRNOF6.mjs +115 -0
  169. package/dist/chunk-Z4FRNOF6.mjs.map +1 -0
  170. package/dist/chunk-ZMYLD3BN.js +166 -0
  171. package/dist/chunk-ZMYLD3BN.js.map +1 -0
  172. package/dist/chunk-ZP2KV6EX.js +815 -0
  173. package/dist/chunk-ZP2KV6EX.js.map +1 -0
  174. package/dist/chunk-ZVKXFELU.js +366 -0
  175. package/dist/chunk-ZVKXFELU.js.map +1 -0
  176. package/dist/elements/Accordion/Accordion.d.ts +139 -0
  177. package/dist/elements/Accordion/Accordion.d.ts.map +1 -0
  178. package/dist/elements/Accordion/Accordion.types.d.ts +143 -0
  179. package/dist/elements/Accordion/Accordion.types.d.ts.map +1 -0
  180. package/dist/elements/Accordion/index.d.ts +13 -0
  181. package/dist/elements/Accordion/index.d.ts.map +1 -0
  182. package/dist/elements/Accordion/index.js +78 -0
  183. package/dist/elements/Accordion/index.js.map +1 -0
  184. package/dist/elements/Accordion/index.mjs +5 -0
  185. package/dist/elements/Accordion/index.mjs.map +1 -0
  186. package/dist/elements/Avatar/Avatar.d.ts +51 -0
  187. package/dist/elements/Avatar/Avatar.d.ts.map +1 -0
  188. package/dist/elements/Avatar/Avatar.types.d.ts +145 -0
  189. package/dist/elements/Avatar/Avatar.types.d.ts.map +1 -0
  190. package/dist/elements/Avatar/AvatarGroup.d.ts +32 -0
  191. package/dist/elements/Avatar/AvatarGroup.d.ts.map +1 -0
  192. package/dist/elements/Avatar/index.d.ts +11 -0
  193. package/dist/elements/Avatar/index.d.ts.map +1 -0
  194. package/dist/elements/Avatar/index.js +54 -0
  195. package/dist/elements/Avatar/index.js.map +1 -0
  196. package/dist/elements/Avatar/index.mjs +5 -0
  197. package/dist/elements/Avatar/index.mjs.map +1 -0
  198. package/dist/elements/Badge/Badge.d.ts +39 -0
  199. package/dist/elements/Badge/Badge.d.ts.map +1 -0
  200. package/dist/elements/Badge/Badge.types.d.ts +76 -0
  201. package/dist/elements/Badge/Badge.types.d.ts.map +1 -0
  202. package/dist/elements/Badge/index.d.ts +18 -0
  203. package/dist/elements/Badge/index.d.ts.map +1 -0
  204. package/dist/elements/Badge/index.js +43 -0
  205. package/dist/elements/Badge/index.js.map +1 -0
  206. package/dist/elements/Badge/index.mjs +6 -0
  207. package/dist/elements/Badge/index.mjs.map +1 -0
  208. package/dist/elements/Breadcrumbs/Breadcrumbs.d.ts +91 -0
  209. package/dist/elements/Breadcrumbs/Breadcrumbs.d.ts.map +1 -0
  210. package/dist/elements/Breadcrumbs/Breadcrumbs.types.d.ts +114 -0
  211. package/dist/elements/Breadcrumbs/Breadcrumbs.types.d.ts.map +1 -0
  212. package/dist/elements/Breadcrumbs/index.d.ts +14 -0
  213. package/dist/elements/Breadcrumbs/index.d.ts.map +1 -0
  214. package/dist/elements/Breadcrumbs/index.js +54 -0
  215. package/dist/elements/Breadcrumbs/index.js.map +1 -0
  216. package/dist/elements/Breadcrumbs/index.mjs +9 -0
  217. package/dist/elements/Breadcrumbs/index.mjs.map +1 -0
  218. package/dist/elements/Button/Button.d.ts +92 -0
  219. package/dist/elements/Button/Button.d.ts.map +1 -0
  220. package/dist/elements/Button/Button.types.d.ts +54 -0
  221. package/dist/elements/Button/Button.types.d.ts.map +1 -0
  222. package/dist/elements/Button/index.d.ts +18 -0
  223. package/dist/elements/Button/index.d.ts.map +1 -0
  224. package/dist/elements/Button/index.js +27 -0
  225. package/dist/elements/Button/index.js.map +1 -0
  226. package/dist/elements/Button/index.mjs +6 -0
  227. package/dist/elements/Button/index.mjs.map +1 -0
  228. package/dist/elements/ButtonGroup/ButtonGroup.d.ts +53 -0
  229. package/dist/elements/ButtonGroup/ButtonGroup.d.ts.map +1 -0
  230. package/dist/elements/ButtonGroup/ButtonGroup.types.d.ts +98 -0
  231. package/dist/elements/ButtonGroup/ButtonGroup.types.d.ts.map +1 -0
  232. package/dist/elements/ButtonGroup/ButtonGroup.utils.d.ts +60 -0
  233. package/dist/elements/ButtonGroup/ButtonGroup.utils.d.ts.map +1 -0
  234. package/dist/elements/ButtonGroup/ButtonGroup.variants.d.ts +39 -0
  235. package/dist/elements/ButtonGroup/ButtonGroup.variants.d.ts.map +1 -0
  236. package/dist/elements/ButtonGroup/ButtonGroupContext.d.ts +42 -0
  237. package/dist/elements/ButtonGroup/ButtonGroupContext.d.ts.map +1 -0
  238. package/dist/elements/ButtonGroup/index.d.ts +35 -0
  239. package/dist/elements/ButtonGroup/index.d.ts.map +1 -0
  240. package/dist/elements/ButtonGroup/index.js +66 -0
  241. package/dist/elements/ButtonGroup/index.js.map +1 -0
  242. package/dist/elements/ButtonGroup/index.mjs +5 -0
  243. package/dist/elements/ButtonGroup/index.mjs.map +1 -0
  244. package/dist/elements/Card/Card.d.ts +104 -0
  245. package/dist/elements/Card/Card.d.ts.map +1 -0
  246. package/dist/elements/Card/Card.types.d.ts +227 -0
  247. package/dist/elements/Card/Card.types.d.ts.map +1 -0
  248. package/dist/elements/Card/index.d.ts +38 -0
  249. package/dist/elements/Card/index.d.ts.map +1 -0
  250. package/dist/elements/Card/index.js +85 -0
  251. package/dist/elements/Card/index.js.map +1 -0
  252. package/dist/elements/Card/index.mjs +8 -0
  253. package/dist/elements/Card/index.mjs.map +1 -0
  254. package/dist/elements/Carousel/Carousel.d.ts +13 -0
  255. package/dist/elements/Carousel/Carousel.d.ts.map +1 -0
  256. package/dist/elements/Carousel/Carousel.types.d.ts +65 -0
  257. package/dist/elements/Carousel/Carousel.types.d.ts.map +1 -0
  258. package/dist/elements/Carousel/LazyCarousel.d.ts +46 -0
  259. package/dist/elements/Carousel/LazyCarousel.d.ts.map +1 -0
  260. package/dist/elements/Carousel/index.d.ts +5 -0
  261. package/dist/elements/Carousel/index.d.ts.map +1 -0
  262. package/dist/elements/Carousel/index.js +23 -0
  263. package/dist/elements/Carousel/index.js.map +1 -0
  264. package/dist/elements/Carousel/index.mjs +10 -0
  265. package/dist/elements/Carousel/index.mjs.map +1 -0
  266. package/dist/elements/Chart/Chart.d.ts +44 -0
  267. package/dist/elements/Chart/Chart.d.ts.map +1 -0
  268. package/dist/elements/Chart/Chart.types.d.ts +254 -0
  269. package/dist/elements/Chart/Chart.types.d.ts.map +1 -0
  270. package/dist/elements/Chart/ChartAnnouncer.d.ts +24 -0
  271. package/dist/elements/Chart/ChartAnnouncer.d.ts.map +1 -0
  272. package/dist/elements/Chart/ChartAxis.d.ts +42 -0
  273. package/dist/elements/Chart/ChartAxis.d.ts.map +1 -0
  274. package/dist/elements/Chart/ChartBarSeries.d.ts +54 -0
  275. package/dist/elements/Chart/ChartBarSeries.d.ts.map +1 -0
  276. package/dist/elements/Chart/ChartContext.d.ts +46 -0
  277. package/dist/elements/Chart/ChartContext.d.ts.map +1 -0
  278. package/dist/elements/Chart/ChartDataPoint.d.ts +56 -0
  279. package/dist/elements/Chart/ChartDataPoint.d.ts.map +1 -0
  280. package/dist/elements/Chart/ChartDataTable.d.ts +35 -0
  281. package/dist/elements/Chart/ChartDataTable.d.ts.map +1 -0
  282. package/dist/elements/Chart/ChartGrid.d.ts +32 -0
  283. package/dist/elements/Chart/ChartGrid.d.ts.map +1 -0
  284. package/dist/elements/Chart/ChartLegend.d.ts +32 -0
  285. package/dist/elements/Chart/ChartLegend.d.ts.map +1 -0
  286. package/dist/elements/Chart/ChartLineSeries.d.ts +52 -0
  287. package/dist/elements/Chart/ChartLineSeries.d.ts.map +1 -0
  288. package/dist/elements/Chart/ChartSVG.d.ts +62 -0
  289. package/dist/elements/Chart/ChartSVG.d.ts.map +1 -0
  290. package/dist/elements/Chart/ChartTooltip.d.ts +45 -0
  291. package/dist/elements/Chart/ChartTooltip.d.ts.map +1 -0
  292. package/dist/elements/Chart/chart.constants.d.ts +108 -0
  293. package/dist/elements/Chart/chart.constants.d.ts.map +1 -0
  294. package/dist/elements/Chart/chart.variants.d.ts +45 -0
  295. package/dist/elements/Chart/chart.variants.d.ts.map +1 -0
  296. package/dist/elements/Chart/index.d.ts +12 -0
  297. package/dist/elements/Chart/index.d.ts.map +1 -0
  298. package/dist/elements/Chart/index.js +47 -0
  299. package/dist/elements/Chart/index.js.map +1 -0
  300. package/dist/elements/Chart/index.mjs +6 -0
  301. package/dist/elements/Chart/index.mjs.map +1 -0
  302. package/dist/elements/Chart/useChartDimensions.d.ts +18 -0
  303. package/dist/elements/Chart/useChartDimensions.d.ts.map +1 -0
  304. package/dist/elements/Chart/useChartKeyboard.d.ts +42 -0
  305. package/dist/elements/Chart/useChartKeyboard.d.ts.map +1 -0
  306. package/dist/elements/Chart/useRovingTabIndex.d.ts +46 -0
  307. package/dist/elements/Chart/useRovingTabIndex.d.ts.map +1 -0
  308. package/dist/elements/Checkbox/Checkbox.d.ts +94 -0
  309. package/dist/elements/Checkbox/Checkbox.d.ts.map +1 -0
  310. package/dist/elements/Checkbox/Checkbox.types.d.ts +82 -0
  311. package/dist/elements/Checkbox/Checkbox.types.d.ts.map +1 -0
  312. package/dist/elements/Checkbox/index.d.ts +7 -0
  313. package/dist/elements/Checkbox/index.d.ts.map +1 -0
  314. package/dist/elements/Checkbox/index.js +47 -0
  315. package/dist/elements/Checkbox/index.js.map +1 -0
  316. package/dist/elements/Checkbox/index.mjs +6 -0
  317. package/dist/elements/Checkbox/index.mjs.map +1 -0
  318. package/dist/elements/CheckboxGroup/CheckboxGroup.d.ts +130 -0
  319. package/dist/elements/CheckboxGroup/CheckboxGroup.d.ts.map +1 -0
  320. package/dist/elements/CheckboxGroup/CheckboxGroup.types.d.ts +142 -0
  321. package/dist/elements/CheckboxGroup/CheckboxGroup.types.d.ts.map +1 -0
  322. package/dist/elements/CheckboxGroup/index.d.ts +10 -0
  323. package/dist/elements/CheckboxGroup/index.d.ts.map +1 -0
  324. package/dist/elements/CheckboxGroup/index.js +71 -0
  325. package/dist/elements/CheckboxGroup/index.js.map +1 -0
  326. package/dist/elements/CheckboxGroup/index.mjs +6 -0
  327. package/dist/elements/CheckboxGroup/index.mjs.map +1 -0
  328. package/dist/elements/DatePicker/Calendar.d.ts +16 -0
  329. package/dist/elements/DatePicker/Calendar.d.ts.map +1 -0
  330. package/dist/elements/DatePicker/DateField.d.ts +13 -0
  331. package/dist/elements/DatePicker/DateField.d.ts.map +1 -0
  332. package/dist/elements/DatePicker/DatePicker.d.ts +16 -0
  333. package/dist/elements/DatePicker/DatePicker.d.ts.map +1 -0
  334. package/dist/elements/DatePicker/DatePicker.types.d.ts +390 -0
  335. package/dist/elements/DatePicker/DatePicker.types.d.ts.map +1 -0
  336. package/dist/elements/DatePicker/DatePicker.variants.d.ts +42 -0
  337. package/dist/elements/DatePicker/DatePicker.variants.d.ts.map +1 -0
  338. package/dist/elements/DatePicker/DateRangePicker.d.ts +13 -0
  339. package/dist/elements/DatePicker/DateRangePicker.d.ts.map +1 -0
  340. package/dist/elements/DatePicker/index.d.ts +14 -0
  341. package/dist/elements/DatePicker/index.d.ts.map +1 -0
  342. package/dist/elements/DatePicker/index.js +123 -0
  343. package/dist/elements/DatePicker/index.js.map +1 -0
  344. package/dist/elements/DatePicker/index.mjs +6 -0
  345. package/dist/elements/DatePicker/index.mjs.map +1 -0
  346. package/dist/elements/Dropdown/Dropdown.d.ts +197 -0
  347. package/dist/elements/Dropdown/Dropdown.d.ts.map +1 -0
  348. package/dist/elements/Dropdown/Dropdown.types.d.ts +175 -0
  349. package/dist/elements/Dropdown/Dropdown.types.d.ts.map +1 -0
  350. package/dist/elements/Dropdown/index.d.ts +12 -0
  351. package/dist/elements/Dropdown/index.d.ts.map +1 -0
  352. package/dist/elements/Dropdown/index.js +41 -0
  353. package/dist/elements/Dropdown/index.js.map +1 -0
  354. package/dist/elements/Dropdown/index.mjs +4 -0
  355. package/dist/elements/Dropdown/index.mjs.map +1 -0
  356. package/dist/elements/FileField/FileField.d.ts +46 -0
  357. package/dist/elements/FileField/FileField.d.ts.map +1 -0
  358. package/dist/elements/FileField/FileField.types.d.ts +99 -0
  359. package/dist/elements/FileField/FileField.types.d.ts.map +1 -0
  360. package/dist/elements/FileField/FileField.variants.d.ts +49 -0
  361. package/dist/elements/FileField/FileField.variants.d.ts.map +1 -0
  362. package/dist/elements/FileField/FilePreview.d.ts +27 -0
  363. package/dist/elements/FileField/FilePreview.d.ts.map +1 -0
  364. package/dist/elements/FileField/FileProgress.d.ts +35 -0
  365. package/dist/elements/FileField/FileProgress.d.ts.map +1 -0
  366. package/dist/elements/FileField/FileProgress.variants.d.ts +55 -0
  367. package/dist/elements/FileField/FileProgress.variants.d.ts.map +1 -0
  368. package/dist/elements/FileField/index.d.ts +41 -0
  369. package/dist/elements/FileField/index.d.ts.map +1 -0
  370. package/dist/elements/FileField/index.js +138 -0
  371. package/dist/elements/FileField/index.js.map +1 -0
  372. package/dist/elements/FileField/index.mjs +9 -0
  373. package/dist/elements/FileField/index.mjs.map +1 -0
  374. package/dist/elements/FileField/useFilePreview.d.ts +46 -0
  375. package/dist/elements/FileField/useFilePreview.d.ts.map +1 -0
  376. package/dist/elements/FileField/utils.d.ts +134 -0
  377. package/dist/elements/FileField/utils.d.ts.map +1 -0
  378. package/dist/elements/FormLayout/FormLayout.d.ts +51 -0
  379. package/dist/elements/FormLayout/FormLayout.d.ts.map +1 -0
  380. package/dist/elements/FormLayout/FormLayout.types.d.ts +66 -0
  381. package/dist/elements/FormLayout/FormLayout.types.d.ts.map +1 -0
  382. package/dist/elements/FormLayout/index.d.ts +3 -0
  383. package/dist/elements/FormLayout/index.d.ts.map +1 -0
  384. package/dist/elements/FormLayout/index.js +17 -0
  385. package/dist/elements/FormLayout/index.js.map +1 -0
  386. package/dist/elements/FormLayout/index.mjs +4 -0
  387. package/dist/elements/FormLayout/index.mjs.map +1 -0
  388. package/dist/elements/Modal/Modal.d.ts +168 -0
  389. package/dist/elements/Modal/Modal.d.ts.map +1 -0
  390. package/dist/elements/Modal/Modal.types.d.ts +265 -0
  391. package/dist/elements/Modal/Modal.types.d.ts.map +1 -0
  392. package/dist/elements/Modal/index.d.ts +14 -0
  393. package/dist/elements/Modal/index.d.ts.map +1 -0
  394. package/dist/elements/Modal/index.js +52 -0
  395. package/dist/elements/Modal/index.js.map +1 -0
  396. package/dist/elements/Modal/index.mjs +3 -0
  397. package/dist/elements/Modal/index.mjs.map +1 -0
  398. package/dist/elements/NumberField/NumberField.d.ts +43 -0
  399. package/dist/elements/NumberField/NumberField.d.ts.map +1 -0
  400. package/dist/elements/NumberField/NumberField.types.d.ts +112 -0
  401. package/dist/elements/NumberField/NumberField.types.d.ts.map +1 -0
  402. package/dist/elements/NumberField/NumberField.variants.d.ts +82 -0
  403. package/dist/elements/NumberField/NumberField.variants.d.ts.map +1 -0
  404. package/dist/elements/NumberField/index.d.ts +25 -0
  405. package/dist/elements/NumberField/index.d.ts.map +1 -0
  406. package/dist/elements/NumberField/index.js +57 -0
  407. package/dist/elements/NumberField/index.js.map +1 -0
  408. package/dist/elements/NumberField/index.mjs +8 -0
  409. package/dist/elements/NumberField/index.mjs.map +1 -0
  410. package/dist/elements/OTPInput/OTPInput.d.ts +105 -0
  411. package/dist/elements/OTPInput/OTPInput.d.ts.map +1 -0
  412. package/dist/elements/OTPInput/OTPInput.styles.d.ts +83 -0
  413. package/dist/elements/OTPInput/OTPInput.styles.d.ts.map +1 -0
  414. package/dist/elements/OTPInput/OTPInput.types.d.ts +189 -0
  415. package/dist/elements/OTPInput/OTPInput.types.d.ts.map +1 -0
  416. package/dist/elements/OTPInput/components/OTPDigit.d.ts +51 -0
  417. package/dist/elements/OTPInput/components/OTPDigit.d.ts.map +1 -0
  418. package/dist/elements/OTPInput/hooks/useOTPInput.d.ts +36 -0
  419. package/dist/elements/OTPInput/hooks/useOTPInput.d.ts.map +1 -0
  420. package/dist/elements/OTPInput/hooks/useOTPKeyboard.d.ts +59 -0
  421. package/dist/elements/OTPInput/hooks/useOTPKeyboard.d.ts.map +1 -0
  422. package/dist/elements/OTPInput/index.d.ts +27 -0
  423. package/dist/elements/OTPInput/index.d.ts.map +1 -0
  424. package/dist/elements/OTPInput/index.js +13 -0
  425. package/dist/elements/OTPInput/index.js.map +1 -0
  426. package/dist/elements/OTPInput/index.mjs +4 -0
  427. package/dist/elements/OTPInput/index.mjs.map +1 -0
  428. package/dist/elements/Panel/Panel.d.ts +111 -0
  429. package/dist/elements/Panel/Panel.d.ts.map +1 -0
  430. package/dist/elements/Panel/Panel.types.d.ts +243 -0
  431. package/dist/elements/Panel/Panel.types.d.ts.map +1 -0
  432. package/dist/elements/Panel/index.d.ts +4 -0
  433. package/dist/elements/Panel/index.d.ts.map +1 -0
  434. package/dist/elements/Panel/index.js +33 -0
  435. package/dist/elements/Panel/index.js.map +1 -0
  436. package/dist/elements/Panel/index.mjs +4 -0
  437. package/dist/elements/Panel/index.mjs.map +1 -0
  438. package/dist/elements/Progress/Progress.d.ts +44 -0
  439. package/dist/elements/Progress/Progress.d.ts.map +1 -0
  440. package/dist/elements/Progress/Progress.types.d.ts +64 -0
  441. package/dist/elements/Progress/Progress.types.d.ts.map +1 -0
  442. package/dist/elements/Progress/index.d.ts +11 -0
  443. package/dist/elements/Progress/index.d.ts.map +1 -0
  444. package/dist/elements/Progress/index.js +30 -0
  445. package/dist/elements/Progress/index.js.map +1 -0
  446. package/dist/elements/Progress/index.mjs +5 -0
  447. package/dist/elements/Progress/index.mjs.map +1 -0
  448. package/dist/elements/RadioGroup/RadioGroup.d.ts +110 -0
  449. package/dist/elements/RadioGroup/RadioGroup.d.ts.map +1 -0
  450. package/dist/elements/RadioGroup/RadioGroup.types.d.ts +143 -0
  451. package/dist/elements/RadioGroup/RadioGroup.types.d.ts.map +1 -0
  452. package/dist/elements/RadioGroup/index.d.ts +10 -0
  453. package/dist/elements/RadioGroup/index.d.ts.map +1 -0
  454. package/dist/elements/RadioGroup/index.js +47 -0
  455. package/dist/elements/RadioGroup/index.js.map +1 -0
  456. package/dist/elements/RadioGroup/index.mjs +6 -0
  457. package/dist/elements/RadioGroup/index.mjs.map +1 -0
  458. package/dist/elements/Resizable/Resizable.types.d.ts +188 -0
  459. package/dist/elements/Resizable/Resizable.types.d.ts.map +1 -0
  460. package/dist/elements/Resizable/components/ResizableHandle.d.ts +28 -0
  461. package/dist/elements/Resizable/components/ResizableHandle.d.ts.map +1 -0
  462. package/dist/elements/Resizable/components/ResizablePanel.d.ts +24 -0
  463. package/dist/elements/Resizable/components/ResizablePanel.d.ts.map +1 -0
  464. package/dist/elements/Resizable/components/ResizablePanelGroup.d.ts +26 -0
  465. package/dist/elements/Resizable/components/ResizablePanelGroup.d.ts.map +1 -0
  466. package/dist/elements/Resizable/components/ResizablePopover.d.ts +45 -0
  467. package/dist/elements/Resizable/components/ResizablePopover.d.ts.map +1 -0
  468. package/dist/elements/Resizable/hooks/useResizable.d.ts +50 -0
  469. package/dist/elements/Resizable/hooks/useResizable.d.ts.map +1 -0
  470. package/dist/elements/Resizable/hooks/useResizableContext.d.ts +36 -0
  471. package/dist/elements/Resizable/hooks/useResizableContext.d.ts.map +1 -0
  472. package/dist/elements/Resizable/index.d.ts +37 -0
  473. package/dist/elements/Resizable/index.d.ts.map +1 -0
  474. package/dist/elements/Resizable/index.js +65 -0
  475. package/dist/elements/Resizable/index.js.map +1 -0
  476. package/dist/elements/Resizable/index.mjs +8 -0
  477. package/dist/elements/Resizable/index.mjs.map +1 -0
  478. package/dist/elements/Select/Select.d.ts +184 -0
  479. package/dist/elements/Select/Select.d.ts.map +1 -0
  480. package/dist/elements/Select/Select.types.d.ts +166 -0
  481. package/dist/elements/Select/Select.types.d.ts.map +1 -0
  482. package/dist/elements/Select/index.d.ts +35 -0
  483. package/dist/elements/Select/index.d.ts.map +1 -0
  484. package/dist/elements/Select/index.js +33 -0
  485. package/dist/elements/Select/index.js.map +1 -0
  486. package/dist/elements/Select/index.mjs +4 -0
  487. package/dist/elements/Select/index.mjs.map +1 -0
  488. package/dist/elements/Skeleton/Skeleton.d.ts +31 -0
  489. package/dist/elements/Skeleton/Skeleton.d.ts.map +1 -0
  490. package/dist/elements/Skeleton/Skeleton.types.d.ts +36 -0
  491. package/dist/elements/Skeleton/Skeleton.types.d.ts.map +1 -0
  492. package/dist/elements/Skeleton/index.d.ts +11 -0
  493. package/dist/elements/Skeleton/index.d.ts.map +1 -0
  494. package/dist/elements/Skeleton/index.js +22 -0
  495. package/dist/elements/Skeleton/index.js.map +1 -0
  496. package/dist/elements/Skeleton/index.mjs +5 -0
  497. package/dist/elements/Skeleton/index.mjs.map +1 -0
  498. package/dist/elements/Switch/Switch.d.ts +39 -0
  499. package/dist/elements/Switch/Switch.d.ts.map +1 -0
  500. package/dist/elements/Switch/Switch.types.d.ts +53 -0
  501. package/dist/elements/Switch/Switch.types.d.ts.map +1 -0
  502. package/dist/elements/Switch/index.d.ts +8 -0
  503. package/dist/elements/Switch/index.d.ts.map +1 -0
  504. package/dist/elements/Switch/index.js +49 -0
  505. package/dist/elements/Switch/index.js.map +1 -0
  506. package/dist/elements/Switch/index.mjs +31 -0
  507. package/dist/elements/Switch/index.mjs.map +1 -0
  508. package/dist/elements/Table/Table.d.ts +123 -0
  509. package/dist/elements/Table/Table.d.ts.map +1 -0
  510. package/dist/elements/Table/Table.types.d.ts +356 -0
  511. package/dist/elements/Table/Table.types.d.ts.map +1 -0
  512. package/dist/elements/Table/index.d.ts +5 -0
  513. package/dist/elements/Table/index.d.ts.map +1 -0
  514. package/dist/elements/Table/index.js +76 -0
  515. package/dist/elements/Table/index.js.map +1 -0
  516. package/dist/elements/Table/index.mjs +7 -0
  517. package/dist/elements/Table/index.mjs.map +1 -0
  518. package/dist/elements/Tabs/Tabs.d.ts +129 -0
  519. package/dist/elements/Tabs/Tabs.d.ts.map +1 -0
  520. package/dist/elements/Tabs/Tabs.types.d.ts +179 -0
  521. package/dist/elements/Tabs/Tabs.types.d.ts.map +1 -0
  522. package/dist/elements/Tabs/index.d.ts +12 -0
  523. package/dist/elements/Tabs/index.d.ts.map +1 -0
  524. package/dist/elements/Tabs/index.js +74 -0
  525. package/dist/elements/Tabs/index.js.map +1 -0
  526. package/dist/elements/Tabs/index.mjs +5 -0
  527. package/dist/elements/Tabs/index.mjs.map +1 -0
  528. package/dist/elements/TextField/TextField.d.ts +155 -0
  529. package/dist/elements/TextField/TextField.d.ts.map +1 -0
  530. package/dist/elements/TextField/TextField.types.d.ts +258 -0
  531. package/dist/elements/TextField/TextField.types.d.ts.map +1 -0
  532. package/dist/elements/TextField/index.css +23 -0
  533. package/dist/elements/TextField/index.css.map +1 -0
  534. package/dist/elements/TextField/index.d.ts +13 -0
  535. package/dist/elements/TextField/index.d.ts.map +1 -0
  536. package/dist/elements/TextField/index.js +260 -0
  537. package/dist/elements/TextField/index.js.map +1 -0
  538. package/dist/elements/TextField/index.mjs +207 -0
  539. package/dist/elements/TextField/index.mjs.map +1 -0
  540. package/dist/elements/TimeField/TimeField.d.ts +34 -0
  541. package/dist/elements/TimeField/TimeField.d.ts.map +1 -0
  542. package/dist/elements/TimeField/TimeField.types.d.ts +151 -0
  543. package/dist/elements/TimeField/TimeField.types.d.ts.map +1 -0
  544. package/dist/elements/TimeField/index.d.ts +24 -0
  545. package/dist/elements/TimeField/index.d.ts.map +1 -0
  546. package/dist/elements/TimeField/index.js +45 -0
  547. package/dist/elements/TimeField/index.js.map +1 -0
  548. package/dist/elements/TimeField/index.mjs +4 -0
  549. package/dist/elements/TimeField/index.mjs.map +1 -0
  550. package/dist/elements/Toast/Toast.d.ts +105 -0
  551. package/dist/elements/Toast/Toast.d.ts.map +1 -0
  552. package/dist/elements/Toast/Toast.types.d.ts +209 -0
  553. package/dist/elements/Toast/Toast.types.d.ts.map +1 -0
  554. package/dist/elements/Toast/ToastProvider.d.ts +37 -0
  555. package/dist/elements/Toast/ToastProvider.d.ts.map +1 -0
  556. package/dist/elements/Toast/Toaster.d.ts +18 -0
  557. package/dist/elements/Toast/Toaster.d.ts.map +1 -0
  558. package/dist/elements/Toast/index.d.ts +27 -0
  559. package/dist/elements/Toast/index.d.ts.map +1 -0
  560. package/dist/elements/Toast/index.js +60 -0
  561. package/dist/elements/Toast/index.js.map +1 -0
  562. package/dist/elements/Toast/index.mjs +7 -0
  563. package/dist/elements/Toast/index.mjs.map +1 -0
  564. package/dist/elements/Tooltip/Tooltip.d.ts +108 -0
  565. package/dist/elements/Tooltip/Tooltip.d.ts.map +1 -0
  566. package/dist/elements/Tooltip/Tooltip.types.d.ts +135 -0
  567. package/dist/elements/Tooltip/Tooltip.types.d.ts.map +1 -0
  568. package/dist/elements/Tooltip/index.d.ts +11 -0
  569. package/dist/elements/Tooltip/index.d.ts.map +1 -0
  570. package/dist/elements/Tooltip/index.js +59 -0
  571. package/dist/elements/Tooltip/index.js.map +1 -0
  572. package/dist/elements/Tooltip/index.mjs +6 -0
  573. package/dist/elements/Tooltip/index.mjs.map +1 -0
  574. package/dist/elements/index.css +23 -0
  575. package/dist/elements/index.css.map +1 -0
  576. package/dist/elements/index.d.ts +42 -0
  577. package/dist/elements/index.d.ts.map +1 -0
  578. package/dist/elements/index.js +839 -0
  579. package/dist/elements/index.js.map +1 -0
  580. package/dist/elements/index.mjs +42 -0
  581. package/dist/elements/index.mjs.map +1 -0
  582. package/dist/index.css +23 -0
  583. package/dist/index.css.map +1 -0
  584. package/dist/index.d.ts +4 -0
  585. package/dist/index.d.ts.map +1 -0
  586. package/dist/index.js +865 -0
  587. package/dist/index.js.map +1 -0
  588. package/dist/index.mjs +44 -0
  589. package/dist/index.mjs.map +1 -0
  590. package/dist/schemas/BaseComponentProps.d.ts +25 -0
  591. package/dist/schemas/BaseComponentProps.d.ts.map +1 -0
  592. package/dist/schemas/RegistryItem.d.ts +55 -0
  593. package/dist/schemas/RegistryItem.d.ts.map +1 -0
  594. package/dist/schemas/index.d.ts +3 -0
  595. package/dist/schemas/index.d.ts.map +1 -0
  596. package/dist/schemas/index.js +29 -0
  597. package/dist/schemas/index.js.map +1 -0
  598. package/dist/schemas/index.mjs +4 -0
  599. package/dist/schemas/index.mjs.map +1 -0
  600. package/dist/styles/defaults.css +174 -0
  601. package/dist/styles/index.d.ts +7 -0
  602. package/dist/styles/index.d.ts.map +1 -0
  603. package/dist/styles/index.js +153 -0
  604. package/dist/styles/index.js.map +1 -0
  605. package/dist/styles/index.mjs +4 -0
  606. package/dist/styles/index.mjs.map +1 -0
  607. package/dist/styles/interaction-states.d.ts +96 -0
  608. package/dist/styles/interaction-states.d.ts.map +1 -0
  609. package/dist/styles/shared-variants.d.ts +120 -0
  610. package/dist/styles/shared-variants.d.ts.map +1 -0
  611. package/dist/styles/tokens.css +89 -0
  612. package/dist/utils/cn.d.ts +13 -0
  613. package/dist/utils/cn.d.ts.map +1 -0
  614. package/dist/utils/index.d.ts +2 -0
  615. package/dist/utils/index.d.ts.map +1 -0
  616. package/dist/utils/index.js +13 -0
  617. package/dist/utils/index.js.map +1 -0
  618. package/dist/utils/index.mjs +4 -0
  619. package/dist/utils/index.mjs.map +1 -0
  620. package/package.json +228 -0
  621. package/src/elements/Accordion/Accordion.stories.tsx +793 -0
  622. package/src/elements/Avatar/Avatar.stories.tsx +408 -0
  623. package/src/elements/Badge/Badge.stories.tsx +509 -0
  624. package/src/elements/Breadcrumbs/Breadcrumbs.stories.tsx +623 -0
  625. package/src/elements/Button/Button.stories.tsx +670 -0
  626. package/src/elements/ButtonGroup/ButtonGroup.stories.tsx +658 -0
  627. package/src/elements/Card/Card.stories.tsx +570 -0
  628. package/src/elements/Carousel/Carousel.stories.tsx +597 -0
  629. package/src/elements/Chart/Chart.stories.tsx +616 -0
  630. package/src/elements/Checkbox/Checkbox.stories.tsx +514 -0
  631. package/src/elements/CheckboxGroup/CheckboxGroup.stories.tsx +1514 -0
  632. package/src/elements/DatePicker/DatePicker.stories.tsx +341 -0
  633. package/src/elements/Dropdown/Dropdown.stories.tsx +397 -0
  634. package/src/elements/FileField/FileField.stories.tsx +1021 -0
  635. package/src/elements/FileField/FileProgress.stories.tsx +359 -0
  636. package/src/elements/FormLayout/FormLayout.stories.tsx +637 -0
  637. package/src/elements/Modal/Modal.stories.tsx +640 -0
  638. package/src/elements/NumberField/NumberField.stories.tsx +678 -0
  639. package/src/elements/OTPInput/OTPInput.stories.tsx +404 -0
  640. package/src/elements/Panel/Panel.stories.tsx +769 -0
  641. package/src/elements/Progress/Progress.stories.tsx +668 -0
  642. package/src/elements/RadioGroup/RadioGroup.stories.tsx +1153 -0
  643. package/src/elements/Resizable/Resizable.stories.tsx +374 -0
  644. package/src/elements/Select/Select.stories.tsx +362 -0
  645. package/src/elements/Skeleton/Skeleton.stories.tsx +284 -0
  646. package/src/elements/Switch/Switch.stories.tsx +441 -0
  647. package/src/elements/Table/Table.stories.tsx +790 -0
  648. package/src/elements/Tabs/Tabs.stories.tsx +661 -0
  649. package/src/elements/TextField/TextField.stories.tsx +1878 -0
  650. package/src/elements/TimeField/TimeField.stories.tsx +671 -0
  651. package/src/elements/Toast/Toast.stories.tsx +971 -0
  652. package/src/elements/Tooltip/Tooltip.stories.tsx +748 -0
  653. package/tailwind.config.js +10 -0
  654. package/tailwind.config.v3.js +10 -0
@@ -0,0 +1,1878 @@
1
+ /**
2
+ * TextField Component Stories
3
+ * Storybook stories for TextField component demonstrating all variants, sizes, and states
4
+ *
5
+ * @see spec.md FR-009 to FR-014 (Accessibility Requirements - WCAG 2.2 AAA)
6
+ */
7
+
8
+ import type { Meta, StoryObj } from '@storybook/nextjs';
9
+ import { TextField } from './TextField';
10
+
11
+ const meta = {
12
+ title: 'Elements/TextField',
13
+ component: TextField,
14
+ parameters: {
15
+ layout: 'centered',
16
+ docs: {
17
+ description: {
18
+ component:
19
+ 'Accessible text input component with label, description, and error handling. Built with React Aria TextField primitive, CVA variant styling, and WCAG 2.2 AAA compliance (7:1 contrast ratio, proper ARIA attributes).',
20
+ },
21
+ },
22
+ },
23
+ tags: ['autodocs'],
24
+ argTypes: {
25
+ size: {
26
+ control: 'select',
27
+ options: ['sm', 'default', 'lg'],
28
+ description: 'TextField size',
29
+ table: {
30
+ defaultValue: { summary: 'default' },
31
+ },
32
+ },
33
+ label: {
34
+ control: 'text',
35
+ description: 'Label text for the input',
36
+ },
37
+ description: {
38
+ control: 'text',
39
+ description: 'Helper text displayed below the input',
40
+ },
41
+ errorMessage: {
42
+ control: 'text',
43
+ description: 'Error message displayed when isInvalid is true',
44
+ },
45
+ type: {
46
+ control: 'select',
47
+ options: ['text', 'email', 'password', 'tel', 'url', 'search'],
48
+ description: 'HTML input type',
49
+ table: {
50
+ defaultValue: { summary: 'text' },
51
+ },
52
+ },
53
+ isRequired: {
54
+ control: 'boolean',
55
+ description: 'Shows required indicator and sets aria-required',
56
+ table: {
57
+ defaultValue: { summary: 'false' },
58
+ },
59
+ },
60
+ isReadOnly: {
61
+ control: 'boolean',
62
+ description: 'Makes input read-only',
63
+ table: {
64
+ defaultValue: { summary: 'false' },
65
+ },
66
+ },
67
+ isDisabled: {
68
+ control: 'boolean',
69
+ description: 'Disables the input',
70
+ table: {
71
+ defaultValue: { summary: 'false' },
72
+ },
73
+ },
74
+ isInvalid: {
75
+ control: 'boolean',
76
+ description: 'Shows error styling and displays error message',
77
+ table: {
78
+ defaultValue: { summary: 'false' },
79
+ },
80
+ },
81
+ placeholder: {
82
+ control: 'text',
83
+ description: 'Placeholder text for the input',
84
+ },
85
+ },
86
+ } satisfies Meta<typeof TextField>;
87
+
88
+ export default meta;
89
+ type Story = StoryObj<typeof meta>;
90
+
91
+ // Basic stories
92
+ export const Default: Story = {
93
+ args: {
94
+ label: 'Username',
95
+ placeholder: 'Enter your username',
96
+ },
97
+ };
98
+
99
+ export const WithDescription: Story = {
100
+ args: {
101
+ label: 'Email',
102
+ description: "We'll never share your email with anyone.",
103
+ placeholder: 'you@example.com',
104
+ type: 'email',
105
+ },
106
+ };
107
+
108
+ export const WithError: Story = {
109
+ args: {
110
+ label: 'Username',
111
+ errorMessage: 'Username is required',
112
+ isInvalid: true,
113
+ },
114
+ parameters: {
115
+ docs: {
116
+ description: {
117
+ story: 'Error state with validation message. Description text is hidden when error is shown.',
118
+ },
119
+ },
120
+ },
121
+ };
122
+
123
+ export const Required: Story = {
124
+ args: {
125
+ label: 'Email',
126
+ description: 'This field is required',
127
+ isRequired: true,
128
+ type: 'email',
129
+ },
130
+ parameters: {
131
+ docs: {
132
+ description: {
133
+ story: 'Required field with visual indicator (*) and aria-required attribute.',
134
+ },
135
+ },
136
+ },
137
+ };
138
+
139
+ export const Disabled: Story = {
140
+ args: {
141
+ label: 'Username',
142
+ value: 'john.doe',
143
+ isDisabled: true,
144
+ },
145
+ };
146
+
147
+ export const ReadOnly: Story = {
148
+ args: {
149
+ label: 'Username',
150
+ value: 'john.doe',
151
+ isReadOnly: true,
152
+ description: 'This field cannot be edited',
153
+ },
154
+ };
155
+
156
+ export const WithoutLabel: Story = {
157
+ args: {
158
+ placeholder: 'Search...',
159
+ type: 'search',
160
+ 'aria-label': 'Search',
161
+ },
162
+ parameters: {
163
+ docs: {
164
+ description: {
165
+ story: 'TextField without visible label. aria-label is required for accessibility.',
166
+ },
167
+ },
168
+ },
169
+ };
170
+
171
+ // Size variants
172
+ export const Small: Story = {
173
+ args: {
174
+ label: 'Username',
175
+ size: 'sm',
176
+ placeholder: 'Small input',
177
+ },
178
+ };
179
+
180
+ export const Large: Story = {
181
+ args: {
182
+ label: 'Username',
183
+ size: 'lg',
184
+ placeholder: 'Large input',
185
+ },
186
+ };
187
+
188
+ export const AllSizes: Story = {
189
+ render: () => (
190
+ <div className="flex flex-col gap-6 w-80">
191
+ <TextField label="Small" size="sm" placeholder="Small input" />
192
+ <TextField label="Default" size="default" placeholder="Default input" />
193
+ <TextField label="Large" size="lg" placeholder="Large input" />
194
+ </div>
195
+ ),
196
+ parameters: {
197
+ docs: {
198
+ description: {
199
+ story: 'All 3 size variants: sm (h-9), default (h-10), lg (h-11).',
200
+ },
201
+ },
202
+ },
203
+ };
204
+
205
+ // Input type variants
206
+ export const TextType: Story = {
207
+ args: {
208
+ label: 'Full Name',
209
+ type: 'text',
210
+ placeholder: 'John Doe',
211
+ },
212
+ };
213
+
214
+ export const EmailType: Story = {
215
+ args: {
216
+ label: 'Email Address',
217
+ type: 'email',
218
+ placeholder: 'you@example.com',
219
+ description: 'We respect your privacy',
220
+ },
221
+ };
222
+
223
+ export const PasswordType: Story = {
224
+ args: {
225
+ label: 'Password',
226
+ type: 'password',
227
+ placeholder: 'Enter your password',
228
+ description: 'At least 8 characters',
229
+ },
230
+ };
231
+
232
+ // NOTE: TelType removed (breaking change) - use TelField component instead
233
+
234
+ export const UrlType: Story = {
235
+ args: {
236
+ label: 'Website',
237
+ type: 'url',
238
+ placeholder: 'https://example.com',
239
+ },
240
+ };
241
+
242
+ export const SearchType: Story = {
243
+ args: {
244
+ label: 'Search',
245
+ type: 'search',
246
+ placeholder: 'Search...',
247
+ },
248
+ };
249
+
250
+ // AutoComplete Examples (Phase 2)
251
+ export const AutoCompleteEmail: Story = {
252
+ args: {
253
+ label: 'Email Address',
254
+ type: 'email',
255
+ autoComplete: 'email',
256
+ placeholder: 'you@example.com',
257
+ description: 'Browser will suggest previously entered emails',
258
+ },
259
+ };
260
+
261
+ export const AutoCompleteName: Story = {
262
+ args: {
263
+ label: 'Full Name',
264
+ type: 'text',
265
+ autoComplete: 'name',
266
+ placeholder: 'John Doe',
267
+ description: 'Browser will suggest your name from previous entries',
268
+ },
269
+ };
270
+
271
+ export const AutoCompleteCurrentPassword: Story = {
272
+ args: {
273
+ label: 'Password',
274
+ type: 'password',
275
+ autoComplete: 'current-password',
276
+ placeholder: 'Enter your password',
277
+ description: 'Password manager will offer to fill this field',
278
+ },
279
+ };
280
+
281
+ export const AutoCompleteNewPassword: Story = {
282
+ args: {
283
+ label: 'New Password',
284
+ type: 'password',
285
+ autoComplete: 'new-password',
286
+ placeholder: 'Create a strong password',
287
+ description: 'Password manager will offer to generate and save',
288
+ },
289
+ };
290
+
291
+ export const AutoCompleteAddressLine1: Story = {
292
+ args: {
293
+ label: 'Street Address',
294
+ type: 'text',
295
+ autoComplete: 'address-line1',
296
+ placeholder: '123 Main St',
297
+ description: 'Browser will suggest street address',
298
+ },
299
+ };
300
+
301
+ export const AutoCompleteCreditCard: Story = {
302
+ args: {
303
+ label: 'Card Number',
304
+ type: 'text',
305
+ autoComplete: 'cc-number',
306
+ placeholder: '1234 5678 9012 3456',
307
+ description: 'Browser may offer saved card numbers',
308
+ },
309
+ };
310
+
311
+ export const AutoCompleteOff: Story = {
312
+ args: {
313
+ label: 'One-Time Code',
314
+ type: 'text',
315
+ autoComplete: 'off',
316
+ placeholder: 'Enter code',
317
+ description: 'Browser autocomplete disabled for security',
318
+ },
319
+ };
320
+
321
+ export const LoginFormWithAutoComplete: Story = {
322
+ render: () => (
323
+ <div className="space-y-4 max-w-sm">
324
+ <h3 className="text-lg font-semibold">Login Form with AutoComplete</h3>
325
+ <TextField
326
+ label="Email"
327
+ type="email"
328
+ autoComplete="email"
329
+ placeholder="you@example.com"
330
+ isRequired
331
+ />
332
+ <TextField
333
+ label="Password"
334
+ type="password"
335
+ autoComplete="current-password"
336
+ placeholder="Enter your password"
337
+ isRequired
338
+ />
339
+ <p className="text-sm text-muted-foreground">
340
+ Browser will remember and suggest your credentials
341
+ </p>
342
+ </div>
343
+ ),
344
+ };
345
+
346
+ export const SignupFormWithAutoComplete: Story = {
347
+ render: () => (
348
+ <div className="space-y-4 max-w-sm">
349
+ <h3 className="text-lg font-semibold">Signup Form with AutoComplete</h3>
350
+ <TextField
351
+ label="Full Name"
352
+ type="text"
353
+ autoComplete="name"
354
+ placeholder="John Doe"
355
+ isRequired
356
+ />
357
+ <TextField
358
+ label="Email"
359
+ type="email"
360
+ autoComplete="email"
361
+ placeholder="you@example.com"
362
+ isRequired
363
+ />
364
+ <TextField
365
+ label="Create Password"
366
+ type="password"
367
+ autoComplete="new-password"
368
+ placeholder="Create a strong password"
369
+ description="Password manager will offer to generate and save"
370
+ isRequired
371
+ />
372
+ </div>
373
+ ),
374
+ };
375
+
376
+ export const AddressFormWithAutoComplete: Story = {
377
+ render: () => (
378
+ <div className="space-y-4 max-w-sm">
379
+ <h3 className="text-lg font-semibold">Address Form with AutoComplete</h3>
380
+ <TextField
381
+ label="Street Address"
382
+ type="text"
383
+ autoComplete="address-line1"
384
+ placeholder="123 Main St"
385
+ isRequired
386
+ />
387
+ <TextField
388
+ label="Apartment/Suite"
389
+ type="text"
390
+ autoComplete="address-line2"
391
+ placeholder="Apt 4B"
392
+ />
393
+ <TextField
394
+ label="City"
395
+ type="text"
396
+ autoComplete="address-level2"
397
+ placeholder="New York"
398
+ isRequired
399
+ />
400
+ <TextField
401
+ label="Postal Code"
402
+ type="text"
403
+ autoComplete="postal-code"
404
+ placeholder="10001"
405
+ isRequired
406
+ />
407
+ <p className="text-sm text-muted-foreground">
408
+ Browser will suggest your saved address details
409
+ </p>
410
+ </div>
411
+ ),
412
+ };
413
+
414
+ // Copy/Paste Restriction Examples (Phase 3)
415
+ export const PasswordConfirmationNoPaste: Story = {
416
+ args: {
417
+ label: 'Confirm Password',
418
+ type: 'password',
419
+ disableCopyPaste: true,
420
+ description: 'Please type your password again (pasting is not allowed)',
421
+ isRequired: true,
422
+ },
423
+ };
424
+
425
+ export const EmailConfirmationNoPaste: Story = {
426
+ args: {
427
+ label: 'Confirm Email',
428
+ type: 'email',
429
+ disableCopyPaste: true,
430
+ description: 'Please type your email again to confirm',
431
+ isRequired: true,
432
+ },
433
+ };
434
+
435
+ export const SecureFieldWithShakeDemo: Story = {
436
+ args: {
437
+ label: 'One-Time Code',
438
+ type: 'text',
439
+ disableCopyPaste: true,
440
+ description: 'Try to paste - the field will shake to indicate pasting is not allowed',
441
+ placeholder: 'Enter code manually',
442
+ },
443
+ };
444
+
445
+ export const CopyPastePasswordConfirmation: Story = {
446
+ render: () => (
447
+ <div className="space-y-4 max-w-sm">
448
+ <h3 className="text-lg font-semibold">Password Confirmation Example</h3>
449
+ <TextField
450
+ label="New Password"
451
+ type="password"
452
+ autoComplete="new-password"
453
+ placeholder="Create password"
454
+ description="Create a strong password"
455
+ isRequired
456
+ />
457
+ <TextField
458
+ label="Confirm Password"
459
+ type="password"
460
+ disableCopyPaste={true}
461
+ placeholder="Type password again"
462
+ description="Please type your password again (pasting is not allowed for security)"
463
+ isRequired
464
+ />
465
+ <p className="text-sm text-muted-foreground">
466
+ The confirmation field prevents pasting to ensure you typed the password correctly.
467
+ If you try to paste, the field will shake and announce the restriction to screen readers.
468
+ </p>
469
+ </div>
470
+ ),
471
+ };
472
+
473
+ export const EmailConfirmationForm: Story = {
474
+ render: () => (
475
+ <div className="space-y-4 max-w-sm">
476
+ <h3 className="text-lg font-semibold">Email Confirmation Example</h3>
477
+ <TextField
478
+ label="Email Address"
479
+ type="email"
480
+ autoComplete="email"
481
+ placeholder="you@example.com"
482
+ isRequired
483
+ />
484
+ <TextField
485
+ label="Confirm Email"
486
+ type="email"
487
+ disableCopyPaste={true}
488
+ placeholder="Type email again"
489
+ description="Re-enter your email address to confirm"
490
+ isRequired
491
+ />
492
+ <p className="text-sm text-muted-foreground">
493
+ Pasting is disabled in the confirmation field to prevent accidental errors.
494
+ </p>
495
+ </div>
496
+ ),
497
+ };
498
+
499
+ // Pattern Validation Examples (Phase 4)
500
+ export const USZipCodePattern: Story = {
501
+ args: {
502
+ label: 'ZIP Code',
503
+ type: 'text',
504
+ pattern: String.raw`\d{5}`,
505
+ patternDescription: '5-digit ZIP code (e.g., 12345)',
506
+ placeholder: '12345',
507
+ isRequired: true,
508
+ },
509
+ };
510
+
511
+ export const UsernamePattern: Story = {
512
+ args: {
513
+ label: 'Username',
514
+ type: 'text',
515
+ pattern: '[a-zA-Z0-9_]{3,16}',
516
+ patternDescription: '3-16 characters: letters, numbers, or underscores',
517
+ placeholder: 'john_doe123',
518
+ isRequired: true,
519
+ },
520
+ };
521
+
522
+ export const HexColorPattern: Story = {
523
+ args: {
524
+ label: 'Brand Color',
525
+ type: 'text',
526
+ pattern: '^#[0-9A-Fa-f]{6}$',
527
+ patternDescription: 'Hex color code (e.g., #FF5733)',
528
+ placeholder: '#FF5733',
529
+ defaultValue: '#',
530
+ },
531
+ };
532
+
533
+ export const PhoneNumberPattern: Story = {
534
+ args: {
535
+ label: 'Phone Number',
536
+ type: 'text',
537
+ pattern: String.raw`\d{3}-\d{3}-\d{4}`,
538
+ patternDescription: 'Format: 123-456-7890',
539
+ placeholder: '123-456-7890',
540
+ isRequired: true,
541
+ },
542
+ };
543
+
544
+ export const CanadianPostalCodePattern: Story = {
545
+ args: {
546
+ label: 'Postal Code',
547
+ type: 'text',
548
+ pattern: '[A-Z]\\d[A-Z] \\d[A-Z]\\d',
549
+ patternDescription: 'Format: A1A 1A1 (uppercase letters and digits)',
550
+ placeholder: 'K1A 0B1',
551
+ isRequired: true,
552
+ },
553
+ };
554
+
555
+ export const SlugPattern: Story = {
556
+ args: {
557
+ label: 'URL Slug',
558
+ type: 'text',
559
+ pattern: '^[a-z0-9]+(?:-[a-z0-9]+)*$',
560
+ patternDescription: 'Lowercase letters, numbers, and hyphens (e.g., my-blog-post)',
561
+ placeholder: 'my-article-title',
562
+ description: 'This will be used in your article URL',
563
+ },
564
+ };
565
+
566
+ export const CreditCardPattern: Story = {
567
+ args: {
568
+ label: 'Card Number',
569
+ type: 'text',
570
+ pattern: String.raw`\d{4} \d{4} \d{4} \d{4}`,
571
+ patternDescription: '16 digits in groups of 4 (e.g., 1234 5678 9012 3456)',
572
+ placeholder: '1234 5678 9012 3456',
573
+ autoComplete: 'cc-number',
574
+ isRequired: true,
575
+ },
576
+ };
577
+
578
+ export const PatternValidationForm: Story = {
579
+ render: () => (
580
+ <div className="space-y-4 max-w-md">
581
+ <h3 className="text-lg font-semibold">Registration Form with Pattern Validation</h3>
582
+ <TextField
583
+ label="Username"
584
+ pattern="[a-z0-9_]{3,16}"
585
+ patternDescription="3-16 lowercase letters, numbers, or underscores"
586
+ placeholder="john_doe"
587
+ description="Choose a unique username"
588
+ isRequired
589
+ />
590
+ <TextField
591
+ label="Phone Number"
592
+ pattern={String.raw`\(\d{3}\) \d{3}-\d{4}`}
593
+ patternDescription="Format: (555) 123-4567"
594
+ placeholder="(555) 123-4567"
595
+ autoComplete="tel"
596
+ isRequired
597
+ />
598
+ <TextField
599
+ label="Website"
600
+ type="url"
601
+ pattern="https?://.+"
602
+ patternDescription="Must start with http:// or https://"
603
+ placeholder="https://example.com"
604
+ autoComplete="url"
605
+ />
606
+ <TextField
607
+ label="Promo Code"
608
+ pattern="[A-Z]{4}\\d{4}"
609
+ patternDescription="4 uppercase letters followed by 4 digits (e.g., SAVE2024)"
610
+ placeholder="SAVE2024"
611
+ />
612
+ <p className="text-sm text-muted-foreground">
613
+ All fields use HTML5 pattern validation. Invalid entries will be highlighted when you submit or move to the next field.
614
+ </p>
615
+ </div>
616
+ ),
617
+ };
618
+
619
+ // Success Validation Examples (Phase 5)
620
+ export const SuccessfulEmailValidation: Story = {
621
+ args: {
622
+ label: 'Email Address',
623
+ type: 'email',
624
+ isValid: true,
625
+ successMessage: 'Email is available!',
626
+ defaultValue: 'john@example.com',
627
+ },
628
+ };
629
+
630
+ export const SuccessfulUsernameCheck: Story = {
631
+ args: {
632
+ label: 'Username',
633
+ type: 'text',
634
+ pattern: '[a-z0-9_]{3,16}',
635
+ patternDescription: '3-16 lowercase letters, numbers, or underscores',
636
+ isValid: true,
637
+ successMessage: 'Username is available!',
638
+ defaultValue: 'john_doe',
639
+ },
640
+ };
641
+
642
+ export const SuccessfulPasswordStrength: Story = {
643
+ args: {
644
+ label: 'Password',
645
+ type: 'password',
646
+ isValid: true,
647
+ successMessage: 'Strong password!',
648
+ description: 'Use at least 8 characters with letters, numbers, and symbols',
649
+ },
650
+ };
651
+
652
+ export const SuccessfulZipCodeValidation: Story = {
653
+ args: {
654
+ label: 'ZIP Code',
655
+ pattern: String.raw`\d{5}`,
656
+ patternDescription: '5-digit ZIP code',
657
+ isValid: true,
658
+ successMessage: 'Valid ZIP code',
659
+ defaultValue: '94102',
660
+ },
661
+ };
662
+
663
+ export const SuccessWithoutMessage: Story = {
664
+ args: {
665
+ label: 'Email',
666
+ type: 'email',
667
+ isValid: true,
668
+ defaultValue: 'verified@example.com',
669
+ description: 'This field is validated',
670
+ },
671
+ };
672
+
673
+ export const RegistrationFormWithValidation: Story = {
674
+ render: () => (
675
+ <div className="space-y-4 max-w-md">
676
+ <h3 className="text-lg font-semibold">Registration Form with Success States</h3>
677
+ <TextField
678
+ label="Username"
679
+ pattern="[a-z0-9_]{3,16}"
680
+ patternDescription="3-16 lowercase letters, numbers, or underscores"
681
+ isValid={true}
682
+ successMessage="Username is available!"
683
+ defaultValue="john_doe"
684
+ isRequired
685
+ />
686
+ <TextField
687
+ label="Email Address"
688
+ type="email"
689
+ isValid={true}
690
+ successMessage="Email verified!"
691
+ defaultValue="john@example.com"
692
+ autoComplete="email"
693
+ isRequired
694
+ />
695
+ <TextField
696
+ label="Password"
697
+ type="password"
698
+ isValid={true}
699
+ successMessage="Strong password!"
700
+ autoComplete="new-password"
701
+ isRequired
702
+ />
703
+ <TextField
704
+ label="Referral Code"
705
+ pattern="[A-Z]{4}\\d{4}"
706
+ patternDescription="4 letters + 4 digits (e.g., SAVE2024)"
707
+ placeholder="SAVE2024"
708
+ />
709
+ <p className="text-sm text-muted-foreground">
710
+ Fields with green borders and checkmarks indicate successful validation.
711
+ </p>
712
+ </div>
713
+ ),
714
+ };
715
+
716
+ // Expand on Focus Examples (Phase 6)
717
+ export const SearchFieldExpandOnFocus: Story = {
718
+ args: {
719
+ label: 'Search',
720
+ type: 'search',
721
+ expandOnFocus: true,
722
+ collapsedWidth: '150px',
723
+ placeholder: 'Search...',
724
+ },
725
+ };
726
+
727
+ export const CompactEmailField: Story = {
728
+ args: {
729
+ label: 'Email',
730
+ type: 'email',
731
+ expandOnFocus: true,
732
+ collapsedWidth: '200px',
733
+ placeholder: 'you@example.com',
734
+ autoComplete: 'email',
735
+ },
736
+ };
737
+
738
+ export const CustomCollapsedWidth: Story = {
739
+ args: {
740
+ label: 'Username',
741
+ expandOnFocus: true,
742
+ collapsedWidth: '120px',
743
+ placeholder: 'Enter username',
744
+ },
745
+ };
746
+
747
+ export const ExpandWithDefaultValue: Story = {
748
+ args: {
749
+ label: 'Search Query',
750
+ type: 'search',
751
+ expandOnFocus: true,
752
+ collapsedWidth: '150px',
753
+ defaultValue: 'React components',
754
+ description: 'Field stays expanded when it has a value',
755
+ },
756
+ };
757
+
758
+ export const MultipleExpandableFields: Story = {
759
+ render: () => (
760
+ <div className="space-y-4 max-w-md">
761
+ <h3 className="text-lg font-semibold">Compact Form with Expand on Focus</h3>
762
+ <div className="flex gap-2">
763
+ <TextField
764
+ label="First Name"
765
+ expandOnFocus={true}
766
+ collapsedWidth="100px"
767
+ placeholder="John"
768
+ />
769
+ <TextField
770
+ label="Last Name"
771
+ expandOnFocus={true}
772
+ collapsedWidth="100px"
773
+ placeholder="Doe"
774
+ />
775
+ </div>
776
+ <TextField
777
+ label="Email Address"
778
+ type="email"
779
+ expandOnFocus={true}
780
+ collapsedWidth="150px"
781
+ placeholder="john@example.com"
782
+ autoComplete="email"
783
+ />
784
+ <TextField
785
+ label="Search"
786
+ type="search"
787
+ expandOnFocus={true}
788
+ collapsedWidth="120px"
789
+ placeholder="Search..."
790
+ />
791
+ <p className="text-sm text-muted-foreground">
792
+ Click on any field to see it smoothly expand. Fields collapse when you leave them empty.
793
+ </p>
794
+ </div>
795
+ ),
796
+ };
797
+
798
+ // State combinations
799
+ export const RequiredWithDescription: Story = {
800
+ args: {
801
+ label: 'Email',
802
+ description: 'Required field - please provide your email address',
803
+ isRequired: true,
804
+ type: 'email',
805
+ placeholder: 'you@example.com',
806
+ },
807
+ };
808
+
809
+ export const ErrorWithDescription: Story = {
810
+ args: {
811
+ label: 'Password',
812
+ description: 'At least 8 characters, one uppercase, one number',
813
+ errorMessage: 'Password must contain at least one uppercase letter',
814
+ isInvalid: true,
815
+ type: 'password',
816
+ },
817
+ parameters: {
818
+ docs: {
819
+ description: {
820
+ story: 'When both description and error are provided, error takes precedence.',
821
+ },
822
+ },
823
+ },
824
+ };
825
+
826
+ export const RequiredAndInvalid: Story = {
827
+ args: {
828
+ label: 'Email',
829
+ errorMessage: 'Email is required',
830
+ isRequired: true,
831
+ isInvalid: true,
832
+ type: 'email',
833
+ },
834
+ };
835
+
836
+ export const AllStates: Story = {
837
+ render: () => (
838
+ <div className="flex flex-col gap-6 w-80">
839
+ <TextField label="Default" placeholder="Default state" />
840
+ <TextField label="Required" isRequired description="This field is required" />
841
+ <TextField
842
+ label="Invalid"
843
+ errorMessage="This field is invalid"
844
+ isInvalid
845
+ />
846
+ <TextField label="Disabled" isDisabled value="Disabled value" />
847
+ <TextField label="Read-only" isReadOnly value="Read-only value" />
848
+ </div>
849
+ ),
850
+ parameters: {
851
+ docs: {
852
+ description: {
853
+ story: 'All state variants in one view.',
854
+ },
855
+ },
856
+ },
857
+ };
858
+
859
+ // Theme integration stories
860
+ export const LightTheme: Story = {
861
+ args: {
862
+ label: 'Username',
863
+ description: 'Light theme styling',
864
+ placeholder: 'Enter username',
865
+ },
866
+ parameters: {
867
+ backgrounds: { default: 'light' },
868
+ },
869
+ };
870
+
871
+ export const DarkTheme: Story = {
872
+ args: {
873
+ label: 'Username',
874
+ description: 'Dark theme styling with Themis semantic tokens',
875
+ placeholder: 'Enter username',
876
+ },
877
+ parameters: {
878
+ backgrounds: { default: 'dark' },
879
+ docs: {
880
+ description: {
881
+ story: 'TextField adapts to dark theme via semantic tokens.',
882
+ },
883
+ },
884
+ },
885
+ };
886
+
887
+ export const HighContrast: Story = {
888
+ args: {
889
+ label: 'Username',
890
+ description: 'Enhanced contrast for accessibility',
891
+ placeholder: 'Enter username',
892
+ },
893
+ parameters: {
894
+ docs: {
895
+ description: {
896
+ story: 'TextField with enhanced contrast for high contrast mode (WCAG 2.2 AAA).',
897
+ },
898
+ },
899
+ },
900
+ };
901
+
902
+ export const ColorblindTheme: Story = {
903
+ args: {
904
+ label: 'Email',
905
+ errorMessage: 'Invalid email format',
906
+ isInvalid: true,
907
+ },
908
+ parameters: {
909
+ docs: {
910
+ description: {
911
+ story:
912
+ 'Error styling visible in colorblind mode (deuteranopia, protanopia, tritanopia support).',
913
+ },
914
+ },
915
+ },
916
+ };
917
+
918
+ // Real-world examples
919
+ export const RealWorldLoginForm: Story = {
920
+ render: () => (
921
+ <form
922
+ className="flex flex-col gap-4 w-80"
923
+ onSubmit={(e) => {
924
+ e.preventDefault();
925
+ alert('Login submitted!');
926
+ }}
927
+ >
928
+ <TextField
929
+ label="Email"
930
+ type="email"
931
+ placeholder="you@example.com"
932
+ isRequired
933
+ description="We'll never share your email"
934
+ />
935
+ <TextField
936
+ label="Password"
937
+ type="password"
938
+ placeholder="Enter your password"
939
+ isRequired
940
+ description="At least 8 characters"
941
+ />
942
+ <button
943
+ type="submit"
944
+ className="mt-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground"
945
+ >
946
+ Sign In
947
+ </button>
948
+ </form>
949
+ ),
950
+ parameters: {
951
+ docs: {
952
+ description: {
953
+ story: 'Complete login form with email and password fields.',
954
+ },
955
+ },
956
+ },
957
+ };
958
+
959
+ export const ContactForm: Story = {
960
+ render: () => (
961
+ <form
962
+ className="flex flex-col gap-4 w-80"
963
+ onSubmit={(e) => {
964
+ e.preventDefault();
965
+ alert('Contact form submitted!');
966
+ }}
967
+ >
968
+ <TextField label="Name" isRequired placeholder="John Doe" />
969
+ <TextField
970
+ label="Email"
971
+ type="email"
972
+ isRequired
973
+ placeholder="you@example.com"
974
+ />
975
+ <TextField
976
+ label="Website"
977
+ type="url"
978
+ placeholder="https://example.com"
979
+ description="Optional"
980
+ />
981
+ <button
982
+ type="submit"
983
+ className="mt-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground"
984
+ >
985
+ Submit
986
+ </button>
987
+ </form>
988
+ ),
989
+ parameters: {
990
+ docs: {
991
+ description: {
992
+ story: 'Contact form with multiple field types and validation.',
993
+ },
994
+ },
995
+ },
996
+ };
997
+
998
+ export const ValidationExample: Story = {
999
+ render: () => {
1000
+ const [email, setEmail] = useState('');
1001
+ const [isInvalid, setIsInvalid] = useState(false);
1002
+
1003
+ const validateEmail = (value: string) => {
1004
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1005
+ setIsInvalid(!emailRegex.test(value) && value.length > 0);
1006
+ };
1007
+
1008
+ return (
1009
+ <div className="w-80">
1010
+ <TextField
1011
+ label="Email"
1012
+ type="email"
1013
+ value={email}
1014
+ onChange={(value) => {
1015
+ setEmail(value);
1016
+ validateEmail(value);
1017
+ }}
1018
+ isInvalid={isInvalid}
1019
+ errorMessage="Please enter a valid email address"
1020
+ description="We'll send you a confirmation email"
1021
+ isRequired
1022
+ />
1023
+ </div>
1024
+ );
1025
+ },
1026
+ parameters: {
1027
+ docs: {
1028
+ description: {
1029
+ story: 'Live validation example with controlled component pattern.',
1030
+ },
1031
+ },
1032
+ },
1033
+ };
1034
+
1035
+ export const MultiFieldForm: Story = {
1036
+ render: () => (
1037
+ <div className="flex flex-col gap-6 w-96">
1038
+ <div className="grid grid-cols-2 gap-4">
1039
+ <TextField label="First Name" isRequired placeholder="John" />
1040
+ <TextField label="Last Name" isRequired placeholder="Doe" />
1041
+ </div>
1042
+ <TextField
1043
+ label="Email"
1044
+ type="email"
1045
+ isRequired
1046
+ placeholder="you@example.com"
1047
+ />
1048
+ <TextField
1049
+ label="Company"
1050
+ placeholder="Acme Inc."
1051
+ description="Optional"
1052
+ />
1053
+ <div className="grid grid-cols-2 gap-4">
1054
+ <TextField label="City" placeholder="New York" />
1055
+ <TextField label="ZIP Code" placeholder="10001" />
1056
+ </div>
1057
+ </div>
1058
+ ),
1059
+ parameters: {
1060
+ docs: {
1061
+ description: {
1062
+ story: 'Multi-field form layout with grid positioning.',
1063
+ },
1064
+ },
1065
+ },
1066
+ };
1067
+
1068
+ // Accessibility stories
1069
+ export const FocusVisible: Story = {
1070
+ args: {
1071
+ label: 'Focus Me',
1072
+ placeholder: 'Tab to see focus ring',
1073
+ },
1074
+ parameters: {
1075
+ docs: {
1076
+ description: {
1077
+ story:
1078
+ 'Press Tab to see the focus ring. Meets WCAG 2.2 AAA standards with visible focus indicator.',
1079
+ },
1080
+ },
1081
+ },
1082
+ };
1083
+
1084
+ export const KeyboardNavigation: Story = {
1085
+ render: () => (
1086
+ <div className="flex flex-col gap-4 w-80">
1087
+ <TextField label="First Field" placeholder="Tab to next" />
1088
+ <TextField label="Second Field" placeholder="Tab to next" />
1089
+ <TextField label="Third Field" placeholder="Tab to next" />
1090
+ <TextField label="Disabled Field" isDisabled placeholder="Skipped" />
1091
+ <TextField label="Fourth Field" placeholder="Last field" />
1092
+ </div>
1093
+ ),
1094
+ parameters: {
1095
+ docs: {
1096
+ description: {
1097
+ story:
1098
+ 'Use Tab/Shift+Tab to navigate. Disabled fields are skipped automatically.',
1099
+ },
1100
+ },
1101
+ },
1102
+ };
1103
+
1104
+ export const ScreenReaderSupport: Story = {
1105
+ args: {
1106
+ label: 'Email Address',
1107
+ description: 'This description is announced by screen readers',
1108
+ isRequired: true,
1109
+ type: 'email',
1110
+ },
1111
+ parameters: {
1112
+ docs: {
1113
+ description: {
1114
+ story:
1115
+ 'All TextField elements are properly linked via ARIA: label, description (aria-describedby), error (aria-errormessage), required (aria-required).',
1116
+ },
1117
+ },
1118
+ },
1119
+ };
1120
+
1121
+ /**
1122
+ * Phase 8: Prefix/Suffix Feature Stories
1123
+ * Demonstrates prefix and suffix for currency, units, and icons
1124
+ */
1125
+
1126
+ // Currency prefix
1127
+ export const CurrencyInput: Story = {
1128
+ args: {
1129
+ label: 'Price',
1130
+ prefix: '$',
1131
+ type: 'text',
1132
+ placeholder: '0.00',
1133
+ description: 'Enter the price in USD',
1134
+ },
1135
+ parameters: {
1136
+ docs: {
1137
+ description: {
1138
+ story: 'Use prefix for currency symbols. The input automatically adds padding to accommodate the prefix.',
1139
+ },
1140
+ },
1141
+ },
1142
+ };
1143
+
1144
+ // Unit suffix
1145
+ export const UnitInput: Story = {
1146
+ args: {
1147
+ label: 'Weight',
1148
+ suffix: 'kg',
1149
+ type: 'text',
1150
+ placeholder: '0',
1151
+ description: 'Enter the weight in kilograms',
1152
+ },
1153
+ parameters: {
1154
+ docs: {
1155
+ description: {
1156
+ story: 'Use suffix for units of measurement. The input automatically adds padding to accommodate the suffix.',
1157
+ },
1158
+ },
1159
+ },
1160
+ };
1161
+
1162
+ // Both prefix and suffix
1163
+ export const PrefixAndSuffix: Story = {
1164
+ args: {
1165
+ label: 'Amount',
1166
+ prefix: '$',
1167
+ suffix: 'USD',
1168
+ type: 'text',
1169
+ placeholder: '0.00',
1170
+ description: 'Enter the amount with currency code',
1171
+ },
1172
+ parameters: {
1173
+ docs: {
1174
+ description: {
1175
+ story: 'Combine prefix and suffix for complex input formats like currency with codes.',
1176
+ },
1177
+ },
1178
+ },
1179
+ };
1180
+
1181
+ // Icon prefix (search)
1182
+ export const IconPrefix: Story = {
1183
+ render: () => {
1184
+ const SearchIcon = () => (
1185
+ <svg
1186
+ width="16"
1187
+ height="16"
1188
+ viewBox="0 0 16 16"
1189
+ fill="none"
1190
+ stroke="currentColor"
1191
+ strokeWidth="2"
1192
+ strokeLinecap="round"
1193
+ strokeLinejoin="round"
1194
+ >
1195
+ <circle cx="7" cy="7" r="5" />
1196
+ <path d="M11 11l3 3" />
1197
+ </svg>
1198
+ );
1199
+
1200
+ return (
1201
+ <TextField
1202
+ label="Search"
1203
+ prefix={<SearchIcon />}
1204
+ prefixSize={16}
1205
+ type="search"
1206
+ placeholder="Search..."
1207
+ />
1208
+ );
1209
+ },
1210
+ parameters: {
1211
+ docs: {
1212
+ description: {
1213
+ story: 'Use ReactNode (like SVG icons) as prefix. Set prefixSize to control icon dimensions.',
1214
+ },
1215
+ },
1216
+ },
1217
+ };
1218
+
1219
+ // Icon suffix (status indicator)
1220
+ export const IconSuffix: Story = {
1221
+ render: () => {
1222
+ const CheckIcon = () => (
1223
+ <svg
1224
+ width="16"
1225
+ height="16"
1226
+ viewBox="0 0 16 16"
1227
+ fill="none"
1228
+ stroke="currentColor"
1229
+ strokeWidth="2"
1230
+ strokeLinecap="round"
1231
+ strokeLinejoin="round"
1232
+ >
1233
+ <path d="M13 4L6 11L3 8" />
1234
+ </svg>
1235
+ );
1236
+
1237
+ return (
1238
+ <TextField
1239
+ label="Username"
1240
+ suffix={<CheckIcon />}
1241
+ suffixSize={16}
1242
+ type="text"
1243
+ placeholder="username"
1244
+ isValid={true}
1245
+ successMessage="Username is available"
1246
+ />
1247
+ );
1248
+ },
1249
+ parameters: {
1250
+ docs: {
1251
+ description: {
1252
+ story: 'Use ReactNode (like SVG icons) as suffix for status indicators or actions.',
1253
+ },
1254
+ },
1255
+ },
1256
+ };
1257
+
1258
+ // Multiple fields with prefixes/suffixes
1259
+ export const FormWithPrefixSuffix: Story = {
1260
+ render: () => (
1261
+ <div className="space-y-4 max-w-md">
1262
+ <h3 className="text-lg font-semibold">Product Details Form</h3>
1263
+ <TextField
1264
+ label="Product Name"
1265
+ type="text"
1266
+ placeholder="Enter product name"
1267
+ isRequired={true}
1268
+ />
1269
+ <TextField
1270
+ label="Price"
1271
+ prefix="$"
1272
+ suffix="USD"
1273
+ type="text"
1274
+ placeholder="0.00"
1275
+ description="Retail price in US dollars"
1276
+ />
1277
+ <TextField
1278
+ label="Weight"
1279
+ suffix="kg"
1280
+ type="text"
1281
+ placeholder="0.0"
1282
+ description="Shipping weight"
1283
+ />
1284
+ <TextField
1285
+ label="Discount"
1286
+ suffix="%"
1287
+ type="text"
1288
+ placeholder="0"
1289
+ description="Percentage discount (0-100)"
1290
+ />
1291
+ <TextField
1292
+ label="SKU"
1293
+ prefix="#"
1294
+ type="text"
1295
+ placeholder="ABC123"
1296
+ description="Stock keeping unit"
1297
+ />
1298
+ </div>
1299
+ ),
1300
+ parameters: {
1301
+ docs: {
1302
+ description: {
1303
+ story: 'A complete form demonstrating various prefix/suffix combinations for different data types.',
1304
+ },
1305
+ },
1306
+ },
1307
+ };
1308
+
1309
+ // Prefix/suffix with different sizes
1310
+ export const PrefixSuffixSizes: Story = {
1311
+ render: () => (
1312
+ <div className="space-y-4 max-w-md">
1313
+ <h3 className="text-lg font-semibold">Prefix/Suffix with Size Variants</h3>
1314
+ <TextField
1315
+ label="Small Amount"
1316
+ prefix="$"
1317
+ size="sm"
1318
+ type="text"
1319
+ placeholder="0.00"
1320
+ />
1321
+ <TextField
1322
+ label="Default Amount"
1323
+ prefix="$"
1324
+ size="default"
1325
+ type="text"
1326
+ placeholder="0.00"
1327
+ />
1328
+ <TextField
1329
+ label="Large Amount"
1330
+ prefix="$"
1331
+ size="lg"
1332
+ type="text"
1333
+ placeholder="0.00"
1334
+ />
1335
+ </div>
1336
+ ),
1337
+ parameters: {
1338
+ docs: {
1339
+ description: {
1340
+ story: 'Prefix and suffix work seamlessly with all input size variants (sm, default, lg).',
1341
+ },
1342
+ },
1343
+ },
1344
+ };
1345
+
1346
+ /**
1347
+ * Phase 7: Password Toggle Feature Stories
1348
+ * Demonstrates password visibility toggle for password fields
1349
+ */
1350
+
1351
+ // Basic password with toggle
1352
+ export const PasswordWithToggle: Story = {
1353
+ args: {
1354
+ label: 'Password',
1355
+ type: 'password',
1356
+ showPasswordToggle: true,
1357
+ placeholder: 'Enter your password',
1358
+ description: 'Click the eye icon to toggle password visibility',
1359
+ },
1360
+ parameters: {
1361
+ docs: {
1362
+ description: {
1363
+ story: 'Enable showPasswordToggle to add a visibility toggle button. Click the eye icon or use keyboard (Tab + Space/Enter) to toggle.',
1364
+ },
1365
+ },
1366
+ },
1367
+ };
1368
+
1369
+ // Password toggle with validation
1370
+ export const PasswordToggleWithValidation: Story = {
1371
+ render: () => {
1372
+ const [password, setPassword] = useState('');
1373
+ const [isValid, setIsValid] = useState<boolean | undefined>(undefined);
1374
+ const [errorMessage, setErrorMessage] = useState('');
1375
+
1376
+ const validatePassword = (value: string) => {
1377
+ if (value.length === 0) {
1378
+ setIsValid(undefined);
1379
+ setErrorMessage('');
1380
+ return;
1381
+ }
1382
+
1383
+ if (value.length < 8) {
1384
+ setIsValid(false);
1385
+ setErrorMessage('Password must be at least 8 characters');
1386
+ return;
1387
+ }
1388
+
1389
+ if (!/[A-Z]/.test(value)) {
1390
+ setIsValid(false);
1391
+ setErrorMessage('Password must contain at least one uppercase letter');
1392
+ return;
1393
+ }
1394
+
1395
+ if (!/[0-9]/.test(value)) {
1396
+ setIsValid(false);
1397
+ setErrorMessage('Password must contain at least one number');
1398
+ return;
1399
+ }
1400
+
1401
+ setIsValid(true);
1402
+ setErrorMessage('');
1403
+ };
1404
+
1405
+ return (
1406
+ <TextField
1407
+ label="New Password"
1408
+ type="password"
1409
+ showPasswordToggle={true}
1410
+ value={password}
1411
+ onChange={(val) => {
1412
+ setPassword(val);
1413
+ validatePassword(val);
1414
+ }}
1415
+ isInvalid={isValid === false}
1416
+ isValid={isValid === true}
1417
+ errorMessage={errorMessage}
1418
+ successMessage="Password meets all requirements"
1419
+ description="Must be 8+ characters with uppercase and number"
1420
+ />
1421
+ );
1422
+ },
1423
+ parameters: {
1424
+ docs: {
1425
+ description: {
1426
+ story: 'Password toggle works seamlessly with validation. Toggle visibility to verify password while typing.',
1427
+ },
1428
+ },
1429
+ },
1430
+ };
1431
+
1432
+ // Password confirmation form
1433
+ export const PasswordToggleConfirmation: Story = {
1434
+ render: () => {
1435
+ const [password, setPassword] = useState('');
1436
+ const [confirmPassword, setConfirmPassword] = useState('');
1437
+ const [passwordsMatch, setPasswordsMatch] = useState<boolean | undefined>(undefined);
1438
+
1439
+ useEffect(() => {
1440
+ if (confirmPassword.length > 0) {
1441
+ setPasswordsMatch(password === confirmPassword);
1442
+ } else {
1443
+ setPasswordsMatch(undefined);
1444
+ }
1445
+ }, [password, confirmPassword]);
1446
+
1447
+ return (
1448
+ <div className="space-y-4 max-w-md">
1449
+ <h3 className="text-lg font-semibold">Create Account</h3>
1450
+ <TextField
1451
+ label="Password"
1452
+ type="password"
1453
+ showPasswordToggle={true}
1454
+ value={password}
1455
+ onChange={setPassword}
1456
+ placeholder="Enter password"
1457
+ description="At least 8 characters"
1458
+ />
1459
+ <TextField
1460
+ label="Confirm Password"
1461
+ type="password"
1462
+ showPasswordToggle={true}
1463
+ value={confirmPassword}
1464
+ onChange={setConfirmPassword}
1465
+ placeholder="Re-enter password"
1466
+ isInvalid={passwordsMatch === false}
1467
+ isValid={passwordsMatch === true}
1468
+ errorMessage="Passwords do not match"
1469
+ successMessage="Passwords match"
1470
+ />
1471
+ </div>
1472
+ );
1473
+ },
1474
+ parameters: {
1475
+ docs: {
1476
+ description: {
1477
+ story: 'Common use case: password confirmation. Toggle visibility on either field independently.',
1478
+ },
1479
+ },
1480
+ },
1481
+ };
1482
+
1483
+ // Password toggle with size variants
1484
+ export const PasswordToggleSizes: Story = {
1485
+ render: () => (
1486
+ <div className="space-y-4 max-w-md">
1487
+ <h3 className="text-lg font-semibold">Password Toggle with Size Variants</h3>
1488
+ <TextField
1489
+ label="Small Password"
1490
+ type="password"
1491
+ showPasswordToggle={true}
1492
+ size="sm"
1493
+ placeholder="Enter password"
1494
+ />
1495
+ <TextField
1496
+ label="Default Password"
1497
+ type="password"
1498
+ showPasswordToggle={true}
1499
+ size="default"
1500
+ placeholder="Enter password"
1501
+ />
1502
+ <TextField
1503
+ label="Large Password"
1504
+ type="password"
1505
+ showPasswordToggle={true}
1506
+ size="lg"
1507
+ placeholder="Enter password"
1508
+ />
1509
+ </div>
1510
+ ),
1511
+ parameters: {
1512
+ docs: {
1513
+ description: {
1514
+ story: 'Password toggle works with all input size variants (sm, default, lg).',
1515
+ },
1516
+ },
1517
+ },
1518
+ };
1519
+
1520
+ // Password with disabled state
1521
+ export const PasswordToggleDisabled: Story = {
1522
+ args: {
1523
+ label: 'Password',
1524
+ type: 'password',
1525
+ showPasswordToggle: true,
1526
+ isDisabled: true,
1527
+ value: 'disabled-password',
1528
+ },
1529
+ parameters: {
1530
+ docs: {
1531
+ description: {
1532
+ story: 'When disabled, the password field and toggle button are both non-interactive.',
1533
+ },
1534
+ },
1535
+ },
1536
+ };
1537
+
1538
+ // Login form example
1539
+ export const PasswordToggleLoginForm: Story = {
1540
+ render: () => {
1541
+ const [email, setEmail] = useState('');
1542
+ const [password, setPassword] = useState('');
1543
+
1544
+ return (
1545
+ <div className="space-y-4 max-w-md">
1546
+ <h3 className="text-lg font-semibold">Login</h3>
1547
+ <TextField
1548
+ label="Email"
1549
+ type="email"
1550
+ value={email}
1551
+ onChange={setEmail}
1552
+ placeholder="you@example.com"
1553
+ autoComplete="email"
1554
+ isRequired={true}
1555
+ />
1556
+ <TextField
1557
+ label="Password"
1558
+ type="password"
1559
+ showPasswordToggle={true}
1560
+ value={password}
1561
+ onChange={setPassword}
1562
+ placeholder="Enter your password"
1563
+ autoComplete="current-password"
1564
+ isRequired={true}
1565
+ />
1566
+ <button
1567
+ type="button"
1568
+ className="w-full bg-[var(--themis-primary)] text-[var(--themis-primary-foreground)] py-2 px-4 rounded-md hover:opacity-90 transition-opacity"
1569
+ >
1570
+ Log In
1571
+ </button>
1572
+ </div>
1573
+ );
1574
+ },
1575
+ parameters: {
1576
+ docs: {
1577
+ description: {
1578
+ story: 'Complete login form with password toggle. Notice proper autoComplete attributes for password managers.',
1579
+ },
1580
+ },
1581
+ },
1582
+ };
1583
+
1584
+ /**
1585
+ * Phase 9: Integration & Polish Stories
1586
+ * Comprehensive examples combining multiple features
1587
+ */
1588
+
1589
+ // All features combined
1590
+ export const AllFeaturesCombined: Story = {
1591
+ render: () => {
1592
+ const [searchQuery, setSearchQuery] = useState('');
1593
+ const [email, setEmail] = useState('');
1594
+ const [password, setPassword] = useState('');
1595
+ const [amount, setAmount] = useState('');
1596
+ const [emailValid, setEmailValid] = useState<boolean | undefined>(undefined);
1597
+
1598
+ useEffect(() => {
1599
+ if (email.length > 0) {
1600
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1601
+ setEmailValid(emailRegex.test(email));
1602
+ } else {
1603
+ setEmailValid(undefined);
1604
+ }
1605
+ }, [email]);
1606
+
1607
+ return (
1608
+ <div className="space-y-6 max-w-2xl">
1609
+ <h2 className="text-2xl font-bold">All TextField Features</h2>
1610
+ <p className="text-sm text-muted-foreground">
1611
+ This showcase demonstrates all TextField enhancement features working together:
1612
+ AutoComplete, Copy/Paste Restriction, Pattern Validation, Success Validation,
1613
+ Expand on Focus, Prefix/Suffix, and Password Toggle.
1614
+ </p>
1615
+
1616
+ <div className="space-y-4">
1617
+ {/* Feature 2: AutoComplete + Feature 6: Expand on Focus */}
1618
+ <TextField
1619
+ label="Search"
1620
+ type="search"
1621
+ prefix={
1622
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2">
1623
+ <circle cx="7" cy="7" r="5" />
1624
+ <path d="M11 11l3 3" />
1625
+ </svg>
1626
+ }
1627
+ value={searchQuery}
1628
+ onChange={setSearchQuery}
1629
+ placeholder="Search..."
1630
+ expandOnFocus={true}
1631
+ collapsedWidth="200px"
1632
+ description="Expands when focused, collapses when empty"
1633
+ autoComplete="off"
1634
+ />
1635
+
1636
+ {/* Feature 2: AutoComplete + Feature 4: Pattern Validation + Feature 5: Success Validation */}
1637
+ <TextField
1638
+ label="Email"
1639
+ type="email"
1640
+ value={email}
1641
+ onChange={setEmail}
1642
+ placeholder="you@example.com"
1643
+ autoComplete="email"
1644
+ pattern="[^\s@]+@[^\s@]+\.[^\s@]+"
1645
+ patternDescription="Must be a valid email format"
1646
+ isValid={emailValid === true}
1647
+ isInvalid={emailValid === false}
1648
+ successMessage="Valid email address"
1649
+ errorMessage="Please enter a valid email"
1650
+ isRequired={true}
1651
+ />
1652
+
1653
+ {/* Feature 7: Password Toggle + Feature 3: Copy/Paste Restriction + Feature 2: AutoComplete */}
1654
+ <TextField
1655
+ label="Password"
1656
+ type="password"
1657
+ showPasswordToggle={true}
1658
+ value={password}
1659
+ onChange={setPassword}
1660
+ placeholder="Enter secure password"
1661
+ autoComplete="new-password"
1662
+ description="Password cannot be copied or pasted for security"
1663
+ disableCopyPaste={true}
1664
+ isRequired={true}
1665
+ />
1666
+
1667
+ {/* Feature 8: Prefix/Suffix + Feature 4: Pattern Validation */}
1668
+ <TextField
1669
+ label="Amount"
1670
+ type="text"
1671
+ prefix="$"
1672
+ suffix="USD"
1673
+ value={amount}
1674
+ onChange={setAmount}
1675
+ placeholder="0.00"
1676
+ pattern="^\d+(\.\d{1,2})?$"
1677
+ patternDescription="Enter a valid amount (e.g., 10.50)"
1678
+ description="Currency amount with validation"
1679
+ />
1680
+ </div>
1681
+
1682
+ <div className="mt-6 p-4 bg-muted rounded-md">
1683
+ <h3 className="font-semibold mb-2">Feature Summary:</h3>
1684
+ <ul className="text-sm space-y-1 list-disc list-inside">
1685
+ <li>Search field: Prefix icon, expand on focus, autocomplete</li>
1686
+ <li>Email: Pattern validation, success/error states, autocomplete</li>
1687
+ <li>Password: Visibility toggle, copy/paste prevention, autocomplete</li>
1688
+ <li>Amount: Prefix/suffix, pattern validation</li>
1689
+ </ul>
1690
+ </div>
1691
+ </div>
1692
+ );
1693
+ },
1694
+ parameters: {
1695
+ docs: {
1696
+ description: {
1697
+ story: 'Comprehensive showcase of all TextField enhancement features working together seamlessly.',
1698
+ },
1699
+ },
1700
+ },
1701
+ };
1702
+
1703
+ // Complex form with all features
1704
+ export const CompleteRegistrationForm: Story = {
1705
+ render: () => {
1706
+ const [formData, setFormData] = useState({
1707
+ username: '',
1708
+ email: '',
1709
+ password: '',
1710
+ confirmPassword: '',
1711
+ amount: '',
1712
+ code: '',
1713
+ });
1714
+
1715
+ const [validation, setValidation] = useState({
1716
+ usernameValid: undefined as boolean | undefined,
1717
+ emailValid: undefined as boolean | undefined,
1718
+ passwordValid: undefined as boolean | undefined,
1719
+ passwordsMatch: undefined as boolean | undefined,
1720
+ codeValid: undefined as boolean | undefined,
1721
+ });
1722
+
1723
+ const updateField = (field: string, value: string) => {
1724
+ setFormData(prev => ({ ...prev, [field]: value }));
1725
+ };
1726
+
1727
+ useEffect(() => {
1728
+ // Username validation
1729
+ if (formData.username.length > 0) {
1730
+ setValidation(prev => ({
1731
+ ...prev,
1732
+ usernameValid: /^[a-zA-Z0-9_]{3,16}$/.test(formData.username),
1733
+ }));
1734
+ }
1735
+
1736
+ // Email validation
1737
+ if (formData.email.length > 0) {
1738
+ setValidation(prev => ({
1739
+ ...prev,
1740
+ emailValid: /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email),
1741
+ }));
1742
+ }
1743
+
1744
+ // Password validation
1745
+ if (formData.password.length > 0) {
1746
+ setValidation(prev => ({
1747
+ ...prev,
1748
+ passwordValid: formData.password.length >= 8 && /[A-Z]/.test(formData.password) && /[0-9]/.test(formData.password),
1749
+ }));
1750
+ }
1751
+
1752
+ // Password match
1753
+ if (formData.confirmPassword.length > 0) {
1754
+ setValidation(prev => ({
1755
+ ...prev,
1756
+ passwordsMatch: formData.password === formData.confirmPassword,
1757
+ }));
1758
+ }
1759
+
1760
+ // Code validation
1761
+ if (formData.code.length > 0) {
1762
+ setValidation(prev => ({
1763
+ ...prev,
1764
+ codeValid: /^[A-Z]{3}$/.test(formData.code),
1765
+ }));
1766
+ }
1767
+ }, [formData]);
1768
+
1769
+ return (
1770
+ <div className="space-y-4 max-w-md">
1771
+ <h3 className="text-lg font-semibold">Complete Registration</h3>
1772
+
1773
+ <TextField
1774
+ label="Username"
1775
+ type="text"
1776
+ value={formData.username}
1777
+ onChange={(val) => updateField('username', val)}
1778
+ placeholder="username"
1779
+ pattern="^[a-zA-Z0-9_]{3,16}$"
1780
+ patternDescription="3-16 characters, letters, numbers, underscore"
1781
+ isValid={validation.usernameValid === true}
1782
+ isInvalid={validation.usernameValid === false}
1783
+ successMessage="Username available"
1784
+ errorMessage="Invalid username format"
1785
+ autoComplete="username"
1786
+ isRequired={true}
1787
+ />
1788
+
1789
+ <TextField
1790
+ label="Email"
1791
+ type="email"
1792
+ value={formData.email}
1793
+ onChange={(val) => updateField('email', val)}
1794
+ placeholder="you@example.com"
1795
+ isValid={validation.emailValid === true}
1796
+ isInvalid={validation.emailValid === false}
1797
+ successMessage="Valid email"
1798
+ errorMessage="Invalid email format"
1799
+ autoComplete="email"
1800
+ isRequired={true}
1801
+ />
1802
+
1803
+ <TextField
1804
+ label="Password"
1805
+ type="password"
1806
+ showPasswordToggle={true}
1807
+ value={formData.password}
1808
+ onChange={(val) => updateField('password', val)}
1809
+ placeholder="Enter password"
1810
+ description="8+ chars, uppercase, number"
1811
+ isValid={validation.passwordValid === true}
1812
+ isInvalid={validation.passwordValid === false}
1813
+ successMessage="Strong password"
1814
+ errorMessage="Password too weak"
1815
+ autoComplete="new-password"
1816
+ isRequired={true}
1817
+ />
1818
+
1819
+ <TextField
1820
+ label="Confirm Password"
1821
+ type="password"
1822
+ showPasswordToggle={true}
1823
+ value={formData.confirmPassword}
1824
+ onChange={(val) => updateField('confirmPassword', val)}
1825
+ placeholder="Re-enter password"
1826
+ disableCopyPaste={true}
1827
+ description="Type password again (no paste)"
1828
+ isValid={validation.passwordsMatch === true}
1829
+ isInvalid={validation.passwordsMatch === false}
1830
+ successMessage="Passwords match"
1831
+ errorMessage="Passwords don't match"
1832
+ autoComplete="new-password"
1833
+ isRequired={true}
1834
+ />
1835
+
1836
+ <TextField
1837
+ label="Referral Code"
1838
+ type="text"
1839
+ prefix="#"
1840
+ value={formData.code}
1841
+ onChange={(val) => updateField('code', val.toUpperCase())}
1842
+ placeholder="ABC"
1843
+ pattern="^[A-Z]{3}$"
1844
+ patternDescription="3 uppercase letters"
1845
+ description="Optional referral code"
1846
+ />
1847
+
1848
+ <TextField
1849
+ label="Initial Deposit"
1850
+ type="text"
1851
+ prefix="$"
1852
+ suffix="USD"
1853
+ value={formData.amount}
1854
+ onChange={(val) => updateField('amount', val)}
1855
+ placeholder="0.00"
1856
+ description="Minimum $10.00"
1857
+ />
1858
+
1859
+ <button
1860
+ type="button"
1861
+ className="w-full bg-[var(--themis-primary)] text-[var(--themis-primary-foreground)] py-2 px-4 rounded-md hover:opacity-90 transition-opacity"
1862
+ >
1863
+ Create Account
1864
+ </button>
1865
+ </div>
1866
+ );
1867
+ },
1868
+ parameters: {
1869
+ docs: {
1870
+ description: {
1871
+ story: 'Complete registration form showcasing real-world usage of all TextField features.',
1872
+ },
1873
+ },
1874
+ },
1875
+ };
1876
+
1877
+ // Import React for validation example
1878
+ import { useState, useEffect } from 'react';