@ttdk-design-system/library-svelte 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/AI_GUIDE.md +6518 -0
  2. package/dist/core/index.d.ts +2 -0
  3. package/dist/core/index.js +2 -0
  4. package/dist/core/tailwind-preset.cjs +62 -0
  5. package/dist/core/tailwind-preset.d.cts +63 -0
  6. package/dist/core/tailwind-preset.d.ts +74 -0
  7. package/dist/core/tailwind-preset.js +79 -0
  8. package/dist/core/theme/tokens.css +663 -0
  9. package/dist/core/types.d.ts +152 -0
  10. package/dist/core/types.js +735 -0
  11. package/dist/index.d.ts +14 -0
  12. package/dist/index.js +15 -0
  13. package/dist/tailwind-preset.cjs +62 -0
  14. package/dist/tailwind-preset.d.cts +63 -0
  15. package/dist/tailwind-preset.d.ts +74 -0
  16. package/dist/tailwind-preset.js +79 -0
  17. package/dist/types.d.ts +1 -0
  18. package/dist/types.js +1 -0
  19. package/dist/web/accordion/AI_GUIDE.md +149 -0
  20. package/dist/web/accordion/accordion.css +1 -0
  21. package/dist/web/accordion/accordion.svelte +217 -0
  22. package/dist/web/accordion/accordion.svelte.d.ts +224 -0
  23. package/dist/web/accordion/index.d.ts +2 -0
  24. package/dist/web/accordion/index.js +2 -0
  25. package/dist/web/accordion/manifest.json +351 -0
  26. package/dist/web/alert/AI_GUIDE.md +139 -0
  27. package/dist/web/alert/alert.css +1 -0
  28. package/dist/web/alert/alert.svelte +175 -0
  29. package/dist/web/alert/alert.svelte.d.ts +165 -0
  30. package/dist/web/alert/index.d.ts +2 -0
  31. package/dist/web/alert/index.js +2 -0
  32. package/dist/web/alert/manifest.json +240 -0
  33. package/dist/web/avatar/AI_GUIDE.md +118 -0
  34. package/dist/web/avatar/avatar.css +1 -0
  35. package/dist/web/avatar/avatar.svelte +108 -0
  36. package/dist/web/avatar/avatar.svelte.d.ts +147 -0
  37. package/dist/web/avatar/index.d.ts +2 -0
  38. package/dist/web/avatar/index.js +2 -0
  39. package/dist/web/avatar/manifest.json +195 -0
  40. package/dist/web/badge/AI_GUIDE.md +94 -0
  41. package/dist/web/badge/badge.css +1 -0
  42. package/dist/web/badge/badge.svelte +50 -0
  43. package/dist/web/badge/badge.svelte.d.ts +111 -0
  44. package/dist/web/badge/index.d.ts +2 -0
  45. package/dist/web/badge/index.js +2 -0
  46. package/dist/web/badge/manifest.json +141 -0
  47. package/dist/web/banner/AI_GUIDE.md +130 -0
  48. package/dist/web/banner/banner.css +1 -0
  49. package/dist/web/banner/banner.svelte +180 -0
  50. package/dist/web/banner/banner.svelte.d.ts +172 -0
  51. package/dist/web/banner/index.d.ts +2 -0
  52. package/dist/web/banner/index.js +2 -0
  53. package/dist/web/banner/manifest.json +240 -0
  54. package/dist/web/breadcrumb/AI_GUIDE.md +120 -0
  55. package/dist/web/breadcrumb/breadcrumb.css +1 -0
  56. package/dist/web/breadcrumb/breadcrumb.svelte +168 -0
  57. package/dist/web/breadcrumb/breadcrumb.svelte.d.ts +141 -0
  58. package/dist/web/breadcrumb/index.d.ts +2 -0
  59. package/dist/web/breadcrumb/index.js +2 -0
  60. package/dist/web/breadcrumb/manifest.json +225 -0
  61. package/dist/web/button/AI_GUIDE.md +121 -0
  62. package/dist/web/button/button.css +1 -0
  63. package/dist/web/button/button.svelte +154 -0
  64. package/dist/web/button/button.svelte.d.ts +159 -0
  65. package/dist/web/button/index.d.ts +2 -0
  66. package/dist/web/button/index.js +2 -0
  67. package/dist/web/button/manifest.json +177 -0
  68. package/dist/web/calendar/AI_GUIDE.md +151 -0
  69. package/dist/web/calendar/calendar.css +1 -0
  70. package/dist/web/calendar/calendar.svelte +1091 -0
  71. package/dist/web/calendar/calendar.svelte.d.ts +268 -0
  72. package/dist/web/calendar/index.d.ts +2 -0
  73. package/dist/web/calendar/index.js +2 -0
  74. package/dist/web/calendar/manifest.json +470 -0
  75. package/dist/web/card/AI_GUIDE.md +133 -0
  76. package/dist/web/card/card.css +1 -0
  77. package/dist/web/card/card.svelte +217 -0
  78. package/dist/web/card/card.svelte.d.ts +242 -0
  79. package/dist/web/card/index.d.ts +2 -0
  80. package/dist/web/card/index.js +2 -0
  81. package/dist/web/card/manifest.json +357 -0
  82. package/dist/web/checkbox/AI_GUIDE.md +146 -0
  83. package/dist/web/checkbox/checkbox.css +1 -0
  84. package/dist/web/checkbox/checkbox.svelte +131 -0
  85. package/dist/web/checkbox/checkbox.svelte.d.ts +199 -0
  86. package/dist/web/checkbox/index.d.ts +2 -0
  87. package/dist/web/checkbox/index.js +2 -0
  88. package/dist/web/checkbox/manifest.json +294 -0
  89. package/dist/web/chip/AI_GUIDE.md +186 -0
  90. package/dist/web/chip/chip.css +1 -0
  91. package/dist/web/chip/chip.svelte +113 -0
  92. package/dist/web/chip/chip.svelte.d.ts +145 -0
  93. package/dist/web/chip/index.d.ts +2 -0
  94. package/dist/web/chip/index.js +2 -0
  95. package/dist/web/chip/manifest.json +186 -0
  96. package/dist/web/dropdown/AI_GUIDE.md +167 -0
  97. package/dist/web/dropdown/dropdown.css +1 -0
  98. package/dist/web/dropdown/dropdown.svelte +844 -0
  99. package/dist/web/dropdown/dropdown.svelte.d.ts +361 -0
  100. package/dist/web/dropdown/index.d.ts +2 -0
  101. package/dist/web/dropdown/index.js +2 -0
  102. package/dist/web/dropdown/manifest.json +576 -0
  103. package/dist/web/flex/AI_GUIDE.md +113 -0
  104. package/dist/web/flex/flex-item.svelte +37 -0
  105. package/dist/web/flex/flex-item.svelte.d.ts +96 -0
  106. package/dist/web/flex/flex.css +1 -0
  107. package/dist/web/flex/flex.svelte +39 -0
  108. package/dist/web/flex/flex.svelte.d.ts +104 -0
  109. package/dist/web/flex/index.d.ts +3 -0
  110. package/dist/web/flex/index.js +3 -0
  111. package/dist/web/flex/manifest.json +162 -0
  112. package/dist/web/form/index.d.ts +1 -0
  113. package/dist/web/form/index.js +2 -0
  114. package/dist/web/grid/AI_GUIDE.md +112 -0
  115. package/dist/web/grid/grid-item.svelte +41 -0
  116. package/dist/web/grid/grid-item.svelte.d.ts +112 -0
  117. package/dist/web/grid/grid.css +1 -0
  118. package/dist/web/grid/grid.svelte +37 -0
  119. package/dist/web/grid/grid.svelte.d.ts +96 -0
  120. package/dist/web/grid/index.d.ts +3 -0
  121. package/dist/web/grid/index.js +3 -0
  122. package/dist/web/grid/manifest.json +153 -0
  123. package/dist/web/index.d.ts +58 -0
  124. package/dist/web/index.js +57 -0
  125. package/dist/web/input/AI_GUIDE.md +159 -0
  126. package/dist/web/input/index.d.ts +2 -0
  127. package/dist/web/input/index.js +2 -0
  128. package/dist/web/input/input.css +1 -0
  129. package/dist/web/input/input.svelte +283 -0
  130. package/dist/web/input/input.svelte.d.ts +283 -0
  131. package/dist/web/input/manifest.json +465 -0
  132. package/dist/web/input-number/AI_GUIDE.md +164 -0
  133. package/dist/web/input-number/index.d.ts +2 -0
  134. package/dist/web/input-number/index.js +2 -0
  135. package/dist/web/input-number/input-number.css +1 -0
  136. package/dist/web/input-number/input-number.svelte +783 -0
  137. package/dist/web/input-number/input-number.svelte.d.ts +352 -0
  138. package/dist/web/input-number/manifest.json +575 -0
  139. package/dist/web/modal/AI_GUIDE.md +171 -0
  140. package/dist/web/modal/index.d.ts +2 -0
  141. package/dist/web/modal/index.js +2 -0
  142. package/dist/web/modal/manifest.json +375 -0
  143. package/dist/web/modal/modal.css +1 -0
  144. package/dist/web/modal/modal.svelte +333 -0
  145. package/dist/web/modal/modal.svelte.d.ts +231 -0
  146. package/dist/web/pagination/AI_GUIDE.md +148 -0
  147. package/dist/web/pagination/index.d.ts +19 -0
  148. package/dist/web/pagination/index.js +19 -0
  149. package/dist/web/pagination/manifest.json +432 -0
  150. package/dist/web/pagination/pagination-content.svelte +25 -0
  151. package/dist/web/pagination/pagination-content.svelte.d.ts +36 -0
  152. package/dist/web/pagination/pagination-ellipsis.svelte +38 -0
  153. package/dist/web/pagination/pagination-ellipsis.svelte.d.ts +35 -0
  154. package/dist/web/pagination/pagination-first.svelte +105 -0
  155. package/dist/web/pagination/pagination-first.svelte.d.ts +74 -0
  156. package/dist/web/pagination/pagination-item.svelte +25 -0
  157. package/dist/web/pagination/pagination-item.svelte.d.ts +36 -0
  158. package/dist/web/pagination/pagination-last.svelte +105 -0
  159. package/dist/web/pagination/pagination-last.svelte.d.ts +74 -0
  160. package/dist/web/pagination/pagination-link.svelte +67 -0
  161. package/dist/web/pagination/pagination-link.svelte.d.ts +69 -0
  162. package/dist/web/pagination/pagination-next.svelte +99 -0
  163. package/dist/web/pagination/pagination-next.svelte.d.ts +75 -0
  164. package/dist/web/pagination/pagination-previous.svelte +99 -0
  165. package/dist/web/pagination/pagination-previous.svelte.d.ts +75 -0
  166. package/dist/web/pagination/pagination.css +1 -0
  167. package/dist/web/pagination/pagination.svelte +471 -0
  168. package/dist/web/pagination/pagination.svelte.d.ts +256 -0
  169. package/dist/web/popover/AI_GUIDE.md +163 -0
  170. package/dist/web/popover/index.d.ts +3 -0
  171. package/dist/web/popover/index.js +3 -0
  172. package/dist/web/popover/manifest.json +396 -0
  173. package/dist/web/popover/popover.css +1 -0
  174. package/dist/web/popover/popover.svelte +497 -0
  175. package/dist/web/popover/popover.svelte.d.ts +116 -0
  176. package/dist/web/radio/AI_GUIDE.md +155 -0
  177. package/dist/web/radio/index.d.ts +2 -0
  178. package/dist/web/radio/index.js +2 -0
  179. package/dist/web/radio/manifest.json +294 -0
  180. package/dist/web/radio/radio.css +1 -0
  181. package/dist/web/radio/radio.svelte +123 -0
  182. package/dist/web/radio/radio.svelte.d.ts +192 -0
  183. package/dist/web/selectbox/AI_GUIDE.md +216 -0
  184. package/dist/web/selectbox/index.d.ts +2 -0
  185. package/dist/web/selectbox/index.js +2 -0
  186. package/dist/web/selectbox/manifest.json +477 -0
  187. package/dist/web/selectbox/selectbox.css +1 -0
  188. package/dist/web/selectbox/selectbox.svelte +704 -0
  189. package/dist/web/selectbox/selectbox.svelte.d.ts +296 -0
  190. package/dist/web/sonner/AI_GUIDE.md +98 -0
  191. package/dist/web/sonner/index.d.ts +46 -0
  192. package/dist/web/sonner/index.js +64 -0
  193. package/dist/web/sonner/manifest.json +132 -0
  194. package/dist/web/sonner/sonner.css +1 -0
  195. package/dist/web/sonner/sonner.svelte +85 -0
  196. package/dist/web/sonner/sonner.svelte.d.ts +105 -0
  197. package/dist/web/table/AI_GUIDE.md +145 -0
  198. package/dist/web/table/index.d.ts +21 -0
  199. package/dist/web/table/index.js +22 -0
  200. package/dist/web/table/manifest.json +168 -0
  201. package/dist/web/table/table-body.svelte +23 -0
  202. package/dist/web/table/table-body.svelte.d.ts +36 -0
  203. package/dist/web/table/table-caption.svelte +23 -0
  204. package/dist/web/table/table-caption.svelte.d.ts +36 -0
  205. package/dist/web/table/table-cell.svelte +35 -0
  206. package/dist/web/table/table-cell.svelte.d.ts +57 -0
  207. package/dist/web/table/table-empty.svelte +56 -0
  208. package/dist/web/table/table-empty.svelte.d.ts +65 -0
  209. package/dist/web/table/table-footer.svelte +23 -0
  210. package/dist/web/table/table-footer.svelte.d.ts +36 -0
  211. package/dist/web/table/table-head.svelte +39 -0
  212. package/dist/web/table/table-head.svelte.d.ts +58 -0
  213. package/dist/web/table/table-header.svelte +23 -0
  214. package/dist/web/table/table-header.svelte.d.ts +36 -0
  215. package/dist/web/table/table-row.svelte +33 -0
  216. package/dist/web/table/table-row.svelte.d.ts +52 -0
  217. package/dist/web/table/table.css +1 -0
  218. package/dist/web/table/table.svelte +178 -0
  219. package/dist/web/table/table.svelte.d.ts +120 -0
  220. package/dist/web/tabs/AI_GUIDE.md +150 -0
  221. package/dist/web/tabs/index.d.ts +2 -0
  222. package/dist/web/tabs/index.js +2 -0
  223. package/dist/web/tabs/manifest.json +315 -0
  224. package/dist/web/tabs/tabs.css +1 -0
  225. package/dist/web/tabs/tabs.svelte +138 -0
  226. package/dist/web/tabs/tabs.svelte.d.ts +204 -0
  227. package/dist/web/text/AI_GUIDE.md +129 -0
  228. package/dist/web/text/index.d.ts +2 -0
  229. package/dist/web/text/index.js +2 -0
  230. package/dist/web/text/manifest.json +195 -0
  231. package/dist/web/text/text.css +1 -0
  232. package/dist/web/text/text.svelte +515 -0
  233. package/dist/web/text/text.svelte.d.ts +168 -0
  234. package/dist/web/textarea/AI_GUIDE.md +141 -0
  235. package/dist/web/textarea/index.d.ts +2 -0
  236. package/dist/web/textarea/index.js +2 -0
  237. package/dist/web/textarea/manifest.json +438 -0
  238. package/dist/web/textarea/textarea.css +1 -0
  239. package/dist/web/textarea/textarea.svelte +224 -0
  240. package/dist/web/textarea/textarea.svelte.d.ts +274 -0
  241. package/dist/web/tooltip/AI_GUIDE.md +110 -0
  242. package/dist/web/tooltip/index.d.ts +2 -0
  243. package/dist/web/tooltip/index.js +2 -0
  244. package/dist/web/tooltip/manifest.json +222 -0
  245. package/dist/web/tooltip/tooltip.css +1 -0
  246. package/dist/web/tooltip/tooltip.svelte +292 -0
  247. package/dist/web/tooltip/tooltip.svelte.d.ts +140 -0
  248. package/dist/webview/bottomsheet/AI_GUIDE.md +141 -0
  249. package/dist/webview/bottomsheet/bottomsheet.css +1 -0
  250. package/dist/webview/bottomsheet/bottomsheet.svelte +462 -0
  251. package/dist/webview/bottomsheet/bottomsheet.svelte.d.ts +200 -0
  252. package/dist/webview/bottomsheet/index.d.ts +4 -0
  253. package/dist/webview/bottomsheet/index.js +3 -0
  254. package/dist/webview/bottomsheet/manifest.json +377 -0
  255. package/dist/webview/button/AI_GUIDE.md +79 -0
  256. package/dist/webview/button/button-ios.css +1 -0
  257. package/dist/webview/button/button-ios.svelte +58 -0
  258. package/dist/webview/button/button-ios.svelte.d.ts +114 -0
  259. package/dist/webview/button/button-material.css +1 -0
  260. package/dist/webview/button/button-material.svelte +58 -0
  261. package/dist/webview/button/button-material.svelte.d.ts +114 -0
  262. package/dist/webview/button/index.d.ts +6 -0
  263. package/dist/webview/button/index.js +4 -0
  264. package/dist/webview/button/manifest.json +148 -0
  265. package/dist/webview/index.d.ts +6 -0
  266. package/dist/webview/index.js +6 -0
  267. package/llms.txt +6518 -0
  268. package/package.json +709 -4
  269. package/ttdk-manifest.json +10188 -0
  270. package/README.md +0 -3
