@lobb-js/studio 0.29.0 → 0.29.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 (109) hide show
  1. package/README.md +1 -0
  2. package/dist/actions.d.ts +2 -0
  3. package/dist/components/Studio.svelte +39 -43
  4. package/dist/components/StudioRoot.svelte +19 -0
  5. package/dist/components/StudioRoot.svelte.d.ts +6 -0
  6. package/dist/components/breadCrumbs.svelte +5 -4
  7. package/dist/components/codeEditor.svelte +1 -1
  8. package/dist/components/dataTable/dataTable.svelte +35 -20
  9. package/dist/components/dataTable/dataTable.svelte.d.ts +2 -1
  10. package/dist/components/dataTable/dataTableTabs.svelte +4 -2
  11. package/dist/components/dataTable/dataTableTabs.svelte.d.ts +2 -0
  12. package/dist/components/dataTable/header.svelte +15 -11
  13. package/dist/components/dataTable/header.svelte.d.ts +1 -0
  14. package/dist/components/dataTable/listViewChildren.svelte +4 -6
  15. package/dist/components/dataTable/listViewChildren.svelte.d.ts +0 -1
  16. package/dist/components/dataTable/table.svelte +8 -10
  17. package/dist/components/dataTable/table.svelte.d.ts +0 -1
  18. package/dist/components/dataTableDrawer/dataTableDrawer.svelte +4 -1
  19. package/dist/components/dataTableDrawer/dataTableDrawer.svelte.d.ts +2 -0
  20. package/dist/components/detailView/create/children.svelte +1 -1
  21. package/dist/components/detailView/create/createDetailView.svelte +19 -61
  22. package/dist/components/detailView/create/createManyView.svelte +2 -4
  23. package/dist/components/detailView/detailView.svelte +81 -0
  24. package/dist/components/detailView/detailView.svelte.d.ts +8 -0
  25. package/dist/components/detailView/fieldInput.svelte +10 -10
  26. package/dist/components/detailView/fieldInputReplacement.svelte +7 -7
  27. package/dist/components/detailView/passwordInput.svelte +1 -1
  28. package/dist/components/detailView/update/updateDetailView.svelte +32 -69
  29. package/dist/components/diffViewer.svelte +1 -1
  30. package/dist/components/extensionsComponents.svelte +3 -1
  31. package/dist/components/foreingKeyInput.svelte +2 -2
  32. package/dist/components/importButton.svelte +12 -9
  33. package/dist/components/landing.svelte +7 -0
  34. package/dist/components/landing.svelte.d.ts +6 -14
  35. package/dist/components/miniSidebar.svelte +86 -15
  36. package/dist/components/miniSidebar.svelte.d.ts +2 -17
  37. package/dist/components/polymorphicInput.svelte +1 -1
  38. package/dist/components/rangeCalendarButton.svelte +10 -10
  39. package/dist/components/richTextEditor.svelte +1 -1
  40. package/dist/components/routes/collections/collections.svelte +32 -10
  41. package/dist/components/routes/data_model/dataModel.svelte +6 -28
  42. package/dist/components/routes/data_model/dataModel.svelte.d.ts +17 -2
  43. package/dist/components/routes/extensions/publicExtension.svelte +19 -0
  44. package/dist/components/routes/extensions/publicExtension.svelte.d.ts +13 -0
  45. package/dist/components/routes/home.svelte +2 -2
  46. package/dist/components/routes/workflows/workflows.svelte +4 -4
  47. package/dist/components/sidebar/sidebar.svelte +1 -1
  48. package/dist/components/sidebar/sidebarElements.svelte +4 -4
  49. package/dist/components/singletone.svelte +4 -6
  50. package/dist/components/ui/button/button.svelte +2 -3
  51. package/dist/components/workflowEditor.svelte +2 -2
  52. package/dist/eventSystem.d.ts +1 -1
  53. package/dist/eventSystem.js +7 -5
  54. package/dist/extensions/extension.types.d.ts +38 -14
  55. package/dist/extensions/extensionUtils.js +4 -2
  56. package/dist/index.d.ts +3 -1
  57. package/dist/index.js +3 -1
  58. package/dist/store.types.d.ts +1 -1
  59. package/dist/studioLifecycle.svelte.d.ts +2 -0
  60. package/dist/studioLifecycle.svelte.js +15 -0
  61. package/package.json +3 -4
  62. package/src/app.css +3 -0
  63. package/src/lib/actions.ts +2 -0
  64. package/src/lib/components/Studio.svelte +39 -43
  65. package/src/lib/components/StudioRoot.svelte +19 -0
  66. package/src/lib/components/breadCrumbs.svelte +5 -4
  67. package/src/lib/components/codeEditor.svelte +1 -1
  68. package/src/lib/components/dataTable/dataTable.svelte +35 -20
  69. package/src/lib/components/dataTable/dataTableTabs.svelte +4 -2
  70. package/src/lib/components/dataTable/header.svelte +15 -11
  71. package/src/lib/components/dataTable/listViewChildren.svelte +4 -6
  72. package/src/lib/components/dataTable/table.svelte +8 -10
  73. package/src/lib/components/dataTableDrawer/dataTableDrawer.svelte +4 -1
  74. package/src/lib/components/detailView/create/children.svelte +1 -1
  75. package/src/lib/components/detailView/create/createDetailView.svelte +19 -61
  76. package/src/lib/components/detailView/create/createManyView.svelte +2 -4
  77. package/src/lib/components/detailView/detailView.svelte +81 -0
  78. package/src/lib/components/detailView/fieldInput.svelte +10 -10
  79. package/src/lib/components/detailView/fieldInputReplacement.svelte +7 -7
  80. package/src/lib/components/detailView/passwordInput.svelte +1 -1
  81. package/src/lib/components/detailView/update/updateDetailView.svelte +32 -69
  82. package/src/lib/components/diffViewer.svelte +1 -1
  83. package/src/lib/components/extensionsComponents.svelte +3 -1
  84. package/src/lib/components/foreingKeyInput.svelte +2 -2
  85. package/src/lib/components/importButton.svelte +12 -9
  86. package/src/lib/components/landing.svelte +7 -0
  87. package/src/lib/components/miniSidebar.svelte +86 -15
  88. package/src/lib/components/polymorphicInput.svelte +1 -1
  89. package/src/lib/components/rangeCalendarButton.svelte +10 -10
  90. package/src/lib/components/richTextEditor.svelte +1 -1
  91. package/src/lib/components/routes/collections/collections.svelte +32 -10
  92. package/src/lib/components/routes/data_model/dataModel.svelte +6 -28
  93. package/src/lib/components/routes/extensions/publicExtension.svelte +19 -0
  94. package/src/lib/components/routes/home.svelte +2 -2
  95. package/src/lib/components/routes/workflows/workflows.svelte +4 -4
  96. package/src/lib/components/sidebar/sidebar.svelte +1 -1
  97. package/src/lib/components/sidebar/sidebarElements.svelte +4 -4
  98. package/src/lib/components/singletone.svelte +4 -6
  99. package/src/lib/components/ui/button/button.svelte +2 -3
  100. package/src/lib/components/workflowEditor.svelte +2 -2
  101. package/src/lib/eventSystem.ts +8 -7
  102. package/src/lib/extensions/extension.types.ts +39 -6
  103. package/src/lib/extensions/extensionUtils.ts +4 -2
  104. package/src/lib/index.ts +3 -1
  105. package/src/lib/store.types.ts +1 -1
  106. package/src/lib/studioLifecycle.svelte.ts +17 -0
  107. package/dist/components/routes/data_model/syncManager.svelte +0 -94
  108. package/dist/components/routes/data_model/syncManager.svelte.d.ts +0 -3
  109. package/src/lib/components/routes/data_model/syncManager.svelte +0 -94
