@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.
- package/CHANGELOG.md +210 -0
- package/components/configuration.values/manifest.toa.yaml +158 -0
- package/components/configuration.values/source/create.ts +56 -0
- package/components/configuration.values/source/fetch.ts +24 -0
- package/components/configuration.values/source/get.ts +33 -0
- package/components/configuration.values/source/lib/map.test.ts +34 -0
- package/components/configuration.values/source/lib/map.ts +34 -0
- package/components/configuration.values/source/lib/resolve.ts +54 -0
- package/components/configuration.values/source/list.ts +19 -0
- package/components/configuration.values/tsconfig.json +9 -0
- package/cucumber.js +8 -0
- package/features/site/_app/immutable/asset.js +1 -0
- package/features/site/index.html +6 -0
- package/features/steps/UI.ts +88 -0
- package/features/steps/tsconfig.json +9 -0
- package/features/ui.feature +85 -0
- package/package.json +14 -7
- package/readme.md +160 -47
- package/schemas/annotation.cos.yaml +29 -1
- package/schemas/manifest.cos.yaml +9 -3
- package/source/Aspect.test.ts +84 -8
- package/source/Aspect.ts +59 -5
- package/source/Client.test.ts +104 -0
- package/source/Client.ts +258 -0
- package/source/Composition.ts +57 -0
- package/source/Factory.ts +28 -5
- package/source/Secret.test.ts +29 -0
- package/source/Secret.ts +29 -0
- package/source/UI.ts +197 -0
- package/source/configuration.test.ts +92 -39
- package/source/configuration.ts +30 -11
- package/source/const.ts +17 -0
- package/source/deployment.test.ts +80 -1
- package/source/deployment.ts +73 -24
- package/source/epoch.test.ts +26 -0
- package/source/epoch.ts +21 -0
- package/source/index.ts +2 -1
- package/transpiled/Aspect.d.ts +18 -4
- package/transpiled/Aspect.js +47 -3
- package/transpiled/Aspect.js.map +1 -1
- package/transpiled/Aspect.test.js +59 -9
- package/transpiled/Aspect.test.js.map +1 -1
- package/transpiled/Client.d.ts +61 -0
- package/transpiled/Client.js +173 -0
- package/transpiled/Client.js.map +1 -0
- package/transpiled/Client.test.d.ts +1 -0
- package/transpiled/Client.test.js +77 -0
- package/transpiled/Client.test.js.map +1 -0
- package/transpiled/Composition.d.ts +14 -0
- package/transpiled/Composition.js +43 -0
- package/transpiled/Composition.js.map +1 -0
- package/transpiled/Factory.d.ts +8 -2
- package/transpiled/Factory.js +17 -2
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Secret.d.ts +13 -0
- package/transpiled/Secret.js +26 -0
- package/transpiled/Secret.js.map +1 -0
- package/transpiled/Secret.test.d.ts +1 -0
- package/transpiled/Secret.test.js +26 -0
- package/transpiled/Secret.test.js.map +1 -0
- package/transpiled/UI.d.ts +25 -0
- package/transpiled/UI.js +186 -0
- package/transpiled/UI.js.map +1 -0
- package/transpiled/configuration.d.ts +7 -2
- package/transpiled/configuration.js +31 -13
- package/transpiled/configuration.js.map +1 -1
- package/transpiled/configuration.test.js +84 -37
- package/transpiled/configuration.test.js.map +1 -1
- package/transpiled/const.d.ts +11 -0
- package/transpiled/const.js +14 -0
- package/transpiled/const.js.map +1 -0
- package/transpiled/deployment.d.ts +10 -4
- package/transpiled/deployment.js +57 -21
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/deployment.test.js +60 -0
- package/transpiled/deployment.test.js.map +1 -1
- package/transpiled/epoch.d.ts +2 -0
- package/transpiled/epoch.js +21 -0
- package/transpiled/epoch.js.map +1 -0
- package/transpiled/epoch.test.d.ts +1 -0
- package/transpiled/epoch.test.js +22 -0
- package/transpiled/epoch.test.js.map +1 -0
- package/transpiled/index.d.ts +2 -1
- package/transpiled/index.js +4 -1
- package/transpiled/index.js.map +1 -1
- package/transpiled/tsconfig.tsbuildinfo +1 -1
- package/ui/.agents/skills/antcn/SKILL.md +91 -0
- package/ui/.agents/skills/antcn/references/analytics.md +78 -0
- package/ui/.agents/skills/antcn/references/bridge.md +41 -0
- package/ui/.agents/skills/antcn/references/clipboard.md +23 -0
- package/ui/.agents/skills/antcn/references/dismissable.md +75 -0
- package/ui/.agents/skills/antcn/references/dropdown.md +153 -0
- package/ui/.agents/skills/antcn/references/fragments.md +29 -0
- package/ui/.agents/skills/antcn/references/fullscreen.md +157 -0
- package/ui/.agents/skills/antcn/references/geo.md +27 -0
- package/ui/.agents/skills/antcn/references/globals.md +31 -0
- package/ui/.agents/skills/antcn/references/grammatical-form.md +69 -0
- package/ui/.agents/skills/antcn/references/hints.md +44 -0
- package/ui/.agents/skills/antcn/references/hold.md +34 -0
- package/ui/.agents/skills/antcn/references/iam.md +117 -0
- package/ui/.agents/skills/antcn/references/input-form.md +34 -0
- package/ui/.agents/skills/antcn/references/locale.md +66 -0
- package/ui/.agents/skills/antcn/references/net.md +33 -0
- package/ui/.agents/skills/antcn/references/panel.md +44 -0
- package/ui/.agents/skills/antcn/references/passkeys.md +27 -0
- package/ui/.agents/skills/antcn/references/payments.md +99 -0
- package/ui/.agents/skills/antcn/references/realtime.md +69 -0
- package/ui/.agents/skills/antcn/references/scrollable.md +39 -0
- package/ui/.agents/skills/antcn/references/selector.md +71 -0
- package/ui/.agents/skills/antcn/references/shake.md +36 -0
- package/ui/.agents/skills/antcn/references/share.md +28 -0
- package/ui/.agents/skills/antcn/references/shell.md +139 -0
- package/ui/.agents/skills/antcn/references/stack.md +53 -0
- package/ui/.agents/skills/antcn/references/system.md +149 -0
- package/ui/.agents/skills/antcn/references/taptap.md +28 -0
- package/ui/.agents/skills/antcn/references/tools.md +68 -0
- package/ui/.agents/skills/antcn/references/transmission.md +96 -0
- package/ui/.agents/skills/shadcn-svelte/SKILL.md +227 -0
- package/ui/.agents/skills/shadcn-svelte/agents/openai.yml +5 -0
- package/ui/.agents/skills/shadcn-svelte/assets/shadcn-svelte-small.png +0 -0
- package/ui/.agents/skills/shadcn-svelte/assets/shadcn-svelte.png +0 -0
- package/ui/.agents/skills/shadcn-svelte/cli.md +166 -0
- package/ui/.agents/skills/shadcn-svelte/customization.md +213 -0
- package/ui/.agents/skills/shadcn-svelte/evals/evals.json +47 -0
- package/ui/.agents/skills/shadcn-svelte/rules/composition.md +244 -0
- package/ui/.agents/skills/shadcn-svelte/rules/forms.md +234 -0
- package/ui/.agents/skills/shadcn-svelte/rules/icons.md +107 -0
- package/ui/.agents/skills/shadcn-svelte/rules/styling.md +195 -0
- package/ui/.agents/skills/svas/SKILL.md +169 -0
- package/ui/.agents/skills/svas/references/patterns.md +95 -0
- package/ui/.agents/skills/svintl/SKILL.md +176 -0
- package/ui/.claude/settings.json +15 -0
- package/ui/.codex/hooks.json +15 -0
- package/ui/.cursor/hooks.json +11 -0
- package/ui/.env.example +1 -0
- package/ui/.prettierrc +9 -0
- package/ui/.vscode/extensions.json +7 -0
- package/ui/.vscode/settings.json +27 -0
- package/ui/AGENTS.md +51 -0
- package/ui/architecture.md +390 -0
- package/ui/components.json +20 -0
- package/ui/eslint.config.js +152 -0
- package/ui/features/base.ts +2 -0
- package/ui/features/boot.feature +5 -0
- package/ui/features/steps/authentication.ts +34 -0
- package/ui/features/steps/navigaton.ts +37 -0
- package/ui/features/steps/typing.ts +24 -0
- package/ui/package-lock.json +8173 -0
- package/ui/package.json +76 -0
- package/ui/playwright.config.ts +13 -0
- package/ui/skills-lock.json +30 -0
- package/ui/src/@/configuration/index.ts +1 -0
- package/ui/src/@/configuration/svc/create.ts +29 -0
- package/ui/src/@/configuration/svc/index.ts +3 -0
- package/ui/src/@/configuration/svc/net/Configuration.ts +18 -0
- package/ui/src/@/configuration/svc/net/index.ts +2 -0
- package/ui/src/@/configuration/svc/net/interface.ts +35 -0
- package/ui/src/@/configuration/svc/store.ts +14 -0
- package/ui/src/@/configuration/ui/Configurations.svelte +85 -0
- package/ui/src/@/configuration/ui/Configurations.ts +5 -0
- package/ui/src/@/configuration/ui/Create.svelte +64 -0
- package/ui/src/@/configuration/ui/Create.ts +7 -0
- package/ui/src/@/configuration/ui/Form.svelte +75 -0
- package/ui/src/@/configuration/ui/Form.ts +79 -0
- package/ui/src/@/configuration/ui/Row.svelte +44 -0
- package/ui/src/@/configuration/ui/Row.ts +9 -0
- package/ui/src/@/configuration/ui/Value.svelte +33 -0
- package/ui/src/@/configuration/ui/Value.ts +6 -0
- package/ui/src/@/configuration/ui/index.ts +9 -0
- package/ui/src/@/configuration/ui/intl/built.js +38 -0
- package/ui/src/@/configuration/ui/intl/context.yaml +51 -0
- package/ui/src/@/configuration/ui/intl/en-US.yaml +21 -0
- package/ui/src/@/configuration/ui/intl/index.ts +9 -0
- package/ui/src/@/configuration/ui/intl/types.ts +31 -0
- package/ui/src/@/configuration/ui/read.test.ts +75 -0
- package/ui/src/@/configuration/ui/read.ts +102 -0
- package/ui/src/@/configuration/ui/ui.test.ts +69 -0
- package/ui/src/@/configuration/ui/ui.ts +115 -0
- package/ui/src/@/iam/index.ts +1 -0
- package/ui/src/@/iam/rc.ts +22 -0
- package/ui/src/@/iam/svc/authenticated.ts +17 -0
- package/ui/src/@/iam/svc/basic.ts +23 -0
- package/ui/src/@/iam/svc/index.ts +10 -0
- package/ui/src/@/iam/svc/logout.ts +5 -0
- package/ui/src/@/iam/svc/named.ts +16 -0
- package/ui/src/@/iam/svc/net/Echo.ts +9 -0
- package/ui/src/@/iam/svc/net/basic/index.ts +1 -0
- package/ui/src/@/iam/svc/net/basic/interface.ts +15 -0
- package/ui/src/@/iam/svc/net/federation/index.ts +1 -0
- package/ui/src/@/iam/svc/net/federation/interface.ts +12 -0
- package/ui/src/@/iam/svc/net/index.ts +6 -0
- package/ui/src/@/iam/svc/net/interface.ts +17 -0
- package/ui/src/@/iam/svc/net/otp/index.ts +1 -0
- package/ui/src/@/iam/svc/net/otp/interface.ts +14 -0
- package/ui/src/@/iam/svc/net/passkeys/index.ts +1 -0
- package/ui/src/@/iam/svc/net/passkeys/interface.ts +12 -0
- package/ui/src/@/iam/svc/oidc/apple.ts +47 -0
- package/ui/src/@/iam/svc/oidc/authenticate.ts +62 -0
- package/ui/src/@/iam/svc/oidc/google.ts +45 -0
- package/ui/src/@/iam/svc/oidc/hello.ts +82 -0
- package/ui/src/@/iam/svc/oidc/index.ts +3 -0
- package/ui/src/@/iam/svc/oidc/nonce.ts +5 -0
- package/ui/src/@/iam/svc/oidc/providers.ts +28 -0
- package/ui/src/@/iam/svc/oidc/standard.ts +28 -0
- package/ui/src/@/iam/svc/otp.ts +18 -0
- package/ui/src/@/iam/svc/passkeys/create.ts +20 -0
- package/ui/src/@/iam/svc/passkeys/index.ts +2 -0
- package/ui/src/@/iam/svc/passkeys/login.ts +21 -0
- package/ui/src/@/iam/svc/store.ts +36 -0
- package/ui/src/@/iam/svc/sync.ts +18 -0
- package/ui/src/@/iam/svc/transfer.ts +11 -0
- package/ui/src/@/iam/svc/update.ts +8 -0
- package/ui/src/@/iam/ui/AccountLike.ts +4 -0
- package/ui/src/@/iam/ui/Authenticated.svelte +37 -0
- package/ui/src/@/iam/ui/Authenticated.ts +10 -0
- package/ui/src/@/iam/ui/Authentication.svelte +50 -0
- package/ui/src/@/iam/ui/Authentication.ts +9 -0
- package/ui/src/@/iam/ui/Authorized.svelte +32 -0
- package/ui/src/@/iam/ui/Authorized.ts +65 -0
- package/ui/src/@/iam/ui/Card.svelte +14 -0
- package/ui/src/@/iam/ui/Card.ts +7 -0
- package/ui/src/@/iam/ui/Refresh.svelte +39 -0
- package/ui/src/@/iam/ui/credentials/Credentials.svelte +26 -0
- package/ui/src/@/iam/ui/credentials/Credentials.ts +5 -0
- package/ui/src/@/iam/ui/credentials/Provider.svelte +24 -0
- package/ui/src/@/iam/ui/credentials/Provider.ts +5 -0
- package/ui/src/@/iam/ui/credentials/index.ts +1 -0
- package/ui/src/@/iam/ui/credentials/passkeys/Key.svelte +42 -0
- package/ui/src/@/iam/ui/credentials/passkeys/Key.ts +29 -0
- package/ui/src/@/iam/ui/credentials/passkeys/Manager.svelte +83 -0
- package/ui/src/@/iam/ui/credentials/passkeys/Manager.ts +5 -0
- package/ui/src/@/iam/ui/credentials/passkeys/Passkeys.svelte +39 -0
- package/ui/src/@/iam/ui/credentials/passkeys/Summary.svelte +27 -0
- package/ui/src/@/iam/ui/credentials/passkeys/Summary.ts +5 -0
- package/ui/src/@/iam/ui/credentials/passkeys/index.ts +1 -0
- package/ui/src/@/iam/ui/credentials/providers.ts +15 -0
- package/ui/src/@/iam/ui/credentials/transfer/Qr.svelte +24 -0
- package/ui/src/@/iam/ui/credentials/transfer/Qr.ts +3 -0
- package/ui/src/@/iam/ui/credentials/transfer/Transfer.svelte +48 -0
- package/ui/src/@/iam/ui/credentials/transfer/Transfer.ts +5 -0
- package/ui/src/@/iam/ui/credentials/transfer/index.ts +1 -0
- package/ui/src/@/iam/ui/index.ts +3 -0
- package/ui/src/@/iam/ui/intl/built.js +79 -0
- package/ui/src/@/iam/ui/intl/context.yaml +91 -0
- package/ui/src/@/iam/ui/intl/en-US.yaml +64 -0
- package/ui/src/@/iam/ui/intl/index.ts +10 -0
- package/ui/src/@/iam/ui/intl/types.ts +70 -0
- package/ui/src/@/iam/ui/oidc/Authentication.svelte +16 -0
- package/ui/src/@/iam/ui/oidc/Authentication.ts +5 -0
- package/ui/src/@/iam/ui/oidc/Button.svelte +36 -0
- package/ui/src/@/iam/ui/oidc/Button.ts +11 -0
- package/ui/src/@/iam/ui/oidc/Refresh.svelte +16 -0
- package/ui/src/@/iam/ui/oidc/icons/Apple.svelte +19 -0
- package/ui/src/@/iam/ui/oidc/icons/Google.svelte +31 -0
- package/ui/src/@/iam/ui/oidc/icons/index.ts +11 -0
- package/ui/src/@/iam/ui/oidc/index.ts +2 -0
- package/ui/src/@/iam/ui/passkey/Authentication.svelte +64 -0
- package/ui/src/@/iam/ui/passkey/Authentication.ts +8 -0
- package/ui/src/@/iam/ui/passkey/Create.svelte +53 -0
- package/ui/src/@/iam/ui/passkey/Create.ts +7 -0
- package/ui/src/@/iam/ui/passkey/Login.svelte +29 -0
- package/ui/src/@/iam/ui/passkey/Refresh.svelte +29 -0
- package/ui/src/@/iam/ui/passkey/index.ts +2 -0
- package/ui/src/@/iam/ui/password/Authentication.svelte +19 -0
- package/ui/src/@/iam/ui/password/Authentication.ts +8 -0
- package/ui/src/@/iam/ui/password/Form.svelte +151 -0
- package/ui/src/@/iam/ui/password/Form.ts +6 -0
- package/ui/src/@/iam/ui/password/Password.svelte +39 -0
- package/ui/src/@/iam/ui/password/Password.ts +6 -0
- package/ui/src/@/iam/ui/password/Refresh.svelte +5 -0
- package/ui/src/@/iam/ui/password/index.ts +2 -0
- package/ui/src/@/net/index.ts +1 -0
- package/ui/src/@/net/svc/index.ts +3 -0
- package/ui/src/@/net/svc/origin.ts +8 -0
- package/ui/src/@/net/svc/query.test.ts +45 -0
- package/ui/src/@/net/svc/query.ts +25 -0
- package/ui/src/@/passkeys/index.ts +1 -0
- package/ui/src/@/passkeys/svc/add.ts +15 -0
- package/ui/src/@/passkeys/svc/create.ts +58 -0
- package/ui/src/@/passkeys/svc/credentials/convert.ts +32 -0
- package/ui/src/@/passkeys/svc/credentials/create.ts +34 -0
- package/ui/src/@/passkeys/svc/credentials/get.ts +14 -0
- package/ui/src/@/passkeys/svc/credentials/index.ts +3 -0
- package/ui/src/@/passkeys/svc/credentials/key.ts +10 -0
- package/ui/src/@/passkeys/svc/get.ts +10 -0
- package/ui/src/@/passkeys/svc/index.ts +6 -0
- package/ui/src/@/passkeys/svc/net/CreationResponse.ts +15 -0
- package/ui/src/@/passkeys/svc/net/Passkey.ts +8 -0
- package/ui/src/@/passkeys/svc/net/RequestResponse.ts +12 -0
- package/ui/src/@/passkeys/svc/net/challenges/Options.ts +21 -0
- package/ui/src/@/passkeys/svc/net/challenges/index.ts +2 -0
- package/ui/src/@/passkeys/svc/net/challenges/interface.ts +16 -0
- package/ui/src/@/passkeys/svc/net/index.ts +4 -0
- package/ui/src/@/passkeys/svc/net/interface.ts +29 -0
- package/ui/src/@/passkeys/svc/remove.ts +13 -0
- package/ui/src/@/passkeys/svc/request.ts +50 -0
- package/ui/src/@/passkeys/svc/store.ts +13 -0
- package/ui/src/@/passkeys/svc/supported.ts +1 -0
- package/ui/src/@/passkeys/ui/aaguid.json +150 -0
- package/ui/src/@/realtime/events.ts +1 -0
- package/ui/src/@/realtime/index.ts +1 -0
- package/ui/src/@/realtime/rc.ts +13 -0
- package/ui/src/@/realtime/svc/connect.ts +67 -0
- package/ui/src/@/realtime/svc/events.ts +17 -0
- package/ui/src/@/realtime/svc/index.ts +5 -0
- package/ui/src/@/realtime/svc/net/Message.ts +6 -0
- package/ui/src/@/realtime/svc/net/index.ts +2 -0
- package/ui/src/@/realtime/svc/net/interface.ts +13 -0
- package/ui/src/@/realtime/svc/reset.ts +5 -0
- package/ui/src/@/realtime/svc/status.ts +12 -0
- package/ui/src/@/realtime/svc/store.ts +30 -0
- package/ui/src/@/realtime/svc/time.ts +15 -0
- package/ui/src/app.d.ts +20 -0
- package/ui/src/app.html +13 -0
- package/ui/src/config/index.ts +70 -0
- package/ui/src/lib/assets/favicon.svg +1 -0
- package/ui/src/lib/components/clipboard/Clipboard.svelte +63 -0
- package/ui/src/lib/components/clipboard/Clipboard.ts +12 -0
- package/ui/src/lib/components/clipboard/index.ts +1 -0
- package/ui/src/lib/components/dismissable/Dismissable.svelte +81 -0
- package/ui/src/lib/components/dismissable/Dismissable.ts +7 -0
- package/ui/src/lib/components/dismissable/index.ts +1 -0
- package/ui/src/lib/components/dropdown/Back.svelte +14 -0
- package/ui/src/lib/components/dropdown/Back.ts +3 -0
- package/ui/src/lib/components/dropdown/Content.svelte +76 -0
- package/ui/src/lib/components/dropdown/Content.ts +13 -0
- package/ui/src/lib/components/dropdown/Context.ts +18 -0
- package/ui/src/lib/components/dropdown/Group.svelte +24 -0
- package/ui/src/lib/components/dropdown/Group.ts +8 -0
- package/ui/src/lib/components/dropdown/GroupContext.ts +15 -0
- package/ui/src/lib/components/dropdown/Item.svelte +31 -0
- package/ui/src/lib/components/dropdown/Item.ts +5 -0
- package/ui/src/lib/components/dropdown/Layer.svelte +11 -0
- package/ui/src/lib/components/dropdown/Layer.ts +7 -0
- package/ui/src/lib/components/dropdown/Root.svelte +88 -0
- package/ui/src/lib/components/dropdown/Root.ts +6 -0
- package/ui/src/lib/components/dropdown/Separator.svelte +13 -0
- package/ui/src/lib/components/dropdown/Separator.ts +5 -0
- package/ui/src/lib/components/dropdown/Trigger.svelte +33 -0
- package/ui/src/lib/components/dropdown/Trigger.ts +5 -0
- package/ui/src/lib/components/dropdown/index.ts +8 -0
- package/ui/src/lib/components/fullscreen/Fullscreen.svelte +97 -0
- package/ui/src/lib/components/fullscreen/Fullscreen.ts +18 -0
- package/ui/src/lib/components/fullscreen/Overlay.svelte +15 -0
- package/ui/src/lib/components/fullscreen/Overlay.ts +7 -0
- package/ui/src/lib/components/fullscreen/index.ts +2 -0
- package/ui/src/lib/components/hold/Hold.svelte +133 -0
- package/ui/src/lib/components/hold/Hold.ts +23 -0
- package/ui/src/lib/components/hold/index.ts +1 -0
- package/ui/src/lib/components/scrollable/Scrollable.svelte +49 -0
- package/ui/src/lib/components/scrollable/Scrollable.ts +117 -0
- package/ui/src/lib/components/scrollable/index.ts +2 -0
- package/ui/src/lib/components/shake/Shake.svelte +62 -0
- package/ui/src/lib/components/shake/Shake.ts +7 -0
- package/ui/src/lib/components/shake/index.ts +1 -0
- package/ui/src/lib/components/share/Share.svelte +58 -0
- package/ui/src/lib/components/share/Share.ts +9 -0
- package/ui/src/lib/components/share/index.ts +1 -0
- package/ui/src/lib/components/shell/Attention.svelte +11 -0
- package/ui/src/lib/components/shell/Attention.ts +6 -0
- package/ui/src/lib/components/shell/Header.svelte +18 -0
- package/ui/src/lib/components/shell/Header.ts +7 -0
- package/ui/src/lib/components/shell/Screen.svelte +28 -0
- package/ui/src/lib/components/shell/Screen.ts +11 -0
- package/ui/src/lib/components/shell/Sticky.svelte +23 -0
- package/ui/src/lib/components/shell/Sticky.ts +8 -0
- package/ui/src/lib/components/shell/Underlay.svelte +21 -0
- package/ui/src/lib/components/shell/Underlay.ts +6 -0
- package/ui/src/lib/components/shell/index.ts +6 -0
- package/ui/src/lib/components/shell/nav/Actions.svelte +31 -0
- package/ui/src/lib/components/shell/nav/Actions.ts +16 -0
- package/ui/src/lib/components/shell/nav/Back.svelte +20 -0
- package/ui/src/lib/components/shell/nav/Back.ts +9 -0
- package/ui/src/lib/components/shell/nav/Bar.svelte +24 -0
- package/ui/src/lib/components/shell/nav/Bar.ts +3 -0
- package/ui/src/lib/components/shell/nav/Button.svelte +64 -0
- package/ui/src/lib/components/shell/nav/Button.ts +7 -0
- package/ui/src/lib/components/shell/nav/Nav.svelte +62 -0
- package/ui/src/lib/components/shell/nav/Nav.ts +35 -0
- package/ui/src/lib/components/shell/nav/Return.svelte +29 -0
- package/ui/src/lib/components/shell/nav/Return.ts +15 -0
- package/ui/src/lib/components/shell/nav/Sections.svelte +58 -0
- package/ui/src/lib/components/shell/nav/Sections.ts +6 -0
- package/ui/src/lib/components/shell/nav/Toolbar.svelte +73 -0
- package/ui/src/lib/components/shell/nav/Toolbar.ts +3 -0
- package/ui/src/lib/components/shell/nav/history.ts +36 -0
- package/ui/src/lib/components/shell/nav/index.ts +5 -0
- package/ui/src/lib/components/shell/nav/store.ts +24 -0
- package/ui/src/lib/components/ui/alert/alert-action.svelte +20 -0
- package/ui/src/lib/components/ui/alert/alert-description.svelte +23 -0
- package/ui/src/lib/components/ui/alert/alert-title.svelte +23 -0
- package/ui/src/lib/components/ui/alert/alert.svelte +43 -0
- package/ui/src/lib/components/ui/alert/index.ts +17 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +27 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +27 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte +32 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte +17 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte +23 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-media.svelte +20 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte +17 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-portal.svelte +7 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte +17 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte +7 -0
- package/ui/src/lib/components/ui/alert-dialog/alert-dialog.svelte +7 -0
- package/ui/src/lib/components/ui/alert-dialog/index.ts +40 -0
- package/ui/src/lib/components/ui/badge/badge.svelte +49 -0
- package/ui/src/lib/components/ui/badge/index.ts +2 -0
- package/ui/src/lib/components/ui/button/button.svelte +82 -0
- package/ui/src/lib/components/ui/button/index.ts +17 -0
- package/ui/src/lib/components/ui/button-group/button-group-separator.svelte +23 -0
- package/ui/src/lib/components/ui/button-group/button-group-text.svelte +28 -0
- package/ui/src/lib/components/ui/button-group/button-group.svelte +46 -0
- package/ui/src/lib/components/ui/button-group/index.ts +15 -0
- package/ui/src/lib/components/ui/card/card-action.svelte +23 -0
- package/ui/src/lib/components/ui/card/card-content.svelte +20 -0
- package/ui/src/lib/components/ui/card/card-description.svelte +20 -0
- package/ui/src/lib/components/ui/card/card-footer.svelte +20 -0
- package/ui/src/lib/components/ui/card/card-header.svelte +23 -0
- package/ui/src/lib/components/ui/card/card-title.svelte +20 -0
- package/ui/src/lib/components/ui/card/card.svelte +22 -0
- package/ui/src/lib/components/ui/card/index.ts +25 -0
- package/ui/src/lib/components/ui/checkbox/checkbox.svelte +39 -0
- package/ui/src/lib/components/ui/checkbox/index.ts +6 -0
- package/ui/src/lib/components/ui/collapsible/collapsible-content.svelte +7 -0
- package/ui/src/lib/components/ui/collapsible/collapsible-trigger.svelte +7 -0
- package/ui/src/lib/components/ui/collapsible/collapsible.svelte +20 -0
- package/ui/src/lib/components/ui/collapsible/index.ts +13 -0
- package/ui/src/lib/components/ui/input/index.ts +7 -0
- package/ui/src/lib/components/ui/input/input.svelte +48 -0
- package/ui/src/lib/components/ui/input-otp/index.ts +15 -0
- package/ui/src/lib/components/ui/input-otp/input-otp-group.svelte +20 -0
- package/ui/src/lib/components/ui/input-otp/input-otp-separator.svelte +27 -0
- package/ui/src/lib/components/ui/input-otp/input-otp-slot.svelte +31 -0
- package/ui/src/lib/components/ui/input-otp/input-otp.svelte +23 -0
- package/ui/src/lib/components/ui/item/index.ts +34 -0
- package/ui/src/lib/components/ui/item/item-actions.svelte +20 -0
- package/ui/src/lib/components/ui/item/item-content.svelte +23 -0
- package/ui/src/lib/components/ui/item/item-description.svelte +23 -0
- package/ui/src/lib/components/ui/item/item-footer.svelte +20 -0
- package/ui/src/lib/components/ui/item/item-group.svelte +21 -0
- package/ui/src/lib/components/ui/item/item-header.svelte +20 -0
- package/ui/src/lib/components/ui/item/item-media.svelte +42 -0
- package/ui/src/lib/components/ui/item/item-separator.svelte +19 -0
- package/ui/src/lib/components/ui/item/item-title.svelte +20 -0
- package/ui/src/lib/components/ui/item/item.svelte +61 -0
- package/ui/src/lib/components/ui/kbd/index.ts +10 -0
- package/ui/src/lib/components/ui/kbd/kbd-group.svelte +20 -0
- package/ui/src/lib/components/ui/kbd/kbd.svelte +23 -0
- package/ui/src/lib/components/ui/label/index.ts +7 -0
- package/ui/src/lib/components/ui/label/label.svelte +20 -0
- package/ui/src/lib/components/ui/progress/index.ts +7 -0
- package/ui/src/lib/components/ui/progress/progress.svelte +27 -0
- package/ui/src/lib/components/ui/select/index.ts +37 -0
- package/ui/src/lib/components/ui/select/select-content.svelte +45 -0
- package/ui/src/lib/components/ui/select/select-group-heading.svelte +21 -0
- package/ui/src/lib/components/ui/select/select-group.svelte +17 -0
- package/ui/src/lib/components/ui/select/select-item.svelte +40 -0
- package/ui/src/lib/components/ui/select/select-label.svelte +20 -0
- package/ui/src/lib/components/ui/select/select-portal.svelte +7 -0
- package/ui/src/lib/components/ui/select/select-scroll-down-button.svelte +20 -0
- package/ui/src/lib/components/ui/select/select-scroll-up-button.svelte +20 -0
- package/ui/src/lib/components/ui/select/select-separator.svelte +18 -0
- package/ui/src/lib/components/ui/select/select-trigger.svelte +29 -0
- package/ui/src/lib/components/ui/select/select.svelte +11 -0
- package/ui/src/lib/components/ui/separator/index.ts +7 -0
- package/ui/src/lib/components/ui/separator/separator.svelte +23 -0
- package/ui/src/lib/components/ui/spinner/index.ts +1 -0
- package/ui/src/lib/components/ui/spinner/spinner.svelte +18 -0
- package/ui/src/lib/components/ui/tabs/index.ts +18 -0
- package/ui/src/lib/components/ui/tabs/tabs-content.svelte +17 -0
- package/ui/src/lib/components/ui/tabs/tabs-list.svelte +40 -0
- package/ui/src/lib/components/ui/tabs/tabs-trigger.svelte +23 -0
- package/ui/src/lib/components/ui/tabs/tabs.svelte +19 -0
- package/ui/src/lib/components/ui/textarea/index.ts +7 -0
- package/ui/src/lib/components/ui/textarea/textarea.svelte +22 -0
- package/ui/src/lib/intl/bcp.ts +25 -0
- package/ui/src/lib/intl/built.js +18 -0
- package/ui/src/lib/intl/context.yaml +18 -0
- package/ui/src/lib/intl/en-US.yaml +6 -0
- package/ui/src/lib/intl/index.ts +65 -0
- package/ui/src/lib/intl/types.ts +19 -0
- package/ui/src/lib/tools/ago.ts +10 -0
- package/ui/src/lib/tools/assert.ts +3 -0
- package/ui/src/lib/tools/cap.ts +5 -0
- package/ui/src/lib/tools/clicks.ts +25 -0
- package/ui/src/lib/tools/contextmenu.ts +19 -0
- package/ui/src/lib/tools/convert.ts +32 -0
- package/ui/src/lib/tools/currency.test.ts +10 -0
- package/ui/src/lib/tools/currency.ts +55 -0
- package/ui/src/lib/tools/date.test.ts +21 -0
- package/ui/src/lib/tools/date.ts +35 -0
- package/ui/src/lib/tools/delay.ts +7 -0
- package/ui/src/lib/tools/image.ts +39 -0
- package/ui/src/lib/tools/index.ts +20 -0
- package/ui/src/lib/tools/location.ts +41 -0
- package/ui/src/lib/tools/metronome.ts +11 -0
- package/ui/src/lib/tools/mq.ts +84 -0
- package/ui/src/lib/tools/onsubmit.ts +21 -0
- package/ui/src/lib/tools/random.ts +15 -0
- package/ui/src/lib/tools/search.ts +25 -0
- package/ui/src/lib/tools/timeout.ts +26 -0
- package/ui/src/lib/tools/transition.ts +207 -0
- package/ui/src/lib/tools/types.ts +3 -0
- package/ui/src/lib/tools/uuid.test.ts +28 -0
- package/ui/src/lib/tools/uuid.ts +9 -0
- package/ui/src/lib/typeset.css +502 -0
- package/ui/src/lib/utils.ts +12 -0
- package/ui/src/routes/(private)/+layout.svelte +112 -0
- package/ui/src/routes/(private)/+page.svelte +7 -0
- package/ui/src/routes/(private)/[component]/+page.svelte +77 -0
- package/ui/src/routes/+layout.svelte +25 -0
- package/ui/src/routes/+layout.ts +14 -0
- package/ui/src/routes/layout.css +232 -0
- package/ui/static/robots.txt +3 -0
- package/ui/svelte.config.js +36 -0
- package/ui/tools/feat.js +43 -0
- package/ui/tools/hooks/README.md +13 -0
- package/ui/tools/hooks/guard-intl.sh +40 -0
- package/ui/tools/shad.js +7 -0
- package/ui/tsconfig.json +20 -0
- 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,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,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
|
+
}
|