eidos-ui 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/README.md +66 -16
  2. package/dist/Avatar.types-BY-C09Ke.d.cts +23 -0
  3. package/dist/Avatar.types-BY-C09Ke.d.ts +23 -0
  4. package/dist/{Header.types-BZi80bWz.d.cts → Header.types-B3QtuiL-.d.cts} +7 -3
  5. package/dist/{Header.types-DJt-q01P.d.ts → Header.types-C6w0FBY8.d.ts} +7 -3
  6. package/dist/{Table.types-Cl5gR8r9.d.cts → Table.types-CPj-udMc.d.cts} +95 -0
  7. package/dist/{Table.types-jhPb7JNU.d.ts → Table.types-CZZ7QWAI.d.ts} +95 -0
  8. package/dist/ThemeProvider.types-DgXN0gEH.d.cts +88 -0
  9. package/dist/ThemeProvider.types-DgXN0gEH.d.ts +88 -0
  10. package/dist/Toolbar.types-DSk8z2iy.d.cts +38 -0
  11. package/dist/Toolbar.types-RN0klQzu.d.ts +38 -0
  12. package/dist/alert/index.cjs +4 -4
  13. package/dist/alert/index.d.cts +2 -1
  14. package/dist/alert/index.d.ts +2 -1
  15. package/dist/alert/index.js +3 -3
  16. package/dist/avatar/index.d.cts +3 -21
  17. package/dist/avatar/index.d.ts +3 -21
  18. package/dist/button/index.cjs +3 -3
  19. package/dist/button/index.js +2 -2
  20. package/dist/chip/index.cjs +3 -3
  21. package/dist/chip/index.js +2 -2
  22. package/dist/chunk-2ZY7M72Q.js +521 -0
  23. package/dist/chunk-2ZY7M72Q.js.map +1 -0
  24. package/dist/{chunk-KIXFSXIN.cjs → chunk-3E7TKBQI.cjs} +5 -3
  25. package/dist/chunk-3E7TKBQI.cjs.map +1 -0
  26. package/dist/{chunk-ZBKJ3EMK.cjs → chunk-442U3W6R.cjs} +3 -3
  27. package/dist/{chunk-ZBKJ3EMK.cjs.map → chunk-442U3W6R.cjs.map} +1 -1
  28. package/dist/{chunk-W6IKHJ76.cjs → chunk-5BX4Q76D.cjs} +134 -126
  29. package/dist/chunk-5BX4Q76D.cjs.map +1 -0
  30. package/dist/{chunk-YQLCPKGV.js → chunk-5HUZYY54.js} +6 -4
  31. package/dist/chunk-5HUZYY54.js.map +1 -0
  32. package/dist/{chunk-G5IGADJI.cjs → chunk-5VM2256W.cjs} +7 -11
  33. package/dist/chunk-5VM2256W.cjs.map +1 -0
  34. package/dist/{chunk-Z4ZY7L7W.js → chunk-5ZL6PYU3.js} +3 -3
  35. package/dist/{chunk-A3NE2C7C.js → chunk-67RFMV6K.js} +2 -2
  36. package/dist/{chunk-2U7UJOOB.cjs → chunk-6HUHH6Y4.cjs} +17 -15
  37. package/dist/chunk-6HUHH6Y4.cjs.map +1 -0
  38. package/dist/{chunk-5WROPW7Z.js → chunk-A7WQINIG.js} +3 -3
  39. package/dist/{chunk-DKZTDYH5.cjs → chunk-AAA6TR5I.cjs} +3 -3
  40. package/dist/{chunk-DKZTDYH5.cjs.map → chunk-AAA6TR5I.cjs.map} +1 -1
  41. package/dist/{chunk-A7Z2QAFZ.cjs → chunk-APK5OQRV.cjs} +5 -5
  42. package/dist/{chunk-A7Z2QAFZ.cjs.map → chunk-APK5OQRV.cjs.map} +1 -1
  43. package/dist/{chunk-ISABZ2VX.cjs → chunk-AXBYJ2OY.cjs} +9 -9
  44. package/dist/{chunk-ISABZ2VX.cjs.map → chunk-AXBYJ2OY.cjs.map} +1 -1
  45. package/dist/{chunk-6RGJAQCU.cjs → chunk-B5G5XVFJ.cjs} +5 -5
  46. package/dist/{chunk-6RGJAQCU.cjs.map → chunk-B5G5XVFJ.cjs.map} +1 -1
  47. package/dist/{chunk-MW2S7PZ7.cjs → chunk-D5IY2HUV.cjs} +5 -5
  48. package/dist/{chunk-MW2S7PZ7.cjs.map → chunk-D5IY2HUV.cjs.map} +1 -1
  49. package/dist/{chunk-FMPXSF3H.cjs → chunk-DAXZRNNO.cjs} +4 -4
  50. package/dist/{chunk-FMPXSF3H.cjs.map → chunk-DAXZRNNO.cjs.map} +1 -1
  51. package/dist/{chunk-AJZTVCST.js → chunk-EXITZVB2.js} +24 -9
  52. package/dist/chunk-EXITZVB2.js.map +1 -0
  53. package/dist/{chunk-AYMD4D4M.cjs → chunk-EZME5CLK.cjs} +3 -3
  54. package/dist/{chunk-AYMD4D4M.cjs.map → chunk-EZME5CLK.cjs.map} +1 -1
  55. package/dist/{chunk-IV4LM3MB.js → chunk-F26VIKNF.js} +9 -11
  56. package/dist/chunk-F26VIKNF.js.map +1 -0
  57. package/dist/{chunk-WPTMMOA6.cjs → chunk-G77YR73R.cjs} +10 -13
  58. package/dist/chunk-G77YR73R.cjs.map +1 -0
  59. package/dist/chunk-GEHL4LKK.cjs +32 -0
  60. package/dist/chunk-GEHL4LKK.cjs.map +1 -0
  61. package/dist/chunk-GGSII6Y2.cjs +921 -0
  62. package/dist/chunk-GGSII6Y2.cjs.map +1 -0
  63. package/dist/{chunk-3VRMTWUS.js → chunk-GHQ6SQPI.js} +7 -10
  64. package/dist/chunk-GHQ6SQPI.js.map +1 -0
  65. package/dist/{chunk-56B6RLOE.js → chunk-GI6VJYOS.js} +4 -4
  66. package/dist/{chunk-56B6RLOE.js.map → chunk-GI6VJYOS.js.map} +1 -1
  67. package/dist/{chunk-UGMONQGH.cjs → chunk-GR2PMCVN.cjs} +10 -12
  68. package/dist/chunk-GR2PMCVN.cjs.map +1 -0
  69. package/dist/{chunk-7AHZTHXR.cjs → chunk-GT22EGJP.cjs} +5 -5
  70. package/dist/{chunk-7AHZTHXR.cjs.map → chunk-GT22EGJP.cjs.map} +1 -1
  71. package/dist/chunk-H5HWFOWZ.js +390 -0
  72. package/dist/chunk-H5HWFOWZ.js.map +1 -0
  73. package/dist/{chunk-ALGX5X4N.js → chunk-IFVT5UCY.js} +3 -3
  74. package/dist/{chunk-5CLC3FJO.js → chunk-KBG77JHC.js} +13 -2
  75. package/dist/chunk-KBG77JHC.js.map +1 -0
  76. package/dist/{chunk-HLNKIAE5.cjs → chunk-KJZUYC4X.cjs} +5 -5
  77. package/dist/{chunk-HLNKIAE5.cjs.map → chunk-KJZUYC4X.cjs.map} +1 -1
  78. package/dist/{chunk-JV7Z3D3U.js → chunk-LEMCJW57.js} +134 -126
  79. package/dist/chunk-LEMCJW57.js.map +1 -0
  80. package/dist/{chunk-4BQM5F76.cjs → chunk-LFWPQYWX.cjs} +3 -3
  81. package/dist/{chunk-4BQM5F76.cjs.map → chunk-LFWPQYWX.cjs.map} +1 -1
  82. package/dist/{chunk-XVSODE4K.cjs → chunk-LIFUHQH5.cjs} +35 -20
  83. package/dist/chunk-LIFUHQH5.cjs.map +1 -0
  84. package/dist/{chunk-PJC7NZUV.cjs → chunk-LUL6RZ4M.cjs} +3 -3
  85. package/dist/{chunk-PJC7NZUV.cjs.map → chunk-LUL6RZ4M.cjs.map} +1 -1
  86. package/dist/{chunk-4UJ7LG4W.cjs → chunk-N2IGZIEX.cjs} +3 -3
  87. package/dist/{chunk-4UJ7LG4W.cjs.map → chunk-N2IGZIEX.cjs.map} +1 -1
  88. package/dist/{chunk-3LHQUOGP.js → chunk-NGVOXM7P.js} +3 -3
  89. package/dist/{chunk-WTXASLBB.js → chunk-O5WEKLNF.js} +2 -2
  90. package/dist/{chunk-BOB5JJ7F.js → chunk-P7IQY5YH.js} +2 -2
  91. package/dist/{chunk-VZYLJSV5.js → chunk-R4PU2TBM.js} +2 -2
  92. package/dist/{chunk-P2GCAVUZ.js → chunk-RAZRQ57B.js} +2 -2
  93. package/dist/{chunk-K7IFNKMN.js → chunk-REVK7IGN.js} +2 -2
  94. package/dist/{chunk-6U2H26A4.cjs → chunk-RHOT7AEI.cjs} +3 -3
  95. package/dist/{chunk-6U2H26A4.cjs.map → chunk-RHOT7AEI.cjs.map} +1 -1
  96. package/dist/{chunk-MH2CD2QT.js → chunk-RKA2OJRT.js} +207 -102
  97. package/dist/chunk-RKA2OJRT.js.map +1 -0
  98. package/dist/{chunk-JC4WLVBG.js → chunk-RWOX2NJN.js} +2 -2
  99. package/dist/{chunk-4LM33LDV.js → chunk-S3CT536K.js} +2 -2
  100. package/dist/chunk-SE7MWOC7.cjs +390 -0
  101. package/dist/chunk-SE7MWOC7.cjs.map +1 -0
  102. package/dist/{chunk-4M3LZLOH.js → chunk-SHYSLWQG.js} +2 -2
  103. package/dist/{chunk-EQEV7GPT.cjs → chunk-SKEWTQJ7.cjs} +5 -5
  104. package/dist/{chunk-EQEV7GPT.cjs.map → chunk-SKEWTQJ7.cjs.map} +1 -1
  105. package/dist/{chunk-2ZENLZEQ.cjs → chunk-SKTDGCWJ.cjs} +232 -127
  106. package/dist/chunk-SKTDGCWJ.cjs.map +1 -0
  107. package/dist/{chunk-2BXCIWL7.js → chunk-SN6EWQDJ.js} +3 -3
  108. package/dist/{chunk-DW2YDWGN.js → chunk-TEJIPPZR.js} +2 -2
  109. package/dist/{chunk-OGKD5PLS.cjs → chunk-TRLBYA5G.cjs} +4 -4
  110. package/dist/{chunk-OGKD5PLS.cjs.map → chunk-TRLBYA5G.cjs.map} +1 -1
  111. package/dist/chunk-U5FHQ73U.cjs +521 -0
  112. package/dist/chunk-U5FHQ73U.cjs.map +1 -0
  113. package/dist/{chunk-WE5FTQGD.js → chunk-VHMOKXUT.js} +3 -7
  114. package/dist/chunk-VHMOKXUT.js.map +1 -0
  115. package/dist/{chunk-S77GR5YQ.cjs → chunk-VHQTDITV.cjs} +3 -3
  116. package/dist/{chunk-S77GR5YQ.cjs.map → chunk-VHQTDITV.cjs.map} +1 -1
  117. package/dist/{chunk-3HMKE2GJ.js → chunk-VSTQEHVZ.js} +6 -4
  118. package/dist/chunk-VSTQEHVZ.js.map +1 -0
  119. package/dist/{chunk-HNUTV3HR.cjs → chunk-WUBQJVB7.cjs} +3 -3
  120. package/dist/{chunk-HNUTV3HR.cjs.map → chunk-WUBQJVB7.cjs.map} +1 -1
  121. package/dist/{chunk-S7TWEVC3.js → chunk-Y53HCLGW.js} +2 -2
  122. package/dist/{chunk-WIE7HDIM.js → chunk-YJXZR7RL.js} +2 -2
  123. package/dist/{chunk-IJYYHBZC.cjs → chunk-Z4SLV6WG.cjs} +3 -3
  124. package/dist/{chunk-IJYYHBZC.cjs.map → chunk-Z4SLV6WG.cjs.map} +1 -1
  125. package/dist/chunk-ZEZK664O.js +921 -0
  126. package/dist/chunk-ZEZK664O.js.map +1 -0
  127. package/dist/{chunk-JMD3P4CY.js → chunk-ZHFPV43D.js} +2 -2
  128. package/dist/color-picker/index.cjs +2 -2
  129. package/dist/color-picker/index.js +1 -1
  130. package/dist/combobox/index.cjs +4 -4
  131. package/dist/combobox/index.js +3 -3
  132. package/dist/context-menu/index.cjs +4 -4
  133. package/dist/context-menu/index.js +3 -3
  134. package/dist/data-grid/index.cjs +13 -13
  135. package/dist/data-grid/index.d.cts +49 -3
  136. package/dist/data-grid/index.d.ts +49 -3
  137. package/dist/data-grid/index.js +12 -12
  138. package/dist/date-picker/index.cjs +6 -6
  139. package/dist/date-picker/index.js +5 -5
  140. package/dist/drawer/index.cjs +4 -4
  141. package/dist/drawer/index.d.cts +2 -1
  142. package/dist/drawer/index.d.ts +2 -1
  143. package/dist/drawer/index.js +3 -3
  144. package/dist/empty-state/index.d.cts +2 -2
  145. package/dist/empty-state/index.d.ts +2 -2
  146. package/dist/fonts/JetBrains-Mono-OFL.txt +93 -0
  147. package/dist/fonts/Plus-Jakarta-Sans-OFL.txt +93 -0
  148. package/dist/fonts/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
  149. package/dist/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
  150. package/dist/fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2 +0 -0
  151. package/dist/fonts/plus-jakarta-sans-latin-wght-normal.woff2 +0 -0
  152. package/dist/fonts.css +32 -0
  153. package/dist/fonts.css.d.ts +2 -0
  154. package/dist/header/index.cjs +4 -4
  155. package/dist/header/index.d.cts +2 -2
  156. package/dist/header/index.d.ts +2 -2
  157. package/dist/header/index.js +3 -3
  158. package/dist/index.cjs +59 -33
  159. package/dist/index.cjs.map +1 -1
  160. package/dist/index.css +625 -174
  161. package/dist/index.d.cts +8 -4
  162. package/dist/index.d.ts +8 -4
  163. package/dist/index.js +62 -36
  164. package/dist/inline-edit/index.cjs +4 -4
  165. package/dist/inline-edit/index.js +3 -3
  166. package/dist/input/index.cjs +3 -3
  167. package/dist/input/index.js +2 -2
  168. package/dist/menu/index.cjs +3 -3
  169. package/dist/menu/index.js +2 -2
  170. package/dist/modal/index.cjs +4 -4
  171. package/dist/modal/index.d.cts +2 -1
  172. package/dist/modal/index.d.ts +2 -1
  173. package/dist/modal/index.js +3 -3
  174. package/dist/navigation/index.cjs +4 -4
  175. package/dist/navigation/index.js +3 -3
  176. package/dist/page-layout/index.cjs +8 -8
  177. package/dist/page-layout/index.d.cts +3 -2
  178. package/dist/page-layout/index.d.ts +3 -2
  179. package/dist/page-layout/index.js +7 -7
  180. package/dist/pagination/index.cjs +6 -6
  181. package/dist/pagination/index.js +5 -5
  182. package/dist/popover/index.cjs +2 -2
  183. package/dist/popover/index.d.cts +2 -2
  184. package/dist/popover/index.d.ts +2 -2
  185. package/dist/popover/index.js +1 -1
  186. package/dist/segmented-control/index.cjs +3 -3
  187. package/dist/segmented-control/index.js +2 -2
  188. package/dist/select/index.cjs +4 -4
  189. package/dist/select/index.js +3 -3
  190. package/dist/snackbar/index.cjs +4 -4
  191. package/dist/snackbar/index.js +3 -3
  192. package/dist/split-button/index.cjs +4 -4
  193. package/dist/split-button/index.js +3 -3
  194. package/dist/table/index.cjs +11 -11
  195. package/dist/table/index.d.cts +3 -3
  196. package/dist/table/index.d.ts +3 -3
  197. package/dist/table/index.js +10 -10
  198. package/dist/tabs/index.cjs +3 -3
  199. package/dist/tabs/index.js +2 -2
  200. package/dist/tag-input/index.cjs +4 -4
  201. package/dist/tag-input/index.js +3 -3
  202. package/dist/textarea/index.cjs +3 -3
  203. package/dist/textarea/index.js +2 -2
  204. package/dist/theme-editor/index.cjs +22 -0
  205. package/dist/theme-editor/index.cjs.map +1 -0
  206. package/dist/theme-editor/index.d.cts +65 -0
  207. package/dist/theme-editor/index.d.ts +65 -0
  208. package/dist/theme-editor/index.js +22 -0
  209. package/dist/theme-editor/index.js.map +1 -0
  210. package/dist/theme-provider/index.cjs +27 -0
  211. package/dist/theme-provider/index.cjs.map +1 -0
  212. package/dist/theme-provider/index.d.cts +123 -0
  213. package/dist/theme-provider/index.d.ts +123 -0
  214. package/dist/theme-provider/index.js +27 -0
  215. package/dist/theme-provider/index.js.map +1 -0
  216. package/dist/toolbar/index.cjs +5 -5
  217. package/dist/toolbar/index.d.cts +3 -2
  218. package/dist/toolbar/index.d.ts +3 -2
  219. package/dist/toolbar/index.js +4 -4
  220. package/package.json +17 -6
  221. package/dist/Toolbar.types-BGD57Uhm.d.ts +0 -22
  222. package/dist/Toolbar.types-tQkLmPIu.d.cts +0 -22
  223. package/dist/chunk-2U7UJOOB.cjs.map +0 -1
  224. package/dist/chunk-2ZENLZEQ.cjs.map +0 -1
  225. package/dist/chunk-3HMKE2GJ.js.map +0 -1
  226. package/dist/chunk-3VRMTWUS.js.map +0 -1
  227. package/dist/chunk-5CLC3FJO.js.map +0 -1
  228. package/dist/chunk-AJZTVCST.js.map +0 -1
  229. package/dist/chunk-G5IGADJI.cjs.map +0 -1
  230. package/dist/chunk-GOR642KK.cjs +0 -21
  231. package/dist/chunk-GOR642KK.cjs.map +0 -1
  232. package/dist/chunk-IV4LM3MB.js.map +0 -1
  233. package/dist/chunk-JV7Z3D3U.js.map +0 -1
  234. package/dist/chunk-KIXFSXIN.cjs.map +0 -1
  235. package/dist/chunk-MH2CD2QT.js.map +0 -1
  236. package/dist/chunk-QONDJ5VM.cjs +0 -744
  237. package/dist/chunk-QONDJ5VM.cjs.map +0 -1
  238. package/dist/chunk-UGMONQGH.cjs.map +0 -1
  239. package/dist/chunk-VSFKM7FE.js +0 -744
  240. package/dist/chunk-VSFKM7FE.js.map +0 -1
  241. package/dist/chunk-W6IKHJ76.cjs.map +0 -1
  242. package/dist/chunk-WE5FTQGD.js.map +0 -1
  243. package/dist/chunk-WPTMMOA6.cjs.map +0 -1
  244. package/dist/chunk-XVSODE4K.cjs.map +0 -1
  245. package/dist/chunk-YQLCPKGV.js.map +0 -1
  246. /package/dist/{chunk-Z4ZY7L7W.js.map → chunk-5ZL6PYU3.js.map} +0 -0
  247. /package/dist/{chunk-A3NE2C7C.js.map → chunk-67RFMV6K.js.map} +0 -0
  248. /package/dist/{chunk-5WROPW7Z.js.map → chunk-A7WQINIG.js.map} +0 -0
  249. /package/dist/{chunk-ALGX5X4N.js.map → chunk-IFVT5UCY.js.map} +0 -0
  250. /package/dist/{chunk-3LHQUOGP.js.map → chunk-NGVOXM7P.js.map} +0 -0
  251. /package/dist/{chunk-WTXASLBB.js.map → chunk-O5WEKLNF.js.map} +0 -0
  252. /package/dist/{chunk-BOB5JJ7F.js.map → chunk-P7IQY5YH.js.map} +0 -0
  253. /package/dist/{chunk-VZYLJSV5.js.map → chunk-R4PU2TBM.js.map} +0 -0
  254. /package/dist/{chunk-P2GCAVUZ.js.map → chunk-RAZRQ57B.js.map} +0 -0
  255. /package/dist/{chunk-K7IFNKMN.js.map → chunk-REVK7IGN.js.map} +0 -0
  256. /package/dist/{chunk-JC4WLVBG.js.map → chunk-RWOX2NJN.js.map} +0 -0
  257. /package/dist/{chunk-4LM33LDV.js.map → chunk-S3CT536K.js.map} +0 -0
  258. /package/dist/{chunk-4M3LZLOH.js.map → chunk-SHYSLWQG.js.map} +0 -0
  259. /package/dist/{chunk-2BXCIWL7.js.map → chunk-SN6EWQDJ.js.map} +0 -0
  260. /package/dist/{chunk-DW2YDWGN.js.map → chunk-TEJIPPZR.js.map} +0 -0
  261. /package/dist/{chunk-S7TWEVC3.js.map → chunk-Y53HCLGW.js.map} +0 -0
  262. /package/dist/{chunk-WIE7HDIM.js.map → chunk-YJXZR7RL.js.map} +0 -0
  263. /package/dist/{chunk-JMD3P4CY.js.map → chunk-ZHFPV43D.js.map} +0 -0