package/README.md CHANGED
@@ -1 +1,2 @@
1
1
  # Lobb Studio
2
+
package/dist/actions.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { CreateDetailViewProp } from "./components/detailView/create/createDetailView.svelte";
2
2
  import type { UpdateDetailViewProp } from "./components/detailView/update/updateDetailView.svelte";
3
3
  import type { StudioContext } from "./context";
4
+ import type { CollectionTab } from "./store.types";
4
5
  export interface OpenDataTableDrawerProps {
5
6
  collectionName: string;
6
7
  filter?: Record<string, any>;
@@ -8,6 +9,7 @@ export interface OpenDataTableDrawerProps {
8
9
  showHeader?: boolean;
9
10
  showFooter?: boolean;
10
11
  position?: "side" | "bottom";
12
+ tabs?: CollectionTab[];
11
13
  }
12
14
  export declare function showDialog(title: string, description: string): Promise<boolean>;
13
15
  export declare function openCreateDetailView(studioContext: StudioContext, props: CreateDetailViewProp): void;
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { Toaster } from "./ui/sonner";
3
- import { onMount, onDestroy } from "svelte";
3
+ import { onMount } from "svelte";
4
4
  import { ModeWatcher } from "mode-watcher";
5
5
  import { createLobb } from "../store.svelte";
6
6
  import { setStudioContext } from "../context";
@@ -8,7 +8,8 @@
8
8
  import { LoaderCircle, ServerOff } from "lucide-svelte";
9
9
  import MiniSidebar from "./miniSidebar.svelte";
10
10
  import * as Tooltip from "./ui/tooltip";
11
- import { Router, Route, Fallback, init as initRouter } from "@wjfe/n-savant";
11
+ import { page } from "$app/state";
12
+ import { afterNavigate } from "$app/navigation";
12
13
  import {
13
14
  executeExtensionsOnStartup,
14
15
  executeExtensionsOnRouteChange,
@@ -22,6 +23,7 @@
22
23
  import Collections from "./routes/collections/collections.svelte";
23
24
  import Workflows from "./routes/workflows/workflows.svelte";
24
25
  import Extension from "./routes/extensions/extension.svelte";
26
+ import PublicExtension from "./routes/extensions/publicExtension.svelte";
25
27
 
26
28
  interface StudioProps {
27
29
  lobbUrl?: string;
@@ -42,13 +44,11 @@
42
44
 
43
45
  let status: "loading" | "error" | "ready" = $state("loading");
44
46
  let isSmallScreen = $derived(!mediaQueries.sm.current);
45
- let cleanupRouter: (() => void) | undefined;
46
47
 
47
48
  onMount(async () => {
48
49
  // Remove the static loading screen defined in app.html — it shows instantly
49
50
  // before JS loads to avoid a blank page, and is replaced by the Studio UI.
50
51
  document.getElementById("app-loading")?.remove();
51
- cleanupRouter = initRouter();
52
52
  try {
53
53
  ctx.meta = await lobb.getMeta();
54
54
  ctx.extensions = await loadExtensions(lobb, ctx, extensionMap);
@@ -59,19 +59,13 @@
59
59
  console.error(err);
60
60
  status = "error";
61
61
  }
62
-
63
- // Fire onRouteChange hooks on every navigation
64
- const onRouteChange = () => executeExtensionsOnRouteChange(lobb, ctx as any, window.location.pathname);
65
- const originalPushState = history.pushState.bind(history);
66
- history.pushState = function (...args) {
67
- originalPushState(...args);
68
- onRouteChange();
69
- };
70
- window.addEventListener("popstate", onRouteChange);
71
62
  });
72
63
 
73
- onDestroy(() => {
74
- if (cleanupRouter) cleanupRouter();
64
+ // Fire onRouteChange hooks via SvelteKit's afterNavigate lifecycle instead
65
+ // of monkey-patching history.pushState. Runs both on initial mount and on
66
+ // every client-side navigation.
67
+ afterNavigate(() => {
68
+ executeExtensionsOnRouteChange(lobb, ctx as any, page.url.pathname);
75
69
  });
76
70
  </script>
77
71
 
@@ -94,6 +88,18 @@
94
88
  <div class="text-xs">Could not connect to the lobb server at this endpoint ({ctx.lobbUrl})</div>
95
89
  </div>
96
90
  </div>
91
+ {:else if page.url.pathname.startsWith("/studio/public/")}
92
+ <!-- Public extension pages skip the dashboard chrome (no sidebar, no
93
+ header) since the viewer is unauthenticated and shouldn't see any
94
+ navigation to gated areas. -->
95
+ <Tooltip.Provider delayDuration={0} disableHoverableContent={true}>
96
+ <main class="bg-background h-screen w-screen">
97
+ <PublicExtension
98
+ extension={page.url.pathname.split("/")[3]}
99
+ page={page.url.pathname.split("/")[4]}
100
+ />
101
+ </main>
102
+ </Tooltip.Provider>
97
103
  {:else}
98
104
  <Tooltip.Provider delayDuration={0} disableHoverableContent={true}>
99
105
  <main
@@ -103,34 +109,24 @@
103
109
  <MiniSidebar />
104
110
  <div class="second_grid">
105
111
  <Header />
106
- <Router id="root-router" basePath="/studio">
107
- <Route key="home" path="/">
108
- {#snippet children(params)}
109
- <Home />
110
- {/snippet}
111
- </Route>
112
- <Route key="collections" path="/collections/:collection?">
113
- {#snippet children(params)}
114
- <Collections collectionName={params?.collection} />
115
- {/snippet}
116
- </Route>
117
- <Route key="datamodel" path="/datamodel/*">
118
- {#snippet children(params)}
119
- <DataModel />
120
- {/snippet}
121
- </Route>
122
- <Route key="workflows" path="/workflows/:workflow?">
123
- {#snippet children(params)}
124
- <Workflows workflowName={params?.workflow} />
125
- {/snippet}
126
- </Route>
127
- <Route key="extensions" path="/extensions/:extension?/:page?/*">
128
- {#snippet children(params)}
129
- <Extension extension={params?.extension} page={params?.page} />
130
- {/snippet}
131
- </Route>
132
- <Fallback>Not Found</Fallback>
133
- </Router>
112
+ {#if page.url.pathname.replace(/\/$/, "") === "/studio"}
113
+ <Home />
114
+ {:else if page.url.pathname.startsWith("/studio/collections")}
115
+ <Collections collectionName={page.url.pathname.split("/")[3]} />
116
+ {:else if page.url.pathname.startsWith("/studio/datamodel")}
117
+ <DataModel />
118
+ {:else if page.url.pathname.startsWith("/studio/workflows")}
119
+ <Workflows workflowName={page.url.pathname.split("/")[3]} />
120
+ {:else if page.url.pathname.startsWith("/studio/extensions")}
121
+ <Extension
122
+ extension={page.url.pathname.split("/")[3]}
123
+ page={page.url.pathname.split("/")[4]}
124
+ />
125
+ {:else}
126
+ <div class="flex h-full w-full items-center justify-center text-muted-foreground">
127
+ Not Found
128
+ </div>
129
+ {/if}
134
130
  </div>
135
131
  </main>
136
132
  </Tooltip.Provider>
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import Studio from "./Studio.svelte";
3
+ import { getStudioMountKey } from "../studioLifecycle.svelte";
4
+
5
+ interface StudioRootProps {
6
+ lobbUrl?: string;
7
+ }
8
+
9
+ let { lobbUrl }: StudioRootProps = $props();
10
+
11
+ // Tracked so any change to the mount key tears down the Studio tree and
12
+ // mounts a fresh one — fresh ctx, fresh extension load, fresh /me, etc.
13
+ // Bumped by remountStudio() on login/logout.
14
+ const mountKey = $derived(getStudioMountKey());
15
+ </script>
16
+
17
+ {#key mountKey}
18
+ <Studio {lobbUrl} />
19
+ {/key}
@@ -0,0 +1,6 @@
1
+ interface StudioRootProps {
2
+ lobbUrl?: string;
3
+ }
4
+ declare const StudioRoot: import("svelte").Component<StudioRootProps, {}, "">;
5
+ type StudioRoot = ReturnType<typeof StudioRoot>;
6
+ export default StudioRoot;
@@ -1,11 +1,12 @@
1
1
  <script lang="ts">
2
2
  import * as Breadcrumb from "./ui/breadcrumb";
3
3
  import { mediaQueries } from "../utils";
4
- import { location } from "@wjfe/n-savant";
4
+ import { page } from "$app/state";
5
+ import { goto } from "$app/navigation";
5
6
 
6
7
  const isSmall = $derived(!mediaQueries.sm.current);
7
8
  const pathNames = $derived(
8
- location.url.pathname
9
+ page.url.pathname
9
10
  .replace("/studio", "")
10
11
  .split("/")
11
12
  .filter((el: any) => el !== "")
@@ -26,7 +27,7 @@
26
27
  {:else}
27
28
  <Breadcrumb.Link
28
29
  class="cursor-pointer"
29
- onclick={() => location.navigate("/studio")}
30
+ onclick={() => goto("/studio")}
30
31
  >
31
32
  Home
32
33
  </Breadcrumb.Link>
@@ -45,7 +46,7 @@
45
46
  <Breadcrumb.Link
46
47
  class="cursor-pointer"
47
48
  onclick={() =>
48
- location.navigate(`/studio/${currentFullPaths}`)}
49
+ goto(`/studio/${currentFullPaths}`)}
49
50
  >
50
51
  {path}
51
52
  </Breadcrumb.Link>
@@ -132,7 +132,7 @@
132
132
  });
133
133
  </script>
134
134
 
135
- <div class={cn('resize-y rounded-md border bg-muted/30 h-60', className)}>
135
+ <div class={cn('resize-y rounded-md border bg-muted-soft h-60', className)}>
136
136
  <div bind:this={editorContainer} class="h-full w-full pl-2" />
137
137
  </div>
138
138
 
@@ -24,8 +24,11 @@
24
24
  import type { Changes, ChildrenChanges } from "../detailView/utils";
25
25
  import ExtensionsComponents from "../extensionsComponents.svelte";
26
26
  import { getExtensionUtils, loadExtensionComponents } from "../../extensions/extensionUtils";
27
+ import { emitEvent } from "../../eventSystem";
28
+ import { onMount } from "svelte";
27
29
  import Tabs from "./dataTableTabs.svelte";
28
30
  import { fade } from "svelte/transition";
31
+ import type { CollectionTab } from "../../store.types";
29
32
 
30
33
  const { lobb, ctx } = getStudioContext();
31
34
 
@@ -38,9 +41,9 @@
38
41
  showHeader?: boolean;
39
42
  showFooter?: boolean;
40
43
  showImport?: boolean;
41
- unifiedBgColor?: "bg-muted/30" | "bg-background";
42
44
  showDelete?: boolean;
43
45
  tableProps?: Partial<TableProps>;
46
+ tabs?: CollectionTab[];
44
47
  headerLeft?: Snippet<[]>;
45
48
  }
46
49
 
@@ -53,12 +56,26 @@
53
56
  showHeader = true,
54
57
  showFooter = true,
55
58
  showImport = true,
56
- unifiedBgColor,
57
59
  showDelete = false,
58
60
  tableProps,
61
+ tabs,
59
62
  headerLeft,
60
63
  }: Props = $props();
61
64
 
65
+ // Gate row/header buttons by the current user's permissions:
66
+ // - showUpdate → per-row edit button
67
+ // - showCreate → header's Create + Import buttons (passed to Header)
68
+ let showUpdate = $state(false);
69
+ let showCreate = $state(false);
70
+ onMount(async () => {
71
+ const [update, create] = await Promise.all([
72
+ emitEvent({ lobb, ctx }, "auth.canAccess", { collection: collectionName, action: "update" }),
73
+ emitEvent({ lobb, ctx }, "auth.canAccess", { collection: collectionName, action: "create" }),
74
+ ]);
75
+ showUpdate = update === true;
76
+ showCreate = create === true;
77
+ });
78
+
62
79
  function getOrCreateUpdatedSlot(recordId: string): Changes | undefined {
63
80
  if (!changes) return undefined;
64
81
  let slot = changes.updated.find((u) => String(u.id) === String(recordId));
@@ -191,10 +208,7 @@
191
208
 
192
209
  <div
193
210
  bind:clientWidth={dataTableContainerWidth}
194
- class="
195
- flex flex-col overflow-auto h-full w-full
196
- {unifiedBgColor ? unifiedBgColor : ''}
197
- "
211
+ class="flex flex-col overflow-auto h-full w-full"
198
212
  >
199
213
  {#snippet rowActionsSnippet(entry: Record<string, any>)}
200
214
  <ExtensionsComponents
@@ -212,6 +226,7 @@
212
226
  {collectionName}
213
227
  bind:selectedRecords
214
228
  {showImport}
229
+ {showCreate}
215
230
  {parentContext}
216
231
  {changes}
217
232
  >
@@ -220,7 +235,7 @@
220
235
  {/snippet}
221
236
  </Header>
222
237
  {/if}
223
- <Tabs {collectionName} {filter} bind:activeTabFilter />
238
+ <Tabs {collectionName} {filter} {tabs} bind:activeTabFilter />
224
239
  <div class="relative flex-1 overflow-auto w-full">
225
240
  {#key activeTabFilter}
226
241
  <div class="h-full w-full" in:fade={{ duration: 120 }}>
@@ -240,22 +255,23 @@
240
255
  showLastColumnBorder={true}
241
256
  bind:sort={params.sort}
242
257
  bind:selectedRecords
243
- {unifiedBgColor}
244
258
  bind:tableWidth={dataTableWidth}
245
259
  {...tableProps}
246
260
  rowActions={hasRowActions ? rowActionsSnippet : undefined}>
247
261
  {#snippet tools(entry)}
248
- <UpdateDetailViewButton
249
- {collectionName}
250
- recordId={entry.id}
251
- variant="ghost"
252
- class="h-5 w-5 px-0 py-0 text-muted-foreground hover:bg-transparent"
253
- Icon={Pencil}
254
- changes={getOrCreateUpdatedSlot(String(entry.id))}
255
- onSuccessfullSave={async () => {
256
- params = { ...params };
257
- }}
258
- ></UpdateDetailViewButton>
262
+ {#if showUpdate}
263
+ <UpdateDetailViewButton
264
+ {collectionName}
265
+ recordId={entry.id}
266
+ variant="ghost"
267
+ class="h-5 w-5 px-0 py-0 text-muted-foreground hover:bg-transparent"
268
+ Icon={Pencil}
269
+ changes={getOrCreateUpdatedSlot(String(entry.id))}
270
+ onSuccessfullSave={async () => {
271
+ params = { ...params };
272
+ }}
273
+ ></UpdateDetailViewButton>
274
+ {/if}
259
275
  {#if parentContext}
260
276
  <Button
261
277
  class="h-6 w-6 text-muted-foreground hover:bg-transparent"
@@ -293,7 +309,6 @@
293
309
  width={dataTableWidth > dataTableContainerWidth
294
310
  ? dataTableContainerWidth
295
311
  : dataTableWidth}
296
- unifiedBgColor={unifiedBgColor ?? "bg-background"}
297
312
  />
298
313
  {/snippet}
299
314
  </Table>
@@ -5,6 +5,7 @@ export interface ParentContext {
5
5
  import { type TableProps } from "./table.svelte";
6
6
  import type { Snippet } from "svelte";
7
7
  import type { ChildrenChanges } from "../detailView/utils";
8
+ import type { CollectionTab } from "../../store.types";
8
9
  interface Props {
9
10
  collectionName: string;
10
11
  filter?: any;
@@ -14,9 +15,9 @@ interface Props {
14
15
  showHeader?: boolean;
15
16
  showFooter?: boolean;
16
17
  showImport?: boolean;
17
- unifiedBgColor?: "bg-muted/30" | "bg-background";
18
18
  showDelete?: boolean;
19
19
  tableProps?: Partial<TableProps>;
20
+ tabs?: CollectionTab[];
20
21
  headerLeft?: Snippet<[]>;
21
22
  }
22
23
  declare const DataTable: import("svelte").Component<Props, {}, "changes">;
@@ -1,17 +1,19 @@
1
1
  <script lang="ts">
2
2
  import { getStudioContext } from "../../context";
3
+ import type { CollectionTab } from "../../store.types";
3
4
 
4
5
  const { lobb, ctx } = getStudioContext();
5
6
 
6
7
  interface Props {
7
8
  collectionName: string;
8
9
  filter?: any;
10
+ tabs?: CollectionTab[];
9
11
  activeTabFilter?: any;
10
12
  }
11
13
 
12
- let { collectionName, filter, activeTabFilter = $bindable() }: Props = $props();
14
+ let { collectionName, filter, tabs: tabsProp, activeTabFilter = $bindable() }: Props = $props();
13
15
 
14
- const tabs = ctx.meta.collections[collectionName].ui?.tabs;
16
+ const tabs: CollectionTab[] | undefined = $derived(tabsProp ?? ctx.meta.collections[collectionName].ui?.tabs);
15
17
  let activeTab = $state<string | null>(null);
16
18
  let tabCounts = $state<Record<string, number>>({});
17
19
 
@@ -1,6 +1,8 @@
1
+ import type { CollectionTab } from "../../store.types";
1
2
  interface Props {
2
3
  collectionName: string;
3
4
  filter?: any;
5
+ tabs?: CollectionTab[];
4
6
  activeTabFilter?: any;
5
7
  }
6
8
  declare const DataTableTabs: import("svelte").Component<Props, {}, "activeTabFilter">;
@@ -25,6 +25,7 @@
25
25
  parentContext?: ParentContext;
26
26
  changes?: ChildrenChanges;
27
27
  showImport?: boolean;
28
+ showCreate?: boolean;
28
29
  left?: Snippet<[]>;
29
30
  }
30
31
 
@@ -35,6 +36,7 @@
35
36
  parentContext,
36
37
  changes,
37
38
  showImport = true,
39
+ showCreate = false,
38
40
  left
39
41
  }: Props = $props();
40
42
 
@@ -167,7 +169,7 @@
167
169
  >
168
170
  {headerIsSmall ? "" : "Refresh"}
169
171
  </Button>
170
- {#if showImport}
172
+ {#if showImport && showCreate}
171
173
  <Tooltip.Provider delayDuration={0}>
172
174
  <Tooltip.Root>
173
175
  <Tooltip.Trigger>
@@ -200,15 +202,17 @@
200
202
  {headerIsSmall ? "" : "Link"}
201
203
  </SelectRecord>
202
204
  {/if}
203
- <CreateDetailViewButton
204
- {collectionName}
205
- variant="default"
206
- class="h-7 px-3 text-xs font-normal"
207
- Icon={Plus}
208
- changes={changes ? createChanges : undefined}
209
- onSuccessfullSave={handleCreateSuccess}
210
- >
211
- {headerIsSmall ? "" : "Create"}
212
- </CreateDetailViewButton>
205
+ {#if showCreate}
206
+ <CreateDetailViewButton
207
+ {collectionName}
208
+ variant="default"
209
+ class="h-7 px-3 text-xs font-normal"
210
+ Icon={Plus}
211
+ changes={changes ? createChanges : undefined}
212
+ onSuccessfullSave={handleCreateSuccess}
213
+ >
214
+ {headerIsSmall ? "" : "Create"}
215
+ </CreateDetailViewButton>
216
+ {/if}
213
217
  </div>
214
218
  </div>
@@ -8,6 +8,7 @@ interface Props {
8
8
  parentContext?: ParentContext;
9
9
  changes?: ChildrenChanges;
10
10
  showImport?: boolean;
11
+ showCreate?: boolean;
11
12
  left?: Snippet<[]>;
12
13
  }
13
14
  declare const Header: import("svelte").Component<Props, {}, "selectedRecords" | "params">;
@@ -12,10 +12,9 @@
12
12
  collectionName: string;
13
13
  recordId: string;
14
14
  width: number;
15
- unifiedBgColor?: "bg-muted/30" | "bg-background";
16
15
  }
17
16
 
18
- let { collectionName, recordId, width, unifiedBgColor }: Props = $props();
17
+ let { collectionName, recordId, width }: Props = $props();
19
18
 
20
19
  const children = (ctx.meta.collections[collectionName]?.children ?? [])
21
20
  .filter((c: any) => c.type === "fk" || c.type === "m2m" || c.type === "polymorphic");
@@ -27,13 +26,13 @@
27
26
 
28
27
  <div class="flex" style="width: {width}px;">
29
28
  <div
30
- class="flex justify-center border-r {unifiedBgColor ? unifiedBgColor : 'bg-background'}"
29
+ class="flex justify-center border-r bg-background"
31
30
  style="width: 40px"
32
31
  ></div>
33
32
  <div class="flex-1 flex flex-col">
34
33
  {#each children as child, index}
35
34
  {@const lastRow = children.length - 1 === index}
36
- <div class="overflow-hidden {unifiedBgColor ? unifiedBgColor : 'bg-background'}">
35
+ <div class="overflow-hidden bg-background">
37
36
  <div
38
37
  bind:clientWidth={tableHeaderWidth}
39
38
  class="flex justify-between items-center gap-2 text-sm h-10 {expandedRows[index] || !lastRow ? 'border-b' : ''}"
@@ -75,7 +74,7 @@
75
74
  {#if expandedRows[index]}
76
75
  <div class="flex max-h-96 overflow-auto {lastRow ? '' : 'border-b'}">
77
76
  <div
78
- class="border-r {unifiedBgColor ? unifiedBgColor : ''}"
77
+ class="border-r"
79
78
  style="width: 100vw; max-width: 40px"
80
79
  ></div>
81
80
  <div class="flex-1" style="width: {tableHeaderWidth - 40}px;">
@@ -92,7 +91,6 @@
92
91
  showHeader={false}
93
92
  showFooter={false}
94
93
  showDelete={child.type === "fk"}
95
- {unifiedBgColor}
96
94
  tableProps={{ showLastRowBorder: false, showLastColumnBorder: false, showCheckboxes: false }}
97
95
  />
98
96
  </ExtensionsComponents>
@@ -2,7 +2,6 @@ interface Props {
2
2
  collectionName: string;
3
3
  recordId: string;
4
4
  width: number;
5
- unifiedBgColor?: "bg-muted/30" | "bg-background";
6
5
  }
7
6
  declare const ListViewChildren: import("svelte").Component<Props, {}, "">;
8
7
  type ListViewChildren = ReturnType<typeof ListViewChildren>;
@@ -38,7 +38,6 @@
38
38
 
39
39
  // other
40
40
  parentWidth?: number;
41
- unifiedBgColor?: "bg-muted/30" | "bg-background";
42
41
  select?: Select;
43
42
  tableWidth?: number;
44
43
  }
@@ -77,7 +76,6 @@
77
76
  tools,
78
77
  rowActions,
79
78
  collapsible,
80
- unifiedBgColor,
81
79
  select,
82
80
  tableWidth = $bindable(),
83
81
  }: TableProps = $props();
@@ -184,7 +182,7 @@
184
182
  flex items-center p-2.5 text-xs h-10
185
183
  border-r border-b gap-2
186
184
  {headerBorderTop ? 'border-t' : ''}
187
- {unifiedBgColor ? unifiedBgColor : 'bg-muted'}
185
+ bg-muted-soft
188
186
  "
189
187
  >
190
188
  <!-- collapsable toggle -->
@@ -209,7 +207,7 @@
209
207
  class="
210
208
  sticky top-0 z-10
211
209
  flex items-center p-2.5 text-xs h-10
212
- {unifiedBgColor ? unifiedBgColor : 'bg-muted'}
210
+ bg-muted-soft
213
211
  {lastColumn && !showLastColumnBorder ? '' : 'border-r'}
214
212
  border-b gap-2
215
213
  {headerBorderTop ? 'border-t' : ''}
@@ -236,7 +234,7 @@
236
234
  class="
237
235
  sticky top-0 right-0 z-20
238
236
  flex items-center p-2.5 h-10
239
- {unifiedBgColor ? unifiedBgColor : 'bg-muted'}
237
+ bg-muted-soft
240
238
  border-l border-b
241
239
  {headerBorderTop ? 'border-t' : ''}
242
240
  "
@@ -251,7 +249,7 @@
251
249
  class="
252
250
  sticky left-0
253
251
  flex items-center p-2.5 text-xs h-10
254
- {unifiedBgColor ? unifiedBgColor : 'bg-background'}
252
+ bg-background
255
253
  border-r gap-2
256
254
  "
257
255
  >
@@ -298,7 +296,7 @@
298
296
  class="
299
297
  flex items-center p-2.5 text-xs h-10 text-nowrap overflow-clip
300
298
  {select ? 'cursor-pointer' : ''}
301
- {unifiedBgColor ? unifiedBgColor : 'bg-background'}
299
+ bg-background
302
300
  {lastColumn && !showLastColumnBorder ? '' : 'border-r'}
303
301
  "
304
302
  >
@@ -315,7 +313,7 @@
315
313
  sticky right-0 z-10
316
314
  flex items-center p-2.5 text-xs h-10
317
315
  border-l gap-2
318
- {unifiedBgColor ? unifiedBgColor : 'bg-background'}
316
+ bg-background
319
317
  "
320
318
  >
321
319
  {@render rowActions?.(entry, index)}
@@ -336,8 +334,8 @@
336
334
  {expandedRows[index] ? '' : 'height: 0px;'}
337
335
  "
338
336
  class="
339
- sticky left-0 top-0 overflow-auto bg-muted/30
340
- {unifiedBgColor ? unifiedBgColor : ''}
337
+ sticky left-0 top-0 overflow-auto bg-muted-soft
338
+
341
339
  {expandedRows[index] ? 'border-t' : ''}
342
340
  "
343
341
  >
@@ -24,7 +24,6 @@ export interface TableProps {
24
24
  rowActions?: Snippet<[Entry, number]>;
25
25
  collapsible?: Snippet<[Entry, number]>;
26
26
  parentWidth?: number;
27
- unifiedBgColor?: "bg-muted/30" | "bg-background";
28
27
  select?: Select;
29
28
  tableWidth?: number;
30
29
  }
@@ -4,6 +4,7 @@
4
4
  import DataTable from "../dataTable/dataTable.svelte";
5
5
  import Drawer from "../drawer.svelte";
6
6
  import type { TableProps } from "../dataTable/table.svelte";
7
+ import type { CollectionTab } from "../../store.types";
7
8
 
8
9
  interface Props {
9
10
  collectionName: string;
@@ -13,6 +14,7 @@
13
14
  showFooter?: boolean;
14
15
  tableProps?: Partial<TableProps>;
15
16
  position?: "side" | "bottom";
17
+ tabs?: CollectionTab[];
16
18
  onClose?: () => void;
17
19
  }
18
20
 
@@ -24,6 +26,7 @@
24
26
  showFooter = true,
25
27
  tableProps,
26
28
  position = "side",
29
+ tabs,
27
30
  onClose,
28
31
  }: Props = $props();
29
32
  </script>
@@ -47,7 +50,7 @@
47
50
  {showHeader}
48
51
  {showFooter}
49
52
  {tableProps}
50
- unifiedBgColor="bg-background"
53
+ {tabs}
51
54
  />
52
55
  </div>
53
56
  </Drawer>
@@ -1,4 +1,5 @@
1
1
  import type { TableProps } from "../dataTable/table.svelte";
2
+ import type { CollectionTab } from "../../store.types";
2
3
  interface Props {
3
4
  collectionName: string;
4
5
  filter?: Record<string, any>;
@@ -7,6 +8,7 @@ interface Props {
7
8
  showFooter?: boolean;
8
9
  tableProps?: Partial<TableProps>;
9
10
  position?: "side" | "bottom";
11
+ tabs?: CollectionTab[];
10
12
  onClose?: () => void;
11
13
  }
12
14
  declare const DataTableDrawer: import("svelte").Component<Props, {}, "">;
@@ -37,7 +37,7 @@
37
37
  parentCollectionName={collectionName}
38
38
  collectionName={child.collection}
39
39
  parentRecord={{ id: entry.id, collectionName }}
40
- class="bg-muted/30 border rounded-md overflow-hidden"
40
+ class="bg-muted-soft border rounded-md overflow-hidden"
41
41
  bind:value={entry[child.collection]}
42
42
  >
43
43
  <CreateManyView