This commit is contained in:
Huakun Shen 2025-02-24 04:29:10 -05:00
commit d0ae1de4fa
No known key found for this signature in database
29 changed files with 1957 additions and 0 deletions

38
.github/workflows/npm-publish.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: NPM Package Publish
on:
push:
branches: [main]
release:
types: [created]
workflow_dispatch:
jobs:
publish-npm:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v4
with:
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
- run: bun install
- run: |
bun run build
bun build.ts
- name: Check if version is already published
run: |
PACKAGE_VERSION=$(node -p "require('./package.json').version")
PACKAGE_NAME=$(jq -r '.name' package.json)
npm view $PACKAGE_NAME@$PACKAGE_VERSION
continue-on-error: true
id: check_version
- name: Publish
if: steps.check_version.outcome != 'success'
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
node_modules
# Output
.output
.vercel
/.svelte-kit
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
extensions_support/
headless-dist

1
.npmrc Normal file
View File

@ -0,0 +1 @@
engine-strict=true

4
.prettierignore Normal file
View File

@ -0,0 +1,4 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock

15
.prettierrc Normal file
View File

@ -0,0 +1,15 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}

57
CHANGELOG.md Normal file
View File

@ -0,0 +1,57 @@
# template-ext-sveltekit
## 0.0.9
### Patch Changes
- Updated dependencies
- @kksh/api@0.1.2
## 0.0.8
### Patch Changes
- Updated dependencies
- @kksh/api@0.1.1
## 0.0.7
### Patch Changes
- Updated dependencies
- @kksh/api@0.1.0
## 0.0.6
### Patch Changes
- Updated dependencies
- @kksh/api@0.0.53
## 0.0.5
### Patch Changes
- Updated dependencies
- @kksh/api@0.0.48
## 0.0.4
### Patch Changes
- Updated dependencies
- @kksh/api@0.0.47
## 0.0.3
### Patch Changes
- Updated dependencies
- @kksh/api@0.0.4
## 0.0.2
### Patch Changes
- Updated dependencies [fba6a49]
- @kksh/svelte@0.0.2

43
README.md Normal file
View File

