@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
@@ -1,15 +1,30 @@
1
1
  import '../../src/@/globals.css'
2
2
 
3
3
  import type { FC, PropsWithChildren } from 'react'
4
+ import { useState } from 'react'
4
5
  import { createRoot } from 'react-dom/client'
5
6
  import { config } from '@owlmeans/client-context'
6
7
  import { AppType, service } from '@owlmeans/config'
7
8
  import { BASE, HOME } from '@owlmeans/context'
8
- import { entrypoint } from '@owlmeans/client-entrypoint'
9
+ import { bindScreen } from '@owlmeans/client-entrypoint'
10
+ import { openProtocol } from '@owlmeans/entrypoint'
9
11
  import { frontend, route } from '@owlmeans/route'
10
12
  import { handler, useNavigate } from '@owlmeans/client'
13
+ import { toast } from 'sonner'
11
14
  import type { PanelNavConfig, PanelNavLink } from '../../src/index.js'
12
- import { makeContext, modules as baseModules, NavLayout, PanelApp } from '../../src/index.js'
15
+ import {
16
+ makeContext, useContext, entrypoints as baseEntrypoints, NavLayout, PanelApp, Toaster,
17
+ lazyHandler, lazyComponent,
18
+ } from '../../src/index.js'
19
+ import { LoginScreen } from '../../src/components/login/index.js'
20
+ import {
21
+ PanelCookieConsent, PanelConsentMenuWidget, appendConsentWidgetService, useConsentMenuPresence,
22
+ appendConsentGeoPlugin,
23
+ } from '../../src/consent/index.js'
24
+ import { LoginOutcome, ensureLoginService } from '@owlmeans/client-auth/login'
25
+ import type { LoginMethod } from '@owlmeans/client-auth/login'
26
+ import { EditorHarness } from './editor.js'
27
+ import { PickerScreen, TranslatedPickerScreen } from './picker.js'
13
28
 
14
29
  // A real app: a context, a layout entrypoint rendering NavLayout, and screens under it.
15
30
  // The nav model resolves the active screen from the router, so nothing here may be faked.
@@ -22,42 +37,219 @@ const alias = {
22
37
  reports: `${SERVICE}:web:reports`,
23
38
  reportsIndex: `${SERVICE}:web:reports-index`,
24
39
  reportDetail: `${SERVICE}:web:report-detail`,
40
+ reportSibling: `${SERVICE}:web:report-sibling`,
25
41
  prefs: `${SERVICE}:web:prefs`,
42
+ login: `${SERVICE}:web:login`,
43
+ socket: `${SERVICE}:web:socket`,
44
+ lazy: `${SERVICE}:web:lazy`,
45
+ lazyEntry: `${SERVICE}:web:lazy-entry`,
46
+ picker: `${SERVICE}:web:picker`,
26
47
  }
27
48
 
49
+ /** A harness id for the ONE tracked connection this screen simulates — a real `ws()`/`useWs()`
50
+ * connection would generate its own, but the status service only cares that it is stable across
51
+ * the two buttons below. */
52
+ const HARNESS_SOCKET_ID = 'harness-socket'
53
+
28
54
  const navConfig: PanelNavConfig = {
29
55
  sections: [
30
56
  // Two screens — the side menu shows.
31
57
  {
32
58
  name: 'work', label: 'Work', items: [
33
- { alias: alias.dash, label: 'Dashboard' },
59
+ { alias: alias.dash, label: 'Dashboard', testId: 'dashboard-nav' },
34
60
  { alias: alias.reports, label: 'Reports' },
35
61
  ]
36
62
  },
37
63
  // One screen — the side menu must not render at all.
38
- { name: 'settings', label: 'Settings', items: [{ alias: alias.prefs, label: 'Preferences' }] },
64
+ { name: 'settings', label: 'Settings', testId: 'settings-nav', items: [{ alias: alias.prefs, label: 'Preferences' }] },
39
65
  // No literal labels: exercises the humanized-alias fallback with no i18n present.
40
66
  { name: 'extra', items: [{ alias: HOME }] },
41
67
  ],
42
68
  }
43
69
 
44
70
  const footerLinks: PanelNavLink[] = [
45
- { alias: alias.dash, label: 'Dashboard' },
71
+ { alias: alias.dash, label: 'Dashboard', testId: 'dashboard-nav' },
46
72
  { href: 'https://owlmeans.com', label: 'OwlMeans', open: true },
47
73
  ]
48
74
 
