wip, run migration command, fix api

This commit is contained in:
silentsilas 2025-01-21 00:08:18 -05:00
parent 08b56e13f3
commit d08171ef14
Signed by: silentsilas
GPG Key ID: 113DFB380F724A81
37 changed files with 8894 additions and 8458 deletions

16826
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +1,66 @@
{ {
"name": "playground", "name": "playground",
"version": "0.0.1", "version": "0.0.1",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"deploy": "bash scripts/deploy.sh", "deploy": "bash scripts/deploy.sh",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test": "vitest", "test": "vitest",
"lint": "prettier --check . && eslint .", "lint": "prettier --check . && eslint .",
"format": "prettier --write .", "format": "prettier --write .",
"model-pipeline:run": "node scripts/model-pipeline.js", "model-pipeline:run": "node scripts/model-pipeline.js",
"generate-embeddings": "node scripts/generate-embeddings.js", "generate-embeddings": "node scripts/generate-embeddings.js",
"finetune": "node scripts/finetune.js" "finetune": "node scripts/finetune.js"
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-auto": "^3.2.4", "@sveltejs/adapter-auto": "^3.2.4",
"@sveltejs/adapter-node": "^5.2.2", "@sveltejs/adapter-node": "^5.2.2",
"@sveltejs/kit": "^2.5.22", "@sveltejs/kit": "^2.16.0",
"@sveltejs/vite-plugin-svelte": "^3.1.1", "@sveltejs/vite-plugin-svelte": "^4.0.0",
"@tailwindcss/typography": "^0.5.14", "@tailwindcss/typography": "^0.5.14",
"@theatre/core": "^0.7.2", "@types/eslint": "^8.56.11",
"@theatre/studio": "^0.7.2", "@types/three": "^0.172.0",
"@threlte/theatre": "^2.1.8", "@typescript-eslint/eslint-plugin": "^7.18.0",
"@types/eslint": "^8.56.11", "@typescript-eslint/parser": "^7.18.0",
"@types/three": "^0.159.0", "autoprefixer": "^10.4.20",
"@typescript-eslint/eslint-plugin": "^7.18.0", "daisyui": "^4.12.10",
"@typescript-eslint/parser": "^7.18.0", "eslint": "^8.57.0",
"autoprefixer": "^10.4.20", "eslint-config-prettier": "^9.1.0",
"daisyui": "^4.12.10", "eslint-plugin-svelte": "^2.45.1",
"eslint": "^8.57.0", "fs-extra": "^11.2.0",
"eslint-config-prettier": "^9.1.0", "postcss": "^8.4.41",
"eslint-plugin-svelte": "^2.43.0", "prettier": "^3.3.3",
"fs-extra": "^11.2.0", "prettier-plugin-svelte": "^3.2.6",
"postcss": "^8.4.41", "svelte": "^5.19.0",
"prettier": "^3.3.3", "svelte-check": "^4.0.0",
"prettier-plugin-svelte": "^3.2.6", "tailwindcss": "^3.4.10",
"svelte": "^4.2.18", "tslib": "^2.6.3",
"svelte-check": "^3.8.5", "typescript": "^5.5.4",
"tailwindcss": "^3.4.10", "vite": "^5.4.4",
"tslib": "^2.6.3", "vitest": "^1.6.0"
"typescript": "^5.5.4", },
"vite": "^5.4.1", "type": "module",
"vitest": "^1.6.0" "dependencies": {
}, "@dimforge/rapier3d-compat": "^0.14.0",
"type": "module", "@langchain/anthropic": "^0.3.1",
"dependencies": { "@langchain/community": "^0.3.1",
"@dimforge/rapier3d-compat": "^0.11.2", "@langchain/core": "^0.3.32",
"@langchain/anthropic": "^0.3.1", "@langchain/openai": "^0.3.17",
"@langchain/community": "^0.3.1", "@langchain/textsplitters": "^0.1.0",
"@langchain/core": "^0.2.34", "@tensorflow-models/universal-sentence-encoder": "^1.3.3",
"@langchain/openai": "^0.3.0", "@tensorflow/tfjs-node": "^4.20.0",
"@langchain/textsplitters": "^0.1.0", "@threlte/core": "^8.0.0",
"@tensorflow-models/universal-sentence-encoder": "^1.3.3", "@threlte/extras": "^9.0.0",
"@tensorflow/tfjs-node": "^4.20.0", "@threlte/rapier": "^3.0.0",
"@threlte/core": "^7.3.1", "epub2": "^3.0.2",
"@threlte/extras": "^8.11.5", "fuse.js": "^7.0.0",
"@threlte/rapier": "^2.0.1", "html-to-text": "^9.0.5",
"epub2": "^3.0.2", "marked": "^12.0.2",
"fuse.js": "^7.0.0", "mdsvex": "^0.12.3",
"html-to-text": "^9.0.5", "three": "^0.172.0"
"marked": "^12.0.2", }
"mdsvex": "^0.11.2",
"three": "^0.159.0"
}
} }

