From b99e636e744e72122bc6dc2b012eeb276c4bc92f Mon Sep 17 00:00:00 2001 From: June Date: Wed, 11 Feb 2026 18:41:42 +1300 Subject: [PATCH 01/23] Add shadcn svelte, theme button --- components.json | 16 +++ package.json | 6 + pnpm-lock.yaml | 109 ++++++++++++++++ src/lib/components/header.svelte | 8 +- src/lib/components/ui/ThemeModeButton.svelte | 17 +++ src/lib/components/ui/button/button.svelte | 82 ++++++++++++ src/lib/components/ui/button/index.ts | 17 +++ src/lib/utils.ts | 13 ++ src/routes/+layout.svelte | 2 + src/routes/layout.css | 129 +++++++++++++++++-- 10 files changed, 386 insertions(+), 13 deletions(-) create mode 100644 components.json create mode 100644 src/lib/components/ui/ThemeModeButton.svelte create mode 100644 src/lib/components/ui/button/button.svelte create mode 100644 src/lib/components/ui/button/index.ts create mode 100644 src/lib/utils.ts diff --git a/components.json b/components.json new file mode 100644 index 0000000..1e6a638 --- /dev/null +++ b/components.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "tailwind": { + "css": "src/routes/layout.css", + "baseColor": "neutral" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils", + "ui": "$lib/components/ui", + "hooks": "$lib/hooks", + "lib": "$lib" + }, + "typescript": true, + "registry": "https://shadcn-svelte.com/registry" +} diff --git a/package.json b/package.json index 812044b..6e862e9 100644 --- a/package.json +++ b/package.json @@ -17,17 +17,22 @@ "db:studio": "drizzle-kit studio" }, "devDependencies": { + "@lucide/svelte": "^0.563.1", "@sveltejs/adapter-node": "^5.5.2", "@sveltejs/kit": "^2.50.1", "@sveltejs/vite-plugin-svelte": "^6.2.4", "@tailwindcss/forms": "^0.5.11", "@tailwindcss/vite": "^4.1.18", "@types/node": "^22", + "clsx": "^2.1.1", "drizzle-kit": "^0.31.8", "drizzle-orm": "^0.45.1", "svelte": "^5.48.2", "svelte-check": "^4.3.5", + "tailwind-merge": "^3.4.0", + "tailwind-variants": "^3.2.2", "tailwindcss": "^4.1.18", + "tw-animate-css": "^1.4.0", "typescript": "^5.9.3", "vite": "^7.3.1" }, @@ -41,6 +46,7 @@ "@tiptap/pm": "^3.18.0", "@tiptap/starter-kit": "^3.18.0", "marked": "^17.0.1", + "mode-watcher": "^1.1.0", "postgres": "^3.4.8", "tiptap": "^1.32.2" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e966e63..8e6b7be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: marked: specifier: ^17.0.1 version: 17.0.1 + mode-watcher: + specifier: ^1.1.0 + version: 1.1.0(svelte@5.49.0) postgres: specifier: ^3.4.8 version: 3.4.8 @@ -42,6 +45,9 @@ importers: specifier: ^1.32.2 version: 1.32.2(vue-template-compiler@2.7.16)(vue@2.7.16) devDependencies: + '@lucide/svelte': + specifier: ^0.563.1 + version: 0.563.1(svelte@5.49.0) '@sveltejs/adapter-node': specifier: ^5.5.2 version: 5.5.2(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2))) @@ -60,6 +66,9 @@ importers: '@types/node': specifier: ^22 version: 22.19.7 + clsx: + specifier: ^2.1.1 + version: 2.1.1 drizzle-kit: specifier: ^0.31.8 version: 0.31.8 @@ -72,9 +81,18 @@ importers: svelte-check: specifier: ^4.3.5 version: 4.3.5(picomatch@4.0.3)(svelte@5.49.0)(typescript@5.9.3) + tailwind-merge: + specifier: ^3.4.0 + version: 3.4.0 + tailwind-variants: + specifier: ^3.2.2 + version: 3.2.2(tailwind-merge@3.4.0)(tailwindcss@4.1.18) tailwindcss: specifier: ^4.1.18 version: 4.1.18 + tw-animate-css: + specifier: ^1.4.0 + version: 1.4.0 typescript: specifier: ^5.9.3 version: 5.9.3 @@ -594,6 +612,11 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@lucide/svelte@0.563.1': + resolution: {integrity: sha512-Kt+MbnE5D9RsuI/csmf7M+HWxALe57x3A0DhQ8pPnnUpneh7zuldrYjlT+veWtk+tVnp5doQtaAAxLujzIlhBw==} + peerDependencies: + svelte: ^5 + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -1304,6 +1327,9 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + inline-style-parser@0.2.7: + resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} @@ -1423,6 +1449,11 @@ packages: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true + mode-watcher@1.1.0: + resolution: {integrity: sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g==} + peerDependencies: + svelte: ^5.27.0 + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1553,6 +1584,16 @@ packages: rope-sequence@1.3.4: resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} + runed@0.23.4: + resolution: {integrity: sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA==} + peerDependencies: + svelte: ^5.7.0 + + runed@0.25.0: + resolution: {integrity: sha512-7+ma4AG9FT2sWQEA0Egf6mb7PBT2vHyuHail1ie8ropfSjvZGtEAx8YTmUjv/APCsdRRxEVvArNjALk9zFSOrg==} + peerDependencies: + svelte: ^5.7.0 + sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} @@ -1575,6 +1616,9 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + style-to-object@1.0.14: + resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -1587,10 +1631,29 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 typescript: '>=5.0.0' + svelte-toolbelt@0.7.1: + resolution: {integrity: sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ==} + engines: {node: '>=18', pnpm: '>=8.7.0'} + peerDependencies: + svelte: ^5.0.0 + svelte@5.49.0: resolution: {integrity: sha512-Fn2mCc3XX0gnnbBYzWOTrZHi5WnF9KvqmB1+KGlUWoJkdioPmFYtg2ALBr6xl2dcnFTz3Vi7/mHpbKSVg/imVg==} engines: {node: '>=18'} + tailwind-merge@3.4.0: + resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} + + tailwind-variants@3.2.2: + resolution: {integrity: sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==} + engines: {node: '>=16.x', pnpm: '>=7.x'} + peerDependencies: + tailwind-merge: '>=3.0.0' + tailwindcss: '*' + peerDependenciesMeta: + tailwind-merge: + optional: true + tailwindcss@4.1.18: resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} @@ -1618,6 +1681,9 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tw-animate-css@1.4.0: + resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} @@ -1998,6 +2064,10 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@lucide/svelte@0.563.1(svelte@5.49.0)': + dependencies: + svelte: 5.49.0 + '@polka/url@1.0.0-next.29': {} '@remirror/core-constants@3.0.0': {} @@ -2618,6 +2688,8 @@ snapshots: he@1.2.0: {} + inline-style-parser@0.2.7: {} + is-core-module@2.16.1: dependencies: hasown: 2.0.2 @@ -2712,6 +2784,12 @@ snapshots: mini-svg-data-uri@1.4.4: {} + mode-watcher@1.1.0(svelte@5.49.0): + dependencies: + runed: 0.25.0(svelte@5.49.0) + svelte: 5.49.0 + svelte-toolbelt: 0.7.1(svelte@5.49.0) + mri@1.2.0: {} mrmime@2.0.1: {} @@ -2891,6 +2969,16 @@ snapshots: rope-sequence@1.3.4: {} + runed@0.23.4(svelte@5.49.0): + dependencies: + esm-env: 1.2.2 + svelte: 5.49.0 + + runed@0.25.0(svelte@5.49.0): + dependencies: + esm-env: 1.2.2 + svelte: 5.49.0 + sade@1.8.1: dependencies: mri: 1.2.0 @@ -2912,6 +3000,10 @@ snapshots: source-map@0.6.1: {} + style-to-object@1.0.14: + dependencies: + inline-style-parser: 0.2.7 + supports-preserve-symlinks-flag@1.0.0: {} svelte-check@4.3.5(picomatch@4.0.3)(svelte@5.49.0)(typescript@5.9.3): @@ -2926,6 +3018,13 @@ snapshots: transitivePeerDependencies: - picomatch + svelte-toolbelt@0.7.1(svelte@5.49.0): + dependencies: + clsx: 2.1.1 + runed: 0.23.4(svelte@5.49.0) + style-to-object: 1.0.14 + svelte: 5.49.0 + svelte@5.49.0: dependencies: '@jridgewell/remapping': 2.3.5 @@ -2944,6 +3043,14 @@ snapshots: magic-string: 0.30.21 zimmerframe: 1.1.4 + tailwind-merge@3.4.0: {} + + tailwind-variants@3.2.2(tailwind-merge@3.4.0)(tailwindcss@4.1.18): + dependencies: + tailwindcss: 4.1.18 + optionalDependencies: + tailwind-merge: 3.4.0 + tailwindcss@4.1.18: {} tapable@2.3.0: {} @@ -2986,6 +3093,8 @@ snapshots: totalist@3.0.1: {} + tw-animate-css@1.4.0: {} + typescript@5.9.3: {} uc.micro@2.1.0: {} diff --git a/src/lib/components/header.svelte b/src/lib/components/header.svelte index 17289f5..4ecac74 100644 --- a/src/lib/components/header.svelte +++ b/src/lib/components/header.svelte @@ -1,3 +1,9 @@ + +
-

Memento

+

Memento

+ +
\ No newline at end of file diff --git a/src/lib/components/ui/ThemeModeButton.svelte b/src/lib/components/ui/ThemeModeButton.svelte new file mode 100644 index 0000000..20bfad5 --- /dev/null +++ b/src/lib/components/ui/ThemeModeButton.svelte @@ -0,0 +1,17 @@ + + + \ No newline at end of file diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte new file mode 100644 index 0000000..a8296ae --- /dev/null +++ b/src/lib/components/ui/button/button.svelte @@ -0,0 +1,82 @@ + + + + +{#if href} + + {@render children?.()} + +{:else} + +{/if} diff --git a/src/lib/components/ui/button/index.ts b/src/lib/components/ui/button/index.ts new file mode 100644 index 0000000..fb585d7 --- /dev/null +++ b/src/lib/components/ui/button/index.ts @@ -0,0 +1,17 @@ +import Root, { + type ButtonProps, + type ButtonSize, + type ButtonVariant, + buttonVariants, +} from "./button.svelte"; + +export { + Root, + type ButtonProps as Props, + // + Root as Button, + buttonVariants, + type ButtonProps, + type ButtonSize, + type ButtonVariant, +}; diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..55b3a91 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,13 @@ +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChild = T extends { child?: any } ? Omit : T; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type WithoutChildren = T extends { children?: any } ? Omit : T; +export type WithoutChildrenOrChild = WithoutChildren>; +export type WithElementRef = T & { ref?: U | null }; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 7ad0b04..a96169b 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -2,6 +2,7 @@ import './layout.css'; import favicon from '$lib/assets/favicon.svg'; import Header from '$lib/components/header.svelte'; + import { ModeWatcher } from "mode-watcher" let { children } = $props(); @@ -10,5 +11,6 @@
+ {@render children()}
diff --git a/src/routes/layout.css b/src/routes/layout.css index 613cb8b..ac256d3 100644 --- a/src/routes/layout.css +++ b/src/routes/layout.css @@ -1,16 +1,121 @@ -@import 'tailwindcss'; -@plugin '@tailwindcss/forms'; +@import "tailwindcss"; -/*@import 'quill/dist/quill.core.css'; -@import 'quill/dist/quill.bubble.css'; -@import 'quill/dist/quill.snow.css';*/ +@import "tw-animate-css"; -html { - @apply py-3 px-4; - @apply bg-[#252525] text-white +@custom-variant dark (&:is(.dark *)); + +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); } - html body { - /*@apply font-[AmericanTypewriter];*/ - /* @apply w-full md:w-[68%] mx-auto h-full; */ - } \ No newline at end of file +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} \ No newline at end of file -- 2.49.1 From a61b342c4cdec653fe59280fa2426597f86107e1 Mon Sep 17 00:00:00 2001 From: June Date: Wed, 11 Feb 2026 19:15:03 +1300 Subject: [PATCH 02/23] calendar work is happening --- package.json | 4 +- pnpm-lock.yaml | 105 +++++- .../{ui => }/ThemeModeButton.svelte | 0 src/lib/components/calendar.svelte | 332 ++---------------- src/lib/components/header.svelte | 2 +- .../ui/calendar/calendar-caption.svelte | 76 ++++ .../ui/calendar/calendar-cell.svelte | 19 + .../ui/calendar/calendar-day.svelte | 35 ++ .../ui/calendar/calendar-grid-body.svelte | 12 + .../ui/calendar/calendar-grid-head.svelte | 12 + .../ui/calendar/calendar-grid-row.svelte | 12 + .../ui/calendar/calendar-grid.svelte | 16 + .../ui/calendar/calendar-head-cell.svelte | 19 + .../ui/calendar/calendar-header.svelte | 19 + .../ui/calendar/calendar-heading.svelte | 16 + .../ui/calendar/calendar-month-select.svelte | 48 +++ .../ui/calendar/calendar-month.svelte | 15 + .../ui/calendar/calendar-months.svelte | 19 + .../ui/calendar/calendar-nav.svelte | 19 + .../ui/calendar/calendar-next-button.svelte | 31 ++ .../ui/calendar/calendar-prev-button.svelte | 31 ++ .../ui/calendar/calendar-year-select.svelte | 47 +++ .../components/ui/calendar/calendar.svelte | 115 ++++++ src/lib/components/ui/calendar/index.ts | 40 +++ src/routes/+layout.svelte | 4 +- src/routes/+page.svelte | 17 +- src/routes/layout.css | 2 +- 27 files changed, 746 insertions(+), 321 deletions(-) rename src/lib/components/{ui => }/ThemeModeButton.svelte (100%) create mode 100644 src/lib/components/ui/calendar/calendar-caption.svelte create mode 100644 src/lib/components/ui/calendar/calendar-cell.svelte create mode 100644 src/lib/components/ui/calendar/calendar-day.svelte create mode 100644 src/lib/components/ui/calendar/calendar-grid-body.svelte create mode 100644 src/lib/components/ui/calendar/calendar-grid-head.svelte create mode 100644 src/lib/components/ui/calendar/calendar-grid-row.svelte create mode 100644 src/lib/components/ui/calendar/calendar-grid.svelte create mode 100644 src/lib/components/ui/calendar/calendar-head-cell.svelte create mode 100644 src/lib/components/ui/calendar/calendar-header.svelte create mode 100644 src/lib/components/ui/calendar/calendar-heading.svelte create mode 100644 src/lib/components/ui/calendar/calendar-month-select.svelte create mode 100644 src/lib/components/ui/calendar/calendar-month.svelte create mode 100644 src/lib/components/ui/calendar/calendar-months.svelte create mode 100644 src/lib/components/ui/calendar/calendar-nav.svelte create mode 100644 src/lib/components/ui/calendar/calendar-next-button.svelte create mode 100644 src/lib/components/ui/calendar/calendar-prev-button.svelte create mode 100644 src/lib/components/ui/calendar/calendar-year-select.svelte create mode 100644 src/lib/components/ui/calendar/calendar.svelte create mode 100644 src/lib/components/ui/calendar/index.ts diff --git a/package.json b/package.json index 6e862e9..b37068f 100644 --- a/package.json +++ b/package.json @@ -17,13 +17,15 @@ "db:studio": "drizzle-kit studio" }, "devDependencies": { - "@lucide/svelte": "^0.563.1", + "@internationalized/date": "^3.11.0", + "@lucide/svelte": "^0.561.0", "@sveltejs/adapter-node": "^5.5.2", "@sveltejs/kit": "^2.50.1", "@sveltejs/vite-plugin-svelte": "^6.2.4", "@tailwindcss/forms": "^0.5.11", "@tailwindcss/vite": "^4.1.18", "@types/node": "^22", + "bits-ui": "^2.15.5", "clsx": "^2.1.1", "drizzle-kit": "^0.31.8", "drizzle-orm": "^0.45.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8e6b7be..9488228 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,9 +45,12 @@ importers: specifier: ^1.32.2 version: 1.32.2(vue-template-compiler@2.7.16)(vue@2.7.16) devDependencies: + '@internationalized/date': + specifier: ^3.11.0 + version: 3.11.0 '@lucide/svelte': - specifier: ^0.563.1 - version: 0.563.1(svelte@5.49.0) + specifier: ^0.561.0 + version: 0.561.0(svelte@5.49.0) '@sveltejs/adapter-node': specifier: ^5.5.2 version: 5.5.2(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2))) @@ -66,6 +69,9 @@ importers: '@types/node': specifier: ^22 version: 22.19.7 + bits-ui: + specifier: ^2.15.5 + version: 2.15.5(@internationalized/date@3.11.0)(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -596,6 +602,9 @@ packages: peerDependencies: '@fullcalendar/core': ~6.1.20 + '@internationalized/date@3.11.0': + resolution: {integrity: sha512-BOx5huLAWhicM9/ZFs84CzP+V3gBW6vlpM02yzsdYC7TGlZJX1OJiEEHcSayF00Z+3jLlm4w79amvSt6RqKN3Q==} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -612,8 +621,8 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@lucide/svelte@0.563.1': - resolution: {integrity: sha512-Kt+MbnE5D9RsuI/csmf7M+HWxALe57x3A0DhQ8pPnnUpneh7zuldrYjlT+veWtk+tVnp5doQtaAAxLujzIlhBw==} + '@lucide/svelte@0.561.0': + resolution: {integrity: sha512-vofKV2UFVrKE6I4ewKJ3dfCXSV6iP6nWVmiM83MLjsU91EeJcEg7LoWUABLp/aOTxj1HQNbJD1f3g3L0JQgH9A==} peerDependencies: svelte: ^5 @@ -828,6 +837,9 @@ packages: svelte: ^5.0.0 vite: ^6.3.0 || ^7.0.0 + '@swc/helpers@0.5.18': + resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==} + '@tailwindcss/forms@0.5.11': resolution: {integrity: sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA==} peerDependencies: @@ -1108,6 +1120,13 @@ packages: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} + bits-ui@2.15.5: + resolution: {integrity: sha512-WhS+P+E//ClLfKU6KqjKC17nGDRLnz+vkwoP6ClFUPd5m1fFVDxTElPX8QVsduLj5V1KFDxlnv6sW2G5Lqk+vw==} + engines: {node: '>=20'} + peerDependencies: + '@internationalized/date': ^3.8.1 + svelte: ^5.33.0 + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -1148,6 +1167,10 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -1430,6 +1453,10 @@ packages: locate-character@3.0.0: resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -1594,6 +1621,15 @@ packages: peerDependencies: svelte: ^5.7.0 + runed@0.35.1: + resolution: {integrity: sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==} + peerDependencies: + '@sveltejs/kit': ^2.21.0 + svelte: ^5.7.0 + peerDependenciesMeta: + '@sveltejs/kit': + optional: true + sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} @@ -1631,6 +1667,12 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 typescript: '>=5.0.0' + svelte-toolbelt@0.10.6: + resolution: {integrity: sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==} + engines: {node: '>=18', pnpm: '>=8.7.0'} + peerDependencies: + svelte: ^5.30.2 + svelte-toolbelt@0.7.1: resolution: {integrity: sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ==} engines: {node: '>=18', pnpm: '>=8.7.0'} @@ -1641,6 +1683,9 @@ packages: resolution: {integrity: sha512-Fn2mCc3XX0gnnbBYzWOTrZHi5WnF9KvqmB1+KGlUWoJkdioPmFYtg2ALBr6xl2dcnFTz3Vi7/mHpbKSVg/imVg==} engines: {node: '>=18'} + tabbable@6.4.0: + resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} + tailwind-merge@3.4.0: resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} @@ -1681,6 +1726,9 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tw-animate-css@1.4.0: resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} @@ -2045,6 +2093,10 @@ snapshots: '@fullcalendar/core': 6.1.20 '@fullcalendar/daygrid': 6.1.20(@fullcalendar/core@6.1.20) + '@internationalized/date@3.11.0': + dependencies: + '@swc/helpers': 0.5.18 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2064,7 +2116,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@lucide/svelte@0.563.1(svelte@5.49.0)': + '@lucide/svelte@0.561.0(svelte@5.49.0)': dependencies: svelte: 5.49.0 @@ -2235,6 +2287,10 @@ snapshots: vite: 7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2) vitefu: 1.1.1(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)) + '@swc/helpers@0.5.18': + dependencies: + tslib: 2.8.1 + '@tailwindcss/forms@0.5.11(tailwindcss@4.1.18)': dependencies: mini-svg-data-uri: 1.4.4 @@ -2507,6 +2563,19 @@ snapshots: axobject-query@4.1.0: {} + bits-ui@2.15.5(@internationalized/date@3.11.0)(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0): + dependencies: + '@floating-ui/core': 1.7.4 + '@floating-ui/dom': 1.7.5 + '@internationalized/date': 3.11.0 + esm-env: 1.2.2 + runed: 0.35.1(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0) + svelte: 5.49.0 + svelte-toolbelt: 0.10.6(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0) + tabbable: 6.4.0 + transitivePeerDependencies: + - '@sveltejs/kit' + buffer-from@1.1.2: {} chokidar@4.0.3: @@ -2531,6 +2600,8 @@ snapshots: deepmerge@4.3.1: {} + dequal@2.0.3: {} + detect-libc@2.1.2: {} devalue@5.6.2: {} @@ -2765,6 +2836,8 @@ snapshots: locate-character@3.0.0: {} + lz-string@1.5.0: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2979,6 +3052,15 @@ snapshots: esm-env: 1.2.2 svelte: 5.49.0 + runed@0.35.1(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0): + dependencies: + dequal: 2.0.3 + esm-env: 1.2.2 + lz-string: 1.5.0 + svelte: 5.49.0 + optionalDependencies: + '@sveltejs/kit': 2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)) + sade@1.8.1: dependencies: mri: 1.2.0 @@ -3018,6 +3100,15 @@ snapshots: transitivePeerDependencies: - picomatch + svelte-toolbelt@0.10.6(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0): + dependencies: + clsx: 2.1.1 + runed: 0.35.1(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.49.0)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0)(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.7)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.49.0) + style-to-object: 1.0.14 + svelte: 5.49.0 + transitivePeerDependencies: + - '@sveltejs/kit' + svelte-toolbelt@0.7.1(svelte@5.49.0): dependencies: clsx: 2.1.1 @@ -3043,6 +3134,8 @@ snapshots: magic-string: 0.30.21 zimmerframe: 1.1.4 + tabbable@6.4.0: {} + tailwind-merge@3.4.0: {} tailwind-variants@3.2.2(tailwind-merge@3.4.0)(tailwindcss@4.1.18): @@ -3093,6 +3186,8 @@ snapshots: totalist@3.0.1: {} + tslib@2.8.1: {} + tw-animate-css@1.4.0: {} typescript@5.9.3: {} diff --git a/src/lib/components/ui/ThemeModeButton.svelte b/src/lib/components/ThemeModeButton.svelte similarity index 100% rename from src/lib/components/ui/ThemeModeButton.svelte rename to src/lib/components/ThemeModeButton.svelte diff --git a/src/lib/components/calendar.svelte b/src/lib/components/calendar.svelte index 46ba066..c4e84e6 100644 --- a/src/lib/components/calendar.svelte +++ b/src/lib/components/calendar.svelte @@ -1,309 +1,29 @@ -
-
- - {#if expanded} - - {monthNames[currentMonth]} {currentYear} - - {:else} - Current Week - {/if} -
- -
- {#each days as day, index} - - {/each} -
-
- - + + {#snippet day({ day })} + + {day.day} + Image for {day} + + {/snippet} + diff --git a/src/lib/components/header.svelte b/src/lib/components/header.svelte index 4ecac74..2cc387a 100644 --- a/src/lib/components/header.svelte +++ b/src/lib/components/header.svelte @@ -1,5 +1,5 @@
diff --git a/src/lib/components/ui/calendar/calendar-caption.svelte b/src/lib/components/ui/calendar/calendar-caption.svelte new file mode 100644 index 0000000..5c93037 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-caption.svelte @@ -0,0 +1,76 @@ + + +{#snippet MonthSelect()} + { + if (!placeholder) return; + const v = Number.parseInt(e.currentTarget.value); + const newPlaceholder = placeholder.set({ month: v }); + placeholder = newPlaceholder.subtract({ months: monthIndex }); + }} + /> +{/snippet} + +{#snippet YearSelect()} + +{/snippet} + +{#if captionLayout === "dropdown"} + {@render MonthSelect()} + {@render YearSelect()} +{:else if captionLayout === "dropdown-months"} + {@render MonthSelect()} + {#if placeholder} + {formatYear(placeholder)} + {/if} +{:else if captionLayout === "dropdown-years"} + {#if placeholder} + {formatMonth(placeholder)} + {/if} + {@render YearSelect()} +{:else} + {formatMonth(month)} {formatYear(month)} +{/if} diff --git a/src/lib/components/ui/calendar/calendar-cell.svelte b/src/lib/components/ui/calendar/calendar-cell.svelte new file mode 100644 index 0000000..4cdb548 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-cell.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-day.svelte b/src/lib/components/ui/calendar/calendar-day.svelte new file mode 100644 index 0000000..19d7bde --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-day.svelte @@ -0,0 +1,35 @@ + + +span]:text-xs [&>span]:opacity-70", + className + )} + {...restProps} +/> diff --git a/src/lib/components/ui/calendar/calendar-grid-body.svelte b/src/lib/components/ui/calendar/calendar-grid-body.svelte new file mode 100644 index 0000000..8cd86de --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-body.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-grid-head.svelte b/src/lib/components/ui/calendar/calendar-grid-head.svelte new file mode 100644 index 0000000..333edc4 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-head.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-grid-row.svelte b/src/lib/components/ui/calendar/calendar-grid-row.svelte new file mode 100644 index 0000000..9032236 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid-row.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-grid.svelte b/src/lib/components/ui/calendar/calendar-grid.svelte new file mode 100644 index 0000000..e0c8627 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-grid.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-head-cell.svelte b/src/lib/components/ui/calendar/calendar-head-cell.svelte new file mode 100644 index 0000000..131807e --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-head-cell.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-header.svelte b/src/lib/components/ui/calendar/calendar-header.svelte new file mode 100644 index 0000000..c39e955 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-header.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-heading.svelte b/src/lib/components/ui/calendar/calendar-heading.svelte new file mode 100644 index 0000000..a9b9810 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-heading.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-month-select.svelte b/src/lib/components/ui/calendar/calendar-month-select.svelte new file mode 100644 index 0000000..664afab --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-month-select.svelte @@ -0,0 +1,48 @@ + + + + + {#snippet child({ props, monthItems, selectedMonthItem })} + + + {/snippet} + + diff --git a/src/lib/components/ui/calendar/calendar-month.svelte b/src/lib/components/ui/calendar/calendar-month.svelte new file mode 100644 index 0000000..e747fae --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-month.svelte @@ -0,0 +1,15 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/calendar/calendar-months.svelte b/src/lib/components/ui/calendar/calendar-months.svelte new file mode 100644 index 0000000..f717a9d --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-months.svelte @@ -0,0 +1,19 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/calendar/calendar-nav.svelte b/src/lib/components/ui/calendar/calendar-nav.svelte new file mode 100644 index 0000000..27f33d7 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-nav.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/calendar/calendar-next-button.svelte b/src/lib/components/ui/calendar/calendar-next-button.svelte new file mode 100644 index 0000000..5c5a78d --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-next-button.svelte @@ -0,0 +1,31 @@ + + +{#snippet Fallback()} + +{/snippet} + + diff --git a/src/lib/components/ui/calendar/calendar-prev-button.svelte b/src/lib/components/ui/calendar/calendar-prev-button.svelte new file mode 100644 index 0000000..33cfd63 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-prev-button.svelte @@ -0,0 +1,31 @@ + + +{#snippet Fallback()} + +{/snippet} + + diff --git a/src/lib/components/ui/calendar/calendar-year-select.svelte b/src/lib/components/ui/calendar/calendar-year-select.svelte new file mode 100644 index 0000000..33cc961 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar-year-select.svelte @@ -0,0 +1,47 @@ + + + + + {#snippet child({ props, yearItems, selectedYearItem })} + + + {/snippet} + + diff --git a/src/lib/components/ui/calendar/calendar.svelte b/src/lib/components/ui/calendar/calendar.svelte new file mode 100644 index 0000000..2971f22 --- /dev/null +++ b/src/lib/components/ui/calendar/calendar.svelte @@ -0,0 +1,115 @@ + + + + + {#snippet children({ months, weekdays })} + + + + + + {#each months as month, monthIndex (month)} + + + + + + + + {#each weekdays as weekday (weekday)} + + {weekday.slice(0, 2)} + + {/each} + + + + {#each month.weeks as weekDates (weekDates)} + + {#each weekDates as date (date)} + + {#if day} + {@render day({ + day: date, + outsideMonth: !isEqualMonth(date, month.value), + })} + {:else} + + {/if} + + {/each} + + {/each} + + + + {/each} + + {/snippet} + diff --git a/src/lib/components/ui/calendar/index.ts b/src/lib/components/ui/calendar/index.ts new file mode 100644 index 0000000..f3a16d2 --- /dev/null +++ b/src/lib/components/ui/calendar/index.ts @@ -0,0 +1,40 @@ +import Root from "./calendar.svelte"; +import Cell from "./calendar-cell.svelte"; +import Day from "./calendar-day.svelte"; +import Grid from "./calendar-grid.svelte"; +import Header from "./calendar-header.svelte"; +import Months from "./calendar-months.svelte"; +import GridRow from "./calendar-grid-row.svelte"; +import Heading from "./calendar-heading.svelte"; +import GridBody from "./calendar-grid-body.svelte"; +import GridHead from "./calendar-grid-head.svelte"; +import HeadCell from "./calendar-head-cell.svelte"; +import NextButton from "./calendar-next-button.svelte"; +import PrevButton from "./calendar-prev-button.svelte"; +import MonthSelect from "./calendar-month-select.svelte"; +import YearSelect from "./calendar-year-select.svelte"; +import Month from "./calendar-month.svelte"; +import Nav from "./calendar-nav.svelte"; +import Caption from "./calendar-caption.svelte"; + +export { + Day, + Cell, + Grid, + Header, + Months, + GridRow, + Heading, + GridBody, + GridHead, + HeadCell, + NextButton, + PrevButton, + Nav, + Month, + YearSelect, + MonthSelect, + Caption, + // + Root as Calendar, +}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index a96169b..185ff24 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,7 +1,6 @@ -
+
+ {#if selectedEntry} {#key selectedEntry.id} @@ -41,7 +49,8 @@ {/if}
-
+
+
    {#each data.all as entry} Date: Wed, 11 Feb 2026 19:25:34 +1300 Subject: [PATCH 03/23] i mean calendar *works* now, just gotta make it look okay --- src/lib/components/calendar.svelte | 78 ++++++++++++++++++++++-------- src/routes/+page.svelte | 2 +- 2 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/lib/components/calendar.svelte b/src/lib/components/calendar.svelte index c4e84e6..0ad3448 100644 --- a/src/lib/components/calendar.svelte +++ b/src/lib/components/calendar.svelte @@ -1,29 +1,67 @@ - + {#snippet day({ day })} {day.day} - Image for {day} + {@const img = getImageForDate(day)} + {#if img} + + {/if} {/snippet} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index db2ac29..818a691 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -14,7 +14,7 @@ let selectedEntry = $state(""); let selectedDate = $state(today()); - let dateValue = $state(new CalendarDate(2026, 1, 1)); + let dateValue = $state(new CalendarDate(2026, 2, 1)); -- 2.49.1 From 09585d8954676b81b274c33c37fcba127d9f04f6 Mon Sep 17 00:00:00 2001 From: June Date: Wed, 11 Feb 2026 19:55:48 +1300 Subject: [PATCH 04/23] images go behind the dates now --- src/lib/components/calendar.svelte | 4 ++-- src/lib/components/ui/calendar/calendar-day.svelte | 2 +- src/lib/components/ui/calendar/calendar-grid-row.svelte | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/components/calendar.svelte b/src/lib/components/calendar.svelte index 0ad3448..2b2d49a 100644 --- a/src/lib/components/calendar.svelte +++ b/src/lib/components/calendar.svelte @@ -53,15 +53,15 @@ > {#snippet day({ day })} - {day.day} {@const img = getImageForDate(day)} {#if img} {/if} + {day.day} {/snippet} diff --git a/src/lib/components/ui/calendar/calendar-day.svelte b/src/lib/components/ui/calendar/calendar-day.svelte index 19d7bde..89664cf 100644 --- a/src/lib/components/ui/calendar/calendar-day.svelte +++ b/src/lib/components/ui/calendar/calendar-day.svelte @@ -14,7 +14,7 @@ bind:ref class={cn( buttonVariants({ variant: "ghost" }), - "flex size-(--cell-size) flex-col items-center justify-center gap-1 p-0 leading-none font-normal whitespace-nowrap select-none", + "relative flex flex-1 flex-col items-center justify-center gap-1 p-0 leading-none font-normal whitespace-nowrap select-none", "[&[data-today]:not([data-selected])]:bg-accent [&[data-today]:not([data-selected])]:text-accent-foreground [&[data-today][data-disabled]]:text-muted-foreground", "data-[selected]:bg-primary dark:data-[selected]:hover:bg-accent/50 data-[selected]:text-primary-foreground", // Outside months diff --git a/src/lib/components/ui/calendar/calendar-grid-row.svelte b/src/lib/components/ui/calendar/calendar-grid-row.svelte index 9032236..e03aaf6 100644 --- a/src/lib/components/ui/calendar/calendar-grid-row.svelte +++ b/src/lib/components/ui/calendar/calendar-grid-row.svelte @@ -9,4 +9,4 @@ }: CalendarPrimitive.GridRowProps = $props(); - + -- 2.49.1 From a0d63fc10eff1659f118572dcd7fc975ca559163 Mon Sep 17 00:00:00 2001 From: June Date: Wed, 11 Feb 2026 19:56:56 +1300 Subject: [PATCH 05/23] removed white text enforcement lol --- src/lib/components/calendar.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/calendar.svelte b/src/lib/components/calendar.svelte index 2b2d49a..677f069 100644 --- a/src/lib/components/calendar.svelte +++ b/src/lib/components/calendar.svelte @@ -61,7 +61,7 @@ class="absolute inset-0 h-full w-full rounded-sm object-cover hover:opacity-20" /> {/if} - {day.day} + {day.day} {/snippet} -- 2.49.1 From 31bfbffb4daff77f8ecae8141a2b100a6586b2a9 Mon Sep 17 00:00:00 2001 From: June Date: Wed, 11 Feb 2026 20:12:17 +1300 Subject: [PATCH 06/23] calendar takes up full width now --- src/lib/components/calendar.svelte | 2 +- src/lib/components/ui/calendar/calendar-cell.svelte | 2 +- src/lib/components/ui/calendar/calendar-month.svelte | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/components/calendar.svelte b/src/lib/components/calendar.svelte index 677f069..2d3dd33 100644 --- a/src/lib/components/calendar.svelte +++ b/src/lib/components/calendar.svelte @@ -49,7 +49,7 @@ type="single" bind:value bind:placeholder - class="rounded-lg border shadow-sm [--cell-size:--spacing(11)] md:[--cell-size:--spacing(12)]" + class="rounded-lg border shadow-sm md:[--cell-size:--spacing(14)]" > {#snippet day({ day })} diff --git a/src/lib/components/ui/calendar/calendar-cell.svelte b/src/lib/components/ui/calendar/calendar-cell.svelte index 4cdb548..441eb4a 100644 --- a/src/lib/components/ui/calendar/calendar-cell.svelte +++ b/src/lib/components/ui/calendar/calendar-cell.svelte @@ -12,7 +12,7 @@ > = $props(); -
    +
    {@render children?.()}
    -- 2.49.1 From e978d0df970a4dd22e9c991ceebdf874d4dc2308 Mon Sep 17 00:00:00 2001 From: June Date: Wed, 11 Feb 2026 20:51:45 +1300 Subject: [PATCH 07/23] Redesign entry summary view and more importantly rearchitected that awful state management --- src/lib/components/entrySummaryView.svelte | 44 +++++++++----- src/lib/components/ui/item/index.ts | 34 +++++++++++ .../components/ui/item/item-actions.svelte | 20 +++++++ .../components/ui/item/item-content.svelte | 20 +++++++ .../ui/item/item-description.svelte | 24 ++++++++ src/lib/components/ui/item/item-footer.svelte | 20 +++++++ src/lib/components/ui/item/item-group.svelte | 21 +++++++ src/lib/components/ui/item/item-header.svelte | 20 +++++++ src/lib/components/ui/item/item-media.svelte | 42 +++++++++++++ .../components/ui/item/item-separator.svelte | 19 ++++++ src/lib/components/ui/item/item-title.svelte | 20 +++++++ src/lib/components/ui/item/item.svelte | 60 +++++++++++++++++++ src/lib/components/ui/separator/index.ts | 7 +++ .../components/ui/separator/separator.svelte | 21 +++++++ src/routes/+page.svelte | 6 +- 15 files changed, 358 insertions(+), 20 deletions(-) create mode 100644 src/lib/components/ui/item/index.ts create mode 100644 src/lib/components/ui/item/item-actions.svelte create mode 100644 src/lib/components/ui/item/item-content.svelte create mode 100644 src/lib/components/ui/item/item-description.svelte create mode 100644 src/lib/components/ui/item/item-footer.svelte create mode 100644 src/lib/components/ui/item/item-group.svelte create mode 100644 src/lib/components/ui/item/item-header.svelte create mode 100644 src/lib/components/ui/item/item-media.svelte create mode 100644 src/lib/components/ui/item/item-separator.svelte create mode 100644 src/lib/components/ui/item/item-title.svelte create mode 100644 src/lib/components/ui/item/item.svelte create mode 100644 src/lib/components/ui/separator/index.ts create mode 100644 src/lib/components/ui/separator/separator.svelte diff --git a/src/lib/components/entrySummaryView.svelte b/src/lib/components/entrySummaryView.svelte index f0e0a75..06e9166 100644 --- a/src/lib/components/entrySummaryView.svelte +++ b/src/lib/components/entrySummaryView.svelte @@ -1,24 +1,36 @@ - + \ No newline at end of file diff --git a/src/lib/components/ui/item/index.ts b/src/lib/components/ui/item/index.ts new file mode 100644 index 0000000..168bc3e --- /dev/null +++ b/src/lib/components/ui/item/index.ts @@ -0,0 +1,34 @@ +import Root from "./item.svelte"; +import Group from "./item-group.svelte"; +import Separator from "./item-separator.svelte"; +import Header from "./item-header.svelte"; +import Footer from "./item-footer.svelte"; +import Content from "./item-content.svelte"; +import Title from "./item-title.svelte"; +import Description from "./item-description.svelte"; +import Actions from "./item-actions.svelte"; +import Media from "./item-media.svelte"; + +export { + Root, + Group, + Separator, + Header, + Footer, + Content, + Title, + Description, + Actions, + Media, + // + Root as Item, + Group as ItemGroup, + Separator as ItemSeparator, + Header as ItemHeader, + Footer as ItemFooter, + Content as ItemContent, + Title as ItemTitle, + Description as ItemDescription, + Actions as ItemActions, + Media as ItemMedia, +}; diff --git a/src/lib/components/ui/item/item-actions.svelte b/src/lib/components/ui/item/item-actions.svelte new file mode 100644 index 0000000..83a6bb2 --- /dev/null +++ b/src/lib/components/ui/item/item-actions.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/item/item-content.svelte b/src/lib/components/ui/item/item-content.svelte new file mode 100644 index 0000000..55516f2 --- /dev/null +++ b/src/lib/components/ui/item/item-content.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/item/item-description.svelte b/src/lib/components/ui/item/item-description.svelte new file mode 100644 index 0000000..65e6e7d --- /dev/null +++ b/src/lib/components/ui/item/item-description.svelte @@ -0,0 +1,24 @@ + + +

    a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", + className + )} + {...restProps} +> + {@render children?.()} +

    diff --git a/src/lib/components/ui/item/item-footer.svelte b/src/lib/components/ui/item/item-footer.svelte new file mode 100644 index 0000000..c998caa --- /dev/null +++ b/src/lib/components/ui/item/item-footer.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/item/item-group.svelte b/src/lib/components/ui/item/item-group.svelte new file mode 100644 index 0000000..57ebbd5 --- /dev/null +++ b/src/lib/components/ui/item/item-group.svelte @@ -0,0 +1,21 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/item/item-header.svelte b/src/lib/components/ui/item/item-header.svelte new file mode 100644 index 0000000..1afe1fa --- /dev/null +++ b/src/lib/components/ui/item/item-header.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/item/item-media.svelte b/src/lib/components/ui/item/item-media.svelte new file mode 100644 index 0000000..78490fd --- /dev/null +++ b/src/lib/components/ui/item/item-media.svelte @@ -0,0 +1,42 @@ + + + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/item/item-separator.svelte b/src/lib/components/ui/item/item-separator.svelte new file mode 100644 index 0000000..6f2f51a --- /dev/null +++ b/src/lib/components/ui/item/item-separator.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/ui/item/item-title.svelte b/src/lib/components/ui/item/item-title.svelte new file mode 100644 index 0000000..8d13d5e --- /dev/null +++ b/src/lib/components/ui/item/item-title.svelte @@ -0,0 +1,20 @@ + + +
    + {@render children?.()} +
    diff --git a/src/lib/components/ui/item/item.svelte b/src/lib/components/ui/item/item.svelte new file mode 100644 index 0000000..77f8ce6 --- /dev/null +++ b/src/lib/components/ui/item/item.svelte @@ -0,0 +1,60 @@ + + + + +{#if child} + {@render child({ props: mergedProps })} +{:else} +
    + {@render mergedProps.children?.()} +
    +{/if} diff --git a/src/lib/components/ui/separator/index.ts b/src/lib/components/ui/separator/index.ts new file mode 100644 index 0000000..82442d2 --- /dev/null +++ b/src/lib/components/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from "./separator.svelte"; + +export { + Root, + // + Root as Separator, +}; diff --git a/src/lib/components/ui/separator/separator.svelte b/src/lib/components/ui/separator/separator.svelte new file mode 100644 index 0000000..f40999f --- /dev/null +++ b/src/lib/components/ui/separator/separator.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 818a691..6327e74 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -15,8 +15,6 @@ let selectedDate = $state(today()); let dateValue = $state(new CalendarDate(2026, 2, 1)); - - let selectEntry = async (hasEntry: boolean, data: string | null) => { // data should be the entryID if hasEntry == true, or the date if there is no entry @@ -51,11 +49,11 @@
    -
      +
        {#each data.all as entry} await selectEntry(true, entry.id)} {entry} + bind:value={dateValue} /> {/each}
      -- 2.49.1 From 865846c6bef0bda15bd68c617843ff2988572442 Mon Sep 17 00:00:00 2001 From: June Date: Wed, 11 Feb 2026 21:55:35 +1300 Subject: [PATCH 08/23] schema update: change from timestamp to date --- src/lib/components/entrySummaryView.svelte | 4 ++-- src/lib/server/db/schema.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/components/entrySummaryView.svelte b/src/lib/components/entrySummaryView.svelte index 06e9166..cdf394f 100644 --- a/src/lib/components/entrySummaryView.svelte +++ b/src/lib/components/entrySummaryView.svelte @@ -1,6 +1,6 @@ + {:else} + + + + {/if} +
    diff --git a/src/lib/upload.ts b/src/lib/upload.ts index 909a120..b97b8ed 100644 --- a/src/lib/upload.ts +++ b/src/lib/upload.ts @@ -55,3 +55,19 @@ export async function updateEntry(entry) { body: JSON.stringify(entry), }); } + +export async function deleteEntry(entry) { + const res = await fetch(`/api/entry/delete`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ id: entry.id }) + }); + + if (res.ok) { + entry = null; + } else { + alert('Failed to delete entry'); + } +} \ No newline at end of file -- 2.49.1 From f5573601058f7447dbd8c43ef8288ce2d497f94d Mon Sep 17 00:00:00 2001 From: June Date: Thu, 12 Feb 2026 12:06:38 +1300 Subject: [PATCH 11/23] max width only applies on large screens --- src/routes/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d747e61..7ae25db 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -23,7 +23,7 @@ {/key}
    -
    +
      {#each data.all as entry} -- 2.49.1 From c5d689a9a8c5b0a6f843a208b4f76ee6fc947a9a Mon Sep 17 00:00:00 2001 From: June Date: Fri, 13 Feb 2026 10:37:00 +1300 Subject: [PATCH 12/23] Implementing different page for the entries, for sharability ig --- src/routes/+layout.svelte | 58 +++++++++++++++++++++++++++++----- src/routes/+page.svelte | 10 ++++-- src/routes/[date]/+page.svelte | 8 +++++ src/routes/[date]/+page.ts | 6 ++++ 4 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 src/routes/[date]/+page.svelte create mode 100644 src/routes/[date]/+page.ts diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 185ff24..8dd44ac 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,14 +1,56 @@ + -
      - - {@render children()} -
      +
      +
      +
      + + {#key dateValue} + + {@render children()} + {/key} +
      + +
      + +
        + {#each entries as entry} + + {/each} +
      +
      +
      \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 7ae25db..a33d3d9 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -13,8 +13,14 @@ + -
      +
      + Click on a date to view or edit an entry. +
      + + + diff --git a/src/routes/[date]/+page.svelte b/src/routes/[date]/+page.svelte new file mode 100644 index 0000000..76ab1e3 --- /dev/null +++ b/src/routes/[date]/+page.svelte @@ -0,0 +1,8 @@ + + +{JSON.stringify(data)} \ No newline at end of file diff --git a/src/routes/[date]/+page.ts b/src/routes/[date]/+page.ts new file mode 100644 index 0000000..ae596ca --- /dev/null +++ b/src/routes/[date]/+page.ts @@ -0,0 +1,6 @@ + +export async function load({ params, fetch }) { + const res = await fetch(`/api/entry?date=${params.date}`); + const entries = await res.json(); + return { entries }; +} -- 2.49.1 From 1d6e5b5d4caef7ce280f74c44448f7293a047ba6 Mon Sep 17 00:00:00 2001 From: June Date: Tue, 17 Feb 2026 11:13:03 +1300 Subject: [PATCH 13/23] Just need a checkpoint cos nothings working atm --- src/lib/components/editor.svelte | 19 ++++++++++++------- src/routes/+layout.svelte | 30 ++++++++++++++++++------------ src/routes/+layout.ts | 13 +++++++++++++ src/routes/+page.ts | 13 ------------- src/routes/[date]/+page.svelte | 10 +++++++++- src/routes/[date]/+page.ts | 6 +++--- 6 files changed, 55 insertions(+), 36 deletions(-) create mode 100644 src/routes/+layout.ts delete mode 100644 src/routes/+page.ts diff --git a/src/lib/components/editor.svelte b/src/lib/components/editor.svelte index 04f35a5..b5201ce 100644 --- a/src/lib/components/editor.svelte +++ b/src/lib/components/editor.svelte @@ -27,8 +27,8 @@ }); -
      -

      {formatDate(entry.date)}

      +
      +

      {formatDate(entry.date)}

      {#if !edit} {:else} - + - {/if}
      diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 8dd44ac..f2cb652 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -2,25 +2,32 @@ import "./layout.css"; import favicon from "$lib/assets/favicon.svg"; import { ModeWatcher } from "mode-watcher"; - import { today, getLocalTimeZone } from "@internationalized/date"; + import { CalendarDate, today, getLocalTimeZone } from "@internationalized/date"; import Header from "$lib/components/header.svelte"; import Calendar from "$lib/components/calendar.svelte"; import EntrySummaryView from "$lib/components/entrySummaryView.svelte"; - import { onMount } from "svelte"; import { goto } from "$app/navigation"; - let { children } = $props(); - let dateValue = $state(today(getLocalTimeZone())); - let entries = $state([]) + let { children, data } = $props(); + let dateValue = $derived(data.date); + let entries = $derived(data.entries) + + // async function fetchForMonth(d: CalendarDate) { + // const res = await fetch( + // `/api/entry?month=${d.year}-${dateValue.month}`, + // ); + + // return await res.json() + // } - onMount(async () => { - const res = await fetch( - `/api/entry?month=${dateValue.year}-${dateValue.month}`, - ); + // onMount(async () => { + // const res = await fetch( + // `/api/entry?month=${dateValue.year}-${dateValue.month}`, + // ); - entries = await res.json() - }); + // entries = await res.json() + // }); $effect(() => { goto(`/${dateValue}`) @@ -37,7 +44,6 @@
      {#key dateValue} - {@render children()} {/key}
      diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts new file mode 100644 index 0000000..76e7c10 --- /dev/null +++ b/src/routes/+layout.ts @@ -0,0 +1,13 @@ +import { today, getLocalTimeZone } from "@internationalized/date"; + +export async function load({ params, fetch }) { + const dateValue = today(getLocalTimeZone()); + + const res = await fetch(`/api/entry?month=${dateValue.year}-${dateValue.month}`) + const entries = await res.json() + + return { + entries: entries, + date: dateValue + }; +} diff --git a/src/routes/+page.ts b/src/routes/+page.ts deleted file mode 100644 index 5b64fe7..0000000 --- a/src/routes/+page.ts +++ /dev/null @@ -1,13 +0,0 @@ -export const load = async ({ fetch, params }) => { - const res = await fetch("/api/entry/all"); - const allEntries = await res.json(); - - const today = new Date().toISOString().split('T')[0]; - const todayEntry = await fetch(`/api/entry?date=${today}`); - const todayEntryData = await todayEntry.json(); - - return { - all: allEntries, - today: todayEntryData, - }; -}; diff --git a/src/routes/[date]/+page.svelte b/src/routes/[date]/+page.svelte index 76ab1e3..f216e42 100644 --- a/src/routes/[date]/+page.svelte +++ b/src/routes/[date]/+page.svelte @@ -1,8 +1,16 @@ -{JSON.stringify(data)} \ No newline at end of file + +{#if data.entry.id} + +{:else} + No entry exists for {data.date} +{/if} + diff --git a/src/routes/[date]/+page.ts b/src/routes/[date]/+page.ts index ae596ca..86518e7 100644 --- a/src/routes/[date]/+page.ts +++ b/src/routes/[date]/+page.ts @@ -1,6 +1,6 @@ export async function load({ params, fetch }) { - const res = await fetch(`/api/entry?date=${params.date}`); - const entries = await res.json(); - return { entries }; + const res = await fetch(`/api/entry?date=${params.date}`); + const entries = await res.json(); + return { entry: entries }; } -- 2.49.1 From 0b038f4deace0f904b39a3e018438bcaa2704fe5 Mon Sep 17 00:00:00 2001 From: June Date: Tue, 17 Feb 2026 11:22:38 +1300 Subject: [PATCH 14/23] okay working now, datevalue respects current page --- src/routes/+layout.svelte | 41 +++++++++++++--------------------- src/routes/+layout.ts | 21 ++++++++++++----- src/routes/[date]/+page.svelte | 2 +- src/routes/[date]/+page.ts | 2 +- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index f2cb652..c870855 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -2,7 +2,11 @@ import "./layout.css"; import favicon from "$lib/assets/favicon.svg"; import { ModeWatcher } from "mode-watcher"; - import { CalendarDate, today, getLocalTimeZone } from "@internationalized/date"; + import { + CalendarDate, + today, + getLocalTimeZone, + } from "@internationalized/date"; import Header from "$lib/components/header.svelte"; import Calendar from "$lib/components/calendar.svelte"; @@ -11,27 +15,17 @@ let { children, data } = $props(); let dateValue = $derived(data.date); - let entries = $derived(data.entries) - - // async function fetchForMonth(d: CalendarDate) { - // const res = await fetch( - // `/api/entry?month=${d.year}-${dateValue.month}`, - // ); - - // return await res.json() - // } + let entries = $derived(data.entries); - // onMount(async () => { - // const res = await fetch( - // `/api/entry?month=${dateValue.year}-${dateValue.month}`, - // ); - - // entries = await res.json() - // }); - $effect(() => { - goto(`/${dateValue}`) - }) + // Navigate when dateValue changes + goto(`/${dateValue}`); + }); + + $effect(() => { + // Sync dateValue with data.date when it changes + dateValue = data.date; + }); @@ -52,11 +46,8 @@
        {#each entries as entry} - + {/each}
      -
    \ No newline at end of file +
    diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 76e7c10..f36ae19 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1,13 +1,22 @@ -import { today, getLocalTimeZone } from "@internationalized/date"; +import { today, getLocalTimeZone, CalendarDate } from "@internationalized/date"; export async function load({ params, fetch }) { - const dateValue = today(getLocalTimeZone()); - - const res = await fetch(`/api/entry?month=${dateValue.year}-${dateValue.month}`) - const entries = await res.json() + let dateValue; + + if (params.date) { + const [year, month, day] = params.date.split("-").map(Number); + dateValue = new CalendarDate(year, month, day); + } else { + dateValue = today(getLocalTimeZone()); + } + + const res = await fetch( + `/api/entry?month=${dateValue.year}-${dateValue.month}`, + ); + const entries = await res.json(); return { entries: entries, - date: dateValue + date: dateValue, }; } diff --git a/src/routes/[date]/+page.svelte b/src/routes/[date]/+page.svelte index f216e42..25c06c8 100644 --- a/src/routes/[date]/+page.svelte +++ b/src/routes/[date]/+page.svelte @@ -8,7 +8,7 @@ -{#if data.entry.id} +{#if data.entry} {:else} No entry exists for {data.date} diff --git a/src/routes/[date]/+page.ts b/src/routes/[date]/+page.ts index 86518e7..ab1af8c 100644 --- a/src/routes/[date]/+page.ts +++ b/src/routes/[date]/+page.ts @@ -2,5 +2,5 @@ export async function load({ params, fetch }) { const res = await fetch(`/api/entry?date=${params.date}`); const entries = await res.json(); - return { entry: entries }; + return { entry: entries[0] }; } -- 2.49.1 From 2a953ef5ce5ebdc2291151b1db6f10a1f44cd384 Mon Sep 17 00:00:00 2001 From: June Date: Tue, 17 Feb 2026 11:34:23 +1300 Subject: [PATCH 15/23] Add param matcher to ensure random paths dont crash the app --- src/params/date.ts | 4 ++++ src/routes/{[date] => [date=date]}/+page.svelte | 0 src/routes/{[date] => [date=date]}/+page.ts | 0 3 files changed, 4 insertions(+) create mode 100644 src/params/date.ts rename src/routes/{[date] => [date=date]}/+page.svelte (100%) rename src/routes/{[date] => [date=date]}/+page.ts (100%) diff --git a/src/params/date.ts b/src/params/date.ts new file mode 100644 index 0000000..810216e --- /dev/null +++ b/src/params/date.ts @@ -0,0 +1,4 @@ + +export function match(value) { + return /^\d{4}-\d{2}-\d{2}$/.test(value) +} \ No newline at end of file diff --git a/src/routes/[date]/+page.svelte b/src/routes/[date=date]/+page.svelte similarity index 100% rename from src/routes/[date]/+page.svelte rename to src/routes/[date=date]/+page.svelte diff --git a/src/routes/[date]/+page.ts b/src/routes/[date=date]/+page.ts similarity index 100% rename from src/routes/[date]/+page.ts rename to src/routes/[date=date]/+page.ts -- 2.49.1 From 44133744299f78a80b4b8769a3ee487961c67d0f Mon Sep 17 00:00:00 2001 From: June Date: Tue, 17 Feb 2026 11:58:22 +1300 Subject: [PATCH 16/23] default editor to today --- src/lib/components/editor.svelte | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib/components/editor.svelte b/src/lib/components/editor.svelte index b5201ce..1c2c6a2 100644 --- a/src/lib/components/editor.svelte +++ b/src/lib/components/editor.svelte @@ -1,13 +1,11 @@ -
    -

    {formatDate(entry.date)}

    +
    + +
    +

    {formatDate(entry.date)}

    +
    + {#if !edit} + + {:else} + + + + {/if} +
    +
    + + + {#if error} +
    + {error} +
    + {/if} + + {#if !edit} - +
    + + {#if entry.image} +
    + Entry +
    + {:else} +
    + No image +
    + {/if} + + + {#if entry.content} +
    +
    + {@html marked(entry.content)} +
    +
    + {:else} +
    + No content yet +
    + {/if} +
    + + {:else} - - - +
    + +
    + + + {#if previewImage} +
    + Preview + +
    + {:else} +
    { + if (e.key === "Enter" || e.key === " ") { + fileInput?.click(); + } + }} + onclick={() => fileInput?.click()} + > + +

    + Click to upload or drag and drop +

    +

    + PNG, JPG, GIF up to 5MB +

    +
    + {/if} + + +
    + + +
    + + -- 2.49.1 From c428aae0773b752cee39c48bfbf04b2a264d35b4 Mon Sep 17 00:00:00 2001 From: June Date: Tue, 17 Feb 2026 12:36:02 +1300 Subject: [PATCH 18/23] fix create new entry endpoint --- src/routes/api/entry/new/+server.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/api/entry/new/+server.ts b/src/routes/api/entry/new/+server.ts index d422e9c..062fced 100644 --- a/src/routes/api/entry/new/+server.ts +++ b/src/routes/api/entry/new/+server.ts @@ -9,7 +9,6 @@ export async function POST({ request }) { try { const body = await request.json(); const entry: typeof entryTable.$inferInsert = body - entry.date = new Date(body.date) await db.insert(entryTable).values(entry) -- 2.49.1 From 70bd76f49efbd4c52ef899c4bf75dfd619ccd218 Mon Sep 17 00:00:00 2001 From: June Date: Tue, 17 Feb 2026 12:37:17 +1300 Subject: [PATCH 19/23] always show editor --- src/routes/[date=date]/+page.svelte | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/routes/[date=date]/+page.svelte b/src/routes/[date=date]/+page.svelte index 25c06c8..a438931 100644 --- a/src/routes/[date=date]/+page.svelte +++ b/src/routes/[date=date]/+page.svelte @@ -7,10 +7,4 @@ - -{#if data.entry} - -{:else} - No entry exists for {data.date} -{/if} - + \ No newline at end of file -- 2.49.1 From f4d503c33502b1ec87d393fb4ee672760bd51a97 Mon Sep 17 00:00:00 2001 From: June Date: Tue, 17 Feb 2026 16:13:54 +1300 Subject: [PATCH 20/23] increase size of image --- src/lib/components/editor.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/editor.svelte b/src/lib/components/editor.svelte index 4c828ea..62f0518 100644 --- a/src/lib/components/editor.svelte +++ b/src/lib/components/editor.svelte @@ -213,7 +213,7 @@ Entry
    {:else} @@ -256,7 +256,7 @@ Preview