49
75
  const screen = (id: string, text: string): FC => () => <div id={id}>{text}</div>
50
76
 
51
- const Layout: FC<PropsWithChildren> = ({ children }) => <NavLayout
52
- nav={navConfig}
53
- title="Harness"
54
- actions={<button id="action-slot">action</button>}
55
- footer={footerLinks}
56
- >{children}</NavLayout>
77
+ /**
78
+ * What the sign-in screen offers in the harness.
79
+ *
80
+ * Real methods, with real `start` handlers that record they were called — the one thing the
81
+ * screen must never do is start one on its own, and a method that only pretended to start could
82
+ * not prove it.
83
+ */
84
+ const started: string[] = []
85
+ ;(globalThis as unknown as { __loginStarted: string[] }).__loginStarted = started
86
+
87
+ const method = (id: string, over?: Partial<LoginMethod>): LoginMethod => ({
88
+ id,
89
+ order: 10,
90
+ start: async () => { started.push(id); return LoginOutcome.Handled },
91
+ ...over,
92
+ })
93
+
94
+ /** The sign-in screen, with the terms confirmation the configuration requires. */
95
+ const LoginHarness: FC = () => {
96
+ const [locale, setLocale] = useState<string | undefined>(localizedTerms ? 'pl' : undefined)
97
+
98
+ return <>
99
+ {localizedTerms && <button id="login-language-fr" onClick={() => setLocale('fr')}>Français</button>}
100
+ <LoginScreen
101
+ Logo={() => <span id="login-logo">logo</span>}
102
+ translate={(_key, defaultValue) => defaultValue}
103
+ locale={locale}
104
+ />
105
+ </>
106
+ }
107
+
108
+ // `?header=broken` simulates the layout-restyle bug this harness pins: a `headerClassName`
109
+ // carrying an invalid Tailwind v4 arbitrary-value background (v3 syntax, silently dropped) and a
110
+ // bare `bg-transparent`, either of which used to leave the sticky header with no background paint
111
+ // of its own at all. One harness process serves both branches, exactly like `reloadDialog` above.
112
+ const brokenHeader = new URLSearchParams(window.location.search).get('header') === 'broken'
113
+ // `?footer=none` omits the `footer` prop entirely — the shape every area layout had before the
114
+ // shell grew a footer-links convention. `NavLayout` must still render the credit line then.
115
+ const noFooterProp = new URLSearchParams(window.location.search).get('footer') === 'none'
116
+ // `?footer=node` hands `NavLayout` a NODE footer — an application's own footer layout (a brand
117
+ // block and a Legal column), the shape a generated app's footer takes — instead of links.
118
+ const nodeFooter = new URLSearchParams(window.location.search).get('footer') === 'node'
119
+ // `?mobileMenu=1` opts into the narrow-viewport menu sheet. Absent, the prop is not passed at
120
+ // all — the shape every existing layout has — and the shell must render exactly what it always did.
121
+ const mobileMenu = new URLSearchParams(window.location.search).get('mobileMenu') === '1'
122
+ // `?consent=bare` mounts `PanelCookieConsent` on a context that never appended the presence
123
+ // service — an application using the dialog on its own. `?consent=menu` appends the service, so
124
+ // the footer's "Cookie settings" control takes over the floating button's job.
125
+ const consentMode = new URLSearchParams(window.location.search).get('consent')
126
+ // `?consentCfg=window|bar` sets `cfg.cookieConsent.mode`; `?modeProp=bar|window` passes `mode` as a
127
+ // prop on top of it (the prop must win). `?consentGeo=<CC>|fail` appends a context-level locator
128
+ // with `appendConsentGeoPlugin` — the gate turns on with no `geo` configured anywhere.
129
+ const consentCfg = new URLSearchParams(window.location.search).get('consentCfg')
130
+ const modeProp = new URLSearchParams(window.location.search).get('modeProp')
131
+ const consentGeo = new URLSearchParams(window.location.search).get('consentGeo')
132
+ // `?skip=off` passes `skipLinkLabel={false}` — an application that renders its own skip link.
133
+ const skipOff = new URLSearchParams(window.location.search).get('skip') === 'off'
134
+ // `?themeToggle=1` asks for the footer's light/dark switcher. Absent, the prop is not passed.
135
+ const themeToggle = new URLSearchParams(window.location.search).get('themeToggle') === '1'
136
+ // `?terms=extended` adds billing/product/custom documents and a revision date to the terms
137
+ // confirmation — the shape that pins the "still exactly one checkbox" and "documents render
138
+ // outside the notice" rules even when there is more than terms+privacy to show.
139
+ const extendedTerms = new URLSearchParams(window.location.search).get('terms') === 'extended'
140
+ // `?terms=localized` selects known translated destinations using the live screen locale.
141
+ const localizedTerms = new URLSearchParams(window.location.search).get('terms') === 'localized'
142
+ // `?defer=bound` registers a step that CONFIRMS the terms, bound to a real screen — the sign-in
143
+ // screen must then show no checkbox, only the privacy notice, and block nothing.
144
+ // `?defer=unbound` registers the same step but never binds its entrypoint — the checkbox must
145
+ // stay (fail-closed): a step nobody can reach must never silently remove the confirmation.
146
+ const defer = new URLSearchParams(window.location.search).get('defer')
147
+ // `?domains=1` passes `linker` through to `PanelCookieConsent` — proving the prop reaches
148
+ // `@owlmeans/web-consent`'s `CookieConsent` with nothing lost in between (the props already just
149
+ // spread through; this is what pins that they keep doing so).
150
+ const withDomains = new URLSearchParams(window.location.search).get('domains') === '1'
151
+ // `?provider=top|inline` configures who signs the person in — the disclosure a platform-hosted
152
+ // app shows. A product name is set only then, so every other screen keeps the brand it always had.
153
+ const providerPlacement = new URLSearchParams(window.location.search).get('provider')
154
+
155
+ /**
156
+ * The footer's "Cookie settings" control — the menu widget, rendered from an always-mounted
157
+ * component that also declares the presence, exactly as the `./consent` rules ask.
158
+ */
159
+ const CookieSettings: FC = () => {
160
+ useConsentMenuPresence()
161
+
162
+ return <PanelConsentMenuWidget label="Cookie settings" className="w-auto" />
163
+ }
164
+
165
+ const FooterBlock: FC = () => <div id="footer-block" className="flex flex-wrap justify-between gap-8">
166
+ <div>
167
+ <strong>Harness</strong>
168
+ <p>One line about what the harness does.</p>
169
+ </div>
170
+ <nav aria-label="Legal">
171
+ <p>Legal</p>
172
+ <ul>
173
+ <li><a href="/privacy">Privacy</a></li>
174
+ <li><a href="/terms">Terms</a></li>
175
+ {consentMode != null && <li><CookieSettings /></li>}
176
+ </ul>
177
+ </nav>
178
+ </div>
179
+
180
+ // `/picker` is a page of its own — no shell around it, so its screenshots show the picker alone.
181
+ const pickerPage = window.location.pathname.startsWith('/picker')
182
+ // `/picker?bare=1` is mounted with no `PanelApp` and no i18n instance at all — the parts must render.
183
+ const pickerBare = pickerPage && new URLSearchParams(window.location.search).get('bare') === '1'
184
+
185
+ const Layout: FC<PropsWithChildren> = ({ children }) => pickerPage ? <>{children}</> : <>
186
+ <NavLayout
187
+ nav={navConfig}
188
+ navTestId="harness-nav"
189
+ title="Harness"
190
+ actions={<button id="action-slot">action</button>}
191
+ {...(noFooterProp ? {} : { footer: nodeFooter ? <FooterBlock /> : footerLinks })}
192
+ {...(mobileMenu ? { mobileMenu: true } : {})}
193
+ {...(skipOff ? { skipLinkLabel: false as const } : {})}
194
+ {...(themeToggle ? { themeToggle: true } : {})}
195
+ // A DARK APPLICATION SHELL, which is what a themed app does to the root: a contrasting
196
+ // surface pair, both halves correct. The header paints its own opaque background, so it is
197
+ // a different surface, and everything in it must stay legible against `--background`
198
+ // rather than against this. The harness carries it permanently so every navigation test
199
+ // runs against the hostile case instead of a default-coloured page.
200
+ className="bg-primary text-primary-foreground"
201
+ // A WIDTH-ONLY rhythm override, which is what a design pass writes when it wants a wider
202
+ // page. It names the width and nothing else, so the centring and the side padding must
203
+ // survive it — substituting this for the default is a page running flush to the window edge.
204
+ containerClassName="max-w-[1280px]"
205
+ {...(brokenHeader ? { headerClassName: 'bg-[--nope] bg-transparent' } : {})}
206
+ >{children}</NavLayout>
207
+ {/* Mounted ONCE, in the layout — exactly where an application mounts it. */}
208
+ <Toaster />
209
+ </>
210
+
211
+ /** The toast surface's exercise: a screen action that reports its outcome. */
212
+ const PrefsScreen: FC = () => <div id="prefs">
213
+ prefs-screen
214
+ <button id="fire-toast" onClick={() => toast.success('preferences saved')}>save</button>
215
+ {/* Outlives any assertion — a theme check must not race the 5s default dismissal. */}
216
+ <button id="fire-sticky" onClick={() => toast.error('sticky failure', { duration: 600_000 })}>fail</button>
217
+ </div>
57
218
 
