@sveltekitchen/sveltekitchen 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +137 -2
  2. package/dist/components/Accordion.svelte +36 -0
  3. package/dist/components/Accordion.svelte.d.ts +15 -0
  4. package/dist/components/AccordionItem.svelte +73 -0
  5. package/dist/components/AccordionItem.svelte.d.ts +21 -0
  6. package/dist/components/Alert.svelte +23 -0
  7. package/dist/components/Alert.svelte.d.ts +15 -0
  8. package/dist/components/Badge.svelte +16 -0
  9. package/dist/components/Badge.svelte.d.ts +15 -0
  10. package/dist/components/Button.svelte +43 -0
  11. package/dist/components/Button.svelte.d.ts +25 -0
  12. package/dist/components/Calendar.svelte +88 -0
  13. package/dist/components/Calendar.svelte.d.ts +13 -0
  14. package/dist/components/Card.svelte +68 -0
  15. package/dist/components/Card.svelte.d.ts +25 -0
  16. package/dist/components/Chevron.svelte +36 -0
  17. package/dist/components/Chevron.svelte.d.ts +19 -0
  18. package/dist/components/Collapsible.svelte +46 -0
  19. package/dist/components/Collapsible.svelte.d.ts +19 -0
  20. package/dist/components/ConfirmDialog.svelte +70 -0
  21. package/dist/components/ConfirmDialog.svelte.d.ts +27 -0
  22. package/dist/components/DatePicker.svelte +60 -0
  23. package/dist/components/DatePicker.svelte.d.ts +17 -0
  24. package/dist/components/Divider.svelte +25 -0
  25. package/dist/components/Divider.svelte.d.ts +17 -0
  26. package/dist/components/Dropdown.svelte +100 -0
  27. package/dist/components/Dropdown.svelte.d.ts +21 -0
  28. package/dist/components/Form/Checkbox.svelte +37 -0
  29. package/dist/components/Form/Checkbox.svelte.d.ts +19 -0
  30. package/dist/components/Form/Field.svelte +28 -0
  31. package/dist/components/Form/Field.svelte.d.ts +21 -0
  32. package/dist/components/Form/Input.svelte +56 -0
  33. package/dist/components/Form/Input.svelte.d.ts +29 -0
  34. package/dist/components/Form/MaskedInput.svelte +152 -0
  35. package/dist/components/Form/MaskedInput.svelte.d.ts +25 -0
  36. package/dist/components/Form/Radio.svelte +28 -0
  37. package/dist/components/Form/Radio.svelte.d.ts +19 -0
  38. package/dist/components/Form/RadioGroup.svelte +28 -0
  39. package/dist/components/Form/RadioGroup.svelte.d.ts +19 -0
  40. package/dist/components/Form/Select.svelte +20 -0
  41. package/dist/components/Form/Select.svelte.d.ts +19 -0
  42. package/dist/components/Form/Textarea.svelte +30 -0
  43. package/dist/components/Form/Textarea.svelte.d.ts +25 -0
  44. package/dist/components/Form/Toggle.svelte +21 -0
  45. package/dist/components/Form/Toggle.svelte.d.ts +17 -0
  46. package/dist/components/Modal.svelte +77 -0
  47. package/dist/components/Modal.svelte.d.ts +27 -0
  48. package/dist/components/Pagination.svelte +77 -0
  49. package/dist/components/Pagination.svelte.d.ts +17 -0
  50. package/dist/components/Progress.svelte +34 -0
  51. package/dist/components/Progress.svelte.d.ts +21 -0
  52. package/dist/components/Spinner.svelte +24 -0
  53. package/dist/components/Spinner.svelte.d.ts +13 -0
  54. package/dist/components/Table.svelte +100 -0
  55. package/dist/components/Table.svelte.d.ts +21 -0
  56. package/dist/components/ThemeToggle.svelte +22 -0
  57. package/dist/components/ThemeToggle.svelte.d.ts +11 -0
  58. package/dist/components/Tooltip.svelte +45 -0
  59. package/dist/components/Tooltip.svelte.d.ts +15 -0
  60. package/dist/css/base/root.css +103 -0
  61. package/dist/css/base.css +47 -0
  62. package/dist/css/components/accordion.css +151 -0
  63. package/dist/css/components/alert.css +56 -0
  64. package/dist/css/components/badge.css +56 -0
  65. package/dist/css/components/button.css +171 -0
  66. package/dist/css/components/calendar.css +105 -0
  67. package/dist/css/components/card.css +128 -0
  68. package/dist/css/components/checkbox-radio.css +105 -0
  69. package/dist/css/components/collapsible.css +61 -0
  70. package/dist/css/components/divider.css +42 -0
  71. package/dist/css/components/dock-layout.css +111 -0
  72. package/dist/css/components/dropdown.css +68 -0
  73. package/dist/css/components/floating-shell.css +93 -0
  74. package/dist/css/components/form.css +286 -0
  75. package/dist/css/components/login.css +145 -0
  76. package/dist/css/components/modal.css +179 -0
  77. package/dist/css/components/nav.css +190 -0
  78. package/dist/css/components/nestable.css +187 -0
  79. package/dist/css/components/pagination.css +50 -0
  80. package/dist/css/components/progress.css +50 -0
  81. package/dist/css/components/sidebar.css +78 -0
  82. package/dist/css/components/spinner.css +36 -0
  83. package/dist/css/components/table.css +98 -0
  84. package/dist/css/components/tooltip.css +77 -0
  85. package/dist/css/components/topbar-layout.css +108 -0
  86. package/dist/css/icons/icons.css +52 -0
  87. package/dist/css/index.css +20 -0
  88. package/dist/css/layout/container.css +12 -0
  89. package/dist/css/layout/grid.css +40 -0
  90. package/dist/css/layout/shell.css +185 -0
  91. package/dist/css/overlay/default.css +27 -0
  92. package/dist/css/tokens/colors.css +81 -0
  93. package/dist/css/tokens/radius.css +8 -0
  94. package/dist/css/tokens/shadows.css +23 -0
  95. package/dist/css/tokens/spacing.css +30 -0
  96. package/dist/css/tokens/transitions.css +10 -0
  97. package/dist/css/tokens/typography.css +44 -0
  98. package/dist/index.d.ts +43 -0
  99. package/dist/index.js +52 -0
  100. package/dist/layout/NavItem.svelte +84 -0
  101. package/dist/layout/NavItem.svelte.d.ts +25 -0
  102. package/dist/layout/Shell.svelte +7 -0
  103. package/dist/layout/Shell.svelte.d.ts +13 -0
  104. package/dist/layout/SidebarProfile.svelte +31 -0
  105. package/dist/layout/SidebarProfile.svelte.d.ts +19 -0
  106. package/dist/layouts/AppShell.svelte +60 -0
  107. package/dist/layouts/AppShell.svelte.d.ts +21 -0
  108. package/dist/layouts/BarLayout.svelte +60 -0
  109. package/dist/layouts/BarLayout.svelte.d.ts +21 -0
  110. package/dist/layouts/BottomBarLayout.svelte +23 -0
  111. package/dist/layouts/BottomBarLayout.svelte.d.ts +15 -0
  112. package/dist/layouts/DockLayout.svelte +81 -0
  113. package/dist/layouts/DockLayout.svelte.d.ts +15 -0
  114. package/dist/layouts/FloatingDockLayout.svelte +56 -0
  115. package/dist/layouts/FloatingDockLayout.svelte.d.ts +13 -0
  116. package/dist/layouts/FloatingLayout.svelte +80 -0
  117. package/dist/layouts/FloatingLayout.svelte.d.ts +19 -0
  118. package/dist/layouts/FloatingLeftLayout.svelte +59 -0
  119. package/dist/layouts/FloatingLeftLayout.svelte.d.ts +15 -0
  120. package/dist/layouts/FloatingShell.svelte +80 -0
  121. package/dist/layouts/FloatingShell.svelte.d.ts +19 -0
  122. package/dist/layouts/FloatingTopLayout.svelte +68 -0
  123. package/dist/layouts/FloatingTopLayout.svelte.d.ts +15 -0
  124. package/dist/layouts/HybridLayout.svelte +20 -0
  125. package/dist/layouts/HybridLayout.svelte.d.ts +17 -0
  126. package/dist/layouts/IconRailLayout.svelte +75 -0
  127. package/dist/layouts/IconRailLayout.svelte.d.ts +15 -0
  128. package/dist/layouts/LeftBarLayout.svelte +19 -0
  129. package/dist/layouts/LeftBarLayout.svelte.d.ts +15 -0
  130. package/dist/layouts/RightBarLayout.svelte +21 -0
  131. package/dist/layouts/RightBarLayout.svelte.d.ts +15 -0
  132. package/dist/layouts/SideBar.svelte +86 -0
  133. package/dist/layouts/SideBar.svelte.d.ts +17 -0
  134. package/dist/layouts/SidebarLayout.svelte +11 -0
  135. package/dist/layouts/SidebarLayout.svelte.d.ts +15 -0
  136. package/dist/layouts/TopBar.svelte +90 -0
  137. package/dist/layouts/TopBar.svelte.d.ts +21 -0
  138. package/dist/layouts/TopBarLayout.svelte +26 -0
  139. package/dist/layouts/TopBarLayout.svelte.d.ts +15 -0
  140. package/dist/theme/theme.svelte.d.ts +11 -0
  141. package/dist/theme/theme.svelte.js +48 -0
  142. package/package.json +56 -4
