@owlmeans/web-panel 0.1.18-rc.9 → 0.1.19-rc.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 (673) 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 +2 -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/plugins/basic-ed25519.js +4 -4
  53. package/build/auth/plugins/basic-ed25519.js.map +1 -1
  54. package/build/auth/plugins/re-captcha.js +3 -3
  55. package/build/auth/plugins/re-captcha.js.map +1 -1
  56. package/build/auth/plugins/tunnel-consumer.js +1 -1
  57. package/build/auth/plugins/tunnel-consumer.js.map +1 -1
  58. package/build/components/block.js +2 -2
  59. package/build/components/block.js.map +1 -1
  60. package/build/components/consts.local.d.ts +14 -0
  61. package/build/components/consts.local.d.ts.map +1 -0
  62. package/build/components/consts.local.js +26 -0
  63. package/build/components/consts.local.js.map +1 -0
  64. package/build/components/footer/component.d.ts +19 -1
  65. package/build/components/footer/component.d.ts.map +1 -1
  66. package/build/components/footer/component.js +38 -11
  67. package/build/components/footer/component.js.map +1 -1
  68. package/build/components/footer/credit.d.ts +27 -0
  69. package/build/components/footer/credit.d.ts.map +1 -0
  70. package/build/components/footer/credit.js +42 -0
  71. package/build/components/footer/credit.js.map +1 -0
  72. package/build/components/footer/index.d.ts +1 -0
  73. package/build/components/footer/index.d.ts.map +1 -1
  74. package/build/components/footer/index.js +1 -0
  75. package/build/components/footer/index.js.map +1 -1
  76. package/build/components/footer/types.d.ts +22 -1
  77. package/build/components/footer/types.d.ts.map +1 -1
  78. package/build/components/form/button/component.d.ts.map +1 -1
  79. package/build/components/form/button/component.js +5 -3
  80. package/build/components/form/button/component.js.map +1 -1
  81. package/build/components/form/component.js +2 -2
  82. package/build/components/form/component.js.map +1 -1
  83. package/build/components/form/text/component.js +2 -2
  84. package/build/components/form/text/component.js.map +1 -1
  85. package/build/components/helper.d.ts.map +1 -1
  86. package/build/components/helper.js +1 -12
  87. package/build/components/helper.js.map +1 -1
  88. package/build/components/index.d.ts +4 -0
  89. package/build/components/index.d.ts.map +1 -1
  90. package/build/components/index.js +4 -0
  91. package/build/components/index.js.map +1 -1
  92. package/build/components/link.js +3 -3
  93. package/build/components/link.js.map +1 -1
  94. package/build/components/login/append.d.ts +15 -0
  95. package/build/components/login/append.d.ts.map +1 -0
  96. package/build/components/login/append.js +26 -0
  97. package/build/components/login/append.js.map +1 -0
  98. package/build/components/login/consts.d.ts +3 -0
  99. package/build/components/login/consts.d.ts.map +1 -0
  100. package/build/components/login/consts.js +3 -0
  101. package/build/components/login/consts.js.map +1 -0
  102. package/build/components/login/consts.local.d.ts +4 -0
  103. package/build/components/login/consts.local.d.ts.map +1 -0
  104. package/build/components/login/consts.local.js +8 -0
  105. package/build/components/login/consts.local.js.map +1 -0
  106. package/build/components/login/credit.d.ts +12 -0
  107. package/build/components/login/credit.d.ts.map +1 -0
  108. package/build/components/login/credit.js +18 -0
  109. package/build/components/login/credit.js.map +1 -0
  110. package/build/components/login/i18n/be.json +10 -0
  111. package/build/components/login/i18n/de.json +10 -0
  112. package/build/components/login/i18n/en.json +10 -0
  113. package/build/components/login/i18n/es.json +10 -0
  114. package/build/components/login/i18n/fr.json +10 -0
  115. package/build/components/login/i18n/pl.json +10 -0
  116. package/build/components/login/i18n/ru.json +10 -0
  117. package/build/components/login/i18n/uk.json +10 -0
  118. package/build/components/login/i18n.d.ts +2 -0
  119. package/build/components/login/i18n.d.ts.map +1 -0
  120. package/build/components/login/i18n.js +28 -0
  121. package/build/components/login/i18n.js.map +1 -0
  122. package/build/components/login/icons.d.ts +14 -0
  123. package/build/components/login/icons.d.ts.map +1 -0
  124. package/build/components/login/icons.js +29 -0
  125. package/build/components/login/icons.js.map +1 -0
  126. package/build/components/login/index.d.ts +11 -0
  127. package/build/components/login/index.d.ts.map +1 -0
  128. package/build/components/login/index.js +10 -0
  129. package/build/components/login/index.js.map +1 -0
  130. package/build/components/login/notify.d.ts +18 -0
  131. package/build/components/login/notify.d.ts.map +1 -0
  132. package/build/components/login/notify.js +41 -0
  133. package/build/components/login/notify.js.map +1 -0
  134. package/build/components/login/provider.d.ts +20 -0
  135. package/build/components/login/provider.d.ts.map +1 -0
  136. package/build/components/login/provider.js +31 -0
  137. package/build/components/login/provider.js.map +1 -0
  138. package/build/components/login/screen.d.ts +24 -0
  139. package/build/components/login/screen.d.ts.map +1 -0
  140. package/build/components/login/screen.js +92 -0
  141. package/build/components/login/screen.js.map +1 -0
  142. package/build/components/login/terms.d.ts +19 -0
  143. package/build/components/login/terms.d.ts.map +1 -0
  144. package/build/components/login/terms.js +32 -0
  145. package/build/components/login/terms.js.map +1 -0
  146. package/build/components/login/types.d.ts +28 -0
  147. package/build/components/login/types.d.ts.map +1 -0
  148. package/build/components/login/types.js +2 -0
  149. package/build/components/login/types.js.map +1 -0
  150. package/build/components/nav/consts.local.d.ts +41 -0
  151. package/build/components/nav/consts.local.d.ts.map +1 -0
  152. package/build/components/nav/consts.local.js +60 -0
  153. package/build/components/nav/consts.local.js.map +1 -0
  154. package/build/components/nav/index.d.ts +1 -0
  155. package/build/components/nav/index.d.ts.map +1 -1
  156. package/build/components/nav/index.js +1 -0
  157. package/build/components/nav/index.js.map +1 -1
  158. package/build/components/nav/layout.d.ts +9 -2
  159. package/build/components/nav/layout.d.ts.map +1 -1
  160. package/build/components/nav/layout.js +48 -7
  161. package/build/components/nav/layout.js.map +1 -1
  162. package/build/components/nav/mobile.d.ts +21 -0
  163. package/build/components/nav/mobile.d.ts.map +1 -0
  164. package/build/components/nav/mobile.js +55 -0
  165. package/build/components/nav/mobile.js.map +1 -0
  166. package/build/components/nav/side.d.ts.map +1 -1
  167. package/build/components/nav/side.js +10 -10
  168. package/build/components/nav/side.js.map +1 -1
  169. package/build/components/nav/top.d.ts.map +1 -1
  170. package/build/components/nav/top.js +12 -8
  171. package/build/components/nav/top.js.map +1 -1
  172. package/build/components/nav/types.d.ts +64 -1
  173. package/build/components/nav/types.d.ts.map +1 -1
  174. package/build/components/nav/viewport.d.ts +3 -0
  175. package/build/components/nav/viewport.d.ts.map +1 -0
  176. package/build/components/nav/viewport.js +14 -0
  177. package/build/components/nav/viewport.js.map +1 -0
  178. package/build/components/panel-app/component.d.ts.map +1 -1
  179. package/build/components/panel-app/component.js +4 -3
  180. package/build/components/panel-app/component.js.map +1 -1
  181. package/build/components/picker/color-picker.d.ts +9 -0
  182. package/build/components/picker/color-picker.d.ts.map +1 -0
  183. package/build/components/picker/color-picker.js +9 -0
  184. package/build/components/picker/color-picker.js.map +1 -0
  185. package/build/components/picker/consts.local.d.ts +76 -0
  186. package/build/components/picker/consts.local.d.ts.map +1 -0
  187. package/build/components/picker/consts.local.js +214 -0
  188. package/build/components/picker/consts.local.js.map +1 -0
  189. package/build/components/picker/dot.d.ts +8 -0
  190. package/build/components/picker/dot.d.ts.map +1 -0
  191. package/build/components/picker/dot.js +10 -0
  192. package/build/components/picker/dot.js.map +1 -0
  193. package/build/components/picker/grid.d.ts +17 -0
  194. package/build/components/picker/grid.d.ts.map +1 -0
  195. package/build/components/picker/grid.js +73 -0
  196. package/build/components/picker/grid.js.map +1 -0
  197. package/build/components/picker/i18n/be.json +60 -0
  198. package/build/components/picker/i18n/de.json +60 -0
  199. package/build/components/picker/i18n/en.json +60 -0
  200. package/build/components/picker/i18n/es.json +60 -0
  201. package/build/components/picker/i18n/fr.json +60 -0
  202. package/build/components/picker/i18n/pl.json +60 -0
  203. package/build/components/picker/i18n/ru.json +60 -0
  204. package/build/components/picker/i18n/uk.json +60 -0
  205. package/build/components/picker/i18n.d.ts +2 -0
  206. package/build/components/picker/i18n.d.ts.map +1 -0
  207. package/build/components/picker/i18n.js +18 -0
  208. package/build/components/picker/i18n.js.map +1 -0
  209. package/build/components/picker/icon-color-picker.d.ts +14 -0
  210. package/build/components/picker/icon-color-picker.d.ts.map +1 -0
  211. package/build/components/picker/icon-color-picker.js +15 -0
  212. package/build/components/picker/icon-color-picker.js.map +1 -0
  213. package/build/components/picker/icon-picker.d.ts +8 -0
  214. package/build/components/picker/icon-picker.d.ts.map +1 -0
  215. package/build/components/picker/icon-picker.js +8 -0
  216. package/build/components/picker/icon-picker.js.map +1 -0
  217. package/build/components/picker/index.d.ts +11 -0
  218. package/build/components/picker/index.d.ts.map +1 -0
  219. package/build/components/picker/index.js +10 -0
  220. package/build/components/picker/index.js.map +1 -0
  221. package/build/components/picker/panel.d.ts +9 -0
  222. package/build/components/picker/panel.d.ts.map +1 -0
  223. package/build/components/picker/panel.js +23 -0
  224. package/build/components/picker/panel.js.map +1 -0
  225. package/build/components/picker/root.d.ts +13 -0
  226. package/build/components/picker/root.d.ts.map +1 -0
  227. package/build/components/picker/root.js +55 -0
  228. package/build/components/picker/root.js.map +1 -0
  229. package/build/components/picker/roving.d.ts +8 -0
  230. package/build/components/picker/roving.d.ts.map +1 -0
  231. package/build/components/picker/roving.js +62 -0
  232. package/build/components/picker/roving.js.map +1 -0
  233. package/build/components/picker/surface.d.ts +18 -0
  234. package/build/components/picker/surface.d.ts.map +1 -0
  235. package/build/components/picker/surface.js +36 -0
  236. package/build/components/picker/surface.js.map +1 -0
  237. package/build/components/picker/swatches/custom.d.ts +10 -0
  238. package/build/components/picker/swatches/custom.d.ts.map +1 -0
  239. package/build/components/picker/swatches/custom.js +65 -0
  240. package/build/components/picker/swatches/custom.js.map +1 -0
  241. package/build/components/picker/swatches.d.ts +16 -0
  242. package/build/components/picker/swatches.d.ts.map +1 -0
  243. package/build/components/picker/swatches.js +35 -0
  244. package/build/components/picker/swatches.js.map +1 -0
  245. package/build/components/picker/text.d.ts +5 -0
  246. package/build/components/picker/text.d.ts.map +1 -0
  247. package/build/components/picker/text.js +29 -0
  248. package/build/components/picker/text.js.map +1 -0
  249. package/build/components/picker/tile.d.ts +11 -0
  250. package/build/components/picker/tile.d.ts.map +1 -0
  251. package/build/components/picker/tile.js +19 -0
  252. package/build/components/picker/tile.js.map +1 -0
  253. package/build/components/picker/translate.d.ts +9 -0
  254. package/build/components/picker/translate.d.ts.map +1 -0
  255. package/build/components/picker/translate.js +13 -0
  256. package/build/components/picker/translate.js.map +1 -0
  257. package/build/components/picker/trigger.d.ts +12 -0
  258. package/build/components/picker/trigger.d.ts.map +1 -0
  259. package/build/components/picker/trigger.js +29 -0
  260. package/build/components/picker/trigger.js.map +1 -0
  261. package/build/components/picker/types.d.ts +114 -0
  262. package/build/components/picker/types.d.ts.map +1 -0
  263. package/build/components/picker/types.js +2 -0
  264. package/build/components/picker/types.js.map +1 -0
  265. package/build/components/picker/types.local.d.ts +143 -0
  266. package/build/components/picker/types.local.d.ts.map +1 -0
  267. package/build/components/picker/types.local.js +2 -0
  268. package/build/components/picker/types.local.js.map +1 -0
  269. package/build/components/scheme/consts.local.d.ts +8 -0
  270. package/build/components/scheme/consts.local.d.ts.map +1 -0
  271. package/build/components/scheme/consts.local.js +13 -0
  272. package/build/components/scheme/consts.local.js.map +1 -0
  273. package/build/components/scheme/hook.d.ts +16 -0
  274. package/build/components/scheme/hook.d.ts.map +1 -0
  275. package/build/components/scheme/hook.js +52 -0
  276. package/build/components/scheme/hook.js.map +1 -0
  277. package/build/components/scheme/index.d.ts +4 -0
  278. package/build/components/scheme/index.d.ts.map +1 -0
  279. package/build/components/scheme/index.js +3 -0
  280. package/build/components/scheme/index.js.map +1 -0
  281. package/build/components/scheme/toggle.d.ts +14 -0
  282. package/build/components/scheme/toggle.d.ts.map +1 -0
  283. package/build/components/scheme/toggle.js +24 -0
  284. package/build/components/scheme/toggle.js.map +1 -0
  285. package/build/components/scheme/types.d.ts +21 -0
  286. package/build/components/scheme/types.d.ts.map +1 -0
  287. package/build/components/scheme/types.js +2 -0
  288. package/build/components/scheme/types.js.map +1 -0
  289. package/build/components/socket/i18n/be.json +9 -0
  290. package/build/components/socket/i18n/de.json +9 -0
  291. package/build/components/socket/i18n/en.json +9 -0
  292. package/build/components/socket/i18n/es.json +9 -0
  293. package/build/components/socket/i18n/fr.json +9 -0
  294. package/build/components/socket/i18n/pl.json +9 -0
  295. package/build/components/socket/i18n/ru.json +9 -0
  296. package/build/components/socket/i18n/uk.json +9 -0
  297. package/build/components/socket/i18n.d.ts +2 -0
  298. package/build/components/socket/i18n.d.ts.map +1 -0
  299. package/build/components/socket/i18n.js +18 -0
  300. package/build/components/socket/i18n.js.map +1 -0
  301. package/build/components/socket/index.d.ts +3 -0
  302. package/build/components/socket/index.d.ts.map +1 -0
  303. package/build/components/socket/index.js +3 -0
  304. package/build/components/socket/index.js.map +1 -0
  305. package/build/components/socket/reload-dialog.d.ts +22 -0
  306. package/build/components/socket/reload-dialog.d.ts.map +1 -0
  307. package/build/components/socket/reload-dialog.js +34 -0
  308. package/build/components/socket/reload-dialog.js.map +1 -0
  309. package/build/components/status.js +1 -1
  310. package/build/components/status.js.map +1 -1
  311. package/build/components/text.d.ts.map +1 -1
  312. package/build/components/text.js +2 -13
  313. package/build/components/text.js.map +1 -1
  314. package/build/components/toaster.d.ts +16 -0
  315. package/build/components/toaster.d.ts.map +1 -0
  316. package/build/components/toaster.js +52 -0
  317. package/build/components/toaster.js.map +1 -0
  318. package/build/components/uploader/consts.local.d.ts +4 -0
  319. package/build/components/uploader/consts.local.d.ts.map +1 -0
  320. package/build/components/uploader/consts.local.js +6 -0
  321. package/build/components/uploader/consts.local.js.map +1 -0
  322. package/build/components/uploader/image.d.ts.map +1 -1
  323. package/build/components/uploader/image.js +2 -6
  324. package/build/components/uploader/image.js.map +1 -1
  325. package/build/consent/component.d.ts +27 -0
  326. package/build/consent/component.d.ts.map +1 -0
  327. package/build/consent/component.js +60 -0
  328. package/build/consent/component.js.map +1 -0
  329. package/build/consent/consts.d.ts +2 -0
  330. package/build/consent/consts.d.ts.map +1 -0
  331. package/build/consent/consts.js +2 -0
  332. package/build/consent/consts.js.map +1 -0
  333. package/build/consent/consts.local.d.ts +9 -0
  334. package/build/consent/consts.local.d.ts.map +1 -0
  335. package/build/consent/consts.local.js +9 -0
  336. package/build/consent/consts.local.js.map +1 -0
  337. package/build/consent/geo.d.ts +17 -0
  338. package/build/consent/geo.d.ts.map +1 -0
  339. package/build/consent/geo.js +19 -0
  340. package/build/consent/geo.js.map +1 -0
  341. package/build/consent/index.d.ts +11 -0
  342. package/build/consent/index.d.ts.map +1 -0
  343. package/build/consent/index.js +9 -0
  344. package/build/consent/index.js.map +1 -0
  345. package/build/consent/language.d.ts +12 -0
  346. package/build/consent/language.d.ts.map +1 -0
  347. package/build/consent/language.js +11 -0
  348. package/build/consent/language.js.map +1 -0
  349. package/build/consent/menu-widget.d.ts +13 -0
  350. package/build/consent/menu-widget.d.ts.map +1 -0
  351. package/build/consent/menu-widget.js +20 -0
  352. package/build/consent/menu-widget.js.map +1 -0
  353. package/build/consent/presence.d.ts +30 -0
  354. package/build/consent/presence.d.ts.map +1 -0
  355. package/build/consent/presence.js +40 -0
  356. package/build/consent/presence.js.map +1 -0
  357. package/build/consent/service.d.ts +18 -0
  358. package/build/consent/service.d.ts.map +1 -0
  359. package/build/consent/service.js +53 -0
  360. package/build/consent/service.js.map +1 -0
  361. package/build/consent/translate.d.ts +14 -0
  362. package/build/consent/translate.d.ts.map +1 -0
  363. package/build/consent/translate.js +28 -0
  364. package/build/consent/translate.js.map +1 -0
  365. package/build/consent/types.d.ts +39 -0
  366. package/build/consent/types.d.ts.map +1 -0
  367. package/build/consent/types.js +2 -0
  368. package/build/consent/types.js.map +1 -0
  369. package/build/consent/types.local.d.ts +6 -0
  370. package/build/consent/types.local.d.ts.map +1 -0
  371. package/build/consent/types.local.js +2 -0
  372. package/build/consent/types.local.js.map +1 -0
  373. package/build/context.d.ts.map +1 -1
  374. package/build/context.js +10 -0
  375. package/build/context.js.map +1 -1
  376. package/build/editor/component.d.ts +4 -0
  377. package/build/editor/component.d.ts.map +1 -0
  378. package/build/editor/component.js +103 -0
  379. package/build/editor/component.js.map +1 -0
  380. package/build/editor/consts.local.d.ts +6 -0
  381. package/build/editor/consts.local.d.ts.map +1 -0
  382. package/build/editor/consts.local.js +58 -0
  383. package/build/editor/consts.local.js.map +1 -0
  384. package/build/editor/index.d.ts +3 -0
  385. package/build/editor/index.d.ts.map +1 -0
  386. package/build/editor/index.js +2 -0
  387. package/build/editor/index.js.map +1 -0
  388. package/build/editor/types.d.ts +24 -0
  389. package/build/editor/types.d.ts.map +1 -0
  390. package/build/editor/types.js +2 -0
  391. package/build/editor/types.js.map +1 -0
  392. package/build/entrypoints.d.ts +2 -0
  393. package/build/entrypoints.d.ts.map +1 -0
  394. package/build/entrypoints.js +4 -0
  395. package/build/entrypoints.js.map +1 -0
  396. package/build/exports.d.ts +6 -5
  397. package/build/exports.d.ts.map +1 -1
  398. package/build/exports.js +5 -5
  399. package/build/exports.js.map +1 -1
  400. package/build/index.d.ts +1 -1
  401. package/build/index.d.ts.map +1 -1
  402. package/build/index.js +1 -1
  403. package/build/index.js.map +1 -1
  404. package/build/main.d.ts +1 -4
  405. package/build/main.d.ts.map +1 -1
  406. package/build/main.js.map +1 -1
  407. package/build/permission/i18n/be.json +13 -0
  408. package/build/permission/i18n/de.json +13 -0
  409. package/build/permission/i18n/en.json +13 -0
  410. package/build/permission/i18n/es.json +13 -0
  411. package/build/permission/i18n/fr.json +13 -0
  412. package/build/permission/i18n/pl.json +13 -0
  413. package/build/permission/i18n/ru.json +13 -0
  414. package/build/permission/i18n/uk.json +13 -0
  415. package/build/permission/i18n.d.ts +2 -0
  416. package/build/permission/i18n.d.ts.map +1 -0
  417. package/build/permission/i18n.js +13 -0
  418. package/build/permission/i18n.js.map +1 -0
  419. package/build/permission/index.d.ts +6 -0
  420. package/build/permission/index.d.ts.map +1 -0
  421. package/build/permission/index.js +27 -0
  422. package/build/permission/index.js.map +1 -0
  423. package/build/permission/toast.d.ts +5 -0
  424. package/build/permission/toast.d.ts.map +1 -0
  425. package/build/permission/toast.js +8 -0
  426. package/build/permission/toast.js.map +1 -0
  427. package/build/permission/types.d.ts +6 -0
  428. package/build/permission/types.d.ts.map +1 -0
  429. package/build/permission/types.js +2 -0
  430. package/build/permission/types.js.map +1 -0
  431. package/build/picker/icons/consts.d.ts +9 -0
  432. package/build/picker/icons/consts.d.ts.map +1 -0
  433. package/build/picker/icons/consts.js +264 -0
  434. package/build/picker/icons/consts.js.map +1 -0
  435. package/build/picker/icons/types.d.ts +18 -0
  436. package/build/picker/icons/types.d.ts.map +1 -0
  437. package/build/picker/icons/types.js +2 -0
  438. package/build/picker/icons/types.js.map +1 -0
  439. package/build/picker/icons.d.ts +4 -0
  440. package/build/picker/icons.d.ts.map +1 -0
  441. package/build/picker/icons.js +54 -0
  442. package/build/picker/icons.js.map +1 -0
  443. package/build/picker/index.d.ts +11 -0
  444. package/build/picker/index.d.ts.map +1 -0
  445. package/build/picker/index.js +10 -0
  446. package/build/picker/index.js.map +1 -0
  447. package/build/picker/utils/color/types.d.ts +35 -0
  448. package/build/picker/utils/color/types.d.ts.map +1 -0
  449. package/build/picker/utils/color/types.js +2 -0
  450. package/build/picker/utils/color/types.js.map +1 -0
  451. package/build/picker/utils/color.d.ts +4 -0
  452. package/build/picker/utils/color.d.ts.map +1 -0
  453. package/build/picker/utils/color.js +96 -0
  454. package/build/picker/utils/color.js.map +1 -0
  455. package/build/picker/vocabulary/consts.d.ts +26 -0
  456. package/build/picker/vocabulary/consts.d.ts.map +1 -0
  457. package/build/picker/vocabulary/consts.js +336 -0
  458. package/build/picker/vocabulary/consts.js.map +1 -0
  459. package/build/picker/vocabulary/types.d.ts +67 -0
  460. package/build/picker/vocabulary/types.d.ts.map +1 -0
  461. package/build/picker/vocabulary/types.js +2 -0
  462. package/build/picker/vocabulary/types.js.map +1 -0
  463. package/build/picker/vocabulary.d.ts +11 -0
  464. package/build/picker/vocabulary.d.ts.map +1 -0
  465. package/build/picker/vocabulary.js +83 -0
  466. package/build/picker/vocabulary.js.map +1 -0
  467. package/build/scheme/consts.d.ts +8 -0
  468. package/build/scheme/consts.d.ts.map +1 -0
  469. package/build/scheme/consts.js +8 -0
  470. package/build/scheme/consts.js.map +1 -0
  471. package/build/scheme/index.d.ts +4 -0
  472. package/build/scheme/index.d.ts.map +1 -0
  473. package/build/scheme/index.js +3 -0
  474. package/build/scheme/index.js.map +1 -0
  475. package/build/scheme/scheme.d.ts +16 -0
  476. package/build/scheme/scheme.d.ts.map +1 -0
  477. package/build/scheme/scheme.js +58 -0
  478. package/build/scheme/scheme.js.map +1 -0
  479. package/build/scheme/types.d.ts +30 -0
  480. package/build/scheme/types.d.ts.map +1 -0
  481. package/build/scheme/types.js +2 -0
  482. package/build/scheme/types.js.map +1 -0
  483. package/build/types.d.ts +18 -2
  484. package/build/types.d.ts.map +1 -1
  485. package/package.json +107 -52
  486. package/src/@/components/ui/alert-dialog.tsx +156 -0
  487. package/src/@/components/ui/alert.tsx +1 -1
  488. package/src/@/components/ui/button.tsx +1 -1
  489. package/src/@/components/ui/card.tsx +1 -1
  490. package/src/@/components/ui/input.tsx +1 -1
  491. package/src/@/components/ui/label.tsx +1 -1
  492. package/src/@/components/ui/navigation-menu.tsx +1 -1
  493. package/src/@/components/ui/popover.tsx +47 -0
  494. package/src/@/components/ui/progress.tsx +1 -1
  495. package/src/@/components/ui/separator.tsx +1 -1
  496. package/src/@/components/ui/sheet.tsx +142 -0
  497. package/src/auth/context.ts +0 -2
  498. package/src/auth/entrypoints.ts +5 -0
  499. package/src/auth/exports.ts +4 -4
  500. package/src/auth/plugins/basic-ed25519.tsx +4 -4
  501. package/src/auth/plugins/re-captcha.tsx +3 -3
  502. package/src/auth/plugins/tunnel-consumer.tsx +1 -1
  503. package/src/components/block.tsx +2 -2
  504. package/src/components/consts.local.ts +29 -0
  505. package/src/components/footer/component.tsx +58 -16
  506. package/src/components/footer/credit.tsx +61 -0
  507. package/src/components/footer/index.ts +1 -0
  508. package/src/components/footer/types.ts +22 -1
  509. package/src/components/form/button/component.tsx +7 -4
  510. package/src/components/form/component.tsx +2 -2
  511. package/src/components/form/text/component.tsx +2 -2
  512. package/src/components/helper.ts +1 -13
  513. package/src/components/index.ts +4 -0
  514. package/src/components/link.tsx +3 -3
  515. package/src/components/login/append.ts +34 -0
  516. package/src/components/login/consts.local.ts +10 -0
  517. package/src/components/login/consts.ts +2 -0
  518. package/src/components/login/credit.tsx +33 -0
  519. package/src/components/login/i18n/be.json +10 -0
  520. package/src/components/login/i18n/de.json +10 -0
  521. package/src/components/login/i18n/en.json +10 -0
  522. package/src/components/login/i18n/es.json +10 -0
  523. package/src/components/login/i18n/fr.json +10 -0
  524. package/src/components/login/i18n/pl.json +10 -0
  525. package/src/components/login/i18n/ru.json +10 -0
  526. package/src/components/login/i18n/uk.json +10 -0
  527. package/src/components/login/i18n.ts +29 -0
  528. package/src/components/login/icons.tsx +39 -0
  529. package/src/components/login/index.ts +11 -0
  530. package/src/components/login/notify.ts +48 -0
  531. package/src/components/login/provider.tsx +57 -0
  532. package/src/components/login/screen.tsx +178 -0
  533. package/src/components/login/terms.tsx +75 -0
  534. package/src/components/login/types.ts +30 -0
  535. package/src/components/nav/consts.local.ts +64 -0
  536. package/src/components/nav/index.ts +1 -0
  537. package/src/components/nav/layout.tsx +184 -26
  538. package/src/components/nav/mobile.tsx +165 -0
  539. package/src/components/nav/side.tsx +43 -27
  540. package/src/components/nav/top.tsx +44 -22
  541. package/src/components/nav/types.ts +65 -2
  542. package/src/components/nav/viewport.ts +16 -0
  543. package/src/components/panel-app/component.tsx +9 -1
  544. package/src/components/picker/color-picker.tsx +15 -0
  545. package/src/components/picker/consts.local.ts +267 -0
  546. package/src/components/picker/dot.tsx +21 -0
  547. package/src/components/picker/grid.tsx +138 -0
  548. package/src/components/picker/i18n/be.json +60 -0
  549. package/src/components/picker/i18n/de.json +60 -0
  550. package/src/components/picker/i18n/en.json +60 -0
  551. package/src/components/picker/i18n/es.json +60 -0
  552. package/src/components/picker/i18n/fr.json +60 -0
  553. package/src/components/picker/i18n/pl.json +60 -0
  554. package/src/components/picker/i18n/ru.json +60 -0
  555. package/src/components/picker/i18n/uk.json +60 -0
  556. package/src/components/picker/i18n.ts +19 -0
  557. package/src/components/picker/icon-color-picker.tsx +25 -0
  558. package/src/components/picker/icon-picker.tsx +13 -0
  559. package/src/components/picker/index.ts +11 -0
  560. package/src/components/picker/panel.tsx +61 -0
  561. package/src/components/picker/root.tsx +81 -0
  562. package/src/components/picker/roving.ts +70 -0
  563. package/src/components/picker/surface.tsx +62 -0
  564. package/src/components/picker/swatches/custom.tsx +110 -0
  565. package/src/components/picker/swatches.tsx +67 -0
  566. package/src/components/picker/text.ts +46 -0
  567. package/src/components/picker/tile.tsx +35 -0
  568. package/src/components/picker/translate.ts +15 -0
  569. package/src/components/picker/trigger.tsx +54 -0
  570. package/src/components/picker/types.local.ts +154 -0
  571. package/src/components/picker/types.ts +125 -0
  572. package/src/components/scheme/consts.local.ts +13 -0
  573. package/src/components/scheme/hook.ts +62 -0
  574. package/src/components/scheme/index.ts +4 -0
  575. package/src/components/scheme/toggle.tsx +32 -0
  576. package/src/components/scheme/types.ts +23 -0
  577. package/src/components/socket/i18n/be.json +9 -0
  578. package/src/components/socket/i18n/de.json +9 -0
  579. package/src/components/socket/i18n/en.json +9 -0
  580. package/src/components/socket/i18n/es.json +9 -0
  581. package/src/components/socket/i18n/fr.json +9 -0
  582. package/src/components/socket/i18n/pl.json +9 -0
  583. package/src/components/socket/i18n/ru.json +9 -0
  584. package/src/components/socket/i18n/uk.json +9 -0
  585. package/src/components/socket/i18n.ts +19 -0
  586. package/src/components/socket/index.ts +2 -0
  587. package/src/components/socket/reload-dialog.tsx +61 -0
  588. package/src/components/status.tsx +1 -1
  589. package/src/components/text.tsx +2 -14
  590. package/src/components/toaster.tsx +65 -0
  591. package/src/components/uploader/consts.local.ts +7 -0
  592. package/src/components/uploader/image.tsx +2 -6
  593. package/src/consent/component.tsx +84 -0
  594. package/src/consent/consts.local.ts +10 -0
  595. package/src/consent/consts.ts +1 -0
  596. package/src/consent/geo.ts +26 -0
  597. package/src/consent/index.ts +24 -0
  598. package/src/consent/language.ts +12 -0
  599. package/src/consent/menu-widget.tsx +22 -0
  600. package/src/consent/presence.ts +45 -0
  601. package/src/consent/service.ts +75 -0
  602. package/src/consent/translate.ts +31 -0
  603. package/src/consent/types.local.ts +6 -0
  604. package/src/consent/types.ts +43 -0
  605. package/src/context.ts +12 -0
  606. package/src/editor/component.tsx +172 -0
  607. package/src/editor/consts.local.ts +62 -0
  608. package/src/editor/index.ts +2 -0
  609. package/src/editor/types.ts +24 -0
  610. package/src/entrypoints.ts +5 -0
  611. package/src/exports.ts +6 -5
  612. package/src/index.ts +1 -1
  613. package/src/main.tsx +2 -6
  614. package/src/permission/i18n/be.json +13 -0
  615. package/src/permission/i18n/de.json +13 -0
  616. package/src/permission/i18n/en.json +13 -0
  617. package/src/permission/i18n/es.json +13 -0
  618. package/src/permission/i18n/fr.json +13 -0
  619. package/src/permission/i18n/pl.json +13 -0
  620. package/src/permission/i18n/ru.json +13 -0
  621. package/src/permission/i18n/uk.json +13 -0
  622. package/src/permission/i18n.ts +13 -0
  623. package/src/permission/index.ts +27 -0
  624. package/src/permission/toast.tsx +20 -0
  625. package/src/permission/types.ts +5 -0
  626. package/src/picker/icons/consts.ts +309 -0
  627. package/src/picker/icons/types.ts +18 -0
  628. package/src/picker/icons.ts +70 -0
  629. package/src/picker/index.ts +11 -0
  630. package/src/picker/utils/color/types.ts +37 -0
  631. package/src/picker/utils/color.ts +119 -0
  632. package/src/picker/vocabulary/consts.ts +347 -0
  633. package/src/picker/vocabulary/types.ts +72 -0
  634. package/src/picker/vocabulary.ts +111 -0
  635. package/src/scheme/consts.ts +8 -0
  636. package/src/scheme/index.ts +3 -0
  637. package/src/scheme/scheme.ts +66 -0
  638. package/src/scheme/types.ts +30 -0
  639. package/src/types.ts +19 -2
  640. package/tests/consent-language.spec.ts +31 -0
  641. package/tests/consent.spec.ts +112 -0
  642. package/tests/context.ts +4 -0
  643. package/tests/editor.spec.ts +58 -0
  644. package/tests/harness/editor.tsx +32 -0
  645. package/tests/harness/index.html +1 -0
  646. package/tests/harness/lazy-screen.tsx +9 -0
  647. package/tests/harness/mount.tsx +370 -29
  648. package/tests/harness/picker.tsx +110 -0
  649. package/tests/lazy.spec.ts +104 -0
  650. package/tests/login-provider.spec.ts +114 -0
  651. package/tests/login.spec.ts +447 -0
  652. package/tests/nav.spec.ts +449 -3
  653. package/tests/package-boundary.spec.ts +19 -0
  654. package/tests/picker-shots.spec.ts +174 -0
  655. package/tests/picker-vocabulary.spec.ts +217 -0
  656. package/tests/picker.spec.ts +333 -0
  657. package/tests/scheme.spec.ts +149 -0
  658. package/tests/smoke.spec.ts +2 -2
  659. package/tests/socket-dialog.spec.ts +154 -0
  660. package/tests/toaster.spec.ts +59 -0
  661. package/zz-tw.d.mts +2 -0
  662. package/zz-tw.d.mts.map +1 -0
  663. package/build/.gitkeep +0 -0
  664. package/build/auth/modules.d.ts +0 -2
  665. package/build/auth/modules.d.ts.map +0 -1
  666. package/build/auth/modules.js +0 -4
  667. package/build/auth/modules.js.map +0 -1
  668. package/build/modules.d.ts +0 -2
  669. package/build/modules.d.ts.map +0 -1
  670. package/build/modules.js +0 -4
  671. package/build/modules.js.map +0 -1
  672. package/src/auth/modules.ts +0 -5
  673. package/src/modules.ts +0 -5
