├── .editorconfig
├── .env.example
├── .github
└── dependabot.yml
├── .gitignore
├── .husky
└── pre-commit
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .typesafe-i18n.json
├── .vscode
├── extensions.json
└── settings.json
├── README.md
├── SECURITY.md
├── components.json
├── eslint.config.js
├── package.json
├── playwright.config.ts
├── pnpm-lock.yaml
├── postcss.config.cjs
├── src
├── ambient.d.ts
├── app.d.ts
├── app.html
├── app.postcss
├── hooks.server.ts
├── index.test.ts
├── lib
│ ├── assets
│ │ ├── animations
│ │ │ └── user-hi.json
│ │ └── images
│ │ │ └── landing-page.png
│ ├── components
│ │ ├── common
│ │ │ ├── Analytics.svelte
│ │ │ ├── AppBackground.svelte
│ │ │ ├── LottieAnimation.svelte
│ │ │ ├── SEO.svelte
│ │ │ └── ThemeToggle.svelte
│ │ ├── icons
│ │ │ ├── google.svelte
│ │ │ └── index.ts
│ │ └── ui
│ │ │ ├── button
│ │ │ ├── button.svelte
│ │ │ └── index.ts
│ │ │ ├── checkbox
│ │ │ ├── checkbox.svelte
│ │ │ └── index.ts
│ │ │ ├── dropdown-menu
│ │ │ ├── dropdown-menu-checkbox-item.svelte
│ │ │ ├── dropdown-menu-content.svelte
│ │ │ ├── dropdown-menu-item.svelte
│ │ │ ├── dropdown-menu-label.svelte
│ │ │ ├── dropdown-menu-radio-group.svelte
│ │ │ ├── dropdown-menu-radio-item.svelte
│ │ │ ├── dropdown-menu-separator.svelte
│ │ │ ├── dropdown-menu-shortcut.svelte
│ │ │ ├── dropdown-menu-sub-content.svelte
│ │ │ ├── dropdown-menu-sub-trigger.svelte
│ │ │ └── index.ts
│ │ │ ├── form
│ │ │ ├── form-button.svelte
│ │ │ ├── form-description.svelte
│ │ │ ├── form-element-field.svelte
│ │ │ ├── form-error.svelte
│ │ │ ├── form-field-errors.svelte
│ │ │ ├── form-field.svelte
│ │ │ ├── form-fieldset.svelte
│ │ │ ├── form-label.svelte
│ │ │ ├── form-legend.svelte
│ │ │ └── index.ts
│ │ │ ├── heading
│ │ │ ├── heading.svelte
│ │ │ └── index.ts
│ │ │ ├── input
│ │ │ ├── index.ts
│ │ │ └── input.svelte
│ │ │ ├── label
│ │ │ ├── index.ts
│ │ │ └── label.svelte
│ │ │ ├── popover
│ │ │ ├── index.ts
│ │ │ └── popover-content.svelte
│ │ │ ├── radio-group
│ │ │ ├── index.ts
│ │ │ ├── radio-group-item.svelte
│ │ │ └── radio-group.svelte
│ │ │ ├── select
│ │ │ ├── index.ts
│ │ │ ├── select-content.svelte
│ │ │ ├── select-item.svelte
│ │ │ ├── select-label.svelte
│ │ │ ├── select-separator.svelte
│ │ │ ├── select-trigger.svelte
│ │ │ └── select.svelte
│ │ │ ├── switch
│ │ │ ├── index.ts
│ │ │ └── switch.svelte
│ │ │ └── textarea
│ │ │ ├── index.ts
│ │ │ └── textarea.svelte
│ ├── constants
│ │ └── index.ts
│ ├── helpers
│ │ ├── analytics.ts
│ │ ├── debounce.ts
│ │ ├── document-scroll.ts
│ │ ├── formatCurrency.ts
│ │ ├── generateUniqueId.ts
│ │ ├── index.ts
│ │ ├── localstorage.ts
│ │ ├── observer.ts
│ │ ├── responsive.ts
│ │ └── validations.ts
│ ├── i18n
│ │ ├── bn
│ │ │ └── index.ts
│ │ ├── en
│ │ │ └── index.ts
│ │ ├── formatters.ts
│ │ ├── i18n-svelte.ts
│ │ ├── i18n-types.ts
│ │ ├── i18n-util.async.ts
│ │ ├── i18n-util.sync.ts
│ │ └── i18n-util.ts
│ ├── services
│ │ └── error.service.ts
│ ├── types
│ │ └── index.ts
│ └── utils.ts
└── routes
│ ├── (auth)
│ └── login
│ │ ├── +page.server.ts
│ │ ├── +page.svelte
│ │ ├── components
│ │ └── login-form.svelte
│ │ ├── helpers
│ │ └── index.ts
│ │ └── schema.ts
│ ├── +error.svelte
│ ├── +layout.server.ts
│ ├── +layout.svelte
│ ├── +layout.ts
│ ├── +page.svelte
│ └── components
│ ├── footer
│ └── Footer.svelte
│ └── navbar
│ └── Navbar.svelte
├── static
├── android-icon-144x144.png
├── android-icon-192x192.png
├── android-icon-36x36.png
├── android-icon-48x48.png
├── android-icon-72x72.png
├── android-icon-96x96.png
├── apple-icon-114x114.png
├── apple-icon-120x120.png
├── apple-icon-144x144.png
├── apple-icon-152x152.png
├── apple-icon-180x180.png
├── apple-icon-57x57.png
├── apple-icon-60x60.png
├── apple-icon-72x72.png
├── apple-icon-76x76.png
├── apple-icon-precomposed.png
├── apple-icon.png
├── apple-touch-icon-120x120-precomposed.png
├── apple-touch-icon-120x120.png
├── apple-touch-icon-precomposed.png
├── apple-touch-icon.png
├── browserconfig.xml
├── company-logo.jpg
├── company-logo.svg
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon-96x96.png
├── favicon.ico
├── fonts
│ ├── poppins-bold-webfont.woff
│ ├── poppins-bold-webfont.woff2
│ ├── poppins-bolditalic-webfont.woff
│ ├── poppins-bolditalic-webfont.woff2
│ ├── poppins-extrabold-webfont.woff
│ ├── poppins-extrabold-webfont.woff2
│ ├── poppins-italic-webfont.woff
│ ├── poppins-italic-webfont.woff2
│ ├── poppins-light-webfont.woff
│ ├── poppins-light-webfont.woff2
│ ├── poppins-medium-webfont.woff
│ ├── poppins-medium-webfont.woff2
│ ├── poppins-regular-webfont.woff
│ ├── poppins-regular-webfont.woff2
│ ├── poppins-semibold-webfont.woff
│ ├── poppins-semibold-webfont.woff2
│ ├── poppins-semibolditalic-webfont.woff
│ ├── poppins-semibolditalic-webfont.woff2
│ ├── poppins-thin-webfont.woff
│ └── poppins-thin-webfont.woff2
├── manifest.json
├── ms-icon-144x144.png
├── ms-icon-150x150.png
├── ms-icon-310x310.png
└── ms-icon-70x70.png
├── svelte.config.js
├── tailwind.config.cjs
├── tests
└── example.spec.ts
├── tsconfig.json
└── vite.config.ts
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | indent_style = tab
7 | indent_size = 2
8 | charset = utf-8
9 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | PUBLIC_LANDING_PAGE=http://localhost:5173
2 | PUBLIC_GOOGLE_TAG_MEASUREMENT_ID=X-XXXXXXXXXX
3 |
4 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: 'npm'
9 | directory: '/'
10 | schedule:
11 | interval: 'weekly'
12 | commit-message:
13 | prefix: 'npm'
14 | groups:
15 | all:
16 | patterns:
17 | - '*'
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.local
8 | !.env.example
9 | vite.config.js.timestamp-*
10 | vite.config.ts.timestamp-*
11 | .unlighthouse
12 | .vercel
13 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npx --no-install lint-staged
5 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 | shamefully-hoist=true
3 | auto-install-peers=true
4 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /.vercel
6 | /package
7 | .env
8 | .env.*
9 | !.env.example
10 | !*.cjs
11 | src/lib/i18n/*.ts
12 | docker-data/
13 | animations/
14 |
15 | # Ignore files for PNPM, NPM and YARN
16 | pnpm-lock.yaml
17 | package-lock.json
18 | yarn.lock
19 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": true,
3 | "singleQuote": true,
4 | "trailingComma": "none",
5 | "printWidth": 100,
6 | "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
7 | "overrides": [
8 | {
9 | "files": "*.svelte",
10 | "options": {
11 | "parser": "svelte"
12 | }
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/.typesafe-i18n.json:
--------------------------------------------------------------------------------
1 | {
2 | "adapter": "svelte",
3 | "outputPath": "./src/lib/i18n/",
4 | "$schema": "https://unpkg.com/typesafe-i18n@5.26.2/schema/typesafe-i18n.json"
5 | }
6 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "esbenp.prettier-vscode",
5 | "svelte.svelte-vscode",
6 | "bradlc.vscode-tailwindcss"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.defaultFormatter": "esbenp.prettier-vscode",
4 | "[svelte]": {
5 | "editor.defaultFormatter": "esbenp.prettier-vscode"
6 | },
7 | "prettier.documentSelectors": ["src/**/*.svelte"],
8 | "eslint.validate": ["javascript", "typescript", "svelte"],
9 | "files.associations": {
10 | "*.css": "tailwindcss"
11 | },
12 | "editor.quickSuggestions": {
13 | "strings": true
14 | },
15 | "tailwindCSS.files.exclude": [
16 | "**/.git/**",
17 | "**/node_modules/**",
18 | "**/.hg/**",
19 | "**/.svn/**",
20 | ".husky/**",
21 | ".svelte-kit/**",
22 | ".vscode/**",
23 | "static/**",
24 | "tests/**",
25 | "src/lib/i18n/**"
26 | ],
27 | "cSpell.words": ["Prefs"]
28 | }
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SvelteKit Stackter
2 |
3 | Discover this incredible SvelteKit production-ready starter template featuring Tailwind CSS, the shadcn-svelte UI library, Superform + Formsnap, type-safe i18n, SEO, Lottie animations, an Image component, and much more. With this template, you can bypass the setup hassle and concentrate on transforming your dreams into reality.
4 |
5 | ## Features
6 |
7 | - [Tailwind CSS](https://tailwindcss.com/)
8 | - [shadcn-svelte](https://www.shadcn-svelte.com/) UI library
9 | - [Superforms](https://superforms.rocks/) for auto form validation and SSR submission
10 | - [Formsnap](https://www.formsnap.dev/) for auto form building
11 | - [lottie-web](https://www.npmjs.com/package/lottie-web) to show awesome animations
12 | - [Lucide Icons](https://lucide.dev/) an awesome icon pack with ease setup
13 | - [Typesafe i18n](https://github.com/ivanhofer/typesafe-i18n) for better i18n experience with SSR support
14 | - [Taze](https://www.npmjs.com/package/taze) to update dependencies with one command
15 | - [Husky](https://www.npmjs.com/package/husky) + (lint-staged) to improve commits & formatting
16 | - [Fingerprintjs](https://www.npmjs.com/package/@fingerprintjs/fingerprintjs) to generate browser hash
17 | - [React equivalent Image component](https://github.com/zerodevx/svelte-img)
18 | - [Fontaine](https://www.npmjs.com/package/fontaine) for better font fallback
19 | - Google Tag support
20 | - Eslint & Prettier for better code formatting
21 | - Tailwind CSS auto class sorting with prettier
22 | - pnpm by default
23 | - of course VITE and Typescript
24 |
25 | ## Developing
26 |
27 | Rename `.env-example` to `.env` or `.env.local`
28 |
29 | Install dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
30 |
31 | ```bash
32 | npm run dev
33 |
34 | # or start the server and open the app in a new browser tab
35 | npm run dev -- --open
36 | ```
37 |
38 | ## Building
39 |
40 | To create a production version of your app:
41 |
42 | ```bash
43 | npm run build
44 | ```
45 |
46 | You can preview the production build with `npm run preview`.
47 |
48 | > To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
49 |
50 | ## Vercel deployment
51 |
52 | [Check here](https://vercel.com/guides/how-can-i-use-bitbucket-pipelines-with-vercel#configuring-bitbucket-pipelines-for-vercel)
53 |
54 | [Twitter](https://twitter.com/shamscorner)
55 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://shadcn-svelte.com/schema.json",
3 | "style": "default",
4 | "tailwind": {
5 | "config": "tailwind.config.js",
6 | "css": "src/app.css",
7 | "baseColor": "slate"
8 | },
9 | "aliases": {
10 | "components": "$lib/components",
11 | "utils": "$lib/utils"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js';
2 | import prettier from 'eslint-config-prettier';
3 | import simpleImportSort from 'eslint-plugin-simple-import-sort';
4 | import svelte from 'eslint-plugin-svelte';
5 | import globals from 'globals';
6 | import ts from 'typescript-eslint';
7 |
8 | /** @type {import('eslint').Linter.FlatConfig[]} */
9 | export default [
10 | js.configs.recommended,
11 | ...ts.configs.recommended,
12 | ...svelte.configs['flat/recommended'],
13 | prettier,
14 | ...svelte.configs['flat/prettier'],
15 | {
16 | languageOptions: {
17 | globals: {
18 | ...globals.browser,
19 | ...globals.node
20 | }
21 | }
22 | },
23 | {
24 | files: ['**/*.svelte'],
25 | languageOptions: {
26 | parserOptions: {
27 | parser: ts.parser
28 | }
29 | }
30 | },
31 | {
32 | ignores: [
33 | 'build/',
34 | '.svelte-kit/',
35 | '.vercel/',
36 | 'test-results/',
37 | 'dist/',
38 | '.DS_Store',
39 | 'src/lib/components/common/Analytics.svelte',
40 | 'src/lib/i18n/'
41 | ]
42 | },
43 | {
44 | rules: {
45 | '@typescript-eslint/no-explicit-any': 'off',
46 | 'svelte/no-at-html-tags': 'off',
47 | '@typescript-eslint/no-unused-vars': 'off'
48 | }
49 | },
50 | {
51 | plugins: {
52 | 'simple-import-sort': simpleImportSort
53 | },
54 | rules: {
55 | 'simple-import-sort/imports': [
56 | 'error',
57 | {
58 | groups: [
59 | // Packages `svelte` related packages come first.
60 | ['^svelte', '^@?\\w'],
61 | // Packages `sveltekit` related packages come first.
62 | ['^sveltekit', '^@?\\w'],
63 | // Packages that starts with $../.. come first.
64 | ['^\\$', '^@?\\w'],
65 | // Side effect imports.
66 | ['^\\u0000'],
67 | // Parent imports. Put `..` last.
68 | ['^\\.\\.(?!/?$)', '^\\.\\./?$'],
69 | // Other relative imports. Put same-folder imports and `.` last.
70 | ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
71 | // Style imports.
72 | ['^.+\\.?(css)$']
73 | ]
74 | }
75 | ],
76 | 'simple-import-sort/exports': 'error'
77 | }
78 | }
79 | ];
80 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sveltekit-stackter",
3 | "version": "1.0.0",
4 | "private": true,
5 | "author": {
6 | "name": "Shamim Hossain",
7 | "email": "hossains159@gmail.com"
8 | },
9 | "type": "module",
10 | "scripts": {
11 | "dev": "npm-run-all --parallel vite:dev typesafe-i18n",
12 | "vite:dev": "vite dev --host",
13 | "build": "vite build",
14 | "start": "node build",
15 | "preview": "vite preview",
16 | "test": "npm run test:integration && npm run test:unit",
17 | "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
18 | "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
19 | "lint": "prettier --check . && eslint .",
20 | "format": "prettier --write . && eslint . --fix",
21 | "prepare": "husky install && svelte-kit sync",
22 | "configure-husky": "npx husky install && npx husky add .husky/pre-commit \"npx --no-install lint-staged\"",
23 | "typesafe-i18n": "typesafe-i18n",
24 | "test:integration": "playwright test",
25 | "test:unit": "vitest",
26 | "update-deps": "taze major -I"
27 | },
28 | "devDependencies": {
29 | "@csstools/postcss-media-minmax": "^2.0.1",
30 | "@fingerprintjs/fingerprintjs": "^4.5.0",
31 | "@playwright/test": "^1.47.2",
32 | "@sveltejs/adapter-auto": "^3.2.5",
33 | "@sveltejs/adapter-vercel": "^5.4.4",
34 | "@sveltejs/kit": "^2.5.28",
35 | "@sveltejs/vite-plugin-svelte": "^3.1.2",
36 | "@tailwindcss/forms": "^0.5.9",
37 | "@tailwindcss/typography": "^0.5.15",
38 | "@types/eslint": "^9.6.1",
39 | "@types/gtag.js": "^0.0.20",
40 | "@typescript-eslint/eslint-plugin": "^8.7.0",
41 | "@typescript-eslint/parser": "^8.7.0",
42 | "@zerodevx/svelte-img": "^2.1.1",
43 | "autoprefixer": "^10.4.20",
44 | "eslint": "^9.11.1",
45 | "eslint-config-prettier": "^9.1.0",
46 | "eslint-plugin-simple-import-sort": "^12.1.1",
47 | "eslint-plugin-svelte": "^2.44.0",
48 | "fontaine": "^0.5.0",
49 | "globals": "^15.9.0",
50 | "husky": "^9.1.6",
51 | "lint-staged": "^15.2.10",
52 | "lottie-web": "^5.12.2",
53 | "npm-run-all": "^4.1.5",
54 | "postcss": "^8.4.47",
55 | "prettier": "^3.3.3",
56 | "prettier-plugin-svelte": "^3.2.6",
57 | "prettier-plugin-tailwindcss": "^0.6.6",
58 | "svelte": "^4.2.19",
59 | "svelte-check": "^4.0.2",
60 | "sveltekit-superforms": "^2.19.0",
61 | "tailwindcss": "^3.4.13",
62 | "taze": "^0.16.9",
63 | "tslib": "^2.7.0",
64 | "typesafe-i18n": "^5.26.2",
65 | "typescript": "^5.6.2",
66 | "typescript-eslint": "^8.7.0",
67 | "vite": "^5.4.7",
68 | "vitest": "^2.1.1",
69 | "zod": "^3.23.8"
70 | },
71 | "lint-staged": {
72 | "**/*.{js,ts,jsx,json,svelte}": [
73 | "eslint . --fix",
74 | "prettier --write ."
75 | ]
76 | },
77 | "husky": {
78 | "hooks": {
79 | "pre-commit": "lint-staged"
80 | }
81 | },
82 | "dependencies": {
83 | "@builder.io/partytown": "^0.10.2",
84 | "bits-ui": "^0.21.15",
85 | "clsx": "^2.1.1",
86 | "dotenv": "^16.4.5",
87 | "formsnap": "^1.0.1",
88 | "lucide-svelte": "^0.445.0",
89 | "mode-watcher": "^0.4.1",
90 | "sharp": "^0.33.5",
91 | "tailwind-merge": "^2.5.2",
92 | "tailwind-variants": "^0.2.1"
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/playwright.config.ts:
--------------------------------------------------------------------------------
1 | import type { PlaywrightTestConfig } from '@playwright/test';
2 |
3 | const config: PlaywrightTestConfig = {
4 | webServer: {
5 | command: 'npm run build && npm run preview',
6 | port: 4173
7 | },
8 | testDir: 'tests'
9 | };
10 |
11 | export default config;
12 |
--------------------------------------------------------------------------------
/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | 'tailwindcss/nesting': {},
4 | '@csstools/postcss-media-minmax': {},
5 | tailwindcss: {},
6 | autoprefixer: {}
7 | }
8 | };
9 |
--------------------------------------------------------------------------------
/src/ambient.d.ts:
--------------------------------------------------------------------------------
1 | // Squelch warnings of image imports from your assets dir
2 | declare module '$lib/assets/*' {
3 | let meta;
4 | export default meta;
5 | }
6 |
--------------------------------------------------------------------------------
/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 | locale: import('$lib/i18n/i18n-types.ts').Locales;
8 | }
9 | // interface PageData {}
10 | // interface Platform {}
11 | }
12 | }
13 |
14 | export {};
15 |
--------------------------------------------------------------------------------
/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | %sveltekit.head%
9 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
54 |
55 | %sveltekit.body%
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/app.postcss:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | :root {
7 | --background: 0 0% 100%;
8 | --foreground: 240 10% 3.9%;
9 |
10 | --muted: 240 4.8% 95.9%;
11 | --muted-foreground: 240 3.8% 46.1%;
12 |
13 | --popover: 0 0% 100%;
14 | --popover-foreground: 240 10% 3.9%;
15 |
16 | --card: 0 0% 100%;
17 | --card-foreground: 240 10% 3.9%;
18 |
19 | --border: 240 5.9% 90%;
20 | --input: 240 5.9% 90%;
21 |
22 | --primary: 240 5.9% 10%;
23 | --primary-foreground: 0 0% 98%;
24 |
25 | --secondary: 240 4.8% 95.9%;
26 | --secondary-foreground: 240 5.9% 10%;
27 |
28 | --accent: 240 4.8% 95.9%;
29 | --accent-foreground: 240 5.9% 10%;
30 |
31 | --destructive: 0 84.2% 60.2%;
32 | --destructive-foreground: 0 0% 98%;
33 |
34 | --ring: 240 5% 64.9%;
35 |
36 | --radius: 0.5rem;
37 | }
38 |
39 | .dark {
40 | --background: 240 10% 3.9%;
41 | --foreground: 0 0% 98%;
42 |
43 | --muted: 240 3.7% 15.9%;
44 | --muted-foreground: 240 5% 64.9%;
45 |
46 | --popover: 240 10% 3.9%;
47 | --popover-foreground: 0 0% 98%;
48 |
49 | --card: 240 10% 3.9%;
50 | --card-foreground: 0 0% 98%;
51 |
52 | --border: 240 3.7% 15.9%;
53 | --input: 240 3.7% 15.9%;
54 |
55 | --primary: 0 0% 98%;
56 | --primary-foreground: 240 5.9% 10%;
57 |
58 | --secondary: 240 3.7% 15.9%;
59 | --secondary-foreground: 0 0% 98%;
60 |
61 | --accent: 240 3.7% 15.9%;
62 | --accent-foreground: 0 0% 98%;
63 |
64 | --destructive: 0 62.8% 30.6%;
65 | --destructive-foreground: 0 85.7% 97.3%;
66 |
67 | --ring: 240 3.7% 15.9%;
68 | }
69 | }
70 |
71 | @layer base {
72 | * {
73 | @apply border-border;
74 | }
75 | body {
76 | @apply bg-background text-foreground selection:bg-primary selection:text-primary-foreground;
77 | font-feature-settings:
78 | 'rlig' 1,
79 | 'calt' 1;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/hooks.server.ts:
--------------------------------------------------------------------------------
1 | import type { Handle } from '@sveltejs/kit';
2 | import { redirect } from '@sveltejs/kit';
3 | import { sequence } from '@sveltejs/kit/hooks';
4 | import { initAcceptLanguageHeaderDetector } from 'typesafe-i18n/detectors';
5 |
6 | import { detectLocale } from '$lib/i18n/i18n-util.js';
7 |
8 | async function urlRewrite({ event, resolve }) {
9 | if (event.url.pathname.match(/[A-Z]/)) {
10 | throw redirect(302, event.url.pathname.toLowerCase());
11 | }
12 |
13 | return resolve(event);
14 | }
15 |
16 | async function i18n({ event, resolve }) {
17 | const acceptLanguageHeaderDetector = initAcceptLanguageHeaderDetector(event.request);
18 | const locale = detectLocale(acceptLanguageHeaderDetector);
19 | event.locals.locale = locale;
20 |
21 | return resolve(event, {
22 | transformPageChunk: ({ html }) => html.replace('%lang%', locale)
23 | });
24 | }
25 |
26 | export const handle = sequence(urlRewrite, i18n) satisfies Handle;
27 |
--------------------------------------------------------------------------------
/src/index.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from 'vitest';
2 |
3 | describe('sum test', () => {
4 | it('adds 1 + 2 to equal 3', () => {
5 | expect(1 + 2).toBe(3);
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/src/lib/assets/animations/user-hi.json:
--------------------------------------------------------------------------------
1 | {"v":"5.6.9","fr":29.9700012207031,"ip":0,"op":60.0000024438501,"w":750,"h":750,"nm":"hello","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Кривые Слой 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[374.5,375.5,0],"ix":2},"a":{"a":0,"k":[375.25,375.25,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[165.686,0],[0,165.686],[-165.686,0],[0,-165.686]],"o":[[-165.686,0],[0,-165.686],[165.686,0],[0,165.686]],"v":[[-0.25,300.25],[-300.25,0.25],[-0.25,-299.75],[299.75,0.25]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-375.25,375.25],[374.75,375.25],[374.75,-374.75],[-375.25,-374.75]],"c":true},"ix":2},"nm":"Контур 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Объединить контуры 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[375.5,375],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Кривые Слой 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[-162]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":35,"s":[18]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":49,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":59,"s":[-58]},{"t":60.0000024438501,"s":[-22]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[166.312,917.136,0],"to":[4.418,-27.768,0],"ti":[-11.025,69.302,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[110.446,704.869,0],"to":[12.268,-77.115,0],"ti":[-12.01,28.89,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[222.312,565.136,0],"to":[3.083,-7.417,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":49,"s":[222.312,565.136,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":59,"s":[19.585,677.5,0],"to":[0,0,0],"ti":[0,0,0]},{"t":60.0000024438501,"s":[109.312,704.136,0]}],"ix":2},"a":{"a":0,"k":[76.853,146.762,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0.454],[0,0.454],[-0.453,0.454],[-0.453,0.453],[-0.454,0.453],[-0.907,0],[0,0],[-0.454,-0.453],[-0.453,-1.361],[0.453,-1.359],[1.36,0],[0.454,0.454],[0.907,0.454],[0.454,0.453],[0,0]],"o":[[-0.454,-0.454],[-0.454,-0.908],[0.454,-0.454],[0.454,-0.453],[0.907,-0.454],[0,0],[0.453,0],[1.36,0.907],[0.454,1.361],[-0.908,1.362],[-0.454,0],[-0.907,0],[-0.454,0],[0,0],[-1.36,-0.451]],"v":[[25.402,32.432],[24.494,31.071],[24.947,28.803],[26.309,26.989],[27.669,26.082],[29.938,25.628],[31.753,25.628],[33.566,26.535],[36.287,29.71],[35.835,33.791],[32.66,36.06],[31.298,36.06],[29.031,35.606],[27.669,34.699],[27.215,34.244]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-0.454,-0.908],[-3.629,-4.083],[-3.629,-3.63],[-1.815,-1.815],[-2.721,0],[-0.907,1.815],[0.453,2.268],[2.268,10.886],[1.36,5.443],[-1.361,1.361],[-0.454,-0.907],[0,-2.722],[-0.907,-2.722],[-2.268,-5.443],[-0.907,-3.175],[-0.907,-2.268],[-2.268,0],[0,2.723],[0.453,2.722],[0,2.721],[0.907,5.442],[0.907,5.443],[0,0],[-1.361,1.361],[-0.908,-1.361],[-0.453,-2.722],[-1.815,-5.897],[-0.907,-11.34],[-2.268,-0.907],[-0.907,2.267],[0,2.721],[0,2.72],[-0.907,11.34],[-0.908,1.361],[-0.907,-1.361],[-0.454,-2.723],[-0.453,-2.268],[0,-10.432],[-3.629,-9.979],[-0.907,-1.361],[0.454,0.454],[-2.721,-1.814],[-4.989,3.175],[-2.722,5.443],[-4.99,3.175],[-1.814,-1.815],[1.361,-1.814],[2.722,-4.536],[1.361,-2.721],[0.907,-3.175],[2.268,-2.722],[2.268,-2.722],[4.536,-5.443],[-0.454,-3.175],[0,0],[3.628,-0.908],[9.072,-1.361],[0,0],[3.175,4.536],[2.268,4.989],[2.268,4.989],[3.175,4.989],[3.629,4.082],[2.721,4.082],[2.722,4.989],[0.453,1.361],[-0.453,0.907]],"o":[[3.175,4.081],[2.722,4.082],[1.814,1.814],[1.814,1.815],[2.268,0],[0.453,-2.268],[-1.815,-11.34],[-1.36,-5.443],[-0.454,-1.361],[1.361,-0.907],[1.361,1.813],[0.454,2.722],[1.361,5.443],[0.907,2.722],[0.453,2.722],[0.907,1.814],[2.268,-0.454],[0,-2.721],[0,-3.174],[-0.454,-5.443],[-0.453,-5.443],[0,0],[-0.453,-2.268],[1.361,-0.907],[1.361,2.268],[1.361,5.443],[2.268,10.886],[0,2.268],[2.268,0.454],[0.454,-2.722],[0,-2.721],[0.908,-11.34],[0,-1.814],[1.36,-1.361],[1.361,2.268],[0.454,2.268],[0.454,10.433],[0,10.886],[0.454,1.814],[-0.453,0],[-2.722,-1.814],[4.99,2.721],[5.444,-3.175],[3.629,-4.99],[1.814,-0.907],[1.815,1.813],[-3.629,4.99],[-1.815,2.268],[-1.361,2.721],[-0.907,2.722],[-2.267,2.722],[-4.082,5.443],[-2.721,2.268],[0,0],[-3.629,0.907],[-8.619,2.268],[0,0],[-1.814,-4.536],[-2.721,-4.536],[-2.268,-4.991],[-2.267,-4.99],[-2.268,-4.99],[-3.174,-3.629],[-2.722,-4.99],[-0.454,-1.361],[-0.454,-0.907],[3.176,-3.631]],"v":[[-68.947,-85.957],[-59.876,-73.256],[-50.35,-61.916],[-44.906,-56.926],[-38.557,-53.297],[-33.566,-56.926],[-33.566,-64.184],[-40.824,-97.75],[-44.452,-114.533],[-43.999,-120.43],[-40.37,-119.523],[-38.103,-112.719],[-36.288,-104.554],[-31.299,-87.771],[-29.031,-79.153],[-26.762,-71.895],[-21.32,-68.72],[-17.238,-73.711],[-17.691,-81.422],[-18.145,-90.039],[-19.958,-106.822],[-22.227,-123.605],[-23.587,-131.77],[-21.773,-137.667],[-17.691,-136.76],[-14.969,-129.502],[-10.432,-112.719],[-4.99,-79.153],[-1.814,-73.256],[3.175,-75.978],[4.083,-83.689],[4.535,-92.307],[6.35,-126.327],[7.712,-130.863],[11.339,-129.956],[13.607,-122.698],[14.514,-115.44],[14.061,-84.142],[20.411,-52.844],[22.68,-47.854],[21.772,-48.308],[19.05,-44.226],[34.926,-44.68],[47.628,-57.834],[59.876,-71.442],[66.678,-71.896],[65.772,-65.092],[57.154,-50.123],[52.163,-42.412],[48.988,-33.34],[43.999,-25.175],[37.648,-17.01],[24.947,-1.134],[21.772,7.938],[21.772,9.299],[10.886,12.021],[-15.876,18.825],[-15.876,18.371],[-24.949,5.67],[-32.206,-8.845],[-39.01,-24.267],[-46.268,-39.689],[-54.887,-53.297],[-63.958,-64.637],[-72.576,-79.152],[-74.391,-82.781],[-74.844,-85.956]],"c":true},"ix":2},"nm":"Контур 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-2.721,-4.989],[-3.629,-4.083],[-2.722,-4.99],[-2.722,-4.989],[-4.99,-9.526],[-1.815,-2.268],[-1.36,-2.267],[0.907,0],[1.814,-2.723],[0,-3.175],[-4.082,-6.349],[-3.175,0],[0,0],[0,-0.454],[0,1.814],[2.722,14.061],[0,0],[0,0],[-3.629,3.629],[0.453,0.908],[4.082,-1.361],[1.36,1.361],[0,1.36],[0.453,4.083],[0,0],[0.454,0.907],[0,0],[0,0],[-1.36,0],[-2.268,0.453],[-6.804,1.813],[-6.805,1.814],[-5.443,0.907],[0,-6.35],[0.454,-7.713],[4.99,-0.453],[4.536,-1.815],[1.361,-0.907],[0.453,-0.453],[-3.628,0.908],[-5.443,0.454],[-3.629,0],[-0.454,-2.268],[-1.361,-4.083],[-1.814,-7.711],[-1.361,-8.164],[-1.814,-4.082],[-1.815,-2.268],[-3.175,-0.908],[1.361,3.175],[0.454,4.082],[1.815,8.165],[1.814,7.711],[1.361,3.629],[0.907,2.721],[0,0],[0.453,1.814],[0.454,8.165],[-1.815,7.258],[1.36,0],[4.536,-1.814],[1.36,-0.453],[0.454,0.454],[-0.907,0.907],[-3.629,6.351],[-2.267,2.722],[-0.907,2.722],[-1.361,2.722],[-1.815,2.268],[-1.36,3.175],[-1.814,2.721],[0.907,2.722],[2.722,0.908],[3.629,-4.084],[4.99,-5.443],[3.175,-0.908],[0.907,1.814],[0.454,2.267],[0.908,5.443],[0,5.443],[0.453,5.443],[0.907,5.443],[4.989,2.721],[1.814,-3.177],[0,-0.455],[0.454,-1.815],[0,-2.721],[0,0],[0,0],[1.361,5.442],[1.815,5.897],[0.908,3.175],[1.361,2.268],[4.083,-2.268],[0,-0.454],[-1.361,-4.99],[-0.454,-11.34],[-0.454,-5.443],[0,0],[0,0],[0,0],[0.454,1.361],[0,0],[1.814,5.897],[1.815,5.443],[4.989,0.454],[1.361,-1.814],[-0.453,-2.268],[-1.814,-5.443],[-1.815,-5.443],[-1.361,-5.897],[-0.453,-1.36],[0.454,-1.361],[0.453,0],[0,0.454],[0.908,0.908],[3.175,4.082],[3.175,4.537],[4.99,-0.908],[0.454,-2.267],[-1.361,-2.267]],"o":[[2.722,4.535],[3.629,4.082],[2.722,4.99],[4.082,10.433],[1.361,2.268],[1.814,1.814],[-0.907,0],[-2.722,0.455],[-1.815,2.722],[-0.454,7.258],[1.815,2.723],[0,0],[-0.907,13.608],[2.268,2.268],[-1.361,-14.515],[0,0],[0,0],[4.536,-0.907],[0.907,-0.454],[-3.629,-3.175],[-1.361,0.455],[-0.907,-0.907],[-0.907,-4.082],[0,0],[0,-0.907],[0,0],[0.454,0],[1.361,0],[2.269,-0.454],[6.804,-1.361],[6.804,-1.815],[4.989,-1.361],[-0.907,6.804],[0.454,7.71],[-4.989,-0.454],[-4.536,-0.454],[-1.361,-0.455],[-0.454,0.454],[-2.721,2.722],[5.444,-1.361],[3.629,0],[-0.454,2.268],[0.453,4.082],[1.361,8.165],[1.814,8.165],[0.454,4.082],[0.907,3.175],[2.268,1.361],[1.814,-3.629],[-1.36,-3.629],[-1.361,-8.165],[-1.814,-7.711],[-0.907,-4.082],[-0.907,-2.722],[0,0],[1.361,0],[-0.454,-8.165],[-0.453,-7.711],[0.453,-1.361],[-4.537,-0.454],[-1.361,0.454],[0,-0.907],[0,-1.361],[4.536,-4.99],[2.268,-2.722],[2.268,-2.268],[0.907,-3.176],[1.361,-2.722],[1.814,-2.723],[1.361,-2.723],[1.815,-2.268],[-0.454,-3.176],[-5.896,-1.36],[-4.989,4.989],[-2.268,2.268],[-1.814,-0.907],[-0.907,-2.268],[-1.814,-4.99],[-0.453,-5.443],[0.453,-5.443],[0,-4.991],[-0.454,-4.536],[-3.176,-1.814],[-0.454,0.454],[-0.907,1.814],[0,2.722],[0,0],[0,0],[-0.454,-5.897],[-1.361,-5.443],[-0.907,-2.722],[-0.453,-2.722],[-1.815,-4.082],[0,0],[-4.536,3.175],[1.814,11.34],[0.454,5.443],[0,0],[0,0],[-0.454,0],[-0.453,-0.907],[0,0],[-1.361,-5.443],[-1.361,-5.443],[-0.907,-4.536],[-1.815,0],[-1.36,1.814],[0.454,5.443],[1.361,5.443],[1.36,5.443],[0.454,1.361],[0.454,0.907],[0,0],[0,0],[-0.907,-0.907],[-3.628,-3.174],[-3.175,-4.082],[-2.269,-3.628],[-2.268,0.454],[-0.453,2.723],[0.907,5.898]],"v":[[-67.133,-66.453],[-57.607,-53.753],[-48.535,-40.598],[-41.277,-25.176],[-27.669,4.762],[-23.133,11.566],[-18.598,17.915],[-21.773,18.369],[-29.938,21.092],[-31.299,31.525],[-28.577,54.204],[-21.32,58.286],[-21.32,58.741],[-20.867,95.483],[-12.247,102.741],[-16.784,58.742],[-16.784,58.288],[-16.329,58.288],[-3.176,52.845],[-3.176,50.123],[-15.423,50.123],[-20.865,50.123],[-22.227,46.041],[-23.133,33.34],[-23.133,28.35],[-23.587,25.175],[-23.587,23.814],[-22.227,23.36],[-18.598,22.906],[-12.247,21.545],[8.618,16.102],[29.484,10.659],[44.906,6.577],[45.813,26.535],[46.721,49.669],[31.751,49.215],[17.237,50.576],[13.607,51.483],[12.701,52.39],[16.783,58.74],[33.113,56.472],[43.546,56.926],[43.999,64.184],[46.721,76.885],[51.257,100.926],[55.793,125.42],[58.061,137.667],[59.876,143.11],[67.587,145.832],[65.772,136.76],[63.958,125.42],[58.967,100.472],[53.525,76.885],[50.35,65.545],[48.081,56.927],[49.895,56.927],[52.617,53.752],[50.802,28.804],[49.896,6.124],[47.628,3.402],[33.566,6.577],[29.484,7.484],[29.031,5.216],[30.844,1.587],[43.546,-14.743],[49.895,-22.908],[54.885,-31.073],[58.061,-40.145],[63.051,-47.403],[68.04,-55.568],[72.576,-63.279],[74.391,-71.444],[68.947,-77.795],[53.07,-70.536],[39.917,-53.299],[31.298,-48.309],[27.669,-52.845],[25.402,-60.103],[21.318,-75.979],[20.865,-92.762],[20.865,-108.638],[19.958,-124.06],[13.608,-137.214],[4.083,-134.492],[3.628,-133.131],[2.268,-127.234],[1.815,-118.616],[0.001,-88.225],[0.001,-90.039],[-2.721,-106.822],[-6.805,-124.059],[-9.072,-132.677],[-11.794,-139.935],[-22.68,-143.564],[-23.133,-143.11],[-26.309,-129.502],[-22.227,-95.482],[-20.865,-78.699],[-20.865,-76.431],[-20.865,-75.07],[-21.32,-75.524],[-22.68,-79.153],[-24.04,-83.689],[-29.031,-100.472],[-33.566,-117.255],[-42.184,-126.781],[-47.628,-124.513],[-49.443,-118.163],[-46.268,-101.38],[-42.184,-84.597],[-38.103,-67.36],[-37.195,-63.278],[-37.195,-59.649],[-37.648,-59.195],[-38.103,-59.649],[-40.824,-61.918],[-51.257,-72.803],[-60.329,-85.505],[-70.762,-94.122],[-74.844,-89.587],[-73.484,-81.876]],"c":true},"ix":2},"nm":"Контур 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Объединить контуры 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[75.795,146.082],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[12.247,4.082],[12.247,15.876],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-12.247,-3.629],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-51.483,-52.844],[-47.4,-55.112],[21.092,-71.895],[22.454,-59.648],[25.629,-24.267],[21.547,-22.452],[25.176,-0.227],[39.237,67.813],[-44.225,20.185],[-41.505,-0.681],[-43.318,-14.742],[-43.318,-21.547],[-49.669,-26.536]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.094117647059,0.619607843137,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[100.062,221.379],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[6.042,7.552],[0,0],[0,0],[3.021,3.02],[0,0],[-1.133,4.484],[-24.795,-35.117],[14.914,47.764],[-6.986,-3.02],[-3.02,-0.567],[1.322,10.949],[-3.587,3.587],[-3.02,-16.237],[-1.532,1.888],[-3.209,1.699],[-0.189,-1.888],[-7.929,-10.572],[-4.72,2.266],[6.608,-12.838],[0.378,-5.286],[0,0],[0,0],[0,0]],"o":[[0,0],[-6.041,-7.551],[0,0],[0,0],[-3.021,-3.021],[0,0],[1.132,-4.484],[5.035,0.881],[0.189,-22.467],[6.985,3.021],[3.021,0.566],[-1.321,-10.95],[3.587,-3.587],[3.021,16.236],[1.531,-1.888],[3.21,-1.699],[0.189,1.887],[7.929,10.572],[4.72,-2.265],[-6.608,12.838],[-0.377,5.286],[0,0],[0,0],[0,0]],"v":[[-15.717,84.108],[-23.269,69.004],[-35.352,46.349],[-48.945,16.142],[-61.028,-0.472],[-71.6,-17.086],[-75.47,-29.924],[-42.023,1.039],[-46.679,-45.216],[-42.148,-65.606],[-23.458,-13.121],[-20.815,-38.986],[-24.968,-80.521],[-10.62,-66.55],[-1.201,-18.974],[5.805,-75.423],[15.056,-69.382],[24.685,11.233],[57.346,-14.443],[69.995,-6.891],[52.626,21.805],[38.278,43.706],[24.874,62.962],[25.44,74.291]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[76.853,88.144],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Кривые Слой 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[9]},{"t":30.0000012219251,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[459.68,340.04,0],"to":[4.417,0.958,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[486.18,345.79,0],"to":[0,0,0],"ti":[4.417,0.958,0]},{"t":30.0000012219251,"s":[459.68,340.04,0]}],"ix":2},"a":{"a":0,"k":[16.148,9.568,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-7.29,-0.988],[-1.115,-9.731],[14.679,1.626]],"o":[[6.009,2.107],[-5.357,0.933],[-4.225,0.605]],"v":[[-8.608,-8.33],[15.898,8.385],[-9.379,0.018]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[16.148,9.568],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Кривые Слой 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[9]},{"t":30.0000012219251,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[398.781,336.878,0],"to":[4,4.708,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[422.781,365.128,0],"to":[0,0,0],"ti":[4,4.708,0]},{"t":30.0000012219251,"s":[398.781,336.878,0]}],"ix":2},"a":{"a":0,"k":[28.904,7.928,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-13.021,1.799],[14.663,-5.646]],"o":[[32.09,2.365],[5.002,-7.734]],"v":[[-3.436,-7.678],[-28.654,7.678]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[28.903,7.928],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Кривые Слой 6","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[9]},{"t":30.0000012219251,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[457.445,376.507,0],"to":[4.125,1.417,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[482.195,385.007,0],"to":[0,0,0],"ti":[4.125,1.417,0]},{"t":30.0000012219251,"s":[457.445,376.507,0]}],"ix":2},"a":{"a":0,"k":[9.761,14.965,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[15.074,5.522],[-4.014,5.458]],"o":[[8.791,-9.49],[-1.742,-2.621],[-0.018,0.464]],"v":[[-5.497,-5.226],[-5.562,9.193],[-5.497,-5.226]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[9.761,14.966],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Кривые Слой 7","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[6]},{"t":30.0000012219251,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[388.435,376.497,0],"to":[4.125,0.583,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[413.185,379.997,0],"to":[0,0,0],"ti":[4.125,0.583,0]},{"t":30.0000012219251,"s":[388.435,376.497,0]}],"ix":2},"a":{"a":0,"k":[8.755,16.341,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":5,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":20,"s":[100,25.492,100]},{"t":30.0000012219251,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.664,8.08],[6.929,-11.612]],"o":[[7.489,-12.053],[-6.893,6.833]],"v":[[-5.841,-4.038],[1.576,9.258]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[8.755,16.341],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Кривые Слой 8","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[433.514,400.28,0],"to":[3.417,0.542,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[454.014,403.53,0],"to":[0,0,0],"ti":[3.417,0.542,0]},{"t":30.0000012219251,"s":[433.514,400.28,0]}],"ix":2},"a":{"a":0,"k":[22.853,25.447,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[14.817,-12.79],[16.031,7.802],[-12.735,-11.129]],"o":[[7.224,2.461],[-3.778,-5.863],[32.471,17.778]],"v":[[1.544,-12.407],[-3.783,2.685],[-9.868,7.419]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[22.853,25.447],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Кривые Слой 9","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[426.817,435.711,0],"to":[3,0.708,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[444.817,439.961,0],"to":[0,0,0],"ti":[3,0.708,0]},{"t":30.0000012219251,"s":[426.817,435.711,0]}],"ix":2,"x":"var $bm_rt;\n$bm_rt = comp('hello').layer('\\u041a\\u0440\\u0438\\u0432\\u044b\\u0435 \\u0421\\u043b\\u043e\\u0439 9').transform.position;"},"a":{"a":0,"k":[25.431,13.712,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[18.126,7.442],[-15.646,-6.368],[-8.368,10.935]],"o":[[-5.37,0.604],[5.15,8.216],[8.153,2.21]],"v":[[-7.225,6.02],[-9.535,-7.094],[17.028,-8.441]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[25.43,13.712],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Кривые Слой 10","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[384.082,578.839,0],"ix":2},"a":{"a":0,"k":[202.984,124.096,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-18.61,6.046],[-53.889,-16.071],[1.805,-33.544],[-1.445,24.987],[-21.608,-32.555],[-1.713,5.079],[32.916,-14.633],[-9.363,-23.747],[28.407,-16.494],[35.076,-65.612],[40.796,-32.468],[3.099,25.082],[-17.584,-0.796],[2.446,-7.232],[-20.406,-9.012],[-10.695,44.471],[-11.149,-24.484]],"o":[[46.88,-32.636],[-3.365,29.492],[18.526,-3.48],[20.571,-1.657],[3.487,-0.731],[-4.901,-10.755],[23.117,-0.939],[-25.633,-14.688],[57.623,-107.709],[-29.019,-14.68],[-2.48,-20.743],[5.265,-8.672],[-0.777,3.017],[-4.923,7.376],[14.29,-6.048],[-3.028,13.666],[-0.976,5.807]],"v":[[-76.229,20.037],[6.98,10.046],[2.796,106.886],[9.305,5.05],[88.678,0.539],[94.839,-3.785],[46.035,-73.346],[83.682,-13.395],[16.742,0.823],[7.444,3.514],[-76.229,8.509],[-76.694,-58.74],[-49.733,-79.876],[-52.057,-71.037],[1.401,-9.168],[-43.682,-90.251],[-77.624,-59.125]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[231.741,107.136],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-9.65,-34.285],[-1.145,-3.884],[23.885,-1.183]],"o":[[0.087,0.352],[22.891,-21.087],[38.888,18.213]],"v":[[20.861,45.359],[22.256,50.355],[-45.147,-49.172]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[360.572,110.251],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[35.515,9.375],[23.467,-4.539],[-6.045,-0.127]],"o":[[-19.583,0.221],[0.662,1.539],[8.883,-0.953]],"v":[[12.923,-4.532],[-48.438,-0.304],[-42.26,1.019]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[318.769,163.984],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-11.446,-3.652],[6.522,2.863]],"o":[[5.109,2.531],[-3.932,5.14]],"v":[[3.169,11.032],[-1.013,-13.563]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[269.953,38.13],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-3.469,-3.295],[17.781,-15.195]],"o":[[8.912,8.752],[0.298,1.44]],"v":[[-6.225,5.721],[-8.087,0.721]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[254.709,200.23],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 5","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-88.195,2.854],[33.895,-38.539]],"o":[[-65.481,-6.13],[21.443,22.596]],"v":[[74.377,-64.915],[-74.377,48.449]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[74.627,112.156],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 6","np":2,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-4.091,-2.489],[18.441,-10.716]],"o":[[10.791,6.306],[-0.293,1.393]],"v":[[-5.779,5.281],[-8.571,-0.871]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[254.263,148.023],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 7","np":2,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-71.07,63.966],[40.24,18.206],[0,0],[40.388,-7.773],[11.257,-24.55],[-13.488,25.675],[6.604,-10.17],[0.51,10.287],[20.119,-40.251],[0,0],[4.277,-7.279]],"o":[[-10.708,-41.487],[0,0],[-21.815,-3.078],[15.848,20.871],[-16.757,-7.326],[-8.866,0.043],[-0.322,3.018],[-37.51,12.085],[0,-0.385],[2.714,10.281],[128.562,80.801]],"v":[[188.035,22.472],[120.165,-78.211],[120.63,-78.595],[75.539,-105.11],[51.367,-28.636],[-12.32,-110.492],[-38.814,-98.195],[-43.93,-95.119],[-149.451,-25.174],[-149.916,-25.944],[-188.035,32.082]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.094117647059,0.619607843137,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[197.117,135.058],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 8","np":2,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Кривые Слой 11","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[13]},{"t":30.0000012219251,"s":[0]}],"ix":10,"x":"var $bm_rt;\n$bm_rt = comp('hello').layer('\\u041a\\u0440\\u0438\\u0432\\u044b\\u0435 \\u0421\\u043b\\u043e\\u0439 11').transform.rotation;"},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[390.242,374.412,0],"to":[4.167,-0.833,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[415.242,369.412,0],"to":[0,0,0],"ti":[4.167,-0.833,0]},{"t":30.0000012219251,"s":[390.242,374.412,0]}],"ix":2,"x":"var $bm_rt;\n$bm_rt = comp('hello').layer('\\u041a\\u0440\\u0438\\u0432\\u044b\\u0435 \\u0421\\u043b\\u043e\\u0439 11').transform.position;"},"a":{"a":0,"k":[129.624,186.838,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[2.266,-0.064],[0.545,0.136],[-0.646,0.018],[26.228,15.737],[15.313,13.048],[70.784,-20.593],[10.746,20.395],[-17.571,3.241],[41.215,55.958],[0.343,0.55],[1.154,-0.068],[9.551,14.54],[4.415,16.088],[18.081,-9.574],[0.68,-27.379],[1.759,0.595],[-19.885,-15.391],[-5.785,-1.04],[-12.582,-10.119],[-3.538,7.088],[-22.161,14.565],[-0.561,21.798],[-4.125,2.999],[-4.441,-1.176],[-6.251,-4.321],[-5.006,-4.409],[-0.546,-0.695],[0.628,0.553],[-5.259,-2.424],[-1.827,-2.317],[-2.581,-2.834],[-3.939,-3.643],[-1.26,-1.66],[1.415,1.309],[-5.517,-5.537],[-0.582,-6.088],[-2.391,-17.937],[1.183,-13.112],[0.467,-2.85],[-0.216,2.39],[8.563,-13.795],[-3.434,1.109],[2.662,-5.379],[0.895,-1.189],[-0.673,1.358],[10.728,-11.638],[16.772,-14.65],[13.603,-6.864],[3.804,-1.518],[-3.543,1.788],[20.104,-8.493],[25.345,4.133]],"o":[[-0.525,-0.14],[0.383,0.346],[38.31,10.181],[27.447,17.657],[25.819,49.929],[-20.62,6.22],[9.458,-13.224],[81.83,7.847],[-1.924,-0.906],[-4.886,0.132],[34.032,32.261],[22.733,37.927],[-21.677,-7.386],[6.122,30.635],[-2.214,4.676],[-10.257,-22.028],[9.444,9.432],[0.219,14.192],[-1.516,20.045],[-30.213,5],[-17.361,-21.957],[-11.951,3.999],[-8.271,-4.729],[-12.114,-4.823],[-10.492,-10.012],[0.383,0.668],[-0.239,-0.823],[-4.643,-8.114],[2.308,-9.435],[-1.916,-8.58],[0.692,-8.545],[0.467,1.53],[-0.095,-1.804],[-2.538,-8.31],[3.707,-17.124],[-5.711,-25.085],[8.549,-26.479],[-0.662,2.141],[0.967,-2.447],[6.617,-21.397],[6.505,0.58],[11.658,-4.357],[-0.847,0.974],[1.036,-0.685],[14.284,-16.423],[16.483,-17.611],[33.922,-17.144],[-4.22,0.532],[4.483,0.006],[18.36,-2.315],[31.564,0.703],[-5.366,-0.879]],"v":[[91.064,-74.58],[89.498,-74.998],[91.064,-74.58],[86.267,-63.023],[86.747,-45.114],[50.831,142.929],[-17.063,126.682],[25.311,136.343],[76.896,-54.077],[72.988,-56.067],[63.266,-57.355],[46.492,-56.575],[31.626,-57.127],[-46.55,-43.705],[-55.949,35.348],[-60.727,38.568],[-87.27,67.626],[-63.365,72.433],[-40.801,112.51],[-67.358,79.729],[-87.867,30.132],[-112.169,-42.859],[-121.103,-52.956],[-116.943,-64.898],[-110.942,-76.307],[-101.331,-85.851],[-99.968,-83.811],[-101.331,-85.851],[-93.882,-97.542],[-82.081,-102.225],[-71.588,-109.285],[-59.694,-113.556],[-57.187,-108.756],[-59.694,-113.556],[-48.796,-121.938],[-31.382,-114.787],[-18.067,-122.67],[-1.566,-126.691],[-3.304,-119.339],[-1.566,-126.691],[11.215,-122.063],[20.053,-134.764],[30.098,-125.134],[27.492,-121.93],[30.098,-125.134],[40.793,-116.791],[54.009,-109.33],[71.11,-104.744],[58.846,-101.709],[71.11,-104.744],[87.341,-92.291],[102.54,-75.452]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[8.222,-2.007],[0,0],[-5.647,-4.782]],"o":[[0,0],[5.4,1.089],[8.895,-2.678]],"v":[[-78.708,46.751],[-78.708,46.751],[-63.394,60.338]],"c":true},"ix":2},"nm":"Контур 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Объединить контуры 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.062745098039,0.086274509804,0.309803921569,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[129.624,149.4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":5,"s":[{"i":[[1,21],[15,22],[0,0],[0,0],[0,0],[0,0],[11,-20],[-18,-2],[-1,-3],[-5,-4],[-9.945,-5.955],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-2,13]],"o":[[-1,-21],[-15,-22],[0,0],[0,0],[0,0],[0,0],[-11,20],[8,0],[1,3],[2.636,2.109],[0,0],[0,0],[0,0],[0,0],[0,0],[2.458,-0.909],[0,0],[2,-13]],"v":[[102.5,-49.5],[83.5,-119.5],[65.5,-150.5],[-48.5,-140.5],[-59.5,-122.5],[-59.5,-41.5],[-92.5,-34.5],[-73.5,2.5],[-63.5,8.5],[-43.5,41.5],[-22.722,55.38],[-24.5,78.5],[19.5,144.5],[75.414,163.351],[69.346,108.728],[59.6,61],[63.5,59.5],[94.5,24.5]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[{"i":[[1,21],[15,22],[0,0],[0,0],[0,0],[0,0],[11,-20],[-18,-2],[-1,-3],[-5,-4],[-9.945,-5.955],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-2,13]],"o":[[-1,-21],[-15,-22],[0,0],[0,0],[0,0],[0,0],[-11,20],[8,0],[1,3],[2.636,2.109],[0,0],[0,0],[0,0],[0,0],[0,0],[2.458,-0.909],[0,0],[2,-13]],"v":[[102.5,-49.5],[83.5,-119.5],[65.5,-150.5],[-48.5,-140.5],[-59.5,-122.5],[-59.5,-41.5],[-92.5,-34.5],[-73.5,2.5],[-63.5,8.5],[-43.5,41.5],[-22.722,55.38],[-24.5,78.5],[19.5,144.5],[75.414,163.351],[80.738,95.835],[59.6,61],[63.5,59.5],[94.5,24.5]],"c":true}]},{"t":30.0000012219251,"s":[{"i":[[1,21],[15,22],[0,0],[0,0],[0,0],[0,0],[11,-20],[-18,-2],[-1,-3],[-5,-4],[-9.945,-5.955],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[-2,13]],"o":[[-1,-21],[-15,-22],[0,0],[0,0],[0,0],[0,0],[-11,20],[8,0],[1,3],[2.636,2.109],[0,0],[0,0],[0,0],[0,0],[0,0],[2.458,-0.909],[0,0],[2,-13]],"v":[[102.5,-49.5],[83.5,-119.5],[65.5,-150.5],[-48.5,-140.5],[-59.5,-122.5],[-59.5,-41.5],[-92.5,-34.5],[-73.5,2.5],[-63.5,8.5],[-43.5,41.5],[-22.722,55.38],[-24.5,78.5],[19.5,144.5],[75.414,163.351],[69.238,107.835],[59.6,61],[63.5,59.5],[94.5,24.5]],"c":true}]}],"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[129.439,222.926],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Группа 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60.0000024438501,"st":0,"bm":0}],"markers":[]}
--------------------------------------------------------------------------------
/src/lib/assets/images/landing-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/src/lib/assets/images/landing-page.png
--------------------------------------------------------------------------------
/src/lib/components/common/Analytics.svelte:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
25 |
26 |
27 |
28 | {@html ``}
30 |
31 | {@html ``}
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/lib/components/common/AppBackground.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
120 |
--------------------------------------------------------------------------------
/src/lib/components/common/LottieAnimation.svelte:
--------------------------------------------------------------------------------
1 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/lib/components/common/SEO.svelte:
--------------------------------------------------------------------------------
1 |
36 |
37 |
38 | {title}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
58 |
59 |
60 |
61 |
62 |
63 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
85 |
86 |
93 |
94 | {@html schemaMarkupScript}
95 |
96 |
--------------------------------------------------------------------------------
/src/lib/components/common/ThemeToggle.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
19 |
--------------------------------------------------------------------------------
/src/lib/components/icons/google.svelte:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/src/lib/components/icons/index.ts:
--------------------------------------------------------------------------------
1 | import type { Icon as LucideIcon } from 'lucide-svelte';
2 | import {
3 | ArrowRight,
4 | ChevronsUpDown,
5 | CircleDollarSign,
6 | Github,
7 | Home,
8 | Instagram,
9 | LayoutDashboard,
10 | Link,
11 | Linkedin,
12 | Loader2,
13 | Menu,
14 | ScrollText,
15 | Settings,
16 | TriangleAlert,
17 | Twitter,
18 | Users2,
19 | X
20 | } from 'lucide-svelte';
21 |
22 | import Google from './google.svelte';
23 |
24 | export type Icon = LucideIcon;
25 |
26 | export const Icons = {
27 | spinner: Loader2,
28 | google: Google,
29 | camera: Instagram,
30 | link: Link,
31 | close: X,
32 | select: ChevronsUpDown,
33 | dashboard: LayoutDashboard,
34 | documents: ScrollText,
35 | users: Users2,
36 | dollarCircle: CircleDollarSign,
37 | settings: Settings,
38 | menu: Menu,
39 | arrowRight: ArrowRight,
40 | twitter: Twitter,
41 | github: Github,
42 | linkedin: Linkedin,
43 | home: Home,
44 | triangleAlert: TriangleAlert
45 | };
46 |
47 | export type IconType = any;
48 |
--------------------------------------------------------------------------------
/src/lib/components/ui/button/button.svelte:
--------------------------------------------------------------------------------
1 |
17 |
18 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/lib/components/ui/button/index.ts:
--------------------------------------------------------------------------------
1 | import type { Button as ButtonPrimitive } from 'bits-ui';
2 | import { tv, type VariantProps } from 'tailwind-variants';
3 |
4 | import Root from './button.svelte';
5 |
6 | const buttonVariants = tv({
7 | base: 'inline-flex items-center justify-center rounded-md text-sm font-medium whitespace-nowrap ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
8 | variants: {
9 | variant: {
10 | default: 'bg-primary text-primary-foreground hover:bg-primary/90',
11 | destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
12 | outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
13 | secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
14 | ghost: 'hover:bg-accent hover:text-accent-foreground',
15 | link: 'text-primary underline-offset-4 hover:underline'
16 | },
17 | size: {
18 | default: 'h-10 px-4 py-2',
19 | sm: 'h-9 rounded-md px-3',
20 | lg: 'h-11 rounded-md px-8',
21 | icon: 'h-10 w-10'
22 | }
23 | },
24 | defaultVariants: {
25 | variant: 'default',
26 | size: 'default'
27 | }
28 | });
29 |
30 | type Variant = VariantProps['variant'];
31 | type Size = VariantProps['size'];
32 |
33 | type Props = ButtonPrimitive.Props & {
34 | variant?: Variant;
35 | size?: Size;
36 | };
37 |
38 | type Events = ButtonPrimitive.Events;
39 |
40 | export {
41 | //
42 | Root as Button,
43 | type Events as ButtonEvents,
44 | type Props as ButtonProps,
45 | buttonVariants,
46 | type Events,
47 | type Props,
48 | Root
49 | };
50 |
--------------------------------------------------------------------------------
/src/lib/components/ui/checkbox/checkbox.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
24 |
29 | {#if isChecked}
30 |
31 | {:else if isIndeterminate}
32 |
33 | {/if}
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/lib/components/ui/checkbox/index.ts:
--------------------------------------------------------------------------------
1 | import Root from './checkbox.svelte';
2 | export {
3 | //
4 | Root as Checkbox,
5 | Root
6 | };
7 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
16 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte:
--------------------------------------------------------------------------------
1 |
17 |
18 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/lib/components/ui/dropdown-menu/index.ts:
--------------------------------------------------------------------------------
1 | import { DropdownMenu as DropdownMenuPrimitive } from 'bits-ui';
2 |
3 | import CheckboxItem from './dropdown-menu-checkbox-item.svelte';
4 | import Content from './dropdown-menu-content.svelte';
5 | import Item from './dropdown-menu-item.svelte';
6 | import Label from './dropdown-menu-label.svelte';
7 | import RadioGroup from './dropdown-menu-radio-group.svelte';
8 | import RadioItem from './dropdown-menu-radio-item.svelte';
9 | import Separator from './dropdown-menu-separator.svelte';
10 | import Shortcut from './dropdown-menu-shortcut.svelte';
11 | import SubContent from './dropdown-menu-sub-content.svelte';
12 | import SubTrigger from './dropdown-menu-sub-trigger.svelte';
13 |
14 | const Sub = DropdownMenuPrimitive.Sub;
15 | const Root = DropdownMenuPrimitive.Root;
16 | const Trigger = DropdownMenuPrimitive.Trigger;
17 | const Group = DropdownMenuPrimitive.Group;
18 |
19 | export {
20 | CheckboxItem,
21 | Content,
22 | //
23 | Root as DropdownMenu,
24 | CheckboxItem as DropdownMenuCheckboxItem,
25 | Content as DropdownMenuContent,
26 | Group as DropdownMenuGroup,
27 | Item as DropdownMenuItem,
28 | Label as DropdownMenuLabel,
29 | RadioGroup as DropdownMenuRadioGroup,
30 | RadioItem as DropdownMenuRadioItem,
31 | Separator as DropdownMenuSeparator,
32 | Shortcut as DropdownMenuShortcut,
33 | Sub as DropdownMenuSub,
34 | SubContent as DropdownMenuSubContent,
35 | SubTrigger as DropdownMenuSubTrigger,
36 | Trigger as DropdownMenuTrigger,
37 | Group,
38 | Item,
39 | Label,
40 | RadioGroup,
41 | RadioItem,
42 | Root,
43 | Separator,
44 | Shortcut,
45 | Sub,
46 | SubContent,
47 | SubTrigger,
48 | Trigger
49 | };
50 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-button.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-description.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-element-field.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-error.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-field-errors.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
22 |
23 | {#each errors as error}
24 | {error}
25 | {/each}
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-field.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-fieldset.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
20 |
21 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-label.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 |
19 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/form-legend.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/lib/components/ui/form/index.ts:
--------------------------------------------------------------------------------
1 | import * as FormPrimitive from 'formsnap';
2 |
3 | import Button from './form-button.svelte';
4 | import Description from './form-description.svelte';
5 | import ElementField from './form-element-field.svelte';
6 | import Error from './form-error.svelte';
7 | import Field from './form-field.svelte';
8 | import FieldErrors from './form-field-errors.svelte';
9 | import Fieldset from './form-fieldset.svelte';
10 | import Label from './form-label.svelte';
11 | import Legend from './form-legend.svelte';
12 |
13 | const Control = FormPrimitive.Control;
14 |
15 | export {
16 | Button,
17 | Control,
18 | Description,
19 | ElementField,
20 | Error,
21 | Field,
22 | FieldErrors,
23 | Fieldset,
24 | Button as FormButton,
25 | Control as FormControl,
26 | Description as FormDescription,
27 | ElementField as FormElementField,
28 | Error as FormError,
29 | //
30 | Field as FormField,
31 | FieldErrors as FormFieldErrors,
32 | Fieldset as FormFieldset,
33 | Label as FormLabel,
34 | Legend as FormLegend,
35 | Label,
36 | Legend
37 | };
38 |
--------------------------------------------------------------------------------
/src/lib/components/ui/heading/heading.svelte:
--------------------------------------------------------------------------------
1 |
24 |
25 | {#if element === 'h1'}
26 |
27 |
28 |
29 | {:else if element === 'h2'}
30 |
31 |
32 |
33 | {:else if element === 'h3'}
34 |
35 |
36 |
37 | {:else if element === 'h4'}
38 |
39 |
40 |
41 | {:else if element === 'h5'}
42 |
43 |
44 |
45 | {:else if element === 'h6'}
46 |
47 |
48 |
49 | {/if}
50 |
--------------------------------------------------------------------------------
/src/lib/components/ui/heading/index.ts:
--------------------------------------------------------------------------------
1 | import { tv, type VariantProps } from 'tailwind-variants';
2 |
3 | import Root from './heading.svelte';
4 |
5 | const headingVariants = tv({
6 | base: 'max-w-lg font-extrabold',
7 | variants: {
8 | size: {
9 | default: 'text-xl md:text-3xl md:leading-[2.5rem]',
10 | xl: 'text-2xl md:text-4xl md:leading-[3rem]'
11 | }
12 | },
13 | defaultVariants: {
14 | size: 'default'
15 | }
16 | });
17 |
18 | type Size = VariantProps['size'];
19 |
20 | type Props = {
21 | size?: Size;
22 | element?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
23 | };
24 |
25 | export {
26 | //
27 | Root as Heading,
28 | type Props as HeadingProps,
29 | headingVariants,
30 | type Props,
31 | Root
32 | };
33 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input/index.ts:
--------------------------------------------------------------------------------
1 | import Root from './input.svelte';
2 |
3 | type FormInputEvent = T & {
4 | currentTarget: EventTarget & HTMLInputElement;
5 | };
6 | export type InputEvents = {
7 | blur: FormInputEvent;
8 | change: FormInputEvent;
9 | click: FormInputEvent;
10 | focus: FormInputEvent;
11 | keydown: FormInputEvent;
12 | keypress: FormInputEvent;
13 | keyup: FormInputEvent;
14 | mouseover: FormInputEvent;
15 | mouseenter: FormInputEvent;
16 | mouseleave: FormInputEvent;
17 | paste: FormInputEvent;
18 | input: FormInputEvent;
19 | };
20 |
21 | export {
22 | //
23 | Root as Input,
24 | Root
25 | };
26 |
--------------------------------------------------------------------------------
/src/lib/components/ui/input/input.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 |
36 |
--------------------------------------------------------------------------------
/src/lib/components/ui/label/index.ts:
--------------------------------------------------------------------------------
1 | import Root from './label.svelte';
2 |
3 | export {
4 | //
5 | Root as Label,
6 | Root
7 | };
8 |
--------------------------------------------------------------------------------
/src/lib/components/ui/label/label.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/lib/components/ui/popover/index.ts:
--------------------------------------------------------------------------------
1 | import { Popover as PopoverPrimitive } from 'bits-ui';
2 |
3 | import Content from './popover-content.svelte';
4 | const Root = PopoverPrimitive.Root;
5 | const Trigger = PopoverPrimitive.Trigger;
6 |
7 | export {
8 | Content,
9 | //
10 | Root as Popover,
11 | Content as PopoverContent,
12 | Trigger as PopoverTrigger,
13 | Root,
14 | Trigger
15 | };
16 |
--------------------------------------------------------------------------------
/src/lib/components/ui/popover/popover-content.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/lib/components/ui/radio-group/index.ts:
--------------------------------------------------------------------------------
1 | import { RadioGroup as RadioGroupPrimitive } from 'bits-ui';
2 |
3 | import Root from './radio-group.svelte';
4 | import Item from './radio-group-item.svelte';
5 | const Input = RadioGroupPrimitive.Input;
6 |
7 | export {
8 | Input,
9 | Item,
10 | //
11 | Root as RadioGroup,
12 | Input as RadioGroupInput,
13 | Item as RadioGroupItem,
14 | Root
15 | };
16 |
--------------------------------------------------------------------------------
/src/lib/components/ui/radio-group/radio-group-item.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/lib/components/ui/radio-group/radio-group.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/index.ts:
--------------------------------------------------------------------------------
1 | import { Select as SelectPrimitive } from 'bits-ui';
2 |
3 | import Root from './select.svelte';
4 | import Content from './select-content.svelte';
5 | import Item from './select-item.svelte';
6 | import Label from './select-label.svelte';
7 | import Separator from './select-separator.svelte';
8 | import Trigger from './select-trigger.svelte';
9 |
10 | const Group = SelectPrimitive.Group;
11 | const Input = SelectPrimitive.Input;
12 | const Value = SelectPrimitive.Value;
13 | export {
14 | Content,
15 | Group,
16 | Input,
17 | Item,
18 | Label,
19 | Root,
20 | //
21 | Root as Select,
22 | Content as SelectContent,
23 | Group as SelectGroup,
24 | Input as SelectInput,
25 | Item as SelectItem,
26 | Label as SelectLabel,
27 | Separator as SelectSeparator,
28 | Trigger as SelectTrigger,
29 | Value as SelectValue,
30 | Separator,
31 | Trigger,
32 | Value
33 | };
34 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/select-content.svelte:
--------------------------------------------------------------------------------
1 |
21 |
22 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/select-item.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/select-label.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/select-separator.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/select-trigger.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/lib/components/ui/select/select.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/lib/components/ui/switch/index.ts:
--------------------------------------------------------------------------------
1 | import Root from './switch.svelte';
2 |
3 | export {
4 | Root,
5 | //
6 | Root as Switch
7 | };
8 |
--------------------------------------------------------------------------------
/src/lib/components/ui/switch/switch.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
21 |
26 |
27 |
--------------------------------------------------------------------------------
/src/lib/components/ui/textarea/index.ts:
--------------------------------------------------------------------------------
1 | import Root from './textarea.svelte';
2 |
3 | type FormTextareaEvent = T & {
4 | currentTarget: EventTarget & HTMLTextAreaElement;
5 | };
6 |
7 | type TextareaEvents = {
8 | blur: FormTextareaEvent;
9 | change: FormTextareaEvent;
10 | click: FormTextareaEvent;
11 | focus: FormTextareaEvent;
12 | keydown: FormTextareaEvent;
13 | keypress: FormTextareaEvent;
14 | keyup: FormTextareaEvent;
15 | mouseover: FormTextareaEvent;
16 | mouseenter: FormTextareaEvent;
17 | mouseleave: FormTextareaEvent;
18 | paste: FormTextareaEvent;
19 | input: FormTextareaEvent;
20 | };
21 |
22 | export {
23 | type FormTextareaEvent,
24 | Root,
25 | //
26 | Root as Textarea,
27 | type TextareaEvents
28 | };
29 |
--------------------------------------------------------------------------------
/src/lib/components/ui/textarea/textarea.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
34 | {#if value && $$restProps.maxlength}
35 |
36 | {String(value).length} / {$$restProps.maxlength}
37 |
38 | {/if}
39 |
40 |
--------------------------------------------------------------------------------
/src/lib/constants/index.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/src/lib/constants/index.ts
--------------------------------------------------------------------------------
/src/lib/helpers/analytics.ts:
--------------------------------------------------------------------------------
1 | import FingerprintJS from '@fingerprintjs/fingerprintjs';
2 |
3 | import { PUBLIC_LANDING_PAGE } from '$env/static/public';
4 | import type { FpType } from '$lib/types';
5 | import type { AnalyticsDto } from '$lib/types';
6 |
7 | export async function getBrowserHash() {
8 | const fp = await FingerprintJS.load();
9 | const { visitorId } = await fp.get();
10 | return visitorId;
11 | }
12 |
13 | export async function getSiteAnalytics(): Promise {
14 | const fpString = localStorage.getItem('fp');
15 |
16 | const fp: FpType | null = JSON.parse(fpString || 'null');
17 |
18 | return {
19 | browserHash: await getBrowserHash(),
20 | landingPage: fp ? fp.landing || PUBLIC_LANDING_PAGE : PUBLIC_LANDING_PAGE,
21 | referralSiteUrl: fp ? fp.referrer || '' : '',
22 | userAgent: navigator.userAgent,
23 | isIncognitoMode: false // TODO: get cognito mode later
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/src/lib/helpers/debounce.ts:
--------------------------------------------------------------------------------
1 | export function useDebounce() {
2 | let timeoutId;
3 |
4 | const debounce = (delay, func, ...args) => {
5 | clearTimeout(timeoutId);
6 |
7 | timeoutId = setTimeout(async () => {
8 | await func(...args);
9 | }, delay);
10 | };
11 |
12 | return {
13 | debounce
14 | };
15 | }
16 |
17 | export function debounceNode(node, params) {
18 | let timer;
19 |
20 | return {
21 | update() {
22 | clearTimeout(timer);
23 | timer = setTimeout(params.func, params.duration);
24 | },
25 | destroy() {
26 | clearTimeout(timer);
27 | }
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/src/lib/helpers/document-scroll.ts:
--------------------------------------------------------------------------------
1 | export function scrollToInPage(
2 | xPosition = 0,
3 | yPosition = 1,
4 | isSmooth = false,
5 | method: 'scrollBy' | 'scrollTo' = 'scrollTo'
6 | ) {
7 | if (isSmooth) {
8 | document.documentElement.style.scrollBehavior = 'smooth';
9 | }
10 | window[method](xPosition, yPosition);
11 | if (isSmooth) {
12 | document.documentElement.style.scrollBehavior = '';
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/lib/helpers/formatCurrency.ts:
--------------------------------------------------------------------------------
1 | function formatCurrency(
2 | amount: number,
3 | isIncludeFraction = false,
4 | style = 'currency',
5 | locale = 'en-US',
6 | currencyCode = 'USD'
7 | ): string {
8 | const formatter = new Intl.NumberFormat(locale, {
9 | style,
10 | currency: currencyCode,
11 | maximumFractionDigits: isIncludeFraction ? undefined : 0
12 | });
13 | return formatter.format(amount);
14 | }
15 |
16 | export default formatCurrency;
17 |
--------------------------------------------------------------------------------
/src/lib/helpers/generateUniqueId.ts:
--------------------------------------------------------------------------------
1 | function generateUniqueId() {
2 | // convert num to base 36 and stringify
3 | const dateStr = Date.now().toString(36);
4 |
5 | // start at index 2 to skip decimal point
6 | const randomStr = Math.random().toString(36).substring(2, 8);
7 |
8 | return `${dateStr}-${randomStr}`;
9 | }
10 |
11 | export default generateUniqueId;
12 |
--------------------------------------------------------------------------------
/src/lib/helpers/index.ts:
--------------------------------------------------------------------------------
1 | import type { RequestEvent } from '@sveltejs/kit';
2 |
3 | import { PUBLIC_LANDING_PAGE } from '$env/static/public';
4 |
5 | export function getRandomItemFromArray(array) {
6 | const randomIndex = Math.floor(Math.random() * array.length);
7 | return array[randomIndex];
8 | }
9 |
10 | export function resetObjectPropertiesToEmptyString(obj: T): T {
11 | const result: Record = {};
12 |
13 | for (const key in obj) {
14 | if (Object.prototype.hasOwnProperty.call(obj, key)) {
15 | if (typeof obj[key] === 'object' && obj[key] !== null) {
16 | result[key] = resetObjectPropertiesToEmptyString(obj[key]);
17 | } else {
18 | result[key] = '';
19 | }
20 | }
21 | }
22 |
23 | return result as T;
24 | }
25 |
26 | export function getUserAgent() {
27 | return navigator.userAgent;
28 | }
29 |
30 | export function getOrigin() {
31 | const { origin } = window.location;
32 | return `${origin}${PUBLIC_LANDING_PAGE}`;
33 | }
34 |
35 | export function getIp(event: RequestEvent>, string | null>) {
36 | let clientIp = '';
37 | try {
38 | clientIp = event.getClientAddress();
39 | } catch {
40 | clientIp = '';
41 | }
42 | return clientIp;
43 | }
44 |
--------------------------------------------------------------------------------
/src/lib/helpers/localstorage.ts:
--------------------------------------------------------------------------------
1 | export type StoredItem = {
2 | value: any;
3 | expiry: number;
4 | };
5 |
6 | export function saveToLocalStorageWithExpiry(key: string, value: any, expiryDays: number): void {
7 | const now = new Date();
8 | const expiryDate = new Date(now.getTime() + expiryDays * 24 * 60 * 60 * 1000);
9 |
10 | const item: StoredItem = {
11 | value: value,
12 | expiry: expiryDate.getTime()
13 | };
14 |
15 | localStorage.setItem(key, JSON.stringify(item));
16 | }
17 |
18 | export function getFromLocalStorageWithExpiry(key: string): any {
19 | const itemJson = localStorage.getItem(key);
20 |
21 | if (!itemJson) {
22 | return null;
23 | }
24 |
25 | const item: StoredItem = JSON.parse(itemJson);
26 | const now = new Date();
27 |
28 | if (now.getTime() > item.expiry) {
29 | localStorage.removeItem(key);
30 | return null;
31 | }
32 |
33 | return item.value;
34 | }
35 |
--------------------------------------------------------------------------------
/src/lib/helpers/observer.ts:
--------------------------------------------------------------------------------
1 | export function observeSectionVisibility(
2 | elSelector: string,
3 | callbackYes: () => void,
4 | callbackNo: () => void,
5 | threshold = 1
6 | ) {
7 | const targetElement = document.querySelector(elSelector);
8 | if (!targetElement) return;
9 |
10 | const intersectionObserver = new IntersectionObserver(
11 | (entries) => {
12 | entries.forEach((entry) => {
13 | if (
14 | (entry.isIntersecting && entry.intersectionRatio >= threshold) ||
15 | entry.boundingClientRect.top < 0
16 | ) {
17 | callbackYes();
18 | } else {
19 | callbackNo();
20 | }
21 | });
22 | },
23 | {
24 | threshold
25 | }
26 | );
27 |
28 | intersectionObserver.observe(targetElement);
29 | }
30 |
--------------------------------------------------------------------------------
/src/lib/helpers/responsive.ts:
--------------------------------------------------------------------------------
1 | export const responsiveSizes = {
2 | xs: 390,
3 | sm: 640,
4 | md: 768,
5 | lg: 1024,
6 | xl: 1280,
7 | '2xl': 1536,
8 | '3xl': 2100
9 | } as const;
10 |
11 | export const screenInfo = {
12 | isXs: false,
13 | isSm: false,
14 | isMd: false,
15 | isLg: false,
16 | isXl: false,
17 | is2Xl: false,
18 | is3Xl: false,
19 | width: 0
20 | };
21 |
22 | export function handleResize() {
23 | screenInfo.width = window.innerWidth;
24 |
25 | for (const key in screenInfo) {
26 | screenInfo[key] = false;
27 | }
28 |
29 | switch (true) {
30 | case screenInfo.width < responsiveSizes.xs:
31 | screenInfo.isXs = true;
32 | break;
33 | case screenInfo.width >= responsiveSizes.sm && screenInfo.width < responsiveSizes.md:
34 | screenInfo.isSm = true;
35 | break;
36 | case screenInfo.width >= responsiveSizes.md && screenInfo.width < responsiveSizes.lg:
37 | screenInfo.isMd = true;
38 | break;
39 | case screenInfo.width >= responsiveSizes.lg && screenInfo.width < responsiveSizes.xl:
40 | screenInfo.isLg = true;
41 | break;
42 | case screenInfo.width >= responsiveSizes.xl && screenInfo.width < responsiveSizes['2xl']:
43 | screenInfo.isXl = true;
44 | break;
45 | case screenInfo.width >= responsiveSizes['2xl'] && screenInfo.width < responsiveSizes['3xl']:
46 | screenInfo.is2Xl = true;
47 | break;
48 | case screenInfo.width >= responsiveSizes['3xl']:
49 | screenInfo.is3Xl = true;
50 | break;
51 | default:
52 | break;
53 | }
54 | }
55 |
56 | export function registerResizeEvent() {
57 | if (typeof window === 'undefined') return;
58 |
59 | window.addEventListener('resize', handleResize);
60 | window.dispatchEvent(new Event('resize'));
61 | }
62 |
63 | export function unregisterResizeEvent() {
64 | if (typeof window === 'undefined') return;
65 |
66 | window.removeEventListener('resize', handleResize);
67 | }
68 |
--------------------------------------------------------------------------------
/src/lib/helpers/validations.ts:
--------------------------------------------------------------------------------
1 | export const urlRegex =
2 | /^(?:(https?|ftp):\/\/)?([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$#_-]+)?@)?([a-zA-Z0-9-]+\.){1,}[a-zA-Z]{2,}(:[0-9]{1,5})?([/?]([a-zA-Z0-9.&%$#_-]+[/]?)?)?(\?[a-zA-Z0-9+&@#/%=~_|!:,.;-]*)?(#[a-zA-Z0-9_-]*)?$/;
3 |
4 | export function validateEmail(email: string): boolean {
5 | const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
6 | return emailRegex.test(email);
7 | }
8 |
9 | export function isValidURL(url: string) {
10 | return urlRegex.test(url);
11 | }
12 |
13 | export enum PasswordStrength {
14 | Pass = 'Pass',
15 | FairPass = 'Fair Pass',
16 | Poor = 'Poor'
17 | }
18 |
19 | export function validatePasswordStrength(password: string): {
20 | label: PasswordStrength | '';
21 | color: 'text-red-500' | 'text-amber-500' | 'text-green-500';
22 | } {
23 | if (password.length < 8) {
24 | return {
25 | label: PasswordStrength.Poor,
26 | color: 'text-red-500'
27 | };
28 | }
29 |
30 | if (!/[A-Z]/.test(password)) {
31 | return {
32 | label: PasswordStrength.Poor,
33 | color: 'text-red-500'
34 | };
35 | }
36 |
37 | if (!/[a-z]/.test(password)) {
38 | return {
39 | label: PasswordStrength.FairPass,
40 | color: 'text-amber-500'
41 | };
42 | }
43 |
44 | if (!/[0-9]/.test(password)) {
45 | return {
46 | label: PasswordStrength.FairPass,
47 | color: 'text-amber-500'
48 | };
49 | }
50 |
51 | if (!/[!@#$%^&*()\-=_+[\]{}|;':",.<>/?]/.test(password)) {
52 | return {
53 | label: PasswordStrength.FairPass,
54 | color: 'text-amber-500'
55 | };
56 | }
57 |
58 | return {
59 | label: PasswordStrength.Pass,
60 | color: 'text-green-500'
61 | };
62 | }
63 |
--------------------------------------------------------------------------------
/src/lib/i18n/bn/index.ts:
--------------------------------------------------------------------------------
1 | import type { Translation } from '../i18n-types';
2 | import en from '../en';
3 |
4 | const productName = 'SvelteKit Stackter';
5 | const title = `${productName} - একটি বিশেষ Sveltekit প্রোডাকশন-রেডি শুরু করার টেমপ্লেট`;
6 | const description = `${productName} একটি প্রোডাকশন-রেডি শুরু করার টেমপ্লেট সবেলটেকিটের জন্য। টেলওইন্ড সিএসএস, shadcn-svelte UI লাইব্রেরি, সুপারফর্ম + ফর্মস্ন্যাপ, টাইপ-সেফ i18n, এসইও, লটি অ্যানিমেশন, ইমেজ কম্পোনেন্ট এবং অনেক কিছু সম্মিলিত এই আপ্রোচটি ব্যবহার করে, আপনি সেটআপের ঘাঁটি পার করতে এবং আপনার স্বপ্নগুলি বাস্তবে পরিণত করতে পারেন।`;
7 |
8 | const common = {
9 | login: 'লগইন',
10 | logout: 'লগআউট',
11 | signup: 'নিবন্ধন করুন',
12 | show: 'প্রদর্শন',
13 | hide: 'লুকান',
14 | or: 'অথবা'
15 | };
16 |
17 | const ar: Translation = {
18 | ...(en as Translation),
19 | appName: productName,
20 | title,
21 | description,
22 | keywords: `স্বেলটেকিট শুরু টেমপ্লেট, টেইলওইন্ড সিএসএস, শাদচেন স্বেলটে ইউআই লাইব্রেরি, সুপারফর্ম, ফর্মস্ন্যাপ, টাইপসেফ আই১৮ন, লটি অ্যানিমেশন, ইমেজ কম্পোনেন্ট, হাস্কি, টাইপস্ক্রিপ্ট, ভাইট, ${productName}`,
23 | appTwitterAccount: '@shamscorner',
24 |
25 | common,
26 |
27 | appLogo: {
28 | hrefTitle: description,
29 | alt: `${productName} লোগো`
30 | },
31 |
32 | schemaMarkup: {
33 | type: 'কর্পোরেশন',
34 | name: 'মেমোউয়াইজ ইংক।',
35 | markupDescription:
36 | 'মেমোউয়াইজ একটি সফটওয়্যার কোম্পানি যা মানুষদের সাহায্য করার জন্য প্রোডাক্ট তৈরি করে। আমরা একটি ছোট দল, উত্সাহী ডেভেলপার, ডিজাইনার এবং উদ্যমপাতি। আমরা ঢাকা, বাংলাদেশে বেস্ড।',
37 | founder: [
38 | {
39 | type: 'ব্যক্তি',
40 | name: 'শামিম হোসেন'
41 | },
42 | {
43 | type: 'ব্যক্তি',
44 | name: 'মাসুদ রানা'
45 | },
46 | {
47 | type: 'ব্যক্তি',
48 | name: 'শাদমান নাসিফ'
49 | }
50 | ],
51 | foundingDate: '2023-10-02',
52 | contactPoint: [
53 | {
54 | type: 'যোগাযোগ পয়েন্ট',
55 | email: 'memowiseinc@gmail.com',
56 | telephone: '',
57 | contactType: 'গ্রাহক সেবা'
58 | }
59 | ]
60 | },
61 |
62 | errorPage: {
63 | title: '404',
64 | subtitle: 'পাওয়া যায়নি',
65 | pageTitle: '404',
66 | description: 'সাহায্য খুঁজছেন? আমাদের সাথে যোগাযোগ করুন support@appdomain.com ঠিকানায়',
67 | keywords: 'সাহায্য, যোগাযোগ, সাহায্য, 404, পাওয়া যায়নি'
68 | },
69 |
70 | homepage: {
71 | title: 'একটি অনুসরণকারী এক হাজার অনুসরণকারীর মুল্যবান।',
72 | subtitle:
73 | 'দান গ্রহণ করুন। একটি সদস্যপদ শুরু করুন। আপনি যা ইচ্ছা তা বেচান - এটি আপনি চিন্তা করেছেন তা চেয়ে সহজ।'
74 | }
75 | };
76 |
77 | export default ar;
78 |
--------------------------------------------------------------------------------
/src/lib/i18n/en/index.ts:
--------------------------------------------------------------------------------
1 | import type { BaseTranslation } from '../i18n-types';
2 |
3 | const productName = 'SvelteKit Stackter';
4 | const title = `${productName} - An awesome Sveltekit Production ready starter template`;
5 | const description = `${productName} is a production ready starter template for Sveltekit. Discover this incredible SvelteKit production-ready starter template featuring Tailwind CSS, the shadcn-svelte UI library, Superform + Formsnap, type-safe i18n, SEO, Lottie animations, an Image component, and much more. With this template, you can bypass the setup hassle and concentrate on transforming your dreams into reality.`;
6 |
7 | const common = {
8 | login: 'Login',
9 | logout: 'Logout',
10 | signup: 'Sign up',
11 | show: 'Show',
12 | hide: 'Hide',
13 | or: 'Or',
14 | toggleTheme: 'Toggle theme'
15 | };
16 |
17 | const en: BaseTranslation = {
18 | appName: productName,
19 | title,
20 | description,
21 | keywords: `sveltekit starter template, tailwind css, shadcn svelte, superform, formsnap, typesafe i18n, lottie animation, image component husky, typescript, vite, ${productName}`,
22 | appTwitterAccount: '@shamscorner',
23 |
24 | common,
25 |
26 | appLogo: {
27 | hrefTitle: description,
28 | alt: `${productName} Logo`
29 | },
30 |
31 | schemaMarkup: {
32 | type: 'Corporation',
33 | name: 'Memowise Inc.',
34 | markupDescription:
35 | 'Memowise is a software company that builds products to help people. We are a small team of passionate developers, designers, and entrepreneurs. We are based in Dhaka, Bangladesh.',
36 | founder: [
37 | {
38 | type: 'Person',
39 | name: 'Shamim Hossain'
40 | },
41 | {
42 | type: 'Person',
43 | name: 'Masud Rana'
44 | },
45 | {
46 | type: 'Person',
47 | name: 'Shadman Nasif'
48 | }
49 | ],
50 | foundingDate: '2023-10-02',
51 | contactPoint: [
52 | {
53 | type: 'ContactPoint',
54 | email: 'memowiseinc@gmail.com',
55 | telephone: '',
56 | contactType: 'customer service'
57 | }
58 | ]
59 | },
60 |
61 | errorPage: {
62 | title: '404',
63 | subtitle: 'Not found',
64 | pageTitle: '404',
65 | description: 'Looking for help? Reach out to us at support@appdomain.com',
66 | keywords: 'Support, Contact, Help, 404, Not found'
67 | },
68 |
69 | homepage: {
70 | title: 'A production ready starter template for SvelteKit.',
71 | subtitle: description,
72 | features: 'Features',
73 |
74 | checkFormSubmission: 'Check form submission demo',
75 | goToLogin: 'Go to login page',
76 |
77 | checkGithub: 'Check Github Repo'
78 | },
79 |
80 | loginPage: {
81 | title: 'Welcome back!',
82 | pageTitle: 'Log in',
83 | description: 'Login to your account and start accepting donations, memberships, and more.',
84 | keywords: 'Login, Sign in, Log in, Sign up, Register',
85 |
86 | form: {
87 | email: 'Email',
88 | password: 'Password',
89 | submit: 'Log in',
90 | continueWith: 'Or continue with',
91 | dontHaveAccount: "Don't have an account?",
92 | signUpButton: 'Sign up',
93 | forgotPassword: 'Forgot password?',
94 | rememberMe: 'Remember me?'
95 | }
96 | },
97 |
98 | errors: {
99 | somethingWentWrong: 'Something went wrong'
100 | }
101 | };
102 |
103 | export default en;
104 |
--------------------------------------------------------------------------------
/src/lib/i18n/formatters.ts:
--------------------------------------------------------------------------------
1 | import type { FormattersInitializer } from 'typesafe-i18n';
2 | import type { Locales, Formatters } from './i18n-types';
3 |
4 | export const initFormatters: FormattersInitializer = () =>
5 | // locale: Locales
6 | {
7 | const formatters: Formatters = {
8 | // add your formatter functions here
9 | };
10 |
11 | return formatters;
12 | };
13 |
--------------------------------------------------------------------------------
/src/lib/i18n/i18n-svelte.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 |
4 | import { initI18nSvelte } from 'typesafe-i18n/svelte'
5 | import type { Formatters, Locales, TranslationFunctions, Translations } from './i18n-types'
6 | import { loadedFormatters, loadedLocales } from './i18n-util'
7 |
8 | const { locale, LL, setLocale } = initI18nSvelte(loadedLocales, loadedFormatters)
9 |
10 | export { locale, LL, setLocale }
11 |
12 | export default LL
13 |
--------------------------------------------------------------------------------
/src/lib/i18n/i18n-types.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 | import type { BaseTranslation as BaseTranslationType, LocalizedString } from 'typesafe-i18n'
4 |
5 | export type BaseTranslation = BaseTranslationType
6 | export type BaseLocale = 'en'
7 |
8 | export type Locales =
9 | | 'bn'
10 | | 'en'
11 |
12 | export type Translation = RootTranslation
13 |
14 | export type Translations = RootTranslation
15 |
16 | type RootTranslation = {
17 | /**
18 | * SvelteKit Stackter
19 | */
20 | appName: string
21 | /**
22 | * SvelteKit Stackter - An awesome Sveltekit Production ready starter template
23 | */
24 | title: string
25 | /**
26 | * SvelteKit Stackter is a production ready starter template for Sveltekit. Discover this incredible SvelteKit production-ready starter template featuring Tailwind CSS, the shadcn-svelte UI library, Superform + Formsnap, type-safe i18n, SEO, Lottie animations, an Image component, and much more. With this template, you can bypass the setup hassle and concentrate on transforming your dreams into reality.
27 | */
28 | description: string
29 | /**
30 | * sveltekit starter template, tailwind css, shadcn svelte, superform, formsnap, typesafe i18n, lottie animation, image component husky, typescript, vite, SvelteKit Stackter
31 | */
32 | keywords: string
33 | /**
34 | * @shamscorner
35 | */
36 | appTwitterAccount: string
37 | common: {
38 | /**
39 | * Login
40 | */
41 | login: string
42 | /**
43 | * Logout
44 | */
45 | logout: string
46 | /**
47 | * Sign up
48 | */
49 | signup: string
50 | /**
51 | * Show
52 | */
53 | show: string
54 | /**
55 | * Hide
56 | */
57 | hide: string
58 | /**
59 | * Or
60 | */
61 | or: string
62 | /**
63 | * Toggle theme
64 | */
65 | toggleTheme: string
66 | }
67 | appLogo: {
68 | /**
69 | * SvelteKit Stackter is a production ready starter template for Sveltekit. Discover this incredible SvelteKit production-ready starter template featuring Tailwind CSS, the shadcn-svelte UI library, Superform + Formsnap, type-safe i18n, SEO, Lottie animations, an Image component, and much more. With this template, you can bypass the setup hassle and concentrate on transforming your dreams into reality.
70 | */
71 | hrefTitle: string
72 | /**
73 | * SvelteKit Stackter Logo
74 | */
75 | alt: string
76 | }
77 | schemaMarkup: {
78 | /**
79 | * Corporation
80 | */
81 | type: string
82 | /**
83 | * Memowise Inc.
84 | */
85 | name: string
86 | /**
87 | * Memowise is a software company that builds products to help people. We are a small team of passionate developers, designers, and entrepreneurs. We are based in Dhaka, Bangladesh.
88 | */
89 | markupDescription: string
90 | founder: {
91 | '0': {
92 | /**
93 | * Person
94 | */
95 | type: string
96 | /**
97 | * Shamim Hossain
98 | */
99 | name: string
100 | }
101 | '1': {
102 | /**
103 | * Person
104 | */
105 | type: string
106 | /**
107 | * Masud Rana
108 | */
109 | name: string
110 | }
111 | '2': {
112 | /**
113 | * Person
114 | */
115 | type: string
116 | /**
117 | * Shadman Nasif
118 | */
119 | name: string
120 | }
121 | }
122 | /**
123 | * 2023-10-02
124 | */
125 | foundingDate: string
126 | contactPoint: {
127 | '0': {
128 | /**
129 | * ContactPoint
130 | */
131 | type: string
132 | /**
133 | * memowiseinc@gmail.com
134 | */
135 | email: string
136 | telephone: string
137 | /**
138 | * customer service
139 | */
140 | contactType: string
141 | }
142 | }
143 | }
144 | errorPage: {
145 | /**
146 | * 404
147 | */
148 | title: string
149 | /**
150 | * Not found
151 | */
152 | subtitle: string
153 | /**
154 | * 404
155 | */
156 | pageTitle: string
157 | /**
158 | * Looking for help? Reach out to us at support@appdomain.com
159 | */
160 | description: string
161 | /**
162 | * Support, Contact, Help, 404, Not found
163 | */
164 | keywords: string
165 | }
166 | homepage: {
167 | /**
168 | * A production ready starter template for SvelteKit.
169 | */
170 | title: string
171 | /**
172 | * SvelteKit Stackter is a production ready starter template for Sveltekit. Discover this incredible SvelteKit production-ready starter template featuring Tailwind CSS, the shadcn-svelte UI library, Superform + Formsnap, type-safe i18n, SEO, Lottie animations, an Image component, and much more. With this template, you can bypass the setup hassle and concentrate on transforming your dreams into reality.
173 | */
174 | subtitle: string
175 | /**
176 | * Features
177 | */
178 | features: string
179 | /**
180 | * Check form submission demo
181 | */
182 | checkFormSubmission: string
183 | /**
184 | * Go to login page
185 | */
186 | goToLogin: string
187 | /**
188 | * Check Github Repo
189 | */
190 | checkGithub: string
191 | }
192 | loginPage: {
193 | /**
194 | * Welcome back!
195 | */
196 | title: string
197 | /**
198 | * Log in
199 | */
200 | pageTitle: string
201 | /**
202 | * Login to your account and start accepting donations, memberships, and more.
203 | */
204 | description: string
205 | /**
206 | * Login, Sign in, Log in, Sign up, Register
207 | */
208 | keywords: string
209 | form: {
210 | /**
211 | * Email
212 | */
213 | email: string
214 | /**
215 | * Password
216 | */
217 | password: string
218 | /**
219 | * Log in
220 | */
221 | submit: string
222 | /**
223 | * Or continue with
224 | */
225 | continueWith: string
226 | /**
227 | * Don't have an account?
228 | */
229 | dontHaveAccount: string
230 | /**
231 | * Sign up
232 | */
233 | signUpButton: string
234 | /**
235 | * Forgot password?
236 | */
237 | forgotPassword: string
238 | /**
239 | * Remember me?
240 | */
241 | rememberMe: string
242 | }
243 | }
244 | errors: {
245 | /**
246 | * Something went wrong
247 | */
248 | somethingWentWrong: string
249 | }
250 | }
251 |
252 | export type TranslationFunctions = {
253 | /**
254 | * SvelteKit Stackter
255 | */
256 | appName: () => LocalizedString
257 | /**
258 | * SvelteKit Stackter - An awesome Sveltekit Production ready starter template
259 | */
260 | title: () => LocalizedString
261 | /**
262 | * SvelteKit Stackter is a production ready starter template for Sveltekit. Discover this incredible SvelteKit production-ready starter template featuring Tailwind CSS, the shadcn-svelte UI library, Superform + Formsnap, type-safe i18n, SEO, Lottie animations, an Image component, and much more. With this template, you can bypass the setup hassle and concentrate on transforming your dreams into reality.
263 | */
264 | description: () => LocalizedString
265 | /**
266 | * sveltekit starter template, tailwind css, shadcn svelte, superform, formsnap, typesafe i18n, lottie animation, image component husky, typescript, vite, SvelteKit Stackter
267 | */
268 | keywords: () => LocalizedString
269 | /**
270 | * @shamscorner
271 | */
272 | appTwitterAccount: () => LocalizedString
273 | common: {
274 | /**
275 | * Login
276 | */
277 | login: () => LocalizedString
278 | /**
279 | * Logout
280 | */
281 | logout: () => LocalizedString
282 | /**
283 | * Sign up
284 | */
285 | signup: () => LocalizedString
286 | /**
287 | * Show
288 | */
289 | show: () => LocalizedString
290 | /**
291 | * Hide
292 | */
293 | hide: () => LocalizedString
294 | /**
295 | * Or
296 | */
297 | or: () => LocalizedString
298 | /**
299 | * Toggle theme
300 | */
301 | toggleTheme: () => LocalizedString
302 | }
303 | appLogo: {
304 | /**
305 | * SvelteKit Stackter is a production ready starter template for Sveltekit. Discover this incredible SvelteKit production-ready starter template featuring Tailwind CSS, the shadcn-svelte UI library, Superform + Formsnap, type-safe i18n, SEO, Lottie animations, an Image component, and much more. With this template, you can bypass the setup hassle and concentrate on transforming your dreams into reality.
306 | */
307 | hrefTitle: () => LocalizedString
308 | /**
309 | * SvelteKit Stackter Logo
310 | */
311 | alt: () => LocalizedString
312 | }
313 | schemaMarkup: {
314 | /**
315 | * Corporation
316 | */
317 | type: () => LocalizedString
318 | /**
319 | * Memowise Inc.
320 | */
321 | name: () => LocalizedString
322 | /**
323 | * Memowise is a software company that builds products to help people. We are a small team of passionate developers, designers, and entrepreneurs. We are based in Dhaka, Bangladesh.
324 | */
325 | markupDescription: () => LocalizedString
326 | founder: {
327 | '0': {
328 | /**
329 | * Person
330 | */
331 | type: () => LocalizedString
332 | /**
333 | * Shamim Hossain
334 | */
335 | name: () => LocalizedString
336 | }
337 | '1': {
338 | /**
339 | * Person
340 | */
341 | type: () => LocalizedString
342 | /**
343 | * Masud Rana
344 | */
345 | name: () => LocalizedString
346 | }
347 | '2': {
348 | /**
349 | * Person
350 | */
351 | type: () => LocalizedString
352 | /**
353 | * Shadman Nasif
354 | */
355 | name: () => LocalizedString
356 | }
357 | }
358 | /**
359 | * 2023-10-02
360 | */
361 | foundingDate: () => LocalizedString
362 | contactPoint: {
363 | '0': {
364 | /**
365 | * ContactPoint
366 | */
367 | type: () => LocalizedString
368 | /**
369 | * memowiseinc@gmail.com
370 | */
371 | email: () => LocalizedString
372 | telephone: () => LocalizedString
373 | /**
374 | * customer service
375 | */
376 | contactType: () => LocalizedString
377 | }
378 | }
379 | }
380 | errorPage: {
381 | /**
382 | * 404
383 | */
384 | title: () => LocalizedString
385 | /**
386 | * Not found
387 | */
388 | subtitle: () => LocalizedString
389 | /**
390 | * 404
391 | */
392 | pageTitle: () => LocalizedString
393 | /**
394 | * Looking for help? Reach out to us at support@appdomain.com
395 | */
396 | description: () => LocalizedString
397 | /**
398 | * Support, Contact, Help, 404, Not found
399 | */
400 | keywords: () => LocalizedString
401 | }
402 | homepage: {
403 | /**
404 | * A production ready starter template for SvelteKit.
405 | */
406 | title: () => LocalizedString
407 | /**
408 | * SvelteKit Stackter is a production ready starter template for Sveltekit. Discover this incredible SvelteKit production-ready starter template featuring Tailwind CSS, the shadcn-svelte UI library, Superform + Formsnap, type-safe i18n, SEO, Lottie animations, an Image component, and much more. With this template, you can bypass the setup hassle and concentrate on transforming your dreams into reality.
409 | */
410 | subtitle: () => LocalizedString
411 | /**
412 | * Features
413 | */
414 | features: () => LocalizedString
415 | /**
416 | * Check form submission demo
417 | */
418 | checkFormSubmission: () => LocalizedString
419 | /**
420 | * Go to login page
421 | */
422 | goToLogin: () => LocalizedString
423 | /**
424 | * Check Github Repo
425 | */
426 | checkGithub: () => LocalizedString
427 | }
428 | loginPage: {
429 | /**
430 | * Welcome back!
431 | */
432 | title: () => LocalizedString
433 | /**
434 | * Log in
435 | */
436 | pageTitle: () => LocalizedString
437 | /**
438 | * Login to your account and start accepting donations, memberships, and more.
439 | */
440 | description: () => LocalizedString
441 | /**
442 | * Login, Sign in, Log in, Sign up, Register
443 | */
444 | keywords: () => LocalizedString
445 | form: {
446 | /**
447 | * Email
448 | */
449 | email: () => LocalizedString
450 | /**
451 | * Password
452 | */
453 | password: () => LocalizedString
454 | /**
455 | * Log in
456 | */
457 | submit: () => LocalizedString
458 | /**
459 | * Or continue with
460 | */
461 | continueWith: () => LocalizedString
462 | /**
463 | * Don't have an account?
464 | */
465 | dontHaveAccount: () => LocalizedString
466 | /**
467 | * Sign up
468 | */
469 | signUpButton: () => LocalizedString
470 | /**
471 | * Forgot password?
472 | */
473 | forgotPassword: () => LocalizedString
474 | /**
475 | * Remember me?
476 | */
477 | rememberMe: () => LocalizedString
478 | }
479 | }
480 | errors: {
481 | /**
482 | * Something went wrong
483 | */
484 | somethingWentWrong: () => LocalizedString
485 | }
486 | }
487 |
488 | export type Formatters = {}
489 |
--------------------------------------------------------------------------------
/src/lib/i18n/i18n-util.async.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 |
4 | import { initFormatters } from './formatters'
5 | import type { Locales, Translations } from './i18n-types'
6 | import { loadedFormatters, loadedLocales, locales } from './i18n-util'
7 |
8 | const localeTranslationLoaders = {
9 | bn: () => import('./bn'),
10 | en: () => import('./en'),
11 | }
12 |
13 | const updateDictionary = (locale: Locales, dictionary: Partial): Translations =>
14 | loadedLocales[locale] = { ...loadedLocales[locale], ...dictionary }
15 |
16 | export const importLocaleAsync = async (locale: Locales): Promise =>
17 | (await localeTranslationLoaders[locale]()).default as unknown as Translations
18 |
19 | export const loadLocaleAsync = async (locale: Locales): Promise => {
20 | updateDictionary(locale, await importLocaleAsync(locale))
21 | loadFormatters(locale)
22 | }
23 |
24 | export const loadAllLocalesAsync = (): Promise => Promise.all(locales.map(loadLocaleAsync))
25 |
26 | export const loadFormatters = (locale: Locales): void =>
27 | void (loadedFormatters[locale] = initFormatters(locale))
28 |
--------------------------------------------------------------------------------
/src/lib/i18n/i18n-util.sync.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 |
4 | import { initFormatters } from './formatters'
5 | import type { Locales, Translations } from './i18n-types'
6 | import { loadedFormatters, loadedLocales, locales } from './i18n-util'
7 |
8 | import bn from './bn'
9 | import en from './en'
10 |
11 | const localeTranslations = {
12 | bn,
13 | en,
14 | }
15 |
16 | export const loadLocale = (locale: Locales): void => {
17 | if (loadedLocales[locale]) return
18 |
19 | loadedLocales[locale] = localeTranslations[locale] as unknown as Translations
20 | loadFormatters(locale)
21 | }
22 |
23 | export const loadAllLocales = (): void => locales.forEach(loadLocale)
24 |
25 | export const loadFormatters = (locale: Locales): void =>
26 | void (loadedFormatters[locale] = initFormatters(locale))
27 |
--------------------------------------------------------------------------------
/src/lib/i18n/i18n-util.ts:
--------------------------------------------------------------------------------
1 | // This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
2 | /* eslint-disable */
3 |
4 | import { i18n as initI18n, i18nObject as initI18nObject, i18nString as initI18nString } from 'typesafe-i18n'
5 | import type { LocaleDetector } from 'typesafe-i18n/detectors'
6 | import type { LocaleTranslationFunctions, TranslateByString } from 'typesafe-i18n'
7 | import { detectLocale as detectLocaleFn } from 'typesafe-i18n/detectors'
8 | import { initExtendDictionary } from 'typesafe-i18n/utils'
9 | import type { Formatters, Locales, Translations, TranslationFunctions } from './i18n-types'
10 |
11 | export const baseLocale: Locales = 'en'
12 |
13 | export const locales: Locales[] = [
14 | 'bn',
15 | 'en'
16 | ]
17 |
18 | export const isLocale = (locale: string): locale is Locales => locales.includes(locale as Locales)
19 |
20 | export const loadedLocales: Record = {} as Record
21 |
22 | export const loadedFormatters: Record = {} as Record
23 |
24 | export const extendDictionary = initExtendDictionary()
25 |
26 | export const i18nString = (locale: Locales): TranslateByString => initI18nString(locale, loadedFormatters[locale])
27 |
28 | export const i18nObject = (locale: Locales): TranslationFunctions =>
29 | initI18nObject(
30 | locale,
31 | loadedLocales[locale],
32 | loadedFormatters[locale]
33 | )
34 |
35 | export const i18n = (): LocaleTranslationFunctions =>
36 | initI18n(loadedLocales, loadedFormatters)
37 |
38 | export const detectLocale = (...detectors: LocaleDetector[]): Locales => detectLocaleFn(baseLocale, locales, ...detectors)
39 |
--------------------------------------------------------------------------------
/src/lib/services/error.service.ts:
--------------------------------------------------------------------------------
1 | export function getEmptyErrorResponse(errorMessage: string) {
2 | return {
3 | message: errorMessage,
4 | code: 422,
5 | response: '',
6 | type: 'unknown',
7 | name: 'Unknown'
8 | };
9 | }
10 |
11 | export type ErrorResponseType = ReturnType;
12 |
--------------------------------------------------------------------------------
/src/lib/types/index.ts:
--------------------------------------------------------------------------------
1 | export type linkTarget = '_blank' | '_self' | '_parent' | '_top';
2 |
3 | export type FpType = {
4 | landing: string;
5 | referrer: string;
6 | referrerUrl: string;
7 | ua: string;
8 | rc: string;
9 | };
10 |
11 | export type AnalyticsDto = {
12 | browserHash: string;
13 | landingPage: string;
14 | userAgent: string;
15 | isIncognitoMode: boolean;
16 | referralSiteUrl?: string | null;
17 | };
18 |
--------------------------------------------------------------------------------
/src/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { cubicOut } from 'svelte/easing';
2 | import type { TransitionConfig } from 'svelte/transition';
3 | import { type ClassValue, clsx } from 'clsx';
4 | import { twMerge } from 'tailwind-merge';
5 |
6 | export function cn(...inputs: ClassValue[]) {
7 | return twMerge(clsx(inputs));
8 | }
9 |
10 | type FlyAndScaleParams = {
11 | y?: number;
12 | x?: number;
13 | start?: number;
14 | duration?: number;
15 | };
16 |
17 | export const flyAndScale = (
18 | node: Element,
19 | params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }
20 | ): TransitionConfig => {
21 | const style = getComputedStyle(node);
22 | const transform = style.transform === 'none' ? '' : style.transform;
23 |
24 | const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
25 | const [minA, maxA] = scaleA;
26 | const [minB, maxB] = scaleB;
27 |
28 | const percentage = (valueA - minA) / (maxA - minA);
29 | const valueB = percentage * (maxB - minB) + minB;
30 |
31 | return valueB;
32 | };
33 |
34 | const styleToString = (style: Record): string => {
35 | return Object.keys(style).reduce((str, key) => {
36 | if (style[key] === undefined) return str;
37 | return str + `${key}:${style[key]};`;
38 | }, '');
39 | };
40 |
41 | return {
42 | duration: params.duration ?? 200,
43 | delay: 0,
44 | css: (t) => {
45 | const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]);
46 | const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]);
47 | const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]);
48 |
49 | return styleToString({
50 | transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
51 | opacity: t
52 | });
53 | },
54 | easing: cubicOut
55 | };
56 | };
57 |
--------------------------------------------------------------------------------
/src/routes/(auth)/login/+page.server.ts:
--------------------------------------------------------------------------------
1 | import { fail } from '@sveltejs/kit';
2 |
3 | import { zod } from 'sveltekit-superforms/adapters';
4 | import { superValidate } from 'sveltekit-superforms/server';
5 |
6 | import type { Actions, PageServerLoad } from './$types';
7 | import { formSchema } from './schema';
8 |
9 | export const load: PageServerLoad = async () => {
10 | return {
11 | form: await superValidate(zod(formSchema))
12 | };
13 | };
14 |
15 | export const actions: Actions = {
16 | default: async (event) => {
17 | const form = await superValidate(event, zod(formSchema));
18 |
19 | if (!form.valid) {
20 | return fail(400, {
21 | form
22 | });
23 | }
24 |
25 | // Simulate a slow response
26 | // Add your logic here
27 | await new Promise((resolve) => setTimeout(resolve, 2000));
28 |
29 | return { form };
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/src/routes/(auth)/login/+page.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/routes/(auth)/login/components/login-form.svelte:
--------------------------------------------------------------------------------
1 |
98 |
99 |
100 |
101 | {$LL.loginPage.title()}
102 |
103 |
104 |
109 |
110 | {$LL.loginPage.form.email()}
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | {$LL.loginPage.form.password()}
119 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | {errorResponse?.message || $LL.errors.somethingWentWrong()}
136 |
137 |
138 |
139 | {#if isLoadingFormSubmit}
140 |
141 | {/if}
142 | {$LL.loginPage.form.submit()}
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | {$LL.loginPage.form.continueWith()}
153 |
154 |
155 |
156 |
157 |
171 |
172 |
173 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/src/routes/(auth)/login/helpers/index.ts:
--------------------------------------------------------------------------------
1 | export const saveLastLoginEmail = (email: string): void => {
2 | localStorage.setItem('lastLoginEmail', email);
3 | };
4 |
5 | export const getLastLoginEmail = (): string | null => {
6 | return localStorage.getItem('lastLoginEmail');
7 | };
8 |
9 | export const deleteLastLoginEmail = (): void => {
10 | localStorage.removeItem('lastLoginEmail');
11 | };
12 |
--------------------------------------------------------------------------------
/src/routes/(auth)/login/schema.ts:
--------------------------------------------------------------------------------
1 | import { z } from 'zod';
2 |
3 | export const formSchema = z.object({
4 | email: z.string().max(100, 'Max 100 characters').email(),
5 | password: z
6 | .string()
7 | .max(50, {
8 | message: 'Max 50 characters'
9 | })
10 | .min(1, 'Required'),
11 | userAgent: z.string().optional(),
12 | browserHash: z.string().optional(),
13 | isIncognitoMode: z.boolean().optional().default(false)
14 | });
15 |
16 | export type FormSchema = typeof formSchema;
17 |
--------------------------------------------------------------------------------
/src/routes/+error.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
14 | {$page.status}
15 | {$page.error?.message}!
16 |
17 |
--------------------------------------------------------------------------------
/src/routes/+layout.server.ts:
--------------------------------------------------------------------------------
1 | import type { LayoutServerLoad } from './$types';
2 |
3 | export const load = (async ({ locals }) => {
4 | return {
5 | locale: locals.locale
6 | };
7 | }) satisfies LayoutServerLoad;
8 |
--------------------------------------------------------------------------------
/src/routes/+layout.svelte:
--------------------------------------------------------------------------------
1 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/routes/+layout.ts:
--------------------------------------------------------------------------------
1 | import { loadLocaleAsync } from '$lib/i18n/i18n-util.async';
2 |
3 | import type { LayoutLoad } from './$types';
4 |
5 | export const load = (async (event) => {
6 | const { locale } = event.data;
7 | await loadLocaleAsync(locale);
8 |
9 | return event.data as App.Locals;
10 | }) satisfies LayoutLoad;
11 |
--------------------------------------------------------------------------------
/src/routes/+page.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 | {$LL.homepage.subtitle()}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
{$LL.homepage.features()}:
32 |
33 | -
34 | Tailwind CSS
35 |
36 | -
37 | shadcn-svelte UI library
38 |
39 | -
40 | Superforms for auto form validation
41 | and SSR submission
42 |
43 | -
44 | Formsnap for auto form building
45 |
46 | -
47 | lottie-web to show
48 | awesome animations
49 |
50 | -
51 | Lucide Icons an awesome icon pack with ease
52 | setup
53 |
54 | -
55 | Typesafe i18n
56 | for better i18n experience with SSR support
57 |
58 | -
59 | Taze to update dependencies
60 | with one command
61 |
62 | -
63 | Husky + (lint-staged) to
64 | improve commits & formatting
65 |
66 | -
67 | Fingerprintjs to generate browser hash
70 |
71 | -
72 |
73 | React equivalent Image component
74 |
75 |
76 | -
77 | Fontaine for better
78 | font fallback
79 |
80 | - Google Tag support
81 | - Eslint & Prettier for better code formatting
82 | - Tailwind CSS auto class sorting with prettier
83 | - pnpm by default
84 | - of course VITE and Typescript
85 |
86 |
87 |
88 |
95 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | {$LL.homepage.checkFormSubmission()}
110 |
111 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
129 |
--------------------------------------------------------------------------------
/src/routes/components/footer/Footer.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
29 |
--------------------------------------------------------------------------------
/src/routes/components/navbar/Navbar.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
26 |
--------------------------------------------------------------------------------
/static/android-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/android-icon-144x144.png
--------------------------------------------------------------------------------
/static/android-icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/android-icon-192x192.png
--------------------------------------------------------------------------------
/static/android-icon-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/android-icon-36x36.png
--------------------------------------------------------------------------------
/static/android-icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/android-icon-48x48.png
--------------------------------------------------------------------------------
/static/android-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/android-icon-72x72.png
--------------------------------------------------------------------------------
/static/android-icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/android-icon-96x96.png
--------------------------------------------------------------------------------
/static/apple-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-114x114.png
--------------------------------------------------------------------------------
/static/apple-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-120x120.png
--------------------------------------------------------------------------------
/static/apple-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-144x144.png
--------------------------------------------------------------------------------
/static/apple-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-152x152.png
--------------------------------------------------------------------------------
/static/apple-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-180x180.png
--------------------------------------------------------------------------------
/static/apple-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-57x57.png
--------------------------------------------------------------------------------
/static/apple-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-60x60.png
--------------------------------------------------------------------------------
/static/apple-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-72x72.png
--------------------------------------------------------------------------------
/static/apple-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-76x76.png
--------------------------------------------------------------------------------
/static/apple-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon-precomposed.png
--------------------------------------------------------------------------------
/static/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-icon.png
--------------------------------------------------------------------------------
/static/apple-touch-icon-120x120-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-touch-icon-120x120-precomposed.png
--------------------------------------------------------------------------------
/static/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/static/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/static/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/apple-touch-icon.png
--------------------------------------------------------------------------------
/static/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 | #ffffff
--------------------------------------------------------------------------------
/static/company-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/company-logo.jpg
--------------------------------------------------------------------------------
/static/company-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
129 |
--------------------------------------------------------------------------------
/static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/favicon-16x16.png
--------------------------------------------------------------------------------
/static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/favicon-32x32.png
--------------------------------------------------------------------------------
/static/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/favicon-96x96.png
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/favicon.ico
--------------------------------------------------------------------------------
/static/fonts/poppins-bold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-bold-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-bold-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-bold-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-bolditalic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-bolditalic-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-bolditalic-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-bolditalic-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-extrabold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-extrabold-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-extrabold-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-extrabold-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-italic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-italic-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-italic-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-italic-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-light-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-light-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-light-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-light-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-medium-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-medium-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-medium-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-medium-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-regular-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-regular-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-regular-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-regular-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-semibold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-semibold-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-semibold-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-semibold-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-semibolditalic-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-semibolditalic-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-semibolditalic-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-semibolditalic-webfont.woff2
--------------------------------------------------------------------------------
/static/fonts/poppins-thin-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-thin-webfont.woff
--------------------------------------------------------------------------------
/static/fonts/poppins-thin-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/fonts/poppins-thin-webfont.woff2
--------------------------------------------------------------------------------
/static/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "SvelteKit Stackter",
3 | "icons": [
4 | {
5 | "src": "/android-icon-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image/png",
8 | "density": "0.75"
9 | },
10 | {
11 | "src": "/android-icon-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image/png",
14 | "density": "1.0"
15 | },
16 | {
17 | "src": "/android-icon-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image/png",
20 | "density": "1.5"
21 | },
22 | {
23 | "src": "/android-icon-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image/png",
26 | "density": "2.0"
27 | },
28 | {
29 | "src": "/android-icon-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image/png",
32 | "density": "3.0"
33 | },
34 | {
35 | "src": "/android-icon-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image/png",
38 | "density": "4.0"
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/static/ms-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/ms-icon-144x144.png
--------------------------------------------------------------------------------
/static/ms-icon-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/ms-icon-150x150.png
--------------------------------------------------------------------------------
/static/ms-icon-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/ms-icon-310x310.png
--------------------------------------------------------------------------------
/static/ms-icon-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shamscorner/sveltekit-stackter/940f2c172f703aed5afb585ded698eb721104042/static/ms-icon-70x70.png
--------------------------------------------------------------------------------
/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from '@sveltejs/adapter-vercel';
2 | import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
7 | // for more information about preprocessors
8 | preprocess: vitePreprocess(),
9 |
10 | kit: {
11 | // See https://kit.svelte.dev/docs/adapters for more information about adapters.
12 | adapter: adapter()
13 | }
14 | };
15 |
16 | export default config;
17 |
--------------------------------------------------------------------------------
/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | import { fontFamily } from 'tailwindcss/defaultTheme';
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | const config = {
5 | darkMode: 'selector',
6 | content: ['./src/**/*.{html,js,svelte,ts}'],
7 | safelist: ['dark'],
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 | light: 'hsl(var(--secondary-light))'
31 | },
32 | destructive: {
33 | DEFAULT: 'hsl(var(--destructive))',
34 | foreground: 'hsl(var(--destructive-foreground))'
35 | },
36 | muted: {
37 | DEFAULT: 'hsl(var(--muted))',
38 | foreground: 'hsl(var(--muted-foreground))'
39 | },
40 | accent: {
41 | DEFAULT: 'hsl(var(--accent))',
42 | foreground: 'hsl(var(--accent-foreground))'
43 | },
44 | popover: {
45 | DEFAULT: 'hsl(var(--popover))',
46 | foreground: 'hsl(var(--popover-foreground))'
47 | },
48 | card: {
49 | DEFAULT: 'hsl(var(--card))',
50 | foreground: 'hsl(var(--card-foreground))'
51 | }
52 | },
53 | borderRadius: {
54 | lg: 'var(--radius)',
55 | md: 'calc(var(--radius) - 2px)',
56 | sm: 'calc(var(--radius) - 4px)'
57 | },
58 | fontFamily: {
59 | sans: ['Poppins', ...fontFamily.sans]
60 | }
61 | }
62 | }
63 | };
64 |
65 | export default config;
66 |
--------------------------------------------------------------------------------
/tests/example.spec.ts:
--------------------------------------------------------------------------------
1 | import { expect, test } from '@playwright/test';
2 |
3 | test('index page has expected h1', async ({ page }) => {
4 | await page.goto('/');
5 | await expect(
6 | page.getByRole('heading', {
7 | name: 'A production ready starter template for SvelteKit.'
8 | })
9 | ).toBeVisible();
10 | });
11 |
--------------------------------------------------------------------------------
/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 | "noImplicitAny": false
13 | }
14 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
15 | //
16 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
17 | // from the referenced tsconfig.json - TypeScript does not merge them in
18 | }
19 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from '@sveltejs/kit/vite';
2 | import { imagetools } from '@zerodevx/svelte-img/vite';
3 | // import { join, resolve } from 'path';
4 | import { FontaineTransform } from 'fontaine';
5 | import { resolve } from 'path';
6 | import { defineConfig } from 'vitest/config';
7 | // import { partytownVite } from '@builder.io/partytown/utils';
8 |
9 | export default defineConfig({
10 | ssr: {
11 | noExternal: ['typesafe-i18n']
12 | },
13 | test: {
14 | include: ['src/**/*.{test,spec}.{js,ts}']
15 | },
16 | resolve: {
17 | alias: {
18 | $: resolve('./src')
19 | }
20 | },
21 | plugins: [
22 | sveltekit(),
23 |
24 | FontaineTransform.vite({
25 | fallbacks: ['BlinkMacSystemFont', 'Segoe UI', 'Helvetica Neue', 'Arial', 'Noto Sans'],
26 | resolvePath: (id) => new URL('.' + id, import.meta.url)
27 | }),
28 |
29 | imagetools()
30 |
31 | // partytownVite({
32 | // dest: join(process.cwd(), '.svelte-kit/output/client/~partytown')
33 | // })
34 | ]
35 | });
36 |
--------------------------------------------------------------------------------