├── .env.example ├── .github └── workflows │ └── deploy.yaml ├── .gitignore ├── .husky └── pre-commit ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── components.json ├── data └── libraries │ ├── agustinl--svelte-tags-input.json │ ├── ampled--svelte-inspect-value.json │ ├── animotionjs--animotion.json │ ├── ankurrsinghal--svelte-intense.json │ ├── artiebits--svelte-seo.json │ ├── bartholomej--svelte-sitemap.json │ ├── barvian--number-flow.json │ ├── bryanmylee--svelte-headless-table.json │ ├── carstenlebek--svelte-email.json │ ├── chakra-ui--ark.json │ ├── chakra-ui--zag.json │ ├── ciscoheat--sveltekit-flash-message.json │ ├── ciscoheat--sveltekit-rate-limiter.json │ ├── ciscoheat--sveltekit-superforms.json │ ├── codediodeio--sveltefire.json │ ├── cweili--svelte-fa.json │ ├── dasdaniel--svelte-table.json │ ├── devantic--diaper.json │ ├── diericx--svelte-breadcrumbs.json │ ├── dominic-schmid--svelte-selfheal.json │ ├── friendofsvelte--tipex.json │ ├── heithemmoumni--svelte-mindmap.json │ ├── hperrin--svelte-material-ui.json │ ├── huntabyte--cmdk-sv.json │ ├── huntabyte--shadcn-svelte.json │ ├── huntabyte--svelte-toolbelt.json │ ├── huntabyte--vaul-svelte.json │ ├── isaachagoel--svelte-dnd-action.json │ ├── janosh--svelte-bricks.json │ ├── jasongitmail--super-sitemap.json │ ├── jonasgeiler--svelte-infinite-loading.json │ ├── joshnuss--svelte-stripe.json │ ├── joysofcode--sveltedown.json │ ├── joysofcode--sveltekit-flexsearch.json │ ├── kampsy--ui.json │ ├── kbrgl--svelte-french-toast.json │ ├── kitschpatrol--svelte-tweakpane-ui.json │ ├── lucide-icons--lucide.json │ ├── matyunya--smelte.json │ ├── melt-ui--melt-ui.json │ ├── metonym--svelte-highlight.json │ ├── metonym--svelte-time.json │ ├── meursyphus--ssgoi.json │ ├── micha-lmxt--svelte-motion.json │ ├── mierune--svelte-maplibre-gl.json │ ├── mitcheljager--svelte-confetti.json │ ├── mskocik--svelty-picker.json │ ├── oekazuma--svelte-meta-tags.json │ ├── open-source-labs--svelvet.json │ ├── orefalo--svelte-splitpanes.json │ ├── orefalo--svelte-virtuallists.json │ ├── paoloricciuti--sveltekit-search-params.json │ ├── paoloricciuti--sveltekit-view-transition.json │ ├── pngwn--mdsvex.json │ ├── retrotheft--svelte-mainloop.json │ ├── rezi--svelte-gestures.json │ ├── rgossiaux--svelte-headlessui.json │ ├── rich-harris--declarative-handlers.json │ ├── rich-harris--svelte-cubed.json │ ├── shyakadavis--geist.json │ ├── sikandarjodd--cnblocks.json │ ├── sockmaster27--svader.json │ ├── svecosystem--barqode.json │ ├── svecosystem--formsnap.json │ ├── svecosystem--mode-watcher.json │ ├── svecosystem--paneforge.json │ ├── svecosystem--runed.json │ ├── svecosystem--strip-types.json │ ├── svecosystem--svelte-interactions.json │ ├── svelte-inview--svelte-inview.json │ ├── sveltejs--branding.json │ ├── sveltejs--svelte-devtools.json │ ├── sveltejs--vite-plugin-svelte.json │ ├── sveltelab--sveltelab.json │ ├── sveltepress--sveltepress.json │ ├── sveltestack--svelte-query.json │ ├── sveltestrap--sveltestrap.json │ ├── svelteuidev--svelteui.json │ ├── swyxio--svelte-actions.json │ ├── tahash--swapy.json │ ├── techniq--layerchart.json │ ├── techniq--svelte-ux.json │ ├── themesberg--flowbite-svelte.json │ ├── thisuxhq--sveltednd.json │ ├── threlte--threlte.json │ ├── touchifyapp--svelte-codemirror-editor.json │ ├── tsuzat--edra.json │ ├── tzezar--datagrid.json │ ├── umaranis--svelte-lexical.json │ ├── vercel--ai.json │ ├── vincjo--datatables.json │ ├── vinodnimbalkar--svelte-pdf.json │ ├── vnphanquang--svelte-put.json │ ├── wobsoriano--svelte-sonner.json │ ├── xyflow--xyflow.json │ ├── zerodevx--svelte-img.json │ └── zerodevx--svelte-toast.json ├── eslint.config.js ├── package.json ├── pnpm-lock.yaml ├── scripts ├── cli.ts ├── commands │ ├── add.ts │ ├── compile.ts │ └── update.ts └── utils │ ├── file.ts │ ├── github.ts │ ├── index.ts │ ├── library.ts │ └── logger.ts ├── src ├── app.css ├── app.d.ts ├── app.html ├── lib │ ├── assets │ │ ├── compiled-data.json │ │ ├── github-mark-white.svg │ │ └── github-mark.svg │ ├── components │ │ ├── controls │ │ │ ├── controls-sort-direction.svelte │ │ │ ├── controls-sort-selector.svelte │ │ │ ├── controls-tag-filter.svelte │ │ │ ├── controls.svelte │ │ │ └── index.ts │ │ ├── error │ │ │ ├── error-confetti-button.svelte │ │ │ ├── error-status.svelte │ │ │ ├── error.svelte │ │ │ └── index.ts │ │ ├── footer │ │ │ ├── footer.svelte │ │ │ └── index.ts │ │ ├── header │ │ │ ├── header-light-switch.svelte │ │ │ ├── header-repository-link.svelte │ │ │ ├── header-search.svelte │ │ │ ├── header.svelte │ │ │ └── index.ts │ │ ├── library-collection │ │ │ ├── index.ts │ │ │ ├── library-collection-item-header.svelte │ │ │ ├── library-collection-item-tag-list.svelte │ │ │ ├── library-collection-item.svelte │ │ │ ├── library-collection-pagination.svelte │ │ │ └── library-collection.svelte │ │ └── ui │ │ │ ├── alert │ │ │ ├── alert-description.svelte │ │ │ ├── alert-title.svelte │ │ │ ├── alert.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-content.svelte │ │ │ ├── card-description.svelte │ │ │ ├── card-footer.svelte │ │ │ ├── card-header.svelte │ │ │ ├── card-title.svelte │ │ │ ├── card.svelte │ │ │ └── index.ts │ │ │ ├── checkbox │ │ │ ├── checkbox.svelte │ │ │ └── index.ts │ │ │ ├── input │ │ │ ├── index.ts │ │ │ └── input.svelte │ │ │ ├── label │ │ │ ├── index.ts │ │ │ └── label.svelte │ │ │ ├── radio-group │ │ │ ├── index.ts │ │ │ ├── radio-group-item.svelte │ │ │ └── radio-group.svelte │ │ │ ├── scroll-area │ │ │ ├── index.ts │ │ │ ├── scroll-area-scrollbar.svelte │ │ │ └── scroll-area.svelte │ │ │ ├── separator │ │ │ ├── index.ts │ │ │ └── separator.svelte │ │ │ ├── sheet │ │ │ ├── index.ts │ │ │ ├── sheet-content.svelte │ │ │ ├── sheet-description.svelte │ │ │ ├── sheet-footer.svelte │ │ │ ├── sheet-header.svelte │ │ │ ├── sheet-overlay.svelte │ │ │ └── sheet-title.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 │ │ │ ├── toggle-group │ │ │ ├── index.ts │ │ │ ├── toggle-group-item.svelte │ │ │ └── toggle-group.svelte │ │ │ ├── toggle │ │ │ ├── index.ts │ │ │ └── toggle.svelte │ │ │ └── tooltip │ │ │ ├── index.ts │ │ │ └── tooltip-content.svelte │ ├── constants.ts │ ├── hooks │ │ ├── is-mobile.svelte.ts │ │ └── query-params.svelte.ts │ ├── index.ts │ ├── schema.ts │ ├── types.ts │ └── utils.ts └── routes │ ├── +error.svelte │ ├── +layout.svelte │ ├── +layout.ts │ ├── +page.svelte │ └── +page.ts ├── static ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon.png ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── fonts │ └── Geist │ │ ├── Geist[wght].woff2 │ │ └── LICENSE.txt ├── og-image.png └── site.webmanifest ├── svelte.config.js ├── tailwind.config.js ├── tsconfig.json └── vite.config.ts /.env.example: -------------------------------------------------------------------------------- 1 | PUBLIC_REPOSITORY_URL=https://github.com/klementine-org/svelte-directory 2 | GITHUB_TOKEN= # Required for the CLI -------------------------------------------------------------------------------- /.github/workflows/deploy.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 'main' 6 | 7 | jobs: 8 | build_site: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | 14 | - name: Install pnpm 15 | uses: pnpm/action-setup@v3 16 | with: 17 | version: 10 18 | 19 | - name: Install Node.js 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: 22 23 | cache: pnpm 24 | 25 | - name: Install dependencies 26 | run: pnpm install 27 | 28 | - name: build 29 | env: 30 | BASE_PATH: '/${{ github.event.repository.name }}' 31 | PUBLIC_REPOSITORY_URL: 'https://github.com/klementine-org/svelte-directory' 32 | run: | 33 | pnpm build 34 | - name: Upload Artifacts 35 | uses: actions/upload-pages-artifact@v3 36 | with: 37 | # this should match the `pages` option in your adapter-static options 38 | path: 'build/' 39 | 40 | deploy: 41 | needs: build_site 42 | runs-on: ubuntu-latest 43 | 44 | permissions: 45 | pages: write 46 | id-token: write 47 | 48 | environment: 49 | name: github-pages 50 | url: ${{ steps.deployment.outputs.page_url }} 51 | 52 | steps: 53 | - name: Deploy 54 | id: deployment 55 | uses: actions/deploy-pages@v4 -------------------------------------------------------------------------------- /.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 | # IDE 26 | .idea 27 | .vscode -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm dlx lint-staged -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v22.14.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Package Managers 2 | package-lock.json 3 | pnpm-lock.yaml 4 | yarn.lock 5 | bun.lock 6 | bun.lockb 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"], 7 | "overrides": [ 8 | { 9 | "files": "*.svelte", 10 | "options": { 11 | "parser": "svelte" 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2025 Klementine 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | Svelte Directory Logo 3 |
4 |

Svelte Directory

5 | 6 |

7 | 8 | License 9 | 10 | 11 | Stars 12 | 13 | 14 | Forks 15 | 16 | 17 | Issues 18 | 19 | 20 | Pull Requests 21 | 22 | 23 | Last Commit 24 | 25 |

26 | 27 |

28 | A curated directory of Svelte libraries, components, and tools to enhance your Svelte development experience. 29 |

