91 Commits

Author SHA1 Message Date
fac25ca67b refactor: remove signin step and related buttons from signup process 2025-04-07 13:25:42 +02:00
d11f22f5f8 larger qr code 2025-03-24 11:01:22 +01:00
42f2a5ba21 hide signup progress on first step 2025-03-24 11:01:17 +01:00
31cd1a61ad hide darkmode toggle for now 2025-03-24 11:01:02 +01:00
9f63e3a77a theme 2025-03-24 10:45:21 +01:00
4c5499d050 drop the countdown for now 2025-03-24 10:45:14 +01:00
497a108647 wip 2025-03-24 10:45:03 +01:00
38e6c145e2 sample qr code 2025-03-24 10:31:58 +01:00
828cc0547e agb check state 2025-03-24 10:29:06 +01:00
c3248099c6 autofocus + more signup logic 2025-03-24 10:26:05 +01:00
2aa8c4178a more 2025-03-23 00:53:46 +01:00
52b8db4a5a more flow 2025-03-23 00:51:23 +01:00
012a0043b3 feat: final state 2025-03-23 00:48:58 +01:00
625c0c3ed2 show basic idea 2025-03-23 00:38:53 +01:00
a3e800aa94 chore: Reinit svelte 2025-03-22 23:15:56 +01:00
399b7b0798 chore: Ignore legacy code 2025-03-22 23:13:07 +01:00
0de50822cd Merge branch 'main' of git.odit.services:lfk/kiosk
Some checks failed
Build latest image / build-container (push) Failing after 18s
2025-03-22 23:10:31 +01:00
0177c50651 refactor(ci): Switch to actions 2025-03-22 23:08:06 +01:00
f7575f46e4 🚀Bumped version to 1.1.0 2024-12-16 17:32:09 +01:00
a8d90d4882 feat: email 2024-12-16 17:31:56 +01:00
a2ffa5055e 2025 2024-12-16 17:31:49 +01:00
b969932582 chore(deps): bump all 2024-12-16 17:31:36 +01:00
72ace57cb3 Merge branch 'main' of git.odit.services:lfk/kiosk
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2023-11-06 20:07:16 +01:00
16f9228390 feat(ci)!: Switch to woodpecker 2023-11-06 20:06:59 +01:00
16d15f7242 🚀Bumped version to 1.0.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 18:27:56 +02:00
115767c656 feat: footer
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 18:27:33 +02:00
bb3c801908 feat: prevent F1 + F5 2023-04-19 18:27:27 +02:00
e512325115 refactor: drop footer 2023-04-19 18:27:12 +02:00
aa7d2dbe1b 🚀Bumped version to 0.6.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 18:07:26 +02:00
01cd8d4b78 add chrome kiosk command to readme
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 18:07:15 +02:00
c7c1c6dc41 refactor!: cleanup userdata localstorage + components
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 18:06:13 +02:00
bf8b351b64 feat!: move to single route application for kiosk mode
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 18:02:33 +02:00
58830c5db3 🚀Bumped version to 0.5.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 17:07:08 +02:00
066e67c64f feat(registration): support next input element with ENTER key
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 17:06:55 +02:00
5f5b03a8a0 feat(registration): disabled done button for 7.5s
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 17:04:36 +02:00
cbfbd92d0e feat(registration): autofocus input fields + done button
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 16:58:35 +02:00
418fe7773f feat(registration): disable text select
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 16:58:08 +02:00
4b6e11d8d2 🚀Bumped version to 0.4.4
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 13:08:38 +02:00
0698038523 fix(registration): Added missing dark styling 2023-04-19 13:08:29 +02:00
297b88016b 🚀Bumped version to 0.4.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 13:04:53 +02:00
8959223016 fix(href): replaced location.replace with goto 2023-04-19 13:04:44 +02:00
a3e437d966 🚀Bumped version to 0.4.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 13:00:04 +02:00
19c9fa339b fix(hrefs): Fixed relative locations 2023-04-19 12:59:52 +02:00
8017f009e4 🚀Bumped version to 0.4.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:57:15 +02:00
482d6387fa Redirects/links relative 2023-04-19 12:57:02 +02:00
ff36691ada fix(userstore): Prefix localstorage keys with kiosk- 2023-04-19 12:56:19 +02:00
8ec4fc0c83 🚀Bumped version to 0.4.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:50:06 +02:00
a07eb4ddf5 Merge pull request 'branding' (#1) from branding into main
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #1
2023-04-19 10:49:18 +00:00
ec6598feb1 Merge branch 'main' into branding
All checks were successful
continuous-integration/drone/pr Build is passing
2023-04-19 12:48:26 +02:00
93872030ed Lockfile 2023-04-19 12:48:09 +02:00
a610c6abd1 chore(deps): update all
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:33:27 +02:00
0a883ce7fb branding 2023-04-19 12:33:07 +02:00
f2d8ab81e9 🚀Bumped version to 0.3.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:16:08 +02:00
c546a96c4d feat(registration): drop privacy checkbox [privacy is linked on page]
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:15:34 +02:00
c82fdf3823 🚀Bumped version to 0.2.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:12:29 +02:00
a46a67793c Merge branch 'main' of https://git.odit.services/lfk/kiosk
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:11:12 +02:00
898d3595a0 feat(registration): cleanup finished page 2023-04-19 12:11:05 +02:00
3aa6f0473b 🚀Bumped version to 0.1.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:10:42 +02:00
22be68311b typo 2023-04-19 12:10:31 +02:00
5d7a25e54f updated release hook 2023-04-19 12:10:01 +02:00
16deab5308 pnpx -> npx
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:08:54 +02:00
45eb4b0828 Merge branch 'main' of git.odit.services:lfk/kiosk 2023-04-19 12:08:28 +02:00
c0a39bdabe release from main 2023-04-19 12:08:07 +02:00
e25aaf3e5e Moved config into call 2023-04-19 12:07:27 +02:00
d68e88ec9a Updated typing 2023-04-19 12:06:13 +02:00
1a0f52f31f Added bwip types 2023-04-19 12:05:19 +02:00
1c5e246095 fix(registration): typo
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:05:13 +02:00
74970c4c5b Merge branch 'main' of https://git.odit.services/lfk/kiosk
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:05:00 +02:00
fffe290360 fix(a11y): input borders 2023-04-19 12:04:43 +02:00
3d110e8f48 Moved barcode height to main config
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-19 12:03:28 +02:00
0bd83f8000 Added readme 2023-04-19 12:01:51 +02:00
910fa3867b pinned dependency 2023-04-19 11:57:47 +02:00
2e355dbb46 Package project info 2023-04-19 11:57:36 +02:00
d3d0d17b3a Registration feedback logic 2023-04-19 11:55:03 +02:00
7cecbfe80e Register results 2023-04-19 11:48:34 +02:00
710cad376e Fix in auth 2023-04-19 11:44:00 +02:00
5a81cb64f5 Added runnerid as barcode 2023-04-19 11:40:24 +02:00
09aee15f60 Basic registration page 2023-04-19 11:35:39 +02:00
f98a4fc2b1 Hide error on successfull signin 2023-04-19 11:34:41 +02:00
7879ca82fd Authed page login logic 2023-04-19 11:26:14 +02:00
c1400c0120 Open footer links in new tab 2023-04-19 11:11:51 +02:00
8b086c5aa8 Added login error 2023-04-19 11:10:58 +02:00
078e8dcb9a Added login page with logic 2023-04-19 11:10:48 +02:00
5ed21bb13d Added basic welcome page 2023-04-19 10:58:18 +02:00
f6dd25c988 Added sample env 2023-04-19 10:38:33 +02:00
88f36575fb Basic userstore 2023-04-19 10:35:22 +02:00
f927cc916b Added lfk client 2023-04-19 10:35:11 +02:00
e5535f1869 Added dockerfile + compose 2023-04-19 10:22:46 +02:00
50764bca47 Bump ts 2023-04-19 10:18:56 +02:00
eca9966e29 Added basic drone docker build, build checks and typechecks 2023-04-19 10:15:36 +02:00
abff31aaee Pin dependencies 2023-04-19 10:14:00 +02:00
51 changed files with 3296 additions and 4150 deletions

View File

@@ -1,13 +0,0 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@@ -1,20 +0,0 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
plugins: ['svelte3', '@typescript-eslint'],
ignorePatterns: ['*.cjs'],
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
settings: {
'svelte3/typescript': () => require('typescript')
},
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020
},
env: {
browser: true,
es2017: true,
node: true
}
};