@@ -0,0 +1,735 @@
1
+ export const ResponsiveBreakpoints = {};
2
+ export const UiProps = {};
3
+ /**
4
+ * Helper to build responsive CSS custom properties from a ResponsiveUiProps object.
5
+ */
6
+ export function buildResponsiveVars(ui, keyMap) {
7
+ if (!ui)
8
+ return {};
9
+ const styles = {};
10
+ const breakpoints = ['sm', 'lt_sm', 'md', 'lt_md', 'lg', 'lt_lg', 'xl', 'lt_xl'];
11
+ // Process default / base level
12
+ for (const [uiKey, cssVar] of Object.entries(keyMap)) {
13
+ if (ui[uiKey] !== undefined) {
14
+ styles[cssVar] = String(ui[uiKey]);
15
+ }
16
+ }
17
+ // Process each breakpoint
18
+ for (const bp of breakpoints) {
19
+ const bpObj = ui[bp];
20
+ if (bpObj && typeof bpObj === 'object') {
21
+ for (const [uiKey, cssVar] of Object.entries(keyMap)) {
22
+ if (bpObj[uiKey] !== undefined) {
23
+ const bpSuffix = bp.replace('_', '-');
24
+ styles[`${cssVar}-${bpSuffix}`] = String(bpObj[uiKey]);
25
+ }
26
+ }
27
+ }
28
+ }
29
+ return styles;
30
+ }
31
+ const PSEUDOS = ['hover', 'active', 'focus', 'disabled', 'dark'];
32
+ const BREAKPOINTS = ['sm', 'lt_sm', 'lt-sm', 'md', 'lt_md', 'lt-md', 'lg', 'lt_lg', 'lt-lg', 'xl', 'lt_xl', 'lt-xl', '2xl'];
33
+ const BREAKPOINT_QUERIES = {
34
+ sm: '(min-width: 640px)',
35
+ lt_sm: '(max-width: 639px)',
36
+ 'lt-sm': '(max-width: 639px)',
37
+ md: '(min-width: 768px)',
38
+ lt_md: '(max-width: 767px)',
39
+ 'lt-md': '(max-width: 767px)',
40
+ lg: '(min-width: 1024px)',
41
+ lt_lg: '(max-width: 1023px)',
42
+ 'lt-lg': '(max-width: 1023px)',
43
+ xl: '(min-width: 1280px)',
44
+ lt_xl: '(max-width: 1279px)',
45
+ 'lt-xl': '(max-width: 1279px)',
46
+ '2xl': '(min-width: 1536px)',
47
+ };
48
+ const BUCKET_ORDER = [
49
+ 'pseudos',
50
+ 'lt_xl',
51
+ 'lt-xl',
52
+ 'lt_lg',
53
+ 'lt-lg',
54
+ 'lt_md',
55
+ 'lt-md',
56
+ 'lt_sm',
57
+ 'lt-sm',
58
+ 'sm',
59
+ 'md',
60
+ 'lg',
61
+ 'xl',
62
+ '2xl',
63
+ ];
64
+ /** Convert camelCase ke kebab-case: backgroundColor → background-color */
65
+ function toKebab(str) {
66
+ return str.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
67
+ }
68
+ /** Membersihkan akhiran !important jika user tidak sengaja menyertakannya di string nilai */
69
+ export function cleanUiValue(v) {
70
+ if (typeof v === 'string') {
71
+ return v.replace(/\s*!important\s*$/i, '').trim();
72
+ }
73
+ return String(v);
74
+ }
75
+ function resolveCssProperty(key) {
76
+ if (key === 'bg')
77
+ return 'background-color';
78
+ if (key === 'size')
79
+ return 'font-size';
80
+ if (key === 'weight')
81
+ return 'font-weight';
82
+ return toKebab(key);
83
+ }
84
+ // ============================================================
85
+ // Dynamic Runtime CSS Injection Engine
86
+ // ============================================================
87
+ const injectedRuleSet = new Set();
88
+ const styleBuckets = {};
89
+ function getBucketElement(bucket) {
90
+ if (typeof document === 'undefined')
91
+ return null;
92
+ if (styleBuckets[bucket] && document.head.contains(styleBuckets[bucket])) {
93
+ return styleBuckets[bucket];
94
+ }
95
+ const safeId = `ttdk-dyn-${bucket.replace('_', '-')}`;
96
+ let el = document.getElementById(safeId);
97
+ if (!el) {
98
+ el = document.createElement('style');
99
+ el.id = safeId;
100
+ el.setAttribute('data-ttdk-dynamic', 'true');
101
+ // Pastikan urutan tag style di <head> sesuai cascade specificity
102
+ const bucketIndex = BUCKET_ORDER.indexOf(bucket);
103
+ let nextSibling = null;
104
+ if (bucketIndex !== -1) {
105
+ for (let i = bucketIndex + 1; i < BUCKET_ORDER.length; i++) {
106
+ const nextId = `ttdk-dyn-${BUCKET_ORDER[i].replace('_', '-')}`;
107
+ const nextEl = document.getElementById(nextId);
108
+ if (nextEl) {
109
+ nextSibling = nextEl;
110
+ break;
111
+ }
112
+ }
113
+ }
114
+ if (nextSibling) {
115
+ document.head.insertBefore(el, nextSibling);
116
+ }
117
+ else {
118
+ document.head.appendChild(el);
119
+ }
120
+ }
121
+ styleBuckets[bucket] = el;
122
+ return el;
123
+ }
124
+ export function injectDynamicCss(bucket, ruleKey, cssRule) {
125
+ if (injectedRuleSet.has(ruleKey))
126
+ return;
127
+ injectedRuleSet.add(ruleKey);
128
+ const el = getBucketElement(bucket);
129
+ if (!el)
130
+ return;
131
+ el.appendChild(document.createTextNode(cssRule + '\n'));
132
+ }
133
+ function getBaseVarRule(pseudo, varName, cssProp) {
134
+ const baseVar = varName.replace(`-${pseudo}-`, '-');
135
+ if (baseVar === varName)
136
+ return '';
137
+ let extra = `${baseVar}: var(${varName}) !important;`;
138
+ // Extra aliases for background
139
+ if (baseVar.endsWith('-background') || baseVar.endsWith('-bg')) {
140
+ extra += ` ${baseVar.replace(/-(background|bg)$/, '-bg')}: var(${varName}) !important;`;
141
+ extra += ` ${baseVar.replace(/-(background|bg)$/, '-background')}: var(${varName}) !important;`;
142
+ extra += ` ${baseVar.replace(/-(background|bg)$/, '-background-color')}: var(${varName}) !important;`;
143
+ }
144
+ return extra;
145
+ }
146
+ function injectPseudoRule(pseudo, varName, cssProp) {
147
+ const baseVarRule = getBaseVarRule(pseudo, varName, cssProp);
148
+ // Dark mode menggunakan ancestor class selector, bukan CSS pseudo-class
149
+ if (pseudo === 'dark') {
150
+ const selector = `.dark [style*="${varName}:"], .dark[style*="${varName}:"], [data-theme="dark"] [style*="${varName}:"], [data-theme="dark"][style*="${varName}:"]`;
151
+ const rule = `${selector} { ${cssProp}: var(${varName}) !important; ${baseVarRule} }`;
152
+ injectDynamicCss('pseudos', `pseudo:${varName}:${cssProp}`, rule);
153
+ return;
154
+ }
155
+ let pseudoSelector = `:hover`;
156
+ if (pseudo === 'active')
157
+ pseudoSelector = `:active`;
158
+ else if (pseudo === 'focus')
159
+ pseudoSelector = `:focus, [style*="${varName}:"]:focus-visible`;
160
+ else if (pseudo === 'disabled')
161
+ pseudoSelector = `:disabled, [style*="${varName}:"][aria-disabled="true"]`;
162
+ const rule = `[style*="${varName}:"]${pseudoSelector} { ${cssProp}: var(${varName}) !important; ${baseVarRule} }`;
163
+ injectDynamicCss('pseudos', `pseudo:${varName}:${cssProp}`, rule);
164
+ }
165
+ function injectBreakpointRule(bp, varName, cssProp) {
166
+ const query = BREAKPOINT_QUERIES[bp];
167
+ if (!query)
168
+ return;
169
+ const rule = `@media ${query} { [style*="${varName}:"] { ${cssProp}: var(${varName}) !important; } }`;
170
+ injectDynamicCss(bp, `bp:${bp}:${varName}:${cssProp}`, rule);
171
+ }
172
+ function injectNestedPseudoBreakpointRule(bp, pseudo, varName, cssProp) {
173
+ const query = BREAKPOINT_QUERIES[bp];
174
+ if (!query)
175
+ return;
176
+ const baseVarRule = getBaseVarRule(pseudo, varName, cssProp);
177
+ // Dark mode menggunakan ancestor class selector dalam media query
178
+ if (pseudo === 'dark') {
179
+ const selector = `.dark [style*="${varName}:"], .dark[style*="${varName}:"], [data-theme="dark"] [style*="${varName}:"], [data-theme="dark"][style*="${varName}:"]`;
180
+ const rule = `@media ${query} { ${selector} { ${cssProp}: var(${varName}) !important; ${baseVarRule} } }`;
181
+ injectDynamicCss(bp, `nested:${bp}:${pseudo}:${varName}:${cssProp}`, rule);
182
+ return;
183
+ }
184
+ let pseudoSelector = `:hover`;
185
+ if (pseudo === 'active')
186
+ pseudoSelector = `:active`;
187
+ else if (pseudo === 'focus')
188
+ pseudoSelector = `:focus, [style*="${varName}:"]:focus-visible`;
189
+ else if (pseudo === 'disabled')
190
+ pseudoSelector = `:disabled, [style*="${varName}:"][aria-disabled="true"]`;
191
+ const rule = `@media ${query} { [style*="${varName}:"]${pseudoSelector} { ${cssProp}: var(${varName}) !important; ${baseVarRule} } }`;
192
+ injectDynamicCss(bp, `nested:${bp}:${pseudo}:${varName}:${cssProp}`, rule);
193
+ }
194
+ /**
195
+ * Mengambil properti CSS native biasa (seperti color, fontSize, letterSpacing, transform, dll.)
196
+ * untuk langsung diterapkan sebagai inline style native browser.
197
+ * Mengabaikan pseudo-classes ('hover', 'focus') dan responsive breakpoints ('sm', 'md', dll.).
198
+ */
199
+ export function extractBaseStyles(ui) {
200
+ if (!ui || typeof ui !== 'object')
201
+ return {};
202
+ const base = {};
203
+ for (const [key, value] of Object.entries(ui)) {
204
+ if (value === undefined || value === null)
205
+ continue;
206
+ if (PSEUDOS.includes(key) || BREAKPOINTS.includes(key))
207
+ continue;
208
+ if (typeof value === 'object')
209
+ continue;
210
+ const cleaned = typeof value === 'string' ? cleanUiValue(value) : value;
211
+ // Support alias
212
+ if (key === 'bg') {
213
+ base['backgroundColor'] = cleaned;
214
+ }
215
+ else if (key === 'size') {
216
+ base['fontSize'] = cleaned;
217
+ }
218
+ else if (key === 'weight') {
219
+ base['fontWeight'] = cleaned;
220
+ }
221
+ else {
222
+ base[key] = cleaned;
223
+ }
224
+ }
225
+ return base;
226
+ }
227
+ /**
228
+ * buildUiVars — konversi UiProps ke CSS custom properties untuk dipakai di style attribute
229
+ * sekaligus mendaftarkan aturan dinamis (pseudo & responsive media queries) secara otomatis.
230
+ */
231
+ export function buildUiVars(ui, prefix = '--ttdk-ui') {
232
+ if (!ui)
233
+ return {};
234
+ const vars = { ...extractBaseStyles(ui) };
235
+ // 1. Base props
236
+ for (const [key, value] of Object.entries(ui)) {
237
+ if (value === undefined || value === null)
238
+ continue;
239
+ if (PSEUDOS.includes(key) || BREAKPOINTS.includes(key))
240
+ continue;
241
+ if (typeof value === 'object')
242
+ continue;
243
+ const strVal = cleanUiValue(value);
244
+ vars[`${prefix}-${toKebab(key)}`] = strVal;
245
+ if (key === 'bg') {
246
+ vars[`${prefix}-background`] = strVal;
247
+ vars[`${prefix}-background-color`] = strVal;
248
+ }
249
+ else if (key === 'background' || key === 'backgroundColor') {
250
+ vars[`${prefix}-background`] = strVal;
251
+ vars[`${prefix}-bg`] = strVal;
252
+ }
253
+ else if (key === 'size') {
254
+ vars[`${prefix}-font-size`] = strVal;
255
+ }
256
+ else if (key === 'weight') {
257
+ vars[`${prefix}-font-weight`] = strVal;
258
+ }
259
+ }
260
+ // 2. Pseudo-classes at root: hover: { color: 'red', md: { color: 'blue' } }
261
+ for (const pseudo of PSEUDOS) {
262
+ const pseudoObj = ui[pseudo];
263
+ if (!pseudoObj || typeof pseudoObj !== 'object')
264
+ continue;
265
+ for (const [key, value] of Object.entries(pseudoObj)) {
266
+ if (value === undefined || value === null)
267
+ continue;
268
+ // Nested breakpoint inside pseudo: hover: { md: { background: 'blue' } }
269
+ if (BREAKPOINTS.includes(key)) {
270
+ const bpObj = value;
271
+ if (bpObj && typeof bpObj === 'object') {
272
+ for (const [subKey, subVal] of Object.entries(bpObj)) {
273
+ if (subVal === undefined || subVal === null || typeof subVal === 'object')
274
+ continue;
275
+ const kebab = toKebab(subKey);
276
+ const varName = `${prefix}-${pseudo}-${kebab}-${key}`;
277
+ vars[varName] = String(subVal);
278
+ injectNestedPseudoBreakpointRule(key, pseudo, varName, resolveCssProperty(subKey));
279
+ if (subKey === 'bg') {
280
+ const bgVar = `${prefix}-${pseudo}-background-${key}`;
281
+ vars[bgVar] = String(subVal);
282
+ injectNestedPseudoBreakpointRule(key, pseudo, bgVar, 'background');
283
+ const bgColVar = `${prefix}-${pseudo}-background-color-${key}`;
284
+ vars[bgColVar] = String(subVal);
285
+ injectNestedPseudoBreakpointRule(key, pseudo, bgColVar, 'background-color');
286
+ }
287
+ else if (subKey === 'background' || subKey === 'backgroundColor') {
288
+ const bgVar = `${prefix}-${pseudo}-background-${key}`;
289
+ vars[bgVar] = String(subVal);
290
+ injectNestedPseudoBreakpointRule(key, pseudo, bgVar, 'background');
291
+ const bgShortVar = `${prefix}-${pseudo}-bg-${key}`;
292
+ vars[bgShortVar] = String(subVal);
293
+ injectNestedPseudoBreakpointRule(key, pseudo, bgShortVar, 'background');
294
+ }
295
+ }
296
+ }
297
+ continue;
298
+ }
299
+ if (typeof value === 'object')
300
+ continue;
301
+ const kebab = toKebab(key);
302
+ const varName = `${prefix}-${pseudo}-${kebab}`;
303
+ vars[varName] = String(value);
304
+ injectPseudoRule(pseudo, varName, resolveCssProperty(key));
305
+ // alias: backgroundColor / bg
306
+ if (key === 'backgroundColor' || key === 'bg') {
307
+ const bgVar = `${prefix}-${pseudo}-background`;
308
+ vars[bgVar] = String(value);
309
+ injectPseudoRule(pseudo, bgVar, 'background');
310
+ const bgShortVar = `${prefix}-${pseudo}-bg`;
311
+ vars[bgShortVar] = String(value);
312
+ injectPseudoRule(pseudo, bgShortVar, 'background');
313
+ }
314
+ else if (key === 'background') {
315
+ const bgShortVar = `${prefix}-${pseudo}-bg`;
316
+ vars[bgShortVar] = String(value);
317
+ injectPseudoRule(pseudo, bgShortVar, 'background');
318
+ }
319
+ }
320
+ }
321
+ // 3. Breakpoints at root: md: { background: 'teal', hover: { background: '#fae8ff' } }
322
+ for (const bp of BREAKPOINTS) {
323
+ const bpObj = ui[bp];
324
+ if (!bpObj || typeof bpObj !== 'object')
325
+ continue;
326
+ for (const [key, value] of Object.entries(bpObj)) {
327
+ if (value === undefined || value === null)
328
+ continue;
329
+ // Nested pseudo inside breakpoint: md: { hover: { background: '#fae8ff' } }
330
+ if (PSEUDOS.includes(key)) {
331
+ const pseudoObj = value;
332
+ if (pseudoObj && typeof pseudoObj === 'object') {
333
+ for (const [pseudoKey, pseudoVal] of Object.entries(pseudoObj)) {
334
+ if (pseudoVal === undefined || pseudoVal === null || typeof pseudoVal === 'object')
335
+ continue;
336
+ const kebab = toKebab(pseudoKey);
337
+ const varName = `${prefix}-${key}-${kebab}-${bp}`;
338
+ vars[varName] = String(pseudoVal);
339
+ injectNestedPseudoBreakpointRule(bp, key, varName, resolveCssProperty(pseudoKey));
340
+ if (pseudoKey === 'bg') {
341
+ const bgVar = `${prefix}-${key}-background-${bp}`;
342
+ vars[bgVar] = String(pseudoVal);
343
+ injectNestedPseudoBreakpointRule(bp, key, bgVar, 'background');
344
+ const bgColVar = `${prefix}-${key}-background-color-${bp}`;
345
+ vars[bgColVar] = String(pseudoVal);
346
+ injectNestedPseudoBreakpointRule(bp, key, bgColVar, 'background-color');
347
+ }
348
+ else if (pseudoKey === 'background' || pseudoKey === 'backgroundColor') {
349
+ const bgVar = `${prefix}-${key}-background-${bp}`;
350
+ vars[bgVar] = String(pseudoVal);
351
+ injectNestedPseudoBreakpointRule(bp, key, bgVar, 'background');
352
+ const bgShortVar = `${prefix}-${key}-bg-${bp}`;
353
+ vars[bgShortVar] = String(pseudoVal);
354
+ injectNestedPseudoBreakpointRule(bp, key, bgShortVar, 'background');
355
+ }
356
+ }
357
+ }
358
+ continue;
359
+ }
360
+ if (typeof value === 'object')
361
+ continue;
362
+ const kebab = toKebab(key);
363
+ const varName = `${prefix}-${kebab}-${bp}`;
364
+ vars[varName] = String(value);
365
+ injectBreakpointRule(bp, varName, resolveCssProperty(key));
366
+ if (key === 'bg') {
367
+ const bgVar = `${prefix}-background-${bp}`;
368
+ vars[bgVar] = String(value);
369
+ injectBreakpointRule(bp, bgVar, 'background');
370
+ const bgColVar = `${prefix}-background-color-${bp}`;
371
+ vars[bgColVar] = String(value);
372
+ injectBreakpointRule(bp, bgColVar, 'background-color');
373
+ }
374
+ else if (key === 'background' || key === 'backgroundColor') {
375
+ const bgVar = `${prefix}-background-${bp}`;
376
+ vars[bgVar] = String(value);
377
+ injectBreakpointRule(bp, bgVar, 'background');
378
+ const bgShortVar = `${prefix}-bg-${bp}`;
379
+ vars[bgShortVar] = String(value);
380
+ injectBreakpointRule(bp, bgShortVar, 'background');
381
+ }
382
+ else if (key === 'size') {
383
+ const sizeVar = `${prefix}-font-size-${bp}`;
384
+ vars[sizeVar] = String(value);
385
+ injectBreakpointRule(bp, sizeVar, 'font-size');
386
+ }
387
+ else if (key === 'weight') {
388
+ const weightVar = `${prefix}-font-weight-${bp}`;
389
+ vars[weightVar] = String(value);
390
+ injectBreakpointRule(bp, weightVar, 'font-weight');
391
+ }
392
+ }
393
+ }
394
+ return vars;
395
+ }
396
+ /**
397
+ * buildUiStyle — Solusi HYBRID:
398
+ * Menggabungkan native inline style (agar ratusan CSS properties native langsung jalan 100%)
399
+ * dengan CSS custom properties (agar :hover dan responsive media query tetap bekerja sempurna).
400
+ */
401
+ export function buildUiStyle(ui, prefix = '--ttdk-ui') {
402
+ return buildUiVars(ui, prefix);
403
+ }
404
+ // ============================================================
405
+ // Layout Helpers for Flex & Grid
406
+ // ============================================================
407
+ function mapFlexJustify(val) {
408
+ if (!val)
409
+ return undefined;
410
+ if (val === 'start')
411
+ return 'flex-start';
412
+ if (val === 'end')
413
+ return 'flex-end';
414
+ if (val === 'around')
415
+ return 'space-around';
416
+ if (val === 'between')
417
+ return 'space-between';
418
+ if (val === 'evenly')
419
+ return 'space-evenly';
420
+ return val;
421
+ }
422
+ function mapFlexAlign(val) {
423
+ if (!val)
424
+ return undefined;
425
+ if (val === 'start')
426
+ return 'flex-start';
427
+ if (val === 'end')
428
+ return 'flex-end';
429
+ return val;
430
+ }
431
+ function formatGap(val) {
432
+ if (val === undefined || val === null || val === '')
433
+ return undefined;
434
+ if (typeof val === 'number')
435
+ return `${val}px`;
436
+ return String(val);
437
+ }
438
+ export function buildFlexVars(props) {
439
+ if (!props)
440
+ return {};
441
+ const vars = {};
442
+ // Base
443
+ if (props.direction)
444
+ vars['--ttdk-flex-direction'] = props.direction;
445
+ if (props.justifyContent)
446
+ vars['--ttdk-flex-justify-content'] = mapFlexJustify(props.justifyContent) || props.justifyContent;
447
+ if (props.alignItems)
448
+ vars['--ttdk-flex-align-items'] = mapFlexAlign(props.alignItems) || props.alignItems;
449
+ if (props.gap !== undefined) {
450
+ const g = formatGap(props.gap);
451
+ if (g)
452
+ vars['--ttdk-flex-gap'] = g;
453
+ }
454
+ if (props.wrap)
455
+ vars['--ttdk-flex-wrap'] = props.wrap;
456
+ // Breakpoints
457
+ const bps = ['sm', 'md', 'lg', 'xl', '2xl'];
458
+ for (const bp of bps) {
459
+ const override = props[bp] || (bp === '2xl' ? (props['xxl'] || props['2xl']) : undefined);
460
+ if (override && typeof override === 'object') {
461
+ if (override.direction)
462
+ vars[`--ttdk-flex-direction-${bp}`] = override.direction;
463
+ if (override.justifyContent)
464
+ vars[`--ttdk-flex-justify-content-${bp}`] = mapFlexJustify(override.justifyContent) || override.justifyContent;
465
+ if (override.alignItems)
466
+ vars[`--ttdk-flex-align-items-${bp}`] = mapFlexAlign(override.alignItems) || override.alignItems;
467
+ if (override.gap !== undefined) {
468
+ const g = formatGap(override.gap);
469
+ if (g)
470
+ vars[`--ttdk-flex-gap-${bp}`] = g;
471
+ }
472
+ if (override.wrap)
473
+ vars[`--ttdk-flex-wrap-${bp}`] = override.wrap;
474
+ }
475
+ }
476
+ return vars;
477
+ }
478
+ function mapFlexAlignSelf(val) {
479
+ if (!val)
480
+ return undefined;
481
+ if (val === 'start')
482
+ return 'flex-start';
483
+ if (val === 'end')
484
+ return 'flex-end';
485
+ return val;
486
+ }
487
+ function formatFlexBasis(val) {
488
+ if (val === undefined || val === null || val === '')
489
+ return undefined;
490
+ if (typeof val === 'number')
491
+ return `${val}px`;
492
+ return String(val);
493
+ }
494
+ function formatFlexGrowShrink(val) {
495
+ if (val === undefined || val === null)
496
+ return undefined;
497
+ if (typeof val === 'boolean')
498
+ return val ? '1' : '0';
499
+ return String(val);
500
+ }
501
+ export function buildFlexItemVars(props) {
502
+ if (!props)
503
+ return {};
504
+ const vars = {};
505
+ // Base
506
+ if (props.order !== undefined)
507
+ vars['--ttdk-flex-item-order'] = String(props.order);
508
+ if (props.grow !== undefined) {
509
+ const g = formatFlexGrowShrink(props.grow);
510
+ if (g)
511
+ vars['--ttdk-flex-item-grow'] = g;
512
+ }
513
+ if (props.shrink !== undefined) {
514
+ const s = formatFlexGrowShrink(props.shrink);
515
+ if (s)
516
+ vars['--ttdk-flex-item-shrink'] = s;
517
+ }
518
+ if (props.basis !== undefined) {
519
+ const b = formatFlexBasis(props.basis);
520
+ if (b)
521
+ vars['--ttdk-flex-item-basis'] = b;
522
+ }
523
+ if (props.alignSelf)
524
+ vars['--ttdk-flex-item-align-self'] = mapFlexAlignSelf(props.alignSelf) || props.alignSelf;
525
+ // Breakpoints
526
+ const bps = ['sm', 'md', 'lg', 'xl', '2xl'];
527
+ for (const bp of bps) {
528
+ const override = props[bp] || (bp === '2xl' ? (props['xxl'] || props['2xl']) : undefined);
529
+ if (override && typeof override === 'object') {
530
+ if (override.order !== undefined)
531
+ vars[`--ttdk-flex-item-order-${bp}`] = String(override.order);
532
+ if (override.grow !== undefined) {
533
+ const g = formatFlexGrowShrink(override.grow);
534
+ if (g)
535
+ vars[`--ttdk-flex-item-grow-${bp}`] = g;
536
+ }
537
+ if (override.shrink !== undefined) {
538
+ const s = formatFlexGrowShrink(override.shrink);
539
+ if (s)
540
+ vars[`--ttdk-flex-item-shrink-${bp}`] = s;
541
+ }
542
+ if (override.basis !== undefined) {
543
+ const b = formatFlexBasis(override.basis);
544
+ if (b)
545
+ vars[`--ttdk-flex-item-basis-${bp}`] = b;
546
+ }
547
+ if (override.alignSelf)
548
+ vars[`--ttdk-flex-item-align-self-${bp}`] = mapFlexAlignSelf(override.alignSelf) || override.alignSelf;
549
+ }
550
+ }
551
+ return vars;
552
+ }
553
+ function formatGridTemplate(val) {
554
+ if (val === undefined || val === null || val === '')
555
+ return undefined;
556
+ if (typeof val === 'number')
557
+ return `repeat(${val}, minmax(0, 1fr))`;
558
+ return String(val);
559
+ }
560
+ function mapGridJustifyContent(val) {
561
+ if (!val)
562
+ return undefined;
563
+ if (val === 'start')
564
+ return 'start';
565
+ if (val === 'center')
566
+ return 'center';
567
+ if (val === 'end')
568
+ return 'end';
569
+ if (val === 'around')
570
+ return 'space-around';
571
+ if (val === 'between')
572
+ return 'space-between';
573
+ if (val === 'evenly')
574
+ return 'space-evenly';
575
+ return val;
576
+ }
577
+ function mapGridAlignContent(val) {
578
+ if (!val)
579
+ return undefined;
580
+ if (val === 'start')
581
+ return 'start';
582
+ if (val === 'center')
583
+ return 'center';
584
+ if (val === 'end')
585
+ return 'end';
586
+ if (val === 'around')
587
+ return 'space-around';
588
+ if (val === 'between')
589
+ return 'space-between';
590
+ if (val === 'evenly')
591
+ return 'space-evenly';
592
+ return val;
593
+ }
594
+ export function buildGridVars(props) {
595
+ if (!props)
596
+ return {};
597
+ const vars = {};
598
+ // Base
599
+ if (props.templateColumns !== undefined) {
600
+ const tc = formatGridTemplate(props.templateColumns);
601
+ if (tc)
602
+ vars['--ttdk-grid-template-columns'] = tc;
603
+ }
604
+ if (props.templateRows !== undefined) {
605
+ const tr = formatGridTemplate(props.templateRows);
606
+ if (tr)
607
+ vars['--ttdk-grid-template-rows'] = tr;
608
+ }
609
+ if (props.gap !== undefined) {
610
+ const g = formatGap(props.gap);
611
+ if (g)
612
+ vars['--ttdk-grid-gap'] = g;
613
+ }
614
+ if (props.justifyContent) {
615
+ vars['--ttdk-grid-justify-content'] = mapGridJustifyContent(props.justifyContent) || props.justifyContent;
616
+ }
617
+ if (props.alignContent) {
618
+ vars['--ttdk-grid-align-content'] = mapGridAlignContent(props.alignContent) || props.alignContent;
619
+ }
620
+ // Breakpoints
621
+ const bps = ['sm', 'md', 'lg', 'xl', '2xl'];
622
+ for (const bp of bps) {
623
+ const override = props[bp] || (bp === '2xl' ? (props['xxl'] || props['2xl']) : undefined);
624
+ if (override && typeof override === 'object') {
625
+ if (override.templateColumns !== undefined) {
626
+ const tc = formatGridTemplate(override.templateColumns);
627
+ if (tc)
628
+ vars[`--ttdk-grid-template-columns-${bp}`] = tc;
629
+ }
630
+ if (override.templateRows !== undefined) {
631
+ const tr = formatGridTemplate(override.templateRows);
632
+ if (tr)
633
+ vars[`--ttdk-grid-template-rows-${bp}`] = tr;
634
+ }
635
+ if (override.gap !== undefined) {
636
+ const g = formatGap(override.gap);
637
+ if (g)
638
+ vars[`--ttdk-grid-gap-${bp}`] = g;
639
+ }
640
+ if (override.justifyContent) {
641
+ vars[`--ttdk-grid-justify-content-${bp}`] = mapGridJustifyContent(override.justifyContent) || override.justifyContent;
642
+ }
643
+ if (override.alignContent) {
644
+ vars[`--ttdk-grid-align-content-${bp}`] = mapGridAlignContent(override.alignContent) || override.alignContent;
645
+ }
646
+ }
647
+ }
648
+ return vars;
649
+ }
650
+ function formatGridColRow(val) {
651
+ if (val === undefined || val === null || val === '')
652
+ return undefined;
653
+ if (typeof val === 'number')
654
+ return `span ${val} / span ${val}`;
655
+ if (val === 'auto')
656
+ return 'auto';
657
+ if (val === 'full')
658
+ return '1 / -1';
659
+ return String(val);
660
+ }
661
+ function resolveGridTrack(span, start, end) {
662
+ const hasSpan = span !== undefined && span !== null && span !== '';
663
+ const hasStart = start !== undefined && start !== null && start !== '';
664
+ const hasEnd = end !== undefined && end !== null && end !== '';
665
+ if (!hasSpan && !hasStart && !hasEnd)
666
+ return undefined;
667
+ if (hasStart && hasEnd) {
668
+ return `${start} / ${end}`;
669
+ }
670
+ if (hasStart && hasSpan) {
671
+ const spanStr = typeof span === 'number' ? `span ${span}` : String(span);
672
+ return `${start} / ${spanStr}`;
673
+ }
674
+ if (hasEnd && hasSpan) {
675
+ const spanStr = typeof span === 'number' ? `span ${span}` : String(span);
676
+ return `${spanStr} / ${end}`;
677
+ }
678
+ if (hasStart) {
679
+ return `${start} / auto`;
680
+ }
681
+ if (hasEnd) {
682
+ return `auto / ${end}`;
683
+ }
684
+ return formatGridColRow(span);
685
+ }
686
+ export function buildGridItemVars(props) {
687
+ if (!props)
688
+ return {};
689
+ const vars = {};
690
+ // Base
691
+ const colVal = resolveGridTrack(props.col, props.colStart, props.colEnd);
692
+ if (colVal)
693
+ vars['--ttdk-grid-item-col'] = colVal;
694
+ if (props.colStart !== undefined)
695
+ vars['--ttdk-grid-item-col-start'] = String(props.colStart);
696
+ if (props.colEnd !== undefined)
697
+ vars['--ttdk-grid-item-col-end'] = String(props.colEnd);
698
+ const rowVal = resolveGridTrack(props.row, props.rowStart, props.rowEnd);
699
+ if (rowVal)
700
+ vars['--ttdk-grid-item-row'] = rowVal;
701
+ if (props.rowStart !== undefined)
702
+ vars['--ttdk-grid-item-row-start'] = String(props.rowStart);
703
+ if (props.rowEnd !== undefined)
704
+ vars['--ttdk-grid-item-row-end'] = String(props.rowEnd);
705
+ if (props.justifySelf)
706
+ vars['--ttdk-grid-item-justify-self'] = props.justifySelf;
707
+ if (props.order !== undefined)
708
+ vars['--ttdk-grid-item-order'] = String(props.order);
709
+ // Breakpoints
710
+ const bps = ['sm', 'md', 'lg', 'xl', '2xl'];
711
+ for (const bp of bps) {
712
+ const override = props[bp] || (bp === '2xl' ? (props['xxl'] || props['2xl']) : undefined);
713
+ if (override && typeof override === 'object') {
714
+ const bpColVal = resolveGridTrack(override.col, override.colStart, override.colEnd);
715
+ if (bpColVal)
716
+ vars[`--ttdk-grid-item-col-${bp}`] = bpColVal;
717
+ if (override.colStart !== undefined)
718
+ vars[`--ttdk-grid-item-col-start-${bp}`] = String(override.colStart);
719
+ if (override.colEnd !== undefined)
720
+ vars[`--ttdk-grid-item-col-end-${bp}`] = String(override.colEnd);
721
+ const bpRowVal = resolveGridTrack(override.row, override.rowStart, override.rowEnd);
722
+ if (bpRowVal)
723
+ vars[`--ttdk-grid-item-row-${bp}`] = bpRowVal;
724
+ if (override.rowStart !== undefined)
725
+ vars[`--ttdk-grid-item-row-start-${bp}`] = String(override.rowStart);
726
+ if (override.rowEnd !== undefined)
727
+ vars[`--ttdk-grid-item-row-end-${bp}`] = String(override.rowEnd);
728
+ if (override.justifySelf)
729
+ vars[`--ttdk-grid-item-justify-self-${bp}`] = override.justifySelf;
730
+ if (override.order !== undefined)
731
+ vars[`--ttdk-grid-item-order-${bp}`] = String(override.order);
732
+ }
733
+ }
734
+ return vars;
735
+ }