package/README.md CHANGED
@@ -19,14 +19,14 @@
19
19
 
20
20
  ## Features
21
21
 
22
- | | |
23
- | ------------------- | ---------------------------------------------------------------------------------------------------------------------- |
24
- | **Themeable** | Every design token is a CSS custom property, so palette, spacing, and radii can be overridden without touching source. |
25
- | **Type-safe** | Written in TypeScript with full prop typings exported for every component. |
26
- | **Tree-shakeable** | Per-component entry points (`eidos-ui/button`, `eidos-ui/table`, ...) keep bundles lean. |
27
- | **Icon-agnostic** | Works with any icon library - Lucide, MUI Icons, Font Awesome, Remix Icons, or your own. |
28
- | **Accessible** | Built with keyboard navigation and ARIA semantics in mind. |
29
- | **Optimized build** | Bundled with tsup, shipping both ESM and CJS with source maps and `.d.ts` files. |
22
+ | | |
23
+ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
24
+ | **Themeable** | Every design token is a CSS custom property. Override them statically, or let users change the palette and typography at runtime with `ThemeProvider`. |
25
+ | **Type-safe** | Written in TypeScript with full prop typings exported for every component. |
26
+ | **Tree-shakeable** | Per-component entry points (`eidos-ui/button`, `eidos-ui/table`, ...) keep bundles lean. |
27
+ | **Icon-agnostic** | Works with any icon library - Lucide, MUI Icons, Font Awesome, Remix Icons, or your own. |
28
+ | **Accessible** | Built with keyboard navigation and ARIA semantics in mind. |
29
+ | **Optimized build** | Bundled with tsup, shipping both ESM and CJS with source maps and `.d.ts` files. |
30
30
 
