siesa-ui-kit 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/bin/install.cjs +502 -0
  2. package/bin/prepare-publish.cjs +28 -0
  3. package/bin/restore-folders.cjs +28 -0
  4. package/claude/settings.local.json +7 -0
  5. package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.d.ts +101 -0
  6. package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.d.ts.map +1 -0
  7. package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.types.d.ts +95 -0
  8. package/dist/components/DropdownItemCollapsible/DropdownItemCollapsible.types.d.ts.map +1 -0
  9. package/dist/components/DropdownItemCollapsible/icons.d.ts +19 -0
  10. package/dist/components/DropdownItemCollapsible/icons.d.ts.map +1 -0
  11. package/dist/components/DropdownItemCollapsible/index.d.ts +9 -0
  12. package/dist/components/DropdownItemCollapsible/index.d.ts.map +1 -0
  13. package/dist/components/DropdownItemHeading/DropdownItemHeading.d.ts +75 -0
  14. package/dist/components/DropdownItemHeading/DropdownItemHeading.d.ts.map +1 -0
  15. package/dist/components/DropdownItemHeading/DropdownItemHeading.types.d.ts +85 -0
  16. package/dist/components/DropdownItemHeading/DropdownItemHeading.types.d.ts.map +1 -0
  17. package/dist/components/DropdownItemHeading/icons.d.ts +48 -0
  18. package/dist/components/DropdownItemHeading/icons.d.ts.map +1 -0
  19. package/dist/components/DropdownItemHeading/index.d.ts +4 -0
  20. package/dist/components/DropdownItemHeading/index.d.ts.map +1 -0
  21. package/dist/components/LoginView/LoginView.d.ts +36 -0
  22. package/dist/components/LoginView/LoginView.d.ts.map +1 -0
  23. package/dist/components/LoginView/LoginView.types.d.ts +46 -0
  24. package/dist/components/LoginView/LoginView.types.d.ts.map +1 -0
  25. package/dist/components/LoginView/icons.d.ts +18 -0
  26. package/dist/components/LoginView/icons.d.ts.map +1 -0
  27. package/dist/components/LoginView/index.d.ts +4 -0
  28. package/dist/components/LoginView/index.d.ts.map +1 -0
  29. package/dist/components/NavigationRailItem/NavigationRailItem.d.ts +90 -0
  30. package/dist/components/NavigationRailItem/NavigationRailItem.d.ts.map +1 -0
  31. package/dist/components/NavigationRailItem/NavigationRailItem.types.d.ts +155 -0
  32. package/dist/components/NavigationRailItem/NavigationRailItem.types.d.ts.map +1 -0
  33. package/dist/components/NavigationRailItem/index.d.ts +3 -0
  34. package/dist/components/NavigationRailItem/index.d.ts.map +1 -0
  35. package/dist/components/NavigationRailPanel/NavigationRailPanel.d.ts +124 -0
  36. package/dist/components/NavigationRailPanel/NavigationRailPanel.d.ts.map +1 -0
  37. package/dist/components/NavigationRailPanel/NavigationRailPanel.types.d.ts +154 -0
  38. package/dist/components/NavigationRailPanel/NavigationRailPanel.types.d.ts.map +1 -0
  39. package/dist/components/NavigationRailPanel/index.d.ts +3 -0
  40. package/dist/components/NavigationRailPanel/index.d.ts.map +1 -0
  41. package/dist/components/NavigationRailTypes/NavigationRailTypes.d.ts +99 -0
  42. package/dist/components/NavigationRailTypes/NavigationRailTypes.d.ts.map +1 -0
  43. package/dist/components/NavigationRailTypes/NavigationRailTypes.types.d.ts +111 -0
  44. package/dist/components/NavigationRailTypes/NavigationRailTypes.types.d.ts.map +1 -0
  45. package/dist/components/NavigationRailTypes/icons.d.ts +58 -0
  46. package/dist/components/NavigationRailTypes/icons.d.ts.map +1 -0
  47. package/dist/components/NavigationRailTypes/index.d.ts +4 -0
  48. package/dist/components/NavigationRailTypes/index.d.ts.map +1 -0
  49. package/dist/components/SignUpView/SignUpView.d.ts +38 -0
  50. package/dist/components/SignUpView/SignUpView.d.ts.map +1 -0
  51. package/dist/components/SignUpView/SignUpView.types.d.ts +51 -0
  52. package/dist/components/SignUpView/SignUpView.types.d.ts.map +1 -0
  53. package/dist/components/SignUpView/icons.d.ts +18 -0
  54. package/dist/components/SignUpView/icons.d.ts.map +1 -0
  55. package/dist/components/SignUpView/index.d.ts +4 -0
  56. package/dist/components/SignUpView/index.d.ts.map +1 -0
  57. package/dist/index.d.ts +30 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/siesa-ui-kit.cjs +906 -66
  60. package/dist/siesa-ui-kit.cjs.map +1 -1
  61. package/dist/siesa-ui-kit.mjs +3547 -411
  62. package/dist/siesa-ui-kit.mjs.map +1 -1
  63. package/docs/border-radius.md +1261 -0
  64. package/docs/colors.md +832 -0
  65. package/docs/dark-mode-guide.md +1426 -0
  66. package/docs/filters.md +1243 -0
  67. package/docs/icons.md +1283 -0
  68. package/docs/shadows.md +1377 -0
  69. package/docs/spacing.md +1684 -0
  70. package/docs/typography.md +1268 -0
  71. package/package.json +21 -3
  72. package/postcss.config.cjs +6 -0
  73. package/public/,Business Logo.png +0 -0
  74. package/public/.Siesa Logo.png +0 -0
  75. package/public/bg_siesa.png +0 -0
  76. package/public/siesa_logo_mobile.png +0 -0
  77. package/public/vite.svg +1 -0
  78. package/src/App.css +42 -0
  79. package/src/App.tsx +8 -0
  80. package/src/ButtonTest.tsx +147 -0
  81. package/src/assets/fonts/README.md +261 -0
  82. package/src/assets/fonts/SiesaBT/SiesaBT-Bold.otf +0 -0
  83. package/src/assets/fonts/SiesaBT/SiesaBT-Light.otf +0 -0
  84. package/src/assets/fonts/SiesaBT/SiesaBT-Regular.otf +0 -0
  85. package/src/assets/react.svg +1 -0
  86. package/src/components/Alert/Alert.stories.tsx +332 -0
  87. package/src/components/Alert/Alert.tsx +106 -0
  88. package/src/components/Alert/Alert.types.ts +54 -0
  89. package/src/components/Avatar/Avatar.stories.tsx +494 -0
  90. package/src/components/Avatar/Avatar.tsx +143 -0
  91. package/src/components/Avatar/Avatar.types.ts +53 -0
  92. package/src/components/Badge/Badge.stories.tsx +339 -0
  93. package/src/components/Badge/Badge.tsx +278 -0
  94. package/src/components/Badge/Badge.types.ts +58 -0
  95. package/src/components/Button/Button.stories.tsx +950 -0
  96. package/src/components/Button/Button.tsx +337 -0
  97. package/src/components/Button/Button.types.ts +180 -0
  98. package/src/components/Button/icons.tsx +87 -0
  99. package/src/components/Button/index.ts +3 -0
  100. package/src/components/Checkbox/Checkbox.stories.tsx +453 -0
  101. package/src/components/Checkbox/Checkbox.tsx +208 -0
  102. package/src/components/Checkbox/Checkbox.types.ts +61 -0
  103. package/src/components/DescriptionList/DescriptionList.stories.tsx +250 -0
  104. package/src/components/DescriptionList/DescriptionList.tsx +96 -0
  105. package/src/components/DescriptionList/DescriptionList.types.ts +29 -0
  106. package/src/components/Divider/Divider.stories.tsx +263 -0
  107. package/src/components/Divider/Divider.tsx +80 -0
  108. package/src/components/Divider/Divider.types.ts +24 -0
  109. package/src/components/Dropdown/Dropdown.stories.tsx +552 -0
  110. package/src/components/Dropdown/Dropdown.tsx +422 -0
  111. package/src/components/Dropdown/Dropdown.types.ts +146 -0
  112. package/src/components/Dropdown/README.md +266 -0
  113. package/src/components/Dropdown/icons.tsx +72 -0
  114. package/src/components/Dropdown/index.ts +8 -0
  115. package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.stories.tsx +317 -0
  116. package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.tsx +287 -0
  117. package/src/components/DropdownItemCollapsible/DropdownItemCollapsible.types.ts +111 -0
  118. package/src/components/DropdownItemCollapsible/README.md +264 -0
  119. package/src/components/DropdownItemCollapsible/icons.tsx +57 -0
  120. package/src/components/DropdownItemCollapsible/index.ts +12 -0
  121. package/src/components/DropdownItemHeading/DropdownItemHeading.stories.tsx +386 -0
  122. package/src/components/DropdownItemHeading/DropdownItemHeading.tsx +216 -0
  123. package/src/components/DropdownItemHeading/DropdownItemHeading.types.ts +93 -0
  124. package/src/components/DropdownItemHeading/README.md +573 -0
  125. package/src/components/DropdownItemHeading/icons.tsx +125 -0
  126. package/src/components/DropdownItemHeading/index.ts +3 -0
  127. package/src/components/Input/Input.stories.tsx +583 -0
  128. package/src/components/Input/Input.tsx +204 -0
  129. package/src/components/Input/Input.types.ts +80 -0
  130. package/src/components/Input/icons.tsx +145 -0
  131. package/src/components/Input/index.ts +2 -0
  132. package/src/components/LoginView/LoginView.stories.tsx +148 -0
  133. package/src/components/LoginView/LoginView.tsx +426 -0
  134. package/src/components/LoginView/LoginView.types.ts +52 -0
  135. package/src/components/LoginView/README.md +396 -0
  136. package/src/components/LoginView/icons.tsx +85 -0
  137. package/src/components/LoginView/index.ts +3 -0
  138. package/src/components/Navbar/Navbar.stories.tsx +810 -0
  139. package/src/components/Navbar/Navbar.tsx +755 -0
  140. package/src/components/Navbar/Navbar.types.ts +219 -0
  141. package/src/components/Navbar/README.md +279 -0
  142. package/src/components/Navbar/icons.tsx +102 -0
  143. package/src/components/Navbar/index.ts +8 -0
  144. package/src/components/NavigationBar/NavigationBar.stories.tsx +406 -0
  145. package/src/components/NavigationBar/NavigationBar.tsx +246 -0
  146. package/src/components/NavigationBar/NavigationBar.types.ts +74 -0
  147. package/src/components/NavigationBar/README.md +469 -0
  148. package/src/components/NavigationBar/index.ts +2 -0
  149. package/src/components/NavigationRail/NavigationRail.stories.tsx +417 -0
  150. package/src/components/NavigationRail/NavigationRail.tsx +418 -0
  151. package/src/components/NavigationRail/NavigationRail.types.ts +109 -0
  152. package/src/components/NavigationRail/README.md +224 -0
  153. package/src/components/NavigationRail/index.ts +2 -0
  154. package/src/components/NavigationRailItem/NavigationRailItem.stories.tsx +667 -0
  155. package/src/components/NavigationRailItem/NavigationRailItem.tsx +313 -0
  156. package/src/components/NavigationRailItem/NavigationRailItem.types.ts +167 -0
  157. package/src/components/NavigationRailItem/README.md +476 -0
  158. package/src/components/NavigationRailItem/index.ts +2 -0
  159. package/src/components/NavigationRailPanel/NavigationRailPanel.stories.tsx +462 -0
  160. package/src/components/NavigationRailPanel/NavigationRailPanel.tsx +332 -0
  161. package/src/components/NavigationRailPanel/NavigationRailPanel.types.ts +178 -0
  162. package/src/components/NavigationRailPanel/README.md +461 -0
  163. package/src/components/NavigationRailPanel/index.ts +6 -0
  164. package/src/components/NavigationRailTypes/NavigationRailTypes.stories.tsx +528 -0
  165. package/src/components/NavigationRailTypes/NavigationRailTypes.tsx +378 -0
  166. package/src/components/NavigationRailTypes/NavigationRailTypes.types.ts +130 -0
  167. package/src/components/NavigationRailTypes/README.md +573 -0
  168. package/src/components/NavigationRailTypes/icons.tsx +141 -0
  169. package/src/components/NavigationRailTypes/index.ts +7 -0
  170. package/src/components/Notification/Notification.stories.tsx +513 -0
  171. package/src/components/Notification/Notification.tsx +145 -0
  172. package/src/components/Notification/Notification.types.ts +142 -0
  173. package/src/components/Notification/README.md +409 -0
  174. package/src/components/Notification/index.ts +3 -0
  175. package/src/components/POSConvention/POSConvention.stories.tsx +235 -0
  176. package/src/components/POSConvention/POSConvention.tsx +129 -0
  177. package/src/components/POSConvention/POSConvention.types.ts +38 -0
  178. package/src/components/POSConvention/README.md +123 -0
  179. package/src/components/POSConvention/icons.tsx +45 -0
  180. package/src/components/POSConvention/index.ts +3 -0
  181. package/src/components/POSLocationButton/POSLocationButton.stories.tsx +531 -0
  182. package/src/components/POSLocationButton/POSLocationButton.tsx +247 -0
  183. package/src/components/POSLocationButton/POSLocationButton.types.ts +87 -0
  184. package/src/components/POSLocationButton/README.md +253 -0
  185. package/src/components/POSLocationButton/icons.tsx +120 -0
  186. package/src/components/POSLocationButton/index.ts +14 -0
  187. package/src/components/POSNumberButton/POSNumberButton.stories.tsx +415 -0
  188. package/src/components/POSNumberButton/POSNumberButton.tsx +179 -0
  189. package/src/components/POSNumberButton/POSNumberButton.types.ts +51 -0
  190. package/src/components/POSNumberButton/README.md +321 -0
  191. package/src/components/POSNumberButton/index.ts +3 -0
  192. package/src/components/POSProductButton/POSProductButton.stories.tsx +318 -0
  193. package/src/components/POSProductButton/POSProductButton.tsx +152 -0
  194. package/src/components/POSProductButton/POSProductButton.types.ts +46 -0
  195. package/src/components/POSProductButton/README.md +269 -0
  196. package/src/components/POSProductButton/index.ts +2 -0
  197. package/src/components/POSProductCard/POSProductCard.stories.tsx +642 -0
  198. package/src/components/POSProductCard/POSProductCard.tsx +208 -0
  199. package/src/components/POSProductCard/POSProductCard.types.ts +76 -0
  200. package/src/components/POSProductCard/README.md +179 -0
  201. package/src/components/POSProductCard/icons.tsx +26 -0
  202. package/src/components/POSProductCard/index.ts +2 -0
  203. package/src/components/POSProductSidebarItems/POSProductSidebarItems.stories.tsx +753 -0
  204. package/src/components/POSProductSidebarItems/POSProductSidebarItems.tsx +332 -0
  205. package/src/components/POSProductSidebarItems/POSProductSidebarItems.types.ts +119 -0
  206. package/src/components/POSProductSidebarItems/README.md +198 -0
  207. package/src/components/POSProductSidebarItems/icons.tsx +21 -0
  208. package/src/components/POSProductSidebarItems/index.ts +3 -0
  209. package/src/components/POSTable/POSTable.stories.tsx +737 -0
  210. package/src/components/POSTable/POSTable.tsx +401 -0
  211. package/src/components/POSTable/POSTable.types.ts +83 -0
  212. package/src/components/POSTable/README.md +286 -0
  213. package/src/components/POSTable/index.ts +7 -0
  214. package/src/components/Pagination/Pagination.stories.tsx +555 -0
  215. package/src/components/Pagination/Pagination.tsx +286 -0
  216. package/src/components/Pagination/Pagination.types.ts +93 -0
  217. package/src/components/Pagination/README.md +298 -0
  218. package/src/components/Pagination/icons.tsx +47 -0
  219. package/src/components/Pagination/index.ts +3 -0
  220. package/src/components/Quantity/Quantity.stories.tsx +457 -0
  221. package/src/components/Quantity/Quantity.tsx +289 -0
  222. package/src/components/Quantity/Quantity.types.ts +70 -0
  223. package/src/components/Radio/Radio.stories.tsx +523 -0
  224. package/src/components/Radio/Radio.tsx +170 -0
  225. package/src/components/Radio/Radio.types.ts +122 -0
  226. package/src/components/Select/README.md +299 -0
  227. package/src/components/Select/Select.stories.tsx +673 -0
  228. package/src/components/Select/Select.tsx +454 -0
  229. package/src/components/Select/Select.types.ts +148 -0
  230. package/src/components/Select/icons.tsx +50 -0
  231. package/src/components/Select/index.ts +3 -0
  232. package/src/components/SignUpView/SignUpView.stories.tsx +129 -0
  233. package/src/components/SignUpView/SignUpView.tsx +503 -0
  234. package/src/components/SignUpView/SignUpView.types.ts +58 -0
  235. package/src/components/SignUpView/icons.tsx +71 -0
  236. package/src/components/SignUpView/index.ts +3 -0
  237. package/src/components/Switch/README.md +112 -0
  238. package/src/components/Switch/Switch.stories.tsx +550 -0
  239. package/src/components/Switch/Switch.tsx +246 -0
  240. package/src/components/Switch/Switch.types.ts +67 -0
  241. package/src/components/Table/README.md +369 -0
  242. package/src/components/Table/Table.stories.tsx +805 -0
  243. package/src/components/Table/Table.tsx +688 -0
  244. package/src/components/Table/Table.types.ts +204 -0
  245. package/src/components/Table/index.ts +9 -0
  246. package/src/components/Tabs/README.md +201 -0
  247. package/src/components/Tabs/Tabs.stories.tsx +580 -0
  248. package/src/components/Tabs/Tabs.tsx +356 -0
  249. package/src/components/Tabs/Tabs.types.ts +127 -0
  250. package/src/components/Tabs/icons.tsx +129 -0
  251. package/src/components/Tabs/index.ts +11 -0
  252. package/src/components/Textarea/Textarea.stories.tsx +535 -0
  253. package/src/components/Textarea/Textarea.tsx +188 -0
  254. package/src/components/Textarea/Textarea.types.ts +54 -0
  255. package/src/context/ThemeContext.tsx +99 -0
  256. package/src/context/index.ts +1 -0
  257. package/src/index.css +29 -0
  258. package/src/index.ts +102 -0
  259. package/src/main.tsx +10 -0
  260. package/src/views/ListView/ListView.stories.tsx +329 -0
  261. package/src/views/ListView/ListView.tsx +570 -0
  262. package/src/views/ListView/ListView.types.ts +211 -0
  263. package/src/views/ListView/icons.tsx +282 -0
  264. package/src/views/ListView/index.ts +11 -0
  265. package/src/views/LoginView/LoginView.stories.tsx +148 -0
  266. package/src/views/LoginView/LoginView.tsx +426 -0
  267. package/src/views/LoginView/LoginView.types.ts +52 -0
  268. package/src/views/LoginView/README.md +396 -0
  269. package/src/views/LoginView/icons.tsx +85 -0
  270. package/src/views/LoginView/index.ts +3 -0
  271. package/src/views/ProductsView/ProductsView.stories.tsx +344 -0
  272. package/src/views/ProductsView/ProductsView.tsx +480 -0
  273. package/src/views/ProductsView/ProductsView.types.ts +238 -0
  274. package/src/views/ProductsView/README.md +312 -0
  275. package/src/views/ProductsView/icons.tsx +38 -0
  276. package/src/views/ProductsView/index.ts +8 -0
  277. package/src/views/RecoverPasswordView/README.md +269 -0
  278. package/src/views/RecoverPasswordView/RecoverPasswordView.stories.tsx +131 -0
  279. package/src/views/RecoverPasswordView/RecoverPasswordView.tsx +376 -0
  280. package/src/views/RecoverPasswordView/RecoverPasswordView.types.ts +56 -0
  281. package/src/views/RecoverPasswordView/icons.tsx +17 -0
  282. package/src/views/RecoverPasswordView/index.ts +2 -0
  283. package/src/views/SignUpView/SignUpView.stories.tsx +129 -0
  284. package/src/views/SignUpView/SignUpView.tsx +503 -0
  285. package/src/views/SignUpView/SignUpView.types.ts +58 -0
  286. package/src/views/SignUpView/icons.tsx +71 -0
  287. package/src/views/SignUpView/index.ts +3 -0
  288. package/src/views/TableLayoutView/README.md +268 -0
  289. package/src/views/TableLayoutView/TableLayoutView.stories.tsx +235 -0
  290. package/src/views/TableLayoutView/TableLayoutView.tsx +461 -0
  291. package/src/views/TableLayoutView/TableLayoutView.types.ts +209 -0
  292. package/src/views/TableLayoutView/icons.tsx +113 -0
  293. package/src/views/TableLayoutView/index.ts +6 -0
  294. package/storybook/main.ts +20 -0
  295. package/storybook/preview.tsx +84 -0
  296. package/storybook/vitest.setup.ts +7 -0
  297. package/tailwind.config.js +128 -0
