@toa.io/extensions.configuration 1.0.0-alpha.272 → 1.0.0-alpha.274

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 (522) hide show
  1. package/CHANGELOG.md +210 -0
  2. package/components/configuration.values/manifest.toa.yaml +158 -0
  3. package/components/configuration.values/source/create.ts +56 -0
  4. package/components/configuration.values/source/fetch.ts +24 -0
  5. package/components/configuration.values/source/get.ts +33 -0
  6. package/components/configuration.values/source/lib/map.test.ts +34 -0
  7. package/components/configuration.values/source/lib/map.ts +34 -0
  8. package/components/configuration.values/source/lib/resolve.ts +54 -0
  9. package/components/configuration.values/source/list.ts +19 -0
  10. package/components/configuration.values/tsconfig.json +9 -0
  11. package/cucumber.js +8 -0
  12. package/features/site/_app/immutable/asset.js +1 -0
  13. package/features/site/index.html +6 -0
  14. package/features/steps/UI.ts +88 -0
  15. package/features/steps/tsconfig.json +9 -0
  16. package/features/ui.feature +85 -0
  17. package/package.json +14 -7
  18. package/readme.md +160 -47
  19. package/schemas/annotation.cos.yaml +29 -1
  20. package/schemas/manifest.cos.yaml +9 -3
  21. package/source/Aspect.test.ts +84 -8
  22. package/source/Aspect.ts +59 -5
  23. package/source/Client.test.ts +104 -0
  24. package/source/Client.ts +258 -0
  25. package/source/Composition.ts +57 -0
  26. package/source/Factory.ts +28 -5
  27. package/source/Secret.test.ts +29 -0
  28. package/source/Secret.ts +29 -0
  29. package/source/UI.ts +197 -0
  30. package/source/configuration.test.ts +92 -39
  31. package/source/configuration.ts +30 -11
  32. package/source/const.ts +17 -0
  33. package/source/deployment.test.ts +80 -1
  34. package/source/deployment.ts +73 -24
  35. package/source/epoch.test.ts +26 -0
  36. package/source/epoch.ts +21 -0
  37. package/source/index.ts +2 -1
  38. package/transpiled/Aspect.d.ts +18 -4
  39. package/transpiled/Aspect.js +47 -3
  40. package/transpiled/Aspect.js.map +1 -1
  41. package/transpiled/Aspect.test.js +59 -9
  42. package/transpiled/Aspect.test.js.map +1 -1
  43. package/transpiled/Client.d.ts +61 -0
  44. package/transpiled/Client.js +173 -0
  45. package/transpiled/Client.js.map +1 -0
  46. package/transpiled/Client.test.d.ts +1 -0
  47. package/transpiled/Client.test.js +77 -0
  48. package/transpiled/Client.test.js.map +1 -0
  49. package/transpiled/Composition.d.ts +14 -0
  50. package/transpiled/Composition.js +43 -0
  51. package/transpiled/Composition.js.map +1 -0
  52. package/transpiled/Factory.d.ts +8 -2
  53. package/transpiled/Factory.js +17 -2
  54. package/transpiled/Factory.js.map +1 -1
  55. package/transpiled/Secret.d.ts +13 -0
  56. package/transpiled/Secret.js +26 -0
  57. package/transpiled/Secret.js.map +1 -0
  58. package/transpiled/Secret.test.d.ts +1 -0
  59. package/transpiled/Secret.test.js +26 -0
  60. package/transpiled/Secret.test.js.map +1 -0
  61. package/transpiled/UI.d.ts +25 -0
  62. package/transpiled/UI.js +186 -0
  63. package/transpiled/UI.js.map +1 -0
  64. package/transpiled/configuration.d.ts +7 -2
  65. package/transpiled/configuration.js +31 -13
  66. package/transpiled/configuration.js.map +1 -1
  67. package/transpiled/configuration.test.js +84 -37
  68. package/transpiled/configuration.test.js.map +1 -1
  69. package/transpiled/const.d.ts +11 -0
  70. package/transpiled/const.js +14 -0
  71. package/transpiled/const.js.map +1 -0
  72. package/transpiled/deployment.d.ts +10 -4
  73. package/transpiled/deployment.js +57 -21
  74. package/transpiled/deployment.js.map +1 -1
  75. package/transpiled/deployment.test.js +60 -0
  76. package/transpiled/deployment.test.js.map +1 -1
  77. package/transpiled/epoch.d.ts +2 -0
  78. package/transpiled/epoch.js +21 -0
  79. package/transpiled/epoch.js.map +1 -0
  80. package/transpiled/epoch.test.d.ts +1 -0
  81. package/transpiled/epoch.test.js +22 -0
  82. package/transpiled/epoch.test.js.map +1 -0
  83. package/transpiled/index.d.ts +2 -1
  84. package/transpiled/index.js +4 -1
  85. package/transpiled/index.js.map +1 -1
  86. package/transpiled/tsconfig.tsbuildinfo +1 -1
  87. package/ui/.agents/skills/antcn/SKILL.md +91 -0
  88. package/ui/.agents/skills/antcn/references/analytics.md +78 -0
  89. package/ui/.agents/skills/antcn/references/bridge.md +41 -0
  90. package/ui/.agents/skills/antcn/references/clipboard.md +23 -0
  91. package/ui/.agents/skills/antcn/references/dismissable.md +75 -0
  92. package/ui/.agents/skills/antcn/references/dropdown.md +153 -0
  93. package/ui/.agents/skills/antcn/references/fragments.md +29 -0
  94. package/ui/.agents/skills/antcn/references/fullscreen.md +157 -0
  95. package/ui/.agents/skills/antcn/references/geo.md +27 -0
  96. package/ui/.agents/skills/antcn/references/globals.md +31 -0
  97. package/ui/.agents/skills/antcn/references/grammatical-form.md +69 -0
  98. package/ui/.agents/skills/antcn/references/hints.md +44 -0
  99. package/ui/.agents/skills/antcn/references/hold.md +34 -0
  100. package/ui/.agents/skills/antcn/references/iam.md +117 -0
  101. package/ui/.agents/skills/antcn/references/input-form.md +34 -0
  102. package/ui/.agents/skills/antcn/references/locale.md +66 -0
  103. package/ui/.agents/skills/antcn/references/net.md +33 -0
  104. package/ui/.agents/skills/antcn/references/panel.md +44 -0
  105. package/ui/.agents/skills/antcn/references/passkeys.md +27 -0
  106. package/ui/.agents/skills/antcn/references/payments.md +99 -0
  107. package/ui/.agents/skills/antcn/references/realtime.md +69 -0
  108. package/ui/.agents/skills/antcn/references/scrollable.md +39 -0
  109. package/ui/.agents/skills/antcn/references/selector.md +71 -0
  110. package/ui/.agents/skills/antcn/references/shake.md +36 -0
  111. package/ui/.agents/skills/antcn/references/share.md +28 -0
  112. package/ui/.agents/skills/antcn/references/shell.md +139 -0
  113. package/ui/.agents/skills/antcn/references/stack.md +53 -0
  114. package/ui/.agents/skills/antcn/references/system.md +149 -0
  115. package/ui/.agents/skills/antcn/references/taptap.md +28 -0
  116. package/ui/.agents/skills/antcn/references/tools.md +68 -0
  117. package/ui/.agents/skills/antcn/references/transmission.md +96 -0
  118. package/ui/.agents/skills/shadcn-svelte/SKILL.md +227 -0
  119. package/ui/.agents/skills/shadcn-svelte/agents/openai.yml +5 -0
  120. package/ui/.agents/skills/shadcn-svelte/assets/shadcn-svelte-small.png +0 -0
  121. package/ui/.agents/skills/shadcn-svelte/assets/shadcn-svelte.png +0 -0
  122. package/ui/.agents/skills/shadcn-svelte/cli.md +166 -0
  123. package/ui/.agents/skills/shadcn-svelte/customization.md +213 -0
  124. package/ui/.agents/skills/shadcn-svelte/evals/evals.json +47 -0
  125. package/ui/.agents/skills/shadcn-svelte/rules/composition.md +244 -0
  126. package/ui/.agents/skills/shadcn-svelte/rules/forms.md +234 -0
  127. package/ui/.agents/skills/shadcn-svelte/rules/icons.md +107 -0
  128. package/ui/.agents/skills/shadcn-svelte/rules/styling.md +195 -0
  129. package/ui/.agents/skills/svas/SKILL.md +169 -0
  130. package/ui/.agents/skills/svas/references/patterns.md +95 -0
  131. package/ui/.agents/skills/svintl/SKILL.md +176 -0
  132. package/ui/.claude/settings.json +15 -0
  133. package/ui/.codex/hooks.json +15 -0
  134. package/ui/.cursor/hooks.json +11 -0
  135. package/ui/.env.example +1 -0
  136. package/ui/.prettierrc +9 -0
  137. package/ui/.vscode/extensions.json +7 -0
  138. package/ui/.vscode/settings.json +27 -0
  139. package/ui/AGENTS.md +51 -0
  140. package/ui/architecture.md +390 -0
  141. package/ui/components.json +20 -0
  142. package/ui/eslint.config.js +152 -0
  143. package/ui/features/base.ts +2 -0
  144. package/ui/features/boot.feature +5 -0
  145. package/ui/features/steps/authentication.ts +34 -0
  146. package/ui/features/steps/navigaton.ts +37 -0
  147. package/ui/features/steps/typing.ts +24 -0
  148. package/ui/package-lock.json +8173 -0
  149. package/ui/package.json +76 -0
  150. package/ui/playwright.config.ts +13 -0
  151. package/ui/skills-lock.json +30 -0
  152. package/ui/src/@/configuration/index.ts +1 -0
  153. package/ui/src/@/configuration/svc/create.ts +29 -0
  154. package/ui/src/@/configuration/svc/index.ts +3 -0
  155. package/ui/src/@/configuration/svc/net/Configuration.ts +18 -0
  156. package/ui/src/@/configuration/svc/net/index.ts +2 -0
  157. package/ui/src/@/configuration/svc/net/interface.ts +35 -0
  158. package/ui/src/@/configuration/svc/store.ts +14 -0
  159. package/ui/src/@/configuration/ui/Configurations.svelte +85 -0
  160. package/ui/src/@/configuration/ui/Configurations.ts +5 -0
  161. package/ui/src/@/configuration/ui/Create.svelte +64 -0
  162. package/ui/src/@/configuration/ui/Create.ts +7 -0
  163. package/ui/src/@/configuration/ui/Form.svelte +75 -0
  164. package/ui/src/@/configuration/ui/Form.ts +79 -0
  165. package/ui/src/@/configuration/ui/Row.svelte +44 -0
  166. package/ui/src/@/configuration/ui/Row.ts +9 -0
  167. package/ui/src/@/configuration/ui/Value.svelte +33 -0
  168. package/ui/src/@/configuration/ui/Value.ts +6 -0
  169. package/ui/src/@/configuration/ui/index.ts +9 -0
  170. package/ui/src/@/configuration/ui/intl/built.js +38 -0
  171. package/ui/src/@/configuration/ui/intl/context.yaml +51 -0
  172. package/ui/src/@/configuration/ui/intl/en-US.yaml +21 -0
  173. package/ui/src/@/configuration/ui/intl/index.ts +9 -0
  174. package/ui/src/@/configuration/ui/intl/types.ts +31 -0
  175. package/ui/src/@/configuration/ui/read.test.ts +75 -0
  176. package/ui/src/@/configuration/ui/read.ts +102 -0
  177. package/ui/src/@/configuration/ui/ui.test.ts +69 -0
  178. package/ui/src/@/configuration/ui/ui.ts +115 -0
  179. package/ui/src/@/iam/index.ts +1 -0
  180. package/ui/src/@/iam/rc.ts +22 -0
  181. package/ui/src/@/iam/svc/authenticated.ts +17 -0
  182. package/ui/src/@/iam/svc/basic.ts +23 -0
  183. package/ui/src/@/iam/svc/index.ts +10 -0
  184. package/ui/src/@/iam/svc/logout.ts +5 -0
  185. package/ui/src/@/iam/svc/named.ts +16 -0
  186. package/ui/src/@/iam/svc/net/Echo.ts +9 -0
  187. package/ui/src/@/iam/svc/net/basic/index.ts +1 -0
  188. package/ui/src/@/iam/svc/net/basic/interface.ts +15 -0
  189. package/ui/src/@/iam/svc/net/federation/index.ts +1 -0
  190. package/ui/src/@/iam/svc/net/federation/interface.ts +12 -0
  191. package/ui/src/@/iam/svc/net/index.ts +6 -0
  192. package/ui/src/@/iam/svc/net/interface.ts +17 -0
  193. package/ui/src/@/iam/svc/net/otp/index.ts +1 -0
  194. package/ui/src/@/iam/svc/net/otp/interface.ts +14 -0
  195. package/ui/src/@/iam/svc/net/passkeys/index.ts +1 -0
  196. package/ui/src/@/iam/svc/net/passkeys/interface.ts +12 -0
  197. package/ui/src/@/iam/svc/oidc/apple.ts +47 -0
  198. package/ui/src/@/iam/svc/oidc/authenticate.ts +62 -0
  199. package/ui/src/@/iam/svc/oidc/google.ts +45 -0
  200. package/ui/src/@/iam/svc/oidc/hello.ts +82 -0
  201. package/ui/src/@/iam/svc/oidc/index.ts +3 -0
  202. package/ui/src/@/iam/svc/oidc/nonce.ts +5 -0
  203. package/ui/src/@/iam/svc/oidc/providers.ts +28 -0
  204. package/ui/src/@/iam/svc/oidc/standard.ts +28 -0
  205. package/ui/src/@/iam/svc/otp.ts +18 -0
  206. package/ui/src/@/iam/svc/passkeys/create.ts +20 -0
  207. package/ui/src/@/iam/svc/passkeys/index.ts +2 -0
  208. package/ui/src/@/iam/svc/passkeys/login.ts +21 -0
  209. package/ui/src/@/iam/svc/store.ts +36 -0
  210. package/ui/src/@/iam/svc/sync.ts +18 -0
  211. package/ui/src/@/iam/svc/transfer.ts +11 -0
  212. package/ui/src/@/iam/svc/update.ts +8 -0
  213. package/ui/src/@/iam/ui/AccountLike.ts +4 -0
  214. package/ui/src/@/iam/ui/Authenticated.svelte +37 -0
  215. package/ui/src/@/iam/ui/Authenticated.ts +10 -0
  216. package/ui/src/@/iam/ui/Authentication.svelte +50 -0
  217. package/ui/src/@/iam/ui/Authentication.ts +9 -0
  218. package/ui/src/@/iam/ui/Authorized.svelte +32 -0
  219. package/ui/src/@/iam/ui/Authorized.ts +65 -0
  220. package/ui/src/@/iam/ui/Card.svelte +14 -0
  221. package/ui/src/@/iam/ui/Card.ts +7 -0
  222. package/ui/src/@/iam/ui/Refresh.svelte +39 -0
  223. package/ui/src/@/iam/ui/credentials/Credentials.svelte +26 -0
  224. package/ui/src/@/iam/ui/credentials/Credentials.ts +5 -0
  225. package/ui/src/@/iam/ui/credentials/Provider.svelte +24 -0
  226. package/ui/src/@/iam/ui/credentials/Provider.ts +5 -0
  227. package/ui/src/@/iam/ui/credentials/index.ts +1 -0
  228. package/ui/src/@/iam/ui/credentials/passkeys/Key.svelte +42 -0
  229. package/ui/src/@/iam/ui/credentials/passkeys/Key.ts +29 -0
  230. package/ui/src/@/iam/ui/credentials/passkeys/Manager.svelte +83 -0
  231. package/ui/src/@/iam/ui/credentials/passkeys/Manager.ts +5 -0
  232. package/ui/src/@/iam/ui/credentials/passkeys/Passkeys.svelte +39 -0
  233. package/ui/src/@/iam/ui/credentials/passkeys/Summary.svelte +27 -0
  234. package/ui/src/@/iam/ui/credentials/passkeys/Summary.ts +5 -0
  235. package/ui/src/@/iam/ui/credentials/passkeys/index.ts +1 -0
  236. package/ui/src/@/iam/ui/credentials/providers.ts +15 -0
  237. package/ui/src/@/iam/ui/credentials/transfer/Qr.svelte +24 -0
  238. package/ui/src/@/iam/ui/credentials/transfer/Qr.ts +3 -0
  239. package/ui/src/@/iam/ui/credentials/transfer/Transfer.svelte +48 -0
  240. package/ui/src/@/iam/ui/credentials/transfer/Transfer.ts +5 -0
  241. package/ui/src/@/iam/ui/credentials/transfer/index.ts +1 -0
  242. package/ui/src/@/iam/ui/index.ts +3 -0
  243. package/ui/src/@/iam/ui/intl/built.js +79 -0
  244. package/ui/src/@/iam/ui/intl/context.yaml +91 -0
  245. package/ui/src/@/iam/ui/intl/en-US.yaml +64 -0
  246. package/ui/src/@/iam/ui/intl/index.ts +10 -0
  247. package/ui/src/@/iam/ui/intl/types.ts +70 -0
  248. package/ui/src/@/iam/ui/oidc/Authentication.svelte +16 -0
  249. package/ui/src/@/iam/ui/oidc/Authentication.ts +5 -0
  250. package/ui/src/@/iam/ui/oidc/Button.svelte +36 -0
  251. package/ui/src/@/iam/ui/oidc/Button.ts +11 -0
  252. package/ui/src/@/iam/ui/oidc/Refresh.svelte +16 -0
  253. package/ui/src/@/iam/ui/oidc/icons/Apple.svelte +19 -0
  254. package/ui/src/@/iam/ui/oidc/icons/Google.svelte +31 -0
  255. package/ui/src/@/iam/ui/oidc/icons/index.ts +11 -0
  256. package/ui/src/@/iam/ui/oidc/index.ts +2 -0
  257. package/ui/src/@/iam/ui/passkey/Authentication.svelte +64 -0
  258. package/ui/src/@/iam/ui/passkey/Authentication.ts +8 -0
  259. package/ui/src/@/iam/ui/passkey/Create.svelte +53 -0
  260. package/ui/src/@/iam/ui/passkey/Create.ts +7 -0
  261. package/ui/src/@/iam/ui/passkey/Login.svelte +29 -0
  262. package/ui/src/@/iam/ui/passkey/Refresh.svelte +29 -0
  263. package/ui/src/@/iam/ui/passkey/index.ts +2 -0
  264. package/ui/src/@/iam/ui/password/Authentication.svelte +19 -0
  265. package/ui/src/@/iam/ui/password/Authentication.ts +8 -0
  266. package/ui/src/@/iam/ui/password/Form.svelte +151 -0
  267. package/ui/src/@/iam/ui/password/Form.ts +6 -0
  268. package/ui/src/@/iam/ui/password/Password.svelte +39 -0
  269. package/ui/src/@/iam/ui/password/Password.ts +6 -0
  270. package/ui/src/@/iam/ui/password/Refresh.svelte +5 -0
  271. package/ui/src/@/iam/ui/password/index.ts +2 -0
  272. package/ui/src/@/net/index.ts +1 -0
  273. package/ui/src/@/net/svc/index.ts +3 -0
  274. package/ui/src/@/net/svc/origin.ts +8 -0
  275. package/ui/src/@/net/svc/query.test.ts +45 -0
  276. package/ui/src/@/net/svc/query.ts +25 -0
  277. package/ui/src/@/passkeys/index.ts +1 -0
  278. package/ui/src/@/passkeys/svc/add.ts +15 -0
  279. package/ui/src/@/passkeys/svc/create.ts +58 -0
  280. package/ui/src/@/passkeys/svc/credentials/convert.ts +32 -0
  281. package/ui/src/@/passkeys/svc/credentials/create.ts +34 -0
  282. package/ui/src/@/passkeys/svc/credentials/get.ts +14 -0
  283. package/ui/src/@/passkeys/svc/credentials/index.ts +3 -0
  284. package/ui/src/@/passkeys/svc/credentials/key.ts +10 -0
  285. package/ui/src/@/passkeys/svc/get.ts +10 -0
  286. package/ui/src/@/passkeys/svc/index.ts +6 -0
  287. package/ui/src/@/passkeys/svc/net/CreationResponse.ts +15 -0
  288. package/ui/src/@/passkeys/svc/net/Passkey.ts +8 -0
  289. package/ui/src/@/passkeys/svc/net/RequestResponse.ts +12 -0
  290. package/ui/src/@/passkeys/svc/net/challenges/Options.ts +21 -0
  291. package/ui/src/@/passkeys/svc/net/challenges/index.ts +2 -0
  292. package/ui/src/@/passkeys/svc/net/challenges/interface.ts +16 -0
  293. package/ui/src/@/passkeys/svc/net/index.ts +4 -0
  294. package/ui/src/@/passkeys/svc/net/interface.ts +29 -0
  295. package/ui/src/@/passkeys/svc/remove.ts +13 -0
  296. package/ui/src/@/passkeys/svc/request.ts +50 -0
  297. package/ui/src/@/passkeys/svc/store.ts +13 -0
  298. package/ui/src/@/passkeys/svc/supported.ts +1 -0
  299. package/ui/src/@/passkeys/ui/aaguid.json +150 -0
  300. package/ui/src/@/realtime/events.ts +1 -0
  301. package/ui/src/@/realtime/index.ts +1 -0
  302. package/ui/src/@/realtime/rc.ts +13 -0
  303. package/ui/src/@/realtime/svc/connect.ts +67 -0
  304. package/ui/src/@/realtime/svc/events.ts +17 -0
  305. package/ui/src/@/realtime/svc/index.ts +5 -0
  306. package/ui/src/@/realtime/svc/net/Message.ts +6 -0
  307. package/ui/src/@/realtime/svc/net/index.ts +2 -0
  308. package/ui/src/@/realtime/svc/net/interface.ts +13 -0
  309. package/ui/src/@/realtime/svc/reset.ts +5 -0
  310. package/ui/src/@/realtime/svc/status.ts +12 -0
  311. package/ui/src/@/realtime/svc/store.ts +30 -0
  312. package/ui/src/@/realtime/svc/time.ts +15 -0
  313. package/ui/src/app.d.ts +20 -0
  314. package/ui/src/app.html +13 -0
  315. package/ui/src/config/index.ts +70 -0
  316. package/ui/src/lib/assets/favicon.svg +1 -0
  317. package/ui/src/lib/components/clipboard/Clipboard.svelte +63 -0
  318. package/ui/src/lib/components/clipboard/Clipboard.ts +12 -0
  319. package/ui/src/lib/components/clipboard/index.ts +1 -0
  320. package/ui/src/lib/components/dismissable/Dismissable.svelte +81 -0
  321. package/ui/src/lib/components/dismissable/Dismissable.ts +7 -0
  322. package/ui/src/lib/components/dismissable/index.ts +1 -0
  323. package/ui/src/lib/components/dropdown/Back.svelte +14 -0
  324. package/ui/src/lib/components/dropdown/Back.ts +3 -0
  325. package/ui/src/lib/components/dropdown/Content.svelte +76 -0
  326. package/ui/src/lib/components/dropdown/Content.ts +13 -0
  327. package/ui/src/lib/components/dropdown/Context.ts +18 -0
  328. package/ui/src/lib/components/dropdown/Group.svelte +24 -0
  329. package/ui/src/lib/components/dropdown/Group.ts +8 -0
  330. package/ui/src/lib/components/dropdown/GroupContext.ts +15 -0
  331. package/ui/src/lib/components/dropdown/Item.svelte +31 -0
  332. package/ui/src/lib/components/dropdown/Item.ts +5 -0
  333. package/ui/src/lib/components/dropdown/Layer.svelte +11 -0
  334. package/ui/src/lib/components/dropdown/Layer.ts +7 -0
  335. package/ui/src/lib/components/dropdown/Root.svelte +88 -0
  336. package/ui/src/lib/components/dropdown/Root.ts +6 -0
  337. package/ui/src/lib/components/dropdown/Separator.svelte +13 -0
  338. package/ui/src/lib/components/dropdown/Separator.ts +5 -0
  339. package/ui/src/lib/components/dropdown/Trigger.svelte +33 -0
  340. package/ui/src/lib/components/dropdown/Trigger.ts +5 -0
  341. package/ui/src/lib/components/dropdown/index.ts +8 -0
  342. package/ui/src/lib/components/fullscreen/Fullscreen.svelte +97 -0
  343. package/ui/src/lib/components/fullscreen/Fullscreen.ts +18 -0
  344. package/ui/src/lib/components/fullscreen/Overlay.svelte +15 -0
  345. package/ui/src/lib/components/fullscreen/Overlay.ts +7 -0
  346. package/ui/src/lib/components/fullscreen/index.ts +2 -0
  347. package/ui/src/lib/components/hold/Hold.svelte +133 -0
  348. package/ui/src/lib/components/hold/Hold.ts +23 -0
  349. package/ui/src/lib/components/hold/index.ts +1 -0
  350. package/ui/src/lib/components/scrollable/Scrollable.svelte +49 -0
  351. package/ui/src/lib/components/scrollable/Scrollable.ts +117 -0
  352. package/ui/src/lib/components/scrollable/index.ts +2 -0
  353. package/ui/src/lib/components/shake/Shake.svelte +62 -0
  354. package/ui/src/lib/components/shake/Shake.ts +7 -0
  355. package/ui/src/lib/components/shake/index.ts +1 -0
  356. package/ui/src/lib/components/share/Share.svelte +58 -0
  357. package/ui/src/lib/components/share/Share.ts +9 -0
  358. package/ui/src/lib/components/share/index.ts +1 -0
  359. package/ui/src/lib/components/shell/Attention.svelte +11 -0
  360. package/ui/src/lib/components/shell/Attention.ts +6 -0
  361. package/ui/src/lib/components/shell/Header.svelte +18 -0
  362. package/ui/src/lib/components/shell/Header.ts +7 -0
  363. package/ui/src/lib/components/shell/Screen.svelte +28 -0
  364. package/ui/src/lib/components/shell/Screen.ts +11 -0
  365. package/ui/src/lib/components/shell/Sticky.svelte +23 -0
  366. package/ui/src/lib/components/shell/Sticky.ts +8 -0
  367. package/ui/src/lib/components/shell/Underlay.svelte +21 -0
  368. package/ui/src/lib/components/shell/Underlay.ts +6 -0
  369. package/ui/src/lib/components/shell/index.ts +6 -0
  370. package/ui/src/lib/components/shell/nav/Actions.svelte +31 -0
  371. package/ui/src/lib/components/shell/nav/Actions.ts +16 -0
  372. package/ui/src/lib/components/shell/nav/Back.svelte +20 -0
  373. package/ui/src/lib/components/shell/nav/Back.ts +9 -0
  374. package/ui/src/lib/components/shell/nav/Bar.svelte +24 -0
  375. package/ui/src/lib/components/shell/nav/Bar.ts +3 -0
  376. package/ui/src/lib/components/shell/nav/Button.svelte +64 -0
  377. package/ui/src/lib/components/shell/nav/Button.ts +7 -0
  378. package/ui/src/lib/components/shell/nav/Nav.svelte +62 -0
  379. package/ui/src/lib/components/shell/nav/Nav.ts +35 -0
  380. package/ui/src/lib/components/shell/nav/Return.svelte +29 -0
  381. package/ui/src/lib/components/shell/nav/Return.ts +15 -0
  382. package/ui/src/lib/components/shell/nav/Sections.svelte +58 -0
  383. package/ui/src/lib/components/shell/nav/Sections.ts +6 -0
  384. package/ui/src/lib/components/shell/nav/Toolbar.svelte +73 -0
  385. package/ui/src/lib/components/shell/nav/Toolbar.ts +3 -0
  386. package/ui/src/lib/components/shell/nav/history.ts +36 -0
  387. package/ui/src/lib/components/shell/nav/index.ts +5 -0
  388. package/ui/src/lib/components/shell/nav/store.ts +24 -0
  389. package/ui/src/lib/components/ui/alert/alert-action.svelte +20 -0
  390. package/ui/src/lib/components/ui/alert/alert-description.svelte +23 -0
  391. package/ui/src/lib/components/ui/alert/alert-title.svelte +23 -0
  392. package/ui/src/lib/components/ui/alert/alert.svelte +43 -0
  393. package/ui/src/lib/components/ui/alert/index.ts +17 -0
  394. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +27 -0
  395. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +27 -0
  396. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte +32 -0
  397. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte +17 -0
  398. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte +23 -0
  399. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
  400. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte +20 -0
  401. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte +17 -0
  402. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte +7 -0
  403. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte +17 -0
  404. package/ui/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte +7 -0
  405. package/ui/src/lib/components/ui/alert-dialog/alert-dialog.svelte +7 -0
  406. package/ui/src/lib/components/ui/alert-dialog/index.ts +40 -0
  407. package/ui/src/lib/components/ui/badge/badge.svelte +49 -0
  408. package/ui/src/lib/components/ui/badge/index.ts +2 -0
  409. package/ui/src/lib/components/ui/button/button.svelte +82 -0
  410. package/ui/src/lib/components/ui/button/index.ts +17 -0
  411. package/ui/src/lib/components/ui/button-group/button-group-separator.svelte +23 -0
  412. package/ui/src/lib/components/ui/button-group/button-group-text.svelte +28 -0
  413. package/ui/src/lib/components/ui/button-group/button-group.svelte +46 -0
  414. package/ui/src/lib/components/ui/button-group/index.ts +15 -0
  415. package/ui/src/lib/components/ui/card/card-action.svelte +23 -0
  416. package/ui/src/lib/components/ui/card/card-content.svelte +20 -0
  417. package/ui/src/lib/components/ui/card/card-description.svelte +20 -0
  418. package/ui/src/lib/components/ui/card/card-footer.svelte +20 -0
  419. package/ui/src/lib/components/ui/card/card-header.svelte +23 -0
  420. package/ui/src/lib/components/ui/card/card-title.svelte +20 -0
  421. package/ui/src/lib/components/ui/card/card.svelte +22 -0
  422. package/ui/src/lib/components/ui/card/index.ts +25 -0
  423. package/ui/src/lib/components/ui/checkbox/checkbox.svelte +39 -0
  424. package/ui/src/lib/components/ui/checkbox/index.ts +6 -0
  425. package/ui/src/lib/components/ui/collapsible/collapsible-content.svelte +7 -0
  426. package/ui/src/lib/components/ui/collapsible/collapsible-trigger.svelte +7 -0
  427. package/ui/src/lib/components/ui/collapsible/collapsible.svelte +20 -0
  428. package/ui/src/lib/components/ui/collapsible/index.ts +13 -0
  429. package/ui/src/lib/components/ui/input/index.ts +7 -0
  430. package/ui/src/lib/components/ui/input/input.svelte +48 -0
  431. package/ui/src/lib/components/ui/input-otp/index.ts +15 -0
  432. package/ui/src/lib/components/ui/input-otp/input-otp-group.svelte +20 -0
  433. package/ui/src/lib/components/ui/input-otp/input-otp-separator.svelte +27 -0
  434. package/ui/src/lib/components/ui/input-otp/input-otp-slot.svelte +31 -0
  435. package/ui/src/lib/components/ui/input-otp/input-otp.svelte +23 -0
  436. package/ui/src/lib/components/ui/item/index.ts +34 -0
  437. package/ui/src/lib/components/ui/item/item-actions.svelte +20 -0
  438. package/ui/src/lib/components/ui/item/item-content.svelte +23 -0
  439. package/ui/src/lib/components/ui/item/item-description.svelte +23 -0
  440. package/ui/src/lib/components/ui/item/item-footer.svelte +20 -0
  441. package/ui/src/lib/components/ui/item/item-group.svelte +21 -0
  442. package/ui/src/lib/components/ui/item/item-header.svelte +20 -0
  443. package/ui/src/lib/components/ui/item/item-media.svelte +42 -0
  444. package/ui/src/lib/components/ui/item/item-separator.svelte +19 -0
  445. package/ui/src/lib/components/ui/item/item-title.svelte +20 -0
  446. package/ui/src/lib/components/ui/item/item.svelte +61 -0
  447. package/ui/src/lib/components/ui/kbd/index.ts +10 -0
  448. package/ui/src/lib/components/ui/kbd/kbd-group.svelte +20 -0
  449. package/ui/src/lib/components/ui/kbd/kbd.svelte +23 -0
  450. package/ui/src/lib/components/ui/label/index.ts +7 -0
  451. package/ui/src/lib/components/ui/label/label.svelte +20 -0
  452. package/ui/src/lib/components/ui/progress/index.ts +7 -0
  453. package/ui/src/lib/components/ui/progress/progress.svelte +27 -0
  454. package/ui/src/lib/components/ui/select/index.ts +37 -0
  455. package/ui/src/lib/components/ui/select/select-content.svelte +45 -0
  456. package/ui/src/lib/components/ui/select/select-group-heading.svelte +21 -0
  457. package/ui/src/lib/components/ui/select/select-group.svelte +17 -0
  458. package/ui/src/lib/components/ui/select/select-item.svelte +40 -0
  459. package/ui/src/lib/components/ui/select/select-label.svelte +20 -0
  460. package/ui/src/lib/components/ui/select/select-portal.svelte +7 -0
  461. package/ui/src/lib/components/ui/select/select-scroll-down-button.svelte +20 -0
  462. package/ui/src/lib/components/ui/select/select-scroll-up-button.svelte +20 -0
  463. package/ui/src/lib/components/ui/select/select-separator.svelte +18 -0
  464. package/ui/src/lib/components/ui/select/select-trigger.svelte +29 -0
  465. package/ui/src/lib/components/ui/select/select.svelte +11 -0
  466. package/ui/src/lib/components/ui/separator/index.ts +7 -0
  467. package/ui/src/lib/components/ui/separator/separator.svelte +23 -0
  468. package/ui/src/lib/components/ui/spinner/index.ts +1 -0
  469. package/ui/src/lib/components/ui/spinner/spinner.svelte +18 -0
  470. package/ui/src/lib/components/ui/tabs/index.ts +18 -0
  471. package/ui/src/lib/components/ui/tabs/tabs-content.svelte +17 -0
  472. package/ui/src/lib/components/ui/tabs/tabs-list.svelte +40 -0
  473. package/ui/src/lib/components/ui/tabs/tabs-trigger.svelte +23 -0
  474. package/ui/src/lib/components/ui/tabs/tabs.svelte +19 -0
  475. package/ui/src/lib/components/ui/textarea/index.ts +7 -0
  476. package/ui/src/lib/components/ui/textarea/textarea.svelte +22 -0
  477. package/ui/src/lib/intl/bcp.ts +25 -0
  478. package/ui/src/lib/intl/built.js +18 -0
  479. package/ui/src/lib/intl/context.yaml +18 -0
  480. package/ui/src/lib/intl/en-US.yaml +6 -0
  481. package/ui/src/lib/intl/index.ts +65 -0
  482. package/ui/src/lib/intl/types.ts +19 -0
  483. package/ui/src/lib/tools/ago.ts +10 -0
  484. package/ui/src/lib/tools/assert.ts +3 -0
  485. package/ui/src/lib/tools/cap.ts +5 -0
  486. package/ui/src/lib/tools/clicks.ts +25 -0
  487. package/ui/src/lib/tools/contextmenu.ts +19 -0
  488. package/ui/src/lib/tools/convert.ts +32 -0
  489. package/ui/src/lib/tools/currency.test.ts +10 -0
  490. package/ui/src/lib/tools/currency.ts +55 -0
  491. package/ui/src/lib/tools/date.test.ts +21 -0
  492. package/ui/src/lib/tools/date.ts +35 -0
  493. package/ui/src/lib/tools/delay.ts +7 -0
  494. package/ui/src/lib/tools/image.ts +39 -0
  495. package/ui/src/lib/tools/index.ts +20 -0
  496. package/ui/src/lib/tools/location.ts +41 -0
  497. package/ui/src/lib/tools/metronome.ts +11 -0
  498. package/ui/src/lib/tools/mq.ts +84 -0
  499. package/ui/src/lib/tools/onsubmit.ts +21 -0
  500. package/ui/src/lib/tools/random.ts +15 -0
  501. package/ui/src/lib/tools/search.ts +25 -0
  502. package/ui/src/lib/tools/timeout.ts +26 -0
  503. package/ui/src/lib/tools/transition.ts +207 -0
  504. package/ui/src/lib/tools/types.ts +3 -0
  505. package/ui/src/lib/tools/uuid.test.ts +28 -0
  506. package/ui/src/lib/tools/uuid.ts +9 -0
  507. package/ui/src/lib/typeset.css +502 -0
  508. package/ui/src/lib/utils.ts +12 -0
  509. package/ui/src/routes/(private)/+layout.svelte +112 -0
  510. package/ui/src/routes/(private)/+page.svelte +7 -0
  511. package/ui/src/routes/(private)/[component]/+page.svelte +77 -0
  512. package/ui/src/routes/+layout.svelte +25 -0
  513. package/ui/src/routes/+layout.ts +14 -0
  514. package/ui/src/routes/layout.css +232 -0
  515. package/ui/static/robots.txt +3 -0
  516. package/ui/svelte.config.js +36 -0
  517. package/ui/tools/feat.js +43 -0
  518. package/ui/tools/hooks/README.md +13 -0
  519. package/ui/tools/hooks/guard-intl.sh +40 -0
  520. package/ui/tools/shad.js +7 -0
  521. package/ui/tsconfig.json +20 -0
  522. package/ui/vite.config.ts +8 -0
