├── .eslintignore
├── .eslintrc.cjs
├── .gitattributes
├── .github
└── workflows
│ └── azure-static-web-apps-nice-sky-059595e10.yml
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc
├── LICENSE
├── README.md
├── assets
└── gifs
│ ├── settings.gif
│ └── showcase.gif
├── package-lock.json
├── package.json
├── postcss.config.js
├── src
├── app.d.ts
├── app.html
├── lib
│ ├── components
│ │ ├── custom
│ │ │ ├── options
│ │ │ │ ├── Options.svelte
│ │ │ │ └── index.ts
│ │ │ ├── settings
│ │ │ │ ├── Settings.svelte
│ │ │ │ └── index.ts
│ │ │ └── svelte-code
│ │ │ │ ├── SvelteCode.svelte
│ │ │ │ └── index.ts
│ │ ├── examples
│ │ │ ├── AccordionExample.svelte
│ │ │ ├── AlertDialogExample.svelte
│ │ │ ├── AlertExample.svelte
│ │ │ ├── AspectRatioExample.svelte
│ │ │ ├── AvatarExample.svelte
│ │ │ ├── BadgeExample.svelte
│ │ │ ├── BreadcrumbExample.svelte
│ │ │ ├── ButtonExample.svelte
│ │ │ ├── CardExample.svelte
│ │ │ ├── CheckboxExample.svelte
│ │ │ ├── CollapsibleExample.svelte
│ │ │ ├── DialogExample.svelte
│ │ │ ├── HoverCardExample.svelte
│ │ │ ├── InputExample.svelte
│ │ │ ├── InputOtpExample.svelte
│ │ │ ├── LabelExample.svelte
│ │ │ ├── LinkExample.svelte
│ │ │ ├── PaginationExample.svelte
│ │ │ ├── PopoverExample.svelte
│ │ │ ├── ProgressExample.svelte
│ │ │ ├── RadioGroupExample.svelte
│ │ │ ├── ScrollAreaExample.svelte
│ │ │ ├── SelectExample.svelte
│ │ │ ├── SeparatorExample.svelte
│ │ │ ├── SheetExample.svelte
│ │ │ ├── SkeletonExample.svelte
│ │ │ ├── SliderExample.svelte
│ │ │ ├── SwitchExample.svelte
│ │ │ ├── TableExample.svelte
│ │ │ ├── TabsExample.svelte
│ │ │ ├── TextareaExample.svelte
│ │ │ ├── ToastExample.svelte
│ │ │ ├── ToggleExample.svelte
│ │ │ ├── ToggleGroupExample.svelte
│ │ │ ├── TooltipExample.svelte
│ │ │ └── index.ts
│ │ └── ui
│ │ │ ├── accordion
│ │ │ ├── Accordion.svelte
│ │ │ ├── AccordionContent.svelte
│ │ │ ├── AccordionItem.svelte
│ │ │ ├── AccordionTrigger.svelte
│ │ │ └── index.ts
│ │ │ ├── alert-dialog
│ │ │ ├── AlertDialog.svelte
│ │ │ ├── AlertDialogAction.svelte
│ │ │ ├── AlertDialogCancel.svelte
│ │ │ ├── AlertDialogContent.svelte
│ │ │ ├── AlertDialogDescription.svelte
│ │ │ ├── AlertDialogFooter.svelte
│ │ │ ├── AlertDialogHeader.svelte
│ │ │ ├── AlertDialogTitle.svelte
│ │ │ ├── AlertDialogTrigger.svelte
│ │ │ └── index.ts
│ │ │ ├── alert
│ │ │ ├── Alert.svelte
│ │ │ ├── AlertDescription.svelte
│ │ │ ├── AlertTitle.svelte
│ │ │ ├── alertVariants.ts
│ │ │ └── index.ts
│ │ │ ├── aspect-ratio
│ │ │ ├── AspectRatio.svelte
│ │ │ └── index.ts
│ │ │ ├── avatar
│ │ │ ├── Avatar.svelte
│ │ │ ├── AvatarFallback.svelte
│ │ │ ├── AvatarImage.svelte
│ │ │ └── index.ts
│ │ │ ├── badge
│ │ │ ├── Badge.svelte
│ │ │ ├── badgeVariants.ts
│ │ │ └── index.ts
│ │ │ ├── breadcrumb
│ │ │ ├── Breadcrumb.svelte
│ │ │ ├── BreadcrumbEllipsis.svelte
│ │ │ ├── BreadcrumbItem.svelte
│ │ │ ├── BreadcrumbLink.svelte
│ │ │ ├── BreadcrumbList.svelte
│ │ │ ├── BreadcrumbPage.svelte
│ │ │ ├── BreadcrumbSeparator.svelte
│ │ │ └── index.ts
│ │ │ ├── button
│ │ │ ├── Button.svelte
│ │ │ ├── buttonVariants.ts
│ │ │ └── index.ts
│ │ │ ├── card
│ │ │ ├── Card.svelte
│ │ │ ├── CardContent.svelte
│ │ │ ├── CardDescription.svelte
│ │ │ ├── CardFooter.svelte
│ │ │ ├── CardHeader.svelte
│ │ │ ├── CardTitle.svelte
│ │ │ └── index.ts
│ │ │ ├── checkbox
│ │ │ ├── Checkbox.svelte
│ │ │ └── index.ts
│ │ │ ├── collapsible
│ │ │ ├── Collapsible.svelte
│ │ │ ├── CollapsibleContent.svelte
│ │ │ ├── CollapsibleTrigger.svelte
│ │ │ └── index.ts
│ │ │ ├── dialog
│ │ │ ├── Dialog.svelte
│ │ │ ├── DialogContent.svelte
│ │ │ ├── DialogDescription.svelte
│ │ │ ├── DialogFooter.svelte
│ │ │ ├── DialogHeader.svelte
│ │ │ ├── DialogTitle.svelte
│ │ │ ├── DialogTrigger.svelte
│ │ │ └── index.ts
│ │ │ ├── hover-card
│ │ │ ├── HoverCard.svelte
│ │ │ ├── HoverCardContent.svelte
│ │ │ ├── HoverCardTrigger.svelte
│ │ │ └── index.ts
│ │ │ ├── input-otp
│ │ │ ├── InputOTP.svelte
│ │ │ ├── InputOTPGroup.svelte
│ │ │ ├── InputOTPSeparator.svelte
│ │ │ ├── InputOTPSlot.svelte
│ │ │ └── index.ts
│ │ │ ├── input
│ │ │ ├── Input.svelte
│ │ │ └── index.ts
│ │ │ ├── label
│ │ │ ├── Label.svelte
│ │ │ └── index.ts
│ │ │ ├── link
│ │ │ ├── Link.svelte
│ │ │ └── index.ts
│ │ │ ├── pagination
│ │ │ ├── Pagination.svelte
│ │ │ ├── PaginationContent.svelte
│ │ │ ├── PaginationEllipsis.svelte
│ │ │ ├── PaginationItem.svelte
│ │ │ ├── PaginationLink.svelte
│ │ │ ├── PaginationNext.svelte
│ │ │ ├── PaginationPrevious.svelte
│ │ │ └── index.ts
│ │ │ ├── popover
│ │ │ ├── Popover.svelte
│ │ │ ├── PopoverContent.svelte
│ │ │ ├── PopoverTrigger.svelte
│ │ │ └── index.ts
│ │ │ ├── progress
│ │ │ ├── Progress.svelte
│ │ │ └── index.ts
│ │ │ ├── radio-group
│ │ │ ├── RadioGroup.svelte
│ │ │ ├── RadioGroupItem.svelte
│ │ │ └── index.ts
│ │ │ ├── scroll-area
│ │ │ ├── ScrollArea.svelte
│ │ │ └── index.ts
│ │ │ ├── select
│ │ │ ├── Select.svelte
│ │ │ ├── SelectContent.svelte
│ │ │ ├── SelectGroup.svelte
│ │ │ ├── SelectItem.svelte
│ │ │ ├── SelectLabel.svelte
│ │ │ ├── SelectScrollDownButton.svelte
│ │ │ ├── SelectScrollUpButton.svelte
│ │ │ ├── SelectTrigger.svelte
│ │ │ ├── SelectValue.svelte
│ │ │ ├── index.ts
│ │ │ └── select.ts
│ │ │ ├── separator
│ │ │ ├── Separator.svelte
│ │ │ └── index.ts
│ │ │ ├── sheet
│ │ │ ├── Sheet.svelte
│ │ │ ├── SheetClose.svelte
│ │ │ ├── SheetContent.svelte
│ │ │ ├── SheetDescription.svelte
│ │ │ ├── SheetFooter.svelte
│ │ │ ├── SheetHeader.svelte
│ │ │ ├── SheetTitle.svelte
│ │ │ ├── SheetTrigger.svelte
│ │ │ ├── index.ts
│ │ │ └── sheetVariants.ts
│ │ │ ├── skeleton
│ │ │ ├── Skeleton.svelte
│ │ │ └── index.ts
│ │ │ ├── slider
│ │ │ ├── Slider.svelte
│ │ │ └── index.ts
│ │ │ ├── switch
│ │ │ ├── Switch.svelte
│ │ │ └── index.ts
│ │ │ ├── table
│ │ │ ├── Table.svelte
│ │ │ ├── TableBody.svelte
│ │ │ ├── TableCaption.svelte
│ │ │ ├── TableCell.svelte
│ │ │ ├── TableFooter.svelte
│ │ │ ├── TableHead.svelte
│ │ │ ├── TableHeader.svelte
│ │ │ ├── TableRow.svelte
│ │ │ └── index.ts
│ │ │ ├── tabs
│ │ │ ├── Tabs.svelte
│ │ │ ├── TabsContent.svelte
│ │ │ ├── TabsList.svelte
│ │ │ ├── TabsTrigger.svelte
│ │ │ └── index.ts
│ │ │ ├── textarea
│ │ │ ├── Textarea.svelte
│ │ │ └── index.ts
│ │ │ ├── toast
│ │ │ ├── Toast.svelte
│ │ │ ├── ToastAction.svelte
│ │ │ ├── ToastClose.svelte
│ │ │ ├── ToastDescription.svelte
│ │ │ ├── ToastProvider.svelte
│ │ │ ├── ToastTitle.svelte
│ │ │ ├── index.ts
│ │ │ ├── toast.ts
│ │ │ └── toastVariants.ts
│ │ │ ├── toggle-group
│ │ │ ├── ToggleGroup.svelte
│ │ │ ├── ToggleGroupItem.svelte
│ │ │ ├── index.ts
│ │ │ └── toggleVariants.ts
│ │ │ ├── toggle
│ │ │ ├── Toggle.svelte
│ │ │ ├── index.ts
│ │ │ └── toggleVariants.ts
│ │ │ └── tooltip
│ │ │ ├── Tooltip.svelte
│ │ │ ├── TooltipContent.svelte
│ │ │ ├── TooltipProvider.svelte
│ │ │ ├── TooltipTrigger.svelte
│ │ │ └── index.ts
│ └── helpers
│ │ ├── actions.ts
│ │ ├── state.ts
│ │ ├── types.ts
│ │ └── utils.ts
├── routes
│ ├── +layout.svelte
│ └── +page.svelte
└── styles
│ └── globals.css
├── static
└── favicon.png
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts
/.eslintignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:svelte/recommended', 'prettier'],
4 | parser: '@typescript-eslint/parser',
5 | plugins: ['@typescript-eslint'],
6 | parserOptions: {
7 | sourceType: 'module',
8 | ecmaVersion: 2020,
9 | extraFileExtensions: ['.svelte']
10 | },
11 | env: {
12 | browser: true,
13 | es2017: true,
14 | node: true
15 | },
16 | overrides: [
17 | {
18 | files: ['*.svelte'],
19 | parser: 'svelte-eslint-parser',
20 | parserOptions: {
21 | parser: '@typescript-eslint/parser'
22 | }
23 | }
24 | ]
25 | };
26 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/workflows/azure-static-web-apps-nice-sky-059595e10.yml:
--------------------------------------------------------------------------------
1 | name: Azure Static Web Apps CI/CD
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | types: [opened, synchronize, reopened, closed]
9 | branches:
10 | - main
11 |
12 | jobs:
13 | build_and_deploy_job:
14 | if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
15 | runs-on: ubuntu-latest
16 | name: Build and Deploy Job
17 | steps:
18 | - uses: actions/checkout@v3
19 | with:
20 | submodules: true
21 | lfs: false
22 | - name: Build And Deploy
23 | id: builddeploy
24 | uses: Azure/static-web-apps-deploy@v1
25 | with:
26 | azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_SKY_059595E10 }}
27 | repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
28 | action: "upload"
29 | ###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
30 | # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
31 | app_location: "./" # App source code path
32 | api_location: "build/server" # Api source code path - optional
33 | output_location: "build/static" # Built app content directory - optional
34 | ###### End of Repository/Build Configurations ######
35 |
36 | close_pull_request_job:
37 | if: github.event_name == 'pull_request' && github.event.action == 'closed'
38 | runs-on: ubuntu-latest
39 | name: Close Pull Request Job
40 | steps:
41 | - name: Close Pull Request
42 | id: closepullrequest
43 | uses: Azure/static-web-apps-deploy@v1
44 | with:
45 | azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_SKY_059595E10 }}
46 | action: "close"
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # build folder
2 | dist/
3 | build/
4 |
5 | # logs
6 | logs/
7 | .cache
8 | .DS_Store
9 | npm-debug.log
10 | yarn-debug.log
11 | yarn-error.log
12 |
13 | # process data
14 | .pid
15 | pids
16 | .pid-lock
17 |
18 | # Coverage & Test
19 | coverage
20 | .nyc_output
21 |
22 | # Dependency folder
23 | node_modules
24 | bower_components
25 | jspm_packages
26 |
27 | # Environment files
28 | .dot
29 |
30 | # Editor and other files
31 | .idea
32 | typing
33 | internal
34 | .vscode
35 | *.tgz
36 | .eslintcache
37 | .svelte-kit
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 | resolution-mode=highest
3 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": true,
3 | "singleQuote": true,
4 | "trailingComma": "none",
5 | "printWidth": 200,
6 | "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
7 | "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
8 | }
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Wail Abou
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Port of shadcn/ui without Radix Depedency or any other UI library
2 |
3 | This repository contains a port of the `shadcn/ui` library, a collection of UI components for web applications. The port is designed to have zero external UI dependencies and utilizes Tailwind CSS for styling. I added some minor additions and improvements like an affirmative variant and a Link component.
4 |
5 | # Demo
6 |
7 | A live demo can be found [here](https://nice-sky-059595e10.4.azurestaticapps.net)
8 |
9 | 
10 |
11 | 
12 |
13 | ## Components
14 |
15 | Here is a list of components that have been ported from `shadcn/ui`. Each component is marked with a checkmark if it has been successfully implemented:
16 |
17 | | Component | Status |
18 | | --------------- | ------ |
19 | | Accordion | ✅ |
20 | | Alert | ✅ |
21 | | Alert Dialog | ✅ |
22 | | Aspect Ratio | ✅ |
23 | | Avatar | ✅ |
24 | | Badge | ✅ |
25 | | Breadcrumb | ✅ |
26 | | Button | ✅ |
27 | | Calendar | ❌ |
28 | | Card | ✅ |
29 | | Carousel | ❌ |
30 | | Chart | ❌ |
31 | | Checkbox | ✅ |
32 | | Collapsible | ✅ |
33 | | Combobox | ❌ |
34 | | Command | ❌ |
35 | | Context Menu | ❌ |
36 | | Data Table | ❌ |
37 | | Date Picker | ❌ |
38 | | Dialog | ✅ |
39 | | Drawer | ❌ |
40 | | Dropdown Menu | ❌ |
41 | | Form | ❌ |
42 | | Hover Card | ✅ |
43 | | Input | ✅ |
44 | | Input OTP | ✅ |
45 | | Label | ✅ |
46 | | Link | ✅ |
47 | | Menubar | ❌ |
48 | | Navigation Menu | ❌ |
49 | | Pagination | ✅ |
50 | | Popover | ✅ |
51 | | Progress | ✅ |
52 | | Radio Group | ✅ |
53 | | Resizable | ❌ |
54 | | Scroll Area | ✅ |
55 | | Select | ✅ |
56 | | Separator | ✅ |
57 | | Sheet | ✅ |
58 | | Sidebar | ❌ |
59 | | Skeleton | ✅ |
60 | | Slider | ✅ |
61 | | Sonner | ❌ |
62 | | Switch | ✅ |
63 | | Table | ✅ |
64 | | Tabs | ✅ |
65 | | Textarea | ✅ |
66 | | Toast | ✅ |
67 | | Toggle | ✅ |
68 | | Toggle Group | ✅ |
69 | | Tooltip | ✅ |
70 |
71 | ## Usage
72 |
73 | Make sure to refer to the original `shadcn/ui` documentation for detailed usage instructions.
74 |
75 | ## Support My Work
76 |
77 | If you find this project useful and want to support continued development, consider [buying me a coffee](https://www.buymeacoffee.com/wailabou).
78 |
79 | ☕ Programming is not just my profession — it's also my passion. I love learning, exploring new challenges, and sharing open source work with the community.
80 |
81 | ## License
82 |
83 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
84 |
85 | ## Special Thanks
86 |
87 | I want to extend my gratitude to the following individuals and projects for their valuable contributions to this port:
88 |
89 | - **Duder-onomy** for their excellent work on [svelte-focus-trap](https://github.com/Duder-onomy/svelte-focus-trap/blob/master/src/utils.js).
90 |
91 | - **SkeletonLabs Team** for their genius implementation of [FocusTrap](https://github.com/skeletonlabs/skeleton/blob/master/packages/skeleton/src/lib/actions/FocusTrap/focusTrap.ts) in the Skeleton framework.
92 |
93 | - **shadcn** for their fantastic [shadcn/ui](https://github.com/shadcn-ui/ui) library, which inspired this project.
94 |
95 | - **huntabyte** for their port of shadcn/ui with Radix Dependency, which served as an excellent reference. Check out their work [here](https://github.com/huntabyte/shadcn-svelte).
96 |
97 | I am grateful for their contributions, which helped make this project possible.
98 |
--------------------------------------------------------------------------------
/assets/gifs/settings.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WailAbou/shadcn-svelte-nodep/3c06686a10278edd3d60b7fbd1a96c1ff93a1443/assets/gifs/settings.gif
--------------------------------------------------------------------------------
/assets/gifs/showcase.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WailAbou/shadcn-svelte-nodep/3c06686a10278edd3d60b7fbd1a96c1ff93a1443/assets/gifs/showcase.gif
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "shadcn-svelte-nodep",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vite dev",
7 | "build": "vite build",
8 | "preview": "vite preview",
9 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
10 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
11 | "lint": "prettier . --check . && eslint .",
12 | "format": "prettier --write \"**/*.{js,jsx,json,md,html,svelte}\""
13 | },
14 | "devDependencies": {
15 | "@sveltejs/kit": "2.20.7",
16 | "@typescript-eslint/eslint-plugin": "8.22.0",
17 | "@typescript-eslint/parser": "8.22.0",
18 | "autoprefixer": "10.4.20",
19 | "eslint": "9.19.0",
20 | "eslint-config-prettier": "10.0.1",
21 | "eslint-plugin-svelte": "2.46.1",
22 | "postcss": "8.5.1",
23 | "prettier": "3.4.2",
24 | "prettier-plugin-svelte": "3.3.3",
25 | "prettier-plugin-tailwindcss": "0.6.11",
26 | "svelte": "5.19.5",
27 | "svelte-adapter-azure-swa": "^0.20.1",
28 | "svelte-check": "4.1.4",
29 | "svelte-highlight": "7.8.2",
30 | "tailwindcss": "3.4.17",
31 | "tslib": "2.8.1",
32 | "typescript": "5.7.3",
33 | "vite": "5.4.18"
34 | },
35 | "type": "module",
36 | "dependencies": {
37 | "class-variance-authority": "0.7.1",
38 | "clsx": "2.1.1",
39 | "lucide-svelte": "0.474.0",
40 | "tailwind-merge": "2.6.0",
41 | "tailwindcss-animate": "1.0.7"
42 | }
43 | }
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {}
5 | }
6 | };
7 |
--------------------------------------------------------------------------------
/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://kit.svelte.dev/docs/types#app
2 | // for information about these interfaces
3 | declare global {
4 | namespace App {
5 | // interface Error {}
6 | // interface Locals {}
7 | // interface PageData {}
8 | // interface Platform {}
9 | }
10 | }
11 |
12 | export {};
13 |
--------------------------------------------------------------------------------
/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | %sveltekit.head%
8 |
9 |
10 | %sveltekit.body%
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/custom/options/Options.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 | (isOpen = open)}>
11 |
12 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/lib/components/custom/options/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Options } from './Options.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/custom/settings/Settings.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | {@html codeCss}
19 |
20 |
21 |
22 |
Settings
23 |
24 |
25 |
26 | {
29 | darkMode = checked;
30 | window.document.body.classList.toggle('dark');
31 | }}
32 | />
33 |
34 |
35 |
36 |
37 | (codeMode = checked ? CodeMode.Source : CodeMode.None)} />
38 |
39 |
40 |
41 | {#if codeMode != CodeMode.None}
42 |
43 | (codeMode = checked ? CodeMode.Html : CodeMode.Source)} />
44 |
45 |
46 | {/if}
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/lib/components/custom/settings/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Settings } from './Settings.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/custom/svelte-code/SvelteCode.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 | {#if codeMode == CodeMode.Source}
17 |
18 | {:else if codeMode == CodeMode.Html}
19 |
20 | {:else}
21 |
22 | {/if}
23 |
--------------------------------------------------------------------------------
/src/lib/components/custom/svelte-code/index.ts:
--------------------------------------------------------------------------------
1 | export { default as SvelteCode } from './SvelteCode.svelte';
2 | export enum CodeMode {
3 | None,
4 | Source,
5 | Html
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/components/examples/AccordionExample.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 | Value: {value}
17 |
18 |
19 |
20 |
21 |
22 | {#key uid}
23 | (value = newValue)} {type} {collapsible} {disabled} class="w-full">
24 |
25 | Is it accessible?
26 | Yes. It adheres to the WAI-ARIA design pattern.
27 |
28 |
29 | Is it styled?
30 | Yes. It comes with default styles that matches the other components' aesthetic.
31 |
32 |
33 | Is it animated?
34 | Yes. It's animated by default, but you can disable it if you prefer.
35 |
36 |
37 | {/key}
38 |
--------------------------------------------------------------------------------
/src/lib/components/examples/AlertDialogExample.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Are you absolutely sure?
23 | This action cannot be undone. This will permanently delete your account and remove your data from our servers.
24 |
25 |
26 | Cancel
27 | Continue
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/lib/components/examples/AlertExample.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | Heads up!
9 | You can add components to your app using the cli.
10 |
11 |
12 |
13 |
14 | Error
15 | Your session has expired. Please log in again.
16 |
17 |
18 |
19 |
20 | Success
21 | You have been successfully logged in.
22 |
23 |
--------------------------------------------------------------------------------
/src/lib/components/examples/AspectRatioExample.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/lib/components/examples/AvatarExample.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 | CN
8 |
9 |
--------------------------------------------------------------------------------
/src/lib/components/examples/BadgeExample.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 | Primary
6 | Secondary
7 | Destructive
8 | Affirmative
9 | Outline
10 |
--------------------------------------------------------------------------------
/src/lib/components/examples/BreadcrumbExample.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 | Home
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Components
18 |
19 |
20 |
21 | Breadcrumb
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Home
30 |
31 |
32 |
33 |
34 |
35 | Components
36 |
37 |
38 |
39 |
40 |
41 | Breadcrumb
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/lib/components/examples/ButtonExample.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/lib/components/examples/CardExample.svelte:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 |
25 | Notifications
26 | You have 3 unread messages.
27 |
28 |
29 |
30 |
31 |
32 |
Push Notifications
33 |
Send notifications to device.
34 |
35 |
36 |
37 |
38 | {#each notifications as notification}
39 |
40 |
41 |
42 |
43 | {notification.title}
44 |
45 |
46 | {notification.description}
47 |
48 |
49 |
50 | {/each}
51 |
52 |
53 |
54 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/lib/components/examples/CheckboxExample.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
You agree to our Terms of Service and Privacy Policy.
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/lib/components/examples/CollapsibleExample.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 | {#key uid}
17 |
18 |
19 |
@peduarte starred 3 repositories
20 |
21 |
25 |
26 |
27 | @radix-ui/primitives
28 |
29 | @radix-ui/colors
30 | @stitches/react
31 |
32 |
33 | {/key}
34 |
--------------------------------------------------------------------------------
/src/lib/components/examples/DialogExample.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
34 |
--------------------------------------------------------------------------------
/src/lib/components/examples/HoverCardExample.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | {#each sides as side}
13 |
14 |
15 | Hover card {side}
16 |
17 |
18 |
19 |
20 |
21 | VC
22 |
23 |
24 |
@nextjs
25 |
The React Framework – created and maintained by @vercel.
26 |
27 | {' '}
28 | Joined December 2021
29 |
30 |
31 |
32 |
33 |
34 | {/each}
35 |
36 |
--------------------------------------------------------------------------------
/src/lib/components/examples/InputExample.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
27 |
--------------------------------------------------------------------------------
/src/lib/components/examples/InputOtpExample.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 | {#if value === ''}
17 | Enter your one-time password.
18 | {:else}
19 | You entered: {value}
20 | {/if}
21 |
22 |
23 |
24 |
25 |
26 | {#key pattern}
27 | (value = newValue)}>
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | {/key}
41 |
--------------------------------------------------------------------------------
/src/lib/components/examples/LabelExample.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/lib/components/examples/LinkExample.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
Click this for a redirect
10 |
11 |
12 |
Click this to open a new tab
13 |
14 |
15 |
Click this button link
16 |
17 |
18 |
Click this badge link
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/lib/components/examples/PaginationExample.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 1
12 |
13 |
14 | 2
15 |
16 |
17 | 3
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/lib/components/examples/PopoverExample.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | {#each sides as side}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Dimensions
21 |
Set the dimensions for the layer.
22 |
23 |
41 |
42 |
43 |
44 | {/each}
45 |
46 |
--------------------------------------------------------------------------------
/src/lib/components/examples/ProgressExample.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/lib/components/examples/RadioGroupExample.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 | Value: {value}
15 |
16 |
17 |
18 | {#key uid}
19 | (value = newValue)}>
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | {/key}
34 |
--------------------------------------------------------------------------------
/src/lib/components/examples/ScrollAreaExample.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
Tags
25 | {#each tagsFull as tag}
26 |
{tag}
27 |
28 | {/each}
29 |
30 |
31 |
32 |
33 |
34 |
Tags
35 | {#each tagsSubset as tag}
36 |
{tag}
37 |
38 | {/each}
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/lib/components/examples/SelectExample.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
21 |
22 |
71 |
72 |
--------------------------------------------------------------------------------
/src/lib/components/examples/SeparatorExample.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
Radix Primitives
7 |
An open-source UI component library.
8 |
9 |
10 |
11 |
12 |
13 |
Blog
14 |
15 |
Docs
16 |
17 |
Source
18 |
19 |
--------------------------------------------------------------------------------
/src/lib/components/examples/SheetExample.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | {#each sides as side}
13 |
14 |
15 |
16 |
17 |
18 |
19 | Edit profile
20 | Make changes to your profile here. Click save when you're done.
21 |
22 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | {/each}
40 |
41 |
--------------------------------------------------------------------------------
/src/lib/components/examples/SkeletonExample.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/examples/SliderExample.svelte:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 | Value: {value}
24 |
25 |
26 |
27 |
28 |
29 | {#key uid}
30 | (value = newValue)} defaultValue={(range[0] + range[1]) / 2} min={range[0]} max={range[1]} {step} {disabled} />
31 | {/key}
32 |
--------------------------------------------------------------------------------
/src/lib/components/examples/SwitchExample.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/lib/components/examples/TableExample.svelte:
--------------------------------------------------------------------------------
1 |
49 |
50 |
51 | A list of your recent invoices.
52 |
53 |
54 | Invoice
55 | Status
56 | Method
57 | Amount
58 |
59 |
60 |
61 | {#each invoices as invoice (invoice.invoice)}
62 |
63 | {invoice.invoice}
64 | {invoice.paymentStatus}
65 | {invoice.paymentMethod}
66 | {invoice.totalAmount}
67 |
68 | {/each}
69 |
70 |
71 |
72 | Total
73 | $2,500.00
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/src/lib/components/examples/TabsExample.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 | Account
12 | Password
13 |
14 |
15 |
16 |
17 | Account
18 | Make changes to your account here. Click save when you're done.
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Password
39 | Change your password here. After saving, you'll be logged out.
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/src/lib/components/examples/TextareaExample.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Your message will be copied to the support team.
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/lib/components/examples/ToastExample.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/lib/components/examples/ToggleExample.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Italic
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/lib/components/examples/ToggleGroupExample.svelte:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 | Value: {value}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {#key uid}
38 | (value = newValue)} {type} {disabled} {variant} {size} {orientation} {rovingFocus} {loop}>
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | {/key}
50 |
--------------------------------------------------------------------------------
/src/lib/components/examples/TooltipExample.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 | {#each sides as side}
11 |
12 |
13 |
14 |
15 |
16 |
17 | Add to library
18 |
19 |
20 |
21 | {/each}
22 |
23 |
--------------------------------------------------------------------------------
/src/lib/components/ui/accordion/Accordion.svelte:
--------------------------------------------------------------------------------
1 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/lib/components/ui/accordion/AccordionContent.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 | {#if $isOpen}
14 |
19 | {/if}
20 |
--------------------------------------------------------------------------------
/src/lib/components/ui/accordion/AccordionItem.svelte:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/lib/components/ui/accordion/AccordionTrigger.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/src/lib/components/ui/accordion/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Accordion } from './Accordion.svelte';
2 | export { default as AccordionContent } from './AccordionContent.svelte';
3 | export { default as AccordionItem } from './AccordionItem.svelte';
4 | export { default as AccordionTrigger } from './AccordionTrigger.svelte';
5 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialog.svelte:
--------------------------------------------------------------------------------
1 |
19 |
20 | isOpen.set(false), ['Escape']]} />
21 |
22 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialogAction.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialogCancel.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialogContent.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 | {#if $isOpen || !$finishedAnimation}
16 |
22 |
33 |
34 |
35 | {/if}
36 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialogDescription.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialogFooter.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialogHeader.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialogTitle.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/AlertDialogTrigger.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert-dialog/index.ts:
--------------------------------------------------------------------------------
1 | export { default as AlertDialog } from './AlertDialog.svelte';
2 | export { default as AlertDialogTrigger } from './AlertDialogTrigger.svelte';
3 | export { default as AlertDialogContent } from './AlertDialogContent.svelte';
4 | export { default as AlertDialogHeader } from './AlertDialogHeader.svelte';
5 | export { default as AlertDialogTitle } from './AlertDialogTitle.svelte';
6 | export { default as AlertDialogDescription } from './AlertDialogDescription.svelte';
7 | export { default as AlertDialogFooter } from './AlertDialogFooter.svelte';
8 | export { default as AlertDialogCancel } from './AlertDialogCancel.svelte';
9 | export { default as AlertDialogAction } from './AlertDialogAction.svelte';
10 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert/Alert.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert/AlertDescription.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert/AlertTitle.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert/alertVariants.ts:
--------------------------------------------------------------------------------
1 | import { cva } from 'class-variance-authority';
2 |
3 | export const alertVariants = cva('relative w-full rounded-lg border p-4 [&:has(svg)]:pl-11 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground', {
4 | variants: {
5 | variant: {
6 | default: 'bg-background text-foreground',
7 | destructive: 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
8 | affirmative: 'border-affirmative/50 text-affirmative dark:border-affirmative [&>svg]:text-affirmative'
9 | }
10 | },
11 | defaultVariants: {
12 | variant: 'default'
13 | }
14 | });
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/alert/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Alert } from './Alert.svelte';
2 | export { default as AlertTitle } from './AlertTitle.svelte';
3 | export { default as AlertDescription } from './AlertDescription.svelte';
4 | export type AlertTitleLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
5 |
--------------------------------------------------------------------------------
/src/lib/components/ui/aspect-ratio/AspectRatio.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/src/lib/components/ui/aspect-ratio/index.ts:
--------------------------------------------------------------------------------
1 | export { default as AspectRatio } from "./AspectRatio.svelte";
--------------------------------------------------------------------------------
/src/lib/components/ui/avatar/Avatar.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/lib/components/ui/avatar/AvatarFallback.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 | {#if showFallback}
17 |
18 |
19 |
20 | {/if}
21 |
--------------------------------------------------------------------------------
/src/lib/components/ui/avatar/AvatarImage.svelte:
--------------------------------------------------------------------------------
1 |
23 |
24 | {#if $imageLoadingStatus === 'loaded'}
25 |
26 | {/if}
27 |
--------------------------------------------------------------------------------
/src/lib/components/ui/avatar/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Avatar } from './Avatar.svelte';
2 | export { default as AvatarFallback } from './AvatarFallback.svelte';
3 | export { default as AvatarImage } from './AvatarImage.svelte';
4 | export type AvatarLoadingtatus = 'idle' | 'loading'| 'loaded' | 'error';
--------------------------------------------------------------------------------
/src/lib/components/ui/badge/Badge.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/lib/components/ui/badge/badgeVariants.ts:
--------------------------------------------------------------------------------
1 | import { cva } from "class-variance-authority";
2 |
3 | export const badgeVariants = cva(
4 | "inline-flex items-center border rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
5 | {
6 | variants: {
7 | variant: {
8 | default: "bg-primary hover:bg-primary/80 border-transparent text-primary-foreground",
9 | secondary: "bg-secondary hover:bg-secondary/80 border-transparent text-secondary-foreground",
10 | destructive: "bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground",
11 | affirmative: 'bg-affirmative hover:bg-affirmative/80 border-transparent text-affirmative-foreground',
12 | outline: "text-foreground"
13 | }
14 | },
15 | defaultVariants: {
16 | variant: "default"
17 | }
18 | }
19 | );
--------------------------------------------------------------------------------
/src/lib/components/ui/badge/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Badge } from './Badge.svelte';
2 | export { badgeVariants } from './badgeVariants';
3 |
--------------------------------------------------------------------------------
/src/lib/components/ui/breadcrumb/Breadcrumb.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/breadcrumb/BreadcrumbEllipsis.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 | More
12 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/ui/breadcrumb/BreadcrumbItem.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/breadcrumb/BreadcrumbLink.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/breadcrumb/BreadcrumbList.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/breadcrumb/BreadcrumbPage.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/breadcrumb/BreadcrumbSeparator.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 | svg]:size-3.5', className)}>
10 | {#if $$slots.default}
11 |
12 | {:else}
13 |
14 | {/if}
15 |
16 |
--------------------------------------------------------------------------------
/src/lib/components/ui/breadcrumb/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Breadcrumb } from './Breadcrumb.svelte';
2 | export { default as BreadcrumbList } from './BreadcrumbList.svelte';
3 | export { default as BreadcrumbItem } from './BreadcrumbItem.svelte';
4 | export { default as BreadcrumbLink } from './BreadcrumbLink.svelte';
5 | export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.svelte';
6 | export { default as BreadcrumbPage } from './BreadcrumbPage.svelte';
7 | export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.svelte';
8 |
--------------------------------------------------------------------------------
/src/lib/components/ui/button/Button.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
17 |
--------------------------------------------------------------------------------
/src/lib/components/ui/button/buttonVariants.ts:
--------------------------------------------------------------------------------
1 | import { cva } from 'class-variance-authority';
2 |
3 | export const buttonVariants = cva(
4 | 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
5 | {
6 | variants: {
7 | variant: {
8 | default: 'bg-primary text-primary-foreground hover:bg-primary/90',
9 | destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
10 | affirmative: 'bg-affirmative text-affirmative-foreground hover:bg-affirmative/90',
11 | outline: 'border border-input hover:bg-accent hover:text-accent-foreground',
12 | secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
13 | ghost: 'hover:bg-accent hover:text-accent-foreground'
14 | },
15 | size: {
16 | default: 'h-10 py-2 px-4',
17 | sm: 'h-9 px-3 rounded-md',
18 | lg: 'h-11 px-8 rounded-md',
19 | icon: 'h-10 w-10'
20 | }
21 | },
22 | defaultVariants: {
23 | variant: 'default',
24 | size: 'default'
25 | }
26 | }
27 | );
28 |
--------------------------------------------------------------------------------
/src/lib/components/ui/button/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Button } from './Button.svelte';
2 | export { buttonVariants } from './buttonVariants';
3 |
--------------------------------------------------------------------------------
/src/lib/components/ui/card/Card.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/card/CardContent.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/card/CardDescription.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/card/CardFooter.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/card/CardHeader.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/card/CardTitle.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/card/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Card } from './Card.svelte';
2 | export { default as CardContent } from './CardContent.svelte';
3 | export { default as CardHeader } from './CardHeader.svelte';
4 | export { default as CardTitle } from './CardTitle.svelte';
5 | export { default as CardDescription } from './CardDescription.svelte';
6 | export { default as CardFooter } from './CardFooter.svelte';
7 |
--------------------------------------------------------------------------------
/src/lib/components/ui/checkbox/Checkbox.svelte:
--------------------------------------------------------------------------------
1 |
24 |
25 |
43 |
44 |
--------------------------------------------------------------------------------
/src/lib/components/ui/checkbox/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Checkbox } from './Checkbox.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/collapsible/Collapsible.svelte:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/lib/components/ui/collapsible/CollapsibleContent.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/collapsible/CollapsibleTrigger.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/collapsible/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Collapsible } from './Collapsible.svelte';
2 | export { default as CollapsibleTrigger } from './CollapsibleTrigger.svelte';
3 | export { default as CollapsibleContent } from './CollapsibleContent.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dialog/Dialog.svelte:
--------------------------------------------------------------------------------
1 |
19 |
20 | isOpen.set(false), ['Escape']]} />
21 |
22 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dialog/DialogContent.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 | {#if $isOpen || !$finishedAnimation}
16 |
22 | isOpen.set(false)]}
25 | use:focusTrap
26 | data-state={$isOpen ? 'open' : 'closed'}
27 | role="dialog"
28 | class={cn(
29 | 'pointer-events-auto fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg md:w-full',
30 | className
31 | )}
32 | tabindex="-1"
33 | >
34 |
35 |
36 | {/if}
37 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dialog/DialogDescription.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dialog/DialogFooter.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dialog/DialogHeader.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dialog/DialogTitle.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dialog/DialogTrigger.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dialog/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Dialog } from './Dialog.svelte';
2 | export { default as DialogTrigger } from './DialogTrigger.svelte';
3 | export { default as DialogContent } from './DialogContent.svelte';
4 | export { default as DialogHeader } from './DialogHeader.svelte';
5 | export { default as DialogTitle } from './DialogTitle.svelte';
6 | export { default as DialogDescription } from './DialogDescription.svelte';
7 | export { default as DialogFooter } from './DialogFooter.svelte';
8 |
--------------------------------------------------------------------------------
/src/lib/components/ui/hover-card/HoverCard.svelte:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/lib/components/ui/hover-card/HoverCardContent.svelte:
--------------------------------------------------------------------------------
1 |
47 |
48 | (position = getPosition($hoverCardTrigger, hoverCardContent, $side, align, sideOffset, alignOffset))} on:scrollend={() => closeOnIdle($mouseEvent)} />
49 |
50 | {#if $isOpen || !$finishedAnimation}
51 |
65 | {/if}
66 |
--------------------------------------------------------------------------------
/src/lib/components/ui/hover-card/HoverCardTrigger.svelte:
--------------------------------------------------------------------------------
1 |
57 |
58 |
69 |
--------------------------------------------------------------------------------
/src/lib/components/ui/hover-card/index.ts:
--------------------------------------------------------------------------------
1 | export { default as HoverCard } from './HoverCard.svelte';
2 | export { default as HoverCardTrigger } from './HoverCardTrigger.svelte';
3 | export { default as HoverCardContent } from './HoverCardContent.svelte';
4 | export type HoverCardState = 'closed' | 'open';
5 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input-otp/InputOTP.svelte:
--------------------------------------------------------------------------------
1 |
48 |
49 |
50 |
51 |
52 | select(get(activeIndex))}
54 | on:focusout={() => select(-1)}
55 | on:keydown={onKeydown}
56 | autocomplete="one-time-code"
57 | class="pointer-events-auto absolute inset-0 flex h-full w-full border-0 bg-transparent text-left font-mono text-[40px] tabular-nums leading-none tracking-tighter text-transparent caret-transparent opacity-0 shadow-none outline-none disabled:cursor-not-allowed"
58 | data-input-otp="true"
59 | inputmode="numeric"
60 | pattern={pattern.source}
61 | maxlength={maxLength}
62 | {value}
63 | {disabled}
64 | />
65 |
66 |
67 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input-otp/InputOTPGroup.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input-otp/InputOTPSeparator.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input-otp/InputOTPSlot.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 |
27 | {#if $selected && !$value}
28 |
29 | {/if}
30 | {$value}
31 |
32 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input-otp/index.ts:
--------------------------------------------------------------------------------
1 | export { default as InputOTP } from './InputOTP.svelte';
2 | export { default as InputOTPGroup } from './InputOTPGroup.svelte';
3 | export { default as InputOTPSlot } from './InputOTPSlot.svelte';
4 | export { default as InputOTPSeparator } from './InputOTPSeparator.svelte';
5 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input/Input.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
25 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Input } from './Input.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/label/Label.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/ui/label/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Label } from './Label.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/link/Link.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/lib/components/ui/link/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Link } from './Link.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/pagination/Pagination.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/pagination/PaginationContent.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/pagination/PaginationEllipsis.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 | More pages
12 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/ui/pagination/PaginationItem.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/pagination/PaginationLink.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/lib/components/ui/pagination/PaginationNext.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
18 | Next
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/lib/components/ui/pagination/PaginationPrevious.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
18 |
19 | Previous
20 |
21 |
--------------------------------------------------------------------------------
/src/lib/components/ui/pagination/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Pagination } from './Pagination.svelte';
2 | export { default as PaginationContent } from './PaginationContent.svelte';
3 | export { default as PaginationEllipsis } from './PaginationEllipsis.svelte';
4 | export { default as PaginationItem } from './PaginationItem.svelte';
5 | export { default as PaginationLink } from './PaginationLink.svelte';
6 | export { default as PaginationNext } from './PaginationNext.svelte';
7 | export { default as PaginationPrevious } from './PaginationPrevious.svelte';
8 |
--------------------------------------------------------------------------------
/src/lib/components/ui/popover/Popover.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/popover/PopoverContent.svelte:
--------------------------------------------------------------------------------
1 |
25 |
26 | (position = getPosition($popoverTrigger, popoverContent, $side, align, sideOffset, alignOffset))} />
27 |
28 | {#if $isOpen || !$finishedAnimation}
29 | isOpen.set(false), $popoverTrigger]}
33 | style="transform: translate({position?.x}px, {position?.y}px);"
34 | class="fixed left-0 top-0 z-50 min-w-max will-change-transform"
35 | >
36 |
49 |
50 |
51 |
52 | {/if}
53 |
--------------------------------------------------------------------------------
/src/lib/components/ui/popover/PopoverTrigger.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/popover/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Popover } from './Popover.svelte';
2 | export { default as PopoverTrigger } from './PopoverTrigger.svelte';
3 | export { default as PopoverContent } from './PopoverContent.svelte';
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/progress/Progress.svelte:
--------------------------------------------------------------------------------
1 |
17 |
18 |
31 |
--------------------------------------------------------------------------------
/src/lib/components/ui/progress/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Progress } from './Progress.svelte';
2 | export type ProgressState = 'indeterminate' | 'complete' | 'loading';
3 |
--------------------------------------------------------------------------------
/src/lib/components/ui/radio-group/RadioGroup.svelte:
--------------------------------------------------------------------------------
1 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/lib/components/ui/radio-group/RadioGroupItem.svelte:
--------------------------------------------------------------------------------
1 |
20 |
21 |
43 |
44 |
--------------------------------------------------------------------------------
/src/lib/components/ui/radio-group/index.ts:
--------------------------------------------------------------------------------
1 | export { default as RadioGroup } from './RadioGroup.svelte';
2 | export { default as RadioGroupItem } from './RadioGroupItem.svelte';
3 |
--------------------------------------------------------------------------------
/src/lib/components/ui/scroll-area/ScrollArea.svelte:
--------------------------------------------------------------------------------
1 |
50 |
51 | (isDragging = false)} on:touchmove={onTouchMove} on:touchend={() => (isDragging = false)} />
52 |
53 |
54 |
59 | {#if showScrollBar}
60 |
(isDragging = true)}
63 | on:touchstart={() => (isDragging = true)}
64 | data-orientation="vertical"
65 | data-state="visible"
66 | class="absolute right-0 top-0 flex h-full w-2.5 touch-none select-none border-l border-l-transparent p-[1px] transition-colors"
67 | >
68 |
69 |
70 | {/if}
71 |
72 |
73 |
83 |
--------------------------------------------------------------------------------
/src/lib/components/ui/scroll-area/index.ts:
--------------------------------------------------------------------------------
1 | export { default as ScrollArea } from './ScrollArea.svelte';
2 | export type ScrollAreaType = 'auto' | 'always' | 'scroll' | 'hover';
3 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/Select.svelte:
--------------------------------------------------------------------------------
1 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/SelectContent.svelte:
--------------------------------------------------------------------------------
1 |
30 |
31 | {#if $isOpen || !$finishedAnimation}
32 | isOpen.set(false), ['Escape']]}
36 | {dir}
37 | class="fixed left-0 top-0 z-50 min-w-max will-change-transform"
38 | style="transform: translate({position?.x}px, {position?.y}px);"
39 | >
40 |
54 |
55 |
56 |
scrollAmount.set(selectScrollView.scrollTop)}
59 | data-select-viewport
60 | role="presentation"
61 | class="relative max-h-[350px] w-full flex-1 overflow-auto p-1"
62 | style="min-width: {bounds?.width}px; height: {bounds?.height}px;"
63 | >
64 |
65 |
66 |
67 |
68 |
69 |
70 | {/if}
71 |
72 |
82 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/SelectGroup.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/SelectItem.svelte:
--------------------------------------------------------------------------------
1 |
22 |
23 |
39 |
40 | {#if $selected}
41 |
42 |
43 |
44 | {/if}
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/SelectLabel.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/SelectScrollDownButton.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 | {#if selectScrollView?.scrollHeight >= 350 && $scrollAmount < selectScrollView?.scrollHeight - 350}
11 |
12 |
13 |
14 | {/if}
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/SelectScrollUpButton.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 | {#if $scrollAmount > 0}
11 |
12 |
13 |
14 | {/if}
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/SelectTrigger.svelte:
--------------------------------------------------------------------------------
1 |
18 |
19 |
42 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/SelectValue.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 | {$valuePlaceholder || placeholder}
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Select } from './Select.svelte';
2 | export { default as SelectTrigger } from './SelectTrigger.svelte';
3 | export { default as SelectValue } from './SelectValue.svelte';
4 | export { default as SelectContent } from './SelectContent.svelte';
5 | export { default as SelectGroup } from './SelectGroup.svelte';
6 | export { default as SelectLabel } from './SelectLabel.svelte';
7 | export { default as SelectItem } from './SelectItem.svelte';
8 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/select.ts:
--------------------------------------------------------------------------------
1 | export function scrollOnHover(node: HTMLElement, [selectScrollView, direction]: [HTMLElement, 'up' | 'down']) {
2 | let scrollInterval: number;
3 |
4 | function startScrolling() {
5 | stopScrolling();
6 | scrollInterval = setInterval(() => {
7 | selectScrollView?.scrollBy({
8 | top: direction === 'down' ? 35 : -35,
9 | behavior: 'smooth'
10 | });
11 | }, 100);
12 | }
13 |
14 | function stopScrolling() {
15 | clearInterval(scrollInterval);
16 | }
17 |
18 | node.addEventListener('mouseenter', startScrolling);
19 | node.addEventListener('mouseleave', stopScrolling);
20 |
21 | return {
22 | destroy() {
23 | stopScrolling();
24 | node.removeEventListener('mouseenter', startScrolling);
25 | node.removeEventListener('mouseleave', stopScrolling);
26 | }
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/src/lib/components/ui/separator/Separator.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/lib/components/ui/separator/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Separator } from './Separator.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/Sheet.svelte:
--------------------------------------------------------------------------------
1 |
19 |
20 | isOpen.set(false), ['Escape']]} />
21 |
22 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/SheetClose.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/SheetContent.svelte:
--------------------------------------------------------------------------------
1 |
17 |
18 | {#if $isOpen || !$finishedAnimation}
19 |
26 | isOpen.set(false)]} use:focusTrap data-state={$isOpen ? 'open' : 'closed'} role="dialog" class={cn(sheetVariants({ side, className }))} tabindex="-1">
27 |
28 |
29 | {/if}
30 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/SheetDescription.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/SheetFooter.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/SheetHeader.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/SheetTitle.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/SheetTrigger.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Sheet } from './Sheet.svelte';
2 | export { default as SheetClose } from './SheetClose.svelte';
3 | export { default as SheetContent } from './SheetContent.svelte';
4 | export { default as SheetDescription } from './SheetDescription.svelte';
5 | export { default as SheetFooter } from './SheetFooter.svelte';
6 | export { default as SheetHeader } from './SheetHeader.svelte';
7 | export { default as SheetTitle } from './SheetTitle.svelte';
8 | export { default as SheetTrigger } from './SheetTrigger.svelte';
9 | export { sheetVariants } from './sheetVariants';
10 |
--------------------------------------------------------------------------------
/src/lib/components/ui/sheet/sheetVariants.ts:
--------------------------------------------------------------------------------
1 | import { cva } from 'class-variance-authority';
2 |
3 | export const sheetVariants = cva(
4 | 'pointer-events-auto fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
5 | {
6 | variants: {
7 | side: {
8 | top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
9 | bottom: 'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
10 | left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm',
11 | right: 'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm'
12 | }
13 | },
14 | defaultVariants: {
15 | side: 'right'
16 | }
17 | }
18 | );
19 |
--------------------------------------------------------------------------------
/src/lib/components/ui/skeleton/Skeleton.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/lib/components/ui/skeleton/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Skeleton } from './Skeleton.svelte';
2 | export type ProgressState = 'indeterminate' | 'complete' | 'loading';
3 |
--------------------------------------------------------------------------------
/src/lib/components/ui/slider/Slider.svelte:
--------------------------------------------------------------------------------
1 |
47 |
48 | (isDragging = false)} on:touchmove={onTouchMove} on:touchend={() => (isDragging = false)} />
49 |
50 | updateValues(100), ['End']]}
56 | use:keyDown={[isFocused, () => updateValues(0), ['Home']]}
57 | use:keyDown={[isFocused, () => updateValues(handleX + step), ['ArrowRight', 'ArrowUp'], 'never']}
58 | use:keyDown={[isFocused, () => updateValues(handleX - step), ['ArrowLeft', 'ArrowDown'], 'never']}
59 | use:keyDown={[isFocused, () => updateValues(handleX + step * 10), ['ArrowRight', 'ArrowUp'], 'always']}
60 | use:keyDown={[isFocused, () => updateValues(handleX - step * 10), ['ArrowLeft', 'ArrowDown'], 'always']}
61 | on:mousedown={(e) => {
62 | isDragging = true;
63 | onMouseMove(e);
64 | }}
65 | on:touchstart={(e) => {
66 | isDragging = true;
67 | onTouchMove(e);
68 | }}
69 | on:focusin={() => isFocused.set(true)}
70 | on:foucsout={() => isFocused.set(false)}
71 | class={cn('relative flex touch-none select-none items-center aria-disabled:pointer-events-none aria-disabled:opacity-50', className)}
72 | >
73 |
74 |
75 |
76 |
77 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/src/lib/components/ui/slider/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Slider } from './Slider.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/switch/Switch.svelte:
--------------------------------------------------------------------------------
1 |
21 |
22 |
41 |
42 |
--------------------------------------------------------------------------------
/src/lib/components/ui/switch/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Switch } from './Switch.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/Table.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/TableBody.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/TableCaption.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/TableCell.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 | |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/TableFooter.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 | tr]:last:border-b-0 border-t bg-muted/50 font-medium', className)}>
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/TableHead.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 | |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/TableHeader.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/TableRow.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/table/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Table } from './Table.svelte';
2 | export { default as TableBody } from './TableBody.svelte';
3 | export { default as TableCaption } from './TableCaption.svelte';
4 | export { default as TableCell } from './TableCell.svelte';
5 | export { default as TableFooter } from './TableFooter.svelte';
6 | export { default as TableHead } from './TableHead.svelte';
7 | export { default as TableHeader } from './TableHeader.svelte';
8 | export { default as TableRow } from './TableRow.svelte';
9 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tabs/Tabs.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tabs/TabsContent.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 | {#if value === $selectedValue}
14 |
22 |
23 |
24 | {/if}
25 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tabs/TabsList.svelte:
--------------------------------------------------------------------------------
1 |
29 |
30 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tabs/TabsTrigger.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 |
34 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tabs/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Tabs } from './Tabs.svelte';
2 | export { default as TabsContent } from './TabsContent.svelte';
3 | export { default as TabsList } from './TabsList.svelte';
4 | export { default as TabsTrigger } from './TabsTrigger.svelte';
5 | export type TabsActivationMode = 'automatic' | 'manual';
6 |
--------------------------------------------------------------------------------
/src/lib/components/ui/textarea/Textarea.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
22 |
--------------------------------------------------------------------------------
/src/lib/components/ui/textarea/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Textarea } from './Textarea.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/Toast.svelte:
--------------------------------------------------------------------------------
1 |
81 |
82 |
83 |
84 |
104 |
105 | {#if toast.title}
106 | {toast.title}
107 | {/if}
108 | {#if toast.description}
109 | {toast.description}
110 | {/if}
111 |
112 | {#if toast.actionLabel}
113 | {
115 | toast.open = false;
116 | toast.actionEvent?.();
117 | }}
118 | >
119 | {toast.actionLabel}
120 |
121 | {/if}
122 | (toast.open = false)} />
123 |
124 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/ToastAction.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/ToastClose.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/ToastDescription.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/ToastProvider.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 | {#if $toasts.length > 0}
15 |
16 | {/if}
17 |
18 |
19 | {#each $toasts as toast (toast.id)}
20 |
21 | {/each}
22 |
23 |
24 | {#if $toasts.length > 0}
25 |
26 | {/if}
27 |
28 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/ToastTitle.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/index.ts:
--------------------------------------------------------------------------------
1 | export { toast } from './toast';
2 | export { default as Toast } from './Toast.svelte';
3 | export { default as ToastProvider } from './ToastProvider.svelte';
4 | export { default as ToastClose } from './ToastClose.svelte';
5 | export { default as ToastAction } from './ToastAction.svelte';
6 | export { default as ToastTitle } from './ToastTitle.svelte';
7 | export { default as ToastDescription } from './ToastDescription.svelte';
8 | export { toastVariants } from './toastVariants';
9 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/toast.ts:
--------------------------------------------------------------------------------
1 | import { writable, type Writable } from 'svelte/store';
2 | import type { toastVariants } from './toastVariants';
3 | import type { VariantProps } from 'class-variance-authority';
4 |
5 | interface ToastSettings {
6 | variant?: VariantProps['variant'];
7 | title?: string;
8 | description?: string;
9 | actionLabel?: string;
10 | actionEvent?: VoidFunction;
11 | }
12 |
13 | export interface Toast extends ToastSettings {
14 | id: number;
15 | open: boolean;
16 | }
17 |
18 | export const toasts: Writable = writable([]);
19 |
20 | export function toast(settings: ToastSettings) {
21 | const newToast: Toast = {
22 | ...settings,
23 | variant: settings?.variant ?? 'default',
24 | id: Date.now(),
25 | open: true
26 | };
27 |
28 | toasts.update((currentToasts) => [...currentToasts, newToast]);
29 | }
30 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toast/toastVariants.ts:
--------------------------------------------------------------------------------
1 | import { cva } from 'class-variance-authority';
2 |
3 | export const toastVariants = cva(
4 | 'select-none touch-none group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full',
5 | {
6 | variants: {
7 | variant: {
8 | default: 'border bg-background text-foreground',
9 | destructive: 'destructive group border-destructive bg-destructive text-destructive-foreground',
10 | affirmative: 'affirmative group border-affirmative bg-affirmative text-affirmative-foreground'
11 | }
12 | },
13 | defaultVariants: {
14 | variant: 'default'
15 | }
16 | }
17 | );
18 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toggle-group/ToggleGroup.svelte:
--------------------------------------------------------------------------------
1 |
52 |
53 | focus($activeIndex)}
61 | >
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toggle-group/ToggleGroupItem.svelte:
--------------------------------------------------------------------------------
1 |
30 |
31 |
50 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toggle-group/index.ts:
--------------------------------------------------------------------------------
1 | export { default as ToggleGroup } from './ToggleGroup.svelte';
2 | export { default as ToggleGroupItem } from './ToggleGroupItem.svelte';
3 | export { toggleVariants } from './toggleVariants';
4 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toggle-group/toggleVariants.ts:
--------------------------------------------------------------------------------
1 | import { cva } from 'class-variance-authority';
2 |
3 | export const toggleVariants = cva(
4 | 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
5 | {
6 | variants: {
7 | variant: {
8 | default: 'bg-transparent',
9 | outline: 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground'
10 | },
11 | size: {
12 | default: 'h-10 px-3',
13 | sm: 'h-9 px-2.5',
14 | lg: 'h-11 px-5'
15 | }
16 | },
17 | defaultVariants: {
18 | variant: 'default',
19 | size: 'default'
20 | }
21 | }
22 | );
23 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toggle/Toggle.svelte:
--------------------------------------------------------------------------------
1 |
21 |
22 |
37 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toggle/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Toggle } from './Toggle.svelte';
2 |
--------------------------------------------------------------------------------
/src/lib/components/ui/toggle/toggleVariants.ts:
--------------------------------------------------------------------------------
1 | import { cva } from 'class-variance-authority';
2 |
3 | export const toggleVariants = cva(
4 | 'inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
5 | {
6 | variants: {
7 | variant: {
8 | default: 'bg-transparent',
9 | outline: 'border border-input bg-transparent hover:bg-accent hover:text-accent-foreground'
10 | },
11 | size: {
12 | default: 'h-10 px-3',
13 | sm: 'h-9 px-2.5',
14 | lg: 'h-11 px-5'
15 | }
16 | },
17 | defaultVariants: {
18 | variant: 'default',
19 | size: 'default'
20 | }
21 | }
22 | );
23 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tooltip/Tooltip.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 | $isOpen && $close?.()} />
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tooltip/TooltipContent.svelte:
--------------------------------------------------------------------------------
1 |
37 |
38 | {#if $isOpen || !$finishedAnimation}
39 |
56 | {/if}
57 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tooltip/TooltipProvider.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tooltip/TooltipTrigger.svelte:
--------------------------------------------------------------------------------
1 |
49 |
50 |
61 |
--------------------------------------------------------------------------------
/src/lib/components/ui/tooltip/index.ts:
--------------------------------------------------------------------------------
1 | export { default as TooltipProvider } from './TooltipProvider.svelte';
2 | export { default as Tooltip } from './Tooltip.svelte';
3 | export { default as TooltipTrigger } from './TooltipTrigger.svelte';
4 | export { default as TooltipContent } from './TooltipContent.svelte';
5 | export type TooltipState = 'closed' | 'delayed-open' | 'instant-open';
6 |
--------------------------------------------------------------------------------
/src/lib/helpers/state.ts:
--------------------------------------------------------------------------------
1 | import { get, writable, type Writable } from 'svelte/store';
2 | import type { InitProps, InitReturns, NavigationDirection, SimpleAction } from './types';
3 |
4 | export function createKeyboardNavigation(
5 | event: KeyboardEvent,
6 | action: SimpleAction,
7 | activeIndex: Writable,
8 | max: number,
9 | navDir: NavigationDirection = 'both',
10 | skip: boolean = false,
11 | tab: boolean = false,
12 | loop: boolean = true
13 | ): void {
14 | const { code, shiftKey } = event;
15 | const index = get(activeIndex);
16 | const nextDir = navDir == 'horizontal' ? 'Right' : 'Down';
17 | const prevDir = navDir == 'horizontal' ? 'Left' : 'Up';
18 |
19 | const nextTabPressed: boolean = code === 'Tab' && !shiftKey && tab;
20 | const previousTabPressed: boolean = code === 'Tab' && shiftKey && tab;
21 |
22 | if (nextTabPressed) activeIndex.set(Math.min(index + 1, max - 1));
23 | else if (previousTabPressed) activeIndex.set(Math.max(index - 1, 0));
24 |
25 | const nextPressed: boolean = navDir == 'both' ? code === 'ArrowRight' || code === 'ArrowDown' : code === `Arrow${nextDir}`;
26 | const previousPressed: boolean = navDir == 'both' ? code === 'ArrowLeft' || code === 'ArrowUp' : code === `Arrow${prevDir}`;
27 |
28 | if (nextPressed || previousPressed) {
29 | event.preventDefault();
30 | if (nextPressed) action(loop ? (index + 1) % max : Math.min(index + 1, max - 1));
31 | else if (previousPressed) action(loop ? (index - 1 + max) % max : Math.max(index - 1, 0));
32 | }
33 |
34 | const lastPressed: boolean = code === 'End';
35 | const firstPressed: boolean = code === 'Home';
36 |
37 | if (skip && (lastPressed || firstPressed)) {
38 | event.preventDefault();
39 | if (lastPressed) action(max - 1);
40 | else if (firstPressed) action(0);
41 | }
42 | }
43 |
44 | export function createState(defaultValue: string | string[] | undefined, select: SimpleAction, currentValue?: Writable): InitReturns {
45 | const values: Writable[] = [];
46 | const items: Writable[] = [];
47 | const triggers: HTMLElement[] = [];
48 | const activeIndex: Writable = writable(0);
49 |
50 | const init = (element: HTMLElement, [value, item, initResult]: InitProps) => {
51 | const writableValue: Writable = typeof value === 'string' ? writable(value) : value;
52 |
53 | values.push(writableValue);
54 | items.push(item);
55 | triggers.push(element);
56 |
57 | const index = items.length - 1;
58 | if (get(writableValue) === defaultValue) select(index);
59 | const toggleItem = () => toggle(index);
60 |
61 | initResult.set({ toggleItem, index, currentValue });
62 | };
63 |
64 | function toggle(index: number) {
65 | focus(index);
66 | select(index);
67 | }
68 |
69 | function focus(index: number) {
70 | triggers[index]?.focus();
71 | activeIndex.set(index);
72 | }
73 |
74 | function reset() {
75 | values.length = 0;
76 | items.length = 0;
77 | triggers.length = 0;
78 | }
79 |
80 | return { methods: { init, toggle, focus, reset }, variables: { values, items, activeIndex, triggers } };
81 | }
82 |
83 | export function createAnimationEnd(state: Writable): [Writable, (event: AnimationEvent) => void] {
84 | const finishedAnimation: Writable = writable(true);
85 |
86 | state.subscribe((newState) => {
87 | if (newState) finishedAnimation.set(false);
88 | });
89 |
90 | const onAnimationEnd = (event: AnimationEvent) => {
91 | if (event.animationName === 'exit') finishedAnimation.set(true);
92 | };
93 |
94 | return [finishedAnimation, onAnimationEnd];
95 | }
96 |
--------------------------------------------------------------------------------
/src/lib/helpers/types.ts:
--------------------------------------------------------------------------------
1 | import type { Writable } from 'svelte/store';
2 |
3 | export type SimpleAction = (index: number) => void;
4 |
5 | export type InitProps = [string | Writable, Writable, Writable];
6 |
7 | export type InitFunction = (node: HTMLElement, [value, item, initResult]: InitProps) => void;
8 |
9 | export interface InitResult {
10 | toggleItem: VoidFunction;
11 | index: number;
12 | currentValue?: Writable;
13 | }
14 |
15 | export interface InitReturns {
16 | methods: { init: InitFunction; toggle: SimpleAction; focus: SimpleAction; reset: VoidFunction };
17 | variables: { values: Writable[]; items: Writable[]; activeIndex: Writable; triggers: HTMLElement[] };
18 | }
19 |
20 | export type SelectionMode = 'single' | 'multiple';
21 |
22 | export type Direction = 'ltr' | 'rtl';
23 |
24 | export type Orientation = 'horizontal' | 'vertical';
25 |
26 | export type NavigationDirection = 'horizontal' | 'vertical' | 'both';
27 |
28 | export type Side = 'top' | 'right' | 'bottom' | 'left';
29 |
30 | export type Align = 'start' | 'center' | 'end';
31 |
32 | export type Position = { x: number; y: number };
33 |
34 | export type KeyCombination = 'always' | 'never' | 'ignore';
35 |
--------------------------------------------------------------------------------
/src/lib/helpers/utils.ts:
--------------------------------------------------------------------------------
1 | import type { ClassValue } from 'clsx';
2 | import { clsx } from 'clsx';
3 | import { twMerge } from 'tailwind-merge';
4 | import type { Align, Position, Side } from './types';
5 |
6 | export function cn(...inputs: ClassValue[]): string {
7 | return twMerge(clsx(inputs));
8 | }
9 |
10 | export function removeValue(source: T[], target: T): T[] {
11 | const index = source.indexOf(target);
12 | if (index !== -1) {
13 | source.splice(index, 1);
14 | }
15 | return source;
16 | }
17 |
18 | export function hasValue(source: undefined | T | T[], target: T): boolean {
19 | return (!Array.isArray(source) && source === target) || (Array.isArray(source) && source?.includes(target));
20 | }
21 |
22 | export function isHoveredOrFocused(mouseEvent: MouseEvent, element: HTMLElement): boolean {
23 | if (!mouseEvent || !element) return false;
24 |
25 | if (document?.activeElement === element || element?.contains(document?.activeElement)) {
26 | return true;
27 | }
28 |
29 | const rect = element.getBoundingClientRect();
30 | return mouseEvent.clientX >= rect.left && mouseEvent.clientX <= rect.right && mouseEvent.clientY >= rect.top && mouseEvent.clientY <= rect.bottom;
31 | }
32 |
33 | export function isNearElementSide(mouseEvent: MouseEvent | null, element: HTMLElement, side?: Side, sideoffset: number = 0): boolean {
34 | if (!mouseEvent || !element) return false;
35 |
36 | const rect = element.getBoundingClientRect();
37 | const { clientX: mouseX, clientY: mouseY } = mouseEvent;
38 |
39 | if (side === 'top') {
40 | const distance = Math.abs(mouseY - rect.bottom);
41 | return distance <= sideoffset + 5 && mouseX >= rect.left && mouseX <= rect.right;
42 | } else if (side === 'bottom') {
43 | const distance = Math.abs(mouseY - rect.top);
44 | return distance <= sideoffset + 5 && mouseX >= rect.left && mouseX <= rect.right;
45 | } else if (side === 'left') {
46 | const distance = Math.abs(mouseX - rect.right);
47 | return distance <= sideoffset + 5 && mouseY >= rect.top && mouseY <= rect.bottom;
48 | } else if (side === 'right') {
49 | const distance = Math.abs(mouseX - rect.left);
50 | return distance <= sideoffset + 5 && mouseY >= rect.top && mouseY <= rect.bottom;
51 | }
52 |
53 | return false;
54 | }
55 |
56 | export function getPosition(centerElement: HTMLElement, targetElement: HTMLElement, side: Side, align: Align, sideOffset: number = 0, alignOffest: number = 0): Position {
57 | const [center, target] = [centerElement?.getBoundingClientRect(), targetElement?.getBoundingClientRect()];
58 | let [x, y] = [0, 0];
59 |
60 | if (!center || !target) return { x: 0, y: 0 };
61 |
62 | switch (side) {
63 | case 'top':
64 | x = getAlign(center.x, center.width, target.width, align, alignOffest);
65 | y = center.y - target.height - 5 - sideOffset;
66 | break;
67 | case 'right':
68 | x = center.x + center.width + 5 + sideOffset;
69 | y = getAlign(center.y, center.height, target.height, align, alignOffest);
70 | break;
71 | case 'bottom':
72 | x = getAlign(center.x, center.width, target.width, align, alignOffest);
73 | y = center.y + center.height + 5 + sideOffset;
74 | break;
75 | case 'left':
76 | x = center.x - target.width - 5 - sideOffset;
77 | y = getAlign(center.y, center.height, target.height, align, alignOffest);
78 | break;
79 | }
80 |
81 | return { x, y };
82 | }
83 |
84 | function getAlign(centerStart: number, centerLength: number, targetLength: number, align: Align, alignOffest: number = 0): number {
85 | switch (align) {
86 | case 'start':
87 | return centerStart + alignOffest;
88 | case 'center':
89 | return centerStart + centerLength / 2 - targetLength / 2;
90 | case 'end':
91 | return centerStart - targetLength + centerLength - alignOffest;
92 | default:
93 | return 0;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/routes/+layout.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/routes/+page.svelte:
--------------------------------------------------------------------------------
1 |
48 |
49 |
50 |
51 |
52 | {#each examples as Example, i}
53 |
54 |
{names[i]}
55 |
56 |
57 |
58 |
59 |
60 | {/each}
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/styles/globals.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap');
2 |
3 | @tailwind base;
4 | @tailwind components;
5 | @tailwind utilities;
6 |
7 | @layer base {
8 | :root {
9 | --background: 0 0% 100%;
10 | --foreground: 240 10% 3.9%;
11 | --card: 0 0% 100%;
12 | --card-foreground: 240 10% 3.9%;
13 | --popover: 0 0% 100%;
14 | --popover-foreground: 240 10% 3.9%;
15 | --primary: 240 5.9% 10%;
16 | --primary-foreground: 0 0% 98%;
17 | --secondary: 240 4.8% 95.9%;
18 | --secondary-foreground: 240 5.9% 10%;
19 | --muted: 240 4.8% 95.9%;
20 | --muted-foreground: 240 3.8% 46.1%;
21 | --accent: 240 4.8% 95.9%;
22 | --accent-foreground: 240 5.9% 10%;
23 | --destructive: 0 72.22% 50.59%;
24 | --destructive-foreground: 0 0% 98%;
25 | --affirmative: 120 61% 34%;
26 | --affirmative-foreground: 210 40% 98%;
27 | --border: 240 5.9% 90%;
28 | --input: 240 5.9% 90%;
29 | --ring: 240 5% 64.9%;
30 | --radius: 0.5rem;
31 | --chart-1: 12 76% 61%;
32 | --chart-2: 173 58% 39%;
33 | --chart-3: 197 37% 24%;
34 | --chart-4: 43 74% 66%;
35 | --chart-5: 27 87% 67%;
36 | --sidebar-background: 0 0% 98%;
37 | --sidebar-foreground: 240 5.3% 26.1%;
38 | --sidebar-primary: 240 5.9% 10%;
39 | --sidebar-primary-foreground: 0 0% 98%;
40 | --sidebar-accent: 240 4.8% 95.9%;
41 | --sidebar-accent-foreground: 240 5.9% 10%;
42 | --sidebar-border: 220 13% 91%;
43 | --sidebar-ring: 240 5% 64.9%;
44 | }
45 |
46 | .dark {
47 | --background: 240 10% 3.9%;
48 | --foreground: 0 0% 98%;
49 | --card: 240 10% 3.9%;
50 | --card-foreground: 0 0% 98%;
51 | --popover: 240 10% 3.9%;
52 | --popover-foreground: 0 0% 98%;
53 | --primary: 0 0% 98%;
54 | --primary-foreground: 240 5.9% 10%;
55 | --secondary: 240 3.7% 15.9%;
56 | --secondary-foreground: 0 0% 98%;
57 | --muted: 240 3.7% 15.9%;
58 | --muted-foreground: 240 5% 64.9%;
59 | --accent: 240 3.7% 15.9%;
60 | --accent-foreground: 0 0% 98%;
61 | --destructive: 0 62.8% 30.6%;
62 | --destructive-foreground: 0 85.7% 97.3%;
63 | --affirmative: 120 50% 50%;
64 | --affirmative-foreground: 222.2 47.4% 1.2%;
65 | --border: 240 3.7% 15.9%;
66 | --input: 240 3.7% 15.9%;
67 | --ring: 240 4.9% 83.9%;
68 | --chart-1: 220 70% 50%;
69 | --chart-2: 160 60% 45%;
70 | --chart-3: 30 80% 55%;
71 | --chart-4: 280 65% 60%;
72 | --chart-5: 340 75% 55%;
73 | --sidebar-background: 240 5.9% 10%;
74 | --sidebar-foreground: 240 4.8% 95.9%;
75 | --sidebar-primary: 224.3 76.3% 48%;
76 | --sidebar-primary-foreground: 0 0% 100%;
77 | --sidebar-accent: 240 3.7% 15.9%;
78 | --sidebar-accent-foreground: 240 4.8% 95.9%;
79 | --sidebar-border: 240 3.7% 15.9%;
80 | --sidebar-ring: 240 4.9% 83.9%;
81 | }
82 | }
83 |
84 | @layer base {
85 | * {
86 | @apply border-border;
87 | }
88 | html {
89 | @apply scroll-smooth;
90 | }
91 | body {
92 | @apply bg-background text-foreground overscroll-none;
93 | /* font-feature-settings: "rlig" 1, "calt" 1; */
94 | font-synthesis-weight: none;
95 | text-rendering: optimizeLegibility;
96 | }
97 |
98 | @supports (font: -apple-system-body) and (-webkit-appearance: none) {
99 | [data-wrapper] {
100 | @apply min-[1800px]:border-t;
101 | }
102 | }
103 |
104 | /* Custom scrollbar styling. Thanks @pranathiperii. */
105 | ::-webkit-scrollbar {
106 | width: 5px;
107 | }
108 | ::-webkit-scrollbar-track {
109 | background: transparent;
110 | }
111 | ::-webkit-scrollbar-thumb {
112 | background: hsl(var(--border));
113 | border-radius: 5px;
114 | }
115 | * {
116 | scrollbar-width: thin;
117 | scrollbar-color: hsl(var(--border)) transparent;
118 | }
119 | }
120 |
121 | @layer utilities {
122 | .step {
123 | counter-increment: step;
124 | }
125 |
126 | .step:before {
127 | @apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background;
128 | @apply ml-[-50px] mt-[-4px];
129 | content: counter(step);
130 | }
131 |
132 | .chunk-container {
133 | @apply shadow-none;
134 | }
135 |
136 | .chunk-container::after {
137 | content: "";
138 | @apply absolute -inset-4 shadow-xl rounded-xl border;
139 | }
140 |
141 | /* Hide scrollbar for Chrome, Safari and Opera */
142 | .no-scrollbar::-webkit-scrollbar {
143 | display: none;
144 | }
145 | /* Hide scrollbar for IE, Edge and Firefox */
146 | .no-scrollbar {
147 | -ms-overflow-style: none; /* IE and Edge */
148 | scrollbar-width: none; /* Firefox */
149 | }
150 |
151 | .border-grid {
152 | @apply border-border/30 dark:border-border border-dashed;
153 | }
154 |
155 | .container-wrapper {
156 | @apply max-w-[1400px] min-[1800px]:max-w-screen-2xl min-[1400px]:border-x border-border/70 dark:border-border mx-auto w-full border-dashed;
157 | }
158 |
159 | .container {
160 | @apply px-4 xl:px-6 mx-auto max-w-screen-2xl;
161 | }
162 | }
--------------------------------------------------------------------------------
/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WailAbou/shadcn-svelte-nodep/3c06686a10278edd3d60b7fbd1a96c1ff93a1443/static/favicon.png
--------------------------------------------------------------------------------
/svelte.config.js:
--------------------------------------------------------------------------------
1 | import azure from 'svelte-adapter-azure-swa';
2 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | kit: {
7 | adapter: azure(),
8 | alias: {
9 | $components: 'src/lib/components',
10 | '$components/*': 'src/lib/components/*'
11 | }
12 | },
13 | preprocess: vitePreprocess()
14 | };
15 |
16 | export default config;
17 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | import { fontFamily } from 'tailwindcss/defaultTheme';
2 | import tailwindcssAnimate from 'tailwindcss-animate';
3 |
4 | /** @type {import('tailwindcss').Config} */
5 | const config = {
6 | darkMode: ['class'],
7 | content: ['./src/**/*.{html,js,svelte,ts}'],
8 | theme: {
9 | container: {
10 | center: true,
11 | padding: '2rem',
12 | screens: {
13 | '2xl': '1400px'
14 | }
15 | },
16 | extend: {
17 | colors: {
18 | border: 'hsl(var(--border))',
19 | input: 'hsl(var(--input))',
20 | ring: 'hsl(var(--ring))',
21 | background: 'hsl(var(--background))',
22 | foreground: 'hsl(var(--foreground))',
23 | primary: {
24 | DEFAULT: 'hsl(var(--primary))',
25 | foreground: 'hsl(var(--primary-foreground))'
26 | },
27 | secondary: {
28 | DEFAULT: 'hsl(var(--secondary))',
29 | foreground: 'hsl(var(--secondary-foreground))'
30 | },
31 | destructive: {
32 | DEFAULT: 'hsl(var(--destructive))',
33 | foreground: 'hsl(var(--destructive-foreground))'
34 | },
35 | affirmative: {
36 | DEFAULT: 'hsl(var(--affirmative))',
37 | foreground: 'hsl(var(--affirmative-foreground))'
38 | },
39 | muted: {
40 | DEFAULT: 'hsl(var(--muted))',
41 | foreground: 'hsl(var(--muted-foreground))'
42 | },
43 | accent: {
44 | DEFAULT: 'hsl(var(--accent))',
45 | foreground: 'hsl(var(--accent-foreground))'
46 | },
47 | popover: {
48 | DEFAULT: 'hsl(var(--popover))',
49 | foreground: 'hsl(var(--popover-foreground))'
50 | },
51 | card: {
52 | DEFAULT: 'hsl(var(--card))',
53 | foreground: 'hsl(var(--card-foreground))'
54 | }
55 | },
56 | borderRadius: {
57 | lg: `var(--radius)`,
58 | md: `calc(var(--radius) - 2px)`,
59 | sm: 'calc(var(--radius) - 4px)'
60 | },
61 | fontFamily: {
62 | sans: ['Inter', ...fontFamily.sans]
63 | },
64 | keyframes: {
65 | 'caret-blink': {
66 | '0%,70%,100%': { opacity: '1' },
67 | '20%,50%': { opacity: '0' }
68 | }
69 | },
70 | animation: {
71 | 'caret-blink': 'caret-blink 1.25s ease-out infinite'
72 | }
73 | }
74 | },
75 | plugins: [tailwindcssAnimate]
76 | };
77 |
78 | export default config;
79 |
--------------------------------------------------------------------------------
/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 | "baseUrl": ".",
13 | "paths": {
14 | "$lib": ["src/lib"],
15 | "$lib/*": ["src/lib/*"],
16 | "$components": ["src/lib/components"],
17 | "$components/*": ["src/lib/components/*"]
18 | }
19 | }
20 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
21 | //
22 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
23 | // from the referenced tsconfig.json - TypeScript does not merge them in
24 | }
25 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from '@sveltejs/kit/vite';
2 | import { defineConfig } from 'vite';
3 |
4 | export default defineConfig({
5 | plugins: [sveltekit()]
6 | });
7 |
--------------------------------------------------------------------------------