@ -0,0 +1,43 @@
# Kunkun Custom UI Extension Template (SvelteKit)
[Custom UI Extension Documentation](https://docs.kunkun.sh/extensions/custom-ui-ext/)
This is a template for a custom UI extension.
This type of extension is basically a static website. You can use any frontend framework you like, this template uses [SvelteKit](https://svelte.dev/).
It is assumed that you have some knowledge of frontend development with SvelteKit.
## Development
Development is the same as developing a normal website.
```bash
pnpm install
pnpm dev
pnpm build
```
- To develop and preview the extension in Kunkun, you need to run the `Add Dev Extension` command in Kunkun, and register this extension's path.
In `package.json`, `"devMain"` is the url for development server, and `"main"` is the path to static `.html` file for production.
To load the extension in development mode, you have to enable it with `Toggle Dev Extension Live Load Mode` command in Kunkun. A `Live` badge will be shown on the commands. This indicates that dev extensions will be loaded from `devMain` instead of `main`.
## Advanced
### Rendering Mode
This is a Meta-Framework template, and already configured with SSG rendering mode.
Please do not enable SSR unless you know what you are doing.
There will not be a JS runtime in production, and Kunkun always load the extension as static files.
The main benefit of using a meta-framework is that it comes with routing, and will output multiple `.html` files, which makes multi-command support much easier.
## Verify Build and Publish
```bash
npx kksh@latest verify --publish # run basic verification
```
See [Documentation](https://docs.kunkun.sh/guides/extensions/publish/design/) for more details on how to publish your extension. You will need to publish your extension package to npm or jsr first with GitHub actioin, then register it on Kunkun's website.

30
build.ts Normal file
View File

@ -0,0 +1,30 @@
import { watch } from 'fs';
import { join } from 'path';
import { refreshTemplateWorkerCommand } from '@kksh/api/dev';
import { $ } from 'bun';
const entrypoints = ['./headless-src/index.ts'];
async function build() {
try {
for (const entrypoint of entrypoints) {
await $`bun build --minify --target=browser --outdir=./headless-dist ${entrypoint}`;
}
if (Bun.argv.includes('dev')) {
await refreshTemplateWorkerCommand();
}
} catch (error) {
console.error(error);
}
}
const srcDir = join(import.meta.dir, 'headless-src');
await build();
if (Bun.argv.includes('dev')) {
console.log(`Watching ${srcDir} for changes...`);
watch(srcDir, { recursive: true }, async (event, filename) => {
await build();
});
}

1207
bun.lock Normal file

File diff suppressed because it is too large Load Diff

14
components.json Normal file
View File

@ -0,0 +1,14 @@
{
"$schema": "https://shadcn-svelte.com/schema.json",
"style": "new-york",
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app.css",
"baseColor": "neutral"
},
"aliases": {
"components": "$lib/components",
"utils": "$lib/utils"
},
"typescript": true
}

33
eslint.config.js Normal file
View File

@ -0,0 +1,33 @@
import js from '@eslint/js';
import ts from 'typescript-eslint';
import svelte from 'eslint-plugin-svelte';
import prettier from 'eslint-config-prettier';
import globals from 'globals';
/** @type {import('eslint').Linter.Config[]} */
export default [
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs['flat/recommended'],
prettier,
...svelte.configs['flat/prettier'],
{
languageOptions: {
globals: {
...globals.browser,
...globals.node
}
}
},
{
files: ['**/*.svelte'],
languageOptions: {
parserOptions: {
parser: ts.parser
}
}
},
{
ignores: ['build/', '.svelte-kit/', 'dist/']
}
];

19
headless-src/index.ts Normal file
View File

@ -0,0 +1,19 @@
import { clipboard, expose, HeadlessCommand, toast } from '@kksh/api/headless';
const rawTestString = `{"version":"0.1.27","notes":"See the assets to download this version and install.","pub_date":"2025-02-22T13:51:47.306Z","platforms":{"darwin-aarch64":{"signature":"dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVTRDFLZzdicjlNZFJ3N0ZYaVdzdzVGSzVxUXNWejVMcVJJeWRvTkN2NytYWSs0azlXV3kwZlgyNVpnMHh0OE9XZmdxL0l2bk1wUzBZckQzUTgyaHNyTytTRHFncmxRMUFJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzQwMjMxNjI1CWZpbGU6a3Vua3VuLmFwcC50YXIuZ3oKcFBJaFJuTzFua1UrcjNLT2lYelptL0kzOE8yWHRzNkFXK2lJNzJvQ2xWOFY0U2JWNTY4bmc3TUV5Unh6U0pNaWt6cEE5UkRYS0FzSzNJampXMzBiQlE9PQo=","url":"https://download.kunkun.sh/Kunkun-v0.1.27/kunkun_aarch64.app.tar.gz"},"linux-x86_64":{"signature":"dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVTRDFLZzdicjlNZFV0NGRRcVlrVnppZnVVZE5BYXJKZzdVaCt2ZnJKT0NzQkRqT0FmWU5CV3h5REwvb3hybE1jazFVMk1GQTNxeGw5eERMTXFnMGVNRk85WmMyaXJkK2djPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzQwMjMxNzc1CWZpbGU6a3Vua3VuXzAuMS4yN19hbWQ2NC5BcHBJbWFnZQpRVVFnMm5nRHU1alpXSnF5Y2xVUFN2UjZvRzJIN3NVQzRLakpoUEpSbzV2K0lLSzhLb3QxU1RtWmNZQVdJNWxpdzVxRzJwb25IdFRYUUNUdDE2b3NBQT09Cg==","url":"https://download.kunkun.sh/Kunkun-v0.1.27/kunkun_0.1.27_amd64.AppImage"},"darwin-x86_64":{"signature":"dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVTRDFLZzdicjlNZFNEUlJvTXF4K0oyaGlCekRPSTNuZGIvbmYwRSs5ZFJvbmgyL3F0UldTZFVqN3A5MTdwZENyMDI0OCtQdzdZQ0N6Y3cyeEQwekRXTFpJRHdhSENtNEFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzQwMjMxOTU5CWZpbGU6a3Vua3VuLmFwcC50YXIuZ3oKSHhjeG5MKzg4dkZJdm5oZ2p5amIraVB4bHdNMjFReWN0aTMrNVB2c0lSMWU4RUd3aEdEUW1BbUk3UDNDNHNHSUFubFpyTjRFck0xSFBFRDY3b2FHQkE9PQo=","url":"https://download.kunkun.sh/Kunkun-v0.1.27/kunkun_x64.app.tar.gz"},"windows-x86_64":{"signature":"dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVTRDFLZzdicjlNZFFnV2NPVlNwRnlQS2tFWnJvbU40ZG9XaUp6RWhINHhnRGxZOVplSWNzbFh1Y3J6NU9CVmtPUGE3cE5OelUxRzVzVTZkWFJUQ1RydFBWOWdaTlZuRXc0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzQwMjMyMzA0CWZpbGU6a3Vua3VuXzAuMS4yN194NjRfZW4tVVMubXNpCmQ1RWVQeGpuTzNuOVZoV1VoeVlYYkJ0Z1ducnFkRm83R0dmc3V5KzYyUHlzVytCNHlBcmlNbVlTcjBXNUFFdGEzTFJPcG9zTTgyaGkrQ0RwMjFRTEJnPT0K","url":"https://download.kunkun.sh/Kunkun-v0.1.27/kunkun_0.1.27_x64_en-US.msi"}}}`;
class JSONFormatter extends HeadlessCommand {
async load() {
try {
const text = await clipboard.readText();
const json = JSON.parse(text);
await clipboard.writeText(JSON.stringify(json, null, 2));
await toast.success('JSON formatted');
} catch (error) {
console.error(error);
toast.error('Failed to format JSON');
}
}
}
expose(new JSONFormatter());

89
package.json Normal file
View File

@ -0,0 +1,89 @@
{
"$schema": "https://schema.kunkun.sh",
"name": "kunkun-ext-json",
"version": "0.0.9",
"license": "MIT",
"kunkun": {
"name": "JSON Formatter/Inspector",
"shortDescription": "JSON Formatter/Inspector",
"longDescription": "JSON Formatter/Inspector",
"identifier": "kunkun-ext-json",
"icon": {
"type": "iconify",
"value": "tabler:json"
},
"demoImages": [],
"permissions": [
"clipboard:write-text",
"clipboard:read-text"
],
"customUiCmds": [
{
"main": "/",
"dist": "build",
"devMain": "http://localhost:5173",
"name": "JSON Inspector",
"cmds": []
}
],
"headlessCmds": [
{
"name": "Format JSON",
"main": "headless-dist/index.js",
"cmds": []
}
]
},
"scripts": {
"dev": "vite dev",
"dev:headless": "bun build.ts dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write ."
},
"dependencies": {
"@kksh/api": "0.1.3",
"@kksh/svelte5": "0.1.15",
"clsx": "^2.1.1",
"lucide-svelte": "^0.469.0",
"mode-watcher": "^0.5.0",
"svelte-inspect-value": "^0.1.4",
"tailwind-merge": "^2.6.0",
"tailwind-variants": "^0.3.0"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^3.3.1",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.15.2",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@tailwindcss/typography": "^0.5.16",
"@types/bun": "^1.2.3",
"@types/eslint": "^9.6.1",
"autoprefixer": "^10.4.20",
"eslint": "^9.17.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.46.1",
"globals": "^15.14.0",
"postcss": "^8.4.49",
"prettier": "^3.4.2",
"prettier-plugin-svelte": "^3.3.2",
"prettier-plugin-tailwindcss": "^0.6.9",
"svelte": "^5.16.6",
"svelte-check": "^4.1.1",
"tailwindcss": "^3.4.17",
"typescript": "^5.7.2",
"typescript-eslint": "^8.19.1",
"vite": "^6.0.7"
},
"type": "module",
"files": [
"build",
"README.md",
"headless-dist",
"package.json",
".gitignore"
]
}

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
};

80
src/app.css Normal file
View File

@ -0,0 +1,80 @@
@import url('@kksh/svelte5/themes');
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 72.2% 50.6%;
--destructive-foreground: 0 0% 98%;
--ring: 0 0% 3.9%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--ring: 0 0% 83.1%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

13
src/app.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};

