@adukiorg/anza 0.2.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 (349) hide show
  1. package/CHANGELOG.md +137 -0
  2. package/README.md +215 -0
  3. package/bin/anza.js +63 -0
  4. package/bin/create.js +150 -0
  5. package/importmap.json +72 -0
  6. package/package.json +100 -0
  7. package/src/core/animations/index.js +55 -0
  8. package/src/core/animations/play.js +111 -0
  9. package/src/core/animations/registry.js +54 -0
  10. package/src/core/animations/scroll.js +50 -0
  11. package/src/core/animations/tokens.js +58 -0
  12. package/src/core/animations/usage.md +301 -0
  13. package/src/core/animations/waapi.js +86 -0
  14. package/src/core/api/cache.js +120 -0
  15. package/src/core/api/caches/glob.js +24 -0
  16. package/src/core/api/caches/index.js +118 -0
  17. package/src/core/api/events/index.js +75 -0
  18. package/src/core/api/fetch.js +99 -0
  19. package/src/core/api/index.js +158 -0
  20. package/src/core/api/pipeline.js +98 -0
  21. package/src/core/api/plan.md +209 -0
  22. package/src/core/api/prefixes/index.js +66 -0
  23. package/src/core/api/retry.js +69 -0
  24. package/src/core/api/stream.js +127 -0
  25. package/src/core/api/upload.js +180 -0
  26. package/src/core/api/usage.md +206 -0
  27. package/src/core/events/bus.js +38 -0
  28. package/src/core/events/delegate.js +79 -0
  29. package/src/core/events/index.js +26 -0
  30. package/src/core/events/listen.js +50 -0
  31. package/src/core/events/missing.md +103 -0
  32. package/src/core/events/once.js +49 -0
  33. package/src/core/events/plan.md +177 -0
  34. package/src/core/events/types/index.js +34 -0
  35. package/src/core/events/usage.md +107 -0
  36. package/src/core/offline/bridge.js +51 -0
  37. package/src/core/offline/clock.js +100 -0
  38. package/src/core/offline/connectivity.js +116 -0
  39. package/src/core/offline/index.js +41 -0
  40. package/src/core/offline/missing.md +89 -0
  41. package/src/core/offline/plan.md +143 -0
  42. package/src/core/offline/queue.js +168 -0
  43. package/src/core/offline/state.js +18 -0
  44. package/src/core/offline/sync.js +106 -0
  45. package/src/core/offline/usage.md +273 -0
  46. package/src/core/platform/guard.js +104 -0
  47. package/src/core/platform/index.js +42 -0
  48. package/src/core/platform/missing.md +119 -0
  49. package/src/core/platform/platform.d.ts +88 -0
  50. package/src/core/platform/polyfills/anchor.js +79 -0
  51. package/src/core/platform/polyfills/navigation.js +142 -0
  52. package/src/core/platform/polyfills/popover.js +142 -0
  53. package/src/core/platform/polyfills/scheduler.js +194 -0
  54. package/src/core/platform/polyfills/shadow.js +35 -0
  55. package/src/core/platform/polyfills/urlpattern.js +119 -0
  56. package/src/core/platform/supports.js +186 -0
  57. package/src/core/platform/usage.md +287 -0
  58. package/src/core/router/cache.js +95 -0
  59. package/src/core/router/container.js +146 -0
  60. package/src/core/router/handler.js +52 -0
  61. package/src/core/router/history.js +120 -0
  62. package/src/core/router/index.js +158 -0
  63. package/src/core/router/intercept.js +376 -0
  64. package/src/core/router/match.js +145 -0
  65. package/src/core/router/missing.md +716 -0
  66. package/src/core/router/outlet.js +139 -0
  67. package/src/core/router/plan.md +370 -0
  68. package/src/core/router/sync/index.js +16 -0
  69. package/src/core/router/sync/tab.js +115 -0
  70. package/src/core/router/sync/transport.js +139 -0
  71. package/src/core/router/transitions.js +59 -0
  72. package/src/core/router/usage.md +773 -0
  73. package/src/core/security/crypto.js +159 -0
  74. package/src/core/security/index.js +49 -0
  75. package/src/core/security/missing.md +97 -0
  76. package/src/core/security/permissions.js +64 -0
  77. package/src/core/security/sanitize.js +100 -0
  78. package/src/core/security/usage.md +283 -0
  79. package/src/core/state/derived.js +117 -0
  80. package/src/core/state/index.js +23 -0
  81. package/src/core/state/missing.md +165 -0
  82. package/src/core/state/persist.js +284 -0
  83. package/src/core/state/store.js +308 -0
  84. package/src/core/state/sync.js +46 -0
  85. package/src/core/state/usage.md +440 -0
  86. package/src/core/storage/cache.js +83 -0
  87. package/src/core/storage/idb.js +196 -0
  88. package/src/core/storage/index.js +373 -0
  89. package/src/core/storage/lru.js +107 -0
  90. package/src/core/storage/missing.md +165 -0
  91. package/src/core/storage/opfs.js +190 -0
  92. package/src/core/storage/plan.md +69 -0
  93. package/src/core/storage/quota.js +69 -0
  94. package/src/core/storage/usage.md +226 -0
  95. package/src/core/ui/base.js +50 -0
  96. package/src/core/ui/define/container.js +82 -0
  97. package/src/core/ui/define/define.js +12 -0
  98. package/src/core/ui/define/element.js +390 -0
  99. package/src/core/ui/define/index.js +9 -0
  100. package/src/core/ui/define/orchestrator.js +105 -0
  101. package/src/core/ui/define/proxy.js +644 -0
  102. package/src/core/ui/define/state.js +6 -0
  103. package/src/core/ui/define/utils.js +134 -0
  104. package/src/core/ui/implementation.md +170 -0
  105. package/src/core/ui/index.js +41 -0
  106. package/src/core/ui/observe.js +117 -0
  107. package/src/core/ui/plan.md +510 -0
  108. package/src/core/ui/schedule.js +60 -0
  109. package/src/core/ui/template.js +37 -0
  110. package/src/core/ui/transitions.js +37 -0
  111. package/src/core/ui/ui.types.md +890 -0
  112. package/src/core/ui/usage.md +1124 -0
  113. package/src/core/ui/watch.md +346 -0
  114. package/src/core/workers/broadcast.js +138 -0
  115. package/src/core/workers/dedicated.js +153 -0
  116. package/src/core/workers/index.js +169 -0
  117. package/src/core/workers/locks.js +160 -0
  118. package/src/core/workers/offscreen.js +166 -0
  119. package/src/core/workers/plan.md +381 -0
  120. package/src/core/workers/pool.js +267 -0
  121. package/src/core/workers/shared.js +137 -0
  122. package/src/core/workers/usage.md +622 -0
  123. package/src/elements/base.js +12 -0
  124. package/src/elements/data/card/index.html +9 -0
  125. package/src/elements/data/card/index.js +19 -0
  126. package/src/elements/data/card/index.tags.json +1 -0
  127. package/src/elements/data/card/style.css +46 -0
  128. package/src/elements/data/chart/index.html +1 -0
  129. package/src/elements/data/chart/index.js +143 -0
  130. package/src/elements/data/chart/index.tags.json +1 -0
  131. package/src/elements/data/chart/style.css +13 -0
  132. package/src/elements/data/list/index.html +3 -0
  133. package/src/elements/data/list/index.js +19 -0
  134. package/src/elements/data/list/index.tags.json +1 -0
  135. package/src/elements/data/list/style.css +39 -0
  136. package/src/elements/data/stat/index.html +9 -0
  137. package/src/elements/data/stat/index.js +19 -0
  138. package/src/elements/data/stat/index.tags.json +1 -0
  139. package/src/elements/data/stat/style.css +50 -0
  140. package/src/elements/data/table/index.html +1 -0
  141. package/src/elements/data/table/index.js +16 -0
  142. package/src/elements/data/table/index.tags.json +1 -0
  143. package/src/elements/data/table/style.css +50 -0
  144. package/src/elements/feedback/alert/index.html +11 -0
  145. package/src/elements/feedback/alert/index.js +28 -0
  146. package/src/elements/feedback/alert/index.tags.json +1 -0
  147. package/src/elements/feedback/alert/style.css +75 -0
  148. package/src/elements/feedback/empty/index.html +13 -0
  149. package/src/elements/feedback/empty/index.js +34 -0
  150. package/src/elements/feedback/empty/index.tags.json +1 -0
  151. package/src/elements/feedback/empty/style.css +45 -0
  152. package/src/elements/feedback/progress/index.html +7 -0
  153. package/src/elements/feedback/progress/index.js +46 -0
  154. package/src/elements/feedback/progress/index.tags.json +1 -0
  155. package/src/elements/feedback/progress/style.css +36 -0
  156. package/src/elements/feedback/skeleton/index.html +1 -0
  157. package/src/elements/feedback/skeleton/index.js +78 -0
  158. package/src/elements/feedback/skeleton/index.tags.json +1 -0
  159. package/src/elements/feedback/skeleton/style.css +28 -0
  160. package/src/elements/feedback/toast/index.html +3 -0
  161. package/src/elements/feedback/toast/index.js +65 -0
  162. package/src/elements/feedback/toast/index.tags.json +1 -0
  163. package/src/elements/feedback/toast/style.css +36 -0
  164. package/src/elements/forms/checkbox/index.html +7 -0
  165. package/src/elements/forms/checkbox/index.js +104 -0
  166. package/src/elements/forms/checkbox/index.tags.json +1 -0
  167. package/src/elements/forms/checkbox/style.css +86 -0
  168. package/src/elements/forms/field/index.html +13 -0
  169. package/src/elements/forms/field/index.js +42 -0
  170. package/src/elements/forms/field/index.tags.json +1 -0
  171. package/src/elements/forms/field/style.css +42 -0
  172. package/src/elements/forms/form/index.html +3 -0
  173. package/src/elements/forms/form/index.js +122 -0
  174. package/src/elements/forms/form/index.tags.json +1 -0
  175. package/src/elements/forms/form/style.css +11 -0
  176. package/src/elements/forms/input/index.html +4 -0
  177. package/src/elements/forms/input/index.js +103 -0
  178. package/src/elements/forms/input/index.tags.json +1 -0
  179. package/src/elements/forms/input/style.css +39 -0
  180. package/src/elements/forms/radio/index.html +4 -0
  181. package/src/elements/forms/radio/index.js +109 -0
  182. package/src/elements/forms/radio/index.tags.json +1 -0
  183. package/src/elements/forms/radio/style.css +65 -0
  184. package/src/elements/forms/select/index.html +9 -0
  185. package/src/elements/forms/select/index.js +114 -0
  186. package/src/elements/forms/select/index.tags.json +1 -0
  187. package/src/elements/forms/select/style.css +95 -0
  188. package/src/elements/forms/textarea/index.html +4 -0
  189. package/src/elements/forms/textarea/index.js +115 -0
  190. package/src/elements/forms/textarea/index.tags.json +1 -0
  191. package/src/elements/forms/textarea/style.css +46 -0
  192. package/src/elements/forms/toggle/index.html +4 -0
  193. package/src/elements/forms/toggle/index.js +89 -0
  194. package/src/elements/forms/toggle/index.tags.json +1 -0
  195. package/src/elements/forms/toggle/style.css +63 -0
  196. package/src/elements/forms/upload/index.html +13 -0
  197. package/src/elements/forms/upload/index.js +120 -0
  198. package/src/elements/forms/upload/index.tags.json +1 -0
  199. package/src/elements/forms/upload/style.css +61 -0
  200. package/src/elements/index.js +71 -0
  201. package/src/elements/layout/app/index.html +7 -0
  202. package/src/elements/layout/app/index.js +16 -0
  203. package/src/elements/layout/app/index.tags.json +1 -0
  204. package/src/elements/layout/app/style.css +41 -0
  205. package/src/elements/layout/grid/index.html +3 -0
  206. package/src/elements/layout/grid/index.js +41 -0
  207. package/src/elements/layout/grid/index.tags.json +1 -0
  208. package/src/elements/layout/grid/style.css +12 -0
  209. package/src/elements/layout/header/index.html +8 -0
  210. package/src/elements/layout/header/index.js +16 -0
  211. package/src/elements/layout/header/index.tags.json +1 -0
  212. package/src/elements/layout/header/style.css +28 -0
  213. package/src/elements/layout/scroll/index.html +3 -0
  214. package/src/elements/layout/scroll/index.js +19 -0
  215. package/src/elements/layout/scroll/index.tags.json +1 -0
  216. package/src/elements/layout/scroll/style.css +24 -0
  217. package/src/elements/layout/sidebar/index.html +3 -0
  218. package/src/elements/layout/sidebar/index.js +24 -0
  219. package/src/elements/layout/sidebar/index.tags.json +1 -0
  220. package/src/elements/layout/sidebar/style.css +30 -0
  221. package/src/elements/layout/split/index.html +3 -0
  222. package/src/elements/layout/split/index.js +18 -0
  223. package/src/elements/layout/split/index.tags.json +1 -0
  224. package/src/elements/layout/split/style.css +28 -0
  225. package/src/elements/layout/stack/index.html +3 -0
  226. package/src/elements/layout/stack/index.js +31 -0
  227. package/src/elements/layout/stack/index.tags.json +1 -0
  228. package/src/elements/layout/stack/style.css +15 -0
  229. package/src/elements/layout/surface/index.html +3 -0
  230. package/src/elements/layout/surface/index.js +19 -0
  231. package/src/elements/layout/surface/index.tags.json +1 -0
  232. package/src/elements/layout/surface/style.css +29 -0
  233. package/src/elements/navigation/breadcrumb/index.html +5 -0
  234. package/src/elements/navigation/breadcrumb/index.js +16 -0
  235. package/src/elements/navigation/breadcrumb/index.tags.json +1 -0
  236. package/src/elements/navigation/breadcrumb/style.css +36 -0
  237. package/src/elements/navigation/nav/index.html +3 -0
  238. package/src/elements/navigation/nav/index.js +24 -0
  239. package/src/elements/navigation/nav/index.tags.json +1 -0
  240. package/src/elements/navigation/nav/style.css +38 -0
  241. package/src/elements/navigation/pagination/index.html +3 -0
  242. package/src/elements/navigation/pagination/index.js +94 -0
  243. package/src/elements/navigation/pagination/index.tags.json +1 -0
  244. package/src/elements/navigation/pagination/style.css +39 -0
  245. package/src/elements/navigation/steps/index.html +6 -0
  246. package/src/elements/navigation/steps/index.js +64 -0
  247. package/src/elements/navigation/steps/index.tags.json +1 -0
  248. package/src/elements/navigation/steps/style.css +78 -0
  249. package/src/elements/navigation/tabs/index.html +6 -0
  250. package/src/elements/navigation/tabs/index.js +132 -0
  251. package/src/elements/navigation/tabs/index.tags.json +1 -0
  252. package/src/elements/navigation/tabs/style.css +52 -0
  253. package/src/elements/overlay/dialog/index.html +5 -0
  254. package/src/elements/overlay/dialog/index.js +57 -0
  255. package/src/elements/overlay/dialog/index.tags.json +1 -0
  256. package/src/elements/overlay/dialog/style.css +31 -0
  257. package/src/elements/overlay/drawer/index.html +3 -0
  258. package/src/elements/overlay/drawer/index.js +56 -0
  259. package/src/elements/overlay/drawer/index.tags.json +1 -0
  260. package/src/elements/overlay/drawer/style.css +48 -0
  261. package/src/elements/overlay/menu/index.html +3 -0
  262. package/src/elements/overlay/menu/index.js +107 -0
  263. package/src/elements/overlay/menu/index.tags.json +1 -0
  264. package/src/elements/overlay/menu/style.css +43 -0
  265. package/src/elements/overlay/popover/index.html +3 -0
  266. package/src/elements/overlay/popover/index.js +44 -0
  267. package/src/elements/overlay/popover/index.tags.json +1 -0
  268. package/src/elements/overlay/popover/style.css +21 -0
  269. package/src/elements/overlay/sheet/index.html +8 -0
  270. package/src/elements/overlay/sheet/index.js +105 -0
  271. package/src/elements/overlay/sheet/index.tags.json +1 -0
  272. package/src/elements/overlay/sheet/style.css +64 -0
  273. package/src/elements/overlay/tooltip/index.html +6 -0
  274. package/src/elements/overlay/tooltip/index.js +16 -0
  275. package/src/elements/overlay/tooltip/index.tags.json +1 -0
  276. package/src/elements/overlay/tooltip/style.css +41 -0
  277. package/src/elements/primitives/avatar/index.html +2 -0
  278. package/src/elements/primitives/avatar/index.js +79 -0
  279. package/src/elements/primitives/avatar/index.tags.json +1 -0
  280. package/src/elements/primitives/avatar/style.css +36 -0
  281. package/src/elements/primitives/badge/index.html +3 -0
  282. package/src/elements/primitives/badge/index.js +20 -0
  283. package/src/elements/primitives/badge/index.tags.json +1 -0
  284. package/src/elements/primitives/badge/style.css +67 -0
  285. package/src/elements/primitives/button/index.html +3 -0
  286. package/src/elements/primitives/button/index.js +61 -0
  287. package/src/elements/primitives/button/index.tags.json +1 -0
  288. package/src/elements/primitives/button/style.css +66 -0
  289. package/src/elements/primitives/divider/index.html +1 -0
  290. package/src/elements/primitives/divider/index.js +43 -0
  291. package/src/elements/primitives/divider/index.tags.json +1 -0
  292. package/src/elements/primitives/divider/style.css +39 -0
  293. package/src/elements/primitives/icon/index.html +3 -0
  294. package/src/elements/primitives/icon/index.js +66 -0
  295. package/src/elements/primitives/icon/index.tags.json +1 -0
  296. package/src/elements/primitives/icon/style.css +20 -0
  297. package/src/elements/primitives/link/index.html +3 -0
  298. package/src/elements/primitives/link/index.js +129 -0
  299. package/src/elements/primitives/link/index.tags.json +1 -0
  300. package/src/elements/primitives/link/style.css +40 -0
  301. package/src/elements/primitives/spinner/index.html +1 -0
  302. package/src/elements/primitives/spinner/index.js +62 -0
  303. package/src/elements/primitives/spinner/index.tags.json +1 -0
  304. package/src/elements/primitives/spinner/style.css +20 -0
  305. package/src/elements/primitives/text/index.html +1 -0
  306. package/src/elements/primitives/text/index.js +79 -0
  307. package/src/elements/primitives/text/index.tags.json +1 -0
  308. package/src/elements/primitives/text/style.css +25 -0
  309. package/src/index.js +23 -0
  310. package/src/styles/base.css +66 -0
  311. package/src/styles/index.css +10 -0
  312. package/src/styles/layers.css +9 -0
  313. package/src/styles/reset.css +66 -0
  314. package/src/sw/activate.js +51 -0
  315. package/src/sw/expire.js +47 -0
  316. package/src/sw/index.js +28 -0
  317. package/src/sw/install.js +35 -0
  318. package/src/sw/push.js +58 -0
  319. package/src/sw/queue.js +60 -0
  320. package/src/sw/routes.js +71 -0
  321. package/src/sw/strategies.js +247 -0
  322. package/src/sw/sync.js +80 -0
  323. package/src/tokens/index.css +26 -0
  324. package/src/tokens/primitives/colors.css +54 -0
  325. package/src/tokens/primitives/motion.css +34 -0
  326. package/src/tokens/primitives/radius.css +16 -0
  327. package/src/tokens/primitives/shadow.css +34 -0
  328. package/src/tokens/primitives/spacing.css +27 -0
  329. package/src/tokens/primitives/typography.css +46 -0
  330. package/src/tokens/primitives/zindex.css +18 -0
  331. package/src/tokens/registered/colors.css +133 -0
  332. package/src/tokens/registered/dimensions.css +31 -0
  333. package/src/tokens/semantic/components.css +125 -0
  334. package/src/tokens/semantic/contrast.css +33 -0
  335. package/src/tokens/semantic/dark.css +61 -0
  336. package/src/tokens/semantic/light.css +64 -0
  337. package/types/core/animations/index.d.ts +52 -0
  338. package/types/core/api/index.d.ts +68 -0
  339. package/types/core/events/index.d.ts +50 -0
  340. package/types/core/offline/index.d.ts +68 -0
  341. package/types/core/platform/index.d.ts +60 -0
  342. package/types/core/router/index.d.ts +203 -0
  343. package/types/core/security/index.d.ts +33 -0
  344. package/types/core/state/index.d.ts +68 -0
  345. package/types/core/storage/index.d.ts +40 -0
  346. package/types/core/ui/index.d.ts +446 -0
  347. package/types/core/workers/index.d.ts +221 -0
  348. package/types/elements/index.d.ts +150 -0
  349. package/types/index.d.ts +18 -0
