@panneau/ui 5.0.0-alpha.0 → 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 (388) hide show
  1. package/README.md +280 -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/namedIcons.d.ts +16 -0
  156. package/dist/icon/namedIcons.d.ts.map +1 -0
  157. package/dist/icon/namedIcons.js +90 -0
  158. package/dist/icon/namedIcons.js.map +1 -0
  159. package/dist/icon-button/IconButton.css +2 -2
  160. package/dist/icon-button/IconButton.d.ts +1 -1
  161. package/dist/icon-button/IconButton.d.ts.map +1 -1
  162. package/dist/icon-button/IconButton.js +3 -3
  163. package/dist/icon-button/IconButton.js.map +1 -1
  164. package/dist/icon-button/IconButton.module.js +2 -2
  165. package/dist/index.d.ts +26 -5
  166. package/dist/index.d.ts.map +1 -1
  167. package/dist/index.js +21 -2
  168. package/dist/inline/Inline.css +142 -0
  169. package/dist/inline/Inline.d.ts +17 -0
  170. package/dist/inline/Inline.d.ts.map +1 -0
  171. package/dist/inline/Inline.js +21 -0
  172. package/dist/inline/Inline.js.map +1 -0
  173. package/dist/inline/Inline.module.js +12 -0
  174. package/dist/inline/Inline.module.js.map +1 -0
  175. package/dist/inline/tokens.d.ts +3 -0
  176. package/dist/inline/tokens.d.ts.map +1 -0
  177. package/dist/inline/tokens.js +10 -0
  178. package/dist/inline/tokens.js.map +1 -0
  179. package/dist/layout/responsive.d.ts +38 -0
  180. package/dist/layout/responsive.d.ts.map +1 -0
  181. package/dist/layout/responsive.js +49 -0
  182. package/dist/layout/responsive.js.map +1 -0
  183. package/dist/menu/Menu.js +2 -2
  184. package/dist/menu/Menu.js.map +1 -1
  185. package/dist/number-input/NumberInput.css +12 -12
  186. package/dist/number-input/NumberInput.js +1 -1
  187. package/dist/number-input/NumberInput.js.map +1 -1
  188. package/dist/number-input/NumberInput.module.js +4 -4
  189. package/dist/number-input/NumberInput.module.js.map +1 -1
  190. package/dist/number-input/tokens.d.ts +3 -0
  191. package/dist/number-input/tokens.d.ts.map +1 -0
  192. package/dist/number-input/tokens.js +10 -0
  193. package/dist/number-input/tokens.js.map +1 -0
  194. package/dist/popover/Popover.css +13 -12
  195. package/dist/popover/Popover.js +2 -2
  196. package/dist/popover/Popover.js.map +1 -1
  197. package/dist/popover/Popover.module.js +3 -3
  198. package/dist/popover/Popover.module.js.map +1 -1
  199. package/dist/popover/tokens.d.ts +3 -0
  200. package/dist/popover/tokens.d.ts.map +1 -0
  201. package/dist/popover/tokens.js +19 -0
  202. package/dist/popover/tokens.js.map +1 -0
  203. package/dist/prose/Prose.css +141 -0
  204. package/dist/prose/Prose.d.ts +11 -0
  205. package/dist/prose/Prose.d.ts.map +1 -0
  206. package/dist/prose/Prose.js +18 -0
  207. package/dist/prose/Prose.js.map +1 -0
  208. package/dist/prose/Prose.module.js +8 -0
  209. package/dist/prose/Prose.module.js.map +1 -0
  210. package/dist/prose/tokens.d.ts +3 -0
  211. package/dist/prose/tokens.d.ts.map +1 -0
  212. package/dist/prose/tokens.js +33 -0
  213. package/dist/prose/tokens.js.map +1 -0
  214. package/dist/radio-group/RadioGroup.css +21 -20
  215. package/dist/radio-group/RadioGroup.d.ts.map +1 -1
  216. package/dist/radio-group/RadioGroup.js +2 -2
  217. package/dist/radio-group/RadioGroup.js.map +1 -1
  218. package/dist/radio-group/RadioGroup.module.js +6 -6
  219. package/dist/radio-group/RadioGroup.module.js.map +1 -1
  220. package/dist/radio-group/tokens.d.ts +3 -0
  221. package/dist/radio-group/tokens.d.ts.map +1 -0
  222. package/dist/radio-group/tokens.js +19 -0
  223. package/dist/radio-group/tokens.js.map +1 -0
  224. package/dist/root/PanneauRoot.css +243 -20
  225. package/dist/root/PanneauRoot.d.ts +28 -4
  226. package/dist/root/PanneauRoot.d.ts.map +1 -1
  227. package/dist/root/PanneauRoot.js +104 -21
  228. package/dist/root/PanneauRoot.js.map +1 -1
  229. package/dist/root/PanneauRoot.module.js +11 -3
  230. package/dist/root/PanneauRoot.module.js.map +1 -1
  231. package/dist/root/ThemeScope.d.ts +24 -0
  232. package/dist/root/ThemeScope.d.ts.map +1 -0
  233. package/dist/root/ThemeScope.js +49 -0
  234. package/dist/root/ThemeScope.js.map +1 -0
  235. package/dist/select/ListBox.css +23 -22
  236. package/dist/select/ListBox.module.js +12 -12
  237. package/dist/select/ListBox.module.js.map +1 -1
  238. package/dist/select/Select.js +1 -1
  239. package/dist/select/Select.js.map +1 -1
  240. package/dist/select/listBoxTokens.d.ts +3 -0
  241. package/dist/select/listBoxTokens.d.ts.map +1 -0
  242. package/dist/select/listBoxTokens.js +19 -0
  243. package/dist/select/listBoxTokens.js.map +1 -0
  244. package/dist/spinner/Spinner.css +8 -8
  245. package/dist/spinner/Spinner.js +1 -1
  246. package/dist/spinner/Spinner.js.map +1 -1
  247. package/dist/spinner/Spinner.module.js +5 -5
  248. package/dist/spinner/Spinner.module.js.map +1 -1
  249. package/dist/spinner/tokens.d.ts +3 -0
  250. package/dist/spinner/tokens.d.ts.map +1 -0
  251. package/dist/spinner/tokens.js +10 -0
  252. package/dist/spinner/tokens.js.map +1 -0
  253. package/dist/stack/Stack.css +135 -0
  254. package/dist/stack/Stack.d.ts +15 -0
  255. package/dist/stack/Stack.d.ts.map +1 -0
  256. package/dist/stack/Stack.js +21 -0
  257. package/dist/stack/Stack.js.map +1 -0
  258. package/dist/stack/Stack.module.js +8 -0
  259. package/dist/stack/Stack.module.js.map +1 -0
  260. package/dist/stack/tokens.d.ts +3 -0
  261. package/dist/stack/tokens.d.ts.map +1 -0
  262. package/dist/stack/tokens.js +10 -0
  263. package/dist/stack/tokens.js.map +1 -0
  264. package/dist/switch/Switch.css +34 -25
  265. package/dist/switch/Switch.d.ts.map +1 -1
  266. package/dist/switch/Switch.js +1 -0
  267. package/dist/switch/Switch.js.map +1 -1
  268. package/dist/switch/Switch.module.js +4 -4
  269. package/dist/switch/Switch.module.js.map +1 -1
  270. package/dist/switch/tokens.d.ts +3 -0
  271. package/dist/switch/tokens.d.ts.map +1 -0
  272. package/dist/switch/tokens.js +25 -0
  273. package/dist/switch/tokens.js.map +1 -0
  274. package/dist/tabs/Tabs.css +24 -23
  275. package/dist/tabs/Tabs.js +4 -4
  276. package/dist/tabs/Tabs.js.map +1 -1
  277. package/dist/tabs/Tabs.module.js +4 -4
  278. package/dist/tabs/Tabs.module.js.map +1 -1
  279. package/dist/tabs/tokens.d.ts +3 -0
  280. package/dist/tabs/tokens.d.ts.map +1 -0
  281. package/dist/tabs/tokens.js +25 -0
  282. package/dist/tabs/tokens.js.map +1 -0
  283. package/dist/text/Text.css +74 -0
  284. package/dist/text/Text.d.ts +27 -0
  285. package/dist/text/Text.d.ts.map +1 -0
  286. package/dist/text/Text.js +16 -0
  287. package/dist/text/Text.js.map +1 -0
  288. package/dist/text/Text.module.js +30 -0
  289. package/dist/text/Text.module.js.map +1 -0
  290. package/dist/text/tokens.d.ts +3 -0
  291. package/dist/text/tokens.d.ts.map +1 -0
  292. package/dist/text/tokens.js +10 -0
  293. package/dist/text/tokens.js.map +1 -0
  294. package/dist/text-area/TextArea.css +1 -1
  295. package/dist/text-area/TextArea.js +1 -1
  296. package/dist/text-area/TextArea.js.map +1 -1
  297. package/dist/text-area/TextArea.module.js +1 -1
  298. package/dist/text-input/TextInput.js +1 -1
  299. package/dist/text-input/TextInput.js.map +1 -1
  300. package/dist/theme/Tone.css +70 -0
  301. package/dist/theme/Tone.module.js +20 -0
  302. package/dist/theme/Tone.module.js.map +1 -0
  303. package/dist/theme/bootstrap.d.ts +10 -0
  304. package/dist/theme/bootstrap.d.ts.map +1 -1
  305. package/dist/theme/bootstrap.js +48 -5
  306. package/dist/theme/bootstrap.js.map +1 -1
  307. package/dist/theme/chartColors.d.ts +23 -0
  308. package/dist/theme/chartColors.d.ts.map +1 -0
  309. package/dist/theme/chartColors.js +27 -0
  310. package/dist/theme/chartColors.js.map +1 -0
  311. package/dist/theme/checkTheme.d.ts +39 -0
  312. package/dist/theme/checkTheme.d.ts.map +1 -0
  313. package/dist/theme/checkTheme.js +132 -0
  314. package/dist/theme/checkTheme.js.map +1 -0
  315. package/dist/theme/cli.d.ts +14 -0
  316. package/dist/theme/cli.d.ts.map +1 -0
  317. package/dist/theme/cli.js +61 -0
  318. package/dist/theme/cli.js.map +1 -0
  319. package/dist/theme/color.d.ts +30 -0
  320. package/dist/theme/color.d.ts.map +1 -0
  321. package/dist/theme/color.js +94 -0
  322. package/dist/theme/color.js.map +1 -0
  323. package/dist/theme/colorVision.d.ts +23 -0
  324. package/dist/theme/colorVision.d.ts.map +1 -0
  325. package/dist/theme/colorVision.js +140 -0
  326. package/dist/theme/colorVision.js.map +1 -0
  327. package/dist/theme/componentTokens.d.ts +24 -0
  328. package/dist/theme/componentTokens.d.ts.map +1 -0
  329. package/dist/theme/componentTokens.js +20 -0
  330. package/dist/theme/componentTokens.js.map +1 -0
  331. package/dist/theme/components.d.ts +38 -0
  332. package/dist/theme/components.d.ts.map +1 -0
  333. package/dist/theme/components.js +65 -0
  334. package/dist/theme/components.js.map +1 -0
  335. package/dist/theme/defineTheme.d.ts +85 -0
  336. package/dist/theme/defineTheme.d.ts.map +1 -0
  337. package/dist/theme/defineTheme.js +130 -0
  338. package/dist/theme/defineTheme.js.map +1 -0
  339. package/dist/theme/fonts.d.ts +32 -0
  340. package/dist/theme/fonts.d.ts.map +1 -0
  341. package/dist/theme/fonts.js +36 -0
  342. package/dist/theme/fonts.js.map +1 -0
  343. package/dist/theme/index.d.ts +13 -0
  344. package/dist/theme/index.d.ts.map +1 -0
  345. package/dist/theme/index.js +10 -0
  346. package/dist/theme/semanticTokens.d.ts +9 -0
  347. package/dist/theme/semanticTokens.d.ts.map +1 -0
  348. package/dist/theme/semanticTokens.js +110 -0
  349. package/dist/theme/semanticTokens.js.map +1 -0
  350. package/dist/theme/theme.d.ts +61 -7
  351. package/dist/theme/theme.d.ts.map +1 -1
  352. package/dist/theme/theme.js +100 -10
  353. package/dist/theme/theme.js.map +1 -1
  354. package/dist/theme/toneClass.d.ts +8 -0
  355. package/dist/theme/toneClass.d.ts.map +1 -0
  356. package/dist/theme/toneClass.js +15 -0
  357. package/dist/theme/toneClass.js.map +1 -0
  358. package/dist/theme/tones.d.ts +89 -0
  359. package/dist/theme/tones.d.ts.map +1 -0
  360. package/dist/theme/tones.js +127 -0
  361. package/dist/theme/tones.js.map +1 -0
  362. package/dist/time-input/TimeInput.js +1 -1
  363. package/dist/time-input/TimeInput.js.map +1 -1
  364. package/dist/toast/Toast.css +22 -44
  365. package/dist/toast/Toast.d.ts +5 -3
  366. package/dist/toast/Toast.d.ts.map +1 -1
  367. package/dist/toast/Toast.js +4 -3
  368. package/dist/toast/Toast.js.map +1 -1
  369. package/dist/toast/Toast.module.js +10 -16
  370. package/dist/toast/Toast.module.js.map +1 -1
  371. package/dist/toast/tokens.d.ts +3 -0
  372. package/dist/toast/tokens.d.ts.map +1 -0
  373. package/dist/toast/tokens.js +21 -0
  374. package/dist/toast/tokens.js.map +1 -0
  375. package/dist/tooltip/Tooltip.css +12 -11
  376. package/dist/tooltip/Tooltip.js +1 -1
  377. package/dist/tooltip/Tooltip.js.map +1 -1
  378. package/dist/tooltip/Tooltip.module.js +2 -2
  379. package/dist/tooltip/Tooltip.module.js.map +1 -1
  380. package/dist/tooltip/tokens.d.ts +3 -0
  381. package/dist/tooltip/tokens.d.ts.map +1 -0
  382. package/dist/tooltip/tokens.js +21 -0
  383. package/dist/tooltip/tokens.js.map +1 -0
  384. package/dist/utils/cx.d.ts +1 -1
  385. package/dist/utils/cx.d.ts.map +1 -1
  386. package/dist/utils/cx.js +2 -2
  387. package/dist/utils/cx.js.map +1 -1
  388. package/package.json +15 -3
