@panneau/ui 5.0.0-alpha.1 → 5.0.0-alpha.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 (384) hide show
  1. package/README.md +263 -6
  2. package/bin/check-theme.js +5 -0
  3. package/dist/alert/Alert.css +28 -42
  4. package/dist/alert/Alert.d.ts +18 -4
  5. package/dist/alert/Alert.d.ts.map +1 -1
  6. package/dist/alert/Alert.js +4 -3
  7. package/dist/alert/Alert.js.map +1 -1
  8. package/dist/alert/Alert.module.js +14 -16
  9. package/dist/alert/Alert.module.js.map +1 -1
  10. package/dist/alert/tokens.d.ts +3 -0
  11. package/dist/alert/tokens.d.ts.map +1 -0
  12. package/dist/alert/tokens.js +21 -0
  13. package/dist/alert/tokens.js.map +1 -0
  14. package/dist/badge/Badge.css +24 -36
  15. package/dist/badge/Badge.d.ts +18 -3
  16. package/dist/badge/Badge.d.ts.map +1 -1
  17. package/dist/badge/Badge.js +3 -2
  18. package/dist/badge/Badge.js.map +1 -1
  19. package/dist/badge/Badge.module.js +9 -13
  20. package/dist/badge/Badge.module.js.map +1 -1
  21. package/dist/badge/tokens.d.ts +3 -0
  22. package/dist/badge/tokens.d.ts.map +1 -0
  23. package/dist/badge/tokens.js +23 -0
  24. package/dist/badge/tokens.js.map +1 -0
  25. package/dist/button/Button.css +58 -42
  26. package/dist/button/Button.d.ts +30 -3
  27. package/dist/button/Button.d.ts.map +1 -1
  28. package/dist/button/Button.js +27 -2
  29. package/dist/button/Button.js.map +1 -1
  30. package/dist/button/Button.module.js +14 -14
  31. package/dist/button/Button.module.js.map +1 -1
  32. package/dist/button/tokens.d.ts +3 -0
  33. package/dist/button/tokens.d.ts.map +1 -0
  34. package/dist/button/tokens.js +25 -0
  35. package/dist/button/tokens.js.map +1 -0
  36. package/dist/card/Card.css +27 -20
  37. package/dist/card/Card.js +1 -1
  38. package/dist/card/Card.js.map +1 -1
  39. package/dist/card/Card.module.js +5 -5
  40. package/dist/card/Card.module.js.map +1 -1
  41. package/dist/card/tokens.d.ts +3 -0
  42. package/dist/card/tokens.d.ts.map +1 -0
  43. package/dist/card/tokens.js +31 -0
  44. package/dist/card/tokens.js.map +1 -0
  45. package/dist/checkbox/Checkbox.css +22 -21
  46. package/dist/checkbox/Checkbox.d.ts.map +1 -1
  47. package/dist/checkbox/Checkbox.js +1 -0
  48. package/dist/checkbox/Checkbox.js.map +1 -1
  49. package/dist/checkbox/Checkbox.module.js +4 -4
  50. package/dist/checkbox/Checkbox.module.js.map +1 -1
  51. package/dist/checkbox/ChoiceChrome.d.ts +3 -1
  52. package/dist/checkbox/ChoiceChrome.d.ts.map +1 -1
  53. package/dist/checkbox/ChoiceChrome.js +2 -2
  54. package/dist/checkbox/ChoiceChrome.js.map +1 -1
  55. package/dist/checkbox/tokens.d.ts +3 -0
  56. package/dist/checkbox/tokens.d.ts.map +1 -0
  57. package/dist/checkbox/tokens.js +21 -0
  58. package/dist/checkbox/tokens.js.map +1 -0
  59. package/dist/combo-box/ComboBox.css +4 -4
  60. package/dist/combo-box/ComboBox.js +1 -1
  61. package/dist/combo-box/ComboBox.js.map +1 -1
  62. package/dist/combo-box/ComboBox.module.js +3 -3
  63. package/dist/container/Container.css +32 -0
  64. package/dist/container/Container.d.ts +15 -0
  65. package/dist/container/Container.d.ts.map +1 -0
  66. package/dist/container/Container.js +18 -0
  67. package/dist/container/Container.js.map +1 -0
  68. package/dist/container/Container.module.js +20 -0
  69. package/dist/container/Container.module.js.map +1 -0
  70. package/dist/container/tokens.d.ts +3 -0
  71. package/dist/container/tokens.d.ts.map +1 -0
  72. package/dist/container/tokens.js +19 -0
  73. package/dist/container/tokens.js.map +1 -0
  74. package/dist/date-picker/DatePicker.css +30 -30
  75. package/dist/date-picker/DatePicker.js +1 -1
  76. package/dist/date-picker/DatePicker.js.map +1 -1
  77. package/dist/date-picker/DatePicker.module.js +11 -11
  78. package/dist/date-picker/DatePicker.module.js.map +1 -1
  79. package/dist/date-picker/calendarTokens.d.ts +3 -0
  80. package/dist/date-picker/calendarTokens.d.ts.map +1 -0
  81. package/dist/date-picker/calendarTokens.js +17 -0
  82. package/dist/date-picker/calendarTokens.js.map +1 -0
  83. package/dist/dialog/Dialog.css +40 -36
  84. package/dist/dialog/Dialog.js +1 -1
  85. package/dist/dialog/Dialog.js.map +1 -1
  86. package/dist/dialog/Dialog.module.js +11 -11
  87. package/dist/dialog/Dialog.module.js.map +1 -1
  88. package/dist/dialog/tokens.d.ts +3 -0
  89. package/dist/dialog/tokens.d.ts.map +1 -0
  90. package/dist/dialog/tokens.js +29 -0
  91. package/dist/dialog/tokens.js.map +1 -0
  92. package/dist/disclosure/Disclosure.css +12 -12
  93. package/dist/disclosure/Disclosure.d.ts.map +1 -1
  94. package/dist/disclosure/Disclosure.js +1 -1
  95. package/dist/disclosure/Disclosure.js.map +1 -1
  96. package/dist/disclosure/Disclosure.module.js +7 -7
  97. package/dist/disclosure/Disclosure.module.js.map +1 -1
  98. package/dist/disclosure/tokens.d.ts +3 -0
  99. package/dist/disclosure/tokens.d.ts.map +1 -0
  100. package/dist/disclosure/tokens.js +15 -0
  101. package/dist/disclosure/tokens.js.map +1 -0
  102. package/dist/divider/Divider.css +17 -0
  103. package/dist/divider/Divider.d.ts +8 -0
  104. package/dist/divider/Divider.d.ts.map +1 -0
  105. package/dist/divider/Divider.js +21 -0
  106. package/dist/divider/Divider.js.map +1 -0
  107. package/dist/divider/Divider.module.js +12 -0
  108. package/dist/divider/Divider.module.js.map +1 -0
  109. package/dist/divider/tokens.d.ts +3 -0
  110. package/dist/divider/tokens.d.ts.map +1 -0
  111. package/dist/divider/tokens.js +13 -0
  112. package/dist/divider/tokens.js.map +1 -0
  113. package/dist/field/Field.css +40 -37
  114. package/dist/field/Field.module.js +11 -11
  115. package/dist/field/Field.module.js.map +1 -1
  116. package/dist/field/Fieldset.js +1 -1
  117. package/dist/field/Fieldset.js.map +1 -1
  118. package/dist/field/inputTokens.d.ts +3 -0
  119. package/dist/field/inputTokens.d.ts.map +1 -0
  120. package/dist/field/inputTokens.js +21 -0
  121. package/dist/field/inputTokens.js.map +1 -0
  122. package/dist/field/tokens.d.ts +3 -0
  123. package/dist/field/tokens.d.ts.map +1 -0
  124. package/dist/field/tokens.js +15 -0
  125. package/dist/field/tokens.js.map +1 -0
  126. package/dist/grid/Grid.css +174 -0
  127. package/dist/grid/Grid.d.ts +28 -0
  128. package/dist/grid/Grid.d.ts.map +1 -0
  129. package/dist/grid/Grid.js +31 -0
  130. package/dist/grid/Grid.js.map +1 -0
  131. package/dist/grid/Grid.module.js +12 -0
  132. package/dist/grid/Grid.module.js.map +1 -0
  133. package/dist/grid/GridItem.css +59 -0
  134. package/dist/grid/GridItem.module.js +7 -0
  135. package/dist/grid/GridItem.module.js.map +1 -0
  136. package/dist/grid/tokens.d.ts +3 -0
  137. package/dist/grid/tokens.d.ts.map +1 -0
  138. package/dist/grid/tokens.js +10 -0
  139. package/dist/grid/tokens.js.map +1 -0
  140. package/dist/heading/Heading.css +52 -0
  141. package/dist/heading/Heading.d.ts +17 -0
  142. package/dist/heading/Heading.d.ts.map +1 -0
  143. package/dist/heading/Heading.js +17 -0
  144. package/dist/heading/Heading.js.map +1 -0
  145. package/dist/heading/Heading.module.js +16 -0
  146. package/dist/heading/Heading.module.js.map +1 -0
  147. package/dist/heading/tokens.d.ts +6 -0
  148. package/dist/heading/tokens.d.ts.map +1 -0
  149. package/dist/heading/tokens.js +66 -0
  150. package/dist/heading/tokens.js.map +1 -0
  151. package/dist/icon/Icon.css +1 -1
  152. package/dist/icon/Icon.js +1 -1
  153. package/dist/icon/Icon.js.map +1 -1
  154. package/dist/icon/Icon.module.js +1 -1
  155. package/dist/icon-button/IconButton.css +2 -2
  156. package/dist/icon-button/IconButton.d.ts +1 -1
  157. package/dist/icon-button/IconButton.d.ts.map +1 -1
  158. package/dist/icon-button/IconButton.js +3 -3
  159. package/dist/icon-button/IconButton.js.map +1 -1
  160. package/dist/icon-button/IconButton.module.js +2 -2
  161. package/dist/index.d.ts +25 -5
  162. package/dist/index.d.ts.map +1 -1
  163. package/dist/index.js +20 -2
  164. package/dist/inline/Inline.css +142 -0
  165. package/dist/inline/Inline.d.ts +17 -0
  166. package/dist/inline/Inline.d.ts.map +1 -0
  167. package/dist/inline/Inline.js +21 -0
  168. package/dist/inline/Inline.js.map +1 -0
  169. package/dist/inline/Inline.module.js +12 -0
  170. package/dist/inline/Inline.module.js.map +1 -0
  171. package/dist/inline/tokens.d.ts +3 -0
  172. package/dist/inline/tokens.d.ts.map +1 -0
  173. package/dist/inline/tokens.js +10 -0
  174. package/dist/inline/tokens.js.map +1 -0
  175. package/dist/layout/responsive.d.ts +38 -0
  176. package/dist/layout/responsive.d.ts.map +1 -0
  177. package/dist/layout/responsive.js +49 -0
  178. package/dist/layout/responsive.js.map +1 -0
  179. package/dist/menu/Menu.js +2 -2
  180. package/dist/menu/Menu.js.map +1 -1
  181. package/dist/number-input/NumberInput.css +12 -12
  182. package/dist/number-input/NumberInput.js +1 -1
  183. package/dist/number-input/NumberInput.js.map +1 -1
  184. package/dist/number-input/NumberInput.module.js +4 -4
  185. package/dist/number-input/NumberInput.module.js.map +1 -1
  186. package/dist/number-input/tokens.d.ts +3 -0
  187. package/dist/number-input/tokens.d.ts.map +1 -0
  188. package/dist/number-input/tokens.js +10 -0
  189. package/dist/number-input/tokens.js.map +1 -0
  190. package/dist/popover/Popover.css +13 -12
  191. package/dist/popover/Popover.js +2 -2
  192. package/dist/popover/Popover.js.map +1 -1
  193. package/dist/popover/Popover.module.js +3 -3
  194. package/dist/popover/Popover.module.js.map +1 -1
  195. package/dist/popover/tokens.d.ts +3 -0
  196. package/dist/popover/tokens.d.ts.map +1 -0
  197. package/dist/popover/tokens.js +19 -0
  198. package/dist/popover/tokens.js.map +1 -0
  199. package/dist/prose/Prose.css +141 -0
  200. package/dist/prose/Prose.d.ts +11 -0
  201. package/dist/prose/Prose.d.ts.map +1 -0
  202. package/dist/prose/Prose.js +18 -0
  203. package/dist/prose/Prose.js.map +1 -0
  204. package/dist/prose/Prose.module.js +8 -0
  205. package/dist/prose/Prose.module.js.map +1 -0
  206. package/dist/prose/tokens.d.ts +3 -0
  207. package/dist/prose/tokens.d.ts.map +1 -0
  208. package/dist/prose/tokens.js +33 -0
  209. package/dist/prose/tokens.js.map +1 -0
  210. package/dist/radio-group/RadioGroup.css +21 -20
  211. package/dist/radio-group/RadioGroup.d.ts.map +1 -1
  212. package/dist/radio-group/RadioGroup.js +2 -2
  213. package/dist/radio-group/RadioGroup.js.map +1 -1
  214. package/dist/radio-group/RadioGroup.module.js +6 -6
  215. package/dist/radio-group/RadioGroup.module.js.map +1 -1
  216. package/dist/radio-group/tokens.d.ts +3 -0
  217. package/dist/radio-group/tokens.d.ts.map +1 -0
  218. package/dist/radio-group/tokens.js +19 -0
  219. package/dist/radio-group/tokens.js.map +1 -0
  220. package/dist/root/PanneauRoot.css +243 -20
  221. package/dist/root/PanneauRoot.d.ts +28 -4
  222. package/dist/root/PanneauRoot.d.ts.map +1 -1
  223. package/dist/root/PanneauRoot.js +104 -21
  224. package/dist/root/PanneauRoot.js.map +1 -1
  225. package/dist/root/PanneauRoot.module.js +11 -3
  226. package/dist/root/PanneauRoot.module.js.map +1 -1
  227. package/dist/root/ThemeScope.d.ts +24 -0
  228. package/dist/root/ThemeScope.d.ts.map +1 -0
  229. package/dist/root/ThemeScope.js +49 -0
  230. package/dist/root/ThemeScope.js.map +1 -0
  231. package/dist/select/ListBox.css +23 -22
  232. package/dist/select/ListBox.module.js +12 -12
  233. package/dist/select/ListBox.module.js.map +1 -1
  234. package/dist/select/Select.js +1 -1
  235. package/dist/select/Select.js.map +1 -1
  236. package/dist/select/listBoxTokens.d.ts +3 -0
  237. package/dist/select/listBoxTokens.d.ts.map +1 -0
  238. package/dist/select/listBoxTokens.js +19 -0
  239. package/dist/select/listBoxTokens.js.map +1 -0
  240. package/dist/spinner/Spinner.css +8 -8
  241. package/dist/spinner/Spinner.js +1 -1
  242. package/dist/spinner/Spinner.js.map +1 -1
  243. package/dist/spinner/Spinner.module.js +5 -5
  244. package/dist/spinner/Spinner.module.js.map +1 -1
  245. package/dist/spinner/tokens.d.ts +3 -0
  246. package/dist/spinner/tokens.d.ts.map +1 -0
  247. package/dist/spinner/tokens.js +10 -0
  248. package/dist/spinner/tokens.js.map +1 -0
  249. package/dist/stack/Stack.css +135 -0
  250. package/dist/stack/Stack.d.ts +15 -0
  251. package/dist/stack/Stack.d.ts.map +1 -0
  252. package/dist/stack/Stack.js +21 -0
  253. package/dist/stack/Stack.js.map +1 -0
  254. package/dist/stack/Stack.module.js +8 -0
  255. package/dist/stack/Stack.module.js.map +1 -0
  256. package/dist/stack/tokens.d.ts +3 -0
  257. package/dist/stack/tokens.d.ts.map +1 -0
  258. package/dist/stack/tokens.js +10 -0
  259. package/dist/stack/tokens.js.map +1 -0
  260. package/dist/switch/Switch.css +34 -25
  261. package/dist/switch/Switch.d.ts.map +1 -1
  262. package/dist/switch/Switch.js +1 -0
  263. package/dist/switch/Switch.js.map +1 -1
  264. package/dist/switch/Switch.module.js +4 -4
  265. package/dist/switch/Switch.module.js.map +1 -1
  266. package/dist/switch/tokens.d.ts +3 -0
  267. package/dist/switch/tokens.d.ts.map +1 -0
  268. package/dist/switch/tokens.js +25 -0
  269. package/dist/switch/tokens.js.map +1 -0
  270. package/dist/tabs/Tabs.css +24 -23
  271. package/dist/tabs/Tabs.js +4 -4
  272. package/dist/tabs/Tabs.js.map +1 -1
  273. package/dist/tabs/Tabs.module.js +4 -4
  274. package/dist/tabs/Tabs.module.js.map +1 -1
  275. package/dist/tabs/tokens.d.ts +3 -0
  276. package/dist/tabs/tokens.d.ts.map +1 -0
  277. package/dist/tabs/tokens.js +25 -0
  278. package/dist/tabs/tokens.js.map +1 -0
  279. package/dist/text/Text.css +74 -0
  280. package/dist/text/Text.d.ts +27 -0
  281. package/dist/text/Text.d.ts.map +1 -0
  282. package/dist/text/Text.js +16 -0
  283. package/dist/text/Text.js.map +1 -0
  284. package/dist/text/Text.module.js +30 -0
  285. package/dist/text/Text.module.js.map +1 -0
  286. package/dist/text/tokens.d.ts +3 -0
  287. package/dist/text/tokens.d.ts.map +1 -0
  288. package/dist/text/tokens.js +10 -0
  289. package/dist/text/tokens.js.map +1 -0
  290. package/dist/text-area/TextArea.css +1 -1
  291. package/dist/text-area/TextArea.js +1 -1
  292. package/dist/text-area/TextArea.js.map +1 -1
  293. package/dist/text-area/TextArea.module.js +1 -1
  294. package/dist/text-input/TextInput.js +1 -1
  295. package/dist/text-input/TextInput.js.map +1 -1
  296. package/dist/theme/Tone.css +70 -0
  297. package/dist/theme/Tone.module.js +20 -0
  298. package/dist/theme/Tone.module.js.map +1 -0
  299. package/dist/theme/bootstrap.d.ts +10 -0
  300. package/dist/theme/bootstrap.d.ts.map +1 -1
  301. package/dist/theme/bootstrap.js +48 -5
  302. package/dist/theme/bootstrap.js.map +1 -1
  303. package/dist/theme/chartColors.d.ts +23 -0
  304. package/dist/theme/chartColors.d.ts.map +1 -0
  305. package/dist/theme/chartColors.js +27 -0
  306. package/dist/theme/chartColors.js.map +1 -0
  307. package/dist/theme/checkTheme.d.ts +39 -0
  308. package/dist/theme/checkTheme.d.ts.map +1 -0
  309. package/dist/theme/checkTheme.js +132 -0
  310. package/dist/theme/checkTheme.js.map +1 -0
  311. package/dist/theme/cli.d.ts +14 -0
  312. package/dist/theme/cli.d.ts.map +1 -0
  313. package/dist/theme/cli.js +61 -0
  314. package/dist/theme/cli.js.map +1 -0
  315. package/dist/theme/color.d.ts +30 -0
  316. package/dist/theme/color.d.ts.map +1 -0
  317. package/dist/theme/color.js +94 -0
  318. package/dist/theme/color.js.map +1 -0
  319. package/dist/theme/colorVision.d.ts +23 -0
  320. package/dist/theme/colorVision.d.ts.map +1 -0
  321. package/dist/theme/colorVision.js +140 -0
  322. package/dist/theme/colorVision.js.map +1 -0
  323. package/dist/theme/componentTokens.d.ts +24 -0
  324. package/dist/theme/componentTokens.d.ts.map +1 -0
  325. package/dist/theme/componentTokens.js +20 -0
  326. package/dist/theme/componentTokens.js.map +1 -0
  327. package/dist/theme/components.d.ts +38 -0
  328. package/dist/theme/components.d.ts.map +1 -0
  329. package/dist/theme/components.js +65 -0
  330. package/dist/theme/components.js.map +1 -0
  331. package/dist/theme/defineTheme.d.ts +85 -0
  332. package/dist/theme/defineTheme.d.ts.map +1 -0
  333. package/dist/theme/defineTheme.js +130 -0
  334. package/dist/theme/defineTheme.js.map +1 -0
  335. package/dist/theme/fonts.d.ts +32 -0
  336. package/dist/theme/fonts.d.ts.map +1 -0
  337. package/dist/theme/fonts.js +36 -0
  338. package/dist/theme/fonts.js.map +1 -0
  339. package/dist/theme/index.d.ts +13 -0
  340. package/dist/theme/index.d.ts.map +1 -0
  341. package/dist/theme/index.js +10 -0
  342. package/dist/theme/semanticTokens.d.ts +9 -0
  343. package/dist/theme/semanticTokens.d.ts.map +1 -0
  344. package/dist/theme/semanticTokens.js +110 -0
  345. package/dist/theme/semanticTokens.js.map +1 -0
  346. package/dist/theme/theme.d.ts +61 -7
  347. package/dist/theme/theme.d.ts.map +1 -1
  348. package/dist/theme/theme.js +100 -10
  349. package/dist/theme/theme.js.map +1 -1
  350. package/dist/theme/toneClass.d.ts +8 -0
  351. package/dist/theme/toneClass.d.ts.map +1 -0
  352. package/dist/theme/toneClass.js +15 -0
  353. package/dist/theme/toneClass.js.map +1 -0
  354. package/dist/theme/tones.d.ts +89 -0
  355. package/dist/theme/tones.d.ts.map +1 -0
  356. package/dist/theme/tones.js +127 -0
  357. package/dist/theme/tones.js.map +1 -0
  358. package/dist/time-input/TimeInput.js +1 -1
  359. package/dist/time-input/TimeInput.js.map +1 -1
  360. package/dist/toast/Toast.css +22 -44
  361. package/dist/toast/Toast.d.ts +5 -3
  362. package/dist/toast/Toast.d.ts.map +1 -1
  363. package/dist/toast/Toast.js +4 -3
  364. package/dist/toast/Toast.js.map +1 -1
  365. package/dist/toast/Toast.module.js +10 -16
  366. package/dist/toast/Toast.module.js.map +1 -1
  367. package/dist/toast/tokens.d.ts +3 -0
  368. package/dist/toast/tokens.d.ts.map +1 -0
  369. package/dist/toast/tokens.js +21 -0
  370. package/dist/toast/tokens.js.map +1 -0
  371. package/dist/tooltip/Tooltip.css +12 -11
  372. package/dist/tooltip/Tooltip.js +1 -1
  373. package/dist/tooltip/Tooltip.js.map +1 -1
  374. package/dist/tooltip/Tooltip.module.js +2 -2
  375. package/dist/tooltip/Tooltip.module.js.map +1 -1
  376. package/dist/tooltip/tokens.d.ts +3 -0
  377. package/dist/tooltip/tokens.d.ts.map +1 -0
  378. package/dist/tooltip/tokens.js +21 -0
  379. package/dist/tooltip/tokens.js.map +1 -0
  380. package/dist/utils/cx.d.ts +1 -1
  381. package/dist/utils/cx.d.ts.map +1 -1
  382. package/dist/utils/cx.js +2 -2
  383. package/dist/utils/cx.js.map +1 -1
  384. package/package.json +15 -3