58
219
  /** A grouping screen — it renders whichever child the router matched. */
59
220
  const ReportsGroup: FC<PropsWithChildren> = ({ children }) => <div id="reports-group">{children}</div>
60
221
 
222
+ /**
223
+ * Drives the SAME status service `SocketReloadDialog` reads, exactly the way a real dropped
224
+ * `ws()`/`useWs()` connection would — through `report()`/`release()`, never a prop the dialog
225
+ * itself exposes, since it has none: the whole point is that any socket, anywhere in the app,
226
+ * can put the dialog up.
227
+ */
228
+ const SocketStatusScreen: FC = () => {
229
+ const context = useContext()
230
+ // A revive the way a real carrier's goes: the connection is retrying again the moment it is
231
+ // asked to. How that retry ends is up to the test — `#report-online` or `#report-lost`.
232
+ const [revived, setRevived] = useState(0)
233
+ const reportLost = () => context.socketStatus().report(HARNESS_SOCKET_ID, 'lost', () => {
234
+ setRevived(n => n + 1)
235
+ context.socketStatus().report(HARNESS_SOCKET_ID, 'reconnecting')
236
+ })
237
+
238
+ return <div id="socket-status">
239
+ socket-status-screen
240
+ <span id="revived">{revived}</span>
241
+ <button id="report-lost" onClick={reportLost}>
242
+ lose connection
243
+ </button>
244
+ <button id="report-online" onClick={() => context.socketStatus().report(HARNESS_SOCKET_ID, 'online')}>
245
+ reconnected
246
+ </button>
247
+ <button id="release-lost" onClick={() => context.socketStatus().release(HARNESS_SOCKET_ID)}>
248
+ restore connection
249
+ </button>
250
+ </div>
251
+ }
252
+
61
253
  /**
62
254
  * The section's landing screen. Its button navigates to a screen the MENU DOES NOT LIST,
63
255
  * which is the only way to exercise the parent-chain walk: an in-app navigation puts the
@@ -69,6 +261,38 @@ const ReportsIndex: FC = () => {
69
261
  return <div id="reports">
70
262
  reports-screen
71
263
  <button id="to-detail" onClick={nav.press(alias.reportDetail)}>detail</button>
264
+ <button id="to-sibling" onClick={nav.press(alias.reportSibling)}>sibling detail</button>
265
+ </div>
266
+ }
267
+
268
+ /**
269
+ * Lazily-loaded screens, declared at MODULE SCOPE as the helpers require — the route renderer
270
+ * remounts a screen on every navigation, so a lazy object made during render would re-suspend
271
+ * each time. Both go through the package root, which is what an application imports.
272
+ *
273
+ * `flakyScreen` fails its first load on purpose: a rejected load must be retried, never cached.
274
+ * The globals let a spec drive `preload()` without a screen of its own.
275
+ */
276
+ let flakyLoads = 0
277
+ const lazyScreen = lazyHandler(
278
+ () => import('./lazy-screen.js'), 'LazyScreen', { fallback: <div id="lazy-fallback">loading</div> }
279
+ )
280
+ const flakyScreen = lazyComponent(async () => {
281
+ if (++flakyLoads === 1) throw new Error('first-load-fails')
282
+ return import('./lazy-screen.js')
283
+ }, 'LazyScreen')
284
+ ;(globalThis as unknown as { __lazyPreload: () => Promise<boolean> }).__lazyPreload =
285
+ async () => typeof await lazyScreen.preload() === 'function'
286
+ ;(globalThis as unknown as { __flakyPreload: () => Promise<string> }).__flakyPreload =
287
+ () => flakyScreen.preload().then(() => 'loaded', (e: Error) => e.message)
288
+
289
+ /** The lazy screen's way in: an in-app navigation, so the layout around it is already mounted. */
290
+ const LazyEntry: FC = () => {
291
+ const nav = useNavigate()
292
+
293
+ return <div id="lazy-entry">
294
+ lazy-entry-screen
295
+ <button id="to-lazy" onClick={nav.press(alias.lazy)}>lazy</button>
72
296
  </div>
73
297
  }