27
.gitea/workflows/dev.yaml Normal file
View File

@@ -0,0 +1,27 @@
name: Build latest image
on:
push:
branches:
- main
jobs:
build-container:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to registry
uses: docker/login-action@v3
with:
registry: registry.odit.services
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: |
${{ vars.REGISTRY }}/lfk/kiosk:latest
platforms: linux/amd64,linux/arm64

View File

@@ -0,0 +1,27 @@
name: Build release images
on:
push:
tags:
- "*.*.*"
jobs:
build-container:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to registry
uses: docker/login-action@v3
with:
registry: registry.odit.services
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: |
${{ vars.REGISTRY }}/lfk/kiosk:${{ github.ref_name }}
platforms: linux/amd64,linux/arm64

22
.gitignore vendored
View File

@@ -1,10 +1,26 @@
.DS_Store
node_modules
/build
# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/package
/build
# OS
.DS_Store
Thumbs.db
# Env
.env
.env.*
!.env.example
!.env.test
# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
# additional
tmp

View File

@@ -1,13 +0,0 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

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

15
Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
FROM registry.odit.services/hub/library/node:19.9.0-alpine3.16 AS build
ARG NPM_REGISTRY_URL=registry.npmjs.org
WORKDIR /app
COPY package.json *.config.cjs *.config.js *.config.ts tsconfig.json .npmrc ./
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
RUN pnpm i
COPY src ./src
COPY static ./static
RUN pnpm build
# final image
FROM registry.odit.services/library/nginx-brotli:3.15 as final
COPY --from=build /app/build /usr/share/nginx/html

