@idealyst/components 1.0.83 → 1.0.84

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 (316) hide show
  1. package/CLAUDE.md +199 -232
  2. package/README.md +5 -5
  3. package/package.json +20 -2
  4. package/plugin/README.md +272 -0
  5. package/plugin/test-cases.jsx +112 -0
  6. package/plugin/web-legacy.js +320 -0
  7. package/plugin/web.js +422 -124
  8. package/src/Accordion/Accordion.native.tsx +182 -0
  9. package/src/Accordion/Accordion.styles.tsx +260 -0
  10. package/src/Accordion/Accordion.web.tsx +147 -0
  11. package/src/Accordion/index.native.tsx +3 -0
  12. package/src/Accordion/index.ts +3 -0
  13. package/src/Accordion/index.web.tsx +3 -0
  14. package/src/Accordion/types.ts +23 -0
  15. package/src/ActivityIndicator/ActivityIndicator.native.tsx +17 -12
  16. package/src/ActivityIndicator/ActivityIndicator.styles.tsx +83 -109
  17. package/src/ActivityIndicator/ActivityIndicator.web.tsx +23 -17
  18. package/src/ActivityIndicator/index.ts +5 -2
  19. package/src/ActivityIndicator/index.web.ts +5 -2
  20. package/src/ActivityIndicator/types.ts +15 -10
  21. package/src/Alert/Alert.native.tsx +113 -0
  22. package/src/Alert/Alert.styles.tsx +304 -0
  23. package/src/Alert/Alert.web.tsx +123 -0
  24. package/src/Alert/index.native.ts +5 -0
  25. package/src/Alert/index.ts +5 -0
  26. package/src/Alert/index.web.ts +5 -0
  27. package/src/Alert/types.ts +21 -0
  28. package/src/Avatar/Avatar.native.tsx +8 -6
  29. package/src/Avatar/Avatar.styles.tsx +64 -58
  30. package/src/Avatar/Avatar.web.tsx +13 -8
  31. package/src/Avatar/index.ts +5 -2
  32. package/src/Avatar/index.web.ts +5 -2
  33. package/src/Avatar/types.ts +19 -13
  34. package/src/Badge/Badge.native.tsx +59 -14
  35. package/src/Badge/Badge.styles.tsx +125 -139
  36. package/src/Badge/Badge.web.tsx +72 -16
  37. package/src/Badge/index.ts +5 -2
  38. package/src/Badge/index.web.ts +5 -2
  39. package/src/Badge/types.ts +23 -11
  40. package/src/Breadcrumb/Breadcrumb.native.tsx +225 -0
  41. package/src/Breadcrumb/Breadcrumb.styles.tsx +234 -0
  42. package/src/Breadcrumb/Breadcrumb.web.tsx +268 -0
  43. package/src/Breadcrumb/index.native.ts +5 -0
  44. package/src/Breadcrumb/index.ts +5 -0
  45. package/src/Breadcrumb/index.web.ts +5 -0
  46. package/src/Breadcrumb/types.ts +56 -0
  47. package/src/Button/Button.native.tsx +75 -24
  48. package/src/Button/Button.styles.tsx +248 -205
  49. package/src/Button/Button.web.tsx +82 -25
  50. package/src/Button/index.ts +5 -5
  51. package/src/Button/index.web.ts +5 -3
  52. package/src/Button/types.ts +32 -15
  53. package/src/Card/Card.native.tsx +14 -11
  54. package/src/Card/Card.styles.tsx +146 -220
  55. package/src/Card/Card.web.tsx +20 -21
  56. package/src/Card/index.ts +5 -5
  57. package/src/Card/index.web.ts +5 -3
  58. package/src/Card/types.ts +24 -17
  59. package/src/Checkbox/Checkbox.native.tsx +24 -34
  60. package/src/Checkbox/Checkbox.styles.tsx +223 -275
  61. package/src/Checkbox/Checkbox.web.tsx +30 -37
  62. package/src/Checkbox/index.ts +5 -5
  63. package/src/Checkbox/index.web.ts +5 -3
  64. package/src/Checkbox/types.ts +26 -20
  65. package/src/Chip/Chip.native.tsx +126 -0
  66. package/src/Chip/Chip.styles.tsx +138 -0
  67. package/src/Chip/Chip.web.tsx +154 -0
  68. package/src/Chip/index.native.ts +5 -0
  69. package/src/Chip/index.ts +5 -0
  70. package/src/Chip/index.web.ts +5 -0
  71. package/src/Chip/types.ts +51 -0
  72. package/src/Dialog/Dialog.native.tsx +65 -12
  73. package/src/Dialog/Dialog.styles.tsx +154 -136
  74. package/src/Dialog/Dialog.web.tsx +16 -11
  75. package/src/Dialog/index.ts +5 -2
  76. package/src/Dialog/index.web.ts +5 -2
  77. package/src/Dialog/types.ts +22 -16
  78. package/src/Divider/Divider.native.tsx +19 -14
  79. package/src/Divider/Divider.styles.tsx +273 -595
  80. package/src/Divider/Divider.web.tsx +19 -12
  81. package/src/Divider/index.ts +5 -5
  82. package/src/Divider/index.web.ts +5 -3
  83. package/src/Divider/types.ts +28 -19
  84. package/src/Icon/Icon.native.tsx +17 -24
  85. package/src/Icon/Icon.styles.tsx +64 -48
  86. package/src/Icon/Icon.web.tsx +14 -11
  87. package/src/Icon/IconSvg/IconSvg.native.tsx +42 -0
  88. package/src/Icon/IconSvg/IconSvg.web.tsx +40 -0
  89. package/src/Icon/IconSvg/index.native.ts +1 -0
  90. package/src/Icon/IconSvg/index.ts +1 -0
  91. package/src/Icon/icon-resolver.native.ts +27 -0
  92. package/src/Icon/icon-resolver.ts +70 -0
  93. package/src/Icon/index.ts +5 -5
  94. package/src/Icon/index.web.ts +5 -3
  95. package/src/Icon/types.ts +17 -11
  96. package/src/Image/Image.native.tsx +86 -0
  97. package/src/Image/Image.styles.tsx +57 -0
  98. package/src/Image/Image.web.tsx +92 -0
  99. package/src/Image/index.native.ts +5 -0
  100. package/src/Image/index.ts +5 -0
  101. package/src/Image/types.ts +21 -0
  102. package/src/Input/Input.native.tsx +103 -26
  103. package/src/Input/Input.styles.tsx +240 -177
  104. package/src/Input/Input.web.tsx +141 -38
  105. package/src/Input/index.ts +5 -5
  106. package/src/Input/index.web.ts +5 -3
  107. package/src/Input/types.ts +43 -20
  108. package/src/List/List.native.tsx +56 -0
  109. package/src/List/List.styles.tsx +257 -0
  110. package/src/List/List.web.tsx +43 -0
  111. package/src/List/ListContext.tsx +16 -0
  112. package/src/List/ListItem.native.tsx +111 -0
  113. package/src/List/ListItem.web.tsx +110 -0
  114. package/src/List/ListSection.native.tsx +31 -0
  115. package/src/List/ListSection.web.tsx +33 -0
  116. package/src/List/index.native.tsx +5 -0
  117. package/src/List/index.ts +5 -0
  118. package/src/List/index.web.tsx +5 -0
  119. package/src/List/types.ts +42 -0
  120. package/src/Menu/Menu.native.tsx +150 -0
  121. package/src/Menu/Menu.styles.tsx +185 -0
  122. package/src/Menu/Menu.web.tsx +99 -0
  123. package/src/Menu/MenuItem.native.tsx +66 -0
  124. package/src/Menu/MenuItem.styles.tsx +119 -0
  125. package/src/Menu/MenuItem.web.tsx +67 -0
  126. package/src/Menu/index.native.ts +3 -0
  127. package/src/Menu/index.ts +3 -0
  128. package/src/Menu/index.web.ts +3 -0
  129. package/src/Menu/types.ts +30 -0
  130. package/src/Popover/Popover.native.tsx +102 -32
  131. package/src/Popover/Popover.styles.tsx +100 -67
  132. package/src/Popover/Popover.web.tsx +36 -260
  133. package/src/Popover/index.ts +5 -2
  134. package/src/Popover/index.web.ts +5 -2
  135. package/src/Popover/types.ts +14 -13
  136. package/src/Pressable/Pressable.native.tsx +7 -6
  137. package/src/Pressable/Pressable.web.tsx +8 -6
  138. package/src/Pressable/index.ts +5 -2
  139. package/src/Pressable/index.web.ts +5 -2
  140. package/src/Pressable/types.ts +11 -10
  141. package/src/Progress/Progress.native.tsx +179 -0
  142. package/src/Progress/Progress.styles.tsx +164 -0
  143. package/src/Progress/Progress.web.tsx +144 -0
  144. package/src/Progress/index.native.ts +1 -0
  145. package/src/Progress/index.ts +5 -0
  146. package/src/Progress/index.web.ts +5 -0
  147. package/src/Progress/types.ts +21 -0
  148. package/src/RadioButton/RadioButton.native.tsx +88 -0
  149. package/src/RadioButton/RadioButton.styles.tsx +163 -0
  150. package/src/RadioButton/RadioButton.web.tsx +85 -0
  151. package/src/RadioButton/RadioGroup.native.tsx +43 -0
  152. package/src/RadioButton/RadioGroup.web.tsx +49 -0
  153. package/src/RadioButton/index.native.ts +2 -0
  154. package/src/RadioButton/index.ts +2 -0
  155. package/src/RadioButton/index.web.ts +2 -0
  156. package/src/RadioButton/types.ts +29 -0
  157. package/src/SVGImage/SVGImage.native.tsx +9 -7
  158. package/src/SVGImage/SVGImage.styles.tsx +63 -55
  159. package/src/SVGImage/SVGImage.web.tsx +16 -13
  160. package/src/SVGImage/index.ts +5 -5
  161. package/src/SVGImage/index.web.ts +5 -2
  162. package/src/SVGImage/types.ts +7 -3
  163. package/src/Screen/Screen.native.tsx +43 -17
  164. package/src/Screen/Screen.styles.tsx +58 -54
  165. package/src/Screen/Screen.web.tsx +11 -5
  166. package/src/Screen/index.ts +5 -2
  167. package/src/Screen/index.web.ts +5 -2
  168. package/src/Screen/types.ts +23 -9
  169. package/src/Select/Select.native.tsx +140 -63
  170. package/src/Select/Select.styles.tsx +312 -302
  171. package/src/Select/Select.web.tsx +156 -316
  172. package/src/Select/index.ts +5 -2
  173. package/src/Select/index.web.ts +5 -2
  174. package/src/Select/types.ts +13 -7
  175. package/src/Skeleton/Skeleton.native.tsx +139 -0
  176. package/src/Skeleton/Skeleton.styles.tsx +59 -0
  177. package/src/Skeleton/Skeleton.web.tsx +112 -0
  178. package/src/Skeleton/index.native.ts +4 -0
  179. package/src/Skeleton/index.ts +5 -0
  180. package/src/Skeleton/index.web.ts +5 -0
  181. package/src/Skeleton/types.ts +75 -0
  182. package/src/Slider/Slider.native.tsx +248 -0
  183. package/src/Slider/Slider.styles.tsx +241 -0
  184. package/src/Slider/Slider.web.tsx +226 -0
  185. package/src/Slider/index.native.ts +3 -0
  186. package/src/Slider/index.ts +5 -0
  187. package/src/Slider/index.web.ts +5 -0
  188. package/src/Slider/types.ts +31 -0
  189. package/src/Switch/Switch.native.tsx +131 -0
  190. package/src/Switch/Switch.styles.tsx +169 -0
  191. package/src/Switch/Switch.web.tsx +121 -0
  192. package/src/Switch/index.native.ts +3 -0
  193. package/src/Switch/index.ts +5 -0
  194. package/src/Switch/index.web.ts +5 -0
  195. package/src/Switch/types.ts +21 -0
  196. package/src/TabBar/TabBar.native.tsx +142 -0
  197. package/src/TabBar/TabBar.styles.tsx +399 -0
  198. package/src/TabBar/TabBar.web.tsx +205 -0
  199. package/src/TabBar/index.native.tsx +3 -0
  200. package/src/TabBar/index.ts +3 -0
  201. package/src/TabBar/index.web.tsx +3 -0
  202. package/src/TabBar/types.ts +26 -0
  203. package/src/Table/Table.native.tsx +122 -0
  204. package/src/Table/Table.styles.tsx +283 -0
  205. package/src/Table/Table.web.tsx +112 -0
  206. package/src/Table/index.native.tsx +3 -0
  207. package/src/Table/index.ts +3 -0
  208. package/src/Table/index.web.tsx +3 -0
  209. package/src/Table/types.ts +28 -0
  210. package/src/Text/Text.native.tsx +12 -11
  211. package/src/Text/Text.styles.tsx +76 -64
  212. package/src/Text/Text.web.tsx +14 -9
  213. package/src/Text/index.ts +5 -5
  214. package/src/Text/index.web.ts +5 -3
  215. package/src/Text/types.ts +20 -13
  216. package/src/TextArea/TextArea.native.tsx +134 -0
  217. package/src/TextArea/TextArea.styles.tsx +175 -0
  218. package/src/TextArea/TextArea.web.tsx +156 -0
  219. package/src/TextArea/index.native.ts +3 -0
  220. package/src/TextArea/index.ts +3 -0
  221. package/src/TextArea/index.web.ts +3 -0
  222. package/src/TextArea/types.ts +30 -0
  223. package/src/Tooltip/Tooltip.native.tsx +165 -0
  224. package/src/Tooltip/Tooltip.styles.tsx +73 -0
  225. package/src/Tooltip/Tooltip.web.tsx +87 -0
  226. package/src/Tooltip/index.native.ts +3 -0
  227. package/src/Tooltip/index.ts +3 -0
  228. package/src/Tooltip/types.ts +18 -0
  229. package/src/Video/Video.native.tsx +105 -0
  230. package/src/Video/Video.styles.tsx +39 -0
  231. package/src/Video/Video.web.tsx +115 -0
  232. package/src/Video/index.native.ts +5 -0
  233. package/src/Video/index.ts +5 -0
  234. package/src/Video/types.ts +29 -0
  235. package/src/View/View.native.tsx +9 -14
  236. package/src/View/View.styles.tsx +101 -93
  237. package/src/View/View.web.tsx +16 -17
  238. package/src/View/index.ts +5 -5
  239. package/src/View/index.web.ts +5 -3
  240. package/src/View/types.ts +29 -21
  241. package/src/examples/AccordionExamples.tsx +126 -0
  242. package/src/examples/AlertExamples.tsx +280 -0
  243. package/src/examples/AvatarExamples.tsx +23 -23
  244. package/src/examples/BadgeExamples.tsx +109 -41
  245. package/src/examples/BreadcrumbExamples.tsx +312 -0
  246. package/src/examples/ButtonExamples.tsx +160 -33
  247. package/src/examples/CardExamples.tsx +40 -40
  248. package/src/examples/CheckboxExamples.tsx +12 -12
  249. package/src/examples/ChipExamples.tsx +197 -0
  250. package/src/examples/DialogExamples.tsx +22 -22
  251. package/src/examples/DividerExamples.tsx +49 -49
  252. package/src/examples/IconExamples.tsx +270 -54
  253. package/src/examples/ImageExamples.tsx +174 -0
  254. package/src/examples/InputExamples.tsx +75 -17
  255. package/src/examples/ListExamples.tsx +288 -0
  256. package/src/examples/MenuExamples.tsx +144 -0
  257. package/src/examples/PopoverExamples.tsx +69 -73
  258. package/src/examples/ProgressExamples.tsx +137 -0
  259. package/src/examples/RadioButtonExamples.tsx +161 -0
  260. package/src/examples/SVGImageExamples.tsx +19 -17
  261. package/src/examples/ScreenExamples.tsx +31 -31
  262. package/src/examples/SelectExamples.tsx +67 -67
  263. package/src/examples/SkeletonExamples.tsx +206 -0
  264. package/src/examples/SliderExamples.tsx +200 -0
  265. package/src/examples/SwitchExamples.tsx +182 -0
  266. package/src/examples/TabBarExamples.tsx +143 -0
  267. package/src/examples/TableExamples.tsx +280 -0
  268. package/src/examples/TextAreaExamples.tsx +173 -0
  269. package/src/examples/TextExamples.tsx +28 -32
  270. package/src/examples/ThemeExtensionExamples.tsx +10 -10
  271. package/src/examples/TooltipExamples.tsx +126 -0
  272. package/src/examples/VideoExamples.tsx +144 -0
  273. package/src/examples/ViewExamples.tsx +64 -56
  274. package/src/examples/index.ts +17 -3
  275. package/src/hooks/useMergeRefs.ts +16 -0
  276. package/src/hooks/useSmartPosition.native.ts +169 -0
  277. package/src/index.native.ts +80 -9
  278. package/src/index.ts +71 -1
  279. package/src/internal/BoundedModalContent.native.tsx +58 -0
  280. package/src/internal/PositionedPortal.tsx +254 -0
  281. package/src/internal/SafeAreaDebugOverlay.native.tsx +173 -0
  282. package/src/unistyles.d.ts +6 -0
  283. package/src/utils/buildSizeVariants.ts +16 -0
  284. package/src/utils/deepMerge.ts +43 -0
  285. package/src/utils/positionUtils.native.ts +280 -0
  286. package/src/utils/styleHelpers.ts +48 -0
  287. package/LLM-ACCESS-GUIDE.md +0 -143
  288. package/src/ActivityIndicator/README.md +0 -132
  289. package/src/Avatar/README.md +0 -139
  290. package/src/Badge/README.md +0 -170
  291. package/src/Button/Button.types.ts +0 -12
  292. package/src/Button/README.md +0 -262
  293. package/src/Card/README.md +0 -258
  294. package/src/Checkbox/README.md +0 -102
  295. package/src/Dialog/README.md +0 -210
  296. package/src/Divider/README.md +0 -108
  297. package/src/Icon/README.md +0 -81
  298. package/src/Input/README.md +0 -100
  299. package/src/SVGImage/README.md +0 -209
  300. package/src/Screen/README.md +0 -86
  301. package/src/Select/README.md +0 -166
  302. package/src/Text/README.md +0 -94
  303. package/src/View/README.md +0 -107
  304. package/src/examples/AllExamples.tsx +0 -88
  305. package/src/examples/README.md +0 -136
  306. package/src/examples/ValidationExamples.tsx +0 -95
  307. package/src/examples/extendedTheme.ts +0 -329
  308. package/src/theme/breakpoints.ts +0 -8
  309. package/src/theme/colorResolver.ts +0 -218
  310. package/src/theme/colors.ts +0 -315
  311. package/src/theme/defaultThemes.ts +0 -326
  312. package/src/theme/index.ts +0 -188
  313. package/src/theme/themeBuilder.ts +0 -602
  314. package/src/theme/unistyles.d.ts +0 -6
  315. package/src/theme/variantHelpers.ts +0 -584
  316. package/src/theme/variants.ts +0 -56
