@hjmds/design-contracts 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (353) hide show
  1. package/README.md +208 -0
  2. package/dist/alert-dialog.d.ts +102 -0
  3. package/dist/alert-dialog.d.ts.map +1 -0
  4. package/dist/alert-dialog.js +136 -0
  5. package/dist/alert-dialog.js.map +1 -0
  6. package/dist/base-recipes.d.ts +184 -0
  7. package/dist/base-recipes.d.ts.map +1 -0
  8. package/dist/base-recipes.js +129 -0
  9. package/dist/base-recipes.js.map +1 -0
  10. package/dist/behaviors.d.ts +1254 -0
  11. package/dist/behaviors.d.ts.map +1 -0
  12. package/dist/behaviors.js +972 -0
  13. package/dist/behaviors.js.map +1 -0
  14. package/dist/bottom-navigation-defaults.d.ts +13 -0
  15. package/dist/bottom-navigation-defaults.d.ts.map +1 -0
  16. package/dist/bottom-navigation-defaults.js +10 -0
  17. package/dist/bottom-navigation-defaults.js.map +1 -0
  18. package/dist/bottom-navigation.d.ts +114 -0
  19. package/dist/bottom-navigation.d.ts.map +1 -0
  20. package/dist/bottom-navigation.js +223 -0
  21. package/dist/bottom-navigation.js.map +1 -0
  22. package/dist/breadcrumb.d.ts +97 -0
  23. package/dist/breadcrumb.d.ts.map +1 -0
  24. package/dist/breadcrumb.js +99 -0
  25. package/dist/breadcrumb.js.map +1 -0
  26. package/dist/calendar.d.ts +285 -0
  27. package/dist/calendar.d.ts.map +1 -0
  28. package/dist/calendar.js +297 -0
  29. package/dist/calendar.js.map +1 -0
  30. package/dist/card.d.ts +39 -0
  31. package/dist/card.d.ts.map +1 -0
  32. package/dist/card.js +50 -0
  33. package/dist/card.js.map +1 -0
  34. package/dist/carousel.d.ts +180 -0
  35. package/dist/carousel.d.ts.map +1 -0
  36. package/dist/carousel.js +172 -0
  37. package/dist/carousel.js.map +1 -0
  38. package/dist/catalog.d.ts +7158 -0
  39. package/dist/catalog.d.ts.map +1 -0
  40. package/dist/catalog.js +220 -0
  41. package/dist/catalog.js.map +1 -0
  42. package/dist/collection.d.ts +123 -0
  43. package/dist/collection.d.ts.map +1 -0
  44. package/dist/collection.js +211 -0
  45. package/dist/collection.js.map +1 -0
  46. package/dist/color-references.d.ts +46 -0
  47. package/dist/color-references.d.ts.map +1 -0
  48. package/dist/color-references.js +39 -0
  49. package/dist/color-references.js.map +1 -0
  50. package/dist/colors.d.ts +56 -0
  51. package/dist/colors.d.ts.map +1 -0
  52. package/dist/colors.js +90 -0
  53. package/dist/colors.js.map +1 -0
  54. package/dist/command-palette.d.ts +240 -0
  55. package/dist/command-palette.d.ts.map +1 -0
  56. package/dist/command-palette.js +97 -0
  57. package/dist/command-palette.js.map +1 -0
  58. package/dist/component-contracts.d.ts +137 -0
  59. package/dist/component-contracts.d.ts.map +1 -0
  60. package/dist/component-contracts.js +53 -0
  61. package/dist/component-contracts.js.map +1 -0
  62. package/dist/component-definitions.d.ts +135 -0
  63. package/dist/component-definitions.d.ts.map +1 -0
  64. package/dist/component-definitions.js +142 -0
  65. package/dist/component-definitions.js.map +1 -0
  66. package/dist/component-recipes.d.ts +3583 -0
  67. package/dist/component-recipes.d.ts.map +1 -0
  68. package/dist/component-recipes.js +1503 -0
  69. package/dist/component-recipes.js.map +1 -0
  70. package/dist/component-references.d.ts +416 -0
  71. package/dist/component-references.d.ts.map +1 -0
  72. package/dist/component-references.js +140 -0
  73. package/dist/component-references.js.map +1 -0
  74. package/dist/content-state.d.ts +104 -0
  75. package/dist/content-state.d.ts.map +1 -0
  76. package/dist/content-state.js +116 -0
  77. package/dist/content-state.js.map +1 -0
  78. package/dist/counter-badge-recipe.d.ts +80 -0
  79. package/dist/counter-badge-recipe.d.ts.map +1 -0
  80. package/dist/counter-badge-recipe.js +44 -0
  81. package/dist/counter-badge-recipe.js.map +1 -0
  82. package/dist/counter-badge.d.ts +12 -0
  83. package/dist/counter-badge.d.ts.map +1 -0
  84. package/dist/counter-badge.js +21 -0
  85. package/dist/counter-badge.js.map +1 -0
  86. package/dist/data-table.d.ts +203 -0
  87. package/dist/data-table.d.ts.map +1 -0
  88. package/dist/data-table.js +182 -0
  89. package/dist/data-table.js.map +1 -0
  90. package/dist/date-picker.d.ts +268 -0
  91. package/dist/date-picker.d.ts.map +1 -0
  92. package/dist/date-picker.js +168 -0
  93. package/dist/date-picker.js.map +1 -0
  94. package/dist/description-list.d.ts +68 -0
  95. package/dist/description-list.d.ts.map +1 -0
  96. package/dist/description-list.js +85 -0
  97. package/dist/description-list.js.map +1 -0
  98. package/dist/design-system-provider.d.ts +80 -0
  99. package/dist/design-system-provider.d.ts.map +1 -0
  100. package/dist/design-system-provider.js +147 -0
  101. package/dist/design-system-provider.js.map +1 -0
  102. package/dist/evidence.d.ts +49 -0
  103. package/dist/evidence.d.ts.map +1 -0
  104. package/dist/evidence.js +133 -0
  105. package/dist/evidence.js.map +1 -0
  106. package/dist/file-picker.d.ts +183 -0
  107. package/dist/file-picker.d.ts.map +1 -0
  108. package/dist/file-picker.js +224 -0
  109. package/dist/file-picker.js.map +1 -0
  110. package/dist/floating-action-button.d.ts +143 -0
  111. package/dist/floating-action-button.d.ts.map +1 -0
  112. package/dist/floating-action-button.js +149 -0
  113. package/dist/floating-action-button.js.map +1 -0
  114. package/dist/form.d.ts +143 -0
  115. package/dist/form.d.ts.map +1 -0
  116. package/dist/form.js +206 -0
  117. package/dist/form.js.map +1 -0
  118. package/dist/foundations.d.ts +300 -0
  119. package/dist/foundations.d.ts.map +1 -0
  120. package/dist/foundations.js +238 -0
  121. package/dist/foundations.js.map +1 -0
  122. package/dist/grid.d.ts +75 -0
  123. package/dist/grid.d.ts.map +1 -0
  124. package/dist/grid.js +133 -0
  125. package/dist/grid.js.map +1 -0
  126. package/dist/icon-button-recipe.d.ts +99 -0
  127. package/dist/icon-button-recipe.d.ts.map +1 -0
  128. package/dist/icon-button-recipe.js +53 -0
  129. package/dist/icon-button-recipe.js.map +1 -0
  130. package/dist/icon.d.ts +41 -0
  131. package/dist/icon.d.ts.map +1 -0
  132. package/dist/icon.js +147 -0
  133. package/dist/icon.js.map +1 -0
  134. package/dist/image.d.ts +82 -0
  135. package/dist/image.d.ts.map +1 -0
  136. package/dist/image.js +100 -0
  137. package/dist/image.js.map +1 -0
  138. package/dist/index.d.ts +58 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +66 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/layout.d.ts +118 -0
  143. package/dist/layout.d.ts.map +1 -0
  144. package/dist/layout.js +118 -0
  145. package/dist/layout.js.map +1 -0
  146. package/dist/link.d.ts +57 -0
  147. package/dist/link.d.ts.map +1 -0
  148. package/dist/link.js +142 -0
  149. package/dist/link.js.map +1 -0
  150. package/dist/load-more.d.ts +64 -0
  151. package/dist/load-more.d.ts.map +1 -0
  152. package/dist/load-more.js +124 -0
  153. package/dist/load-more.js.map +1 -0
  154. package/dist/mentions.d.ts +67 -0
  155. package/dist/mentions.d.ts.map +1 -0
  156. package/dist/mentions.js +107 -0
  157. package/dist/mentions.js.map +1 -0
  158. package/dist/number-field.d.ts +208 -0
  159. package/dist/number-field.d.ts.map +1 -0
  160. package/dist/number-field.js +247 -0
  161. package/dist/number-field.js.map +1 -0
  162. package/dist/otp-field.d.ts +152 -0
  163. package/dist/otp-field.d.ts.map +1 -0
  164. package/dist/otp-field.js +117 -0
  165. package/dist/otp-field.js.map +1 -0
  166. package/dist/pagination.d.ts +181 -0
  167. package/dist/pagination.d.ts.map +1 -0
  168. package/dist/pagination.js +226 -0
  169. package/dist/pagination.js.map +1 -0
  170. package/dist/password-field.d.ts +187 -0
  171. package/dist/password-field.d.ts.map +1 -0
  172. package/dist/password-field.js +120 -0
  173. package/dist/password-field.js.map +1 -0
  174. package/dist/popover.d.ts +152 -0
  175. package/dist/popover.d.ts.map +1 -0
  176. package/dist/popover.js +137 -0
  177. package/dist/popover.js.map +1 -0
  178. package/dist/progress-recipe.d.ts +43 -0
  179. package/dist/progress-recipe.d.ts.map +1 -0
  180. package/dist/progress-recipe.js +16 -0
  181. package/dist/progress-recipe.js.map +1 -0
  182. package/dist/recipes.d.ts +31 -0
  183. package/dist/recipes.d.ts.map +1 -0
  184. package/dist/recipes.js +46 -0
  185. package/dist/recipes.js.map +1 -0
  186. package/dist/responsive.d.ts +27 -0
  187. package/dist/responsive.d.ts.map +1 -0
  188. package/dist/responsive.js +66 -0
  189. package/dist/responsive.js.map +1 -0
  190. package/dist/result.d.ts +111 -0
  191. package/dist/result.d.ts.map +1 -0
  192. package/dist/result.js +97 -0
  193. package/dist/result.js.map +1 -0
  194. package/dist/selection-helpers.d.ts +16 -0
  195. package/dist/selection-helpers.d.ts.map +1 -0
  196. package/dist/selection-helpers.js +52 -0
  197. package/dist/selection-helpers.js.map +1 -0
  198. package/dist/semantic-colors.d.ts +275 -0
  199. package/dist/semantic-colors.d.ts.map +1 -0
  200. package/dist/semantic-colors.js +84 -0
  201. package/dist/semantic-colors.js.map +1 -0
  202. package/dist/sheet.d.ts +51 -0
  203. package/dist/sheet.d.ts.map +1 -0
  204. package/dist/sheet.js +69 -0
  205. package/dist/sheet.js.map +1 -0
  206. package/dist/showcase.d.ts +153 -0
  207. package/dist/showcase.d.ts.map +1 -0
  208. package/dist/showcase.js +210 -0
  209. package/dist/showcase.js.map +1 -0
  210. package/dist/side-panel.d.ts +199 -0
  211. package/dist/side-panel.d.ts.map +1 -0
  212. package/dist/side-panel.js +111 -0
  213. package/dist/side-panel.js.map +1 -0
  214. package/dist/slider.d.ts +138 -0
  215. package/dist/slider.d.ts.map +1 -0
  216. package/dist/slider.js +150 -0
  217. package/dist/slider.js.map +1 -0
  218. package/dist/splitter.d.ts +113 -0
  219. package/dist/splitter.d.ts.map +1 -0
  220. package/dist/splitter.js +99 -0
  221. package/dist/splitter.js.map +1 -0
  222. package/dist/statistic.d.ts +41 -0
  223. package/dist/statistic.d.ts.map +1 -0
  224. package/dist/statistic.js +76 -0
  225. package/dist/statistic.js.map +1 -0
  226. package/dist/steps.d.ts +196 -0
  227. package/dist/steps.d.ts.map +1 -0
  228. package/dist/steps.js +160 -0
  229. package/dist/steps.js.map +1 -0
  230. package/dist/tag.d.ts +128 -0
  231. package/dist/tag.d.ts.map +1 -0
  232. package/dist/tag.js +93 -0
  233. package/dist/tag.js.map +1 -0
  234. package/dist/timeline.d.ts +147 -0
  235. package/dist/timeline.d.ts.map +1 -0
  236. package/dist/timeline.js +127 -0
  237. package/dist/timeline.js.map +1 -0
  238. package/dist/toast.d.ts +164 -0
  239. package/dist/toast.d.ts.map +1 -0
  240. package/dist/toast.js +529 -0
  241. package/dist/toast.js.map +1 -0
  242. package/dist/tokens.d.ts +9 -0
  243. package/dist/tokens.d.ts.map +1 -0
  244. package/dist/tokens.js +9 -0
  245. package/dist/tokens.js.map +1 -0
  246. package/dist/tooltip.d.ts +44 -0
  247. package/dist/tooltip.d.ts.map +1 -0
  248. package/dist/tooltip.js +88 -0
  249. package/dist/tooltip.js.map +1 -0
  250. package/dist/tour.d.ts +218 -0
  251. package/dist/tour.d.ts.map +1 -0
  252. package/dist/tour.js +211 -0
  253. package/dist/tour.js.map +1 -0
  254. package/dist/transfer-list.d.ts +207 -0
  255. package/dist/transfer-list.d.ts.map +1 -0
  256. package/dist/transfer-list.js +193 -0
  257. package/dist/transfer-list.js.map +1 -0
  258. package/dist/tree-select.d.ts +78 -0
  259. package/dist/tree-select.d.ts.map +1 -0
  260. package/dist/tree-select.js +132 -0
  261. package/dist/tree-select.js.map +1 -0
  262. package/dist/tree.d.ts +206 -0
  263. package/dist/tree.d.ts.map +1 -0
  264. package/dist/tree.js +223 -0
  265. package/dist/tree.js.map +1 -0
  266. package/dist/upload-item.d.ts +173 -0
  267. package/dist/upload-item.d.ts.map +1 -0
  268. package/dist/upload-item.js +156 -0
  269. package/dist/upload-item.js.map +1 -0
  270. package/dist/version.d.ts +3 -0
  271. package/dist/version.d.ts.map +1 -0
  272. package/dist/version.js +3 -0
  273. package/dist/version.js.map +1 -0
  274. package/docs/affix.md +63 -0
  275. package/docs/anchor.md +59 -0
  276. package/docs/ant-design-coverage.md +119 -0
  277. package/docs/app-provider.md +50 -0
  278. package/docs/app-rn-adoption.md +227 -0
  279. package/docs/architecture.md +320 -0
  280. package/docs/authoring-brief.md +87 -0
  281. package/docs/border-beam.md +66 -0
  282. package/docs/bottom-navigation.md +127 -0
  283. package/docs/breadcrumb.md +82 -0
  284. package/docs/calendar.md +154 -0
  285. package/docs/carousel.md +130 -0
  286. package/docs/cascader.md +93 -0
  287. package/docs/catalog-decision-status.md +306 -0
  288. package/docs/color-picker.md +72 -0
  289. package/docs/command-palette.md +116 -0
  290. package/docs/confirm-popover.md +93 -0
  291. package/docs/consistency-audit.md +383 -0
  292. package/docs/consumer-release-gate.md +90 -0
  293. package/docs/content-state.md +156 -0
  294. package/docs/context-panel.md +88 -0
  295. package/docs/cross-platform-core-normalization.md +118 -0
  296. package/docs/data-table.md +79 -0
  297. package/docs/date-picker.md +84 -0
  298. package/docs/description-list.md +75 -0
  299. package/docs/design-system-provider.md +139 -0
  300. package/docs/dropdown.md +78 -0
  301. package/docs/expansion-roadmap.md +285 -0
  302. package/docs/file-picker.md +59 -0
  303. package/docs/floating-action-button.md +111 -0
  304. package/docs/form.md +134 -0
  305. package/docs/generated/component-maturity.md +103 -0
  306. package/docs/generated/renderer-evidence.json +5597 -0
  307. package/docs/generated/renderer-evidence.md +132 -0
  308. package/docs/generated/showcase-manifest.json +3732 -0
  309. package/docs/icon.md +22 -0
  310. package/docs/identity.md +121 -0
  311. package/docs/image.md +84 -0
  312. package/docs/implementation-0.5.md +85 -0
  313. package/docs/layout-primitives.md +107 -0
  314. package/docs/layout.md +83 -0
  315. package/docs/library-reference-decisions.md +123 -0
  316. package/docs/link.md +67 -0
  317. package/docs/load-more.md +31 -0
  318. package/docs/mentions.md +82 -0
  319. package/docs/migration-0.2.md +108 -0
  320. package/docs/migration-0.3.md +72 -0
  321. package/docs/migration-0.5.md +82 -0
  322. package/docs/migration-0.6.md +197 -0
  323. package/docs/notification.md +54 -0
  324. package/docs/number-field.md +82 -0
  325. package/docs/otp-field.md +103 -0
  326. package/docs/pagination.md +139 -0
  327. package/docs/password-field.md +98 -0
  328. package/docs/popover.md +124 -0
  329. package/docs/promotion-candidates.md +169 -0
  330. package/docs/qr-code.md +69 -0
  331. package/docs/rating.md +58 -0
  332. package/docs/responsive-grid.md +90 -0
  333. package/docs/result.md +96 -0
  334. package/docs/showcase.md +97 -0
  335. package/docs/side-panel.md +71 -0
  336. package/docs/slider.md +79 -0
  337. package/docs/splitter.md +55 -0
  338. package/docs/statistic.md +16 -0
  339. package/docs/steps.md +115 -0
  340. package/docs/tag.md +57 -0
  341. package/docs/time-picker.md +88 -0
  342. package/docs/timeline.md +146 -0
  343. package/docs/toast.md +127 -0
  344. package/docs/tooltip.md +58 -0
  345. package/docs/tour.md +136 -0
  346. package/docs/transfer-list.md +94 -0
  347. package/docs/tree-select.md +101 -0
  348. package/docs/tree.md +123 -0
  349. package/docs/upload-item.md +68 -0
  350. package/docs/utility.md +53 -0
  351. package/docs/virtual-list.md +70 -0
  352. package/docs/watermark.md +58 -0
  353. package/package.json +402 -0
