@axzydev/axzy_ui_system 1.2.6 → 1.2.8

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 (185) hide show
  1. package/dist/index.cjs +777 -535
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +1 -1
  4. package/dist/index.css.map +1 -1
  5. package/dist/index.d.cts +1470 -87
  6. package/dist/index.d.ts +1470 -87
  7. package/dist/index.js +799 -555
  8. package/dist/index.js.map +1 -1
  9. package/package.json +1 -1
  10. package/src/App.tsx +19 -54
  11. package/src/components/alert/alert.doc.mdx +48 -0
  12. package/src/components/alert/alert.props.ts +7 -0
  13. package/src/components/alert/alert.tsx +8 -0
  14. package/src/components/avatar/avatar.doc.mdx +48 -0
  15. package/src/components/avatar/avatar.props.ts +8 -0
  16. package/src/components/avatar/avatar.tsx +25 -5
  17. package/src/components/badget/badget.doc.mdx +46 -0
  18. package/src/components/badget/badget.props.ts +6 -0
  19. package/src/components/badget/badget.tsx +11 -0
  20. package/src/components/breadcrumbs/breadcrumbs.doc.mdx +57 -0
  21. package/src/components/breadcrumbs/breadcrumbs.props.ts +6 -0
  22. package/src/components/breadcrumbs/breadcrumbs.tsx +12 -0
  23. package/src/components/button/button.doc.mdx +59 -0
  24. package/src/components/button/button.props.ts +12 -0
  25. package/src/components/button/button.tsx +11 -0
  26. package/src/components/calendar/calendar.doc.mdx +75 -0
  27. package/src/components/calendar/calendar.props.ts +27 -7
  28. package/src/components/calendar/calendar.tsx +13 -0
  29. package/src/components/card/card.doc.mdx +54 -0
  30. package/src/components/card/card.props.ts +11 -0
  31. package/src/components/card/card.tsx +13 -0
  32. package/src/components/checkbox/checkbox.doc.mdx +54 -0
  33. package/src/components/checkbox/checkbox.props.ts +7 -0
  34. package/src/components/checkbox/checkbox.tsx +9 -0
  35. package/src/components/confirm-dialog/confirm-dialog.doc.mdx +60 -0
  36. package/src/components/confirm-dialog/confirm-dialog.props.ts +9 -0
  37. package/src/components/confirm-dialog/confirm-dialog.tsx +19 -0
  38. package/src/components/data-table/ITDataTable.doc.mdx +59 -0
  39. package/src/components/data-table/dataTable.props.ts +15 -0
  40. package/src/components/data-table/dataTable.tsx +178 -73
  41. package/src/components/date-picker/date-picker.doc.mdx +65 -0
  42. package/src/components/date-picker/date-picker.props.ts +17 -0
  43. package/src/components/date-picker/datePicker.tsx +31 -1
  44. package/src/components/dialog/dialog.doc.mdx +54 -0
  45. package/src/components/dialog/dialog.props.ts +7 -0
  46. package/src/components/dialog/dialog.tsx +26 -0
  47. package/src/components/divider/divider.doc.mdx +42 -0
  48. package/src/components/divider/divider.props.ts +5 -0
  49. package/src/components/divider/divider.tsx +16 -0
  50. package/src/components/drawer/drawer.doc.mdx +59 -0
  51. package/src/components/drawer/drawer.props.ts +9 -0
  52. package/src/components/drawer/drawer.tsx +20 -0
  53. package/src/components/dropfile/dropfile.doc.mdx +59 -0
  54. package/src/components/dropfile/dropfile.props.ts +41 -0
  55. package/src/components/dropfile/dropfile.tsx +21 -33
  56. package/src/components/empty-state/empty-state.doc.mdx +50 -0
  57. package/src/components/empty-state/empty-state.props.ts +5 -0
  58. package/src/components/empty-state/empty-state.tsx +16 -0
  59. package/src/components/flex/flex.doc.mdx +59 -0
  60. package/src/components/flex/flex.props.ts +13 -0
  61. package/src/components/flex/flex.tsx +15 -0
  62. package/src/components/form-builder/fieldRenderer.tsx +52 -2
  63. package/src/components/form-builder/formBuilder.doc.mdx +124 -0
  64. package/src/components/form-builder/formBuilder.props.ts +12 -2
  65. package/src/components/form-builder/formBuilder.tsx +31 -0
  66. package/src/components/form-header/form-header.doc.mdx +38 -0
  67. package/src/components/form-header/form-header.props.ts +3 -0
  68. package/src/components/form-header/form-header.stories.tsx +53 -0
  69. package/src/components/form-header/form-header.tsx +11 -0
  70. package/src/components/grid/grid.doc.mdx +54 -0
  71. package/src/components/grid/grid.props.ts +13 -0
  72. package/src/components/grid/grid.tsx +26 -2
  73. package/src/components/image/image.doc.mdx +44 -0
  74. package/src/components/image/image.props.ts +5 -0
  75. package/src/components/image/image.stories.tsx +49 -0
  76. package/src/components/image/image.tsx +19 -0
  77. package/src/components/input/input.doc.mdx +70 -0
  78. package/src/components/input/input.props.ts +34 -2
  79. package/src/components/input/input.tsx +29 -0
  80. package/src/components/layout/layout.doc.mdx +51 -0
  81. package/src/components/layout/layout.props.ts +5 -0
  82. package/src/components/layout/layout.tsx +41 -17
  83. package/src/components/loader/loader.doc.mdx +43 -0
  84. package/src/components/loader/loader.props.ts +4 -0
  85. package/src/components/loader/loader.tsx +17 -0
  86. package/src/components/navbar/navbar.doc.mdx +77 -0
  87. package/src/components/navbar/navbar.props.ts +37 -1
  88. package/src/components/navbar/navbar.stories.tsx +84 -0
  89. package/src/components/navbar/navbar.tsx +78 -46
  90. package/src/components/page/page.doc.mdx +80 -0
  91. package/src/components/page/page.props.ts +25 -0
  92. package/src/components/page/page.tsx +35 -7
  93. package/src/components/page-header/page-header.doc.mdx +54 -0
  94. package/src/components/page-header/page-header.props.ts +11 -0
  95. package/src/components/page-header/page-header.stories.tsx +14 -0
  96. package/src/components/page-header/page-header.tsx +50 -15
  97. package/src/components/pagination/pagination.doc.mdx +62 -0
  98. package/src/components/pagination/pagination.props.ts +11 -32
  99. package/src/components/pagination/pagination.tsx +17 -0
  100. package/src/components/popover/popover.doc.mdx +53 -0
  101. package/src/components/popover/popover.props.ts +8 -0
  102. package/src/components/popover/popover.tsx +13 -0
  103. package/src/components/progress/progress.doc.mdx +48 -0
  104. package/src/components/progress/progress.props.ts +8 -0
  105. package/src/components/progress/progress.tsx +9 -0
  106. package/src/components/radio/radio.doc.mdx +62 -0
  107. package/src/components/radio/radio.props.ts +11 -0
  108. package/src/components/radio/radio.tsx +18 -0
  109. package/src/components/search-select/search-select.doc.mdx +72 -0
  110. package/src/components/search-select/search-select.props.ts +23 -18
  111. package/src/components/search-select/search-select.tsx +27 -2
  112. package/src/components/searchTable/searchTable.doc.mdx +79 -0
  113. package/src/components/searchTable/searchTable.props.ts +42 -3
  114. package/src/components/searchTable/searchTable.stories.tsx +74 -0
  115. package/src/components/searchTable/searchTable.tsx +23 -0
  116. package/src/components/segmented-control/segmented-control.doc.mdx +60 -0
  117. package/src/components/segmented-control/segmented-control.props.ts +12 -0
  118. package/src/components/segmented-control/segmented-control.tsx +15 -0
  119. package/src/components/select/select.doc.mdx +75 -0
  120. package/src/components/select/select.props.ts +22 -0
  121. package/src/components/select/select.tsx +2 -5
  122. package/src/components/sidebar/sidebar.doc.mdx +86 -0
  123. package/src/components/sidebar/sidebar.props.ts +22 -0
  124. package/src/components/sidebar/sidebar.tsx +22 -0
  125. package/src/components/skeleton/skeleton.doc.mdx +43 -0
  126. package/src/components/skeleton/skeleton.props.ts +8 -0
  127. package/src/components/skeleton/skeleton.tsx +10 -0
  128. package/src/components/slide/slide.doc.mdx +46 -0
  129. package/src/components/slide/slide.props.ts +11 -24
  130. package/src/components/slide/slide.tsx +10 -1
  131. package/src/components/slider/slider.doc.mdx +49 -0
  132. package/src/components/slider/slider.props.ts +9 -0
  133. package/src/components/slider/slider.tsx +15 -0
  134. package/src/components/stack/stack.doc.mdx +126 -0
  135. package/src/components/stack/stack.props.ts +18 -0
  136. package/src/components/stack/stack.stories.tsx +221 -16
  137. package/src/components/stack/stack.tsx +21 -0
  138. package/src/components/stat-card/stat-card.doc.mdx +48 -0
  139. package/src/components/stat-card/stat-card.props.ts +9 -0
  140. package/src/components/stat-card/stat-card.tsx +10 -0
  141. package/src/components/stepper/stepper.doc.mdx +54 -0
  142. package/src/components/stepper/stepper.props.ts +11 -1
  143. package/src/components/stepper/stepper.tsx +15 -0
  144. package/src/components/table/table.doc.mdx +58 -0
  145. package/src/components/table/table.props.ts +17 -0
  146. package/src/components/table/table.tsx +199 -84
  147. package/src/components/tabs/tabs.doc.mdx +52 -0
  148. package/src/components/tabs/tabs.props.ts +11 -0
  149. package/src/components/tabs/tabs.tsx +14 -0
  150. package/src/components/text/text.doc.mdx +41 -0
  151. package/src/components/text/text.props.ts +5 -0
  152. package/src/components/text/text.stories.tsx +67 -0
  153. package/src/components/text/text.tsx +10 -0
  154. package/src/components/textarea/textarea.doc.mdx +64 -0
  155. package/src/components/textarea/textarea.props.ts +11 -0
  156. package/src/components/textarea/textarea.tsx +16 -0
  157. package/src/components/theme-provider/themeProvider.doc.mdx +75 -0
  158. package/src/components/theme-provider/themeProvider.props.ts +3 -0
  159. package/src/components/theme-provider/themeProvider.stories.tsx +59 -0
  160. package/src/components/theme-provider/themeProvider.tsx +14 -0
  161. package/src/components/time-picker/timePicker.doc.mdx +68 -0
  162. package/src/components/time-picker/timePicker.props.ts +14 -0
  163. package/src/components/time-picker/timePicker.tsx +22 -1
  164. package/src/components/toast/toast.doc.mdx +50 -0
  165. package/src/components/toast/toast.props.ts +5 -0
  166. package/src/components/toast/toast.tsx +21 -0
  167. package/src/components/tooltip/tooltip.doc.mdx +47 -0
  168. package/src/components/tooltip/tooltip.props.ts +6 -0
  169. package/src/components/tooltip/tooltip.tsx +19 -0
  170. package/src/components/topbar/topbar.doc.mdx +69 -0
  171. package/src/components/topbar/topbar.props.ts +15 -0
  172. package/src/components/topbar/topbar.tsx +38 -0
  173. package/src/components/triple-filter/tripleFilter.doc.mdx +62 -0
  174. package/src/components/triple-filter/tripleFilter.props.ts +7 -0
  175. package/src/components/triple-filter/tripleFilter.tsx +32 -0
  176. package/src/index.css +17 -0
  177. package/src/showcases/DataShowcases.tsx +529 -45
  178. package/src/showcases/FormShowcases.tsx +399 -29
  179. package/src/showcases/HomeShowcase.tsx +252 -272
  180. package/src/showcases/LayoutPrimitivesShowcases.tsx +1224 -248
  181. package/src/showcases/PageShowcases.tsx +868 -151
  182. package/src/showcases/ShowcaseLayout.tsx +237 -73
  183. package/src/showcases/StructureShowcases.tsx +1039 -97
  184. package/src/types/table.types.ts +1 -1
  185. package/src/utils/styles.ts +2 -1