@@ -0,0 +1,19 @@
1
+ export default SidebarProfile;
2
+ type SidebarProfile = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const SidebarProfile: import("svelte").Component<{
7
+ name?: string;
8
+ role?: string;
9
+ initials?: string;
10
+ avatarSrc?: any;
11
+ children: any;
12
+ } & Record<string, any>, {}, "">;
13
+ type $$ComponentProps = {
14
+ name?: string;
15
+ role?: string;
16
+ initials?: string;
17
+ avatarSrc?: any;
18
+ children: any;
19
+ } & Record<string, any>;
@@ -0,0 +1,60 @@
1
+ <script>
2
+ // AppShell — one app layout driven by two independent, bindable menu props:
3
+ //
4
+ // topMenu → renders a top bar (omit for no top bar)
5
+ // sideMenu → renders a sidebar (omit for no sidebar)
6
+ //
7
+ // both → hybrid (top bar + sidebar)
8
+ // one → top-only or side-only
9
+ // none → just content
10
+ //
11
+ // Each menu is its own bindable prop, so users wire and update them
12
+ // independently:
13
+ // <AppShell bind:topMenu bind:sideMenu>{content}</AppShell>
14
+ //
15
+ // Menu contract (same for both regions):
16
+ // { brand?, sections: [{ label?, items: [{ id, label, icon?, href?, badge?, children? }] }], active? }
17
+ import TopBar from './TopBar.svelte';
18
+ import SideBar from './SideBar.svelte';
19
+
20
+ let {
21
+ topMenu = $bindable(undefined),
22
+ sideMenu = $bindable(undefined),
23
+ sideRight = false, // place the sidebar on the right
24
+ actions, // snippet: top bar right-side actions
25
+ footer, // snippet: sidebar footer (e.g. profile)
26
+ children,
27
+ ...rest
28
+ } = $props();
29
+
30
+ let hasTop = $derived(!!topMenu);
31
+ let hasSide = $derived(!!sideMenu);
32
+
33
+ // Flatten the top menu's sections into a horizontal item list.
34
+ let topItems = $derived(hasTop ? (topMenu.sections ?? []).flatMap((s) => s.items ?? []) : []);
35
+ </script>
36
+
37
+ <div class="lyt lyt-col" {...rest}>
38
+ {#if hasTop}
39
+ <TopBar
40
+ brand={topMenu.brand}
41
+ items={topItems}
42
+ active={topMenu.active}
43
+ {actions}
44
+ />
45
+ {/if}
46
+
47
+ {#if hasSide}
48
+ <div class="lyt-row lyt-fill" class:lyt-side-right={sideRight}>
49
+ <SideBar
50
+ brand={hasTop ? undefined : sideMenu.brand}
51
+ sections={sideMenu.sections}
52
+ active={sideMenu.active}
53
+ {footer}
54
+ />
55
+ <main class="lyt-main"><div class="lyt-inner">{@render children?.()}</div></main>
56
+ </div>
57
+ {:else}
58
+ <main class="lyt-main"><div class="lyt-inner">{@render children?.()}</div></main>
59
+ {/if}
60
+ </div>
@@ -0,0 +1,21 @@
1
+ export default AppShell;
2
+ type AppShell = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const AppShell: import("svelte").Component<{
7
+ topMenu?: any;
8
+ sideMenu?: any;
9
+ sideRight?: boolean;
10
+ actions: any;
11
+ footer: any;
12
+ children: any;
13
+ } & Record<string, any>, {}, "topMenu" | "sideMenu">;
14
+ type $$ComponentProps = {
15
+ topMenu?: any;
16
+ sideMenu?: any;
17
+ sideRight?: boolean;
18
+ actions: any;
19
+ footer: any;
20
+ children: any;
21
+ } & Record<string, any>;
@@ -0,0 +1,60 @@
1
+ <script>
2
+ // BarLayout — one app layout driven by two independent, bindable menu props:
3
+ //
4
+ // topMenu → renders a top bar (omit for no top bar)
5
+ // sideMenu → renders a sidebar (omit for no sidebar)
6
+ //
7
+ // both → hybrid (top bar + sidebar)
8
+ // one → top-only or side-only
9
+ // none → just content
10
+ //
11
+ // Each menu is its own bindable prop, so users wire and update them
12
+ // independently:
13
+ // <BarLayout bind:topMenu bind:sideMenu>{content}</AppShell>
14
+ //
15
+ // Menu contract (same for both regions):
16
+ // { brand?, sections: [{ label?, items: [{ id, label, icon?, href?, badge?, children? }] }], active? }
17
+ import TopBar from './TopBar.svelte';
18
+ import SideBar from './SideBar.svelte';
19
+
20
+ let {
21
+ topMenu = $bindable(undefined),
22
+ sideMenu = $bindable(undefined),
23
+ sideRight = false, // place the sidebar on the right
24
+ actions, // snippet: top bar right-side actions
25
+ footer, // snippet: sidebar footer (e.g. profile)
26
+ children,
27
+ ...rest
28
+ } = $props();
29
+
30
+ let hasTop = $derived(!!topMenu);
31
+ let hasSide = $derived(!!sideMenu);
32
+
33
+ // Flatten the top menu's sections into a horizontal item list.
34
+ let topItems = $derived(hasTop ? (topMenu.sections ?? []).flatMap((s) => s.items ?? []) : []);
35
+ </script>
36
+
37
+ <div class="lyt lyt-col" {...rest}>
38
+ {#if hasTop}
39
+ <TopBar
40
+ brand={topMenu.brand}
41
+ items={topItems}
42
+ active={topMenu.active}
43
+ {actions}
44
+ />
45
+ {/if}
46
+
47
+ {#if hasSide}
48
+ <div class="lyt-row lyt-fill" class:lyt-side-right={sideRight}>
49
+ <SideBar
50
+ brand={hasTop ? undefined : sideMenu.brand}
51
+ sections={sideMenu.sections}
52
+ active={sideMenu.active}
53
+ {footer}
54
+ />
55
+ <main class="lyt-main"><div class="lyt-inner">{@render children?.()}</div></main>
56
+ </div>
57
+ {:else}
58
+ <main class="lyt-main"><div class="lyt-inner">{@render children?.()}</div></main>
59
+ {/if}
60
+ </div>
@@ -0,0 +1,21 @@
1
+ export default BarLayout;
2
+ type BarLayout = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const BarLayout: import("svelte").Component<{
7
+ topMenu?: any;
8
+ sideMenu?: any;
9
+ sideRight?: boolean;
10
+ actions: any;
11
+ footer: any;
12
+ children: any;
13
+ } & Record<string, any>, {}, "topMenu" | "sideMenu">;
14
+ type $$ComponentProps = {
15
+ topMenu?: any;
16
+ sideMenu?: any;
17
+ sideRight?: boolean;
18
+ actions: any;
19
+ footer: any;
20
+ children: any;
21
+ } & Record<string, any>;
@@ -0,0 +1,23 @@
1
+ <script>
2
+ // BottomBarLayout — a fillable content area + a single bottom bar region.
3
+ // Bottom bar is a horizontal menu pinned to the bottom. Nestable.
4
+ import TopBar from './TopBar.svelte';
5
+
6
+ let {
7
+ menu = $bindable(undefined),
8
+ actions,
9
+ children,
10
+ ...rest
11
+ } = $props();
12
+
13
+ let items = $derived(menu ? (menu.sections ?? []).flatMap((s) => s.items ?? []) : []);
14
+ </script>
15
+
16
+ <div class="nl nl-col" {...rest}>
17
+ <div class="nl-fill nl-scroll">{@render children?.()}</div>
18
+ {#if menu}
19
+ <div class="nl-bottom">
20
+ <TopBar brand={menu.brand} {items} active={menu.active} {actions} />
21
+ </div>
22
+ {/if}
23
+ </div>
@@ -0,0 +1,15 @@
1
+ export default BottomBarLayout;
2
+ type BottomBarLayout = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const BottomBarLayout: import("svelte").Component<{
7
+ menu?: any;
8
+ actions: any;
9
+ children: any;
10
+ } & Record<string, any>, {}, "menu">;
11
+ type $$ComponentProps = {
12
+ menu?: any;
13
+ actions: any;
14
+ children: any;
15
+ } & Record<string, any>;
@@ -0,0 +1,81 @@
1
+ <script>
2
+ // DockLayout — a macOS-style floating dock: a centered, rounded bar of icons
3
+ // floating over the content near the bottom. Minimal brand/actions in the
4
+ // corners. One bindable `menu` drives the dock items.
5
+ //
6
+ // <DockLayout bind:menu>{content}</DockLayout>
7
+ //
8
+ // Menu contract (shared):
9
+ // { brand?, sections: [{ items: [{ id, label, icon?, href?, children? }] }], active? }
10
+ import ThemeToggle from '../components/ThemeToggle.svelte';
11
+
12
+ let {
13
+ menu = $bindable({ brand: {}, sections: [], active: undefined }),
14
+ actions, // snippet: top-right actions (defaults to ThemeToggle)
15
+ children,
16
+ ...rest
17
+ } = $props();
18
+
19
+ let brand = $derived(menu?.brand ?? {});
20
+ let items = $derived((menu?.sections ?? []).flatMap((s) => s.items ?? []));
21
+
22
+ // Flyout for dock items that have children (opens upward).
23
+ let openId = $state(null);
24
+ function toggle(id) { openId = openId === id ? null : id; }
25
+ $effect(() => {
26
+ if (openId == null) return;
27
+ function onDoc(e) { if (!e.target.closest?.('.dk-flywrap')) openId = null; }
28
+ document.addEventListener('pointerdown', onDoc);
29
+ return () => document.removeEventListener('pointerdown', onDoc);
30
+ });
31
+ </script>
32
+
33
+ <div class="dk" {...rest}>
34
+ {#if brand?.label}
35
+ <div class="dk-corner dk-corner-left">
36
+ {#if brand.icon}<span class="material-symbols-outlined dk-brand-icon">{brand.icon}</span>{/if}
37
+ <span class="dk-brand-name">{brand.label}</span>
38
+ </div>
39
+ {/if}
40
+ <div class="dk-corner dk-corner-right">
41
+ {#if actions}{@render actions()}{:else}<ThemeToggle />{/if}
42
+ </div>
43
+
44
+ <main class="dk-main">
45
+ <div class="dk-inner">{@render children?.()}</div>
46
+ </main>
47
+
48
+ <nav class="dk-dock" aria-label="Primary">
49
+ {#each items as item}
50
+ {#if item.children}
51
+ <div class="dk-flywrap">
52
+ {#if openId === item.id}
53
+ <div class="dk-flyout">
54
+ {#each item.children as child}
55
+ <a href={child.href} class="dk-flyout-item" onclick={() => (openId = null)}>
56
+ {#if child.icon}<span class="material-symbols-outlined">{child.icon}</span>{/if}
57
+ {child.label}
58
+ </a>
59
+ {/each}
60
+ </div>
61
+ {/if}
62
+ <button
63
+ class="dk-item"
64
+ class:active={item.id === menu.active}
65
+ title={item.label}
66
+ aria-label={item.label}
67
+ onclick={() => toggle(item.id)}
68
+ >
69
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
70
+ <span class="dk-label">{item.label}</span>
71
+ </button>
72
+ </div>
73
+ {:else}
74
+ <a href={item.href} class="dk-item" class:active={item.id === menu.active} title={item.label}>
75
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
76
+ <span class="dk-label">{item.label}</span>
77
+ </a>
78
+ {/if}
79
+ {/each}
80
+ </nav>
81
+ </div>
@@ -0,0 +1,15 @@
1
+ export default DockLayout;
2
+ type DockLayout = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const DockLayout: import("svelte").Component<{
7
+ menu?: Record<string, any>;
8
+ actions: any;
9
+ children: any;
10
+ } & Record<string, any>, {}, "menu">;
11
+ type $$ComponentProps = {
12
+ menu?: Record<string, any>;
13
+ actions: any;
14
+ children: any;
15
+ } & Record<string, any>;
@@ -0,0 +1,56 @@
1
+ <script>
2
+ // FloatingDockLayout — content with a centered floating dock of icons near
3
+ // the bottom (macOS-style). Nestable single-region layout. Items with
4
+ // children open an upward flyout.
5
+ let { menu = $bindable(undefined), children, ...rest } = $props();
6
+ let items = $derived(menu ? (menu.sections ?? []).flatMap((s) => s.items ?? []) : []);
7
+
8
+ let openId = $state(null);
9
+ const toggle = (id) => { openId = openId === id ? null : id; };
10
+ $effect(() => {
11
+ if (openId == null) return;
12
+ const onDoc = (e) => { if (!e.target.closest?.('.nldk-flywrap')) openId = null; };
13
+ document.addEventListener('pointerdown', onDoc);
14
+ return () => document.removeEventListener('pointerdown', onDoc);
15
+ });
16
+ </script>
17
+
18
+ <div class="nl nl-col nldk" {...rest}>
19
+ <div class="nl-fill nl-scroll nldk-content">{@render children?.()}</div>
20
+ {#if menu}
21
+ <div class="nldk-dockwrap">
22
+ <nav class="nldk-dock" aria-label="Primary">
23
+ {#each items as item}
24
+ {#if item.children?.length}
25
+ <div class="nldk-flywrap">
26
+ {#if openId === item.id}
27
+ <div class="nldk-flyout">
28
+ {#each item.children as child}
29
+ <a href={child.href} class="nldk-flyout-item" onclick={() => (openId = null)}>
30
+ {#if child.icon}<span class="material-symbols-outlined">{child.icon}</span>{/if}
31
+ {child.label}
32
+ </a>
33
+ {/each}
34
+ </div>
35
+ {/if}
36
+ <button
37
+ class="nldk-item"
38
+ class:active={item.id === menu.active || item.children.some((c) => c.id === menu.active)}
39
+ title={item.label} aria-label={item.label}
40
+ onclick={() => toggle(item.id)}
41
+ >
42
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
43
+ <span class="nldk-label">{item.label}</span>
44
+ </button>
45
+ </div>
46
+ {:else}
47
+ <a href={item.href} class="nldk-item" class:active={item.id === menu.active} title={item.label} aria-label={item.label}>
48
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
49
+ <span class="nldk-label">{item.label}</span>
50
+ </a>
51
+ {/if}
52
+ {/each}
53
+ </nav>
54
+ </div>
55
+ {/if}
56
+ </div>
@@ -0,0 +1,13 @@
1
+ export default FloatingDockLayout;
2
+ type FloatingDockLayout = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const FloatingDockLayout: import("svelte").Component<{
7
+ menu?: any;
8
+ children: any;
9
+ } & Record<string, any>, {}, "menu">;
10
+ type $$ComponentProps = {
11
+ menu?: any;
12
+ children: any;
13
+ } & Record<string, any>;
@@ -0,0 +1,80 @@
1
+ <script>
2
+ // FloatingLayout — a layout where the menus float as detached, rounded cards
3
+ // over the content, rather than attached bars.
4
+ //
5
+ // topMenu → a floating card along the top (horizontal)
6
+ // sideMenu → a floating card on the left (vertical)
7
+ //
8
+ // Each is its own bindable prop, using the shared menu contract:
9
+ // { brand?, sections: [{ label?, items: [{ id, label, icon?, href?, badge?, children? }] }], active? }
10
+ //
11
+ // <FloatingLayout bind:topMenu bind:sideMenu>{content}</FloatingShell>
12
+ import ThemeToggle from '../components/ThemeToggle.svelte';
13
+
14
+ let {
15
+ topMenu = $bindable(undefined),
16
+ sideMenu = $bindable(undefined),
17
+ actions, // snippet: top card right-side actions
18
+ footer, // snippet: side card footer
19
+ children,
20
+ ...rest
21
+ } = $props();
22
+
23
+ let hasTop = $derived(!!topMenu);
24
+ let hasSide = $derived(!!sideMenu);
25
+ let topItems = $derived(hasTop ? (topMenu.sections ?? []).flatMap((s) => s.items ?? []) : []);
26
+ </script>
27
+
28
+ <div class="fl-root" {...rest}>
29
+ {#if hasTop}
30
+ <div class="fl-topcard">
31
+ {#if topMenu.brand?.label}
32
+ <div class="fl-brand">
33
+ {#if topMenu.brand.icon}<span class="material-symbols-outlined fl-brand-icon">{topMenu.brand.icon}</span>{/if}
34
+ {topMenu.brand.label}
35
+ </div>
36
+ {/if}
37
+ <nav class="fl-topnav">
38
+ {#each topItems as item}
39
+ <a href={item.href} class="fl-toplink" class:active={item.id === topMenu.active}>
40
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
41
+ {item.label}
42
+ </a>
43
+ {/each}
44
+ </nav>
45
+ <div class="fl-actions">
46
+ {#if actions}{@render actions()}{:else}<ThemeToggle />{/if}
47
+ </div>
48
+ </div>
49
+ {/if}
50
+
51
+ <div class="fl-body">
52
+ {#if hasSide}
53
+ <aside class="fl-sidecard">
54
+ {#if sideMenu.brand?.label && !hasTop}
55
+ <div class="fl-brand fl-side-brand">
56
+ {#if sideMenu.brand.icon}<span class="material-symbols-outlined fl-brand-icon">{sideMenu.brand.icon}</span>{/if}
57
+ {sideMenu.brand.label}
58
+ </div>
59
+ {/if}
60
+ <nav class="fl-sidenav">
61
+ {#each sideMenu.sections as section}
62
+ {#if section.label}<div class="fl-side-label">{section.label}</div>{/if}
63
+ {#each section.items as item}
64
+ <a href={item.href} class="fl-sidelink" class:active={item.id === sideMenu.active}>
65
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
66
+ <span class="fl-sidelabel">{item.label}</span>
67
+ {#if item.badge != null}<span class="fl-badge">{item.badge}</span>{/if}
68
+ </a>
69
+ {/each}
70
+ {/each}
71
+ </nav>
72
+ {#if footer}<div class="fl-side-foot">{@render footer()}</div>{/if}
73
+ </aside>
74
+ {/if}
75
+
76
+ <main class="fl-content">
77
+ <div class="fl-inner">{@render children?.()}</div>
78
+ </main>
79
+ </div>
80
+ </div>
@@ -0,0 +1,19 @@
1
+ export default FloatingLayout;
2
+ type FloatingLayout = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const FloatingLayout: import("svelte").Component<{
7
+ topMenu?: any;
8
+ sideMenu?: any;
9
+ actions: any;
10
+ footer: any;
11
+ children: any;
12
+ } & Record<string, any>, {}, "topMenu" | "sideMenu">;
13
+ type $$ComponentProps = {
14
+ topMenu?: any;
15
+ sideMenu?: any;
16
+ actions: any;
17
+ footer: any;
18
+ children: any;
19
+ } & Record<string, any>;
@@ -0,0 +1,59 @@
1
+ <script>
2
+ // FloatingLeftLayout — a detached, rounded left menu card floating over the
3
+ // content. Nestable single-region layout. Supports 2-level submenus.
4
+ let { menu = $bindable(undefined), footer, children, ...rest } = $props();
5
+ let brand = $derived(menu?.brand ?? {});
6
+
7
+ let toggled = $state({});
8
+ const isChildActive = (item) => item.children?.some((c) => c.id === menu?.active);
9
+ const isOpen = (item) => toggled[item.id] ?? isChildActive(item);
10
+ const toggle = (item) => { toggled = { ...toggled, [item.id]: !isOpen(item) }; };
11
+ </script>
12
+
13
+ <div class="nl nl-row nlf-pad" {...rest}>
14
+ {#if menu}
15
+ <aside class="nlf-sidecard">
16
+ {#if brand.label}
17
+ <div class="nlf-brand nlf-side-brand">
18
+ {#if brand.icon}<span class="material-symbols-outlined nlf-brand-icon">{brand.icon}</span>{/if}
19
+ {brand.label}
20
+ </div>
21
+ {/if}
22
+ <nav class="nlf-sidenav">
23
+ {#each (menu.sections ?? []) as section}
24
+ {#if section.label}<div class="nlf-side-label">{section.label}</div>{/if}
25
+ {#each section.items as item}
26
+ {#if item.children?.length}
27
+ <button type="button" class="nlf-sidelink nlf-parent"
28
+ class:active={item.id === menu.active || isChildActive(item)}
29
+ aria-expanded={isOpen(item)} onclick={() => toggle(item)}>
30
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
31
+ <span class="nlf-sidelabel">{item.label}</span>
32
+ {#if item.badge != null}<span class="nlf-badge">{item.badge}</span>{/if}
33
+ <span class="material-symbols-outlined nlf-chevron" class:open={isOpen(item)}>chevron_right</span>
34
+ </button>
35
+ {#if isOpen(item)}
36
+ <div class="nlf-subnav">
37
+ {#each item.children as child}
38
+ <a href={child.href} class="nlf-sublink" class:active={child.id === menu.active}>
39
+ {#if child.icon}<span class="material-symbols-outlined">{child.icon}</span>{/if}
40
+ <span class="nlf-sidelabel">{child.label}</span>
41
+ </a>
42
+ {/each}
43
+ </div>
44
+ {/if}
45
+ {:else}
46
+ <a href={item.href} class="nlf-sidelink" class:active={item.id === menu.active}>
47
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
48
+ <span class="nlf-sidelabel">{item.label}</span>
49
+ {#if item.badge != null}<span class="nlf-badge">{item.badge}</span>{/if}
50
+ </a>
51
+ {/if}
52
+ {/each}
53
+ {/each}
54
+ </nav>
55
+ {#if footer}<div class="nlf-side-foot">{@render footer()}</div>{/if}
56
+ </aside>
57
+ {/if}
58
+ <div class="nl-fill nl-scroll nlf-content">{@render children?.()}</div>
59
+ </div>
@@ -0,0 +1,15 @@
1
+ export default FloatingLeftLayout;
2
+ type FloatingLeftLayout = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const FloatingLeftLayout: import("svelte").Component<{
7
+ menu?: any;
8
+ footer: any;
9
+ children: any;
10
+ } & Record<string, any>, {}, "menu">;
11
+ type $$ComponentProps = {
12
+ menu?: any;
13
+ footer: any;
14
+ children: any;
15
+ } & Record<string, any>;
@@ -0,0 +1,80 @@
1
+ <script>
2
+ // FloatingShell — a layout where the menus float as detached, rounded cards
3
+ // over the content, rather than attached bars.
4
+ //
5
+ // topMenu → a floating card along the top (horizontal)
6
+ // sideMenu → a floating card on the left (vertical)
7
+ //
8
+ // Each is its own bindable prop, using the shared menu contract:
9
+ // { brand?, sections: [{ label?, items: [{ id, label, icon?, href?, badge?, children? }] }], active? }
10
+ //
11
+ // <FloatingShell bind:topMenu bind:sideMenu>{content}</FloatingShell>
12
+ import ThemeToggle from '../components/ThemeToggle.svelte';
13
+
14
+ let {
15
+ topMenu = $bindable(undefined),
16
+ sideMenu = $bindable(undefined),
17
+ actions, // snippet: top card right-side actions
18
+ footer, // snippet: side card footer
19
+ children,
20
+ ...rest
21
+ } = $props();
22
+
23
+ let hasTop = $derived(!!topMenu);
24
+ let hasSide = $derived(!!sideMenu);
25
+ let topItems = $derived(hasTop ? (topMenu.sections ?? []).flatMap((s) => s.items ?? []) : []);
26
+ </script>
27
+
28
+ <div class="fl-root" {...rest}>
29
+ {#if hasTop}
30
+ <div class="fl-topcard">
31
+ {#if topMenu.brand?.label}
32
+ <div class="fl-brand">
33
+ {#if topMenu.brand.icon}<span class="material-symbols-outlined fl-brand-icon">{topMenu.brand.icon}</span>{/if}
34
+ {topMenu.brand.label}
35
+ </div>
36
+ {/if}
37
+ <nav class="fl-topnav">
38
+ {#each topItems as item}
39
+ <a href={item.href} class="fl-toplink" class:active={item.id === topMenu.active}>
40
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
41
+ {item.label}
42
+ </a>
43
+ {/each}
44
+ </nav>
45
+ <div class="fl-actions">
46
+ {#if actions}{@render actions()}{:else}<ThemeToggle />{/if}
47
+ </div>
48
+ </div>
49
+ {/if}
50
+
51
+ <div class="fl-body">
52
+ {#if hasSide}
53
+ <aside class="fl-sidecard">
54
+ {#if sideMenu.brand?.label && !hasTop}
55
+ <div class="fl-brand fl-side-brand">
56
+ {#if sideMenu.brand.icon}<span class="material-symbols-outlined fl-brand-icon">{sideMenu.brand.icon}</span>{/if}
57
+ {sideMenu.brand.label}
58
+ </div>
59
+ {/if}
60
+ <nav class="fl-sidenav">
61
+ {#each sideMenu.sections as section}
62
+ {#if section.label}<div class="fl-side-label">{section.label}</div>{/if}
63
+ {#each section.items as item}
64
+ <a href={item.href} class="fl-sidelink" class:active={item.id === sideMenu.active}>
65
+ {#if item.icon}<span class="material-symbols-outlined">{item.icon}</span>{/if}
66
+ <span class="fl-sidelabel">{item.label}</span>
67
+ {#if item.badge != null}<span class="fl-badge">{item.badge}</span>{/if}
68
+ </a>
69
+ {/each}
70
+ {/each}
71
+ </nav>
72
+ {#if footer}<div class="fl-side-foot">{@render footer()}</div>{/if}
73
+ </aside>
74
+ {/if}
75
+
76
+ <main class="fl-content">
77
+ <div class="fl-inner">{@render children?.()}</div>
78
+ </main>
79
+ </div>
80
+ </div>
@@ -0,0 +1,19 @@
1
+ export default FloatingShell;
2
+ type FloatingShell = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const FloatingShell: import("svelte").Component<{
7
+ topMenu?: any;
8
+ sideMenu?: any;
9
+ actions: any;
10
+ footer: any;
11
+ children: any;
12
+ } & Record<string, any>, {}, "topMenu" | "sideMenu">;
13
+ type $$ComponentProps = {
14
+ topMenu?: any;
15
+ sideMenu?: any;
16
+ actions: any;
17
+ footer: any;
18
+ children: any;
19
+ } & Record<string, any>;