@lobb-js/studio 0.30.0 → 0.32.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.
Files changed (71) hide show
  1. package/dist/actions.d.ts +2 -0
  2. package/dist/components/Studio.svelte +1 -10
  3. package/dist/components/dataTable/dataTable.svelte +104 -39
  4. package/dist/components/dataTable/dataTable.svelte.d.ts +4 -1
  5. package/dist/components/dataTable/fieldCell.svelte +7 -4
  6. package/dist/components/dataTable/fieldCell.svelte.d.ts +2 -2
  7. package/dist/components/dataTable/filter.svelte +0 -15
  8. package/dist/components/dataTable/header.svelte +13 -14
  9. package/dist/components/dataTable/header.svelte.d.ts +3 -2
  10. package/dist/components/dataTable/numberCell.svelte +28 -0
  11. package/dist/components/dataTable/numberCell.svelte.d.ts +7 -0
  12. package/dist/components/dataTable/polymorphicFieldCell.svelte +3 -3
  13. package/dist/components/dataTable/polymorphicFieldCell.svelte.d.ts +2 -2
  14. package/dist/components/dataTablePopup/dataTablePopup.svelte +17 -0
  15. package/dist/components/dataTablePopup/dataTablePopup.svelte.d.ts +2 -0
  16. package/dist/components/detailView/create/createDetailView.svelte +28 -54
  17. package/dist/components/detailView/create/createDetailView.svelte.d.ts +4 -3
  18. package/dist/components/detailView/create/createDetailViewChildren.svelte +113 -0
  19. package/dist/components/detailView/create/createDetailViewChildren.svelte.d.ts +9 -0
  20. package/dist/components/detailView/create/createManyView.svelte +2 -2
  21. package/dist/components/detailView/detailView.svelte +6 -1
  22. package/dist/components/detailView/fieldInput.svelte +7 -5
  23. package/dist/components/detailView/update/updateDetailView.svelte +46 -40
  24. package/dist/components/detailView/update/updateDetailView.svelte.d.ts +5 -3
  25. package/dist/components/detailView/update/updateDetailViewButton.svelte +0 -1
  26. package/dist/components/detailView/update/updateDetailViewChildren.svelte +122 -0
  27. package/dist/components/detailView/update/updateDetailViewChildren.svelte.d.ts +10 -0
  28. package/dist/components/detailView/utils.d.ts +1 -2
  29. package/dist/components/importButton.svelte +1 -1
  30. package/dist/components/miniSidebar.svelte +6 -3
  31. package/dist/components/richTextEditor.svelte +2 -0
  32. package/dist/components/routes/extensions/extension.svelte +1 -1
  33. package/dist/components/routes/home.svelte +35 -21
  34. package/dist/components/ui/input/numberInput.svelte +104 -0
  35. package/dist/components/ui/input/numberInput.svelte.d.ts +9 -0
  36. package/dist/components/workflowEditor.svelte +6 -4
  37. package/package.json +4 -3
  38. package/src/lib/actions.ts +2 -0
  39. package/src/lib/components/Studio.svelte +1 -10
  40. package/src/lib/components/dataTable/dataTable.svelte +104 -39
  41. package/src/lib/components/dataTable/fieldCell.svelte +7 -4
  42. package/src/lib/components/dataTable/filter.svelte +0 -15
  43. package/src/lib/components/dataTable/header.svelte +13 -14
  44. package/src/lib/components/dataTable/numberCell.svelte +28 -0
  45. package/src/lib/components/dataTable/polymorphicFieldCell.svelte +3 -3
  46. package/src/lib/components/dataTablePopup/dataTablePopup.svelte +17 -0
  47. package/src/lib/components/detailView/create/createDetailView.svelte +28 -54
  48. package/src/lib/components/detailView/create/createDetailViewChildren.svelte +113 -0
  49. package/src/lib/components/detailView/create/createManyView.svelte +2 -2
  50. package/src/lib/components/detailView/detailView.svelte +6 -1
  51. package/src/lib/components/detailView/fieldInput.svelte +7 -5
  52. package/src/lib/components/detailView/update/updateDetailView.svelte +46 -40
  53. package/src/lib/components/detailView/update/updateDetailViewButton.svelte +0 -1
  54. package/src/lib/components/detailView/update/updateDetailViewChildren.svelte +122 -0
  55. package/src/lib/components/detailView/utils.ts +1 -1
  56. package/src/lib/components/importButton.svelte +1 -1
  57. package/src/lib/components/miniSidebar.svelte +6 -3
  58. package/src/lib/components/richTextEditor.svelte +2 -0
  59. package/src/lib/components/routes/extensions/extension.svelte +1 -1
  60. package/src/lib/components/routes/home.svelte +35 -21
  61. package/src/lib/components/ui/input/numberInput.svelte +104 -0
  62. package/src/lib/components/workflowEditor.svelte +6 -4
  63. package/dist/components/breadCrumbs.svelte +0 -61
  64. package/dist/components/breadCrumbs.svelte.d.ts +0 -3
  65. package/dist/components/detailView/update/detailViewChildren.svelte +0 -61
  66. package/dist/components/detailView/update/detailViewChildren.svelte.d.ts +0 -9
  67. package/dist/components/header.svelte +0 -45
  68. package/dist/components/header.svelte.d.ts +0 -6
  69. package/src/lib/components/breadCrumbs.svelte +0 -61
  70. package/src/lib/components/detailView/update/detailViewChildren.svelte +0 -61
  71. package/src/lib/components/header.svelte +0 -45
