Compare commits
7 Commits
1e1e829e2d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8dfbfc564d | ||
|
|
e496147aa4 | ||
|
|
ca036467ca | ||
|
|
73c1343b0d | ||
|
|
ceb05f4a75 | ||
|
|
794a0549ab | ||
|
|
67a83edb57 |
21
.gitignore
vendored
21
.gitignore
vendored
@@ -1,24 +1,3 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
dist-ssr
|
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
.DS_Store
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
||||||
|
|||||||
5
.prettierrc
Normal file
5
.prettierrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-svelte"],
|
||||||
|
"pluginSearchDirs": ["."],
|
||||||
|
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
|
||||||
|
}
|
||||||
@@ -7,10 +7,7 @@
|
|||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width" />
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Roboto+Slab:wght@400;500;600;700;800;900&display=swap" rel="stylesheet" />
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Roboto+Slab:wght@400;500;600;700;800;900&display=swap"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<title>Minibusservice</title>
|
<title>Minibusservice</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
3829
package-lock.json
generated
3829
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
59
package.json
59
package.json
@@ -1,26 +1,37 @@
|
|||||||
{
|
{
|
||||||
"name": "minibusservice.no",
|
"name": "minibusservice.no",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json"
|
"check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json",
|
||||||
},
|
"format": "prettier --write ."
|
||||||
"devDependencies": {
|
},
|
||||||
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
"devDependencies": {
|
||||||
"@tailwindcss/vite": "^0.0.0-insiders.aaaefe8",
|
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
||||||
"@tsconfig/svelte": "^5.0.8",
|
"@tailwindcss/vite": "^0.0.0-insiders.aaaefe8",
|
||||||
"@types/leaflet": "^1.9.21",
|
"@tsconfig/svelte": "^5.0.8",
|
||||||
"@types/node": "^24.12.0",
|
"@types/leaflet": "^1.9.21",
|
||||||
"leaflet": "^1.9.4",
|
"@types/node": "^24.12.0",
|
||||||
"svelte": "^5.53.7",
|
"leaflet": "^1.9.4",
|
||||||
"svelte-check": "^4.4.5",
|
"prettier": "^3.8.1",
|
||||||
"tailwind-merge": "^3.5.0",
|
"prettier-plugin-svelte": "^3.5.1",
|
||||||
"tailwindcss": "^0.0.0-insiders.aaaefe8",
|
"svelte": "^5.53.7",
|
||||||
"typescript": "~5.9.3",
|
"svelte-check": "^4.4.5",
|
||||||
"vite": "^8.0.0"
|
"tailwind-merge": "^3.5.0",
|
||||||
}
|
"tailwindcss": "^0.0.0-insiders.aaaefe8",
|
||||||
|
"typescript": "~5.9.3",
|
||||||
|
"vite": "^8.0.0"
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"trailingComma": "none",
|
||||||
|
"tabWidth": 4,
|
||||||
|
"printWidth": 180,
|
||||||
|
"plugins": [
|
||||||
|
"prettier-plugin-svelte"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,20 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Router, { route } from "./lib/components/Router.svelte";
|
import Router, { route } from "./lib/components/Router.svelte";
|
||||||
|
import { getTheme } from "./lib/theme.svelte";
|
||||||
|
import Layout from "./Layout.svelte";
|
||||||
import "./app.css";
|
import "./app.css";
|
||||||
|
|
||||||
import HomePage from "./pages/HomePage.svelte";
|
$effect(() => {
|
||||||
import ToastProvider from "./lib/components/toast/ToastProvider.svelte";
|
document.body.dataset.theme = getTheme();
|
||||||
import Navigation from "./Navigation.svelte";
|
});
|
||||||
import Footer from "./Footer.svelte";
|
|
||||||
import TaxiPage from "./pages/TaxiPage.svelte";
|
|
||||||
import BusPage from "./pages/BusPage.svelte";
|
|
||||||
import ContactPage from "./pages/ContactPage.svelte";
|
|
||||||
import AccessibilityPage from "./pages/AccessibilityPage.svelte";
|
|
||||||
|
|
||||||
route("/", HomePage);
|
|
||||||
route("/taxi", TaxiPage);
|
|
||||||
route("/bus", BusPage);
|
|
||||||
route("/contact", ContactPage);
|
|
||||||
route("/accessibility", AccessibilityPage);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex min-h-screen flex-col bg-primary-200 text-contrast-900">
|
<Layout>
|
||||||
<Navigation>
|
<Router>
|
||||||
<main class="grow px-4 pb-16 pt-8">
|
{#snippet notfound()}
|
||||||
<div class="mx-auto max-w-7xl">
|
<h1>Not found</h1>
|
||||||
<Router>
|
<p>Sorry, the page you are looking for does not exist.</p>
|
||||||
{#snippet notfound()}
|
<p>Return to <a href="/">home</a>.</p>
|
||||||
<h1>Not found</h1>
|
{/snippet}
|
||||||
<p>
|
</Router>
|
||||||
Sorry, the page you are looking for does not exist.
|
</Layout>
|
||||||
</p>
|
|
||||||
<p>Return to <a href="/">home</a>.</p>
|
|
||||||
{/snippet}
|
|
||||||
</Router>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<Footer />
|
|
||||||
</Navigation>
|
|
||||||
</div>
|
|
||||||
<ToastProvider />
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import Link from "./lib/components/link/Link.svelte";
|
|
||||||
import { Routes } from "./lib/global/routes";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<footer
|
|
||||||
class="flex flex-col items-center border-t-2 border-contrast-900 bg-contrast-900 px-2 py-8 text-primary-200 dark:border-primary-300 dark:bg-primary-100 dark:text-contrast-900"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex flex-row flex-wrap justify-center gap-8 text-center md:text-lg"
|
|
||||||
>
|
|
||||||
{#each Routes.footerRoutes as section}
|
|
||||||
<ul class="flex-1">
|
|
||||||
<li>
|
|
||||||
<h6 class="font-semibold">{section.text}</h6>
|
|
||||||
</li>
|
|
||||||
{#each section.routes as route}
|
|
||||||
<li>
|
|
||||||
<Link target={route.target} href={route.url}>
|
|
||||||
{route.text}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
</ul>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<div class="mt-8 text-center font-semibold">Org nr: 816 230 942</div>
|
|
||||||
<div class="mt-2 text-center font-semibold">
|
|
||||||
© 2026 minibusservice.no - All Rights Reserved.
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
133
src/Layout.svelte
Normal file
133
src/Layout.svelte
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Logo from "./lib/components/icons/logo/Logo.svelte";
|
||||||
|
import sunIcon from "./assets/icons/sun.svg";
|
||||||
|
import moonIcon from "./assets/icons/moon.svg";
|
||||||
|
import { slide } from "svelte/transition";
|
||||||
|
import Toggle from "./lib/components/Toggle.svelte";
|
||||||
|
import { Routes } from "./lib/routes";
|
||||||
|
import { isCurrentPath } from "./lib/components/Router.svelte";
|
||||||
|
import { getTheme, toggleTheme } from "./lib/theme.svelte";
|
||||||
|
import ToastProvider from "./lib/components/toast/ToastProvider.svelte";
|
||||||
|
import Link from "./lib/components/link/Link.svelte";
|
||||||
|
|
||||||
|
let sidebarOpen = $state(false);
|
||||||
|
|
||||||
|
let { children } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex min-h-screen flex-col bg-primary-200 text-contrast-900">
|
||||||
|
<header class="sticky top-0 z-20 flex h-16 justify-center border-b-2 border-contrast-100 bg-primary-100 shadow-lg">
|
||||||
|
<div class="flex w-full max-w-7xl flex-row items-center justify-between p-4">
|
||||||
|
<a class="h-full grow" href="/">
|
||||||
|
<Logo />
|
||||||
|
</a>
|
||||||
|
<ul class="hidden flex-row justify-end gap-10 font-medium uppercase md:text-lg lg:flex">
|
||||||
|
{#each Routes.topbarRoutes as route}
|
||||||
|
<li>
|
||||||
|
<a class:border-b-2={isCurrentPath(route.url)} class="border-b-0 border-accent transition-colors hover:text-accent" href={route.url} target={route.target}>
|
||||||
|
{route.text}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
<div class="ml-12 flex aspect-square h-full items-center justify-center p-1">
|
||||||
|
<button
|
||||||
|
class="hamburger-icon relative inline-block h-full w-full cursor-pointer text-contrast-100"
|
||||||
|
aria-label="open sidebar"
|
||||||
|
class:open={sidebarOpen}
|
||||||
|
onclick={() => (sidebarOpen = !sidebarOpen)}
|
||||||
|
>
|
||||||
|
<div class="line absolute top-0 h-0.5 w-full origin-top-left rounded-full bg-contrast-900 transition-all"></div>
|
||||||
|
<div class="line middle absolute top-1/2 h-0.5 w-full -translate-y-1/2 rounded-full bg-contrast-900 transition-all delay-100"></div>
|
||||||
|
<div class="line absolute bottom-0 h-0.5 w-full origin-bottom-left rounded-full bg-contrast-900 transition-all"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#if sidebarOpen}
|
||||||
|
<aside>
|
||||||
|
<nav
|
||||||
|
transition:slide={{ axis: "x" }}
|
||||||
|
class="fixed bottom-14 right-0 top-16 z-10 flex max-w-full flex-col overflow-auto border-l-2 border-contrast-100 bg-primary-100 px-4 py-8 shadow-lg sm:bottom-0"
|
||||||
|
>
|
||||||
|
<ul class="flex grow flex-col gap-2 pr-20 text-lg font-medium lg:text-xl">
|
||||||
|
{#each Routes.sidebarRoutes as route}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class:border-b-2={isCurrentPath(route.url)}
|
||||||
|
class="border-b-0 border-accent transition-colors hover:text-accent"
|
||||||
|
href={route.url}
|
||||||
|
target={route.target}
|
||||||
|
>
|
||||||
|
{route.text}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
<div class="flex w-fit flex-col items-center gap-3">
|
||||||
|
<Toggle invertColor={true} checked={getTheme() == "dark"} leftIcon={sunIcon} rightIcon={moonIcon} on:change={toggleTheme} />
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</aside>
|
||||||
|
{/if}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="grow px-4 pb-16 pt-8">
|
||||||
|
<div class="mx-auto max-w-7xl">
|
||||||
|
{@render children()}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer
|
||||||
|
class="flex flex-col items-center border-t-2 border-contrast-900 bg-contrast-900 px-2 py-8 text-primary-200 dark:border-primary-300 dark:bg-primary-100 dark:text-contrast-900"
|
||||||
|
>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-8 text-center md:text-lg">
|
||||||
|
{#each Routes.footerRoutes as section}
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<h6 class="font-semibold">{section.text}</h6>
|
||||||
|
</li>
|
||||||
|
{#each section.routes as route}
|
||||||
|
<li>
|
||||||
|
<Link target={route.target} href={route.url}>
|
||||||
|
{route.text}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
<div class="mt-8 text-center font-semibold">Org nr: 816 230 942</div>
|
||||||
|
<div class="mt-2 text-center font-semibold">© 2026 minibusservice.no - All Rights Reserved.</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- Mobile navigation -->
|
||||||
|
<nav class="sticky bottom-0 z-10 flex h-14 flex-row items-center justify-around border-t-2 border-contrast-100 bg-primary-100 px-2 text-xs shadow-t-lg sm:hidden">
|
||||||
|
{#each Routes.topbarRoutes as route}
|
||||||
|
<a
|
||||||
|
href={route.url}
|
||||||
|
target={route.target}
|
||||||
|
class={`flex flex-col items-center decoration-accent transition-opacity ${isCurrentPath(route.url) ? "underline opacity-100" : "opacity-50"}`}
|
||||||
|
>
|
||||||
|
<img src={route.icon} alt={route.text} class="h-6 dark:invert" />
|
||||||
|
<span> {route.text} </span>
|
||||||
|
</a>
|
||||||
|
{/each}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ToastProvider />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hamburger-icon.open .line:first-child {
|
||||||
|
transform: rotate(45deg) translateX(15%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburger-icon.open .line:last-child {
|
||||||
|
transform: rotate(-45deg) translateX(15%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hamburger-icon.open .line.middle {
|
||||||
|
width: 0;
|
||||||
|
transition: transform 0.1s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import Logo from "./lib/components/icons/logo/Logo.svelte";
|
|
||||||
import sunIcon from "./assets/icons/sun.svg";
|
|
||||||
import moonIcon from "./assets/icons/moon.svg";
|
|
||||||
import { slide } from "svelte/transition";
|
|
||||||
import Toggle from "./lib/components/Toggle.svelte";
|
|
||||||
import { darkTheme } from "./lib/stores/theme";
|
|
||||||
import { Routes } from "./lib/global/routes";
|
|
||||||
import { isCurrentPath } from "./lib/components/Router.svelte";
|
|
||||||
|
|
||||||
let sidebarOpen = false;
|
|
||||||
|
|
||||||
function toggleMenuOpen() {
|
|
||||||
sidebarOpen = !sidebarOpen;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<header
|
|
||||||
class="sticky top-0 z-20 flex h-16 justify-center border-b-2 border-contrast-100 bg-primary-100 shadow-lg"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex w-full max-w-7xl flex-row items-center justify-between p-4"
|
|
||||||
>
|
|
||||||
<a class="h-full grow" href="/">
|
|
||||||
<Logo />
|
|
||||||
</a>
|
|
||||||
<ul
|
|
||||||
class="hidden flex-row justify-end gap-10 font-medium uppercase md:text-lg lg:flex"
|
|
||||||
>
|
|
||||||
{#each Routes.topbarRoutes as route}
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class:border-b-2={isCurrentPath(route.url)}
|
|
||||||
class="border-b-0 border-accent transition-colors hover:text-accent"
|
|
||||||
href={route.url}
|
|
||||||
target={route.target}
|
|
||||||
>
|
|
||||||
{route.text}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
</ul>
|
|
||||||
<div
|
|
||||||
class="ml-12 flex aspect-square h-full items-center justify-center p-1"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="hamburger-icon relative inline-block h-full w-full cursor-pointer text-contrast-100"
|
|
||||||
aria-label="open sidebar"
|
|
||||||
class:open={sidebarOpen}
|
|
||||||
on:click={toggleMenuOpen}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="line absolute top-0 h-0.5 w-full origin-top-left rounded-full bg-contrast-900 transition-all"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
class="line middle absolute top-1/2 h-0.5 w-full -translate-y-1/2 rounded-full bg-contrast-900 transition-all delay-100"
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
class="line absolute bottom-0 h-0.5 w-full origin-bottom-left rounded-full bg-contrast-900 transition-all"
|
|
||||||
></div>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{#if sidebarOpen}
|
|
||||||
<aside>
|
|
||||||
<nav
|
|
||||||
transition:slide={{ axis: "x" }}
|
|
||||||
class="fixed bottom-14 right-0 top-16 z-10 flex max-w-full flex-col overflow-auto border-l-2 border-contrast-100 bg-primary-100 px-4 py-8 shadow-lg sm:bottom-0"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
class="flex grow flex-col gap-2 pr-20 text-lg font-medium lg:text-xl"
|
|
||||||
>
|
|
||||||
{#each Routes.sidebarRoutes as route}
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class:border-b-2={`/${window.location.pathname.split("/")[1]}` ==
|
|
||||||
route.url}
|
|
||||||
class="border-b-0 border-accent transition-colors hover:text-accent"
|
|
||||||
href={route.url}
|
|
||||||
target={route.target}
|
|
||||||
>
|
|
||||||
{route.text}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
</ul>
|
|
||||||
<div class="flex w-fit flex-col items-center gap-3">
|
|
||||||
<Toggle
|
|
||||||
invertColor={true}
|
|
||||||
checked={$darkTheme}
|
|
||||||
leftIcon={sunIcon}
|
|
||||||
rightIcon={moonIcon}
|
|
||||||
on:change={() => {
|
|
||||||
$darkTheme = $darkTheme = !$darkTheme;
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</aside>
|
|
||||||
{/if}
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<slot />
|
|
||||||
|
|
||||||
<!-- Mobile navigation -->
|
|
||||||
<nav
|
|
||||||
class="sticky bottom-0 z-10 flex h-14 flex-row items-center justify-around border-t-2 border-contrast-100 bg-primary-100 px-2 text-xs shadow-t-lg sm:hidden"
|
|
||||||
>
|
|
||||||
{#each Routes.topbarRoutes as route}
|
|
||||||
<a
|
|
||||||
href={route.url}
|
|
||||||
target={route.target}
|
|
||||||
class={`flex flex-col items-center decoration-accent transition-opacity ${
|
|
||||||
`/${window.location.pathname.split("/")[1]}` == route.url
|
|
||||||
? "underline opacity-100"
|
|
||||||
: "opacity-50"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<img src={route.icon} alt={route.text} class="h-6 dark:invert" />
|
|
||||||
<span> {route.text} </span>
|
|
||||||
</a>
|
|
||||||
{/each}
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.hamburger-icon.open .line:first-child {
|
|
||||||
transform: rotate(45deg) translateX(15%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger-icon.open .line:last-child {
|
|
||||||
transform: rotate(-45deg) translateX(15%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger-icon.open .line.middle {
|
|
||||||
width: 0;
|
|
||||||
transition: transform 0.1s;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
80
src/app.css
80
src/app.css
@@ -2,72 +2,36 @@
|
|||||||
|
|
||||||
@custom-variant dark (&:where([data-theme='dark'], [data-theme='dark'] *));
|
@custom-variant dark (&:where([data-theme='dark'], [data-theme='dark'] *));
|
||||||
|
|
||||||
:root {
|
body {
|
||||||
--mb-color-primary-100: rgb(250 250 250);
|
color-scheme: light;
|
||||||
--mb-color-primary-200: rgb(240 240 240);
|
|
||||||
--mb-color-primary-300: rgb(230 230 230);
|
|
||||||
--mb-color-primary-400: rgb(220 220 220);
|
|
||||||
--mb-color-primary-500: rgb(210 210 210);
|
|
||||||
--mb-color-primary-600: rgb(200 200 200);
|
|
||||||
--mb-color-primary-700: rgb(190 190 190);
|
|
||||||
--mb-color-primary-800: rgb(180 180 180);
|
|
||||||
--mb-color-primary-900: rgb(170 170 170);
|
|
||||||
|
|
||||||
--mb-color-contrast-100: rgb(220 220 220);
|
|
||||||
--mb-color-contrast-200: rgb(200 200 200);
|
|
||||||
--mb-color-contrast-300: rgb(180 180 180);
|
|
||||||
--mb-color-contrast-400: rgb(160 160 160);
|
|
||||||
--mb-color-contrast-500: rgb(140 140 140);
|
|
||||||
--mb-color-contrast-600: rgb(110 110 110);
|
|
||||||
--mb-color-contrast-700: rgb(80 80 80);
|
|
||||||
--mb-color-contrast-800: rgb(60 60 60);
|
|
||||||
--mb-color-contrast-900: rgb(30 30 30);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] {
|
body[data-theme="dark"] {
|
||||||
--mb-color-primary-100: rgb(28 28 28);
|
color-scheme: dark;
|
||||||
--mb-color-primary-200: rgb(32 32 32);
|
|
||||||
--mb-color-primary-300: rgb(38 38 38);
|
|
||||||
--mb-color-primary-400: rgb(44 44 44);
|
|
||||||
--mb-color-primary-500: rgb(50 50 50);
|
|
||||||
--mb-color-primary-600: rgb(56 56 56);
|
|
||||||
--mb-color-primary-700: rgb(62 62 62);
|
|
||||||
--mb-color-primary-800: rgb(68 68 68);
|
|
||||||
--mb-color-primary-900: rgb(74 74 74);
|
|
||||||
|
|
||||||
--mb-color-contrast-100: rgb(25 25 25);
|
|
||||||
--mb-color-contrast-200: rgb(50 50 50);
|
|
||||||
--mb-color-contrast-300: rgb(80 80 80);
|
|
||||||
--mb-color-contrast-400: rgb(110 110 110);
|
|
||||||
--mb-color-contrast-500: rgb(140 140 140);
|
|
||||||
--mb-color-contrast-600: rgb(160 160 160);
|
|
||||||
--mb-color-contrast-700: rgb(180 180 180);
|
|
||||||
--mb-color-contrast-800: rgb(200 200 200);
|
|
||||||
--mb-color-contrast-900: rgb(220 220 220);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--color-accent: rgb(255 29 37);
|
--color-accent: rgb(255 29 37);
|
||||||
|
|
||||||
--color-primary-100: var(--mb-color-primary-100);
|
--color-primary-100: light-dark(rgb(250 250 250), rgb(28 28 28));
|
||||||
--color-primary-200: var(--mb-color-primary-200);
|
--color-primary-200: light-dark(rgb(240 240 240), rgb(32 32 32));
|
||||||
--color-primary-300: var(--mb-color-primary-300);
|
--color-primary-300: light-dark(rgb(230 230 230), rgb(38 38 38));
|
||||||
--color-primary-400: var(--mb-color-primary-400);
|
--color-primary-400: light-dark(rgb(220 220 220), rgb(44 44 44));
|
||||||
--color-primary-500: var(--mb-color-primary-500);
|
--color-primary-500: light-dark(rgb(210 210 210), rgb(50 50 50));
|
||||||
--color-primary-600: var(--mb-color-primary-600);
|
--color-primary-600: light-dark(rgb(200 200 200), rgb(56 56 56));
|
||||||
--color-primary-700: var(--mb-color-primary-700);
|
--color-primary-700: light-dark(rgb(190 190 190), rgb(62 62 62));
|
||||||
--color-primary-800: var(--mb-color-primary-800);
|
--color-primary-800: light-dark(rgb(180 180 180), rgb(68 68 68));
|
||||||
--color-primary-900: var(--mb-color-primary-900);
|
--color-primary-900: light-dark(rgb(170 170 170), rgb(74 74 74));
|
||||||
|
|
||||||
--color-contrast-100: var(--mb-color-contrast-100);
|
--color-contrast-100: light-dark(rgb(220 220 220), rgb(25 25 25));
|
||||||
--color-contrast-200: var(--mb-color-contrast-200);
|
--color-contrast-200: light-dark(rgb(200 200 200), rgb(50 50 50));
|
||||||
--color-contrast-300: var(--mb-color-contrast-300);
|
--color-contrast-300: light-dark(rgb(180 180 180), rgb(80 80 80));
|
||||||
--color-contrast-400: var(--mb-color-contrast-400);
|
--color-contrast-400: light-dark(rgb(160 160 160), rgb(110 110 110));
|
||||||
--color-contrast-500: var(--mb-color-contrast-500);
|
--color-contrast-500: light-dark(rgb(140 140 140), rgb(140 140 140));
|
||||||
--color-contrast-600: var(--mb-color-contrast-600);
|
--color-contrast-600: light-dark(rgb(110 110 110), rgb(160 160 160));
|
||||||
--color-contrast-700: var(--mb-color-contrast-700);
|
--color-contrast-700: light-dark(rgb(80 80 80), rgb(180 180 180));
|
||||||
--color-contrast-800: var(--mb-color-contrast-800);
|
--color-contrast-800: light-dark(rgb(60 60 60), rgb(200 200 200));
|
||||||
--color-contrast-900: var(--mb-color-contrast-900);
|
--color-contrast-900: light-dark(rgb(30 30 30), rgb(220 220 220));
|
||||||
|
|
||||||
--shadow-t-lg: 0px -4px 6px -1px rgba(0, 0, 0, 0.1);
|
--shadow-t-lg: 0px -4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,26 +8,16 @@
|
|||||||
<p class="pt-2 font-medium opacity-70">
|
<p class="pt-2 font-medium opacity-70">
|
||||||
Spørsmål?<br />Kontakt oss via tlf eller e-post
|
Spørsmål?<br />Kontakt oss via tlf eller e-post
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<Link class="w-fit font-bold text-accent hover:underline" href="tel:45256161">Tlf: +47 45 25 61 61</Link>
|
||||||
class="w-fit font-bold text-accent hover:underline"
|
<Link class="w-fit font-bold text-accent hover:underline" href="mailto:minibusstur@hotmail.com">E-post: minibusstur@hotmail.com</Link>
|
||||||
href="tel:45256161"
|
|
||||||
>
|
|
||||||
Tlf: +47 45 25 61 61
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
class="w-fit font-bold text-accent hover:underline"
|
|
||||||
href="mailto:minibusstur@hotmail.com"
|
|
||||||
>
|
|
||||||
E-post: minibusstur@hotmail.com
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<MapPoint
|
<MapPoint
|
||||||
class="card mt-5 min-h-140 grow overflow-hidden rounded-md border-2"
|
class="card mt-5 min-h-140 grow overflow-hidden rounded-md border-2"
|
||||||
coordinates={[
|
coordinates={[
|
||||||
{
|
{
|
||||||
latitude: 62.48303957042255,
|
latitude: 62.48303957042255,
|
||||||
longitude: 6.8108274964451745,
|
longitude: 6.8108274964451745
|
||||||
},
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,23 +23,19 @@
|
|||||||
|
|
||||||
iconSize: [32, 32],
|
iconSize: [32, 32],
|
||||||
iconAnchor: [16, 32],
|
iconAnchor: [16, 32],
|
||||||
popupAnchor: [-3, -76],
|
popupAnchor: [-3, -76]
|
||||||
});
|
});
|
||||||
|
|
||||||
map = L.map(mapElement);
|
map = L.map(mapElement);
|
||||||
|
|
||||||
if (coordinates.length >= 1) {
|
if (coordinates.length >= 1) {
|
||||||
map.setView(
|
map.setView([coordinates[0].latitude, coordinates[0].longitude], 15);
|
||||||
[coordinates[0].latitude, coordinates[0].longitude],
|
|
||||||
15,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||||
maxZoom: 18,
|
maxZoom: 18,
|
||||||
attribution:
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
id: "base"
|
||||||
id: "base",
|
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
|
|
||||||
updateMarkers();
|
updateMarkers();
|
||||||
@@ -51,12 +47,12 @@
|
|||||||
|
|
||||||
function addMarker(point: MarkerPoint) {
|
function addMarker(point: MarkerPoint) {
|
||||||
let marker = L.marker([point.latitude, point.longitude], {
|
let marker = L.marker([point.latitude, point.longitude], {
|
||||||
icon: icon,
|
icon: icon
|
||||||
});
|
});
|
||||||
|
|
||||||
if (point.tooltip)
|
if (point.tooltip)
|
||||||
marker.bindTooltip(point.tooltip, {
|
marker.bindTooltip(point.tooltip, {
|
||||||
direction: "bottom",
|
direction: "bottom"
|
||||||
});
|
});
|
||||||
|
|
||||||
markers.push(marker);
|
markers.push(marker);
|
||||||
@@ -71,7 +67,7 @@
|
|||||||
coordinates.forEach(addMarker);
|
coordinates.forEach(addMarker);
|
||||||
|
|
||||||
map?.flyToBounds(L.featureGroup(markers).getBounds(), {
|
map?.flyToBounds(L.featureGroup(markers).getBounds(), {
|
||||||
duration: 1,
|
duration: 1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +75,4 @@
|
|||||||
$: coordinates && updateMarkers();
|
$: coordinates && updateMarkers();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div bind:this={mapElement} class={twMerge("z-0 h-full w-full", $$restProps["class"])}></div>
|
||||||
bind:this={mapElement}
|
|
||||||
class={twMerge("z-0 h-full w-full", $$restProps["class"])}
|
|
||||||
></div>
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
import { SvelteMap } from "svelte/reactivity";
|
import { SvelteMap } from "svelte/reactivity";
|
||||||
import { onMount, type Component, type Snippet } from "svelte";
|
import { onMount, type Component, type Snippet } from "svelte";
|
||||||
|
|
||||||
|
export class RouteError extends Error {}
|
||||||
|
export class MissingRouteError extends RouteError {}
|
||||||
|
export class RouteFormatError extends RouteError {}
|
||||||
|
|
||||||
type RouteInfo = {
|
type RouteInfo = {
|
||||||
path: string;
|
path: string;
|
||||||
pattern: RegExp;
|
pattern: RegExp;
|
||||||
@@ -63,24 +67,19 @@
|
|||||||
export function route(path: string, component: Component<{}>): void {
|
export function route(path: string, component: Component<{}>): void {
|
||||||
if (routes.has(path)) {
|
if (routes.has(path)) {
|
||||||
console.warn(`Route already registered for path: '${path}'.`);
|
console.warn(`Route already registered for path: '${path}'.`);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = Array.from(path.matchAll(/\[([^\]]+)\]/g)).map(
|
const params = Array.from(path.matchAll(/\[([^\]]+)\]/g)).map((x) => x[1]);
|
||||||
(x) => x[1],
|
|
||||||
);
|
|
||||||
|
|
||||||
routes.set(path, {
|
routes.set(path, {
|
||||||
pattern: new RegExp(createRoutePattern(path)),
|
pattern: new RegExp(createRoutePattern(path)),
|
||||||
path: path,
|
path: path,
|
||||||
paramNames: params,
|
paramNames: params,
|
||||||
component: component,
|
component: component
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RouteError extends Error {}
|
|
||||||
export class MissingRouteError extends RouteError {}
|
|
||||||
export class RouteFormatError extends RouteError {}
|
|
||||||
|
|
||||||
export function isCurrentPath(path: string): boolean {
|
export function isCurrentPath(path: string): boolean {
|
||||||
if (!currentRoute) {
|
if (!currentRoute) {
|
||||||
return false;
|
return false;
|
||||||
@@ -100,9 +99,7 @@
|
|||||||
export function paramString(name: string): string {
|
export function paramString(name: string): string {
|
||||||
const value = currentParams[name];
|
const value = currentParams[name];
|
||||||
if (!value) {
|
if (!value) {
|
||||||
throw new MissingRouteError(
|
throw new MissingRouteError(`Route does not have a parameter matching the name '${name}''`);
|
||||||
`Route does not have a parameter matching the name '${name}''`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -115,9 +112,7 @@
|
|||||||
const value = paramString(name);
|
const value = paramString(name);
|
||||||
const parsed = parseInt(value, 10);
|
const parsed = parseInt(value, 10);
|
||||||
if (Number.isNaN(parsed)) {
|
if (Number.isNaN(parsed)) {
|
||||||
throw new RouteFormatError(
|
throw new RouteFormatError(`parameter ${value} could not be parsed as an integer`);
|
||||||
`parameter ${value} could not be parsed as an integer`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
@@ -129,10 +124,7 @@
|
|||||||
*/
|
*/
|
||||||
export function queryString(name: string): string | null;
|
export function queryString(name: string): string | null;
|
||||||
export function queryString(name: string, defaultValue: string): string;
|
export function queryString(name: string, defaultValue: string): string;
|
||||||
export function queryString(
|
export function queryString(name: string, defaultValue?: string): string | null {
|
||||||
name: string,
|
|
||||||
defaultValue?: string,
|
|
||||||
): string | null {
|
|
||||||
const value = currentUrl.searchParams.get(name);
|
const value = currentUrl.searchParams.get(name);
|
||||||
if (value) {
|
if (value) {
|
||||||
return value;
|
return value;
|
||||||
@@ -147,10 +139,7 @@
|
|||||||
*/
|
*/
|
||||||
export function queryNumber(name: string): number | null;
|
export function queryNumber(name: string): number | null;
|
||||||
export function queryNumber(name: string, defaultValue: number): number;
|
export function queryNumber(name: string, defaultValue: number): number;
|
||||||
export function queryNumber(
|
export function queryNumber(name: string, defaultValue?: number): number | null {
|
||||||
name: string,
|
|
||||||
defaultValue?: number,
|
|
||||||
): number | null {
|
|
||||||
const value = currentUrl.searchParams.get(name);
|
const value = currentUrl.searchParams.get(name);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -179,7 +168,7 @@
|
|||||||
event.intercept({
|
event.intercept({
|
||||||
handler: async () => {
|
handler: async () => {
|
||||||
currentUrl = new URL(event.destination.url);
|
currentUrl = new URL(event.destination.url);
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,59 +177,7 @@
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.navigation.removeEventListener(
|
window.navigation.removeEventListener("navigate", handleNavigate);
|
||||||
"navigate",
|
|
||||||
handleNavigate,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
function refresh() {
|
|
||||||
currentUrl = new URL(window.location.href);
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeProxy(target: any) {
|
|
||||||
return new Proxy(target, {
|
|
||||||
apply: (target, thisArg, argArray) => {
|
|
||||||
const result = target.apply(thisArg, argArray);
|
|
||||||
refresh();
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.history.pushState = makeProxy(window.history.pushState);
|
|
||||||
window.history.replaceState = makeProxy(
|
|
||||||
window.history.replaceState,
|
|
||||||
);
|
|
||||||
window.history.go = makeProxy(window.history.go);
|
|
||||||
window.history.forward = makeProxy(window.history.forward);
|
|
||||||
window.history.back = makeProxy(window.history.back);
|
|
||||||
|
|
||||||
function handleClick(e: MouseEvent) {
|
|
||||||
if (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const anchor = (e.target as Element)?.closest("a");
|
|
||||||
if (!(anchor instanceof HTMLAnchorElement)) return;
|
|
||||||
if (anchor.target === "_blank") return;
|
|
||||||
|
|
||||||
const targetUrl = new URL(anchor.href, document.baseURI);
|
|
||||||
const documentUrl = new URL(document.baseURI);
|
|
||||||
|
|
||||||
if (targetUrl.origin === documentUrl.origin) {
|
|
||||||
e.preventDefault();
|
|
||||||
history.pushState({}, "", targetUrl);
|
|
||||||
currentUrl = targetUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("popstate", refresh);
|
|
||||||
document.addEventListener("click", handleClick);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("popstate", refresh);
|
|
||||||
document.removeEventListener("click", handleClick);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,34 +1,20 @@
|
|||||||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||||
<svg {...$$restProps} width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg">
|
<svg {...$$restProps} width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg">
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient x1="8.042%" y1="0%" x2="65.682%" y2="23.865%" id="a">
|
<linearGradient x1="8.042%" y1="0%" x2="65.682%" y2="23.865%" id="a">
|
||||||
<stop stop-color="currentColor" stop-opacity="0" offset="0%" />
|
<stop stop-color="currentColor" stop-opacity="0" offset="0%" />
|
||||||
<stop stop-color="currentColor" stop-opacity=".631" offset="63.146%" />
|
<stop stop-color="currentColor" stop-opacity=".631" offset="63.146%" />
|
||||||
<stop stop-color="currentColor" offset="100%" />
|
<stop stop-color="currentColor" offset="100%" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
<g fill="none" fill-rule="evenodd">
|
<g fill="none" fill-rule="evenodd">
|
||||||
<g transform="translate(1 1)">
|
<g transform="translate(1 1)">
|
||||||
<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke="url(#a)" stroke-width="2">
|
<path d="M36 18c0-9.94-8.06-18-18-18" id="Oval-2" stroke="url(#a)" stroke-width="2">
|
||||||
<animateTransform
|
<animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.9s" repeatCount="indefinite" />
|
||||||
attributeName="transform"
|
</path>
|
||||||
type="rotate"
|
<circle fill="currentColor" cx="36" cy="18" r="1">
|
||||||
from="0 18 18"
|
<animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.9s" repeatCount="indefinite" />
|
||||||
to="360 18 18"
|
</circle>
|
||||||
dur="0.9s"
|
</g>
|
||||||
repeatCount="indefinite"
|
</g>
|
||||||
/>
|
|
||||||
</path>
|
|
||||||
<circle fill="currentColor" cx="36" cy="18" r="1">
|
|
||||||
<animateTransform
|
|
||||||
attributeName="transform"
|
|
||||||
type="rotate"
|
|
||||||
from="0 18 18"
|
|
||||||
to="360 18 18"
|
|
||||||
dur="0.9s"
|
|
||||||
repeatCount="indefinite"
|
|
||||||
/>
|
|
||||||
</circle>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -9,29 +9,15 @@
|
|||||||
|
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
{#if leftIcon}
|
{#if leftIcon}
|
||||||
<img
|
<img src={leftIcon} class={`h-6 ${invertColor && "dark:invert"}`} alt="" />
|
||||||
src={leftIcon}
|
|
||||||
class={`h-6 ${invertColor && "dark:invert"}`}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
{/if}
|
{/if}
|
||||||
<label class="relative inline-flex cursor-pointer items-center">
|
<label class="relative inline-flex cursor-pointer items-center">
|
||||||
<input
|
<input on:change {checked} type="checkbox" value="" class="peer sr-only" />
|
||||||
on:change
|
|
||||||
{checked}
|
|
||||||
type="checkbox"
|
|
||||||
value=""
|
|
||||||
class="peer sr-only"
|
|
||||||
/>
|
|
||||||
<div
|
<div
|
||||||
class="h-6 w-11 rounded-full border-2 border-contrast-100 outline-2 transition-colors after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border-2 after:border-contrast-100 after:bg-contrast-900 after:transition-all after:content-[''] peer-checked:bg-accent peer-checked:after:translate-x-full dark:peer-focus:ring-accent"
|
class="h-6 w-11 rounded-full border-2 border-contrast-100 outline-2 transition-colors after:absolute after:left-0.5 after:top-0.5 after:h-5 after:w-5 after:rounded-full after:border-2 after:border-contrast-100 after:bg-contrast-900 after:transition-all after:content-[''] peer-checked:bg-accent peer-checked:after:translate-x-full dark:peer-focus:ring-accent"
|
||||||
></div>
|
></div>
|
||||||
</label>
|
</label>
|
||||||
{#if rightIcon}
|
{#if rightIcon}
|
||||||
<img
|
<img src={rightIcon} class={`h-6 ${invertColor && "dark:invert"}`} alt="" />
|
||||||
src={rightIcon}
|
|
||||||
class={`h-6 ${invertColor && "dark:invert"}`}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Spinner from '../Spinner.svelte';
|
import Spinner from "../Spinner.svelte";
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
/** @description Disallow clicking and reduce opacity **/
|
/** @description Disallow clicking and reduce opacity **/
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
/** @description Show a loading spinner **/
|
/** @description Show a loading spinner **/
|
||||||
export let loading = false;
|
export let loading = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
on:click
|
on:click
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
disabled={disabled || loading}
|
disabled={disabled || loading}
|
||||||
class:opacity-50={disabled || loading}
|
class:opacity-50={disabled || loading}
|
||||||
class:cursor-not-allowed={disabled || loading}
|
class:cursor-not-allowed={disabled || loading}
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
'relative rounded-md border-2 border-contrast-200 bg-primary-300 px-4 py-2 transition-colors hover:border-contrast-900 dark:border-contrast-100 dark:hover:border-accent',
|
"relative rounded-md border-2 border-contrast-200 bg-primary-300 px-4 py-2 transition-colors hover:border-contrast-900 dark:border-contrast-100 dark:hover:border-accent",
|
||||||
$$restProps['class']
|
$$restProps["class"]
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span class:opacity-0={loading}>
|
<span class:opacity-0={loading}>
|
||||||
<slot />
|
<slot />
|
||||||
</span>
|
</span>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
<span class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
|
<span class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||||
<Spinner class="h-6" />
|
<Spinner class="h-6" />
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,61 +1,57 @@
|
|||||||
<script lang="ts" generics="T">
|
<script lang="ts" generics="T">
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
export let items: T[];
|
export let items: T[];
|
||||||
|
|
||||||
/** @description Tailwind classes for styling the button colors */
|
/** @description Tailwind classes for styling the button colors */
|
||||||
export let buttonClass = '';
|
export let buttonClass = "";
|
||||||
|
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
|
||||||
const next = () => {
|
const next = () => {
|
||||||
index = (index + 1) % items.length;
|
index = (index + 1) % items.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
const prev = () => {
|
const prev = () => {
|
||||||
index = (index - 1 + items.length) % items.length;
|
index = (index - 1 + items.length) % items.length;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div style={`--index: ${index}`} {...$$restProps} class={twMerge("inline-flex w-full gap-5 overflow-auto sm:overflow-hidden", $$restProps["class"])}>
|
||||||
style={`--index: ${index}`}
|
{#each items as item, index}
|
||||||
{...$$restProps}
|
<div class="carousel transition-transform">
|
||||||
class={twMerge('inline-flex w-full gap-5 overflow-auto sm:overflow-hidden', $$restProps['class'])}
|
<slot {item} {index} />
|
||||||
>
|
</div>
|
||||||
{#each items as item, index}
|
{/each}
|
||||||
<div class="carousel transition-transform">
|
|
||||||
<slot {item} {index} />
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hidden sm:block">
|
<div class="hidden sm:block">
|
||||||
{#if items.length > 1}
|
{#if items.length > 1}
|
||||||
<div class="mt-2 flex justify-between md:text-lg">
|
<div class="mt-2 flex justify-between md:text-lg">
|
||||||
<button
|
<button
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
'rounded-md border-2 border-contrast-100 bg-primary-300 px-4 py-2 transition-colors hover:border-contrast-200 dark:hover:border-accent',
|
"rounded-md border-2 border-contrast-100 bg-primary-300 px-4 py-2 transition-colors hover:border-contrast-200 dark:hover:border-accent",
|
||||||
buttonClass
|
buttonClass
|
||||||
)}
|
)}
|
||||||
on:click={prev}
|
on:click={prev}
|
||||||
>
|
>
|
||||||
Forrige
|
Forrige
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
'rounded-md border-2 border-contrast-100 bg-primary-300 px-4 py-2 transition-colors hover:border-contrast-200 dark:hover:border-accent',
|
"rounded-md border-2 border-contrast-100 bg-primary-300 px-4 py-2 transition-colors hover:border-contrast-200 dark:hover:border-accent",
|
||||||
buttonClass
|
buttonClass
|
||||||
)}
|
)}
|
||||||
on:click={next}
|
on:click={next}
|
||||||
>
|
>
|
||||||
Neste
|
Neste
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.carousel {
|
.carousel {
|
||||||
transform: translateX(calc((-100% - 20px) * var(--index)));
|
transform: translateX(calc((-100% - 20px) * var(--index)));
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,79 +1,56 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
export let layout: 'narrow' | 'wide' = 'wide';
|
export let layout: "narrow" | "wide" = "wide";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if layout === 'wide'}
|
{#if layout === "wide"}
|
||||||
<svg
|
<svg xmlns="http://www.w3.org/2000/svg" class={twMerge("h-full", $$restProps["class"])} {...$$restProps} viewBox="0 0 1840.81 395.57">
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<path fill="currentColor" d="M102,153.89,50.09,81.21V191.75H.34V6.59H50.09l64.66,94.79L179.42,6.59h49.74V191.75H179.42V81.21l-51.95,72.68Z" />
|
||||||
class={twMerge('h-full', $$restProps['class'])}
|
<path fill="currentColor" d="M336.11,6.59V191.75H286.36V6.59Z" />
|
||||||
{...$$restProps}
|
<path fill="currentColor" d="M535.35,125.42V6.59H585.1V191.75H535.35l-97-118.83V191.75H388.61V6.59h49.74Z" />
|
||||||
viewBox="0 0 1840.81 395.57"
|
<path fill="currentColor" d="M692,6.59V191.75H642.3V6.59Z" />
|
||||||
>
|
<path
|
||||||
<path
|
fill="currentColor"
|
||||||
fill="currentColor"
|
d="M845.69,1.07h7.74c61.9,0,79,24.87,79,55.27v5.52c0,16.31-8,30.4-32.88,37,29,6.64,38.41,21.28,38.41,37.59V142c0,30.39-18.24,55.27-84.56,55.27h-7.74a927.22,927.22,0,0,1-101.14-5.53V6.59A927.25,927.25,0,0,1,845.69,1.07Zm-51.4,46.7V78.44h49.19c44.77,0,44.77-7.18,44.77-16.58,0-9.12-1.38-16.58-41.45-16.58C833.25,45.28,812.53,46.11,794.29,47.77Zm0,74.89v27.91c18.24,1.66,38.69,2.49,53.33,2.49,44.22,0,46.16-7.46,46.16-16.58,0-7.74,0-13.82-50.3-13.82Z"
|
||||||
d="M102,153.89,50.09,81.21V191.75H.34V6.59H50.09l64.66,94.79L179.42,6.59h49.74V191.75H179.42V81.21l-51.95,72.68Z"
|
/>
|
||||||
/>
|
<path
|
||||||
<path fill="currentColor" d="M336.11,6.59V191.75H286.36V6.59Z" />
|
fill="currentColor"
|
||||||
<path
|
d="M1185.32,6.59V114.65c0,45.32-20.73,82.63-94.51,82.63h-10c-73.79,0-94.51-37.31-94.51-82.63V6.59h49.74V107.46c0,24,0,45.6,49.74,45.6s49.75-21.56,49.75-45.6V6.59Z"
|
||||||
fill="currentColor"
|
/>
|
||||||
d="M535.35,125.42V6.59H585.1V191.75H535.35l-97-118.83V191.75H388.61V6.59h49.74Z"
|
<path
|
||||||
/>
|
fill="currentColor"
|
||||||
<path fill="currentColor" d="M692,6.59V191.75H642.3V6.59Z" />
|
d="M1369.37,137c0-13-11.61-14.92-43.67-15.75-28.18-.83-89.53-2.76-89.53-56.65V61c0-31.78,20.45-60,90.64-60h10a290.93,290.93,0,0,1,72.12,9.12V55.78c-26.8-6.35-53.05-10.22-80.14-10.22-40.07,0-42.83,9.12-42.83,15.47,0,13.27,12.16,15.2,43.39,16,26.25.56,89.81,2.49,89.81,56.93v3.59c0,31.51-20.45,59.7-90.92,59.7h-10a400.9,400.9,0,0,1-82.9-8.85V142c29.84,6.63,63.28,11.05,91.47,11.05C1366.33,153.06,1369.37,143.94,1369.37,137Z"
|
||||||
<path
|
/>
|
||||||
fill="currentColor"
|
<path
|
||||||
d="M845.69,1.07h7.74c61.9,0,79,24.87,79,55.27v5.52c0,16.31-8,30.4-32.88,37,29,6.64,38.41,21.28,38.41,37.59V142c0,30.39-18.24,55.27-84.56,55.27h-7.74a927.22,927.22,0,0,1-101.14-5.53V6.59A927.25,927.25,0,0,1,845.69,1.07Zm-51.4,46.7V78.44h49.19c44.77,0,44.77-7.18,44.77-16.58,0-9.12-1.38-16.58-41.45-16.58C833.25,45.28,812.53,46.11,794.29,47.77Zm0,74.89v27.91c18.24,1.66,38.69,2.49,53.33,2.49,44.22,0,46.16-7.46,46.16-16.58,0-7.74,0-13.82-50.3-13.82Z"
|
fill="#ff1d25"
|
||||||
/>
|
d="M846.11,350.74c0-9.9-8.84-11.37-33.26-12-21.48-.63-68.22-2.11-68.22-43.16v-2.74c0-24.21,15.58-45.69,69.06-45.69h7.58a222,222,0,0,1,55,6.95v34.74c-20.42-4.84-40.43-7.79-61.06-7.79-30.53,0-32.63,6.95-32.63,11.79,0,10.11,9.26,11.58,33.05,12.21,20,.42,68.43,1.9,68.43,43.37v2.74c0,24-15.58,45.48-69.27,45.48h-7.58A305.66,305.66,0,0,1,744,389.9V354.53c22.74,5.05,48.21,8.42,69.69,8.42C843.79,363,846.11,356,846.11,350.74Z"
|
||||||
<path
|
/>
|
||||||
fill="currentColor"
|
<path fill="#ff1d25" d="M1056.87,285.05H959.81V306.1h76v33.69h-76v18.95h97.06v33.69h-135V251.36h135Z" />
|
||||||
d="M1185.32,6.59V114.65c0,45.32-20.73,82.63-94.51,82.63h-10c-73.79,0-94.51-37.31-94.51-82.63V6.59h49.74V107.46c0,24,0,45.6,49.74,45.6s49.75-21.56,49.75-45.6V6.59Z"
|
<path
|
||||||
/>
|
fill="#ff1d25"
|
||||||
<path
|
d="M1201.09,392.43l-28.21-44.22c-15,0-29.06,0-42.53-2.1v46.32h-37.9V251.36a707.77,707.77,0,0,1,77.06-4.21h5.89c47.17,0,60.22,20.85,60.22,46.32v8.42c0,17.69-5.9,33.06-24,40.85l26.1,41.26v8.43Zm-70.74-109.7v29.9a266.16,266.16,0,0,0,33.05,1.9c33.69,0,34.32-5.9,34.32-19.16,0-7.58-.21-14.53-27.79-14.53C1160.25,280.84,1144.25,281.47,1130.35,282.73Z"
|
||||||
fill="currentColor"
|
/>
|
||||||
d="M1369.37,137c0-13-11.61-14.92-43.67-15.75-28.18-.83-89.53-2.76-89.53-56.65V61c0-31.78,20.45-60,90.64-60h10a290.93,290.93,0,0,1,72.12,9.12V55.78c-26.8-6.35-53.05-10.22-80.14-10.22-40.07,0-42.83,9.12-42.83,15.47,0,13.27,12.16,15.2,43.39,16,26.25.56,89.81,2.49,89.81,56.93v3.59c0,31.51-20.45,59.7-90.92,59.7h-10a400.9,400.9,0,0,1-82.9-8.85V142c29.84,6.63,63.28,11.05,91.47,11.05C1366.33,153.06,1369.37,143.94,1369.37,137Z"
|
<path fill="#ff1d25" d="M1426,251.36v8.43l-62.75,132.64h-37.89l-62.74-132.64v-8.43h34.1l47.58,107.38,47.59-107.38Z" />
|
||||||
/>
|
<path fill="#ff1d25" d="M1496.49,251.36V392.43h-37.9V251.36Z" />
|
||||||
<path
|
<path
|
||||||
fill="#ff1d25"
|
fill="#ff1d25"
|
||||||
d="M846.11,350.74c0-9.9-8.84-11.37-33.26-12-21.48-.63-68.22-2.11-68.22-43.16v-2.74c0-24.21,15.58-45.69,69.06-45.69h7.58a222,222,0,0,1,55,6.95v34.74c-20.42-4.84-40.43-7.79-61.06-7.79-30.53,0-32.63,6.95-32.63,11.79,0,10.11,9.26,11.58,33.05,12.21,20,.42,68.43,1.9,68.43,43.37v2.74c0,24-15.58,45.48-69.27,45.48h-7.58A305.66,305.66,0,0,1,744,389.9V354.53c22.74,5.05,48.21,8.42,69.69,8.42C843.79,363,846.11,356,846.11,350.74Z"
|
d="M1534.39,316.42c0-38.11,16.63-69.27,76.22-69.27h7.57a218.19,218.19,0,0,1,54.32,6.95v34.32c-19.37-5.69-41-7.79-55.37-7.79-44,0-44,17.26-44,41.26s0,41.48,44,41.48a212.15,212.15,0,0,0,55.37-8V389.9a228.46,228.46,0,0,1-54.32,6.74h-7.57c-59.59,0-76.22-31.16-76.22-69.27Z"
|
||||||
/>
|
/>
|
||||||
<path
|
<path fill="#ff1d25" d="M1841.15,285.05h-97.06V306.1h76v33.69h-76v18.95h97.06v33.69h-135V251.36h135Z" />
|
||||||
fill="#ff1d25"
|
<polygon fill="currentColor" points="1458.66 108.93 1458.66 83.93 1565.16 96.43 1671.66 108.93 1565.16 121.43 1458.66 133.93 1458.66 108.93" />
|
||||||
d="M1056.87,285.05H959.81V306.1h76v33.69h-76v18.95h97.06v33.69h-135V251.36h135Z"
|
</svg>
|
||||||
/>
|
{:else if layout === "narrow"}
|
||||||
<path
|
<svg class={$$restProps["class"]} {...$$restProps} viewBox="0 0 1920 1920">
|
||||||
fill="#ff1d25"
|
<g>
|
||||||
d="M1201.09,392.43l-28.21-44.22c-15,0-29.06,0-42.53-2.1v46.32h-37.9V251.36a707.77,707.77,0,0,1,77.06-4.21h5.89c47.17,0,60.22,20.85,60.22,46.32v8.42c0,17.69-5.9,33.06-24,40.85l26.1,41.26v8.43Zm-70.74-109.7v29.9a266.16,266.16,0,0,0,33.05,1.9c33.69,0,34.32-5.9,34.32-19.16,0-7.58-.21-14.53-27.79-14.53C1160.25,280.84,1144.25,281.47,1130.35,282.73Z"
|
<path
|
||||||
/>
|
fill="#ff1d25"
|
||||||
<path
|
d="M780.1,1364.81l88.49-508.71l-323.41,419.08h-88.42L280.44,867l-87.78,497.81H8.56l149.5-847.85h162.3 l224.43,526.88l405.4-526.88h161.09l-147.08,847.85H780.1z"
|
||||||
fill="#ff1d25"
|
/>
|
||||||
d="M1426,251.36v8.43l-62.75,132.64h-37.89l-62.74-132.64v-8.43h34.1l47.58,107.38,47.59-107.38Z"
|
<path
|
||||||
/>
|
fill="#ff1d25"
|
||||||
<path fill="#ff1d25" d="M1496.49,251.36V392.43h-37.9V251.36Z" />
|
d="M1113.38,1281.23l92.67-147.77c62.28,52.08,162.46,88.42,264.2,88.42c116.28,0,170.35-38.76,179.53-90.84 c27.98-158.67-484.21-49.66-428.68-364.58c25.42-144.14,162.83-264.05,403.87-264.05c106.59,0,211.11,25.44,281.08,75.1 l-86.83,148.98c-70.83-44.81-148.13-66.62-223.23-66.62c-116.28,0-168.78,43.6-178.18,96.9 c-27.55,156.25,484.42,48.45,429.53,359.73c-24.99,141.71-163.83,262.83-406.08,262.83 C1306.83,1379.34,1178.22,1339.37,1113.38,1281.23z"
|
||||||
<path
|
/>
|
||||||
fill="#ff1d25"
|
</g>
|
||||||
d="M1534.39,316.42c0-38.11,16.63-69.27,76.22-69.27h7.57a218.19,218.19,0,0,1,54.32,6.95v34.32c-19.37-5.69-41-7.79-55.37-7.79-44,0-44,17.26-44,41.26s0,41.48,44,41.48a212.15,212.15,0,0,0,55.37-8V389.9a228.46,228.46,0,0,1-54.32,6.74h-7.57c-59.59,0-76.22-31.16-76.22-69.27Z"
|
</svg>
|
||||||
/>
|
|
||||||
<path
|
|
||||||
fill="#ff1d25"
|
|
||||||
d="M1841.15,285.05h-97.06V306.1h76v33.69h-76v18.95h97.06v33.69h-135V251.36h135Z"
|
|
||||||
/>
|
|
||||||
<polygon
|
|
||||||
fill="currentColor"
|
|
||||||
points="1458.66 108.93 1458.66 83.93 1565.16 96.43 1671.66 108.93 1565.16 121.43 1458.66 133.93 1458.66 108.93"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
{:else if layout === 'narrow'}
|
|
||||||
<svg class={$$restProps['class']} {...$$restProps} viewBox="0 0 1920 1920">
|
|
||||||
<g>
|
|
||||||
<path
|
|
||||||
fill="#ff1d25"
|
|
||||||
d="M780.1,1364.81l88.49-508.71l-323.41,419.08h-88.42L280.44,867l-87.78,497.81H8.56l149.5-847.85h162.3 l224.43,526.88l405.4-526.88h161.09l-147.08,847.85H780.1z"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
fill="#ff1d25"
|
|
||||||
d="M1113.38,1281.23l92.67-147.77c62.28,52.08,162.46,88.42,264.2,88.42c116.28,0,170.35-38.76,179.53-90.84 c27.98-158.67-484.21-49.66-428.68-364.58c25.42-144.14,162.83-264.05,403.87-264.05c106.59,0,211.11,25.44,281.08,75.1 l-86.83,148.98c-70.83-44.81-148.13-66.62-223.23-66.62c-116.28,0-168.78,43.6-178.18,96.9 c-27.55,156.25,484.42,48.45,429.53,359.73c-24.99,141.71-163.83,262.83-406.08,262.83 C1306.83,1379.34,1178.22,1339.37,1113.38,1281.23z"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
class={twMerge('h-full', $$restProps['class'])}
|
class={twMerge("h-full", $$restProps["class"])}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="Layer_1"
|
id="Layer_1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 0 493.488 493.488"
|
viewBox="0 0 493.488 493.488"
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
>
|
>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path
|
<path
|
||||||
d="M492.358,143.652L350.266,1.304c-0.736-0.736-1.716-1.136-2.74-1.136L146.406,0c-1.012,0-1.996,0.4-2.716,1.108
|
d="M492.358,143.652L350.266,1.304c-0.736-0.736-1.716-1.136-2.74-1.136L146.406,0c-1.012,0-1.996,0.4-2.716,1.108
|
||||||
L1.358,143.216c-0.732,0.712-1.148,1.692-1.148,2.724L0.03,347.052c0,1.02,0.404,2,1.12,2.72l142.1,142.336
|
L1.358,143.216c-0.732,0.712-1.148,1.692-1.148,2.724L0.03,347.052c0,1.02,0.404,2,1.12,2.72l142.1,142.336
|
||||||
c0.72,0.712,1.692,1.168,2.716,1.168l201.12,0.212h0.008c1.02,0,1.996-0.44,2.704-1.16l142.36-142.1
|
c0.72,0.712,1.692,1.168,2.716,1.168l201.12,0.212h0.008c1.02,0,1.996-0.44,2.704-1.16l142.36-142.1
|
||||||
c0.736-0.716,1.136-1.704,1.136-2.724l0.164-201.128C493.458,145.352,493.062,144.368,492.358,143.652z M257.318,373.324
|
c0.736-0.716,1.136-1.704,1.136-2.724l0.164-201.128C493.458,145.352,493.062,144.368,492.358,143.652z M257.318,373.324
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
c-0.008,8.484-6.916,15.408-15.428,15.408c-8.512-0.008-15.428-6.94-15.42-15.436l0.216-169.668
|
c-0.008,8.484-6.916,15.408-15.428,15.408c-8.512-0.008-15.428-6.94-15.42-15.436l0.216-169.668
|
||||||
c0.008-8.512,7.776-15.428,15.488-15.428v-0.006c4.099,0.019,7.926,1.624,10.816,4.538c2.912,2.916,4.496,6.796,4.496,10.908
|
c0.008-8.512,7.776-15.428,15.488-15.428v-0.006c4.099,0.019,7.926,1.624,10.816,4.538c2.912,2.916,4.496,6.796,4.496,10.908
|
||||||
L261.894,300.728z"
|
L261.894,300.728z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
class={twMerge('h-full', $$restProps['class'])}
|
class={twMerge("h-full", $$restProps["class"])}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="Layer_1"
|
id="Layer_1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 0 493.636 493.636"
|
viewBox="0 0 493.636 493.636"
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
>
|
>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path
|
<path
|
||||||
d="M421.428,72.476C374.868,25.84,312.86,0.104,246.724,0.044C110.792,0.044,0.112,110.624,0,246.548
|
d="M421.428,72.476C374.868,25.84,312.86,0.104,246.724,0.044C110.792,0.044,0.112,110.624,0,246.548
|
||||||
c-0.068,65.912,25.544,127.944,72.1,174.584c46.564,46.644,108.492,72.46,174.4,72.46h0.58v-0.048
|
c-0.068,65.912,25.544,127.944,72.1,174.584c46.564,46.644,108.492,72.46,174.4,72.46h0.58v-0.048
|
||||||
c134.956,0,246.428-110.608,246.556-246.532C493.7,181.12,468,119.124,421.428,72.476z M257.516,377.292
|
c134.956,0,246.428-110.608,246.556-246.532C493.7,181.12,468,119.124,421.428,72.476z M257.516,377.292
|
||||||
c-2.852,2.856-6.844,4.5-10.904,4.5c-4.052,0-8.044-1.66-10.932-4.516c-2.856-2.864-4.496-6.852-4.492-10.916
|
c-2.852,2.856-6.844,4.5-10.904,4.5c-4.052,0-8.044-1.66-10.932-4.516c-2.856-2.864-4.496-6.852-4.492-10.916
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
c-0.008,8.508-6.928,15.404-15.448,15.404c-8.5-0.008-15.42-6.916-15.416-15.432L231.528,135
|
c-0.008,8.508-6.928,15.404-15.448,15.404c-8.5-0.008-15.42-6.916-15.416-15.432L231.528,135
|
||||||
c0.004-8.484,3.975-15.387,15.488-15.414c4.093,0.021,7.895,1.613,10.78,4.522c2.912,2.916,4.476,6.788,4.472,10.912
|
c0.004-8.484,3.975-15.387,15.488-15.414c4.093,0.021,7.895,1.613,10.78,4.522c2.912,2.916,4.476,6.788,4.472,10.912
|
||||||
L262.112,304.692z"
|
L262.112,304.692z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
class={twMerge('h-full', $$restProps['class'])}
|
class={twMerge("h-full", $$restProps["class"])}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="Layer_1"
|
id="Layer_1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 0 493.464 493.464"
|
viewBox="0 0 493.464 493.464"
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
>
|
>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path
|
<path
|
||||||
d="M246.736,0C110.692,0,0.004,110.68,0.004,246.732c0,136.06,110.688,246.732,246.732,246.732
|
d="M246.736,0C110.692,0,0.004,110.68,0.004,246.732c0,136.06,110.688,246.732,246.732,246.732
|
||||||
c136.048,0,246.724-110.672,246.724-246.732C493.456,110.68,382.78,0,246.736,0z M360.524,208.716L230.98,338.268
|
c136.048,0,246.724-110.672,246.724-246.732C493.456,110.68,382.78,0,246.736,0z M360.524,208.716L230.98,338.268
|
||||||
c-2.82,2.824-7.816,2.824-10.64,0l-86.908-86.912c-1.412-1.416-2.192-3.3-2.192-5.324c0.004-2.016,0.784-3.912,2.192-5.336
|
c-2.82,2.824-7.816,2.824-10.64,0l-86.908-86.912c-1.412-1.416-2.192-3.3-2.192-5.324c0.004-2.016,0.784-3.912,2.192-5.336
|
||||||
l11.108-11.104c1.412-1.408,3.3-2.18,5.328-2.18c2.016,0,3.908,0.772,5.316,2.18l67.752,67.752c1.5,1.516,3.94,1.516,5.444,0
|
l11.108-11.104c1.412-1.408,3.3-2.18,5.328-2.18c2.016,0,3.908,0.772,5.316,2.18l67.752,67.752c1.5,1.516,3.94,1.516,5.444,0
|
||||||
l110.392-110.392c2.824-2.824,7.828-2.824,10.644,0l11.108,11.124c1.412,1.4,2.208,3.304,2.208,5.308
|
l110.392-110.392c2.824-2.824,7.828-2.824,10.644,0l11.108,11.124c1.412,1.4,2.208,3.304,2.208,5.308
|
||||||
C362.732,205.412,361.936,207.3,360.524,208.716z"
|
C362.732,205.412,361.936,207.3,360.524,208.716z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
class={twMerge('h-full', $$restProps['class'])}
|
class={twMerge("h-full", $$restProps["class"])}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="Layer_1"
|
id="Layer_1"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
>
|
>
|
||||||
<g>
|
<g>
|
||||||
<g>
|
<g>
|
||||||
<path
|
<path
|
||||||
d="M507.494,426.066L282.864,53.537c-5.677-9.415-15.87-15.172-26.865-15.172c-10.995,0-21.188,5.756-26.865,15.172
|
d="M507.494,426.066L282.864,53.537c-5.677-9.415-15.87-15.172-26.865-15.172c-10.995,0-21.188,5.756-26.865,15.172
|
||||||
L4.506,426.066c-5.842,9.689-6.015,21.774-0.451,31.625c5.564,9.852,16.001,15.944,27.315,15.944h449.259
|
L4.506,426.066c-5.842,9.689-6.015,21.774-0.451,31.625c5.564,9.852,16.001,15.944,27.315,15.944h449.259
|
||||||
c11.314,0,21.751-6.093,27.315-15.944C513.508,447.839,513.336,435.755,507.494,426.066z M256.167,167.227
|
c11.314,0,21.751-6.093,27.315-15.944C513.508,447.839,513.336,435.755,507.494,426.066z M256.167,167.227
|
||||||
c12.901,0,23.817,7.278,23.817,20.178c0,39.363-4.631,95.929-4.631,135.292c0,10.255-11.247,14.554-19.186,14.554
|
c12.901,0,23.817,7.278,23.817,20.178c0,39.363-4.631,95.929-4.631,135.292c0,10.255-11.247,14.554-19.186,14.554
|
||||||
c-10.584,0-19.516-4.3-19.516-14.554c0-39.363-4.63-95.929-4.63-135.292C232.021,174.505,242.605,167.227,256.167,167.227z
|
c-10.584,0-19.516-4.3-19.516-14.554c0-39.363-4.63-95.929-4.63-135.292C232.021,174.505,242.605,167.227,256.167,167.227z
|
||||||
M256.498,411.018c-14.554,0-25.471-11.908-25.471-25.47c0-13.893,10.916-25.47,25.471-25.47c13.562,0,25.14,11.577,25.14,25.47
|
M256.498,411.018c-14.554,0-25.471-11.908-25.471-25.47c0-13.893,10.916-25.47,25.471-25.47c13.562,0,25.14,11.577,25.14,25.47
|
||||||
C281.638,399.11,270.06,411.018,256.498,411.018z"
|
C281.638,399.11,270.06,411.018,256.498,411.018z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
export let href: string;
|
export let href: string;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a
|
<a {...$$restProps} {href} class={twMerge("font-medium transition-colors hover:text-accent hover:underline", $$restProps["class"])}>
|
||||||
{...$$restProps}
|
<slot />
|
||||||
{href}
|
|
||||||
class={twMerge(
|
|
||||||
'font-medium transition-colors hover:text-accent hover:underline',
|
|
||||||
$$restProps['class']
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,59 +1,59 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { scale } from 'svelte/transition';
|
import { scale } from "svelte/transition";
|
||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
export const toggle = () => {
|
export const toggle = () => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
close();
|
close();
|
||||||
} else {
|
} else {
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const show = () => {
|
export const show = () => {
|
||||||
modalRef.showModal();
|
modalRef.showModal();
|
||||||
onShow();
|
onShow();
|
||||||
visible = true;
|
visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const close = () => {
|
export const close = () => {
|
||||||
modalRef.close();
|
modalRef.close();
|
||||||
onClose();
|
onClose();
|
||||||
visible = false;
|
visible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
export let onShow = () => {};
|
export let onShow = () => {};
|
||||||
export let onClose = () => {};
|
export let onClose = () => {};
|
||||||
|
|
||||||
let visible = false;
|
let visible = false;
|
||||||
|
|
||||||
let modalRef: HTMLDialogElement;
|
let modalRef: HTMLDialogElement;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||||
<dialog
|
<dialog
|
||||||
bind:this={modalRef}
|
bind:this={modalRef}
|
||||||
on:close={() => (visible = false)}
|
on:close={() => (visible = false)}
|
||||||
transition:scale={{ duration: 200 }}
|
transition:scale={{ duration: 200 }}
|
||||||
class={twMerge(
|
class={twMerge(
|
||||||
`fixed inset-0 z-40 flex max-h-[calc(100vh-16rem)] flex-col rounded-md border-2 border-contrast-100 bg-primary-100 p-6 text-contrast-900 lg:w-3/4`,
|
`fixed inset-0 z-40 flex max-h-[calc(100vh-16rem)] flex-col rounded-md border-2 border-contrast-100 bg-primary-100 p-6 text-contrast-900 lg:w-3/4`,
|
||||||
$$restProps['class'],
|
$$restProps["class"],
|
||||||
visible ? '' : 'hidden'
|
visible ? "" : "hidden"
|
||||||
)}
|
)}
|
||||||
{...$$restProps}
|
{...$$restProps}
|
||||||
>
|
>
|
||||||
<div class="mb-4 flex">
|
<div class="mb-4 flex">
|
||||||
<h1 class="grow text-2xl font-semibold">
|
<h1 class="grow text-2xl font-semibold">
|
||||||
<slot name="header" />
|
<slot name="header" />
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grow overflow-auto rounded-md bg-primary-300 p-4 shadow-inner">
|
<div class="grow overflow-auto rounded-md bg-primary-300 p-4 shadow-inner">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4 flex justify-end gap-4">
|
<div class="mt-4 flex justify-end gap-4">
|
||||||
<slot name="button-row" />
|
<slot name="button-row" />
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|||||||
@@ -8,9 +8,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $toasts.length >= 1}
|
{#if $toasts.length >= 1}
|
||||||
<div
|
<div class="fixed bottom-0 right-0 z-50 flex w-full flex-col gap-2 p-4 text-white sm:w-96">
|
||||||
class="fixed bottom-0 right-0 z-50 flex w-full flex-col gap-2 p-4 text-white sm:w-96"
|
|
||||||
>
|
|
||||||
{#each $toasts as toastItem}
|
{#each $toasts as toastItem}
|
||||||
<div
|
<div
|
||||||
class:bg-red-500={toastItem.type === "error"}
|
class:bg-red-500={toastItem.type === "error"}
|
||||||
@@ -42,24 +40,9 @@
|
|||||||
{toastItem.text}
|
{toastItem.text}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<button
|
<button on:click={() => toast.dismiss(toastItem.id)} class="shrink-0" aria-label="dismiss">
|
||||||
on:click={() => toast.dismiss(toastItem.id)}
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6">
|
||||||
class="shrink-0"
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||||
aria-label="dismiss"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
class="w-6"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
d="M6 18L18 6M6 6l12 12"
|
|
||||||
/>
|
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,46 +1,36 @@
|
|||||||
import { writable } from 'svelte/store';
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
export const toasts = writable<Toast[]>([]);
|
export const toasts = writable<Toast[]>([]);
|
||||||
|
|
||||||
type Toast = {
|
type Toast = {
|
||||||
id: string;
|
id: string;
|
||||||
type: 'success' | 'error' | 'info' | 'warning';
|
type: "success" | "error" | "info" | "warning";
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function addToast(
|
function addToast(text: string, type: "success" | "error" | "warning" | "info" = "info", dismissible: boolean) {
|
||||||
text: string,
|
const id: string = `toast-${crypto.randomUUID ? crypto.randomUUID() : Math.floor(Date.now() * Math.random() * 100).toString()}`;
|
||||||
type: 'success' | 'error' | 'warning' | 'info' = 'info',
|
|
||||||
dismissible: boolean
|
|
||||||
) {
|
|
||||||
const id: string = `toast-${
|
|
||||||
crypto.randomUUID
|
|
||||||
? crypto.randomUUID()
|
|
||||||
: Math.floor(Date.now() * Math.random() * 100).toString()
|
|
||||||
}`;
|
|
||||||
|
|
||||||
toasts.update((all) => [
|
toasts.update((all) => [
|
||||||
...all,
|
...all,
|
||||||
{
|
{
|
||||||
id: id,
|
id: id,
|
||||||
text: text,
|
text: text,
|
||||||
dismissible: dismissible,
|
dismissible: dismissible,
|
||||||
type: type
|
type: type
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismiss(id: string) {
|
function dismiss(id: string) {
|
||||||
toasts.update((all) => all.filter((x) => x.id !== id));
|
toasts.update((all) => all.filter((x) => x.id !== id));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const toast = {
|
export const toast = {
|
||||||
clear: () => toasts.set([]),
|
clear: () => toasts.set([]),
|
||||||
error: (text: string | null, dismissible = true) =>
|
error: (text: string | null, dismissible = true) => addToast(text ?? "En feil oppstod", "error", dismissible),
|
||||||
addToast(text ?? 'En feil oppstod', 'error', dismissible),
|
info: (text: string, dismissible = true) => addToast(text, "info", dismissible),
|
||||||
info: (text: string, dismissible = true) => addToast(text, 'info', dismissible),
|
warning: (text: string, dismissible = true) => addToast(text, "warning", dismissible),
|
||||||
warning: (text: string, dismissible = true) => addToast(text, 'warning', dismissible),
|
success: (text: string | null, dismissible = true) => addToast(text ?? "Suksess", "success", dismissible),
|
||||||
success: (text: string | null, dismissible = true) =>
|
dismiss: dismiss
|
||||||
addToast(text ?? 'Suksess', 'success', dismissible),
|
|
||||||
dismiss: dismiss
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
import homeIcon from "../../assets/icons/home_icon.svg";
|
|
||||||
import contactIcon from "../../assets/icons/contact_icon.svg";
|
|
||||||
import busIcon from "../../assets/icons/bus_icon.svg";
|
|
||||||
|
|
||||||
type Route = {
|
|
||||||
url: string;
|
|
||||||
text: string;
|
|
||||||
icon: string | null;
|
|
||||||
target: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Routes {
|
|
||||||
static home: Route = {
|
|
||||||
url: "/",
|
|
||||||
text: "Hjem",
|
|
||||||
icon: homeIcon,
|
|
||||||
target: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bus: Route = {
|
|
||||||
url: "/bus",
|
|
||||||
text: "Buss",
|
|
||||||
icon: busIcon,
|
|
||||||
target: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
static taxi: Route = {
|
|
||||||
url: "/taxi",
|
|
||||||
text: "Taxi",
|
|
||||||
icon: null,
|
|
||||||
target: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
static accessibility: Route = {
|
|
||||||
url: "/accessibility",
|
|
||||||
text: "Tilgjengelighetsfunksjoner",
|
|
||||||
icon: null,
|
|
||||||
target: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
static contact: Route = {
|
|
||||||
url: "/contact",
|
|
||||||
text: "Ta kontakt",
|
|
||||||
icon: contactIcon,
|
|
||||||
target: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
static facebook: Route = {
|
|
||||||
url: "https://www.facebook.com/MinibusserviceSteneAS/",
|
|
||||||
text: "Facebook",
|
|
||||||
icon: null,
|
|
||||||
target: "_blank",
|
|
||||||
};
|
|
||||||
|
|
||||||
static email: Route = {
|
|
||||||
url: "mailto:minibusstur@hotmail.com",
|
|
||||||
text: "E-post",
|
|
||||||
icon: null,
|
|
||||||
target: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
static phone: Route = {
|
|
||||||
url: "tel:45256161",
|
|
||||||
text: "Telefon",
|
|
||||||
icon: null,
|
|
||||||
target: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
static topbarRoutes: Route[] = [Routes.home, Routes.bus, Routes.contact];
|
|
||||||
|
|
||||||
static sidebarRoutes: Route[] = [
|
|
||||||
Routes.home,
|
|
||||||
Routes.bus,
|
|
||||||
Routes.taxi,
|
|
||||||
Routes.accessibility,
|
|
||||||
Routes.contact,
|
|
||||||
];
|
|
||||||
|
|
||||||
static footerRoutes: { text: string; routes: Route[] }[] = [
|
|
||||||
{
|
|
||||||
text: "HJELP",
|
|
||||||
routes: [Routes.contact],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "SIDER",
|
|
||||||
routes: [
|
|
||||||
Routes.home,
|
|
||||||
Routes.bus,
|
|
||||||
Routes.taxi,
|
|
||||||
Routes.accessibility,
|
|
||||||
Routes.contact,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "MINIBUSSERVICE",
|
|
||||||
routes: [Routes.facebook, Routes.email, Routes.phone],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
87
src/lib/routes.ts
Normal file
87
src/lib/routes.ts
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import homeIcon from "../assets/icons/home_icon.svg";
|
||||||
|
import contactIcon from "../assets/icons/contact_icon.svg";
|
||||||
|
import busIcon from "../assets/icons/bus_icon.svg";
|
||||||
|
|
||||||
|
type Route = {
|
||||||
|
url: string;
|
||||||
|
text: string;
|
||||||
|
icon: string | null;
|
||||||
|
target: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Routes {
|
||||||
|
static home: Route = {
|
||||||
|
url: "/",
|
||||||
|
text: "Hjem",
|
||||||
|
icon: homeIcon,
|
||||||
|
target: null
|
||||||
|
};
|
||||||
|
|
||||||
|
static bus: Route = {
|
||||||
|
url: "/bus",
|
||||||
|
text: "Buss",
|
||||||
|
icon: busIcon,
|
||||||
|
target: null
|
||||||
|
};
|
||||||
|
|
||||||
|
static taxi: Route = {
|
||||||
|
url: "/taxi",
|
||||||
|
text: "Taxi",
|
||||||
|
icon: null,
|
||||||
|
target: null
|
||||||
|
};
|
||||||
|
|
||||||
|
static accessibility: Route = {
|
||||||
|
url: "/accessibility",
|
||||||
|
text: "Tilgjengelighetsfunksjoner",
|
||||||
|
icon: null,
|
||||||
|
target: null
|
||||||
|
};
|
||||||
|
|
||||||
|
static contact: Route = {
|
||||||
|
url: "/contact",
|
||||||
|
text: "Ta kontakt",
|
||||||
|
icon: contactIcon,
|
||||||
|
target: null
|
||||||
|
};
|
||||||
|
|
||||||
|
static facebook: Route = {
|
||||||
|
url: "https://www.facebook.com/MinibusserviceSteneAS/",
|
||||||
|
text: "Facebook",
|
||||||
|
icon: null,
|
||||||
|
target: "_blank"
|
||||||
|
};
|
||||||
|
|
||||||
|
static email: Route = {
|
||||||
|
url: "mailto:minibusstur@hotmail.com",
|
||||||
|
text: "E-post",
|
||||||
|
icon: null,
|
||||||
|
target: null
|
||||||
|
};
|
||||||
|
|
||||||
|
static phone: Route = {
|
||||||
|
url: "tel:45256161",
|
||||||
|
text: "Telefon",
|
||||||
|
icon: null,
|
||||||
|
target: null
|
||||||
|
};
|
||||||
|
|
||||||
|
static topbarRoutes: Route[] = [Routes.home, Routes.bus, Routes.contact];
|
||||||
|
|
||||||
|
static sidebarRoutes: Route[] = [Routes.home, Routes.bus, Routes.taxi, Routes.accessibility, Routes.contact];
|
||||||
|
|
||||||
|
static footerRoutes: { text: string; routes: Route[] }[] = [
|
||||||
|
{
|
||||||
|
text: "HJELP",
|
||||||
|
routes: [Routes.contact]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "SIDER",
|
||||||
|
routes: [Routes.home, Routes.bus, Routes.taxi, Routes.accessibility, Routes.contact]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "MINIBUSSERVICE",
|
||||||
|
routes: [Routes.facebook, Routes.email, Routes.phone]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import { writable } from "svelte/store";
|
|
||||||
|
|
||||||
function createThemeToggler() {
|
|
||||||
let defaultValue = false;
|
|
||||||
let savedValue = localStorage.getItem("dark_theme");
|
|
||||||
|
|
||||||
if (savedValue) {
|
|
||||||
defaultValue = JSON.parse(savedValue);
|
|
||||||
} else if (
|
|
||||||
window.matchMedia &&
|
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
||||||
) {
|
|
||||||
defaultValue = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defaultValue) {
|
|
||||||
document.body.dataset.theme = "dark";
|
|
||||||
} else {
|
|
||||||
document.body.dataset.theme = "light";
|
|
||||||
}
|
|
||||||
|
|
||||||
const { subscribe, update } = writable(defaultValue);
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe,
|
|
||||||
set: (value: boolean) => {
|
|
||||||
update(() => value);
|
|
||||||
if (value) {
|
|
||||||
document.body.dataset.theme = "dark";
|
|
||||||
} else {
|
|
||||||
document.body.dataset.theme = "light";
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem("dark_theme", JSON.stringify(value));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export const darkTheme = createThemeToggler();
|
|
||||||
24
src/lib/theme.svelte.ts
Normal file
24
src/lib/theme.svelte.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
function loadTheme() {
|
||||||
|
let theme = localStorage.getItem("theme");
|
||||||
|
if (!theme) {
|
||||||
|
if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||||
|
theme = "dark";
|
||||||
|
} else {
|
||||||
|
theme = "light";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentTheme = $state(loadTheme());
|
||||||
|
|
||||||
|
export function toggleTheme() {
|
||||||
|
const newTheme = currentTheme === "dark" ? "light" : "dark";
|
||||||
|
localStorage.setItem("theme", newTheme);
|
||||||
|
currentTheme = newTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTheme(): string {
|
||||||
|
return currentTheme;
|
||||||
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
export function debounce<T extends Function>(cb: T, wait = 500) {
|
|
||||||
let h: any;
|
|
||||||
let callable = () => {
|
|
||||||
clearTimeout(h);
|
|
||||||
h = setTimeout(() => cb(), wait);
|
|
||||||
};
|
|
||||||
return callable;
|
|
||||||
}
|
|
||||||
15
src/main.ts
15
src/main.ts
@@ -1,8 +1,21 @@
|
|||||||
import { mount } from "svelte";
|
import { mount } from "svelte";
|
||||||
|
import { route } from "./lib/components/Router.svelte";
|
||||||
import App from "./App.svelte";
|
import App from "./App.svelte";
|
||||||
|
|
||||||
|
import HomePage from "./pages/HomePage.svelte";
|
||||||
|
import TaxiPage from "./pages/TaxiPage.svelte";
|
||||||
|
import BusPage from "./pages/BusPage.svelte";
|
||||||
|
import ContactPage from "./pages/ContactPage.svelte";
|
||||||
|
import AccessibilityPage from "./pages/AccessibilityPage.svelte";
|
||||||
|
|
||||||
|
route("/", HomePage);
|
||||||
|
route("/taxi", TaxiPage);
|
||||||
|
route("/bus", BusPage);
|
||||||
|
route("/contact", ContactPage);
|
||||||
|
route("/accessibility", AccessibilityPage);
|
||||||
|
|
||||||
const app = mount(App, {
|
const app = mount(App, {
|
||||||
target: document.getElementById("app")!,
|
target: document.getElementById("app")!
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -4,34 +4,21 @@
|
|||||||
import threeRampsOpen from "../assets/images/three_ramps_open.jpg";
|
import threeRampsOpen from "../assets/images/three_ramps_open.jpg";
|
||||||
import Carousel from "../lib/components/carousel/Carousel.svelte";
|
import Carousel from "../lib/components/carousel/Carousel.svelte";
|
||||||
|
|
||||||
let rampCarouselItems: string[] = [
|
let rampCarouselItems: string[] = [singleRampLeftClosed, singleRampRightClosed, threeRampsOpen];
|
||||||
singleRampLeftClosed,
|
|
||||||
singleRampRightClosed,
|
|
||||||
threeRampsOpen,
|
|
||||||
];
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1 class="text-xl font-semibold md:text-2xl">Tilgjengelighetsfunksjoner</h1>
|
<h1 class="text-xl font-semibold md:text-2xl">Tilgjengelighetsfunksjoner</h1>
|
||||||
|
|
||||||
<section
|
<section class="mt-4 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex">
|
||||||
class="mt-4 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex"
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="grow text-lg font-semibold md:text-xl">
|
<h2 class="grow text-lg font-semibold md:text-xl">Sitter du i rullestol?</h2>
|
||||||
Sitter du i rullestol?
|
|
||||||
</h2>
|
|
||||||
<p class="md:text-lg">
|
<p class="md:text-lg">
|
||||||
Vi har flere busser med rullestolstøtte, med kapasitet opp til 2
|
Vi har flere busser med rullestolstøtte, med kapasitet opp til 2 rullestoler per buss.
|
||||||
rullestoler per buss.
|
|
||||||
<br />Total kapasitet er 5 rullestilbrukere fordelt på 3 busser
|
<br />Total kapasitet er 5 rullestilbrukere fordelt på 3 busser
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:w-96">
|
<div class="md:w-96">
|
||||||
<Carousel
|
<Carousel items={rampCarouselItems} buttonClass="bg-primary-200" let:item>
|
||||||
items={rampCarouselItems}
|
|
||||||
buttonClass="bg-primary-200"
|
|
||||||
let:item
|
|
||||||
>
|
|
||||||
<div class="h-full w-96 overflow-hidden shadow-sm">
|
<div class="h-full w-96 overflow-hidden shadow-sm">
|
||||||
<img class="card w-full object-cover" src={item} alt="" />
|
<img class="card w-full object-cover" src={item} alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,43 +9,23 @@
|
|||||||
import tourBusSideLogo from "../assets/images/tour_bus_side_logo.jpg";
|
import tourBusSideLogo from "../assets/images/tour_bus_side_logo.jpg";
|
||||||
import Carousel from "../lib/components/carousel/Carousel.svelte";
|
import Carousel from "../lib/components/carousel/Carousel.svelte";
|
||||||
|
|
||||||
let minibusCarouselItems: string[] = [
|
let minibusCarouselItems: string[] = [threeBusses, twoBusses, fiveBusses, singleRampLeftClosed, threeRampsOpen];
|
||||||
threeBusses,
|
|
||||||
twoBusses,
|
|
||||||
fiveBusses,
|
|
||||||
singleRampLeftClosed,
|
|
||||||
threeRampsOpen,
|
|
||||||
];
|
|
||||||
|
|
||||||
let tourBusCarouselItems: string[] = [
|
let tourBusCarouselItems: string[] = [twoTourBuses, tourBusSide, tourBusSideLogo];
|
||||||
twoTourBuses,
|
|
||||||
tourBusSide,
|
|
||||||
tourBusSideLogo,
|
|
||||||
];
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1 class="text-xl font-semibold md:text-2xl">Buss</h1>
|
<h1 class="text-xl font-semibold md:text-2xl">Buss</h1>
|
||||||
|
|
||||||
<section
|
<section id="minibus" class="mt-4 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex">
|
||||||
id="minibus"
|
|
||||||
class="mt-4 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex"
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="grow text-lg font-semibold md:text-xl">Minibusser</h2>
|
<h2 class="grow text-lg font-semibold md:text-xl">Minibusser</h2>
|
||||||
<p class="md:text-lg">
|
<p class="md:text-lg">
|
||||||
Vi har idag fire minibusser, to Mercedes Sprinter og to Ford
|
Vi har idag fire minibusser, to Mercedes Sprinter og to Ford Transit. Vi har også en fullelektrisk Mercedes EQV og en Mitsubishi Outlander.
|
||||||
Transit. Vi har også en fullelektrisk Mercedes EQV og en Mitsubishi
|
<br />Vi finner løsninger for grupper fra 5 - 32 passasjerer med støtte for inntil 3 rullestolbrukere samtidig
|
||||||
Outlander.
|
|
||||||
<br />Vi finner løsninger for grupper fra 5 - 32 passasjerer med
|
|
||||||
støtte for inntil 3 rullestolbrukere samtidig
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:w-96">
|
<div class="md:w-96">
|
||||||
<Carousel
|
<Carousel items={minibusCarouselItems} buttonClass="bg-primary-200" let:item>
|
||||||
items={minibusCarouselItems}
|
|
||||||
buttonClass="bg-primary-200"
|
|
||||||
let:item
|
|
||||||
>
|
|
||||||
<div class="w-96 overflow-hidden shadow-sm">
|
<div class="w-96 overflow-hidden shadow-sm">
|
||||||
<img class="card w-full object-cover" src={item} alt="" />
|
<img class="card w-full object-cover" src={item} alt="" />
|
||||||
</div>
|
</div>
|
||||||
@@ -53,26 +33,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section
|
<section id="tour" class="mt-12 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex">
|
||||||
id="tour"
|
|
||||||
class="mt-12 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex"
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="grow text-lg font-semibold md:text-xl">Turbusser</h2>
|
<h2 class="grow text-lg font-semibold md:text-xl">Turbusser</h2>
|
||||||
<p class="md:text-lg">
|
<p class="md:text-lg">
|
||||||
Vi er medeier i Storfjord Turbuss AS som har tre turbusser.
|
Vi er medeier i Storfjord Turbuss AS som har tre turbusser.
|
||||||
<br />Storfjord Turbuss AS ble etablert i 2018, og vi utfører
|
<br />Storfjord Turbuss AS ble etablert i 2018, og vi utfører turkjøring og lager pakkeløsninger etter dine ønsker og behov.
|
||||||
turkjøring og lager pakkeløsninger etter dine ønsker og behov.
|
<br />Vår målsetning er å alltid være det naturlige førstevalget av transportør
|
||||||
<br />Vår målsetning er å alltid være det naturlige førstevalget av
|
|
||||||
transportør
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:w-96">
|
<div class="md:w-96">
|
||||||
<Carousel
|
<Carousel items={tourBusCarouselItems} buttonClass="bg-primary-200" let:item>
|
||||||
items={tourBusCarouselItems}
|
|
||||||
buttonClass="bg-primary-200"
|
|
||||||
let:item
|
|
||||||
>
|
|
||||||
<div class="w-96 overflow-hidden shadow-sm">
|
<div class="w-96 overflow-hidden shadow-sm">
|
||||||
<img class="card w-full object-cover" src={item} alt="" />
|
<img class="card w-full object-cover" src={item} alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
import twoTourBusses from "../assets/images/two_tour_busses.jpg";
|
import twoTourBusses from "../assets/images/two_tour_busses.jpg";
|
||||||
import van from "../assets/images/van.webp";
|
import van from "../assets/images/van.webp";
|
||||||
import Link from "../lib/components/link/Link.svelte";
|
import Link from "../lib/components/link/Link.svelte";
|
||||||
import { Routes } from "../lib/global/routes";
|
import { Routes } from "../lib/routes";
|
||||||
|
|
||||||
type CardCarouselItem = {
|
type CardCarouselItem = {
|
||||||
header: string;
|
header: string;
|
||||||
@@ -22,79 +22,59 @@
|
|||||||
image: threeBusses,
|
image: threeBusses,
|
||||||
header: "Minibusstransport",
|
header: "Minibusstransport",
|
||||||
text: "Vi har 4 minibusser i ulike størrelser",
|
text: "Vi har 4 minibusser i ulike størrelser",
|
||||||
url: `${Routes.bus.url}#minibus`,
|
url: `${Routes.bus.url}#minibus`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
image: taxis,
|
image: taxis,
|
||||||
header: "Taxikjøring",
|
header: "Taxikjøring",
|
||||||
text: "Vi kjører taxi med kapasitet opptil 8 personer",
|
text: "Vi kjører taxi med kapasitet opptil 8 personer",
|
||||||
url: `${Routes.taxi.url}#person`,
|
url: `${Routes.taxi.url}#person`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
image: wheelchairRamps,
|
image: wheelchairRamps,
|
||||||
header: "Rullestoltransport",
|
header: "Rullestoltransport",
|
||||||
text: "Fire av våre biler er rullestoltilpasset med plass til inntil 3 rullestoler",
|
text: "Fire av våre biler er rullestoltilpasset med plass til inntil 3 rullestoler",
|
||||||
url: `${Routes.accessibility.url}`,
|
url: `${Routes.accessibility.url}`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
image: twoTourBusses,
|
image: twoTourBusses,
|
||||||
header: "Turbuss",
|
header: "Turbuss",
|
||||||
text: "Vi er medeier i Storfjord Turbuss AS, som har tre moderne turbusser for inntil 50 personer",
|
text: "Vi er medeier i Storfjord Turbuss AS, som har tre moderne turbusser for inntil 50 personer",
|
||||||
url: `${Routes.bus.url}#tour`,
|
url: `${Routes.bus.url}#tour`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
image: van,
|
image: van,
|
||||||
header: "Pakketaxi",
|
header: "Pakketaxi",
|
||||||
text: "Vi har tilbud om pakketaxi. Både småpakker og volumkrevende gods kan transporteres",
|
text: "Vi har tilbud om pakketaxi. Både småpakker og volumkrevende gods kan transporteres",
|
||||||
url: `${Routes.taxi.url}#package`,
|
url: `${Routes.taxi.url}#package`
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex gap-8">
|
<div class="flex gap-8">
|
||||||
<div class="overflow-hidden">
|
<div class="overflow-hidden">
|
||||||
<div>
|
<div>
|
||||||
<img
|
<img src={header_image} class="rounded-md border-2 border-contrast-100" alt="Minibusses lined up in a row" />
|
||||||
src={header_image}
|
|
||||||
class="rounded-md border-2 border-contrast-100"
|
|
||||||
alt="Minibusses lined up in a row"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h1 class="mt-4 text-xl font-semibold md:text-2xl">
|
<h1 class="mt-4 text-xl font-semibold md:text-2xl">
|
||||||
Med komfort og sikkerhet i førersetet<br />Bli med på en trygg
|
Med komfort og sikkerhet i førersetet<br />Bli med på en trygg og behagelig tur
|
||||||
og behagelig tur
|
|
||||||
</h1>
|
</h1>
|
||||||
<p class="mt-2 font-medium opacity-70 md:text-lg">
|
<p class="mt-2 font-medium opacity-70 md:text-lg">
|
||||||
Minibusservice Stene AS driver personbefordring med taxi,
|
Minibusservice Stene AS driver personbefordring med taxi, minibuss og busser.
|
||||||
minibuss og busser.
|
<br />Vi har lang erfaring og finner gode løsninger for kundene våre.
|
||||||
<br />Vi har lang erfaring og finner gode løsninger for kundene
|
<br />Kontraktskjøring for helseforetak, busselskap og kommune utgjør størsteparten av oppdragene våre, men vi tilbyr også turer for privatpersoner, bedrifter og
|
||||||
våre.
|
turister.
|
||||||
<br />Kontraktskjøring for helseforetak, busselskap og kommune
|
<br />Vi er godkjent lærebedrift og setter kunden og miljøet i fokus. Vi har både elektriske, hybride og dieselkjøretøy i flåten
|
||||||
utgjør størsteparten av oppdragene våre, men vi tilbyr også
|
|
||||||
turer for privatpersoner, bedrifter og turister.
|
|
||||||
<br />Vi er godkjent lærebedrift og setter kunden og miljøet i
|
|
||||||
fokus. Vi har både elektriske, hybride og dieselkjøretøy i
|
|
||||||
flåten
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-12">
|
<div class="mt-12">
|
||||||
<h1 class="text-xl font-semibold md:text-2xl">Våre tjenester</h1>
|
<h1 class="text-xl font-semibold md:text-2xl">Våre tjenester</h1>
|
||||||
|
|
||||||
<Carousel
|
<Carousel class="mt-2 rounded-md border-2 border-contrast-100 bg-primary-300 p-4 shadow-inner" items={carouselItems} let:item>
|
||||||
class="mt-2 rounded-md border-2 border-contrast-100 bg-primary-300 p-4 shadow-inner"
|
<div class="card flex h-full w-64 flex-col overflow-hidden border-contrast-100 shadow-sm transition-transform">
|
||||||
items={carouselItems}
|
|
||||||
let:item
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="card flex h-full w-64 flex-col overflow-hidden border-contrast-100 shadow-sm transition-transform"
|
|
||||||
>
|
|
||||||
{#if item.image}
|
{#if item.image}
|
||||||
<img
|
<img class="h-44 w-full border-b-2 border-contrast-100 object-cover" src={item.image} alt="" />
|
||||||
class="h-44 w-full border-b-2 border-contrast-100 object-cover"
|
|
||||||
src={item.image}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
{/if}
|
{/if}
|
||||||
<div class="flex grow flex-col p-4">
|
<div class="flex grow flex-col p-4">
|
||||||
<h3 class="font-semibold">
|
<h3 class="font-semibold">
|
||||||
@@ -103,10 +83,7 @@
|
|||||||
<p class="grow whitespace-normal">
|
<p class="grow whitespace-normal">
|
||||||
{item.text}
|
{item.text}
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<Link class="hi mt-2 w-fit font-semibold" href={item.url}>Les mer...</Link>
|
||||||
class="hi mt-2 w-fit font-semibold"
|
|
||||||
href={item.url}>Les mer...</Link
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Carousel>
|
</Carousel>
|
||||||
|
|||||||
@@ -9,25 +9,17 @@
|
|||||||
|
|
||||||
<h1 class="text-xl font-semibold md:text-2xl">Taxi</h1>
|
<h1 class="text-xl font-semibold md:text-2xl">Taxi</h1>
|
||||||
|
|
||||||
<section
|
<section id="person" class="mt-4 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex">
|
||||||
id="person"
|
|
||||||
class="mt-4 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex"
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="grow text-lg font-semibold md:text-xl">Persontaxi</h2>
|
<h2 class="grow text-lg font-semibold md:text-xl">Persontaxi</h2>
|
||||||
<p class="md:text-lg">
|
<p class="md:text-lg">
|
||||||
Vi har taxier som dekker de fleste behov.
|
Vi har taxier som dekker de fleste behov.
|
||||||
<br />Rullestoltransport, firehjulstrekk og helelektrisk bil er noen
|
<br />Rullestoltransport, firehjulstrekk og helelektrisk bil er noen av tilbudene våre.
|
||||||
av tilbudene våre.
|
|
||||||
<br />Taxiene våre kan ta opp til 8 passasjerer
|
<br />Taxiene våre kan ta opp til 8 passasjerer
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="md:w-96">
|
<div class="md:w-96">
|
||||||
<Carousel
|
<Carousel items={taxiCarouselItems} buttonClass="bg-primary-200" let:item>
|
||||||
items={taxiCarouselItems}
|
|
||||||
buttonClass="bg-primary-200"
|
|
||||||
let:item
|
|
||||||
>
|
|
||||||
<div class="card w-96 overflow-hidden shadow-sm">
|
<div class="card w-96 overflow-hidden shadow-sm">
|
||||||
<img class="w-full object-cover" src={item} alt="" />
|
<img class="w-full object-cover" src={item} alt="" />
|
||||||
</div>
|
</div>
|
||||||
@@ -35,23 +27,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section
|
<section id="package" class="mt-4 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex">
|
||||||
id="package"
|
|
||||||
class="mt-4 justify-between gap-5 rounded-md bg-primary-300 p-4 shadow-inner md:flex"
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="grow text-lg font-semibold md:text-xl">Pakketaxi</h2>
|
<h2 class="grow text-lg font-semibold md:text-xl">Pakketaxi</h2>
|
||||||
<p class="md:text-lg">
|
<p class="md:text-lg">Vi har tilbud om pakketaxi. Både småpakker og volumkrevende gods kan transporteres</p>
|
||||||
Vi har tilbud om pakketaxi. Både småpakker og volumkrevende gods kan
|
|
||||||
transporteres
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="md:w-96">
|
<div class="md:w-96">
|
||||||
<Carousel
|
<Carousel items={packageTaxiCarouselItems} buttonClass="bg-primary-200" let:item>
|
||||||
items={packageTaxiCarouselItems}
|
|
||||||
buttonClass="bg-primary-200"
|
|
||||||
let:item
|
|
||||||
>
|
|
||||||
<div class="card w-96 overflow-hidden">
|
<div class="card w-96 overflow-hidden">
|
||||||
<img class="w-full object-cover" src={item} alt="" />
|
<img class="w-full object-cover" src={item} alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
/** @type {import("@sveltejs/vite-plugin-svelte").SvelteConfig} */
|
/** @type {import("@sveltejs/vite-plugin-svelte").SvelteConfig} */
|
||||||
export default {}
|
export default {};
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
{
|
{
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
"target": "ES2023",
|
"target": "ES2023",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"types": ["svelte", "vite/client"],
|
"types": ["svelte", "vite/client"],
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
/**
|
/**
|
||||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||||
* Disable checkJs if you'd like to use dynamic types in JS.
|
* Disable checkJs if you'd like to use dynamic types in JS.
|
||||||
* Note that setting allowJs false does not prevent the use
|
* Note that setting allowJs false does not prevent the use
|
||||||
* of JS in `.svelte` files.
|
* of JS in `.svelte` files.
|
||||||
*/
|
*/
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
"moduleDetection": "force"
|
"moduleDetection": "force"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
|
"include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
{
|
{
|
||||||
"files": [],
|
"files": [],
|
||||||
"references": [
|
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
|
||||||
{ "path": "./tsconfig.app.json" },
|
|
||||||
{ "path": "./tsconfig.node.json" }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
"target": "ES2023",
|
"target": "ES2023",
|
||||||
"lib": ["ES2023"],
|
"lib": ["ES2023"],
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"types": ["node"],
|
"types": ["node"],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
/* Bundler mode */
|
/* Bundler mode */
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
|
|
||||||
/* Linting */
|
/* Linting */
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"erasableSyntaxOnly": true,
|
"erasableSyntaxOnly": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true
|
"noUncheckedSideEffectImports": true
|
||||||
},
|
},
|
||||||
"include": ["vite.config.ts"]
|
"include": ["vite.config.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ import tailwindcss from "@tailwindcss/vite";
|
|||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [svelte(), tailwindcss()],
|
plugins: [svelte(), tailwindcss()]
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user