74
298
 
@@ -77,7 +301,55 @@ const ReportsIndex: FC = () => {
77
301
  // sides are declared here exactly as a real app declares them.
78
302
  const base = service({ type: AppType.Frontend, service: SERVICE, host: 'localhost', port: 5173 })
79
303
  service({ type: AppType.Backend, service: API, host: 'localhost', port: 5174, base: 'api' }, base)
80
- base.security = { unsecure: true }
304
+ base.security = {
305
+ unsecure: true,
306
+ auth: {
307
+ login: {
308
+ // Confirmation required, which is the case that matters: a method must be blocked until it
309
+ // is given, and blocking must SAY so rather than swallow the click.
310
+ terms: {
311
+ required: true, terms: 'https://example.test/terms', privacy: 'https://example.test/privacy',
312
+ ...(localizedTerms ? {
313
+ billing: { href: 'https://example.test/billing', revisedAt: '2026-10-04' },
314
+ cookies: 'https://example.test/cookies', showRevision: true,
315
+ localizedHrefs: {
316
+ terms: { pl: 'https://example.test/pl/terms', fr: 'https://example.test/fr/terms' },
317
+ billing: { pl: 'https://example.test/pl/billing', fr: 'https://example.test/fr/billing' },
318
+ privacy: { pl: 'https://example.test/pl/privacy', fr: 'https://example.test/fr/privacy' },
319
+ cookies: { pl: 'https://example.test/pl/cookies', fr: 'https://example.test/fr/cookies' },
320
+ },
321
+ } : {}),
322
+ ...(extendedTerms ? {
323
+ billing: { href: 'https://example.test/billing', revisedAt: '2026-01-01' },
324
+ product: { name: 'Harness', href: 'https://example.test/product' },
325
+ documents: [
326
+ { key: 'custom-a', href: 'https://example.test/custom-a', label: 'Custom A' },
327
+ { key: 'custom-b', href: 'https://example.test/custom-b', label: 'Custom B' },
328
+ ],
329
+ showRevision: true,
330
+ } : {}),
331
+ },
332
+ credit: { poweredBy: true, product: 'Harness', organization: 'Acme' },
333
+ ...(providerPlacement === 'top' || providerPlacement === 'inline' ? {
334
+ provider: {
335
+ name: 'Harness IAM', operator: 'Harness Hosting', info: 'https://example.test/about',
336
+ placement: providerPlacement,
337
+ },
338
+ } : {}),
339
+ },
340
+ },
341
+ }
342
+ if (providerPlacement != null) {
343
+ base.brand = { ...base.brand, name: 'Harness App' }
344
+ }
345
+ // Every other screen in this harness stays unaffected: nothing ever reports into the status
346
+ // service unless `#report-lost` is clicked, so the flag being on by default costs nothing. A
347
+ // test that needs the OFF case loads `?reloadDialog=0` — one harness process, both branches.
348
+ const reloadDialogEnabled = new URLSearchParams(window.location.search).get('reloadDialog') !== '0'
349
+ ;(base as { socket?: { reloadDialog?: boolean } }).socket = { reloadDialog: reloadDialogEnabled }
350
+ if (consentCfg === 'window' || consentCfg === 'bar') {
351
+ ;(base as { cookieConsent?: { mode: 'window' | 'bar' } }).cookieConsent = { mode: consentCfg }
352
+ }
81
353
 
82
354
  // `ready` stays false: the Router compiles the entrypoint tree into routes ONLY while the
83
355
  // context is un-initialized, so a pre-readied context renders a blank page.
@@ -85,29 +357,98 @@ const cfg = config(SERVICE, base as never)
85
357
  const context = makeContext(cfg as never)
86
358
  context.serviceRoute(SERVICE, true)
87
359
  context.serviceRoute(API, true)
360
+ if (consentMode === 'menu') {
361
+ appendConsentWidgetService(context as never)
362
+ }
363
+ if (consentGeo != null) {
364
+ appendConsentGeoPlugin(context as never, {
365
+ alias: 'harness-geo',
366
+ locate: async () => {
367
+ if (consentGeo === 'fail') {
368
+ throw new Error('the harness locator cannot tell')
369
+ }
370
+
371
+ return { country: consentGeo }
372
+ },
373
+ })
374
+ }
375
+
376
+ ensureLoginService(context as never).registerMethodSource({
377
+ alias: 'harness',
378
+ list: () => [
379
+ method('primary', { emphasis: 'primary', icon: 'google', label: 'Continue with Google' }),
380
+ // A method that finishes without moving the document — the shape of a relying party that
381
+ // could not build an authorization URL. The screen must SAY so; silence reads as a dead
382
+ // button, which is exactly the bug this pins.
383
+ method('secondary', {
384
+ order: 20, label: 'Sign in with a key',
385
+ start: async () => { started.push('secondary'); return LoginOutcome.Passed },
386
+ }),
387
+ method('operator', { order: 900, restricted: true, label: 'Secret key' }),
388
+ ],
389
+ })
390
+
391
+ if (defer != null) {
392
+ ensureLoginService(context as never).registerStep({
393
+ alias: 'harness-terms-step',
394
+ // "bound" points at a real screen of this harness (`/prefs`, already registered below) —
395
+ // `termsDeferred` only reads `ctx.hasEntrypoint`, so any bound alias proves the point.
396
+ // "unbound" points nowhere: `hasEntrypoint` answers false and the step stays unreachable.
397
+ entrypoint: defer === 'bound' ? alias.prefs : 'harness-terms-step-nowhere',
398
+ confirmsTerms: true,
399
+ required: true,
400
+ pending: async () => false,
401
+ })
402
+ }
403
+
404
+ const protocols = {
405
+ base: openProtocol(route(BASE, '/', frontend())),
406
+ home: openProtocol(route(HOME, '/', frontend({ default: true, parent: BASE }))),
407
+ dash: openProtocol(route(alias.dash, '/dash', frontend({ parent: BASE }))),
408
+ reports: openProtocol(route(alias.reports, '/reports', frontend({ parent: BASE }))),
409
+ reportsIndex: openProtocol(route(alias.reportsIndex, '/', frontend({ default: true, parent: alias.reports }))),
410
+ reportDetail: openProtocol(route(alias.reportDetail, '/detail', frontend({ parent: alias.reports }))),
411
+ reportSibling: openProtocol(route(alias.reportSibling, '/reports/sibling', frontend({ parent: BASE }))),
412
+ prefs: openProtocol(route(alias.prefs, '/prefs', frontend({ parent: BASE }))),
413
+ login: openProtocol(route(alias.login, '/login', frontend({ parent: BASE }))),
414
+ socket: openProtocol(route(alias.socket, '/socket', frontend({ parent: BASE }))),
415
+ lazy: openProtocol(route(alias.lazy, '/lazy', frontend({ parent: BASE }))),
416
+ lazyEntry: openProtocol(route(alias.lazyEntry, '/lazy-entry', frontend({ parent: BASE }))),
417
+ picker: openProtocol(route(alias.picker, '/picker', frontend({ parent: BASE }))),
418
+ }
88
419
 
89
- const modules = [
420
+ const entrypoints = [
90
421
  // The framework's own entrypoints come first — the api-config middleware the panel context
91
422
  // registers resolves one of them during init, and without them init throws before any route
92
423
  // is compiled.
93
- ...baseModules,
94
- entrypoint(route(BASE, '/', frontend()), handler(Layout)),
95
- entrypoint(route(HOME, '/', frontend({ default: true, parent: BASE })), handler(screen('home', 'home-screen'))),
96
- entrypoint(route(alias.dash, '/dash', frontend({ parent: BASE })), handler(screen('dash', 'dash-screen'))),
424
+ ...baseEntrypoints,
425
+ bindScreen(protocols.base, handler(Layout)),
426
+ bindScreen(protocols.home, handler(screen('home', 'home-screen'))),
427
+ bindScreen(protocols.dash, handler(screen('dash', 'dash-screen'))),
97
428
  // A screen that has children needs a `default: true` child of its own — without one its own
98
429
  // path matches nothing and the page renders blank.
99
- entrypoint(route(alias.reports, '/reports', frontend({ parent: BASE })), handler(ReportsGroup)),
100
- entrypoint(
101
- route(alias.reportsIndex, '/', frontend({ default: true, parent: alias.reports })),
102
- handler(ReportsIndex)
103
- ),
104
- entrypoint(
105
- route(alias.reportDetail, '/detail', frontend({ parent: alias.reports })),
106
- handler(screen('detail', 'detail-screen'))
107
- ),
108
- entrypoint(route(alias.prefs, '/prefs', frontend({ parent: BASE })), handler(screen('prefs', 'prefs-screen'))),
430
+ bindScreen(protocols.reports, handler(ReportsGroup)),
431
+ bindScreen(protocols.reportsIndex, handler(ReportsIndex)),
432
+ bindScreen(protocols.reportDetail, handler(screen('detail', 'detail-screen'))),
433
+ bindScreen(protocols.reportSibling, handler(screen('sibling-detail', 'sibling-detail-screen'))),
434
+ bindScreen(protocols.prefs, handler(PrefsScreen)),
435
+ bindScreen(protocols.login, handler(LoginHarness)),
436
+ bindScreen(protocols.socket, handler(SocketStatusScreen)),
437
+ bindScreen(protocols.lazy, lazyScreen),
438
+ bindScreen(protocols.lazyEntry, handler(LazyEntry)),
439
+ bindScreen(protocols.picker, handler(TranslatedPickerScreen)),
109
440
  ]
110
441
 
111
- context.registerEntrypoints(modules)
442
+ context.registerEntrypoints(entrypoints)
112
443
 
113
- createRoot(document.getElementById('root')!).render(<PanelApp context={context as never} />)
444
+ // The consent dialog is a sibling of the Router, as in an application — and only on the consent
445
+ // branches, since its first-visit overlay covers the page every other test clicks through.
446
+ createRoot(document.getElementById('root')!).render(new URLSearchParams(location.search).has('editor') ? <EditorHarness /> : pickerBare
447
+ ? <div className="min-h-screen bg-background text-foreground"><PickerScreen /></div>
448
+ : <PanelApp context={context as never}>
449
+ {consentMode != null && <PanelCookieConsent
450
+ policyHref="/cookies"
451
+ {...(withDomains ? { linker: { domains: ['harness-partner.test'] } } : {})}
452
+ {...(modeProp === 'window' || modeProp === 'bar' ? { mode: modeProp } : {})}
453
+ />}
454
+ </PanelApp>)
@@ -0,0 +1,110 @@
1
+ import { useState } from 'react'
2
+ import type { FC } from 'react'
3
+ import {
4
+ ColorDot, ColorPicker, ColorSwatches, IconColorPicker, IconGrid, IconPicker, IconTile, usePickerTranslate,
5
+ } from '../../src/picker/index.js'
6
+ import type { IconColorChange, PickerTranslate } from '../../src/picker/index.js'
7
+ import { Sheet, SheetContent, SheetTitle, SheetTrigger } from '../../src/@/components/ui/sheet.js'
8
+
9
+ /**
10
+ * The picker's scenarios, picked by query parameters:
11
+ *
12
+ * - `?custom=1` — `customColors` on every picker;
13
+ * - `?surface=popover|sheet` — forces the surface (default `auto`);
14
+ * - `?compact=1` — the `tile` / `dot` triggers;
15
+ * - `?empty=1` — nothing chosen yet;
16
+ * - `?inSheet=1` — the composite picker inside a Radix Sheet of the page's own;
17
+ * - `?inline=1` — the inline parts (`ColorSwatches`, `IconGrid`) on the page;
18
+ * - `?bare=1` — mounted with no `PanelApp` and no i18n instance at all (mount.tsx);
19
+ * - `?dark=1` — `.dark` on the document element.
20
+ */
21
+ const params = new URLSearchParams(window.location.search)
22
+ const custom = params.get('custom') === '1'
23
+ const compact = params.get('compact') === '1'
24
+ const empty = params.get('empty') === '1'
25
+ const inSheet = params.get('inSheet') === '1'
26
+ const inline = params.get('inline') === '1'
27
+ const surfaceParam = params.get('surface')
28
+ const surface = surfaceParam === 'popover' || surfaceParam === 'sheet' ? surfaceParam : 'auto'
29
+
30
+ if (params.get('dark') === '1') {
31
+ document.documentElement.classList.add('dark')
32
+ }
33
+
34
+ const SAMPLES: Array<[string, string]> = [
35
+ ['rocket', 'blue'], ['bug', 'red'], ['handshake', 'emerald'], ['flag', 'amber'], ['users', 'violet'],
36
+ ['package', 'brown'], ['map-pin', 'navy'], ['siren', 'maroon'], ['leaf', 'olive'], ['star', 'graphite'],
37
+ ]
38
+
39
+ export const PickerScreen: FC<{ translate?: PickerTranslate }> = ({ translate }) => {
40
+ const [mark, setMark] = useState<IconColorChange>(empty ? {} : { icon: 'rocket', color: 'indigo' })
41
+ const [color, setColor] = useState<string | undefined>(empty ? undefined : 'teal')
42
+ const [icon, setIcon] = useState<string | undefined>(empty ? undefined : 'briefcase')
43
+ const [submits, setSubmits] = useState(0)
44
+
45
+ const form = (id: string) => <form
46
+ id={id} className="flex flex-col gap-4"
47
+ onSubmit={event => { event.preventDefault(); setSubmits(count => count + 1) }}
48
+ >
49
+ <div className="flex flex-col gap-1.5">
50
+ <label htmlFor={`${id}-mark`} className="text-sm font-medium">Mark</label>
51
+ <IconColorPicker
52
+ id={`${id}-mark`} label="Mark" value={mark} onChange={setMark} customColors={custom} surface={surface}
53
+ trigger={compact ? 'tile' : 'button'} translate={translate}
54
+ />
55
+ </div>
56
+ <div className="grid gap-4 sm:grid-cols-2">
57
+ <div className="flex flex-col gap-1.5">
58
+ <label htmlFor={`${id}-color`} className="text-sm font-medium">Colour</label>
59
+ <ColorPicker
60
+ id={`${id}-color`} label="Colour" value={color} onChange={setColor} customColors={custom} surface={surface}
61
+ trigger={compact ? 'dot' : 'button'} translate={translate}
62
+ />
63
+ </div>
64
+ <div className="flex flex-col gap-1.5">
65
+ <label htmlFor={`${id}-icon`} className="text-sm font-medium">Icon</label>
66
+ <IconPicker
67
+ id={`${id}-icon`} label="Icon" value={icon} onChange={setIcon} color={color} surface={surface}
68
+ trigger={compact ? 'tile' : 'button'} translate={translate}
69
+ />
70
+ </div>
71
+ </div>
72
+ <button type="submit" className="self-start rounded-md border px-3 py-1.5 text-sm">Save</button>
73
+ </form>
74
+
75
+ return <main id="picker" className="mx-auto flex w-full max-w-2xl flex-col gap-6 px-4 py-8">
76
+ <h1 className="text-xl font-semibold">Icon and colour picker</h1>
77
+ {inSheet
78
+ ? <Sheet>
79
+ <SheetTrigger id="open-sheet" className="self-start rounded-md border px-3 py-1.5 text-sm">Open sheet</SheetTrigger>
80
+ <SheetContent side="right" aria-describedby={undefined} className="gap-0 p-6 text-foreground">
81
+ <SheetTitle className="mb-4">Edit type</SheetTitle>
82
+ {form('sheet-form')}
83
+ </SheetContent>
84
+ </Sheet>
85
+ : <section className="rounded-xl border p-4">{form('picker-form')}</section>}
86
+ {inline && <section id="inline" className="flex flex-col gap-4 rounded-xl border p-4">
87
+ <ColorSwatches value={mark.color} onChange={next => setMark({ ...mark, color: next })} customColors={custom} translate={translate} />
88
+ <div className="max-h-72 overflow-y-auto">
89
+ <IconGrid value={mark.icon} onChange={next => setMark({ ...mark, icon: next })} color={mark.color} translate={translate} />
90
+ </div>
91
+ </section>}
92
+ <section id="samples" className="flex flex-wrap items-center gap-3 rounded-xl border p-4">
93
+ {SAMPLES.map(([sampleIcon, sampleColor]) =>
94
+ <IconTile key={sampleColor} icon={sampleIcon} color={sampleColor} label={`${sampleIcon} ${sampleColor}`} />)}
95
+ <IconTile icon="rocket" color="blue" variant="plain" size="lg" label="plain rocket" />
96
+ <IconTile icon="not-an-icon" color="not-a-colour" label="fallback" />
97
+ <ColorDot color="blue" size="md" label="blue dot" />
98
+ <ColorDot color="#ff00aa" size="md" label="custom dot" />
99
+ </section>
100
+ <dl className="grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 text-sm">
101
+ <dt>mark</dt><dd><output id="mark-value">{JSON.stringify(mark)}</output></dd>
102
+ <dt>colour</dt><dd><output id="color-value">{color ?? ''}</output></dd>
103
+ <dt>icon</dt><dd><output id="icon-value">{icon ?? ''}</output></dd>
104
+ <dt>submits</dt><dd><output id="submits">{submits}</output></dd>
105
+ </dl>
106
+ </main>
107
+ }
108
+
109
+ /** The screen as an application rendered by `PanelApp` mounts it: strings from the packaged bundle. */
110
+ export const TranslatedPickerScreen: FC = () => <PickerScreen translate={usePickerTranslate()} />