@@ -1,46 +1,527 @@
1
1
  import React, { useState } from "react";
2
- import { FaCheckCircle } from "react-icons/fa";
3
- import { ITCard, ITButton, ITInput, ITSlideToggle, ITText, ITNavbar } from "../index";
2
+ import {
3
+ FaHome,
4
+ FaUsers,
5
+ FaShoppingCart,
6
+ FaCog,
7
+ FaBoxOpen,
8
+ FaChartLine,
9
+ FaFileAlt,
10
+ FaBell,
11
+ FaCode,
12
+ FaCheck,
13
+ FaPlayCircle,
14
+ FaPlus,
15
+ FaSearch,
16
+ } from "react-icons/fa";
17
+ import {
18
+ ITCard,
19
+ ITButton,
20
+ ITInput,
21
+ ITAvatar,
22
+ ITFlex,
23
+ ITSlideToggle,
24
+ ITText,
25
+ ITNavbar,
26
+ ITLayout,
27
+ ITStack,
28
+ ITStatCard,
29
+ ITGrid,
30
+ ITPageHeader,
31
+ ITBadget,
32
+ ITDivider,
33
+ ITProgress,
34
+ ITSelect,
35
+ } from "../index";
4
36
  import { ShowcaseLayout, CodeViewer } from "./ShowcaseLayout";
5
37
 
38
+ // ─────────────────────────────────────────
6
39
  // 1. ITCard Showcase