30 | 31 | ## 📚 Add Library 32 | 33 | The Svelte Directory is a community-driven collection of Svelte libraries and components. 34 | We welcome contributions from the community to help grow this resource. 35 | To add a new library or component, please follow the steps below: 36 | 37 | 1. [Create a new issue](https://github.com/klementine-org/svelte-directory/issues/new/choose) in the repository with the title "Add: [Library Name]" 38 | 2. Add the GitHub URL to your issue description 39 | 3. Our team will review the submission and add it to the directory 40 | 41 | ## 💻 Development 42 | 43 | ### Installation 44 | 45 | 1. Clone the repository: 46 | 47 | ```bash 48 | git clone https://github.com/klementine-org/svelte-directory.git 49 | cd svelte-directory 50 | ``` 51 | 52 | 2. Install [Node.js](https://nodejs.org/) (check the `.nvmrc` file for the recommended version) 53 | 3. Install [pnpm](https://pnpm.io/): 54 | 55 | ```bash 56 | corepack enable pnpm 57 | ``` 58 | 59 | 4. Install dependencies: 60 | 61 | ```bash 62 | # Using pnpm (recommended) 63 | pnpm install 64 | ``` 65 | 66 | ### Scripts 67 | 68 | - Start the development server: 69 | 70 | ```bash 71 | pnpm dev 72 | ``` 73 | 74 | - Build the project for production: 75 | 76 | ```bash 77 | pnpm build 78 | ``` 79 | 80 | - Preview the production build: 81 | 82 | ```bash 83 | pnpm preview 84 | ``` 85 | 86 | - Library management: 87 | 88 | ```bash 89 | # Compile library from data/libraries to src/lib/assets/compiled-data (with search index and tags set) 90 | pnpm lib:compile 91 | 92 | # Add a new library to data/libraries (with GitHub URL) 93 | pnpm lib:add 94 | 95 | # Update all libraries in data/libraries with the latest information from GitHub 96 | pnpm lib:update 97 | 98 | # Update specific libraries in data/libraries with the latest information from GitHub (separate multiple URLs with spaces) 99 | pnpm lib:update [] 100 | 101 | # Example 102 | pnpm lib:update https://github.com/huntabyte/shadcn-svelte https://github.com/ciscoheat/sveltekit-superforms 103 | ``` 104 | 105 | ## 👥 Contributing 106 | 107 | Contributions are welcome! Here's how you can contribute: 108 | 109 | 1. Fork the repository 110 | 2. Create a new branch (`git checkout -b feature/amazing-feature`) 111 | 3. Make your changes 112 | 4. Commit your changes (`git commit -m ':gitmoji: Add some amazing feature'`) 113 | > Note: Prefix commit messages with [:gitmoji:](https://gitmoji.dev/) 114 | 5. Push to the branch (`git push origin feature/amazing-feature`) 115 | 6. Open a Pull Request 116 | 117 | ## 📄 License 118 | 119 | This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details. 120 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://next.shadcn-svelte.com/schema.json", 3 | "style": "default", 4 | "tailwind": { 5 | "config": "tailwind.config.js", 6 | "css": "src/app.css", 7 | "baseColor": "slate" 8 | }, 9 | "aliases": { 10 | "components": "$lib/components", 11 | "utils": "$lib/utils", 12 | "ui": "$lib/components/ui", 13 | "hooks": "$lib/hooks" 14 | }, 15 | "typescript": true, 16 | "registry": "https://next.shadcn-svelte.com/registry" 17 | } 18 | -------------------------------------------------------------------------------- /data/libraries/melt-ui--melt-ui.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "melt-ui--melt-ui", 3 | "name": "melt-ui", 4 | "description": "A set of headless, accessible component builders for Svelte.", 5 | "owner": "melt-ui", 6 | "ownerAvatarBase64": "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", 7 | "authors": ["TGlide", "huntabyte", "github-actions[bot]", "AdrianGonz97", "HalfdanJ"], 8 | "websiteUrl": "https://melt-ui.com", 9 | "githubUrl": "https://github.com/melt-ui/melt-ui", 10 | "stars": 3999, 11 | "lastUpdated": "2025-03-28", 12 | "topics": ["component-library", "headless", "svelte", "typescript"], 13 | "license": "MIT", 14 | "version": "0.86.6" 15 | } 16 | -------------------------------------------------------------------------------- /data/libraries/mitcheljager--svelte-confetti.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "mitcheljager--svelte-confetti", 3 | "name": "svelte-confetti", 4 | "description": "Confetti in Svelte! Celebrate things with some extra flair. Animates using just HTML and CSS meaning it can work with SSR in SvelteKit!", 5 | "owner": "Mitcheljager", 6 | "ownerAvatarBase64": "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", 7 | "authors": ["Mitcheljager", "bersling", "mstachowiak"], 8 | "websiteUrl": "https://mitcheljager.github.io/svelte-confetti/", 9 | "githubUrl": "https://github.com/Mitcheljager/svelte-confetti", 10 | "stars": 286, 11 | "lastUpdated": "2025-02-07", 12 | "topics": ["svelte"], 13 | "license": "Unlicense", 14 | "version": "unknown" 15 | } 16 | -------------------------------------------------------------------------------- /data/libraries/rezi--svelte-gestures.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "rezi--svelte-gestures", 3 | "name": "svelte-gestures", 4 | "description": "A library called svelte-gestures", 5 | "owner": "Rezi", 6 | "ownerAvatarBase64": "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", 7 | "authors": ["Rezi", "ydylla", "gwennlbh", "xpengy"], 8 | "websiteUrl": "https://github.com/Rezi/svelte-gestures", 9 | "githubUrl": "https://github.com/Rezi/svelte-gestures", 10 | "stars": 148, 11 | "lastUpdated": "2025-04-22", 12 | "topics": [], 13 | "license": "MIT", 14 | "version": "-1.3.2" 15 | } 16 | -------------------------------------------------------------------------------- /data/libraries/rgossiaux--svelte-headlessui.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "rgossiaux--svelte-headlessui", 3 | "name": "svelte-headlessui", 4 | "description": "Unofficial Svelte port of the Headless UI component library", 5 | "owner": "rgossiaux", 6 | "ownerAvatarBase64": "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", 7 | "authors": ["rgossiaux", "davepar", "dependabot[bot]", "VitroidFPV", "safwanolaimat"], 8 | "websiteUrl": "https://svelte-headlessui.goss.io", 9 | "githubUrl": "https://github.com/rgossiaux/svelte-headlessui", 10 | "stars": 1806, 11 | "lastUpdated": "2023-06-11", 12 | "topics": ["svelte", "svelte-components", "svelte3", "sveltejs"], 13 | "license": "MIT", 14 | "version": "2.0.0" 15 | } 16 | -------------------------------------------------------------------------------- /data/libraries/svelte-inview--svelte-inview.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "svelte-inview--svelte-inview", 3 | "name": "svelte-inview", 4 | "description": "A Svelte action that monitors an element enters or leaves the viewport.🔥 ", 5 | "owner": "svelte-inview", 6 | "ownerAvatarBase64": "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", 7 | "authors": ["maciekgrzybek", "phocks", "nosovk", "jhubbardsf", "mindvoxel"], 8 | "websiteUrl": "https://github.com/svelte-inview/svelte-inview", 9 | "githubUrl": "https://github.com/svelte-inview/svelte-inview", 10 | "stars": 772, 11 | "lastUpdated": "2024-10-01", 12 | "topics": [ 13 | "hacktoberfest", 14 | "intersection-observer", 15 | "intersectionobserver", 16 | "intersectionobserver-api", 17 | "javascript", 18 | "observer", 19 | "svelte", 20 | "svelte-component", 21 | "svelte-js", 22 | "svelte3", 23 | "typescript", 24 | "viewport" 25 | ], 26 | "license": "MIT", 27 | "version": "4.0.4" 28 | } 29 | -------------------------------------------------------------------------------- /data/libraries/svelteuidev--svelteui.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "svelteuidev--svelteui", 3 | "name": "svelteui", 4 | "description": "SvelteUI Monorepo", 5 | "owner": "svelteuidev", 6 | "ownerAvatarBase64": "iVBORw0KGgoAAAANSUhEUgAAAG4AAABuCAYAAADGWyb7AAAQbElEQVR4nOxdXW8U1/l/zrzYjg1/r4Njg/kLm5A4SqSYxQbaG6hJgtSLRiFS7lopWCVUFZUCnwD4BAlSEQolwpHaq6QKUXJRNW0wcFNhXrZEApWExIsUu+YluxvAWXt35lTP2R2z3rd5Zs45O2vIT7K8LOudmfM7z+t5nnMsWIaIH03FwYC4YcAAY0Y/AI9xgDj+HwOIQeGnFGkOkGYM0vgaOJvi3E26AAnIw1RiX1cimicJDxb1DfghfjIVgyzssixjIwc+ChwGqhAjDwYTDFgi77pnoAUmEmNdaeXXUIimJC5+LDVgWMabrEDUaCQ3wWCCu/wT14VTid93TUVyD3XQNMShZBkLsJsZ7LXIyKoFBgnO+RHXgYlmITFy4uLHUqOmabwJwHdpUYHKwcYdxz0cNYGREScIs9jBppMuKhhMOHmOBE5Ec/kGY9kTVo4CgWONlsCGEYc2zMwZ7wDw3Y26ZmPRWBXaEOJGjmfeBuCHlocNk8IUOjGXftf1ru4LaSUO3XrTYicfGbVIx5Tj8B06pc/Q9cUoZabJLj+GpCEG8NmH30vt13UB5RIn4rG8cZBxru2mlxMYY+9eeKvzgPLvVfllqBotk33s5Q1/wiKUq05lqjJ+NBU3TXb6J9KqAlXnaZzYqr5QicQJ0mx2+jHwGmWRNnJ8x6SC1Qhp4kZO/PAmuO647PfohG0w6FvJoLOVQUdL4bdtFt73MJfjMJcDSGddyMxzuD3HxXtaYBi7L+75vw9kvkKKuGYmDUnpjzHoW2FAd3s4i5DJckj+4MD0PQ0kSpIXmriierwc9u91AQl75klD/JRKlCySGQeu3XGVEmjk+KawajPUk4nA2hSkNZVNQ7Ke7zaVElYOxQSGtnmBn7BIGjoiyjwkWbTbDDavMUOrxKBA0q7dcSCZcVV8XahQIfCTNhtpKGUvr7caRhoUJ8rIGktItwKgIHwsSjQCINDTDv8p806zkPZUO4OXBmwY6rG0qsZ6QOJG1ighL27ljYNB/oD8xMUMv/astx+QpOe70flQMmBKkM5y+GIqJ/09nPMD1JUFEnHN4oyglA2vsaDDjrziogLotFyccWS/Ju04fBPF3pHqKot2LTLSVEnZuk4Dnuu2oKeDQWcbg1hrYQLM5zmk5wFm77tw/a4jfoKiv9MUATw6LRKImSY7CQA7/D7oO3WjVpE42Bt75Vz8oV4TtvXbImNCgQi8My6cu5kTr4Pg7M083JmT8zYpKrPuk0Tp+qtw8Xs7GLyyoQX6O8NnTpC8K7N0KcJQ4Z/f5iHnSsV5acfm6+sV5dZ9ItMUnk7DSZN18VstJiTst8NtoUlDoDr91WALvLLBJv8NTji8f0kU63Nqo6bEFaXtW9k7CAIcqI09clKGqvXV51rIapEKlLrPri+QPptzAP52IycrdcAcvuNCjfK/ms5JsVakIfDyizIBLUrZ9n4LtvTp6WNBO5l1bPjHDX+33zYLWkPSUQFuMtR4VYmrOi0L1cXCtmmHChd/cJUJOzfQnQ8ZfP5NDia/y/t+TrfUVZ2exYJV7RjqMaVcfM8GydixoNi2zhJqE0OIekCp61vJIJmRG8haUlfxxGJ5XXNlFqrG7essKdK2rrVgz6bWhpKGaLMYbO2j3bei/Ono5mOpCj4qvrnoSWoDkoazNuxDoZT9eqgVXnnaFnZNBjczLnw564jfQbBlLc2O9q1QM6m4aIpZiiVP3ghP8qUBG2Jt4QYcXXyc7SoIO5vMLSEsqNr985V5EuFo5xSs3VXEdUvu0gC9KhJtWhjS0MXft7VNSKoMaWiXPr+RqzroGGz/9eoCzD6gDfJzq2jqsjPkJC2D6B0sfWMJccxib6u4SjXg4Ae1aUgSeou/GWqV9hiRqBOX52FyurZHmBXE0mI1KiEdktrBA2PstdJ/LyrrolOipSaykCQORpqqQBolCV14auL4FlHiqMTZ6lafRjed+LH/8p4nklBKnGHALmWXKAMGo9Q4TUjZ07YIeGWB8dbZm3lf1325gDnZMQA4BKXEFXuvlaPdZkJ6KMBZrEItopR9en0hsLcIRXX5/qUsDK22RGBf617m/WNw5WCM/WLxNSw2HbKUjoshaZvX+LvPKGl7huVIQ8k6/10ezk/7B8hUvNhrwvYqS0Koej+66m8Pr91xpFNfpXBs3oXepRhRcwFGdXXKPUt0SFA9ypCG0oVSFnT9zA8Y5+FPOYHJNE2aVRfSGjlh0sYFcZzBqA7eUE1SyEB7FtamoWSdTebreosqgOR9ddcVIQkG4Ne/p0nRA/lSlHIIB1IQxxjbqMO+dbfTpgMG1mGA6go9RtVSVgsiXPgmJ1bHqddUfW8MCnauYHw05SYpKR+0gUFVpIzzoQLU0CIzz6VXB6pALGxb8eMpbf1sLaY/IdQMhIfl5OLffqBlYsXiR1Nxy+QwoMsx6Wzz/0wPMRGLRH14VU7K0HMdXGXAE2bhdZttQDbnijRXOsvhluKBTv6gZ3IZNsQtDhDXtfxIqcxa3UG7+t+/yYUiDQna2GPAs91WjQTyQ4mXqe4qx+05DpmsJlXOYQCJG4iyvJSSNEan4MsAlVYeMIB+dZC+/NPZxmCoreDhXpl1pAi8mVEXu5WDMaPfMgzW36jakrAImqVQsTKO5OHfo3oOqkIxdlPUyVMdrttl6KxQpnhUFCejNUD9j8qVcZwAe4Zb4cXeYAVI6DxphcE2GpzrI26BoC0yWf/PtFnMd9W5t0Pdyng5UN1S861QLIDSDYNplDiKfUgSbcG2dRb0dFQOnqriVz+88UILeSlnXaf2TqKYpVNVUvJ0/7nrkGo42opJaHQaMABGhwU90i3/35iyPLw+2s2/XJn3/SxKXHe7Id1DUAcxrbugT9/n8MyT9T+DLn5mnpMHXyavKQuUaFSZlLCkbwWDO3P67kVrbRvGMRQH5WxSfSZWF6h51b6VessGtUpczgWxR0h/Z31pwhhtqNdtWI3kpFizywsbjE4N2qTt/bRCJLxHtHV+9rvdZiIBoSFXKWCIAxQ0ghrPfHZ9QXv+cfYBFxVepSsK+N7kdF4UElGvP0hcY+wmZoVCIG1wzcShgb495z8gOJAfElaUw8Ary3v/UramfcLrnyf0BCB6ifnVFn0KJN0Q3TSXo0kdDupHV9VKHqUsz8PkNC00odaGtuvrVU9jHKf1XJmn2g3RH00Fuvo40OhpygDJ//T6glCN1HxjljhhqB6wrUssGKQtl/OMwfTFQWF63nCgj57PiqB7aLUVOE4Lu2bXWyXAr4asQ/tem7AeGQqcTaEfpW3DZ5Q2avlCNZy7WajYGlxlwMZeq27aCSX0yn/lKryozRzUpLeubRM5d5MWuDAFmuLZdT5hAAXzxSUdb1kH3Xd029ElxwHEWDE9T0tW14LXzUoN7GfvR1My4QHNm+WakNCVh9ARhBaaMjhARs33hSl1nyLmV9OSdroWnDxMGYm9Yss95SEBqsmo9tiioLWYewxaOY3296u71JpKiRusg8S+rkRBqTOYUt3wQbFtqO4GV5mknmqVQJW4M+Tyz5VZ2r3mHNBTusAKbcWFgljOzzBgSol7itBx2t9piAFEb05FnYcfZFfG8f6u3KKpyds/6nJM+L9hMVfpQEK1g0JpLxpcVbi8VyZwfjqvTfq2rrWkGyPPBphcM/f01JwwXiJxbhucMnNwUuUF2glJ9FiJbUFpQOnb2mcJ6QtSLVwPsttCeTiXzJELllBNTt/T5Ji0lBCXGOtKjxxP4xvKKpopjknPisrPeOoMilkU/Amyl5YHlCxPymSBpJ0LUEcyfZ+2nBUY7OGhu4tPJewcY011gBE6Lmj/ghKnsps1TKm7yraqUnCXf+K9XiTOdWHcNEHrVhnlwKBZZWGPym2hwqbNkDRdGRPXhVPe60XFX9yVVNl5nw8IN58lTExUnZQKK5TOP2xplSYNpcxbswtKmrc7uiYkSneOXTIinD8URVnkCdolmaY95M4NLTUl09uw5o0Xan+GCrRlJy7T9i8pB9o0nfWUHPiR0n8vIc5tgXFVWRRKp8otYs4PPcM9m1qXlOd5ZXkqil+RqPcvZYUDEjbniXZY21k8yI2zVBtWTNGR91LjwFjFFkRBQen9brMY7NvSGkhScGB/dGCx40YGqrpZVfd5V4KNX9zbOVb6TsVUZS4oOeRo5p6/NGXz9HIBD0gWxn8qtoWirozXw8WZvGbSABzHPVz+XgVxxb0RpZ2UnAukWpNJhTskUIDX+uhqsJXxahB7L0/l9DZ3QDF2q7KdfVXjwBxewXAYzNz3n4nZorpqBNDF/+PkfKjt6Uvx9feO2DC7Eb3nLF+di5r6ZuR4+rRsJsU2AH75jE3Koux82iavQAeFqp5xlLILM47O0vKlYDBx8a1Y1TMIao4USh035TIpqC6//t4l1Z1g3NRqAQwFbGnyg6qecbRj+Cy6ClyrwcnzsVr/V1cUVHiYQaQOil05YbfPKAVK1+c36NsY1sLtOVcs5TRqS46HqPQkS1F3ejstsN/MwWsyHT0oddduu+R6Doyl0vO86jZMFKhy8VGy8L6/Tun1GKuBA0y5VTzJUviOzPB7qf2MsbqHF1CwbZ0duOHvxV4TfrbWFmfh+EHlPl4oZRdn9AbU9cA4P3BB5ogWD6oclZfW26G2qffylatXGEtqH1F9pbOucMlRJcoShlJ2YdqBmQiruFDaLu2Nrff7HMkTcBw+JnsMGapMVIMvrw9+UB8S9GXWCbXzAhXo4l+701jnoxwcIO063PckK6D2x2EAyLl8bIeqBz28KAenHN49oQMS9X0ZnB+mnpUaaOqPHE+9CyC/bzOqvp+vjf4Av2aQsofgRy7u7dpP/XSgkStuSHra23pPBu124fyBKMiLzsWvDqpdK0Wg9ZDEWFfacfjrXEG/AaqoL77NiVnfKKBkFXYMaky6ioKC60+za6UINd23HE3FXVvd8ZtrVhriTAKd0he1i18NRWeEdCZqOUKPVJG8y2H/vhrQ5X++Wy2BSBjasYblFwPAyfFNiRCn7oMMcYjhY6ndrHAYq1J0i2ZIQ5wGFab/AFViMs1FmVwzEgbCRvGxyb1dodc+pae2LvI8IImxtsLvwk4GsEQiH+S4iBHRZmXmXUhnoWnJ8iBLGqggDjTYvEcVwqbl+I6w6rEUShrYJvd1JRyHb1LhbT6qEN6jItJAlcR5iB9LDRgmO80iOMm4yYET+/Uw3mMtaPG/VWVYHg3wI44Nh+qd6R0G2gKn4nLQwcfV7nGx+w8/7Lc8ExZa802PrepkMOHk+ZhK1Vh5iQYApQ8Ye/tRJ1C3lJWiYRlecf6qAYdUVEk3J9i4Y7sHVNuymldrxEVKIQgsnOrfVL14ocFgguX54WqHrOu9bETYfCw1ygsHxS9PAiMi7OHlI8ZyUqFowxiwU8xxP4iKMA+RE+dBeKAAo+JkZE2H7IYGgwnu8k/cFhhvlA3zQ9MQVwpBogG7iue2RqNKURW6/Izlwvi/NLr1YdGUxJVClEsUjgIdhcIBhcqJFCpQ7K7Ez3AHEm4bnGoWyaqFpieuGsRqhAUD4iQuZvQD4xgfxoqnlsTKD8Eobl8siChsrMrSnLtJcGHKdCExqSjx20j8LwAA//8cmOgCltgvfAAAAABJRU5ErkJggg==", 7 | "authors": ["BeeMargarida", "kamellperry", "snake-345", "khalibloo", "1yne"], 8 | "websiteUrl": "https://svelteui.dev", 9 | "githubUrl": "https://github.com/svelteuidev/svelteui", 10 | "stars": 1375, 11 | "lastUpdated": "2024-07-07", 12 | "topics": [], 13 | "license": "MIT", 14 | "version": "0.15.7" 15 | } 16 | -------------------------------------------------------------------------------- /data/libraries/thisuxhq--sveltednd.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "thisuxhq--sveltednd", 3 | "name": "sveltednd", 4 | "description": "A lightweight, flexible drag and drop library for Svelte 5 applications.", 5 | "owner": "thisuxhq", 6 | "ownerAvatarBase64": "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o+Pq1ava48BWiCwEeTyetWvXbtiwobCwsKCgoKSk5JlnnnG5XLpT3bx588qVK9FodGhoaHBwcGho6Pr163Nzc7pTwa6ILNLK6XQWFxeXlJQUFxf7fL7y8nKPxyP6Tv309PTAfcPDw5988klfXx8fxEI6EVkoczqd69atW7t2rcfj8fl8Xq83Ly9v5cqVubm5brc7Jyfnsf8PyWRyenp6fHx86r7R0dFoNDo6OjoyMnL16lWSCgCAbTm0BwAAOyOyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIKILAAIIrIAIIjIAoAgIgsAgogsAAgisgAgiMgCgCAiCwCCiCwACCKyACCIyAKAICILAIL+XwAAAP//udtSgexOYMsAAAAASUVORK5CYII=", 7 | "authors": ["Spikeysanju", "colecrouter", "builtbybengt", "alexweber", "TheFireBlast"], 8 | "websiteUrl": "https://sveltednd.thisux.com", 9 | "githubUrl": "https://github.com/thisuxhq/sveltednd", 10 | "stars": 383, 11 | "lastUpdated": "2025-01-23", 12 | "topics": [ 13 | "dnd", 14 | "drag", 15 | "drag-and-drop", 16 | "drop", 17 | "runes", 18 | "svelte-dnd", 19 | "svelte5", 20 | "sveltekit", 21 | "tailwindcss", 22 | "thisux", 23 | "typescript" 24 | ], 25 | "license": "MIT", 26 | "version": "0.0.20" 27 | } 28 | -------------------------------------------------------------------------------- /data/libraries/vercel--ai.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "vercel--ai", 3 | "name": "ai", 4 | "description": "The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents ", 5 | "owner": "vercel", 6 | "ownerAvatarBase64": "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QDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDABIEAwASBAMAEgQDAB4O32/y8AAP//OAXCtWCRE+MAAAAASUVORK5CYII=", 7 | "authors": ["lgrammel", "github-actions[bot]", "shaper", "jaredpalmer", "nicoalbanese"], 8 | "websiteUrl": "https://ai-sdk.dev", 9 | "githubUrl": "https://github.com/vercel/ai", 10 | "stars": 13763, 11 | "lastUpdated": "2025-04-25", 12 | "topics": [ 13 | "anthropic", 14 | "artificial-intelligence", 15 | "gemini", 16 | "generative-ai", 17 | "generative-ui", 18 | "javascript", 19 | "language-model", 20 | "llm", 21 | "nextjs", 22 | "openai", 23 | "react", 24 | "svelte", 25 | "typescript", 26 | "vercel", 27 | "vue" 28 | ], 29 | "license": "NOASSERTION", 30 | "version": "undefined" 31 | } 32 | -------------------------------------------------------------------------------- /data/libraries/vincjo--datatables.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "vincjo--datatables", 3 | "name": "datatables", 4 | "description": "A toolkit for creating datatable components with Svelte", 5 | "owner": "vincjo", 6 | "ownerAvatarBase64": "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", 7 | "authors": ["vincjo", "bn-l", "droher", "andre-brandao", "gusbuncedev"], 8 | "websiteUrl": "https://vincjo.fr/datatables", 9 | "githubUrl": "https://github.com/vincjo/datatables", 10 | "stars": 528, 11 | "lastUpdated": "2025-03-09", 12 | "topics": [ 13 | "datatable", 14 | "datatables", 15 | "filter", 16 | "headless", 17 | "lazy-loading", 18 | "pagination", 19 | "selection", 20 | "simple", 21 | "sort", 22 | "svelte", 23 | "sveltejs", 24 | "table" 25 | ], 26 | "license": "MIT", 27 | "version": "unknown" 28 | } 29 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import prettier from 'eslint-config-prettier'; 2 | import js from '@eslint/js'; 3 | import { includeIgnoreFile } from '@eslint/compat'; 4 | import svelte from 'eslint-plugin-svelte'; 5 | import globals from 'globals'; 6 | import { fileURLToPath } from 'node:url'; 7 | import ts from 'typescript-eslint'; 8 | import svelteConfig from './svelte.config.js'; 9 | 10 | const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url)); 11 | 12 | export default ts.config( 13 | includeIgnoreFile(gitignorePath), 14 | js.configs.recommended, 15 | ...ts.configs.recommended, 16 | ...svelte.configs.recommended, 17 | prettier, 18 | ...svelte.configs.prettier, 19 | { 20 | languageOptions: { 21 | globals: { ...globals.browser, ...globals.node } 22 | }, 23 | rules: { 'no-undef': 'off' } 24 | }, 25 | { 26 | files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'], 27 | languageOptions: { 28 | parserOptions: { 29 | projectService: true, 30 | extraFileExtensions: ['.svelte'], 31 | parser: ts.parser, 32 | svelteConfig 33 | } 34 | } 35 | } 36 | ); 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-directory", 3 | "private": true, 4 | "version": "0.0.1", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite dev", 8 | "build": "npm run lib:compile && vite build", 9 | "preview": "vite preview", 10 | "prepare": "(svelte-kit sync || echo 'Warning: svelte-kit sync failed') && husky\n", 11 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", 12 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", 13 | "format": "prettier --write .", 14 | "lint": "prettier --check . && eslint .", 15 | "lib:compile": "tsx scripts/cli compile", 16 | "lib:add": "tsx scripts/cli add", 17 | "lib:update": "tsx scripts/cli update" 18 | }, 19 | "devDependencies": { 20 | "@eslint/compat": "^1.2.5", 21 | "@eslint/js": "^9.18.0", 22 | "@lucide/svelte": "^0.501.0", 23 | "@sveltejs/adapter-static": "^3.0.8", 24 | "@sveltejs/kit": "^2.16.0", 25 | "@sveltejs/vite-plugin-svelte": "^5.0.0", 26 | "@tailwindcss/vite": "^4.0.0", 27 | "@types/lodash": "^4.17.16", 28 | "@types/lunr": "^2.3.7", 29 | "@types/node": "^22.15.0", 30 | "bits-ui": "^1.3.19", 31 | "chalk": "^5.4.1", 32 | "clsx": "^2.1.1", 33 | "commander": "^13.1.0", 34 | "dotenv": "^16.5.0", 35 | "eslint": "^9.18.0", 36 | "eslint-config-prettier": "^10.0.1", 37 | "eslint-plugin-svelte": "^3.0.0", 38 | "globals": "^16.0.0", 39 | "husky": "^9.1.7", 40 | "lint-staged": "^15.5.1", 41 | "lodash": "^4.17.21", 42 | "lunr": "^2.3.9", 43 | "mode-watcher": "0.5.1", 44 | "octokit": "^4.1.3", 45 | "prettier": "^3.4.2", 46 | "prettier-plugin-svelte": "^3.3.3", 47 | "prettier-plugin-tailwindcss": "^0.6.11", 48 | "svelte": "^5.0.0", 49 | "svelte-check": "^4.0.0", 50 | "svelte-confetti": "^2.0.0", 51 | "sveltekit-search-params": "^3.0.0", 52 | "tailwind-merge": "^3.2.0", 53 | "tailwind-variants": "^1.0.0", 54 | "tailwindcss": "^4.0.0", 55 | "tsx": "^4.19.3", 56 | "tw-animate-css": "^1.2.5", 57 | "typescript": "^5.0.0", 58 | "typescript-eslint": "^8.20.0", 59 | "vite": "^6.2.5", 60 | "zod": "^3.24.3" 61 | }, 62 | "lint-staged": { 63 | "*.{js,ts,svelte,css,scss,postcss,md,json}": [ 64 | "prettier --write", 65 | "prettier --check" 66 | ], 67 | "*.{js,ts,svelte}": "eslint" 68 | }, 69 | "pnpm": { 70 | "onlyBuiltDependencies": [ 71 | "esbuild" 72 | ] 73 | }, 74 | "packageManager": "pnpm@9.6.0+sha512.38dc6fba8dba35b39340b9700112c2fe1e12f10b17134715a4aa98ccf7bb035e76fd981cf0bb384dfa98f8d6af5481c2bef2f4266a24bfa20c34eb7147ce0b5e" 75 | } 76 | -------------------------------------------------------------------------------- /scripts/cli.ts: -------------------------------------------------------------------------------- 1 | import 'dotenv/config'; 2 | 3 | import { Command } from 'commander'; 4 | import addCommand from './commands/add'; 5 | import updateCommand from './commands/update'; 6 | import compileCommand from './commands/compile'; 7 | 8 | const program = new Command() 9 | .name('svelte-directory') 10 | .description('CLI tool for managing libraries in the Svelte Directory') 11 | .version('1.0.0'); 12 | 13 | program.addCommand(addCommand); 14 | program.addCommand(updateCommand); 15 | program.addCommand(compileCommand); 16 | 17 | // Display help if no command is provided 18 | if (process.argv.length === 2) { 19 | program.help(); 20 | } 21 | 22 | program.parse(); 23 | -------------------------------------------------------------------------------- /scripts/commands/add.ts: -------------------------------------------------------------------------------- 1 | import { Command } from 'commander'; 2 | import { librarySchema } from '$lib/schema'; 3 | import { getRepoFromUrl, saveLibraryFile, convertToLibrary, Logger } from '../utils'; 4 | 5 | const logger = new Logger('add'); 6 | 7 | const command = new Command('add') 8 | .description('Add a GitHub repository as a library') 9 | .argument('', 'GitHub repository URL') 10 | .option('-f, --force', 'Overwrite existing library file') 11 | .action(async (githubUrl, options) => { 12 | logger.info(`Adding library from GitHub URL: ${githubUrl}`); 13 | const repo = await getRepoFromUrl(githubUrl); 14 | const library = await convertToLibrary(repo); 15 | 16 | try { 17 | librarySchema.parse(library); 18 | } catch (validationError) { 19 | console.error('Validation errors:'); 20 | console.error(validationError); 21 | process.exit(1); 22 | } 23 | 24 | const filePath = saveLibraryFile(library, options.force); 25 | logger.success(`Library entry created and saved to ${filePath}`); 26 | }); 27 | 28 | export default command; 29 | -------------------------------------------------------------------------------- /scripts/commands/compile.ts: -------------------------------------------------------------------------------- 1 | import { Command } from 'commander'; 2 | import fs from 'fs'; 3 | import path from 'path'; 4 | import lunr from 'lunr'; 5 | import { loadLibraries, ASSETS_DIR, Logger } from '../utils'; 6 | import type { Library } from '$lib/types'; 7 | import _ from 'lodash'; 8 | 9 | const logger = new Logger('compile'); 10 | 11 | const command = new Command('compile') 12 | .description('Compile library data into a unified JSON file with search index') 13 | .option('-o, --output ', 'Custom output path for the compiled data') 14 | .action(async (options) => { 15 | const libraries = loadLibraries(); 16 | logger.info(`Loaded ${libraries.length} libraries`); 17 | 18 | // Create search index 19 | logger.await('Creating search index...'); 20 | const searchIndex = lunr(function () { 21 | // Define the fields to index 22 | this.field('id'); 23 | this.field('name', { boost: 10 }); // Boost name for higher relevance 24 | this.field('description', { boost: 5 }); // Boost description for higher relevance 25 | this.field('owner'); 26 | this.field('authors'); 27 | this.field('topics', { boost: 5 }); // Boost tags for higher relevance 28 | // TODO: license field are not displayed in the UI yet, so we can ignore them for now 29 | // this.field('license'); 30 | 31 | // Reference field for retrieving documents 32 | this.ref('id'); 33 | 34 | // Add each library to the index 35 | libraries.forEach((library) => { 36 | // Convert arrays to strings for indexing 37 | const indexableLibrary = { 38 | ...library, 39 | authors: library.authors.join(' '), 40 | topics: library.topics.join(' ') 41 | }; 42 | 43 | this.add(indexableLibrary); 44 | }); 45 | }); 46 | 47 | // Extract unique tags and sort them 48 | const allTags = libraries.flatMap((library) => library.topics); 49 | let countedTags = _.countBy(allTags); 50 | // Omit all tags with count 1 51 | countedTags = _.omitBy(countedTags, (count) => count <= 1); 52 | // Omit specific tags 53 | const SPECIFIC_TAGS = ['svelte', 'sveltejs', 'vue', 'react']; 54 | countedTags = _.omit(countedTags, SPECIFIC_TAGS); 55 | const uniqueTags = Array.from(Object.keys(countedTags)).sort(); 56 | logger.info(`Keeping ${uniqueTags.length} tags: ${uniqueTags.join(', ')}`); 57 | 58 | const libraryMap = libraries.reduce( 59 | (acc, library) => { 60 | // Create a map of library IDs to their respective objects 61 | acc[library.id] = library; 62 | return acc; 63 | }, 64 | {} as Record 65 | ); 66 | 67 | // Create a serializable object with the index, tags, and library data 68 | const compiledData = { 69 | index: searchIndex, 70 | tags: uniqueTags, 71 | libraries: libraryMap 72 | }; 73 | 74 | // Determine output path 75 | const outputPath = options.output || path.join(ASSETS_DIR, 'compiled-data.json'); 76 | 77 | // Ensure directory exists 78 | fs.mkdirSync(path.dirname(outputPath), { recursive: true }); 79 | 80 | // Write the unified data to a file 81 | fs.writeFileSync(outputPath, JSON.stringify(compiledData, null, 2), 'utf8'); 82 | logger.success(`Compiled data created and saved to ${outputPath}`); 83 | }); 84 | 85 | export default command; 86 | -------------------------------------------------------------------------------- /scripts/commands/update.ts: -------------------------------------------------------------------------------- 1 | import { Command } from 'commander'; 2 | import { librarySchema } from '$lib/schema'; 3 | import { 4 | convertToLibrary, 5 | createLibraryId, 6 | extractOwnerAndRepo, 7 | getRepo, 8 | loadLibraries, 9 | Logger, 10 | saveLibraryFile 11 | } from '../utils'; 12 | 13 | const logger = new Logger('update'); 14 | 15 | const command = new Command('update') 16 | .description('Update library entries with latest GitHub information') 17 | .argument( 18 | '[githubUrls...]', 19 | 'GitHub URLs of specific libraries to update (defaults to all if none provided)' 20 | ) 21 | .action(async (githubUrls: string[]) => { 22 | let librariesToUpdate = loadLibraries(); 23 | 24 | // Filter libraries if specific GitHub URLs are provided 25 | if (githubUrls?.length > 0) { 26 | const libraryIds = githubUrls 27 | .map((url) => extractOwnerAndRepo(url)) 28 | .map(({ ownerId, repoId }) => createLibraryId(ownerId, repoId)); 29 | librariesToUpdate = librariesToUpdate.filter((lib) => libraryIds.includes(lib.id)); 30 | 31 | // Check if all provided GitHub URLs match libraries in the database 32 | if (libraryIds.length !== librariesToUpdate.length) { 33 | const notFoundIds = libraryIds.filter( 34 | (id) => !librariesToUpdate.some((lib) => lib.id === id) 35 | ); 36 | logger.error( 37 | `❌ Some provided GitHub URLs do not match any libraries in the database: ${notFoundIds.join(', ')}` 38 | ); 39 | logger.note('⚠️ Please check the URLs and add them to the directory if necessary.'); 40 | process.exit(1); 41 | } 42 | } 43 | 44 | const errors = []; 45 | let updatedCount = 0; 46 | 47 | // Process libraries sequentially to avoid rate limiting 48 | logger.await(`Updating ${librariesToUpdate.length} libraries...`); 49 | for (const library of librariesToUpdate) { 50 | try { 51 | const repo = await getRepo(library.owner, library.name); 52 | const newLib = await convertToLibrary(repo); 53 | 54 | librarySchema.parse(newLib); 55 | saveLibraryFile(newLib, true); 56 | updatedCount++; 57 | } catch (error) { 58 | errors.push(error); 59 | } 60 | } 61 | 62 | logger.success(`Updated ${updatedCount} libraries successfully.`); 63 | if (errors.length > 0) { 64 | logger.error(`Encountered ${errors.length} errors during the update process.`); 65 | errors.forEach((error) => { 66 | logger.error(error); 67 | }); 68 | } 69 | }); 70 | 71 | export default command; 72 | -------------------------------------------------------------------------------- /scripts/utils/file.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import type { Library } from '$lib/types'; 4 | import { Logger } from './logger'; 5 | 6 | const logger = new Logger(); 7 | 8 | const cwd = process.cwd(); 9 | const isRoot = fs.existsSync(path.join(cwd, 'package.json')); 10 | if (!isRoot) { 11 | logger.error('Error: This script must be run from the root directory of the project.'); 12 | logger.error('Please navigate to the root directory and try again.'); 13 | process.exit(1); 14 | } 15 | 16 | export const LIBRARIES_DIR = path.join(cwd, 'data', 'libraries'); 17 | export const ASSETS_DIR = path.join(cwd, 'src', 'lib', 'assets'); 18 | 19 | export function loadLibraries(): Library[] { 20 | const files = fs.readdirSync(LIBRARIES_DIR).filter((file) => file.endsWith('.json')); 21 | 22 | return files.map((file) => { 23 | const filePath = path.join(LIBRARIES_DIR, file); 24 | const content = fs.readFileSync(filePath, 'utf8'); 25 | return JSON.parse(content) as Library; 26 | }); 27 | } 28 | 29 | export function saveLibraryFile(library: Library, force = false): string { 30 | const filePath = path.join(LIBRARIES_DIR, `${library.id}.json`); 31 | 32 | if (fs.existsSync(filePath) && !force) { 33 | logger.error(`Library file already exists: ${filePath}`); 34 | logger.error('Use --force option to overwrite the existing file.'); 35 | process.exit(1); 36 | } 37 | 38 | fs.mkdirSync(path.dirname(filePath), { recursive: true }); 39 | fs.writeFileSync(filePath, JSON.stringify(library, null, 2), 'utf8'); 40 | 41 | return filePath; 42 | } 43 | -------------------------------------------------------------------------------- /scripts/utils/github.ts: -------------------------------------------------------------------------------- 1 | import { Octokit } from 'octokit'; 2 | import { Logger } from './logger'; 3 | 4 | const logger = new Logger(); 5 | const octokit = new Octokit({ 6 | auth: process.env.GITHUB_TOKEN 7 | }); 8 | 9 | /** 10 | * Extract owner and repository name from GitHub URL 11 | * @param githubUrl 12 | */ 13 | export function extractOwnerAndRepo(githubUrl: string) { 14 | const githubUrlRegex = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\/?$/; 15 | const match = githubUrl.match(githubUrlRegex); 16 | 17 | if (!match) { 18 | logger.error('Invalid GitHub URL format.'); 19 | logger.note('The URL should be in the format: https://github.com/owner/repo'); 20 | process.exit(1); 21 | } 22 | 23 | return { 24 | ownerId: match[1], 25 | repoId: match[2] 26 | }; 27 | } 28 | 29 | /** 30 | * Fetch repository information from GitHub 31 | * @param owner 32 | * @param repo 33 | */ 34 | export async function getRepo(owner: string, repo: string) { 35 | // Fetch repository information 36 | const { data: repoData } = await octokit.rest.repos.get({ owner, repo }); 37 | 38 | // Fetch contributors information 39 | const { data: contributorsData } = await octokit.rest.repos.listContributors({ 40 | owner, 41 | repo, 42 | per_page: 5 43 | }); 44 | 45 | // Fetch latest release to get release date 46 | let latestReleaseDate = null; 47 | try { 48 | const { data: releaseData } = await octokit.rest.repos.getLatestRelease({ 49 | owner, 50 | repo 51 | }); 52 | latestReleaseDate = releaseData.published_at; 53 | } catch { 54 | logger.note(`No releases found for ${owner}/${repo} or error fetching releases.`); 55 | } 56 | 57 | let latestCommitDate = null; 58 | const { data: commitsData } = await octokit.rest.repos.listCommits({ 59 | owner, 60 | repo, 61 | per_page: 1 62 | }); 63 | 64 | latestCommitDate = commitsData[0].commit.committer?.date || commitsData[0].commit.author?.date; 65 | if (!latestCommitDate) { 66 | logger.error('No releases found for commits.'); 67 | process.exit(1); 68 | } 69 | 70 | // Fetch tags information for version 71 | const { data: tagsData } = await octokit.rest.repos.listTags({ 72 | owner, 73 | repo, 74 | per_page: 1 75 | }); 76 | 77 | return { 78 | ...repoData, 79 | contributors: contributorsData, 80 | latestReleaseDate, 81 | latestCommitDate, 82 | tags: tagsData 83 | }; 84 | } 85 | 86 | /** 87 | * Fetch repository information from GitHub using the URL 88 | * @param githubUrl 89 | */ 90 | export async function getRepoFromUrl(githubUrl: string) { 91 | const { ownerId, repoId } = extractOwnerAndRepo(githubUrl); 92 | return await getRepo(ownerId, repoId); 93 | } 94 | -------------------------------------------------------------------------------- /scripts/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './file'; 2 | export * from './github'; 3 | export * from './library'; 4 | export * from './logger'; 5 | -------------------------------------------------------------------------------- /scripts/utils/library.ts: -------------------------------------------------------------------------------- 1 | import type { Library } from '$lib/types'; 2 | import type { getRepo } from './github'; 3 | 4 | /** 5 | * Create library ID from owner and repo 6 | */ 7 | export function createLibraryId(owner: string, repo: string) { 8 | return (owner + '--' + repo).toLowerCase(); 9 | } 10 | 11 | /** 12 | * Convert GitHub repository information to a library object 13 | * @param repo 14 | */ 15 | export async function convertToLibrary(repo: Awaited>) { 16 | // Convert to avatar image to base64 17 | const ownerAvatarBase64 = await fetch(repo.owner.avatar_url) 18 | .then((response) => response.arrayBuffer()) 19 | .then((buffer) => Buffer.from(buffer).toString('base64')); 20 | 21 | // Determine the last updated date: 22 | // 1. Use the latest release date if available 23 | // 2. Use the latest commit date if available 24 | let lastUpdated = repo?.latestReleaseDate || repo.latestCommitDate; 25 | 26 | // Format the date to YYYY-MM-DD 27 | lastUpdated = lastUpdated.split('T')[0]; 28 | 29 | return { 30 | id: createLibraryId(repo.owner.login, repo.name), 31 | name: repo.name, 32 | description: repo.description || `A library called ${repo.name}`, 33 | owner: repo.owner.login, 34 | ownerAvatarBase64, 35 | authors: repo.contributors.map((c) => c.login).filter(Boolean) as string[], 36 | websiteUrl: repo.homepage || repo.html_url, 37 | githubUrl: repo.html_url, 38 | stars: repo.stargazers_count, 39 | lastUpdated, 40 | topics: repo.topics || [], 41 | license: repo.license?.spdx_id || 'Unknown', 42 | version: repo.tags.length > 0 ? repo.tags[0].name.replace(/^v/, '') : 'unknown' 43 | } as Library; 44 | } 45 | -------------------------------------------------------------------------------- /scripts/utils/logger.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | 3 | /** 4 | * Custom logger using chalk for styling and icons for visual cues 5 | */ 6 | export class Logger { 7 | #scope?: string; 8 | 9 | /** 10 | * Create a new Logger instance 11 | * @param scope Optional scope prefix for log messages 12 | */ 13 | constructor(scope?: string) { 14 | this.#scope = scope; 15 | } 16 | 17 | /** 18 | * Format the current date and time in a human-readable format 19 | * Includes date and time but excludes milliseconds and timezone 20 | */ 21 | private getTimestamp(): string { 22 | const now = new Date(); 23 | const year = now.getFullYear(); 24 | const month = (now.getMonth() + 1).toString().padStart(2, '0'); 25 | const day = now.getDate().toString().padStart(2, '0'); 26 | const hours = now.getHours().toString().padStart(2, '0'); 27 | const minutes = now.getMinutes().toString().padStart(2, '0'); 28 | const seconds = now.getSeconds().toString().padStart(2, '0'); 29 | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; 30 | } 31 | 32 | /** 33 | * Format a message with optional scope prefix 34 | */ 35 | private formatMessage(message: string): string { 36 | const timestamp = chalk.gray(`[${this.getTimestamp()}]`); 37 | const scopePrefix = this.#scope ? chalk.cyan(`[${this.#scope}]`) : ''; 38 | return `${timestamp} ${scopePrefix} ${message}`; 39 | } 40 | 41 | /** 42 | * Log an informational message 43 | * @param message The message to log 44 | */ 45 | info(message: string | object): void { 46 | const icon = chalk.blue('ℹ'); 47 | if (typeof message === 'object') { 48 | console.log(this.formatMessage(`${icon} ${chalk.blue('Info')}`)); 49 | console.log(message); 50 | } else { 51 | console.log(this.formatMessage(`${icon} ${chalk.blue(message)}`)); 52 | } 53 | } 54 | 55 | /** 56 | * Log a success message 57 | * @param message The message to log 58 | */ 59 | success(message: string | object): void { 60 | const icon = chalk.green('✓'); 61 | if (typeof message === 'object') { 62 | console.log(this.formatMessage(`${icon} ${chalk.green('Success')}`)); 63 | console.log(message); 64 | } else { 65 | console.log(this.formatMessage(`${icon} ${chalk.green(message)}`)); 66 | } 67 | } 68 | 69 | /** 70 | * Log a note or informational detail 71 | * @param message The message to log 72 | */ 73 | note(message: string | object): void { 74 | const icon = chalk.yellow('●'); 75 | if (typeof message === 'object') { 76 | console.log(this.formatMessage(`${icon} ${chalk.yellow('Note')}`)); 77 | console.log(message); 78 | } else { 79 | console.log(this.formatMessage(`${icon} ${chalk.yellow(message)}`)); 80 | } 81 | } 82 | 83 | /** 84 | * Log a warning message 85 | * @param message The message to log 86 | */ 87 | warn(message: string | object): void { 88 | const icon = chalk.yellow('⚠'); 89 | if (typeof message === 'object') { 90 | console.log(this.formatMessage(`${icon} ${chalk.yellow('Warning')}`)); 91 | console.log(message); 92 | } else { 93 | console.log(this.formatMessage(`${icon} ${chalk.yellow(message)}`)); 94 | } 95 | } 96 | 97 | /** 98 | * Log an error message 99 | * @param message The message to log 100 | */ 101 | error(message: string | object | unknown): void { 102 | const icon = chalk.red('✗'); 103 | if (typeof message === 'object') { 104 | console.log(this.formatMessage(`${icon} ${chalk.red('Error')}`)); 105 | console.error(message); 106 | } else { 107 | console.log(this.formatMessage(`${icon} ${chalk.red(message)}`)); 108 | } 109 | } 110 | 111 | /** 112 | * Log a pending/awaiting message 113 | * @param message The message to log 114 | */ 115 | await(message: string | object): void { 116 | const icon = chalk.blue('⏳'); 117 | if (typeof message === 'object') { 118 | console.log(this.formatMessage(`${icon} ${chalk.blue('Waiting')}`)); 119 | console.log(message); 120 | } else { 121 | console.log(this.formatMessage(`${icon} ${chalk.blue(message)}`)); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/app.css: -------------------------------------------------------------------------------- 1 | @import 'tailwindcss'; 2 | @import 'tw-animate-css'; 3 | 4 | @font-face { 5 | font-family: 'Geist'; 6 | src: url('/fonts/Geist/Geist[wght].woff2') format('woff2'); 7 | font-weight: 100 900; 8 | font-display: swap; 9 | } 10 | 11 | :root { 12 | --background: hsl(0 0% 100%); 13 | --foreground: hsl(240 10% 3.9%); 14 | --card: hsl(0 0% 100%); 15 | --card-foreground: hsl(240 10% 3.9%); 16 | --popover: hsl(0 0% 100%); 17 | --popover-foreground: hsl(240 10% 3.9%); 18 | --primary: #ff3e00; 19 | --primary-foreground: #ffffff; 20 | --secondary: hsl(240 4.8% 95.9%); 21 | --secondary-foreground: hsl(240 5.9% 10%); 22 | --muted: hsl(240 4.8% 95.9%); 23 | --muted-foreground: hsl(240 3.8% 46.1%); 24 | --accent: hsl(240 4.8% 95.9%); 25 | --accent-foreground: hsl(240 5.9% 10%); 26 | --destructive: hsl(0 72.22% 50.59%); 27 | --destructive-foreground: hsl(0 0% 98%); 28 | --border: hsl(240 5.9% 90%); 29 | --input: hsl(240 5.9% 90%); 30 | --ring: hsl(240 5.9% 10%); 31 | --radius: 0.5rem; 32 | 33 | /* Sidebar */ 34 | --sidebar-background: hsl(0 0% 98%); 35 | --sidebar-foreground: hsl(240 5.3% 26.1%); 36 | --sidebar-primary: hsl(240 5.9% 10%); 37 | --sidebar-primary-foreground: hsl(0 0% 98%); 38 | --sidebar-accent: hsl(240 4.8% 95.9%); 39 | --sidebar-accent-foreground: hsl(240 5.9% 10%); 40 | --sidebar-border: hsl(220 13% 91%); 41 | --sidebar-ring: hsl(217.2 91.2% 59.8%); 42 | } 43 | 44 | .dark { 45 | --background: hsl(240 10% 3.9%); 46 | --foreground: hsl(0 0% 98%); 47 | --card: hsl(240 10% 3.9%); 48 | --card-foreground: hsl(0 0% 98%); 49 | --popover: hsl(240 10% 3.9%); 50 | --popover-foreground: hsl(0 0% 98%); 51 | --primary: #f77b52; 52 | --primary-foreground: #ffffff; 53 | --secondary: hsl(240 3.7% 15.9%); 54 | --secondary-foreground: hsl(0 0% 98%); 55 | --muted: hsl(240 3.7% 15.9%); 56 | --muted-foreground: hsl(240 5% 64.9%); 57 | --accent: hsl(240 3.7% 15.9%); 58 | --accent-foreground: hsl(0 0% 98%); 59 | --destructive: hsl(0 62.8% 30.6%); 60 | --destructive-foreground: hsl(0 0% 98%); 61 | --border: hsl(240 3.7% 15.9%); 62 | --input: hsl(240 3.7% 15.9%); 63 | --ring: hsl(240 4.9% 83.9%); 64 | 65 | /* Sidebar */ 66 | --sidebar-background: hsl(240 5.9% 10%); 67 | --sidebar-foreground: hsl(240 4.8% 95.9%); 68 | --sidebar-primary: hsl(224.3 76.3% 48%); 69 | --sidebar-primary-foreground: hsl(0 0% 100%); 70 | --sidebar-accent: hsl(240 3.7% 15.9%); 71 | --sidebar-accent-foreground: hsl(240 4.8% 95.9%); 72 | --sidebar-border: hsl(240 3.7% 15.9%); 73 | --sidebar-ring: hsl(217.2 91.2% 59.8%); 74 | } 75 | 76 | @theme { 77 | --font-sans: 78 | 'Geist', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 79 | 'Segoe UI Symbol', 'Noto Color Emoji'; 80 | } 81 | 82 | @theme inline { 83 | --color-background: var(--background); 84 | --color-foreground: var(--foreground); 85 | --color-card: var(--card); 86 | --color-card-foreground: var(--card-foreground); 87 | --color-popover: var(--popover); 88 | --color-popover-foreground: var(--popover-foreground); 89 | --color-primary: var(--primary); 90 | --color-primary-foreground: var(--primary-foreground); 91 | --color-secondary: var(--secondary); 92 | --color-secondary-foreground: var(--secondary-foreground); 93 | --color-muted: var(--muted); 94 | --color-muted-foreground: var(--muted-foreground); 95 | --color-accent: var(--accent); 96 | --color-accent-foreground: var(--accent-foreground); 97 | --color-destructive: var(--destructive); 98 | --color-destructive-foreground: var(--destructive-foreground); 99 | --color-border: var(--border); 100 | --color-input: var(--input); 101 | --color-ring: var(--ring); 102 | 103 | --color-sidebar: var(--sidebar-background); 104 | --color-sidebar-foreground: var(--sidebar-foreground); 105 | --color-sidebar-primary: var(--sidebar-primary); 106 | --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); 107 | --color-sidebar-accent: var(--sidebar-accent); 108 | --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); 109 | --color-sidebar-border: var(--sidebar-border); 110 | --color-sidebar-ring: var(--sidebar-ring); 111 | } 112 | 113 | @layer base { 114 | * { 115 | @apply border-border; 116 | } 117 | body { 118 | @apply bg-background text-foreground; 119 | } 120 | 121 | ::selection { 122 | @apply bg-primary text-primary-foreground; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /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 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Svelte Directory 16 | 17 | 21 | 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | %sveltekit.head% 42 | 43 | 44 |
%sveltekit.body%
45 | 46 | 47 | -------------------------------------------------------------------------------- /src/lib/assets/github-mark-white.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lib/assets/github-mark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lib/components/controls/controls-sort-direction.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 | 23 | 24 | 30 | {#each sortOptionEntries as [value, { label, icon: Icon }] (value)} 31 | 32 | 33 | {label} 34 | 35 | {/each} 36 | 37 | -------------------------------------------------------------------------------- /src/lib/components/controls/controls-sort-selector.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 | 25 | 26 | 32 | {#each sortOptionEntries as [value, { label, icon: Icon }] (value)} 33 | 34 | 35 | {label} 36 | 37 | {/each} 38 | 39 | -------------------------------------------------------------------------------- /src/lib/components/controls/controls-tag-filter.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 |
14 | {#each allTags as tag (tag)} 15 | {@const isActive = queryParams.isActiveTag(tag)} 16 | queryParams.toggleTag(tag)} 18 | variant={isActive ? 'default' : 'secondary'} 19 | class={cn( 20 | 'cursor-pointer px-3 py-1.5 transition-all duration-150 select-none', 21 | !isActive && 'hover:brightness-80' 22 | )} 23 | > 24 | {tag} 25 | 26 | {/each} 27 |
28 | -------------------------------------------------------------------------------- /src/lib/components/controls/controls.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 10 | Sort 11 | 12 | 13 | 14 | 15 | 16 | 17 | Sort Direction 18 | 19 | 20 | 21 | 22 | 23 | 24 | Tags 25 | 26 | 27 | 28 | 29 |
30 | -------------------------------------------------------------------------------- /src/lib/components/controls/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Controls } from './controls.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/error/error-confetti-button.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 |
28 | 35 |
36 | {#each particles as particle, i (i)} 37 |
38 | 39 |
40 | {/each} 41 |
42 |
43 | -------------------------------------------------------------------------------- /src/lib/components/error/error-status.svelte: -------------------------------------------------------------------------------- 1 | 48 | 49 |
50 |
53 | 57 |
58 | 59 |

62 | {#if page.status === 404} 63 | Page not found 64 | {:else if page.status === 500} 65 | Server error 66 | {:else} 67 | Error {page.status} 68 | {/if} 69 |

70 | 71 |

72 | {errorMessage} 73 |

74 | -------------------------------------------------------------------------------- /src/lib/components/error/error.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
10 | 11 | 12 | 22 |
23 | -------------------------------------------------------------------------------- /src/lib/components/error/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Error } from './error.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/footer/footer.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 73 | -------------------------------------------------------------------------------- /src/lib/components/footer/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Footer } from './footer.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/header/header-light-switch.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /src/lib/components/header/header-repository-link.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | {#if $mode === 'dark'} 14 | GitHub 15 | {:else} 16 | GitHub 17 | {/if} 18 | 19 | -------------------------------------------------------------------------------- /src/lib/components/header/header-search.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 24 | -------------------------------------------------------------------------------- /src/lib/components/header/header.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | {#snippet Links()} 15 |
16 | 17 | 18 |
19 | {/snippet} 20 | 21 | {#snippet SearchWithInfo()} 22 |
23 | 24 | 25 | {count} 26 | {count === 1 ? 'Library' : 'Libraries'} Found 27 | 28 |
29 | {/snippet} 30 | 31 |
32 | {#if isMobile.current} 33 |
34 |
35 |
36 | 37 |
38 | {@render Links()} 39 |
40 | {@render SearchWithInfo()} 41 |
42 | {:else} 43 |
44 |
45 | 46 |
47 |
48 | {@render SearchWithInfo()} 49 |
50 | {@render Links()} 51 |
52 | {/if} 53 |
54 | -------------------------------------------------------------------------------- /src/lib/components/header/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Header } from './header.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/library-collection/index.ts: -------------------------------------------------------------------------------- 1 | export { default as LibraryCollection } from './library-collection.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/library-collection/library-collection-item-header.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 |
22 |
23 | 24 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 | {library.owner} 36 |
37 |
38 |
39 | Updated {library.lastUpdated} 40 |
41 | {#if library.websiteUrl} 42 | 43 | 48 | 49 | {library.websiteUrl} 52 | 53 | {/if} 54 |
55 |
56 |
57 | -------------------------------------------------------------------------------- /src/lib/components/library-collection/library-collection-item-tag-list.svelte: -------------------------------------------------------------------------------- 1 | 21 | 22 |
23 | {#each visibleTags as tag, index (tag)} 24 | {@const isActive = queryParams.isActiveTag(tag)} 25 | 34 | {#if index < visibleTags.length - 1} 35 | · 36 | {/if} 37 | {/each} 38 | {#if collapsed} 39 | 45 | {/if} 46 |
47 | -------------------------------------------------------------------------------- /src/lib/components/library-collection/library-collection-item.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | {#snippet StarLink()} 13 |
14 | 19 | {library.name} 20 | 21 |
22 | 23 | {library.stars.toLocaleString()} 24 |
25 |
26 | {/snippet} 27 | 28 | 29 |
30 |
31 | {@render StarLink()} 32 |

{library.description}

33 | 34 |
35 | -------------------------------------------------------------------------------- /src/lib/components/library-collection/library-collection-pagination.svelte: -------------------------------------------------------------------------------- 1 | 40 | 41 | 60 | 61 | 66 | {#snippet children({ pages, range })} 67 |
68 | 69 | 70 | 71 | 72 | Showing {range.start} to {range.end} of {page.data.count} results 73 | 74 | 100 | 101 | 102 | 103 |
104 | {/snippet} 105 |
106 | -------------------------------------------------------------------------------- /src/lib/components/library-collection/library-collection.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 | {#if libraries.length === 0} 10 |
11 |

No libraries found

12 |

Try adjusting your search or filters.

13 |
14 | {:else} 15 |
16 |
17 | {#each libraries as library (library.id)} 18 | 19 | {/each} 20 |
21 |
22 | 23 |
24 |
25 | {/if} 26 | -------------------------------------------------------------------------------- /src/lib/components/ui/alert/alert-description.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 | {@render children?.()} 16 |
17 | -------------------------------------------------------------------------------- /src/lib/components/ui/alert/alert-title.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
24 | {@render children?.()} 25 |
26 | -------------------------------------------------------------------------------- /src/lib/components/ui/alert/alert.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 | 36 | 37 | 40 | -------------------------------------------------------------------------------- /src/lib/components/ui/alert/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './alert.svelte'; 2 | import Description from './alert-description.svelte'; 3 | import Title from './alert-title.svelte'; 4 | export { alertVariants, type AlertVariant } from './alert.svelte'; 5 | 6 | export { 7 | Root, 8 | Description, 9 | Title, 10 | // 11 | Root as Alert, 12 | Description as AlertDescription, 13 | Title as AlertTitle 14 | }; 15 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar/avatar-fallback.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar/avatar-image.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/lib/components/ui/avatar/avatar.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /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/badge.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | 40 | 41 | 48 | {@render children?.()} 49 | 50 | -------------------------------------------------------------------------------- /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/button.svelte: -------------------------------------------------------------------------------- 1 | 39 | 40 | 54 | 55 | {#if href} 56 | 57 | {@render children?.()} 58 | 59 | {:else} 60 | 68 | {/if} 69 | -------------------------------------------------------------------------------- /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-content.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 | {@render children?.()} 16 |
17 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-description.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |

15 | {@render children?.()} 16 |

17 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-footer.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 | {@render children?.()} 16 |
17 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-header.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 | {@render children?.()} 16 |
17 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card-title.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
24 | {@render children?.()} 25 |
26 | -------------------------------------------------------------------------------- /src/lib/components/ui/card/card.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /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 | 8 | export { 9 | Root, 10 | Content, 11 | Description, 12 | Footer, 13 | Header, 14 | Title, 15 | // 16 | Root as Card, 17 | Content as CardContent, 18 | Description as CardDescription, 19 | Footer as CardFooter, 20 | Header as CardHeader, 21 | Title as CardTitle 22 | }; 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/checkbox/checkbox.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 26 | {#snippet children({ checked, indeterminate })} 27 |
28 | {#if indeterminate} 29 | 30 | {:else} 31 | 32 | {/if} 33 |
34 | {/snippet} 35 |
36 | -------------------------------------------------------------------------------- /src/lib/components/ui/checkbox/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './checkbox.svelte'; 2 | export { 3 | Root, 4 | // 5 | Root as Checkbox 6 | }; 7 | -------------------------------------------------------------------------------- /src/lib/components/ui/input/index.ts: -------------------------------------------------------------------------------- 1 | import Root, { inputVariants } from './input.svelte'; 2 | 3 | export { 4 | Root, 5 | // 6 | Root as Input, 7 | inputVariants 8 | }; 9 | -------------------------------------------------------------------------------- /src/lib/components/ui/input/input.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | 40 | 41 | {#if type === 'file'} 42 | 50 | {:else} 51 | 52 | {/if} 53 | -------------------------------------------------------------------------------- /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/radio-group/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './radio-group.svelte'; 2 | import Item from './radio-group-item.svelte'; 3 | 4 | export { 5 | Root, 6 | Item, 7 | // 8 | Root as RadioGroup, 9 | Item as RadioGroupItem 10 | }; 11 | -------------------------------------------------------------------------------- /src/lib/components/ui/radio-group/radio-group-item.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | {#snippet children({ checked })} 22 |
23 | {#if checked} 24 | 25 | {/if} 26 |
27 | {/snippet} 28 |
29 | -------------------------------------------------------------------------------- /src/lib/components/ui/radio-group/radio-group.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /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 | 25 | {@render children?.()} 26 | 29 | 30 | -------------------------------------------------------------------------------- /src/lib/components/ui/scroll-area/scroll-area.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 23 | {@render children?.()} 24 | 25 | {#if orientation === 'vertical' || orientation === 'both'} 26 | 27 | {/if} 28 | {#if orientation === 'horizontal' || orientation === 'both'} 29 | 30 | {/if} 31 | 32 | 33 | -------------------------------------------------------------------------------- /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 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/index.ts: -------------------------------------------------------------------------------- 1 | import { Dialog as SheetPrimitive } from 'bits-ui'; 2 | import Overlay from './sheet-overlay.svelte'; 3 | import Content from './sheet-content.svelte'; 4 | import Header from './sheet-header.svelte'; 5 | import Footer from './sheet-footer.svelte'; 6 | import Title from './sheet-title.svelte'; 7 | import Description from './sheet-description.svelte'; 8 | 9 | const Root = SheetPrimitive.Root; 10 | const Close = SheetPrimitive.Close; 11 | const Trigger = SheetPrimitive.Trigger; 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-content.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 | 43 | 44 | 45 | 46 | 47 | {@render children?.()} 48 | 51 | 52 | Close 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-description.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-footer.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-header.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
19 | {@render children?.()} 20 |
21 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-overlay.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sheet/sheet-title.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /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 = '20rem'; 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/context.svelte.ts: -------------------------------------------------------------------------------- 1 | import { IsMobile } from '$lib/hooks/is-mobile.svelte.js'; 2 | import { getContext, setContext } from 'svelte'; 3 | import { SIDEBAR_KEYBOARD_SHORTCUT } from './constants.js'; 4 | 5 | type Getter = () => T; 6 | 7 | export type SidebarStateProps = { 8 | /** 9 | * A getter function that returns the current open state of the sidebar. 10 | * We use a getter function here to support `bind:open` on the `Sidebar.Provider` 11 | * component. 12 | */ 13 | open: Getter; 14 | 15 | /** 16 | * A function that sets the open state of the sidebar. To support `bind:open`, we need 17 | * a source of truth for changing the open state to ensure it will be synced throughout 18 | * the sub-components and any `bind:` references. 19 | */ 20 | setOpen: (open: boolean) => void; 21 | }; 22 | 23 | class SidebarState { 24 | readonly props: SidebarStateProps; 25 | open = $derived.by(() => this.props.open()); 26 | openMobile = $state(false); 27 | setOpen: SidebarStateProps['setOpen']; 28 | #isMobile: IsMobile; 29 | state = $derived.by(() => (this.open ? 'expanded' : 'collapsed')); 30 | 31 | constructor(props: SidebarStateProps) { 32 | this.setOpen = props.setOpen; 33 | this.#isMobile = new IsMobile(); 34 | this.props = props; 35 | } 36 | 37 | // Convenience getter for checking if the sidebar is mobile 38 | // without this, we would need to use `sidebar.isMobile.current` everywhere 39 | get isMobile() { 40 | return this.#isMobile.current; 41 | } 42 | 43 | // Event handler to apply to the `` 44 | handleShortcutKeydown = (e: KeyboardEvent) => { 45 | if (e.key === SIDEBAR_KEYBOARD_SHORTCUT && (e.metaKey || e.ctrlKey)) { 46 | e.preventDefault(); 47 | this.toggle(); 48 | } 49 | }; 50 | 51 | setOpenMobile = (value: boolean) => { 52 | this.openMobile = value; 53 | }; 54 | 55 | toggle = () => { 56 | return this.#isMobile.current ? (this.openMobile = !this.openMobile) : this.setOpen(!this.open); 57 | }; 58 | } 59 | 60 | const SYMBOL_KEY = 'scn-sidebar'; 61 | 62 | /** 63 | * Instantiates a new `SidebarState` instance and sets it in the context. 64 | * 65 | * @param props The constructor props for the `SidebarState` class. 66 | * @returns The `SidebarState` instance. 67 | */ 68 | export function setSidebar(props: SidebarStateProps): SidebarState { 69 | return setContext(Symbol.for(SYMBOL_KEY), new SidebarState(props)); 70 | } 71 | 72 | /** 73 | * Retrieves the `SidebarState` instance from the context. This is a class instance, 74 | * so you cannot destructure it. 75 | * @returns The `SidebarState` instance. 76 | */ 77 | export function useSidebar(): SidebarState { 78 | return getContext(Symbol.for(SYMBOL_KEY)); 79 | } 80 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/index.ts: -------------------------------------------------------------------------------- 1 | import { useSidebar } from './context.svelte.js'; 2 | import Content from './sidebar-content.svelte'; 3 | import Footer from './sidebar-footer.svelte'; 4 | import GroupAction from './sidebar-group-action.svelte'; 5 | import GroupContent from './sidebar-group-content.svelte'; 6 | import GroupLabel from './sidebar-group-label.svelte'; 7 | import Group from './sidebar-group.svelte'; 8 | import Header from './sidebar-header.svelte'; 9 | import Input from './sidebar-input.svelte'; 10 | import Inset from './sidebar-inset.svelte'; 11 | import MenuAction from './sidebar-menu-action.svelte'; 12 | import MenuBadge from './sidebar-menu-badge.svelte'; 13 | import MenuButton from './sidebar-menu-button.svelte'; 14 | import MenuItem from './sidebar-menu-item.svelte'; 15 | import MenuSkeleton from './sidebar-menu-skeleton.svelte'; 16 | import MenuSubButton from './sidebar-menu-sub-button.svelte'; 17 | import MenuSubItem from './sidebar-menu-sub-item.svelte'; 18 | import MenuSub from './sidebar-menu-sub.svelte'; 19 | import Menu from './sidebar-menu.svelte'; 20 | import Provider from './sidebar-provider.svelte'; 21 | import Rail from './sidebar-rail.svelte'; 22 | import Separator from './sidebar-separator.svelte'; 23 | import Trigger from './sidebar-trigger.svelte'; 24 | import Root from './sidebar.svelte'; 25 | 26 | export { 27 | Content, 28 | Footer, 29 | Group, 30 | GroupAction, 31 | GroupContent, 32 | GroupLabel, 33 | Header, 34 | Input, 35 | Inset, 36 | Menu, 37 | MenuAction, 38 | MenuBadge, 39 | MenuButton, 40 | MenuItem, 41 | MenuSkeleton, 42 | MenuSub, 43 | MenuSubButton, 44 | MenuSubItem, 45 | Provider, 46 | Rail, 47 | Root, 48 | Separator, 49 | // 50 | Root as Sidebar, 51 | Content as SidebarContent, 52 | Footer as SidebarFooter, 53 | Group as SidebarGroup, 54 | GroupAction as SidebarGroupAction, 55 | GroupContent as SidebarGroupContent, 56 | GroupLabel as SidebarGroupLabel, 57 | Header as SidebarHeader, 58 | Input as SidebarInput, 59 | Inset as SidebarInset, 60 | Menu as SidebarMenu, 61 | MenuAction as SidebarMenuAction, 62 | MenuBadge as SidebarMenuBadge, 63 | MenuButton as SidebarMenuButton, 64 | MenuItem as SidebarMenuItem, 65 | MenuSkeleton as SidebarMenuSkeleton, 66 | MenuSub as SidebarMenuSub, 67 | MenuSubButton as SidebarMenuSubButton, 68 | MenuSubItem as SidebarMenuSubItem, 69 | Provider as SidebarProvider, 70 | Rail as SidebarRail, 71 | Separator as SidebarSeparator, 72 | Trigger as SidebarTrigger, 73 | Trigger, 74 | useSidebar 75 | }; 76 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-content.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
23 | {@render children?.()} 24 |
25 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-footer.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-group-action.svelte: -------------------------------------------------------------------------------- 1 | 29 | 30 | {#if child} 31 | {@render child({ props: propObj })} 32 | {:else} 33 | 36 | {/if} 37 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-group-content.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-group-label.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | {#if child} 29 | {@render child({ props: mergedProps })} 30 | {:else} 31 |
32 | {@render children?.()} 33 |
34 | {/if} 35 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-group.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-header.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
20 | {@render children?.()} 21 |
22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-input.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | 24 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-inset.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
23 | {@render children?.()} 24 |
25 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-action.svelte: -------------------------------------------------------------------------------- 1 | 36 | 37 | {#if child} 38 | {@render child({ props: mergedProps })} 39 | {:else} 40 | 43 | {/if} 44 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-badge.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
28 | {@render children?.()} 29 |
30 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-button.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | 66 | 67 | {#snippet Button({ props }: { props?: Record })} 68 | {@const mergedProps = mergeProps(buttonProps, props)} 69 | {#if child} 70 | {@render child({ props: mergedProps })} 71 | {:else} 72 | 75 | {/if} 76 | {/snippet} 77 | 78 | {#if !tooltipContent} 79 | {@render Button({})} 80 | {:else} 81 | 82 | 83 | {#snippet child({ props })} 84 | {@render Button({ props })} 85 | {/snippet} 86 | 87 | 95 | {/if} 96 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-item.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
  • 20 | {@render children?.()} 21 |
  • 22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-skeleton.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 |
    27 | {#if showIcon} 28 | 29 | {/if} 30 | 35 | {@render children?.()} 36 |
    37 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-sub-button.svelte: -------------------------------------------------------------------------------- 1 | 36 | 37 | {#if child} 38 | {@render child({ props: mergedProps })} 39 | {:else} 40 | 41 | {@render children?.()} 42 | 43 | {/if} 44 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-sub-item.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
  • 13 | {@render children?.()} 14 |
  • 15 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu-sub.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
      24 | {@render children?.()} 25 |
    26 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-menu.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
      20 | {@render children?.()} 21 |
    22 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-provider.svelte: -------------------------------------------------------------------------------- 1 | 38 | 39 | 40 | 41 | 42 |
    51 | {@render children?.()} 52 |
    53 |
    54 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-rail.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | 37 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-separator.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar-trigger.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 | 35 | -------------------------------------------------------------------------------- /src/lib/components/ui/sidebar/sidebar.svelte: -------------------------------------------------------------------------------- 1 | 25 | 26 | {#if collapsible === 'none'} 27 |
    35 | {@render children?.()} 36 |
    37 | {:else if sidebar.isMobile} 38 | sidebar.openMobile, (v) => sidebar.setOpenMobile(v)} {...restProps}> 39 | 46 |
    47 | {@render children?.()} 48 |
    49 |
    50 |
    51 | {:else} 52 | 93 | {/if} 94 | -------------------------------------------------------------------------------- /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 | 12 | 13 |
    18 | -------------------------------------------------------------------------------- /src/lib/components/ui/toggle-group/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './toggle-group.svelte'; 2 | import Item from './toggle-group-item.svelte'; 3 | 4 | export { 5 | Root, 6 | Item, 7 | // 8 | Root as ToggleGroup, 9 | Item as ToggleGroupItem 10 | }; 11 | -------------------------------------------------------------------------------- /src/lib/components/ui/toggle-group/toggle-group-item.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 | 31 | -------------------------------------------------------------------------------- /src/lib/components/ui/toggle-group/toggle-group.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 31 | 32 | 36 | 42 | -------------------------------------------------------------------------------- /src/lib/components/ui/toggle/index.ts: -------------------------------------------------------------------------------- 1 | import Root from './toggle.svelte'; 2 | export { 3 | toggleVariants, 4 | type ToggleSize, 5 | type ToggleVariant, 6 | type ToggleVariants 7 | } from './toggle.svelte'; 8 | 9 | export { 10 | Root, 11 | // 12 | Root as Toggle 13 | }; 14 | -------------------------------------------------------------------------------- /src/lib/components/ui/toggle/toggle.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | 44 | 45 | 51 | -------------------------------------------------------------------------------- /src/lib/components/ui/tooltip/index.ts: -------------------------------------------------------------------------------- 1 | import { Tooltip as TooltipPrimitive } from 'bits-ui'; 2 | import Content from './tooltip-content.svelte'; 3 | 4 | const Root = TooltipPrimitive.Root; 5 | const Trigger = TooltipPrimitive.Trigger; 6 | const Provider = TooltipPrimitive.Provider; 7 | 8 | export { 9 | Root, 10 | Trigger, 11 | Content, 12 | Provider, 13 | // 14 | Root as Tooltip, 15 | Content as TooltipContent, 16 | Trigger as TooltipTrigger, 17 | Provider as TooltipProvider 18 | }; 19 | -------------------------------------------------------------------------------- /src/lib/components/ui/tooltip/tooltip-content.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /src/lib/constants.ts: -------------------------------------------------------------------------------- 1 | export enum SortKeyEnum { 2 | NAME = 'name', 3 | STARS = 'stars', 4 | LAST_UPDATED = 'lastUpdated' 5 | } 6 | 7 | export enum SortDirectionEnum { 8 | ASC = 'asc', 9 | DESC = 'desc' 10 | } 11 | 12 | export enum QueryParamEnum { 13 | SEARCH = 'search', 14 | SORT_KEY = 'sortKey', 15 | SORT_DIRECTION = 'sortDirection', 16 | TAGS = 'tags' 17 | } 18 | 19 | export const QUERY_DEFAULTS = { 20 | [QueryParamEnum.SORT_KEY]: SortKeyEnum.NAME, 21 | [QueryParamEnum.SORT_DIRECTION]: SortDirectionEnum.ASC 22 | }; 23 | 24 | export enum PaginationParamEnum { 25 | LIMIT = 'limit', 26 | SKIP = 'skip' 27 | } 28 | 29 | export const PAGINATION_DEFAULTS = { 30 | limit: 50, 31 | skip: 0 32 | } as const; 33 | -------------------------------------------------------------------------------- /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/hooks/query-params.svelte.ts: -------------------------------------------------------------------------------- 1 | import { queryParam, ssp } from 'sveltekit-search-params'; 2 | import { QUERY_DEFAULTS, QueryParamEnum } from '$lib/constants'; 3 | import { fromStore } from 'svelte/store'; 4 | 5 | class QueryParams { 6 | #searchStore; 7 | #sortKeyStore; 8 | #sortDirectionStore; 9 | #tagsStore; 10 | 11 | constructor() { 12 | this.#searchStore = queryParam(QueryParamEnum.SEARCH, ssp.string(), { debounceHistory: 500 }); 13 | this.#sortKeyStore = queryParam( 14 | QueryParamEnum.SORT_KEY, 15 | ssp.string(QUERY_DEFAULTS[QueryParamEnum.SORT_KEY]), 16 | { 17 | debounceHistory: 250 18 | } 19 | ); 20 | this.#sortDirectionStore = queryParam( 21 | QueryParamEnum.SORT_DIRECTION, 22 | ssp.string(QUERY_DEFAULTS[QueryParamEnum.SORT_DIRECTION]), 23 | { 24 | debounceHistory: 250 25 | } 26 | ); 27 | this.#tagsStore = queryParam(QueryParamEnum.TAGS, ssp.array(), { 28 | debounceHistory: 250 29 | }); 30 | } 31 | 32 | get search() { 33 | return fromStore(this.#searchStore).current; 34 | } 35 | 36 | set search(v: string | null) { 37 | this.#searchStore.set(v); 38 | } 39 | 40 | get sortKey() { 41 | return fromStore(this.#sortKeyStore).current; 42 | } 43 | 44 | set sortKey(v: string | undefined) { 45 | // Value must always be a valid SortOption, so we use a type assertion to prevent deselection 46 | if (!v) return; 47 | this.#sortKeyStore.set(v); 48 | } 49 | 50 | get sortDirection() { 51 | return fromStore(this.#sortDirectionStore).current; 52 | } 53 | 54 | set sortDirection(v: string | undefined) { 55 | if (!v) return; 56 | this.#sortDirectionStore.set(v); 57 | } 58 | 59 | get tags() { 60 | return fromStore(this.#tagsStore).current; 61 | } 62 | 63 | isActiveTag(tag: string) { 64 | return this.tags?.includes(tag); 65 | } 66 | 67 | toggleTag(tag: string) { 68 | if (this.tags?.includes(tag)) { 69 | this.#tagsStore.update((tags) => tags && tags.filter((t) => t !== tag)); 70 | } else { 71 | this.#tagsStore.update((tags) => (tags ? [...tags, tag] : [tag])); 72 | } 73 | } 74 | } 75 | 76 | export const queryParams = new QueryParams(); 77 | -------------------------------------------------------------------------------- /src/lib/index.ts: -------------------------------------------------------------------------------- 1 | // place files you want to import through the `$lib` alias in this folder. 2 | -------------------------------------------------------------------------------- /src/lib/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | PAGINATION_DEFAULTS, 4 | PaginationParamEnum, 5 | QUERY_DEFAULTS, 6 | QueryParamEnum, 7 | SortDirectionEnum, 8 | SortKeyEnum 9 | } from './constants'; 10 | 11 | export const librarySchema = z.object({ 12 | id: z.string(), 13 | name: z.string(), 14 | description: z.string(), 15 | owner: z.string(), 16 | ownerAvatarBase64: z.string().optional(), 17 | authors: z.array(z.string()), 18 | websiteUrl: z.string(), 19 | githubUrl: z.string(), 20 | stars: z.number(), 21 | lastUpdated: z.string(), 22 | topics: z.array(z.string()), 23 | license: z.string(), 24 | version: z.string() 25 | }); 26 | 27 | export const queryParamsSchema = z.object({ 28 | [QueryParamEnum.SEARCH]: z.string().optional().catch(undefined), 29 | [QueryParamEnum.TAGS]: z 30 | .preprocess((val) => (typeof val === 'string' ? JSON.parse(val) : val), z.array(z.string())) 31 | .optional() 32 | .transform((val) => { 33 | // Either filter by tags (which requires at least one tag) or don't filter at all (which is null) 34 | // If an empty was empty, it would filter out all libraries, so we return null instead 35 | return val?.length === 0 ? null : val; 36 | }), 37 | [QueryParamEnum.SORT_KEY]: z 38 | .enum([SortKeyEnum.NAME, SortKeyEnum.STARS, SortKeyEnum.LAST_UPDATED]) 39 | .catch(QUERY_DEFAULTS[QueryParamEnum.SORT_KEY]), // We need .catch here, because on initial load no default params are provided, only after the first load query params will be set in the client. 40 | [QueryParamEnum.SORT_DIRECTION]: z 41 | .enum([SortDirectionEnum.ASC, SortDirectionEnum.DESC]) 42 | .catch(QUERY_DEFAULTS[QueryParamEnum.SORT_DIRECTION]), // We need .catch here, because on initial load no default params are provided, only after the first load query params will be set in the client. 43 | [PaginationParamEnum.LIMIT]: z.coerce 44 | .number() 45 | .positive() 46 | .optional() 47 | .default(PAGINATION_DEFAULTS.limit), 48 | [PaginationParamEnum.SKIP]: z.coerce 49 | .number() 50 | .nonnegative() 51 | .optional() 52 | .default(PAGINATION_DEFAULTS.skip) 53 | }); 54 | -------------------------------------------------------------------------------- /src/lib/types.ts: -------------------------------------------------------------------------------- 1 | import { librarySchema } from './schema'; 2 | import type { z } from 'zod'; 3 | 4 | export type Library = z.infer; 5 | -------------------------------------------------------------------------------- /src/lib/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 | -------------------------------------------------------------------------------- /src/routes/+error.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | {@render children?.()} 10 | -------------------------------------------------------------------------------- /src/routes/+layout.ts: -------------------------------------------------------------------------------- 1 | export const prerender = true; 2 | export const ssr = false; 3 | -------------------------------------------------------------------------------- /src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | {#snippet AppSidebar()} 11 | 12 | 13 | 14 |
    15 | 16 |
    17 | Svelte 18 | Directory 19 |
    20 |
    21 |
    22 | 23 | 24 | 25 | 26 | 27 |
    28 | {/snippet} 29 | 30 | 31 | {@render AppSidebar()} 32 |
    33 |
    34 |
    35 | 36 |
    37 |
    39 |
    40 | -------------------------------------------------------------------------------- /src/routes/+page.ts: -------------------------------------------------------------------------------- 1 | import type { Library } from '$lib/types'; 2 | import compiledData from '$lib/assets/compiled-data.json' assert { type: 'json' }; 3 | import _ from 'lodash'; 4 | import lunr from 'lunr'; 5 | import { QueryParamEnum, PaginationParamEnum } from '$lib/constants'; 6 | import { queryParamsSchema } from '$lib/schema'; 7 | 8 | const { libraries, index, tags } = compiledData; 9 | 10 | // TODO: replace lunr, since it sometimes retunrns empty results for some queries (https://github.com/olivernn/lunr.js/issues/38) 11 | // Load search index 12 | const searchIndex = lunr.Index.load(index); 13 | 14 | export const load = async ({ url }) => { 15 | const params = queryParamsSchema.parse({ 16 | [QueryParamEnum.SEARCH]: url.searchParams.get(QueryParamEnum.SEARCH) || undefined, 17 | [QueryParamEnum.TAGS]: url.searchParams.get(QueryParamEnum.TAGS) || undefined, 18 | [QueryParamEnum.SORT_KEY]: url.searchParams.get(QueryParamEnum.SORT_KEY) || undefined, 19 | [QueryParamEnum.SORT_DIRECTION]: 20 | url.searchParams.get(QueryParamEnum.SORT_DIRECTION) || undefined, 21 | [PaginationParamEnum.SKIP]: url.searchParams.get(PaginationParamEnum.SKIP) || undefined, 22 | [PaginationParamEnum.LIMIT]: url.searchParams.get(PaginationParamEnum.LIMIT) || undefined 23 | }); 24 | 25 | let results: Library[] = Object.values(libraries); 26 | 27 | // Apply search if search term is more than 3 letters 28 | if (_.gt(params.search?.length, 1)) { 29 | const matches = searchIndex.search(params[QueryParamEnum.SEARCH] as string); 30 | results = matches.map((m) => libraries[m.ref as keyof typeof libraries]); 31 | } 32 | 33 | // Filter by tags (keeps library if library tags include all selected tags) 34 | if (params[QueryParamEnum.TAGS]) { 35 | const tagSet = new Set(params[QueryParamEnum.TAGS]); 36 | const includesAllSelectedTags = ({ topics }: Library) => new Set(topics).isSupersetOf(tagSet); 37 | results = results.filter(includesAllSelectedTags); 38 | } 39 | 40 | // Sort libraries based on sort key and direction 41 | const sortKey = params[QueryParamEnum.SORT_KEY]; 42 | const sortDirection = params[QueryParamEnum.SORT_DIRECTION]; 43 | results = _.orderBy(results, [sortKey], sortDirection); 44 | 45 | const totalCount = results.length; 46 | 47 | // Apply pagination 48 | const skip = params.skip; 49 | const limit = params.limit; 50 | results = results.slice(skip, skip + limit); 51 | 52 | return { 53 | libraries: results, 54 | tags, 55 | count: totalCount 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /static/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klementine-org/svelte-directory/72eaec9fd4efd1536253d7d218161b216cf58004/static/android-chrome-192x192.png -------------------------------------------------------------------------------- /static/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klementine-org/svelte-directory/72eaec9fd4efd1536253d7d218161b216cf58004/static/android-chrome-512x512.png -------------------------------------------------------------------------------- /static/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klementine-org/svelte-directory/72eaec9fd4efd1536253d7d218161b216cf58004/static/apple-touch-icon.png -------------------------------------------------------------------------------- /static/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klementine-org/svelte-directory/72eaec9fd4efd1536253d7d218161b216cf58004/static/favicon-16x16.png -------------------------------------------------------------------------------- /static/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klementine-org/svelte-directory/72eaec9fd4efd1536253d7d218161b216cf58004/static/favicon-32x32.png -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klementine-org/svelte-directory/72eaec9fd4efd1536253d7d218161b216cf58004/static/favicon.ico -------------------------------------------------------------------------------- /static/fonts/Geist/Geist[wght].woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klementine-org/svelte-directory/72eaec9fd4efd1536253d7d218161b216cf58004/static/fonts/Geist/Geist[wght].woff2 -------------------------------------------------------------------------------- /static/fonts/Geist/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Vercel, in collaboration with basement.studio 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | ----------------------------------------------------------- 8 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 9 | ----------------------------------------------------------- 10 | 11 | PREAMBLE 12 | The goals of the Open Font License (OFL) are to stimulate worldwide 13 | development of collaborative font projects, to support the font creation 14 | efforts of academic and linguistic communities, and to provide a free and 15 | open framework in which fonts may be shared and improved in partnership 16 | with others. 17 | 18 | The OFL allows the licensed fonts to be used, studied, modified and 19 | redistributed freely as long as they are not sold by themselves. The 20 | fonts, including any derivative works, can be bundled, embedded, 21 | redistributed and/or sold with any software provided that any reserved 22 | names are not used by derivative works. The fonts and derivatives, 23 | however, cannot be released under any other type of license. The 24 | requirement for fonts to remain under this license does not apply 25 | to any document created using the fonts or their derivatives. 26 | 27 | DEFINITIONS 28 | "Font Software" refers to the set of files released by the Copyright 29 | Holder(s) under this license and clearly marked as such. This may 30 | include source files, build scripts and documentation. 31 | 32 | "Reserved Font Name" refers to any names specified as such after the 33 | copyright statement(s). 34 | 35 | "Original Version" refers to the collection of Font Software components as 36 | distributed by the Copyright Holder(s). 37 | 38 | "Modified Version" refers to any derivative made by adding to, deleting, 39 | or substituting -- in part or in whole -- any of the components of the 40 | Original Version, by changing formats or by porting the Font Software to a 41 | new environment. 42 | 43 | "Author" refers to any designer, engineer, programmer, technical 44 | writer or other person who contributed to the Font Software. 45 | 46 | PERMISSION AND CONDITIONS 47 | Permission is hereby granted, free of charge, to any person obtaining 48 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 49 | redistribute, and sell modified and unmodified copies of the Font 50 | Software, subject to the following conditions: 51 | 52 | 1) Neither the Font Software nor any of its individual components, 53 | in Original or Modified Versions, may be sold by itself. 54 | 55 | 2) Original or Modified Versions of the Font Software may be bundled, 56 | redistributed and/or sold with any software, provided that each copy 57 | contains the above copyright notice and this license. These can be 58 | included either as stand-alone text files, human-readable headers or 59 | in the appropriate machine-readable metadata fields within text or 60 | binary files as long as those fields can be easily viewed by the user. 61 | 62 | 3) No Modified Version of the Font Software may use the Reserved Font 63 | Name(s) unless explicit written permission is granted by the corresponding 64 | Copyright Holder. This restriction only applies to the primary font name as 65 | presented to the users. 66 | 67 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 68 | Software shall not be used to promote, endorse or advertise any 69 | Modified Version, except to acknowledge the contribution(s) of the 70 | Copyright Holder(s) and the Author(s) or with their explicit written 71 | permission. 72 | 73 | 5) The Font Software, modified or unmodified, in part or in whole, 74 | must be distributed entirely under this license, and must not be 75 | distributed under any other license. The requirement for fonts to 76 | remain under this license does not apply to any document created 77 | using the Font Software. 78 | 79 | TERMINATION 80 | This license becomes null and void if any of the above conditions are 81 | not met. 82 | 83 | DISCLAIMER 84 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 85 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 86 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 87 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 88 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 89 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 90 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 91 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 92 | OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /static/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klementine-org/svelte-directory/72eaec9fd4efd1536253d7d218161b216cf58004/static/og-image.png -------------------------------------------------------------------------------- /static/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, 6 | { "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } 7 | ], 8 | "theme_color": "#ffffff", 9 | "background_color": "#ffffff", 10 | "display": "standalone" 11 | } 12 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-static'; 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 | kit: { 10 | adapter: adapter({ 11 | pages: 'build', 12 | assets: 'build', 13 | fallback: undefined, 14 | precompress: false, 15 | strict: true 16 | }), 17 | paths: { 18 | base: process.argv.includes('dev') ? '' : process.env.BASE_PATH 19 | } 20 | } 21 | }; 22 | 23 | export default config; 24 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | // TODO: Remove this once shadcn-svelte does not require it 2 | 3 | /** @type {import('tailwindcss').Config} */ 4 | export default { 5 | darkMode: ['class'], 6 | content: ['./src/**/*.{html,js,svelte,ts}'], 7 | safelist: ['dark'] 8 | }; 9 | -------------------------------------------------------------------------------- /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 | // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias 15 | // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files 16 | // 17 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes 18 | // from the referenced tsconfig.json - TypeScript does not merge them in 19 | "include": [ 20 | ".svelte-kit/ambient.d.ts", 21 | ".svelte-kit/non-ambient.d.ts", 22 | ".svelte-kit/types/**/$types.d.ts", 23 | "vite.config.js", 24 | "vite.config.ts", 25 | "src/**/*.js", 26 | "src/**/*.ts", 27 | "src/**/*.svelte", 28 | "tests/**/*.js", 29 | "tests/**/*.ts", 30 | "tests/**/*.svelte", 31 | "scripts/**/*.js", 32 | "scripts/**/*.ts" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import tailwindcss from '@tailwindcss/vite'; 2 | import { sveltekit } from '@sveltejs/kit/vite'; 3 | import { defineConfig } from 'vite'; 4 | 5 | export default defineConfig({ 6 | plugins: [tailwindcss(), sveltekit()] 7 | }); 8 | --------------------------------------------------------------------------------