package/README.md CHANGED
@@ -1,54 +1,55 @@
1
1
  # @owlmeans/web-panel
2
2
 
3
- shadcn UI + Tailwind v4 implementation of the OwlMeans web panel layer.
4
- Wraps the headless `@owlmeans/client-panel` logic with shadcn primitives
5
- instead of Material UI.
3
+ shadcn UI + Tailwind v4 implementation of the OwlMeans web panel layer. It wraps the headless
4
+ `@owlmeans/client-panel` logic and `@owlmeans/web-client`'s context with shadcn primitives: the base
5
+ context factory, the navigation shell, forms, panels, the sign-in screen, toasts and the socket
6
+ reload prompt. New OwlMeans web apps build on it. An app that renders only its own components and
7
+ needs no panel can stay on [`@owlmeans/web-client`](../web-client). Material UI apps already on
8
+ [`@owlmeans/mui-panel`](../mui-panel) are legacy: the same surface rendered with MUI, maintained
9
+ but never started.
6
10
 
7
- ## When to use this package
8
-
9
- - New OwlMeans web apps where the consumer owns its shadcn primitives and
10
- Tailwind v4 theme.
11
- - Drop-in replacement for the previous Material-UI based `@owlmeans/web-panel`
12
- (which has been renamed to [`@owlmeans/mui-panel`](../mui-panel) for
13
- backwards-compatibility consumers).
14
-
15
- ## Install
11
+ ## Installation
16
12
 