40
+ // ─────────────────────────────────────────
41
+
42
+ const CARD_PATTERN_CODES = {
43
+ course: `<ITCard
44
+ title="Advanced TypeScript Patterns"
45
+ image="/courses/typescript.jpg"
46
+ onClick={() => resume(course.id)}
47
+ actions={
48
+ <ITButton label="Continue lesson 8" variant="filled" color="primary" size="small" />
49
+ }
50
+ >
51
+ <ITFlex align="center" gap={3} className="mb-3">
52
+ <ITText muted className="text-xs">12 lessons</ITText>
53
+ <ITDivider orientation="vertical" className="h-3" />
54
+ <ITText muted className="text-xs font-mono">4h 32m</ITText>
55
+ <ITDivider orientation="vertical" className="h-3" />
56
+ <ITBadget label="★ 4.9" color="warning" size="small" variant="outlined" />
57
+ </ITFlex>
58
+ <ITProgress value={66} color="primary" size="md" />
59
+ <ITFlex justify="between" align="center" className="mt-2">
60
+ <ITText muted className="text-xs">66% complete</ITText>
61
+ <ITText muted className="text-xs">Lesson 8 of 12</ITText>
62
+ </ITFlex>
63
+ </ITCard>`,
64
+ pricing: `<div className="relative">
65
+ <ITBadget
66
+ label="Most popular"
67
+ color="primary"
68
+ size="small"
69
+ className="absolute -top-2 left-4 z-10 shadow-md"
70
+ />
71
+ <ITCard
72
+ title="Scale"
73
+ className="ring-2 ring-primary-500/30"
74
+ actions={
75
+ <ITButton label="Start 14-day free trial"
76
+ variant="filled" color="primary" size="medium" className="w-full" />
77
+ }
78
+ >
79
+ <ITFlex align="baseline" gap={1}>
80
+ <ITText as="span" className="text-4xl font-extrabold font-mono">$79</ITText>
81
+ <ITText muted as="span" className="text-xs">/ month</ITText>
82
+ </ITFlex>
83
+ <ITText muted as="span" className="text-xs mt-1 block">Billed annually · Up to 25 seats</ITText>
84
+ <ITDivider className="my-4" />
85
+ <ITStack spacing={2}>
86
+ {FEATURES.map(f => (
87
+ <ITFlex align="center" gap={2}>
88
+ <FaCheck className="text-primary-500 shrink-0" />
89
+ <ITText as="span" className="text-sm text-slate-700">{f}</ITText>
90
+ </ITFlex>
91
+ ))}
92
+ </ITStack>
93
+ </ITCard>
94
+ </div>`,
95
+ activity: `<ITCard
96
+ actions={
97
+ <ITFlex gap={2}>
98
+ <ITButton label="Reply" variant="text" color="primary" size="small" />
99
+ <ITButton label="Mute" variant="text" color="gray" size="small" />
100
+ </ITFlex>
101
+ }
102
+ >
103
+ <ITFlex align="start" gap={3}>
104
+ <ITAvatar initials="DK" size="md" />
105
+ <div className="min-w-0 flex-1">
106
+ <ITText className="text-sm leading-relaxed">
107
+ <ITText as="span" className="font-semibold">Daniela Klein</ITText>
108
+ {' '}deployed{' '}
109
+ <ITBadget label="v2.4.1" color="primary" size="small" variant="outlined" />
110
+ {' '}to <ITText as="span" className="font-semibold">production</ITText>.
111
+ </ITText>
112
+ <ITText muted className="text-xs mt-1.5 block">3 minutes ago · api-service</ITText>
113
+ <ITFlex align="center" gap={2} className="mt-3">
114
+ <ITFlex align="center" gap={1}>
115
+ <FaPlayCircle size={10} />
116
+ <ITText muted as="span" className="text-xs">4 reactions</ITText>
117
+ </ITFlex>
118
+ <ITDivider orientation="vertical" className="h-3" />
119
+ <ITFlex align="center" gap={1}>
120
+ <FaFileAlt size={10} />
121
+ <ITText muted as="span" className="text-xs">2 comments</ITText>
122
+ </ITFlex>
123
+ </ITFlex>
124
+ </div>
125
+ </ITFlex>
126
+ </ITCard>`,
127
+ teamMember: `<ITCard
128
+ title="Mariana Reyes"
129
+ image="/team/cover.jpg"
130
+ imageClassName="h-32"
131
+ onClick={() => openProfile(user.id)}
132
+ actions={
133
+ <ITFlex gap={2}>
134
+ <ITButton label="Message" variant="filled" color="primary" size="small" />
135
+ <ITButton label="View profile" variant="outlined" color="gray" size="small" />
136
+ </ITFlex>
137
+ }
138
+ >
139
+ <ITFlex align="center" gap={3} className="mb-3">
140
+ <ITAvatar initials="MR" size="md" />
141
+ <div>
142
+ <ITText as="span" className="text-sm font-semibold block">Engineering Lead</ITText>
143
+ <ITText muted as="span" className="text-xs">Madrid · 142 commits / month</ITText>
144
+ </div>
145
+ </ITFlex>
146
+ <ITText className="text-sm leading-relaxed">
147
+ Building resilient distributed systems and mentoring the platform team across 4 time zones.
148
+ </ITText>
149
+ <ITFlex gap={1} wrap="wrap" className="mt-3">
150
+ {['TypeScript', 'Distributed systems', 'Open source'].map(t => (
151
+ <ITBadget key={t} label={t} color="primary" size="small" variant="outlined" />
152
+ ))}
153
+ </ITFlex>
154
+ </ITCard>`,
155
+ release: `<ITCard
156
+ title="Midnight Frequencies"
157
+ image="/albums/midnight.jpg"
158
+ imageClassName="h-40"
159
+ onClick={() => play(album.id)}
160
+ actions={
161
+ <ITButton label="Play album" variant="filled" color="primary" size="small" />
162
+ }
163
+ >
164
+ <ITFlex justify="between" gap={3}>
165
+ <div className="min-w-0">
166
+ <ITText as="span" className="text-sm font-semibold block">Aurelia Sound</ITText>
167
+ <ITText muted as="span" className="text-xs">Released Mar 2026</ITText>
168
+ </div>
169
+ <ITStack spacing={0} align="end">
170
+ <ITText as="span" className="text-xs font-mono font-semibold">9 tracks</ITText>
171
+ <ITText muted as="span" className="text-[10px] font-mono">38 min</ITText>
172
+ </ITStack>
173
+ </ITFlex>
174
+ <ITFlex align="center" gap={1} className="mt-3">
175
+ {Array.from({length: 5}).map((_, i) => (
176
+ <FaPlay key={i} size={7}
177
+ className={i < 4 ? 'text-primary-500' : 'text-slate-300'} />
178
+ ))}
179
+ <ITText muted as="span" className="text-[10px] font-mono ml-1.5">4.7 · 12.4k plays</ITText>
180
+ </ITFlex>
181
+ </ITCard>`,
182
+ };
183
+
184
+ const TEXT_PATTERN_CODES = {
185
+ articleHeader: `<ITFlex align="center" gap={2} className="mb-3">
186
+ <ITBadget label="ENGINEERING" color="primary" size="small" variant="outlined" />
187
+ <ITText muted as="span" className="text-[11px] uppercase tracking-wider font-semibold">
188
+ Featured
189
+ </ITText>
190
+ </ITFlex>
191
+ <ITText as="h2" className="text-2xl font-bold leading-tight mb-2 block">
192
+ How we cut bundle size by 38% in two weeks
193
+ </ITText>
194
+ <ITText as="p" className="text-sm leading-relaxed mb-3 block">
195
+ A pragmatic walkthrough of our lazy-loading rollout…
196
+ </ITText>
197
+ <ITFlex align="center" gap={3}>
198
+ <ITAvatar initials="MR" size="sm" />
199
+ <ITText as="span" className="text-xs font-semibold">Mariana Reyes</ITText>
200
+ <ITDivider orientation="vertical" className="h-3" />
201
+ <ITText muted as="span" className="text-xs">Nov 14, 2025</ITText>
202
+ <ITDivider orientation="vertical" className="h-3" />
203
+ <ITText muted as="span" className="text-xs font-mono">8 min read</ITText>
204
+ </ITFlex>`,
205
+ sectionHeading: `<ITFlex justify="between" align="start" gap={4} className="mb-2">
206
+ <ITText as="h2" className="text-xl font-bold">Recent activity</ITText>
207
+ <ITButton label="View all →" variant="text" color="primary" size="small" />
208
+ </ITFlex>
209
+ <ITText as="p" muted className="text-sm leading-relaxed">
210
+ Latest commits, deployments and reviews from your team this week.
211
+ </ITText>`,
212
+ emptyState: `<ITStack spacing={3} alignItems="center" className="text-center">
213
+ <div className="w-14 h-14 rounded-2xl bg-gradient-to-br from-primary-500 to-primary-700">
214
+ <FaBell className="text-white" />
215
+ </div>
216
+ <ITText as="h3" className="text-lg font-bold">You're all caught up</ITText>
217
+ <ITText as="p" className="text-sm">
218
+ No new notifications.
219
+ </ITText>
220
+ <ITText as="p" muted className="text-xs">
221
+ Last checked 2 minutes ago
222
+ </ITText>
223
+ </ITStack>`,
224
+ inlineContent: `<ITText as="p" className="text-sm leading-relaxed">
225
+ <ITText as="span" className="font-semibold">Daniela Klein</ITText>
226
+ {' '}pushed commit{' '}
227
+ <ITText as="code" className="px-1.5 py-0.5 rounded bg-slate-100
228
+ text-primary-600 font-mono text-[11px]">a3f9c2e</ITText>
229
+ {' '}to <ITText as="span" className="font-semibold">main</ITText>.
230
+ </ITText>`,
231
+ formLabels: `<ITText as="label" className="text-sm font-semibold block mb-1">
232
+ Workspace name <ITText as="span" className="text-danger-500">*</ITText>
233
+ </ITText>
234
+ <ITInput name="ws_name" placeholder="my-awesome-project" />
235
+ <ITText muted as="span" className="text-[11px] mt-1 block">
236
+ Lowercase letters, numbers and hyphens only.
237
+ </ITText>`,
238
+ };
239
+
240
+ const GallerySection = ({ title, subtitle, children }: { title: string; subtitle?: string; children: React.ReactNode }) => (
241
+ <div>
242
+ <div className="mb-5">
243
+ <h3 className="text-base font-bold text-slate-800 dark:text-slate-100 flex items-center gap-2">
244
+ <span className="w-1 h-5 rounded-full bg-gradient-to-b from-primary-500 to-primary-700" />
245
+ {title}
246
+ </h3>
247
+ {subtitle && <p className="text-xs text-slate-500 dark:text-slate-400 mt-1 ml-3">{subtitle}</p>}
248
+ </div>
249
+ {children}
250
+ </div>
251
+ );
252
+
253
+ const PatternCard = ({ title, desc, code, children }: { title: string; desc?: string; code?: string; children: React.ReactNode }) => {
254
+ const [showCode, setShowCode] = useState(false);
255
+ return (
256
+ <div className="bg-white dark:bg-slate-900/60 rounded-2xl border border-slate-200 dark:border-slate-700 shadow-sm hover:shadow-md transition-shadow overflow-hidden">
257
+ <div className="flex items-start justify-between gap-2 p-4 pb-3">
258
+ <div className="min-w-0">
259
+ <p className="text-sm font-semibold text-slate-800 dark:text-slate-100">{title}</p>
260
+ {desc && <p className="text-[11px] text-slate-500 dark:text-slate-400 mt-0.5">{desc}</p>}
261
+ </div>
262
+ {code && (
263
+ <ITButton variant="outlined" color="gray" size="small" onClick={() => setShowCode(!showCode)}>
264
+ <ITFlex align="center" gap={1}>
265
+ <FaCode size={9} />
266
+ {showCode ? "Hide code" : "Code"}
267
+ </ITFlex>
268
+ </ITButton>
269
+ )}
270
+ </div>
271
+ <div className="px-4 pb-4">{children}</div>
272
+ {showCode && code && (
273
+ <div className="px-4 pb-4 border-t border-slate-200 dark:border-slate-700 pt-3">
274
+ <CodeViewer code={code} compact />
275
+ </div>
276
+ )}
277
+ </div>
278
+ );
279
+ };
280
+
7
281
  export const CardShowcase = () => {
8
- const [title, setTitle] = useState("Registro de Logs del Sistema");
282
+ const [title, setTitle] = useState("Monthly revenue");
9
283
  const [showActions, setShowActions] = useState(true);
284
+ const [showImage, setShowImage] = useState(false);
285
+ const [clickable, setClickable] = useState(false);
10
286
 
11
- const code = `<ITCard\n title="${title}"\n actions={${showActions ? "<ITButton label='Exportar' />" : "undefined"}}\n>\n <p>Contenido interno de la tarjeta.</p>\n</ITCard>`;
287
+ const buildCode = () => {
288
+ const lines = [`<ITCard`];
289
+ if (title) lines.push(` title="${title}"`);
290
+ if (showImage) lines.push(` image="https://images.unsplash.com/photo-1554224155-6726b3ff858f?w=400&h=200&fit=crop"`);
291
+ if (clickable) lines.push(` onClick={() => openDetails()}`);
292
+ if (showActions) lines.push(` actions={<ITButton label="View" variant="filled" color="primary" size="small" />}`);
293
+ lines.push(`>`);
294
+ lines.push(` <p className="text-3xl font-bold">$48,230</p>`);
295
+ lines.push(` <p className="text-xs text-emerald-600">↑ 12.4% vs last month</p>`);
296
+ lines.push(`</ITCard>`);
297
+ return lines.join("\n");
298
+ };
12
299
 
13
300
  return (
14
301
  <ShowcaseLayout
15
302
  title="ITCard"
16
- description="Tarjetas de contenedor multipropósito con cabecera y espacio para acciones."
17
- code={code}
303
+ description="Contenedor multipropósito con cabecera opcional, imagen, contenido y pie de acciones. Se vuelve interactivo con `onClick` (efecto hover)."
304
+ code={buildCode()}
18
305
  demo={
19
- <div className="w-full max-w-md">
20
- <ITCard
21
- title={title}
22
- actions={showActions ? <ITButton label="Exportar" color="primary" size="small" variant="outlined" /> : undefined}
23
- >
24
- <div className="space-y-3">
25
- <p className="text-sm text-slate-600 dark:text-slate-300">
26
- Esta es una tarjeta administrativa estándar AXZY. Es ideal para agrupar paneles de control, tablas y formularios.
306
+ <div className="w-full max-w-xl flex flex-col">
307
+ <div className="min-h-[360px]">
308
+ <ITCard
309
+ title={title || undefined}
310
+ image={showImage ? "https://images.unsplash.com/photo-1554224155-6726b3ff858f?w=400&h=200&fit=crop" : undefined}
311
+ actions={showActions ? (
312
+ <ITButton label="View details" variant="filled" color="primary" size="small" />
313
+ ) : undefined}
314
+ onClick={clickable ? () => {} : undefined}
315
+ className="max-w-sm mx-auto"
316
+ >
317
+ <p className="text-3xl font-extrabold text-slate-800 dark:text-slate-100 font-mono">$48,230</p>
318
+ <p className="text-xs text-emerald-600 dark:text-emerald-400 font-semibold mt-1 flex items-center gap-1">
319
+ <span>↑</span> 12.4% vs last month
27
320
  </p>
28
- <div className="p-3 bg-emerald-50 dark:bg-emerald-950/20 border border-emerald-100 dark:border-emerald-900 rounded-xl flex items-center gap-2">
29
- <FaCheckCircle className="text-emerald-500" />
30
- <span className="text-xs font-medium text-emerald-800 dark:text-emerald-300">Estado de servidor: Conectado</span>
31
- </div>
32
- </div>
33
- </ITCard>
321
+ <p className="text-xs text-slate-500 dark:text-slate-400 mt-3">
322
+ Total revenue across all active subscriptions for the current billing cycle.
323
+ </p>
324
+ </ITCard>
325
+ </div>
326
+
327
+ {/* Fixed footer with active-property badges */}
328
+ <div className="sticky bottom-0 mt-4 -mx-6 -mb-6 px-6 py-3 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-t border-slate-200 dark:border-slate-700 flex items-center flex-wrap gap-1.5 text-[10px] font-mono">
329
+ <span className="text-[9px] uppercase tracking-wider font-bold text-slate-400 dark:text-slate-500 mr-1">Active:</span>
330
+ {title && <span className="px-2 py-0.5 rounded-md bg-slate-900 text-white dark:bg-white dark:text-slate-900 font-semibold">title</span>}
331
+ {showImage && <span className="px-2 py-0.5 rounded-md bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300">image</span>}
332
+ {showActions && <span className="px-2 py-0.5 rounded-md bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300">actions</span>}
333
+ {clickable && <span className="px-2 py-0.5 rounded-md bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300">onClick</span>}
334
+ </div>
34
335
  </div>
35
336
  }
36
337
  controls={
37
- <>
38
- <ITInput name="title_ctrl" label="Título de Tarjeta" value={title} onChange={(e: any) => setTitle(e.target.value)} onBlur={() => { }} />
39
- <div className="flex items-center justify-between pt-2">
40
- <span className="text-sm font-semibold text-gray-700">Mostrar Botón de Acción</span>
338
+ <ITStack spacing={4}>
339
+ <ITInput
340
+ name="title_ctrl"
341
+ label="Title"
342
+ value={title}
343
+ onChange={(e: any) => setTitle(e.target.value)}
344
+ onBlur={() => { }}
345
+ placeholder="Leave empty to hide"
346
+ />
347
+ <div className="flex items-center justify-between pt-1">
348
+ <span className="text-sm font-semibold text-slate-700 dark:text-slate-300">Show image</span>
349
+ <ITSlideToggle isOn={showImage} onToggle={setShowImage} size="sm" />
350
+ </div>
351
+ <div className="flex items-center justify-between">
352
+ <span className="text-sm font-semibold text-slate-700 dark:text-slate-300">Show actions</span>
41
353
  <ITSlideToggle isOn={showActions} onToggle={setShowActions} size="sm" />
42
354
  </div>
43
- </>
355
+ <div className="flex items-center justify-between">
356
+ <span className="text-sm font-semibold text-slate-700 dark:text-slate-300">Interactive (onClick)</span>
357
+ <ITSlideToggle isOn={clickable} onToggle={setClickable} size="sm" />
358
+ </div>
359
+ </ITStack>
360
+ }
361
+ gallery={
362
+ <ITStack spacing={8}>
363
+ <GallerySection
364
+ title="Real UI cases"
365
+ subtitle="Production-ready card layouts built with ITCard"
366
+ >
367
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-5">
368
+
369
+ {/* 1. Course progress — ITProgress + ITBadget + ITDivider + ITText */}
370
+ <PatternCard
371
+ title="Course progress"
372
+ desc="ITProgress + ITBadget + ITDivider + ITText"
373
+ code={CARD_PATTERN_CODES.course}
374
+ >
375
+ <div className="max-w-sm mx-auto">
376
+ <ITCard
377
+ title="Advanced TypeScript Patterns"
378
+ image="https://images.unsplash.com/photo-1516321318423-f06f85e504b3?w=600&h=200&fit=crop"
379
+ onClick={() => {}}
380
+ actions={
381
+ <ITButton label="Continue lesson 8" variant="filled" color="primary" size="small" />
382
+ }
383
+ >
384
+ <ITFlex align="center" gap={3} className="mb-3">
385
+ <ITText muted className="text-xs">12 lessons</ITText>
386
+ <ITDivider orientation="vertical" className="h-3" />
387
+ <ITText muted className="text-xs font-mono">4h 32m</ITText>
388
+ <ITDivider orientation="vertical" className="h-3" />
389
+ <ITBadget label="★ 4.9" color="warning" size="small" variant="outlined" />
390
+ </ITFlex>
391
+ <ITProgress value={66} color="primary" size="md" />
392
+ <ITFlex justify="between" align="center" className="mt-2">
393
+ <ITText muted className="text-xs">66% complete</ITText>
394
+ <ITText muted className="text-xs">Lesson 8 of 12</ITText>
395
+ </ITFlex>
396
+ <ITText className="text-xs mt-2 block">
397
+ Next up: <ITText as="span" className="font-semibold text-slate-700">Conditional types deep dive</ITText>
398
+ </ITText>
399
+ </ITCard>
400
+ </div>
401
+ </PatternCard>
402
+
403
+ {/* 2. Featured pricing plan — ITBadget outside + ITFlex + ITStack + ITDivider */}
404
+ <PatternCard
405
+ title="Featured pricing plan"
406
+ desc="ITBadget + ITDivider + ITStack with ITFlex items"
407
+ code={CARD_PATTERN_CODES.pricing}
408
+ >
409
+ <div className="max-w-sm mx-auto pt-3">
410
+ <div className="relative">
411
+ <ITBadget
412
+ label="Most popular"
413
+ color="primary"
414
+ size="small"
415
+ className="absolute -top-2 left-4 z-10 shadow-md"
416
+ />
417
+ <ITCard
418
+ title="Scale"
419
+ className="ring-2 ring-primary-500/30"
420
+ actions={
421
+ <ITButton label="Start 14-day free trial" variant="filled" color="primary" size="medium" className="w-full" />
422
+ }
423
+ >
424
+ <ITFlex align="baseline" gap={1}>
425
+ <ITText as="span" className="text-4xl font-extrabold font-mono text-slate-800">$79</ITText>
426
+ <ITText muted as="span" className="text-xs">/ month</ITText>
427
+ </ITFlex>
428
+ <ITText muted as="span" className="text-xs mt-1 block">Billed annually · Up to 25 seats</ITText>
429
+ <ITDivider className="my-4" />
430
+ <ITStack spacing={2}>
431
+ {['Unlimited projects', 'Advanced analytics', 'Priority support', 'SSO & audit logs', 'Custom integrations'].map((f) => (
432
+ <ITFlex key={f} align="center" gap={2}>
433
+ <FaCheck size={11} className="text-primary-500 shrink-0" />
434
+ <ITText as="span" className="text-sm text-slate-700">{f}</ITText>
435
+ </ITFlex>
436
+ ))}
437
+ </ITStack>
438
+ </ITCard>
439
+ </div>
440
+ </div>
441
+ </PatternCard>
442
+
443
+ {/* 3. Activity feed item — ITText + ITBadget for commit hash + ITDivider separators */}
444
+ <PatternCard
445
+ title="Activity feed item"
446
+ desc="ITText + ITBadget (commit hash) + ITDivider separators"
447
+ code={CARD_PATTERN_CODES.activity}
448
+ >
449
+ <div className="max-w-md mx-auto">
450
+ <ITCard
451
+ actions={
452
+ <ITFlex gap={2}>
453
+ <ITButton label="Reply" variant="text" color="primary" size="small" />
454
+ <ITButton label="Mute" variant="text" color="gray" size="small" />
455
+ </ITFlex>
456
+ }
457
+ >
458
+ <ITFlex align="start" gap={3}>
459
+ <ITAvatar initials="DK" size="md" />
460
+ <div className="min-w-0 flex-1">
461
+ <ITText className="text-sm leading-relaxed text-slate-700">
462
+ <ITText as="span" className="font-semibold">Daniela Klein</ITText>
463
+ {' '}deployed{' '}
464
+ <ITBadget label="v2.4.1" color="primary" size="small" variant="outlined" />
465
+ {' '}to <ITText as="span" className="font-semibold">production</ITText>.
466
+ </ITText>
467
+ <ITText muted className="text-xs mt-1.5 block">3 minutes ago · api-service</ITText>
468
+ <ITFlex align="center" gap={2} className="mt-3">
469
+ <ITFlex align="center" gap={1}>
470
+ <FaPlayCircle size={10} className="text-slate-500" />
471
+ <ITText muted as="span" className="text-xs">4 reactions</ITText>
472
+ </ITFlex>
473
+ <ITDivider orientation="vertical" className="h-3" />
474
+ <ITFlex align="center" gap={1}>
475
+ <FaFileAlt size={10} className="text-slate-500" />
476
+ <ITText muted as="span" className="text-xs">2 comments</ITText>
477
+ </ITFlex>
478
+ </ITFlex>
479
+ </div>
480
+ </ITFlex>
481
+ </ITCard>
482
+ </div>
483
+ </PatternCard>
484
+
485
+ {/* 4. Team member profile — ITFlex + ITBadget for skills + ITText throughout */}
486
+ <PatternCard
487
+ title="Team member profile"
488
+ desc="ITFlex + ITBadget skills + ITText throughout"
489
+ code={CARD_PATTERN_CODES.teamMember}
490
+ >
491
+ <div className="max-w-sm mx-auto">
492
+ <ITCard
493
+ title="Mariana Reyes"
494
+ image="https://images.unsplash.com/photo-1497366216548-37526070297c?w=600&h=200&fit=crop"
495
+ imageClassName="h-32"
496
+ onClick={() => {}}
497
+ actions={
498
+ <ITFlex gap={2}>
499
+ <ITButton label="Message" variant="filled" color="primary" size="small" />
500
+ <ITButton label="View profile" variant="outlined" color="gray" size="small" />
501
+ </ITFlex>
502
+ }
503
+ >
504
+ <ITFlex align="center" gap={3} className="mb-3">
505
+ <ITAvatar initials="MR" size="md" />
506
+ <div className="min-w-0">
507
+ <ITText as="span" className="text-sm font-semibold text-slate-800 block">Engineering Lead</ITText>
508
+ <ITText muted as="span" className="text-xs">Madrid · 142 commits / month</ITText>
509
+ </div>
510
+ </ITFlex>
511
+ <ITText className="text-sm leading-relaxed text-slate-600">
512
+ Building resilient distributed systems and mentoring the platform team across 4 time zones.
513
+ </ITText>
514
+ <ITFlex gap={1} wrap="wrap" className="mt-3">
515
+ {['TypeScript', 'Distributed systems', 'Open source'].map((t) => (
516
+ <ITBadget key={t} label={t} color="primary" size="small" variant="outlined" />
517
+ ))}
518
+ </ITFlex>
519
+ </ITCard>
520
+ </div>
521
+ </PatternCard>
522
+ </div>
523
+ </GallerySection>
524
+ </ITStack>
44
525
  }
45
526
  />
46
527
  );
@@ -48,105 +529,566 @@ export const CardShowcase = () => {
48
529
 
49
530
  // 2. ITText Showcase
50
531
  export const TextShowcase = () => {
51
- const [bold, setBold] = useState(false);
532
+ const [element, setElement] = useState("p");
52
533
  const [size, setSize] = useState("text-base");
534
+ const [bold, setBold] = useState(false);
535
+ const [muted, setMuted] = useState(false);
536
+ const [maxLength, setMaxLength] = useState<string>("0");
537
+ const [lineClamp, setLineClamp] = useState(0);
538
+ const [breakLength, setBreakLength] = useState<string>("0");
53
539
 
54
- const code = `<ITText className="${bold ? "font-bold" : ""} ${size}">\n Texto tipográfico estándar AXZY\n</ITText>`;
540
+ const FULL_SAMPLE =
541
+ "AXZY UI System provee una capa tipográfica consistente sobre React, permitiendo que cada componente respire con la misma jerarquía visual sin importar el tema o el contexto.";
542
+
543
+ const maxLengthNum = maxLength === "" ? 0 : Number(maxLength) || 0;
544
+ const breakLengthNum = breakLength === "" ? 0 : Number(breakLength) || 0;
545
+
546
+ const buildCode = () => {
547
+ const lines = [`<ITText`];
548
+ if (element !== "p") lines.push(` as="${element}"`);
549
+ if (muted) lines.push(` muted`);
550
+ const cls = [
551
+ bold ? "font-bold" : "",
552
+ size,
553
+ lineClamp > 0 ? `line-clamp-${lineClamp}` : "",
554
+ "text-slate-800 dark:text-white",
555
+ ].filter(Boolean).join(" ");
556
+ lines.push(` className="${cls.trim()}"`);
557
+ if (maxLengthNum > 0) lines.push(` // truncated at ${maxLengthNum} chars`);
558
+ if (breakLengthNum > 0) lines.push(` // wrap hint every ${breakLengthNum} chars`);
559
+ lines.push(`>`);
560
+ lines.push(` ${FULL_SAMPLE.slice(0, 80)}${FULL_SAMPLE.length > 80 ? "…" : ""}`);
561
+ lines.push(`</ITText>`);
562
+ return lines.join("\n");
563
+ };
564
+
565
+ const processedText = (() => {
566
+ let t = FULL_SAMPLE;
567
+ if (maxLengthNum > 0 && t.length > maxLengthNum) t = t.slice(0, maxLengthNum).trimEnd() + "…";
568
+ return t;
569
+ })();
570
+
571
+ const renderWithBreaks = (text: string) => {
572
+ if (!breakLengthNum || breakLengthNum <= 0) return text;
573
+ const parts: string[] = [];
574
+ for (let i = 0; i < text.length; i += breakLengthNum) {
575
+ parts.push(text.slice(i, i + breakLengthNum));
576
+ }
577
+ return parts.join("\u200B");
578
+ };
579
+
580
+ const clampClass = lineClamp > 0 ? `line-clamp-${lineClamp}` : "";
55
581
 
56
582
  return (
57
583
  <ShowcaseLayout
58
584
  title="ITText"
59
- description="Contenedor tipográfico básico alineado con las tipografías globales del tema."
60
- code={code}
585
+ description="Wrapper tipográfico semántico. Renderiza cualquier elemento HTML, con soporte para truncado por caracteres, clamp de líneas y corte programático."
586
+ code={buildCode()}
61
587
  demo={
62
- <ITText className={`${bold ? "font-bold" : ""} ${size} text-slate-800 dark:text-white`}>
63
- Diseñado para inyectar consistencia tipográfica sobre las variables globales de Outfit/Inter.
64
- </ITText>
588
+ <div className="w-full flex flex-col">
589
+ <div className="min-h-[360px] flex items-center justify-center">
590
+ <div className="w-full max-w-md p-6 rounded-2xl bg-white dark:bg-slate-900/60 border border-slate-200 dark:border-slate-700 shadow-sm">
591
+ {/* BIG element indicator — makes the `as` change unmissable */}
592
+ <ITStack spacing={2} alignItems="center" className="mb-5 text-center">
593
+ <ITText muted as="span" className="text-[10px] uppercase tracking-wider font-bold">
594
+ Rendering as
595
+ </ITText>
596
+ <code
597
+ key={element}
598
+ className="inline-block px-3 py-1 rounded-lg bg-slate-900 text-white dark:bg-white dark:text-slate-900 font-mono text-sm font-bold shadow-sm"
599
+ >
600
+ &lt;{element}&gt;
601
+ </code>
602
+ </ITStack>
603
+
604
+ <div key={`wrap-${element}`} className="text-center">
605
+ <ITText
606
+ key={element}
607
+ as={element as any}
608
+ muted={muted}
609
+ className={`${bold ? "font-bold" : ""} ${size} ${clampClass} text-slate-800 dark:text-white block break-words`}
610
+ >
611
+ {element === "code" ? "const axzy = 'design-system';" : renderWithBreaks(processedText)}
612
+ </ITText>
613
+ </div>
614
+ </div>
615
+ </div>
616
+
617
+ {/* Fixed footer with active-property badges */}
618
+ <div className="sticky bottom-0 mt-4 -mx-6 -mb-6 px-6 py-3 bg-white/95 dark:bg-slate-900/95 backdrop-blur-sm border-t border-slate-200 dark:border-slate-700 flex items-center flex-wrap gap-1.5 text-[10px] font-mono">
619
+ <span className="text-[9px] uppercase tracking-wider font-bold text-slate-400 dark:text-slate-500 mr-1">Active:</span>
620
+ {element !== "p" && <span className="px-2 py-0.5 rounded-md bg-slate-900 text-white dark:bg-white dark:text-slate-900 font-semibold">as=&quot;{element}&quot;</span>}
621
+ <span className="px-2 py-0.5 rounded-md bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300">{size}</span>
622
+ {bold && <span className="px-2 py-0.5 rounded-md bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300">font-bold</span>}
623
+ {muted && <span className="px-2 py-0.5 rounded-md bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300">muted</span>}
624
+ {maxLengthNum > 0 && <span className="px-2 py-0.5 rounded-md bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300">max {maxLengthNum}c</span>}
625
+ {lineClamp > 0 && <span className="px-2 py-0.5 rounded-md bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300">clamp-{lineClamp}</span>}
626
+ {breakLengthNum > 0 && <span className="px-2 py-0.5 rounded-md bg-rose-100 dark:bg-rose-900/30 text-rose-700 dark:text-rose-300">break@{breakLengthNum}c</span>}
627
+ </div>
628
+ </div>
65
629
  }
66
630
  controls={
67
- <>
68
- <ITSelectStub
631
+ <ITStack spacing={4}>
632
+ <ITSelect
633
+ name="elem_ctrl"
634
+ label="Elemento HTML (as)"
635
+ value={element}
636
+ onChange={(e) => setElement(e.target.value)}
637
+ options={[
638
+ { label: "Párrafo (p)", value: "p" },
639
+ { label: "Encabezado H1", value: "h1" },
640
+ { label: "Encabezado H2", value: "h2" },
641
+ { label: "Encabezado H3", value: "h3" },
642
+ { label: "Span inline", value: "span" },
643
+ { label: "Etiqueta (label)", value: "label" },
644
+ { label: "Código (code)", value: "code" },
645
+ ]}
646
+ />
647
+ <ITSelect
69
648
  name="sz_ctrl"
70
- label="Tamaño de Fuente"
649
+ label="Tamaño"
71
650
  value={size}
72
- onChange={(e: any) => setSize(e.target.value)}
651
+ onChange={(e) => setSize(e.target.value)}
652
+ options={[
653
+ { label: "XS (12px)", value: "text-xs" },
654
+ { label: "SM (14px)", value: "text-sm" },
655
+ { label: "Base (16px)", value: "text-base" },
656
+ { label: "LG (18px)", value: "text-lg" },
657
+ { label: "XL (20px)", value: "text-xl" },
658
+ { label: "2XL (24px)", value: "text-2xl" },
659
+ ]}
660
+ />
661
+ <ITSelect
662
+ name="clamp_ctrl"
663
+ label="Número de líneas (lineClamp)"
664
+ value={String(lineClamp)}
665
+ onChange={(e) => setLineClamp(Number(e.target.value))}
73
666
  options={[
74
- { label: "Chico (text-xs)", value: "text-xs" },
75
- { label: "Estándar (text-base)", value: "text-base" },
76
- { label: "Grande (text-xl)", value: "text-xl" },
77
- { label: "Título (text-3xl)", value: "text-3xl" }
667
+ { label: "Sin límite", value: "0" },
668
+ { label: "1 línea", value: "1" },
669
+ { label: "2 líneas", value: "2" },
670
+ { label: "3 líneas", value: "3" },
671
+ { label: "4 líneas", value: "4" },
78
672
  ]}
79
673
  />
80
- <div className="flex items-center justify-between pt-2">
81
- <span className="text-sm font-semibold text-gray-700">Negrita (Bold)</span>
674
+ <ITInput
675
+ name="max_ctrl"
676
+ label="Texto máximo (caracteres)"
677
+ type="number"
678
+ value={maxLength}
679
+ onChange={(e) => setMaxLength(e.target.value)}
680
+ placeholder="0 = sin límite"
681
+ />
682
+ <ITFlex justify="between" align="center">
683
+ <ITText muted as="span" className="text-[10px]">
684
+ Trunca con "…" al superar (0 = desactivado).
685
+ </ITText>
686
+ <ITButton variant="text" color="primary" size="small" onClick={() => setMaxLength("0")}>
687
+ Reset
688
+ </ITButton>
689
+ </ITFlex>
690
+ <ITInput
691
+ name="break_ctrl"
692
+ label="Salto de línea después de (caracteres)"
693
+ type="number"
694
+ value={breakLength}
695
+ onChange={(e) => setBreakLength(e.target.value)}
696
+ placeholder="0 = sin salto"
697
+ />
698
+ <ITFlex justify="between" align="center">
699
+ <ITText muted as="span" className="text-[10px]">
700
+ Inserta un &lt;br /&gt; al superar el límite.
701
+ </ITText>
702
+ <ITButton variant="text" color="primary" size="small" onClick={() => setBreakLength("0")}>
703
+ Reset
704
+ </ITButton>
705
+ </ITFlex>
706
+ <div>
707
+ <ITText as="label" htmlFor="break_ctrl" className="text-xs font-semibold text-slate-600 dark:text-slate-400 block mb-1">
708
+ breakLengthWrap (corte cada N caracteres)
709
+ </ITText>
710
+ <input
711
+ id="break_ctrl"
712
+ type="number"
713
+ min={0}
714
+ step={5}
715
+ value={breakLength}
716
+ onChange={(e) => setBreakLength(e.target.value)}
717
+ className="w-full bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-lg p-2 text-xs text-slate-800 dark:text-slate-100 outline-none focus:ring-2 focus:ring-primary-500"
718
+ placeholder="0 = sin corte"
719
+ />
720
+ <ITFlex justify="between" align="center" className="mt-1.5">
721
+ <ITText muted as="span" className="text-[10px]">
722
+ Inserta oportunidades de corte cada N chars (0 = desactivado).
723
+ </ITText>
724
+ <button
725
+ type="button"
726
+ onClick={() => setBreakLength("0")}
727
+ className="text-[10px] font-semibold text-primary-600 hover:text-primary-700 dark:text-primary-400"
728
+ >
729
+ Reset
730
+ </button>
731
+ </ITFlex>
732
+ </div>
733
+ <div className="flex items-center justify-between pt-1">
734
+ <ITText as="span" className="text-sm font-semibold text-slate-700 dark:text-slate-300">Negrita (font-bold)</ITText>
82
735
  <ITSlideToggle isOn={bold} onToggle={setBold} size="sm" />
83
736
  </div>
84
- </>
737
+ <div className="flex items-center justify-between">
738
+ <ITText as="span" className="text-sm font-semibold text-slate-700 dark:text-slate-300">Muted color</ITText>
739
+ <ITSlideToggle isOn={muted} onToggle={setMuted} size="sm" />
740
+ </div>
741
+ </ITStack>
742
+ }
743
+ gallery={
744
+ <ITStack spacing={8}>
745
+ <GallerySection
746
+ title="Real UI cases"
747
+ subtitle="Production-ready typography patterns built with ITText"
748
+ >
749
+ <div className="grid grid-cols-1 lg:grid-cols-2 gap-5">
750
+
751
+ {/* 1. Article header — eyebrow + title + meta */}
752
+ <PatternCard
753
+ title="Article header"
754
+ desc="eyebrow tag + h1 title + author/date/read-time meta"
755
+ code={TEXT_PATTERN_CODES.articleHeader}
756
+ >
757
+ <div className="max-w-md">
758
+ <ITFlex align="center" gap={2} className="mb-3">
759
+ <ITBadget label="ENGINEERING" color="primary" size="small" variant="outlined" />
760
+ <ITText muted as="span" className="text-[11px] uppercase tracking-wider font-semibold">Featured</ITText>
761
+ </ITFlex>
762
+ <ITText as="h2" className="text-2xl font-bold text-slate-800 dark:text-slate-100 leading-tight mb-2 block">
763
+ How we cut bundle size by 38% in two weeks
764
+ </ITText>
765
+ <ITText as="p" className="text-sm text-slate-600 dark:text-slate-300 leading-relaxed mb-3 block">
766
+ A pragmatic walkthrough of our lazy-loading rollout, route-level code splitting, and the metrics that proved it worked.
767
+ </ITText>
768
+ <ITFlex align="center" gap={3}>
769
+ <ITAvatar initials="MR" size="sm" />
770
+ <ITText as="span" className="text-xs text-slate-700 dark:text-slate-300 font-semibold">Mariana Reyes</ITText>
771
+ <ITDivider orientation="vertical" className="h-3" />
772
+ <ITText muted as="span" className="text-xs">Nov 14, 2025</ITText>
773
+ <ITDivider orientation="vertical" className="h-3" />
774
+ <ITText muted as="span" className="text-xs font-mono">8 min read</ITText>
775
+ </ITFlex>
776
+ </div>
777
+ </PatternCard>
778
+
779
+ {/* 2. Section heading — h2 + description + action link */}
780
+ <PatternCard
781
+ title="Section heading"
782
+ desc="h2 title + description + action link on the right"
783
+ code={TEXT_PATTERN_CODES.sectionHeading}
784
+ >
785
+ <div>
786
+ <ITFlex justify="between" align="start" gap={4} className="mb-2">
787
+ <ITText as="h2" className="text-xl font-bold text-slate-800 dark:text-slate-100">
788
+ Recent activity
789
+ </ITText>
790
+ <ITButton label="View all →" variant="text" color="primary" size="small" />
791
+ </ITFlex>
792
+ <ITText as="p" muted className="text-sm leading-relaxed">
793
+ Latest commits, deployments and reviews from your team this week. Updates every 30 seconds.
794
+ </ITText>
795
+ </div>
796
+ </PatternCard>
797
+
798
+ {/* 3. Empty state — big title + description + muted helper */}
799
+ <PatternCard
800
+ title="Empty state"
801
+ desc="big title + description + muted helper text"
802
+ code={TEXT_PATTERN_CODES.emptyState}
803
+ >
804
+ <ITStack spacing={3} alignItems="center" className="text-center py-2">
805
+ <div
806
+ className="w-14 h-14 rounded-2xl flex items-center justify-center"
807
+ style={{
808
+ background: 'linear-gradient(135deg, var(--color-primary-500) 0%, var(--color-primary-700) 100%)',
809
+ boxShadow: '0 8px 24px 0 rgba(59, 130, 246, 0.3)',
810
+ }}
811
+ >
812
+ <FaBell className="text-white text-xl" />
813
+ </div>
814
+ <ITText as="h3" className="text-lg font-bold text-slate-800 dark:text-slate-100">
815
+ You're all caught up
816
+ </ITText>
817
+ <ITText as="p" className="text-sm text-slate-600 dark:text-slate-300 max-w-xs">
818
+ No new notifications. We'll let you know when something important happens.
819
+ </ITText>
820
+ <ITText as="p" muted className="text-xs">
821
+ Last checked 2 minutes ago
822
+ </ITText>
823
+ </ITStack>
824
+ </PatternCard>
825
+
826
+ {/* 4. Inline content — paragraph with bold name + inline code + muted meta */}
827
+ <PatternCard
828
+ title="Inline content"
829
+ desc="paragraph with bold name + inline code + muted timestamp"
830
+ code={TEXT_PATTERN_CODES.inlineContent}
831
+ >
832
+ <div className="max-w-md">
833
+ <ITText as="p" className="text-sm text-slate-700 dark:text-slate-200 leading-relaxed">
834
+ <ITText as="span" className="font-semibold">Daniela Klein</ITText>
835
+ {' '}pushed commit{' '}
836
+ <ITText as="code" className="px-1.5 py-0.5 rounded bg-slate-100 dark:bg-slate-800 text-primary-600 dark:text-primary-400 font-mono text-[11px]">
837
+ a3f9c2e
838
+ </ITText>
839
+ {' '}to{' '}
840
+ <ITText as="span" className="font-semibold">main</ITText>
841
+ {' '}with the message{' '}
842
+ <ITText as="span" className="italic">"fix: race condition in cache invalidation"</ITText>.
843
+ </ITText>
844
+ <ITFlex align="center" gap={2} className="mt-3">
845
+ <ITText muted as="span" className="text-[11px]">12 minutes ago</ITText>
846
+ <ITDivider orientation="vertical" className="h-3" />
847
+ <ITText muted as="span" className="text-[11px] font-mono">api-service</ITText>
848
+ <ITDivider orientation="vertical" className="h-3" />
849
+ <ITBadget label="+124 -38" color="success" size="small" variant="outlined" />
850
+ </ITFlex>
851
+ </div>
852
+ </PatternCard>
853
+
854
+ {/* 5. Form labels — label + helper text */}
855
+ <PatternCard
856
+ title="Form labels"
857
+ desc="label + required asterisk + muted helper text"
858
+ code={TEXT_PATTERN_CODES.formLabels}
859
+ >
860
+ <ITStack spacing={4} className="max-w-sm">
861
+ <div>
862
+ <ITText as="label" className="text-sm font-semibold text-slate-700 dark:text-slate-200 block mb-1">
863
+ Workspace name <ITText as="span" className="text-danger-500">*</ITText>
864
+ </ITText>
865
+ <ITInput
866
+ name="ws_name"
867
+ value=""
868
+ onChange={() => {}}
869
+ onBlur={() => {}}
870
+ placeholder="my-awesome-project"
871
+ />
872
+ <ITText muted as="span" className="text-[11px] mt-1 block">
873
+ Lowercase letters, numbers and hyphens only.
874
+ </ITText>
875
+ </div>
876
+ <div>
877
+ <ITText as="label" className="text-sm font-semibold text-slate-700 dark:text-slate-200 block mb-1">
878
+ Description
879
+ </ITText>
880
+ <ITInput
881
+ name="ws_desc"
882
+ value=""
883
+ onChange={() => {}}
884
+ onBlur={() => {}}
885
+ placeholder="A short summary of what your team is building"
886
+ />
887
+ <ITText muted as="span" className="text-[11px] mt-1 block">
888
+ Optional. Max 140 characters.
889
+ </ITText>
890
+ </div>
891
+ </ITStack>
892
+ </PatternCard>
893
+ </div>
894
+ </GallerySection>
895
+ </ITStack>
85
896
  }
86
897
  />
87
898
  );
88
899
  };
89
900
 
90
- // Temporary helper helper to render ITSelect inside showcases
91
- const ITSelectStub = ({ name, label, value, onChange, options }: any) => {
92
- return (
93
- <div className="flex flex-col gap-1">
94
- <label className="text-xs font-semibold text-slate-600 dark:text-slate-400">{label}</label>
95
- <select
96
- name={name}
97
- value={value}
98
- onChange={onChange}
99
- className="w-full bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-lg p-2 text-xs text-slate-800 dark:text-slate-100 outline-none"
100
- >
101
- {options.map((opt: any) => (
102
- <option key={opt.value} value={opt.value}>
103
- {opt.label}
104
- </option>
105
- ))}
106
- </select>
107
- </div>
108
- );
109
- };
901
+
110
902
 
111
903
  // 3. ITLayout & ITNavbar Showcase
112
904
  export const LayoutShowcase = () => {
113
- const code = `<ITLayout\n topBar={topBarProps}\n sidebar={sidebarProps}\n>\n {/* Tu Contenido aquí */}\n</ITLayout>`;
905
+ const [collapsed, setCollapsed] = useState(false);
906
+ const [activeId, setActiveId] = useState("dashboard");
907
+ const [navActiveId, setNavActiveId] = useState<string | null>("1");
908
+
909
+ const topBar = {
910
+ logo: <div className="w-9 h-9 rounded-lg bg-primary-500 flex items-center justify-center text-white font-bold">A</div>,
911
+ logoText: "AXZY Console",
912
+ navItems: [
913
+ { id: "home", label: "Inicio", icon: <FaHome />, action: () => setActiveId("home") },
914
+ { id: "docs", label: "Documentos", icon: <FaFileAlt />, action: () => setActiveId("docs") },
915
+ { id: "alerts", label: "Alertas", icon: <FaBell />, action: () => setActiveId("alerts") },
916
+ ],
917
+ onNavItemClick: (id: string) => setActiveId(id),
918
+ userMenu: {
919
+ userName: "Auditor AXZY",
920
+ userEmail: "auditor@axzy.dev",
921
+ menuItems: [
922
+ { label: "Ajustes", onClick: () => {} },
923
+ { label: "Cerrar sesión", onClick: () => {} },
924
+ ],
925
+ },
926
+ };
927
+
928
+ const sidebar = {
929
+ navigationItems: [
930
+ { id: "dashboard", label: "Dashboard", icon: <FaChartLine />, isActive: activeId === "dashboard", action: () => setActiveId("dashboard") },
931
+ { id: "users", label: "Usuarios", icon: <FaUsers />, isActive: activeId === "users", action: () => setActiveId("users") },
932
+ {
933
+ id: "sales",
934
+ label: "Ventas",
935
+ icon: <FaShoppingCart />,
936
+ isActive: activeId === "sales" || activeId === "orders",
937
+ subitems: [
938
+ { id: "orders", label: "Órdenes", action: () => setActiveId("orders") },
939
+ { id: "invoices", label: "Facturas", action: () => setActiveId("invoices") },
940
+ ],
941
+ },
942
+ { id: "products", label: "Productos", icon: <FaBoxOpen />, isActive: activeId === "products", action: () => setActiveId("products"), badge: "3" },
943
+ { id: "settings", label: "Configuración", icon: <FaCog />, isActive: activeId === "settings", action: () => setActiveId("settings") },
944
+ ],
945
+ isCollapsed: collapsed,
946
+ onToggleCollapse: () => setCollapsed(v => !v),
947
+ };
948
+
949
+ const code = `<ITLayout
950
+ topBar={{
951
+ logo: <Logo />,
952
+ logoText: "AXZY Console",
953
+ userMenu: { userName, userEmail, menuItems }
954
+ }}
955
+ sidebar={{
956
+ navigationItems: [...],
957
+ isCollapsed: ${collapsed},
958
+ onToggleCollapse: () => setCollapsed(v => !v)
959
+ }}
960
+ >
961
+ {/* Tu contenido */}
962
+ </ITLayout>`;
963
+
964
+ const navbarItems = [
965
+ { id: "1", label: "Inicio", icon: <FaHome />, isActive: navActiveId === "1", action: () => setNavActiveId("1") },
966
+ { id: "2", label: "Documentos", icon: <FaFileAlt />, isActive: navActiveId === "2", action: () => setNavActiveId("2") },
967
+ { id: "3", label: "Alertas", icon: <FaBell />, isActive: navActiveId === "3", action: () => setNavActiveId("3") },
968
+ ];
969
+
970
+ const navbarCode = `<ITNavbar
971
+ logoText="AXZY"
972
+ navigationItems={[
973
+ { id: "1", label: "Inicio", icon: <FaHome />, isActive: true },
974
+ { id: "2", label: "Documentos", icon: <FaFileAlt /> },
975
+ { id: "3", label: "Alertas", icon: <FaBell /> }
976
+ ]}
977
+ userMenu={{
978
+ userName: "Auditor AXZY",
979
+ userEmail: "auditor@axzy.dev",
980
+ menuItems: [{ label: "Ajustes", onClick: () => {} }]
981
+ }}
982
+ />`;
114
983
 
115
984
  return (
116
- <div className="space-y-6">
117
- <div>
118
- <h1 className="text-3xl font-extrabold text-slate-800 dark:text-white">ITLayout & ITNavbar</h1>
119
- <p className="text-slate-500 mt-1.5 text-sm md:text-base">El chasis estructural del portal administrativo con control responsivo y colapso de sidebar.</p>
120
- </div>
985
+ <ShowcaseLayout
986
+ title="ITLayout & ITNavbar"
987
+ description="Chasis estructural del portal con barra superior y lateral colapsable. Totalmente responsivo con drawer móvil."
988
+ code={code}
989
+ demo={
990
+ <div className="w-full h-[640px] rounded-xl overflow-hidden border border-slate-200 dark:border-slate-700 shadow-md">
991
+ <ITLayout topBar={topBar} sidebar={sidebar}>
992
+ <ITStack spacing={5}>
993
+ <ITPageHeader
994
+ title="Dashboard"
995
+ description="Resumen general del sistema"
996
+ icon={<FaChartLine size={20} />}
997
+ iconColor="#6366f1"
998
+ />
999
+ <ITGrid container spacing={3}>
1000
+ <ITGrid item xs={12} sm={6} lg={3}>
1001
+ <ITStatCard label="Usuarios" value="1,245" trend="+12%" trendDirection="up" />
1002
+ </ITGrid>
1003
+ <ITGrid item xs={12} sm={6} lg={3}>
1004
+ <ITStatCard label="Ventas Hoy" value="$4,320" trend="+5.4%" trendDirection="up" color="bg-blue-50 dark:bg-blue-950/20" />
1005
+ </ITGrid>
1006
+ <ITGrid item xs={12} sm={6} lg={3}>
1007
+ <ITStatCard label="Órdenes" value="89" trend="-2.1%" trendDirection="down" color="bg-amber-50 dark:bg-amber-950/20" />
1008
+ </ITGrid>
1009
+ <ITGrid item xs={12} sm={6} lg={3}>
1010
+ <ITStatCard label="Tickets" value="12" trend="-8%" trendDirection="down" color="bg-rose-50 dark:bg-rose-950/20" />
1011
+ </ITGrid>
1012
+ </ITGrid>
1013
+ <ITCard title="Actividad reciente">
1014
+ <ITText className="text-sm text-slate-600 dark:text-slate-300">
1015
+ El layout se adapta al colapsar/expandir el sidebar y muestra un drawer en móvil.
1016
+ </ITText>
1017
+ </ITCard>
1018
+ </ITStack>
1019
+ </ITLayout>
1020
+ </div>
1021
+ }
1022
+ controls={
1023
+ <ITStack spacing={4}>
1024
+ <div className="flex items-center justify-between">
1025
+ <span className="text-sm font-semibold text-slate-700 dark:text-slate-300">Sidebar colapsado</span>
1026
+ <ITSlideToggle isOn={collapsed} onToggle={setCollapsed} size="sm" />
1027
+ </div>
1028
+ <div className="text-xs text-slate-500">
1029
+ En móvil (&lt;lg) el sidebar se abre como drawer con un fondo oscuro. Usa el botón ☰ del topbar.
1030
+ </div>
1031
+ </ITStack>
1032
+ }
1033
+ gallery={
1034
+ <ITStack spacing={6}>
1035
+ <div>
1036
+ <h4 className="text-sm font-bold text-slate-700 dark:text-slate-200 mb-3">ITNavbar (standalone)</h4>
1037
+ <div className="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden h-[420px]">
1038
+ <ITNavbar
1039
+ logoText="AXZY"
1040
+ navigationItems={navbarItems}
1041
+ userMenu={{
1042
+ userName: "Auditor AXZY",
1043
+ userEmail: "auditor@axzy.dev",
1044
+ menuItems: [
1045
+ { label: "Ajustes", onClick: () => {} },
1046
+ { label: "Cerrar sesión", onClick: () => {} },
1047
+ ],
1048
+ }}
1049
+ >
1050
+ <div className="p-8 text-center text-slate-500 text-sm">
1051
+ {navActiveId ? `Item activo: "${navbarItems.find(i => i.isActive)?.label}"` : "Selecciona un item en la navegación"}
1052
+ </div>
1053
+ </ITNavbar>
1054
+ </div>
1055
+ <div className="mt-3">
1056
+ <CodeViewer code={navbarCode} />
1057
+ </div>
1058
+ </div>
121
1059
 
122
- <ITCard title="Layout Estructural">
123
- <div className="space-y-4">
124
- <p className="text-sm text-slate-600 dark:text-slate-300">
125
- Este componente es el contenedor raíz de toda la suite que estás navegando en este momento. Proporciona:
126
- </p>
127
- <ul className="list-disc pl-5 space-y-2 text-sm text-slate-600 dark:text-slate-300">
128
- <li>Menú superior (Navbar) con avatar del usuario, correo y menú desplegable.</li>
129
- <li>Barra de navegación lateral interactiva (Sidebar) colapsable con sub-ítems y badges.</li>
130
- <li>Fondo dinámico adaptado a presets claros y oscuros.</li>
131
- </ul>
132
- <div className="mt-4 p-4 bg-slate-50 dark:bg-slate-900 border rounded-xl">
133
- <h5 className="font-bold text-xs uppercase text-slate-400 mb-2">Simulación de Barra de Navegación Horizontal (ITNavbar)</h5>
134
- <ITNavbar
135
- logoText="PREVIEW NAVBAR"
136
- navigationItems={[
137
- { id: "1", label: "Inicio", isActive: true },
138
- { id: "2", label: "Auditoría" }
139
- ]}
140
- userMenu={{
141
- userName: "Auditor AXZY",
142
- userEmail: "auditor@axzy.dev",
143
- menuItems: [{ label: "Ajustes", onClick: () => { } }]
144
- }}
145
- />
1060
+ <div>
1061
+ <h4 className="text-sm font-bold text-slate-700 dark:text-slate-200 mb-3">ITNavbar con submenús</h4>
1062
+ <div className="border border-slate-200 dark:border-slate-700 rounded-xl overflow-hidden h-[420px]">
1063
+ <ITNavbar
1064
+ logoText="Admin"
1065
+ navigationItems={[
1066
+ { id: "u", label: "Usuarios", icon: <FaUsers /> },
1067
+ {
1068
+ id: "s",
1069
+ label: "Ventas",
1070
+ icon: <FaShoppingCart />,
1071
+ subitems: [
1072
+ { id: "o", label: "Órdenes", action: () => {} },
1073
+ { id: "i", label: "Facturas", action: () => {} },
1074
+ ],
1075
+ },
1076
+ { id: "c", label: "Configuración", icon: <FaCog /> },
1077
+ ]}
1078
+ userMenu={{
1079
+ userName: "Admin",
1080
+ userEmail: "admin@axzy.dev",
1081
+ menuItems: [{ label: "Salir", onClick: () => {} }],
1082
+ }}
1083
+ >
1084
+ <div className="p-8 text-center text-slate-500 text-sm">
1085
+ Haz clic en "Ventas" para expandir/colapsar el submenú
1086
+ </div>
1087
+ </ITNavbar>
1088
+ </div>
146
1089
  </div>
147
- <CodeViewer code={code} />
148
- </div>
149
- </ITCard>
150
- </div>
1090
+ </ITStack>
1091
+ }
1092
+ />
151
1093
  );
152
1094
  };