31
31
  ## Installation
32
32
 
@@ -45,6 +45,7 @@ npm install lucide-react
45
45
  ```tsx
46
46
  import { Button, Tooltip } from 'eidos-ui';
47
47
  import 'eidos-ui/styles';
48
+ import 'eidos-ui/fonts'; // optional - bundled Plus Jakarta Sans + JetBrains Mono
48
49
 
49
50
  function App() {
50
51
  return (
@@ -91,6 +92,11 @@ These are the same groups used in Storybook, so the README and the docs sidebar
91
92
  - Toolbar
92
93
  - Breadcrumb
93
94
 
95
+ **Theming**
96
+
97
+ - ThemeProvider
98
+ - ThemeEditor
99
+
94
100
  **Elements**
95
101
 
96
102
  - Button
@@ -120,7 +126,6 @@ These are the same groups used in Storybook, so the README and the docs sidebar
120
126
  - Switch
121
127
  - Slider
122
128
  - ColorPicker
123
- - DatePicker
124
129
  - OTPInput
125
130
  - TagInput
126
131
  - FileUpload
@@ -139,7 +144,9 @@ These are the same groups used in Storybook, so the README and the docs sidebar
139
144
  **Data**
140
145
 
141
146
  - Table
147
+ - TableFiltersDropdown
142
148
  - DataGrid
149
+ - DatePicker
143
150
  - Timeline
144
151
  - VirtualList
145
152
 
@@ -180,15 +187,19 @@ npm run storybook
180
187
 
181
188
  ## Theming
182
189
 
183
- All design tokens are exposed as CSS custom properties, so themes can be overridden globally without touching component source.
190
+ Every design token is a CSS custom property. There are two ways to change them, depending on whether the theme is fixed at build time or chosen by the user.
191
+
192
+ ### Static overrides
193
+
194
+ Redeclare any token in your own stylesheet:
184
195
 
185
196
  ```css