@@ -0,0 +1,23 @@
1
+ import { type Rgb } from './color';
2
+ /** A color vision deficiency, at full severity: red-blind, green-blind or blue-blind. */
3
+ export type ColorVisionDeficiency = 'protanopia' | 'deuteranopia' | 'tritanopia';
4
+ /** A color as a person with a color vision deficiency sees it. */
5
+ export declare function simulateColorVision(color: Rgb, deficiency: ColorVisionDeficiency): Rgb;
6
+ /** The perceived difference between two colors: the CIE76 distance in CIELAB. */
7
+ export declare function colorDifference(first: Rgb, second: Rgb): number;
8
+ /** Two colors of a palette that look too alike, for everyone or with a deficiency. */
9
+ export interface ColorDifferenceCheck {
10
+ vision: 'typical' | ColorVisionDeficiency;
11
+ first: string;
12
+ second: string;
13
+ difference: number;
14
+ minimum: number;
15
+ }
16
+ /**
17
+ * Checks that the colors of a palette (the categorical colors of charts) stay distinct, for
18
+ * typical vision and under protanopia, deuteranopia and tritanopia: every pair must differ by at
19
+ * least `minimum` (CIE76, 10 by default, a difference anyone notices side by side). Colors Panneau
20
+ * can't read are skipped. Returns the pairs below the minimum.
21
+ */
22
+ export declare function checkColorDifferences(colors: readonly string[], minimum?: number): ColorDifferenceCheck[];
23
+ //# sourceMappingURL=colorVision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colorVision.d.ts","sourceRoot":"","sources":["../../src/theme/colorVision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAc,MAAM,SAAS,CAAC;AAE/C,yFAAyF;AACzF,MAAM,MAAM,qBAAqB,GAAG,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;AA+BjF,kEAAkE;AAClE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,qBAAqB,GAAG,GAAG,CAMtF;AAWD,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,MAAM,CAI/D;AAED,sFAAsF;AACtF,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,SAAS,GAAG,qBAAqB,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACjC,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,OAAO,SAAK,GACb,oBAAoB,EAAE,CAoBxB"}
@@ -0,0 +1,140 @@
1
+ import { parseColor } from "./color.js";
2
+ //#region src/theme/colorVision.ts
3
+ /** Simulation matrices of Machado, Oliveira and Fernandes (2009), severity 1, on linear RGB. */
4
+ var MATRICES = {
5
+ protanopia: [
6
+ [
7
+ .152286,
8
+ 1.052583,
9
+ -.204868
10
+ ],
11
+ [
12
+ .114503,
13
+ .786281,
14
+ .099216
15
+ ],
16
+ [
17
+ -.003882,
18
+ -.048116,
19
+ 1.051998
20
+ ]
21
+ ],
22
+ deuteranopia: [
23
+ [
24
+ .367322,
25
+ .860646,
26
+ -.227968
27
+ ],
28
+ [
29
+ .280085,
30
+ .672501,
31
+ .047413
32
+ ],
33
+ [
34
+ -.01182,
35
+ .04294,
36
+ .968881
37
+ ]
38
+ ],
39
+ tritanopia: [
40
+ [
41
+ 1.255528,
42
+ -.076749,
43
+ -.178779
44
+ ],
45
+ [
46
+ -.078411,
47
+ .930809,
48
+ .147602
49
+ ],
50
+ [
51
+ .004733,
52
+ .691367,
53
+ .3039
54
+ ]
55
+ ]
56
+ };
57
+ var toLinear = (channel) => {
58
+ const value = channel / 255;
59
+ return value <= .04045 ? value / 12.92 : ((value + .055) / 1.055) ** 2.4;
60
+ };
61
+ var fromLinear = (value) => {
62
+ const clamped = Math.min(1, Math.max(0, value));
63
+ return (clamped <= .0031308 ? clamped * 12.92 : 1.055 * clamped ** (1 / 2.4) - .055) * 255;
64
+ };
65
+ /** A color as a person with a color vision deficiency sees it. */
66
+ function simulateColorVision(color, deficiency) {
67
+ const linear = [
68
+ toLinear(color.r),
69
+ toLinear(color.g),
70
+ toLinear(color.b)
71
+ ];
72
+ const [r = 0, g = 0, b = 0] = MATRICES[deficiency].map((row) => fromLinear(row.reduce((sum, weight, index) => sum + weight * (linear[index] ?? 0), 0)));
73
+ return {
74
+ r,
75
+ g,
76
+ b
77
+ };
78
+ }
79
+ function toLab(color) {
80
+ const [r, g, b] = [
81
+ toLinear(color.r),
82
+ toLinear(color.g),
83
+ toLinear(color.b)
84
+ ];
85
+ const f = (t) => t > .008856 ? Math.cbrt(t) : 7.787 * t + 16 / 116;
86
+ const x = f((.4124 * r + .3576 * g + .1805 * b) / .95047);
87
+ const y = f(.2126 * r + .7152 * g + .0722 * b);
88
+ const z = f((.0193 * r + .1192 * g + .9505 * b) / 1.08883);
89
+ return [
90
+ 116 * y - 16,
91
+ 500 * (x - y),
92
+ 200 * (y - z)
93
+ ];
94
+ }
95
+ /** The perceived difference between two colors: the CIE76 distance in CIELAB. */
96
+ function colorDifference(first, second) {
97
+ const [l1, a1, b1] = toLab(first);
98
+ const [l2, a2, b2] = toLab(second);
99
+ return Math.hypot(l1 - l2, a1 - a2, b1 - b2);
100
+ }
101
+ /**
102
+ * Checks that the colors of a palette (the categorical colors of charts) stay distinct, for
103
+ * typical vision and under protanopia, deuteranopia and tritanopia: every pair must differ by at
104
+ * least `minimum` (CIE76, 10 by default, a difference anyone notices side by side). Colors Panneau
105
+ * can't read are skipped. Returns the pairs below the minimum.
106
+ */
107
+ function checkColorDifferences(colors, minimum = 10) {
108
+ const parsed = colors.flatMap((color) => {
109
+ const rgb = parseColor(color);
110
+ return rgb !== null ? [{
111
+ color,
112
+ rgb
113
+ }] : [];
114
+ });
115
+ return [
116
+ "typical",
117
+ "protanopia",
118
+ "deuteranopia",
119
+ "tritanopia"
120
+ ].flatMap((vision) => {
121
+ const seen = parsed.map(({ color, rgb }) => ({
122
+ color,
123
+ rgb: vision === "typical" ? rgb : simulateColorVision(rgb, vision)
124
+ }));
125
+ return seen.flatMap((first, index) => seen.slice(index + 1).flatMap((second) => {
126
+ const difference = Math.round(colorDifference(first.rgb, second.rgb) * 10) / 10;
127
+ return difference < minimum ? [{
128
+ vision,
129
+ first: first.color,
130
+ second: second.color,
131
+ difference,
132
+ minimum
133
+ }] : [];
134
+ }));
135
+ });
136
+ }
137
+ //#endregion
138
+ export { checkColorDifferences, colorDifference, simulateColorVision };
139
+
140
+ //# sourceMappingURL=colorVision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colorVision.js","names":[],"sources":["../../src/theme/colorVision.ts"],"sourcesContent":["import { type Rgb, parseColor } from './color';\n\n/** A color vision deficiency, at full severity: red-blind, green-blind or blue-blind. */\nexport type ColorVisionDeficiency = 'protanopia' | 'deuteranopia' | 'tritanopia';\n\n/** Simulation matrices of Machado, Oliveira and Fernandes (2009), severity 1, on linear RGB. */\nconst MATRICES: Record<ColorVisionDeficiency, readonly (readonly number[])[]> = {\n protanopia: [\n [0.152286, 1.052583, -0.204868],\n [0.114503, 0.786281, 0.099216],\n [-0.003882, -0.048116, 1.051998],\n ],\n deuteranopia: [\n [0.367322, 0.860646, -0.227968],\n [0.280085, 0.672501, 0.047413],\n [-0.01182, 0.04294, 0.968881],\n ],\n tritanopia: [\n [1.255528, -0.076749, -0.178779],\n [-0.078411, 0.930809, 0.147602],\n [0.004733, 0.691367, 0.3039],\n ],\n};\n\nconst toLinear = (channel: number) => {\n const value = channel / 255;\n return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;\n};\n\nconst fromLinear = (value: number) => {\n const clamped = Math.min(1, Math.max(0, value));\n return (clamped <= 0.0031308 ? clamped * 12.92 : 1.055 * clamped ** (1 / 2.4) - 0.055) * 255;\n};\n\n/** A color as a person with a color vision deficiency sees it. */\nexport function simulateColorVision(color: Rgb, deficiency: ColorVisionDeficiency): Rgb {\n const linear = [toLinear(color.r), toLinear(color.g), toLinear(color.b)];\n const [r = 0, g = 0, b = 0] = MATRICES[deficiency].map((row) =>\n fromLinear(row.reduce((sum, weight, index) => sum + weight * (linear[index] ?? 0), 0)),\n );\n return { r, g, b };\n}\n\nfunction toLab(color: Rgb): [number, number, number] {\n const [r, g, b] = [toLinear(color.r), toLinear(color.g), toLinear(color.b)];\n const f = (t: number) => (t > 0.008856 ? Math.cbrt(t) : 7.787 * t + 16 / 116);\n const x = f((0.4124 * r + 0.3576 * g + 0.1805 * b) / 0.95047);\n const y = f(0.2126 * r + 0.7152 * g + 0.0722 * b);\n const z = f((0.0193 * r + 0.1192 * g + 0.9505 * b) / 1.08883);\n return [116 * y - 16, 500 * (x - y), 200 * (y - z)];\n}\n\n/** The perceived difference between two colors: the CIE76 distance in CIELAB. */\nexport function colorDifference(first: Rgb, second: Rgb): number {\n const [l1, a1, b1] = toLab(first);\n const [l2, a2, b2] = toLab(second);\n return Math.hypot(l1 - l2, a1 - a2, b1 - b2);\n}\n\n/** Two colors of a palette that look too alike, for everyone or with a deficiency. */\nexport interface ColorDifferenceCheck {\n vision: 'typical' | ColorVisionDeficiency;\n first: string;\n second: string;\n difference: number;\n minimum: number;\n}\n\n/**\n * Checks that the colors of a palette (the categorical colors of charts) stay distinct, for\n * typical vision and under protanopia, deuteranopia and tritanopia: every pair must differ by at\n * least `minimum` (CIE76, 10 by default, a difference anyone notices side by side). Colors Panneau\n * can't read are skipped. Returns the pairs below the minimum.\n */\nexport function checkColorDifferences(\n colors: readonly string[],\n minimum = 10,\n): ColorDifferenceCheck[] {\n const parsed = colors.flatMap((color) => {\n const rgb = parseColor(color);\n return rgb !== null ? [{ color, rgb }] : [];\n });\n const visions = ['typical', 'protanopia', 'deuteranopia', 'tritanopia'] as const;\n return visions.flatMap((vision) => {\n const seen = parsed.map(({ color, rgb }) => ({\n color,\n rgb: vision === 'typical' ? rgb : simulateColorVision(rgb, vision),\n }));\n return seen.flatMap((first, index) =>\n seen.slice(index + 1).flatMap((second) => {\n const difference = Math.round(colorDifference(first.rgb, second.rgb) * 10) / 10;\n return difference < minimum\n ? [{ vision, first: first.color, second: second.color, difference, minimum }]\n : [];\n }),\n );\n });\n}\n"],"mappings":";;;AAMA,IAAM,WAA0E;CAC5E,YAAY;EACR;GAAC;GAAU;GAAU;EAAS;EAC9B;GAAC;GAAU;GAAU;EAAQ;EAC7B;GAAC;GAAW;GAAW;EAAQ;CAAC;CAEpC,cAAc;EACV;GAAC;GAAU;GAAU;EAAS;EAC9B;GAAC;GAAU;GAAU;EAAQ;EAC7B;GAAC;GAAU;GAAS;EAAQ;CAAC;CAEjC,YAAY;EACR;GAAC;GAAU;GAAW;EAAS;EAC/B;GAAC;GAAW;GAAU;EAAQ;EAC9B;GAAC;GAAU;GAAU;EAAM;CAAC;AAEpC;AAEA,IAAM,YAAY,YAAoB;CAClC,MAAM,QAAQ,UAAU;CACxB,OAAO,SAAS,SAAU,QAAQ,UAAU,QAAQ,QAAS,UAAU;AAC3E;AAEA,IAAM,cAAc,UAAkB;CAClC,MAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC;CAC9C,QAAQ,WAAW,WAAY,UAAU,QAAQ,QAAQ,YAAY,IAAI,OAAO,QAAS;AAC7F;;AAGA,SAAgB,oBAAoB,OAAY,YAAwC;CACpF,MAAM,SAAS;EAAC,SAAS,MAAM,CAAC;EAAG,SAAS,MAAM,CAAC;EAAG,SAAS,MAAM,CAAC;CAAC;CACvE,MAAM,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,KAAK,SAAS,WAAW,CAAC,KAAK,QACpD,WAAW,IAAI,QAAQ,KAAK,QAAQ,UAAU,MAAM,UAAU,OAAO,UAAU,IAAI,CAAC,CAAC,CACzF;CACA,OAAO;EAAE;EAAG;EAAG;CAAE;AACrB;AAEA,SAAS,MAAM,OAAsC;CACjD,MAAM,CAAC,GAAG,GAAG,KAAK;EAAC,SAAS,MAAM,CAAC;EAAG,SAAS,MAAM,CAAC;EAAG,SAAS,MAAM,CAAC;CAAC;CAC1E,MAAM,KAAK,MAAe,IAAI,UAAW,KAAK,KAAK,CAAC,IAAI,QAAQ,IAAI,KAAK;CACzE,MAAM,IAAI,GAAG,QAAS,IAAI,QAAS,IAAI,QAAS,KAAK,MAAO;CAC5D,MAAM,IAAI,EAAE,QAAS,IAAI,QAAS,IAAI,QAAS,CAAC;CAChD,MAAM,IAAI,GAAG,QAAS,IAAI,QAAS,IAAI,QAAS,KAAK,OAAO;CAC5D,OAAO;EAAC,MAAM,IAAI;EAAI,OAAO,IAAI;EAAI,OAAO,IAAI;CAAE;AACtD;;AAGA,SAAgB,gBAAgB,OAAY,QAAqB;CAC7D,MAAM,CAAC,IAAI,IAAI,MAAM,MAAM,KAAK;CAChC,MAAM,CAAC,IAAI,IAAI,MAAM,MAAM,MAAM;CACjC,OAAO,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE;AAC/C;;;;;;;AAiBA,SAAgB,sBACZ,QACA,UAAU,IACY;CACtB,MAAM,SAAS,OAAO,SAAS,UAAU;EACrC,MAAM,MAAM,WAAW,KAAK;EAC5B,OAAO,QAAQ,OAAO,CAAC;GAAE;GAAO;EAAI,CAAC,IAAI,CAAA;CAC7C,CAAC;CAED,OAAO;EADU;EAAW;EAAc;EAAgB;CACnD,CAAA,CAAQ,SAAS,WAAW;EAC/B,MAAM,OAAO,OAAO,KAAK,EAAE,OAAO,WAAW;GACzC;GACA,KAAK,WAAW,YAAY,MAAM,oBAAoB,KAAK,MAAM;EACrE,EAAE;EACF,OAAO,KAAK,SAAS,OAAO,UACxB,KAAK,MAAM,QAAQ,CAAC,CAAC,CAAC,SAAS,WAAW;GACtC,MAAM,aAAa,KAAK,MAAM,gBAAgB,MAAM,KAAK,OAAO,GAAG,IAAI,EAAE,IAAI;GAC7E,OAAO,aAAa,UACd,CAAC;IAAE;IAAQ,OAAO,MAAM;IAAO,QAAQ,OAAO;IAAO;IAAY;GAAQ,CAAC,IAC1E,CAAA;EACV,CAAC,CACL;CACJ,CAAC;AACL"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The tokens of one component: CSS variables named `--panneau-<component>-<token>`, with their
3
+ * default values (decision 0024).
4
+ */
5
+ export interface ComponentTokens<Component extends string = string, Name extends string = string> {
6
+ /**
7
+ * The component or the part it styles, as in its `panneau-<component>` class (`button`,
8
+ * `badge`), or a part shared by several components (`input`, `field`, `list-box`, `calendar`).
9
+ */
10
+ readonly component: Component;
11
+ /** Default values, keyed by token name without the leading `--`: `panneau-button-radius`. */
12
+ readonly tokens: Readonly<Record<Name, string>>;
13
+ }
14
+ /**
15
+ * Declares the tokens of a component, as `{ <token>: <default> }`. Each token becomes the CSS
16
+ * variable `--panneau-<component>-<token>`.
17
+ *
18
+ * The component's CSS reads every token with its default as the fallback,
19
+ * `var(--panneau-button-radius, var(--panneau-radius-md))`, and never declares it: a value set by a
20
+ * theme, a scope or any ancestor element then reaches the component, and semantic tokens resolve
21
+ * where the component is. A test checks that the CSS and this declaration agree.
22
+ */
23
+ export declare function defineComponentTokens<const Component extends string, const Tokens extends Record<string, string>>(component: Component, tokens: Tokens): ComponentTokens<Component, `panneau-${Component}-${keyof Tokens & string}`>;
24
+ //# sourceMappingURL=componentTokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"componentTokens.d.ts","sourceRoot":"","sources":["../../src/theme/componentTokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,eAAe,CAAC,SAAS,SAAS,MAAM,GAAG,MAAM,EAAE,IAAI,SAAS,MAAM,GAAG,MAAM;IAC5F;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,6FAA6F;IAC7F,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACjC,KAAK,CAAC,SAAS,SAAS,MAAM,EAC9B,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAE3C,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,GACf,eAAe,CAAC,SAAS,EAAE,WAAW,SAAS,IAAI,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,CAY7E"}
@@ -0,0 +1,20 @@
1
+ //#region src/theme/componentTokens.ts
2
+ /**
3
+ * Declares the tokens of a component, as `{ <token>: <default> }`. Each token becomes the CSS
4
+ * variable `--panneau-<component>-<token>`.
5
+ *
6
+ * The component's CSS reads every token with its default as the fallback,
7
+ * `var(--panneau-button-radius, var(--panneau-radius-md))`, and never declares it: a value set by a
8
+ * theme, a scope or any ancestor element then reaches the component, and semantic tokens resolve
9
+ * where the component is. A test checks that the CSS and this declaration agree.
10
+ */
11
+ function defineComponentTokens(component, tokens) {
12
+ return {
13
+ component,
14
+ tokens: Object.freeze(Object.fromEntries(Object.entries(tokens).map(([name, value]) => [`panneau-${component}-${name}`, value])))
15
+ };
16
+ }
17
+ //#endregion
18
+ export { defineComponentTokens };
19
+
20
+ //# sourceMappingURL=componentTokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"componentTokens.js","names":[],"sources":["../../src/theme/componentTokens.ts"],"sourcesContent":["/**\n * The tokens of one component: CSS variables named `--panneau-<component>-<token>`, with their\n * default values (decision 0024).\n */\nexport interface ComponentTokens<Component extends string = string, Name extends string = string> {\n /**\n * The component or the part it styles, as in its `panneau-<component>` class (`button`,\n * `badge`), or a part shared by several components (`input`, `field`, `list-box`, `calendar`).\n */\n readonly component: Component;\n /** Default values, keyed by token name without the leading `--`: `panneau-button-radius`. */\n readonly tokens: Readonly<Record<Name, string>>;\n}\n\n/**\n * Declares the tokens of a component, as `{ <token>: <default> }`. Each token becomes the CSS\n * variable `--panneau-<component>-<token>`.\n *\n * The component's CSS reads every token with its default as the fallback,\n * `var(--panneau-button-radius, var(--panneau-radius-md))`, and never declares it: a value set by a\n * theme, a scope or any ancestor element then reaches the component, and semantic tokens resolve\n * where the component is. A test checks that the CSS and this declaration agree.\n */\nexport function defineComponentTokens<\n const Component extends string,\n const Tokens extends Record<string, string>,\n>(\n component: Component,\n tokens: Tokens,\n): ComponentTokens<Component, `panneau-${Component}-${keyof Tokens & string}`> {\n return {\n component,\n tokens: Object.freeze(\n Object.fromEntries(\n Object.entries(tokens).map(([name, value]) => [\n `panneau-${component}-${name}`,\n value,\n ]),\n ),\n ) as Record<`panneau-${Component}-${keyof Tokens & string}`, string>,\n };\n}\n"],"mappings":";;;;;;;;;;AAuBA,SAAgB,sBAIZ,WACA,QAC2E;CAC3E,OAAO;EACH;EACA,QAAQ,OAAO,OACX,OAAO,YACH,OAAO,QAAQ,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW,CAC1C,WAAW,UAAS,GAAI,QACxB,KAAK,CACR,CACL,CACJ;CACJ;AACJ"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The component tokens of `@panneau/ui` and their defaults, by component: what a theme, a scope or
3
+ * a project's CSS can set to restyle one component without touching the others (decision 0024).
4
+ */
5
+ export declare const componentTokens: Readonly<{
6
+ alert: Readonly<Record<"panneau-alert-radius" | "panneau-alert-gap" | "panneau-alert-padding-y" | "panneau-alert-padding-x" | "panneau-alert-border-width" | "panneau-alert-title-font-weight", string>>;
7
+ badge: Readonly<Record<"panneau-badge-height" | "panneau-badge-radius" | "panneau-badge-gap" | "panneau-badge-padding-x" | "panneau-badge-border-width" | "panneau-badge-font-size" | "panneau-badge-font-weight", string>>;
8
+ button: Readonly<Record<"panneau-button-radius" | "panneau-button-gap" | "panneau-button-padding-x" | "panneau-button-border-width" | "panneau-button-font-size" | "panneau-button-font-weight" | "panneau-button-padding-x-sm" | "panneau-button-font-size-sm", string>>;
9
+ calendar: Readonly<Record<"panneau-calendar-cell-size" | "panneau-calendar-cell-radius" | "panneau-calendar-selected-color" | "panneau-calendar-selected-bg", string>>;
10
+ card: Readonly<Record<"panneau-card-radius" | "panneau-card-gap" | "panneau-card-padding-y" | "panneau-card-padding-x" | "panneau-card-border-width" | "panneau-card-title-font-weight" | "panneau-card-bg" | "panneau-card-border-color" | "panneau-card-shadow" | "panneau-card-header-padding-y" | "panneau-card-title-font-size", string>>;
11
+ checkbox: Readonly<Record<"panneau-checkbox-size" | "panneau-checkbox-radius" | "panneau-checkbox-bg" | "panneau-checkbox-border-color" | "panneau-checkbox-checked-color" | "panneau-checkbox-checked-bg", string>>;
12
+ container: Readonly<Record<"panneau-container-padding-x" | "panneau-container-width-sm" | "panneau-container-width-md" | "panneau-container-width-lg" | "panneau-container-width-xl", string>>;
13
+ dialog: Readonly<Record<"panneau-dialog-width" | "panneau-dialog-radius" | "panneau-dialog-padding-x" | "panneau-dialog-title-font-weight" | "panneau-dialog-bg" | "panneau-dialog-shadow" | "panneau-dialog-title-font-size" | "panneau-dialog-width-sm" | "panneau-dialog-width-lg" | "panneau-dialog-backdrop", string>>;
14
+ disclosure: Readonly<Record<"panneau-disclosure-gap" | "panneau-disclosure-title-font-weight" | "panneau-disclosure-title-font-size", string>>;
15
+ divider: Readonly<Record<"panneau-divider-color" | "panneau-divider-width", string>>;
16
+ field: Readonly<Record<"panneau-field-gap" | "panneau-field-label-font-size" | "panneau-field-label-font-weight", string>>;
17
+ grid: Readonly<Record<"panneau-grid-gap", string>>;
18
+ heading: Readonly<Record<"panneau-heading-color" | "panneau-heading-font-family" | "panneau-heading-display-font-family" | "panneau-heading-1-font-size" | "panneau-heading-1-font-weight" | "panneau-heading-1-line-height" | "panneau-heading-1-letter-spacing" | "panneau-heading-2-font-size" | "panneau-heading-2-font-weight" | "panneau-heading-2-line-height" | "panneau-heading-2-letter-spacing" | "panneau-heading-3-font-size" | "panneau-heading-3-font-weight" | "panneau-heading-3-line-height" | "panneau-heading-3-letter-spacing" | "panneau-heading-4-font-size" | "panneau-heading-4-font-weight" | "panneau-heading-4-line-height" | "panneau-heading-4-letter-spacing" | "panneau-heading-display-1-font-size" | "panneau-heading-display-1-font-weight" | "panneau-heading-display-1-line-height" | "panneau-heading-display-1-letter-spacing" | "panneau-heading-display-2-font-size" | "panneau-heading-display-2-font-weight" | "panneau-heading-display-2-line-height" | "panneau-heading-display-2-letter-spacing", string>>;
19
+ inline: Readonly<Record<"panneau-inline-gap", string>>;
20
+ input: Readonly<Record<"panneau-input-radius" | "panneau-input-padding-x" | "panneau-input-border-width" | "panneau-input-bg" | "panneau-input-border-color" | "panneau-input-border-color-hover", string>>;
21
+ 'list-box': Readonly<Record<"panneau-list-box-padding" | "panneau-list-box-item-padding-y" | "panneau-list-box-item-padding-x" | "panneau-list-box-item-radius" | "panneau-list-box-item-bg-hover", string>>;
22
+ 'number-input': Readonly<Record<"panneau-number-input-stepper-width", string>>;
23
+ popover: Readonly<Record<"panneau-popover-radius" | "panneau-popover-padding" | "panneau-popover-bg" | "panneau-popover-border-color" | "panneau-popover-shadow", string>>;
24
+ prose: Readonly<Record<"panneau-prose-gap" | "panneau-prose-border-color" | "panneau-prose-line-height" | "panneau-prose-heading-gap" | "panneau-prose-list-indent" | "panneau-prose-link-color" | "panneau-prose-code-font-size" | "panneau-prose-code-color" | "panneau-prose-code-bg" | "panneau-prose-code-radius" | "panneau-prose-quote-border-color" | "panneau-prose-quote-color", string>>;
25
+ radio: Readonly<Record<"panneau-radio-size" | "panneau-radio-bg" | "panneau-radio-border-color" | "panneau-radio-checked-color" | "panneau-radio-checked-border-width", string>>;
26
+ spinner: Readonly<Record<"panneau-spinner-border-width", string>>;
27
+ stack: Readonly<Record<"panneau-stack-gap", string>>;
28
+ switch: Readonly<Record<"panneau-switch-height" | "panneau-switch-width" | "panneau-switch-radius" | "panneau-switch-checked-bg" | "panneau-switch-track-bg" | "panneau-switch-thumb-size" | "panneau-switch-thumb-bg" | "panneau-switch-checked-thumb-bg", string>>;
29
+ tabs: Readonly<Record<"panneau-tabs-gap" | "panneau-tabs-border-color" | "panneau-tabs-tab-padding-x" | "panneau-tabs-tab-font-weight" | "panneau-tabs-tab-color" | "panneau-tabs-indicator-height" | "panneau-tabs-tab-color-selected" | "panneau-tabs-indicator-color", string>>;
30
+ text: Readonly<Record<"panneau-text-muted-color", string>>;
31
+ toast: Readonly<Record<"panneau-toast-width" | "panneau-toast-radius" | "panneau-toast-bg" | "panneau-toast-border-color" | "panneau-toast-shadow" | "panneau-toast-tone-width", string>>;
32
+ tooltip: Readonly<Record<"panneau-tooltip-color" | "panneau-tooltip-radius" | "panneau-tooltip-padding-y" | "panneau-tooltip-padding-x" | "panneau-tooltip-font-size" | "panneau-tooltip-bg", string>>;
33
+ }>;
34
+ /** The name of a component token of `@panneau/ui`, without the leading `--`. */
35
+ export type ComponentTokenName = {
36
+ [Component in keyof typeof componentTokens]: keyof (typeof componentTokens)[Component];
37
+ }[keyof typeof componentTokens];
38
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/theme/components.ts"],"names":[],"mappings":"AA4BA;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4B1B,CAAC;AAEH,gFAAgF;AAChF,MAAM,MAAM,kBAAkB,GAAG;KAC5B,SAAS,IAAI,MAAM,OAAO,eAAe,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC,SAAS,CAAC;CACzF,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC"}
@@ -0,0 +1,65 @@
1
+ import { alertTokens } from "../alert/tokens.js";
2
+ import { badgeTokens } from "../badge/tokens.js";
3
+ import { buttonTokens } from "../button/tokens.js";
4
+ import { cardTokens } from "../card/tokens.js";
5
+ import { checkboxTokens } from "../checkbox/tokens.js";
6
+ import { containerTokens } from "../container/tokens.js";
7
+ import { calendarTokens } from "../date-picker/calendarTokens.js";
8
+ import { dialogTokens } from "../dialog/tokens.js";
9
+ import { disclosureTokens } from "../disclosure/tokens.js";
10
+ import { dividerTokens } from "../divider/tokens.js";
11
+ import { inputTokens } from "../field/inputTokens.js";
12
+ import { fieldTokens } from "../field/tokens.js";
13
+ import { gridTokens } from "../grid/tokens.js";
14
+ import { headingTokens } from "../heading/tokens.js";
15
+ import { inlineTokens } from "../inline/tokens.js";
16
+ import { numberInputTokens } from "../number-input/tokens.js";
17
+ import { popoverTokens } from "../popover/tokens.js";
18
+ import { proseTokens } from "../prose/tokens.js";
19
+ import { radioTokens } from "../radio-group/tokens.js";
20
+ import { listBoxTokens } from "../select/listBoxTokens.js";
21
+ import { spinnerTokens } from "../spinner/tokens.js";
22
+ import { stackTokens } from "../stack/tokens.js";
23
+ import { switchTokens } from "../switch/tokens.js";
24
+ import { tabsTokens } from "../tabs/tokens.js";
25
+ import { textTokens } from "../text/tokens.js";
26
+ import { toastTokens } from "../toast/tokens.js";
27
+ import { tooltipTokens } from "../tooltip/tokens.js";
28
+ //#region src/theme/components.ts
29
+ /**
30
+ * The component tokens of `@panneau/ui` and their defaults, by component: what a theme, a scope or
31
+ * a project's CSS can set to restyle one component without touching the others (decision 0024).
32
+ */
33
+ var componentTokens = Object.freeze({
34
+ alert: alertTokens.tokens,
35
+ badge: badgeTokens.tokens,
36
+ button: buttonTokens.tokens,
37
+ calendar: calendarTokens.tokens,
38
+ card: cardTokens.tokens,
39
+ checkbox: checkboxTokens.tokens,
40
+ container: containerTokens.tokens,
41
+ dialog: dialogTokens.tokens,
42
+ disclosure: disclosureTokens.tokens,
43
+ divider: dividerTokens.tokens,
44
+ field: fieldTokens.tokens,
45
+ grid: gridTokens.tokens,
46
+ heading: headingTokens.tokens,
47
+ inline: inlineTokens.tokens,
48
+ input: inputTokens.tokens,
49
+ "list-box": listBoxTokens.tokens,
50
+ "number-input": numberInputTokens.tokens,
51
+ popover: popoverTokens.tokens,
52
+ prose: proseTokens.tokens,
53
+ radio: radioTokens.tokens,
54
+ spinner: spinnerTokens.tokens,
55
+ stack: stackTokens.tokens,
56
+ switch: switchTokens.tokens,
57
+ tabs: tabsTokens.tokens,
58
+ text: textTokens.tokens,
59
+ toast: toastTokens.tokens,
60
+ tooltip: tooltipTokens.tokens
61
+ });
62
+ //#endregion
63
+ export { componentTokens };
64
+
65
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","names":[],"sources":["../../src/theme/components.ts"],"sourcesContent":["import { alertTokens } from '../alert/tokens';\nimport { badgeTokens } from '../badge/tokens';\nimport { buttonTokens } from '../button/tokens';\nimport { cardTokens } from '../card/tokens';\nimport { checkboxTokens } from '../checkbox/tokens';\nimport { containerTokens } from '../container/tokens';\nimport { calendarTokens } from '../date-picker/calendarTokens';\nimport { dialogTokens } from '../dialog/tokens';\nimport { disclosureTokens } from '../disclosure/tokens';\nimport { dividerTokens } from '../divider/tokens';\nimport { inputTokens } from '../field/inputTokens';\nimport { fieldTokens } from '../field/tokens';\nimport { gridTokens } from '../grid/tokens';\nimport { headingTokens } from '../heading/tokens';\nimport { inlineTokens } from '../inline/tokens';\nimport { numberInputTokens } from '../number-input/tokens';\nimport { popoverTokens } from '../popover/tokens';\nimport { proseTokens } from '../prose/tokens';\nimport { radioTokens } from '../radio-group/tokens';\nimport { listBoxTokens } from '../select/listBoxTokens';\nimport { spinnerTokens } from '../spinner/tokens';\nimport { stackTokens } from '../stack/tokens';\nimport { switchTokens } from '../switch/tokens';\nimport { tabsTokens } from '../tabs/tokens';\nimport { textTokens } from '../text/tokens';\nimport { toastTokens } from '../toast/tokens';\nimport { tooltipTokens } from '../tooltip/tokens';\n\n/**\n * The component tokens of `@panneau/ui` and their defaults, by component: what a theme, a scope or\n * a project's CSS can set to restyle one component without touching the others (decision 0024).\n */\nexport const componentTokens = Object.freeze({\n alert: alertTokens.tokens,\n badge: badgeTokens.tokens,\n button: buttonTokens.tokens,\n calendar: calendarTokens.tokens,\n card: cardTokens.tokens,\n checkbox: checkboxTokens.tokens,\n container: containerTokens.tokens,\n dialog: dialogTokens.tokens,\n disclosure: disclosureTokens.tokens,\n divider: dividerTokens.tokens,\n field: fieldTokens.tokens,\n grid: gridTokens.tokens,\n heading: headingTokens.tokens,\n inline: inlineTokens.tokens,\n input: inputTokens.tokens,\n 'list-box': listBoxTokens.tokens,\n 'number-input': numberInputTokens.tokens,\n popover: popoverTokens.tokens,\n prose: proseTokens.tokens,\n radio: radioTokens.tokens,\n spinner: spinnerTokens.tokens,\n stack: stackTokens.tokens,\n switch: switchTokens.tokens,\n tabs: tabsTokens.tokens,\n text: textTokens.tokens,\n toast: toastTokens.tokens,\n tooltip: tooltipTokens.tokens,\n});\n\n/** The name of a component token of `@panneau/ui`, without the leading `--`. */\nexport type ComponentTokenName = {\n [Component in keyof typeof componentTokens]: keyof (typeof componentTokens)[Component];\n}[keyof typeof componentTokens];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,kBAAkB,OAAO,OAAO;CACzC,OAAO,YAAY;CACnB,OAAO,YAAY;CACnB,QAAQ,aAAa;CACrB,UAAU,eAAe;CACzB,MAAM,WAAW;CACjB,UAAU,eAAe;CACzB,WAAW,gBAAgB;CAC3B,QAAQ,aAAa;CACrB,YAAY,iBAAiB;CAC7B,SAAS,cAAc;CACvB,OAAO,YAAY;CACnB,MAAM,WAAW;CACjB,SAAS,cAAc;CACvB,QAAQ,aAAa;CACrB,OAAO,YAAY;CACnB,YAAY,cAAc;CAC1B,gBAAgB,kBAAkB;CAClC,SAAS,cAAc;CACvB,OAAO,YAAY;CACnB,OAAO,YAAY;CACnB,SAAS,cAAc;CACvB,OAAO,YAAY;CACnB,QAAQ,aAAa;CACrB,MAAM,WAAW;CACjB,MAAM,WAAW;CACjB,OAAO,YAAY;CACnB,SAAS,cAAc;AAC3B,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { type ComponentTokenName } from './components';
2
+ import type { ThemeFont } from './fonts';
3
+ import { type SemanticTokenName } from './semanticTokens';
4
+ import type { Density, Theme } from './theme';
5
+ import type { ToneInput } from './tones';
6
+ /**
7
+ * Tokens that a project adds, such as those of its own components: declare them here so that
8
+ * `defineTheme()` accepts them.
9
+ *
10
+ * ```ts
11
+ * declare module '@panneau/ui' {
12
+ * interface PanneauTokens {
13
+ * 'panneau-map-marker-color': true;
14
+ * }
15
+ * }
16
+ * ```
17
+ */
18
+ export interface PanneauTokens {
19
+ }
20
+ /** The variable of a palette color: `panneau-palette-orange`. */
21
+ export type PaletteTokenName = `panneau-palette-${string}`;
22
+ /**
23
+ * The name of a token a theme can set, without the leading `--`: a semantic token, a component
24
+ * token, a palette color, or a token declared in `PanneauTokens`.
25
+ */
26
+ export type TokenName = SemanticTokenName | ComponentTokenName | PaletteTokenName | (keyof PanneauTokens & string);
27
+ /** Values of tokens, keyed by their name: only known names type-check. */
28
+ export type ThemeTokens = {
29
+ [Name in SemanticTokenName | ComponentTokenName | (keyof PanneauTokens & string)]?: string;
30
+ } & {
31
+ [Name in PaletteTokenName]?: string;
32
+ };
33
+ /** A theme as `defineTheme()` takes it: like `Theme`, with typed tokens and `extends`. */
34
+ export interface ThemeDefinition {
35
+ /** A name for theme pickers. */
36
+ label?: string;
37
+ /** Themes this one builds on, in order: its own values override theirs. */
38
+ extends?: Theme | readonly Theme[];
39
+ /** Tokens of the light scheme, or of both schemes when `dark` does not set them. */
40
+ tokens?: ThemeTokens;
41
+ /** Tokens that change in the dark scheme. */
42
+ dark?: ThemeTokens;
43
+ /** Raw colors, used with `var(--panneau-palette-<name>)`. */
44
+ palette?: Record<string, string>;
45
+ /** Tones added or redefined by the theme. Declare added tones in `PanneauTones`. */
46
+ tones?: Record<string, ToneInput>;
47
+ /** Named variants of components. Declare them in `BadgeVariants` (and the like). */
48
+ components?: Record<string, {
49
+ variants?: Record<string, ThemeTokens>;
50
+ }>;
51
+ /** Tokens of each density, which change with the density of the root. */
52
+ densities?: Partial<Record<Exclude<Density, 'auto'>, ThemeTokens>>;
53
+ /** Font faces and font stylesheets. */
54
+ fonts?: ThemeFont[];
55
+ }
56
+ /**
57
+ * Merges themes, in order: each one overrides the tokens, palette colors, tones and variants of
58
+ * those before it. A token a theme sets in `tokens` but not in `dark` applies to both schemes, so it
59
+ * also replaces the dark value of earlier themes. Variants merge token by token; tones are replaced
60
+ * whole; densities merge token by token; fonts add up. The label is the last one set. Same as `mergeThemes()` of `@panneau/protocol`.
61
+ */
62
+ export declare function mergeThemes(...themes: readonly Partial<Theme>[]): Theme;
63
+ /**
64
+ * Tokens of a theme (in its tokens, dark tokens, densities and variants) that Panneau doesn't know although they are in its namespaces
65
+ * (`panneau-color-*`, `panneau-button-*`…): most likely typos. Tokens of a project's own components
66
+ * are outside these namespaces, and palette colors are always accepted.
67
+ */
68
+ export declare function findUnknownTokens(theme: Theme): string[];
69
+ /**
70
+ * Declares a theme: TypeScript checks the names of its tokens, and `extends` builds it on other
71
+ * themes (`bootstrapTheme`, a shared brand theme), whose values its own override. It returns a
72
+ * plain `Theme`, which `PanneauRoot`, plugins and JSON files all take. Tokens that Panneau doesn't
73
+ * know in its own namespaces, most likely typos, are reported in the console.
74
+ *
75
+ * ```ts
76
+ * const brand = defineTheme({
77
+ * palette: { orange: '#f25c05' },
78
+ * tokens: { 'panneau-color-accent': 'var(--panneau-palette-orange)' },
79
+ * tones: { signal: 'var(--panneau-palette-orange)' },
80
+ * });
81
+ * const compact = defineTheme({ extends: brand, tokens: { 'panneau-control-height': '2rem' } });
82
+ * ```
83
+ */
84
+ export declare function defineTheme(definition: ThemeDefinition): Theme;
85
+ //# sourceMappingURL=defineTheme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defineTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defineTheme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAmB,MAAM,cAAc,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,aAAa;CAAG;AAEjC,iEAAiE;AACjE,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,MAAM,EAAE,CAAC;AAE3D;;;GAGG;AACH,MAAM,MAAM,SAAS,GACjB,iBAAiB,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC;AAE/F,0EAA0E;AAC1E,MAAM,MAAM,WAAW,GAAG;KACrB,IAAI,IAAI,iBAAiB,GAAG,kBAAkB,GAAG,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM;CAC7F,GAAG;KAAG,IAAI,IAAI,gBAAgB,CAAC,CAAC,EAAE,MAAM;CAAE,CAAC;AAE5C,0FAA0F;AAC1F,MAAM,WAAW,eAAe;IAC5B,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,OAAO,CAAC,EAAE,KAAK,GAAG,SAAS,KAAK,EAAE,CAAC;IACnC,oFAAoF;IACpF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;KAAE,CAAC,CAAC;IACxE,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;IACnE,uCAAuC;IACvC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;CACvB;AAmED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,MAAM,EAAE,SAAS,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,CAgCvE;AAgBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAmBxD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,eAAe,GAAG,KAAK,CAY9D"}
@@ -0,0 +1,130 @@
1
+ import { componentTokens } from "./components.js";
2
+ import { SEMANTIC_TOKENS } from "./semanticTokens.js";
3
+ //#region src/theme/defineTheme.ts
4
+ function mergeRecords(first, second) {
5
+ return first === void 0 && second === void 0 ? void 0 : {
6
+ ...first,
7
+ ...second
8
+ };
9
+ }
10
+ function mergeComponents(first, second) {
11
+ const components = mergeRecords(first, second);
12
+ if (components === void 0) return;
13
+ return Object.fromEntries(Object.keys(components).map((component) => {
14
+ const before = first?.[component];
15
+ const after = second?.[component];
16
+ const variants = mergeRecords(before?.variants, after?.variants);
17
+ return [component, {
18
+ ...before,
19
+ ...after,
20
+ ...variants !== void 0 && { variants: Object.fromEntries(Object.keys(variants).map((name) => [name, {
21
+ ...before?.variants?.[name],
22
+ ...after?.variants?.[name]
23
+ }])) }
24
+ }];
25
+ }));
26
+ }
27
+ var DENSITIES = [
28
+ "compact",
29
+ "comfortable",
30
+ "touch"
31
+ ];
32
+ function mergeDensities(first, second) {
33
+ if (first === void 0 && second === void 0) return;
34
+ const densities = {
35
+ ...first,
36
+ ...second
37
+ };
38
+ DENSITIES.forEach((density) => {
39
+ if (first?.[density] !== void 0 && second?.[density] !== void 0) densities[density] = {
40
+ ...first[density],
41
+ ...second[density]
42
+ };
43
+ });
44
+ return densities;
45
+ }
46
+ function mergeFonts(first, second) {
47
+ if (first === void 0 && second === void 0) return;
48
+ const fonts = [...first ?? [], ...second ?? []];
49
+ return fonts.filter((font, index) => fonts.findIndex((other) => JSON.stringify(other) === JSON.stringify(font)) === index);
50
+ }
51
+ /**
52
+ * Merges themes, in order: each one overrides the tokens, palette colors, tones and variants of
53
+ * those before it. A token a theme sets in `tokens` but not in `dark` applies to both schemes, so it
54
+ * also replaces the dark value of earlier themes. Variants merge token by token; tones are replaced
55
+ * whole; densities merge token by token; fonts add up. The label is the last one set. Same as `mergeThemes()` of `@panneau/protocol`.
56
+ */
57
+ function mergeThemes(...themes) {
58
+ return themes.reduce((merged, theme) => {
59
+ const tokens = theme.tokens ?? {};
60
+ const dark = mergeRecords(merged.dark !== void 0 ? Object.fromEntries(Object.entries(merged.dark).filter(([name]) => !Object.hasOwn(tokens, name))) : void 0, theme.dark);
61
+ const result = {
62
+ ...merged,
63
+ ...theme,
64
+ label: theme.label ?? merged.label,
65
+ tokens: {
66
+ ...merged.tokens,
67
+ ...tokens
68
+ },
69
+ dark: dark !== void 0 && Object.keys(dark).length > 0 ? dark : void 0,
70
+ palette: mergeRecords(merged.palette, theme.palette),
71
+ tones: mergeRecords(merged.tones, theme.tones),
72
+ components: mergeComponents(merged.components, theme.components),
73
+ densities: mergeDensities(merged.densities, theme.densities),
74
+ fonts: mergeFonts(merged.fonts, theme.fonts)
75
+ };
76
+ return Object.fromEntries(Object.entries(result).filter(([, value]) => value !== void 0));
77
+ }, { tokens: {} });
78
+ }
79
+ /** The first segments of the semantic tokens, and the components: names Panneau owns. */
80
+ var NAMESPACES = [.../* @__PURE__ */ new Set([
81
+ ...SEMANTIC_TOKENS.map((name) => name.split("-")[1]),
82
+ ...Object.keys(componentTokens),
83
+ "tone"
84
+ ])];
85
+ var KNOWN_TOKENS = /* @__PURE__ */ new Set([...SEMANTIC_TOKENS, ...Object.values(componentTokens).flatMap((tokens) => Object.keys(tokens))]);
86
+ /**
87
+ * Tokens of a theme (in its tokens, dark tokens, densities and variants) that Panneau doesn't know although they are in its namespaces
88
+ * (`panneau-color-*`, `panneau-button-*`…): most likely typos. Tokens of a project's own components
89
+ * are outside these namespaces, and palette colors are always accepted.
90
+ */
91
+ function findUnknownTokens(theme) {
92
+ const names = [
93
+ ...Object.keys(theme.tokens),
94
+ ...Object.keys(theme.dark ?? {}),
95
+ ...Object.values(theme.densities ?? {}).flatMap((tokens) => Object.keys(tokens)),
96
+ ...Object.values(theme.components ?? {}).flatMap(({ variants = {} }) => Object.values(variants).flatMap((tokens) => Object.keys(tokens)))
97
+ ];
98
+ return [...new Set(names.filter((name) => !KNOWN_TOKENS.has(name) && !name.startsWith("panneau-palette-") && NAMESPACES.some((namespace) => name.startsWith(`panneau-${namespace}-`))))];
99
+ }
100
+ /**
101
+ * Declares a theme: TypeScript checks the names of its tokens, and `extends` builds it on other
102
+ * themes (`bootstrapTheme`, a shared brand theme), whose values its own override. It returns a
103
+ * plain `Theme`, which `PanneauRoot`, plugins and JSON files all take. Tokens that Panneau doesn't
104
+ * know in its own namespaces, most likely typos, are reported in the console.
105
+ *
106
+ * ```ts
107
+ * const brand = defineTheme({
108
+ * palette: { orange: '#f25c05' },
109
+ * tokens: { 'panneau-color-accent': 'var(--panneau-palette-orange)' },
110
+ * tones: { signal: 'var(--panneau-palette-orange)' },
111
+ * });
112
+ * const compact = defineTheme({ extends: brand, tokens: { 'panneau-control-height': '2rem' } });
113
+ * ```
114
+ */
115
+ function defineTheme(definition) {
116
+ const { extends: extended = [], ...own } = definition;
117
+ const bases = Array.isArray(extended) ? extended : [extended];
118
+ const ownTheme = {
119
+ ...own,
120
+ tokens: own.tokens ?? {}
121
+ };
122
+ const theme = mergeThemes(...bases, ownTheme);
123
+ const unknown = findUnknownTokens(ownTheme);
124
+ if (unknown.length > 0) console.warn(`[panneau] Unknown tokens in theme${theme.label !== void 0 ? ` "${theme.label}"` : ""}: ${unknown.join(", ")}.`);
125
+ return theme;
126
+ }
127
+ //#endregion
128
+ export { defineTheme, findUnknownTokens, mergeThemes };
129
+
130
+ //# sourceMappingURL=defineTheme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defineTheme.js","names":[],"sources":["../../src/theme/defineTheme.ts"],"sourcesContent":["import { type ComponentTokenName, componentTokens } from './components';\nimport type { ThemeFont } from './fonts';\nimport { SEMANTIC_TOKENS, type SemanticTokenName } from './semanticTokens';\nimport type { Density, Theme } from './theme';\nimport type { ToneInput } from './tones';\n\n/**\n * Tokens that a project adds, such as those of its own components: declare them here so that\n * `defineTheme()` accepts them.\n *\n * ```ts\n * declare module '@panneau/ui' {\n * interface PanneauTokens {\n * 'panneau-map-marker-color': true;\n * }\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- extended by projects\nexport interface PanneauTokens {}\n\n/** The variable of a palette color: `panneau-palette-orange`. */\nexport type PaletteTokenName = `panneau-palette-${string}`;\n\n/**\n * The name of a token a theme can set, without the leading `--`: a semantic token, a component\n * token, a palette color, or a token declared in `PanneauTokens`.\n */\nexport type TokenName =\n SemanticTokenName | ComponentTokenName | PaletteTokenName | (keyof PanneauTokens & string);\n\n/** Values of tokens, keyed by their name: only known names type-check. */\nexport type ThemeTokens = {\n [Name in SemanticTokenName | ComponentTokenName | (keyof PanneauTokens & string)]?: string;\n} & { [Name in PaletteTokenName]?: string };\n\n/** A theme as `defineTheme()` takes it: like `Theme`, with typed tokens and `extends`. */\nexport interface ThemeDefinition {\n /** A name for theme pickers. */\n label?: string;\n /** Themes this one builds on, in order: its own values override theirs. */\n extends?: Theme | readonly Theme[];\n /** Tokens of the light scheme, or of both schemes when `dark` does not set them. */\n tokens?: ThemeTokens;\n /** Tokens that change in the dark scheme. */\n dark?: ThemeTokens;\n /** Raw colors, used with `var(--panneau-palette-<name>)`. */\n palette?: Record<string, string>;\n /** Tones added or redefined by the theme. Declare added tones in `PanneauTones`. */\n tones?: Record<string, ToneInput>;\n /** Named variants of components. Declare them in `BadgeVariants` (and the like). */\n components?: Record<string, { variants?: Record<string, ThemeTokens> }>;\n /** Tokens of each density, which change with the density of the root. */\n densities?: Partial<Record<Exclude<Density, 'auto'>, ThemeTokens>>;\n /** Font faces and font stylesheets. */\n fonts?: ThemeFont[];\n}\n\nfunction mergeRecords<T>(\n first: Readonly<Record<string, T>> | undefined,\n second: Readonly<Record<string, T>> | undefined,\n): Record<string, T> | undefined {\n return first === undefined && second === undefined ? undefined : { ...first, ...second };\n}\n\nfunction mergeComponents(\n first: Theme['components'],\n second: Theme['components'],\n): Theme['components'] {\n const components = mergeRecords(first, second);\n if (components === undefined) {\n return undefined;\n }\n return Object.fromEntries(\n Object.keys(components).map((component) => {\n const before = first?.[component];\n const after = second?.[component];\n const variants = mergeRecords(before?.variants, after?.variants);\n return [\n component,\n {\n ...before,\n ...after,\n ...(variants !== undefined && {\n variants: Object.fromEntries(\n Object.keys(variants).map((name) => [\n name,\n { ...before?.variants?.[name], ...after?.variants?.[name] },\n ]),\n ),\n }),\n },\n ];\n }),\n );\n}\n\nconst DENSITIES = ['compact', 'comfortable', 'touch'] as const;\n\nfunction mergeDensities(first: Theme['densities'], second: Theme['densities']): Theme['densities'] {\n if (first === undefined && second === undefined) {\n return undefined;\n }\n const densities = { ...first, ...second };\n DENSITIES.forEach((density) => {\n if (first?.[density] !== undefined && second?.[density] !== undefined) {\n densities[density] = { ...first[density], ...second[density] };\n }\n });\n return densities;\n}\n\nfunction mergeFonts(first: Theme['fonts'], second: Theme['fonts']): Theme['fonts'] {\n if (first === undefined && second === undefined) {\n return undefined;\n }\n const fonts = [...(first ?? []), ...(second ?? [])];\n return fonts.filter(\n (font, index) =>\n fonts.findIndex((other) => JSON.stringify(other) === JSON.stringify(font)) === index,\n );\n}\n\n/**\n * Merges themes, in order: each one overrides the tokens, palette colors, tones and variants of\n * those before it. A token a theme sets in `tokens` but not in `dark` applies to both schemes, so it\n * also replaces the dark value of earlier themes. Variants merge token by token; tones are replaced\n * whole; densities merge token by token; fonts add up. The label is the last one set. Same as `mergeThemes()` of `@panneau/protocol`.\n */\nexport function mergeThemes(...themes: readonly Partial<Theme>[]): Theme {\n return themes.reduce<Theme>(\n (merged, theme) => {\n const tokens = theme.tokens ?? {};\n const dark = mergeRecords(\n merged.dark !== undefined\n ? Object.fromEntries(\n Object.entries(merged.dark).filter(\n ([name]) => !Object.hasOwn(tokens, name),\n ),\n )\n : undefined,\n theme.dark,\n );\n const result: Theme = {\n ...merged,\n ...theme,\n label: theme.label ?? merged.label,\n tokens: { ...merged.tokens, ...tokens },\n dark: dark !== undefined && Object.keys(dark).length > 0 ? dark : undefined,\n palette: mergeRecords(merged.palette, theme.palette),\n tones: mergeRecords(merged.tones, theme.tones),\n components: mergeComponents(merged.components, theme.components),\n densities: mergeDensities(merged.densities, theme.densities),\n fonts: mergeFonts(merged.fonts, theme.fonts),\n };\n return Object.fromEntries(\n Object.entries(result).filter(([, value]) => value !== undefined),\n ) as unknown as Theme;\n },\n { tokens: {} },\n );\n}\n\n/** The first segments of the semantic tokens, and the components: names Panneau owns. */\nconst NAMESPACES = [\n ...new Set([\n ...SEMANTIC_TOKENS.map((name) => name.split('-')[1]),\n ...Object.keys(componentTokens),\n 'tone',\n ]),\n];\n\nconst KNOWN_TOKENS = new Set<string>([\n ...SEMANTIC_TOKENS,\n ...Object.values(componentTokens).flatMap((tokens) => Object.keys(tokens)),\n]);\n\n/**\n * Tokens of a theme (in its tokens, dark tokens, densities and variants) that Panneau doesn't know although they are in its namespaces\n * (`panneau-color-*`, `panneau-button-*`…): most likely typos. Tokens of a project's own components\n * are outside these namespaces, and palette colors are always accepted.\n */\nexport function findUnknownTokens(theme: Theme): string[] {\n const names = [\n ...Object.keys(theme.tokens),\n ...Object.keys(theme.dark ?? {}),\n ...Object.values(theme.densities ?? {}).flatMap((tokens) => Object.keys(tokens)),\n ...Object.values(theme.components ?? {}).flatMap(({ variants = {} }) =>\n Object.values(variants).flatMap((tokens) => Object.keys(tokens)),\n ),\n ];\n return [\n ...new Set(\n names.filter(\n (name) =>\n !KNOWN_TOKENS.has(name) &&\n !name.startsWith('panneau-palette-') &&\n NAMESPACES.some((namespace) => name.startsWith(`panneau-${namespace}-`)),\n ),\n ),\n ];\n}\n\n/**\n * Declares a theme: TypeScript checks the names of its tokens, and `extends` builds it on other\n * themes (`bootstrapTheme`, a shared brand theme), whose values its own override. It returns a\n * plain `Theme`, which `PanneauRoot`, plugins and JSON files all take. Tokens that Panneau doesn't\n * know in its own namespaces, most likely typos, are reported in the console.\n *\n * ```ts\n * const brand = defineTheme({\n * palette: { orange: '#f25c05' },\n * tokens: { 'panneau-color-accent': 'var(--panneau-palette-orange)' },\n * tones: { signal: 'var(--panneau-palette-orange)' },\n * });\n * const compact = defineTheme({ extends: brand, tokens: { 'panneau-control-height': '2rem' } });\n * ```\n */\nexport function defineTheme(definition: ThemeDefinition): Theme {\n const { extends: extended = [], ...own } = definition;\n const bases: readonly Theme[] = Array.isArray(extended) ? extended : [extended as Theme];\n const ownTheme = { ...own, tokens: own.tokens ?? {} } as Theme;\n const theme = mergeThemes(...bases, ownTheme);\n const unknown = findUnknownTokens(ownTheme);\n if (unknown.length > 0) {\n console.warn(\n `[panneau] Unknown tokens in theme${theme.label !== undefined ? ` \"${theme.label}\"` : ''}: ${unknown.join(', ')}.`,\n );\n }\n return theme;\n}\n"],"mappings":"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"}