@@ -0,0 +1,622 @@
1
+ # Native Workers Usage Guide
2
+
3
+ The Native Workers layer provides a small browser-native concurrency facade for Dedicated Workers, pooled task execution, SharedWorker connections, BroadcastChannel events, Web Locks, and OffscreenCanvas rendering.
4
+
5
+ Status: this guide documents the implemented public Workers contract: `workers.run`, `workers.dedicated`, `workers.shared`, `workers.lock`, `workers.broadcast`, `workers.subscribe`, `workers.offscreen`, `workers.close`, `workers.clear`, feature detection, request/response messages, transferables, and lifecycle cleanup.
6
+
7
+ Import from the workers entry point:
8
+
9
+ ```javascript
10
+ import { workers, has } from '@adukiorg/anza/workers';
11
+ ```
12
+
13
+ ## 1. Feature Detection
14
+
15
+ Use `has` when behavior depends on a browser primitive.
16
+
17
+ ```javascript
18
+ if (!has.worker) {
19
+ throw new Error('This feature needs Web Worker support');
20
+ }
21
+
22
+ if (has.isolated) {
23
+ // SharedArrayBuffer paths may be enabled here.
24
+ }
25
+ ```
26
+
27
+ Flags:
28
+
29
+ ```javascript
30
+ has.worker
31
+ has.shared
32
+ has.channel
33
+ has.locks
34
+ has.offscreen
35
+ has.isolated
36
+ ```
37
+
38
+ Rules:
39
+
40
+ - `has.worker` gates Dedicated Workers and pools.
41
+ - `has.shared` only tells whether native SharedWorker is available; `workers.shared` can still fall back to a Dedicated Worker.
42
+ - `has.channel` gates BroadcastChannel messaging.
43
+ - `has.locks` gates native cross-context Web Locks; `workers.lock` has a same-tab fallback.
44
+ - `has.offscreen` gates OffscreenCanvas.
45
+ - `has.isolated` is required before using SharedArrayBuffer.
46
+
47
+ ## 2. Message Contract
48
+
49
+ Worker request/response messages use structured-clone-safe plain data.
50
+
51
+ Request sent to a task worker:
52
+
53
+ ```javascript
54
+ {
55
+ task,
56
+ payload,
57
+ meta,
58
+ port
59
+ }
60
+ ```
61
+
62
+ Response sent back through `port`:
63
+
64
+ ```javascript
65
+ { ok: true, value }
66
+ { ok: false, error }
67
+ ```
68
+
69
+ Worker script:
70
+
71
+ ```javascript
72
+ const tasks = {
73
+ async double(payload) {
74
+ return payload * 2;
75
+ },
76
+
77
+ async sum(payload) {
78
+ return payload.reduce((total, value) => total + value, 0);
79
+ }
80
+ };
81
+
82
+ self.onmessage = async ({ data }) => {
83
+ const { task, payload, port } = data;
84
+
85
+ try {
86
+ const run = tasks[task];
87
+ if (!run) throw new Error(`Unknown task: ${task}`);
88
+
89
+ const value = await run(payload);
90
+ port.postMessage({ ok: true, value });
91
+ } catch (err) {
92
+ port.postMessage({ ok: false, error: err.message });
93
+ } finally {
94
+ port.close();
95
+ }
96
+ };
97
+ ```
98
+
99
+ Rules:
100
+
101
+ - Pass plain objects, arrays, Maps, Sets, typed arrays, primitives, Blobs, Files, and other structured-clone-safe values.
102
+ - Do not pass DOM nodes, functions, class instances with methods, symbols, WeakMaps, WeakSets, or WeakRefs.
103
+ - Validate `task` names inside worker scripts.
104
+ - Treat worker messages as untrusted input.
105
+ - Keep worker scripts as module workers.
106
+
107
+ ## 3. Transferables
108
+
109
+ Use transferables for large binary data so ownership moves instead of bytes being copied.
110
+
111
+ ```javascript
112
+ const buffer = new ArrayBuffer(1024 * 1024);
113
+
114
+ const result = await workers.run('/workers/bytes.js', 'hash', {
115
+ payload: buffer,
116
+ transferables: [buffer]
117
+ });
118
+ ```
119
+
120
+ After transfer, the sender loses access to the transferred object.
121
+
122
+ Common transferables:
123
+
124
+ - `ArrayBuffer`
125
+ - `MessagePort`
126
+ - `ReadableStream`
127
+ - `WritableStream`
128
+ - `TransformStream`
129
+ - `ImageBitmap`
130
+ - `OffscreenCanvas`
131
+ - `AudioData`
132
+ - `VideoFrame`
133
+
134
+ ## 4. `workers.run`
135
+
136
+ Use `workers.run` for CPU-bound tasks that should execute in a lazily allocated pool.
137
+
138
+ ```javascript
139
+ const value = await workers.run('/workers/math.js', 'sum', {
140
+ payload: [1, 2, 3],
141
+ priority: 'user-visible',
142
+ timeout: 3000
143
+ });
144
+ ```
145
+
146
+ With cancellation:
147
+
148
+ ```javascript
149
+ const ctrl = new AbortController();
150
+
151
+ const task = workers.run('/workers/search.js', 'index', {
152
+ payload: records,
153
+ signal: ctrl.signal,
154
+ timeout: 5000,
155
+ priority: 'background'
156
+ });
157
+
158
+ ctrl.abort();
159
+
160
+ await task;
161
+ ```
162
+
163
+ Priority values:
164
+
165
+ ```javascript
166
+ 'user-blocking'
167
+ 'user-visible'
168
+ 'background'
169
+ ```
170
+
171
+ Use priorities like this:
172
+
173
+ - `user-blocking`: input-triggered work needed before the next visible response.
174
+ - `user-visible`: normal work the user is waiting on.
175
+ - `background`: indexing, warming, cleanup, sync, and telemetry work.
176
+
177
+ Pool options are read when the pool for a script is first created:
178
+
179
+ ```javascript
180
+ await workers.run('/workers/image.js', 'resize', {
181
+ payload: image,
182
+ size: 2,
183
+ max: 4,
184
+ idle: 15000
185
+ });
186
+ ```
187
+
188
+ Use `idempotent` only when retrying the task is safe:
189
+
190
+ ```javascript
191
+ await workers.run('/workers/sync.js', 'replay', {
192
+ payload: item,
193
+ idempotent: true
194
+ });
195
+ ```
196
+
197
+ ## 5. `workers.dedicated`
198
+
199
+ Use `workers.dedicated` when one caller needs direct control of a single long-lived Dedicated Worker.
200
+
201
+ ```javascript
202
+ const worker = workers.dedicated('/workers/parser.js');
203
+
204
+ const parsed = await worker.run('json', {
205
+ payload: text,
206
+ timeout: 2000
207
+ });
208
+
209
+ worker.terminate();
210
+ ```
211
+
212
+ Direct Dedicated Workers are useful for:
213
+
214
+ - A long-lived parser.
215
+ - A persistent crypto worker.
216
+ - A custom protocol worker.
217
+ - A workflow that should not share a pool with other work.
218
+
219
+ ## 6. `Pool`
220
+
221
+ Use `Pool` directly when you need a reusable pool instance with explicit lifetime.
222
+
223
+ ```javascript
224
+ import { Pool } from '@adukiorg/anza/workers';
225
+
226
+ const pool = new Pool('/workers/image.js', {
227
+ max: 3,
228
+ idle: 30000
229
+ });
230
+
231
+ const thumbnail = await pool.run('thumbnail', {
232
+ payload: file,
233
+ priority: 'user-visible'
234
+ });
235
+
236
+ pool.terminate();
237
+ ```
238
+
239
+ Use the facade for most app code. Use `Pool` directly when a module owns its own worker lifetime.
240
+
241
+ ## 7. `Shared`
242
+
243
+ Use `workers.shared` when multiple same-origin tabs need one shared background resource.
244
+
245
+ ```javascript
246
+ const socket = workers.shared('/workers/socket.js', 'socket');
247
+
248
+ const stop = socket.subscribe((message) => {
249
+ console.log(message);
250
+ });
251
+
252
+ socket.send({
253
+ type: 'subscribe',
254
+ topic: 'prices'
255
+ });
256
+
257
+ stop();
258
+ socket.close();
259
+ ```
260
+
261
+ Shared workers are best for:
262
+
263
+ - One WebSocket shared across tabs.
264
+ - One auth refresh coordinator.
265
+ - One same-origin rate limiter.
266
+ - One shared state coordinator.
267
+
268
+ When native SharedWorker is unavailable, the implementation falls back to a Dedicated Worker with the same `send` and `subscribe` shape.
269
+
270
+ Compatibility aliases:
271
+
272
+ ```javascript
273
+ socket.postMessage(message);
274
+ socket.onMessage(handler);
275
+ ```
276
+
277
+ Prefer:
278
+
279
+ ```javascript
280
+ socket.send(message);
281
+ socket.subscribe(handler);
282
+ ```
283
+
284
+ ## 8. Shared Worker Script
285
+
286
+ A SharedWorker script receives ports through `onconnect`.
287
+
288
+ ```javascript
289
+ const ports = new Set();
290
+
291
+ self.onconnect = (event) => {
292
+ const port = event.ports[0];
293
+ ports.add(port);
294
+
295
+ port.onmessage = ({ data }) => {
296
+ if (data.type === 'subscribe') {
297
+ port.postMessage({ type: 'subscribed', topic: data.topic });
298
+ }
299
+ };
300
+
301
+ port.start();
302
+ };
303
+
304
+ function publish(message) {
305
+ for (const port of ports) {
306
+ port.postMessage(message);
307
+ }
308
+ }
309
+ ```
310
+
311
+ For the Dedicated Worker fallback, support normal `self.onmessage` too if the script needs to run in both modes.
312
+
313
+ ```javascript
314
+ self.onmessage = ({ data }) => {
315
+ self.postMessage({ type: 'received', value: data });
316
+ };
317
+ ```
318
+
319
+ ## 9. `workers.broadcast`
320
+
321
+ Use BroadcastChannel for stateless cross-tab events.
322
+
323
+ ```javascript
324
+ const stop = workers.subscribe('sync:done', (payload) => {
325
+ console.log('synced at', payload.at);
326
+ });
327
+
328
+ workers.broadcast('sync:done', {
329
+ at: Date.now()
330
+ });
331
+
332
+ stop();
333
+ ```
334
+
335
+ With `AbortSignal` cleanup:
336
+
337
+ ```javascript
338
+ const ctrl = new AbortController();
339
+
340
+ workers.subscribe('profile:changed', refresh, ctrl.signal);
341
+
342
+ ctrl.abort();
343
+ ```
344
+
345
+ Use BroadcastChannel for:
346
+
347
+ - Cache invalidation.
348
+ - Sync completion.
349
+ - State refresh notices.
350
+ - Lightweight tab-to-tab notifications.
351
+
352
+ Use SharedWorker instead when state must persist or when only one connection should exist.
353
+
354
+ ## 10. Broadcast Manager
355
+
356
+ The named `broadcast` export exposes direct channel controls.
357
+
358
+ ```javascript
359
+ import { broadcast } from '@adukiorg/anza/workers';
360
+
361
+ const stop = broadcast.subscribe('cache:avatar', clearAvatar);
362
+
363
+ broadcast.broadcast('cache:avatar', { user: '123' });
364
+
365
+ stop();
366
+ broadcast.close('cache:avatar');
367
+ broadcast.clear();
368
+ ```
369
+
370
+ `broadcast.clear()` closes every managed channel.
371
+
372
+ ## 11. `workers.lock`
373
+
374
+ Use Web Locks for cross-tab mutual exclusion.
375
+
376
+ ```javascript
377
+ await workers.lock('idb:records', async () => {
378
+ await saveRecord(record);
379
+ });
380
+ ```
381
+
382
+ With options:
383
+
384
+ ```javascript
385
+ await workers.lock('auth:refresh', refreshToken, {
386
+ mode: 'exclusive',
387
+ timeout: 5000,
388
+ signal: ctrl.signal,
389
+ ifAvailable: false,
390
+ steal: false
391
+ });
392
+ ```
393
+
394
+ Shared mode:
395
+
396
+ ```javascript
397
+ await workers.lock('opfs:report', readReport, {
398
+ mode: 'shared'
399
+ });
400
+ ```
401
+
402
+ Try-lock behavior:
403
+
404
+ ```javascript
405
+ try {
406
+ await workers.lock('sync:leader', lead, {
407
+ ifAvailable: true
408
+ });
409
+ } catch (err) {
410
+ // Another tab is already leading.
411
+ }
412
+ ```
413
+
414
+ Lock naming:
415
+
416
+ | Pattern | Use |
417
+ |---|---|
418
+ | `idb:<store>` | IndexedDB store access |
419
+ | `opfs:<file>` | OPFS file access |
420
+ | `auth:<op>` | Auth operations |
421
+ | `sync:<role>` | Sync leader or sync phase |
422
+ | `cache:<name>` | Cache invalidation |
423
+
424
+ Rules:
425
+
426
+ - Use exclusive locks for writes.
427
+ - Use shared locks for reads when supported.
428
+ - Keep lock callbacks short.
429
+ - Do not wait on user input inside a lock.
430
+ - Use `timeout` for locks that should never wait forever.
431
+
432
+ ## 12. `workers.offscreen`
433
+
434
+ Use OffscreenCanvas for render loops that should not block UI work.
435
+
436
+ ```javascript
437
+ const handle = await workers.offscreen(canvas, '/workers/render.js', {
438
+ onError(err) {
439
+ console.error('render failed', err);
440
+ },
441
+
442
+ onResize(size) {
443
+ console.log(size.width, size.height, size.dpr);
444
+ }
445
+ });
446
+
447
+ handle.send({
448
+ type: 'frame',
449
+ scene
450
+ });
451
+
452
+ handle.resize();
453
+ handle.close();
454
+ ```
455
+
456
+ The returned promise resolves after the worker acknowledges readiness.
457
+
458
+ ## 13. Offscreen Worker Script
459
+
460
+ The render worker receives the canvas and a control port.
461
+
462
+ ```javascript
463
+ let ctx;
464
+ let port;
465
+
466
+ self.onmessage = ({ data }) => {
467
+ if (data.canvas && data.port) {
468
+ ctx = data.canvas.getContext('2d');
469
+ port = data.port;
470
+ port.onmessage = oncommand;
471
+ port.postMessage({ ok: true });
472
+ }
473
+ };
474
+
475
+ function oncommand({ data }) {
476
+ if (data.type === 'resize') {
477
+ resize(data);
478
+ return;
479
+ }
480
+
481
+ if (data.type === 'frame') {
482
+ draw(data.scene);
483
+ }
484
+ }
485
+
486
+ function resize({ width, height, dpr }) {
487
+ ctx.canvas.width = Math.round(width * dpr);
488
+ ctx.canvas.height = Math.round(height * dpr);
489
+ }
490
+
491
+ function draw(scene) {
492
+ ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
493
+ // draw scene
494
+ }
495
+ ```
496
+
497
+ Keep the control port open if the main thread will call `handle.send()` or `handle.resize()`.
498
+
499
+ ## 14. Lifecycle
500
+
501
+ Close what you open.
502
+
503
+ ```javascript
504
+ const worker = workers.dedicated('/workers/job.js');
505
+ worker.terminate();
506
+
507
+ const shared = workers.shared('/workers/socket.js');
508
+ shared.close();
509
+
510
+ const stop = workers.subscribe('event', handler);
511
+ stop();
512
+
513
+ const canvas = await workers.offscreen(el, '/workers/render.js');
514
+ canvas.close();
515
+ ```
516
+
517
+ Pool lifecycle:
518
+
519
+ ```javascript
520
+ workers.close('/workers/image.js');
521
+ workers.clear();
522
+ ```
523
+
524
+ `workers.close(script)` terminates one pool.
525
+
526
+ `workers.clear()` terminates all pools and clears managed broadcast channels.
527
+
528
+ ## 15. Error Handling
529
+
530
+ Handle task errors like normal promise errors.
531
+
532
+ ```javascript
533
+ try {
534
+ await workers.run('/workers/job.js', 'import', {
535
+ payload: file,
536
+ timeout: 10000
537
+ });
538
+ } catch (err) {
539
+ console.error(err);
540
+ }
541
+ ```
542
+
543
+ Worker-side task failures should return an error response.
544
+
545
+ ```javascript
546
+ port.postMessage({
547
+ ok: false,
548
+ error: err.message
549
+ });
550
+ ```
551
+
552
+ Unhandled worker errors reject pending Dedicated Worker requests.
553
+
554
+ ## 16. Testing Workers
555
+
556
+ Mock `Worker` when unit testing callers.
557
+
558
+ ```javascript
559
+ const original = globalThis.Worker;
560
+
561
+ globalThis.Worker = class MockWorker {
562
+ addEventListener() {}
563
+
564
+ postMessage({ task, payload, port }) {
565
+ port.postMessage({
566
+ ok: true,
567
+ value: `${task}:${payload}`
568
+ });
569
+ }
570
+
571
+ terminate() {}
572
+ };
573
+
574
+ try {
575
+ const value = await workers.run('/mock.js', 'ping', {
576
+ payload: 'pong'
577
+ });
578
+ } finally {
579
+ globalThis.Worker = original;
580
+ }
581
+ ```
582
+
583
+ Test these paths:
584
+
585
+ - Success response.
586
+ - `{ ok: false }` response.
587
+ - Abort before start.
588
+ - Abort while queued.
589
+ - Timeout.
590
+ - Worker error.
591
+ - `messageerror`.
592
+ - Transferables.
593
+ - Cleanup after `close`, `terminate`, and `clear`.
594
+
595
+ ## 17. Choosing a Primitive
596
+
597
+ | Need | Use |
598
+ |---|---|
599
+ | CPU task with scheduling | `workers.run` |
600
+ | Single tab-owned worker | `workers.dedicated` |
601
+ | Owned pool instance | `new Pool()` |
602
+ | Shared socket | `workers.shared` |
603
+ | Cross-tab event | `workers.broadcast` |
604
+ | Cross-tab subscription | `workers.subscribe` |
605
+ | Cross-tab mutex | `workers.lock` |
606
+ | Canvas render loop | `workers.offscreen` |
607
+
608
+ ## 18. Checklist
609
+
610
+ - Use `workers.run` for normal CPU work.
611
+ - Use `workers.dedicated` only when direct worker ownership matters.
612
+ - Use `workers.shared` for persistent same-origin coordination.
613
+ - Use `workers.broadcast` for stateless events.
614
+ - Use `workers.lock` for shared resources and leader election.
615
+ - Use `workers.offscreen` for expensive canvas rendering.
616
+ - Pass `AbortSignal` to cancellable tasks.
617
+ - Use `timeout` when a task or lock should not wait forever.
618
+ - Pass transferables for large binary values.
619
+ - Do not pass DOM nodes, functions, or class instances to workers.
620
+ - Validate task names inside worker scripts.
621
+ - Close direct workers, shared connections, broadcasts, and offscreen handles.
622
+ - Call `workers.clear()` during app-level teardown.
@@ -0,0 +1,12 @@
1
+ /**
2
+ * src/elements/base.js
3
+ *
4
+ * Elements Base boundary.
5
+ * Re-exports the unified lifecycle BaseElement class as `Base` to maintain
6
+ * clean architectural limits for custom components authoring.
7
+ *
8
+ * Source: doc 04 — Web Components §1
9
+ */
10
+
11
+ import { BaseElement } from '../core/ui/base.js';
12
+ export { BaseElement as Base };
@@ -0,0 +1,9 @@
1
+ <div class="header" part="header">
2
+ <slot name="header"></slot>
3
+ </div>
4
+ <div class="body" part="body">
5
+ <slot></slot>
6
+ </div>
7
+ <div class="footer" part="footer">
8
+ <slot name="footer"></slot>
9
+ </div>
@@ -0,0 +1,19 @@
1
+ /**
2
+ * src/elements/data/card/index.js
3
+ *
4
+ * Data Element: <ui-card>
5
+ * Premium card containment container including header, body, footer slots,
6
+ * and subtle micro-animation interactive hover lifts.
7
+ *
8
+ * Source: doc 04 — Web Components §3, doc 05 — Native UI Primitives §3
9
+ */
10
+
11
+ import { ui } from '../../../core/ui/index.js';
12
+
13
+ ui.element('ui-card', {
14
+ style: './style.css',
15
+ template: './index.html',
16
+ props: {
17
+ interactive: { type: Boolean, reflect: true }
18
+ }
19
+ }, import.meta.url);
@@ -0,0 +1 @@
1
+ {"version":1,"refs":[],"ids":[],"classes":["body","footer","header"],"tags":["div","slot"],"compound":["div.body","div.footer","div.header"],"attrs":["class","name","part"],"refTypes":{}}
@@ -0,0 +1,46 @@
1
+ :host {
2
+ display: flex;
3
+ flex-direction: column;
4
+ background: var(--color-surface-elevated);
5
+ border: var(--space-px) solid var(--color-border-default);
6
+ border-radius: var(--radius-lg);
7
+ box-shadow: var(--shadow-sm);
8
+ overflow: hidden;
9
+ font-family: var(--font-family-sans);
10
+ transition:
11
+ transform var(--duration-fast) var(--ease-out),
12
+ box-shadow var(--duration-fast) var(--ease-out),
13
+ border-color var(--duration-fast) var(--ease-out);
14
+ box-sizing: border-box;
15
+ width: 100%;
16
+ }
17
+
18
+ .header {
19
+ padding: var(--space-4) var(--space-6);
20
+ border-bottom: var(--space-px) solid var(--color-border-default);
21
+ }
22
+
23
+ .body {
24
+ padding: var(--space-6);
25
+ flex: 1;
26
+ }
27
+
28
+ .footer {
29
+ padding: var(--space-4) var(--space-6);
30
+ background: var(--color-surface-page);
31
+ border-top: var(--space-px) solid var(--color-border-default);
32
+ display: flex;
33
+ gap: var(--space-3);
34
+ justify-content: flex-end;
35
+ }
36
+
37
+ /* Hover elevation highlights for interactive cards */
38
+ :host([interactive]) {
39
+ cursor: pointer;
40
+ }
41
+
42
+ :host([interactive]:hover) {
43
+ transform: translateY(calc(-1 * var(--space-1)));
44
+ box-shadow: var(--shadow-md);
45
+ border-color: var(--color-border-strong);
46
+ }
@@ -0,0 +1 @@
1
+ <canvas></canvas>