@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,301 @@
1
+ # Native Animations Usage Guide
2
+
3
+ The Native animations layer provides WAAPI (Web Animations API) helpers, easing curves, keyframe templates, stagger groups, scroll-linked animations, and view transitions. All timing values are sourced from CSS motion tokens for consistency.
4
+
5
+ Import from the animations entry point:
6
+
7
+ ```javascript
8
+ import { animate, stagger, register, scroll, view, timing, keyframes, reduced } from '@adukiorg/anza/animations';
9
+ ```
10
+
11
+ ## 1. Basic Animation
12
+
13
+ Animate a single element with keyframes and timing options:
14
+
15
+ ```javascript
16
+ import { animate, timing } from '@adukiorg/anza/animations';
17
+
18
+ const animation = animate(
19
+ element,
20
+ [
21
+ { opacity: 0, transform: 'translateY(20px)' },
22
+ { opacity: 1, transform: 'translateY(0)' }
23
+ ],
24
+ timing()
25
+ );
26
+ ```
27
+
28
+ The `timing()` helper defaults to the CSS `--duration-normal` and `--ease-default` tokens:
29
+
30
+ ```javascript
31
+ timing(duration, easing, fill)
32
+ // Defaults: timing('normal', 'default', 'both')
33
+ ```
34
+
35
+ Custom timing:
36
+
37
+ ```javascript
38
+ timing(300, 'ease-out', 'forwards')
39
+ ```
40
+
41
+ ## 2. Timing and Easing
42
+
43
+ ### Timing Presets
44
+
45
+ Use the `Timing` object for named easing curves:
46
+
47
+ ```javascript
48
+ import { Timing } from '@adukiorg/anza/animations';
49
+
50
+ animate(element, keyframes, {
51
+ duration: 250,
52
+ easing: Timing.FAST, // --ease-out
53
+ fill: 'both'
54
+ });
55
+ ```
56
+
57
+ Available easing curves:
58
+
59
+ | Constant | Value | Token |
60
+ |----------|-------|-------|
61
+ | `Timing.EASE` | `ease` | - |
62
+ | `Timing.EASE_IN` | `ease-in` | - |
63
+ | `Timing.EASE_OUT` | `ease-out` | - |
64
+ | `Timing.EASE_IN_OUT` | `ease-in-out` | - |
65
+ | `Timing.LINEAR` | `linear` | - |
66
+ | `Timing.DEFAULT` | `--ease-default` | CSS token |
67
+ | `Timing.SMOOTH` | `--ease-default` | CSS token |
68
+ | `Timing.FAST` | `--ease-out` | CSS token |
69
+ | `Timing.SOFT` | `--ease-in-out` | CSS token |
70
+ | `Timing.BOUNCE` | `--ease-spring` | CSS token |
71
+ | `Timing.SPRING` | `--ease-spring` | CSS token |
72
+
73
+ ### Duration Tokens
74
+
75
+ Durations are read from CSS `--duration-*` tokens:
76
+
77
+ ```javascript
78
+ import { duration } from '@adukiorg/anza/animations';
79
+
80
+ const fast = duration('fast'); // --duration-fast (100ms)
81
+ const normal = duration('normal'); // --duration-normal (200ms)
82
+ const slow = duration('slow'); // --duration-slow (300ms)
83
+ ```
84
+
85
+ Fallback values are used when CSS tokens are unavailable (SSR, missing styles).
86
+
87
+ ## 3. Keyframe Templates
88
+
89
+ Use `keyframes()` for common transition patterns:
90
+
91
+ ```javascript
92
+ import { keyframes, animate } from '@adukiorg/anza/animations';
93
+
94
+ // Fade in/out
95
+ animate(element, keyframes('fade'), timing());
96
+
97
+ // Slide (default: Y axis)
98
+ animate(element, keyframes('slide', { axis: 'y', from: '20px' }), timing());
99
+
100
+ // Scale
101
+ animate(element, keyframes('scale'), timing());
102
+
103
+ // Zoom
104
+ animate(element, keyframes('zoom'), timing());
105
+
106
+ // Blur
107
+ animate(element, keyframes('blur'), timing());
108
+ ```
109
+
110
+ Custom keyframe options:
111
+
112
+ ```javascript
113
+ keyframes('fade', { from: 0.5, to: 1 })
114
+ keyframes('slide', { axis: 'x', from: '100px' })
115
+ keyframes('scale', { from: 0.8 })
116
+ ```
117
+
118
+ ## 4. Staggered Animations
119
+
120
+ Animate a group of elements with sequential delays:
121
+
122
+ ```javascript
123
+ import { stagger } from '@adukiorg/anza/animations';
124
+
125
+ const cards = document.querySelectorAll('.card');
126
+
127
+ stagger(Array.from(cards), [
128
+ { opacity: 0, transform: 'translateY(20px)' },
129
+ { opacity: 1, transform: 'translateY(0)' }
130
+ ], {
131
+ duration: 250,
132
+ staggerDelay: 60
133
+ });
134
+ ```
135
+
136
+ Returns an array of `Animation` objects for control:
137
+
138
+ ```javascript
139
+ const animations = stagger(elements, keyframes, options);
140
+ animations.forEach(anim => anim.pause());
141
+ ```
142
+
143
+ ## 5. Scroll-Linked Animations
144
+
145
+ Link animations to scroll position:
146
+
147
+ ```javascript
148
+ import { scroll } from '@adukiorg/anza/animations';
149
+
150
+ const stop = scroll(element, [
151
+ { transform: 'translateY(0)' },
152
+ { transform: 'translateY(-50px)' }
153
+ ], {
154
+ range: [0, 1], // 0-1 scroll progress
155
+ target: document.documentElement
156
+ });
157
+ ```
158
+
159
+ Call the returned function to clean up:
160
+
161
+ ```javascript
162
+ stop(); // Disconnects ScrollTimeline
163
+ ```
164
+
165
+ ## 6. View Transitions
166
+
167
+ Use the View Transitions API for page navigation animations:
168
+
169
+ ```javascript
170
+ import { view } from '@adukiorg/anza/animations';
171
+
172
+ view(async () => {
173
+ // Update DOM here
174
+ document.body.classList.add('new-page');
175
+ });
176
+ ```
177
+
178
+ Custom transition:
179
+
180
+ ```javascript
181
+ view(async () => {
182
+ await updateDOM();
183
+ }, {
184
+ duration: 300,
185
+ easing: 'ease-out'
186
+ });
187
+ ```
188
+
189
+ ## 7. Reduced Motion
190
+
191
+ Check for user's motion preference:
192
+
193
+ ```javascript
194
+ import { reduced } from '@adukiorg/anza/animations';
195
+
196
+ if (!reduced()) {
197
+ animate(element, keyframes('fade'), timing());
198
+ }
199
+ ```
200
+
201
+ The `reduced()` function checks `prefers-reduced-motion: reduce`.
202
+
203
+ ## 8. Token Integration
204
+
205
+ All timing values are sourced from CSS motion tokens:
206
+
207
+ ```css
208
+ /* src/tokens/primitives/motion.css */
209
+ :root {
210
+ --duration-instant: 50ms;
211
+ --duration-fast: 100ms;
212
+ --duration-normal: 200ms;
213
+ --duration-slow: 300ms;
214
+ --duration-slower: 500ms;
215
+
216
+ --ease-default: cubic-bezier(0.4, 0, 0.2, 1);
217
+ --ease-in: cubic-bezier(0.4, 0, 1, 1);
218
+ --ease-out: cubic-bezier(0, 0, 0.2, 1);
219
+ --ease-in-out: cubic-bezier(0.4, 0, 0.6, 1);
220
+ --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
221
+ --ease-linear: linear;
222
+ }
223
+ ```
224
+
225
+ JS animations automatically use these values, ensuring CSS and JS animations share one source of truth.
226
+
227
+ ## 9. Animation Control
228
+
229
+ `animate()` returns a WAAPI `Animation` object:
230
+
231
+ ```javascript
232
+ const anim = animate(element, keyframes, timing());
233
+
234
+ anim.pause();
235
+ anim.play();
236
+ anim.finish();
237
+ anim.cancel();
238
+ anim.reverse();
239
+
240
+ anim.finished.then(() => console.log('done'));
241
+ ```
242
+
243
+ ## 10. Registered Presets
244
+
245
+ Common animation presets are pre-registered for convenience:
246
+
247
+ ```javascript
248
+ import { animate } from '@adukiorg/anza/animations';
249
+
250
+ // Use registered presets by name
251
+ animate(element, 'fade');
252
+ animate(element, 'slide');
253
+ animate(element, 'slide-x');
254
+ animate(element, 'slide-y');
255
+ animate(element, 'scale');
256
+ animate(element, 'zoom');
257
+ animate(element, 'blur');
258
+ ```
259
+
260
+ Available presets:
261
+ - `fade` - Opacity transition
262
+ - `slide` - Y-axis slide
263
+ - `slide-x` - X-axis slide
264
+ - `slide-y` - Y-axis slide
265
+ - `scale` - Scale from 0.95 to 1
266
+ - `zoom` - Scale from 1.1 to 1
267
+ - `blur` - Blur transition
268
+
269
+ Register custom presets:
270
+
271
+ ```javascript
272
+ import { registry, keyframes, timing } from '@adukiorg/anza/animations';
273
+
274
+ registry.register('myPreset', keyframes('fade'), timing(300));
275
+ ```
276
+
277
+ ## 11. Sequence Helper
278
+
279
+ Chain animations sequentially, each starting when the previous finishes:
280
+
281
+ ```javascript
282
+ import { sequence } from '@adukiorg/anza/animations';
283
+
284
+ const { finished } = sequence([
285
+ [element1, keyframes('fade'), timing()],
286
+ [element2, keyframes('slide'), timing()],
287
+ [element3, keyframes('scale'), timing()]
288
+ ]);
289
+
290
+ await finished;
291
+ ```
292
+
293
+ Each step is `[element, animationInput, options?]`. Returns `{ finished }` promise.
294
+
295
+ ## 11. Performance Guidelines
296
+
297
+ - Use `requestAnimationFrame` for visual updates (handled by WAAPI)
298
+ - Prefer transforms and opacity for GPU-accelerated properties
299
+ - Respect `prefers-reduced-motion` for accessibility
300
+ - Use `stagger()` for list animations instead of manual delays
301
+ - Clean up scroll-linked animations with the returned disposer
@@ -0,0 +1,86 @@
1
+ /**
2
+ * src/core/animations/waapi.js
3
+ *
4
+ * WAAPI Easing Curves and Keyframe Helpers.
5
+ * Easing curves and durations are sourced from the CSS motion tokens
6
+ * (`--ease-*`, `--duration-*`) via ./tokens.js, so JS animations and CSS share a
7
+ * single source of truth. Values fall back to the token defaults when the
8
+ * document is unavailable.
9
+ *
10
+ * Source: doc 03 — Native CSS Architecture §6, doc 12 — Performance §4
11
+ */
12
+
13
+ import { duration as durationToken, ease } from './tokens.js';
14
+
15
+ /**
16
+ * Named easing curves. CSS keywords are returned verbatim; the curated curves
17
+ * resolve to the matching `--ease-*` motion token at access time.
18
+ */
19
+ export const Timing = {
20
+ EASE: 'ease',
21
+ EASE_IN: 'ease-in',
22
+ EASE_OUT: 'ease-out',
23
+ EASE_IN_OUT: 'ease-in-out',
24
+ LINEAR: 'linear',
25
+ get DEFAULT() { return ease('default'); },
26
+ get SMOOTH() { return ease('default'); },
27
+ get FAST() { return ease('out'); },
28
+ get SOFT() { return ease('in-out'); },
29
+ get BOUNCE() { return ease('spring'); },
30
+ get SPRING() { return ease('spring'); }
31
+ };
32
+
33
+ /**
34
+ * Convenience helper to format WAAPI timing descriptors. Duration defaults to the
35
+ * `--duration-normal` token; easing defaults to the `--ease-default` token.
36
+ */
37
+ export function timing(duration = durationToken('normal'), easing = ease('default'), fill = 'both') {
38
+ return { duration, easing, fill };
39
+ }
40
+
41
+ /**
42
+ * Builds keyframe arrays for common transition templates.
43
+ * Types: fade, slide, scale, zoom, blur.
44
+ */
45
+ export function keyframes(type, options = {}) {
46
+ if (type === 'fade') {
47
+ return [
48
+ { opacity: options.from ?? 0 },
49
+ { opacity: options.to ?? 1 }
50
+ ];
51
+ }
52
+
53
+ if (type === 'slide') {
54
+ const axis = options.axis ?? 'y';
55
+ const amount = options.from ?? '20px';
56
+ const transformFrom = axis === 'x' ? `translateX(${amount})` : `translateY(${amount})`;
57
+
58
+ return [
59
+ { transform: transformFrom, opacity: 0 },
60
+ { transform: 'translate(0, 0)', opacity: 1 }
61
+ ];
62
+ }
63
+
64
+ if (type === 'scale') {
65
+ return [
66
+ { transform: `scale(${options.from ?? 0.95})`, opacity: 0 },
67
+ { transform: 'scale(1)', opacity: 1 }
68
+ ];
69
+ }
70
+
71
+ if (type === 'zoom') {
72
+ return [
73
+ { transform: `scale(${options.from ?? 1.1})`, opacity: 0 },
74
+ { transform: 'scale(1)', opacity: 1 }
75
+ ];
76
+ }
77
+
78
+ if (type === 'blur') {
79
+ return [
80
+ { filter: `blur(${options.from ?? '8px'})`, opacity: 0 },
81
+ { filter: 'blur(0)', opacity: 1 }
82
+ ];
83
+ }
84
+
85
+ return [];
86
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * src/core/api/cache.js
3
+ *
4
+ * Direct Cache API integration on the main thread.
5
+ * Implements three standard caching strategies:
6
+ * 1. cache-first: Shell & static assets cache.
7
+ * 2. network-first: Dynamic API data fallback.
8
+ * 3. stale-while-revalidate: High-performance near-instant timelines/feeds.
9
+ *
10
+ * Source: doc 11 — Networking §6
11
+ */
12
+
13
+ import { cache as apiCache } from './caches/index.js';
14
+
15
+ const CACHE_NAME = 'platform-api-cache';
16
+
17
+ /**
18
+ * Handles request caching using declared strategies and TTL controls.
19
+ */
20
+ export async function handle(descriptor, executeFetch) {
21
+ const { cache: strategy, url, method = 'GET' } = descriptor;
22
+
23
+ // Caching is strictly limited to GET requests and when Cache API is present
24
+ if (method !== 'GET' || typeof caches === 'undefined') {
25
+ return executeFetch(descriptor);
26
+ }
27
+
28
+ // Check for fine-grained TTL / Expiry options
29
+ const ttl = descriptor.expiry || descriptor.ttl || (strategy && typeof strategy === 'object' ? strategy.expiry || strategy.ttl : null);
30
+
31
+ if (ttl) {
32
+ const cached = await apiCache.get(url);
33
+ if (cached) return cached;
34
+
35
+ const response = await executeFetch(descriptor);
36
+ if (response.ok) {
37
+ await apiCache.set(url, response.clone(), ttl);
38
+ }
39
+ return response;
40
+ }
41
+
42
+ // Fallback to legacy string-based strategies if cache strategy is specified
43
+ if (!strategy || typeof strategy !== 'string') {
44
+ return executeFetch(descriptor);
45
+ }
46
+
47
+ const storage = await caches.open(CACHE_NAME);
48
+
49
+ if (strategy === 'cache-first') {
50
+ const cached = await storage.match(url);
51
+ if (cached) return cached;
52
+
53
+ const response = await executeFetch(descriptor);
54
+ if (response.ok) {
55
+ await storage.put(url, response.clone());
56
+ }
57
+ return response;
58
+ }
59
+
60
+ if (strategy === 'network-first') {
61
+ try {
62
+ const response = await executeFetch(descriptor);
63
+ if (response.ok) {
64
+ await storage.put(url, response.clone());
65
+ }
66
+ return response;
67
+ } catch (err) {
68
+ const cached = await storage.match(url);
69
+ if (cached) return cached;
70
+ throw err; // propagates the normalized error if no cache is present
71
+ }
72
+ }
73
+
74
+ if (strategy === 'stale-while-revalidate') {
75
+ const cached = await storage.match(url);
76
+
77
+ const revalidate = async () => {
78
+ try {
79
+ const response = await executeFetch(descriptor);
80
+ if (response.ok) {
81
+ await storage.put(url, response.clone());
82
+ // Broadcast to the system that state cache has updated
83
+ globalThis.dispatchEvent(
84
+ new CustomEvent('cache:updated', {
85
+ detail: { url, status: 'updated' }
86
+ })
87
+ );
88
+ }
89
+ } catch (err) {
90
+ console.warn(`Background revalidation failed for ${url}:`, err);
91
+ }
92
+ };
93
+
94
+ if (cached) {
95
+ // Trigger background revalidation asynchronously
96
+ revalidate();
97
+ return cached;
98
+ }
99
+
100
+ const response = await executeFetch(descriptor);
101
+ if (response.ok) {
102
+ await storage.put(url, response.clone());
103
+ }
104
+ return response;
105
+ }
106
+
107
+ return executeFetch(descriptor);
108
+ }
109
+
110
+ /**
111
+ * Clears specific entry or entire API cache store.
112
+ */
113
+ export async function invalidate(url) {
114
+ if (url) {
115
+ await apiCache.delete(url);
116
+ } else {
117
+ await apiCache.clear();
118
+ }
119
+ }
120
+
@@ -0,0 +1,24 @@
1
+ /**
2
+ * src/core/api/caches/glob.js
3
+ *
4
+ * Converts a simple glob pattern into a regular expression for namespace-based clearing.
5
+ *
6
+ * Source: doc 11 — Networking §6, core/api/plan.md
7
+ */
8
+
9
+ /**
10
+ * Translates a glob pattern (e.g., "/user/*") into a RegExp object.
11
+ * Supports standard * wildcards.
12
+ *
13
+ * @param {string} pattern
14
+ * @returns {RegExp}
15
+ */
16
+ export function globToRegex(pattern) {
17
+ // Escape standard regex special characters
18
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&');
19
+
20
+ // Replace * with .* to permit wildcard matching
21
+ const wildcarded = escaped.replace(/\*/g, '.*');
22
+
23
+ return new RegExp(`^${wildcarded}$`);
24
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * src/core/api/caches/index.js
3
+ *
4
+ * Unified Cache API wrapper for the dynamic API client.
5
+ * Implements granular TTL/expiry controls and glob namespace invalidation patterns.
6
+ *
7
+ * Source: doc 11 — Networking §6, core/api/plan.md
8
+ */
9
+
10
+ import { globToRegex } from './glob.js';
11
+
12
+ const CACHE_NAME = 'platform-api-cache';
13
+
14
+ export class ApiCache {
15
+ constructor(name = CACHE_NAME) {
16
+ this.name = name;
17
+ }
18
+
19
+ /**
20
+ * Opens the underlying cache store.
21
+ *
22
+ * @returns {Promise<Cache>}
23
+ */
24
+ open() {
25
+ return caches.open(this.name);
26
+ }
27
+
28
+ /**
29
+ * Retrieves an item from the cache store.
30
+ * Evicts the record and returns null if the entry has expired.
31
+ *
32
+ * @param {string|Request} request
33
+ * @returns {Promise<Response|null>}
34
+ */
35
+ async get(request) {
36
+ if (typeof caches === 'undefined') return null;
37
+
38
+ const store = await this.open();
39
+ const req = typeof request === 'string' ? new Request(request) : request;
40
+ const cached = await store.match(req);
41
+
42
+ if (!cached) return null;
43
+
44
+ const expiresAt = cached.headers.get('x-expires-at');
45
+ if (expiresAt && Date.now() > Number(expiresAt)) {
46
+ await store.delete(req);
47
+ return null;
48
+ }
49
+
50
+ return cached.clone();
51
+ }
52
+
53
+ /**
54
+ * Caches a Response with a designated TTL.
55
+ *
56
+ * @param {string|Request} request
57
+ * @param {Response} response
58
+ * @param {number} ttlMs
59
+ * @returns {Promise<void>}
60
+ */
61
+ async set(request, response, ttlMs) {
62
+ if (typeof caches === 'undefined') return;
63
+
64
+ const store = await this.open();
65
+ const req = typeof request === 'string' ? new Request(request) : request;
66
+ const headers = new Headers(response.headers);
67
+
68
+ if (ttlMs) {
69
+ headers.set('x-expires-at', String(Date.now() + ttlMs));
70
+ }
71
+
72
+ const cloned = new Response(response.body ? response.clone().body : null, {
73
+ status: response.status,
74
+ statusText: response.statusText,
75
+ headers
76
+ });
77
+
78
+ await store.put(req, cloned);
79
+ }
80
+
81
+ /**
82
+ * Removes cached entries matching the provided url or glob pattern.
83
+ *
84
+ * @param {string} pattern
85
+ * @returns {Promise<void>}
86
+ */
87
+ async delete(pattern) {
88
+ if (typeof caches === 'undefined') return;
89
+
90
+ const store = await this.open();
91
+
92
+ if (pattern.includes('*')) {
93
+ const regex = globToRegex(pattern);
94
+ const keys = await store.keys();
95
+
96
+ for (const req of keys) {
97
+ const urlObj = new URL(req.url);
98
+ if (regex.test(req.url) || regex.test(urlObj.pathname)) {
99
+ await store.delete(req);
100
+ }
101
+ }
102
+ } else {
103
+ await store.delete(pattern);
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Completely purges the entire API cache store.
109
+ *
110
+ * @returns {Promise<void>}
111
+ */
112
+ async clear() {
113
+ if (typeof caches === 'undefined') return;
114
+ await caches.delete(this.name);
115
+ }
116
+ }
117
+
118
+ export const cache = new ApiCache();