Enhance routing and layout for site-specific pages. Added support for dynamic site routes, updated component imports, and improved layout styles for fullscreen display. Refactored navigation to utilize site data for dynamic button generation.
This commit is contained in:
@@ -5,15 +5,18 @@ export const nodes = [
|
||||
() => import('./nodes/1'),
|
||||
() => import('./nodes/2'),
|
||||
() => import('./nodes/3'),
|
||||
() => import('./nodes/4')
|
||||
() => import('./nodes/4'),
|
||||
() => import('./nodes/5'),
|
||||
() => import('./nodes/6')
|
||||
];
|
||||
|
||||
export const server_loads = [0];
|
||||
|
||||
export const dictionary = {
|
||||
"/": [2],
|
||||
"/login": [~4],
|
||||
"/logout": [~3]
|
||||
"/": [3],
|
||||
"/login": [~6],
|
||||
"/logout": [~4],
|
||||
"/[site]": [~5,[2]]
|
||||
};
|
||||
|
||||
export const hooks = {
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default as component } from "../../../../src/routes/+page.svelte";
|
||||
export { default as component } from "../../../../src/routes/[site]/+layout.svelte";
|
||||
@@ -1 +1 @@
|
||||
export { default as component } from "../../../../src/routes/logout/+page.svelte";
|
||||
export { default as component } from "../../../../src/routes/+page.svelte";
|
||||
@@ -1 +1 @@
|
||||
export { default as component } from "../../../../src/routes/login/+page.svelte";
|
||||
export { default as component } from "../../../../src/routes/logout/+page.svelte";
|
||||
@@ -0,0 +1 @@
|
||||
export { default as component } from "../../../../src/routes/[site]/+page.svelte";
|
||||
@@ -0,0 +1 @@
|
||||
export { default as component } from "../../../../src/routes/login/+page.svelte";
|
||||
@@ -5,7 +5,7 @@
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
// stores
|
||||
let { stores, page, constructors, components = [], form, data_0 = null, data_1 = null } = $props();
|
||||
let { stores, page, constructors, components = [], form, data_0 = null, data_1 = null, data_2 = null } = $props();
|
||||
|
||||
if (!browser) {
|
||||
// svelte-ignore state_referenced_locally
|
||||
@@ -19,7 +19,7 @@
|
||||
stores.page.set(page);
|
||||
}
|
||||
$effect(() => {
|
||||
stores;page;constructors;components;form;data_0;data_1;
|
||||
stores;page;constructors;components;form;data_0;data_1;data_2;
|
||||
stores.page.notify();
|
||||
});
|
||||
|
||||
@@ -41,15 +41,27 @@
|
||||
return unsubscribe;
|
||||
});
|
||||
|
||||
const Pyramid_1=$derived(constructors[1])
|
||||
const Pyramid_2=$derived(constructors[2])
|
||||
</script>
|
||||
|
||||
{#if constructors[1]}
|
||||
{@const Pyramid_0 = constructors[0]}
|
||||
<!-- svelte-ignore binding_property_non_reactive -->
|
||||
<Pyramid_0 bind:this={components[0]} data={data_0} {form} params={page.params}>
|
||||
<!-- svelte-ignore binding_property_non_reactive -->
|
||||
<Pyramid_1 bind:this={components[1]} data={data_1} {form} params={page.params} />
|
||||
{#if constructors[2]}
|
||||
{@const Pyramid_1 = constructors[1]}
|
||||
<!-- svelte-ignore binding_property_non_reactive -->
|
||||
<Pyramid_1 bind:this={components[1]} data={data_1} {form} params={page.params}>
|
||||
<!-- svelte-ignore binding_property_non_reactive -->
|
||||
<Pyramid_2 bind:this={components[2]} data={data_2} {form} params={page.params} />
|
||||
</Pyramid_1>
|
||||
|
||||
{:else}
|
||||
{@const Pyramid_1 = constructors[1]}
|
||||
<!-- svelte-ignore binding_property_non_reactive -->
|
||||
<Pyramid_1 bind:this={components[1]} data={data_1} {form} params={page.params} />
|
||||
|
||||
{/if}
|
||||
</Pyramid_0>
|
||||
|
||||
{:else}
|
||||
|
||||
@@ -24,7 +24,7 @@ export const options = {
|
||||
app: ({ head, body, assets, nonce, env }) => "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <link rel=\"icon\" href=\"" + assets + "/favicon.png\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5, viewport-fit=cover\" />\n " + head + "\n </head>\n <body data-sveltekit-preload-data=\"hover\">\n <div style=\"display: contents\">" + body + "</div>\n </body>\n</html>\n",
|
||||
error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
|
||||
},
|
||||
version_hash: "k1vc61"
|
||||
version_hash: "1jm6xni"
|
||||
};
|
||||
|
||||
export async function get_hooks() {
|
||||
|
||||
Vendored
+6
-5
@@ -27,18 +27,19 @@ export {};
|
||||
|
||||
declare module "$app/types" {
|
||||
export interface AppTypes {
|
||||
RouteId(): "/" | "/api" | "/api/darkmode" | "/login" | "/logout";
|
||||
RouteId(): "/" | "/api" | "/api/darkmode" | "/login" | "/logout" | "/[site]";
|
||||
RouteParams(): {
|
||||
|
||||
"/[site]": { site: string }
|
||||
};
|
||||
LayoutParams(): {
|
||||
"/": Record<string, never>;
|
||||
"/": { site?: string };
|
||||
"/api": Record<string, never>;
|
||||
"/api/darkmode": Record<string, never>;
|
||||
"/login": Record<string, never>;
|
||||
"/logout": Record<string, never>
|
||||
"/logout": Record<string, never>;
|
||||
"/[site]": { site: string }
|
||||
};
|
||||
Pathname(): "/" | "/api/darkmode" | "/login" | "/logout";
|
||||
Pathname(): "/" | "/api/darkmode" | "/login" | "/logout" | `/${string}` & {};
|
||||
ResolvedPathname(): `${"" | `/${string}`}${ReturnType<AppTypes['Pathname']>}`;
|
||||
Asset(): string & {};
|
||||
}
|
||||
|
||||
@@ -13,5 +13,10 @@
|
||||
"/logout": [
|
||||
"src/routes/logout/+page.server.ts",
|
||||
"src/routes/+layout.server.ts"
|
||||
],
|
||||
"/[site]": [
|
||||
"src/routes/[site]/+page.server.ts",
|
||||
"src/routes/+layout.server.ts",
|
||||
"src/routes/+layout.server.ts"
|
||||
]
|
||||
}
|
||||
+2
-2
@@ -12,8 +12,8 @@ type EnsureDefined<T> = T extends null | undefined ? {} : T;
|
||||
type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;
|
||||
export type Snapshot<T = any> = Kit.Snapshot<T>;
|
||||
type PageParentData = EnsureDefined<LayoutData>;
|
||||
type LayoutRouteId = RouteId | "/" | "/logout" | "/login" | null
|
||||
type LayoutParams = RouteParams & { }
|
||||
type LayoutRouteId = RouteId | "/" | "/logout" | "/[site]" | "/login" | null
|
||||
type LayoutParams = RouteParams & { site?: string }
|
||||
type LayoutServerParentData = EnsureDefined<{}>;
|
||||
type LayoutParentData = EnsureDefined<{}>;
|
||||
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import type * as Kit from '@sveltejs/kit';
|
||||
|
||||
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
||||
// @ts-ignore
|
||||
type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;
|
||||
type RouteParams = { site: string };
|
||||
type RouteId = '/[site]';
|
||||
type MaybeWithVoid<T> = {} extends T ? T | void : T;
|
||||
export type RequiredKeys<T> = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T];
|
||||
type OutputDataShape<T> = MaybeWithVoid<Omit<App.PageData, RequiredKeys<T>> & Partial<Pick<App.PageData, keyof T & keyof App.PageData>> & Record<string, any>>
|
||||
type EnsureDefined<T> = T extends null | undefined ? {} : T;
|
||||
type OptionalUnion<U extends Record<string, any>, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude<A, keyof U>]?: never } & U : never;
|
||||
export type Snapshot<T = any> = Kit.Snapshot<T>;
|
||||
type PageServerParentData = Omit<EnsureDefined<import('../$types.js').LayoutServerData>, keyof LayoutServerData> & EnsureDefined<LayoutServerData>;
|
||||
type PageParentData = Omit<EnsureDefined<import('../$types.js').LayoutData>, keyof LayoutData> & EnsureDefined<LayoutData>;
|
||||
type LayoutRouteId = RouteId | "/[site]"
|
||||
type LayoutParams = RouteParams & { site?: string }
|
||||
type LayoutParentData = EnsureDefined<import('../$types.js').LayoutData>;
|
||||
|
||||
export type EntryGenerator = () => Promise<Array<RouteParams>> | Array<RouteParams>;
|
||||
export type PageServerLoad<OutputData extends OutputDataShape<PageServerParentData> = OutputDataShape<PageServerParentData>> = Kit.ServerLoad<RouteParams, PageServerParentData, OutputData, RouteId>;
|
||||
export type PageServerLoadEvent = Parameters<PageServerLoad>[0];
|
||||
export type ActionData = unknown;
|
||||
export type PageServerData = Expand<OptionalUnion<EnsureDefined<Kit.LoadProperties<Awaited<ReturnType<typeof import('../../../../../src/routes/[site]/+page.server.js').load>>>>>>;
|
||||
export type PageData = Expand<Omit<PageParentData, keyof PageServerData> & EnsureDefined<PageServerData>>;
|
||||
export type Action<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Action<RouteParams, OutputData, RouteId>
|
||||
export type Actions<OutputData extends Record<string, any> | void = Record<string, any> | void> = Kit.Actions<RouteParams, OutputData, RouteId>
|
||||
export type PageProps = { params: RouteParams; data: PageData; form: ActionData }
|
||||
export type LayoutServerData = null;
|
||||
export type LayoutData = Expand<LayoutParentData>;
|
||||
export type LayoutProps = { params: LayoutParams; data: LayoutData; children: import("svelte").Snippet }
|
||||
export type RequestEvent = Kit.RequestEvent<RouteParams, RouteId>;
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Config for each linked site: route slug → URL and optional per-site options.
|
||||
* Add site-specific options here (e.g. title, sandbox, allow) as needed.
|
||||
*/
|
||||
export const sites = {
|
||||
prism: {
|
||||
url: 'https://prism.ccllc.pro',
|
||||
title: 'Prism'
|
||||
},
|
||||
tasgrid: {
|
||||
url: 'https://tasgrid.ccllc.pro',
|
||||
title: 'TasGrid'
|
||||
},
|
||||
stackq: {
|
||||
url: 'https://stackq.ccllc.pro',
|
||||
title: 'Stackq'
|
||||
},
|
||||
hrm: {
|
||||
url: 'https://hrm.ccllc.pro',
|
||||
title: 'HRM'
|
||||
}
|
||||
} as const;
|
||||
|
||||
export type SiteSlug = keyof typeof sites;
|
||||
|
||||
export const siteSlugs = Object.keys(sites) as SiteSlug[];
|
||||
+7
-12
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/environment';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { sites, siteSlugs } from '$lib/sites';
|
||||
|
||||
let { data }: { data: Record<string, unknown> } = $props();
|
||||
</script>
|
||||
@@ -17,18 +18,12 @@
|
||||
<main class="flex min-h-0 flex-1 flex-col items-center justify-center gap-4 p-4 sm:gap-6 sm:p-6">
|
||||
<h1 class="text-2xl font-semibold">Base</h1>
|
||||
<div class="flex w-full max-w-xs flex-col gap-3">
|
||||
<a href="https://prism.ccllc.pro" class="block" target="_blank" rel="noopener noreferrer">
|
||||
<Button class="h-16 w-full min-h-16" variant="outline">Prism</Button>
|
||||
</a>
|
||||
<a href="https://tasgrid.ccllc.pro" class="block" target="_blank" rel="noopener noreferrer">
|
||||
<Button class="h-16 min-h-16 w-full" variant="outline">TasGrid</Button>
|
||||
</a>
|
||||
<a href="https://stackq.ccllc.pro" class="block" target="_blank" rel="noopener noreferrer">
|
||||
<Button class="h-16 min-h-16 w-full" variant="outline">Stackq</Button>
|
||||
</a>
|
||||
<a href="https://hrm.ccllc.pro" class="block" target="_blank" rel="noopener noreferrer">
|
||||
<Button class="h-16 min-h-16 w-full" variant="outline">HRM</Button>
|
||||
</a>
|
||||
{#each siteSlugs as slug}
|
||||
{@const site = sites[slug]}
|
||||
<a href="/{slug}" class="block">
|
||||
<Button class="h-16 w-full min-h-16" variant="outline">{site.title}</Button>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</main>
|
||||
{/if}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { sites, siteSlugs } from '$lib/sites';
|
||||
|
||||
let { data: _data }: { data: Record<string, unknown> } = $props();
|
||||
// `_data` is accepted to mirror Stackq's pattern (unused for now).
|
||||
@@ -7,20 +8,15 @@
|
||||
|
||||
<main class="flex min-h-0 flex-1 flex-col items-center justify-center gap-4 p-4 sm:gap-6 sm:p-6">
|
||||
<h1 class="w-full max-w-xs shrink-0 text-center text-2xl font-semibold">Base</h1>
|
||||
|
||||
<div class="flex w-full max-w-xs shrink-0 flex-col gap-3">
|
||||
<a href="https://prism.ccllc.pro" class="block" target="_blank" rel="noopener noreferrer">
|
||||
<Button class="h-16 min-h-16 w-full" variant="outline">Prism</Button>
|
||||
</a>
|
||||
<a href="https://tasgrid.ccllc.pro" class="block" target="_blank" rel="noopener noreferrer">
|
||||
<Button class="h-16 min-h-16 w-full" variant="outline">TasGrid</Button>
|
||||
</a>
|
||||
<a href="https://stackq.ccllc.pro" class="block" target="_blank" rel="noopener noreferrer">
|
||||
<Button class="h-16 min-h-16 w-full" variant="outline">Stackq</Button>
|
||||
</a>
|
||||
<a href="https://hrm.ccllc.pro" class="block" target="_blank" rel="noopener noreferrer">
|
||||
<Button class="h-16 min-h-16 w-full" variant="outline">HRM</Button>
|
||||
</a>
|
||||
{#each siteSlugs as slug}
|
||||
{@const site = sites[slug]}
|
||||
<a href="/{slug}" class="block">
|
||||
<Button class="h-16 min-h-16 w-full" variant="outline">
|
||||
{site.title}
|
||||
</Button>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<script lang="ts">
|
||||
let { children }: { children: import('svelte').Snippet } = $props();
|
||||
</script>
|
||||
|
||||
<div class="site-fullscreen">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
import { sites, type SiteSlug } from '$lib/sites';
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export function load({ params }) {
|
||||
const slug = params.site?.toLowerCase() as SiteSlug | undefined;
|
||||
const site = slug && slug in sites ? sites[slug as SiteSlug] : null;
|
||||
|
||||
if (!site) {
|
||||
throw error(404, `Unknown site: ${params.site}`);
|
||||
}
|
||||
|
||||
return {
|
||||
slug: slug as SiteSlug,
|
||||
url: site.url,
|
||||
title: site.title
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
|
||||
let { data }: {
|
||||
data: { slug: string; url: string; title: string };
|
||||
} = $props();
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.title} — Base</title>
|
||||
</svelte:head>
|
||||
|
||||
<main class="relative flex-1 min-h-0 min-w-0 flex flex-col">
|
||||
<iframe
|
||||
id="app-iframe"
|
||||
title={data.title}
|
||||
src={data.url}
|
||||
class="absolute inset-0 w-full h-full border-0 rounded-none"
|
||||
/>
|
||||
<div
|
||||
class="absolute top-2 left-1/2 -translate-x-1/2 z-10 flex items-center justify-center pointer-events-none pt-[env(safe-area-inset-top)]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="pointer-events-auto">
|
||||
<a href="/">
|
||||
<Button type="button" variant="secondary" class="shadow-md">
|
||||
Base
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
@@ -142,6 +142,18 @@
|
||||
min-height: 36px;
|
||||
}
|
||||
}
|
||||
/* [site] iframe route: break out of shell and fill viewport */
|
||||
.site-fullscreen {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
width: 100vw;
|
||||
height: 100dvh;
|
||||
min-height: 100dvh;
|
||||
z-index: 40;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use on icon-only links for 44px touch target */
|
||||
|
||||
Reference in New Issue
Block a user