@lobb-js/studio 0.33.0 → 0.34.0
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.
- package/dist/applyUITheme.d.ts +2 -0
- package/dist/{applyStudioTheme.js → applyUITheme.js} +4 -4
- package/dist/components/LlmButton.svelte +4 -2
- package/dist/components/LlmButton.svelte.d.ts +1 -0
- package/dist/components/Studio.svelte +15 -7
- package/dist/components/createManyButton.svelte +2 -2
- package/dist/components/dataTable/dataTable.svelte +1 -1
- package/dist/components/dataTable/dataTableTabs.svelte +1 -1
- package/dist/components/dataTable/filter.svelte +3 -2
- package/dist/components/dataTable/filterButton.svelte +1 -1
- package/dist/components/dataTable/footer.svelte +1 -1
- package/dist/components/dataTable/header.svelte +14 -21
- package/dist/components/dataTable/listViewChildren.svelte +1 -1
- package/dist/components/dataTable/sort.svelte +1 -1
- package/dist/components/dataTable/sortButton.svelte +1 -1
- package/dist/components/dataTable/table.svelte +4 -4
- package/dist/components/dataTablePopup/dataTablePopup.svelte +1 -1
- package/dist/components/detailView/create/createDetailView.svelte +2 -2
- package/dist/components/detailView/create/createDetailViewButton.svelte +2 -0
- package/dist/components/detailView/create/createDetailViewButton.svelte.d.ts +1 -0
- package/dist/components/detailView/create/createDetailViewChildren.svelte +3 -3
- package/dist/components/detailView/create/createManyView.svelte +2 -2
- package/dist/components/detailView/update/updateDetailView.svelte +2 -2
- package/dist/components/detailView/update/updateDetailViewButton.svelte +2 -0
- package/dist/components/detailView/update/updateDetailViewButton.svelte.d.ts +1 -0
- package/dist/components/detailView/update/updateDetailViewChildren.svelte +3 -3
- package/dist/components/drawer.svelte +2 -2
- package/dist/components/horizontalNav.svelte +85 -0
- package/dist/components/horizontalNav.svelte.d.ts +3 -0
- package/dist/components/importButton.svelte +6 -6
- package/dist/components/mainNav.svelte +15 -0
- package/dist/components/mainNav.svelte.d.ts +6 -0
- package/dist/components/mainNavShared.d.ts +10 -0
- package/dist/components/mainNavShared.js +62 -0
- package/dist/components/rangeCalendarButton.svelte +1 -2
- package/dist/components/routes/home.svelte +1 -1
- package/dist/components/routes/workflows/workflows.svelte +1 -1
- package/dist/components/setServerPage.svelte +1 -1
- package/dist/components/sidebar/sidebar.svelte +2 -2
- package/dist/components/sidebar/sidebarElements.svelte +3 -3
- package/dist/components/singletone.svelte +2 -2
- package/dist/components/ui/skeleton/skeleton.svelte +1 -1
- package/dist/components/ui/tooltip/tooltip-content.svelte +1 -1
- package/dist/components/verticalNav.svelte +174 -0
- package/dist/components/verticalNav.svelte.d.ts +3 -0
- package/dist/components/workflowEditor.svelte +2 -2
- package/dist/store.types.d.ts +4 -3
- package/package.json +2 -2
- package/src/app.css +52 -75
- package/src/lib/{applyStudioTheme.ts → applyUITheme.ts} +5 -5
- package/src/lib/components/LlmButton.svelte +4 -2
- package/src/lib/components/Studio.svelte +15 -7
- package/src/lib/components/createManyButton.svelte +2 -2
- package/src/lib/components/dataTable/dataTable.svelte +1 -1
- package/src/lib/components/dataTable/dataTableTabs.svelte +1 -1
- package/src/lib/components/dataTable/filter.svelte +3 -2
- package/src/lib/components/dataTable/filterButton.svelte +1 -1
- package/src/lib/components/dataTable/footer.svelte +1 -1
- package/src/lib/components/dataTable/header.svelte +14 -21
- package/src/lib/components/dataTable/listViewChildren.svelte +1 -1
- package/src/lib/components/dataTable/sort.svelte +1 -1
- package/src/lib/components/dataTable/sortButton.svelte +1 -1
- package/src/lib/components/dataTable/table.svelte +4 -4
- package/src/lib/components/dataTablePopup/dataTablePopup.svelte +1 -1
- package/src/lib/components/detailView/create/createDetailView.svelte +2 -2
- package/src/lib/components/detailView/create/createDetailViewButton.svelte +2 -0
- package/src/lib/components/detailView/create/createDetailViewChildren.svelte +3 -3
- package/src/lib/components/detailView/create/createManyView.svelte +2 -2
- package/src/lib/components/detailView/update/updateDetailView.svelte +2 -2
- package/src/lib/components/detailView/update/updateDetailViewButton.svelte +2 -0
- package/src/lib/components/detailView/update/updateDetailViewChildren.svelte +3 -3
- package/src/lib/components/drawer.svelte +2 -2
- package/src/lib/components/horizontalNav.svelte +85 -0
- package/src/lib/components/importButton.svelte +6 -6
- package/src/lib/components/mainNav.svelte +15 -0
- package/src/lib/components/mainNavShared.ts +67 -0
- package/src/lib/components/rangeCalendarButton.svelte +1 -2
- package/src/lib/components/routes/home.svelte +1 -1
- package/src/lib/components/routes/workflows/workflows.svelte +1 -1
- package/src/lib/components/setServerPage.svelte +1 -1
- package/src/lib/components/sidebar/sidebar.svelte +2 -2
- package/src/lib/components/sidebar/sidebarElements.svelte +3 -3
- package/src/lib/components/singletone.svelte +2 -2
- package/src/lib/components/ui/skeleton/skeleton.svelte +1 -1
- package/src/lib/components/ui/tooltip/tooltip-content.svelte +1 -1
- package/src/lib/components/verticalNav.svelte +174 -0
- package/src/lib/components/workflowEditor.svelte +2 -2
- package/src/lib/store.types.ts +2 -2
- package/dist/applyStudioTheme.d.ts +0 -2
- package/dist/components/miniSidebar.svelte +0 -300
- package/dist/components/miniSidebar.svelte.d.ts +0 -5
- package/src/lib/components/miniSidebar.svelte +0 -300
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { UITheme } from "./store.types";
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// UI theme injection. Writes the configured CSS-variable overrides into
|
|
4
|
+
// a single <style> tag — light overrides under `:root`, dark under
|
|
5
5
|
// `.dark` — so each mode picks up its own variant. Idempotent: re-runs
|
|
6
6
|
// replace the previous block.
|
|
7
7
|
|
|
8
|
-
const STYLE_ID = "lobb-
|
|
8
|
+
const STYLE_ID = "lobb-ui-theme";
|
|
9
9
|
|
|
10
10
|
function buildDeclarations(vars: Record<string, string> | undefined): string {
|
|
11
11
|
if (!vars) return "";
|
|
@@ -17,7 +17,7 @@ function buildDeclarations(vars: Record<string, string> | undefined): string {
|
|
|
17
17
|
return out.join(" ");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function
|
|
20
|
+
export function applyUITheme(theme: UITheme | undefined): void {
|
|
21
21
|
if (typeof document === "undefined") return;
|
|
22
22
|
|
|
23
23
|
document.getElementById(STYLE_ID)?.remove();
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
format?: any;
|
|
17
17
|
messages?: any[];
|
|
18
18
|
variant?: ButtonProps["variant"];
|
|
19
|
+
size?: ButtonProps["size"];
|
|
19
20
|
class?: ButtonProps["class"];
|
|
20
21
|
Icon?: ButtonProps["Icon"];
|
|
21
22
|
children?: ButtonProps["children"];
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
description,
|
|
29
30
|
placeholder = "write prompt description",
|
|
30
31
|
variant = "default",
|
|
32
|
+
size,
|
|
31
33
|
Icon = Brain,
|
|
32
34
|
onApiResponseComplete,
|
|
33
35
|
messages,
|
|
@@ -98,7 +100,7 @@
|
|
|
98
100
|
{#if ctx.meta.extensions.llm && ctx.meta.collections.llm_chat}
|
|
99
101
|
<Popover.Root bind:open={popoverOpen}>
|
|
100
102
|
<Popover.Trigger>
|
|
101
|
-
<Button {variant} class={props.class}>
|
|
103
|
+
<Button {variant} {size} class={props.class}>
|
|
102
104
|
{#if loading}
|
|
103
105
|
<LoaderIcon class="animate-spin" />
|
|
104
106
|
{:else}
|
|
@@ -129,7 +131,7 @@
|
|
|
129
131
|
<Button
|
|
130
132
|
type="submit"
|
|
131
133
|
Icon={Send}
|
|
132
|
-
|
|
134
|
+
size="sm">Submit</Button
|
|
133
135
|
>
|
|
134
136
|
</form>
|
|
135
137
|
</Popover.Content>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { createLobb } from "../store.svelte";
|
|
6
6
|
import { setStudioContext } from "../context";
|
|
7
7
|
import { LoaderCircle, ServerOff } from "lucide-svelte";
|
|
8
|
-
import
|
|
8
|
+
import MainNav from "./mainNav.svelte";
|
|
9
9
|
import * as Tooltip from "./ui/tooltip";
|
|
10
10
|
import { page } from "$app/state";
|
|
11
11
|
import { afterNavigate } from "$app/navigation";
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
} from "../extensions/extensionUtils";
|
|
18
18
|
import extensionMap from 'virtual:lobb-studio-extensions';
|
|
19
19
|
import { mediaQueries } from "../utils";
|
|
20
|
-
import {
|
|
20
|
+
import { applyUITheme } from "../applyUITheme";
|
|
21
21
|
import Home from "./routes/home.svelte";
|
|
22
22
|
import DataModel from "./routes/data_model/dataModel.svelte";
|
|
23
23
|
import Collections from "./routes/collections/collections.svelte";
|
|
@@ -44,6 +44,12 @@
|
|
|
44
44
|
|
|
45
45
|
let status: "loading" | "error" | "ready" = $state("loading");
|
|
46
46
|
let isSmallScreen = $derived(!mediaQueries.sm.current);
|
|
47
|
+
// Horizontal nav forces the layout to row mode (top bar instead of
|
|
48
|
+
// left rail). Falls back to vertical when small-screen mode is on,
|
|
49
|
+
// since there's no useful horizontal layout below 640px.
|
|
50
|
+
const horizontalNav = $derived(
|
|
51
|
+
(ctx.meta as any)?.ui?.horizontalNav === true && !isSmallScreen,
|
|
52
|
+
);
|
|
47
53
|
|
|
48
54
|
onMount(async () => {
|
|
49
55
|
// Remove the static loading screen defined in app.html — it shows instantly
|
|
@@ -51,7 +57,7 @@
|
|
|
51
57
|
document.getElementById("app-loading")?.remove();
|
|
52
58
|
try {
|
|
53
59
|
ctx.meta = await lobb.getMeta();
|
|
54
|
-
|
|
60
|
+
applyUITheme(ctx.meta.ui?.theme);
|
|
55
61
|
ctx.extensions = await loadExtensions(lobb, ctx, extensionMap);
|
|
56
62
|
await executeExtensionsOnStartup(lobb, ctx);
|
|
57
63
|
loadExtensionWorkflows(ctx as any);
|
|
@@ -104,11 +110,13 @@
|
|
|
104
110
|
{:else}
|
|
105
111
|
<Tooltip.Provider delayDuration={0} disableHoverableContent={true}>
|
|
106
112
|
<main
|
|
107
|
-
class="bg-muted h-screen w-screen"
|
|
108
|
-
style=
|
|
113
|
+
class="bg-muted h-screen w-screen overflow-hidden"
|
|
114
|
+
style={horizontalNav
|
|
115
|
+
? "display: grid; grid-template-rows: 3rem 1fr;"
|
|
116
|
+
: `display: grid; grid-template-columns: ${isSmallScreen ? '1fr' : '3.5rem 1fr'};`}
|
|
109
117
|
>
|
|
110
|
-
<
|
|
111
|
-
<div class="min-h-0 h-
|
|
118
|
+
<MainNav orientation={horizontalNav ? "horizontal" : "vertical"} />
|
|
119
|
+
<div class="min-h-0 h-full overflow-hidden">
|
|
112
120
|
{#if page.url.pathname.replace(/\/$/, "") === "/studio"}
|
|
113
121
|
<Home />
|
|
114
122
|
{:else if page.url.pathname.startsWith("/studio/collections")}
|
|
@@ -90,14 +90,14 @@
|
|
|
90
90
|
<Button
|
|
91
91
|
variant="outline"
|
|
92
92
|
onclick={() => hideDrawer()}
|
|
93
|
-
|
|
93
|
+
size="sm"
|
|
94
94
|
Icon={X}
|
|
95
95
|
>
|
|
96
96
|
Cancel
|
|
97
97
|
</Button>
|
|
98
98
|
<Button
|
|
99
99
|
variant="default"
|
|
100
|
-
|
|
100
|
+
size="sm"
|
|
101
101
|
Icon={Plus}
|
|
102
102
|
onclick={handleCreateMany}
|
|
103
103
|
>
|
|
@@ -279,7 +279,7 @@
|
|
|
279
279
|
|
|
280
280
|
<div
|
|
281
281
|
bind:clientWidth={dataTableContainerWidth}
|
|
282
|
-
class="flex flex-col overflow-auto h-full w-full"
|
|
282
|
+
class="flex flex-col overflow-auto h-full w-full bg-card"
|
|
283
283
|
>
|
|
284
284
|
{#snippet rowActionsSnippet(entry: Record<string, any>)}
|
|
285
285
|
<ExtensionsComponents
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
</script>
|
|
45
45
|
|
|
46
46
|
{#if tabs}
|
|
47
|
-
<div class="flex items-center gap-1 px-3 py-1.5 border-b shrink-0 bg-
|
|
47
|
+
<div class="flex items-center gap-1 px-3 py-1.5 border-b shrink-0 bg-card">
|
|
48
48
|
{#each tabs as tab}
|
|
49
49
|
{@const key = tab.id ?? tab.label}
|
|
50
50
|
{@const isActive = activeTab ? activeTab === key : (tab.default ?? tabs[0] === tab)}
|
|
@@ -71,7 +71,8 @@
|
|
|
71
71
|
<Popover.Trigger
|
|
72
72
|
class={buttonVariants({
|
|
73
73
|
variant: "ghost",
|
|
74
|
-
|
|
74
|
+
size: "sm",
|
|
75
|
+
class: "text-muted-foreground",
|
|
75
76
|
})}
|
|
76
77
|
>
|
|
77
78
|
<Plus />
|
|
@@ -184,7 +185,7 @@
|
|
|
184
185
|
<Popover.Trigger
|
|
185
186
|
class={buttonVariants({
|
|
186
187
|
variant: "ghost",
|
|
187
|
-
|
|
188
|
+
size: "sm",
|
|
188
189
|
})}
|
|
189
190
|
>
|
|
190
191
|
<Plus />
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import type { ParentContext } from "./dataTable.svelte";
|
|
5
5
|
import CanAccess from "../canAccess.svelte";
|
|
6
6
|
import { Download, ListRestart, Plus, Trash, Link } from "lucide-svelte";
|
|
7
|
-
import * as Tooltip from "../ui/tooltip";
|
|
8
7
|
import LlmButton from "../LlmButton.svelte";
|
|
9
8
|
import FilterButton from "./filterButton.svelte";
|
|
10
9
|
import SortButton from "./sortButton.svelte";
|
|
@@ -105,7 +104,7 @@
|
|
|
105
104
|
</script>
|
|
106
105
|
|
|
107
106
|
<div
|
|
108
|
-
class="flex justify-between items-center gap-2 p-2 border-b bg-
|
|
107
|
+
class="flex justify-between items-center gap-2 p-2 border-b bg-card h-12"
|
|
109
108
|
bind:clientWidth={headerWidth}
|
|
110
109
|
>
|
|
111
110
|
<div class="flex items-center gap-1">
|
|
@@ -115,7 +114,7 @@
|
|
|
115
114
|
Icon={Trash}
|
|
116
115
|
onclick={handleDeleteButton}
|
|
117
116
|
variant="outline"
|
|
118
|
-
|
|
117
|
+
size="sm"
|
|
119
118
|
>
|
|
120
119
|
Delete {selectedRecords.length}
|
|
121
120
|
{selectedRecords.length > 1 ? "records" : "record"}
|
|
@@ -135,7 +134,7 @@
|
|
|
135
134
|
variant="outline"
|
|
136
135
|
title="Filter table with AI"
|
|
137
136
|
description="Tell the AI how do you want to filter the table"
|
|
138
|
-
|
|
137
|
+
size="sm"
|
|
139
138
|
format={{
|
|
140
139
|
type: "json_object",
|
|
141
140
|
}}
|
|
@@ -161,7 +160,8 @@
|
|
|
161
160
|
<div>
|
|
162
161
|
<Button
|
|
163
162
|
variant="ghost"
|
|
164
|
-
|
|
163
|
+
size="sm"
|
|
164
|
+
class="text-muted-foreground"
|
|
165
165
|
Icon={ListRestart}
|
|
166
166
|
onclick={() => (params = { ...params })}
|
|
167
167
|
>
|
|
@@ -169,20 +169,13 @@
|
|
|
169
169
|
</Button>
|
|
170
170
|
{#if showImport}
|
|
171
171
|
<CanAccess collection={collectionName} action="create">
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
Icon={Download}
|
|
180
|
-
onSuccessfullSave={() => (params = { ...params })}
|
|
181
|
-
/>
|
|
182
|
-
</Tooltip.Trigger>
|
|
183
|
-
<Tooltip.Content>Import</Tooltip.Content>
|
|
184
|
-
</Tooltip.Root>
|
|
185
|
-
</Tooltip.Provider>
|
|
172
|
+
<ImportButton
|
|
173
|
+
{collectionName}
|
|
174
|
+
variant="outline"
|
|
175
|
+
size="sm"
|
|
176
|
+
Icon={Download}
|
|
177
|
+
onSuccessfullSave={() => (params = { ...params })}
|
|
178
|
+
/>
|
|
186
179
|
</CanAccess>
|
|
187
180
|
{/if}
|
|
188
181
|
<ExtensionsComponents
|
|
@@ -195,7 +188,7 @@
|
|
|
195
188
|
<SelectRecord
|
|
196
189
|
{collectionName}
|
|
197
190
|
variant="outline"
|
|
198
|
-
|
|
191
|
+
size="sm"
|
|
199
192
|
Icon={Link}
|
|
200
193
|
onSelect={handleLink}
|
|
201
194
|
>
|
|
@@ -206,7 +199,7 @@
|
|
|
206
199
|
<CreateDetailViewButton
|
|
207
200
|
{collectionName}
|
|
208
201
|
variant="default"
|
|
209
|
-
|
|
202
|
+
size="sm"
|
|
210
203
|
Icon={Plus}
|
|
211
204
|
onChanges={onCreate ? handleCreate : undefined}
|
|
212
205
|
onSuccessfullSave={onCreate ? undefined : handleCreate}
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
<CreateDetailViewButton
|
|
62
62
|
collectionName={child.collection}
|
|
63
63
|
variant="ghost"
|
|
64
|
-
|
|
64
|
+
size="sm"
|
|
65
65
|
Icon={Plus}
|
|
66
66
|
values={{ [child.field]: recordId }}
|
|
67
67
|
onSuccessfullSave={async () => { refreshDataTable = !refreshDataTable; }}
|
|
@@ -249,7 +249,7 @@
|
|
|
249
249
|
class="
|
|
250
250
|
sticky left-0
|
|
251
251
|
flex items-center p-2.5 text-xs h-10
|
|
252
|
-
bg-
|
|
252
|
+
bg-card
|
|
253
253
|
border-r gap-2
|
|
254
254
|
"
|
|
255
255
|
>
|
|
@@ -295,8 +295,8 @@
|
|
|
295
295
|
}}
|
|
296
296
|
class="
|
|
297
297
|
flex items-center p-2.5 text-xs h-10 text-nowrap overflow-clip
|
|
298
|
-
{select ? 'cursor-pointer' : ''}
|
|
299
|
-
bg-
|
|
298
|
+
{select ? 'cursor-pointer hover:bg-accent' : ''}
|
|
299
|
+
bg-card
|
|
300
300
|
{lastColumn && !showLastColumnBorder ? '' : 'border-r'}
|
|
301
301
|
"
|
|
302
302
|
>
|
|
@@ -313,7 +313,7 @@
|
|
|
313
313
|
sticky right-0 z-10
|
|
314
314
|
flex items-center p-2.5 text-xs h-10
|
|
315
315
|
border-l gap-2
|
|
316
|
-
bg-
|
|
316
|
+
bg-card
|
|
317
317
|
"
|
|
318
318
|
>
|
|
319
319
|
{@render rowActions?.(entry, index)}
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
|
|
60
60
|
<div
|
|
61
61
|
transition:scale={{ duration: 200, easing: cubicOut, start: 0.95 }}
|
|
62
|
-
class="fixed left-1/2 top-1/2 z-40 flex h-[85vh] w-[95vw] max-w-7xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border bg-
|
|
62
|
+
class="fixed left-1/2 top-1/2 z-40 flex h-[85vh] w-[95vw] max-w-7xl -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-lg border bg-card shadow-2xl"
|
|
63
63
|
>
|
|
64
64
|
<div class="flex h-12 shrink-0 items-center justify-between gap-4 border-b px-4">
|
|
65
65
|
<div class="text-sm font-medium">{title ?? collectionName}</div>
|
|
@@ -143,14 +143,14 @@
|
|
|
143
143
|
<Button
|
|
144
144
|
variant="outline"
|
|
145
145
|
onclick={handleCancel}
|
|
146
|
-
|
|
146
|
+
size="sm"
|
|
147
147
|
Icon={X}
|
|
148
148
|
>
|
|
149
149
|
Cancel
|
|
150
150
|
</Button>
|
|
151
151
|
<Button
|
|
152
152
|
variant="default"
|
|
153
|
-
|
|
153
|
+
size="sm"
|
|
154
154
|
Icon={submitButton?.icon ? submitButton.icon : Plus}
|
|
155
155
|
onclick={handleSave}
|
|
156
156
|
>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
interface LocalProp extends CreateDetailViewProp {
|
|
8
8
|
variant?: ButtonProps["variant"];
|
|
9
|
+
size?: ButtonProps["size"];
|
|
9
10
|
class?: ButtonProps["class"];
|
|
10
11
|
Icon?: ButtonProps["Icon"];
|
|
11
12
|
children?: ButtonProps["children"];
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
|
|
18
19
|
<Button
|
|
19
20
|
variant={props.variant}
|
|
21
|
+
size={props.size}
|
|
20
22
|
class={props.class}
|
|
21
23
|
Icon={props.Icon}
|
|
22
24
|
onclick={() => { open = true; }}
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
<SelectRecord
|
|
68
68
|
collectionName={child.collection}
|
|
69
69
|
variant="outline"
|
|
70
|
-
|
|
70
|
+
size="sm"
|
|
71
71
|
Icon={Link}
|
|
72
72
|
onSelect={(r) => handleEmptyLink(child.collection, r)}
|
|
73
73
|
>
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
<CreateDetailViewButton
|
|
77
77
|
collectionName={child.collection}
|
|
78
78
|
variant="default"
|
|
79
|
-
|
|
79
|
+
size="sm"
|
|
80
80
|
Icon={Plus}
|
|
81
81
|
onChanges={(c) => handleEmptyCreate(child.collection, c)}
|
|
82
82
|
>
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
</div>
|
|
87
87
|
</div>
|
|
88
88
|
{:else}
|
|
89
|
-
<div class="rounded-lg border bg-
|
|
89
|
+
<div class="rounded-lg border bg-card overflow-hidden flex flex-col max-h-96">
|
|
90
90
|
<DataTable
|
|
91
91
|
collectionName={child.collection}
|
|
92
92
|
searchParams={{ children_of: collectionName, parent_id: -1 }}
|
|
@@ -137,12 +137,12 @@
|
|
|
137
137
|
text="Select existing"
|
|
138
138
|
onSelect={onRecordSelect}
|
|
139
139
|
filter={selectRecordFilter}
|
|
140
|
-
|
|
140
|
+
size="sm"
|
|
141
141
|
variant="ghost"
|
|
142
142
|
/>
|
|
143
143
|
<CreateDetailViewButton
|
|
144
144
|
variant="ghost"
|
|
145
|
-
|
|
145
|
+
size="sm"
|
|
146
146
|
Icon={Plus}
|
|
147
147
|
{collectionName}
|
|
148
148
|
onChanges={(updated) => { addChanges = updated; }}
|
|
@@ -180,14 +180,14 @@
|
|
|
180
180
|
<Button
|
|
181
181
|
variant="outline"
|
|
182
182
|
onclick={handleCancel}
|
|
183
|
-
|
|
183
|
+
size="sm"
|
|
184
184
|
Icon={X}
|
|
185
185
|
>
|
|
186
186
|
Cancel
|
|
187
187
|
</Button>
|
|
188
188
|
<Button
|
|
189
189
|
variant="default"
|
|
190
|
-
|
|
190
|
+
size="sm"
|
|
191
191
|
Icon={submitButton?.icon ? submitButton.icon : Pencil}
|
|
192
192
|
onclick={handleSave}
|
|
193
193
|
disabled={!hasChanges}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
interface LocalProp extends UpdateDetailViewProp {
|
|
9
9
|
variant?: ButtonProps["variant"];
|
|
10
|
+
size?: ButtonProps["size"];
|
|
10
11
|
class?: ButtonProps["class"];
|
|
11
12
|
Icon?: ButtonProps["Icon"];
|
|
12
13
|
children?: ButtonProps["children"];
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
|
|
34
35
|
<Button
|
|
35
36
|
variant={props.variant}
|
|
37
|
+
size={props.size}
|
|
36
38
|
class={props.class}
|
|
37
39
|
Icon={props.Icon}
|
|
38
40
|
onclick={openView}
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
<SelectRecord
|
|
76
76
|
collectionName={child.collection}
|
|
77
77
|
variant="outline"
|
|
78
|
-
|
|
78
|
+
size="sm"
|
|
79
79
|
Icon={Link}
|
|
80
80
|
onSelect={(r) => handleEmptyLink(child.collection, r)}
|
|
81
81
|
>
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
<CreateDetailViewButton
|
|
85
85
|
collectionName={child.collection}
|
|
86
86
|
variant="default"
|
|
87
|
-
|
|
87
|
+
size="sm"
|
|
88
88
|
Icon={Plus}
|
|
89
89
|
onChanges={(c) => handleEmptyCreate(child.collection, c)}
|
|
90
90
|
>
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
</div>
|
|
95
95
|
</div>
|
|
96
96
|
{:else}
|
|
97
|
-
<div class="rounded-lg border bg-
|
|
97
|
+
<div class="rounded-lg border bg-card overflow-hidden flex flex-col max-h-96">
|
|
98
98
|
<DataTable
|
|
99
99
|
collectionName={child.collection}
|
|
100
100
|
searchParams={{ children_of: collectionName, parent_id: entry.id }}
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
<div
|
|
39
39
|
transition:slide={{ axis: position === "bottom" ? "y" : "x" }}
|
|
40
40
|
class={position === "bottom"
|
|
41
|
-
? "fixed bottom-0 left-0 z-40 flex h-[60vh] w-full flex-col border-t bg-
|
|
42
|
-
: "fixed right-0 top-0 z-40 flex h-full w-full flex-col border-l bg-
|
|
41
|
+
? "fixed bottom-0 left-0 z-40 flex h-[60vh] w-full flex-col border-t bg-card"
|
|
42
|
+
: "fixed right-0 top-0 z-40 flex h-full w-full flex-col border-l bg-card"}
|
|
43
43
|
style={position === "side" ? `max-width: ${calculateDrawerWidth()}px;` : ""}
|
|
44
44
|
>
|
|
45
45
|
{@render children?.()}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
import { page } from "$app/state";
|
|
4
|
+
import Button from "./ui/button/button.svelte";
|
|
5
|
+
import Separator from "./ui/separator/separator.svelte";
|
|
6
|
+
import * as Popover from "./ui/popover";
|
|
7
|
+
import { getStudioContext } from "../context";
|
|
8
|
+
import { buildNavSections, isItemActive, type NavItem } from "./mainNavShared";
|
|
9
|
+
|
|
10
|
+
const { lobb, ctx } = getStudioContext();
|
|
11
|
+
|
|
12
|
+
let sections: NavItem[][] = $state([[], [], []]);
|
|
13
|
+
onMount(async () => {
|
|
14
|
+
sections = await buildNavSections(lobb, ctx);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const currentPath = $derived(page.url.pathname.replace(/\/$/, "") || "/");
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
{#snippet section(section: NavItem[])}
|
|
21
|
+
<div class="flex flex-row items-center gap-1">
|
|
22
|
+
{#each section as item}
|
|
23
|
+
{@const active = isItemActive(currentPath, item)}
|
|
24
|
+
{#if !item.navs}
|
|
25
|
+
<Button
|
|
26
|
+
onclick={() => { if (item.onclick) item.onclick(); }}
|
|
27
|
+
href={item.href}
|
|
28
|
+
class="h-8 px-2.5 text-xs font-normal {active
|
|
29
|
+
? 'bg-accent text-foreground'
|
|
30
|
+
: 'text-foreground/70 hover:bg-accent/50 hover:text-foreground'}"
|
|
31
|
+
variant="ghost"
|
|
32
|
+
Icon={item.icon}
|
|
33
|
+
>
|
|
34
|
+
{item.label}
|
|
35
|
+
</Button>
|
|
36
|
+
{:else}
|
|
37
|
+
<Popover.Root>
|
|
38
|
+
<Popover.Trigger>
|
|
39
|
+
<Button
|
|
40
|
+
class="h-8 px-2.5 text-xs font-normal {active
|
|
41
|
+
? 'bg-accent text-accent-foreground'
|
|
42
|
+
: 'text-muted-foreground'}"
|
|
43
|
+
variant="ghost"
|
|
44
|
+
Icon={item.icon}
|
|
45
|
+
>
|
|
46
|
+
{item.label}
|
|
47
|
+
</Button>
|
|
48
|
+
</Popover.Trigger>
|
|
49
|
+
<Popover.Content sideOffset={6} side="bottom" align="start" class="w-60 p-0">
|
|
50
|
+
<div class="py-1">
|
|
51
|
+
{#each item.navs as childItem}
|
|
52
|
+
{@const childActive = isItemActive(currentPath, childItem)}
|
|
53
|
+
<div class="px-1 text-xs text-muted-foreground">
|
|
54
|
+
<Button
|
|
55
|
+
variant="ghost"
|
|
56
|
+
class="flex h-7 w-full justify-start p-2 text-xs font-normal {childActive
|
|
57
|
+
? 'bg-accent text-accent-foreground'
|
|
58
|
+
: 'text-muted-foreground'}"
|
|
59
|
+
Icon={childItem.icon}
|
|
60
|
+
onclick={() => { if (childItem.onclick) childItem.onclick(); }}
|
|
61
|
+
href={childItem.href}
|
|
62
|
+
>
|
|
63
|
+
{childItem.label}
|
|
64
|
+
</Button>
|
|
65
|
+
</div>
|
|
66
|
+
{/each}
|
|
67
|
+
</div>
|
|
68
|
+
</Popover.Content>
|
|
69
|
+
</Popover.Root>
|
|
70
|
+
{/if}
|
|
71
|
+
{/each}
|
|
72
|
+
</div>
|
|
73
|
+
{/snippet}
|
|
74
|
+
|
|
75
|
+
<div class="relative border-b border-border bg-card text-foreground h-12 w-full px-3 flex items-center justify-between gap-2">
|
|
76
|
+
<div class="flex flex-row items-center gap-2">
|
|
77
|
+
{@render section(sections[0])}
|
|
78
|
+
{#if sections[1].length > 0}
|
|
79
|
+
<Separator orientation="vertical" class="h-6 bg-border" />
|
|
80
|
+
{@render section(sections[1])}
|
|
81
|
+
{/if}
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
{@render section(sections[2])}
|
|
85
|
+
</div>
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
}
|
|
171
171
|
</script>
|
|
172
172
|
|
|
173
|
-
<Button variant={rest.variant} class={rest.class} onclick={showDrawer}>
|
|
173
|
+
<Button variant={rest.variant} size={rest.size} class={rest.class} onclick={showDrawer}>
|
|
174
174
|
<ExtensionsComponents
|
|
175
175
|
name="collections.import.button.content"
|
|
176
176
|
utils={getExtensionUtils(lobb, ctx)}
|
|
@@ -264,11 +264,11 @@
|
|
|
264
264
|
</div>
|
|
265
265
|
|
|
266
266
|
<div class="flex h-12 shrink-0 items-center justify-end gap-2 border-t px-4">
|
|
267
|
-
<Button variant="outline" onclick={hideDrawer}
|
|
267
|
+
<Button variant="outline" onclick={hideDrawer} size="sm" Icon={X}>
|
|
268
268
|
Cancel
|
|
269
269
|
</Button>
|
|
270
270
|
{#if activeTab === "paste"}
|
|
271
|
-
<Button onclick={() => processContent(pasteContent)}
|
|
271
|
+
<Button onclick={() => processContent(pasteContent)} size="sm" Icon={FileText}>
|
|
272
272
|
Parse
|
|
273
273
|
</Button>
|
|
274
274
|
{/if}
|
|
@@ -289,10 +289,10 @@
|
|
|
289
289
|
</div>
|
|
290
290
|
|
|
291
291
|
<div class="flex h-12 shrink-0 items-center justify-end gap-2 border-t px-4">
|
|
292
|
-
<Button variant="outline" onclick={() => (step = "input")}
|
|
292
|
+
<Button variant="outline" onclick={() => (step = "input")} size="sm" Icon={X}>
|
|
293
293
|
Cancel
|
|
294
294
|
</Button>
|
|
295
|
-
<Button onclick={handleImport}
|
|
295
|
+
<Button onclick={handleImport} size="sm" Icon={Check}>
|
|
296
296
|
Import {transformedRows.length} records
|
|
297
297
|
</Button>
|
|
298
298
|
</div>
|
|
@@ -345,7 +345,7 @@
|
|
|
345
345
|
</div>
|
|
346
346
|
{/if}
|
|
347
347
|
<div class="flex h-12 shrink-0 items-center justify-end gap-2 border-t px-4">
|
|
348
|
-
<Button onclick={hideDrawer}
|
|
348
|
+
<Button onclick={hideDrawer} size="sm" Icon={Check}>
|
|
349
349
|
Done
|
|
350
350
|
</Button>
|
|
351
351
|
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import VerticalNav from "./verticalNav.svelte";
|
|
3
|
+
import HorizontalNav from "./horizontalNav.svelte";
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
orientation?: "vertical" | "horizontal";
|
|
7
|
+
}
|
|
8
|
+
const { orientation = "vertical" }: Props = $props();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
{#if orientation === "horizontal"}
|
|
12
|
+
<HorizontalNav />
|
|
13
|
+
{:else}
|
|
14
|
+
<VerticalNav />
|
|
15
|
+
{/if}
|