12
src/app.html Normal file
View File

@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View File

@ -0,0 +1,20 @@
<script lang="ts">
import { ThemeCustomizerButton, type ThemeConfig, updateTheme } from '@kksh/svelte5';
import { ui } from '@kksh/api/ui/custom';
import { onMount } from 'svelte';
let config: ThemeConfig = {
radius: 0.5,
theme: 'zinc',
lightMode: 'auto'
};
onMount(() => {
ui.getTheme().then((theme) => {
config = theme;
});
});
$: updateTheme(config);
</script>
<ThemeCustomizerButton bind:config />

1
src/lib/index.ts Normal file
View File

@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.

56
src/lib/utils.ts Normal file
View File

@ -0,0 +1,56 @@
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
import { cubicOut } from 'svelte/easing';
import type { TransitionConfig } from 'svelte/transition';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
type FlyAndScaleParams = {
y?: number;
x?: number;
start?: number;
duration?: number;
};
export const flyAndScale = (
node: Element,
params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }
): TransitionConfig => {
const style = getComputedStyle(node);
const transform = style.transform === 'none' ? '' : style.transform;
const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
const [minA, maxA] = scaleA;
const [minB, maxB] = scaleB;
const percentage = (valueA - minA) / (maxA - minA);
const valueB = percentage * (maxB - minB) + minB;
return valueB;
};
const styleToString = (style: Record<string, number | string | undefined>): string => {
return Object.keys(style).reduce((str, key) => {
if (style[key] === undefined) return str;
return str + `${key}:${style[key]};`;
}, '');
};
return {
duration: params.duration ?? 200,
delay: 0,
css: (t) => {
const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]);
const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]);
const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]);
return styleToString({
transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
opacity: t
});
},
easing: cubicOut
};
};

19
src/routes/+layout.svelte Normal file
View File

