├── .changeset └── config.json ├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ └── publish.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .vscode ├── extensions.json └── tasks.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── components.json ├── eslint.config.js ├── jsrepo-build-config.json ├── jsrepo.json ├── messages ├── de.json ├── en.json └── fr.json ├── package.json ├── pnpm-lock.yaml ├── project.inlang ├── .gitignore ├── project_id └── settings.json ├── rules └── shadcn-svelte-extras.mdc ├── src ├── app.css ├── app.d.ts ├── app.html ├── hooks.server.ts ├── hooks.ts ├── lib │ ├── actions │ │ ├── active.svelte.ts │ │ ├── shortcut.svelte.ts │ │ └── typewriter.svelte.ts │ ├── components │ │ ├── app-sidebar.svelte │ │ ├── docs │ │ │ ├── code-span.svelte │ │ │ ├── command │ │ │ │ ├── command.svelte │ │ │ │ └── index.ts │ │ │ ├── examples │ │ │ │ ├── code-block.svelte │ │ │ │ ├── configure-device.svelte │ │ │ │ ├── editor-file-tree.svelte │ │ │ │ ├── file-drop-zone.svelte │ │ │ │ ├── index.ts │ │ │ │ ├── phone-number-setting.svelte │ │ │ │ ├── pm-command.svelte │ │ │ │ ├── review-form.svelte │ │ │ │ └── terminal.svelte │ │ │ ├── index.ts │ │ │ ├── jsrepo-command.svelte │ │ │ └── subheading.svelte │ │ ├── icons │ │ │ ├── css.svelte │ │ │ ├── github.svelte │ │ │ ├── index.ts │ │ │ ├── mcp.svelte │ │ │ ├── svelte.svelte │ │ │ └── typescript.svelte │ │ ├── installation.svelte │ │ ├── logo.svelte │ │ ├── page-wrapper.svelte │ │ ├── playground.svelte │ │ ├── search-button.svelte │ │ ├── shadcn-svelte-extras.svelte │ │ ├── site │ │ │ └── meta-tags │ │ │ │ ├── index.ts │ │ │ │ ├── meta-tags-context.svelte.ts │ │ │ │ └── meta-tags.svelte │ │ └── ui │ │ │ ├── accordion │ │ │ ├── accordion-content.svelte │ │ │ ├── accordion-item.svelte │ │ │ ├── accordion-root.svelte │ │ │ ├── accordion-trigger.svelte │ │ │ └── index.ts │ │ │ ├── avatar-group │ │ │ ├── avatar-group-etc.svelte │ │ │ ├── avatar-group-member.svelte │ │ │ ├── avatar-group.svelte │ │ │ └── index.ts │ │ │ ├── avatar │ │ │ ├── avatar-fallback.svelte │ │ │ ├── avatar-image.svelte │ │ │ ├── avatar.svelte │ │ │ └── index.ts │ │ │ ├── badge │ │ │ ├── badge.svelte │ │ │ └── index.ts │ │ │ ├── button │ │ │ ├── button.svelte │ │ │ └── index.ts │ │ │ ├── card │ │ │ ├── card-action.svelte │ │ │ ├── card-content.svelte │ │ │ ├── card-description.svelte │ │ │ ├── card-footer.svelte │ │ │ ├── card-header.svelte │ │ │ ├── card-title.svelte │ │ │ ├── card.svelte │ │ │ └── index.ts │ │ │ ├── chat │ │ │ ├── chat-bubble-avatar.svelte │ │ │ ├── chat-bubble-message.svelte │ │ │ ├── chat-bubble.svelte │ │ │ ├── chat-list.svelte │ │ │ ├── index.ts │ │ │ └── loading-dots.svelte │ │ │ ├── code │ │ │ ├── code.svelte │ │ │ ├── index.ts │ │ │ └── shiki.ts │ │ │ ├── collapsible │ │ │ ├── collapsible-content.svelte │ │ │ ├── collapsible-trigger.svelte │ │ │ ├── collapsible.svelte │ │ │ └── index.ts │ │ │ ├── command │ │ │ ├── command-dialog.svelte │ │ │ ├── command-empty.svelte │ │ │ ├── command-group.svelte │ │ │ ├── command-input.svelte │ │ │ ├── command-item.svelte │ │ │ ├── command-link-item.svelte │ │ │ ├── command-list.svelte │ │ │ ├── command-separator.svelte │ │ │ ├── command-shortcut.svelte │ │ │ ├── command.svelte │ │ │ └── index.ts │ │ │ ├── copy-button │ │ │ ├── copy-button.svelte │ │ │ └── index.ts │ │ │ ├── dialog │ │ │ ├── dialog-close.svelte │ │ │ ├── dialog-content.svelte │ │ │ ├── dialog-description.svelte │ │ │ ├── dialog-footer.svelte │ │ │ ├── dialog-header.svelte │ │ │ ├── dialog-overlay.svelte │ │ │ ├── dialog-title.svelte │ │ │ ├── dialog-trigger.svelte │ │ │ └── index.ts │ │ │ ├── drawer │ │ │ ├── drawer-close.svelte │ │ │ ├── drawer-content.svelte │ │ │ ├── drawer-description.svelte │ │ │ ├── drawer-footer.svelte │ │ │ ├── drawer-header.svelte │ │ │ ├── drawer-nested.svelte │ │ │ ├── drawer-overlay.svelte │ │ │ ├── drawer-title.svelte │ │ │ ├── drawer-trigger.svelte │ │ │ ├── drawer.svelte │ │ │ └── index.ts │ │ │ ├── dropdown-menu │ │ │ ├── dropdown-menu-checkbox-item.svelte │ │ │ ├── dropdown-menu-content.svelte │ │ │ ├── dropdown-menu-group-heading.svelte │ │ │ ├── dropdown-menu-group.svelte │ │ │ ├── dropdown-menu-item.svelte │ │ │ ├── dropdown-menu-label.svelte │ │ │ ├── dropdown-menu-radio-group.svelte │ │ │ ├── dropdown-menu-radio-item.svelte │ │ │ ├── dropdown-menu-separator.svelte │ │ │ ├── dropdown-menu-shortcut.svelte │ │ │ ├── dropdown-menu-sub-content.svelte │ │ │ ├── dropdown-menu-sub-trigger.svelte │ │ │ ├── dropdown-menu-trigger.svelte │ │ │ └── index.ts │ │ │ ├── field-set │ │ │ ├── field-set-content.svelte │ │ │ ├── field-set-footer.svelte │ │ │ ├── field-set-title.svelte │ │ │ ├── field-set.svelte │ │ │ └── index.ts │ │ │ ├── file-drop-zone │ │ │ ├── file-drop-zone.svelte │ │ │ └── index.ts │ │ │ ├── image-cropper │ │ │ ├── image-cropper-cancel.svelte │ │ │ ├── image-cropper-controls.svelte │ │ │ ├── image-cropper-crop.svelte │ │ │ ├── image-cropper-cropper.svelte │ │ │ ├── image-cropper-dialog.svelte │ │ │ ├── image-cropper-preview.svelte │ │ │ ├── image-cropper-upload-trigger.svelte │ │ │ ├── image-cropper.svelte │ │ │ ├── image-cropper.svelte.ts │ │ │ ├── index.ts │ │ │ ├── types.ts │ │ │ └── utils.ts │ │ │ ├── input │ │ │ ├── index.ts │ │ │ └── input.svelte │ │ │ ├── ipv4address-input │ │ │ ├── index.ts │ │ │ ├── ipv4address-input-input.svelte │ │ │ └── ipv4address-input.svelte │ │ │ ├── kbd │ │ │ ├── index.ts │ │ │ └── kbd.svelte │ │ │ ├── label │ │ │ ├── index.ts │ │ │ └── label.svelte │ │ │ ├── language-switcher │ │ │ ├── index.ts │ │ │ ├── language-switcher.svelte │ │ │ └── types.ts │ │ │ ├── light-switch │ │ │ ├── index.ts │ │ │ └── light-switch.svelte │ │ │ ├── link │ │ │ ├── index.ts │ │ │ └── link.svelte │ │ │ ├── modal │ │ │ ├── index.ts │ │ │ ├── modal-content.svelte │ │ │ ├── modal-description.svelte │ │ │ ├── modal-footer.svelte │ │ │ ├── modal-header.svelte │ │ │ ├── modal-title.svelte │ │ │ ├── modal-trigger.svelte │ │ │ ├── modal.svelte │ │ │ └── modal.svelte.ts │ │ │ ├── nlp-date-input │ │ │ ├── index.ts │ │ │ └── nlp-date-input.svelte │ │ │ ├── phone-input │ │ │ ├── country-selector.svelte │ │ │ ├── flag.svelte │ │ │ ├── index.ts │ │ │ └── phone-input.svelte │ │ │ ├── pm-command │ │ │ ├── index.ts │ │ │ └── pm-command.svelte │ │ │ ├── popover │ │ │ ├── index.ts │ │ │ ├── popover-content.svelte │ │ │ └── popover-trigger.svelte │ │ │ ├── prev-next │ │ │ ├── index.ts │ │ │ ├── next.svelte │ │ │ ├── prev-next.svelte │ │ │ └── previous.svelte │ │ │ ├── progress │ │ │ ├── index.ts │ │ │ └── progress.svelte │ │ │ ├── scroll-area │ │ │ ├── index.ts │ │ │ ├── scroll-area-scrollbar.svelte │ │ │ └── scroll-area.svelte │ │ │ ├── separator │ │ │ ├── index.ts │ │ │ └── separator.svelte │ │ │ ├── sheet │ │ │ ├── index.ts │ │ │ ├── sheet-close.svelte │ │ │ ├── sheet-content.svelte │ │ │ ├── sheet-description.svelte │ │ │ ├── sheet-footer.svelte │ │ │ ├── sheet-header.svelte │ │ │ ├── sheet-overlay.svelte │ │ │ ├── sheet-title.svelte │ │ │ └── sheet-trigger.svelte │ │ │ ├── sidebar │ │ │ ├── constants.ts │ │ │ ├── context.svelte.ts │ │ │ ├── index.ts │ │ │ ├── sidebar-content.svelte │ │ │ ├── sidebar-footer.svelte │ │ │ ├── sidebar-group-action.svelte │ │ │ ├── sidebar-group-content.svelte │ │ │ ├── sidebar-group-label.svelte │ │ │ ├── sidebar-group.svelte │ │ │ ├── sidebar-header.svelte │ │ │ ├── sidebar-input.svelte │ │ │ ├── sidebar-inset.svelte │ │ │ ├── sidebar-menu-action.svelte │ │ │ ├── sidebar-menu-badge.svelte │ │ │ ├── sidebar-menu-button.svelte │ │ │ ├── sidebar-menu-item.svelte │ │ │ ├── sidebar-menu-skeleton.svelte │ │ │ ├── sidebar-menu-sub-button.svelte │ │ │ ├── sidebar-menu-sub-item.svelte │ │ │ ├── sidebar-menu-sub.svelte │ │ │ ├── sidebar-menu.svelte │ │ │ ├── sidebar-provider.svelte │ │ │ ├── sidebar-rail.svelte │ │ │ ├── sidebar-separator.svelte │ │ │ ├── sidebar-trigger.svelte │ │ │ └── sidebar.svelte │ │ │ ├── skeleton │ │ │ ├── index.ts │ │ │ └── skeleton.svelte │ │ │ ├── snippet │ │ │ ├── index.ts │ │ │ └── snippet.svelte │ │ │ ├── sonner │ │ │ ├── index.ts │ │ │ └── sonner.svelte │ │ │ ├── star-rating │ │ │ ├── index.ts │ │ │ ├── star-rating-star.svelte │ │ │ ├── star-rating.svelte │ │ │ └── star-rating.svelte.ts │ │ │ ├── tabs │ │ │ ├── index.ts │ │ │ ├── tabs-content.svelte │ │ │ ├── tabs-list.svelte │ │ │ ├── tabs-trigger.svelte │ │ │ └── tabs.svelte │ │ │ ├── tags-input │ │ │ ├── index.ts │ │ │ ├── tags-input-tag.svelte │ │ │ ├── tags-input.svelte │ │ │ └── types.ts │ │ │ ├── terminal │ │ │ ├── index.ts │ │ │ ├── terminal-animated-span.svelte │ │ │ ├── terminal-loading.svelte │ │ │ ├── terminal-loop.svelte │ │ │ ├── terminal-typing-animation.svelte │ │ │ ├── terminal.svelte │ │ │ ├── terminal.svelte.ts │ │ │ └── types.ts │ │ │ ├── textarea │ │ │ ├── index.ts │ │ │ └── textarea.svelte │ │ │ ├── theme-selector │ │ │ ├── index.ts │ │ │ └── theme-selector.svelte │ │ │ ├── toc │ │ │ ├── index.ts │ │ │ └── toc.svelte │ │ │ ├── tooltip │ │ │ ├── index.ts │ │ │ ├── tooltip-content.svelte │ │ │ └── tooltip-trigger.svelte │ │ │ ├── tree-view │ │ │ ├── index.ts │ │ │ ├── tree-view-file.svelte │ │ │ ├── tree-view-folder.svelte │ │ │ └── tree-view.svelte │ │ │ └── window │ │ │ ├── index.ts │ │ │ └── window.svelte │ ├── context.ts │ ├── hooks │ │ ├── is-mobile.svelte.ts │ │ ├── use-auto-scroll.svelte.ts │ │ ├── use-boolean.svelte.ts │ │ ├── use-clipboard.svelte.ts │ │ ├── use-promise.svelte.ts │ │ └── use-toc.svelte.ts │ ├── map.ts │ ├── utils.ts │ └── utils │ │ ├── box.ts │ │ ├── ipv4-address.ts │ │ ├── is-number.ts │ │ ├── result.ts │ │ ├── sleep.ts │ │ ├── types.ts │ │ ├── types │ │ └── result.ts │ │ └── utils.ts └── routes │ ├── +layout.svelte │ ├── +page.svelte │ ├── actions │ ├── active │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ └── examples.ts │ └── shortcut │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ └── examples.ts │ ├── components │ ├── +page.server.ts │ ├── +page.svelte │ ├── avatar-group │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ └── vertical.svelte │ ├── button │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ ├── loading.svelte │ │ └── on-click-promise.svelte │ ├── chat │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── data.ts │ │ ├── examples.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── code │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ ├── highlight-lines.svelte │ │ ├── no-line-numbers.svelte │ │ ├── overflow.svelte │ │ └── variants.svelte │ ├── copy-button │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ ├── icon.svelte │ │ └── with-text.svelte │ ├── field-set │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── destructive.svelte │ │ └── examples.ts │ ├── file-drop-zone │ │ ├── +page.server.ts │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ ├── form.svelte │ │ └── schema.ts │ ├── image-cropper │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── custom-preview.svelte │ │ ├── custom-trigger.svelte │ │ ├── examples.ts │ │ ├── no-default-image.svelte │ │ └── square-preview.svelte │ ├── ipv4address-input │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ ├── placeholder.svelte │ │ ├── reactive.svelte │ │ └── valid.svelte │ ├── kbd │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ ├── sizes.svelte │ │ └── variants.svelte │ ├── language-switcher │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ ├── paraglide.svelte │ │ └── variants.svelte │ ├── light-switch │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ └── variants.svelte │ ├── link │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ └── examples.ts │ ├── modal │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ └── examples.ts │ ├── nlp-date-input │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ └── min-max.svelte │ ├── phone-input │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── custom-ordering.svelte │ │ ├── default-country.svelte │ │ ├── default-value.svelte │ │ └── examples.ts │ ├── pm-command │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── commands.svelte │ │ ├── customize-agents.svelte │ │ ├── examples.ts │ │ ├── overflow.svelte │ │ ├── persisted-pm.svelte │ │ └── variants.svelte │ ├── snippet │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ ├── multiline.svelte │ │ └── variants.svelte │ ├── star-rating │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── custom-color.svelte │ │ ├── custom-size.svelte │ │ ├── custom-stars.svelte │ │ ├── disabled.svelte │ │ ├── examples.ts │ │ ├── half-rating.svelte │ │ └── readonly.svelte │ ├── tags-input │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── custom-validate.ts │ │ ├── examples.ts │ │ └── lowercase.svelte │ ├── terminal │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ └── loop.svelte │ ├── theme-selector │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ └── variants.svelte │ ├── toc │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── examples.ts │ │ └── toc.ts │ ├── tree-view │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ ├── custom-icons.svelte │ │ ├── examples.ts │ │ └── tree-view-file-custom.svelte │ └── window │ │ ├── +page.svelte │ │ ├── basic.svelte │ │ └── examples.ts │ ├── docs │ ├── installation │ │ └── +page.svelte │ ├── introduction │ │ └── +page.svelte │ └── using-extras │ │ ├── +page.server.ts │ │ └── +page.svelte │ └── hooks │ ├── use-auto-scroll │ └── +page.svelte │ ├── use-boolean │ └── +page.svelte │ ├── use-clipboard │ └── +page.svelte │ ├── use-promise │ ├── +page.svelte │ ├── basic.svelte │ └── examples.ts │ └── use-toc │ └── +page.svelte ├── static ├── dark.svg ├── favicon.png ├── favicon.svg ├── light.svg └── og.png ├── svelte.config.js ├── tsconfig.json └── vite.config.ts /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", 3 | "changelog": [ 4 | "@svitejs/changesets-changelog-github-compact", 5 | { "repo": "ieedan/shadcn-svelte-extras" } 6 | ], 7 | "commit": false, 8 | "fixed": [], 9 | "linked": [], 10 | "access": "restricted", 11 | "baseBranch": "main", 12 | "updateInternalDependencies": "patch", 13 | "ignore": [], 14 | "privatePackages": { 15 | "version": true, 16 | "tag": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ieedan] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: [main] 6 | 7 | jobs: 8 | CI: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: pnpm/action-setup@v4 13 | - uses: actions/setup-node@v4 14 | with: 15 | node-version: '20' 16 | 17 | - name: Install dependencies 18 | run: pnpm install 19 | 20 | - name: Generate i18n files and Lint 21 | run: pnpm generate-i18n && pnpm lint 22 | 23 | - name: Check 24 | run: pnpm check 25 | 26 | - name: Build Registry 27 | run: pnpm build:registry 28 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | name: Build & Publish Release 13 | if: github.repository == 'ieedan/shadcn-svelte-extras' 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: pnpm/action-setup@v4 19 | - uses: actions/setup-node@v4 20 | with: 21 | node-version: '20' 22 | cache: pnpm 23 | 24 | - name: Install dependencies 25 | run: pnpm install 26 | 27 | - name: Kit Sync 28 | run: pnpm sync 29 | 30 | - name: Create Release Pull Request or Publish 31 | id: changesets 32 | uses: changesets/action@v1 33 | with: 34 | commit: 'chore(release): version package' 35 | title: 'chore(release): version package' 36 | publish: pnpm ci:release 37 | env: 38 | JSREPO_TOKEN: ${{ secrets.JSREPO_TOKEN }} 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 40 | NODE_ENV: production 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | # Output 4 | .output 5 | .vercel 6 | .netlify 7 | .wrangler 8 | /.svelte-kit 9 | /build 10 | 11 | # OS 12 | .DS_Store 13 | Thumbs.db 14 | 15 | # Env 16 | .env 17 | .env.* 18 | !.env.example 19 | !.env.test 20 | 21 | # Vite 22 | vite.config.js.timestamp-* 23 | vite.config.ts.timestamp-* 24 | 25 | # Generated code 26 | src/lib/paraglide/ 27 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Package Managers 2 | package-lock.json 3 | pnpm-lock.yaml 4 | yarn.lock 5 | 6 | CHANGELOG.md 7 | 8 | # Generated code 9 | src/lib/paraglide/ 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], 7 | "tailwindFunctions": ["tv"], 8 | "overrides": [ 9 | { 10 | "files": "*.svelte", 11 | "options": { 12 | "parser": "svelte" 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["inlang.vs-code-extension"] 3 | } 4 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://next.shadcn-svelte.com/schema.json", 3 | "tailwind": { 4 | "css": "src/app.css", 5 | "baseColor": "zinc" 6 | }, 7 | "aliases": { 8 | "components": "$lib/components", 9 | "utils": "$lib/utils/utils", 10 | "ui": "$lib/components/ui", 11 | "hooks": "$lib/hooks", 12 | "lib": "$lib" 13 | }, 14 | "typescript": true, 15 | "registry": "https://next.shadcn-svelte.com/registry" 16 | } 17 | -------------------------------------------------------------------------------- /jsrepo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/jsrepo@1.32.0/schemas/project-config.json", 3 | "repos": ["@ieedan/std"], 4 | "includeTests": false, 5 | "watermark": true, 6 | "formatter": "prettier", 7 | "paths": { 8 | "*": "./src/blocks", 9 | "types": "$lib/utils/types", 10 | "utils": "$lib/utils", 11 | "ui": "$lib/components/ui", 12 | "hooks": "$lib/hooks", 13 | "ts": "$lib/utils" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /messages/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://inlang.com/schema/inlang-message-format", 3 | "example_message": "Hallo Welt!" 4 | } 5 | -------------------------------------------------------------------------------- /messages/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://inlang.com/schema/inlang-message-format", 3 | "example_message": "Hello world!" 4 | } 5 | -------------------------------------------------------------------------------- /messages/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://inlang.com/schema/inlang-message-format", 3 | "example_message": "Bonjour le monde!" 4 | } 5 | -------------------------------------------------------------------------------- /project.inlang/.gitignore: -------------------------------------------------------------------------------- 1 | cache -------------------------------------------------------------------------------- /project.inlang/project_id: -------------------------------------------------------------------------------- 1 | WLYo10jJ5EIfuDcXFX -------------------------------------------------------------------------------- /project.inlang/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://inlang.com/schema/project-settings", 3 | "baseLocale": "en", 4 | "locales": ["en", "de", "fr"], 5 | "modules": [ 6 | "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js", 7 | "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js" 8 | ], 9 | "plugin.inlang.messageFormat": { 10 | "pathPattern": "./messages/{locale}.json" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /rules/shadcn-svelte-extras.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: 4 | alwaysApply: true 5 | --- 6 | Before creating a new component try to find a component already in `@ieedan/shadcn-svelte-extras` with jsrepo. If I am using a pinned version in my [jsrepo.json](mdc:jsrepo.json) file please use that version when fetching components i.e. `@ieedan/shadcn-svelte-extras@1.0.0/ts/math`. 7 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | // See https://svelte.dev/docs/kit/types#app.d.ts 2 | // for information about these interfaces 3 | declare global { 4 | namespace App { 5 | // interface Error {} 6 | // interface Locals {} 7 | // interface PageData {} 8 | // interface PageState {} 9 | // interface Platform {} 10 | } 11 | } 12 | 13 | export {}; 14 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/hooks.server.ts: -------------------------------------------------------------------------------- 1 | import type { Handle } from '@sveltejs/kit'; 2 | import { paraglideMiddleware } from '$lib/paraglide/server'; 3 | 4 | // creating a handle to use the paraglide middleware 5 | const paraglideHandle: Handle = ({ event, resolve }) => 6 | paraglideMiddleware(event.request, ({ request: localizedRequest, locale }) => { 7 | event.request = localizedRequest; 8 | return resolve(event, { 9 | transformPageChunk: ({ html }) => { 10 | return html.replace('%lang%', locale); 11 | } 12 | }); 13 | }); 14 | 15 | export const handle: Handle = paraglideHandle; 16 | -------------------------------------------------------------------------------- /src/hooks.ts: -------------------------------------------------------------------------------- 1 | import type { Reroute } from '@sveltejs/kit'; 2 | import { deLocalizeUrl } from '$lib/paraglide/runtime'; 3 | 4 | export const reroute: Reroute = (request) => { 5 | return deLocalizeUrl(request.url).pathname; 6 | }; 7 | -------------------------------------------------------------------------------- /src/lib/actions/typewriter.svelte.ts: -------------------------------------------------------------------------------- 1 | import { createAttachmentKey } from 'svelte/attachments'; 2 | import type { TransitionConfig } from 'svelte/transition'; 3 | 4 | export type Options = { 5 | speed: number; 6 | delay: number; 7 | onComplete?: () => void; 8 | }; 9 | 10 | export const typewriter = ( 11 | node: HTMLElement, 12 | { speed = 1, delay = 0, onComplete }: Partial 13 | ) => { 14 | const text = node.textContent ?? ''; 15 | const duration = text.length / (speed * 0.01); 16 | 17 | return { 18 | delay, 19 | duration, 20 | tick: (t) => { 21 | const i = Math.trunc(text.length * t); 22 | node.textContent = text.slice(0, i); 23 | if (node.textContent.length === text.length) onComplete?.(); 24 | } 25 | } satisfies TransitionConfig; 26 | }; 27 | 28 | export function attachTypewriter(opts: Partial = {}) { 29 | return { 30 | [createAttachmentKey()]: (node: HTMLElement) => typewriter(node, opts) 31 | }; 32 | } 33 | -------------------------------------------------------------------------------- /src/lib/components/docs/code-span.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | {@render children?.()} 14 | 15 | -------------------------------------------------------------------------------- /src/lib/components/docs/command/index.ts: -------------------------------------------------------------------------------- 1 | import Command from './command.svelte'; 2 | 3 | export { Command }; 4 | -------------------------------------------------------------------------------- /src/lib/components/docs/examples/code-block.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 |
15 |
16 | 17 | 18 | src/routes/+layout.svelte 19 | 20 |
21 | 22 |
23 | 24 |
25 | -------------------------------------------------------------------------------- /src/lib/components/docs/examples/index.ts: -------------------------------------------------------------------------------- 1 | import ReviewForm from './review-form.svelte'; 2 | import ConfigureDevice from './configure-device.svelte'; 3 | import PhoneNumberSetting from './phone-number-setting.svelte'; 4 | import CodeBlock from './code-block.svelte'; 5 | import EditorFileTree from './editor-file-tree.svelte'; 6 | import Terminal from './terminal.svelte'; 7 | import FileDropZone from './file-drop-zone.svelte'; 8 | import PmCommand from './pm-command.svelte'; 9 | 10 | export { 11 | ReviewForm, 12 | PmCommand, 13 | ConfigureDevice, 14 | PhoneNumberSetting, 15 | CodeBlock, 16 | EditorFileTree, 17 | Terminal, 18 | FileDropZone 19 | }; 20 | -------------------------------------------------------------------------------- /src/lib/components/docs/examples/phone-number-setting.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | Phone Number 12 | 13 | 14 | 15 | Add your phone number. 16 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/lib/components/docs/examples/pm-command.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/lib/components/docs/index.ts: -------------------------------------------------------------------------------- 1 | import Subheading from './subheading.svelte'; 2 | import CodeSpan from './code-span.svelte'; 3 | 4 | export { Subheading, CodeSpan }; 5 | -------------------------------------------------------------------------------- /src/lib/components/docs/subheading.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 |