@@ -0,0 +1,122 @@
1
+ <script lang="ts">
2
+ import DataTable from "../../dataTable/dataTable.svelte";
3
+ import { getStudioContext } from "../../../context";
4
+ import { Table, Link, Plus } from "lucide-svelte";
5
+ import { untrack } from "svelte";
6
+ import CreateDetailViewButton from "../create/createDetailViewButton.svelte";
7
+ import SelectRecord from "../../selectRecord.svelte";
8
+
9
+ const { ctx } = getStudioContext();
10
+
11
+ import type { Changes, ChildrenChanges } from "../utils";
12
+
13
+ interface LocalProp {
14
+ collectionName: string;
15
+ entry: any;
16
+ changes?: Changes;
17
+ onChanges?: (children: Changes["children"]) => void;
18
+ }
19
+
20
+ let { collectionName, entry, changes, onChanges }: LocalProp = $props();
21
+
22
+ const children = (ctx.meta.collections[collectionName]?.children ?? [])
23
+ .filter((c: any) => c.type === "fk" || c.type === "m2m" || c.type === "polymorphic");
24
+
25
+ let localChildren = $state<Changes["children"]>(untrack(() => changes?.children ?? {}));
26
+ let serverCounts = $state<Record<string, number | undefined>>({});
27
+
28
+ function handleChildChanges(collection: string, updated: ChildrenChanges) {
29
+ localChildren[collection] = updated;
30
+ onChanges?.($state.snapshot(localChildren));
31
+ }
32
+
33
+ function handleDataLoad(collection: string, total: number) {
34
+ serverCounts[collection] = total;
35
+ }
36
+
37
+ function handleEmptyCreate(collection: string, c: Changes) {
38
+ if (!localChildren[collection]) {
39
+ localChildren[collection] = { created: [], updated: [], deleted: [], linked: [], unlinked: [] };
40
+ }
41
+ localChildren[collection].created.push({ data: c.data });
42
+ onChanges?.($state.snapshot(localChildren));
43
+ }
44
+
45
+ function handleEmptyLink(collection: string, record: any) {
46
+ if (!localChildren[collection]) {
47
+ localChildren[collection] = { created: [], updated: [], deleted: [], linked: [], unlinked: [] };
48
+ }
49
+ localChildren[collection].linked.push(record);
50
+ onChanges?.($state.snapshot(localChildren));
51
+ }
52
+ </script>
53
+
54
+ {#if children.length}
55
+ <div class="flex flex-col gap-3 border-t p-4">
56
+ <div class="flex items-center gap-2">
57
+ <Link size="14" class="text-muted-foreground" />
58
+ <span class="text-sm font-medium">Sub Records</span>
59
+ </div>
60
+ {#each children as child}
61
+ {@const serverCount = serverCounts[child.collection]}
62
+ {@const localAdditions = (localChildren[child.collection]?.created.length ?? 0) + (localChildren[child.collection]?.linked.length ?? 0)}
63
+ {@const showEmpty = serverCount !== undefined && serverCount === 0 && localAdditions === 0}
64
+ {#if showEmpty}
65
+ <div class="rounded-lg border bg-muted-soft overflow-hidden flex flex-col">
66
+ <div class="flex flex-col items-center justify-center gap-3 py-6 px-4">
67
+ <div class="flex flex-col items-center gap-2 text-center">
68
+ <div class="flex items-center gap-1.5 text-sm font-medium text-muted-foreground">
69
+ <span>No records in</span>
70
+ <span class="rounded-md border bg-muted px-2 py-0.5 text-xs font-normal">{child.collection}</span>
71
+ </div>
72
+ <span class="text-xs text-muted-foreground/70">Create a new record or link an existing one.</span>
73
+ </div>
74
+ <div class="flex gap-2">
75
+ <SelectRecord
76
+ collectionName={child.collection}
77
+ variant="outline"
78
+ class="h-7 px-3 text-xs font-normal"
79
+ Icon={Link}
80
+ onSelect={(r) => handleEmptyLink(child.collection, r)}
81
+ >
82
+ Link
83
+ </SelectRecord>
84
+ <CreateDetailViewButton
85
+ collectionName={child.collection}
86
+ variant="default"
87
+ class="h-7 px-3 text-xs font-normal"
88
+ Icon={Plus}
89
+ onChanges={(c) => handleEmptyCreate(child.collection, c)}
90
+ >
91
+ Create
92
+ </CreateDetailViewButton>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ {:else}
97
+ <div class="rounded-lg border bg-background overflow-hidden flex flex-col max-h-96">
98
+ <DataTable
99
+ collectionName={child.collection}
100
+ searchParams={{ children_of: collectionName, parent_id: entry.id }}
101
+ parentContext={{ collectionName, recordId: entry.id }}
102
+ onChanges={(updated) => handleChildChanges(child.collection, updated)}
103
+ changes={localChildren[child.collection]}
104
+ showImport={false}
105
+ showHeader={true}
106
+ showFooter={true}
107
+ showDelete={child.type === "fk" || child.type === "m2m"}
108
+ tableProps={{ showLastColumnBorder: false, showLastRowBorder: true }}
109
+ onDataLoad={(total) => handleDataLoad(child.collection, total)}
110
+ >
111
+ {#snippet headerLeft()}
112
+ <div class="flex items-center gap-2 px-1">
113
+ <Table size="14" class="text-muted-foreground" />
114
+ <span class="text-sm font-medium">{child.collection}</span>
115
+ </div>
116
+ {/snippet}
117
+ </DataTable>
118
+ </div>
119
+ {/if}
120
+ {/each}
121
+ </div>
122
+ {/if}
@@ -0,0 +1,10 @@
1
+ import type { Changes } from "../utils";
2
+ interface LocalProp {
3
+ collectionName: string;
4
+ entry: any;
5
+ changes?: Changes;
6
+ onChanges?: (children: Changes["children"]) => void;
7
+ }
8
+ declare const UpdateDetailViewChildren: import("svelte").Component<LocalProp, {}, "">;
9
+ type UpdateDetailViewChildren = ReturnType<typeof UpdateDetailViewChildren>;
10
+ export default UpdateDetailViewChildren;
@@ -6,8 +6,7 @@ export type ChildrenChanges = {
6
6
  }>;
7
7
  updated: Array<{
8
8
  id: string | number;
9
- data: Record<string, any>;
10
- children: Record<string, ChildrenChanges>;
9
+ changes: Changes;
11
10
  }>;
12
11
  deleted: Array<Record<string, any>>;
13
12
  linked: Array<Record<string, any>>;
@@ -132,7 +132,7 @@
132
132
  importResults = [];
133
133
  let hasSuccess = false;
134
134
  for (const row of finalRows) {
135
- const response = await lobb.createOne(collectionName, row);
135
+ const response = await lobb.createOne(collectionName, { data: row });
136
136
  if (response.ok) {
137
137
  importResults.push({ row, error: null });
138
138
  hasSuccess = true;
@@ -90,12 +90,15 @@
90
90
  // prefix of everything); other items use startsWith so sub-paths
91
91
  // (e.g. /studio/collections/risks) still highlight their parent.
92
92
  // Popover items with children are active when any of their children match.
93
- const currentPath = $derived(page.url.pathname);
93
+ // SvelteKit's pathname can come back with a trailing slash (`/studio/`)
94
+ // depending on config, so we normalize it before comparing.
95
+ const currentPath = $derived(page.url.pathname.replace(/\/$/, "") || "/");
94
96
  function isItemActive(item: any): boolean {
95
97
  if (item.navs) return item.navs.some((c: any) => isItemActive(c));
96
98
  if (!item.href) return false;
97
- if (item.href === "/studio") return currentPath === "/studio";
98
- return currentPath === item.href || currentPath.startsWith(item.href + "/");
99
+ const itemHref = item.href.replace(/\/$/, "") || "/";
100
+ if (itemHref === "/studio") return currentPath === "/studio";
101
+ return currentPath === itemHref || currentPath.startsWith(itemHref + "/");
99
102
  }
100
103
 
101
104
  // onMount is enough — Studio gets remounted on login/logout (see
@@ -72,6 +72,8 @@
72
72
  extensions: [
73
73
  StarterKit.configure({
74
74
  heading: { levels: [1, 2, 3] },
75
+ underline: false,
76
+ link: false,
75
77
  }),
76
78
  UnderlineExt,
77
79
  LinkExt.configure({ openOnClick: false }),
@@ -8,7 +8,7 @@
8
8
  const { lobb, ctx } = getStudioContext();
9
9
  </script>
10
10
 
11
- <div class="grid overflow-auto bg-background">
11
+ <div class="grid h-full overflow-auto bg-background">
12
12
  {#key extension && page}
13
13
  <ExtensionsComponents
14
14
  name="pages.{page}"
@@ -3,29 +3,43 @@
3
3
  import { goto } from "$app/navigation";
4
4
  import { ArrowRight } from "lucide-svelte";
5
5
  import HomeFooter from "./homeFooter.svelte";
6
+ import ExtensionsComponents from "../extensionsComponents.svelte";
7
+ import { getExtensionUtils } from "../../extensions/extensionUtils";
8
+ import { getStudioContext } from "../../context";
9
+
10
+ const { lobb, ctx } = getStudioContext();
6
11
  </script>
7
12
 
8
- <div class="flex flex-col">
9
- <div
10
- class="flex flex-1 w-full flex-col items-center justify-center gap-4 text-muted-foreground"
11
- >
12
- <div class="flex flex-col items-center justify-center p-4">
13
- <div class="text-3xl">Welcome to Lobb!</div>
14
- <div class="text-xs text-center">
15
- Your journey starts here. Explore and make the most of your
16
- experience.
13
+ <!--
14
+ Any extension that registers a `pages.home` component takes over /studio
15
+ (e.g. an app-specific overview dashboard). ExtensionsComponents falls
16
+ back to rendering its children when nothing matches, so the default
17
+ Lobb welcome below stays as the safety net for projects without an
18
+ overriding extension.
19
+ -->
20
+ <ExtensionsComponents name="pages.home" utils={getExtensionUtils(lobb, ctx)}>
21
+ <div class="flex h-full flex-col">
22
+ <div
23
+ class="flex flex-1 w-full flex-col items-center justify-center gap-4 text-muted-foreground"
24
+ >
25
+ <div class="flex flex-col items-center justify-center p-4">
26
+ <div class="text-3xl">Welcome to Lobb!</div>
27
+ <div class="text-xs text-center">
28
+ Your journey starts here. Explore and make the most of your
29
+ experience.
30
+ </div>
31
+ </div>
32
+ <div class="flex flex-col items-center justify-center">
33
+ <Button
34
+ Icon={ArrowRight}
35
+ variant="outline"
36
+ class="h-7 px-3 text-xs font-normal"
37
+ onclick={() => goto("/studio/collections")}
38
+ >
39
+ Go to collections
40
+ </Button>
17
41
  </div>
18
42
  </div>
19
- <div class="flex flex-col items-center justify-center">
20
- <Button
21
- Icon={ArrowRight}
22
- variant="outline"
23
- class="h-7 px-3 text-xs font-normal"
24
- onclick={() => goto("/studio/collections")}
25
- >
26
- Go to collections
27
- </Button>
28
- </div>
43
+ <HomeFooter />
29
44
  </div>
30
- <HomeFooter />
31
- </div>
45
+ </ExtensionsComponents>
@@ -0,0 +1,104 @@
1
+ <script lang="ts">
2
+ import IMask from "imask";
3
+ import type { HTMLInputAttributes } from "svelte/elements";
4
+ import { cn } from "../../../utils.js";
5
+
6
+ // Locale-neutral grouping: space for thousands, dot for decimals
7
+ // (ISO 31-0). Norwegian, French, scientific contexts — same shape, and
8
+ // space can't be confused with comma-as-decimal vs comma-as-thousands.
9
+ const THOUSANDS = " ";
10
+ const RADIX = ".";
11
+
12
+ type Props = Omit<HTMLInputAttributes, "type" | "value" | "step"> & {
13
+ value?: number | string | null;
14
+ // 0 = integer-only, > 0 = allow that many decimal places.
15
+ scale?: number;
16
+ // When false, render a plain browser number input — no masking, no
17
+ // formatting. Default false so the component is safe to drop in
18
+ // anywhere; opt into grouping only where it makes sense.
19
+ groupDigits?: boolean;
20
+ };
21
+
22
+ let {
23
+ value = $bindable<number | string | null | undefined>(),
24
+ scale = 0,
25
+ groupDigits = false,
26
+ class: className,
27
+ ...rest
28
+ }: Props = $props();
29
+
30
+ let inputEl: HTMLInputElement | undefined = $state();
31
+ let mask: ReturnType<typeof IMask> | null = null;
32
+ // Re-entrance guard: imask's `accept` event fires when we programmatically
33
+ // set unmaskedValue, which would create a sync→reflect loop with the
34
+ // "external value changed" effect below.
35
+ let applyingExternal = false;
36
+
37
+ $effect(() => {
38
+ if (!groupDigits) return;
39
+ if (!inputEl) return;
40
+ mask = IMask(inputEl, {
41
+ mask: Number,
42
+ thousandsSeparator: THOUSANDS,
43
+ radix: RADIX,
44
+ scale,
45
+ signed: true,
46
+ padFractionalZeros: false,
47
+ normalizeZeros: true,
48
+ // Allow the user to type either radix; imask remaps to the chosen
49
+ // one and ignores stray locale separators on input.
50
+ mapToRadix: [",", "."],
51
+ });
52
+
53
+ mask.on("accept", () => {
54
+ if (applyingExternal) return;
55
+ const unmasked = mask!.unmaskedValue;
56
+ value = unmasked === "" ? null : Number(unmasked);
57
+ });
58
+
59
+ applyingExternal = true;
60
+ mask.unmaskedValue = value == null ? "" : String(value);
61
+ applyingExternal = false;
62
+
63
+ return () => {
64
+ mask?.destroy();
65
+ mask = null;
66
+ };
67
+ });
68
+
69
+ // Sync external value changes back into the mask (e.g. form reset, parent
70
+ // clearing the value). No-op when grouping is off.
71
+ $effect(() => {
72
+ const v = value;
73
+ if (!mask) return;
74
+ const next = v == null ? "" : String(v);
75
+ if (mask.unmaskedValue === next) return;
76
+ applyingExternal = true;
77
+ mask.unmaskedValue = next;
78
+ applyingExternal = false;
79
+ });
80
+ </script>
81
+
82
+ {#if groupDigits}
83
+ <input
84
+ bind:this={inputEl}
85
+ type="text"
86
+ inputmode={scale > 0 ? "decimal" : "numeric"}
87
+ class={cn(
88
+ "border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-base transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
89
+ className,
90
+ )}
91
+ {...rest}
92
+ />
93
+ {:else}
94
+ <input
95
+ type="number"
96
+ step={scale > 0 ? "any" : "1"}
97
+ class={cn(
98
+ "border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-base transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
99
+ className,
100
+ )}
101
+ bind:value
102
+ {...rest}
103
+ />
104
+ {/if}
@@ -0,0 +1,9 @@
1
+ import type { HTMLInputAttributes } from "svelte/elements";
2
+ type Props = Omit<HTMLInputAttributes, "type" | "value" | "step"> & {
3
+ value?: number | string | null;
4
+ scale?: number;
5
+ groupDigits?: boolean;
6
+ };
7
+ declare const NumberInput: import("svelte").Component<Props, {}, "value">;
8
+ type NumberInput = ReturnType<typeof NumberInput>;
9
+ export default NumberInput;
@@ -93,7 +93,7 @@
93
93
  return;
94
94
  }
95
95
 
96
- const reponse = await lobb.createOne("core_workflows", workflow);
96
+ const reponse = await lobb.createOne("core_workflows", { data: workflow });
97
97
  const result = await reponse.json();
98
98
  const workflowEntry = result.data;
99
99
  goto(`/studio/workflows/${workflowEntry.name}`);
@@ -107,9 +107,11 @@
107
107
  );
108
108
  }
109
109
  const reponse = await lobb.updateOne("core_workflows", workflow.id, {
110
- name: workflow.name,
111
- event_name: workflow.event_name,
112
- handler: workflow.handler,
110
+ data: {
111
+ name: workflow.name,
112
+ event_name: workflow.event_name,
113
+ handler: workflow.handler,
114
+ },
113
115
  });
114
116
  const result = await reponse.json();
115
117
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lobb-js/studio",
3
3
  "license": "UNLICENSED",
4
- "version": "0.30.0",
4
+ "version": "0.32.0",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -42,7 +42,7 @@
42
42
  "postpublish": "./scripts/postpublish.sh"
43
43
  },
44
44
  "devDependencies": {
45
- "@lobb-js/core": "^0.32.1",
45
+ "@lobb-js/core": "^0.33.0",
46
46
  "@chromatic-com/storybook": "^4.1.2",
47
47
  "@storybook/addon-a11y": "^10.0.1",
48
48
  "@storybook/addon-docs": "^10.0.1",
@@ -87,7 +87,7 @@
87
87
  "@codemirror/view": "^6.39.12",
88
88
  "@dagrejs/dagre": "^1.1.5",
89
89
  "@internationalized/date": "^3.12.0",
90
- "@lobb-js/sdk": "^0.2.1",
90
+ "@lobb-js/sdk": "^0.3.0",
91
91
  "@lucide/svelte": "^0.563.1",
92
92
  "@tailwindcss/vite": "^4.3.0",
93
93
  "@tiptap/core": "^3.0.0",
@@ -101,6 +101,7 @@
101
101
  "codemirror": "^6.0.2",
102
102
  "fflate": "^0.8.2",
103
103
  "fuse.js": "^7.3.0",
104
+ "imask": "^7.6.1",
104
105
  "javascript-time-ago": "^2.6.4",
105
106
  "json-stable-stringify": "^1.3.0",
106
107
  "lucide-svelte": "^0.488.0",
@@ -24,6 +24,8 @@ export interface OpenDataTableDrawerProps {
24
24
  export interface OpenDataTablePopupProps {
25
25
  collectionName: string;
26
26
  filter?: Record<string, any>;
27
+ sort?: Record<string, "asc" | "desc">;
28
+ limit?: number;
27
29
  title?: string;
28
30
  showHeader?: boolean;
29
31
  showFooter?: boolean;
@@ -4,7 +4,6 @@
4
4
  import { ModeWatcher } from "mode-watcher";
5
5
  import { createLobb } from "../store.svelte";
6
6
  import { setStudioContext } from "../context";
7
- import Header from "./header.svelte";
8
7
  import { LoaderCircle, ServerOff } from "lucide-svelte";
9
8
  import MiniSidebar from "./miniSidebar.svelte";
10
9
  import * as Tooltip from "./ui/tooltip";
@@ -107,8 +106,7 @@
107
106
  style="display: grid; grid-template-columns: {isSmallScreen ? '1fr' : '3.5rem 1fr'};"
108
107
  >
109
108
  <MiniSidebar />
110
- <div class="second_grid">
111
- <Header />
109
+ <div class="min-h-0 h-screen overflow-hidden">
112
110
  {#if page.url.pathname.replace(/\/$/, "") === "/studio"}
113
111
  <Home />
114
112
  {:else if page.url.pathname.startsWith("/studio/collections")}
@@ -131,10 +129,3 @@
131
129
  </main>
132
130
  </Tooltip.Provider>
133
131
  {/if}
134
-
135
- <style>
136
- .second_grid {
137
- display: grid;
138
- grid-template-rows: 2.5rem 1fr;
139
- }
140
- </style>