View File

@ -63,13 +63,13 @@
type="text" type="text"
placeholder="Search" placeholder="Search"
class="input w-24 md:w-auto" class="input w-24 md:w-auto"
on:keyup={handleSearch} onkeyup={handleSearch}
/> />
</div> </div>
</div> </div>
<div class="navbar-end hidden lg:flex"> <div class="navbar-end hidden lg:flex">
<div class="form-control"> <div class="form-control">
<input type="text" placeholder="Search" class="input md:w-auto" on:keyup={handleSearch} /> <input type="text" placeholder="Search" class="input md:w-auto" onkeyup={handleSearch} />
</div> </div>
<ToggleTheme /> <ToggleTheme />
<ul class="menu menu-horizontal px-1"> <ul class="menu menu-horizontal px-1">

View File

@ -3,7 +3,7 @@
import type { SearchResult } from '$lib/utils/search'; import type { SearchResult } from '$lib/utils/search';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
let results: SearchResult[] = []; let results: SearchResult[] = $state([]);
searchResults.subscribe((value: SearchResult[]) => { searchResults.subscribe((value: SearchResult[]) => {
results = value ? value : []; results = value ? value : [];

View File

@ -2,13 +2,17 @@
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
export let message: string; interface Props {
export let type: 'info' | 'success' | 'warning' | 'error' = 'info'; message: string;
export let duration: number = 3000; type?: 'info' | 'success' | 'warning' | 'error';
duration?: number;
}
let { message, type = 'info', duration = 3000 }: Props = $props();
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
let visible = true; let visible = $state(true);
setTimeout(() => { setTimeout(() => {
visible = false; visible = false;

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
// Reactive variable to store the current theme // Reactive variable to store the current theme
let theme = 'forest'; // default theme let theme = $state('forest'); // default theme
// On component mount, check for saved theme in local storage // On component mount, check for saved theme in local storage
import { onMount } from 'svelte'; import { onMount } from 'svelte';
@ -28,7 +28,7 @@
<input <input
type="checkbox" type="checkbox"
class="toggle toggle-primary toggle-sm" class="toggle toggle-primary toggle-sm"
on:click={toggleTheme} onclick={toggleTheme}
checked={theme === 'forest'} checked={theme === 'forest'}
/> />
🌛 🌛

View File

@ -1,6 +1,11 @@
<script> <script lang="ts">
import Footer from '$lib/components/Footer.svelte'; import Footer from '$lib/components/Footer.svelte';
import NavBar from '$lib/components/NavBar.svelte'; import NavBar from '$lib/components/NavBar.svelte';
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script> </script>
<div <div
@ -10,7 +15,7 @@
<NavBar></NavBar> <NavBar></NavBar>
<div class="flex flex-1 overflow-auto"> <div class="flex flex-1 overflow-auto">
<slot /> {@render children?.()}
</div> </div>
<Footer></Footer> <Footer></Footer>

View File

@ -1,6 +1,13 @@
<!-- src/lib/CanvasLayout.svelte --> <!-- src/lib/CanvasLayout.svelte -->
<script lang="ts"> <script lang="ts">
import { preventDefault } from 'svelte/legacy';
import { Canvas } from '@threlte/core'; import { Canvas } from '@threlte/core';
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
function preventRightClick(event: MouseEvent) { function preventRightClick(event: MouseEvent) {
event.preventDefault(); event.preventDefault();
@ -9,11 +16,11 @@
<div <div
class="canvas flex flex-1" class="canvas flex flex-1"
on:contextmenu|preventDefault={preventRightClick} oncontextmenu={preventDefault(preventRightClick)}
role="application" role="application"
> >
<Canvas> <Canvas>
<slot /> {@render children?.()}
</Canvas> </Canvas>
</div> </div>

View File

@ -7,7 +7,7 @@
let camLookatPosition: Vector3 = new Vector3(); let camLookatPosition: Vector3 = new Vector3();
let camCurrentPosition: Vector3 = new Vector3(); let camCurrentPosition: Vector3 = new Vector3();
let camDamping: number = 1; let camDamping: number = 1;
let camera: PerspectiveCamera; let camera: PerspectiveCamera = $state();
const handleMouseMove = (event: MouseEvent) => { const handleMouseMove = (event: MouseEvent) => {
// normalize the mouse position to [-1, 1], and smoothly interpolate the camera's lookAt position // normalize the mouse position to [-1, 1], and smoothly interpolate the camera's lookAt position

View File

@ -2,13 +2,24 @@
import { HTML } from '@threlte/extras'; import { HTML } from '@threlte/extras';
import { Attractor } from '@threlte/rapier'; import { Attractor } from '@threlte/rapier';
export let position: [number, number, number] = [0, 0, 0]; interface Props {
export let range: number = 100; position?: [number, number, number];
export let clickHandler: (() => void) | undefined = undefined; range?: number;
export let active: boolean = false; clickHandler?: (() => void) | undefined;
active?: boolean;
children?: import('svelte').Snippet;
}
let isHovering = false; let {
let isPointerDown = false; position = [0, 0, 0],
range = 100,
clickHandler = undefined,
active = false,
children
}: Props = $props();
let isHovering = $state(false);
let isPointerDown = $state(false);
const onClick = () => { const onClick = () => {
if (clickHandler) { if (clickHandler) {
@ -20,22 +31,22 @@
<HTML position.x={position[0]} position.y={position[1]} position.z={position[2]}> <HTML position.x={position[0]} position.y={position[1]} position.z={position[2]}>
<button <button
type="button" type="button"
on:pointerenter={() => (isHovering = true)} onpointerenter={() => (isHovering = true)}
on:pointerleave={() => { onpointerleave={() => {
isPointerDown = false; isPointerDown = false;
isHovering = false; isHovering = false;
}} }}
on:pointerdown={() => (isPointerDown = true)} onpointerdown={() => (isPointerDown = true)}
on:pointerup={() => (isPointerDown = false)} onpointerup={() => (isPointerDown = false)}
on:pointercancel={() => { onpointercancel={() => {
isPointerDown = false; isPointerDown = false;
isHovering = false; isHovering = false;
}} }}
on:click={onClick} onclick={onClick}
class="bg-base-300 border border-primary px-3 py-3 text-primary md:opacity-50 hover:opacity-90 active:opacity-100" class="bg-base-300 border border-primary px-3 py-3 text-primary md:opacity-50 hover:opacity-90 active:opacity-100"
style="transform: translate(-50%, 50%); display: block; width: 170px;" style="transform: translate(-50%, 50%); display: block; width: 170px;"
> >
<slot /> {@render children?.()}
</button> </button>
</HTML> </HTML>

View File

@ -1,5 +1,13 @@
<script lang="ts">
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script>
<div class="overlay container prose bg-base-300/80 border border-primary" id="overlay"> <div class="overlay container prose bg-base-300/80 border border-primary" id="overlay">
<slot /> {@render children?.()}
</div> </div>
<style> <style>

View File

@ -1,4 +1,4 @@
<script lang="ts" context="module"> <script lang="ts" module>
import { T } from '@threlte/core'; import { T } from '@threlte/core';
import { Attractor, Collider, RigidBody } from '@threlte/rapier'; import { Attractor, Collider, RigidBody } from '@threlte/rapier';
import { MeshBasicMaterial, SphereGeometry } from 'three'; import { MeshBasicMaterial, SphereGeometry } from 'three';

View File

@ -1,10 +1,14 @@
<script lang="ts"> <script lang="ts">
import { T } from '@threlte/core'; import { T } from '@threlte/core';
export let size = 100; interface Props {
export let count = 500; size?: number;
export let color = localStorage.getItem('theme') === 'forest' ? 'white' : '#a991f7'; count?: number;
color?: any;
}
const positions = new Float32Array(count * 3); let { size = 100, count = 500, color = localStorage.getItem('theme') === 'forest' ? 'white' : '#a991f7' }: Props = $props();
const positions = $state(new Float32Array(count * 3));
// randomly distribute points in a cube // randomly distribute points in a cube
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {

View File

@ -6,9 +6,14 @@
import { Group, type Object3DEventMap } from 'three'; import { Group, type Object3DEventMap } from 'three';
import DollyCam from './DollyCam.svelte'; import DollyCam from './DollyCam.svelte';
import Planet from '$lib/components/scenes/app/Planet.svelte'; import Planet from '$lib/components/scenes/app/Planet.svelte';
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
const { invalidate } = useThrelte(); const { invalidate } = useThrelte();
let spaceObjects: Group<Object3DEventMap>; let spaceObjects: Group<Object3DEventMap> = $state();
useTask( useTask(
'updateSpaceObjects', 'updateSpaceObjects',
@ -31,6 +36,6 @@
<Planet /> <Planet />
<slot /> {@render children?.()}
</T.Group> </T.Group>
</World> </World>

View File

@ -6,10 +6,10 @@
import spinnersJson from '$lib/components/scenes/editor/SpinnersState.json'; import spinnersJson from '$lib/components/scenes/editor/SpinnersState.json';
import { type IProjectConfig } from '@theatre/core'; import { type IProjectConfig } from '@theatre/core';
let sequence: SequenceController; let sequence: SequenceController = $state();
let ball: Mesh; let ball: Mesh = $state();
let spotlight: SpotLight; let spotlight: SpotLight = $state();
let lastBallPosition = new Vector3(); let lastBallPosition = new Vector3();
let currentBallPosition = new Vector3(); let currentBallPosition = new Vector3();
let config = spinnersJson as IProjectConfig; let config = spinnersJson as IProjectConfig;
@ -33,16 +33,18 @@
<!-- create a T.SpotLight that looks at box--> <!-- create a T.SpotLight that looks at box-->
<T.SpotLight position={[0, 5, 3]} intensity={10} bind:ref={spotlight}></T.SpotLight> <T.SpotLight position={[0, 5, 3]} intensity={10} bind:ref={spotlight}></T.SpotLight>
<SheetObject key="Box" let:Transform let:Sync on:change={ballMoved}> <SheetObject key="Box" on:change={ballMoved}>
<Transform> {#snippet children({ Transform, Sync })}
<T.Mesh position.y={0.5} bind:ref={ball}> <Transform>
<T.SphereGeometry args={[1, 8, 4]} /> <T.Mesh position.y={0.5} bind:ref={ball}>
<T.MeshStandardMaterial color="#b00d03"> <T.SphereGeometry args={[1, 8, 4]} />
<Sync color roughness metalness /> <T.MeshStandardMaterial color="#b00d03">
</T.MeshStandardMaterial> <Sync color roughness metalness />
</T.Mesh> </T.MeshStandardMaterial>
</Transform> </T.Mesh>
</SheetObject> </Transform>
{/snippet}
</SheetObject>
<Sequence iterationCount={Infinity} direction="alternate" autoplay rate={1} bind:sequence /> <Sequence iterationCount={Infinity} direction="alternate" autoplay rate={1} bind:sequence />
</Sheet> </Sheet>
</Project> </Project>

View File

@ -1,4 +1,4 @@
<script context="module"> <script module>
import { tick } from 'svelte'; import { tick } from 'svelte';
/** /**
@ -51,13 +51,17 @@
</script> </script>
<script> <script>
/** /**
* DOM Element or CSS Selector * @typedef {Object} Props
* @type { HTMLElement|string} * @property { HTMLElement|string} [target] - DOM Element or CSS Selector
* @property {import('svelte').Snippet} [children]
*/ */
export let target = 'body';
/** @type {Props} */
let { target = 'body', children } = $props();
</script> </script>
<div use:portal={target} hidden style="display: contents;"> <div use:portal={target} hidden style="display: contents;">
<slot /> {@render children?.()}
</div> </div>

View File

@ -1,18 +1,13 @@
<script context="module"> <script module>
import Headline from './poetry/h1.svelte'; import Headline from './poetry/h1.svelte';
import p from './poetry/p.svelte'; import p from './poetry/p.svelte';
export { Headline as h1, p }; export { Headline as h1, p };
</script> </script>
<script lang="ts"> <script lang="ts">
export let title; let { title, date, categories, tags, year, layout, children } = $props();
export let date;
export let categories;
export let tags;
export let year;
export let layout;
</script> </script>
<main> <main>
<slot /> {@render children?.()}
</main> </main>

View File

@ -1,18 +1,21 @@
<script context="module"> <script module>
import Headline from './thoughts/h1.svelte'; import Headline from './thoughts/h1.svelte';
import p from './thoughts/p.svelte'; import p from './thoughts/p.svelte';
export { Headline as h1, p }; export { Headline as h1, p };
</script> </script>
<script lang="ts"> <script lang="ts">
export let title; let {
export let date; title,
export let categories; date,
export let tags; categories,
export let year; tags,
export let layout; year,
layout,
children
} = $props();
</script> </script>
<main> <main>
<slot /> {@render children?.()}
</main> </main>

View File

@ -1,3 +1,5 @@
import { render } from 'svelte/server';
export interface Metadata { export interface Metadata {
title: string; title: string;
date: string; date: string;
@ -21,11 +23,10 @@ export interface Post {
id: string; id: string;
} }
// Update the Data interface to match the new structure
interface Data { interface Data {
metadata: Metadata; metadata: Metadata;
default: { default: any; // The component itself
render: () => { html: string };
};
} }
function isData(obj: unknown): obj is Data { function isData(obj: unknown): obj is Data {
@ -74,8 +75,8 @@ export const fetchMarkdownPosts = async (
return undefined; return undefined;
} }
const { metadata } = data; const { metadata } = data;
const { html } = data.default.render(); // Use the new render function from svelte/server
// remove html tags const { html } = render(data.default, {});
const content = html.replace(/<[^>]*>/g, ''); const content = html.replace(/<[^>]*>/g, '');
const section = path.split('/')[3]; const section = path.split('/')[3];
const filename = path.split('/').pop()?.slice(0, -3); const filename = path.split('/').pop()?.slice(0, -3);

View File

@ -1,3 +1,11 @@
<script lang="ts">
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script>
<h1 class="poetry-headline"> <h1 class="poetry-headline">
<slot></slot> {@render children?.()}
</h1> </h1>

View File

@ -1,3 +1,11 @@
<script lang="ts">
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script>
<p class="whitespace-pre-wrap"> <p class="whitespace-pre-wrap">
<slot></slot> {@render children?.()}
</p> </p>

View File

@ -1,3 +1,11 @@
<script lang="ts">
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script>
<h1 class="poetry-headline"> <h1 class="poetry-headline">
<slot></slot> {@render children?.()}
</h1> </h1>

View File

@ -1,3 +1,11 @@
<script lang="ts">
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script>
<p class="whitespace-pre-wrap"> <p class="whitespace-pre-wrap">
<slot></slot> {@render children?.()}
</p> </p>

View File

@ -2,9 +2,14 @@
import '../../app.css'; import '../../app.css';
import SearchResults from '$lib/components/SearchResults.svelte'; import SearchResults from '$lib/components/SearchResults.svelte';
import AppContainer from '$lib/components/scenes/app/AppContainer.svelte'; import AppContainer from '$lib/components/scenes/app/AppContainer.svelte';
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script> </script>
<AppContainer> <AppContainer>
<slot /> {@render children?.()}
<SearchResults /> <SearchResults />
</AppContainer> </AppContainer>

View File

@ -4,7 +4,7 @@
import { searchResults } from '$lib/store'; import { searchResults } from '$lib/store';
import type { SearchResult } from '$lib/utils/search'; import type { SearchResult } from '$lib/utils/search';
let results: SearchResult[] = []; let results: SearchResult[] = $state([]);
searchResults.subscribe((value: SearchResult[]) => { searchResults.subscribe((value: SearchResult[]) => {
results = value ? value : []; results = value ? value : [];
@ -40,8 +40,8 @@
let greetings = [...GREETINGS]; let greetings = [...GREETINGS];
let currentGreeting: Greeting = { greeting: 'Hello', language: 'English' }; let currentGreeting: Greeting = $state({ greeting: 'Hello', language: 'English' });
let visible = false; let visible = $state(false);
onMount(() => { onMount(() => {
visible = true; visible = true;

View File

@ -1,13 +1,19 @@
<script lang="ts"> <script lang="ts">
import { run } from 'svelte/legacy';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { searchResults } from '$lib/store'; import { searchResults } from '$lib/store';
import type { SearchResult } from '$lib/utils/search'; import type { SearchResult } from '$lib/utils/search';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import type { PageData } from '../poetry/$types'; import type { PageData } from '../poetry/$types';
export let data: PageData; interface Props {
data: PageData;
}
let results: SearchResult[] = []; let { data }: Props = $props();
let results: SearchResult[] = $state([]);
searchResults.subscribe((value: SearchResult[]) => { searchResults.subscribe((value: SearchResult[]) => {
results = value ? value : []; results = value ? value : [];
@ -21,13 +27,15 @@
}); });
}; };
let { posts, total } = data; let { posts, total } = $state(data);
const limit = 8; const limit = 8;
let currentPage = Number($page.url.searchParams.get('page')) || 1; let currentPage = $state(Number($page.url.searchParams.get('page')) || 1);
let totalPages = Math.ceil(total / limit); let totalPages = $state(Math.ceil(total / limit));
$: $page.url.searchParams.get('page'), run(() => {
(currentPage = Number($page.url.searchParams.get('page')) || 1); $page.url.searchParams.get('page'),
(currentPage = Number($page.url.searchParams.get('page')) || 1);
});
async function fetchData(page: number) { async function fetchData(page: number) {
const response = await fetch(`/api/poetry?limit=${limit}&page=${page}`); const response = await fetch(`/api/poetry?limit=${limit}&page=${page}`);
@ -73,13 +81,13 @@
<nav class="join justify-end py-10"> <nav class="join justify-end py-10">
<button <button
class="join-item btn-primary btn btn-outline" class="join-item btn-primary btn btn-outline"
on:click={() => navigate(currentPage - 1)} onclick={() => navigate(currentPage - 1)}
disabled={currentPage === 1}>Prev</button disabled={currentPage === 1}>Prev</button
> >
<div class="join-item content-center px-10">{currentPage} of {totalPages}</div> <div class="join-item content-center px-10">{currentPage} of {totalPages}</div>
<button <button
class="join-item btn btn-primary btn-outline" class="join-item btn btn-primary btn-outline"
on:click={() => navigate(currentPage + 1)} onclick={() => navigate(currentPage + 1)}
disabled={currentPage === totalPages}>Next</button disabled={currentPage === totalPages}>Next</button
> >
</nav> </nav>

View File

@ -3,11 +3,15 @@
import type { SearchResult } from '$lib/utils/search'; import type { SearchResult } from '$lib/utils/search';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
export let data: PageData; interface Props {
data: PageData;
}
let { data }: Props = $props();
const { title, date: _date, Content, categories: _ } = data; const { title, date: _date, Content, categories: _ } = data;
let results: SearchResult[] = []; let results: SearchResult[] = $state([]);
searchResults.subscribe((value: SearchResult[]) => { searchResults.subscribe((value: SearchResult[]) => {
results = value ? value : []; results = value ? value : [];

View File

@ -2,7 +2,7 @@
import type { SearchResult } from '$lib/utils/search'; import type { SearchResult } from '$lib/utils/search';
import { searchResults } from '$lib/store'; import { searchResults } from '$lib/store';
let results: SearchResult[] = []; let results: SearchResult[] = $state([]);
searchResults.subscribe((value: SearchResult[]) => { searchResults.subscribe((value: SearchResult[]) => {
results = value ? value : []; results = value ? value : [];

View File

@ -1,13 +1,19 @@
<script lang="ts"> <script lang="ts">
import { run } from 'svelte/legacy';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { searchResults } from '$lib/store'; import { searchResults } from '$lib/store';
import type { SearchResult } from '$lib/utils/search'; import type { SearchResult } from '$lib/utils/search';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import type { PageData } from '../thoughts/$types'; import type { PageData } from '../thoughts/$types';
export let data: PageData; interface Props {
data: PageData;
}
let results: SearchResult[] = []; let { data }: Props = $props();
let results: SearchResult[] = $state([]);
searchResults.subscribe((value: SearchResult[]) => { searchResults.subscribe((value: SearchResult[]) => {
results = value ? value : []; results = value ? value : [];
@ -21,13 +27,15 @@
}); });
}; };
let { posts, total } = data; let { posts, total } = $state(data);
const limit = 8; const limit = 8;
let currentPage = Number($page.url.searchParams.get('page')) || 1; let currentPage = $state(Number($page.url.searchParams.get('page')) || 1);
let totalPages = Math.ceil(total / limit); let totalPages = $state(Math.ceil(total / limit));
$: $page.url.searchParams.get('page'), run(() => {
(currentPage = Number($page.url.searchParams.get('page')) || 1); $page.url.searchParams.get('page'),
(currentPage = Number($page.url.searchParams.get('page')) || 1);
});
async function fetchData(page: number) { async function fetchData(page: number) {
const response = await fetch(`/api/thoughts?limit=${limit}&page=${page}`); const response = await fetch(`/api/thoughts?limit=${limit}&page=${page}`);
@ -74,13 +82,13 @@
<nav class="join justify-end py-4"> <nav class="join justify-end py-4">
<button <button
class="join-item btn-primary btn btn-outline" class="join-item btn-primary btn btn-outline"
on:click={() => navigate(currentPage - 1)} onclick={() => navigate(currentPage - 1)}
disabled={currentPage === 1}>Prev</button disabled={currentPage === 1}>Prev</button
> >
<div class="join-item content-center px-10">{currentPage} of {totalPages}</div> <div class="join-item content-center px-10">{currentPage} of {totalPages}</div>
<button <button
class="join-item btn btn-primary btn-outline" class="join-item btn btn-primary btn-outline"
on:click={() => navigate(currentPage + 1)} onclick={() => navigate(currentPage + 1)}
disabled={currentPage === totalPages}>Next</button disabled={currentPage === totalPages}>Next</button
> >
</nav> </nav>

View File

@ -3,11 +3,15 @@
import type { SearchResult } from '$lib/utils/search'; import type { SearchResult } from '$lib/utils/search';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
export let data: PageData; interface Props {
data: PageData;
}
let { data }: Props = $props();
const { title, date: _date, Content, categories: _ } = data; const { title, date: _date, Content, categories: _ } = data;
let results: SearchResult[] = []; let results: SearchResult[] = $state([]);
searchResults.subscribe((value: SearchResult[]) => { searchResults.subscribe((value: SearchResult[]) => {
results = value ? value : []; results = value ? value : [];

View File

@ -1 +1,9 @@
<slot /> <script lang="ts">
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script>
{@render children?.()}

View File

@ -1,9 +1,14 @@
<script lang="ts"> <script lang="ts">
import SearchResults from '$lib/components/SearchResults.svelte'; import SearchResults from '$lib/components/SearchResults.svelte';
import AppContainer from '$lib/components/scenes/app/AppContainer.svelte'; import AppContainer from '$lib/components/scenes/app/AppContainer.svelte';
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script> </script>
<AppContainer> <AppContainer>
<slot /> {@render children?.()}
<SearchResults /> <SearchResults />
</AppContainer> </AppContainer>

View File

@ -1,4 +1,6 @@
<script lang="ts"> <script lang="ts">
import { preventDefault } from 'svelte/legacy';
import '../../app.css'; import '../../app.css';
import type { SearchResult } from '$lib/utils/search'; import type { SearchResult } from '$lib/utils/search';
import { searchResults, type ChatHistory } from '$lib/store'; import { searchResults, type ChatHistory } from '$lib/store';
@ -8,11 +10,11 @@
import { PUBLIC_LOAD_DUMMY_HISTORY } from '$env/static/public'; import { PUBLIC_LOAD_DUMMY_HISTORY } from '$env/static/public';
import Toast from '$lib/components/Toast.svelte'; import Toast from '$lib/components/Toast.svelte';
let searchResultsValue: SearchResult[] = []; let searchResultsValue: SearchResult[] = $state([]);
let query = ''; let query = $state('');
let loading = false; let loading = $state(false);
let showToast = false; let showToast = $state(false);
let toastMessage = ''; let toastMessage = $state('');
type Questions = { type Questions = {
[key: string]: string[]; [key: string]: string[];
@ -68,7 +70,7 @@
]; ];
} }
let chatHistory: ChatHistory = []; let chatHistory: ChatHistory = $state([]);
onMount(async () => { onMount(async () => {
try { try {
@ -207,7 +209,7 @@
<span>This may take a minute; streaming is still a work in progress.</span> <span>This may take a minute; streaming is still a work in progress.</span>
</div> </div>
{/if} {/if}
<form on:submit|preventDefault={handleSubmit} class="mt-4 flex-col"> <form onsubmit={preventDefault(handleSubmit)} class="mt-4 flex-col">
<label class="form-control"> <label class="form-control">
<textarea <textarea
bind:value={query} bind:value={query}
@ -221,7 +223,7 @@
<button <button
type="button" type="button"
class="btn btn-block btn-error btn-outline mt-2" class="btn btn-block btn-error btn-outline mt-2"
on:click={handleNewSession} onclick={handleNewSession}
> >
New Session New Session
</button> </button>
@ -241,7 +243,7 @@
<button <button
type="button" type="button"
class="btn btn-sm btn-outline" class="btn btn-sm btn-outline"
on:click={() => copyToClipboard(item)} onclick={() => copyToClipboard(item)}
title="Copy to clipboard" title="Copy to clipboard"
> >
<svg <svg

View File

@ -5,11 +5,11 @@ export const GET = async ({ url }) => {
const page = Number(url.searchParams.get('page')) || 1; const page = Number(url.searchParams.get('page')) || 1;
const limit = Number(url.searchParams.get('limit')) || 8; const limit = Number(url.searchParams.get('limit')) || 8;
const offset = (page - 1) * limit; const offset = (page - 1) * limit;
const {posts: allPosts, total: total} = await fetchMarkdownPosts('poetry', limit, offset); const { posts: allPosts, total: total } = await fetchMarkdownPosts('poetry', limit, offset);
const sortedPosts = allPosts.sort((a, b) => { const sortedPosts = allPosts.sort((a, b) => {
return new Date(b.meta.date).getTime() - new Date(a.meta.date).getTime(); return new Date(b.meta.date).getTime() - new Date(a.meta.date).getTime();
}); });
return json({posts: sortedPosts, total: total, page: page}); return json({ posts: sortedPosts, total: total, page: page });
}; };

View File

@ -1,9 +1,14 @@
<script lang="ts"> <script lang="ts">
import SearchResults from '$lib/components/SearchResults.svelte'; import SearchResults from '$lib/components/SearchResults.svelte';
import AppContainer from '$lib/components/scenes/app/AppContainer.svelte'; import AppContainer from '$lib/components/scenes/app/AppContainer.svelte';
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script> </script>
<AppContainer> <AppContainer>
<slot /> {@render children?.()}
<SearchResults /> <SearchResults />
</AppContainer> </AppContainer>

View File

@ -8,9 +8,9 @@
import { searchResults } from '$lib/store'; import { searchResults } from '$lib/store';
import Overlay from '$lib/components/scenes/app/Overlay.svelte'; import Overlay from '$lib/components/scenes/app/Overlay.svelte';
let results: SearchResult[] = []; let results: SearchResult[] = $state([]);
let open = false; let open = $state(false);
let selected = -1; let selected = $state(-1);
searchResults.subscribe((value: SearchResult[]) => { searchResults.subscribe((value: SearchResult[]) => {
results = value ? value : []; results = value ? value : [];
@ -105,7 +105,7 @@
<button <button
type="button" type="button"
class="close-button p-4 m-4 btn btn-outline" class="close-button p-4 m-4 btn btn-outline"
on:click={() => { onclick={() => {
open = false; open = false;
selected = -1; selected = -1;
}}>X</button }}>X</button

View File

@ -6,13 +6,16 @@ import { mdsvex } from 'mdsvex';
const config = { const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors // Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors // for more information about preprocessors
preprocess: [vitePreprocess(), mdsvex({ preprocess: [
extensions: ['.md'], layout: { vitePreprocess(),
poetry: './src/lib/utils/PoetryLayout.svelte', mdsvex({
thoughts: './src/lib/utils/ThoughtsLayout.svelte', extensions: ['.md'],
} layout: {
})], poetry: './src/lib/utils/PoetryLayout.svelte',
thoughts: './src/lib/utils/ThoughtsLayout.svelte'
}
})
],
kit: { kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.