@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,234 @@
|
|
|
1
|
+
# Forms & Inputs
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Forms use Field.FieldGroup + Field.Field
|
|
6
|
+
- InputGroup requires InputGroup.Input/InputGroup.Textarea
|
|
7
|
+
- Buttons inside inputs use InputGroup.Root + InputGroup.Addon
|
|
8
|
+
- Option sets (2–7 choices) use ToggleGroup.Root + ToggleGroup.Item
|
|
9
|
+
- Field.FieldSet + Field.FieldLegend for grouping related fields
|
|
10
|
+
- Field validation and disabled states
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Forms use Field.FieldGroup + Field.Field
|
|
15
|
+
|
|
16
|
+
Always use `Field.FieldGroup` + `Field.Field` — never raw `div` with `space-y-*`:
|
|
17
|
+
|
|
18
|
+
```svelte
|
|
19
|
+
<script lang="ts">
|
|
20
|
+
import * as Field from "$lib/components/ui/field";
|
|
21
|
+
import { Input } from "$lib/components/ui/input";
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<Field.FieldGroup>
|
|
25
|
+
<Field.Field>
|
|
26
|
+
<Field.FieldLabel for="email">Email</Field.FieldLabel>
|
|
27
|
+
<Input id="email" type="email" />
|
|
28
|
+
</Field.Field>
|
|
29
|
+
<Field.Field>
|
|
30
|
+
<Field.FieldLabel for="password">Password</Field.FieldLabel>
|
|
31
|
+
<Input id="password" type="password" />
|
|
32
|
+
</Field.Field>
|
|
33
|
+
</Field.FieldGroup>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Use `Field` with `orientation="horizontal"` for settings pages. Use `Field.FieldLabel` with `class="sr-only"` for visually hidden labels.
|
|
37
|
+
|
|
38
|
+
**Choosing form controls:**
|
|
39
|
+
|
|
40
|
+
- Simple text input → `Input`
|
|
41
|
+
- Dropdown with predefined options → `Select`
|
|
42
|
+
- Searchable dropdown → `Combobox`
|
|
43
|
+
- Native HTML select (no JS) → `native-select`
|
|
44
|
+
- Boolean toggle → `Switch` (for settings) or `Checkbox` (for forms)
|
|
45
|
+
- Single choice from few options → `RadioGroup`
|
|
46
|
+
- Toggle between 2–5 options → `ToggleGroup.Root` + `ToggleGroup.Item`
|
|
47
|
+
- OTP/verification code → `InputOTP`
|
|
48
|
+
- Multi-line text → `Textarea`
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## InputGroup requires InputGroup.Input/InputGroup.Textarea
|
|
53
|
+
|
|
54
|
+
Never use raw `Input` or `Textarea` inside an `InputGroup.Root`.
|
|
55
|
+
|
|
56
|
+
**Incorrect:**
|
|
57
|
+
|
|
58
|
+
```svelte
|
|
59
|
+
<script lang="ts">
|
|
60
|
+
import * as InputGroup from "$lib/components/ui/input-group";
|
|
61
|
+
import { Input } from "$lib/components/ui/input";
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<InputGroup.Root>
|
|
65
|
+
<Input placeholder="Search..." />
|
|
66
|
+
</InputGroup.Root>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Correct:**
|
|
70
|
+
|
|
71
|
+
```svelte
|
|
72
|
+
<script lang="ts">
|
|
73
|
+
import * as InputGroup from "$lib/components/ui/input-group";
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<InputGroup.Root>
|
|
77
|
+
<InputGroup.Input placeholder="Search..." />
|
|
78
|
+
</InputGroup.Root>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Buttons inside inputs use InputGroup.Root + InputGroup.Addon
|
|
84
|
+
|
|
85
|
+
Never place a `Button` directly inside or adjacent to an `Input` with custom positioning.
|
|
86
|
+
|
|
87
|
+
**Incorrect:**
|
|
88
|
+
|
|
89
|
+
```svelte
|
|
90
|
+
<script lang="ts">
|
|
91
|
+
import { Input } from "$lib/components/ui/input";
|
|
92
|
+
import { Button } from "$lib/components/ui/button";
|
|
93
|
+
import SearchIcon from "@lucide/svelte/icons/search";
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
<div class="relative">
|
|
97
|
+
<Input placeholder="Search..." class="pr-10" />
|
|
98
|
+
<Button class="absolute top-0 right-0" size="icon">
|
|
99
|
+
<SearchIcon />
|
|
100
|
+
</Button>
|
|
101
|
+
</div>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Correct:**
|
|
105
|
+
|
|
106
|
+
```svelte
|
|
107
|
+
<script lang="ts">
|
|
108
|
+
import * as InputGroup from "$lib/components/ui/input-group";
|
|
109
|
+
import { Button } from "$lib/components/ui/button";
|
|
110
|
+
import SearchIcon from "@lucide/svelte/icons/search";
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<InputGroup.Root>
|
|
114
|
+
<InputGroup.Input placeholder="Search..." />
|
|
115
|
+
<InputGroup.Addon>
|
|
116
|
+
<Button size="icon">
|
|
117
|
+
<SearchIcon data-icon="inline-start" />
|
|
118
|
+
</Button>
|
|
119
|
+
</InputGroup.Addon>
|
|
120
|
+
</InputGroup.Root>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Option sets (2–7 choices) use ToggleGroup.Root + ToggleGroup.Item
|
|
126
|
+
|
|
127
|
+
Don't manually loop `Button` components with active state.
|
|
128
|
+
|
|
129
|
+
**Incorrect:**
|
|
130
|
+
|
|
131
|
+
```svelte
|
|
132
|
+
<script lang="ts">
|
|
133
|
+
import { Button } from "$lib/components/ui/button";
|
|
134
|
+
let selected = $state("daily");
|
|
135
|
+
</script>
|
|
136
|
+
|
|
137
|
+
<div class="flex gap-2">
|
|
138
|
+
{#each ["daily", "weekly", "monthly"] as option (option)}
|
|
139
|
+
<Button
|
|
140
|
+
variant={selected === option ? "default" : "outline"}
|
|
141
|
+
onclick={() => (selected = option)}
|
|
142
|
+
>
|
|
143
|
+
{option}
|
|
144
|
+
</Button>
|
|
145
|
+
{/each}
|
|
146
|
+
</div>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Correct:**
|
|
150
|
+
|
|
151
|
+
```svelte
|
|
152
|
+
<script lang="ts">
|
|
153
|
+
import * as ToggleGroup from "$lib/components/ui/toggle-group";
|
|
154
|
+
let selected = $state("daily");
|
|
155
|
+
</script>
|
|
156
|
+
|
|
157
|
+
<ToggleGroup.Root bind:value={selected} spacing={2}>
|
|
158
|
+
<ToggleGroup.Item value="daily">Daily</ToggleGroup.Item>
|
|
159
|
+
<ToggleGroup.Item value="weekly">Weekly</ToggleGroup.Item>
|
|
160
|
+
<ToggleGroup.Item value="monthly">Monthly</ToggleGroup.Item>
|
|
161
|
+
</ToggleGroup.Root>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Combine with `Field` for labelled toggle groups:
|
|
165
|
+
|
|
166
|
+
```svelte
|
|
167
|
+
<script lang="ts">
|
|
168
|
+
import * as Field from "$lib/components/ui/field";
|
|
169
|
+
import * as ToggleGroup from "$lib/components/ui/toggle-group";
|
|
170
|
+
</script>
|
|
171
|
+
|
|
172
|
+
<Field.Field orientation="horizontal">
|
|
173
|
+
<Field.FieldTitle id="theme-label">Theme</Field.FieldTitle>
|
|
174
|
+
<ToggleGroup.Root aria-labelledby="theme-label" spacing={2}>
|
|
175
|
+
<ToggleGroup.Item value="light">Light</ToggleGroup.Item>
|
|
176
|
+
<ToggleGroup.Item value="dark">Dark</ToggleGroup.Item>
|
|
177
|
+
<ToggleGroup.Item value="system">System</ToggleGroup.Item>
|
|
178
|
+
</ToggleGroup.Root>
|
|
179
|
+
</Field.Field>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Field.FieldSet + Field.FieldLegend for grouping related fields
|
|
185
|
+
|
|
186
|
+
Use `Field.FieldSet` + `Field.FieldLegend` for related checkboxes, radios, or switches — not `div` with a heading:
|
|
187
|
+
|
|
188
|
+
```svelte
|
|
189
|
+
<script lang="ts">
|
|
190
|
+
import * as Field from "$lib/components/ui/field";
|
|
191
|
+
import { Checkbox } from "$lib/components/ui/checkbox";
|
|
192
|
+
</script>
|
|
193
|
+
|
|
194
|
+
<Field.FieldSet>
|
|
195
|
+
<Field.FieldLegend variant="label">Preferences</Field.FieldLegend>
|
|
196
|
+
<Field.FieldDescription>Select all that apply.</Field.FieldDescription>
|
|
197
|
+
<Field.FieldGroup class="gap-3">
|
|
198
|
+
<Field.Field orientation="horizontal">
|
|
199
|
+
<Checkbox id="dark" />
|
|
200
|
+
<Field.FieldLabel for="dark" class="font-normal"
|
|
201
|
+
>Dark mode</Field.FieldLabel
|
|
202
|
+
>
|
|
203
|
+
</Field.Field>
|
|
204
|
+
</Field.FieldGroup>
|
|
205
|
+
</Field.FieldSet>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Field validation and disabled states
|
|
211
|
+
|
|
212
|
+
Both attributes are needed — `data-invalid`/`data-disabled` styles the field (label, description), while `aria-invalid`/`disabled` styles the control.
|
|
213
|
+
|
|
214
|
+
```svelte
|
|
215
|
+
<script lang="ts">
|
|
216
|
+
import * as Field from "$lib/components/ui/field";
|
|
217
|
+
import { Input } from "$lib/components/ui/input";
|
|
218
|
+
</script>
|
|
219
|
+
|
|
220
|
+
<!-- Invalid. -->
|
|
221
|
+
<Field.Field data-invalid>
|
|
222
|
+
<Field.FieldLabel for="email">Email</Field.FieldLabel>
|
|
223
|
+
<Input id="email" aria-invalid />
|
|
224
|
+
<Field.FieldDescription>Invalid email address.</Field.FieldDescription>
|
|
225
|
+
</Field.Field>
|
|
226
|
+
|
|
227
|
+
<!-- Disabled. -->
|
|
228
|
+
<Field.Field data-disabled>
|
|
229
|
+
<Field.FieldLabel for="email">Email</Field.FieldLabel>
|
|
230
|
+
<Input id="email" disabled />
|
|
231
|
+
</Field.Field>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Works for all controls: `Input`, `Textarea`, `Select`, `Checkbox`, `RadioGroupItem`, `Switch`, `Slider`, `NativeSelect`, `InputOTP`.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Icons
|
|
2
|
+
|
|
3
|
+
**Always use the project's configured `iconLibrary` for imports.** Check the `iconLibrary` field in `components.json`: `lucide` → `@lucide/svelte`, `tabler` → `@tabler/icons-svelte`, etc. Never assume `@lucide/svelte`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Icons in Button use data-icon attribute
|
|
8
|
+
|
|
9
|
+
Add `data-icon="inline-start"` (prefix) or `data-icon="inline-end"` (suffix) to the icon. No sizing classes on the icon.
|
|
10
|
+
|
|
11
|
+
**Incorrect:**
|
|
12
|
+
|
|
13
|
+
```svelte
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { Button } from "$lib/components/ui/button";
|
|
16
|
+
import SearchIcon from "@lucide/svelte/icons/search";
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<Button>
|
|
20
|
+
<SearchIcon class="mr-2 size-4" />
|
|
21
|
+
Search
|
|
22
|
+
</Button>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct:**
|
|
26
|
+
|
|
27
|
+
```svelte
|
|
28
|
+
<script lang="ts">
|
|
29
|
+
import { Button } from "$lib/components/ui/button";
|
|
30
|
+
import SearchIcon from "@lucide/svelte/icons/search";
|
|
31
|
+
import ArrowRightIcon from "@lucide/svelte/icons/arrow-right";
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<Button>
|
|
35
|
+
<SearchIcon data-icon="inline-start" />
|
|
36
|
+
Search
|
|
37
|
+
</Button>
|
|
38
|
+
|
|
39
|
+
<Button>
|
|
40
|
+
Next
|
|
41
|
+
<ArrowRightIcon data-icon="inline-end" />
|
|
42
|
+
</Button>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## No sizing classes on icons inside components
|
|
48
|
+
|
|
49
|
+
Components handle icon sizing via CSS. Don't add `size-4`, `w-4 h-4`, or other sizing classes to icons inside `<Button>`, `DropdownMenu.Item`, `Alert.Root`, `Sidebar.*`, or other shadcn-svelte components — unless the user explicitly asks for custom icon sizes.
|
|
50
|
+
|
|
51
|
+
**Incorrect:**
|
|
52
|
+
|
|
53
|
+
```svelte
|
|
54
|
+
<script lang="ts">
|
|
55
|
+
import { Button } from "$lib/components/ui/button";
|
|
56
|
+
import SearchIcon from "@lucide/svelte/icons/search";
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<Button>
|
|
60
|
+
<SearchIcon class="size-4" data-icon="inline-start" />
|
|
61
|
+
Search
|
|
62
|
+
</Button>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Correct:**
|
|
66
|
+
|
|
67
|
+
```svelte
|
|
68
|
+
<script lang="ts">
|
|
69
|
+
import { Button } from "$lib/components/ui/button";
|
|
70
|
+
import SearchIcon from "@lucide/svelte/icons/search";
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
<Button>
|
|
74
|
+
<SearchIcon data-icon="inline-start" />
|
|
75
|
+
Search
|
|
76
|
+
</Button>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The same applies to icons inside `DropdownMenu.Item`, sidebar items, and other menu rows — no extra sizing classes on the icon component.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Pass icons as components, not string keys
|
|
84
|
+
|
|
85
|
+
Use a component reference, not a string key to a lookup map.
|
|
86
|
+
|
|
87
|
+
**Incorrect:**
|
|
88
|
+
|
|
89
|
+
```svelte
|
|
90
|
+
<!-- String key lookup — avoid -->
|
|
91
|
+
<DynamicIcon name="check" />
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Correct:**
|
|
95
|
+
|
|
96
|
+
```svelte
|
|
97
|
+
<script lang="ts">
|
|
98
|
+
import type { Component } from "svelte";
|
|
99
|
+
import CheckIcon from "@lucide/svelte/icons/check";
|
|
100
|
+
|
|
101
|
+
let { Icon }: { Icon: Component } = $props();
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<Icon />
|
|
105
|
+
|
|
106
|
+
<!-- <StatusBadge Icon={CheckIcon} /> -->
|
|
107
|
+
```
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Styling & Customization
|
|
2
|
+
|
|
3
|
+
See [customization.md](../customization.md) for theming, CSS variables, and adding custom colors.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- Semantic colors
|
|
8
|
+
- Built-in variants first
|
|
9
|
+
- class for layout only
|
|
10
|
+
- No space-x-_ / space-y-_
|
|
11
|
+
- Prefer size-_ over w-_ h-\* when equal
|
|
12
|
+
- Prefer truncate shorthand
|
|
13
|
+
- No manual dark: color overrides
|
|
14
|
+
- Use cn() for conditional classes
|
|
15
|
+
- No manual z-index on overlay components
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Semantic colors
|
|
20
|
+
|
|
21
|
+
**Incorrect:**
|
|
22
|
+
|
|
23
|
+
```svelte
|
|
24
|
+
<div class="bg-blue-500 text-white">
|
|
25
|
+
<p class="text-gray-600">Secondary text</p>
|
|
26
|
+
</div>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Correct:**
|
|
30
|
+
|
|
31
|
+
```svelte
|
|
32
|
+
<div class="bg-primary text-primary-foreground">
|
|
33
|
+
<p class="text-muted-foreground">Secondary text</p>
|
|
34
|
+
</div>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## No raw color values for status/state indicators
|
|
40
|
+
|
|
41
|
+
For positive, negative, or status indicators, use Badge variants, semantic tokens like `text-destructive`, or define custom CSS variables — don't reach for raw Tailwind colors.
|
|
42
|
+
|
|
43
|
+
**Incorrect:**
|
|
44
|
+
|
|
45
|
+
```svelte
|
|
46
|
+
<span class="text-emerald-600">+20.1%</span>
|
|
47
|
+
<span class="text-green-500">Active</span>
|
|
48
|
+
<span class="text-red-600">-3.2%</span>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Correct:**
|
|
52
|
+
|
|
53
|
+
```svelte
|
|
54
|
+
<script lang="ts">
|
|
55
|
+
import { Badge } from "$lib/components/ui/badge";
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<Badge variant="secondary">+20.1%</Badge>
|
|
59
|
+
<Badge>Active</Badge>
|
|
60
|
+
<span class="text-destructive">-3.2%</span>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If you need a success/positive color that doesn't exist as a semantic token, use a Badge variant or ask the user about adding a custom CSS variable to the theme (see [customization.md](../customization.md)).
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Built-in variants first
|
|
68
|
+
|
|
69
|
+
**Incorrect:**
|
|
70
|
+
|
|
71
|
+
```svelte
|
|
72
|
+
<script lang="ts">
|
|
73
|
+
import { Button } from "$lib/components/ui/button";
|
|
74
|
+
</script>
|
|
75
|
+
|
|
76
|
+
<Button class="border-input hover:bg-accent border bg-transparent"
|
|
77
|
+
>Click me</Button
|
|
78
|
+
>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Correct:**
|
|
82
|
+
|
|
83
|
+
```svelte
|
|
84
|
+
<script lang="ts">
|
|
85
|
+
import { Button } from "$lib/components/ui/button";
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<Button variant="outline">Click me</Button>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## class for layout only
|
|
94
|
+
|
|
95
|
+
Use `class` for layout (e.g. `max-w-md`, `mx-auto`, `mt-4`), **not** for overriding component colors or typography. To change colors, use semantic tokens, built-in variants, or CSS variables.
|
|
96
|
+
|
|
97
|
+
**Incorrect:**
|
|
98
|
+
|
|
99
|
+
```svelte
|
|
100
|
+
<script lang="ts">
|
|
101
|
+
import * as Card from "$lib/components/ui/card";
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<Card.Root class="bg-blue-100 font-bold text-blue-900">
|
|
105
|
+
<Card.Content>Dashboard</Card.Content>
|
|
106
|
+
</Card.Root>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Correct:**
|
|
110
|
+
|
|
111
|
+
```svelte
|
|
112
|
+
<script lang="ts">
|
|
113
|
+
import * as Card from "$lib/components/ui/card";
|
|
114
|
+
</script>
|
|
115
|
+
|
|
116
|
+
<Card.Root class="mx-auto max-w-md">
|
|
117
|
+
<Card.Content>Dashboard</Card.Content>
|
|
118
|
+
</Card.Root>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
To customize a component's appearance, prefer these approaches in order:
|
|
122
|
+
|
|
123
|
+
1. **Built-in variants** — `variant="outline"`, `variant="destructive"`, etc.
|
|
124
|
+
2. **Semantic color tokens** — `bg-primary`, `text-muted-foreground`.
|
|
125
|
+
3. **CSS variables** — define custom colors in the global CSS file (see [customization.md](../customization.md)).
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## No space-x-_ / space-y-_
|
|
130
|
+
|
|
131
|
+
Use `gap-*` instead. `space-y-4` → `flex flex-col gap-4`. `space-x-2` → `flex gap-2`.
|
|
132
|
+
|
|
133
|
+
```svelte
|
|
134
|
+
<script lang="ts">
|
|
135
|
+
import { Input } from "$lib/components/ui/input";
|
|
136
|
+
import { Button } from "$lib/components/ui/button";
|
|
137
|
+
</script>
|
|
138
|
+
|
|
139
|
+
<div class="flex flex-col gap-4">
|
|
140
|
+
<Input />
|
|
141
|
+
<Input />
|
|
142
|
+
<Button>Submit</Button>
|
|
143
|
+
</div>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Prefer size-_ over w-_ h-\* when equal
|
|
149
|
+
|
|
150
|
+
`size-10` not `w-10 h-10`. Applies to icons, avatars, skeletons, etc.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Prefer truncate shorthand
|
|
155
|
+
|
|
156
|
+
`truncate` not `overflow-hidden text-ellipsis whitespace-nowrap`.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## No manual dark: color overrides
|
|
161
|
+
|
|
162
|
+
Use semantic tokens — they handle light/dark via CSS variables. `bg-background text-foreground` not `bg-white dark:bg-gray-950`.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Use cn() for conditional classes
|
|
167
|
+
|
|
168
|
+
Use the `cn()` utility from the project for conditional or merged class names. Don't write manual ternaries in `class` strings.
|
|
169
|
+
|
|
170
|
+
**Incorrect:**
|
|
171
|
+
|
|
172
|
+
```svelte
|
|
173
|
+
<script lang="ts">
|
|
174
|
+
let isActive = $state(false);
|
|
175
|
+
</script>
|
|
176
|
+
|
|
177
|
+
<div class={`flex items-center ${isActive ? "bg-primary text-primary-foreground" : "bg-muted"}`}>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Correct:**
|
|
181
|
+
|
|
182
|
+
```svelte
|
|
183
|
+
<script lang="ts">
|
|
184
|
+
import { cn } from "$lib/utils";
|
|
185
|
+
let isActive = $state(false);
|
|
186
|
+
</script>
|
|
187
|
+
|
|
188
|
+
<div class={cn("flex items-center", isActive ? "bg-primary text-primary-foreground" : "bg-muted")}>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## No manual z-index on overlay components
|
|
194
|
+
|
|
195
|
+
`Dialog`, `Sheet`, `Drawer`, `AlertDialog`, `DropdownMenu`, `Popover`, `Tooltip`, `HoverCard` handle their own stacking. Never add `z-50` or `z-[999]`.
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: svas
|
|
3
|
+
description: >
|
|
4
|
+
Async Svelte stores (svas): fetching, caching, revalidation, persistence.
|
|
5
|
+
Use when UI presents data from the API.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# svas — Svelte Async Stores
|
|
9
|
+
|
|
10
|
+
Stores that fetch lazily, cache, revalidate, and persist. Every store emits one of three types:
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
type Maybe<T, E extends Error = Error> = null | T | E
|
|
14
|
+
// null → no data yet (loading / cleared / not fetched)
|
|
15
|
+
// T → resolved value
|
|
16
|
+
// E → fetch error (errors are values, never thrown)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import {
|
|
21
|
+
value, values, collection, // stores
|
|
22
|
+
ok, ensure, having, awaited, once, // guards & awaiting
|
|
23
|
+
combined, sync, Async, // compose & render
|
|
24
|
+
type Maybe
|
|
25
|
+
} from 'svas'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Shared lifecycle
|
|
29
|
+
|
|
30
|
+
Every store fetches on **first subscribe**, then auto-revalidates. Common options:
|
|
31
|
+
|
|
32
|
+
| Option | Meaning |
|
|
33
|
+
|--------|---------|
|
|
34
|
+
| `get` | fetcher returning `Promise<T \| Error>` |
|
|
35
|
+
| `revalidate` | ms before re-fetch (default `300_000`; `Infinity` disables) |
|
|
36
|
+
| `persist` | mirror into local storage under this key |
|
|
37
|
+
| `session` | use `sessionStorage` instead of `localStorage` |
|
|
38
|
+
| `stale` | keep previous value visible while revalidating (default `false`) |
|
|
39
|
+
| `bind` | `Readable<unknown \| null>` — reset/clear store when bound store is `null` (tie data to a user) |
|
|
40
|
+
| `default` | initial value when nothing is persisted |
|
|
41
|
+
|
|
42
|
+
## Stores
|
|
43
|
+
|
|
44
|
+
All stores implements Readable interface from svelte/store.
|
|
45
|
+
|
|
46
|
+
Use `persist` whenever it makes sense to persist the data, it will vastly speed up the initial load.
|
|
47
|
+
If store contains user-bound data, use `bind` to reset the store when the user is logged out.
|
|
48
|
+
|
|
49
|
+
### `value<T>` — one async value
|
|
50
|
+
|
|
51
|
+
`Writable<T | null>`. For single fetched values, auth tokens, transient UI flags.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const me = value<User>({ get: () => api.me(), persist: 'user' })
|
|
55
|
+
const seen = value<number>({ persist: 'seen', default: 0 }) // transient/local-only
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Methods: `set(v)`, `update(fn)`, `extract(): T | null` (sync read), `sync()` (revalidate if stale).
|
|
59
|
+
|
|
60
|
+
### `values<T>` — keyed cache
|
|
61
|
+
|
|
62
|
+
A map of independent `Readable<Maybe<T>>` lifecycles, one per key.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
const products = values<Product>({ get: (id) => api.product(id), stale: true, persist: 'products' })
|
|
66
|
+
|
|
67
|
+
const one = products.get('42') // Readable<Maybe<Product>>, fetches if missing
|
|
68
|
+
products.set('42', next) // write by key
|
|
69
|
+
products.extract('42') // Product | null, sync
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Methods: `get(key, { fetch? })` · `set(key, v, { stash? })` · `reset(key)` (restore stashed value) · `extract(key)` · `delete(key)` · `clear()`.
|
|
73
|
+
|
|
74
|
+
Extra options: `permanent` (don't revalidate persisted entries on startup). `stash: true` on `set` remembers the prior persisted value so `reset(key)` can roll back — use for optimistic updates.
|
|
75
|
+
|
|
76
|
+
### `collection<T>` — list of `Identifiable` items
|
|
77
|
+
|
|
78
|
+
`Readable<Maybe<T[]>>`. Items must have `{ id: string }`. Pass a `values` store to also observe items individually via `get(id)`.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
const todos = collection<Todo>({
|
|
82
|
+
get: () => api.todos(),
|
|
83
|
+
values: values<Todo>(), // enables todos.get(id) / extract(id)
|
|
84
|
+
stale: true,
|
|
85
|
+
persist: 'todos',
|
|
86
|
+
bind: session
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Methods: `subscribe` · `add(item)` · `set(item, { add? })` (replace by id; `add` inserts if absent) · `update(id, fn, opts?)` · `delete(id)` · `replace(items)` · `get(id)`/`extract(id)` (require `values`) · `sync(): this` · `fetch(): Promise<this>`.
|
|
91
|
+
|
|
92
|
+
Mutations mirror into the `values` store, so components subscribed via `get(id)` update without re-fetching.
|
|
93
|
+
|
|
94
|
+
## Guards & extraction
|
|
95
|
+
|
|
96
|
+
Never use `?.` on a `Maybe<T>` — an `Error` has no domain properties. Narrow first.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
ok($store) // boolean type guard: narrows Maybe<T> → T (excludes null | Error)
|
|
100
|
+
ensure(store) // sync read, THROWS if null/Error — use when value must exist now (e.g. unsafe net requests in response to user action)
|
|
101
|
+
store.extract(key?) // sync read, T | null (ignores errors) — never throws
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
if (ok($todos)) $todos.length // typed as T
|
|
106
|
+
items.filter((i) => ok(i.account) && !i.account.deleted) // ✅ guard before access
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Awaiting
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
await having(store) // first non-null value; REJECTS on Error — services needing auth
|
|
113
|
+
await awaited(store) // first non-null value; returns Error as a value (never rejects)
|
|
114
|
+
await once(store, (v) => v === 'ready') // first value satisfying a condition
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Compose & render
|
|
118
|
+
|
|
119
|
+
### `<Async>` — render a `Maybe`
|
|
120
|
+
|
|
121
|
+
```svelte
|
|
122
|
+
<Async store={todos}>
|
|
123
|
+
{#snippet awaited(todos)}
|
|
124
|
+
<!-- here todos are T[] -->
|
|
125
|
+
{#each todos as t}<Row {t} />{/each}
|
|
126
|
+
{/snippet}
|
|
127
|
+
{#snippet waiting()}<Spinner />{/snippet} <!-- optional; default loader otherwise -->
|
|
128
|
+
{#snippet error(e)}<Err {e} />{/snippet} <!-- optional; default error UI otherwise -->
|
|
129
|
+
</Async>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Props: `store` (required), `awaited` snippet (required), optional `waiting` / `error` snippets, `silent` (suppress default loader/error chrome). Combine with `combined` to await several at once.
|
|
133
|
+
|
|
134
|
+
### `combined(...stores)`
|
|
135
|
+
|
|
136
|
+
One `Maybe` from many: tuple when **all** resolve, first `Error`, else `null`. Spreadable.
|
|
137
|
+
|
|
138
|
+
```svelte
|
|
139
|
+
<Async store={combined(account, todos)}>
|
|
140
|
+
{#snippet awaited([account, todos])}
|
|
141
|
+
<!-- here account is U and todos is T[] -->
|
|
142
|
+
<Profile {account} />
|
|
143
|
+
{#each todos as t}<Row {t} />{/each}
|
|
144
|
+
{/snippet}
|
|
145
|
+
</Async>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### `sync(store, item, { delete? })`
|
|
149
|
+
|
|
150
|
+
Conflict-free update.
|
|
151
|
+
|
|
152
|
+
T must implement interface Comparable { id: string; _version: number;_deleted?: number | null }
|
|
153
|
+
|
|
154
|
+
Merge a versioned item into a `collection` or `value`, respecting `_version`; removes on `_deleted` (unless `delete: false`). For applying server/realtime events.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
events.on('todos.sync', (todo) => sync(todos, todo))
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Rules
|
|
161
|
+
|
|
162
|
+
- **Errors are values** — fetchers and services return `T | Error`; check `instanceof Error`, never `try/catch` for expected failures.
|
|
163
|
+
- **Guard before access** — `ok()`/`ensure()`/`extract()`, never `?.` on `Maybe<T>`.
|
|
164
|
+
- **One store per source** — derive everything else; don't duplicate fetched data into local state.
|
|
165
|
+
- **Lazy by design** — a store does nothing until subscribed; `$store`, `<Async>`, `get`, `having`, or `.subscribe` triggers it.
|
|
166
|
+
|
|
167
|
+
## Advanced
|
|
168
|
+
|
|
169
|
+
For derived `Maybe` stores with live subscriptions/cleanup, realtime event wiring, linked/enriched entities, and optimistic update patterns, see [references/patterns.md](references/patterns.md).
|