@@ -0,0 +1,289 @@
1
+ import { forwardRef, useState, useEffect } from 'react';
2
+ import type { QuantityProps } from './Quantity.types';
3
+
4
+ /**
5
+ * Quantity - Componente de cantidad del sistema de diseño Siesa
6
+ *
7
+ * Componente para seleccionar cantidades con soporte para:
8
+ * - Botones de incremento/decremento
9
+ * - Valores mínimo y máximo
10
+ * - Label opcional con link
11
+ * - Texto de ayuda opcional
12
+ * - Estado de error
13
+ * - Estado deshabilitado
14
+ * - Dark mode completo
15
+ *
16
+ * Mejores prácticas implementadas:
17
+ * - Orden de modificadores: {responsive}:{dark}:{state}:{utility}
18
+ * - Dark mode con estrategia 'class' (darkMode: 'class')
19
+ * - Tokens de color consistentes con la documentación
20
+ * - Focus rings adaptativos para light y dark mode
21
+ * - Type safety con TypeScript estricto
22
+ * - Accesibilidad con ARIA labels
23
+ *
24
+ * @see docs/colors.md - Sistema de colores
25
+ * @see docs/typography.md - Sistema tipográfico
26
+ * @see docs/spacing.md - Sistema de espaciado
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * <Quantity
31
+ * label="Cantidad"
32
+ * value={5}
33
+ * min={0}
34
+ * max={10}
35
+ * onChange={(value) => console.log(value)}
36
+ * />
37
+ * ```
38
+ */
39
+ export const Quantity = forwardRef<HTMLDivElement, QuantityProps>(
40
+ (
41
+ {
42
+ value: controlledValue,
43
+ defaultValue = 0,
44
+ onChange,
45
+ min = 0,
46
+ max,
47
+ label,
48
+ linkText,
49
+ onLinkClick,
50
+ helperText,
51
+ error = false,
52
+ disabled = false,
53
+ className = '',
54
+ ...props
55
+ },
56
+ ref
57
+ ) => {
58
+ // Estado interno para valor no controlado
59
+ const [internalValue, setInternalValue] = useState(defaultValue);
60
+ const isControlled = controlledValue !== undefined;
61
+ const currentValue = isControlled ? controlledValue : internalValue;
62
+
63
+ // Sincronizar valor interno con defaultValue cuando cambia
64
+ useEffect(() => {
65
+ if (!isControlled) {
66
+ setInternalValue(defaultValue);
67
+ }
68
+ }, [defaultValue, isControlled]);
69
+
70
+ // Handler para cambio de valor
71
+ const handleValueChange = (newValue: number) => {
72
+ // Aplicar restricciones de min/max
73
+ let clampedValue = newValue;
74
+ if (min !== undefined && clampedValue < min) {
75
+ clampedValue = min;
76
+ }
77
+ if (max !== undefined && clampedValue > max) {
78
+ clampedValue = max;
79
+ }
80
+
81
+ // Actualizar estado interno si no está controlado
82
+ if (!isControlled) {
83
+ setInternalValue(clampedValue);
84
+ }
85
+
86
+ // Llamar onChange si existe
87
+ onChange?.(clampedValue);
88
+ };
89
+
90
+ // Handlers para botones
91
+ const handleDecrement = () => {
92
+ if (disabled) return;
93
+ handleValueChange(currentValue - 1);
94
+ };
95
+
96
+ const handleIncrement = () => {
97
+ if (disabled) return;
98
+ handleValueChange(currentValue + 1);
99
+ };
100
+
101
+ // Verificar si los botones deben estar deshabilitados
102
+ const isDecrementDisabled = disabled || (min !== undefined && currentValue <= min);
103
+ const isIncrementDisabled = disabled || (max !== undefined && currentValue >= max);
104
+
105
+ // Iconos SVG inline
106
+ const MinusIcon = () => (
107
+ <svg
108
+ width="16"
109
+ height="16"
110
+ viewBox="0 0 16 16"
111
+ fill="none"
112
+ xmlns="http://www.w3.org/2000/svg"
113
+ >
114
+ <path
115
+ d="M3 8H13"
116
+ stroke="currentColor"
117
+ strokeWidth="1.5"
118
+ strokeLinecap="round"
119
+ strokeLinejoin="round"
120
+ />
121
+ </svg>
122
+ );
123
+
124
+ const PlusIcon = () => (
125
+ <svg
126
+ width="16"
127
+ height="16"
128
+ viewBox="0 0 16 16"
129
+ fill="none"
130
+ xmlns="http://www.w3.org/2000/svg"
131
+ >
132
+ <path
133
+ d="M8 3V13M3 8H13"
134
+ stroke="currentColor"
135
+ strokeWidth="1.5"
136
+ strokeLinecap="round"
137
+ strokeLinejoin="round"
138
+ />
139
+ </svg>
140
+ );
141
+
142
+ // Clases para el estado (usando especificaciones exactas de Figma)
143
+ const borderClass = error
144
+ ? 'border-error-border dark:border-error-border'
145
+ : 'border-border-primary dark:border-dark-border-primary';
146
+
147
+ const hoverClass = !disabled && !error
148
+ ? 'hover:border-[#f9f9f9] dark:hover:border-[#f9f9f9]'
149
+ : '';
150
+
151
+ const focusClass = !disabled && !error
152
+ ? 'focus-within:border-2 focus-within:border-[#329cff] dark:focus-within:border-[#329cff]'
153
+ : '';
154
+
155
+ return (
156
+ <div
157
+ ref={ref}
158
+ className={`flex flex-col gap-2 ${className}`.trim()}
159
+ {...props}
160
+ >
161
+ {/* Label con link opcional */}
162
+ {label && (
163
+ <div className="flex items-center justify-between">
164
+ <label className="text-sm leading-5 font-bold text-content-primary dark:text-dark-content-primary">
165
+ {label}
166
+ </label>
167
+ {linkText && (
168
+ <button
169
+ type="button"
170
+ onClick={onLinkClick}
171
+ disabled={disabled}
172
+ className={`
173
+ text-xs leading-4
174
+ text-primary-custom-600
175
+ hover:underline
176
+ dark:text-primary-custom-600
177
+ ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
178
+ transition-colors
179
+ duration-200
180
+ `.trim().replace(/\s+/g, ' ')}
181
+ >
182
+ {linkText}
183
+ </button>
184
+ )}
185
+ </div>
186
+ )}
187
+
188
+ {/* Input con botones */}
189
+ <div
190
+ className={`
191
+ flex
192
+ items-center
193
+ gap-2
194
+ px-3
195
+ py-1.5
196
+ bg-white
197
+ dark:bg-dark-bg-primary
198
+ border
199
+ ${borderClass}
200
+ ${hoverClass}
201
+ ${focusClass}
202
+ rounded-lg
203
+ transition-colors
204
+ duration-200
205
+ ${disabled ? 'opacity-50 cursor-not-allowed' : ''}
206
+ `.trim().replace(/\s+/g, ' ')}
207
+ >
208
+ {/* Botón decrementar */}
209
+ <button
210
+ type="button"
211
+ onClick={handleDecrement}
212
+ disabled={isDecrementDisabled}
213
+ className={`
214
+ flex
215
+ items-center
216
+ justify-center
217
+ w-4
218
+ h-4
219
+ ${isDecrementDisabled
220
+ ? 'text-content-tertiary dark:text-content-tertiary cursor-not-allowed'
221
+ : 'text-content-primary dark:text-dark-content-primary hover:text-content-secondary dark:hover:text-content-secondary cursor-pointer'
222
+ }
223
+ transition-colors
224
+ duration-200
225
+ `.trim().replace(/\s+/g, ' ')}
226
+ aria-label="Decrementar"
227
+ >
228
+ <MinusIcon />
229
+ </button>
230
+
231
+ {/* Valor actual */}
232
+ <div className="flex-1 text-center">
233
+ <span
234
+ className={`
235
+ text-base leading-6
236
+ ${currentValue === 0
237
+ ? 'text-content-tertiary dark:text-content-tertiary'
238
+ : 'text-content-primary dark:text-dark-content-primary'
239
+ }
240
+ `.trim().replace(/\s+/g, ' ')}
241
+ >
242
+ {currentValue}
243
+ </span>
244
+ </div>
245
+
246
+ {/* Botón incrementar */}
247
+ <button
248
+ type="button"
249
+ onClick={handleIncrement}
250
+ disabled={isIncrementDisabled}
251
+ className={`
252
+ flex
253
+ items-center
254
+ justify-center
255
+ w-4
256
+ h-4
257
+ ${isIncrementDisabled
258
+ ? 'text-content-tertiary dark:text-content-tertiary cursor-not-allowed'
259
+ : 'text-content-primary dark:text-dark-content-primary hover:text-content-secondary dark:hover:text-content-secondary cursor-pointer'
260
+ }
261
+ transition-colors
262
+ duration-200
263
+ `.trim().replace(/\s+/g, ' ')}
264
+ aria-label="Incrementar"
265
+ >
266
+ <PlusIcon />
267
+ </button>
268
+ </div>
269
+
270
+ {/* Helper text */}
271
+ {helperText && (
272
+ <p
273
+ className={`
274
+ text-sm leading-5
275
+ ${error
276
+ ? 'text-error-content dark:text-error-content'
277
+ : 'text-content-tertiary dark:text-content-tertiary'
278
+ }
279
+ `.trim().replace(/\s+/g, ' ')}
280
+ >
281
+ {helperText}
282
+ </p>
283
+ )}
284
+ </div>
285
+ );
286
+ }
287
+ );
288
+
289
+ Quantity.displayName = 'Quantity';
@@ -0,0 +1,70 @@
1
+ import type { HTMLAttributes } from 'react';
2
+
3
+ /**
4
+ * Props del componente Quantity
5
+ */
6
+ export interface QuantityProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
7
+ /**
8
+ * Valor actual del quantity
9
+ */
10
+ value?: number;
11
+
12
+ /**
13
+ * Valor por defecto
14
+ * @default 0
15
+ */
16
+ defaultValue?: number;
17
+
18
+ /**
19
+ * Callback cuando el valor cambia
20
+ */
21
+ onChange?: (value: number) => void;
22
+
23
+ /**
24
+ * Valor mínimo permitido
25
+ * @default 0
26
+ */
27
+ min?: number;
28
+
29
+ /**
30
+ * Valor máximo permitido
31
+ */
32
+ max?: number;
33
+
34
+ /**
35
+ * Label opcional
36
+ */
37
+ label?: string;
38
+
39
+ /**
40
+ * Texto del link opcional (aparece a la derecha del label)
41
+ */
42
+ linkText?: string;
43
+
44
+ /**
45
+ * Callback cuando se hace click en el link
46
+ */
47
+ onLinkClick?: () => void;
48
+
49
+ /**
50
+ * Texto de ayuda opcional
51
+ */
52
+ helperText?: string;
53
+
54
+ /**
55
+ * Si está en estado de error
56
+ * @default false
57
+ */
58
+ error?: boolean;
59
+
60
+ /**
61
+ * Si está deshabilitado
62
+ * @default false
63
+ */
64
+ disabled?: boolean;
65
+
66
+ /**
67
+ * Clases CSS adicionales
68
+ */
69
+ className?: string;
70
+ }