@owlmeans/web-panel 0.1.18-rc.9 → 0.1.18

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 (669) hide show
  1. package/README.md +510 -143
  2. package/THIRD-PARTY-NOTICES.txt +24 -0
  3. package/agent-meta/manifest.json +163 -4
  4. package/agent-meta/skills/web-panel/SKILL.md +136 -83
  5. package/agent-meta/skills/web-panel/parts/consent.md +114 -0
  6. package/agent-meta/skills/web-panel/parts/editor.md +47 -0
  7. package/agent-meta/skills/web-panel/parts/forms.md +85 -0
  8. package/agent-meta/skills/web-panel/parts/navigation.md +203 -0
  9. package/agent-meta/skills/web-panel/parts/picker.md +164 -0
  10. package/agent-meta/skills/web-panel/parts/reload.md +46 -0
  11. package/agent-meta/skills/web-panel/parts/sign-in.md +65 -0
  12. package/agent-meta/skills/web-panel/parts/theme.md +74 -0
  13. package/build/@/components/ui/alert-dialog.d.ts +15 -0
  14. package/build/@/components/ui/alert-dialog.d.ts.map +1 -0
  15. package/build/@/components/ui/alert-dialog.js +39 -0
  16. package/build/@/components/ui/alert-dialog.js.map +1 -0
  17. package/build/@/components/ui/alert.js +1 -1
  18. package/build/@/components/ui/alert.js.map +1 -1
  19. package/build/@/components/ui/button.js +1 -1
  20. package/build/@/components/ui/button.js.map +1 -1
  21. package/build/@/components/ui/card.js +1 -1
  22. package/build/@/components/ui/card.js.map +1 -1
  23. package/build/@/components/ui/input.js +1 -1
  24. package/build/@/components/ui/input.js.map +1 -1
  25. package/build/@/components/ui/label.js +1 -1
  26. package/build/@/components/ui/label.js.map +1 -1
  27. package/build/@/components/ui/navigation-menu.js +1 -1
  28. package/build/@/components/ui/navigation-menu.js.map +1 -1
  29. package/build/@/components/ui/popover.d.ts +8 -0
  30. package/build/@/components/ui/popover.d.ts.map +1 -0
  31. package/build/@/components/ui/popover.js +17 -0
  32. package/build/@/components/ui/popover.js.map +1 -0
  33. package/build/@/components/ui/progress.js +1 -1
  34. package/build/@/components/ui/progress.js.map +1 -1
  35. package/build/@/components/ui/separator.js +1 -1
  36. package/build/@/components/ui/separator.js.map +1 -1
  37. package/build/@/components/ui/sheet.d.ts +15 -0
  38. package/build/@/components/ui/sheet.d.ts.map +1 -0
  39. package/build/@/components/ui/sheet.js +40 -0
  40. package/build/@/components/ui/sheet.js.map +1 -0
  41. package/build/auth/context.d.ts.map +1 -1
  42. package/build/auth/context.js +0 -1
  43. package/build/auth/context.js.map +1 -1
  44. package/build/auth/entrypoints.d.ts +10 -0
  45. package/build/auth/entrypoints.d.ts.map +1 -0
  46. package/build/auth/entrypoints.js +4 -0
  47. package/build/auth/entrypoints.js.map +1 -0
  48. package/build/auth/exports.d.ts +4 -4
  49. package/build/auth/exports.d.ts.map +1 -1
  50. package/build/auth/exports.js +3 -3
  51. package/build/auth/exports.js.map +1 -1
  52. package/build/auth/modules.d.ts +1 -1
  53. package/build/auth/modules.d.ts.map +1 -1
  54. package/build/auth/plugins/basic-ed25519.js +4 -4
  55. package/build/auth/plugins/basic-ed25519.js.map +1 -1
  56. package/build/auth/plugins/re-captcha.js +3 -3
  57. package/build/auth/plugins/re-captcha.js.map +1 -1
  58. package/build/auth/plugins/tunnel-consumer.js +1 -1
  59. package/build/auth/plugins/tunnel-consumer.js.map +1 -1
  60. package/build/components/block.js +2 -2
  61. package/build/components/block.js.map +1 -1
  62. package/build/components/consts.local.d.ts +14 -0
  63. package/build/components/consts.local.d.ts.map +1 -0
  64. package/build/components/consts.local.js +26 -0
  65. package/build/components/consts.local.js.map +1 -0
  66. package/build/components/footer/component.d.ts +19 -1
  67. package/build/components/footer/component.d.ts.map +1 -1
  68. package/build/components/footer/component.js +38 -11
  69. package/build/components/footer/component.js.map +1 -1
  70. package/build/components/footer/credit.d.ts +27 -0
  71. package/build/components/footer/credit.d.ts.map +1 -0
  72. package/build/components/footer/credit.js +42 -0
  73. package/build/components/footer/credit.js.map +1 -0
  74. package/build/components/footer/index.d.ts +1 -0
  75. package/build/components/footer/index.d.ts.map +1 -1
  76. package/build/components/footer/index.js +1 -0
  77. package/build/components/footer/index.js.map +1 -1
  78. package/build/components/footer/types.d.ts +22 -1
  79. package/build/components/footer/types.d.ts.map +1 -1
  80. package/build/components/form/button/component.d.ts.map +1 -1
  81. package/build/components/form/button/component.js +5 -3
  82. package/build/components/form/button/component.js.map +1 -1
  83. package/build/components/form/component.js +2 -2
  84. package/build/components/form/component.js.map +1 -1
  85. package/build/components/form/text/component.js +2 -2
  86. package/build/components/form/text/component.js.map +1 -1
  87. package/build/components/helper.d.ts.map +1 -1
  88. package/build/components/helper.js +1 -12
  89. package/build/components/helper.js.map +1 -1
  90. package/build/components/index.d.ts +4 -0
  91. package/build/components/index.d.ts.map +1 -1
  92. package/build/components/index.js +4 -0
  93. package/build/components/index.js.map +1 -1
  94. package/build/components/link.js +3 -3
  95. package/build/components/link.js.map +1 -1
  96. package/build/components/login/append.d.ts +15 -0
  97. package/build/components/login/append.d.ts.map +1 -0
  98. package/build/components/login/append.js +26 -0
  99. package/build/components/login/append.js.map +1 -0
  100. package/build/components/login/consts.d.ts +3 -0
  101. package/build/components/login/consts.d.ts.map +1 -0
  102. package/build/components/login/consts.js +3 -0
  103. package/build/components/login/consts.js.map +1 -0
  104. package/build/components/login/consts.local.d.ts +4 -0
  105. package/build/components/login/consts.local.d.ts.map +1 -0
  106. package/build/components/login/consts.local.js +8 -0
  107. package/build/components/login/consts.local.js.map +1 -0
  108. package/build/components/login/credit.d.ts +12 -0
  109. package/build/components/login/credit.d.ts.map +1 -0
  110. package/build/components/login/credit.js +18 -0
  111. package/build/components/login/credit.js.map +1 -0
  112. package/build/components/login/i18n/be.json +10 -0
  113. package/build/components/login/i18n/de.json +10 -0
  114. package/build/components/login/i18n/en.json +10 -0
  115. package/build/components/login/i18n/es.json +10 -0
  116. package/build/components/login/i18n/fr.json +10 -0
  117. package/build/components/login/i18n/pl.json +10 -0
  118. package/build/components/login/i18n/ru.json +10 -0
  119. package/build/components/login/i18n/uk.json +10 -0
  120. package/build/components/login/i18n.d.ts +2 -0
  121. package/build/components/login/i18n.d.ts.map +1 -0
  122. package/build/components/login/i18n.js +28 -0
  123. package/build/components/login/i18n.js.map +1 -0
  124. package/build/components/login/icons.d.ts +14 -0
  125. package/build/components/login/icons.d.ts.map +1 -0
  126. package/build/components/login/icons.js +29 -0
  127. package/build/components/login/icons.js.map +1 -0
  128. package/build/components/login/index.d.ts +11 -0
  129. package/build/components/login/index.d.ts.map +1 -0
  130. package/build/components/login/index.js +10 -0
  131. package/build/components/login/index.js.map +1 -0
  132. package/build/components/login/notify.d.ts +18 -0
  133. package/build/components/login/notify.d.ts.map +1 -0
  134. package/build/components/login/notify.js +41 -0
  135. package/build/components/login/notify.js.map +1 -0
  136. package/build/components/login/provider.d.ts +20 -0
  137. package/build/components/login/provider.d.ts.map +1 -0
  138. package/build/components/login/provider.js +31 -0
  139. package/build/components/login/provider.js.map +1 -0
  140. package/build/components/login/screen.d.ts +24 -0
  141. package/build/components/login/screen.d.ts.map +1 -0
  142. package/build/components/login/screen.js +92 -0
  143. package/build/components/login/screen.js.map +1 -0
  144. package/build/components/login/terms.d.ts +19 -0
  145. package/build/components/login/terms.d.ts.map +1 -0
  146. package/build/components/login/terms.js +32 -0
  147. package/build/components/login/terms.js.map +1 -0
  148. package/build/components/login/types.d.ts +28 -0
  149. package/build/components/login/types.d.ts.map +1 -0
  150. package/build/components/login/types.js +2 -0
  151. package/build/components/login/types.js.map +1 -0
  152. package/build/components/nav/consts.local.d.ts +41 -0
  153. package/build/components/nav/consts.local.d.ts.map +1 -0
  154. package/build/components/nav/consts.local.js +60 -0
  155. package/build/components/nav/consts.local.js.map +1 -0
  156. package/build/components/nav/index.d.ts +1 -0
  157. package/build/components/nav/index.d.ts.map +1 -1
  158. package/build/components/nav/index.js +1 -0
  159. package/build/components/nav/index.js.map +1 -1
  160. package/build/components/nav/layout.d.ts +9 -2
  161. package/build/components/nav/layout.d.ts.map +1 -1
  162. package/build/components/nav/layout.js +48 -7
  163. package/build/components/nav/layout.js.map +1 -1
  164. package/build/components/nav/mobile.d.ts +21 -0
  165. package/build/components/nav/mobile.d.ts.map +1 -0
  166. package/build/components/nav/mobile.js +55 -0
  167. package/build/components/nav/mobile.js.map +1 -0
  168. package/build/components/nav/side.d.ts.map +1 -1
  169. package/build/components/nav/side.js +10 -10
  170. package/build/components/nav/side.js.map +1 -1
  171. package/build/components/nav/top.d.ts.map +1 -1
  172. package/build/components/nav/top.js +12 -8
  173. package/build/components/nav/top.js.map +1 -1
  174. package/build/components/nav/types.d.ts +64 -1
  175. package/build/components/nav/types.d.ts.map +1 -1
  176. package/build/components/nav/viewport.d.ts +3 -0
  177. package/build/components/nav/viewport.d.ts.map +1 -0
  178. package/build/components/nav/viewport.js +14 -0
  179. package/build/components/nav/viewport.js.map +1 -0
  180. package/build/components/panel-app/component.d.ts.map +1 -1
  181. package/build/components/panel-app/component.js +4 -3
  182. package/build/components/panel-app/component.js.map +1 -1
  183. package/build/components/picker/color-picker.d.ts +9 -0
  184. package/build/components/picker/color-picker.d.ts.map +1 -0
  185. package/build/components/picker/color-picker.js +9 -0
  186. package/build/components/picker/color-picker.js.map +1 -0
  187. package/build/components/picker/consts.local.d.ts +76 -0
  188. package/build/components/picker/consts.local.d.ts.map +1 -0
  189. package/build/components/picker/consts.local.js +214 -0
  190. package/build/components/picker/consts.local.js.map +1 -0
  191. package/build/components/picker/dot.d.ts +8 -0
  192. package/build/components/picker/dot.d.ts.map +1 -0
  193. package/build/components/picker/dot.js +10 -0
  194. package/build/components/picker/dot.js.map +1 -0
  195. package/build/components/picker/grid.d.ts +17 -0
  196. package/build/components/picker/grid.d.ts.map +1 -0
  197. package/build/components/picker/grid.js +73 -0
  198. package/build/components/picker/grid.js.map +1 -0
  199. package/build/components/picker/i18n/be.json +60 -0
  200. package/build/components/picker/i18n/de.json +60 -0
  201. package/build/components/picker/i18n/en.json +60 -0
  202. package/build/components/picker/i18n/es.json +60 -0
  203. package/build/components/picker/i18n/fr.json +60 -0
  204. package/build/components/picker/i18n/pl.json +60 -0
  205. package/build/components/picker/i18n/ru.json +60 -0
  206. package/build/components/picker/i18n/uk.json +60 -0
  207. package/build/components/picker/i18n.d.ts +2 -0
  208. package/build/components/picker/i18n.d.ts.map +1 -0
  209. package/build/components/picker/i18n.js +18 -0
  210. package/build/components/picker/i18n.js.map +1 -0
  211. package/build/components/picker/icon-color-picker.d.ts +14 -0
  212. package/build/components/picker/icon-color-picker.d.ts.map +1 -0
  213. package/build/components/picker/icon-color-picker.js +15 -0
  214. package/build/components/picker/icon-color-picker.js.map +1 -0
  215. package/build/components/picker/icon-picker.d.ts +8 -0
  216. package/build/components/picker/icon-picker.d.ts.map +1 -0
  217. package/build/components/picker/icon-picker.js +8 -0
  218. package/build/components/picker/icon-picker.js.map +1 -0
  219. package/build/components/picker/index.d.ts +11 -0
  220. package/build/components/picker/index.d.ts.map +1 -0
  221. package/build/components/picker/index.js +10 -0
  222. package/build/components/picker/index.js.map +1 -0
  223. package/build/components/picker/panel.d.ts +9 -0
  224. package/build/components/picker/panel.d.ts.map +1 -0
  225. package/build/components/picker/panel.js +23 -0
  226. package/build/components/picker/panel.js.map +1 -0
  227. package/build/components/picker/root.d.ts +13 -0
  228. package/build/components/picker/root.d.ts.map +1 -0
  229. package/build/components/picker/root.js +55 -0
  230. package/build/components/picker/root.js.map +1 -0
  231. package/build/components/picker/roving.d.ts +8 -0
  232. package/build/components/picker/roving.d.ts.map +1 -0
  233. package/build/components/picker/roving.js +62 -0
  234. package/build/components/picker/roving.js.map +1 -0
  235. package/build/components/picker/surface.d.ts +18 -0
  236. package/build/components/picker/surface.d.ts.map +1 -0
  237. package/build/components/picker/surface.js +36 -0
  238. package/build/components/picker/surface.js.map +1 -0
  239. package/build/components/picker/swatches/custom.d.ts +10 -0
  240. package/build/components/picker/swatches/custom.d.ts.map +1 -0
  241. package/build/components/picker/swatches/custom.js +65 -0
  242. package/build/components/picker/swatches/custom.js.map +1 -0
  243. package/build/components/picker/swatches.d.ts +16 -0
  244. package/build/components/picker/swatches.d.ts.map +1 -0
  245. package/build/components/picker/swatches.js +35 -0
  246. package/build/components/picker/swatches.js.map +1 -0
  247. package/build/components/picker/text.d.ts +5 -0
  248. package/build/components/picker/text.d.ts.map +1 -0
  249. package/build/components/picker/text.js +29 -0
  250. package/build/components/picker/text.js.map +1 -0
  251. package/build/components/picker/tile.d.ts +11 -0
  252. package/build/components/picker/tile.d.ts.map +1 -0
  253. package/build/components/picker/tile.js +19 -0
  254. package/build/components/picker/tile.js.map +1 -0
  255. package/build/components/picker/translate.d.ts +9 -0
  256. package/build/components/picker/translate.d.ts.map +1 -0
  257. package/build/components/picker/translate.js +13 -0
  258. package/build/components/picker/translate.js.map +1 -0
  259. package/build/components/picker/trigger.d.ts +12 -0
  260. package/build/components/picker/trigger.d.ts.map +1 -0
  261. package/build/components/picker/trigger.js +29 -0
  262. package/build/components/picker/trigger.js.map +1 -0
  263. package/build/components/picker/types.d.ts +114 -0
  264. package/build/components/picker/types.d.ts.map +1 -0
  265. package/build/components/picker/types.js +2 -0
  266. package/build/components/picker/types.js.map +1 -0
  267. package/build/components/picker/types.local.d.ts +143 -0
  268. package/build/components/picker/types.local.d.ts.map +1 -0
  269. package/build/components/picker/types.local.js +2 -0
  270. package/build/components/picker/types.local.js.map +1 -0
  271. package/build/components/scheme/consts.local.d.ts +8 -0
  272. package/build/components/scheme/consts.local.d.ts.map +1 -0
  273. package/build/components/scheme/consts.local.js +13 -0
  274. package/build/components/scheme/consts.local.js.map +1 -0
  275. package/build/components/scheme/hook.d.ts +16 -0
  276. package/build/components/scheme/hook.d.ts.map +1 -0
  277. package/build/components/scheme/hook.js +52 -0
  278. package/build/components/scheme/hook.js.map +1 -0
  279. package/build/components/scheme/index.d.ts +4 -0
  280. package/build/components/scheme/index.d.ts.map +1 -0
  281. package/build/components/scheme/index.js +3 -0
  282. package/build/components/scheme/index.js.map +1 -0
  283. package/build/components/scheme/toggle.d.ts +14 -0
  284. package/build/components/scheme/toggle.d.ts.map +1 -0
  285. package/build/components/scheme/toggle.js +24 -0
  286. package/build/components/scheme/toggle.js.map +1 -0
  287. package/build/components/scheme/types.d.ts +21 -0
  288. package/build/components/scheme/types.d.ts.map +1 -0
  289. package/build/components/scheme/types.js +2 -0
  290. package/build/components/scheme/types.js.map +1 -0
  291. package/build/components/socket/i18n/be.json +9 -0
  292. package/build/components/socket/i18n/de.json +9 -0
  293. package/build/components/socket/i18n/en.json +9 -0
  294. package/build/components/socket/i18n/es.json +9 -0
  295. package/build/components/socket/i18n/fr.json +9 -0
  296. package/build/components/socket/i18n/pl.json +9 -0
  297. package/build/components/socket/i18n/ru.json +9 -0
  298. package/build/components/socket/i18n/uk.json +9 -0
  299. package/build/components/socket/i18n.d.ts +2 -0
  300. package/build/components/socket/i18n.d.ts.map +1 -0
  301. package/build/components/socket/i18n.js +18 -0
  302. package/build/components/socket/i18n.js.map +1 -0
  303. package/build/components/socket/index.d.ts +3 -0
  304. package/build/components/socket/index.d.ts.map +1 -0
  305. package/build/components/socket/index.js +3 -0
  306. package/build/components/socket/index.js.map +1 -0
  307. package/build/components/socket/reload-dialog.d.ts +22 -0
  308. package/build/components/socket/reload-dialog.d.ts.map +1 -0
  309. package/build/components/socket/reload-dialog.js +34 -0
  310. package/build/components/socket/reload-dialog.js.map +1 -0
  311. package/build/components/status.js +1 -1
  312. package/build/components/status.js.map +1 -1
  313. package/build/components/text.d.ts.map +1 -1
  314. package/build/components/text.js +2 -13
  315. package/build/components/text.js.map +1 -1
  316. package/build/components/toaster.d.ts +16 -0
  317. package/build/components/toaster.d.ts.map +1 -0
  318. package/build/components/toaster.js +52 -0
  319. package/build/components/toaster.js.map +1 -0
  320. package/build/components/uploader/consts.local.d.ts +4 -0
  321. package/build/components/uploader/consts.local.d.ts.map +1 -0
  322. package/build/components/uploader/consts.local.js +6 -0
  323. package/build/components/uploader/consts.local.js.map +1 -0
  324. package/build/components/uploader/image.d.ts.map +1 -1
  325. package/build/components/uploader/image.js +2 -6
  326. package/build/components/uploader/image.js.map +1 -1
  327. package/build/consent/component.d.ts +27 -0
  328. package/build/consent/component.d.ts.map +1 -0
  329. package/build/consent/component.js +60 -0
  330. package/build/consent/component.js.map +1 -0
  331. package/build/consent/consts.d.ts +2 -0
  332. package/build/consent/consts.d.ts.map +1 -0
  333. package/build/consent/consts.js +2 -0
  334. package/build/consent/consts.js.map +1 -0
  335. package/build/consent/consts.local.d.ts +9 -0
  336. package/build/consent/consts.local.d.ts.map +1 -0
  337. package/build/consent/consts.local.js +9 -0
  338. package/build/consent/consts.local.js.map +1 -0
  339. package/build/consent/geo.d.ts +17 -0
  340. package/build/consent/geo.d.ts.map +1 -0
  341. package/build/consent/geo.js +19 -0
  342. package/build/consent/geo.js.map +1 -0
  343. package/build/consent/index.d.ts +11 -0
  344. package/build/consent/index.d.ts.map +1 -0
  345. package/build/consent/index.js +9 -0
  346. package/build/consent/index.js.map +1 -0
  347. package/build/consent/language.d.ts +12 -0
  348. package/build/consent/language.d.ts.map +1 -0
  349. package/build/consent/language.js +11 -0
  350. package/build/consent/language.js.map +1 -0
  351. package/build/consent/menu-widget.d.ts +13 -0
  352. package/build/consent/menu-widget.d.ts.map +1 -0
  353. package/build/consent/menu-widget.js +20 -0
  354. package/build/consent/menu-widget.js.map +1 -0
  355. package/build/consent/presence.d.ts +30 -0
  356. package/build/consent/presence.d.ts.map +1 -0
  357. package/build/consent/presence.js +40 -0
  358. package/build/consent/presence.js.map +1 -0
  359. package/build/consent/service.d.ts +18 -0
  360. package/build/consent/service.d.ts.map +1 -0
  361. package/build/consent/service.js +53 -0
  362. package/build/consent/service.js.map +1 -0
  363. package/build/consent/translate.d.ts +14 -0
  364. package/build/consent/translate.d.ts.map +1 -0
  365. package/build/consent/translate.js +28 -0
  366. package/build/consent/translate.js.map +1 -0
  367. package/build/consent/types.d.ts +39 -0
  368. package/build/consent/types.d.ts.map +1 -0
  369. package/build/consent/types.js +2 -0
  370. package/build/consent/types.js.map +1 -0
  371. package/build/consent/types.local.d.ts +6 -0
  372. package/build/consent/types.local.d.ts.map +1 -0
  373. package/build/consent/types.local.js +2 -0
  374. package/build/consent/types.local.js.map +1 -0
  375. package/build/context.d.ts.map +1 -1
  376. package/build/context.js +10 -0
  377. package/build/context.js.map +1 -1
  378. package/build/editor/component.d.ts +4 -0
  379. package/build/editor/component.d.ts.map +1 -0
  380. package/build/editor/component.js +103 -0
  381. package/build/editor/component.js.map +1 -0
  382. package/build/editor/consts.local.d.ts +6 -0
  383. package/build/editor/consts.local.d.ts.map +1 -0
  384. package/build/editor/consts.local.js +58 -0
  385. package/build/editor/consts.local.js.map +1 -0
  386. package/build/editor/index.d.ts +3 -0
  387. package/build/editor/index.d.ts.map +1 -0
  388. package/build/editor/index.js +2 -0
  389. package/build/editor/index.js.map +1 -0
  390. package/build/editor/types.d.ts +24 -0
  391. package/build/editor/types.d.ts.map +1 -0
  392. package/build/editor/types.js +2 -0
  393. package/build/editor/types.js.map +1 -0
  394. package/build/entrypoints.d.ts +8 -0
  395. package/build/entrypoints.d.ts.map +1 -0
  396. package/build/entrypoints.js +4 -0
  397. package/build/entrypoints.js.map +1 -0
  398. package/build/exports.d.ts +6 -5
  399. package/build/exports.d.ts.map +1 -1
  400. package/build/exports.js +5 -5
  401. package/build/exports.js.map +1 -1
  402. package/build/index.d.ts +1 -1
  403. package/build/index.d.ts.map +1 -1
  404. package/build/index.js +1 -1
  405. package/build/index.js.map +1 -1
  406. package/build/main.d.ts +1 -4
  407. package/build/main.d.ts.map +1 -1
  408. package/build/main.js.map +1 -1
  409. package/build/modules.d.ts +1 -1
  410. package/build/modules.d.ts.map +1 -1
  411. package/build/permission/i18n/be.json +13 -0
  412. package/build/permission/i18n/de.json +13 -0
  413. package/build/permission/i18n/en.json +13 -0
  414. package/build/permission/i18n/es.json +13 -0
  415. package/build/permission/i18n/fr.json +13 -0
  416. package/build/permission/i18n/pl.json +13 -0
  417. package/build/permission/i18n/ru.json +13 -0
  418. package/build/permission/i18n/uk.json +13 -0
  419. package/build/permission/i18n.d.ts +2 -0
  420. package/build/permission/i18n.d.ts.map +1 -0
  421. package/build/permission/i18n.js +13 -0
  422. package/build/permission/i18n.js.map +1 -0
  423. package/build/permission/index.d.ts +6 -0
  424. package/build/permission/index.d.ts.map +1 -0
  425. package/build/permission/index.js +27 -0
  426. package/build/permission/index.js.map +1 -0
  427. package/build/permission/toast.d.ts +5 -0
  428. package/build/permission/toast.d.ts.map +1 -0
  429. package/build/permission/toast.js +8 -0
  430. package/build/permission/toast.js.map +1 -0
  431. package/build/permission/types.d.ts +6 -0
  432. package/build/permission/types.d.ts.map +1 -0
  433. package/build/permission/types.js +2 -0
  434. package/build/permission/types.js.map +1 -0
  435. package/build/picker/icons/consts.d.ts +9 -0
  436. package/build/picker/icons/consts.d.ts.map +1 -0
  437. package/build/picker/icons/consts.js +264 -0
  438. package/build/picker/icons/consts.js.map +1 -0
  439. package/build/picker/icons/types.d.ts +18 -0
  440. package/build/picker/icons/types.d.ts.map +1 -0
  441. package/build/picker/icons/types.js +2 -0
  442. package/build/picker/icons/types.js.map +1 -0
  443. package/build/picker/icons.d.ts +4 -0
  444. package/build/picker/icons.d.ts.map +1 -0
  445. package/build/picker/icons.js +54 -0
  446. package/build/picker/icons.js.map +1 -0
  447. package/build/picker/index.d.ts +11 -0
  448. package/build/picker/index.d.ts.map +1 -0
  449. package/build/picker/index.js +10 -0
  450. package/build/picker/index.js.map +1 -0
  451. package/build/picker/utils/color/types.d.ts +35 -0
  452. package/build/picker/utils/color/types.d.ts.map +1 -0
  453. package/build/picker/utils/color/types.js +2 -0
  454. package/build/picker/utils/color/types.js.map +1 -0
  455. package/build/picker/utils/color.d.ts +4 -0
  456. package/build/picker/utils/color.d.ts.map +1 -0
  457. package/build/picker/utils/color.js +96 -0
  458. package/build/picker/utils/color.js.map +1 -0
  459. package/build/picker/vocabulary/consts.d.ts +26 -0
  460. package/build/picker/vocabulary/consts.d.ts.map +1 -0
  461. package/build/picker/vocabulary/consts.js +336 -0
  462. package/build/picker/vocabulary/consts.js.map +1 -0
  463. package/build/picker/vocabulary/types.d.ts +67 -0
  464. package/build/picker/vocabulary/types.d.ts.map +1 -0
  465. package/build/picker/vocabulary/types.js +2 -0
  466. package/build/picker/vocabulary/types.js.map +1 -0
  467. package/build/picker/vocabulary.d.ts +11 -0
  468. package/build/picker/vocabulary.d.ts.map +1 -0
  469. package/build/picker/vocabulary.js +83 -0
  470. package/build/picker/vocabulary.js.map +1 -0
  471. package/build/scheme/consts.d.ts +8 -0
  472. package/build/scheme/consts.d.ts.map +1 -0
  473. package/build/scheme/consts.js +8 -0
  474. package/build/scheme/consts.js.map +1 -0
  475. package/build/scheme/index.d.ts +4 -0
  476. package/build/scheme/index.d.ts.map +1 -0
  477. package/build/scheme/index.js +3 -0
  478. package/build/scheme/index.js.map +1 -0
  479. package/build/scheme/scheme.d.ts +16 -0
  480. package/build/scheme/scheme.d.ts.map +1 -0
  481. package/build/scheme/scheme.js +58 -0
  482. package/build/scheme/scheme.js.map +1 -0
  483. package/build/scheme/types.d.ts +30 -0
  484. package/build/scheme/types.d.ts.map +1 -0
  485. package/build/scheme/types.js +2 -0
  486. package/build/scheme/types.js.map +1 -0
  487. package/build/types.d.ts +18 -2
  488. package/build/types.d.ts.map +1 -1
  489. package/package.json +107 -52
  490. package/src/@/components/ui/alert-dialog.tsx +156 -0
  491. package/src/@/components/ui/alert.tsx +1 -1
  492. package/src/@/components/ui/button.tsx +1 -1
  493. package/src/@/components/ui/card.tsx +1 -1
  494. package/src/@/components/ui/input.tsx +1 -1
  495. package/src/@/components/ui/label.tsx +1 -1
  496. package/src/@/components/ui/navigation-menu.tsx +1 -1
  497. package/src/@/components/ui/popover.tsx +47 -0
  498. package/src/@/components/ui/progress.tsx +1 -1
  499. package/src/@/components/ui/separator.tsx +1 -1
  500. package/src/@/components/ui/sheet.tsx +142 -0
  501. package/src/auth/context.ts +0 -2
  502. package/src/auth/entrypoints.ts +5 -0
  503. package/src/auth/exports.ts +4 -4
  504. package/src/auth/plugins/basic-ed25519.tsx +4 -4
  505. package/src/auth/plugins/re-captcha.tsx +3 -3
  506. package/src/auth/plugins/tunnel-consumer.tsx +1 -1
  507. package/src/components/block.tsx +2 -2
  508. package/src/components/consts.local.ts +29 -0
  509. package/src/components/footer/component.tsx +58 -16
  510. package/src/components/footer/credit.tsx +61 -0
  511. package/src/components/footer/index.ts +1 -0
  512. package/src/components/footer/types.ts +22 -1
  513. package/src/components/form/button/component.tsx +7 -4
  514. package/src/components/form/component.tsx +2 -2
  515. package/src/components/form/text/component.tsx +2 -2
  516. package/src/components/helper.ts +1 -13
  517. package/src/components/index.ts +4 -0
  518. package/src/components/link.tsx +3 -3
  519. package/src/components/login/append.ts +34 -0
  520. package/src/components/login/consts.local.ts +10 -0
  521. package/src/components/login/consts.ts +2 -0
  522. package/src/components/login/credit.tsx +33 -0
  523. package/src/components/login/i18n/be.json +10 -0
  524. package/src/components/login/i18n/de.json +10 -0
  525. package/src/components/login/i18n/en.json +10 -0
  526. package/src/components/login/i18n/es.json +10 -0
  527. package/src/components/login/i18n/fr.json +10 -0
  528. package/src/components/login/i18n/pl.json +10 -0
  529. package/src/components/login/i18n/ru.json +10 -0
  530. package/src/components/login/i18n/uk.json +10 -0
  531. package/src/components/login/i18n.ts +29 -0
  532. package/src/components/login/icons.tsx +39 -0
  533. package/src/components/login/index.ts +11 -0
  534. package/src/components/login/notify.ts +48 -0
  535. package/src/components/login/provider.tsx +57 -0
  536. package/src/components/login/screen.tsx +178 -0
  537. package/src/components/login/terms.tsx +75 -0
  538. package/src/components/login/types.ts +30 -0
  539. package/src/components/nav/consts.local.ts +64 -0
  540. package/src/components/nav/index.ts +1 -0
  541. package/src/components/nav/layout.tsx +184 -26
  542. package/src/components/nav/mobile.tsx +165 -0
  543. package/src/components/nav/side.tsx +43 -27
  544. package/src/components/nav/top.tsx +44 -22
  545. package/src/components/nav/types.ts +65 -2
  546. package/src/components/nav/viewport.ts +16 -0
  547. package/src/components/panel-app/component.tsx +9 -1
  548. package/src/components/picker/color-picker.tsx +15 -0
  549. package/src/components/picker/consts.local.ts +267 -0
  550. package/src/components/picker/dot.tsx +21 -0
  551. package/src/components/picker/grid.tsx +138 -0
  552. package/src/components/picker/i18n/be.json +60 -0
  553. package/src/components/picker/i18n/de.json +60 -0
  554. package/src/components/picker/i18n/en.json +60 -0
  555. package/src/components/picker/i18n/es.json +60 -0
  556. package/src/components/picker/i18n/fr.json +60 -0
  557. package/src/components/picker/i18n/pl.json +60 -0
  558. package/src/components/picker/i18n/ru.json +60 -0
  559. package/src/components/picker/i18n/uk.json +60 -0
  560. package/src/components/picker/i18n.ts +19 -0
  561. package/src/components/picker/icon-color-picker.tsx +25 -0
  562. package/src/components/picker/icon-picker.tsx +13 -0
  563. package/src/components/picker/index.ts +11 -0
  564. package/src/components/picker/panel.tsx +61 -0
  565. package/src/components/picker/root.tsx +81 -0
  566. package/src/components/picker/roving.ts +70 -0
  567. package/src/components/picker/surface.tsx +62 -0
  568. package/src/components/picker/swatches/custom.tsx +110 -0
  569. package/src/components/picker/swatches.tsx +67 -0
  570. package/src/components/picker/text.ts +46 -0
  571. package/src/components/picker/tile.tsx +35 -0
  572. package/src/components/picker/translate.ts +15 -0
  573. package/src/components/picker/trigger.tsx +54 -0
  574. package/src/components/picker/types.local.ts +154 -0
  575. package/src/components/picker/types.ts +125 -0
  576. package/src/components/scheme/consts.local.ts +13 -0
  577. package/src/components/scheme/hook.ts +62 -0
  578. package/src/components/scheme/index.ts +4 -0
  579. package/src/components/scheme/toggle.tsx +32 -0
  580. package/src/components/scheme/types.ts +23 -0
  581. package/src/components/socket/i18n/be.json +9 -0
  582. package/src/components/socket/i18n/de.json +9 -0
  583. package/src/components/socket/i18n/en.json +9 -0
  584. package/src/components/socket/i18n/es.json +9 -0
  585. package/src/components/socket/i18n/fr.json +9 -0
  586. package/src/components/socket/i18n/pl.json +9 -0
  587. package/src/components/socket/i18n/ru.json +9 -0
  588. package/src/components/socket/i18n/uk.json +9 -0
  589. package/src/components/socket/i18n.ts +19 -0
  590. package/src/components/socket/index.ts +2 -0
  591. package/src/components/socket/reload-dialog.tsx +61 -0
  592. package/src/components/status.tsx +1 -1
  593. package/src/components/text.tsx +2 -14
  594. package/src/components/toaster.tsx +65 -0
  595. package/src/components/uploader/consts.local.ts +7 -0
  596. package/src/components/uploader/image.tsx +2 -6
  597. package/src/consent/component.tsx +84 -0
  598. package/src/consent/consts.local.ts +10 -0
  599. package/src/consent/consts.ts +1 -0
  600. package/src/consent/geo.ts +26 -0
  601. package/src/consent/index.ts +24 -0
  602. package/src/consent/language.ts +12 -0
  603. package/src/consent/menu-widget.tsx +22 -0
  604. package/src/consent/presence.ts +45 -0
  605. package/src/consent/service.ts +75 -0
  606. package/src/consent/translate.ts +31 -0
  607. package/src/consent/types.local.ts +6 -0
  608. package/src/consent/types.ts +43 -0
  609. package/src/context.ts +12 -0
  610. package/src/editor/component.tsx +172 -0
  611. package/src/editor/consts.local.ts +62 -0
  612. package/src/editor/index.ts +2 -0
  613. package/src/editor/types.ts +24 -0
  614. package/src/entrypoints.ts +5 -0
  615. package/src/exports.ts +6 -5
  616. package/src/index.ts +1 -1
  617. package/src/main.tsx +2 -6
  618. package/src/permission/i18n/be.json +13 -0
  619. package/src/permission/i18n/de.json +13 -0
  620. package/src/permission/i18n/en.json +13 -0
  621. package/src/permission/i18n/es.json +13 -0
  622. package/src/permission/i18n/fr.json +13 -0
  623. package/src/permission/i18n/pl.json +13 -0
  624. package/src/permission/i18n/ru.json +13 -0
  625. package/src/permission/i18n/uk.json +13 -0
  626. package/src/permission/i18n.ts +13 -0
  627. package/src/permission/index.ts +27 -0
  628. package/src/permission/toast.tsx +20 -0
  629. package/src/permission/types.ts +5 -0
  630. package/src/picker/icons/consts.ts +309 -0
  631. package/src/picker/icons/types.ts +18 -0
  632. package/src/picker/icons.ts +70 -0
  633. package/src/picker/index.ts +11 -0
  634. package/src/picker/utils/color/types.ts +37 -0
  635. package/src/picker/utils/color.ts +119 -0
  636. package/src/picker/vocabulary/consts.ts +347 -0
  637. package/src/picker/vocabulary/types.ts +72 -0
  638. package/src/picker/vocabulary.ts +111 -0
  639. package/src/scheme/consts.ts +8 -0
  640. package/src/scheme/index.ts +3 -0
  641. package/src/scheme/scheme.ts +66 -0
  642. package/src/scheme/types.ts +30 -0
  643. package/src/types.ts +19 -2
  644. package/tests/consent-language.spec.ts +31 -0
  645. package/tests/consent.spec.ts +112 -0
  646. package/tests/context.ts +4 -0
  647. package/tests/editor.spec.ts +58 -0
  648. package/tests/harness/editor.tsx +32 -0
  649. package/tests/harness/index.html +1 -0
  650. package/tests/harness/lazy-screen.tsx +9 -0
  651. package/tests/harness/mount.tsx +370 -29
  652. package/tests/harness/picker.tsx +110 -0
  653. package/tests/lazy.spec.ts +104 -0
  654. package/tests/login-provider.spec.ts +114 -0
  655. package/tests/login.spec.ts +447 -0
  656. package/tests/nav.spec.ts +449 -3
  657. package/tests/package-boundary.spec.ts +19 -0
  658. package/tests/picker-shots.spec.ts +174 -0
  659. package/tests/picker-vocabulary.spec.ts +217 -0
  660. package/tests/picker.spec.ts +333 -0
  661. package/tests/scheme.spec.ts +149 -0
  662. package/tests/smoke.spec.ts +2 -2
  663. package/tests/socket-dialog.spec.ts +154 -0
  664. package/tests/toaster.spec.ts +59 -0
  665. package/zz-tw.d.mts +2 -0
  666. package/zz-tw.d.mts.map +1 -0
  667. package/build/.gitkeep +0 -0
  668. package/src/auth/modules.ts +0 -5
  669. package/src/modules.ts +0 -5