@ -0,0 +1,19 @@
<script>
import '../app.css';
import { ModeWatcher } from 'mode-watcher';
import { ThemeWrapper, updateTheme } from '@kksh/svelte5';
import { onMount } from 'svelte';
import { ui } from '@kksh/api/ui/custom';
onMount(() => {
ui.registerDragRegion();
ui.getTheme().then((theme) => {
updateTheme(theme);
});
});
</script>
<ModeWatcher />
<ThemeWrapper>
<slot />
</ThemeWrapper>

2
src/routes/+layout.ts Normal file
View File

@ -0,0 +1,2 @@
export const prerender = true;
export const ssr = false;

44
src/routes/+page.svelte Normal file
View File

@ -0,0 +1,44 @@
<script lang="ts">
import { clipboard, toast, ui } from '@kksh/api/ui/custom';
import { Button } from '@kksh/svelte5';
import { onMount } from 'svelte';
import { Inspect } from 'svelte-inspect-value';
let rawJson = $state('');
let jsonData = $state({});
function loadJsonFromClipboard() {
clipboard.readText().then((text) => {
rawJson = text;
});
}
onMount(() => {
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
ui.goBack();
}
});
ui.showBackButton({
bottom: 0.5,
right: 0.5
});
ui.hideMoveButton();
});
$effect(() => {
try {
jsonData = JSON.parse(rawJson);
} catch (error) {
toast.error('Invalid JSON');
}
});
</script>
<div class="h-12" data-kunkun-drag-region></div>
<main class="container">
<Inspect value={jsonData} />
<div class="fixed bottom-5 left-0 flex w-full justify-center">
<Button onclick={loadJsonFromClipboard} class="w-[95vw]">Load JSON from Clipboard</Button>
</div>
</main>

View File

@ -0,0 +1,15 @@
<script>
import { base } from '$app/paths';
import { Alert, Button, ThemeWrapper } from '@kksh/svelte5';
</script>
<ThemeWrapper>
<Alert.Root>
<Alert.Title class="text-3xl font-bold">About Page</Alert.Title>
<Alert.Description>
<a href="{base}/">
<Button>Home Page</Button>
</a>
</Alert.Description>
</Alert.Root>
</ThemeWrapper>

BIN
static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

21
svelte.config.js Normal file
View File

@ -0,0 +1,21 @@
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter({}),
alias: {
'@/*': './src/lib/*'
}
}
};
export default config;

67
tailwind.config.ts Normal file
View File

@ -0,0 +1,67 @@
import { fontFamily } from 'tailwindcss/defaultTheme';
import type { Config } from 'tailwindcss';
const config: Config = {
darkMode: ['class'],
content: [
'./src/**/*.{html,js,svelte,ts}',
'node_modules/@kksh/svelte5/dist/**/*.{html,js,svelte,ts}'
],
safelist: ['dark'],
theme: {
container: {
center: true,
padding: '2rem',
screens: {
'2xl': '1400px'
}
},
extend: {
colors: {
border: 'hsl(var(--border) / <alpha-value>)',
input: 'hsl(var(--input) / <alpha-value>)',
ring: 'hsl(var(--ring) / <alpha-value>)',
background: 'hsl(var(--background) / <alpha-value>)',
foreground: 'hsl(var(--foreground) / <alpha-value>)',
primary: {
DEFAULT: 'hsl(var(--primary) / <alpha-value>)',
foreground: 'hsl(var(--primary-foreground) / <alpha-value>)'
},
secondary: {
DEFAULT: 'hsl(var(--secondary) / <alpha-value>)',
foreground: 'hsl(var(--secondary-foreground) / <alpha-value>)'
},
destructive: {
DEFAULT: 'hsl(var(--destructive) / <alpha-value>)',
foreground: 'hsl(var(--destructive-foreground) / <alpha-value>)'
},
muted: {
DEFAULT: 'hsl(var(--muted) / <alpha-value>)',
foreground: 'hsl(var(--muted-foreground) / <alpha-value>)'
},
accent: {
DEFAULT: 'hsl(var(--accent) / <alpha-value>)',
foreground: 'hsl(var(--accent-foreground) / <alpha-value>)'
},
popover: {
DEFAULT: 'hsl(var(--popover) / <alpha-value>)',
foreground: 'hsl(var(--popover-foreground) / <alpha-value>)'
},
card: {
DEFAULT: 'hsl(var(--card) / <alpha-value>)',
foreground: 'hsl(var(--card-foreground) / <alpha-value>)'
}
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)'
},
fontFamily: {
sans: [...fontFamily.sans]
}
}
}
};
export default config;

21
tsconfig.json Normal file
View File

@ -0,0 +1,21 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"module": "esnext",
"target": "ESNext",
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}

6
vite.config.ts Normal file
View File

@ -0,0 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()]
});