26 | {@render children?.()} 27 |

28 | -------------------------------------------------------------------------------- /src/lib/components/icons/index.ts: -------------------------------------------------------------------------------- 1 | import type { HTMLAttributes } from 'svelte/elements'; 2 | import GitHub from './github.svelte'; 3 | import Svelte from './svelte.svelte'; 4 | import CSS from './css.svelte'; 5 | import MCP from './mcp.svelte'; 6 | import TypeScript from './typescript.svelte'; 7 | 8 | export interface Props extends HTMLAttributes { 9 | class?: string; 10 | width?: number; 11 | height?: number; 12 | } 13 | 14 | export { GitHub, Svelte, CSS, TypeScript, MCP }; 15 | -------------------------------------------------------------------------------- /src/lib/components/installation.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | Installation 13 | 14 | -------------------------------------------------------------------------------- /src/lib/components/search-button.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 31 | -------------------------------------------------------------------------------- /src/lib/components/shadcn-svelte-extras.svelte: -------------------------------------------------------------------------------- 1 | shadcn-svelte-extras 2 | -------------------------------------------------------------------------------- /src/lib/components/site/meta-tags/index.ts: -------------------------------------------------------------------------------- 1 | export { default as MetaTags } from './meta-tags.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/site/meta-tags/meta-tags-context.svelte.ts: -------------------------------------------------------------------------------- 1 | import { Context } from 'runed'; 2 | import type { ReadableBoxedValues } from 'svelte-toolbelt'; 3 | import { deepMerge, type MetaTagsProps } from 'svelte-meta-tags'; 4 | 5 | export type RootStateProps = ReadableBoxedValues<{ 6 | props: Partial; 7 | }>; 8 | 9 | export class MetaTagsRootState { 10 | constructor( 11 | readonly base: MetaTagsRootState | null, 12 | readonly opts: RootStateProps 13 | ) { 14 | if (this.base === null) { 15 | ctx.set(this); 16 | } 17 | } 18 | 19 | get props() { 20 | const baseProps: Partial = this.base ? this.base.props : {}; 21 | 22 | return deepMerge(baseProps, this.opts.props.current); 23 | } 24 | } 25 | 26 | const ctx = new Context('meta-tags-ctx'); 27 | 28 | export function useMetaTags(opts: RootStateProps) { 29 | let base: MetaTagsRootState | null; 30 | try { 31 | base = ctx.get(); 32 | } catch { 33 | base = null; 34 | } 35 | 36 | return new MetaTagsRootState(base, opts); 37 | } 38 | -------------------------------------------------------------------------------- /src/lib/components/site/meta-tags/meta-tags.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/lib/components/ui/accordion/accordion-content.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 |
23 | {@render children?.()} 24 |
25 |
26 | -------------------------------------------------------------------------------- /src/lib/components/ui/accordion/accordion-item.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/accordion/accordion-root.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/accordion/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './accordion-root.svelte'; 2 | import Content from './accordion-content.svelte'; 3 | import Item from './accordion-item.svelte'; 4 | import Trigger from './accordion-trigger.svelte'; 5 | 6 | export { 7 | Root, 8 | Content, 9 | Item, 10 | Trigger, 11 | // 12 | Root as Accordion, 13 | Content as AccordionContent, 14 | Item as AccordionItem, 15 | Trigger as AccordionTrigger 16 | }; 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar-group/avatar-group-etc.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
18 | +{plus} 19 |
20 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar-group/avatar-group-member.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar-group/avatar-group.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar-group/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './avatar-group.svelte'; 2 | import Member from './avatar-group-member.svelte'; 3 | import Etc from './avatar-group-etc.svelte'; 4 | 5 | import { Fallback, Image } from '$lib/components/ui/avatar'; 6 | 7 | export { Root, Member, Etc, Image as MemberImage, Fallback as MemberFallback }; 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar/avatar-fallback.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar/avatar-image.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar/avatar.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './avatar.svelte'; 2 | import Image from './avatar-image.svelte'; 3 | import Fallback from './avatar-fallback.svelte'; 4 | 5 | export { 6 | Root, 7 | Image, 8 | Fallback, 9 | // 10 | Root as Avatar, 11 | Image as AvatarImage, 12 | Fallback as AvatarFallback 13 | }; 14 | -------------------------------------------------------------------------------- /src/lib/components/ui/badge/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Badge } from './badge.svelte'; 2 | export { badgeVariants, type BadgeVariant } from './badge.svelte'; 3 | -------------------------------------------------------------------------------- /src/lib/components/ui/button/index.ts: -------------------------------------------------------------------------------- 1 | import Root, { 2 | type ButtonProps, 3 | type ButtonSize, 4 | type ButtonVariant, 5 | buttonVariants 6 | } from './button.svelte'; 7 | 8 | export { 9 | Root, 10 | type ButtonProps as Props, 11 | // 12 | Root as Button, 13 | buttonVariants, 14 | type ButtonProps, 15 | type ButtonSize, 16 | type ButtonVariant 17 | }; 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-action.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-content.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | {@render children?.()} 15 |
16 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-description.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |

19 | {@render children?.()} 20 |

21 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-footer.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-header.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
22 | {@render children?.()} 23 |
24 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-title.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
22 | {@render children?.()} 23 |
24 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './card.svelte'; 2 | import Content from './card-content.svelte'; 3 | import Description from './card-description.svelte'; 4 | import Footer from './card-footer.svelte'; 5 | import Header from './card-header.svelte'; 6 | import Title from './card-title.svelte'; 7 | import Action from './card-action.svelte'; 8 | 9 | export { 10 | Root, 11 | Content, 12 | Description, 13 | Footer, 14 | Header, 15 | Title, 16 | Action, 17 | // 18 | Root as Card, 19 | Content as CardContent, 20 | Description as CardDescription, 21 | Footer as CardFooter, 22 | Header as CardHeader, 23 | Title as CardTitle, 24 | Action as CardAction 25 | }; 26 | -------------------------------------------------------------------------------- /src/lib/components/ui/chat/chat-bubble-avatar.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/chat/chat-bubble-message.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 |
21 | {#if typing} 22 |
23 | 24 |
25 | {:else} 26 | {@render children?.()} 27 | {/if} 28 |
29 | -------------------------------------------------------------------------------- /src/lib/components/ui/chat/chat-bubble.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
16 | {@render children?.()} 17 |
18 | -------------------------------------------------------------------------------- /src/lib/components/ui/chat/index.ts: -------------------------------------------------------------------------------- 1 | import Bubble from './chat-bubble.svelte'; 2 | import BubbleMessage from './chat-bubble-message.svelte'; 3 | import BubbleAvatar from './chat-bubble-avatar.svelte'; 4 | import List from './chat-list.svelte'; 5 | import * as Avatar from '$lib/components/ui/avatar'; 6 | 7 | const BubbleAvatarImage = Avatar.Image; 8 | const BubbleAvatarFallback = Avatar.Fallback; 9 | 10 | export { List, Bubble, BubbleMessage, BubbleAvatar, BubbleAvatarImage, BubbleAvatarFallback }; 11 | -------------------------------------------------------------------------------- /src/lib/components/ui/chat/loading-dots.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 | {#each { length: 3 } as _, i (i)} 11 | 12 | {/each} 13 |
14 | 15 | 43 | -------------------------------------------------------------------------------- /src/lib/components/ui/code/index.ts: -------------------------------------------------------------------------------- 1 | import Code from './code.svelte'; 2 | 3 | export { Code }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/code/shiki.ts: -------------------------------------------------------------------------------- 1 | // Follows the best practices established in https://shiki.matsu.io/guide/best-performance 2 | import { createJavaScriptRegexEngine } from 'shiki/engine/javascript'; 3 | import { createHighlighterCore } from 'shiki/core'; 4 | 5 | const bundledLanguages = { 6 | bash: () => import('@shikijs/langs/bash'), 7 | diff: () => import('@shikijs/langs/diff'), 8 | javascript: () => import('@shikijs/langs/javascript'), 9 | json: () => import('@shikijs/langs/json'), 10 | svelte: () => import('@shikijs/langs/svelte'), 11 | typescript: () => import('@shikijs/langs/typescript') 12 | }; 13 | 14 | /** The languages configured for the highlighter */ 15 | export type SupportedLanguage = keyof typeof bundledLanguages; 16 | 17 | /** A preloaded highlighter instance. */ 18 | export const highlighter = createHighlighterCore({ 19 | themes: [ 20 | import('@shikijs/themes/github-light-default'), 21 | import('@shikijs/themes/github-dark-default') 22 | ], 23 | langs: Object.entries(bundledLanguages).map(([_, lang]) => lang), 24 | engine: createJavaScriptRegexEngine() 25 | }); 26 | -------------------------------------------------------------------------------- /src/lib/components/ui/collapsible/collapsible-content.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/collapsible/collapsible-trigger.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/collapsible/collapsible.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/lib/components/ui/collapsible/index.ts: -------------------------------------------------------------------------------- 1 | import { Collapsible as CollapsiblePrimitive } from 'bits-ui'; 2 | 3 | const Root = CollapsiblePrimitive.Root; 4 | const Trigger = CollapsiblePrimitive.Trigger; 5 | const Content = CollapsiblePrimitive.Content; 6 | 7 | export { 8 | Root, 9 | Content, 10 | Trigger, 11 | // 12 | Root as Collapsible, 13 | Content as CollapsibleContent, 14 | Trigger as CollapsibleTrigger 15 | }; 16 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command-empty.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command-group.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | {#if heading} 25 | 26 | {heading} 27 | 28 | {/if} 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command-input.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 | 16 | 26 |
27 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command-item.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command-link-item.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command-list.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command-separator.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command-shortcut.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | {@render children?.()} 20 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/command/command.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/copy-button/index.ts: -------------------------------------------------------------------------------- 1 | import CopyButton from './copy-button.svelte'; 2 | 3 | export { CopyButton }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/dialog/dialog-close.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/dialog/dialog-description.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/dialog/dialog-footer.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/dialog/dialog-header.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/dialog/dialog-overlay.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/dialog/dialog-title.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/dialog/dialog-trigger.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/dialog/index.ts: -------------------------------------------------------------------------------- 1 | import { Dialog as DialogPrimitive } from 'bits-ui'; 2 | 3 | import Title from './dialog-title.svelte'; 4 | import Footer from './dialog-footer.svelte'; 5 | import Header from './dialog-header.svelte'; 6 | import Overlay from './dialog-overlay.svelte'; 7 | import Content from './dialog-content.svelte'; 8 | import Description from './dialog-description.svelte'; 9 | import Trigger from './dialog-trigger.svelte'; 10 | import Close from './dialog-close.svelte'; 11 | 12 | const Root = DialogPrimitive.Root; 13 | const Portal = DialogPrimitive.Portal; 14 | 15 | export { 16 | Root, 17 | Title, 18 | Portal, 19 | Footer, 20 | Header, 21 | Trigger, 22 | Overlay, 23 | Content, 24 | Description, 25 | Close, 26 | // 27 | Root as Dialog, 28 | Title as DialogTitle, 29 | Portal as DialogPortal, 30 | Footer as DialogFooter, 31 | Header as DialogHeader, 32 | Trigger as DialogTrigger, 33 | Overlay as DialogOverlay, 34 | Content as DialogContent, 35 | Description as DialogDescription, 36 | Close as DialogClose 37 | }; 38 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer-close.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer-description.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer-footer.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer-header.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer-nested.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer-overlay.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer-title.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer-trigger.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/drawer/drawer.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 |
23 | {@render children?.()} 24 |
25 | -------------------------------------------------------------------------------- /src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | {@render children?.()} 20 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/field-set/field-set-content.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/field-set/field-set-footer.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/field-set/field-set-title.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
24 | {@render children?.()} 25 |
26 | -------------------------------------------------------------------------------- /src/lib/components/ui/field-set/field-set.svelte: -------------------------------------------------------------------------------- 1 | 25 | 26 |
27 | {@render children?.()} 28 |
29 | -------------------------------------------------------------------------------- /src/lib/components/ui/field-set/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './field-set.svelte'; 2 | import Content from './field-set-content.svelte'; 3 | import Footer from './field-set-footer.svelte'; 4 | import Title from './field-set-title.svelte'; 5 | 6 | export { Root, Content, Footer, Title }; 7 | -------------------------------------------------------------------------------- /src/lib/components/ui/file-drop-zone/index.ts: -------------------------------------------------------------------------------- 1 | import FileDropZone, { 2 | type FileRejectedReason, 3 | type FileDropZoneProps 4 | } from './file-drop-zone.svelte'; 5 | 6 | export const displaySize = (bytes: number): string => { 7 | if (bytes < KILOBYTE) return `${bytes.toFixed(0)} B`; 8 | 9 | if (bytes < MEGABYTE) return `${(bytes / KILOBYTE).toFixed(0)} KB`; 10 | 11 | if (bytes < GIGABYTE) return `${(bytes / MEGABYTE).toFixed(0)} MB`; 12 | 13 | return `${(bytes / GIGABYTE).toFixed(0)} GB`; 14 | }; 15 | 16 | // Utilities for working with file sizes 17 | export const BYTE = 1; 18 | export const KILOBYTE = 1024; 19 | export const MEGABYTE = 1024 * KILOBYTE; 20 | export const GIGABYTE = 1024 * MEGABYTE; 21 | 22 | // utilities for limiting accepted files 23 | export const ACCEPT_IMAGE = 'image/*'; 24 | export const ACCEPT_VIDEO = 'video/*'; 25 | export const ACCEPT_AUDIO = 'audio/*'; 26 | 27 | export { FileDropZone, type FileRejectedReason, type FileDropZoneProps }; 28 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/image-cropper-cancel.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 20 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/image-cropper-controls.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | {@render children?.()} 10 |
11 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/image-cropper-crop.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 20 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/image-cropper-cropper.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 |
17 | 25 |
26 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/image-cropper-dialog.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 21 |
22 | {@render children?.()} 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/image-cropper-preview.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | {#if child} 14 | {@render child({ src: previewState.rootState.src })} 15 | {:else} 16 | 19 | 20 | 21 | 22 | Upload image 23 | 24 | 25 | {/if} 26 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/image-cropper-upload-trigger.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/image-cropper.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | {@render children?.()} 29 | { 32 | const file = e.currentTarget.files?.[0]; 33 | if (!file) return; 34 | rootState.onUpload(file); 35 | // reset so that we can reupload the same file 36 | (e.target! as HTMLInputElement).value = ''; 37 | }} 38 | type="file" 39 | {id} 40 | style="display: none;" 41 | /> 42 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './image-cropper.svelte'; 2 | import UploadTrigger from './image-cropper-upload-trigger.svelte'; 3 | import Preview from './image-cropper-preview.svelte'; 4 | import Dialog from './image-cropper-dialog.svelte'; 5 | import Cropper from './image-cropper-cropper.svelte'; 6 | import Controls from './image-cropper-controls.svelte'; 7 | import Crop from './image-cropper-crop.svelte'; 8 | import Cancel from './image-cropper-cancel.svelte'; 9 | import { getFileFromUrl } from './utils'; 10 | 11 | export { Root, UploadTrigger, Preview, Dialog, Cropper, Controls, Crop, Cancel, getFileFromUrl }; 12 | -------------------------------------------------------------------------------- /src/lib/components/ui/image-cropper/types.ts: -------------------------------------------------------------------------------- 1 | import type { AvatarRootProps, DialogContentProps, WithChildren } from 'bits-ui'; 2 | import type { Snippet } from 'svelte'; 3 | import type { HTMLInputAttributes } from 'svelte/elements'; 4 | 5 | export type ImageCropperRootProps = HTMLInputAttributes & 6 | WithChildren<{ 7 | id?: string; 8 | src?: string; 9 | onCropped?: (url: string) => void; 10 | }>; 11 | 12 | export type ImageCropperDialogProps = DialogContentProps; 13 | 14 | export type ImageCropperPreviewProps = Omit & { 15 | child?: Snippet<[{ src: string }]>; 16 | }; 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/input/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './input.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Input 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/kbd/index.ts: -------------------------------------------------------------------------------- 1 | import Kbd from './kbd.svelte'; 2 | 3 | export { Kbd }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/label/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './label.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Label 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/label/label.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 20 | -------------------------------------------------------------------------------- /src/lib/components/ui/language-switcher/index.ts: -------------------------------------------------------------------------------- 1 | import LanguageSwitcher from './language-switcher.svelte'; 2 | 3 | export type * from './types'; 4 | 5 | export { LanguageSwitcher as Root, LanguageSwitcher }; 6 | -------------------------------------------------------------------------------- /src/lib/components/ui/language-switcher/types.ts: -------------------------------------------------------------------------------- 1 | export interface Language { 2 | /** Language code (e.g., 'en', 'de') */ 3 | code: string; 4 | /** Display name (e.g., 'English', 'Deutsch') */ 5 | label: string; 6 | } 7 | 8 | export interface LanguageSwitcherProps { 9 | /** List of available languages */ 10 | languages: Language[]; 11 | 12 | /** Current selected language code */ 13 | value?: string; 14 | 15 | /** Dropdown alignment */ 16 | align?: 'start' | 'center' | 'end'; 17 | 18 | /** Button variant */ 19 | variant?: 'outline' | 'ghost'; 20 | 21 | /** Called when the language changes */ 22 | onChange?: (code: string) => void; 23 | 24 | class?: string; 25 | } 26 | -------------------------------------------------------------------------------- /src/lib/components/ui/light-switch/index.ts: -------------------------------------------------------------------------------- 1 | import LightSwitch from './light-switch.svelte'; 2 | 3 | export { LightSwitch }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/light-switch/light-switch.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/link/index.ts: -------------------------------------------------------------------------------- 1 | import Link from './link.svelte'; 2 | 3 | export { Link }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/link/link.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | {@render children?.()} 10 | 11 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './modal.svelte'; 2 | import Trigger from './modal-trigger.svelte'; 3 | import Content from './modal-content.svelte'; 4 | import Footer from './modal-footer.svelte'; 5 | import Header from './modal-header.svelte'; 6 | import Title from './modal-title.svelte'; 7 | import Description from './modal-description.svelte'; 8 | 9 | export { Root, Trigger, Content, Footer, Header, Title, Description }; 10 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/modal-content.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | {#if modal.view === 'desktop'} 18 | 19 | {@render children?.()} 20 | 21 | {:else} 22 | 23 | {@render children?.()} 24 | 25 | {/if} 26 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/modal-description.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | {#if modal.view === 'desktop'} 13 | 14 | {:else} 15 | 16 | {/if} 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/modal-footer.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | {#if modal.view === 'desktop'} 18 | 19 | {@render children?.()} 20 | 21 | {:else} 22 | 23 | {@render children?.()} 24 | 25 | {/if} 26 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/modal-header.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | {#if modal.view === 'desktop'} 18 | 19 | {@render children?.()} 20 | 21 | {:else} 22 | 23 | {@render children?.()} 24 | 25 | {/if} 26 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/modal-title.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | {#if modal.view === 'desktop'} 13 | 14 | {:else} 15 | 16 | {/if} 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/modal-trigger.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | {#if modal.view === 'desktop'} 13 | 14 | {@render children?.()} 15 | 16 | {:else} 17 | 18 | {@render children?.()} 19 | 20 | {/if} 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/modal.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | {#if modal.view === 'desktop'} 13 | 14 | {@render children?.()} 15 | 16 | {:else} 17 | 18 | {@render children?.()} 19 | 20 | {/if} 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/modal/modal.svelte.ts: -------------------------------------------------------------------------------- 1 | import { Context } from 'runed'; 2 | import { MediaQuery } from 'svelte/reactivity'; 3 | 4 | class ModalRootState { 5 | #isDesktop = new MediaQuery('(min-width: 768px)'); 6 | 7 | get view() { 8 | return this.#isDesktop.current ? 'desktop' : 'mobile'; 9 | } 10 | } 11 | 12 | class ModalSubState { 13 | constructor(private root: ModalRootState) {} 14 | 15 | get view() { 16 | return this.root.view; 17 | } 18 | } 19 | 20 | const ctx = new Context('modal-root-state'); 21 | 22 | export function useModal() { 23 | return ctx.set(new ModalRootState()); 24 | } 25 | 26 | export function useModalSub() { 27 | return new ModalSubState(ctx.get()); 28 | } 29 | -------------------------------------------------------------------------------- /src/lib/components/ui/nlp-date-input/index.ts: -------------------------------------------------------------------------------- 1 | import NLPDateInput from './nlp-date-input.svelte'; 2 | 3 | export { NLPDateInput }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/phone-input/flag.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | {#if country} 13 | 17 | {/if} 18 | 19 | -------------------------------------------------------------------------------- /src/lib/components/ui/phone-input/index.ts: -------------------------------------------------------------------------------- 1 | import PhoneInput from './phone-input.svelte'; 2 | import type { 3 | Country, 4 | CountryCode, 5 | DetailedValue, 6 | E164Number, 7 | TelInputOptions 8 | } from 'svelte-tel-input/types'; 9 | 10 | export type Props = { 11 | country?: CountryCode | null; 12 | defaultCountry?: CountryCode | null; 13 | el?: HTMLInputElement; 14 | name?: string; 15 | placeholder?: string; 16 | disabled?: boolean; 17 | readonly?: boolean; 18 | class?: string; 19 | value?: E164Number | null; 20 | valid?: boolean; 21 | detailedValue?: Partial | null; 22 | options?: TelInputOptions; 23 | order?: ((a: Country, b: Country) => number) | undefined; 24 | }; 25 | 26 | export const defaultOptions: TelInputOptions = { 27 | spaces: true, 28 | autoPlaceholder: false, 29 | format: 'international' 30 | }; 31 | 32 | export { PhoneInput }; 33 | -------------------------------------------------------------------------------- /src/lib/components/ui/pm-command/index.ts: -------------------------------------------------------------------------------- 1 | import PMCommand from './pm-command.svelte'; 2 | 3 | export { PMCommand }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/popover/index.ts: -------------------------------------------------------------------------------- 1 | import { Popover as PopoverPrimitive } from 'bits-ui'; 2 | import Content from './popover-content.svelte'; 3 | import Trigger from './popover-trigger.svelte'; 4 | const Root = PopoverPrimitive.Root; 5 | const Close = PopoverPrimitive.Close; 6 | 7 | export { 8 | Root, 9 | Content, 10 | Trigger, 11 | Close, 12 | // 13 | Root as Popover, 14 | Content as PopoverContent, 15 | Trigger as PopoverTrigger, 16 | Close as PopoverClose 17 | }; 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/popover/popover-trigger.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/prev-next/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './prev-next.svelte'; 2 | import Next from './next.svelte'; 3 | import Previous from './previous.svelte'; 4 | 5 | export { Root, Next, Previous }; 6 | -------------------------------------------------------------------------------- /src/lib/components/ui/prev-next/next.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/prev-next/prev-next.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 |
16 | {@render previous?.()} 17 |
18 |
19 | {@render next?.()} 20 |
21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/prev-next/previous.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/progress/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './progress.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Progress 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/progress/progress.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 22 |
27 |
28 | -------------------------------------------------------------------------------- /src/lib/components/ui/scroll-area/index.ts: -------------------------------------------------------------------------------- 1 | import Scrollbar from './scroll-area-scrollbar.svelte'; 2 | import Root from './scroll-area.svelte'; 3 | 4 | export { 5 | Root, 6 | Scrollbar, 7 | //, 8 | Root as ScrollArea, 9 | Scrollbar as ScrollAreaScrollbar 10 | }; 11 | -------------------------------------------------------------------------------- /src/lib/components/ui/scroll-area/scroll-area-scrollbar.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 26 | {@render children?.()} 27 | 31 | 32 | -------------------------------------------------------------------------------- /src/lib/components/ui/separator/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './separator.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Separator 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/separator/separator.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/index.ts: -------------------------------------------------------------------------------- 1 | import { Dialog as SheetPrimitive } from 'bits-ui'; 2 | import Trigger from './sheet-trigger.svelte'; 3 | import Close from './sheet-close.svelte'; 4 | import Overlay from './sheet-overlay.svelte'; 5 | import Content from './sheet-content.svelte'; 6 | import Header from './sheet-header.svelte'; 7 | import Footer from './sheet-footer.svelte'; 8 | import Title from './sheet-title.svelte'; 9 | import Description from './sheet-description.svelte'; 10 | 11 | const Root = SheetPrimitive.Root; 12 | const Portal = SheetPrimitive.Portal; 13 | 14 | export { 15 | Root, 16 | Close, 17 | Trigger, 18 | Portal, 19 | Overlay, 20 | Content, 21 | Header, 22 | Footer, 23 | Title, 24 | Description, 25 | // 26 | Root as Sheet, 27 | Close as SheetClose, 28 | Trigger as SheetTrigger, 29 | Portal as SheetPortal, 30 | Overlay as SheetOverlay, 31 | Content as SheetContent, 32 | Header as SheetHeader, 33 | Footer as SheetFooter, 34 | Title as SheetTitle, 35 | Description as SheetDescription 36 | }; 37 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-close.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-description.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-footer.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-header.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-overlay.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-title.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-trigger.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/constants.ts: -------------------------------------------------------------------------------- 1 | export const SIDEBAR_COOKIE_NAME = 'sidebar:state'; 2 | export const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; 3 | export const SIDEBAR_WIDTH = '16rem'; 4 | export const SIDEBAR_WIDTH_MOBILE = '18rem'; 5 | export const SIDEBAR_WIDTH_ICON = '3rem'; 6 | export const SIDEBAR_KEYBOARD_SHORTCUT = 'b'; 7 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-content.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
23 | {@render children?.()} 24 |
25 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-footer.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-group-content.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-group.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-header.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-input.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-inset.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
23 | {@render children?.()} 24 |
25 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-badge.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
28 | {@render children?.()} 29 |
30 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-item.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
  • 20 | {@render children?.()} 21 |
  • 22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 |
    27 | {#if showIcon} 28 | 29 | {/if} 30 | 35 | {@render children?.()} 36 |
    37 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
  • 20 | {@render children?.()} 21 |
  • 22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-sub.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
      24 | {@render children?.()} 25 |
    26 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
      20 | {@render children?.()} 21 |
    22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-separator.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 20 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-trigger.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 | 36 | -------------------------------------------------------------------------------- /src/lib/components/ui/skeleton/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './skeleton.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Skeleton 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/skeleton/skeleton.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
    18 | -------------------------------------------------------------------------------- /src/lib/components/ui/snippet/index.ts: -------------------------------------------------------------------------------- 1 | import Snippet from './snippet.svelte'; 2 | 3 | export { Snippet }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/sonner/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Toaster } from './sonner.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/ui/sonner/sonner.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 14 | -------------------------------------------------------------------------------- /src/lib/components/ui/star-rating/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Root } from './star-rating.svelte'; 2 | export { default as Star } from './star-rating-star.svelte'; 3 | -------------------------------------------------------------------------------- /src/lib/components/ui/star-rating/star-rating.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/tabs/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './tabs.svelte'; 2 | import Content from './tabs-content.svelte'; 3 | import List from './tabs-list.svelte'; 4 | import Trigger from './tabs-trigger.svelte'; 5 | 6 | export { 7 | Root, 8 | Content, 9 | List, 10 | Trigger, 11 | // 12 | Root as Tabs, 13 | Content as TabsContent, 14 | List as TabsList, 15 | Trigger as TabsTrigger 16 | }; 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/tabs/tabs-content.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /src/lib/components/ui/tabs/tabs-list.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/tabs/tabs-trigger.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /src/lib/components/ui/tabs/tabs.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 20 | -------------------------------------------------------------------------------- /src/lib/components/ui/tags-input/index.ts: -------------------------------------------------------------------------------- 1 | import TagsInput from './tags-input.svelte'; 2 | 3 | export { TagsInput }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/tags-input/tags-input-tag.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
    18 | 19 | {value} 20 | 21 | 24 |
    25 | -------------------------------------------------------------------------------- /src/lib/components/ui/tags-input/types.ts: -------------------------------------------------------------------------------- 1 | import type { HTMLInputAttributes } from 'svelte/elements'; 2 | 3 | export interface TagsInputProps extends HTMLInputAttributes { 4 | value?: string[]; 5 | class?: string; 6 | placeholder?: string; 7 | disabled?: boolean; 8 | validate?: (val: string, tags: string[]) => string | undefined; 9 | } 10 | -------------------------------------------------------------------------------- /src/lib/components/ui/terminal/index.ts: -------------------------------------------------------------------------------- 1 | import Loop from './terminal-loop.svelte'; 2 | import Root from './terminal.svelte'; 3 | import TypingAnimation from './terminal-typing-animation.svelte'; 4 | import AnimatedSpan from './terminal-animated-span.svelte'; 5 | import Loading from './terminal-loading.svelte'; 6 | 7 | export { Loop, Root, TypingAnimation, AnimatedSpan, Loading }; 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/terminal/terminal-loop.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 | {#key loopIndex} 26 | {@render children?.()} 27 | {/key} 28 | -------------------------------------------------------------------------------- /src/lib/components/ui/terminal/terminal-typing-animation.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | {#if playAnimation} 24 | animation.onComplete?.() 29 | }} 30 | > 31 | {@render children?.()} 32 | 33 | {/if} 34 | -------------------------------------------------------------------------------- /src/lib/components/ui/terminal/terminal.svelte: -------------------------------------------------------------------------------- 1 | 28 | 29 | 30 | {@render children?.()} 31 | 32 | -------------------------------------------------------------------------------- /src/lib/components/ui/terminal/types.ts: -------------------------------------------------------------------------------- 1 | import type { WithChildren } from 'bits-ui'; 2 | 3 | export type TerminalAnimationProps = WithChildren<{ 4 | delay?: number; 5 | class?: string; 6 | }>; 7 | -------------------------------------------------------------------------------- /src/lib/components/ui/textarea/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './textarea.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Textarea 7 | }; 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/textarea/textarea.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/theme-selector/index.ts: -------------------------------------------------------------------------------- 1 | import ThemeSelector from './theme-selector.svelte'; 2 | 3 | export { ThemeSelector }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/toc/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './toc.svelte'; 2 | 3 | export { Root }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/toc/toc.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 |
      17 | {#each toc as heading, i (i)} 18 |
    • 23 | {#if heading.id} 24 | 25 | {heading.label} 26 | 27 | {:else} 28 | {heading.label} 29 | {/if} 30 |
    • 31 | {#if heading.children.length > 0} 32 | 33 | {/if} 34 | {/each} 35 |
    36 | -------------------------------------------------------------------------------- /src/lib/components/ui/tooltip/index.ts: -------------------------------------------------------------------------------- 1 | import { Tooltip as TooltipPrimitive } from 'bits-ui'; 2 | import Trigger from './tooltip-trigger.svelte'; 3 | import Content from './tooltip-content.svelte'; 4 | 5 | const Root = TooltipPrimitive.Root; 6 | const Provider = TooltipPrimitive.Provider; 7 | const Portal = TooltipPrimitive.Portal; 8 | 9 | export { 10 | Root, 11 | Trigger, 12 | Content, 13 | Provider, 14 | Portal, 15 | // 16 | Root as Tooltip, 17 | Content as TooltipContent, 18 | Trigger as TooltipTrigger, 19 | Provider as TooltipProvider, 20 | Portal as TooltipPortal 21 | }; 22 | -------------------------------------------------------------------------------- /src/lib/components/ui/tooltip/tooltip-trigger.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/components/ui/tree-view/index.ts: -------------------------------------------------------------------------------- 1 | import TreeView from './tree-view.svelte'; 2 | import TreeViewFile from './tree-view-file.svelte'; 3 | import TreeViewFolder from './tree-view-folder.svelte'; 4 | 5 | export { 6 | TreeView, 7 | TreeViewFile, 8 | TreeViewFolder, 9 | 10 | // ... 11 | TreeView as Root, 12 | TreeViewFile as File, 13 | TreeViewFolder as Folder 14 | }; 15 | -------------------------------------------------------------------------------- /src/lib/components/ui/tree-view/tree-view-file.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/tree-view/tree-view.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
    14 | {@render children?.()} 15 |
    16 | -------------------------------------------------------------------------------- /src/lib/components/ui/window/index.ts: -------------------------------------------------------------------------------- 1 | import Window from './window.svelte'; 2 | 3 | export { Window }; 4 | -------------------------------------------------------------------------------- /src/lib/components/ui/window/window.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
    13 |
    14 |
    15 |
    16 |
    17 |
    18 |
    19 |
    20 |
    21 | {@render children?.()} 22 |
    23 |
    24 | -------------------------------------------------------------------------------- /src/lib/context.ts: -------------------------------------------------------------------------------- 1 | import { Context } from 'runed'; 2 | import type { UseBoolean } from './hooks/use-boolean.svelte'; 3 | 4 | export const commandContext = new Context('command-menu-context'); 5 | -------------------------------------------------------------------------------- /src/lib/hooks/is-mobile.svelte.ts: -------------------------------------------------------------------------------- 1 | import { MediaQuery } from 'svelte/reactivity'; 2 | 3 | const MOBILE_BREAKPOINT = 768; 4 | 5 | export class IsMobile extends MediaQuery { 6 | constructor() { 7 | super(`max-width: ${MOBILE_BREAKPOINT - 1}px`); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from 'clsx'; 2 | import { twMerge } from 'tailwind-merge'; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | 8 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 9 | export type WithoutChild = T extends { child?: any } ? Omit : T; 10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 11 | export type WithoutChildren = T extends { children?: any } ? Omit : T; 12 | export type WithoutChildrenOrChild = WithoutChildren>; 13 | export type WithElementRef = T & { ref?: U | null }; 14 | -------------------------------------------------------------------------------- /src/lib/utils/box.ts: -------------------------------------------------------------------------------- 1 | import type { ReadableBox, WritableBox } from 'svelte-toolbelt'; 2 | 3 | export type Box = ReadableBox | WritableBox; 4 | 5 | export type WritableBoxedValues = { 6 | [K in keyof T]: WritableBox; 7 | }; 8 | 9 | export type ReadableBoxedValues = { 10 | [K in keyof T]: ReadableBox; 11 | }; 12 | -------------------------------------------------------------------------------- /src/lib/utils/is-number.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Installed from @ieedan/std 3 | */ 4 | 5 | /** Checks if provided value is actually a number. 6 | * 7 | * @param num value to check 8 | * @returns 9 | * 10 | * ## Usage 11 | * 12 | * ```ts 13 | * isNumber("2"); // true 14 | * isNumber("1.11"); // true 15 | * isNumber("0xff"); // true 16 | * 17 | * isNumber("two"); // false 18 | * isNumber({ two: 2 }); // false 19 | * isNumber(Number.POSITIVE_INFINITY); // false 20 | * ``` 21 | */ 22 | export function isNumber(num: unknown): boolean { 23 | if (typeof num === 'number') return num - num === 0; 24 | 25 | if (typeof num === 'string' && num.trim() !== '') return Number.isFinite(+num); 26 | 27 | return false; 28 | } 29 | -------------------------------------------------------------------------------- /src/lib/utils/sleep.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Installed from @ieedan/std 3 | */ 4 | 5 | /** Await this to pause execution until the duration has passed. 6 | * 7 | * @param durationMs The duration in ms until the sleep in over 8 | * @returns 9 | * 10 | * ## Usage 11 | * ```ts 12 | * console.log(Date.now()) // 1725739228744 13 | * 14 | * await sleep(1000); 15 | * 16 | * console.log(Date.now()) // 1725739229744 17 | * ``` 18 | */ 19 | export function sleep(durationMs: number): Promise { 20 | return new Promise((res) => setTimeout(res, durationMs)); 21 | } 22 | -------------------------------------------------------------------------------- /src/lib/utils/types.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Installed from @ieedan/std 3 | */ 4 | 5 | /** Allows you to have autocomplete on a string while still accepting any string value. 6 | * 7 | * ## Usage 8 | * ```ts 9 | * type Fruits = LooseAutocomplete<'apple' | 'orange' | 'pear'>; 10 | * 11 | * // you will still get autocomplete here 12 | * let fruit: Fruits = 'apple'; // valid 13 | * fruit = 'banana'; // valid 14 | * ``` 15 | */ 16 | export type LooseAutocomplete = T | (string & {}); 17 | 18 | /** Flattens a complex object type down into a single object. 19 | * Super useful when using joins with `Omit` and other helpers without needing to reveal the base type. 20 | */ 21 | export type Prettify = { 22 | [K in keyof T]: T[K]; 23 | } & {}; 24 | -------------------------------------------------------------------------------- /src/lib/utils/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from 'clsx'; 2 | import { twMerge } from 'tailwind-merge'; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | 8 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 9 | export type WithoutChild = T extends { child?: any } ? Omit : T; 10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 11 | export type WithoutChildren = T extends { children?: any } ? Omit : T; 12 | export type WithoutChildrenOrChild = WithoutChildren>; 13 | export type WithElementRef = T & { ref?: U | null }; 14 | -------------------------------------------------------------------------------- /src/routes/actions/active/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | 4 | const examples = { 5 | basic: { 6 | code: basicRaw, 7 | Component: Basic 8 | } 9 | }; 10 | 11 | export { examples }; 12 | -------------------------------------------------------------------------------- /src/routes/actions/shortcut/basic.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | toast.success('You pressed Ctrl + 1') 15 | }} 16 | /> 17 | 18 |

    19 | + 1 20 |

    21 | -------------------------------------------------------------------------------- /src/routes/actions/shortcut/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | 4 | const examples = { 5 | basic: { 6 | code: basicRaw, 7 | Component: Basic 8 | } 9 | }; 10 | 11 | export { examples }; 12 | -------------------------------------------------------------------------------- /src/routes/components/+page.server.ts: -------------------------------------------------------------------------------- 1 | import { redirect } from '@sveltejs/kit'; 2 | 3 | // just in case anyone linked to the old path 4 | 5 | export function load() { 6 | throw redirect(307, '/components/avatar-group'); 7 | } 8 | -------------------------------------------------------------------------------- /src/routes/components/+page.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ieedan/shadcn-svelte-extras/fd06d9df74e6a1a25ff1ef00b17f5dd9cf1b92fd/src/routes/components/+page.svelte -------------------------------------------------------------------------------- /src/routes/components/avatar-group/basic.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | {#each members as member (member.username)} 22 | 23 | 24 | 25 | {member.username[0]} 26 | 27 | 28 | {/each} 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/routes/components/avatar-group/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Vertical from './vertical.svelte'; 4 | import verticalRaw from './vertical.svelte?raw'; 5 | 6 | const examples = { 7 | basic: { 8 | code: basicRaw, 9 | Component: Basic 10 | }, 11 | vertical: { 12 | code: verticalRaw, 13 | Component: Vertical 14 | } 15 | }; 16 | 17 | export { examples }; 18 | -------------------------------------------------------------------------------- /src/routes/components/avatar-group/vertical.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | {#each members as member (member.username)} 22 | 23 | 24 | 25 | {member.username[0]} 26 | 27 | 28 | {/each} 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/routes/components/button/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |

    The same old button you know from shadcn-svelte with a few extra touches.

    9 | Basic 10 | 11 | 12 | 13 | 14 | Loading 15 | 16 | 17 | 18 | onClickPromise 19 |

    20 | You can also pass a promise to onClickPromise to show a loading state until it 21 | resolves. 22 |

    23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/routes/components/button/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/button/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Loading from './loading.svelte'; 4 | import loadingRaw from './loading.svelte?raw'; 5 | import OnClickPromise from './on-click-promise.svelte'; 6 | import onClickPromiseRaw from './on-click-promise.svelte?raw'; 7 | 8 | const examples = { 9 | basic: { 10 | code: basicRaw, 11 | Component: Basic 12 | }, 13 | loading: { 14 | code: loadingRaw, 15 | Component: Loading 16 | }, 17 | onClickPromise: { 18 | code: onClickPromiseRaw, 19 | Component: OnClickPromise 20 | } 21 | }; 22 | 23 | export { examples }; 24 | -------------------------------------------------------------------------------- /src/routes/components/button/loading.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/button/on-click-promise.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/routes/components/chat/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | 4 | const examples = { 5 | basic: { 6 | code: basicRaw, 7 | Component: Basic 8 | } 9 | }; 10 | 11 | export { examples }; 12 | -------------------------------------------------------------------------------- /src/routes/components/chat/types.ts: -------------------------------------------------------------------------------- 1 | export type User = { 2 | id: string; 3 | username: string; 4 | name: string; 5 | img: string; 6 | }; 7 | 8 | export type Message = { 9 | senderId: string; 10 | message: string; 11 | sentAt: string; 12 | }; 13 | -------------------------------------------------------------------------------- /src/routes/components/chat/utils.ts: -------------------------------------------------------------------------------- 1 | export const formatShortTime = (date: Date) => { 2 | return date.toLocaleTimeString('en-US', { 3 | hour: 'numeric', 4 | minute: '2-digit', 5 | hour12: true 6 | }); 7 | }; 8 | 9 | export const initials = (name: string) => 10 | name 11 | .split(' ') 12 | .map((n) => n[0]) 13 | .join(''); 14 | -------------------------------------------------------------------------------- /src/routes/components/code/basic.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
    10 | 11 |
    12 | -------------------------------------------------------------------------------- /src/routes/components/code/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import NoLineNumbers from './no-line-numbers.svelte'; 4 | import noLineNumbersRaw from './no-line-numbers.svelte?raw'; 5 | import Variants from './variants.svelte'; 6 | import variantsRaw from './variants.svelte?raw'; 7 | import HighlightLines from './highlight-lines.svelte'; 8 | import highlightLinesRaw from './highlight-lines.svelte?raw'; 9 | import Overflow from './overflow.svelte'; 10 | import overflowRaw from './overflow.svelte?raw'; 11 | 12 | const examples = { 13 | basic: { 14 | code: basicRaw, 15 | Component: Basic 16 | }, 17 | noLineNumbers: { 18 | code: noLineNumbersRaw, 19 | Component: NoLineNumbers 20 | }, 21 | variants: { 22 | code: variantsRaw, 23 | Component: Variants 24 | }, 25 | highlightLines: { 26 | code: highlightLinesRaw, 27 | Component: HighlightLines 28 | }, 29 | overflow: { 30 | code: overflowRaw, 31 | Component: Overflow 32 | } 33 | }; 34 | 35 | export { examples }; 36 | -------------------------------------------------------------------------------- /src/routes/components/code/highlight-lines.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 |
    22 | 30 |
    31 | -------------------------------------------------------------------------------- /src/routes/components/code/no-line-numbers.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
    8 | 9 |
    10 | -------------------------------------------------------------------------------- /src/routes/components/code/overflow.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 8 |
    9 | -------------------------------------------------------------------------------- /src/routes/components/code/variants.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    6 | 13 | 19 | Button 20 | `} 21 | /> 22 |
    23 | -------------------------------------------------------------------------------- /src/routes/components/copy-button/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | Basic 9 | 10 | 11 | 12 | 13 | Custom Icon 14 | 15 | 16 | 17 | With Text 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/routes/components/copy-button/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/copy-button/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Icon from './icon.svelte'; 4 | import iconRaw from './icon.svelte?raw'; 5 | import WithText from './with-text.svelte'; 6 | import withTextRaw from './with-text.svelte?raw'; 7 | 8 | const examples = { 9 | basic: { 10 | code: basicRaw, 11 | Component: Basic 12 | }, 13 | icon: { 14 | code: iconRaw, 15 | Component: Icon 16 | }, 17 | withText: { 18 | code: withTextRaw, 19 | Component: WithText 20 | } 21 | }; 22 | 23 | export { examples }; 24 | -------------------------------------------------------------------------------- /src/routes/components/copy-button/icon.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | {#snippet icon()} 8 | 9 | {/snippet} 10 | 11 | -------------------------------------------------------------------------------- /src/routes/components/copy-button/with-text.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | {#snippet icon()} 10 | 11 | {/snippet} 12 | {command} 13 | 14 | -------------------------------------------------------------------------------- /src/routes/components/field-set/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | Basic 9 | 10 | 11 | 12 | 13 | Destructive 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/routes/components/field-set/basic.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
    9 | 10 | 11 |
    12 | 13 | 14 |
    15 |
    16 | 17 |
    18 | Save your username. 19 | 20 |
    21 |
    22 |
    23 |
    24 | -------------------------------------------------------------------------------- /src/routes/components/field-set/destructive.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
    9 | 10 | 11 |
    12 | 13 | 14 |
    15 |
    16 | 17 |
    18 | Rename your project. 19 | 20 |
    21 |
    22 |
    23 |
    24 | -------------------------------------------------------------------------------- /src/routes/components/field-set/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Destructive from './destructive.svelte'; 4 | import destructiveRaw from './destructive.svelte?raw'; 5 | 6 | const examples = { 7 | basic: { 8 | code: basicRaw, 9 | Component: Basic 10 | }, 11 | destructive: { 12 | code: destructiveRaw, 13 | Component: Destructive 14 | } 15 | }; 16 | 17 | export { examples }; 18 | -------------------------------------------------------------------------------- /src/routes/components/file-drop-zone/+page.server.ts: -------------------------------------------------------------------------------- 1 | import { fail, message, superValidate } from 'sveltekit-superforms'; 2 | import { valibot } from 'sveltekit-superforms/adapters'; 3 | import { schema } from './schema'; 4 | 5 | export const load = async () => { 6 | return { 7 | form: await superValidate({}, valibot(schema)) 8 | }; 9 | }; 10 | 11 | export const actions = { 12 | default: async ({ request }) => { 13 | const form = await superValidate(request, valibot(schema)); 14 | 15 | if (!form.valid) { 16 | return fail(400, { form }); 17 | } 18 | 19 | return message(form, 'Posted!'); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/routes/components/file-drop-zone/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Form from './form.svelte'; 4 | import formRaw from './form.svelte?raw'; 5 | import schemaRaw from './schema.ts?raw'; 6 | 7 | const examples = { 8 | basic: { 9 | code: basicRaw, 10 | Component: Basic 11 | }, 12 | form: { 13 | code: formRaw, 14 | Component: Form 15 | }, 16 | schema: schemaRaw 17 | }; 18 | 19 | export { examples }; 20 | -------------------------------------------------------------------------------- /src/routes/components/file-drop-zone/schema.ts: -------------------------------------------------------------------------------- 1 | import * as v from 'valibot'; 2 | import { MEGABYTE } from '$lib/components/ui/file-drop-zone'; 3 | 4 | export const schema = v.object({ 5 | attachments: v.array(v.pipe(v.file(), v.maxSize(MEGABYTE * 2))) 6 | }); 7 | 8 | export type Schema = v.InferInput; 9 | -------------------------------------------------------------------------------- /src/routes/components/image-cropper/basic.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | { 9 | // if you need the file for a form you can call getFileFromUrl with the cropped url 10 | const file = await getFileFromUrl(url); 11 | 12 | console.log(file); 13 | }} 14 | > 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/routes/components/image-cropper/custom-preview.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | {#snippet child({ src })} 9 | your avatar 10 | {/snippet} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/routes/components/image-cropper/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import SquarePreview from './square-preview.svelte'; 4 | import squarePreviewRaw from './square-preview.svelte?raw'; 5 | import NoDefaultImage from './no-default-image.svelte'; 6 | import noDefaultImageRaw from './no-default-image.svelte?raw'; 7 | import CustomTrigger from './custom-trigger.svelte'; 8 | import customTriggerRaw from './custom-trigger.svelte?raw'; 9 | import CustomPreview from './custom-preview.svelte'; 10 | import customPreviewRaw from './custom-preview.svelte?raw'; 11 | 12 | const examples = { 13 | basic: { 14 | code: basicRaw, 15 | Component: Basic 16 | }, 17 | squarePreview: { 18 | code: squarePreviewRaw, 19 | Component: SquarePreview 20 | }, 21 | noDefaultImage: { 22 | code: noDefaultImageRaw, 23 | Component: NoDefaultImage 24 | }, 25 | customTrigger: { 26 | code: customTriggerRaw, 27 | Component: CustomTrigger 28 | }, 29 | customPreview: { 30 | code: customPreviewRaw, 31 | Component: CustomPreview 32 | } 33 | }; 34 | 35 | export { examples }; 36 | -------------------------------------------------------------------------------- /src/routes/components/image-cropper/no-default-image.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/routes/components/image-cropper/square-preview.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/routes/components/ipv4address-input/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | Basic 9 | 10 | 11 | 12 | 13 | Placeholder 14 | 15 | 16 | 17 | Reactive 18 | 19 | 20 | 21 | Validation 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/routes/components/ipv4address-input/basic.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 8 | 9 |
    10 | -------------------------------------------------------------------------------- /src/routes/components/ipv4address-input/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Placeholder from './placeholder.svelte'; 4 | import placeholderRaw from './placeholder.svelte?raw'; 5 | import Reactive from './reactive.svelte'; 6 | import reactiveRaw from './reactive.svelte?raw'; 7 | import Valid from './valid.svelte'; 8 | import validRaw from './valid.svelte?raw'; 9 | 10 | const examples = { 11 | basic: { 12 | code: basicRaw, 13 | Component: Basic 14 | }, 15 | placeholder: { 16 | code: placeholderRaw, 17 | Component: Placeholder 18 | }, 19 | reactive: { 20 | code: reactiveRaw, 21 | Component: Reactive 22 | }, 23 | valid: { 24 | code: validRaw, 25 | Component: Valid 26 | } 27 | }; 28 | 29 | export { examples }; 30 | -------------------------------------------------------------------------------- /src/routes/components/ipv4address-input/placeholder.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 8 | 9 |
    10 | -------------------------------------------------------------------------------- /src/routes/components/ipv4address-input/reactive.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
    10 | 11 | 12 | 13 |
    14 | -------------------------------------------------------------------------------- /src/routes/components/ipv4address-input/valid.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
    9 | 10 | 11 | 12 | 13 | Valid: 14 | 15 | {valid} 16 | 17 | 18 |
    19 | -------------------------------------------------------------------------------- /src/routes/components/kbd/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | Basic 9 | 10 | 11 | 12 | 13 | Sizes 14 | 15 | 16 | 17 | Variants 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/routes/components/kbd/basic.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | + K 9 | 10 | -------------------------------------------------------------------------------- /src/routes/components/kbd/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Sizes from './sizes.svelte'; 4 | import sizesRaw from './sizes.svelte?raw'; 5 | import Variants from './variants.svelte'; 6 | import variantsRaw from './variants.svelte?raw'; 7 | 8 | const examples = { 9 | basic: { 10 | code: basicRaw, 11 | Component: Basic 12 | }, 13 | sizes: { 14 | code: sizesRaw, 15 | Component: Sizes 16 | }, 17 | variants: { 18 | code: variantsRaw, 19 | Component: Variants 20 | } 21 | }; 22 | 23 | export { examples }; 24 | -------------------------------------------------------------------------------- /src/routes/components/kbd/sizes.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    6 | A 7 | B 8 | C 9 |
    10 | -------------------------------------------------------------------------------- /src/routes/components/kbd/variants.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    6 |
    7 | A 8 | B 9 | C 10 |
    11 |
    12 | A 13 | B 14 | C 15 |
    16 |
    17 | A 18 | B 19 | C 20 |
    21 |
    22 | -------------------------------------------------------------------------------- /src/routes/components/language-switcher/+page.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | Basic 10 | 11 | 12 | 13 | 14 | 15 | Ghost + Align 16 | 17 | 18 | 19 | 20 | Paraglide Integration 21 |

    22 | Example of how to integrate with 27 | ParaglideJS 28 | : 29 |

    30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/routes/components/language-switcher/basic.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/routes/components/language-switcher/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Variants from './variants.svelte'; 4 | import variantsRaw from './variants.svelte?raw'; 5 | import Paraglide from './paraglide.svelte'; 6 | import paraglideRaw from './paraglide.svelte?raw'; 7 | 8 | const examples = { 9 | basic: { 10 | code: basicRaw, 11 | Component: Basic 12 | }, 13 | variants: { 14 | code: variantsRaw, 15 | Component: Variants 16 | }, 17 | paraglide: { 18 | code: paraglideRaw, 19 | Component: Paraglide 20 | } 21 | }; 22 | 23 | export { examples }; 24 | -------------------------------------------------------------------------------- /src/routes/components/language-switcher/paraglide.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 |
    28 | { 32 | if (isLocale(code)) setLocale(code); 33 | }} 34 | /> 35 | 36 |

    {m.example_message()}

    37 |
    38 | -------------------------------------------------------------------------------- /src/routes/components/language-switcher/variants.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/routes/components/light-switch/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | Basic 9 | 10 | 11 | 12 | 13 | Ghost 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/routes/components/light-switch/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/light-switch/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Variants from './variants.svelte'; 4 | import variantsRaw from './variants.svelte?raw'; 5 | 6 | const examples = { 7 | basic: { 8 | code: basicRaw, 9 | Component: Basic 10 | }, 11 | variants: { 12 | code: variantsRaw, 13 | Component: Variants 14 | } 15 | }; 16 | 17 | export { examples }; 18 | -------------------------------------------------------------------------------- /src/routes/components/light-switch/variants.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/link/+page.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | Usage 14 |
    15 | 18 | import { Link } from '$lib/components/ui/link'; 19 | \<\/script\> 20 | 21 | Hello`} 22 | /> 23 |
    24 | -------------------------------------------------------------------------------- /src/routes/components/link/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |

    6 | Crafted by 7 | huntabyte, enhanced by 8 | ieedan. 9 |

    10 | -------------------------------------------------------------------------------- /src/routes/components/link/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | 4 | const examples = { 5 | basic: { 6 | code: basicRaw, 7 | Component: Basic 8 | } 9 | }; 10 | 11 | export { examples }; 12 | -------------------------------------------------------------------------------- /src/routes/components/modal/+page.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | Usage 14 |

    The modal component can be composed just like a dialog or drawer component.

    15 |
    16 | 19 | import * as Modal from "$lib/components/ui/modal"; 20 | \<\/script\> 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | `} 32 | /> 33 |
    34 | -------------------------------------------------------------------------------- /src/routes/components/modal/basic.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | Edit Profile 10 | 11 | 12 | Edit Profile 13 | 14 | Make changes to your profile here. Click save when you're done. 15 | 16 | 17 |
    18 |
    19 | 20 | 21 |
    22 |
    23 | 24 | 25 |
    26 |
    27 | 28 | 29 | 30 |
    31 |
    32 | -------------------------------------------------------------------------------- /src/routes/components/modal/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | 4 | const examples = { 5 | basic: { 6 | code: basicRaw, 7 | Component: Basic 8 | } 9 | }; 10 | 11 | export { examples }; 12 | -------------------------------------------------------------------------------- /src/routes/components/nlp-date-input/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |

    Allows you to provide a date in natural language and helps by giving suggestions.

    9 | 10 | 11 | 12 | 13 | Min/Max 14 |

    15 | You may want to limit what suggestions are actually presented to the user so that they don't 16 | schedule an appointment 30 years from now. You can do this with the 17 | min and max props. 18 |

    19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/routes/components/nlp-date-input/basic.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 9 | toast.success(label, { 10 | description: `${date.toDateString()} ${date.toLocaleTimeString()}` 11 | })} 12 | /> 13 |
    14 | -------------------------------------------------------------------------------- /src/routes/components/nlp-date-input/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import MinMax from './min-max.svelte'; 4 | import minMaxRaw from './min-max.svelte?raw'; 5 | 6 | const examples = { 7 | basic: { 8 | code: basicRaw, 9 | Component: Basic 10 | }, 11 | minMax: { 12 | code: minMaxRaw, 13 | Component: MinMax 14 | } 15 | }; 16 | 17 | export { examples }; 18 | -------------------------------------------------------------------------------- /src/routes/components/nlp-date-input/min-max.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
    9 | 14 | toast.success(label, { 15 | description: `${date.toDateString()} ${date.toLocaleTimeString()}` 16 | })} 17 | /> 18 |
    19 | -------------------------------------------------------------------------------- /src/routes/components/phone-input/basic.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 8 | 9 |
    10 | -------------------------------------------------------------------------------- /src/routes/components/phone-input/custom-ordering.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 8 | { 11 | if (a.iso2 == 'US') return -1; 12 | if (b.iso2 == 'US') return 1; 13 | if (a.iso2 == 'CN') return -1; 14 | if (b.iso2 == 'CN') return 1; 15 | 16 | return a.name.localeCompare(b.name); 17 | }} 18 | /> 19 |
    20 | -------------------------------------------------------------------------------- /src/routes/components/phone-input/default-country.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 8 | 9 |
    10 | -------------------------------------------------------------------------------- /src/routes/components/phone-input/default-value.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 |
    7 | 8 | 9 |
    10 | -------------------------------------------------------------------------------- /src/routes/components/phone-input/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import DefaultCountry from './default-country.svelte'; 4 | import defaultCountryRaw from './default-country.svelte?raw'; 5 | import DefaultValue from './default-value.svelte'; 6 | import defaultValueRaw from './default-value.svelte?raw'; 7 | import CustomOrdering from './custom-ordering.svelte'; 8 | import customOrderingRaw from './custom-ordering.svelte?raw'; 9 | 10 | const examples = { 11 | basic: { 12 | code: basicRaw, 13 | Component: Basic 14 | }, 15 | defaultCountry: { 16 | code: defaultCountryRaw, 17 | Component: DefaultCountry 18 | }, 19 | defaultValue: { 20 | code: defaultValueRaw, 21 | Component: DefaultValue 22 | }, 23 | customOrdering: { 24 | code: customOrderingRaw, 25 | Component: CustomOrdering 26 | } 27 | }; 28 | 29 | export { examples }; 30 | -------------------------------------------------------------------------------- /src/routes/components/pm-command/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/pm-command/commands.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    6 | 7 | 8 |
    9 | -------------------------------------------------------------------------------- /src/routes/components/pm-command/customize-agents.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /src/routes/components/pm-command/overflow.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 20 | -------------------------------------------------------------------------------- /src/routes/components/pm-command/persisted-pm.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/routes/components/pm-command/variants.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/snippet/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | Basic 9 | 10 | 11 | 12 | 13 | Variants 14 | 15 | 16 | 17 | Multiline 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/routes/components/snippet/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/snippet/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Variants from './variants.svelte'; 4 | import variantsRaw from './variants.svelte?raw'; 5 | import Multiline from './multiline.svelte'; 6 | import multilineRaw from './multiline.svelte?raw'; 7 | 8 | const examples = { 9 | basic: { 10 | code: basicRaw, 11 | Component: Basic 12 | }, 13 | variants: { 14 | code: variantsRaw, 15 | Component: Variants 16 | }, 17 | multiline: { 18 | code: multilineRaw, 19 | Component: Multiline 20 | } 21 | }; 22 | 23 | export { examples }; 24 | -------------------------------------------------------------------------------- /src/routes/components/snippet/multiline.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/snippet/variants.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    6 | 7 | 8 | 9 | 10 |
    11 | -------------------------------------------------------------------------------- /src/routes/components/star-rating/basic.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
    8 | 9 | {#snippet children({ items })} 10 | {#each items as item (item.index)} 11 | 12 | {/each} 13 | {/snippet} 14 | 15 | Rating is {value} 16 |
    17 | -------------------------------------------------------------------------------- /src/routes/components/star-rating/custom-color.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | {#snippet children({ items })} 7 | {#each items as item (item.index)} 8 | 9 | {/each} 10 | {/snippet} 11 | 12 | -------------------------------------------------------------------------------- /src/routes/components/star-rating/custom-size.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | {#snippet children({ items })} 7 | {#each items as item (item.index)} 8 | 9 | {/each} 10 | {/snippet} 11 | 12 | -------------------------------------------------------------------------------- /src/routes/components/star-rating/custom-stars.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | {#snippet children({ items })} 7 | {#each items as item (item.index)} 8 | 9 | {/each} 10 | {/snippet} 11 | 12 | -------------------------------------------------------------------------------- /src/routes/components/star-rating/disabled.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | {#snippet children({ items })} 7 | {#each items as item (item.index)} 8 | 9 | {/each} 10 | {/snippet} 11 | 12 | -------------------------------------------------------------------------------- /src/routes/components/star-rating/half-rating.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
    8 |
    9 | 10 | {#snippet children({ items })} 11 | {#each items as item (item.index)} 12 | 13 | {/each} 14 | {/snippet} 15 | 16 | Rating is {value} 17 |
    18 |
    19 | تقييم بالنجوم (RTL) 20 | 21 | {#snippet children({ items })} 22 | {#each items as item (item.index)} 23 | 24 | {/each} 25 | {/snippet} 26 | 27 |
    28 |
    29 | -------------------------------------------------------------------------------- /src/routes/components/star-rating/readonly.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | {#snippet children({ items })} 7 | {#each items as item (item.index)} 8 | 9 | {/each} 10 | {/snippet} 11 | 12 | -------------------------------------------------------------------------------- /src/routes/components/tags-input/basic.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
    8 | 9 |
    10 | -------------------------------------------------------------------------------- /src/routes/components/tags-input/custom-validate.ts: -------------------------------------------------------------------------------- 1 | import type { TagsInputProps } from '$lib/components/ui/tags-input/types'; 2 | 3 | export const customValidate: TagsInputProps['validate'] = (val, tags) => { 4 | // trim and convert to lowercase 5 | const transformed = val.trim().toLowerCase(); 6 | 7 | // disallow empties 8 | if (transformed.length === 0) return undefined; 9 | 10 | // disallow duplicates 11 | if (tags.find((t) => transformed === t.toLowerCase())) return undefined; 12 | 13 | return transformed; 14 | }; 15 | -------------------------------------------------------------------------------- /src/routes/components/tags-input/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import customValidateCode from './custom-validate?raw'; 4 | import Lowercase from './lowercase.svelte'; 5 | import lowercaseRaw from './lowercase.svelte?raw'; 6 | 7 | const examples = { 8 | basic: { 9 | code: basicRaw, 10 | Component: Basic 11 | }, 12 | customValidateCode, 13 | lowercase: { 14 | code: lowercaseRaw, 15 | Component: Lowercase 16 | } 17 | }; 18 | 19 | export { examples }; 20 | -------------------------------------------------------------------------------- /src/routes/components/tags-input/lowercase.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
    9 | 10 |
    11 | -------------------------------------------------------------------------------- /src/routes/components/terminal/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Loop from './loop.svelte'; 4 | import loopRaw from './loop.svelte?raw'; 5 | 6 | const examples = { 7 | basic: { 8 | code: basicRaw, 9 | Component: Basic 10 | }, 11 | loop: { 12 | code: loopRaw, 13 | Component: Loop 14 | } 15 | }; 16 | 17 | export { examples }; 18 | -------------------------------------------------------------------------------- /src/routes/components/theme-selector/+page.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | Basic 9 | 10 | 11 | 12 | 13 | Ghost 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/routes/components/theme-selector/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/theme-selector/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import Variants from './variants.svelte'; 4 | import variantsRaw from './variants.svelte?raw'; 5 | 6 | const examples = { 7 | basic: { 8 | code: basicRaw, 9 | Component: Basic 10 | }, 11 | variants: { 12 | code: variantsRaw, 13 | Component: Variants 14 | } 15 | }; 16 | 17 | export { examples }; 18 | -------------------------------------------------------------------------------- /src/routes/components/theme-selector/variants.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/components/toc/+page.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | Usage 14 |
    15 | 18 | import * as Toc from '$lib/components/ui/toc'; 19 | \<\/script\> 20 | 21 | `} 22 | /> 23 |
    24 | Generate the table of contents with UseToc 25 |
    26 | 29 | import * as Toc from '$lib/components/ui/toc'; 30 | 31 | const toc = new UseToc(); 32 | \<\/script\> 33 | 34 |
    35 | 36 |
    37 | `} 38 | /> 39 |
    40 | -------------------------------------------------------------------------------- /src/routes/components/toc/basic.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/routes/components/toc/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | 4 | const examples = { 5 | basic: { 6 | code: basicRaw, 7 | Component: Basic 8 | } 9 | }; 10 | 11 | export { examples }; 12 | -------------------------------------------------------------------------------- /src/routes/components/toc/toc.ts: -------------------------------------------------------------------------------- 1 | export const toc = [ 2 | { 3 | kind: 'h2', 4 | id: 'cli', 5 | level: 2, 6 | label: 'CLI', 7 | active: false, 8 | children: [ 9 | { 10 | kind: 'h3', 11 | id: 'cli-installation', 12 | level: 3, 13 | label: 'Installation', 14 | active: false, 15 | children: [] 16 | } 17 | ] 18 | }, 19 | { 20 | kind: 'h2', 21 | id: 'usage', 22 | level: 2, 23 | label: 'Usage', 24 | active: false, 25 | children: [ 26 | { 27 | kind: 'h3', 28 | id: 'usage-components', 29 | level: 3, 30 | label: 'Components', 31 | active: false, 32 | children: [] 33 | }, 34 | { 35 | kind: 'h3', 36 | id: 'hooks', 37 | level: 3, 38 | label: 'Hooks', 39 | active: false, 40 | children: [] 41 | } 42 | ] 43 | } 44 | ]; 45 | -------------------------------------------------------------------------------- /src/routes/components/tree-view/+page.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | Basic 10 | 11 | 12 | 13 | 14 | Custom Icons 15 | 16 | 17 | 18 |

    19 | If you are using custom icons in a project we recommend you wrap the folder/file components with 20 | the custom icons: 21 |

    22 | 23 | -------------------------------------------------------------------------------- /src/routes/components/tree-view/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
    6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    17 | -------------------------------------------------------------------------------- /src/routes/components/tree-view/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | import CustomIcons from './custom-icons.svelte'; 4 | import customIconsRaw from './custom-icons.svelte?raw'; 5 | import treeViewFileCustomRaw from './tree-view-file-custom.svelte?raw'; 6 | 7 | const examples = { 8 | basic: { 9 | code: basicRaw, 10 | Component: Basic 11 | }, 12 | customIcons: { 13 | code: customIconsRaw, 14 | Component: CustomIcons 15 | }, 16 | customFileComponentCode: treeViewFileCustomRaw 17 | }; 18 | 19 | export { examples }; 20 | -------------------------------------------------------------------------------- /src/routes/components/tree-view/tree-view-file-custom.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | {#snippet icon({ name })} 14 | {#if name.endsWith('.css')} 15 | 16 | {:else if name.endsWith('.svelte')} 17 | 18 | {:else if name.endsWith('.ts')} 19 | 20 | {/if} 21 | {/snippet} 22 | 23 | -------------------------------------------------------------------------------- /src/routes/components/window/+page.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/routes/components/window/basic.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | # Window 7 |

    An awesome styled window component.

    8 |
    9 | -------------------------------------------------------------------------------- /src/routes/components/window/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | 4 | const examples = { 5 | basic: { 6 | code: basicRaw, 7 | Component: Basic 8 | } 9 | }; 10 | 11 | export { examples }; 12 | -------------------------------------------------------------------------------- /src/routes/docs/using-extras/+page.server.ts: -------------------------------------------------------------------------------- 1 | import { redirect } from '@sveltejs/kit'; 2 | 3 | // just in case anyone linked to the old path 4 | 5 | export function load() { 6 | throw redirect(307, '/docs/installation'); 7 | } 8 | -------------------------------------------------------------------------------- /src/routes/docs/using-extras/+page.svelte: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ieedan/shadcn-svelte-extras/fd06d9df74e6a1a25ff1ef00b17f5dd9cf1b92fd/src/routes/docs/using-extras/+page.svelte -------------------------------------------------------------------------------- /src/routes/hooks/use-auto-scroll/+page.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | Usage 9 |

    Create a container that automatically scrolls to the bottom.

    10 | 14 | import { UseAutoScroll } from '$lib/hooks/use-auto-scroll.svelte'; 15 | 16 | let { children } = $props(); 17 | 18 | const autoScroll = new UseAutoScroll(); 19 | \<\/script\> 20 | 21 |
    22 |
    23 | {@render children?.()} 24 |
    25 | {#if !autoScroll.isAtBottom} 26 | 29 | {/if} 30 |
    `} 31 | /> 32 | -------------------------------------------------------------------------------- /src/routes/hooks/use-promise/basic.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 |
    26 | 30 |
    31 | -------------------------------------------------------------------------------- /src/routes/hooks/use-promise/examples.ts: -------------------------------------------------------------------------------- 1 | import Basic from './basic.svelte'; 2 | import basicRaw from './basic.svelte?raw'; 3 | 4 | const examples = { 5 | basic: { 6 | code: basicRaw, 7 | Component: Basic 8 | } 9 | }; 10 | 11 | export { examples }; 12 | -------------------------------------------------------------------------------- /src/routes/hooks/use-toc/+page.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | Usage 9 |

    Generate a table of contents using the content of the page.

    10 | 14 | const toc = new UseToc(); 15 | \<\/script\> 16 | 17 |
    18 |

    Installation

    19 |

    CLI

    20 |

    Manual

    21 |

    Usage

    22 |
    `} 23 | /> 24 | -------------------------------------------------------------------------------- /static/dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /static/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ieedan/shadcn-svelte-extras/fd06d9df74e6a1a25ff1ef00b17f5dd9cf1b92fd/static/favicon.png -------------------------------------------------------------------------------- /static/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /static/light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /static/og.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ieedan/shadcn-svelte-extras/fd06d9df74e6a1a25ff1ef00b17f5dd9cf1b92fd/static/og.png -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-vercel'; 2 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; 3 | 4 | /** @type {import('@sveltejs/kit').Config} */ 5 | const config = { 6 | // Consult https://svelte.dev/docs/kit/integrations 7 | // for more information about preprocessors 8 | preprocess: vitePreprocess(), 9 | 10 | kit: { 11 | adapter: adapter() 12 | } 13 | }; 14 | 15 | export default config; 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "allowJs": true, 5 | "checkJs": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "sourceMap": true, 11 | "strict": true, 12 | "moduleResolution": "bundler" 13 | }, 14 | "exclude": ["src/lib/paraglide/**"] 15 | // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias 16 | // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files 17 | // 18 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 19 | // from the referenced tsconfig.json - TypeScript does not merge them in 20 | } 21 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { paraglideVitePlugin } from '@inlang/paraglide-js'; 2 | import { sveltekit } from '@sveltejs/kit/vite'; 3 | import { defineConfig } from 'vite'; 4 | import tailwindcss from '@tailwindcss/vite'; 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | tailwindcss(), 9 | paraglideVitePlugin({ 10 | project: './project.inlang', 11 | outdir: './src/lib/paraglide', 12 | strategy: ['url', 'cookie', 'baseLocale'], 13 | disableAsyncLocalStorage: true 14 | }), 15 | sveltekit() 16 | ] 17 | }); 18 | --------------------------------------------------------------------------------