@@ -0,0 +1,119 @@
1
+ import type { ColorUtils, DerivedColor, Oklch, Rgb } from './color/types.js'
2
+
3
+ /** The text-contrast floor every derived ink keeps — above the 3:1 icons and dots need. */
4
+ const TARGET = 4.5
5
+ const WHITE = '#ffffff'
6
+ const BLACK = '#000000'
7
+
8
+ const toLinear = (c: number): number => c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4
9
+ const fromLinear = (c: number): number => c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055
10
+
11
+ /** sRGB → OKLCH (Björn Ottosson's matrices). */
12
+ const toOklch = ({ r, g, b }: Rgb): Oklch => {
13
+ const [lr, lg, lb] = [toLinear(r), toLinear(g), toLinear(b)]
14
+ const l = Math.cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb)
15
+ const m = Math.cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb)
16
+ const s = Math.cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb)
17
+ const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s
18
+ const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s
19
+ const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
20
+
21
+ return { l: L, c: Math.hypot(A, B), h: Math.atan2(B, A) }
22
+ }
23
+
24
+ /** OKLCH → linear sRGB channels, unclamped (out-of-gamut values fall outside 0..1). */
25
+ const toLinearRgb = ({ l, c, h }: Oklch): [number, number, number] => {
26
+ const a = c * Math.cos(h)
27
+ const b = c * Math.sin(h)
28
+ const l3 = (l + 0.3963377774 * a + 0.2158037573 * b) ** 3
29
+ const m3 = (l - 0.1055613458 * a - 0.0638541728 * b) ** 3
30
+ const s3 = (l - 0.0894841775 * a - 1.291485548 * b) ** 3
31
+
32
+ return [
33
+ 4.0767416621 * l3 - 3.3077115913 * m3 + 0.2309699292 * s3,
34
+ -1.2684380046 * l3 + 2.6097574011 * m3 - 0.3413193965 * s3,
35
+ -0.0041960863 * l3 - 0.7034186147 * m3 + 1.707614701 * s3,
36
+ ]
37
+ }
38
+
39
+ const inGamut = (channels: [number, number, number]): boolean =>
40
+ channels.every(channel => channel >= -1e-4 && channel <= 1 + 1e-4)
41
+
42
+ export const createColorUtils = (): ColorUtils => {
43
+ const parse = (hex: string): Rgb | null => {
44
+ const match = /^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex.trim())
45
+ if (match == null) {
46
+ return null
47
+ }
48
+ const [r, g, b] = match.slice(1).map(part => parseInt(part, 16) / 255)
49
+
50
+ return { r, g, b }
51
+ }
52
+
53
+ const hex = ({ r, g, b }: Rgb): string => `#${[r, g, b]
54
+ .map(channel => Math.round(Math.min(1, Math.max(0, channel)) * 255).toString(16).padStart(2, '0'))
55
+ .join('')}`
56
+
57
+ const luminance = (value: string): number => {
58
+ const rgb = parse(value) ?? { r: 0, g: 0, b: 0 }
59
+
60
+ return 0.2126 * toLinear(rgb.r) + 0.7152 * toLinear(rgb.g) + 0.0722 * toLinear(rgb.b)
61
+ }
62
+
63
+ const contrast = (a: string, b: string): number => {
64
+ const [x, y] = [luminance(a), luminance(b)]
65
+
66
+ return (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05)
67
+ }
68
+
69
+ /** The colour at this lightness and hue with as much of `c` as sRGB can show, as hex. */
70
+ const fit = (l: number, c: number, h: number): string => {
71
+ let low = 0
72
+ let high = c
73
+ if (!inGamut(toLinearRgb({ l, c, h }))) {
74
+ for (let step = 0; step < 24; step++) {
75
+ const mid = (low + high) / 2
76
+ if (inGamut(toLinearRgb({ l, c: mid, h }))) {
77
+ low = mid
78
+ } else {
79
+ high = mid
80
+ }
81
+ }
82
+ } else {
83
+ low = c
84
+ }
85
+ const [r, g, b] = toLinearRgb({ l, c: low, h }).map(channel => fromLinear(Math.min(1, Math.max(0, channel))))
86
+
87
+ return hex({ r, g, b })
88
+ }
89
+
90
+ /** Walk the lightness from `from` by `step` until `ok` holds; the far end (black or white) always does. */
91
+ const walk = (from: number, step: number, c: number, h: number, ok: (candidate: string) => boolean): string => {
92
+ for (let l = from; l >= 0 && l <= 1; l += step) {
93
+ const candidate = fit(l, c, h)
94
+ if (ok(candidate)) {
95
+ return candidate
96
+ }
97
+ }
98
+
99
+ return step < 0 ? BLACK : WHITE
100
+ }
101
+
102
+ const derive = (value: string): DerivedColor => {
103
+ const base = toOklch(parse(value) ?? { r: 0, g: 0, b: 0 })
104
+ // A grey has no hue to keep; any angle at zero chroma is the same grey.
105
+ const h = base.c < 1e-4 ? 0 : base.h
106
+ const soft = fit(0.965, Math.min(base.c, 0.035), h)
107
+ const softDark = fit(0.25, Math.min(base.c, 0.06), h)
108
+ const ink = walk(Math.min(base.l, 0.66), -0.01, base.c, h,
109
+ candidate => contrast(candidate, WHITE) >= TARGET && contrast(candidate, soft) >= TARGET)
110
+ const inkDark = walk(Math.max(base.l, 0.72), 0.01, Math.min(base.c, 0.16), h,
111
+ candidate => contrast(candidate, BLACK) >= TARGET && contrast(candidate, softDark) >= TARGET)
112
+
113
+ return { ink, soft, inkDark, softDark }
114
+ }
115
+
116
+ return { parse, hex, contrast, derive }
117
+ }
118
+
119
+ export const colorUtils = createColorUtils()
@@ -0,0 +1,347 @@
1
+ import type { PickerColor, PickerIconCategory, PickerIconEntry } from './types.js'
2
+
3
+ /** The palette's keys in hue order — the order the swatch grid shows them in. */
4
+ export const PICKER_COLOR_KEYS = [
5
+ 'red', 'orange', 'amber', 'yellow', 'lime', 'green', 'emerald', 'teal', 'cyan', 'sky', 'blue', 'indigo',
6
+ 'violet', 'purple', 'fuchsia', 'pink', 'rose', 'maroon', 'brown', 'olive', 'navy', 'slate', 'stone', 'graphite',
7
+ ] as const
8
+
9
+ /**
10
+ * The 24-colour palette.
11
+ *
12
+ * Hues follow one scale: the swatch is the hue's 500, the light ink its 700–800, the light ground
13
+ * its 100, the dark ink its 300 (200 or 400 where a neighbouring hue's 300 sits too close) and the
14
+ * dark ground its 900–950. Ten hues keep the exact values the generated targets' look has always
15
+ * used (slate, blue, sky, teal, green, amber, orange, red, pink, violet). The deep four — maroon,
16
+ * brown, olive, navy — run on scales of their own: a darker light ink and a mid-tone dark ink, so
17
+ * they stay apart from red, amber, lime and indigo in both modes. Every ink keeps 4.5:1 on its own
18
+ * ground and on the page in both modes (`tests/picker-vocabulary.spec.ts`).
19
+ */
20
+ export const PICKER_COLORS: readonly PickerColor[] = Object.freeze([
21
+ { key: 'red', label: 'Red', swatch: '#EF4444', ink: '#B91C1C', soft: '#FEE2E2', inkDark: '#FCA5A5', softDark: '#450A0A' },
22
+ { key: 'orange', label: 'Orange', swatch: '#F97316', ink: '#9A3412', soft: '#FFEDD5', inkDark: '#FDBA74', softDark: '#431407' },
23
+ { key: 'amber', label: 'Amber', swatch: '#F59E0B', ink: '#92400E', soft: '#FEF3C7', inkDark: '#FCD34D', softDark: '#451A03' },
24
+ { key: 'yellow', label: 'Yellow', swatch: '#EAB308', ink: '#A16207', soft: '#FEF9C3', inkDark: '#FEF08A', softDark: '#422006' },
25
+ { key: 'lime', label: 'Lime', swatch: '#84CC16', ink: '#4D7C0F', soft: '#ECFCCB', inkDark: '#BEF264', softDark: '#1A2E05' },
26
+ { key: 'green', label: 'Green', swatch: '#22C55E', ink: '#166534', soft: '#DCFCE7', inkDark: '#86EFAC', softDark: '#052E16' },
27
+ { key: 'emerald', label: 'Emerald', swatch: '#10B981', ink: '#047857', soft: '#D1FAE5', inkDark: '#34D399', softDark: '#022C22' },
28
+ { key: 'teal', label: 'Teal', swatch: '#14B8A6', ink: '#115E59', soft: '#CCFBF1', inkDark: '#5EEAD4', softDark: '#042F2E' },
29
+ { key: 'cyan', label: 'Cyan', swatch: '#06B6D4', ink: '#0E7490', soft: '#CFFAFE', inkDark: '#A5F3FC', softDark: '#083344' },
30
+ { key: 'sky', label: 'Sky', swatch: '#0EA5E9', ink: '#0369A1', soft: '#E0F2FE', inkDark: '#7DD3FC', softDark: '#082F49' },
31
+ { key: 'blue', label: 'Blue', swatch: '#3B82F6', ink: '#1D4ED8', soft: '#DBEAFE', inkDark: '#93C5FD', softDark: '#172554' },
32
+ { key: 'indigo', label: 'Indigo', swatch: '#6366F1', ink: '#4338CA', soft: '#E0E7FF', inkDark: '#818CF8', softDark: '#1E1B4B' },
33
+ { key: 'violet', label: 'Violet', swatch: '#8B5CF6', ink: '#6D28D9', soft: '#EDE9FE', inkDark: '#C4B5FD', softDark: '#2E1065' },
34
+ { key: 'purple', label: 'Purple', swatch: '#A855F7', ink: '#6B21A8', soft: '#F3E8FF', inkDark: '#C084FC', softDark: '#3B0764' },
35
+ { key: 'fuchsia', label: 'Fuchsia', swatch: '#D946EF', ink: '#A21CAF', soft: '#FAE8FF', inkDark: '#F0ABFC', softDark: '#4A044E' },
36
+ { key: 'pink', label: 'Pink', swatch: '#EC4899', ink: '#BE185D', soft: '#FCE7F3', inkDark: '#F9A8D4', softDark: '#500724' },
37
+ { key: 'rose', label: 'Rose', swatch: '#F43F5E', ink: '#9F1239', soft: '#FFE4E6', inkDark: '#FB7185', softDark: '#4C0519' },
38
+ { key: 'maroon', label: 'Maroon', swatch: '#8C1D30', ink: '#6E1423', soft: '#F6E3E6', inkDark: '#D07A8A', softDark: '#3A0B14' },
39
+ { key: 'brown', label: 'Brown', swatch: '#8B5E3C', ink: '#6B4226', soft: '#F2E8DF', inkDark: '#D4A373', softDark: '#2B1D12' },
40
+ { key: 'olive', label: 'Olive', swatch: '#7D7F1F', ink: '#535B16', soft: '#F1F2DE', inkDark: '#C5C77E', softDark: '#1F2208' },
41
+ { key: 'navy', label: 'Navy', swatch: '#233876', ink: '#1E2A5E', soft: '#E3E7F4', inkDark: '#8EA2E0', softDark: '#0D1530' },
42
+ { key: 'slate', label: 'Slate', swatch: '#64748B', ink: '#334155', soft: '#F1F5F9', inkDark: '#CBD5E1', softDark: '#1E293B' },
43
+ { key: 'stone', label: 'Stone', swatch: '#78716C', ink: '#57534E', soft: '#F5F5F4', inkDark: '#A8A29E', softDark: '#1C1917' },
44
+ { key: 'graphite', label: 'Graphite', swatch: '#404040', ink: '#262626', soft: '#E5E5E5', inkDark: '#F0F0F0', softDark: '#171717' },
45
+ ])
46
+
47
+ /** What an unknown colour value renders as. */
48
+ export const PICKER_FALLBACK_COLOR = 'slate'
49
+
50
+ /** The icon catalogue's categories, in the order the picker's chips show them. */
51
+ export const PICKER_ICON_CATEGORIES = [
52
+ 'work', 'people', 'communication', 'commerce', 'operations', 'places', 'tech', 'status', 'objects', 'nature',
53
+ ] as const
54
+
55
+ /** What an unknown icon name renders as. */
56
+ export const PICKER_FALLBACK_ICON = 'circle'
57
+
58
+ /**
59
+ * The curated icon catalogue by category: a kebab-case lucide name (canonical, never an alias) and
60
+ * its English search words. Icon names stay English in every language — they are what is stored.
61
+ * A superset of the icons the planning kits use.
62
+ */
63
+ const CATALOGUE: Readonly<Record<PickerIconCategory, ReadonlyArray<readonly [string, string]>>> = {
64
+ work: [
65
+ ['briefcase', 'job, business, portfolio, case'],
66
+ ['folder', 'directory, project, files'],
67
+ ['folder-open', 'directory, browse, project'],
68
+ ['folder-kanban', 'board, project, tasks'],
69
+ ['file', 'document, page'],
70
+ ['file-text', 'document, doc, page, note, text'],
71
+ ['files', 'documents, copies'],
72
+ ['clipboard-list', 'checklist, tasks, list, agenda'],
73
+ ['clipboard-check', 'done, approved, review'],
74
+ ['list-checks', 'checklist, tasks, todo'],
75
+ ['list-todo', 'tasks, todo, backlog'],
76
+ ['square-check', 'done, task, complete, checkbox'],
77
+ ['kanban', 'board, columns, workflow, tasks'],
78
+ ['calendar', 'date, schedule, event, day'],
79
+ ['calendar-check', 'booked, scheduled, appointment, done'],
80
+ ['calendar-days', 'month, schedule, planner'],
81
+ ['calendar-clock', 'deadline, due, schedule'],
82
+ ['clock', 'time, hours, schedule'],
83
+ ['timer', 'stopwatch, countdown, duration'],
84
+ ['hourglass', 'waiting, time, pending'],
85
+ ['target', 'goal, aim, objective, focus'],
86
+ ['flag', 'milestone, priority, report, mark'],
87
+ ['milestone', 'roadmap, sign, step'],
88
+ ['rocket', 'launch, release, start, fast'],
89
+ ['lightbulb', 'idea, insight, tip, innovation'],
90
+ ['book-open', 'read, docs, guide, knowledge'],
91
+ ['notebook-pen', 'notes, journal, write'],
92
+ ['presentation', 'slides, meeting, demo, board'],
93
+ ['layers', 'stack, levels, epic'],
94
+ ['layout-grid', 'dashboard, grid, apps'],
95
+ ['workflow', 'process, flow, pipeline, automation'],
96
+ ['goal', 'objective, finish, success'],
97
+ ['trophy', 'win, award, achievement, prize'],
98
+ ['award', 'badge, medal, quality, recognition'],
99
+ ['pen-line', 'edit, sign, write'],
100
+ ['archive', 'storage, old, history, box'],
101
+ ['paperclip', 'attachment, attach, clip'],
102
+ ],
103
+ people: [
104
+ ['user', 'person, account, profile, member'],
105
+ ['user-round', 'person, contact, profile'],
106
+ ['user-round-check', 'verified, approved, assigned'],
107
+ ['user-round-plus', 'invite, add, new member'],
108
+ ['user-check', 'verified, approved'],
109
+ ['user-plus', 'invite, add, signup'],
110
+ ['users', 'team, group, people, members'],
111
+ ['users-round', 'team, community, group'],
112
+ ['contact', 'address book, card, person, lead'],
113
+ ['id-card', 'identity, badge, passport, license'],
114
+ ['handshake', 'deal, agreement, partner, sale'],
115
+ ['person-standing', 'individual, human, figure'],
116
+ ['accessibility', 'a11y, disability, inclusive'],
117
+ ['face-slightly-smiling', 'smile, happy, satisfaction, feedback'],
118
+ ['heart-handshake', 'support, care, volunteer, charity'],
119
+ ['graduation-cap', 'education, student, school, course'],
120
+ ['user-cog', 'admin, settings, profile'],
121
+ ['crown', 'owner, vip, premium, leader'],
122
+ ['hand', 'help, raise, stop, volunteer'],
123
+ ['thumbs-up', 'like, approve, good'],
124
+ ],
125
+ communication: [
126
+ ['mail', 'email, message, letter, inbox'],
127
+ ['mail-open', 'read, email, letter'],
128
+ ['inbox', 'incoming, messages, queue, tray'],
129
+ ['send', 'submit, deliver, outgoing, plane'],
130
+ ['message-square', 'chat, comment, message, conversation'],
131
+ ['message-circle', 'chat, bubble, talk'],
132
+ ['messages-square', 'conversation, chat, thread, discussion'],
133
+ ['phone', 'call, telephone, contact'],
134
+ ['phone-call', 'ringing, call, support'],
135
+ ['megaphone', 'announcement, marketing, campaign, broadcast'],
136
+ ['bell', 'notification, alert, reminder'],
137
+ ['bell-ring', 'alarm, notification, ring'],
138
+ ['at-sign', 'email, mention, address'],
139
+ ['headset', 'support, help desk, call center, service'],
140
+ ['video', 'call, meeting, camera, record'],
141
+ ['mic', 'voice, audio, record, podcast'],
142
+ ['share-2', 'share, network, social'],
143
+ ['reply', 'answer, respond, back'],
144
+ ['languages', 'translate, language, i18n'],
145
+ ['newspaper', 'news, press, article, blog'],
146
+ ],
147
+ commerce: [
148
+ ['shopping-cart', 'cart, buy, checkout, order'],
149
+ ['shopping-bag', 'bag, purchase, shop'],
150
+ ['store', 'shop, retail, storefront'],
151
+ ['receipt', 'invoice, bill, payment'],
152
+ ['credit-card', 'card, payment, pay'],
153
+ ['wallet', 'money, funds, budget'],
154
+ ['banknote', 'cash, money, bill, payment'],
155
+ ['coins', 'money, cash, cost, change'],
156
+ ['piggy-bank', 'savings, budget, money'],
157
+ ['dollar-sign', 'money, price, revenue, usd'],
158
+ ['euro', 'money, price, eur'],
159
+ ['percent', 'discount, rate, tax'],
160
+ ['tag', 'label, price, category'],
161
+ ['tags', 'labels, categories'],
162
+ ['ticket', 'event, pass, admission, support ticket'],
163
+ ['gift', 'present, reward, bonus'],
164
+ ['package', 'box, product, parcel, delivery'],
165
+ ['badge-percent', 'sale, discount, promotion'],
166
+ ['trending-up', 'growth, increase, sales, up'],
167
+ ['trending-down', 'decline, decrease, loss'],
168
+ ['scale', 'balance, legal, compare, law'],
169
+ ['landmark', 'bank, finance, government, institution'],
170
+ ['calculator', 'math, accounting, estimate'],
171
+ ['hand-coins', 'pay, donation, tip, payment'],
172
+ ['chart-line', 'analytics, graph, metrics, trend'],
173
+ ['chart-column', 'bar chart, stats, report'],
174
+ ['chart-pie', 'share, distribution, analytics'],
175
+ ],
176
+ operations: [
177
+ ['wrench', 'maintenance, repair, fix, tool'],
178
+ ['hammer', 'build, construction, tool'],
179
+ ['settings', 'configuration, preferences, gear'],
180
+ ['cog', 'gear, mechanism, setup'],
181
+ ['sliders-horizontal', 'controls, adjust, filters'],
182
+ ['funnel', 'filter, pipeline, sales funnel, leads'],
183
+ ['truck', 'delivery, shipping, logistics, transport'],
184
+ ['warehouse', 'storage, inventory, stock, depot'],
185
+ ['factory', 'manufacturing, production, plant'],
186
+ ['container', 'shipping, freight, cargo'],
187
+ ['boxes', 'inventory, stock, products'],
188
+ ['package-check', 'delivered, received, fulfilled'],
189
+ ['route', 'path, journey, road, trip'],
190
+ ['gauge', 'performance, speed, meter, kpi'],
191
+ ['activity', 'pulse, health, monitoring'],
192
+ ['siren', 'emergency, incident, alarm, urgent'],
193
+ ['shield', 'security, protection, safety, guard'],
194
+ ['shield-check', 'secure, verified, compliance'],
195
+ ['lock', 'secure, private, locked, password'],
196
+ ['key', 'access, password, credentials'],
197
+ ['hard-hat', 'safety, construction, worker'],
198
+ ['construction', 'under construction, roadwork, barrier'],
199
+ ['recycle', 'reuse, sustainability, waste'],
200
+ ['stamp', 'approval, certify, seal, official'],
201
+ ],
202
+ places: [
203
+ ['building', 'office, company, organization, business'],
204
+ ['building-complex', 'offices, campus, enterprise, city'],
205
+ ['house', 'home, residence, property'],
206
+ ['hotel', 'hospitality, stay, accommodation'],
207
+ ['school', 'education, campus, class'],
208
+ ['hospital', 'health, clinic, medical'],
209
+ ['map', 'location, region, territory'],
210
+ ['map-pin', 'location, place, address, marker'],
211
+ ['map-pinned', 'location, venue, destination'],
212
+ ['globe', 'world, international, web, global'],
213
+ ['earth', 'planet, world, environment'],
214
+ ['compass', 'direction, explore, navigation'],
215
+ ['navigation', 'direction, gps, arrow'],
216
+ ['plane', 'travel, flight, airport, trip'],
217
+ ['car', 'vehicle, drive, auto, fleet'],
218
+ ['bus', 'transit, transport, travel'],
219
+ ['train-front', 'rail, transit, travel'],
220
+ ['ship', 'boat, sea, cruise, shipping'],
221
+ ['bike', 'bicycle, cycling, ride'],
222
+ ['mountain', 'outdoors, peak, adventure'],
223
+ ],
224
+ tech: [
225
+ ['code', 'development, programming, source'],
226
+ ['terminal', 'console, shell, command line, cli'],
227
+ ['server', 'backend, hosting, infrastructure'],
228
+ ['database', 'data, storage, records, sql'],
229
+ ['cloud', 'hosting, saas, online'],
230
+ ['cpu', 'processor, chip, hardware'],
231
+ ['monitor', 'screen, desktop, display'],
232
+ ['laptop', 'computer, notebook, device'],
233
+ ['smartphone', 'mobile, phone, app, device'],
234
+ ['tablet', 'ipad, device, touch'],
235
+ ['wifi', 'internet, wireless, network'],
236
+ ['bluetooth', 'wireless, device, pairing'],
237
+ ['plug', 'integration, power, connect, plugin'],
238
+ ['hard-drive', 'disk, storage, backup'],
239
+ ['git-branch', 'version control, branch, repository'],
240
+ ['git-pull-request', 'review, merge, code review'],
241
+ ['bot', 'robot, automation, ai, assistant'],
242
+ ['brain', 'ai, intelligence, mind, think'],
243
+ ['puzzle', 'integration, plugin, extension, piece'],
244
+ ['blocks', 'modules, components, building blocks'],
245
+ ['bug', 'defect, issue, error, insect'],
246
+ ['webhook', 'hook, integration, event, api'],
247
+ ['link', 'url, connection, chain'],
248
+ ['qr-code', 'scan, code, mobile'],
249
+ ['keyboard', 'typing, input, shortcut'],
250
+ ['printer', 'print, document, office'],
251
+ ],
252
+ status: [
253
+ ['circle', 'dot, default, neutral, generic'],
254
+ ['circle-check', 'done, success, complete, ok'],
255
+ ['circle-x', 'cancel, failed, error, close'],
256
+ ['circle-alert', 'warning, attention, issue'],
257
+ ['circle-question-mark', 'help, question, unknown, faq'],
258
+ ['circle-pause', 'paused, hold, on hold'],
259
+ ['circle-play', 'start, running, in progress'],
260
+ ['circle-dot', 'active, current, selected, record'],
261
+ ['circle-dashed', 'draft, pending, not started, todo'],
262
+ ['triangle-alert', 'warning, caution, risk, danger'],
263
+ ['octagon-alert', 'stop, critical, error, blocker'],
264
+ ['info', 'information, about, details'],
265
+ ['ban', 'blocked, forbidden, cancelled, prohibited'],
266
+ ['check', 'done, ok, yes, approve'],
267
+ ['x', 'close, no, reject, cancel'],
268
+ ['loader', 'loading, progress, spinner, working'],
269
+ ['refresh-cw', 'sync, retry, recurring, update'],
270
+ ['eye', 'view, visible, watch, review'],
271
+ ['eye-off', 'hidden, private, invisible'],
272
+ ['flame', 'hot, trending, urgent, fire'],
273
+ ['zap', 'fast, energy, power, quick'],
274
+ ['sparkles', 'new, magic, ai, highlight'],
275
+ ['star', 'favorite, rating, featured, priority'],
276
+ ['heart', 'like, love, favorite, health'],
277
+ ['thumbs-down', 'dislike, reject, bad'],
278
+ ['badge-check', 'verified, certified, approved, quality'],
279
+ ['shield-alert', 'risk, threat, security issue'],
280
+ ['bookmark', 'save, saved, later, mark'],
281
+ ['pin', 'pinned, important, fixed'],
282
+ ],
283
+ objects: [
284
+ ['book', 'read, manual, library, guide'],
285
+ ['pen', 'write, sign, edit'],
286
+ ['pencil', 'edit, draft, write, sketch'],
287
+ ['palette', 'design, colors, art, theme'],
288
+ ['brush', 'paint, design, art'],
289
+ ['camera', 'photo, picture, photography'],
290
+ ['image', 'picture, photo, media, gallery'],
291
+ ['music', 'audio, song, sound'],
292
+ ['headphones', 'audio, listen, podcast, support'],
293
+ ['gamepad-2', 'game, gaming, play, controller'],
294
+ ['umbrella', 'insurance, protection, rain, cover'],
295
+ ['shirt', 'clothing, apparel, fashion, merch'],
296
+ ['watch', 'time, wearable, clock'],
297
+ ['coffee', 'break, cafe, drink, morning'],
298
+ ['utensils', 'food, restaurant, dining, meal'],
299
+ ['lamp', 'light, idea, desk'],
300
+ ['armchair', 'furniture, comfort, lounge, waiting room'],
301
+ ['bed', 'hotel, sleep, rest, room'],
302
+ ['scissors', 'cut, trim, craft'],
303
+ ['ruler', 'measure, size, design'],
304
+ ['trash', 'delete, bin, remove, waste'],
305
+ ['box', 'package, storage, container'],
306
+ ['magnet', 'attract, leads, pull'],
307
+ ['flask-conical', 'lab, science, experiment, test'],
308
+ ['microscope', 'research, science, lab'],
309
+ ['stethoscope', 'medical, doctor, health, care'],
310
+ ['pill', 'medicine, pharmacy, health'],
311
+ ['dumbbell', 'fitness, gym, workout, sport'],
312
+ ],
313
+ nature: [
314
+ ['leaf', 'eco, green, plant, organic'],
315
+ ['tree-pine', 'forest, christmas, outdoors'],
316
+ ['trees', 'forest, park, nature'],
317
+ ['flower', 'blossom, spring, garden'],
318
+ ['flower-2', 'blossom, daisy, garden'],
319
+ ['sprout', 'growth, seedling, startup, new'],
320
+ ['sun', 'day, light, summer, weather'],
321
+ ['moon', 'night, dark, sleep'],
322
+ ['cloud-rain', 'weather, rain, storm'],
323
+ ['cloud-sun', 'weather, forecast, partly cloudy'],
324
+ ['snowflake', 'winter, cold, frozen, freeze'],
325
+ ['droplet', 'water, liquid, drop'],
326
+ ['waves-horizontal', 'water, sea, ocean, waves'],
327
+ ['wind', 'air, breeze, weather'],
328
+ ['mountain-snow', 'alpine, peak, winter'],
329
+ ['bird', 'animal, fly, wing'],
330
+ ['fish', 'animal, sea, food'],
331
+ ['cat', 'pet, animal'],
332
+ ['dog', 'pet, animal'],
333
+ ['paw-print', 'pet, animal, vet'],
334
+ ['feather', 'light, write, bird'],
335
+ ['apple', 'fruit, food, health, education'],
336
+ ['carrot', 'vegetable, food, garden'],
337
+ ],
338
+ }
339
+
340
+ /** Every catalogue icon with its category and search words, category by category. */
341
+ export const PICKER_ICON_ENTRIES: readonly PickerIconEntry[] = Object.freeze(PICKER_ICON_CATEGORIES.flatMap(
342
+ category => CATALOGUE[category].map(([name, keywords]): PickerIconEntry =>
343
+ Object.freeze({ name, category, keywords: Object.freeze(keywords.split(', ')) }))
344
+ ))
345
+
346
+ /** The catalogue's names, in catalogue order. */
347
+ export const PICKER_ICON_NAMES: readonly string[] = Object.freeze(PICKER_ICON_ENTRIES.map(icon => icon.name))
@@ -0,0 +1,72 @@
1
+ import type { PICKER_COLOR_KEYS, PICKER_ICON_CATEGORIES } from './consts.js'
2
+
3
+ /**
4
+ * One colour a picker offers. The palette's own entries carry hex values; an application's palette
5
+ * may carry any CSS colour — a status palette reads its theme's `var(--tone-<t>)` tokens.
6
+ */
7
+ export interface PickerColor {
8
+ /** Palette key (`'blue'`), or any id of an application palette (`'info'`). What is stored. */
9
+ key: string
10
+ /** The swatch circle the picker shows for this colour (hex or `var(...)`). */
11
+ swatch: string
12
+ /** Icon and dot colour on the light page — at least 3:1 on `soft` and on white. */
13
+ ink: string
14
+ /** Tile ground on the light page. */
15
+ soft: string
16
+ /** Icon and dot colour on the dark page — at least 3:1 on `softDark` and on black. Defaults to `ink`. */
17
+ inkDark?: string
18
+ /** Tile ground on the dark page. Defaults to `soft`. */
19
+ softDark?: string
20
+ /** English name; absent, the key humanized. */
21
+ label?: string
22
+ }
23
+
24
+ /** A stored colour value read against a palette: every field filled in. */
25
+ export interface ResolvedPickerColor {
26
+ /** The palette key, or the normalized lowercase `#rrggbb` of a custom colour. */
27
+ key: string
28
+ /** `true` for a hex value that is not a palette key. */
29
+ custom: boolean
30
+ /** English name — the palette label, or the hex itself for a custom colour. */
31
+ label: string
32
+ swatch: string
33
+ ink: string
34
+ soft: string
35
+ inkDark: string
36
+ softDark: string
37
+ }
38
+
39
+ /** One of the 24 palette keys. */
40
+ export type PickerColorKey = typeof PICKER_COLOR_KEYS[number]
41
+
42
+ /** One of the icon catalogue's categories. */
43
+ export type PickerIconCategory = typeof PICKER_ICON_CATEGORIES[number]
44
+
45
+ /** One icon of the catalogue: a kebab-case lucide name, its category and English search words. */
46
+ export interface PickerIconEntry {
47
+ name: string
48
+ category: PickerIconCategory
49
+ keywords: readonly string[]
50
+ }
51
+
52
+ /** Reads, validates and renders a stored colour value. React-free. */
53
+ export interface PickerColorHelper {
54
+ /** `'#abc'` or `'#aabbcc'`, any case — the forms a picker accepts as a custom colour. */
55
+ isHex: (value: unknown) => value is string
56
+ /** `'#ABC'`, `'abc'`, `'AABBCC'` → `'#aabbcc'`; anything else → `null`. */
57
+ normalizeHex: (value: string) => string | null
58
+ /**
59
+ * A key of `colors` (default the 24-colour palette) or a hex value, every field filled in — a hex
60
+ * gets an ink and a ground derived from it that keep 4.5:1 in both modes. Unknown or empty → `null`.
61
+ */
62
+ resolve: (value: string | null | undefined, colors?: readonly PickerColor[]) => ResolvedPickerColor | null
63
+ /**
64
+ * The CSS custom properties `--pick-swatch`, `--pick-ink`, `--pick-soft`, `--pick-ink-dark` and
65
+ * `--pick-soft-dark` for a value — what every picker part reads. Unknown → the fallback colour's
66
+ * (`slate`, or the first entry of an application palette without one). A plain string record, so it
67
+ * goes straight into a React `style` (and merges with other properties there).
68
+ */
69
+ styleOf: (value: string | null | undefined, colors?: readonly PickerColor[]) => Record<string, string>
70
+ /** The same key for the same seed — a stable colour for a record that has none of its own. */
71
+ hashKey: (seed: string, keys?: readonly string[]) => string
72
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * `@owlmeans/web-panel/picker/vocabulary` — the picker's data and its colour helper, with no React
3
+ * and no icon set: the palette, the icon catalogue's names, categories and search words, and
4
+ * `pickerColorHelper`. Safe to import from a server, a seed or a Node build script.
5
+ */
6
+
7
+ import { PICKER_COLORS, PICKER_COLOR_KEYS, PICKER_FALLBACK_COLOR } from './vocabulary/consts.js'
8
+ import type { PickerColor, PickerColorHelper, ResolvedPickerColor } from './vocabulary/types.js'
9
+ import { colorUtils } from './utils/color.js'
10
+
11
+ export * from './vocabulary/consts.js'
12
+ export type * from './vocabulary/types.js'
13
+
14
+ export const createPickerColorHelper = (): PickerColorHelper => {
15
+ // Derivation walks lightness in small steps; a page renders the same custom colour many times.
16
+ const derived = new Map<string, ResolvedPickerColor>()
17
+
18
+ const isHex = (value: unknown): value is string =>
19
+ typeof value === 'string' && /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test(value.trim())
20
+
21
+ const normalizeHex = (value: string): string | null => {
22
+ const match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(value.trim())
23
+ if (match == null) {
24
+ return null
25
+ }
26
+ const digits = match[1].toLowerCase()
27
+
28
+ return `#${digits.length === 3 ? [...digits].map(digit => digit + digit).join('') : digits}`
29
+ }
30
+
31
+ const humanize = (key: string): string => {
32
+ const words = key.replace(/[-_]+/g, ' ').trim()
33
+
34
+ return words === '' ? key : words[0].toUpperCase() + words.slice(1)
35
+ }
36
+
37
+ const fill = (color: PickerColor): ResolvedPickerColor => ({
38
+ key: color.key,
39
+ custom: false,
40
+ label: color.label ?? humanize(color.key),
41
+ swatch: color.swatch,
42
+ ink: color.ink,
43
+ soft: color.soft,
44
+ inkDark: color.inkDark ?? color.ink,
45
+ softDark: color.softDark ?? color.soft,
46
+ })
47
+
48
+ const custom = (hex: string): ResolvedPickerColor => {
49
+ const known = derived.get(hex)
50
+ if (known != null) {
51
+ return known
52
+ }
53
+ const resolved: ResolvedPickerColor = { key: hex, custom: true, label: hex.toUpperCase(), swatch: hex, ...colorUtils.derive(hex) }
54
+ derived.set(hex, resolved)
55
+
56
+ return resolved
57
+ }
58
+
59
+ const resolve = (
60
+ value: string | null | undefined, colors: readonly PickerColor[] = PICKER_COLORS
61
+ ): ResolvedPickerColor | null => {
62
+ if (typeof value !== 'string' || value.trim() === '') {
63
+ return null
64
+ }
65
+ const key = value.trim()
66
+ const known = colors.find(color => color.key === key) ?? colors.find(color => color.key === key.toLowerCase())
67
+ if (known != null) {
68
+ return fill(known)
69
+ }
70
+ const hex = normalizeHex(key)
71
+
72
+ return hex != null && key.startsWith('#') ? custom(hex) : null
73
+ }
74
+
75
+ const paletteFallback = fill(PICKER_COLORS.find(color => color.key === PICKER_FALLBACK_COLOR) ?? PICKER_COLORS[0])
76
+
77
+ const fallbackOf = (colors: readonly PickerColor[]): ResolvedPickerColor => {
78
+ const fallback = colors.find(color => color.key === PICKER_FALLBACK_COLOR) ?? colors.at(0)
79
+
80
+ return fallback != null ? fill(fallback) : paletteFallback
81
+ }
82
+
83
+ const styleOf = (
84
+ value: string | null | undefined, colors: readonly PickerColor[] = PICKER_COLORS
85
+ ): Record<string, string> => {
86
+ const color = resolve(value, colors) ?? fallbackOf(colors)
87
+
88
+ return {
89
+ '--pick-swatch': color.swatch,
90
+ '--pick-ink': color.ink,
91
+ '--pick-soft': color.soft,
92
+ '--pick-ink-dark': color.inkDark,
93
+ '--pick-soft-dark': color.softDark,
94
+ }
95
+ }
96
+
97
+ const hashKey = (seed: string, keys: readonly string[] = PICKER_COLOR_KEYS): string => {
98
+ // FNV-1a: tiny, stable across runtimes, and spreads short ids well enough for a palette.
99
+ let hash = 0x811c9dc5
100
+ for (let index = 0; index < seed.length; index++) {
101
+ hash ^= seed.charCodeAt(index)
102
+ hash = Math.imul(hash, 0x01000193) >>> 0
103
+ }
104
+
105
+ return keys.length > 0 ? keys[hash % keys.length] : PICKER_FALLBACK_COLOR
106
+ }
107
+
108
+ return { isHex, normalizeHex, resolve, styleOf, hashKey }
109
+ }
110
+
111
+ export const pickerColorHelper = createPickerColorHelper()
@@ -0,0 +1,8 @@
1
+ /** The `localStorage` key the choice lives under. */
2
+ export const COLOR_SCHEME_KEY = 'owlmeans:color-scheme'
3
+
4
+ /**
5
+ * The event `applyColorScheme` dispatches on `window` after every change, so every mounted
6
+ * `useColorScheme` in the document — two toggles, a header and a footer — agrees at once.
7
+ */
8
+ export const COLOR_SCHEME_EVENT = 'owlmeans:color-scheme'
@@ -0,0 +1,3 @@
1
+ export { colorSchemeHelper, createColorSchemeHelper, colorSchemeBootstrapScript } from './scheme.js'
2
+ export { COLOR_SCHEME_KEY, COLOR_SCHEME_EVENT } from './consts.js'
3
+ export type { ColorSchemeChoice, ColorSchemeHelper } from './types.js'