17
13
  ```sh
18
- bun add @owlmeans/web-panel
14
+ bun add @owlmeans/web-panel@^0.1.19-rc.0
19
15
  ```
20
16
 
21
17
  Peer requirements (the consuming app provides these): `react`, `react-dom`,
22
18
  `react-hook-form`, `ajv`, `tailwindcss@^4`, `lucide-react`, `clsx`,
23
19
  `tailwind-merge`, `class-variance-authority`, plus the radix primitives
24
- listed in `peerDependencies`.
25
-
26
- ## Consumer setup — the `@` contract
27
-
28
- This package imports its shadcn primitives as `@/components/ui/<name>` and
29
- its utility as `@/lib/utils`. Build emits these specifiers verbatim
30
- (TypeScript `moduleResolution: Bundler`). The consumer's bundler must
31
- resolve `@/*` to its own shadcn primitive copy.
32
-
33
- ### 1. Add the package's primitives to your app
34
-
35
- Generate the matching primitives in your app once. You can either copy them
36
- from this package's `src/@/components/ui/` or use the shadcn CLI:
37
-
38
- ```sh
39
- npx shadcn add button card input label progress alert separator navigation-menu
40
- ```
41
-
42
- `navigation-menu` also needs `@radix-ui/react-navigation-menu` in your app's
43
- dependencies — the `TopNav` section menu is built on it.
44
-
45
- This package was authored against the shadcn `new-york` style with
46
- `baseColor: neutral`. See `components.json` for the exact config.
47
-
48
- ### 2. Add Tailwind v4 theme tokens
49
-
50
- The components rely on the following CSS variables (defined inside
51
- `@theme` in your app's globals.css):
20
+ listed in `peerDependencies` (`alert-dialog`, `dialog`, `label`, `navigation-menu`, `popover`,
21
+ `progress`, `separator`, `slot` — keep `dialog` and `popover` on the same Radix generation). Also declare `ajv-formats` next to `ajv`: the form model imports it, but no dependency
22
+ section of this manifest lists it.
23
+
24
+ ## Concepts
25
+
26
+ - **Panel context** — `makeContext(cfg)` is `@owlmeans/web-client`'s context plus
27
+ `apiConfigMiddleware`, the flow service (`context.flow()`), the socket-status service and the
28
+ default shadcn sign-in screen. The app factory calls it and appends its own mixins.
29
+ - **Package boundary** — the shadcn primitives and `cn` are private files under the package's own
30
+ `build/@/` tree, imported relatively. A consumer needs no `@` alias and vendors nothing. It
31
+ supplies the peers, its Tailwind theme tokens and an `@source` line for this package.
32
+ - **Two-layer navigation** — the top menu lists sections and the side menu lists the active
33
+ section's screens. A section holding a single screen renders no side menu. The model
34
+ (`usePanelNav`, `PanelNav*`) is headless in `@owlmeans/client-panel`. With `mobileMenu`, a
35
+ narrow viewport gets both levels behind one menu button and a sheet instead.
36
+ - **Style slots** — `className` (page root), `headerClassName` (sticky bar), `contentClassName`
37
+ and `containerClassName` (width and padding of all three rows) are merged over their defaults
38
+ with tailwind-merge, never substituted.
39
+ - **Global overlays** — `PanelApp` renders its `children` and `SocketReloadDialog` beside the
40
+ router, so a dialog survives navigation.
41
+ - **`translate` props** — the navigation, login and picker components take a
42
+ `(key, defaultValue) => string` resolver as a prop instead of reading an i18n provider implicitly.
43
+ - **Icon + colour picker** — `@owlmeans/web-panel/picker` is the standard way a person chooses an
44
+ icon and/or a colour (24 palette keys, ~250 curated lucide icons, an opt-in custom colour) and the
45
+ way a chosen mark is rendered (`IconTile`, `ColorDot`). A popover on wide screens, a bottom sheet
46
+ on phones; its data and colour helper are React-free under `./picker/vocabulary`.
47
+
48
+ ## Usage
49
+
50
+ ### Consumer setup — theme tokens and `@source`
51
+
52
+ The components paint with these CSS variables, defined inside `@theme` in the app's globals.css:
52
53
 
53
54
  - `--color-background`, `--color-foreground`
54
55
  - `--color-card`, `--color-card-foreground`
@@ -63,48 +64,138 @@ The components rely on the following CSS variables (defined inside
63
64
  - `--animate-progress-indeterminate` + the `@keyframes progress-indeterminate`
64
65
  rule for the `Progress` component's indeterminate mode
65
66
 
66
- A working set is shipped at `src/@/globals.css` (for dev/test only).
67
+ A working set is shipped at `src/@/globals.css` (for dev/test only). Toasts and the picker's
68
+ surfaces additionally read `--popover`, `--popover-foreground` and `--border`.
67
69
 
68
- ### 3. Bundler alias
70
+ Tailwind's scanner reads your CSS root plus its `@source` directives, and it excludes
71
+ `node_modules`. Classes that exist only inside this package's components — the whole navigation
72
+ shell and footer — therefore never reach your stylesheet unless you point Tailwind at the
73
+ installed package's `src`:
74
+
75
+ ```css
76
+ @import "tailwindcss";
77
+
78
+ @source "../../../node_modules/@owlmeans/web-panel/src";
79
+ ```
80
+
81
+ Adjust the relative depth to your own layout. An app using `./consent` adds a second `@source` for
82
+ `@owlmeans/web-consent`'s `src`.
83
+
84
+ ### 1. Config and context factory
85
+
86
+ ```ts
87
+ // src/config.ts
88
+ import { config } from '@owlmeans/web-panel'
89
+ import { commonConfig, MY_APP_WEB } from 'my-app-common'
90
+ import type { Config } from './types.js'
91
+
92
+ const cfg: Config = config(MY_APP_WEB, commonConfig as Config)
93
+ // Block the screen with a "try again / reload the page" prompt once a socket has given up reconnecting.
94
+ cfg.socket = { ...cfg.socket, reloadDialog: true }
95
+
96
+ export default cfg
97
+ ```
69
98
 
70
99
  ```ts
71
- // vite.config.ts
72
- resolve: { alias: { '@': fileURLToPath(new URL('./src/@', import.meta.url)) } }
100
+ // src/context.ts
101
+ import { appendLoginScreen, makeContext as makePanelContext, useContext as usePanelContext } from '@owlmeans/web-panel'
102
+ import type { AppConfig, AppContext } from '@owlmeans/web-panel'
103
+ import { appendConsentWidgetService } from '@owlmeans/web-panel/consent'
104
+ import { appendStateResource } from '@owlmeans/state'
105
+ import { BrandMark } from './components/brand.js'
106
+ import { PROJECT_STATE } from './consts.js'
107
+
108
+ export interface Config extends AppConfig {}
109
+ export interface Context<C extends Config = Config> extends AppContext<C> {}
110
+
111
+ export const useContext = (): Context => usePanelContext<Config, Context>()
112
+
113
+ export const makeContext = <C extends Config, T extends Context<C>>(cfg: C): T => {
114
+ const context = makePanelContext<C, T>(cfg)
115
+ // Idempotent: makeContext registered the default screen; this puts the app's mark on it.
116
+ appendLoginScreen<C, T>(context, { Logo: BrandMark })
117
+ appendConsentWidgetService<C, T>(context)
118
+ appendStateResource<C, T>(context, PROJECT_STATE)
119
+
120
+ return context
121
+ }
73
122
  ```
74
123
 
75
- ### 4. Tailwind `@source` for this package
124
+ ### 2. Entrypoints and mounting with overlays
76
125
 
77
- Tailwind's scanner reads your CSS root plus its `@source` directives, and it
78
- excludes `node_modules`. Classes that exist only inside this package's
79
- components — the whole navigation shell and footer — therefore never reach your
80
- stylesheet unless you point Tailwind at the built package:
126
+ ```ts
127
+ // src/entrypoints.ts
128
+ import { bindAll, bindScreen, entrypoints as panelEntrypoints, handler } from '@owlmeans/web-panel'
129
+ import { entrypoints as authEntrypoints } from '@owlmeans/client-auth'
130
+ import { apiProtocols, webProtocols } from 'my-app-common'
131
+ import { MainLayout } from './layout/main.js'
132
+ import { HomeScreen } from './screens/home.js'
133
+ import { CookiePolicyScreen } from './screens/legal/cookies.js'
134
+
135
+ export const appEntrypoints = [
136
+ ...authEntrypoints,
137
+ ...panelEntrypoints,
138
+ ...bindAll(apiProtocols),
139
+ bindScreen(webProtocols.base, handler(MainLayout)),
140
+ bindScreen(webProtocols.home, handler(HomeScreen)),
141
+ bindScreen(webProtocols.legal.cookies, handler(CookiePolicyScreen)),
142
+ ]
143
+ ```
81
144
 
82
- ```css
83
- @import "tailwindcss";
145
+ `render(context, { rootClassName })` mounts `PanelApp` with the browser language detector
146
+ installed. An app with global overlays of its own mounts `PanelApp` itself:
84
147
 
85
- @source "../../../node_modules/@owlmeans/web-panel/build";
148
+ ```tsx
149
+ // src/render.tsx
150
+ import type { FC } from 'react'
151
+ import { render as mount } from '@owlmeans/web-client'
152
+ import type { AppContext } from '@owlmeans/web-client'
153
+ import { useI18nInstance } from '@owlmeans/client-i18n/utils'
154
+ import { PanelApp } from '@owlmeans/web-panel'
155
+ import { PanelCookieConsent } from '@owlmeans/web-panel/consent'
156
+ import detector from 'i18next-browser-languagedetector'
157
+
158
+ const App: FC<{ context: AppContext }> = ({ context }) => {
159
+ useI18nInstance(context.cfg).use(detector)
160
+
161
+ // Children of PanelApp sit beside the router, so the dialog survives navigation.
162
+ return <PanelApp context={context} rootClassName="dark">
163
+ <PanelCookieConsent policyHref="/legal/cookies" />
164
+ </PanelApp>
165
+ }
166
+
167
+ export const render = (context: AppContext) => mount(<App context={context} />)
86
168
  ```
87
169
 
88
- Adjust the relative depth to your own layout; the target is this package's
89
- installed `build` directory.
170
+ ```ts
171
+ // src/index.tsx
172
+ const context = makeContext(config)
173
+ context.registerEntrypoints(appEntrypoints)
174
+ context.serviceRoute(MY_APP_WEB, true)
175
+ render(context)
176
+ ```
90
177
 
91
- ## Navigation shell
178
+ ### 3. Navigation shell, toasts and a guarded layout
92
179
 
93
- `NavLayout` is the standard application shell — header, section menu, the active
94
- section's screen menu, content, footer. A layout entrypoint elevates a component
95
- that renders it and nothing else; the matched screen arrives as `children`.
180
+ `NavLayout` is the standard shell: header, section menu, the active section's screen menu, content
181
+ and footer. A layout entrypoint binds a component that renders it; the matched screen arrives as
182
+ `children`. Keep the navigation as data in its own module, so screens, entrypoints and the shell
183
+ read the same aliases.
96
184
 
97
185
  ```tsx
98
- import { NavLayout, HOME } from '@owlmeans/web-panel'
186
+ import type { FC, PropsWithChildren } from 'react'
187
+ import { HOME, NavLayout, Toaster, useI18nApp } from '@owlmeans/web-panel'
99
188
  import type { PanelNavConfig, PanelNavLink } from '@owlmeans/web-panel'
189
+ import { useSelfAuth } from '@owlmeans/client-auth'
190
+ import { webProtocols } from 'my-app-common'
100
191
 
101
- const navConfig: PanelNavConfig = {
192
+ export const navConfig: PanelNavConfig = {
102
193
  sections: [
103
194
  { name: 'home', label: 'Home', items: [{ alias: HOME, label: 'Overview' }] },
104
195
  {
105
- name: 'demo', label: 'Demo', items: [
106
- { alias: web.session, label: 'Session' },
107
- { alias: web.about, label: 'About' },
196
+ name: 'projects', items: [
197
+ { alias: webProtocols.projects.alias },
198
+ { alias: webProtocols.archive.alias },
108
199
  ]
109
200
  },
110
201
  ],
@@ -112,98 +203,374 @@ const navConfig: PanelNavConfig = {
112
203
 
113
204
  const footerLinks: PanelNavLink[] = [
114
205
  { alias: HOME, label: 'My App' },
115
- { href: 'https://owlmeans.com', label: 'OwlMeans', open: true },
206
+ { href: 'https://example.com/docs', label: 'Docs', open: true },
116
207
  ]
117
208
 
118
- export const MainLayout: FC<PropsWithChildren> = ({ children }) => (
119
- <NavLayout nav={navConfig} title="My App" footer={footerLinks}>
120
- {children}
121
- </NavLayout>
122
- )
209
+ export const MainLayout: FC<PropsWithChildren> = ({ children }) => {
210
+ useSelfAuth(true)
211
+ const t = useI18nApp('menu')
212
+
213
+ return <>
214
+ <NavLayout nav={navConfig} title="My App" footer={footerLinks}
215
+ translate={(key, defaultValue) => t(key, { defaultValue })}
216
+ headerClassName="bg-secondary text-secondary-foreground"
217
+ containerClassName="max-w-[1280px]">
218
+ {children}
219
+ </NavLayout>
220
+ {/* Exactly once, in the layout. Messages come from `toast.success(...)` in `sonner`. */}
221
+ <Toaster />
222
+ </>
223
+ }
123
224
  ```
124
225
 
125
- Navigation is **two-layer**: the top menu lists sections, the side menu lists the
126
- active section's screens. A section holding a single screen renders **no side
127
- menu at all**. `NavLayout` mounts `SideNav` twice — a `hidden md:block` column
128
- beside the content and a `md:hidden` strip under the header — so the same items
129
- serve wide and narrow viewports.
226
+ Labels resolve as literal `label`, then `translate(key, humanized alias)`, then the humanized
227
+ alias. Default keys are `nav.<section>` and `modules.<alias>`.
130
228
 
131
229
  | Component | Props |
132
230
  |---|---|
133
- | `NavLayout` | `nav`, `translate?`, `title?`, `home?` (brand target; defaults to the first section's first item), `actions?`, `footer?` (`PanelNavLink[]` renders the standard footer, a node replaces it), `contentClassName?`, `className?`, `style?` |
231
+ | `NavLayout` | `nav`, `translate?`, `title?`, `home?` (brand target; defaults to the first section's first item), `actions?`, `mobileMenu?` (below `md`, a menu button and a sheet replace the section menu and the screen strip; `actions` stay), `skipLinkLabel?` (the first-on-page skip link to `<main id="main">`; default `shell.skip` → "Skip to content"; `false` renders no link and no `#main`), `themeToggle?` (`true` or `{ labels? }`: the light/dark switcher in the footer's bottom row beside the credit; names via `shell.toLight` / `shell.toDark`), `footer?` (`PanelNavLink[]` renders the centred link row; a node renders as a full-width block above the credit), `headerClassName?`, `contentClassName?`, `containerClassName?`, `className?`, `style?` |
134
232
  | `TopNav` | `config`, `translate?`, `ariaLabel?`, `className?`, `style?` |
135
233
  | `SideNav` | the same, plus `variant?: 'side' \| 'bar'` |
136
- | `Footer` | `links?`, `translate?`, `children?`, `className?`, `style?` |
137
-
138
- The navigation model itself (`usePanelNav`, `PanelNavConfig`, `PanelNavItem`,
139
- `PanelNavSection`, `PanelNavLink`, `NavTranslate`) is headless and lives in
140
- [`@owlmeans/client-panel`](../client-panel); these components are its shadcn
141
- rendering.
142
-
143
- Two things to know when wiring it:
144
-
145
- - **Labels do not use i18n unless you pass a resolver.** `translate` is a prop
146
- (`NavTranslate`), defaulting to one that returns the fallback, because an app
147
- rendered without an i18n provider throws if a menu reads the panel i18n
148
- context. Labels resolve as literal `label` → `translate(key, humanized)` →
149
- humanized alias, with default keys `nav.<section>` and `modules.<alias>`.
150
- - **A parent route needs a `default: true` child.** A frontend entrypoint with
151
- children but no default child renders blank at its own path — give a grouping
152
- screen an index child at `'/'`.
153
-
154
- ## Breaking changes vs `@owlmeans/mui-panel`
155
-
156
- This package keeps the same public name and re-export surface as the
157
- previous MUI implementation, but the following props/types have changed:
158
-
159
- - **`styles?: SxProps` is removed.** Use the new `className?: string` and
160
- `style?: React.CSSProperties` props instead. Affected: `BlockProps`,
161
- `TextProps`, `LinkProps`, `WebFormProps`, `LayoutProps`.
162
- - **`variant` on `Text` / `Link` is now `TextVariant`**, a string-literal
163
- union: `'h1' | 'h2' | 'h3' | 'h4' | 'p' | 'lead' | 'large' | 'small' |
164
- 'muted' | 'blockquote'`. The previous MUI `TypographyOwnProps['variant']`
165
- union no longer applies.
166
- - **`PanelAppProps.theme?: Theme` is replaced with
167
- `PanelAppProps.rootClassName?: string`.** Apply your theme via Tailwind
168
- classes / CSS variables instead of MUI's `Theme` object.
169
- - **`render(context, theme?, opts?)` signature → `render(context, opts?)`**
170
- where `opts` includes the new `rootClassName?: string`.
171
- - **`scalingToStyles()`** now returns a class-name string (composable with
172
- `cn()`), not an `SxProps` object. The `theme?: Theme` parameter is
173
- removed (Tailwind handles breakpoints declaratively).
174
- - **`useBreakPoint` / `useMapBreakpoint`** now use Tailwind's static
175
- default breakpoints (`xs/sm/md/lg/xl`) instead of MUI's `Theme.breakpoints`.
176
- Customise via Tailwind config in the consuming app.
177
- - **Component prop API for buttons** stays compatible (`'small' | 'medium'
178
- | 'large'`, `variant` strings `contained`/`outlined`/`text`/shadcn names).
179
- Internally they map to shadcn variants.
180
-
181
- Consumers that need the previous MUI behaviour should swap to
182
- [`@owlmeans/mui-panel`](../mui-panel) — same exports, MUI-rendered.
183
-
184
- ## Public exports
234
+ | `MobileNav` | the same as `TopNav`; the trigger's name and the sheet title resolve `shell.menu` ("Menu"), its close button `shell.close` ("Close"); `className`/`style` land on the trigger |
235
+ | `Footer` | `links?`, `content?` (full-width block, `data-footer-content`), `translate?`, `containerClassName?`, `children?` (join the link row), `themeToggle?`, `className?`, `style?` — always renders the platform/owner credit line last, via `ShellCredit` |
236
+ | `ThemeToggle` | `labels?: { toLight?, toDark? }` (English defaults), `className?`, `style?` — a 44px `<button data-theme-toggle>` flipping the resolved scheme |
237
+ | `ShellCredit`, `useShellCredit` | `className?` — "Powered by OwlMeans" plus the owner's copyright, resolved the same way the sign-in screen's credit is |
185
238
 
186
- ```ts
187
- import {
188
- PanelApp, Layout, NavLayout, TopNav, SideNav, Footer,
189
- Form, TextInput, SubmitButton, Button, ButtonSelector,
190
- Block, Text, Link, Status, ImageUploader,
191
- scalingToStyles, useBreakPoint, useMapBreakpoint,
192
- render,
193
- } from '@owlmeans/web-panel'
194
-
195
- import { setupExternalAuthentication } from '@owlmeans/web-panel/auth'
196
- import { modules } from '@owlmeans/web-panel/auth/modules'
239
+ ### 4. Forms, panels and status
240
+
241
+ `Form` owns the whole model: `useForm` with an `ajvResolver` over `validation`, published through
242
+ `FormProvider` and `FormContext`, so every control below reads one form.
243
+
244
+ ```tsx
245
+ import type { FC } from 'react'
246
+ import { useCallback } from 'react'
247
+ import { toast } from 'sonner'
248
+ import { Block, BlockScaling, Button, Form, PanelContext, SubmitButton, TextInput, useFormRef } from '@owlmeans/web-panel'
249
+ import { apiProtocols, ProjectCreateSchema } from 'my-app-common'
250
+ import type { ProjectCreate } from 'my-app-common'
251
+ import { useContext } from '../context.js'
252
+
253
+ export const CreateProject: FC<{ onCancel: () => void }> = ({ onCancel }) => {
254
+ const context = useContext()
255
+ const formRef = useFormRef<ProjectCreate>()
256
+
257
+ const onSubmit = useCallback(async (data: ProjectCreate) => {
258
+ try {
259
+ await context.entrypoint(apiProtocols.project.create).call({ body: data })
260
+ toast.success('Project created')
261
+ } catch (error) {
262
+ // Plants a root error; Form shows it through Status when decorated.
263
+ formRef.current?.error(error)
264
+ }
265
+ }, [])
266
+
267
+ return <PanelContext resource="my-app" prefix="project-create">
268
+ {/* `decorate` renders a Card, the root error and a SubmitButton in the footer. */}
269
+ <Form decorate name="project" formRef={formRef} validation={ProjectCreateSchema}
270
+ horizontal={BlockScaling.Half} onSubmit={onSubmit}>
271
+ <TextInput name="name" label placeholder hint />
272
+ <TextInput name="repository" type="url" label="Repository URL" disableAutocomplete />
273
+ </Form>
274
+ <Button label="cancel" variant="text" onClick={onCancel} />
275
+ </PanelContext>
276
+ }
277
+ ```
278
+
279
+ - `TextInput` takes `label`, `placeholder` and `hint` as `string | boolean`: `true` resolves
280
+ `<name>.label` / `.placeholder` / `.hint` from the form namespace, and a string is used verbatim.
281
+ - Without `decorate`, `Form` is a bare flex column with no card, no root-error surface and no submit
282
+ button, so render your own `SubmitButton` inside it.
283
+ - `formRef` (from `useFormRef()`) is filled with `{ form, update, loader, error }`.
284
+ - `Button` maps `contained` / `outlined` / `text` onto shadcn `default` / `outline` / `ghost`, and
285
+ forwards any other shadcn variant name unchanged.
286
+
287
+ Panels and feedback:
288
+
289
+ ```tsx
290
+ import { Block, ButtonSelector, ImageUploader, Link, Status, Text } from '@owlmeans/web-panel'
291
+
292
+ <Block horizontal={BlockScaling.Wide} Actions={() => <Link module={webProtocols.projects.alias} />}>
293
+ <Text variant="h3" name="title" />
294
+ <ButtonSelector name="period" options={['day', 'week', 'month']} current={period} onSelect={setPeriod} />
295
+ <ImageUploader maxFiles={1} previewUrl={logoUrl} onDrop={files => upload(files[0])} />
296
+ {result != null && <Status ok={result.ok} error={result.error} message={result.message} />}
297
+ </Block>
298
+ ```
299
+
300
+ ### 5. Socket connection state
301
+
302
+ With `cfg.socket.reloadDialog` set, `PanelApp` mounts `SocketReloadDialog`. It is a blocking
303
+ `AlertDialog` that opens when every `ws()` / `useWs()` connection has exhausted its retry budget
304
+ (`useSocketStatus() === 'lost'`), and its only action reloads the page. An app that prefers an
305
+ inline state leaves the flag off and reads the same status:
306
+
307
+ ```tsx
308
+ import type { FC } from 'react'
309
+ import { useSocketStatus } from '@owlmeans/client-socket'
310
+ import { useI18nApp } from '@owlmeans/web-panel'
311
+
312
+ export const ConnectionBadge: FC = () => {
313
+ const status = useSocketStatus() // 'online' | 'reconnecting' | 'lost'
314
+ const t = useI18nApp('connection')
315
+
316
+ return status === 'online' ? null : <span role="status" data-state={status}>{t(status)}</span>
317
+ }
318
+ ```
319
+
320
+ The dialog's strings are the lib-tier `socket` namespace (`reload.title`, `reload.description`,
321
+ `reload.action`), shipped in seven languages.
322
+
323
+ ### 6. Icon and colour picker
324
+
325
+ A person choosing a type's mark — an icon and a colour — gets one control; the stored values are a
326
+ palette key (or `#rrggbb` with `customColors`) and a kebab-case lucide name:
327
+
328
+ ```tsx
329
+ import { useState, type FC } from 'react'
330
+ import { IconColorPicker, IconTile, usePickerTranslate } from '@owlmeans/web-panel/picker'
331
+ import type { IconColorChange } from '@owlmeans/web-panel/picker'
332
+
333
+ export const TypeMarkField: FC<{ initial: IconColorChange, onSave: (mark: IconColorChange) => void }> =
334
+ ({ initial, onSave }) => {
335
+ const translate = usePickerTranslate() // only under PanelApp / render()
336
+ const [mark, setMark] = useState(initial)
337
+
338
+ return <div className="flex items-center gap-3">
339
+ <IconColorPicker label="Mark" value={mark} onChange={setMark} translate={translate} />
340
+ <button type="button" onClick={() => onSave(mark)}>Save</button>
341
+ <IconTile icon={mark.icon} color={mark.color} size="sm" /> {/* how a list shows it */}
342
+ </div>
343
+ }
197
344
  ```
198
345
 
346
+ `ColorPicker` and `IconPicker` edit one half; `ColorSwatches` and `IconGrid` are the same grids
347
+ inline, for a dialog the app already owns. Stored marks render with `IconTile` / `ColorDot`, or with
348
+ `pickerColorHelper.styleOf(color)` in custom markup. From 768px up the picker opens as a popover
349
+ (modal, so it works inside an app's own Dialog or Sheet), below that as a bottom sheet with 44px
350
+ targets and a Done button. Without `translate` every string is English; the packaged bundle covers
351
+ eight languages.
352
+
353
+ ## API
354
+
355
+ ### Context and mounting
356
+
357
+ | Symbol | Kind | Purpose |
358
+ |---|---|---|
359
+ | `makeContext<C, T>(cfg)` | function | Panel context factory — see *Concepts* |
360
+ | `useContext<C, T>()` | hook | The current panel context |
361
+ | `render(context, opts?)` | function | Mount `PanelApp` with the language detector; `opts` is `WebRenderOptions` |
362
+ | `WebRenderOptions` | type | `@owlmeans/web-client`'s `RenderOptions` plus `rootClassName` |
363
+ | `PanelApp`, `PanelAppProps` | component, type | Themed root `div`, i18n provider, app and router, overlays |
364
+ | `entrypoints` | const | `@owlmeans/web-client`'s entrypoints plus `@owlmeans/api-config-client`'s |
365
+ | `AppConfig`, `AppContext` | type | Adds `socket?: SocketClientSettings & { reloadDialog? }`, `flow()` and the socket-status append |
366
+
367
+ ### Components
368
+
369
+ | Symbol | Kind | Purpose |
370
+ |---|---|---|
371
+ | `NavLayout`, `TopNav`, `SideNav`, `MobileNav`, `Footer`, `ShellCredit` | component | Navigation shell and its pieces, including the narrow-viewport menu sheet and the footer's platform/owner credit |
372
+ | `NavLayoutProps`, `TopNavProps`, `SideNavProps`, `MobileNavProps`, `FooterProps`, `ShellCreditProps` | type | Their props |
373
+ | `useShellCredit` | hook | Resolves the credit `ShellCredit` renders, without rendering it |
374
+ | `Layout`, `LayoutProps` | component, type | Plain content wrapper |
375
+ | `Form`, `WebFormProps` | component, type | Web form; `FormProps` plus `className` / `style` |
376
+ | `TextInput`, `TextInputProps` | component, type | `react-hook-form` controlled input |
377
+ | `Button`, `SubmitButton`, `ButtonProps`, `SubmitProps` | component, type | Action buttons; `SubmitButton` is bound to `handleSubmit` |
378
+ | `ButtonSelector`, `SelectorProps` | component, type | One button per option, the current one `contained` |
379
+ | `Block`, `Text`, `Link`, `Status` | component | Card panel with `Actions`, translated text, entrypoint link, translated `Alert` |
380
+ | `BlockProps`, `TextProps`, `LinkProps`, `StatusProps`, `StyledProps`, `TextVariant` | type | Their props |
381
+ | `ImageUploader`, `ImageUploaderProps` | component, type | Drop target with a `previewUrl` |
382
+ | `Toaster` | component | `sonner` surface themed from app tokens; follows `.dark` on the document element |
383
+ | `ThemeToggle`, `ThemeToggleProps`, `ThemeToggleLabels` | component, type | The light/dark switcher |
384
+ | `useColorScheme()`, `ColorSchemeModel` | hook, type | `{ scheme, choice, setChoice }` — the resolved scheme, the stored choice (`null` = follow the OS), and the setter |
385
+ | `SocketReloadDialog` | component | Blocking reload prompt for `'lost'` sockets |
386
+ | `LoginScreen`, `LocalizedLoginScreen` | component | Identity-provider choice screen; the localized one binds `translate` to the app's resources |
387
+ | `appendLoginScreen(ctx, setup?)`, `LoginScreenSetup` | function, type | Register the screen on the login service, with `Logo` and other `LoginScreenProps` |
388
+ | `LoginTerms`, `LoginPrivacyNotice`, `LoginCredit`, `LoginMethodIcon` | component | The screen's terms confirmation, its privacy-only disclosure (rendered alone once `termsDeferred` moves the checkbox to a post-login step — see `@owlmeans/client-auth/login`), the credit line and method icons |
389
+ | `LoginTermsProps`, `LoginPrivacyNoticeProps`, `LoginCreditProps` | type | Their props |
390
+ | `scalingToStyles(horizontal?, vertical?)` | function | `BlockScaling` to Tailwind width/height classes |
391
+ | `useBreakPoint()` | hook | The current Tailwind breakpoint name |
392
+ | `useMapBreakpoint(map, def?, breakpoint?)` | hook | The map entry for the current breakpoint; throws `SyntaxError` when nothing matches and no `def` is given |
393
+
394
+ ### Re-exports
395
+
396
+ | Symbol | From |
397
+ |---|---|
398
+ | everything (`usePanelNav`, `PanelNavConfig` / `PanelNavItem` / `PanelNavSection` / `PanelNavLink` / `NavTranslate`, `PanelContext`, `BlockScaling`, `useFormRef`, `FormContext`, ...) | `@owlmeans/client-panel` |
399
+ | `handler`, `useNavigate`, `useValue`, `useEntrypoint` | `@owlmeans/client` |
400
+ | `bind`, `bindAll`, `bindScreen`, `clientRequestHelper`, `provideRequest` (deprecated, use `clientRequestHelper.provideRequest`), `stab`; type `Module` | `@owlmeans/client-entrypoint` |
401
+ | `route`, `frontend` / `croute` | `@owlmeans/route` / `@owlmeans/client-route` |
402
+ | `config` / `service` / `addWebService` | `@owlmeans/client-context` / `@owlmeans/config` / `@owlmeans/client-config` |
403
+ | `AppType`, `HOME`, `ROOT`, `BASE`, `GUEST` | `@owlmeans/context` |
404
+ | `DISPATCHER`, `CAUTHEN_FLOW_ENTER`; type `AuthToken` | `@owlmeans/auth` |
405
+ | `DAUTH_GUARD` (`DEFAULT_ALIAS`), `bindExternalAuthentication` | `@owlmeans/client-auth` |
406
+ | `Dispatcher`, `appendWebAuthService` | `@owlmeans/web-client` |
407
+ | `composePrefix`, `useI18n`, `useI18nApp`, `useI18nLib`, `useLanguage` | `@owlmeans/client-i18n` |
408
+ | `i18nHelper`, `addI18nApp` / `addI18nLib` (deprecated, use `i18nHelper.*`), `SUPPORTED_LNGS` | `@owlmeans/i18n` |
409
+ | `flow`, `configureFlows` / `FLOW_PARAM`, `SERVICE_PARAM`, `useFlow` | `@owlmeans/flow` / `@owlmeans/web-flow` |
410
+
411
+ ### `@owlmeans/web-panel/auth`
412
+
413
+ The context and screens for an authentication manager app — the identity-provider side, not a
414
+ relying party.
415
+
416
+ | Symbol | Kind | Purpose |
417
+ |---|---|---|
418
+ | `makeContext`, `useContext` | function, hook | Client context with IndexedDB, router, `apiConfigMiddleware` and flow service, without the relying-party auth service |
419
+ | `AppConfig`, `AppContext` | type | With `flow()` |
420
+ | `render` | function | Same as the root `render` |
421
+ | `plugins` | registry | `@owlmeans/client-auth/manager`'s registry with the shadcn renderers assigned |
422
+ | `Ed22519BasicAuthUIPlugin`, `ReCaptchaAuthUIPlugin`, `TunnelConsumerUIPlugin` | component | Those renderers |
423
+ | `AuthenticationHOC`, `AuthenticationType`, `DISPATCHER`, `CAUTHEN`, `EntrypointOutcome`, `RouteMethod`, `FLOW_ALIAS`, type `Navigator` / `AbstractRequest` / `Request` / `ServiceRoute` / `FlowService`, and the `@owlmeans/client-panel/auth` exports | re-export | Authentication-manager vocabulary |
424
+
425
+ `@owlmeans/web-panel/auth/entrypoints` exports `entrypoints`: `@owlmeans/client-auth/manager`'s
426
+ bindings plus `@owlmeans/api-config-client`'s.
427
+
428
+ ### `@owlmeans/web-panel/scheme`
429
+
430
+ React-free — it imports nothing, so a Node build script can load it.
431
+
432
+ | Symbol | Kind | Purpose |
433
+ |---|---|---|
434
+ | `COLOR_SCHEME_KEY` | const | `'owlmeans:color-scheme'`, the `localStorage` key |
435
+ | `COLOR_SCHEME_EVENT` | const | The `window` event every change dispatches |
436
+ | `ColorSchemeChoice` | type | `'light' \| 'dark'` |
437
+ | `colorSchemeHelper.readColorScheme()` | helper member | The stored choice or `null` (storage errors swallowed) |
438
+ | `colorSchemeHelper.applyColorScheme(choice \| null)` | helper member | Sets the `light`/`dark` class on `<html>`, stores or clears the key, dispatches the event |
439
+ | `colorSchemeHelper.colorSchemeBootstrapScript()` | helper member | The inline head script that applies a stored choice before first paint |
440
+
441
+ The class contract: `.dark` = chosen dark, `.light` = chosen light, neither = follow the OS. A
442
+ consumer's CSS puts dark tokens under `.dark` AND under
443
+ `@media (prefers-color-scheme: dark) { :root:not(.light) { … } }`, and inlines
444
+ `colorSchemeHelper.colorSchemeBootstrapScript()` in the document head.
445
+
446
+ ### `@owlmeans/web-panel/consent`
447
+
448
+ | Symbol | Kind | Purpose |
449
+ |---|---|---|
450
+ | `PanelCookieConsent`, `PanelCookiePolicy` | component | `@owlmeans/web-consent` components bound to the app's language, translations and `cfg.cookieConsent` (`{ mode?, geo? }` — a prop wins) |
451
+ | `appendConsentGeoPlugin(ctx, plugin)` | function | Register the app's own country locator (`ConsentGeoPlugin`) while the context is configured; turns the geo gate on |
452
+ | `PanelCookieConsentConfig`, `ConsentGeoPluginAppend` | type | `cfg.cookieConsent`; the `context.consentGeo()` accessor |
453
+ | `PanelConsentMenuWidget` | component | The cookie-preferences control for a host menu or footer ("Cookie settings" — pass `label` and `className`) |
454
+ | `appendConsentWidgetService(ctx, alias?)`, `createConsentWidgetService` | function | Ref-counted presence service over a state resource |
455
+ | `useConsentMenuPresence()`, `useConsentWidgetPresent()` | hook | Declare that a menu shows the row; read whether one does (hides the floating button) |
456
+ | `CONSENT_WIDGET_SERVICE`, `CONSENT_WIDGET_STATE` | const | Service alias and state alias |
457
+ | `ConsentWidgetPresenceRecord`, `ConsentWidgetService`, `ConsentWidgetServiceAppend` | type | Service types |
458
+ | `useConsent`, `useConsentCategory`, `consentStore`, `openConsent`, `isConsented`, `readConsent`, `writeConsent`, `clearConsent`, `consentBootstrapScript`, `DEFAULT_CONSENT_CATEGORIES`, `CONSENT_KEY`, `CONSENT_ESSENTIAL`, `CONSENT_ANALYTICS`, `CONSENT_MARKETING` and the consent types | re-export | `@owlmeans/web-consent` |
459
+
460
+ ### `@owlmeans/web-panel/picker`
461
+
462
+ Not re-exported by the root. Re-exports everything of `./picker/vocabulary` too.
463
+
464
+ | Symbol | Kind | Purpose |
465
+ |---|---|---|
466
+ | `IconColorPicker`, `IconColorPickerProps` | component, type | Icon + colour: `value?: { icon?, color? }`, `onChange({ icon?, color? })`, `colors?`, `icons?`, `customColors?`, `trigger?: 'button' \| 'tile'` |
467
+ | `ColorPicker`, `ColorPickerProps` | component, type | A colour: `value?`, `onChange(color)`, `colors?`, `customColors?`, `trigger?: 'button' \| 'dot'` |
468
+ | `IconPicker`, `IconPickerProps` | component, type | An icon: `value?`, `onChange(icon)`, `color?` (tint), `icons?`, `trigger?: 'button' \| 'tile'` |
469
+ | `PickerBaseProps` | type | Shared: `label?`, `placeholder?`, `disabled?`, `surface?: 'auto' \| 'popover' \| 'sheet'`, `translate?`, `className?`, `id?` |
470
+ | `ColorSwatches`, `IconGrid` (+ `…Props`) | component, type | The grids inline, for an app's own dialog or sheet |
471
+ | `IconTile`, `IconTileProps` | component, type | A stored mark: `icon?`, `color?`, `colors?`, `size?: 'xs' \| 'sm' \| 'md' \| 'lg'`, `variant?: 'tile' \| 'plain'`, `label?` |
472
+ | `ColorDot`, `ColorDotProps` | component, type | A stored colour as a dot in its ink: `color?`, `colors?`, `size?`, `label?` |
473
+ | `usePickerTranslate()`, `PickerTranslate` | hook, type | `(key, fallback) => string` over the lib-tier `picker` bundle — only under `PanelApp` / `render()` |
474
+ | `IconColorValue`, `IconColorChange` | type | The composite's value and its change (`undefined`, never `null`, for an unset half) |
475
+ | `PICKER_ICONS` | const | Catalogue name → statically imported lucide component |
476
+ | `pickerIconHelper` (`iconOf`, `has`, `search`, `byCategory`), `createPickerIconHelper`, `PickerIconHelper` | helper, type | Icon lookup with the `circle` fallback and catalogue search |
477
+
478
+ ### `@owlmeans/web-panel/picker/vocabulary`
479
+
480
+ React-free and icon-free — safe on a server or in a seed.
481
+
482
+ | Symbol | Kind | Purpose |
483
+ |---|---|---|
484
+ | `PICKER_COLOR_KEYS`, `PickerColorKey` | const, type | The 24 keys in hue order: red … rose, maroon, brown, olive, navy, slate, stone, graphite |
485
+ | `PICKER_COLORS`, `PickerColor` | const, type | `{ key, swatch, ink, soft, inkDark?, softDark?, label? }` — every ink 4.5:1 on its ground and the page in both modes |
486
+ | `PICKER_FALLBACK_COLOR`, `PICKER_FALLBACK_ICON` | const | `'slate'`, `'circle'` |
487
+ | `PICKER_ICON_ENTRIES`, `PICKER_ICON_NAMES`, `PICKER_ICON_CATEGORIES` | const | The catalogue: `{ name, category, keywords }`, its names, its ten categories |
488
+ | `PickerIconEntry`, `PickerIconCategory`, `ResolvedPickerColor` | type | |
489
+ | `pickerColorHelper` (`isHex`, `normalizeHex`, `resolve`, `styleOf`, `hashKey`), `createPickerColorHelper`, `PickerColorHelper` | helper, type | Validate, normalize and resolve a stored colour (a hex gets contrast-safe inks); `styleOf` → the `--pick-*` custom properties the parts read |
490
+
491
+ ### Differences from `@owlmeans/mui-panel`
492
+
493
+ The public names match the MUI implementation; these props and types differ:
494
+
495
+ - **`styles?: SxProps` is removed.** Use `className?: string` and `style?: React.CSSProperties`
496
+ (`BlockProps`, `TextProps`, `LinkProps`, `WebFormProps`, `LayoutProps`).
497
+ - **`variant` on `Text` / `Link` is `TextVariant`**: `'h1' | 'h2' | 'h3' | 'h4' | 'p' | 'lead' |
498
+ 'large' | 'small' | 'muted' | 'blockquote'`.
499
+ - **`PanelAppProps.theme?: Theme` is replaced with `rootClassName?: string`.** Apply the theme
500
+ through Tailwind classes and CSS variables.
501
+ - **`render(context, theme?, opts?)` is now `render(context, opts?)`**, where `opts` includes
502
+ `rootClassName`.
503
+ - **`scalingToStyles()` returns a class-name string** composable with other classes, not an
504
+ `SxProps`; its `theme` parameter is gone.
505
+ - **`useBreakPoint` / `useMapBreakpoint` use Tailwind's default breakpoints**
506
+ (`xs/sm/md/lg/xl`) instead of MUI's `Theme.breakpoints`.
507
+ - **Button props stay compatible** (`'small' | 'medium' | 'large'`, `contained` / `outlined` /
508
+ `text` or shadcn variant names).
509
+
510
+ ## Common pitfalls
511
+
512
+ - **Add the `@source` line** for this package's `src` (and for `@owlmeans/web-consent` when using
513
+ `./consent`). Without it the navigation shell renders unstyled.
514
+ - **A parent frontend route needs a `default: true` child.** A grouping screen with children but no
515
+ default child renders blank at its own path.
516
+ - **Menu and login labels need a `translate` prop to be localized.** The components never read the
517
+ i18n context implicitly, so without the prop they show literal labels or humanized aliases.
518
+ - **Mount `Toaster` exactly once, in the layout.** Two surfaces render every toast twice. An app
519
+ raising its own toasts declares `sonner` at a range that resolves to the same copy.
520
+ - **Mount dialogs beside the router** (`PanelApp` children or the web-client overlay slot), never
521
+ inside a route.
522
+ - **Give a dark top bar both halves through `headerClassName`** (`bg-secondary
523
+ text-secondary-foreground`). The header is its own surface; colouring only the root leaves its
524
+ menu unreadable.
525
+ - **Name only the utility you want to move in `containerClassName`.** It merges over
526
+ `mx-auto w-full max-w-6xl px-4`, so `max-w-[1280px]` changes only the width.
527
+ - **`Link` resolves its `href` asynchronously.** Never key a test or layout on the anchor having an
528
+ `href` at first paint.
529
+ - **`reloadDialog` is off by default.** The dialog renders nothing unless `cfg.socket.reloadDialog`
530
+ is `true`.
531
+ - **Run `useConsentMenuPresence()` from the menu's always-mounted component**, never from inside a
532
+ dropdown row, which mounts only while the menu is open. Without `appendConsentWidgetService` it
533
+ does nothing and `PanelCookieConsent` keeps its floating button.
534
+ - **Pass an application footer layout as a node `footer`.** It renders full-width above the credit;
535
+ an array renders the centred link row. Neither removes the credit.
536
+ - **A theme for `ThemeToggle` reads both classes.** Dark tokens under `.dark` only never follow
537
+ the OS; under the media query only, they ignore an explicit light choice. Inline the head
538
+ bootstrap or a stored dark choice flashes light for a frame.
539
+ - **The shell already renders the skip link and `<main id="main">`.** A screen never renders a
540
+ second `<main>` or `#main`; an app with its own skip link passes `skipLinkLabel={false}`.
541
+ - **`mobileMenu` is opt-in.** Without it a narrow viewport keeps the section menu and the screen
542
+ strip; with it both move into the sheet.
543
+ - **Never import `@/…` from package code or vendor its primitives in the app.** The `@` alias
544
+ belongs to the consumer.
545
+ - **Every override of a packaged string covers all seven languages** (`SUPPORTED_LNGS`).
546
+ - **A person-chosen colour or icon goes through `./picker`.** Never a `Select` or radio group of
547
+ colour names, a hand-made swatch row, or a class built from the stored value
548
+ (`` `text-${color}-600` ``); store the key and the icon name, never the label.
549
+ - **Keep `@radix-ui/react-popover` and `@radix-ui/react-dialog` on one Radix generation.** They
550
+ share the dismissable-layer and focus-scope stacks; mixed, a picker inside a Dialog loses focus
551
+ to the dialog and its clicks count as outside.
552
+ - **`usePickerTranslate()` needs `PanelApp` / `render()`.** Without an i18n instance it throws;
553
+ the picker parts themselves render English with no `translate`.
554
+
199
555
  ## Related packages
200
556
 
201
- - [`@owlmeans/mui-panel`](../mui-panel) — Material UI implementation of the
202
- same surface.
203
- - [`@owlmeans/web-oidc-rp`](../web-oidc-rp) — companion OIDC/OAuth UI for
204
- this package; uses the same Tailwind theme.
205
- - [`@owlmeans/client-panel`](../client-panel) — framework-agnostic headless
206
- form/layout logic this package wraps.
557
+ - [`@owlmeans/web-client`](../web-client) — the web context and mount helpers this package builds on
558
+ - [`@owlmeans/client-panel`](../client-panel) — headless form, layout, navigation and login models
559
+ - [`@owlmeans/client-auth`](../client-auth) — auth service, login hooks and plugin registry
560
+ - [`@owlmeans/client-socket`](../client-socket) — `useSocketStatus` behind the reload prompt
561
+ - [`@owlmeans/web-consent`](../web-consent) — cookie consent components behind `./consent`
562
+ - [`@owlmeans/web-oidc-rp`](../web-oidc-rp) — OIDC relying party UI on the same Tailwind theme
563
+ - [`@owlmeans/web-router`](../web-router) — default OwlMeans routing plugin
564
+ - [`@owlmeans/mui-panel`](../mui-panel) — legacy Material UI implementation of the same surface
565
+
566
+ ## Notes for coding agents
567
+
568
+ - Read the embedded `web-panel` skill first: its *Choosing a component* table maps every job to the
569
+ export, the import path and a correct one-liner, and lists the mistakes that recur in generated
570
+ code (private primitives, a missing `@source`, two `Toaster`s, `Form decorate` with an own submit).
571
+ - An icon or a colour a person chooses is edited with `@owlmeans/web-panel/picker`
572
+ (`IconColorPicker`, `ColorPicker`, `IconPicker`) and shown with `IconTile` / `ColorDot`; pass
573
+ `translate={usePickerTranslate()}` in an app rendered by `PanelApp`.
207
574
 
208
575
  <!-- owlmeans:agent-guidance:start -->
209
576
  ## Agent guidance
@@ -213,7 +580,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
213
580
  your project's skill store (`.agents/skills/`):
214
581
 
215
582
  ```sh
216
- npx @owlmeans/agent-skills
583
+ npx @owlmeans/agent-skills@^0.1.19-rc.0
217
584
  ```
218
585
 
219
586
  The embedded files are version-matched to this package release. Do not edit them