@@ -0,0 +1,32 @@
1
+ export function base64urlToUint8Array(base64Url: string): Uint8Array {
2
+ const padding = '='.repeat((4 - (base64Url.length % 4)) % 4)
3
+ const base64 = (base64Url + padding).replace(/-/g, '+').replace(/_/g, '/')
4
+ const rawData = atob(base64)
5
+
6
+ return new Uint8Array([...rawData].map((char) => char.charCodeAt(0)))
7
+ }
8
+
9
+ export function stringToUint8Array(str: string): Uint8Array {
10
+ return new TextEncoder().encode(str)
11
+ }
12
+
13
+ export function arrayBufferToBase64(buffer: ArrayBuffer): string {
14
+ return btoa(String.fromCharCode(...new Uint8Array(buffer)))
15
+ }
16
+
17
+ export function bufferToBase64url(buffer: ArrayBuffer): string {
18
+ return arrayBufferToBase64(buffer)
19
+ .replace(/\+/g, '-')
20
+ .replace(/\//g, '_')
21
+ .replace(/=+$/, '')
22
+ }
23
+
24
+ export function toBase64Url(string: string): string {
25
+ return btoa(string).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
26
+ }
27
+
28
+ export function fromBase64Url(base64Url: string): string {
29
+ const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
30
+
31
+ return atob(base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '='))
32
+ }
@@ -0,0 +1,10 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { unit } from './currency'
3
+
4
+ describe('unit', () => {
5
+ it('converts major units to cents as integer', () => {
6
+ expect(unit(18.6, 'en-US')).toBe(1860)
7
+ expect(unit(0.1, 'en-US')).toBe(10)
8
+ expect(unit(0.01, 'en-US')).toBe(1)
9
+ })
10
+ })
@@ -0,0 +1,55 @@
1
+ import type { Locale } from './types'
2
+
3
+ /**
4
+ * Formats a balance value expressed in the currency's ISO 4217 smallest unit
5
+ * (e.g., cents for USD, yen for JPY) into a properly formatted currency string.
6
+ *
7
+ * @param amount - The balance value in the currency's smallest unit (integer)
8
+ * @param locale - Locale for formatting
9
+ * @param currency - Optional ISO 4217 currency code (e.g., 'USD', 'EUR', 'JPY').
10
+ * @returns Formatted currency string (e.g., "$1.00", "€1.00", "¥100")
11
+ */
12
+ export function currency(amount: number, locale: Locale, currency?: string): string {
13
+ if (currency === undefined) {
14
+ const value = amount / 100
15
+ const precision = value > 500 ? 0 : 2
16
+
17
+ return Number.isInteger(value) ? value.toString() : value.toFixed(precision)
18
+ }
19
+
20
+ const formatter = new Intl.NumberFormat(locale, {
21
+ style: 'currency',
22
+ currency,
23
+ })
24
+
25
+ const options = formatter.resolvedOptions()
26
+ const decimalPlaces = options.minimumFractionDigits ?? 2
27
+ const divisor = Math.pow(10, decimalPlaces)
28
+ const majorUnit = amount / divisor
29
+
30
+ return formatter.format(majorUnit)
31
+ }
32
+
33
+ /**
34
+ * Converts a currency value expressed in the currency's ISO 4217 smallest unit
35
+ * (e.g., cents for USD, yen for JPY) into a number.
36
+ *
37
+ * @param amount - The currency value in the currency's smallest unit (integer)
38
+ * @param locale - Locale for formatting
39
+ * @param currency - Optional ISO 4217 currency code (e.g., 'USD', 'EUR', 'JPY'). Defaults to 'USD'
40
+ * @returns Number value (e.g., 100 for $1.00, 10000 for ¥100)
41
+ */
42
+ export function unit(amount: number, locale: Locale, currency?: string): number {
43
+ if (currency === undefined) return Math.round(amount * 100)
44
+
45
+ const tempFormatter = new Intl.NumberFormat(locale, {
46
+ style: 'currency',
47
+ currency,
48
+ })
49
+
50
+ const options = tempFormatter.resolvedOptions()
51
+ const decimalPlaces = options.minimumFractionDigits ?? 2
52
+ const divisor = Math.pow(10, decimalPlaces)
53
+
54
+ return Math.round(amount * divisor)
55
+ }
@@ -0,0 +1,21 @@
1
+ import { describe, it, expect, vi, afterEach } from 'vitest'
2
+ import { date, formatISODuration } from './date'
3
+
4
+ describe('date', () => {
5
+ afterEach(() => { vi.useRealTimers() })
6
+
7
+ it('carries the year only outside the current one', () => {
8
+ vi.useFakeTimers().setSystemTime(new Date('2026-08-05'))
9
+
10
+ expect(date('2026-02-17', 'en-US')).toBe('Feb 17')
11
+ expect(date('2024-02-17', 'en-US')).toBe('Feb 17, 2024')
12
+ })
13
+ })
14
+
15
+ describe('formatISODuration', () => {
16
+ it('formats ISO duration', () => {
17
+ expect(formatISODuration('P1Y', 'en-US')).toBe('1 year')
18
+ expect(formatISODuration('P1W', 'en-US')).toBe('1 week')
19
+ expect(formatISODuration('P1M', 'ru-RU')).toBe('1 месяц')
20
+ })
21
+ })
@@ -0,0 +1,35 @@
1
+ import type { Locale } from './types'
2
+
3
+ /**
4
+ * Formats a date into a short localized representation, carrying the year only when the date
5
+ * falls outside the current one (e.g., "Feb 17" this year, "Feb 17, 2024" earlier).
6
+ *
7
+ * @param value - ISO date string or Date
8
+ * @param locale - Locale for formatting
9
+ * @returns Formatted date string
10
+ */
11
+ export function date(value: string | Date | number, locale: Locale): string {
12
+ const d = new Date(value)
13
+ const year = d.getFullYear() === new Date().getFullYear() ? undefined : 'numeric'
14
+
15
+ return new Intl.DateTimeFormat(locale, { year, month: 'short', day: 'numeric' }).format(d)
16
+ }
17
+
18
+ /**
19
+ * Formats an ISO duration string into a localized representation (e.g., "1 year", "1 month").
20
+ *
21
+ * @param iso - ISO duration string
22
+ * @param locale - Locale for formatting
23
+ * @returns Formatted duration string
24
+ */
25
+ export function formatISODuration(iso: string, locale: Locale): string {
26
+ const match = iso.match(/^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/)
27
+
28
+ if (match === null) return iso
29
+
30
+ const [, y, mo, w, d, h, mi, s] = match.map((v) => Number.isNaN(Number(v)) ? undefined : Number(v))
31
+
32
+ // @ts-ignore Intl.DurationFormat — Stage 3 proposal, available at runtime in modern engines
33
+ return new Intl.DurationFormat(locale, { style: 'long' })
34
+ .format({ years: y, months: mo, weeks: w, days: d, hours: h, minutes: mi, seconds: s })
35
+ }
@@ -0,0 +1,7 @@
1
+ export function delay<T>(fn: () => Promise<T> | T, duration: number): Promise<T> {
2
+ return new Promise((resolve) =>
3
+ setTimeout(async () => {
4
+ resolve(await fn())
5
+ }, duration),
6
+ )
7
+ }
@@ -0,0 +1,39 @@
1
+ export type DensityMap = Record<`${number}x`, string>
2
+
3
+ /**
4
+ * Preload the best-matching image for current pixel density.
5
+ *
6
+ * Picks the smallest density `>=` `devicePixelRatio`, or the highest available.
7
+ *
8
+ * @param assets - {@link DensityMap}
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * preload({ '1x': '/img/bg.webp', '2x': '/img/bg@2x.webp' })
13
+ * ```
14
+ */
15
+ export function preload(assets: DensityMap) {
16
+ const densities = Object.keys(assets)
17
+ .map((key) => parseFloat(key))
18
+ .sort((a, b) => a - b)
19
+
20
+ const match = densities.find((d) => d >= devicePixelRatio) ?? densities.at(-1)!
21
+
22
+ new Image().src = assets[`${match}x`]
23
+ }
24
+
25
+ /**
26
+ * Build a CSS `image-set()` value from a density map.
27
+ *
28
+ * @param assets - {@link DensityMap}
29
+ * @returns CSS `image-set(…)` string for use in `background-image`.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * imageSet({ '1x': '/img/bg.webp', '2x': '/img/bg@2x.webp' })
34
+ * // → "image-set(url('/img/bg.webp') 1x, url('/img/bg@2x.webp') 2x)"
35
+ * ```
36
+ */
37
+ export function imageSet(assets: DensityMap) {
38
+ return `image-set(${Object.entries(assets).map(([density, url]) => `url('${url}') ${density}`).join(', ')})`
39
+ }
@@ -0,0 +1,20 @@
1
+ export { onsubmit } from './onsubmit'
2
+ export { assert } from './assert'
3
+ export { transit, navigate, takeoff, transition, styles } from './transition'
4
+ export { fragment, query, inAppPopOut } from './location'
5
+ export { timeout } from './timeout'
6
+ export * as convert from './convert'
7
+ export * from './mq'
8
+ export { deterministic } from './random'
9
+ export { currency, unit } from './currency'
10
+ export { date, formatISODuration } from './date'
11
+ export { search } from './search'
12
+ export * from './types'
13
+ export { delay } from './delay'
14
+ export { metronome } from './metronome'
15
+ export { expire, cap } from './cap'
16
+ export { clicks } from './clicks'
17
+ export { ago } from './ago'
18
+ export { suppressContextMenu } from './contextmenu'
19
+ export * as image from './image'
20
+ export { toUuid } from './uuid'
@@ -0,0 +1,41 @@
1
+ import { apple, inApp } from './mq'
2
+
3
+ const hash: URLSearchParams = new URLSearchParams()
4
+ const search: URLSearchParams = new URLSearchParams()
5
+
6
+ export function fragment(name: string): string | null {
7
+ return hash.get(name)
8
+ }
9
+
10
+ export function query(name: string): string | null {
11
+ return search.get(name)
12
+ }
13
+
14
+ // function debug() {
15
+ // if (hash.size > 0)
16
+ // console.debug('Hash', Object.fromEntries(hash.entries()))
17
+
18
+ // if (search.size > 0)
19
+ // console.debug('Search', Object.fromEntries(search.entries()))
20
+ // }
21
+
22
+ // if (typeof window !== 'undefined') (() => {
23
+ // hash = new URLSearchParams(window.location.hash.slice(1))
24
+ // search = new URLSearchParams(window.location.search.slice(1))
25
+
26
+ // if (dev)
27
+ // debug()
28
+
29
+ // // window.history.replaceState({}, '', window.location.pathname)
30
+ // })()
31
+
32
+ export function inAppPopOut() {
33
+ if (!inApp) return
34
+
35
+ const url = window.location.href
36
+
37
+ if (apple)
38
+ window.location.href = `x-safari-${url}`
39
+ else
40
+ window.location.href = `intent://${url.replace(/^https?:\/\//, '')}#Intent;scheme=https;action=android.intent.action.VIEW;category=android.intent.category.BROWSABLE;end`
41
+ }
@@ -0,0 +1,11 @@
1
+ import { readable } from 'svelte/store'
2
+
3
+ function metronome(interval = 1000) {
4
+ return readable(Date.now(), (set) => {
5
+ const id = setInterval(() => set(Date.now()), interval)
6
+
7
+ return () => clearInterval(id)
8
+ })
9
+ }
10
+
11
+ export { metronome }
@@ -0,0 +1,84 @@
1
+ import { browser } from '$app/environment'
2
+
3
+ export const windows = browser && navigator.userAgent.toLowerCase().includes('windows')
4
+
5
+ export const apple = browser
6
+ ? /mac ?os|ios|ipad ?os/i.test((navigator as any).userAgentData?.platform ?? '') ||
7
+ /(Mac|iPhone|iPad|iPod)/.test(navigator.userAgent)
8
+ : false
9
+
10
+ export const android = browser ? /android/i.test(navigator.userAgent) : false
11
+
12
+ export const ios = browser ? /(iPhone|iPad|iPod)/.test(navigator.userAgent) : false
13
+
14
+ export const safari = browser ? /^((?!chrome|android).)*safari/i.test(navigator.userAgent) : false
15
+
16
+ export const touch = browser ? 'ontouchstart' in window : false
17
+
18
+ export const standalone = browser ? window.matchMedia('(display-mode: standalone)').matches : false
19
+
20
+ export const shell = browser ? /PWAShell/i.test(navigator.userAgent) : false
21
+
22
+ // PWAShell/<version>
23
+ export const shellVersion = navigator.userAgent.match(/PWAShell\/(\S+)/)?.[1] ?? null
24
+
25
+ // do not autofocus on touch devices, as it's annoying
26
+ export const autofocus = browser ? !('ontouchstart' in window) : false
27
+
28
+ export const units = {
29
+ lbs: ['en-US', 'en-LR', 'en-MM'].includes(navigator.language),
30
+ inches: ['en-US', 'en-GB', 'en-CA', 'en-AU', 'en-NZ', 'en-IE', 'en-IN', 'en-LR', 'en-MM'].includes(navigator.language),
31
+ } as const
32
+
33
+ export function isInAppWebView(ua: string = navigator.userAgent): boolean {
34
+ const inAppBrowserPatterns = [
35
+ /FBAN|FBAV|FB_IAB/i, // Facebook
36
+ /Instagram/i, // Instagram
37
+ /Twitter/i, // Twitter
38
+ /Line/i, // LINE Messenger
39
+ /LinkedIn/i, // LinkedIn
40
+ /Snapchat/i, // Snapchat
41
+ /WhatsApp/i, // WhatsApp
42
+ /WeChat/i, // WeChat
43
+ /Messenger/i, // Facebook Messenger
44
+ /QQ/i, // QQ Browser
45
+ /Reddit/i, // Reddit
46
+ /Puffin/i, // Puffin Browser
47
+ /TikTok/i, // TikTok
48
+ /musical.ly/i, // TikTok (older)
49
+ /YouTube/i, // YouTube
50
+ /Pinterest/i, // Pinterest
51
+ /Discord/i, // Discord
52
+ /Telegram/i, // Telegram
53
+ /Viber/i, // Viber
54
+ /Slack/i, // Slack
55
+ /Signal/i, // Signal
56
+ /KakaoTalk/i, // KakaoTalk (Popular in South Korea)
57
+ /Baidu/i, // Baidu (Popular in China)
58
+ ]
59
+
60
+ const isInAppBrowser = () => inAppBrowserPatterns.some((pattern) => pattern.test(ua))
61
+
62
+ const isGenericWebView = () => {
63
+ const rules = [
64
+ 'WebView', // Generic WebView detection
65
+ '(iPhone|iPod|iPad)(?!.*Safari/)', // iOS WebView without Safari
66
+ 'Android.*(wv)', // Android WebView
67
+ '(AppleWebKit)(?!.*Safari)', // iOS Safari WebView (missing Safari in UA)
68
+ ]
69
+
70
+ const regex = new RegExp(`(${rules.join('|')})`, 'ig')
71
+
72
+ return ua.match(regex) !== null
73
+ }
74
+
75
+ const isTelegram = () => (
76
+ 'TelegramWebviewProxy' in window ||
77
+ 'TelegramWebviewProxyProto' in window ||
78
+ 'TelegramWebview' in window
79
+ )
80
+
81
+ return browser && (isInAppBrowser() || isGenericWebView() || isTelegram())
82
+ }
83
+
84
+ export const inApp = isInAppWebView(navigator.userAgent)
@@ -0,0 +1,21 @@
1
+ export function onsubmit(callback: Callback) {
2
+ return async (event: Event) => {
3
+ event.preventDefault()
4
+
5
+ const form = event.target as HTMLFormElement
6
+ const fieldsets = form.querySelectorAll('fieldset') as NodeListOf<HTMLFieldSetElement>
7
+ const disabled: HTMLFieldSetElement[] = []
8
+
9
+ for (const fieldset of fieldsets) {
10
+ fieldset.disabled = true
11
+ disabled.push(fieldset)
12
+ }
13
+
14
+ await callback(event)
15
+
16
+ for (const fieldset of disabled)
17
+ fieldset.disabled = false
18
+ }
19
+ }
20
+
21
+ type Callback = (event: Event) => Promise<void> | void
@@ -0,0 +1,15 @@
1
+ export function deterministic(id: string, max: number): number {
2
+ if (max <= 0) return 0
3
+
4
+ if (id.length === 0) return 0
5
+
6
+ let hash = 0
7
+
8
+ for (let i = 0; i < id.length; i++) {
9
+ const char = id.charCodeAt(i)
10
+
11
+ hash = ((hash << 5) - hash + char) | 0 // djb2 hash with 32-bit conversion
12
+ }
13
+
14
+ return Math.abs(hash) % max
15
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Filters an array of items by a search string.
3
+ * The search is case-insensitive and checks if the stringified item includes the search term.
4
+ *
5
+ * @param items - Array of items to filter
6
+ * @param search - Search string (optional)
7
+ * @param stringify - Function to extract the searchable text from each item
8
+ * @returns Filtered array of items
9
+ */
10
+ export function search<T>(
11
+ items: T[],
12
+ search: string | undefined,
13
+ stringify: (item: T) => string | null | undefined = JSON.stringify,
14
+ ): T[] {
15
+ if (search === undefined || search === '')
16
+ return items
17
+
18
+ const lowercase = search.toLowerCase()
19
+
20
+ return items.filter((item) => {
21
+ const text = stringify(item)
22
+
23
+ return text?.toLowerCase().includes(lowercase) ?? false
24
+ })
25
+ }
@@ -0,0 +1,26 @@
1
+ import { readable } from 'svelte/store'
2
+
3
+ /**
4
+ * Create a Readable<number> that counts down from ms to 0
5
+ */
6
+ export function timeout(ms: number, fps = 24) {
7
+ return readable(ms, (set) => {
8
+ const then = Date.now()
9
+ const interval = setInterval(() => tick(), 1000 / fps)
10
+
11
+ function tick() {
12
+ const remaining = ms - (Date.now() - then)
13
+
14
+ if (remaining > 0)
15
+ set(remaining)
16
+ else {
17
+ set(0)
18
+ clearInterval(interval)
19
+ }
20
+ }
21
+
22
+ tick()
23
+
24
+ return () => clearInterval(interval)
25
+ })
26
+ }
@@ -0,0 +1,207 @@
1
+ import { derived, writable, type Readable } from 'svelte/store'
2
+ import type { OnNavigate } from '@sveltejs/kit'
3
+
4
+ export function transit(fn?: (() => void) | (() => Promise<void>)): Promise<void> {
5
+ if (document.startViewTransition === undefined)
6
+ return Promise.resolve(fn?.())
7
+
8
+ const fly = fn !== undefined
9
+
10
+ if (fly) depart()
11
+
12
+ return new Promise((resolve) => {
13
+ const transition = document.startViewTransition(async () => {
14
+ land()
15
+ resolve(await fn?.())
16
+ })
17
+
18
+ // An aborted transition rejects `finished`, and the flight has to be unwound either
19
+ // way: leaving `flying` set keeps view-transition-names on every flyer and breaks the
20
+ // next transition. Handling both settlements also keeps the rejection from escaping.
21
+ transition.finished.then(done, done)
22
+
23
+ // and so does `ready`, which nothing here waits on: it rejects whenever the transition
24
+ // is skipped — a hidden tab, a second one started on top of this — and an unhandled
25
+ // rejection is not what a page should show for an animation it merely did without
26
+ transition.ready.catch(ignore)
27
+
28
+ function done() {
29
+ if (fly) arrive()
30
+
31
+ touchdown()
32
+ }
33
+ })
34
+ }
35
+
36
+ function ignore(): void {}
37
+
38
+ /**
39
+ * SvelteKit navigation, wrapped. The update callback has to outlive the navigation it
40
+ * lets through: it resolves to unblock the router, and only then waits for the new page
41
+ * to be there. Returning any sooner captures the outgoing page as both the old state and
42
+ * the new one, and the transition animates nothing at all.
43
+ */
44
+ export function navigate(nav: OnNavigate): Promise<void> | void {
45
+ if (nav.type === 'popstate' && nav.event.hasUAVisualTransition) return
46
+
47
+ if (document.startViewTransition === undefined) return
48
+
49
+ return new Promise((resolve) => {
50
+ // typed `route`, so a page can style what a navigation does to the whole screen
51
+ // without styling what every in-page `transit` does to it
52
+ const transition = document.startViewTransition({
53
+ types: ['route'],
54
+ update: async () => {
55
+ land()
56
+ resolve()
57
+
58
+ await nav.complete
59
+ },
60
+ })
61
+
62
+ // the same unwinding `transit` does, and for the same reason: an aborted transition
63
+ // rejects, and a name left on a departed element breaks the next one
64
+ transition.finished.then(touchdown, touchdown)
65
+ transition.ready.catch(ignore)
66
+ })
67
+ }
68
+
69
+ let launch: Launch | null = null
70
+
71
+ export function takeoff(id: string, name: string, classes?: string) {
72
+ if (launch !== null) clearInline(launch)
73
+
74
+ const el = document.getElementById(id)
75
+
76
+ if (el === null) {
77
+ console.warn('No element to depart from', id)
78
+ launch = null
79
+
80
+ return
81
+ }
82
+
83
+ el.style.viewTransitionName = name
84
+
85
+ if (classes !== undefined)
86
+ el.style.viewTransitionClass = classes
87
+
88
+ launch = { el, name, classes }
89
+ }
90
+
91
+ function land() {
92
+ if (launch === null) return
93
+
94
+ const clear = launch.el.style.viewTransitionName === launch.name
95
+
96
+ launch.el.style.viewTransitionName = clear ? '' : launch.name
97
+ launch.el.style.viewTransitionClass = clear ? '' : (launch.classes ?? '')
98
+ }
99
+
100
+ function touchdown() {
101
+ if (launch === null) return
102
+
103
+ // Keep `launch` alive after forward pass so land() can re-apply the name
104
+ // on return transit (source → target → source morph).
105
+ if (launch.el.style.viewTransitionName !== launch.name) return
106
+
107
+ clearInline(launch)
108
+ launch = null
109
+ }
110
+
111
+ function clearInline(launch: Launch) {
112
+ launch.el.style.viewTransitionName = ''
113
+ launch.el.style.viewTransitionClass = ''
114
+ }
115
+
116
+ const flying = writable<boolean>(false)
117
+ const flyers = new Set<Flyer>()
118
+
119
+ /**
120
+ * Action to include an element in the non-navigation view transitions.
121
+ *
122
+ * @param node
123
+ * @param options
124
+ * @returns
125
+ */
126
+ export function transition(node: HTMLElement, options: FlyOptions) {
127
+ const flyer = {
128
+ node,
129
+ options,
130
+ original: {
131
+ name: node.style.viewTransitionName,
132
+ classes: node.style.viewTransitionClass,
133
+ },
134
+ }
135
+
136
+ flyers.add(flyer)
137
+
138
+ return {
139
+ destroy: () => flyers.delete(flyer),
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Create a readable store that has `style` value when in non-navigation view transition.
145
+ *
146
+ * @param name
147
+ * @param classes
148
+ * @returns Readable<string | undefined>
149
+ */
150
+ export function styles(name: string, classes?: string): Readable<string | undefined> {
151
+ let value = `view-transition-name: ${name};`
152
+
153
+ if (classes !== undefined)
154
+ value += ` view-transition-class: ${classes};`
155
+
156
+ return derived(flying, (flying) => flying ? value : undefined)
157
+ }
158
+
159
+ function depart() {
160
+ flying.set(true)
161
+
162
+ for (const flyer of flyers) {
163
+ // could have changed
164
+ flyer.original = {
165
+ name: flyer.node.style.viewTransitionName,
166
+ classes: flyer.node.style.viewTransitionClass,
167
+ }
168
+
169
+ flyer.node.style.viewTransitionName = flyer.options.name
170
+
171
+ if (flyer.options.classes !== undefined)
172
+ flyer.node.style.viewTransitionClass = flyer.options.classes
173
+ }
174
+ }
175
+
176
+ function arrive() {
177
+ for (const flyer of flyers) {
178
+ if (flyer.original === undefined) continue
179
+
180
+ flyer.node.style.viewTransitionName = flyer.original.name
181
+ flyer.node.style.viewTransitionClass = flyer.original.classes
182
+ }
183
+
184
+ flying.set(false)
185
+ }
186
+
187
+ interface Flyer {
188
+ node: HTMLElement
189
+ options: FlyOptions
190
+ original?: {
191
+ name: string
192
+ classes: string
193
+ }
194
+ }
195
+
196
+ interface FlyOptions {
197
+ /** view-transition-name */
198
+ name: string
199
+ /** view-transition-class */
200
+ classes?: string
201
+ }
202
+
203
+ interface Launch {
204
+ el: HTMLElement
205
+ name: string
206
+ classes?: string
207
+ }
@@ -0,0 +1,3 @@
1
+ export type Exact<A, B> = A extends B ? (B extends A ? A : never) : never
2
+
3
+ export type Locale = string