@@ -0,0 +1,238 @@
1
+ /** Numeric units are consumed as CSS pixels on web and density-independent points on native. */
2
+ export const spacing = {
3
+ xxs: 4,
4
+ xs: 8,
5
+ sm: 12,
6
+ md: 16,
7
+ lg: 20,
8
+ xl: 24,
9
+ xxl: 32,
10
+ xxxl: 40,
11
+ };
12
+ export const radius = {
13
+ sm: 8,
14
+ md: 12,
15
+ lg: 16,
16
+ xl: 24,
17
+ full: 999,
18
+ };
19
+ /**
20
+ * Ordered fallbacks keep the contract platform-neutral: Web renderers join
21
+ * the list as a CSS stack, while native renderers select the first family
22
+ * available on the device instead of receiving a CSS-only string.
23
+ */
24
+ export const fontFamily = {
25
+ ui: [
26
+ "Inter",
27
+ "Pretendard",
28
+ "-apple-system",
29
+ "BlinkMacSystemFont",
30
+ "Segoe UI",
31
+ "sans-serif",
32
+ ],
33
+ code: [
34
+ "ui-monospace",
35
+ "SFMono-Regular",
36
+ "Consolas",
37
+ "Liberation Mono",
38
+ "monospace",
39
+ ],
40
+ };
41
+ /** String weights translate unchanged to CSS and React Native text styles. */
42
+ export const fontWeight = {
43
+ regular: "400",
44
+ medium: "500",
45
+ semibold: "600",
46
+ bold: "700",
47
+ heavy: "800",
48
+ };
49
+ /** Numeric tracking uses CSS pixels on Web and density-independent points on Native. */
50
+ export const letterSpacing = {
51
+ tight: -0.2,
52
+ normal: 0,
53
+ wide: 0.2,
54
+ };
55
+ /** Renderers map the shared intent to `font-variant-numeric` / `fontVariant`. */
56
+ export const numeric = {
57
+ proportional: "proportional-nums",
58
+ tabular: "tabular-nums",
59
+ };
60
+ export const typography = {
61
+ caption: { fontSize: 11, lineHeight: 16, fontWeight: fontWeight.regular },
62
+ label: { fontSize: 12, lineHeight: 18, fontWeight: fontWeight.semibold },
63
+ body: { fontSize: 14, lineHeight: 20, fontWeight: fontWeight.regular },
64
+ bodyLarge: { fontSize: 16, lineHeight: 24, fontWeight: fontWeight.regular },
65
+ title: { fontSize: 18, lineHeight: 26, fontWeight: fontWeight.bold },
66
+ titleLarge: { fontSize: 20, lineHeight: 28, fontWeight: fontWeight.heavy },
67
+ heading: { fontSize: 24, lineHeight: 32, fontWeight: fontWeight.heavy },
68
+ };
69
+ /**
70
+ * Document heading hierarchy without widening the established `TextVariant`
71
+ * union. Levels 3–5 reuse the existing semantic styles; larger levels are
72
+ * additive display roles for dense product pages and documentation.
73
+ */
74
+ export const heading = {
75
+ level1: { fontSize: 40, lineHeight: 48, fontWeight: fontWeight.heavy },
76
+ level2: { fontSize: 32, lineHeight: 40, fontWeight: fontWeight.heavy },
77
+ level3: typography.heading,
78
+ level4: typography.titleLarge,
79
+ level5: typography.title,
80
+ };
81
+ /** Glyphs include icons and avatars; they do not inherit paragraph line-height. */
82
+ export const glyph = {
83
+ xs: 14,
84
+ sm: 20,
85
+ md: 24,
86
+ lg: 28,
87
+ xl: 32,
88
+ xxl: 44,
89
+ xxxl: 48,
90
+ };
91
+ export const motion = {
92
+ fast: 120,
93
+ normal: 200,
94
+ slow: 320,
95
+ };
96
+ /**
97
+ * Curves are stored as normalized cubic-bezier tuples so CSS and native
98
+ * animation drivers can translate the same motion intent without sharing a
99
+ * renderer dependency.
100
+ */
101
+ export const easing = {
102
+ standard: [0.2, 0, 0, 1],
103
+ enter: [0, 0, 0, 1],
104
+ exit: [0.3, 0, 1, 1],
105
+ emphasized: [0.2, 0, 0, 1],
106
+ };
107
+ /** Shared transition intent; renderers translate easing tuples to their animation API. */
108
+ export const motionPreset = {
109
+ micro: {
110
+ duration: motion.fast,
111
+ easing: "standard",
112
+ reducedMotion: "instant",
113
+ },
114
+ enter: {
115
+ duration: motion.normal,
116
+ easing: "enter",
117
+ reducedMotion: "opacity",
118
+ },
119
+ exit: {
120
+ duration: motion.fast,
121
+ easing: "exit",
122
+ reducedMotion: "instant",
123
+ },
124
+ context: {
125
+ duration: motion.slow,
126
+ easing: "emphasized",
127
+ reducedMotion: "opacity",
128
+ },
129
+ };
130
+ /** Native renderers may use these values directly; web renderers use easing. */
131
+ export const spring = {
132
+ responsive: { stiffness: 760, damping: 52, mass: 1 },
133
+ expressive: { stiffness: 520, damping: 38, mass: 1 },
134
+ };
135
+ /** Reusable state strengths. Components still decide which states are valid. */
136
+ export const opacity = {
137
+ disabled: 0.5,
138
+ muted: 0.72,
139
+ pressed: 0.86,
140
+ dragged: 0.64,
141
+ };
142
+ /** Overlaying the content color at these strengths creates predictable states. */
143
+ export const stateLayer = {
144
+ hover: 0.06,
145
+ focus: 0.08,
146
+ pressed: 0.1,
147
+ selected: 0.1,
148
+ };
149
+ export const stroke = {
150
+ subtle: 1,
151
+ default: 1,
152
+ strong: 2,
153
+ focus: 2,
154
+ };
155
+ export const control = {
156
+ minTouchTarget: 44,
157
+ buttonHeight: {
158
+ small: 36,
159
+ medium: 44,
160
+ large: 52,
161
+ },
162
+ buttonHitSlop: {
163
+ small: 4,
164
+ medium: 0,
165
+ large: 0,
166
+ },
167
+ fieldHeight: 44,
168
+ chipHeight: {
169
+ small: 36,
170
+ medium: 44,
171
+ },
172
+ selectionIndicator: 24,
173
+ };
174
+ /** Product renderers may narrow these widths, but should not invent new rhythm. */
175
+ export const layout = {
176
+ pagePadding: {
177
+ compact: spacing.md,
178
+ regular: spacing.lg,
179
+ spacious: spacing.xl,
180
+ },
181
+ sectionGap: spacing.xl,
182
+ contentGap: spacing.md,
183
+ rowHeight: {
184
+ singleLine: 56,
185
+ twoLine: 68,
186
+ },
187
+ readingMaxWidth: 720,
188
+ contentMaxWidth: 1200,
189
+ };
190
+ /** Width thresholds use CSS pixels on Web and density-independent points on Native. */
191
+ export const breakpoint = {
192
+ compact: 0,
193
+ medium: 600,
194
+ expanded: 960,
195
+ wide: 1280,
196
+ };
197
+ /** Shared stacking intent. Values remain sparse to leave room for app layers. */
198
+ export const layer = {
199
+ base: 0,
200
+ sticky: 100,
201
+ dropdown: 400,
202
+ overlay: 800,
203
+ modal: 900,
204
+ tooltip: 950,
205
+ toast: 1000,
206
+ };
207
+ export const overlay = {
208
+ scrim: 0.6,
209
+ veil: 0.25,
210
+ };
211
+ /** Fixed backdrop contracts avoid renderer-specific names such as CSS `scrim`. */
212
+ export const backdrop = {
213
+ modal: { color: "#000000", opacity: overlay.scrim },
214
+ veil: { color: "#000000", opacity: overlay.veil },
215
+ };
216
+ export const scrim = `rgba(0, 0, 0, ${overlay.scrim})`;
217
+ /** Renderers translate this contract to box-shadow or native shadow/elevation properties. */
218
+ export const shadow = {
219
+ raised: {
220
+ color: "#000000",
221
+ opacity: 0.08,
222
+ radius: 4,
223
+ offsetY: 1,
224
+ },
225
+ floating: {
226
+ color: "#000000",
227
+ opacity: 0.12,
228
+ radius: 12,
229
+ offsetY: 4,
230
+ },
231
+ overlay: {
232
+ color: "#000000",
233
+ opacity: 0.16,
234
+ radius: 24,
235
+ offsetY: 8,
236
+ },
237
+ };
238
+ //# sourceMappingURL=foundations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"foundations.js","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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","sourcesContent":["/** Numeric units are consumed as CSS pixels on web and density-independent points on native. */\nexport const spacing = {\n xxs: 4,\n xs: 8,\n sm: 12,\n md: 16,\n lg: 20,\n xl: 24,\n xxl: 32,\n xxxl: 40,\n} as const;\n\nexport const radius = {\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n full: 999,\n} as const;\n\n/**\n * Ordered fallbacks keep the contract platform-neutral: Web renderers join\n * the list as a CSS stack, while native renderers select the first family\n * available on the device instead of receiving a CSS-only string.\n */\nexport const fontFamily = {\n ui: [\n \"Inter\",\n \"Pretendard\",\n \"-apple-system\",\n \"BlinkMacSystemFont\",\n \"Segoe UI\",\n \"sans-serif\",\n ],\n code: [\n \"ui-monospace\",\n \"SFMono-Regular\",\n \"Consolas\",\n \"Liberation Mono\",\n \"monospace\",\n ],\n} as const;\n\nexport type FontFamily = keyof typeof fontFamily;\n\n/** String weights translate unchanged to CSS and React Native text styles. */\nexport const fontWeight = {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n heavy: \"800\",\n} as const;\n\nexport type FontWeight = keyof typeof fontWeight;\nexport type FontWeightValue = (typeof fontWeight)[FontWeight];\n\n/** Numeric tracking uses CSS pixels on Web and density-independent points on Native. */\nexport const letterSpacing = {\n tight: -0.2,\n normal: 0,\n wide: 0.2,\n} as const;\n\nexport type LetterSpacing = keyof typeof letterSpacing;\n\n/** Renderers map the shared intent to `font-variant-numeric` / `fontVariant`. */\nexport const numeric = {\n proportional: \"proportional-nums\",\n tabular: \"tabular-nums\",\n} as const;\n\nexport type NumericVariant = keyof typeof numeric;\n\nexport const typography = {\n caption: { fontSize: 11, lineHeight: 16, fontWeight: fontWeight.regular },\n label: { fontSize: 12, lineHeight: 18, fontWeight: fontWeight.semibold },\n body: { fontSize: 14, lineHeight: 20, fontWeight: fontWeight.regular },\n bodyLarge: { fontSize: 16, lineHeight: 24, fontWeight: fontWeight.regular },\n title: { fontSize: 18, lineHeight: 26, fontWeight: fontWeight.bold },\n titleLarge: { fontSize: 20, lineHeight: 28, fontWeight: fontWeight.heavy },\n heading: { fontSize: 24, lineHeight: 32, fontWeight: fontWeight.heavy },\n} as const;\n\nexport type TextVariant = keyof typeof typography;\n\n/**\n * Document heading hierarchy without widening the established `TextVariant`\n * union. Levels 3–5 reuse the existing semantic styles; larger levels are\n * additive display roles for dense product pages and documentation.\n */\nexport const heading = {\n level1: { fontSize: 40, lineHeight: 48, fontWeight: fontWeight.heavy },\n level2: { fontSize: 32, lineHeight: 40, fontWeight: fontWeight.heavy },\n level3: typography.heading,\n level4: typography.titleLarge,\n level5: typography.title,\n} as const;\n\nexport type HeadingLevel = keyof typeof heading;\n\n/** Glyphs include icons and avatars; they do not inherit paragraph line-height. */\nexport const glyph = {\n xs: 14,\n sm: 20,\n md: 24,\n lg: 28,\n xl: 32,\n xxl: 44,\n xxxl: 48,\n} as const;\n\nexport type GlyphSize = keyof typeof glyph;\n\nexport const motion = {\n fast: 120,\n normal: 200,\n slow: 320,\n} as const;\n\n/**\n * Curves are stored as normalized cubic-bezier tuples so CSS and native\n * animation drivers can translate the same motion intent without sharing a\n * renderer dependency.\n */\nexport const easing = {\n standard: [0.2, 0, 0, 1],\n enter: [0, 0, 0, 1],\n exit: [0.3, 0, 1, 1],\n emphasized: [0.2, 0, 0, 1],\n} as const;\n\nexport type ReducedMotionBehavior = \"instant\" | \"opacity\" | \"static\";\n\n/** Shared transition intent; renderers translate easing tuples to their animation API. */\nexport const motionPreset = {\n micro: {\n duration: motion.fast,\n easing: \"standard\",\n reducedMotion: \"instant\",\n },\n enter: {\n duration: motion.normal,\n easing: \"enter\",\n reducedMotion: \"opacity\",\n },\n exit: {\n duration: motion.fast,\n easing: \"exit\",\n reducedMotion: \"instant\",\n },\n context: {\n duration: motion.slow,\n easing: \"emphasized\",\n reducedMotion: \"opacity\",\n },\n} as const satisfies Record<\n \"micro\" | \"enter\" | \"exit\" | \"context\",\n {\n duration: number;\n easing: keyof typeof easing;\n reducedMotion: ReducedMotionBehavior;\n }\n>;\n\n/** Native renderers may use these values directly; web renderers use easing. */\nexport const spring = {\n responsive: { stiffness: 760, damping: 52, mass: 1 },\n expressive: { stiffness: 520, damping: 38, mass: 1 },\n} as const;\n\n/** Reusable state strengths. Components still decide which states are valid. */\nexport const opacity = {\n disabled: 0.5,\n muted: 0.72,\n pressed: 0.86,\n dragged: 0.64,\n} as const;\n\n/** Overlaying the content color at these strengths creates predictable states. */\nexport const stateLayer = {\n hover: 0.06,\n focus: 0.08,\n pressed: 0.1,\n selected: 0.1,\n} as const;\n\nexport const stroke = {\n subtle: 1,\n default: 1,\n strong: 2,\n focus: 2,\n} as const;\n\nexport const control = {\n minTouchTarget: 44,\n buttonHeight: {\n small: 36,\n medium: 44,\n large: 52,\n },\n buttonHitSlop: {\n small: 4,\n medium: 0,\n large: 0,\n },\n fieldHeight: 44,\n chipHeight: {\n small: 36,\n medium: 44,\n },\n selectionIndicator: 24,\n} as const;\n\n/** Product renderers may narrow these widths, but should not invent new rhythm. */\nexport const layout = {\n pagePadding: {\n compact: spacing.md,\n regular: spacing.lg,\n spacious: spacing.xl,\n },\n sectionGap: spacing.xl,\n contentGap: spacing.md,\n rowHeight: {\n singleLine: 56,\n twoLine: 68,\n },\n readingMaxWidth: 720,\n contentMaxWidth: 1200,\n} as const;\n\n/** Width thresholds use CSS pixels on Web and density-independent points on Native. */\nexport const breakpoint = {\n compact: 0,\n medium: 600,\n expanded: 960,\n wide: 1280,\n} as const;\n\n/** Shared stacking intent. Values remain sparse to leave room for app layers. */\nexport const layer = {\n base: 0,\n sticky: 100,\n dropdown: 400,\n overlay: 800,\n modal: 900,\n tooltip: 950,\n toast: 1000,\n} as const;\n\nexport const overlay = {\n scrim: 0.6,\n veil: 0.25,\n} as const;\n\nexport type BackdropReference = Readonly<{\n color: \"#000000\";\n opacity: number;\n}>;\n\n/** Fixed backdrop contracts avoid renderer-specific names such as CSS `scrim`. */\nexport const backdrop = {\n modal: { color: \"#000000\", opacity: overlay.scrim },\n veil: { color: \"#000000\", opacity: overlay.veil },\n} as const satisfies Record<\"modal\" | \"veil\", BackdropReference>;\n\nexport const scrim = `rgba(0, 0, 0, ${overlay.scrim})`;\n\n/** Renderers translate this contract to box-shadow or native shadow/elevation properties. */\nexport const shadow = {\n raised: {\n color: \"#000000\",\n opacity: 0.08,\n radius: 4,\n offsetY: 1,\n },\n floating: {\n color: \"#000000\",\n opacity: 0.12,\n radius: 12,\n offsetY: 4,\n },\n overlay: {\n color: \"#000000\",\n opacity: 0.16,\n radius: 24,\n offsetY: 8,\n },\n} as const;\n"]}
package/dist/grid.d.ts ADDED
@@ -0,0 +1,75 @@
1
+ import { type ResponsiveValue, type WindowClass } from "./responsive.js";
2
+ /** `none` is the only non-token gap: the semantic absence of space. */
3
+ export declare const gridGaps: {
4
+ readonly xxs: 4;
5
+ readonly xs: 8;
6
+ readonly sm: 12;
7
+ readonly md: 16;
8
+ readonly lg: 20;
9
+ readonly xl: 24;
10
+ readonly xxl: 32;
11
+ readonly xxxl: 40;
12
+ readonly none: 0;
13
+ };
14
+ export type GridGapToken = keyof typeof gridGaps;
15
+ /** A single token applies to both axes; the object form allows independent axes. */
16
+ export type GridGap = GridGapToken | Readonly<{
17
+ row: GridGapToken;
18
+ column: GridGapToken;
19
+ }>;
20
+ export type GridDescriptor = Readonly<{
21
+ /** Requested column count at each window class; every value must be a positive integer. */
22
+ columns: ResponsiveValue<number>;
23
+ /** Token-only spacing. Missing larger classes inherit toward compact. */
24
+ gap?: ResponsiveValue<GridGap>;
25
+ /**
26
+ * Optional target floor. The resolver reduces `columns` before allowing
27
+ * multiple columns below this width; one column still shrinks to its container.
28
+ */
29
+ minColumnWidth?: ResponsiveValue<number>;
30
+ }>;
31
+ export declare const gridDefaults: {
32
+ readonly gap: "md";
33
+ readonly flow: "row-major";
34
+ };
35
+ export declare const gridRecipe: {
36
+ readonly slots: readonly ["root", "item"];
37
+ readonly defaults: {
38
+ readonly gap: "md";
39
+ readonly flow: "row-major";
40
+ };
41
+ readonly gaps: {
42
+ readonly xxs: 4;
43
+ readonly xs: 8;
44
+ readonly sm: 12;
45
+ readonly md: 16;
46
+ readonly lg: 20;
47
+ readonly xl: 24;
48
+ readonly xxl: 32;
49
+ readonly xxxl: 40;
50
+ readonly none: 0;
51
+ };
52
+ };
53
+ export type ResolveGridLayoutOptions = Readonly<{
54
+ /** Full window/viewport width used only to choose the shared WindowClass. */
55
+ windowWidth: number;
56
+ /** Inner grid width after page padding/sidebar; defaults to windowWidth. */
57
+ availableWidth?: number;
58
+ }>;
59
+ export type ResolvedGridLayout = Readonly<{
60
+ windowClass: WindowClass;
61
+ flow: "row-major";
62
+ requestedColumns: number;
63
+ columns: number;
64
+ rowGap: number;
65
+ columnGap: number;
66
+ columnWidth: number;
67
+ }>;
68
+ export declare function validateGridDescriptor(descriptor: GridDescriptor): void;
69
+ /**
70
+ * Resolves renderer-neutral grid geometry. Columns may only collapse from
71
+ * the requested count when `minColumnWidth` requires it; they never widen.
72
+ * Renderers must preserve child source order (`row-major`) on both platforms.
73
+ */
74
+ export declare function resolveGridLayout(descriptor: GridDescriptor, options: ResolveGridLayoutOptions): ResolvedGridLayout;
75
+ //# sourceMappingURL=grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AAEzB,uEAAuE;AACvE,eAAO,MAAM,QAAQ;;;;;;;;;;CAGX,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,QAAQ,CAAC;AAEjD,oFAAoF;AACpF,MAAM,MAAM,OAAO,GACf,YAAY,GACZ,QAAQ,CAAC;IACP,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;CACtB,CAAC,CAAC;AAEP,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,2FAA2F;IAC3F,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IACjC,yEAAyE;IACzE,GAAG,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC/B;;;OAGG;IACH,cAAc,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;CAC1C,CAAC,CAAC;AAEH,eAAO,MAAM,YAAY;;;CAMvB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAIb,CAAC;AAEX,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAsEH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,cAAc,GAAG,IAAI,CAevE;AA4BD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,cAAc,EAC1B,OAAO,EAAE,wBAAwB,GAChC,kBAAkB,CAuCpB"}
package/dist/grid.js ADDED
@@ -0,0 +1,133 @@
1
+ import { spacing } from "./foundations.js";
2
+ import { resolveResponsiveValue, resolveWindowClass, validateResponsiveValue, windowClassOrder, } from "./responsive.js";
3
+ /** `none` is the only non-token gap: the semantic absence of space. */
4
+ export const gridGaps = {
5
+ none: 0,
6
+ ...spacing,
7
+ };
8
+ export const gridDefaults = {
9
+ gap: "md",
10
+ flow: "row-major",
11
+ };
12
+ export const gridRecipe = {
13
+ slots: ["root", "item"],
14
+ defaults: gridDefaults,
15
+ gaps: gridGaps,
16
+ };
17
+ const descriptorKeys = new Set(["columns", "gap", "minColumnWidth"]);
18
+ const gapKeys = new Set(["row", "column"]);
19
+ const optionKeys = new Set(["windowWidth", "availableWidth"]);
20
+ const gapTokens = new Set(Object.keys(gridGaps));
21
+ function isRecord(value) {
22
+ return value !== null && typeof value === "object" && !Array.isArray(value);
23
+ }
24
+ function rejectUnknownKeys(value, allowed, field) {
25
+ for (const key of Object.keys(value)) {
26
+ if (!allowed.has(key)) {
27
+ throw new TypeError(`Unsupported Grid ${field} field: ${key}`);
28
+ }
29
+ }
30
+ }
31
+ function forEachResponsiveValue(responsive, visit) {
32
+ validateResponsiveValue(responsive);
33
+ for (const windowClass of windowClassOrder) {
34
+ if (Object.hasOwn(responsive, windowClass)) {
35
+ visit(responsive[windowClass], windowClass);
36
+ }
37
+ }
38
+ }
39
+ function validateColumnCount(value, windowClass) {
40
+ if (!Number.isInteger(value) || value <= 0) {
41
+ throw new RangeError(`Grid columns at ${windowClass} must be a positive integer`);
42
+ }
43
+ }
44
+ function validatePositiveWidth(value, field) {
45
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
46
+ throw new RangeError(`Grid ${field} must be a positive finite number`);
47
+ }
48
+ }
49
+ function validateGapToken(value, field) {
50
+ if (typeof value !== "string" || !gapTokens.has(value)) {
51
+ throw new TypeError(`Unsupported Grid ${field} gap: ${String(value)}`);
52
+ }
53
+ }
54
+ function validateGap(value, windowClass) {
55
+ if (typeof value === "string") {
56
+ validateGapToken(value, windowClass);
57
+ return;
58
+ }
59
+ if (!isRecord(value)) {
60
+ throw new TypeError(`Grid gap at ${windowClass} must be a token or axis object`);
61
+ }
62
+ rejectUnknownKeys(value, gapKeys, `gap.${windowClass}`);
63
+ validateGapToken(value.row, `${windowClass}.row`);
64
+ validateGapToken(value.column, `${windowClass}.column`);
65
+ }
66
+ export function validateGridDescriptor(descriptor) {
67
+ if (!isRecord(descriptor)) {
68
+ throw new TypeError("Grid descriptor must be an object");
69
+ }
70
+ rejectUnknownKeys(descriptor, descriptorKeys, "descriptor");
71
+ forEachResponsiveValue(descriptor.columns, validateColumnCount);
72
+ if (descriptor.gap !== undefined) {
73
+ forEachResponsiveValue(descriptor.gap, validateGap);
74
+ }
75
+ if (descriptor.minColumnWidth !== undefined) {
76
+ forEachResponsiveValue(descriptor.minColumnWidth, (value, windowClass) => {
77
+ validatePositiveWidth(value, `minColumnWidth at ${windowClass}`);
78
+ });
79
+ }
80
+ }
81
+ function validateResolveOptions(options) {
82
+ if (!isRecord(options)) {
83
+ throw new TypeError("Grid layout options must be an object");
84
+ }
85
+ rejectUnknownKeys(options, optionKeys, "layout options");
86
+ // resolveWindowClass owns the zero-width/negative distinction for the window.
87
+ const windowClass = resolveWindowClass(options.windowWidth);
88
+ const availableWidth = options.availableWidth ?? options.windowWidth;
89
+ validatePositiveWidth(availableWidth, "availableWidth");
90
+ return { availableWidth, windowClass };
91
+ }
92
+ function resolveGap(gap) {
93
+ if (typeof gap === "string") {
94
+ const resolved = gridGaps[gap];
95
+ return { row: resolved, column: resolved };
96
+ }
97
+ return {
98
+ row: gridGaps[gap.row],
99
+ column: gridGaps[gap.column],
100
+ };
101
+ }
102
+ /**
103
+ * Resolves renderer-neutral grid geometry. Columns may only collapse from
104
+ * the requested count when `minColumnWidth` requires it; they never widen.
105
+ * Renderers must preserve child source order (`row-major`) on both platforms.
106
+ */
107
+ export function resolveGridLayout(descriptor, options) {
108
+ validateGridDescriptor(descriptor);
109
+ const { availableWidth, windowClass } = validateResolveOptions(options);
110
+ const requestedColumns = resolveResponsiveValue(descriptor.columns, windowClass);
111
+ const responsiveGap = descriptor.gap ?? { compact: gridDefaults.gap };
112
+ const { row: rowGap, column: columnGap } = resolveGap(resolveResponsiveValue(responsiveGap, windowClass));
113
+ let columns = requestedColumns;
114
+ if (descriptor.minColumnWidth !== undefined) {
115
+ const minColumnWidth = resolveResponsiveValue(descriptor.minColumnWidth, windowClass);
116
+ const fittingColumns = Math.max(1, Math.floor((availableWidth + columnGap) / (minColumnWidth + columnGap)));
117
+ columns = Math.min(requestedColumns, fittingColumns);
118
+ }
119
+ const columnWidth = (availableWidth - columnGap * (columns - 1)) / columns;
120
+ if (!Number.isFinite(columnWidth) || columnWidth <= 0) {
121
+ throw new RangeError("Grid columns and column gap leave no positive column width");
122
+ }
123
+ return {
124
+ windowClass,
125
+ flow: gridDefaults.flow,
126
+ requestedColumns,
127
+ columns,
128
+ rowGap,
129
+ columnGap,
130
+ columnWidth,
131
+ };
132
+ }
133
+ //# sourceMappingURL=grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.js","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"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","sourcesContent":["import { spacing } from \"./foundations.js\";\nimport {\n resolveResponsiveValue,\n resolveWindowClass,\n validateResponsiveValue,\n windowClassOrder,\n type ResponsiveValue,\n type WindowClass,\n} from \"./responsive.js\";\n\n/** `none` is the only non-token gap: the semantic absence of space. */\nexport const gridGaps = {\n none: 0,\n ...spacing,\n} as const;\n\nexport type GridGapToken = keyof typeof gridGaps;\n\n/** A single token applies to both axes; the object form allows independent axes. */\nexport type GridGap =\n | GridGapToken\n | Readonly<{\n row: GridGapToken;\n column: GridGapToken;\n }>;\n\nexport type GridDescriptor = Readonly<{\n /** Requested column count at each window class; every value must be a positive integer. */\n columns: ResponsiveValue<number>;\n /** Token-only spacing. Missing larger classes inherit toward compact. */\n gap?: ResponsiveValue<GridGap>;\n /**\n * Optional target floor. The resolver reduces `columns` before allowing\n * multiple columns below this width; one column still shrinks to its container.\n */\n minColumnWidth?: ResponsiveValue<number>;\n}>;\n\nexport const gridDefaults = {\n gap: \"md\",\n flow: \"row-major\",\n} as const satisfies Readonly<{\n gap: GridGapToken;\n flow: \"row-major\";\n}>;\n\nexport const gridRecipe = {\n slots: [\"root\", \"item\"] as const,\n defaults: gridDefaults,\n gaps: gridGaps,\n} as const;\n\nexport type ResolveGridLayoutOptions = Readonly<{\n /** Full window/viewport width used only to choose the shared WindowClass. */\n windowWidth: number;\n /** Inner grid width after page padding/sidebar; defaults to windowWidth. */\n availableWidth?: number;\n}>;\n\nexport type ResolvedGridLayout = Readonly<{\n windowClass: WindowClass;\n flow: \"row-major\";\n requestedColumns: number;\n columns: number;\n rowGap: number;\n columnGap: number;\n columnWidth: number;\n}>;\n\nconst descriptorKeys = new Set([\"columns\", \"gap\", \"minColumnWidth\"]);\nconst gapKeys = new Set([\"row\", \"column\"]);\nconst optionKeys = new Set([\"windowWidth\", \"availableWidth\"]);\nconst gapTokens = new Set<GridGapToken>(\n Object.keys(gridGaps) as GridGapToken[],\n);\n\nfunction isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction rejectUnknownKeys(\n value: Readonly<Record<string, unknown>>,\n allowed: ReadonlySet<string>,\n field: string,\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) {\n throw new TypeError(`Unsupported Grid ${field} field: ${key}`);\n }\n }\n}\n\nfunction forEachResponsiveValue<Value>(\n responsive: ResponsiveValue<Value>,\n visit: (value: Value, windowClass: WindowClass) => void,\n): void {\n validateResponsiveValue(responsive);\n for (const windowClass of windowClassOrder) {\n if (Object.hasOwn(responsive, windowClass)) {\n visit(responsive[windowClass] as Value, windowClass);\n }\n }\n}\n\nfunction validateColumnCount(value: number, windowClass: WindowClass): void {\n if (!Number.isInteger(value) || value <= 0) {\n throw new RangeError(\n `Grid columns at ${windowClass} must be a positive integer`,\n );\n }\n}\n\nfunction validatePositiveWidth(value: number, field: string): void {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw new RangeError(`Grid ${field} must be a positive finite number`);\n }\n}\n\nfunction validateGapToken(value: unknown, field: string): asserts value is GridGapToken {\n if (typeof value !== \"string\" || !gapTokens.has(value as GridGapToken)) {\n throw new TypeError(`Unsupported Grid ${field} gap: ${String(value)}`);\n }\n}\n\nfunction validateGap(value: GridGap, windowClass: WindowClass): void {\n if (typeof value === \"string\") {\n validateGapToken(value, windowClass);\n return;\n }\n if (!isRecord(value)) {\n throw new TypeError(`Grid gap at ${windowClass} must be a token or axis object`);\n }\n rejectUnknownKeys(value, gapKeys, `gap.${windowClass}`);\n validateGapToken(value.row, `${windowClass}.row`);\n validateGapToken(value.column, `${windowClass}.column`);\n}\n\nexport function validateGridDescriptor(descriptor: GridDescriptor): void {\n if (!isRecord(descriptor)) {\n throw new TypeError(\"Grid descriptor must be an object\");\n }\n rejectUnknownKeys(descriptor, descriptorKeys, \"descriptor\");\n\n forEachResponsiveValue(descriptor.columns, validateColumnCount);\n if (descriptor.gap !== undefined) {\n forEachResponsiveValue(descriptor.gap, validateGap);\n }\n if (descriptor.minColumnWidth !== undefined) {\n forEachResponsiveValue(descriptor.minColumnWidth, (value, windowClass) => {\n validatePositiveWidth(value, `minColumnWidth at ${windowClass}`);\n });\n }\n}\n\nfunction validateResolveOptions(options: ResolveGridLayoutOptions): Readonly<{\n availableWidth: number;\n windowClass: WindowClass;\n}> {\n if (!isRecord(options)) {\n throw new TypeError(\"Grid layout options must be an object\");\n }\n rejectUnknownKeys(options, optionKeys, \"layout options\");\n // resolveWindowClass owns the zero-width/negative distinction for the window.\n const windowClass = resolveWindowClass(options.windowWidth);\n const availableWidth = options.availableWidth ?? options.windowWidth;\n validatePositiveWidth(availableWidth, \"availableWidth\");\n return { availableWidth, windowClass };\n}\n\nfunction resolveGap(gap: GridGap): Readonly<{ row: number; column: number }> {\n if (typeof gap === \"string\") {\n const resolved = gridGaps[gap];\n return { row: resolved, column: resolved };\n }\n return {\n row: gridGaps[gap.row],\n column: gridGaps[gap.column],\n };\n}\n\n/**\n * Resolves renderer-neutral grid geometry. Columns may only collapse from\n * the requested count when `minColumnWidth` requires it; they never widen.\n * Renderers must preserve child source order (`row-major`) on both platforms.\n */\nexport function resolveGridLayout(\n descriptor: GridDescriptor,\n options: ResolveGridLayoutOptions,\n): ResolvedGridLayout {\n validateGridDescriptor(descriptor);\n const { availableWidth, windowClass } = validateResolveOptions(options);\n const requestedColumns = resolveResponsiveValue(descriptor.columns, windowClass);\n const responsiveGap = descriptor.gap ?? { compact: gridDefaults.gap };\n const { row: rowGap, column: columnGap } = resolveGap(\n resolveResponsiveValue(responsiveGap, windowClass),\n );\n\n let columns = requestedColumns;\n if (descriptor.minColumnWidth !== undefined) {\n const minColumnWidth = resolveResponsiveValue(\n descriptor.minColumnWidth,\n windowClass,\n );\n const fittingColumns = Math.max(\n 1,\n Math.floor((availableWidth + columnGap) / (minColumnWidth + columnGap)),\n );\n columns = Math.min(requestedColumns, fittingColumns);\n }\n\n const columnWidth =\n (availableWidth - columnGap * (columns - 1)) / columns;\n if (!Number.isFinite(columnWidth) || columnWidth <= 0) {\n throw new RangeError(\n \"Grid columns and column gap leave no positive column width\",\n );\n }\n\n return {\n windowClass,\n flow: gridDefaults.flow,\n requestedColumns,\n columns,\n rowGap,\n columnGap,\n columnWidth,\n };\n}\n"]}
@@ -0,0 +1,99 @@
1
+ import { type ColorReferencePalette } from "./color-references.js";
2
+ export type IconButtonSize = "small" | "medium" | "large";
3
+ export type IconButtonShape = "rounded" | "circle";
4
+ export type IconButtonTone = "primary" | "secondary" | "ghost" | "danger";
5
+ export declare const iconButtonRecipe: {
6
+ readonly slots: readonly ["root", "icon", "spinner"];
7
+ readonly defaults: {
8
+ readonly tone: "ghost";
9
+ readonly size: "medium";
10
+ readonly shape: "rounded";
11
+ };
12
+ readonly tones: {
13
+ readonly primary: {
14
+ readonly background: Readonly<{
15
+ source: "theme";
16
+ key: "primary";
17
+ alpha?: number;
18
+ }>;
19
+ readonly content: Readonly<{
20
+ source: "theme";
21
+ key: "onPrimary";
22
+ alpha?: number;
23
+ }>;
24
+ readonly border: null;
25
+ };
26
+ readonly secondary: {
27
+ readonly background: Readonly<{
28
+ source: "theme";
29
+ key: "surfaceAlt";
30
+ alpha?: number;
31
+ }>;
32
+ readonly content: Readonly<{
33
+ source: "theme";
34
+ key: "text";
35
+ alpha?: number;
36
+ }>;
37
+ readonly border: Readonly<{
38
+ source: "theme";
39
+ key: "border";
40
+ alpha?: number;
41
+ }>;
42
+ };
43
+ readonly ghost: {
44
+ readonly background: null;
45
+ readonly content: Readonly<{
46
+ source: "theme";
47
+ key: "textMuted";
48
+ alpha?: number;
49
+ }>;
50
+ readonly border: null;
51
+ };
52
+ readonly danger: {
53
+ readonly background: Readonly<{
54
+ source: "theme";
55
+ key: "dangerFill";
56
+ alpha?: number;
57
+ }>;
58
+ readonly content: Readonly<{
59
+ source: "theme";
60
+ key: "onDanger";
61
+ alpha?: number;
62
+ }>;
63
+ readonly border: null;
64
+ };
65
+ };
66
+ readonly sizes: {
67
+ readonly small: {
68
+ readonly diameter: 36;
69
+ readonly hitSlop: 4;
70
+ readonly glyph: "sm";
71
+ };
72
+ readonly medium: {
73
+ readonly diameter: 44;
74
+ readonly hitSlop: 0;
75
+ readonly glyph: "md";
76
+ };
77
+ readonly large: {
78
+ readonly diameter: 52;
79
+ readonly hitSlop: 0;
80
+ readonly glyph: "lg";
81
+ };
82
+ };
83
+ readonly shapes: {
84
+ readonly rounded: "md";
85
+ readonly circle: "full";
86
+ };
87
+ readonly states: {
88
+ readonly pressedOpacity: 0.86;
89
+ readonly disabledOpacity: 0.5;
90
+ };
91
+ };
92
+ export type ResolvedIconButtonPresentation = Readonly<{
93
+ background: string | null;
94
+ content: string;
95
+ border: string | null;
96
+ }>;
97
+ /** Resolve one recipe tone for non-CSS renderers without a second tone table. */
98
+ export declare function resolveIconButtonPresentation(tone: IconButtonTone, palette: ColorReferencePalette): ResolvedIconButtonPresentation;
99
+ //# sourceMappingURL=icon-button-recipe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-button-recipe.d.ts","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAQ/B,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC1D,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AACnD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1E,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiD5B,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CAAC;IACpD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC,CAAC;AAEH,iFAAiF;AACjF,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,qBAAqB,GAC7B,8BAA8B,CAahC"}
@@ -0,0 +1,53 @@
1
+ import { resolveColorReference, } from "./color-references.js";
2
+ import { opacity, radius, } from "./foundations.js";
3
+ import { semanticColors } from "./semantic-colors.js";
4
+ export const iconButtonRecipe = {
5
+ slots: ["root", "icon", "spinner"],
6
+ defaults: { tone: "ghost", size: "medium", shape: "rounded" },
7
+ tones: {
8
+ primary: {
9
+ background: semanticColors.action.brand.background,
10
+ content: semanticColors.action.brand.content,
11
+ border: null,
12
+ },
13
+ secondary: {
14
+ background: semanticColors.action.neutral.background,
15
+ content: semanticColors.action.neutral.content,
16
+ border: semanticColors.border.default,
17
+ },
18
+ ghost: {
19
+ background: null,
20
+ content: semanticColors.content.secondary,
21
+ border: null,
22
+ },
23
+ danger: {
24
+ background: semanticColors.action.danger.background,
25
+ content: semanticColors.action.danger.content,
26
+ border: null,
27
+ },
28
+ },
29
+ sizes: {
30
+ small: { diameter: 36, hitSlop: 4, glyph: "sm" },
31
+ medium: { diameter: 44, hitSlop: 0, glyph: "md" },
32
+ large: { diameter: 52, hitSlop: 0, glyph: "lg" },
33
+ },
34
+ shapes: { rounded: "md", circle: "full" },
35
+ states: {
36
+ pressedOpacity: opacity.pressed,
37
+ disabledOpacity: opacity.disabled,
38
+ },
39
+ };
40
+ /** Resolve one recipe tone for non-CSS renderers without a second tone table. */
41
+ export function resolveIconButtonPresentation(tone, palette) {
42
+ const contract = iconButtonRecipe.tones[tone];
43
+ return {
44
+ background: contract.background === null
45
+ ? null
46
+ : resolveColorReference(contract.background, palette),
47
+ content: resolveColorReference(contract.content, palette),
48
+ border: contract.border === null
49
+ ? null
50
+ : resolveColorReference(contract.border, palette),
51
+ };
52
+ }
53
+ //# sourceMappingURL=icon-button-recipe.js.map