@@ -1,584 +0,0 @@
1
- /**
2
- * Variant Helper Functions
3
- *
4
- * These functions dynamically generate style variants from theme configuration,
5
- * making the system extensible when new colors or intents are added.
6
- */
7
-
8
- import type { ColorVariant, IntentVariant, ColorPaletteShade } from './variants';
9
-
10
- // Validation and logging functions
11
- const shouldWarn = () => {
12
- // Always warn in development for better developer experience
13
- // Production builds can disable this by setting a global flag
14
- try {
15
- return (globalThis as any)?.__IDEALIST_DISABLE_WARNINGS !== true;
16
- } catch {
17
- return true; // Default to showing warnings
18
- }
19
- };
20
-
21
- /**
22
- * Validates if a color exists in the theme palette
23
- */
24
- export function validateColor(theme: ThemeContext, color: string): boolean {
25
- const isSemanticColor = ['primary', 'secondary', 'disabled', 'inverse', 'muted'].includes(color);
26
- const isPaletteColor = theme.palettes && Object.keys(theme.palettes).includes(color);
27
-
28
- return isSemanticColor || isPaletteColor;
29
- }
30
-
31
- /**
32
- * Validates if an intent exists in the theme
33
- */
34
- export function validateIntent(theme: ThemeContext, intent: string): boolean {
35
- return theme.intents ? Object.keys(theme.intents).includes(intent) : false;
36
- }
37
-
38
- /**
39
- * Logs a warning for invalid color usage
40
- */
41
- export function warnInvalidColor(color: string, componentName?: string): void {
42
- if (shouldWarn()) {
43
- const component = componentName ? ` in ${componentName}` : '';
44
- console.warn(
45
- `🎨 Invalid color variant "${color}"${component}. ` +
46
- `Available colors are determined by your theme palette. ` +
47
- `Check your theme configuration or ensure the color is properly defined.`
48
- );
49
- }
50
- }
51
-
52
- /**
53
- * Logs a warning for invalid intent usage
54
- */
55
- export function warnInvalidIntent(intent: string, componentName?: string): void {
56
- if (shouldWarn()) {
57
- const component = componentName ? ` in ${componentName}` : '';
58
- console.warn(
59
- `🎯 Invalid intent variant "${intent}"${component}. ` +
60
- `Available intents are determined by your theme configuration. ` +
61
- `Check your theme.intents or ensure the intent is properly defined.`
62
- );
63
- }
64
- }
65
-
66
- // Type definitions for theme structure
67
- type ThemeContext = {
68
- palettes?: Record<string, Record<number, string>>;
69
- intents?: Record<string, {
70
- main: string;
71
- on: string;
72
- container: string;
73
- onContainer: string;
74
- light: string;
75
- dark: string;
76
- border: string;
77
- }>;
78
- colors?: {
79
- text?: {
80
- primary?: string;
81
- secondary?: string;
82
- disabled?: string;
83
- inverse?: string;
84
- muted?: string;
85
- };
86
- };
87
- };
88
-
89
- /**
90
- * Parses a color variant string and returns the color name and shade
91
- * Examples: 'blue' -> { color: 'blue', shade: 500 }
92
- * 'blue.300' -> { color: 'blue', shade: 300 }
93
- */
94
- function parseColorVariant(colorVariant: string): { color: string; shade: number } {
95
- const parts = colorVariant.split('.');
96
- const color = parts[0];
97
- const shade = parts[1] ? parseInt(parts[1], 10) : 500; // Default to 500
98
- return { color, shade };
99
- }
100
-
101
- /**
102
- * Generate color variants for display components
103
- * Supports both simple colors ('blue') and shade-specific colors ('blue.300')
104
- */
105
- export function generateColorVariants(
106
- theme: ThemeContext,
107
- defaultShade: ColorPaletteShade = 500,
108
- fallbacks: Record<string, string> = {
109
- red: '#ef4444',
110
- orange: '#f97316',
111
- yellow: '#eab308',
112
- green: '#22c55e',
113
- blue: '#3b82f6',
114
- purple: '#a855f7',
115
- black: '#202124',
116
- gray: '#6b7280',
117
- white: '#f8f8f8',
118
- }
119
- ) {
120
- const variants: Record<string, { color: string }> = {};
121
-
122
- // Add semantic color variants
123
- if (theme.colors?.text) {
124
- if (theme.colors.text.primary) {
125
- variants.primary = { color: theme.colors.text.primary };
126
- }
127
- if (theme.colors.text.secondary) {
128
- variants.secondary = { color: theme.colors.text.secondary };
129
- }
130
- if (theme.colors.text.disabled) {
131
- variants.disabled = { color: theme.colors.text.disabled };
132
- }
133
- if (theme.colors.text.inverse) {
134
- variants.inverse = { color: theme.colors.text.inverse };
135
- }
136
- if (theme.colors.text.muted) {
137
- variants.muted = { color: theme.colors.text.muted };
138
- }
139
- }
140
-
141
- // Add palette color variants (both simple and shade-specific)
142
- if (theme.palettes) {
143
- Object.keys(theme.palettes).forEach((colorKey) => {
144
- const palette = theme.palettes![colorKey];
145
- if (palette) {
146
- // Add simple color variant (defaults to defaultShade)
147
- if (palette[defaultShade]) {
148
- variants[colorKey] = { color: palette[defaultShade] };
149
- } else if (fallbacks[colorKey]) {
150
- variants[colorKey] = { color: fallbacks[colorKey] };
151
- }
152
-
153
- // Add all shade-specific variants
154
- Object.keys(palette).forEach((shadeKey) => {
155
- const shade = parseInt(shadeKey, 10);
156
- if (!isNaN(shade)) {
157
- variants[`${colorKey}.${shade}`] = { color: palette[shade] };
158
- }
159
- });
160
- }
161
- });
162
- } else {
163
- // Fallback to default colors if no palettes
164
- Object.entries(fallbacks).forEach(([colorKey, color]) => {
165
- variants[colorKey] = { color };
166
- });
167
- }
168
-
169
- return variants;
170
- }
171
-
172
- /**
173
- * Generate intent variants for action components
174
- * Uses the intent system (primary.main, success.main, etc.)
175
- */
176
- export function generateIntentVariants(
177
- theme: ThemeContext,
178
- fallbacks: Record<IntentVariant, string> = {
179
- primary: '#3b82f6',
180
- success: '#22c55e',
181
- error: '#ef4444',
182
- warning: '#f59e0b',
183
- neutral: '#6b7280',
184
- info: '#06b6d4',
185
- }
186
- ) {
187
- const variants: Record<string, { backgroundColor: string; color: string }> = {};
188
-
189
- if (theme.intents) {
190
- Object.entries(theme.intents).forEach(([intentKey, intent]) => {
191
- if (intent && intent.main && intent.on) {
192
- variants[intentKey] = {
193
- backgroundColor: intent.main,
194
- color: intent.on,
195
- };
196
- }
197
- });
198
- } else {
199
- // Fallback to default colors if no intents
200
- Object.entries(fallbacks).forEach(([intentKey, backgroundColor]) => {
201
- variants[intentKey] = {
202
- backgroundColor,
203
- color: '#ffffff',
204
- };
205
- });
206
- }
207
-
208
- return variants;
209
- }
210
-
211
- /**
212
- * Generate background variants for display components
213
- * Uses palette colors for backgrounds
214
- */
215
- export function generateBackgroundVariants(
216
- theme: ThemeContext,
217
- shade: ColorPaletteShade = 500,
218
- fallbacks: Record<string, string> = {
219
- red: '#ef4444',
220
- orange: '#f97316',
221
- yellow: '#eab308',
222
- green: '#22c55e',
223
- blue: '#3b82f6',
224
- purple: '#a855f7',
225
- black: '#202124',
226
- gray: '#6b7280',
227
- white: '#f8f8f8',
228
- }
229
- ) {
230
- const variants: Record<string, { backgroundColor: string }> = {};
231
-
232
- if (theme.palettes) {
233
- Object.keys(theme.palettes).forEach((colorKey) => {
234
- const palette = theme.palettes![colorKey];
235
- if (palette && palette[shade]) {
236
- variants[colorKey] = { backgroundColor: palette[shade] };
237
- } else if (fallbacks[colorKey as ColorVariant]) {
238
- variants[colorKey] = { backgroundColor: fallbacks[colorKey as ColorVariant] };
239
- // Warn if color exists in theme but shade is missing
240
- if (palette) {
241
- warnInvalidColor(`${colorKey}.${shade}`, 'background variant generation');
242
- }
243
- }
244
- });
245
- } else {
246
- // Fallback to default colors if no palettes
247
- Object.entries(fallbacks).forEach(([colorKey, backgroundColor]) => {
248
- variants[colorKey] = { backgroundColor };
249
- });
250
- }
251
-
252
- return variants;
253
- }
254
-
255
- /**
256
- * Generate border variants for display components
257
- * Uses palette colors for borders
258
- */
259
- export function generateBorderVariants(
260
- theme: ThemeContext,
261
- shade: ColorPaletteShade = 500,
262
- fallbacks: Record<string, string> = {
263
- red: '#ef4444',
264
- orange: '#f97316',
265
- yellow: '#eab308',
266
- green: '#22c55e',
267
- blue: '#3b82f6',
268
- purple: '#a855f7',
269
- black: '#202124',
270
- gray: '#6b7280',
271
- white: '#f8f8f8',
272
- }
273
- ) {
274
- const variants: Record<string, { borderColor: string; _web?: { border: string; color: string } }> = {};
275
-
276
- if (theme.palettes) {
277
- Object.keys(theme.palettes).forEach((colorKey) => {
278
- const palette = theme.palettes![colorKey];
279
- const color = palette?.[shade] || fallbacks[colorKey as ColorVariant];
280
- if (color) {
281
- variants[colorKey] = {
282
- borderColor: color,
283
- _web: {
284
- border: `1px solid ${color}`,
285
- color: color,
286
- },
287
- };
288
- }
289
- });
290
- } else {
291
- // Fallback to default colors if no palettes
292
- Object.entries(fallbacks).forEach(([colorKey, color]) => {
293
- variants[colorKey] = {
294
- borderColor: color,
295
- _web: {
296
- border: `1px solid ${color}`,
297
- color: color,
298
- },
299
- };
300
- });
301
- }
302
-
303
- return variants;
304
- }
305
-
306
- /**
307
- * Generate compound variants for combinations like variant + color
308
- */
309
- export function generateCompoundVariants<T extends Record<string, any>>(
310
- combinations: Array<{
311
- conditions: Record<string, string>;
312
- styles: T;
313
- }>
314
- ) {
315
- return combinations.map(({ conditions, styles }) => ({
316
- ...conditions,
317
- styles,
318
- }));
319
- }
320
-
321
- /**
322
- * Resolves a color variant to its actual color value
323
- * Supports both simple colors ('blue') and shade-specific colors ('blue.300')
324
- */
325
- function resolveColorVariant(colorVariant: string, theme: ThemeContext): string | null {
326
- const fallbacks: Record<string, string> = {
327
- red: '#ef4444',
328
- orange: '#f97316',
329
- yellow: '#eab308',
330
- green: '#22c55e',
331
- blue: '#3b82f6',
332
- purple: '#a855f7',
333
- black: '#202124',
334
- gray: '#6b7280',
335
- white: '#f8f8f8',
336
- };
337
-
338
- // Handle semantic colors
339
- if (['primary', 'secondary', 'disabled', 'inverse', 'muted'].includes(colorVariant)) {
340
- return theme.colors?.text?.[colorVariant as keyof typeof theme.colors.text] || null;
341
- }
342
-
343
- // Parse color variant (e.g., 'blue.300' or 'blue')
344
- const { color, shade } = parseColorVariant(colorVariant);
345
-
346
- // Try to get from theme palette
347
- if (theme.palettes?.[color]?.[shade]) {
348
- return theme.palettes[color][shade];
349
- }
350
-
351
- // Fallback for simple colors
352
- if (shade === 500 && fallbacks[color]) {
353
- return fallbacks[color];
354
- }
355
-
356
- return null;
357
- }
358
-
359
- /**
360
- * Generate compound variants for badge-like components
361
- * Combines variant type (filled, outlined, dot) with color (including shade-specific)
362
- */
363
- export function generateBadgeCompoundVariants(theme: ThemeContext) {
364
- const variants: Array<{
365
- variant: string;
366
- color: string;
367
- styles: Record<string, any>;
368
- }> = [];
369
-
370
- // Get all color variants from the generated color variants
371
- const colorVariants = generateColorVariants(theme);
372
-
373
- Object.keys(colorVariants).forEach((colorKey) => {
374
- const resolvedColor = resolveColorVariant(colorKey, theme);
375
-
376
- if (resolvedColor) {
377
- // Filled variant
378
- variants.push({
379
- variant: 'filled',
380
- color: colorKey,
381
- styles: {
382
- backgroundColor: resolvedColor,
383
- },
384
- });
385
-
386
- // Dot variant
387
- variants.push({
388
- variant: 'dot',
389
- color: colorKey,
390
- styles: {
391
- backgroundColor: resolvedColor,
392
- },
393
- });
394
-
395
- // Outlined variant
396
- variants.push({
397
- variant: 'outlined',
398
- color: colorKey,
399
- styles: {
400
- borderColor: resolvedColor,
401
- _web: {
402
- border: `1px solid ${resolvedColor}`,
403
- color: resolvedColor,
404
- },
405
- },
406
- });
407
- }
408
- });
409
-
410
- return variants;
411
- }
412
-
413
- /**
414
- * Generate compound variants for badge-like components using intents
415
- * Combines variant type (filled, outlined, dot) with intent
416
- */
417
- export function generateBadgeIntentCompoundVariants(theme: ThemeContext) {
418
- const variants: Array<{
419
- variant: string;
420
- intent: string;
421
- styles: Record<string, any>;
422
- }> = [];
423
-
424
- const intentKeys = theme.intents ? Object.keys(theme.intents) : [
425
- 'primary', 'success', 'error', 'warning', 'neutral', 'info'
426
- ];
427
-
428
- const fallbacks: Record<string, string> = {
429
- primary: '#3b82f6',
430
- success: '#22c55e',
431
- error: '#ef4444',
432
- warning: '#f59e0b',
433
- neutral: '#6b7280',
434
- info: '#06b6d4',
435
- };
436
-
437
- intentKeys.forEach((intentKey) => {
438
- const intent = theme.intents?.[intentKey];
439
- const mainColor = intent?.main || fallbacks[intentKey];
440
- if (mainColor) {
441
- // Filled variant
442
- variants.push({
443
- variant: 'filled',
444
- intent: intentKey,
445
- styles: {
446
- backgroundColor: mainColor,
447
- },
448
- });
449
-
450
- // Dot variant
451
- variants.push({
452
- variant: 'dot',
453
- intent: intentKey,
454
- styles: {
455
- backgroundColor: mainColor,
456
- },
457
- });
458
-
459
- // Outlined variant
460
- variants.push({
461
- variant: 'outlined',
462
- intent: intentKey,
463
- styles: {
464
- borderColor: mainColor,
465
- _web: {
466
- border: `1px solid ${mainColor}`,
467
- color: mainColor,
468
- },
469
- },
470
- });
471
- }
472
- });
473
-
474
- return variants;
475
- }
476
-
477
- /**
478
- * Generate compound variants for button-like components
479
- * Combines variant type (contained, outlined, text) with intent
480
- */
481
- export function generateButtonCompoundVariants(theme: ThemeContext) {
482
- const variants: Array<{
483
- variant: string;
484
- intent: string;
485
- styles: Record<string, any>;
486
- }> = [];
487
-
488
- const intentKeys = theme.intents ? Object.keys(theme.intents) : [
489
- 'primary', 'success', 'error', 'warning', 'neutral', 'info'
490
- ];
491
-
492
- const fallbacks: Record<string, string> = {
493
- primary: '#3b82f6',
494
- success: '#22c55e',
495
- error: '#ef4444',
496
- warning: '#f59e0b',
497
- neutral: '#6b7280',
498
- info: '#06b6d4',
499
- };
500
-
501
- intentKeys.forEach((intentKey) => {
502
- const intent = theme.intents?.[intentKey];
503
- const mainColor = intent?.main || fallbacks[intentKey];
504
- if (mainColor) {
505
- // Outlined variant
506
- variants.push({
507
- variant: 'outlined',
508
- intent: intentKey,
509
- styles: {
510
- backgroundColor: 'transparent',
511
- border: `1px solid ${mainColor}`,
512
- color: mainColor,
513
- },
514
- });
515
-
516
- // Text variant
517
- variants.push({
518
- variant: 'text',
519
- intent: intentKey,
520
- styles: {
521
- backgroundColor: 'transparent',
522
- color: mainColor,
523
- },
524
- });
525
- }
526
- });
527
-
528
- return variants;
529
- }
530
-
531
- /**
532
- * Component-level validation functions
533
- * These should be called by components to validate their props
534
- */
535
-
536
- /**
537
- * Validates a color prop used by a component
538
- */
539
- export function validateColorProp(
540
- theme: ThemeContext,
541
- color: string | undefined,
542
- componentName: string
543
- ): boolean {
544
- if (!color) return true; // undefined/null is valid (uses default)
545
-
546
- const isValid = validateColor(theme, color);
547
- if (!isValid) {
548
- warnInvalidColor(color, componentName);
549
- }
550
- return isValid;
551
- }
552
-
553
- /**
554
- * Validates an intent prop used by a component
555
- */
556
- export function validateIntentProp(
557
- theme: ThemeContext,
558
- intent: string | undefined,
559
- componentName: string
560
- ): boolean {
561
- if (!intent) return true; // undefined/null is valid (uses default)
562
-
563
- const isValid = validateIntent(theme, intent);
564
- if (!isValid) {
565
- warnInvalidIntent(intent, componentName);
566
- }
567
- return isValid;
568
- }
569
-
570
- /**
571
- * Gets available colors from theme (for error messages)
572
- */
573
- export function getAvailableColors(theme: ThemeContext): string[] {
574
- const semanticColors = ['primary', 'secondary', 'disabled', 'inverse', 'muted'];
575
- const paletteColors = theme.palettes ? Object.keys(theme.palettes) : [];
576
- return [...semanticColors, ...paletteColors];
577
- }
578
-
579
- /**
580
- * Gets available intents from theme (for error messages)
581
- */
582
- export function getAvailableIntents(theme: ThemeContext): string[] {
583
- return theme.intents ? Object.keys(theme.intents) : [];
584
- }
@@ -1,56 +0,0 @@
1
- /**
2
- * Theme Variant Types
3
- *
4
- * This file defines the type system for component styling:
5
- * - IntentVariant: For action-oriented components (buttons, inputs, alerts, etc.)
6
- * - ColorVariant: For display components (text, badges, avatars, etc.)
7
- */
8
-
9
- // Intent variants for action-oriented components
10
- // These map to semantic meanings and have contextual colors (main, on, container, etc.)
11
- export type IntentVariant =
12
- | 'primary'
13
- | 'success'
14
- | 'error'
15
- | 'warning'
16
- | 'neutral'
17
- | 'info';
18
-
19
- // Base color names - Standard color palette
20
- type BaseColors = 'red' | 'orange' | 'yellow' | 'green' | 'blue' | 'purple' | 'black' | 'gray' | 'white';
21
-
22
- // Color shades available in the palette
23
- type ColorShades = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
24
-
25
- // Generate color variants with shades using template literal types
26
- type ColorWithShades<T extends string> = T | `${T}.${ColorShades}`;
27
-
28
- // Color variants for display components
29
- // These map directly to color palette entries
30
- // Automatically generates: 'blue' | 'blue.50' | 'blue.100' | ... | 'cyan.900'
31
- export type ColorVariant = ColorWithShades<BaseColors>;
32
-
33
- // Semantic color variants for text and other display elements
34
- export type SemanticColorVariant =
35
- | 'primary' // Main text color
36
- | 'secondary' // Secondary text color
37
- | 'disabled' // Disabled text color
38
- | 'inverse' // Inverse text color
39
- | 'muted'; // Muted text color
40
-
41
- // Combined color variant type that includes both palette colors and semantic colors
42
- export type DisplayColorVariant = ColorVariant | SemanticColorVariant;
43
-
44
- // Helper types for theme integration
45
- export type IntentMapping = {
46
- palette: ColorVariant;
47
- main: number;
48
- on: string;
49
- container: number;
50
- onContainer: number;
51
- light: number;
52
- dark: number;
53
- border: number;
54
- };
55
-
56
- export type ColorPaletteShade = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;