View File

@@ -1,8 +0,0 @@
The MIT License (MIT)
Copyright © 2023 ODIT.Services UG (haftungsbeschränkts) - info@odit.services
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,6 +1,6 @@
# create-svelte
# sv
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
## Creating a project
@@ -8,10 +8,10 @@ If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm create svelte@latest
npx sv create
# create a new project in my-app
npm create svelte@latest my-app
npx sv create my-app
```
## Developing
@@ -35,4 +35,4 @@ npm run build
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.

14
components.json Normal file
View File

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

6
docker-compose.yml Normal file
View File

@@ -0,0 +1,6 @@
version: "3"
services:
httpd:
build: .
ports:
- 8181:80

36
eslint.config.js Normal file
View File

@@ -0,0 +1,36 @@
import js from '@eslint/js';
import { includeIgnoreFile } from '@eslint/compat';
import svelte from 'eslint-plugin-svelte';
import globals from 'globals';
import { fileURLToPath } from 'node:url';
import ts from 'typescript-eslint';
import svelteConfig from './svelte.config.js';
const gitignorePath = fileURLToPath(new URL("./.gitignore", import.meta.url));
export default ts.config(
includeIgnoreFile(gitignorePath),
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs.recommended,
{
languageOptions: {
globals: {
...globals.browser,
...globals.node
}
}
},
{
files: ["**/*.svelte", "**/*.svelte.ts", "**/*.svelte.js"],
ignores: ["eslint.config.js", "svelte.config.js"],
languageOptions: {
parserOptions: {
projectService: true,
extraFileExtensions: ['.svelte'],
parser: ts.parser,
svelteConfig
}
}
}
);

View File

@@ -1,68 +1,46 @@
{
"name": "@lfk/kiosk",
"name": "kiosk",
"private": true,
"version": "0.0.1",
"private": false,
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --plugin-search-dir . --check . && eslint .",
"format": "prettier --plugin-search-dir . --write .",
"release": "release-it",
"license:export": "license-exporter --markdown && git stage licenses.md"
"lint": "eslint ."
},
"devDependencies": {
"@odit/license-exporter": "^0.0.12",
"@sveltejs/adapter-static": "^2.0.2",
"@sveltejs/kit": "^1.5.0",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"auto-changelog": "^2.4.0",
"autoprefixer": "^10.4.7",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte3": "^4.0.0",
"postcss": "^8.4.14",
"postcss-load-config": "^4.0.1",
"prettier": "^2.8.0",
"prettier-plugin-svelte": "^2.8.1",
"release-it": "^15.10.1",
"svelte": "^3.54.0",
"svelte-check": "^3.0.1",
"svelte-preprocess": "^4.10.7",
"tailwindcss": "^3.1.5",
"tslib": "^2.4.1",
"@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.16.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"autoprefixer": "^10.4.20",
"bits-ui": "0.22.0",
"clsx": "^2.1.1",
"eslint": "^9.18.0",
"eslint-plugin-svelte": "^3.0.0",
"globals": "^16.0.0",
"lucide-svelte": "^0.483.0",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"tailwind-merge": "^3.0.2",
"tailwind-variants": "^1.0.0",
"tailwindcss": "^3.4.17",
"typescript": "^5.0.0",
"vite": "^4.2.0"
"typescript-eslint": "^8.20.0",
"vite": "^6.0.0"
},
"pnpm": {
"onlyBuiltDependencies": [
"esbuild"
]
},
"type": "module",
"dependencies": {
"bwip-js": "^3.4.0"
},
"release-it": {
"git": {
"commit": true,
"requireCleanWorkingDir": false,
"commitMessage": "🚀Bumped version to ${version}",
"requireBranch": "dev",
"push": true,
"tag": true,
"tagName": null,
"tagAnnotation": "${version}"
},
"npm": {
"publish": false
},
"hooks": {
"after:bump": "pnpx auto-changelog --commit-limit false -p -u --hide-credit && pnpm licenses:export && git add CHANGELOG.md licenses.md"
}
},
"volta": {
"node": "19.9.0"
},
"engines": {
"pnpm": "8"
"@lucide/svelte": "^0.483.0",
"mode-watcher": "^0.5.1"
}
}
}

6145
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +0,0 @@
const tailwindcss = require('tailwindcss');
const autoprefixer = require('autoprefixer');
const config = {
plugins: [
//Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(),
//But others, like autoprefixer, need to run after,
autoprefixer
]
};
module.exports = config;

6
postcss.config.js Normal file
View File

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

49
src/app.css Normal file
View File

@@ -0,0 +1,49 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 72.22% 50.59%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 221.2 83.2% 53.3%;
--radius: 0.75rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 217.2 91.2% 59.8%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 224.3 76.3% 48%;
}
}

3
src/app.d.ts vendored
View File

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

View File

@@ -1,9 +1,9 @@
<!DOCTYPE html>
<!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" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">

View File

@@ -1,4 +0,0 @@
/* Write your global styles here, in PostCSS syntax */
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,25 @@
<script lang="ts">
import { Button as ButtonPrimitive } from "bits-ui";
import { type Events, type Props, buttonVariants } from "./index.js";
import { cn } from "$lib/utils.js";
type $$Props = Props;
type $$Events = Events;
let className: $$Props["class"] = undefined;
export let variant: $$Props["variant"] = "default";
export let size: $$Props["size"] = "default";
export let builders: $$Props["builders"] = [];
export { className as class };
</script>
<ButtonPrimitive.Root
{builders}
class={cn(buttonVariants({ variant, size, className }))}
type="button"
{...$$restProps}
on:click
on:keydown
>
<slot />
</ButtonPrimitive.Root>

View File

@@ -0,0 +1,49 @@
import { type VariantProps, tv } from "tailwind-variants";
import type { Button as ButtonPrimitive } from "bits-ui";
import Root from "./button.svelte";
const buttonVariants = tv({
base: "ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border-input bg-background hover:bg-accent hover:text-accent-foreground border",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
});
type Variant = VariantProps<typeof buttonVariants>["variant"];
type Size = VariantProps<typeof buttonVariants>["size"];
type Props = ButtonPrimitive.Props & {
variant?: Variant;
size?: Size;
};
type Events = ButtonPrimitive.Events;
export {
Root,
type Props,
type Events,
//
Root as Button,
type Props as ButtonProps,
type Events as ButtonEvents,
buttonVariants,
};

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<div class={cn("p-6", className)} {...$$restProps}>
<slot />
</div>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLParagraphElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<p class={cn("text-muted-foreground text-sm", className)} {...$$restProps}>
<slot />
</p>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<div class={cn("flex items-center p-6 pt-0", className)} {...$$restProps}>
<slot />
</div>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<div class={cn("flex flex-col space-y-1.5 p-6 pb-0", className)} {...$$restProps}>
<slot />
</div>

View File

@@ -0,0 +1,21 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import type { HeadingLevel } from "./index.js";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLHeadingElement> & {
tag?: HeadingLevel;
};
let className: $$Props["class"] = undefined;
export let tag: $$Props["tag"] = "h3";
export { className as class };
</script>
<svelte:element
this={tag}
class={cn("text-lg font-semibold leading-none tracking-tight", className)}
{...$$restProps}
>
<slot />
</svelte:element>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import type { HTMLAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<div
class={cn("bg-card text-card-foreground rounded-lg border shadow-sm", className)}
{...$$restProps}
>
<slot />
</div>

View File

@@ -0,0 +1,24 @@
import Root from "./card.svelte";
import Content from "./card-content.svelte";
import Description from "./card-description.svelte";
import Footer from "./card-footer.svelte";
import Header from "./card-header.svelte";
import Title from "./card-title.svelte";
export {
Root,
Content,
Description,
Footer,
Header,
Title,
//
Root as Card,
Content as CardContent,
Description as CardDescription,
Footer as CardFooter,
Header as CardHeader,
Title as CardTitle,
};
export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";

View File

@@ -0,0 +1,35 @@
<script lang="ts">
import { Checkbox as CheckboxPrimitive } from "bits-ui";
import Check from "lucide-svelte/icons/check";
import Minus from "lucide-svelte/icons/minus";
import { cn } from "$lib/utils.js";
type $$Props = CheckboxPrimitive.Props;
type $$Events = CheckboxPrimitive.Events;
let className: $$Props["class"] = undefined;
export let checked: $$Props["checked"] = false;
export { className as class };
</script>
<CheckboxPrimitive.Root
class={cn(
"border-primary ring-offset-background focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer box-content h-4 w-4 shrink-0 rounded-sm border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50",
className
)}
bind:checked
{...$$restProps}
on:click
>
<CheckboxPrimitive.Indicator
class={cn("flex h-4 w-4 items-center justify-center text-current")}
let:isChecked
let:isIndeterminate
>
{#if isChecked}
<Check class="h-3.5 w-3.5" />
{:else if isIndeterminate}
<Minus class="h-3.5 w-3.5" />
{/if}
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>

View File

@@ -0,0 +1,6 @@
import Root from "./checkbox.svelte";
export {
Root,
//
Root as Checkbox,
};

View File

@@ -0,0 +1,29 @@
import Root from "./input.svelte";
export type FormInputEvent<T extends Event = Event> = T & {
currentTarget: EventTarget & HTMLInputElement;
};
export type InputEvents = {
blur: FormInputEvent<FocusEvent>;
change: FormInputEvent<Event>;
click: FormInputEvent<MouseEvent>;
focus: FormInputEvent<FocusEvent>;
focusin: FormInputEvent<FocusEvent>;
focusout: FormInputEvent<FocusEvent>;
keydown: FormInputEvent<KeyboardEvent>;
keypress: FormInputEvent<KeyboardEvent>;
keyup: FormInputEvent<KeyboardEvent>;
mouseover: FormInputEvent<MouseEvent>;
mouseenter: FormInputEvent<MouseEvent>;
mouseleave: FormInputEvent<MouseEvent>;
mousemove: FormInputEvent<MouseEvent>;
paste: FormInputEvent<ClipboardEvent>;
input: FormInputEvent<InputEvent>;
wheel: FormInputEvent<WheelEvent>;
};
export {
Root,
//
Root as Input,
};

View File

@@ -0,0 +1,42 @@
<script lang="ts">
import type { HTMLInputAttributes } from "svelte/elements";
import type { InputEvents } from "./index.js";
import { cn } from "$lib/utils.js";
type $$Props = HTMLInputAttributes;
type $$Events = InputEvents;
let className: $$Props["class"] = undefined;
export let value: $$Props["value"] = undefined;
export { className as class };
// Workaround for https://github.com/sveltejs/svelte/issues/9305
// Fixed in Svelte 5, but not backported to 4.x.
export let readonly: $$Props["readonly"] = undefined;
</script>
<input
class={cn(
"border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className
)}
bind:value
{readonly}
on:blur
on:change
on:click
on:focus
on:focusin
on:focusout
on:keydown
on:keypress
on:keyup
on:mouseover
on:mouseenter
on:mouseleave
on:mousemove
on:paste
on:input
on:wheel|passive
{...$$restProps}
/>

View File

@@ -0,0 +1,7 @@
import Root from "./label.svelte";
export {
Root,
//
Root as Label,
};

View File

@@ -0,0 +1,21 @@
<script lang="ts">
import { Label as LabelPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
type $$Props = LabelPrimitive.Props;
type $$Events = LabelPrimitive.Events;
let className: $$Props["class"] = undefined;
export { className as class };
</script>
<LabelPrimitive.Root
class={cn(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
className
)}
{...$$restProps}
on:mousedown
>
<slot />
</LabelPrimitive.Root>

View File

@@ -0,0 +1,7 @@
import Root from "./progress.svelte";
export {
Root,
//
Root as Progress,
};

View File

@@ -0,0 +1,21 @@
<script lang="ts">
import { Progress as ProgressPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
type $$Props = ProgressPrimitive.Props;
let className: $$Props["class"] = undefined;
export let max: $$Props["max"] = 100;
export let value: $$Props["value"] = undefined;
export { className as class };
</script>
<ProgressPrimitive.Root
class={cn("bg-secondary relative h-4 w-full overflow-hidden rounded-full", className)}
{...$$restProps}
>
<div
class="bg-primary h-full w-full flex-1 transition-all"
style={`transform: translateX(-${100 - (100 * (value ?? 0)) / (max ?? 1)}%)`}
></div>
</ProgressPrimitive.Root>

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.

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

@@ -0,0 +1,62 @@
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
};
};

View File

@@ -0,0 +1,36 @@
<script>
import { Button } from "$lib/components/ui/button";
</script>
<div class="container p-4 mx-auto">
<div class="rounded-lg border bg-card text-card-foreground shadow-sm">
<div class="p-6 space-y-4">
<div class="flex items-center justify-between">
<h2 class="text-2xl font-bold">Guide</h2>
</div>
<div class="grid gap-4">
<div class="rounded-md bg-muted p-4">
<h3 class="font-medium mb-2">Where am I?</h3>
<p>
Welcome to the Lauf für Kaya Kiosk application.<br>
This tool helps you with signing up runners an getting them started.
</p>
</div>
<div class="rounded-md bg-muted p-4">
<h3 class="font-medium mb-2">Basic Functions</h3>
<ul class="list-disc pl-5 space-y-1">
<li>Register new participants</li>
<li>Get your personal selfservice token</li>
</ul>
</div>
<div class="rounded-md bg-muted p-4">
<h3 class="font-medium mb-2">Need More Help?</h3>
<p>Contact the event organizers for additional assistance.</p>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,33 @@
<script lang="ts">
import { Button } from "$lib/components/ui/button/index.js";
import * as Card from "$lib/components/ui/card/index.js";
import { Input } from "$lib/components/ui/input/index.js";
import { Label } from "$lib/components/ui/label/index.js";
let { loggedin = $bindable() } = $props();
</script>
<div class="pt-48">
<form
onsubmit={() => {
loggedin = true;
}}
class="flex justify-center items-center overflow-hidden"
>
<Card.Root class="w-full max-w-sm">
<Card.Header>
<Card.Title class="text-2xl">Login</Card.Title>
<Card.Description>Please enter kiosk credentials.</Card.Description>
</Card.Header>
<Card.Content class="grid gap-4">
<div class="grid gap-2">
<Label for="password">Token</Label>
<Input id="password" type="password" required autofocus />
</div>
</Card.Content>
<Card.Footer>
<Button class="w-full" type="submit">Sign in</Button>
</Card.Footer>
</Card.Root>
</form>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

View File

@@ -0,0 +1,259 @@
<script lang="ts">
import { Button } from "$lib/components/ui/button/index.js";
import * as Card from "$lib/components/ui/card/index.js";
import Checkbox from "$lib/components/ui/checkbox/checkbox.svelte";
import { Input } from "$lib/components/ui/input";
import { Label } from "$lib/components/ui/label";
import { Progress } from "$lib/components/ui/progress";
import sampleQR from "./sampleqrlfkselfservice.png";
const Steps = {
WELCOME: {
name: "Welcome",
progress: 0,
showback: false,
},
SIGNUP: {
name: "Signup",
progress: 25,
showback: true,
},
SIGNUP_MAIL: {
name: "Signup with Mail",
progress: 50,
showback: true,
},
SIGNUP_AGB_ACCEPT: {
name: "Accept terms",
progress: 75,
showback: true,
},
SIGNUP_SUCCESS: {
name: "Done",
progress: 100,
showback: false,
},
SIGNIN: {
name: "Signin with Barcode",
progress: 100,
showback: false,
},
SIGNIN_MAIL: {
name: "Signin by Mail",
progress: 75,
showback: true,
},
SIGNIN_MAIL_SUCCESS: {
name: "Signin by Mail Success",
progress: 100,
showback: false,
},
} as const;
type StepType = (typeof Steps)[keyof typeof Steps];
let currentStep = $state<StepType>(Steps.WELCOME);
let agbAgreed = $state<boolean>(false);
let email = $state<string>("");
let firstname = $state<string>("");
let lastname = $state<string>("");
let remainingseconds = $state<number>(5);
</script>
<div class="pt-48">
<div class="flex justify-center items-center overflow-hidden">
<Card.Root class="w-full max-w-xl">
<Card.Header>
<Card.Title class="text-2xl">Welcome</Card.Title>
<Card.Description
>Let me guide you through the signup process.</Card.Description
>
{#if currentStep.name !== Steps.WELCOME.name}
<Progress value={currentStep.progress} />
{/if}
</Card.Header>
<Card.Content class="grid gap-4">
{#if currentStep.name == Steps.WELCOME.name}
<div class="grid gap-2">
<Button
autofocus
class="w-full"
on:click={() => {
currentStep = Steps.SIGNUP;
}}>I want to sign up now</Button
>
</div>
<div class="grid gap-2">
<Button
variant="secondary"
class="w-full"
on:click={() => {
currentStep = Steps.SIGNIN;
}}>I already signed up online</Button
>
</div>
{:else if currentStep.name == Steps.SIGNUP.name}
<form
class="grid gap-2"
onsubmit={() => {
currentStep = Steps.SIGNUP_MAIL;
}}
>
<div class="grid gap-2">
<Label for="firstname">Please enter your first name</Label>
<Input
on:keypress={(event) => {
console.log(event.key);
if (event.key === "Enter") {
document.getElementById("lastname")?.focus();
}
}}
bind:value={firstname}
id="firstname"
type="text"
placeholder="Max"
required
autofocus
/>
</div>
<div class="grid gap-2">
<Label for="lastname">Please enter your last name</Label>
<Input
bind:value={lastname}
id="lastname"
type="text"
placeholder="Mustermann"
required
/>
</div>
<Button type="submit" variant="default" class="w-full"
>Continue</Button
>
</form>
{:else if currentStep.name == Steps.SIGNUP_MAIL.name}
<form
class="grid gap-2"
onsubmit={() => {
currentStep = Steps.SIGNUP_AGB_ACCEPT;
}}
>
<div class="grid gap-2">
<Label for="email"
>Enter your email to get an invitation to our selfservice
(optional)</Label
>
<Input
autofocus
id="email"
type="email"
placeholder="m@example.com"
bind:value={email}
/>
</div>
<Button type="submit" variant="default" class="w-full"
>Continue</Button
>
</form>
{:else if currentStep.name == Steps.SIGNUP_AGB_ACCEPT.name}
{#if email !== ""}
By registering, you confirm that {email} is your email
{/if}
<div class="items-top flex space-x-2">
<Checkbox bind:checked={agbAgreed} autofocus id="terms1" />
<div class="grid gap-1.5 leading-none">
<Label
for="terms1"
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Accept terms and conditions
</Label>
<p class="text-muted-foreground text-sm">
You agree to our Terms of Service and Privacy Policy.
</p>
</div>
</div>
<Button
disabled={!agbAgreed}
variant="default"
class="w-full"
on:click={() => {
currentStep = Steps.SIGNUP_SUCCESS;
}}>Continue</Button
>
{:else if currentStep.name == Steps.SIGNUP_SUCCESS.name}
<p class="text-center">
Alright that's it, just walk up to the next available person and
tell them your name.<br />
You can scan this qr code to login to our selfservice.
<!-- TODO: generate actual qr code -->
<img class="mx-auto h-56" src={sampleQR} alt="" />
</p>
{:else if currentStep.name == Steps.SIGNIN.name}
Just walk up to the next available person and show them your barcode.
{:else if currentStep.name == Steps.SIGNIN_MAIL.name}
<div class="grid gap-2">
<Label for="email"
>No problem, just enter the email address you used to sign up</Label
>
<Input
id="email"
type="email"
placeholder="m@example.com"
bind:value={email}
required
/>
</div>
<div class="grid gap-2">
<Button
class="w-full"
on:click={() => {
console.log("Email: ", email);
currentStep = Steps.SIGNIN_MAIL_SUCCESS;
}}>Continue</Button
>
</div>
{:else if currentStep.name == Steps.SIGNIN_MAIL_SUCCESS.name}
We found your email address, just walk up to the next available person
and tell them your name.
{/if}
</Card.Content>
<Card.Footer class="grid gap-2">
{#if currentStep.showback}
<Button
variant="destructive"
class="w-full"
on:click={() => {
switch (currentStep.name) {
case Steps.SIGNUP.name:
currentStep = Steps.WELCOME;
break;
case Steps.SIGNUP_MAIL.name:
currentStep = Steps.SIGNUP;
break;
case Steps.SIGNUP_AGB_ACCEPT.name:
currentStep = Steps.SIGNUP_MAIL;
break;
case Steps.SIGNIN.name:
currentStep = Steps.WELCOME;
break;
case Steps.SIGNIN_MAIL.name:
currentStep = Steps.SIGNIN;
break;
default:
break;
}
}}>Go Back</Button
>
{/if}
{#if currentStep.progress == 100}
<Button
variant="default"
class="w-full"
on:click={() => {
currentStep = Steps.WELCOME;
}}>Done</Button
>
{/if}
</Card.Footer>
</Card.Root>
</div>
</div>

View File

@@ -1,5 +1,53 @@
<script>
import '../app.postcss';
<script lang="ts">
import "../app.css";
import { ModeWatcher } from "mode-watcher";
import { Button } from "$lib/components/ui/button";
import { Sun, Moon, HelpCircle } from "@lucide/svelte";
import { toggleMode } from "mode-watcher";
import Help from "./(components)/help.svelte";
let { children } = $props();
let showHelp = $state(false);
</script>
<slot />
<ModeWatcher />
<div class="overflow-hidden">
<div
class="fixed top-0 left-0 right-0 z-50 border-b bg-background/80 backdrop-blur-sm"
>
<div class="container flex items-center justify-between py-2">
<h1 class="text-xl font-bold">Lauf für Kaya! Kiosk</h1>
<div class="flex items-center gap-2">
<!-- <Button on:click={toggleMode} variant="outline" size="icon">
<Sun
class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0"
/>
<Moon
class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100"
/>
<span class="sr-only">Toggle theme</span>
</Button> -->
<Button
variant="outline"
size="icon"
on:click={() => (showHelp = !showHelp)}
>
<HelpCircle
class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all"
/>
<span class="sr-only">Show help</span>
</Button>
<!-- More buttons can be added here -->
</div>
</div>
</div>
<div class="mt-14">
{#if showHelp}
<Help />
{:else}
<!-- This div adds spacing below the fixed navbar -->
{@render children()}
{/if}
</div>
</div>

View File

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

View File

@@ -1,2 +1,11 @@
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
<script lang="ts">
import Login from "./(components)/login.svelte";
import Signup from "./(components)/signup.svelte";
let loggedin = $state(false);
</script>
{#if !loggedin}
<Login bind:loggedin />
{:else}
<Signup />
{/if}

View File

@@ -1,23 +1,18 @@
import preprocess from 'svelte-preprocess';
import adapter from '@sveltejs/adapter-static';
import { vitePreprocess } from '@sveltejs/kit/vite';
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
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: [
vitePreprocess(),
preprocess({
postcss: true
})
],
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/*",
}
};

View File

@@ -1,11 +0,0 @@
const config = {
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
},
plugins: []
};
module.exports = config;

64
tailwind.config.ts Normal file
View File

@@ -0,0 +1,64 @@
import { fontFamily } from "tailwindcss/defaultTheme";
import type { Config } from "tailwindcss";
const config: Config = {
darkMode: ["class"],
content: ["./src/**/*.{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;

View File

@@ -8,9 +8,11 @@
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
// except $lib which is handled by https://svelte.dev/docs/kit/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