@@ -1,3 +1,5 @@
1
+ import { parseColor } from "./color.js";
2
+ import { TONE_VARIABLES, resolveTone, toneClassName } from "./tones.js";
1
3
  //#region src/theme/theme.ts
2
4
  function declarations(tokens) {
3
5
  return Object.entries(tokens).filter(([name, value]) => /^[a-zA-Z0-9-_]+$/.test(name) && !/[{};<]/.test(value)).map(([name, value]) => `--${name}:${value};`).join("");
@@ -8,23 +10,111 @@ function hashString(value) {
8
10
  for (let index = 0; index < value.length; index += 1) hash = hash * 33 ^ value.charCodeAt(index);
9
11
  return (hash >>> 0).toString(36);
10
12
  }
13
+ var NAME = /^[a-z0-9-]+$/;
14
+ var VARIABLE = /^var\(--([a-zA-Z0-9_-]+)\)$/;
15
+ /** The palette of a theme, as variables: `{ 'panneau-palette-orange': '#f25c05' }`. */
16
+ function paletteVariables(palette = {}) {
17
+ return Object.fromEntries(Object.entries(palette).filter(([name]) => NAME.test(name)).map(([name, value]) => [`panneau-palette-${name}`, value]));
18
+ }
19
+ /**
20
+ * Follows `var(--name)` references through the given variables (tokens, palette colors), until a
21
+ * value that is not one: `var(--panneau-palette-orange)` becomes `#f25c05`. A reference to a
22
+ * variable that isn't given is returned as is.
23
+ */
24
+ function resolveReference(value, variables) {
25
+ let current = value;
26
+ for (let depth = 0; depth < 10; depth += 1) {
27
+ const name = VARIABLE.exec(current.trim())?.[1];
28
+ if (name === void 0 || !Object.hasOwn(variables, name)) return current;
29
+ current = variables[name] ?? current;
30
+ }
31
+ return current;
32
+ }
33
+ function toneDeclarations(values) {
34
+ return declarations(Object.fromEntries(Object.keys(TONE_VARIABLES).map((key) => [TONE_VARIABLES[key], values[key]])));
35
+ }
36
+ /**
37
+ * The surfaces of a theme in each scheme, when it sets ones Panneau can read: tones derived from
38
+ * one color are made readable on them.
39
+ */
40
+ function themeSurfaces(theme) {
41
+ const palette = paletteVariables(theme.palette);
42
+ const surface = (tokens) => {
43
+ const variables = {
44
+ ...palette,
45
+ ...tokens
46
+ };
47
+ const value = variables["panneau-color-surface"];
48
+ return value !== void 0 ? parseColor(resolveReference(value, variables)) : null;
49
+ };
50
+ const light = surface(theme.tokens);
51
+ const dark = theme.dark?.["panneau-color-surface"] !== void 0 ? surface({
52
+ ...theme.tokens,
53
+ ...theme.dark
54
+ }) : null;
55
+ return {
56
+ ...light !== null && { light },
57
+ ...dark !== null && { dark }
58
+ };
59
+ }
60
+ /**
61
+ * The rules of the densities of a theme. `auto` takes the comfortable values on fine pointers and
62
+ * the touch ones on coarse pointers, like the default theme.
63
+ */
64
+ function densityCss(root, densities = {}) {
65
+ const body = (density) => declarations(densities[density] ?? {});
66
+ const rule = (selector, css) => css !== "" ? `${selector}{${css}}` : "";
67
+ const media = (query, css) => css !== "" ? `@media ${query}{${css}}` : "";
68
+ const selector = (density) => `${root}[data-density="${density}"]`;
69
+ return [
70
+ rule(selector("compact"), body("compact")),
71
+ rule(selector("comfortable"), body("comfortable")),
72
+ media("not (pointer: coarse)", rule(selector("auto"), body("comfortable"))),
73
+ rule(selector("touch"), body("touch")),
74
+ media("(pointer: coarse)", rule(selector("auto"), body("touch")))
75
+ ].join("");
76
+ }
11
77
  /**
12
- * The CSS of a theme, scoped to the roots that carry `data-panneau-theme="<scope>"`. Its rules are
13
- * more specific than the default tokens, and dark overrides more specific than light ones. Token
14
- * names must be plain identifiers, and values can't contain `{`, `}`, `;` or `<`: other entries are
15
- * ignored.
78
+ * The CSS of a theme, scoped to the roots that carry `data-panneau-theme="<scope>"`: its palette and
79
+ * tokens, its densities, its tones and the variants of components. Its rules are more specific than the default
80
+ * tokens and the built-in tones, and dark overrides more specific than light ones. Token, tone,
81
+ * component and variant names must be plain identifiers, and values can't contain `{`, `}`, `;` or
82
+ * `<`: other entries are ignored.
16
83
  */
17
84
  function getThemeCss(theme, scope) {
18
85
  const root = `[data-panneau-theme="${scope}"]`;
19
- const light = declarations(theme.tokens);
20
- const dark = theme.dark !== void 0 ? declarations(theme.dark) : "";
86
+ const dark = `${root}[data-color-scheme="dark"]`;
87
+ const auto = `${root}[data-color-scheme="auto"]`;
88
+ const light = [];
89
+ const darkRules = [];
90
+ const rule = (selector, body) => body !== "" ? `${selector}{${body}}` : "";
91
+ const palette = paletteVariables(theme.palette);
92
+ const surfaces = themeSurfaces(theme);
93
+ light.push(rule(root, declarations({
94
+ ...palette,
95
+ ...theme.tokens
96
+ })));
97
+ light.push(densityCss(root, theme.densities));
98
+ if (theme.dark !== void 0) darkRules.push(rule("§", declarations(theme.dark)));
99
+ Object.entries(theme.tones ?? {}).filter(([name]) => NAME.test(name)).forEach(([name, input]) => {
100
+ const values = resolveTone(typeof input === "string" ? resolveReference(input, palette) : input, surfaces);
101
+ const selector = `.${toneClassName(name)}`;
102
+ light.push(rule(`${root} ${selector}`, toneDeclarations(values.light)));
103
+ darkRules.push(rule(`§ ${selector}`, toneDeclarations(values.dark)));
104
+ });
105
+ Object.entries(theme.components ?? {}).filter(([component]) => NAME.test(component)).forEach(([component, { variants = {} }]) => {
106
+ Object.entries(variants).filter(([name]) => NAME.test(name)).forEach(([name, tokens]) => {
107
+ light.push(rule(`${root} .panneau-${component}-variant-${name}`, declarations(tokens)));
108
+ });
109
+ });
110
+ const darkCss = darkRules.filter(Boolean);
21
111
  return [
22
- light !== "" ? `${root}{${light}}` : "",
23
- dark !== "" ? `${root}[data-color-scheme="dark"]{${dark}}` : "",
24
- dark !== "" ? `@media (prefers-color-scheme: dark){${root}[data-color-scheme="auto"]{${dark}}}` : ""
112
+ ...light,
113
+ ...darkCss.map((css) => css.replaceAll("§", dark)),
114
+ darkCss.length > 0 ? `@media (prefers-color-scheme: dark){${darkCss.map((css) => css.replaceAll("§", auto)).join("")}}` : ""
25
115
  ].join("");
26
116
  }
27
117
  //#endregion
28
- export { getThemeCss, hashString };
118
+ export { getThemeCss, hashString, paletteVariables, resolveReference, themeSurfaces };
29
119
 
30
120
  //# sourceMappingURL=theme.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"theme.js","names":[],"sources":["../../src/theme/theme.ts"],"sourcesContent":["/**\n * A theme: design tokens, as CSS variables without the leading `--`, with optional overrides for\n * the dark scheme. It has the same shape as the `Theme` of `@panneau/core` plugins.\n */\nexport interface Theme {\n label?: string;\n /** Tokens of the light scheme, or of both schemes without `dark`: `{ 'panneau-color-accent': '#05f' }`. */\n tokens: Record<string, string>;\n /** Tokens that change in the dark scheme. */\n dark?: Record<string, string>;\n}\n\n/** `auto` follows the system setting (`prefers-color-scheme`). */\nexport type ColorScheme = 'light' | 'dark' | 'auto';\n\nfunction declarations(tokens: Record<string, string>): string {\n return Object.entries(tokens)\n .filter(([name, value]) => /^[a-zA-Z0-9-_]+$/.test(name) && !/[{};<]/.test(value))\n .map(([name, value]) => `--${name}:${value};`)\n .join('');\n}\n\n/** A short, stable hash of a string, to scope the CSS of a theme. */\nexport function hashString(value: string): string {\n let hash = 5381;\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash * 33) ^ value.charCodeAt(index);\n }\n return (hash >>> 0).toString(36);\n}\n\n/**\n * The CSS of a theme, scoped to the roots that carry `data-panneau-theme=\"<scope>\"`. Its rules are\n * more specific than the default tokens, and dark overrides more specific than light ones. Token\n * names must be plain identifiers, and values can't contain `{`, `}`, `;` or `<`: other entries are\n * ignored.\n */\nexport function getThemeCss(theme: Theme, scope: string): string {\n const root = `[data-panneau-theme=\"${scope}\"]`;\n const light = declarations(theme.tokens);\n const dark = theme.dark !== undefined ? declarations(theme.dark) : '';\n return [\n light !== '' ? `${root}{${light}}` : '',\n dark !== '' ? `${root}[data-color-scheme=\"dark\"]{${dark}}` : '',\n dark !== ''\n ? `@media (prefers-color-scheme: dark){${root}[data-color-scheme=\"auto\"]{${dark}}}`\n : '',\n ].join('');\n}\n"],"mappings":";AAeA,SAAS,aAAa,QAAwC;CAC1D,OAAO,OAAO,QAAQ,MAAM,CAAC,CACxB,QAAQ,CAAC,MAAM,WAAW,mBAAmB,KAAK,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,CAAC,CACjF,KAAK,CAAC,MAAM,WAAW,KAAK,KAAI,GAAI,MAAK,EAAG,CAAC,CAC7C,KAAK,EAAE;AAChB;;AAGA,SAAgB,WAAW,OAAuB;CAC9C,IAAI,OAAO;CACX,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAC/C,OAAQ,OAAO,KAAM,MAAM,WAAW,KAAK;CAE/C,QAAQ,SAAS,EAAA,CAAG,SAAS,EAAE;AACnC;;;;;;;AAQA,SAAgB,YAAY,OAAc,OAAuB;CAC7D,MAAM,OAAO,wBAAwB,MAAK;CAC1C,MAAM,QAAQ,aAAa,MAAM,MAAM;CACvC,MAAM,OAAO,MAAM,SAAS,KAAA,IAAY,aAAa,MAAM,IAAI,IAAI;CACnE,OAAO;EACH,UAAU,KAAK,GAAG,KAAI,GAAI,MAAK,KAAM;EACrC,SAAS,KAAK,GAAG,KAAI,6BAA8B,KAAI,KAAM;EAC7D,SAAS,KACH,uCAAuC,KAAI,6BAA8B,KAAI,MAC7E;CAAE,CACX,CAAC,KAAK,EAAE;AACb"}
1
+ {"version":3,"file":"theme.js","names":[],"sources":["../../src/theme/theme.ts"],"sourcesContent":["import { parseColor } from './color';\nimport type { ThemeFont } from './fonts';\nimport {\n TONE_VARIABLES,\n type ToneInput,\n type ToneSurfaces,\n type ToneValues,\n resolveTone,\n toneClassName,\n} from './tones';\n\n/**\n * A theme: design tokens, as CSS variables without the leading `--`, with optional overrides for\n * the dark scheme, raw palette colors, its own tones, and named variants of components (decision\n * 0024). A theme is plain data: the `Theme` schema of `@panneau/protocol` validates it, and plugins\n * of `@panneau/core` register it. Write one with `defineTheme()` to check token names.\n *\n * It is a type rather than an interface so that it is assignable to the `Theme` of\n * `@panneau/protocol`, which accepts properties of later versions.\n */\nexport type Theme = {\n /** A name for theme pickers. */\n label?: string;\n /** Tokens of the light scheme, or of both schemes without `dark`: `{ 'panneau-color-accent': '#05f' }`. */\n tokens: Record<string, string>;\n /** Tokens that change in the dark scheme. */\n dark?: Record<string, string>;\n /**\n * Raw colors, written as `--panneau-palette-<name>`: tokens and tones use them with\n * `var(--panneau-palette-<name>)`, so that a theme names its brand colors once.\n */\n palette?: Record<string, string>;\n /**\n * Tones added or redefined by the theme: one color, from which Panneau derives the others,\n * or every value. Declare added tones in `PanneauTones` so that `tone=\"signal\"` type-checks.\n */\n tones?: Record<string, ToneInput>;\n /**\n * Named variants of components: token overrides that `<Badge variant=\"tag\">` applies through\n * its `panneau-badge-variant-tag` class. Declare them in `BadgeVariants` (and the like).\n */\n components?: Record<string, { variants?: Record<string, Record<string, string>> }>;\n /**\n * Tokens of each density, such as `panneau-control-height`: tokens set here change with the\n * density of the root, while the same tokens in `tokens` would apply to every density.\n */\n densities?: Partial<Record<Exclude<Density, 'auto'>, Record<string, string>>>;\n /**\n * Font faces and font stylesheets, which `PanneauRoot` adds to the page once. Font tokens\n * (`panneau-font-family-heading`) then use their families.\n */\n fonts?: ThemeFont[];\n};\n\n/** `auto` follows the system setting (`prefers-color-scheme`). */\nexport type ColorScheme = 'light' | 'dark' | 'auto';\n\n/**\n * How much room controls and rows take: `compact`, `comfortable`, or `touch`, with larger targets.\n * `auto` is `touch` on coarse pointers (touch screens) and `comfortable` otherwise.\n */\nexport type Density = 'compact' | 'comfortable' | 'touch' | 'auto';\n\nfunction declarations(tokens: Record<string, string>): string {\n return Object.entries(tokens)\n .filter(([name, value]) => /^[a-zA-Z0-9-_]+$/.test(name) && !/[{};<]/.test(value))\n .map(([name, value]) => `--${name}:${value};`)\n .join('');\n}\n\n/** A short, stable hash of a string, to scope the CSS of a theme. */\nexport function hashString(value: string): string {\n let hash = 5381;\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash * 33) ^ value.charCodeAt(index);\n }\n return (hash >>> 0).toString(36);\n}\n\nconst NAME = /^[a-z0-9-]+$/;\n\nconst VARIABLE = /^var\\(--([a-zA-Z0-9_-]+)\\)$/;\n\n/** The palette of a theme, as variables: `{ 'panneau-palette-orange': '#f25c05' }`. */\nexport function paletteVariables(\n palette: Readonly<Record<string, string>> = {},\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(palette)\n .filter(([name]) => NAME.test(name))\n .map(([name, value]) => [`panneau-palette-${name}`, value]),\n );\n}\n\n/**\n * Follows `var(--name)` references through the given variables (tokens, palette colors), until a\n * value that is not one: `var(--panneau-palette-orange)` becomes `#f25c05`. A reference to a\n * variable that isn't given is returned as is.\n */\nexport function resolveReference(\n value: string,\n variables: Readonly<Record<string, string>>,\n): string {\n let current = value;\n for (let depth = 0; depth < 10; depth += 1) {\n const name = VARIABLE.exec(current.trim())?.[1];\n if (name === undefined || !Object.hasOwn(variables, name)) {\n return current;\n }\n current = variables[name] ?? current;\n }\n return current;\n}\n\nfunction toneDeclarations(values: ToneValues): string {\n return declarations(\n Object.fromEntries(\n (Object.keys(TONE_VARIABLES) as (keyof ToneValues)[]).map((key) => [\n TONE_VARIABLES[key],\n values[key],\n ]),\n ),\n );\n}\n\n/**\n * The surfaces of a theme in each scheme, when it sets ones Panneau can read: tones derived from\n * one color are made readable on them.\n */\nexport function themeSurfaces(theme: Theme): ToneSurfaces {\n const palette = paletteVariables(theme.palette);\n const surface = (tokens: Record<string, string>) => {\n const variables = { ...palette, ...tokens };\n const value = variables['panneau-color-surface'];\n return value !== undefined ? parseColor(resolveReference(value, variables)) : null;\n };\n const light = surface(theme.tokens);\n const dark =\n theme.dark?.['panneau-color-surface'] !== undefined\n ? surface({ ...theme.tokens, ...theme.dark })\n : null;\n return {\n ...(light !== null && { light }),\n ...(dark !== null && { dark }),\n };\n}\n\n/**\n * The rules of the densities of a theme. `auto` takes the comfortable values on fine pointers and\n * the touch ones on coarse pointers, like the default theme.\n */\nfunction densityCss(root: string, densities: Theme['densities'] = {}): string {\n const body = (density: Exclude<Density, 'auto'>) => declarations(densities[density] ?? {});\n const rule = (selector: string, css: string) => (css !== '' ? `${selector}{${css}}` : '');\n const media = (query: string, css: string) => (css !== '' ? `@media ${query}{${css}}` : '');\n const selector = (density: Density) => `${root}[data-density=\"${density}\"]`;\n return [\n rule(selector('compact'), body('compact')),\n rule(selector('comfortable'), body('comfortable')),\n media('not (pointer: coarse)', rule(selector('auto'), body('comfortable'))),\n rule(selector('touch'), body('touch')),\n media('(pointer: coarse)', rule(selector('auto'), body('touch'))),\n ].join('');\n}\n\n/**\n * The CSS of a theme, scoped to the roots that carry `data-panneau-theme=\"<scope>\"`: its palette and\n * tokens, its densities, its tones and the variants of components. Its rules are more specific than the default\n * tokens and the built-in tones, and dark overrides more specific than light ones. Token, tone,\n * component and variant names must be plain identifiers, and values can't contain `{`, `}`, `;` or\n * `<`: other entries are ignored.\n */\nexport function getThemeCss(theme: Theme, scope: string): string {\n const root = `[data-panneau-theme=\"${scope}\"]`;\n const dark = `${root}[data-color-scheme=\"dark\"]`;\n const auto = `${root}[data-color-scheme=\"auto\"]`;\n const light: string[] = [];\n const darkRules: string[] = [];\n const rule = (selector: string, body: string) => (body !== '' ? `${selector}{${body}}` : '');\n\n const palette = paletteVariables(theme.palette);\n const surfaces = themeSurfaces(theme);\n light.push(rule(root, declarations({ ...palette, ...theme.tokens })));\n light.push(densityCss(root, theme.densities));\n if (theme.dark !== undefined) {\n darkRules.push(rule('§', declarations(theme.dark)));\n }\n Object.entries(theme.tones ?? {})\n .filter(([name]) => NAME.test(name))\n .forEach(([name, input]) => {\n // A tone from a palette color derives from the color itself.\n const values = resolveTone(\n typeof input === 'string' ? resolveReference(input, palette) : input,\n surfaces,\n );\n const selector = `.${toneClassName(name)}`;\n light.push(rule(`${root} ${selector}`, toneDeclarations(values.light)));\n darkRules.push(rule(`§ ${selector}`, toneDeclarations(values.dark)));\n });\n Object.entries(theme.components ?? {})\n .filter(([component]) => NAME.test(component))\n .forEach(([component, { variants = {} }]) => {\n Object.entries(variants)\n .filter(([name]) => NAME.test(name))\n .forEach(([name, tokens]) => {\n light.push(\n rule(`${root} .panneau-${component}-variant-${name}`, declarations(tokens)),\n );\n });\n });\n\n const darkCss = darkRules.filter(Boolean);\n return [\n ...light,\n ...darkCss.map((css) => css.replaceAll('§', dark)),\n darkCss.length > 0\n ? `@media (prefers-color-scheme: dark){${darkCss.map((css) => css.replaceAll('§', auto)).join('')}}`\n : '',\n ].join('');\n}\n"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type Tone } from './tones';
2
+ /**
3
+ * The class of a tone, `panneau-tone-<tone>`. The built-in tones come from `Tone.module.css`, whose
4
+ * classes get the same stable names, so using it includes their CSS; a theme's own tones get their
5
+ * rules from the theme.
6
+ */
7
+ export declare function toneClass(tone: Tone): string;
8
+ //# sourceMappingURL=toneClass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toneClass.d.ts","sourceRoot":"","sources":["../../src/theme/toneClass.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAiB,MAAM,SAAS,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5C"}
@@ -0,0 +1,15 @@
1
+ import Tone_module_default from "./Tone.module.js";
2
+ import { toneClassName } from "./tones.js";
3
+ //#region src/theme/toneClass.ts
4
+ /**
5
+ * The class of a tone, `panneau-tone-<tone>`. The built-in tones come from `Tone.module.css`, whose
6
+ * classes get the same stable names, so using it includes their CSS; a theme's own tones get their
7
+ * rules from the theme.
8
+ */
9
+ function toneClass(tone) {
10
+ return (Object.hasOwn(Tone_module_default, tone) ? Tone_module_default[tone] : void 0) ?? toneClassName(tone);
11
+ }
12
+ //#endregion
13
+ export { toneClass };
14
+
15
+ //# sourceMappingURL=toneClass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toneClass.js","names":["styles"],"sources":["../../src/theme/toneClass.ts"],"sourcesContent":["import styles from './Tone.module.css';\nimport { type Tone, toneClassName } from './tones';\n\n/**\n * The class of a tone, `panneau-tone-<tone>`. The built-in tones come from `Tone.module.css`, whose\n * classes get the same stable names, so using it includes their CSS; a theme's own tones get their\n * rules from the theme.\n */\nexport function toneClass(tone: Tone): string {\n return (Object.hasOwn(styles, tone) ? styles[tone] : undefined) ?? toneClassName(tone);\n}\n"],"mappings":";;;;;;;;AAQA,SAAgB,UAAU,MAAoB;CAC1C,QAAQ,OAAO,OAAOA,qBAAQ,IAAI,IAAIA,oBAAO,QAAQ,KAAA,MAAc,cAAc,IAAI;AACzF"}
@@ -0,0 +1,89 @@
1
+ import { type Rgb } from './color';
2
+ /**
3
+ * The tones that components accept (`tone="success"`), like Bootstrap's `$theme-colors`. A theme
4
+ * adds its own; declare them here so that `tone="signal"` type-checks:
5
+ *
6
+ * ```ts
7
+ * declare module '@panneau/ui' {
8
+ * interface PanneauTones {
9
+ * signal: true;
10
+ * }
11
+ * }
12
+ * ```
13
+ */
14
+ export interface PanneauTones {
15
+ neutral: true;
16
+ accent: true;
17
+ success: true;
18
+ warning: true;
19
+ danger: true;
20
+ info: true;
21
+ }
22
+ /** A tone name: a built-in tone, or one declared in `PanneauTones`. */
23
+ export type Tone = keyof PanneauTones & string;
24
+ /** The tones Panneau defines, from the semantic tokens of the theme. */
25
+ export declare const BUILT_IN_TONES: readonly ["neutral", "accent", "success", "warning", "danger", "info"];
26
+ /** The colors of a tone, as CSS values. */
27
+ export type ToneValues = {
28
+ /** Text and icons on surfaces: the outline, subtle and ghost appearances. */
29
+ text: string;
30
+ /** Background of the subtle appearance. */
31
+ subtle: string;
32
+ /** Border of the subtle appearance. */
33
+ border: string;
34
+ /** Border of the outline appearance. */
35
+ outline: string;
36
+ /** Background of the solid appearance. */
37
+ solid: string;
38
+ /** Background of the solid appearance on hover and press. */
39
+ solidHover: string;
40
+ /** Text on the solid appearance. */
41
+ solidText: string;
42
+ };
43
+ /**
44
+ * A tone of a theme: one color, from which Panneau derives the others (`'#f25c05'`), or every
45
+ * value, with optional overrides for the dark scheme.
46
+ */
47
+ export type ToneInput = string | (ToneValues & {
48
+ dark?: Partial<ToneValues>;
49
+ });
50
+ /** The local CSS variables of a tone, which components read. */
51
+ export declare const TONE_VARIABLES: Readonly<Record<keyof ToneValues, string>>;
52
+ /** The class that applies a tone: `panneau-tone-<tone>`. */
53
+ export declare function toneClassName(tone: string): string;
54
+ /** The surfaces of a theme, in each scheme, when it sets ones Panneau can read. */
55
+ export type ToneSurfaces = Partial<Record<'light' | 'dark', Rgb>>;
56
+ /** How much of the tone's color the subtle background mixes into the surface, per scheme. */
57
+ export declare const SUBTLE_AMOUNTS: {
58
+ light: number;
59
+ dark: number;
60
+ };
61
+ /** Text must reach this contrast ratio (WCAG AA for normal text). */
62
+ export declare const MIN_CONTRAST_RATIO = 4.5;
63
+ /**
64
+ * The values of a tone, in both schemes, from one color: Panneau's `button-variant()` and
65
+ * `color-contrast()`.
66
+ *
67
+ * - The solid background is the color, with white or black text, whichever reads better, and a
68
+ * hover 15% darker (or lighter, when the text is black and darker would hurt it).
69
+ * - The text color is the color, darkened (light scheme) or lightened (dark scheme) until it
70
+ * reaches 4.5:1 against the subtle background, which is tinted, and so against the surface too.
71
+ * - The subtle background and the border are mixed with the surface in CSS, so they follow the
72
+ * surface of any theme.
73
+ *
74
+ * A color Panneau can't read (a CSS variable, a named color) is used as is, with `color-mix()` for
75
+ * the hover and white text: `checkTheme()` reports it as unchecked.
76
+ *
77
+ * Text is made readable on the surfaces of the default theme, or on those given, which themes pass
78
+ * so that a tone stays readable on their own surfaces.
79
+ */
80
+ export declare function deriveTone(color: string, surfaces?: ToneSurfaces): {
81
+ light: ToneValues;
82
+ dark: ToneValues;
83
+ };
84
+ /** The values of a tone input, in both schemes, derived on the given surfaces if it is one color. */
85
+ export declare function resolveTone(input: ToneInput, surfaces?: ToneSurfaces): {
86
+ light: ToneValues;
87
+ dark: ToneValues;
88
+ };
89
+ //# sourceMappingURL=tones.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tones.d.ts","sourceRoot":"","sources":["../../src/theme/tones.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,GAAG,EAQX,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,IAAI,CAAC;IACb,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,MAAM,EAAE,IAAI,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;CACd;AAED,uEAAuE;AACvE,MAAM,MAAM,IAAI,GAAG,MAAM,YAAY,GAAG,MAAM,CAAC;AAE/C,wEAAwE;AACxE,eAAO,MAAM,cAAc,wEAOjB,CAAC;AAEX,2CAA2C;AAC3C,MAAM,MAAM,UAAU,GAAG;IACrB,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;CAAE,CAAC,CAAC;AAE/E,gEAAgE;AAChE,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,UAAU,EAAE,MAAM,CAAC,CAQrE,CAAC;AAEF,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAKD,mFAAmF;AACnF,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AAElE,6FAA6F;AAC7F,eAAO,MAAM,cAAc;;;CAA8B,CAAC;AAE1D,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAEtC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CACtB,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,YAAiB,GAC5B;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAuDzC;AAED,qGAAqG;AACrG,wBAAgB,WAAW,CACvB,KAAK,EAAE,SAAS,EAChB,QAAQ,GAAE,YAAiB,GAC5B;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAMzC"}
@@ -0,0 +1,127 @@
1
+ import { WHITE, contrastRatio, ensureContrast, mixColors, parseColor, readableTextColor, toHex } from "./color.js";
2
+ //#region src/theme/tones.ts
3
+ /** The tones Panneau defines, from the semantic tokens of the theme. */
4
+ var BUILT_IN_TONES = [
5
+ "neutral",
6
+ "accent",
7
+ "success",
8
+ "warning",
9
+ "danger",
10
+ "info"
11
+ ];
12
+ /** The local CSS variables of a tone, which components read. */
13
+ var TONE_VARIABLES = {
14
+ text: "panneau-tone-text",
15
+ subtle: "panneau-tone-subtle",
16
+ border: "panneau-tone-border",
17
+ outline: "panneau-tone-outline",
18
+ solid: "panneau-tone-solid",
19
+ solidHover: "panneau-tone-solid-hover",
20
+ solidText: "panneau-tone-solid-text"
21
+ };
22
+ /** The class that applies a tone: `panneau-tone-<tone>`. */
23
+ function toneClassName(tone) {
24
+ return `panneau-tone-${tone}`;
25
+ }
26
+ /** Surfaces text must be readable on, in each scheme of the default theme. */
27
+ var SURFACES = {
28
+ light: WHITE,
29
+ dark: {
30
+ r: 24,
31
+ g: 24,
32
+ b: 27
33
+ }
34
+ };
35
+ /** How much of the tone's color the subtle background mixes into the surface, per scheme. */
36
+ var SUBTLE_AMOUNTS = {
37
+ light: .12,
38
+ dark: .22
39
+ };
40
+ /** Text must reach this contrast ratio (WCAG AA for normal text). */
41
+ var MIN_CONTRAST_RATIO = 4.5;
42
+ /**
43
+ * The values of a tone, in both schemes, from one color: Panneau's `button-variant()` and
44
+ * `color-contrast()`.
45
+ *
46
+ * - The solid background is the color, with white or black text, whichever reads better, and a
47
+ * hover 15% darker (or lighter, when the text is black and darker would hurt it).
48
+ * - The text color is the color, darkened (light scheme) or lightened (dark scheme) until it
49
+ * reaches 4.5:1 against the subtle background, which is tinted, and so against the surface too.
50
+ * - The subtle background and the border are mixed with the surface in CSS, so they follow the
51
+ * surface of any theme.
52
+ *
53
+ * A color Panneau can't read (a CSS variable, a named color) is used as is, with `color-mix()` for
54
+ * the hover and white text: `checkTheme()` reports it as unchecked.
55
+ *
56
+ * Text is made readable on the surfaces of the default theme, or on those given, which themes pass
57
+ * so that a tone stays readable on their own surfaces.
58
+ */
59
+ function deriveTone(color, surfaces = {}) {
60
+ const subtle = (amount) => `color-mix(in srgb, ${color} ${amount}%, var(--panneau-color-surface))`;
61
+ const parsed = parseColor(color);
62
+ if (parsed === null) {
63
+ const values = {
64
+ text: color,
65
+ subtle: subtle(SUBTLE_AMOUNTS.light * 100),
66
+ border: subtle(45),
67
+ outline: color,
68
+ solid: color,
69
+ solidHover: `color-mix(in srgb, ${color}, #000 15%)`,
70
+ solidText: "#fff"
71
+ };
72
+ return {
73
+ light: values,
74
+ dark: {
75
+ ...values,
76
+ subtle: subtle(SUBTLE_AMOUNTS.dark * 100)
77
+ }
78
+ };
79
+ }
80
+ const solidText = readableTextColor(parsed);
81
+ const darker = mixColors(parsed, {
82
+ r: 0,
83
+ g: 0,
84
+ b: 0
85
+ }, .15);
86
+ const hover = contrastRatio(solidText, darker) >= contrastRatio(solidText, parsed) ? darker : mixColors(parsed, WHITE, .15);
87
+ const shared = {
88
+ solid: toHex(parsed),
89
+ solidHover: toHex(hover),
90
+ solidText: toHex(solidText)
91
+ };
92
+ const readable = (scheme) => toHex(ensureContrast(parsed, mixColors(surfaces[scheme] ?? SURFACES[scheme], parsed, SUBTLE_AMOUNTS[scheme]), MIN_CONTRAST_RATIO));
93
+ const light = readable("light");
94
+ const dark = readable("dark");
95
+ return {
96
+ light: {
97
+ ...shared,
98
+ text: light,
99
+ outline: light,
100
+ subtle: subtle(SUBTLE_AMOUNTS.light * 100),
101
+ border: subtle(45)
102
+ },
103
+ dark: {
104
+ ...shared,
105
+ text: dark,
106
+ outline: dark,
107
+ subtle: subtle(SUBTLE_AMOUNTS.dark * 100),
108
+ border: subtle(55)
109
+ }
110
+ };
111
+ }
112
+ /** The values of a tone input, in both schemes, derived on the given surfaces if it is one color. */
113
+ function resolveTone(input, surfaces = {}) {
114
+ if (typeof input === "string") return deriveTone(input, surfaces);
115
+ const { dark, ...light } = input;
116
+ return {
117
+ light,
118
+ dark: {
119
+ ...light,
120
+ ...dark
121
+ }
122
+ };
123
+ }
124
+ //#endregion
125
+ export { BUILT_IN_TONES, MIN_CONTRAST_RATIO, SUBTLE_AMOUNTS, TONE_VARIABLES, deriveTone, resolveTone, toneClassName };
126
+
127
+ //# sourceMappingURL=tones.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tones.js","names":[],"sources":["../../src/theme/tones.ts"],"sourcesContent":["import {\n type Rgb,\n WHITE,\n contrastRatio,\n ensureContrast,\n mixColors,\n parseColor,\n readableTextColor,\n toHex,\n} from './color';\n\n/**\n * The tones that components accept (`tone=\"success\"`), like Bootstrap's `$theme-colors`. A theme\n * adds its own; declare them here so that `tone=\"signal\"` type-checks:\n *\n * ```ts\n * declare module '@panneau/ui' {\n * interface PanneauTones {\n * signal: true;\n * }\n * }\n * ```\n */\nexport interface PanneauTones {\n neutral: true;\n accent: true;\n success: true;\n warning: true;\n danger: true;\n info: true;\n}\n\n/** A tone name: a built-in tone, or one declared in `PanneauTones`. */\nexport type Tone = keyof PanneauTones & string;\n\n/** The tones Panneau defines, from the semantic tokens of the theme. */\nexport const BUILT_IN_TONES = [\n 'neutral',\n 'accent',\n 'success',\n 'warning',\n 'danger',\n 'info',\n] as const;\n\n/** The colors of a tone, as CSS values. */\nexport type ToneValues = {\n /** Text and icons on surfaces: the outline, subtle and ghost appearances. */\n text: string;\n /** Background of the subtle appearance. */\n subtle: string;\n /** Border of the subtle appearance. */\n border: string;\n /** Border of the outline appearance. */\n outline: string;\n /** Background of the solid appearance. */\n solid: string;\n /** Background of the solid appearance on hover and press. */\n solidHover: string;\n /** Text on the solid appearance. */\n solidText: string;\n};\n\n/**\n * A tone of a theme: one color, from which Panneau derives the others (`'#f25c05'`), or every\n * value, with optional overrides for the dark scheme.\n */\nexport type ToneInput = string | (ToneValues & { dark?: Partial<ToneValues> });\n\n/** The local CSS variables of a tone, which components read. */\nexport const TONE_VARIABLES: Readonly<Record<keyof ToneValues, string>> = {\n text: 'panneau-tone-text',\n subtle: 'panneau-tone-subtle',\n border: 'panneau-tone-border',\n outline: 'panneau-tone-outline',\n solid: 'panneau-tone-solid',\n solidHover: 'panneau-tone-solid-hover',\n solidText: 'panneau-tone-solid-text',\n};\n\n/** The class that applies a tone: `panneau-tone-<tone>`. */\nexport function toneClassName(tone: string): string {\n return `panneau-tone-${tone}`;\n}\n\n/** Surfaces text must be readable on, in each scheme of the default theme. */\nconst SURFACES: Record<'light' | 'dark', Rgb> = { light: WHITE, dark: { r: 24, g: 24, b: 27 } };\n\n/** The surfaces of a theme, in each scheme, when it sets ones Panneau can read. */\nexport type ToneSurfaces = Partial<Record<'light' | 'dark', Rgb>>;\n\n/** How much of the tone's color the subtle background mixes into the surface, per scheme. */\nexport const SUBTLE_AMOUNTS = { light: 0.12, dark: 0.22 };\n\n/** Text must reach this contrast ratio (WCAG AA for normal text). */\nexport const MIN_CONTRAST_RATIO = 4.5;\n\n/**\n * The values of a tone, in both schemes, from one color: Panneau's `button-variant()` and\n * `color-contrast()`.\n *\n * - The solid background is the color, with white or black text, whichever reads better, and a\n * hover 15% darker (or lighter, when the text is black and darker would hurt it).\n * - The text color is the color, darkened (light scheme) or lightened (dark scheme) until it\n * reaches 4.5:1 against the subtle background, which is tinted, and so against the surface too.\n * - The subtle background and the border are mixed with the surface in CSS, so they follow the\n * surface of any theme.\n *\n * A color Panneau can't read (a CSS variable, a named color) is used as is, with `color-mix()` for\n * the hover and white text: `checkTheme()` reports it as unchecked.\n *\n * Text is made readable on the surfaces of the default theme, or on those given, which themes pass\n * so that a tone stays readable on their own surfaces.\n */\nexport function deriveTone(\n color: string,\n surfaces: ToneSurfaces = {},\n): { light: ToneValues; dark: ToneValues } {\n const subtle = (amount: number) =>\n `color-mix(in srgb, ${color} ${amount}%, var(--panneau-color-surface))`;\n const parsed = parseColor(color);\n if (parsed === null) {\n const values: ToneValues = {\n text: color,\n subtle: subtle(SUBTLE_AMOUNTS.light * 100),\n border: subtle(45),\n outline: color,\n solid: color,\n solidHover: `color-mix(in srgb, ${color}, #000 15%)`,\n solidText: '#fff',\n };\n return { light: values, dark: { ...values, subtle: subtle(SUBTLE_AMOUNTS.dark * 100) } };\n }\n const solidText = readableTextColor(parsed);\n const darker = mixColors(parsed, { r: 0, g: 0, b: 0 }, 0.15);\n const hover =\n contrastRatio(solidText, darker) >= contrastRatio(solidText, parsed)\n ? darker\n : mixColors(parsed, WHITE, 0.15);\n const solid = toHex(parsed);\n const shared = {\n solid,\n solidHover: toHex(hover),\n solidText: toHex(solidText),\n };\n // Readable on the subtle background, which is closer to the text color than the surface.\n const readable = (scheme: 'light' | 'dark') =>\n toHex(\n ensureContrast(\n parsed,\n mixColors(surfaces[scheme] ?? SURFACES[scheme], parsed, SUBTLE_AMOUNTS[scheme]),\n MIN_CONTRAST_RATIO,\n ),\n );\n const light = readable('light');\n const dark = readable('dark');\n return {\n light: {\n ...shared,\n text: light,\n outline: light,\n subtle: subtle(SUBTLE_AMOUNTS.light * 100),\n border: subtle(45),\n },\n dark: {\n ...shared,\n text: dark,\n outline: dark,\n subtle: subtle(SUBTLE_AMOUNTS.dark * 100),\n border: subtle(55),\n },\n };\n}\n\n/** The values of a tone input, in both schemes, derived on the given surfaces if it is one color. */\nexport function resolveTone(\n input: ToneInput,\n surfaces: ToneSurfaces = {},\n): { light: ToneValues; dark: ToneValues } {\n if (typeof input === 'string') {\n return deriveTone(input, surfaces);\n }\n const { dark, ...light } = input;\n return { light, dark: { ...light, ...dark } };\n}\n"],"mappings":";;;AAoCA,IAAa,iBAAiB;CAC1B;CACA;CACA;CACA;CACA;CACA;AAAM;;AA4BV,IAAa,iBAA6D;CACtE,MAAM;CACN,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,OAAO;CACP,YAAY;CACZ,WAAW;AACf;;AAGA,SAAgB,cAAc,MAAsB;CAChD,OAAO,gBAAgB;AAC3B;;AAGA,IAAM,WAA0C;CAAE,OAAO;CAAO,MAAM;EAAE,GAAG;EAAI,GAAG;EAAI,GAAG;CAAG;AAAE;;AAM9F,IAAa,iBAAiB;CAAE,OAAO;CAAM,MAAM;AAAK;;AAGxD,IAAa,qBAAqB;;;;;;;;;;;;;;;;;;AAmBlC,SAAgB,WACZ,OACA,WAAyB,CAAC,GACa;CACvC,MAAM,UAAU,WACZ,sBAAsB,MAAK,GAAI,OAAM;CACzC,MAAM,SAAS,WAAW,KAAK;CAC/B,IAAI,WAAW,MAAM;EACjB,MAAM,SAAqB;GACvB,MAAM;GACN,QAAQ,OAAO,eAAe,QAAQ,GAAG;GACzC,QAAQ,OAAO,EAAE;GACjB,SAAS;GACT,OAAO;GACP,YAAY,sBAAsB,MAAK;GACvC,WAAW;EACf;EACA,OAAO;GAAE,OAAO;GAAQ,MAAM;IAAE,GAAG;IAAQ,QAAQ,OAAO,eAAe,OAAO,GAAG;GAAE;EAAE;CAC3F;CACA,MAAM,YAAY,kBAAkB,MAAM;CAC1C,MAAM,SAAS,UAAU,QAAQ;EAAE,GAAG;EAAG,GAAG;EAAG,GAAG;CAAE,GAAG,GAAI;CAC3D,MAAM,QACF,cAAc,WAAW,MAAM,KAAK,cAAc,WAAW,MAAM,IAC7D,SACA,UAAU,QAAQ,OAAO,GAAI;CAEvC,MAAM,SAAS;EACX,OAFU,MAAM,MAEhB;EACA,YAAY,MAAM,KAAK;EACvB,WAAW,MAAM,SAAS;CAC9B;CAEA,MAAM,YAAY,WACd,MACI,eACI,QACA,UAAU,SAAS,WAAW,SAAS,SAAS,QAAQ,eAAe,OAAO,GAC9E,kBACJ,CACJ;CACJ,MAAM,QAAQ,SAAS,OAAO;CAC9B,MAAM,OAAO,SAAS,MAAM;CAC5B,OAAO;EACH,OAAO;GACH,GAAG;GACH,MAAM;GACN,SAAS;GACT,QAAQ,OAAO,eAAe,QAAQ,GAAG;GACzC,QAAQ,OAAO,EAAE;EACrB;EACA,MAAM;GACF,GAAG;GACH,MAAM;GACN,SAAS;GACT,QAAQ,OAAO,eAAe,OAAO,GAAG;GACxC,QAAQ,OAAO,EAAE;EACrB;CACJ;AACJ;;AAGA,SAAgB,YACZ,OACA,WAAyB,CAAC,GACa;CACvC,IAAI,OAAO,UAAU,UACjB,OAAO,WAAW,OAAO,QAAQ;CAErC,MAAM,EAAE,MAAM,GAAG,UAAU;CAC3B,OAAO;EAAE;EAAO,MAAM;GAAE,GAAG;GAAO,GAAG;EAAK;CAAE;AAChD"}
@@ -13,7 +13,7 @@ function TimeInput({ label, description, errors = [], isRequired, isReadOnly, cl
13
13
  isReadOnly,
14
14
  isInvalid: errors.length > 0,
15
15
  validationBehavior: "aria",
16
- className: cx(Field_module_default.field, className),
16
+ className: cx("panneau-time-input", Field_module_default.field, className),
17
17
  children: [
18
18
  /* @__PURE__ */ jsx(FieldLabel, {
19
19
  isRequired,
@@ -1 +1 @@
1
- {"version":3,"file":"TimeInput.js","names":["fieldStyles","datePickerStyles"],"sources":["../../src/time-input/TimeInput.tsx"],"sourcesContent":["import {\n DateInput,\n DateSegment,\n TimeField,\n type TimeFieldProps,\n type TimeValue,\n} from 'react-aria-components';\n\nimport datePickerStyles from '../date-picker/DatePicker.module.css';\nimport {\n type FieldChromeProps,\n FieldDescription,\n FieldErrors,\n FieldLabel,\n fieldStyles,\n} from '../field/FieldParts';\nimport { cx } from '../utils/cx';\n\nexport interface TimeInputProps\n extends\n Omit<\n TimeFieldProps<TimeValue>,\n 'className' | 'style' | 'children' | 'isInvalid' | 'validate'\n >,\n FieldChromeProps {\n controlClassName?: string;\n}\n\n/** A time of day, typed segment by segment in the format of the locale. */\nexport function TimeInput({\n label,\n description,\n errors = [],\n isRequired,\n isReadOnly,\n className,\n labelClassName,\n descriptionClassName,\n errorsClassName,\n controlClassName,\n ...props\n}: TimeInputProps) {\n return (\n <TimeField\n {...props}\n isRequired={isRequired}\n isReadOnly={isReadOnly}\n isInvalid={errors.length > 0}\n validationBehavior=\"aria\"\n className={cx(fieldStyles.field, className)}\n >\n <FieldLabel isRequired={isRequired} className={labelClassName}>\n {label}\n </FieldLabel>\n <DateInput\n className={cx(fieldStyles.control, datePickerStyles.input, controlClassName)}\n data-readonly={isReadOnly || undefined}\n >\n {(segment) => (\n <DateSegment segment={segment} className={datePickerStyles.segment} />\n )}\n </DateInput>\n <FieldDescription className={descriptionClassName}>{description}</FieldDescription>\n <FieldErrors errors={errors} className={errorsClassName} />\n </TimeField>\n );\n}\n"],"mappings":";;;;;;;;AA6BA,SAAgB,UAAU,EACtB,OACA,aACA,SAAS,CAAA,GACT,YACA,YACA,WACA,gBACA,sBACA,iBACA,kBACA,GAAG,SACY;CACf,OACI,qBAAC,WAAD;EACI,GAAI;EACQ;EACA;EACZ,WAAW,OAAO,SAAS;EAC3B,oBAAmB;EACnB,WAAW,GAAGA,qBAAY,OAAO,SAAS;EAN9C,UAAA;GAQI,oBAAC,YAAD;IAAwB;IAAY,WAAW;IAC1C,UAAA;GACO,CAAA;GACZ,oBAAC,WAAD;IACI,WAAW,GAAGA,qBAAY,SAASC,0BAAiB,OAAO,gBAAgB;IAC3E,iBAAe,cAAc,KAAA;IAE3B,WAAA,YACE,oBAAC,aAAD;KAAsB;KAAS,WAAWA,0BAAiB;IAAQ,CAAA;GAEhE,CAAA;GACX,oBAAC,kBAAD;IAAkB,WAAW;IAAuB,UAAA;GAA8B,CAAA;GAClF,oBAAC,aAAD;IAAqB;IAAQ,WAAW;GAAgB,CAAA;EACjD;;AAEnB"}
1
+ {"version":3,"file":"TimeInput.js","names":["fieldStyles","datePickerStyles"],"sources":["../../src/time-input/TimeInput.tsx"],"sourcesContent":["import {\n DateInput,\n DateSegment,\n TimeField,\n type TimeFieldProps,\n type TimeValue,\n} from 'react-aria-components';\n\nimport datePickerStyles from '../date-picker/DatePicker.module.css';\nimport {\n type FieldChromeProps,\n FieldDescription,\n FieldErrors,\n FieldLabel,\n fieldStyles,\n} from '../field/FieldParts';\nimport { cx } from '../utils/cx';\n\nexport interface TimeInputProps\n extends\n Omit<\n TimeFieldProps<TimeValue>,\n 'className' | 'style' | 'children' | 'isInvalid' | 'validate'\n >,\n FieldChromeProps {\n controlClassName?: string;\n}\n\n/** A time of day, typed segment by segment in the format of the locale. */\nexport function TimeInput({\n label,\n description,\n errors = [],\n isRequired,\n isReadOnly,\n className,\n labelClassName,\n descriptionClassName,\n errorsClassName,\n controlClassName,\n ...props\n}: TimeInputProps) {\n return (\n <TimeField\n {...props}\n isRequired={isRequired}\n isReadOnly={isReadOnly}\n isInvalid={errors.length > 0}\n validationBehavior=\"aria\"\n className={cx('panneau-time-input', fieldStyles.field, className)}\n >\n <FieldLabel isRequired={isRequired} className={labelClassName}>\n {label}\n </FieldLabel>\n <DateInput\n className={cx(fieldStyles.control, datePickerStyles.input, controlClassName)}\n data-readonly={isReadOnly || undefined}\n >\n {(segment) => (\n <DateSegment segment={segment} className={datePickerStyles.segment} />\n )}\n </DateInput>\n <FieldDescription className={descriptionClassName}>{description}</FieldDescription>\n <FieldErrors errors={errors} className={errorsClassName} />\n </TimeField>\n );\n}\n"],"mappings":";;;;;;;;AA6BA,SAAgB,UAAU,EACtB,OACA,aACA,SAAS,CAAA,GACT,YACA,YACA,WACA,gBACA,sBACA,iBACA,kBACA,GAAG,SACY;CACf,OACI,qBAAC,WAAD;EACI,GAAI;EACQ;EACA;EACZ,WAAW,OAAO,SAAS;EAC3B,oBAAmB;EACnB,WAAW,GAAG,sBAAsBA,qBAAY,OAAO,SAAS;EANpE,UAAA;GAQI,oBAAC,YAAD;IAAwB;IAAY,WAAW;IAC1C,UAAA;GACO,CAAA;GACZ,oBAAC,WAAD;IACI,WAAW,GAAGA,qBAAY,SAASC,0BAAiB,OAAO,gBAAgB;IAC3E,iBAAe,cAAc,KAAA;IAE3B,WAAA,YACE,oBAAC,aAAD;KAAsB;KAAS,WAAWA,0BAAiB;IAAQ,CAAA;GAEhE,CAAA;GACX,oBAAC,kBAAD;IAAkB,WAAW;IAAuB,UAAA;GAA8B,CAAA;GAClF,oBAAC,aAAD;IAAqB;IAAQ,WAAW;GAAgB,CAAA;EACjD;;AAEnB"}
@@ -1,5 +1,5 @@
1
1
  /* The region carries the root's class (tokens), since React Aria renders it in the body. */
2
- .panneau-region-wzx1vG.panneau-region-wzx1vG {
2
+ .panneau-toast-region.panneau-toast-region {
3
3
  position: fixed;
4
4
  inset-block-end: var(--panneau-space-4);
5
5
  inset-inline-end: var(--panneau-space-4);
@@ -7,81 +7,59 @@
7
7
  display: flex;
8
8
  flex-direction: column-reverse;
9
9
  gap: var(--panneau-space-2);
10
- width: min(24rem, calc(100vw - 2 * var(--panneau-space-4)));
10
+ width: min(var(--panneau-toast-width, 24rem), calc(100vw - 2 * var(--panneau-space-4)));
11
11
  background: transparent;
12
12
  outline: none;
13
13
  }
14
14
 
15
- .panneau-region-wzx1vG[data-focus-visible] {
15
+ .panneau-toast-region[data-focus-visible] {
16
16
  outline: var(--panneau-focus-width) solid var(--panneau-color-focus);
17
17
  outline-offset: 4px;
18
18
  }
19
19
 
20
20
  @media (max-width: 30rem) {
21
- .panneau-region-wzx1vG.panneau-region-wzx1vG {
21
+ .panneau-toast-region.panneau-toast-region {
22
22
  inset-inline: var(--panneau-space-2);
23
23
  inset-block-end: var(--panneau-space-2);
24
24
  width: auto;
25
25
  }
26
26
  }
27
27
 
28
- .panneau-toast-zcR9rJ {
28
+ .panneau-toast {
29
29
  display: flex;
30
30
  align-items: flex-start;
31
31
  gap: var(--panneau-space-3);
32
32
  padding: var(--panneau-space-3) var(--panneau-space-3) var(--panneau-space-3)
33
33
  var(--panneau-space-4);
34
34
  color: var(--panneau-color-text);
35
- background-color: var(--panneau-color-surface-raised);
36
- border: var(--panneau-border-width) solid var(--panneau-color-border);
37
- border-inline-start-width: 4px;
38
- border-radius: var(--panneau-radius-lg);
39
- box-shadow: var(--panneau-shadow-lg);
35
+ background-color: var(--panneau-toast-bg, var(--panneau-color-surface-raised));
36
+ border: var(--panneau-border-width) solid
37
+ var(--panneau-toast-border-color, var(--panneau-color-border));
38
+ border-inline-start-width: var(--panneau-toast-tone-width, 4px);
39
+ border-radius: var(--panneau-toast-radius, var(--panneau-radius-lg));
40
+ box-shadow: var(--panneau-toast-shadow, var(--panneau-shadow-lg));
40
41
  outline: none;
41
42
  }
42
43
 
43
- .panneau-toast-zcR9rJ[data-focus-visible] {
44
+ .panneau-toast[data-focus-visible] {
44
45
  outline: var(--panneau-focus-width) solid var(--panneau-color-focus);
45
46
  outline-offset: 2px;
46
47
  }
47
48
 
48
- .panneau-success-bKO-t0 {
49
- border-inline-start-color: var(--panneau-color-success);
50
- }
51
-
52
- .panneau-danger-xAgJYb {
53
- border-inline-start-color: var(--panneau-color-danger);
54
- }
55
-
56
- .panneau-warning-8eqKky {
57
- border-inline-start-color: var(--panneau-color-warning);
58
- }
59
-
60
- .panneau-info-3p-uFF {
61
- border-inline-start-color: var(--panneau-color-info);
62
- }
63
-
64
- .panneau-icon-xCysks {
49
+ .panneau-toast-icon {
65
50
  margin-top: 0.125rem;
66
51
  }
67
52
 
68
- .panneau-success-bKO-t0 .panneau-icon-xCysks {
69
- color: var(--panneau-color-success);
70
- }
71
-
72
- .panneau-danger-xAgJYb .panneau-icon-xCysks {
73
- color: var(--panneau-color-danger);
74
- }
75
-
76
- .panneau-warning-8eqKky .panneau-icon-xCysks {
77
- color: var(--panneau-color-warning);
53
+ /* A toast with a tone other than neutral: a colored edge and icon, from its tone class. */
54
+ .panneau-toast-toned {
55
+ border-inline-start-color: var(--panneau-tone-text);
78
56
  }
79
57
 
80
- .panneau-info-3p-uFF .panneau-icon-xCysks {
81
- color: var(--panneau-color-info);
58
+ .panneau-toast-toned .panneau-toast-icon {
59
+ color: var(--panneau-tone-text);
82
60
  }
83
61
 
84
- .panneau-content-oL01to {
62
+ .panneau-toast-content {
85
63
  display: flex;
86
64
  flex: 1 1 auto;
87
65
  flex-direction: column;
@@ -90,18 +68,18 @@
90
68
  padding-top: 0.125rem;
91
69
  }
92
70
 
93
- .panneau-title-ZUmw4H {
71
+ .panneau-toast-title {
94
72
  font-weight: var(--panneau-font-weight-medium);
95
73
  overflow-wrap: anywhere;
96
74
  }
97
75
 
98
- .panneau-description-bQFVpf {
76
+ .panneau-toast-description {
99
77
  font-size: var(--panneau-font-size-sm);
100
78
  color: var(--panneau-color-text-muted);
101
79
  overflow-wrap: anywhere;
102
80
  }
103
81
 
104
- .panneau-actions-4GKOfg {
82
+ .panneau-toast-actions {
105
83
  display: flex;
106
84
  flex: 0 0 auto;
107
85
  align-items: center;
@@ -1,11 +1,13 @@
1
1
  import { type ReactNode } from 'react';
2
- export type ToastTone = 'neutral' | 'success' | 'danger' | 'warning' | 'info';
2
+ import type { Tone } from '../theme/tones';
3
+ /** @deprecated Use `Tone`. */
4
+ export type ToastTone = Tone;
3
5
  /** What a toast says. */
4
6
  export interface ToastContent {
5
7
  title: string;
6
8
  description?: string;
7
- /** Defaults to `neutral`. */
8
- tone?: ToastTone;
9
+ /** Defaults to `neutral`. Any tone other than neutral colors the edge and the icon. */
10
+ tone?: Tone;
9
11
  /** A button in the toast, such as "Retry" or "Undo". The toast closes when it is pressed. */
10
12
  action?: {
11
13
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../src/toast/Toast.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAgC,MAAM,OAAO,CAAC;AAiBrE,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9E,yBAAyB;AACzB,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,6FAA6F;IAC7F,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CACpD;AAED,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,MAAM;IACnB,sCAAsC;IACtC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAC5D,6BAA6B;IAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAYD,iDAAiD;AACjD,wBAAgB,QAAQ,IAAI,MAAM,CAMjC;AAED,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC9D;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,EAAE,kBAAkB,+BAqE3F"}
1
+ {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../src/toast/Toast.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAgC,MAAM,OAAO,CAAC;AAerE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAI3C,8BAA8B;AAC9B,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC;AAE7B,yBAAyB;AACzB,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,6FAA6F;IAC7F,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CACpD;AAED,MAAM,WAAW,YAAY;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,MAAM;IACnB,sCAAsC;IACtC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAC5D,6BAA6B;IAC7B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAYD,iDAAiD;AACjD,wBAAgB,QAAQ,IAAI,MAAM,CAMjC;AAED,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC9D;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,EAAE,kBAAkB,+BA6E3F"}