186
197
  :root {
187
- /* Colors */
188
- --primary-color: #6366f1;
189
- --secondary-color: #ec4899;
198
+ /* Colours - each family also has -dark, -light, -rgb and -contrast */
199
+ --primary-color: #5c5de8;
200
+ --secondary-color: #617087;
190
201
 
191
- /* Spacing */
202
+ /* Spacing (em-based, so it scales with font size) */
192
203
  --spacing-md: 1em;
193
204
  --spacing-lg: 1.5em;
194
205
 
@@ -197,15 +208,54 @@ All design tokens are exposed as CSS custom properties, so themes can be overrid
197
208
  }
198
209
  ```
199
210
 
200
- Individual component styles can also be targeted directly, following each component's `eidos-<name>` BEM-style class names:
211
+ Individual components can also be targeted directly, following each component's `eidos-<name>` BEM-style class names:
201
212
 
202
213
  ```css
203
214
  .eidos-button--filled.eidos-button--primary {
204
215
  border-radius: 20px;
205
- background: linear-gradient(to right, #6366f1, #8b5cf6);
216
+ background: linear-gradient(to right, #5c5de8, #8b5cf6);
206
217
  }
207
218
  ```
208
219
 
220
+ ### Runtime theming
221
+
222
+ `ThemeProvider` applies a theme at runtime — for a settings screen, a per-tenant palette, or a colour a user picks. Supply one base colour per family and the shades, tints, ramp steps and accessible foregrounds are derived from it:
223
+
224
+ ```tsx
225
+ import { ThemeProvider, ThemeEditor } from 'eidos-ui';
226
+
227
+ <ThemeProvider defaultTheme={{ colors: { primary: '#0ea5e9' } }}>
228
+ <App />
229
+ </ThemeProvider>;
230
+ ```
231
+
232
+ `ThemeEditor` is a ready-made panel for editing the active theme, with live WCAG contrast readouts per colour:
233
+
234
+ ```tsx
235
+ <ThemeProvider theme={theme} onThemeChange={saveThemeForUser}>
236
+ <ThemeEditor />
237
+ <App />
238
+ </ThemeProvider>
239
+ ```
240
+
241
+ Ten things are editable — seven colour bases, two font stacks, and a font scale. Tokens are written through the CSSOM to `document.documentElement`, which needs **no Content Security Policy allowance** and covers portaled overlays too. A theme equal to the preset writes nothing at all.
242
+
243
+ Use `useTheme()` to read or change it from your own UI, and `toCss()` to export the resolved tokens as a `:root` block you can paste into a stylesheet — useful for baking a theme in at build time.
244
+
245
+ ### Fonts
246
+
247
+ The theme names Plus Jakarta Sans and JetBrains Mono, but a font stack only _names_ families — it cannot install them. Import the bundled copies to actually use them:
248
+
249
+ ```ts
250
+ import 'eidos-ui/fonts';
251
+ ```
252
+
253
+ This is a separate entry point because these are the only rules in the library that fetch a subresource; importing it means allowing `font-src 'self'` (already covered by `default-src 'self'`). Skip it and the stylesheet fetches nothing, falling back to system fonts.
254
+
255
+ For a font of your own, `registerFontFace(family, arrayBuffer)` registers one at runtime with no CSP allowance at all.
256
+
257
+ See the **Theming** and **Content Security Policy** pages in Storybook for the full reference.
258
+
209
259
  ## TypeScript
210
260
 
211
261
  Every component ships with exported prop types:
@@ -0,0 +1,23 @@
1
+ import React__default from 'react';
2
+
3
+ type AvatarSize = 'sm' | 'md' | 'lg';
4
+ type AvatarColor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'gray';
5
+ interface AvatarProps {
6
+ src?: string;
7
+ alt?: string;
8
+ name?: string;
9
+ size?: AvatarSize;
10
+ color?: AvatarColor;
11
+ shape?: 'circle' | 'square';
12
+ fallback?: React__default.ReactNode;
13
+ className?: string;
14
+ onClick?: () => void;
15
+ }
16
+ interface AvatarGroupProps {
17
+ children: React__default.ReactNode;
18
+ max?: number;
19
+ size?: AvatarSize;
20
+ className?: string;
21
+ }
22
+
23
+ export type { AvatarColor as A, AvatarGroupProps as a, AvatarProps as b, AvatarSize as c };
@@ -0,0 +1,23 @@
1
+ import React__default from 'react';
2
+
3
+ type AvatarSize = 'sm' | 'md' | 'lg';
4
+ type AvatarColor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'gray';
5
+ interface AvatarProps {
6
+ src?: string;
7
+ alt?: string;
8
+ name?: string;
9
+ size?: AvatarSize;
10
+ color?: AvatarColor;
11
+ shape?: 'circle' | 'square';
12
+ fallback?: React__default.ReactNode;
13
+ className?: string;
14
+ onClick?: () => void;
15
+ }
16
+ interface AvatarGroupProps {
17
+ children: React__default.ReactNode;
18
+ max?: number;
19
+ size?: AvatarSize;
20
+ className?: string;
21
+ }
22
+
23
+ export type { AvatarColor as A, AvatarGroupProps as a, AvatarProps as b, AvatarSize as c };
@@ -1,10 +1,14 @@
1
1
  import { T as TextButtonProps, I as IconButtonProps } from './Button.types-DZRCVqyN.cjs';
2
2
 
3
3
  interface HeaderProps {
4
- /** Page or section title. */
5
- title: string;
4
+ /**
5
+ * Page or section title. Accepts inline nodes alongside the text - a
6
+ * status `Pill`/`Chip` beside the title is the common case - not just a
7
+ * string. Keep the children inline-level; the title is a heading.
8
+ */
9
+ title: React.ReactNode;
6
10
  /** Supporting text rendered below the title. */
7
- subtitle?: string | React.ReactNode;
11
+ subtitle?: React.ReactNode;
8
12
  /** Trailing action buttons, rendered right-aligned. */
9
13
  actions?: HeaderActionProps[];
10
14
  className?: string;
@@ -1,10 +1,14 @@
1
1
  import { T as TextButtonProps, I as IconButtonProps } from './Button.types-BH0CPyPx.js';
2
2
 
3
3
  interface HeaderProps {
4
- /** Page or section title. */
5
- title: string;
4
+ /**
5
+ * Page or section title. Accepts inline nodes alongside the text - a
6
+ * status `Pill`/`Chip` beside the title is the common case - not just a
7
+ * string. Keep the children inline-level; the title is a heading.
8
+ */
9
+ title: React.ReactNode;
6
10
  /** Supporting text rendered below the title. */
7
- subtitle?: string | React.ReactNode;
11
+ subtitle?: React.ReactNode;
8
12
  /** Trailing action buttons, rendered right-aligned. */
9
13
  actions?: HeaderActionProps[];
10
14
  className?: string;
@@ -85,9 +85,30 @@ interface TableColumnCommon {
85
85
  }[];
86
86
  dateFilterMode?: 'single' | 'multiple' | 'range';
87
87
  width?: string;
88
+ /**
89
+ * Cell text alignment. Applies in table mode only: card view renders each
90
+ * field as a label above its value, where aligning the value away from its
91
+ * own label reads as a misalignment rather than a choice.
92
+ *
93
+ * Ignored on `type: 'icon'` and `type: 'action'` columns, which are always
94
+ * centred - they hold a single control in a fixed-width cell, so there is
95
+ * nothing to align it within. `DataGrid`'s actions column behaves the same.
96
+ */
88
97
  align?: 'left' | 'center' | 'right';
89
98
  /** Enables position:sticky on this column */
90
99
  pin?: 'left' | 'right';
100
+ /**
101
+ * Render this column's value as the card's title instead of a label:value
102
+ * field row. Only the first column with `cardHeader` set is used - if
103
+ * several are marked, the rest render as normal fields.
104
+ */
105
+ cardHeader?: boolean;
106
+ /**
107
+ * Render this column's value as the card's subtitle, directly under the
108
+ * `cardHeader` value. Only the first column with `cardSubheader` set is
109
+ * used. Has no effect without a `cardHeader` column also being set.
110
+ */
111
+ cardSubheader?: boolean;
91
112
  }
92
113
  /**
93
114
  * A column bound to the row field named by `key`, which is what lets `render`
@@ -170,7 +191,48 @@ interface TableProps<T extends object = Record<string, unknown>> {
170
191
  rowKey?: RowKey<T>;
171
192
  selectedRows?: string[];
172
193
  defaultSelectedRows?: string[];
194
+ /**
195
+ * Fires with every selected key, plus the row object for each of those keys.
196
+ *
197
+ * `selectedKeys` is authoritative; `selectedRows` is best-effort. The row
198
+ * for each selected key is cached, so a row selected while it was rendered
199
+ * still comes back after `data` has moved on - but a key that was selected
200
+ * before the table ever saw its row (seeded via `defaultSelectedRows`, say)
201
+ * has no row to hand back.
202
+ */
173
203
  onSelectionChange?: (selectedKeys: string[], selectedRows: T[]) => void;
204
+ /**
205
+ * What the select-all control acts on - the header checkbox in table mode,
206
+ * or the toolbar checkbox in card view (where there is no header row):
207
+ *
208
+ * - `'all'` - every row in `data`, across pages.
209
+ * - `'page'` - only the rows currently rendered.
210
+ *
211
+ * Either way it only ever adds to or removes from the rows in its own
212
+ * scope, so a selection made on another page survives.
213
+ *
214
+ * `'all'` can only reach the rows the table actually holds: if `data` is one
215
+ * page of a larger set (with `totalItems` describing the whole), it cannot
216
+ * know the keys of rows it has never received, and says so with a dev-only
217
+ * warning. Matches `DataGrid.selectAllScope`.
218
+ *
219
+ * @default 'all'
220
+ */
221
+ selectAllScope?: 'all' | 'page';
222
+ /**
223
+ * Resolves the keys of **every** row matching the current query, including
224
+ * rows not present in `data`. Supplying it adds a "Select all N" action to
225
+ * the toolbar once everything the table does hold is selected.
226
+ *
227
+ * Only relevant when `data` is a subset of a larger set and `totalItems`
228
+ * describes the whole - a table paginating its own `data` already has every
229
+ * key. Called with no arguments, may be async (the action shows a loading
230
+ * state), and whatever it returns replaces the selection.
231
+ *
232
+ * Matches `DataGrid.onSelectAllMatching`, which is where this mostly earns
233
+ * its keep: `DataGrid` has a real server-side pagination mode.
234
+ */
235
+ onSelectAllMatching?: () => string[] | Promise<string[]>;
174
236
  bulkActions?: BulkAction<T>[];
175
237
  density?: 'compact' | 'comfortable' | 'spacious';
176
238
  showColumnVisibility?: boolean;
@@ -178,6 +240,39 @@ interface TableProps<T extends object = Record<string, unknown>> {
178
240
  showDensity?: boolean;
179
241
  draggableColumns?: boolean;
180
242
  onColumnReorder?: (newColumns: TableColumn<T>[]) => void;
243
+ /**
244
+ * On by default: below `cardViewBreakpoint`, or once the table's own width
245
+ * can no longer fit every visible column at a usable width, swap the table
246
+ * for a stacked list of cards - one per row. Only the row rendering
247
+ * changes; the toolbar, pagination, filtering, sorting and selection all
248
+ * keep working. `draggableColumns` has no effect in card view (there are no
249
+ * column headers to drag).
250
+ *
251
+ * Matches `DataGridProps.hasCardView` - both components use the same
252
+ * defaults and the same measured-container logic. Set to `false` to always
253
+ * render a table.
254
+ *
255
+ * @default true
256
+ */
257
+ hasCardView?: boolean;
258
+ /**
259
+ * Container width (px) at/below which card view kicks in. This is an
260
+ * explicit floor - card view also switches on automatically, regardless
261
+ * of this value, once the container can't fit every visible column at a
262
+ * usable minimum width, so a many-column table never has to overflow
263
+ * horizontally waiting for a hand-tuned breakpoint.
264
+ *
265
+ * @default 640
266
+ */
267
+ cardViewBreakpoint?: number;
268
+ /**
269
+ * Cards lay out in a responsive grid (CSS `repeat(auto-fill, minmax(...))`)
270
+ * rather than one per row - this sets the minimum width (px) a card can
271
+ * shrink to before the next one wraps to a new row.
272
+ *
273
+ * @default 280
274
+ */
275
+ cardMinWidth?: number;
181
276
  }
182
277
 
183
278
  export type { BulkAction as B, FilterValue as F, RowKey as R, TableColumn as T, BulkActionButton as a, BulkActionSplitButton as b, BulkActionSplitOption as c, TableCustomColumn as d, TableFilters as e, TableProps as f, TableValueColumn as g };
@@ -85,9 +85,30 @@ interface TableColumnCommon {
85
85
  }[];
86
86
  dateFilterMode?: 'single' | 'multiple' | 'range';
87
87
  width?: string;
88
+ /**
89
+ * Cell text alignment. Applies in table mode only: card view renders each
90
+ * field as a label above its value, where aligning the value away from its
91
+ * own label reads as a misalignment rather than a choice.
92
+ *
93
+ * Ignored on `type: 'icon'` and `type: 'action'` columns, which are always
94
+ * centred - they hold a single control in a fixed-width cell, so there is
95
+ * nothing to align it within. `DataGrid`'s actions column behaves the same.
96
+ */
88
97
  align?: 'left' | 'center' | 'right';
89
98
  /** Enables position:sticky on this column */
90
99
  pin?: 'left' | 'right';
100
+ /**
101
+ * Render this column's value as the card's title instead of a label:value
102
+ * field row. Only the first column with `cardHeader` set is used - if
103
+ * several are marked, the rest render as normal fields.
104
+ */
105
+ cardHeader?: boolean;
106
+ /**
107
+ * Render this column's value as the card's subtitle, directly under the
108
+ * `cardHeader` value. Only the first column with `cardSubheader` set is
109
+ * used. Has no effect without a `cardHeader` column also being set.
110
+ */
111
+ cardSubheader?: boolean;
91
112
  }
92
113
  /**
93
114
  * A column bound to the row field named by `key`, which is what lets `render`
@@ -170,7 +191,48 @@ interface TableProps<T extends object = Record<string, unknown>> {
170
191
  rowKey?: RowKey<T>;
171
192
  selectedRows?: string[];
172
193
  defaultSelectedRows?: string[];
194
+ /**
195
+ * Fires with every selected key, plus the row object for each of those keys.
196
+ *
197
+ * `selectedKeys` is authoritative; `selectedRows` is best-effort. The row
198
+ * for each selected key is cached, so a row selected while it was rendered
199
+ * still comes back after `data` has moved on - but a key that was selected
200
+ * before the table ever saw its row (seeded via `defaultSelectedRows`, say)
201
+ * has no row to hand back.
202
+ */
173
203
  onSelectionChange?: (selectedKeys: string[], selectedRows: T[]) => void;
204
+ /**
205
+ * What the select-all control acts on - the header checkbox in table mode,
206
+ * or the toolbar checkbox in card view (where there is no header row):
207
+ *
208
+ * - `'all'` - every row in `data`, across pages.
209
+ * - `'page'` - only the rows currently rendered.
210
+ *
211
+ * Either way it only ever adds to or removes from the rows in its own
212
+ * scope, so a selection made on another page survives.
213
+ *
214
+ * `'all'` can only reach the rows the table actually holds: if `data` is one
215
+ * page of a larger set (with `totalItems` describing the whole), it cannot
216
+ * know the keys of rows it has never received, and says so with a dev-only
217
+ * warning. Matches `DataGrid.selectAllScope`.
218
+ *
219
+ * @default 'all'
220
+ */
221
+ selectAllScope?: 'all' | 'page';
222
+ /**
223
+ * Resolves the keys of **every** row matching the current query, including
224
+ * rows not present in `data`. Supplying it adds a "Select all N" action to
225
+ * the toolbar once everything the table does hold is selected.
226
+ *
227
+ * Only relevant when `data` is a subset of a larger set and `totalItems`
228
+ * describes the whole - a table paginating its own `data` already has every
229
+ * key. Called with no arguments, may be async (the action shows a loading
230
+ * state), and whatever it returns replaces the selection.
231
+ *
232
+ * Matches `DataGrid.onSelectAllMatching`, which is where this mostly earns
233
+ * its keep: `DataGrid` has a real server-side pagination mode.
234
+ */
235
+ onSelectAllMatching?: () => string[] | Promise<string[]>;
174
236
  bulkActions?: BulkAction<T>[];
175
237
  density?: 'compact' | 'comfortable' | 'spacious';
176
238
  showColumnVisibility?: boolean;
@@ -178,6 +240,39 @@ interface TableProps<T extends object = Record<string, unknown>> {
178
240
  showDensity?: boolean;
179
241
  draggableColumns?: boolean;
180
242
  onColumnReorder?: (newColumns: TableColumn<T>[]) => void;
243
+ /**
244
+ * On by default: below `cardViewBreakpoint`, or once the table's own width
245
+ * can no longer fit every visible column at a usable width, swap the table
246
+ * for a stacked list of cards - one per row. Only the row rendering
247
+ * changes; the toolbar, pagination, filtering, sorting and selection all
248
+ * keep working. `draggableColumns` has no effect in card view (there are no
249
+ * column headers to drag).
250
+ *
251
+ * Matches `DataGridProps.hasCardView` - both components use the same
252
+ * defaults and the same measured-container logic. Set to `false` to always
253
+ * render a table.
254
+ *
255
+ * @default true
256
+ */
257
+ hasCardView?: boolean;
258
+ /**
259
+ * Container width (px) at/below which card view kicks in. This is an
260
+ * explicit floor - card view also switches on automatically, regardless
261
+ * of this value, once the container can't fit every visible column at a
262
+ * usable minimum width, so a many-column table never has to overflow
263
+ * horizontally waiting for a hand-tuned breakpoint.
264
+ *
265
+ * @default 640
266
+ */
267
+ cardViewBreakpoint?: number;
268
+ /**
269
+ * Cards lay out in a responsive grid (CSS `repeat(auto-fill, minmax(...))`)
270
+ * rather than one per row - this sets the minimum width (px) a card can
271
+ * shrink to before the next one wraps to a new row.
272
+ *
273
+ * @default 280
274
+ */
275
+ cardMinWidth?: number;
181
276
  }
182
277
 
183
278
  export type { BulkAction as B, FilterValue as F, RowKey as R, TableColumn as T, BulkActionButton as a, BulkActionSplitButton as b, BulkActionSplitOption as c, TableCustomColumn as d, TableFilters as e, TableProps as f, TableValueColumn as g };
@@ -0,0 +1,88 @@
1
+ import React__default from 'react';
2
+
3
+ /** The seven themeable colour families. */
4
+ type ThemeColorKey = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'hyperlink';
5
+ /**
6
+ * A themeable colour: either a bare hex string, or an object that also pins the
7
+ * foreground to place on it.
8
+ *
9
+ * `contrast` exists because the provider writes tokens inline on
10
+ * `document.documentElement`, and inline styles beat author stylesheets - a
11
+ * consumer who must have a specific foreground could otherwise only override it
12
+ * with `!important`. Leave it unset to have it computed (see `pickContrast`).
13
+ */
14
+ type ThemeColorValue = string | {
15
+ base: string;
16
+ contrast?: string;
17
+ };
18
+ type ThemeColors = Partial<Record<ThemeColorKey, ThemeColorValue>>;
19
+ /** A selectable font stack, as offered by `ThemeEditor`. */
20
+ interface ThemeFontOption {
21
+ /** Display name, e.g. "Plus Jakarta Sans". */
22
+ label: string;
23
+ /** The full CSS font stack written to the token. */
24
+ value: string;
25
+ }
26
+ interface ThemeTypography {
27
+ /** Replaces `--font-family-primary`. A full CSS font stack. */
28
+ fontFamily?: string;
29
+ /** Replaces `--font-family-mono`. A full CSS font stack. */
30
+ monoFamily?: string;
31
+ /**
32
+ * Multiplier applied to all eight `--font-size-*` tokens. 1 is the preset.
33
+ *
34
+ * Note that `--spacing-*` is declared in `em`, so this scales most padding
35
+ * and gaps along with the text rather than only the glyphs.
36
+ */
37
+ fontScale?: number;
38
+ }
39
+ /**
40
+ * A theme. Every field is optional and anything omitted falls back to
41
+ * `defaultTheme`, so a theme may be as small as one colour.
42
+ *
43
+ * Named `ThemeConfig` rather than `Theme` to avoid colliding with the `Theme`
44
+ * exported by MUI, styled-components and others in a consumer's namespace.
45
+ */
46
+ interface ThemeConfig {
47
+ colors?: ThemeColors;
48
+ typography?: ThemeTypography;
49
+ }
50
+ /** A theme with every field populated - what the provider actually applies. */
51
+ interface ResolvedTheme {
52
+ colors: Record<ThemeColorKey, {
53
+ base: string;
54
+ contrast?: string;
55
+ }>;
56
+ typography: Required<ThemeTypography>;
57
+ }
58
+ interface ThemeContextValue {
59
+ /** The theme as supplied, with omitted fields left absent. */
60
+ theme: ThemeConfig;
61
+ /** The same theme with every field filled in from the preset. */
62
+ resolvedTheme: ResolvedTheme;
63
+ /** Replaces the whole theme. */
64
+ setTheme: (theme: ThemeConfig) => void;
65
+ /** Deep-merges a partial theme into the current one. */
66
+ updateTheme: (patch: ThemeConfig) => void;
67
+ /** Returns to the preset. */
68
+ resetTheme: () => void;
69
+ /** True when nothing differs from the preset, so no tokens are being written. */
70
+ isDefault: boolean;
71
+ /** The resolved theme as a `:root { … }` CSS block. */
72
+ toCss: () => string;
73
+ }
74
+ interface ThemeProviderProps {
75
+ children: React__default.ReactNode;
76
+ /**
77
+ * Controlled theme. Pair with `onThemeChange` and own persistence yourself -
78
+ * this is the mode to use when the theme comes from a user record on your
79
+ * server.
80
+ */
81
+ theme?: ThemeConfig;
82
+ /** Initial theme for uncontrolled usage. Ignored when `theme` is supplied. */
83
+ defaultTheme?: ThemeConfig;
84
+ /** Fires whenever the theme changes, in both controlled and uncontrolled mode. */
85
+ onThemeChange?: (theme: ThemeConfig) => void;
86
+ }
87
+
88
+ export type { ResolvedTheme as R, ThemeColorKey as T, ThemeColorValue as a, ThemeColors as b, ThemeConfig as c, ThemeContextValue as d, ThemeFontOption as e, ThemeProviderProps as f, ThemeTypography as g };
@@ -0,0 +1,88 @@
1
+ import React__default from 'react';
2
+
3
+ /** The seven themeable colour families. */
4
+ type ThemeColorKey = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'hyperlink';
5
+ /**
6
+ * A themeable colour: either a bare hex string, or an object that also pins the
7
+ * foreground to place on it.
8
+ *
9
+ * `contrast` exists because the provider writes tokens inline on
10
+ * `document.documentElement`, and inline styles beat author stylesheets - a
11
+ * consumer who must have a specific foreground could otherwise only override it
12
+ * with `!important`. Leave it unset to have it computed (see `pickContrast`).
13
+ */
14
+ type ThemeColorValue = string | {
15
+ base: string;
16
+ contrast?: string;
17
+ };
18
+ type ThemeColors = Partial<Record<ThemeColorKey, ThemeColorValue>>;
19
+ /** A selectable font stack, as offered by `ThemeEditor`. */
20
+ interface ThemeFontOption {
21
+ /** Display name, e.g. "Plus Jakarta Sans". */
22
+ label: string;
23
+ /** The full CSS font stack written to the token. */
24
+ value: string;
25
+ }
26
+ interface ThemeTypography {
27
+ /** Replaces `--font-family-primary`. A full CSS font stack. */
28
+ fontFamily?: string;
29
+ /** Replaces `--font-family-mono`. A full CSS font stack. */
30
+ monoFamily?: string;
31
+ /**
32
+ * Multiplier applied to all eight `--font-size-*` tokens. 1 is the preset.
33
+ *
34
+ * Note that `--spacing-*` is declared in `em`, so this scales most padding
35
+ * and gaps along with the text rather than only the glyphs.
36
+ */
37
+ fontScale?: number;
38
+ }
39
+ /**
40
+ * A theme. Every field is optional and anything omitted falls back to
41
+ * `defaultTheme`, so a theme may be as small as one colour.
42
+ *
43
+ * Named `ThemeConfig` rather than `Theme` to avoid colliding with the `Theme`
44
+ * exported by MUI, styled-components and others in a consumer's namespace.
45
+ */
46
+ interface ThemeConfig {
47
+ colors?: ThemeColors;
48
+ typography?: ThemeTypography;
49
+ }
50
+ /** A theme with every field populated - what the provider actually applies. */
51
+ interface ResolvedTheme {
52
+ colors: Record<ThemeColorKey, {
53
+ base: string;
54
+ contrast?: string;
55
+ }>;
56
+ typography: Required<ThemeTypography>;
57
+ }
58
+ interface ThemeContextValue {
59
+ /** The theme as supplied, with omitted fields left absent. */
60
+ theme: ThemeConfig;
61
+ /** The same theme with every field filled in from the preset. */
62
+ resolvedTheme: ResolvedTheme;
63
+ /** Replaces the whole theme. */
64
+ setTheme: (theme: ThemeConfig) => void;
65
+ /** Deep-merges a partial theme into the current one. */
66
+ updateTheme: (patch: ThemeConfig) => void;
67
+ /** Returns to the preset. */
68
+ resetTheme: () => void;
69
+ /** True when nothing differs from the preset, so no tokens are being written. */
70
+ isDefault: boolean;
71
+ /** The resolved theme as a `:root { … }` CSS block. */
72
+ toCss: () => string;
73
+ }
74
+ interface ThemeProviderProps {
75
+ children: React__default.ReactNode;
76
+ /**
77
+ * Controlled theme. Pair with `onThemeChange` and own persistence yourself -
78
+ * this is the mode to use when the theme comes from a user record on your
79
+ * server.
80
+ */
81
+ theme?: ThemeConfig;
82
+ /** Initial theme for uncontrolled usage. Ignored when `theme` is supplied. */
83
+ defaultTheme?: ThemeConfig;
84
+ /** Fires whenever the theme changes, in both controlled and uncontrolled mode. */
85
+ onThemeChange?: (theme: ThemeConfig) => void;
86
+ }
87
+
88
+ export type { ResolvedTheme as R, ThemeColorKey as T, ThemeColorValue as a, ThemeColors as b, ThemeConfig as c, ThemeContextValue as d, ThemeFontOption as e, ThemeProviderProps as f, ThemeTypography as g };