@lobb-js/studio 0.28.6 → 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 (160) hide show
  1. package/README.md +1 -0
  2. package/dist/actions.d.ts +2 -0
  3. package/dist/components/Studio.svelte +46 -47
  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/combobox.svelte +3 -3
  9. package/dist/components/confirmationDialog/confirmationDialog.svelte +1 -1
  10. package/dist/components/dataTable/dataTable.svelte +108 -101
  11. package/dist/components/dataTable/dataTable.svelte.d.ts +5 -20
  12. package/dist/components/dataTable/dataTableTabs.svelte +4 -2
  13. package/dist/components/dataTable/dataTableTabs.svelte.d.ts +2 -0
  14. package/dist/components/dataTable/filter.svelte +1 -1
  15. package/dist/components/dataTable/filterButton.svelte +1 -1
  16. package/dist/components/dataTable/header.svelte +30 -47
  17. package/dist/components/dataTable/header.svelte.d.ts +4 -2
  18. package/dist/components/dataTable/listViewChildren.svelte +4 -6
  19. package/dist/components/dataTable/listViewChildren.svelte.d.ts +0 -1
  20. package/dist/components/dataTable/sort.svelte +1 -1
  21. package/dist/components/dataTable/sortButton.svelte +2 -2
  22. package/dist/components/dataTable/table.svelte +8 -10
  23. package/dist/components/dataTable/table.svelte.d.ts +0 -1
  24. package/dist/components/dataTableDrawer/dataTableDrawer.svelte +4 -1
  25. package/dist/components/dataTableDrawer/dataTableDrawer.svelte.d.ts +2 -0
  26. package/dist/components/detailView/create/children.svelte +2 -2
  27. package/dist/components/detailView/create/createDetailView.svelte +81 -88
  28. package/dist/components/detailView/create/createDetailView.svelte.d.ts +2 -2
  29. package/dist/components/detailView/create/createDetailViewButton.svelte +2 -2
  30. package/dist/components/detailView/create/createDetailViewButton.svelte.d.ts +1 -1
  31. package/dist/components/detailView/create/createManyView.svelte +12 -10
  32. package/dist/components/detailView/detailView.svelte +81 -0
  33. package/dist/components/detailView/detailView.svelte.d.ts +8 -0
  34. package/dist/components/detailView/fieldInput.svelte +11 -11
  35. package/dist/components/detailView/fieldInputReplacement.svelte +8 -8
  36. package/dist/components/detailView/passwordInput.svelte +1 -1
  37. package/dist/components/detailView/update/detailViewChildren.svelte +15 -26
  38. package/dist/components/detailView/update/detailViewChildren.svelte.d.ts +3 -8
  39. package/dist/components/detailView/update/updateDetailView.svelte +90 -69
  40. package/dist/components/detailView/update/updateDetailView.svelte.d.ts +2 -2
  41. package/dist/components/detailView/update/updateDetailViewButton.svelte +3 -2
  42. package/dist/components/detailView/update/updateDetailViewButton.svelte.d.ts +1 -1
  43. package/dist/components/detailView/utils.d.ts +17 -0
  44. package/dist/components/diffViewer.svelte +1 -1
  45. package/dist/components/extensionsComponents.svelte +3 -1
  46. package/dist/components/foreingKeyInput.svelte +2 -2
  47. package/dist/components/importButton.svelte +12 -9
  48. package/dist/components/landing.svelte +7 -0
  49. package/dist/components/landing.svelte.d.ts +6 -14
  50. package/dist/components/miniSidebar.svelte +90 -19
  51. package/dist/components/miniSidebar.svelte.d.ts +2 -17
  52. package/dist/components/polymorphicInput.svelte +1 -1
  53. package/dist/components/rangeCalendarButton.svelte +13 -13
  54. package/dist/components/richTextEditor.svelte +1 -1
  55. package/dist/components/routes/collections/collection.svelte +3 -3
  56. package/dist/components/routes/collections/collections.svelte +34 -12
  57. package/dist/components/routes/data_model/dataModel.svelte +6 -28
  58. package/dist/components/routes/data_model/dataModel.svelte.d.ts +17 -2
  59. package/dist/components/routes/extensions/extension.svelte +1 -1
  60. package/dist/components/routes/extensions/publicExtension.svelte +19 -0
  61. package/dist/components/routes/extensions/publicExtension.svelte.d.ts +13 -0
  62. package/dist/components/routes/home.svelte +3 -3
  63. package/dist/components/routes/workflows/workflows.svelte +9 -9
  64. package/dist/components/selectRecord.svelte +2 -21
  65. package/dist/components/setServerPage.svelte +1 -1
  66. package/dist/components/sidebar/sidebar.svelte +1 -1
  67. package/dist/components/sidebar/sidebarElements.svelte +4 -4
  68. package/dist/components/singletone.svelte +4 -6
  69. package/dist/components/ui/alert-dialog/alert-dialog-action.svelte +1 -1
  70. package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte +1 -1
  71. package/dist/components/ui/button/button.svelte +2 -3
  72. package/dist/components/ui/command/command-dialog.svelte +1 -1
  73. package/dist/components/ui/range-calendar/range-calendar-day.svelte +1 -1
  74. package/dist/components/ui/range-calendar/range-calendar-next-button.svelte +1 -1
  75. package/dist/components/ui/range-calendar/range-calendar-prev-button.svelte +1 -1
  76. package/dist/components/ui/select/select-separator.svelte +1 -1
  77. package/dist/components/workflowEditor.svelte +5 -5
  78. package/dist/eventSystem.d.ts +1 -1
  79. package/dist/eventSystem.js +7 -5
  80. package/dist/extensions/extension.types.d.ts +38 -14
  81. package/dist/extensions/extensionUtils.js +4 -2
  82. package/dist/index.d.ts +3 -1
  83. package/dist/index.js +3 -1
  84. package/dist/store.types.d.ts +2 -2
  85. package/dist/studioLifecycle.svelte.d.ts +2 -0
  86. package/dist/studioLifecycle.svelte.js +15 -0
  87. package/package.json +3 -4
  88. package/src/app.css +3 -0
  89. package/src/lib/actions.ts +2 -0
  90. package/src/lib/components/Studio.svelte +46 -47
  91. package/src/lib/components/StudioRoot.svelte +19 -0
  92. package/src/lib/components/breadCrumbs.svelte +5 -4
  93. package/src/lib/components/codeEditor.svelte +1 -1
  94. package/src/lib/components/combobox.svelte +3 -3
  95. package/src/lib/components/confirmationDialog/confirmationDialog.svelte +1 -1
  96. package/src/lib/components/dataTable/dataTable.svelte +108 -101
  97. package/src/lib/components/dataTable/dataTableTabs.svelte +4 -2
  98. package/src/lib/components/dataTable/filter.svelte +1 -1
  99. package/src/lib/components/dataTable/filterButton.svelte +1 -1
  100. package/src/lib/components/dataTable/header.svelte +30 -47
  101. package/src/lib/components/dataTable/listViewChildren.svelte +4 -6
  102. package/src/lib/components/dataTable/sort.svelte +1 -1
  103. package/src/lib/components/dataTable/sortButton.svelte +2 -2
  104. package/src/lib/components/dataTable/table.svelte +8 -10
  105. package/src/lib/components/dataTableDrawer/dataTableDrawer.svelte +4 -1
  106. package/src/lib/components/detailView/create/children.svelte +2 -2
  107. package/src/lib/components/detailView/create/createDetailView.svelte +81 -88
  108. package/src/lib/components/detailView/create/createDetailViewButton.svelte +2 -2
  109. package/src/lib/components/detailView/create/createManyView.svelte +12 -10
  110. package/src/lib/components/detailView/detailView.svelte +81 -0
  111. package/src/lib/components/detailView/fieldInput.svelte +11 -11
  112. package/src/lib/components/detailView/fieldInputReplacement.svelte +8 -8
  113. package/src/lib/components/detailView/passwordInput.svelte +1 -1
  114. package/src/lib/components/detailView/update/detailViewChildren.svelte +15 -26
  115. package/src/lib/components/detailView/update/updateDetailView.svelte +90 -69
  116. package/src/lib/components/detailView/update/updateDetailViewButton.svelte +3 -2
  117. package/src/lib/components/detailView/utils.ts +13 -0
  118. package/src/lib/components/diffViewer.svelte +1 -1
  119. package/src/lib/components/extensionsComponents.svelte +3 -1
  120. package/src/lib/components/foreingKeyInput.svelte +2 -2
  121. package/src/lib/components/importButton.svelte +12 -9
  122. package/src/lib/components/landing.svelte +7 -0
  123. package/src/lib/components/miniSidebar.svelte +90 -19
  124. package/src/lib/components/polymorphicInput.svelte +1 -1
  125. package/src/lib/components/rangeCalendarButton.svelte +13 -13
  126. package/src/lib/components/richTextEditor.svelte +1 -1
  127. package/src/lib/components/routes/collections/collection.svelte +3 -3
  128. package/src/lib/components/routes/collections/collections.svelte +34 -12
  129. package/src/lib/components/routes/data_model/dataModel.svelte +6 -28
  130. package/src/lib/components/routes/extensions/extension.svelte +1 -1
  131. package/src/lib/components/routes/extensions/publicExtension.svelte +19 -0
  132. package/src/lib/components/routes/home.svelte +3 -3
  133. package/src/lib/components/routes/workflows/workflows.svelte +9 -9
  134. package/src/lib/components/selectRecord.svelte +2 -21
  135. package/src/lib/components/setServerPage.svelte +1 -1
  136. package/src/lib/components/sidebar/sidebar.svelte +1 -1
  137. package/src/lib/components/sidebar/sidebarElements.svelte +4 -4
  138. package/src/lib/components/singletone.svelte +4 -6
  139. package/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +1 -1
  140. package/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +1 -1
  141. package/src/lib/components/ui/button/button.svelte +2 -3
  142. package/src/lib/components/ui/command/command-dialog.svelte +1 -1
  143. package/src/lib/components/ui/range-calendar/range-calendar-day.svelte +1 -1
  144. package/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte +1 -1
  145. package/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte +1 -1
  146. package/src/lib/components/ui/select/select-separator.svelte +1 -1
  147. package/src/lib/components/workflowEditor.svelte +5 -5
  148. package/src/lib/eventSystem.ts +8 -7
  149. package/src/lib/extensions/extension.types.ts +39 -6
  150. package/src/lib/extensions/extensionUtils.ts +4 -2
  151. package/src/lib/index.ts +3 -1
  152. package/src/lib/store.types.ts +2 -2
  153. package/src/lib/studioLifecycle.svelte.ts +17 -0
  154. package/vite-plugins/index.js +2 -4
  155. package/vite-plugins/utils.js +15 -0
  156. package/vite-plugins/{workspace-optimize.js → workspace-fs-allow.js} +4 -18
  157. package/dist/components/routes/data_model/syncManager.svelte +0 -94
  158. package/dist/components/routes/data_model/syncManager.svelte.d.ts +0 -3
  159. package/src/lib/components/routes/data_model/syncManager.svelte +0 -94
  160. package/vite-plugins/contextual-lib-alias.js +0 -67
@@ -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>
@@ -2,7 +2,7 @@
2
2
  import { getStudioContext } from "../../../context";
3
3
  import { Link } from "lucide-svelte";
4
4
  import CreateManyView from "./createManyView.svelte";
5
- import ExtensionsComponents from "../../../components/extensionsComponents.svelte";
5
+ import ExtensionsComponents from "../../extensionsComponents.svelte";
6
6
  import { getExtensionUtils } from "../../../extensions/extensionUtils";
7
7
 
8
8
  const { ctx, lobb } = getStudioContext();
@@ -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
@@ -8,114 +8,142 @@
8
8
  collectionName: string;
9
9
  values?: Record<string, any>;
10
10
  showRelatedRecords?: boolean;
11
- rollback?: boolean;
12
11
  submitButton?: SubmitButton;
13
12
  title?: Snippet<[string]>;
14
13
  onSuccessfullSave?: (entry: any) => Promise<void>;
15
14
  onCancel?: () => Promise<void>;
15
+ changes?: import("../utils").Changes | undefined;
16
16
  }
17
17
  </script>
18
18
 
19
19
  <script lang="ts">
20
20
  import { ArrowLeft, Plus, X } from "lucide-svelte";
21
- import Button from "../../../components/ui/button/button.svelte";
21
+ import Button from "../../ui/button/button.svelte";
22
22
  import { getStudioContext } from "../../../context";
23
23
  import { toast } from "svelte-sonner";
24
+ import { untrack } from "svelte";
24
25
 
25
26
  const { lobb, ctx } = getStudioContext();
26
- import ExtensionsComponents from "../../extensionsComponents.svelte";
27
- import { getExtensionUtils } from "../../../extensions/extensionUtils";
28
- import { getField, getFieldIcon } from "../../dataTable/utils";
29
27
  import Children from "./children.svelte";
30
- import {
31
- buildChildren,
32
- getDefaultEntry,
33
- } from "../utils";
28
+ import { buildChildren, getDefaultEntry } from "../utils";
29
+ import type { Changes } from "../utils";
34
30
  import { getChangedProperties } from "../../../utils";
35
31
  import type { Snippet } from "svelte";
36
- import FieldInput from "../fieldInput.svelte";
37
- import { emitEvent } from "../../../eventSystem";
38
- import Drawer from "../../../components/drawer.svelte";
32
+ import DetailView from "../detailView.svelte";
33
+ import Drawer from "../../drawer.svelte";
39
34
 
40
35
  let {
41
36
  collectionName,
42
- values = {},
37
+ values: passedValues = {} as Record<string, any>,
43
38
  showRelatedRecords = true,
44
- rollback = false,
45
39
  onCancel,
46
40
  onSuccessfullSave,
47
41
  title,
48
42
  submitButton,
43
+ changes: passedChanges = $bindable<Changes | undefined>(undefined),
49
44
  }: CreateDetailViewProp = $props();
50
45
 
46
+ const isRecordingMode = passedChanges !== undefined;
47
+ if (!isRecordingMode) passedChanges = { data: {}, children: {} };
48
+ const changes = passedChanges as Changes;
49
+
51
50
  const fieldNames = Object.keys(ctx.meta.collections[collectionName].fields);
52
- let entry: Record<string, any> = $state(
53
- getDefaultEntry(ctx, fieldNames, collectionName, values),
54
- );
55
- const initialEntry = $state.snapshot(entry);
51
+ let values = $state(getDefaultEntry(ctx, fieldNames, collectionName, passedValues));
56
52
  let fieldsErrors: Record<string, any> = $state({});
57
- const subCollections = ctx.meta.relations.filter((relation) => relation.to.collection === collectionName).map((relation) => relation.from.collection);
53
+
54
+ const childCollections = ctx.meta.relations
55
+ .filter((r) => r.to.collection === collectionName)
56
+ .map((r) => (r as any).from.collection);
57
+
58
58
  const subCollectionsValues: Record<string, any> = {};
59
- for (let index = 0; index < subCollections.length; index++) {
60
- const subCollection = subCollections[index];
61
- if (values[subCollection]) {
62
- subCollectionsValues[subCollection] = values[subCollection];
63
- }
59
+ for (const col of childCollections) {
60
+ if (passedValues[col]) subCollectionsValues[col] = passedValues[col];
64
61
  }
65
62
 
66
- async function handleSave() {
67
- let localEntry = getChangedProperties(initialEntry, $state.snapshot(entry));
63
+ $effect(() => {
64
+ const snap = $state.snapshot(values);
68
65
 
69
- await emitEvent({ lobb, ctx }, "studio.collections.preCreate", {
70
- collectionName,
71
- entry: localEntry,
72
- });
66
+ untrack(() => {
67
+ const data: Record<string, any> = {};
68
+ const children: Record<string, any> = {};
73
69
 
74
- // remove empty children records data
75
- for (const [key, value] of Object.entries(localEntry)) {
76
- if (Array.isArray(value) && !value.length) {
77
- delete localEntry[key];
70
+ for (const [key, value] of Object.entries(snap)) {
71
+ if (childCollections.includes(key) && Array.isArray(value)) {
72
+ children[key] = {
73
+ created: (value as any[]).filter((r) => !r.id).map((r) => ({ data: r })),
74
+ updated: [],
75
+ deleted: [],
76
+ linked: (value as any[]).filter((r) => r.id).map((r) => r.id),
77
+ unlinked: [],
78
+ };
79
+ } else if (value !== null && value !== undefined && value !== '') {
80
+ data[key] = value;
81
+ }
78
82
  }
79
- }
80
83
 
81
- if (rollback) {
82
- if (onSuccessfullSave) await onSuccessfullSave(localEntry);
83
- onCancel?.();
84
- return;
84
+ changes.data = data;
85
+ changes.children = children;
86
+
87
+ if (!isRecordingMode) {
88
+ console.log(`[${collectionName}] changes:`, $state.snapshot(changes));
89
+ }
90
+ });
91
+ });
92
+
93
+ function handleCancel() {
94
+ if (isRecordingMode) {
95
+ changes.data = {};
96
+ changes.children = {};
85
97
  }
98
+ onCancel?.();
99
+ }
86
100
 
87
- const children = buildChildren(ctx, collectionName, localEntry);
88
- const response = await lobb.createOne(collectionName, localEntry, children);
101
+ async function handleSave() {
102
+ const snap = $state.snapshot(changes);
89
103
 
90
- await emitEvent({ lobb, ctx }, "studio.collections.create", {
91
- collectionName,
92
- entry: localEntry,
93
- response: response,
94
- });
104
+ const children = buildChildren(ctx, collectionName, { ...snap.data, ...Object.fromEntries(
105
+ Object.entries(snap.children).map(([col, ops]) => [
106
+ col,
107
+ [
108
+ ...(ops.created.map((op) => op.data)),
109
+ ...(ops.linked.map((id) => ({ id }))),
110
+ ]
111
+ ])
112
+ )});
113
+
114
+ const response = await lobb.createOne(collectionName, snap.data, children, undefined, isRecordingMode);
115
+
116
+ if (response.status === 204) {
117
+ if (onSuccessfullSave) await onSuccessfullSave(snap);
118
+ toast.success(`The record was successfully created`);
119
+ handleCancel();
120
+ return;
121
+ }
95
122
 
96
123
  if (!response.bodyUsed) {
97
- let result = await response.json();
124
+ const result = await response.json();
98
125
  if (response.status >= 400) {
99
126
  if (result.message && result.details) {
100
127
  fieldsErrors = result.details;
101
128
  return;
102
129
  } else if (result.message) {
130
+ toast.error(result.message);
103
131
  return;
104
132
  }
105
133
  }
106
134
  }
107
135
 
108
- if (onSuccessfullSave) await onSuccessfullSave(localEntry);
136
+ if (onSuccessfullSave) await onSuccessfullSave(snap);
109
137
  toast.success(`The record was successfully created`);
110
138
  onCancel?.();
111
139
  }
112
140
  </script>
113
141
 
114
- <Drawer onHide={onCancel}>
142
+ <Drawer onHide={handleCancel}>
115
143
  <div class="flex h-12 items-center gap-4 border-b px-4">
116
144
  <Button
117
145
  variant="outline"
118
- onclick={onCancel}
146
+ onclick={handleCancel}
119
147
  class=" h-8 w-8 rounded-full text-xs font-normal"
120
148
  Icon={ArrowLeft}
121
149
  ></Button>
@@ -131,51 +159,16 @@
131
159
  </div>
132
160
  </div>
133
161
  <div class="flex-1 overflow-y-auto">
134
- <div class="flex flex-col gap-4 p-4">
135
- {#each fieldNames as fieldName}
136
- {#if !ctx.meta.collections[collectionName].fields[fieldName]?.ui?.hidden}
137
- {@const field = getField(ctx, fieldName, collectionName)}
138
- {@const FieldIcon = getFieldIcon(ctx, fieldName, collectionName)}
139
- <div class="flex flex-col gap-2">
140
- <div class="flex flex-1 items-end justify-between gap-2 text-xs">
141
- <div class="flex gap-2">
142
- <div class="h-fit">{field.label}</div>
143
- <div class="flex h-fit items-center gap-1 text-[0.7rem] text-muted-foreground">
144
- <FieldIcon size="12" />
145
- {field.type}
146
- </div>
147
- </div>
148
- <div>
149
- <ExtensionsComponents
150
- name="dvFields.topRight.{collectionName}.{fieldName}"
151
- utils={getExtensionUtils(lobb, ctx)}
152
- bind:value={entry[fieldName]}
153
- />
154
- </div>
155
- </div>
156
- <FieldInput
157
- {collectionName}
158
- {fieldName}
159
- bind:value={
160
- () => entry[fieldName],
161
- (v) => (entry = { ...entry, [fieldName]: v })
162
- }
163
- bind:entry
164
- errorMessages={fieldsErrors[fieldName]}
165
- />
166
- </div>
167
- {/if}
168
- {/each}
169
- </div>
162
+ <DetailView {collectionName} bind:entry={values} {fieldsErrors} />
170
163
  {#if showRelatedRecords}
171
- <Children {collectionName} values={subCollectionsValues} bind:entry />
164
+ <Children {collectionName} values={subCollectionsValues} bind:entry={values} />
172
165
  {/if}
173
166
  </div>
174
167
  <div class="flex h-12 items-center justify-end gap-2 border-t px-4">
175
168
  <div class="flex gap-3">
176
169
  <Button
177
170
  variant="outline"
178
- onclick={onCancel}
171
+ onclick={handleCancel}
179
172
  class="h-7 px-3 text-xs font-normal"
180
173
  Icon={X}
181
174
  >
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { CreateDetailViewProp } from "./createDetailView.svelte";
3
- import type { ButtonProps } from "../../../components/ui/button/button.svelte";
4
- import Button from "../../../components/ui/button/button.svelte";
3
+ import type { ButtonProps } from "../../ui/button/button.svelte";
4
+ import Button from "../../ui/button/button.svelte";
5
5
  import CreateDetailView from "./createDetailView.svelte";
6
6
 
7
7
  interface LocalProp extends CreateDetailViewProp {
@@ -11,11 +11,15 @@
11
11
  import Table, { type TableProps } from "../../dataTable/table.svelte";
12
12
  import Button from "../../ui/button/button.svelte";
13
13
  import CreateDetailViewButton from "./createDetailViewButton.svelte";
14
- import { getCollectionColumns } from "../../../components/dataTable/utils";
15
- import SelectRecord from "../../../components/selectRecord.svelte";
16
- import FieldCell from "../../../components/dataTable/fieldCell.svelte";
14
+ import type { Changes } from "../utils";
15
+
16
+ let addChanges = $state<Changes>({ data: {}, children: {} });
17
+ let editChanges = $state<Changes>({ data: {}, children: {} });
18
+ import { getCollectionColumns } from "../../dataTable/utils";
19
+ import SelectRecord from "../../selectRecord.svelte";
20
+ import FieldCell from "../../dataTable/fieldCell.svelte";
17
21
  import SubRecords from "./subRecords.svelte";
18
- import ListViewChildren from "../../../components/dataTable/listViewChildren.svelte";
22
+ import ListViewChildren from "../../dataTable/listViewChildren.svelte";
19
23
  import { getStudioContext } from "../../../context";
20
24
 
21
25
  const { ctx } = getStudioContext();
@@ -108,7 +112,7 @@
108
112
  >
109
113
  <div
110
114
  class="
111
- flex items-center justify-between px-2 h-10 bg-muted/30
115
+ flex items-center justify-between px-2 h-10 bg-muted-soft
112
116
  {expanded ? 'border-b' : ''}
113
117
  "
114
118
  >
@@ -141,7 +145,7 @@
141
145
  class="h-7 px-2 font-normal text-xs"
142
146
  Icon={Plus}
143
147
  {collectionName}
144
- rollback={true}
148
+ changes={addChanges}
145
149
  showRelatedRecords={true}
146
150
  onSuccessfullSave={onRecordAdd}
147
151
  values={createValues}
@@ -161,13 +165,12 @@
161
165
  </div>
162
166
  </div>
163
167
  {#if expanded}
164
- <div bind:clientWidth={tableWidth} class="bg-muted/30 overflow-auto">
168
+ <div bind:clientWidth={tableWidth} class="bg-muted-soft overflow-auto">
165
169
  <Table
166
170
  data={entries}
167
171
  {columns}
168
172
  selectByColumn="id"
169
173
  showCollapsible={doesCollectionHasChildren}
170
- unifiedBgColor="bg-muted/30"
171
174
  >
172
175
  {#snippet tools(entry, index)}
173
176
  <Button
@@ -197,7 +200,7 @@
197
200
  class="h-6 w-6 text-muted-foreground hover:bg-transparent p-0"
198
201
  Icon={Pencil}
199
202
  {collectionName}
200
- rollback={true}
203
+ changes={editChanges}
201
204
  showRelatedRecords={true}
202
205
  onSuccessfullSave={(entry) =>
203
206
  onRecordOverride(entry, index)}
@@ -236,7 +239,6 @@
236
239
  {collectionName}
237
240
  recordId={entry.id}
238
241
  width={tableWidth}
239
- unifiedBgColor="bg-muted/30"
240
242
  />
241
243
  {:else}
242
244
  <SubRecords
@@ -0,0 +1,81 @@
1
+ <script lang="ts">
2
+ import { CircleHelp } from "lucide-svelte";
3
+ import * as Tooltip from "../ui/tooltip";
4
+ import { getStudioContext } from "../../context";
5
+ import ExtensionsComponents from "../extensionsComponents.svelte";
6
+ import { getExtensionUtils } from "../../extensions/extensionUtils";
7
+ import { getField, getFieldIcon } from "../dataTable/utils";
8
+ import FieldInput from "./fieldInput.svelte";
9
+
10
+ interface Props {
11
+ collectionName: string;
12
+ entry: Record<string, any>;
13
+ fieldsErrors?: Record<string, string[]>;
14
+ }
15
+
16
+ let {
17
+ collectionName,
18
+ entry = $bindable(),
19
+ fieldsErrors = {},
20
+ }: Props = $props();
21
+
22
+ const { lobb, ctx } = getStudioContext();
23
+ const fieldNames = $derived(
24
+ Object.keys(ctx.meta.collections[collectionName].fields),
25
+ );
26
+ </script>
27
+
28
+ <div class="flex flex-col gap-4 p-4">
29
+ {#each fieldNames as fieldName}
30
+ {#if !ctx.meta.collections[collectionName].fields[fieldName]?.ui?.hidden}
31
+ {@const field = getField(ctx, fieldName, collectionName)}
32
+ {@const FieldIcon = getFieldIcon(ctx, fieldName, collectionName)}
33
+ {@const description = ctx.meta.collections[collectionName].fields[fieldName]?.description}
34
+ <div class="flex flex-col gap-2">
35
+ <div class="flex flex-1 items-end justify-between gap-2 text-xs">
36
+ <div class="flex items-center gap-1.5">
37
+ <ExtensionsComponents
38
+ name="detailView.field.label"
39
+ utils={getExtensionUtils(lobb, ctx)}
40
+ {collectionName}
41
+ {fieldName}
42
+ bind:value={entry[fieldName]}
43
+ >
44
+ <div class="flex items-center gap-1.5">
45
+ <div class="h-fit">{field.label}</div>
46
+ <div class="flex h-fit items-center gap-1 text-[0.7rem] text-muted-foreground">
47
+ <FieldIcon size="12" />
48
+ {field.type}
49
+ </div>
50
+ </div>
51
+ </ExtensionsComponents>
52
+ {#if description}
53
+ <Tooltip.Root>
54
+ <Tooltip.Trigger>
55
+ <CircleHelp size="12" class="text-muted-foreground" />
56
+ </Tooltip.Trigger>
57
+ <Tooltip.Content class="max-w-64 text-xs">
58
+ {description}
59
+ </Tooltip.Content>
60
+ </Tooltip.Root>
61
+ {/if}
62
+ </div>
63
+ <div>
64
+ <ExtensionsComponents
65
+ name="dvFields.topRight.{collectionName}.{fieldName}"
66
+ utils={getExtensionUtils(lobb, ctx)}
67
+ bind:value={entry[fieldName]}
68
+ />
69
+ </div>
70
+ </div>
71
+ <FieldInput
72
+ {collectionName}
73
+ {fieldName}
74
+ bind:value={entry[fieldName]}
75
+ bind:entry
76
+ errorMessages={fieldsErrors[fieldName]}
77
+ />
78
+ </div>
79
+ {/if}
80
+ {/each}
81
+ </div>
@@ -6,7 +6,7 @@
6
6
  import Button from "../ui/button/button.svelte";
7
7
  import FieldCustomInput from "./fieldCustomInput.svelte";
8
8
  import Input from "../ui/input/input.svelte";
9
- import * as Select from "../../components/ui/select/index";
9
+ import * as Select from "../ui/select/index";
10
10
  import EnumBadge from "../dataTable/enumBadge.svelte";
11
11
  import type { EnumOption } from "@lobb-js/core";
12
12
  import Textarea from "../ui/textarea/textarea.svelte";
@@ -86,7 +86,7 @@
86
86
  {:else if field.label === "id"}
87
87
  <Input
88
88
  placeholder="AUTO GENERATED"
89
- class="bg-muted/30 text-xs"
89
+ class="bg-muted-soft text-xs"
90
90
  bind:value
91
91
  />
92
92
  {:else if fieldRelationTarget && entry}
@@ -126,7 +126,7 @@
126
126
  >
127
127
  <Select.Trigger
128
128
  class="
129
- h-9 w-full bg-muted/30 pr-8
129
+ h-9 w-full bg-muted-soft pr-8
130
130
  {destructive ? 'border-destructive bg-destructive/10' : ''}
131
131
  "
132
132
  >
@@ -158,7 +158,7 @@
158
158
  placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
159
159
  type="text"
160
160
  class="
161
- bg-muted/30 text-xs
161
+ bg-muted-soft text-xs
162
162
  {destructive ? 'border-destructive bg-destructive/10' : ''}
163
163
  "
164
164
  bind:value
@@ -168,7 +168,7 @@
168
168
  placeholder={ui?.placeholder ? ui.placeholder : value === "" ? "EMPTY STRING" : "NULL"}
169
169
  rows={5}
170
170
  class="
171
- bg-muted/30 text-xs
171
+ bg-muted-soft text-xs
172
172
  {destructive ? 'border-destructive bg-destructive/10' : ''}
173
173
  "
174
174
  bind:value
@@ -178,7 +178,7 @@
178
178
  type="date"
179
179
  placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
180
180
  class="
181
- dateInput block w-full bg-muted/30 pr-9 text-xs
181
+ dateInput block w-full bg-muted-soft pr-9 text-xs
182
182
  {destructive ? 'border-destructive bg-destructive/10' : ''}
183
183
  "
184
184
  bind:value={
@@ -197,7 +197,7 @@
197
197
  type="time"
198
198
  placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
199
199
  class="
200
- dateInput block w-full bg-muted/30 pr-9 text-xs
200
+ dateInput block w-full bg-muted-soft pr-9 text-xs
201
201
  {destructive ? 'border-destructive bg-destructive/10' : ''}
202
202
  "
203
203
  bind:value={
@@ -215,7 +215,7 @@
215
215
  type="datetime-local"
216
216
  placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
217
217
  class="
218
- dateInput block w-full bg-muted/30 pr-9 text-xs
218
+ dateInput block w-full bg-muted-soft pr-9 text-xs
219
219
  {destructive ? 'border-destructive bg-destructive/10' : ''}
220
220
  "
221
221
  bind:value={
@@ -236,7 +236,7 @@
236
236
  <Select.Trigger
237
237
  placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
238
238
  class="
239
- bg-muted/30 pr-9
239
+ bg-muted-soft pr-9
240
240
  {destructive ? 'border-destructive bg-destructive/10' : ''}
241
241
  "
242
242
  >
@@ -263,7 +263,7 @@
263
263
  type="number"
264
264
  step="any"
265
265
  class="
266
- bg-muted/30 text-xs
266
+ bg-muted-soft text-xs
267
267
  {destructive ? 'border-destructive bg-destructive/10' : ''}
268
268
  "
269
269
  bind:value
@@ -273,7 +273,7 @@
273
273
  placeholder={ui?.placeholder ? ui.placeholder : "NULL"}
274
274
  type="number"
275
275
  class="
276
- bg-muted/30 text-xs
276
+ bg-muted-soft text-xs
277
277
  {destructive ? 'border-destructive bg-destructive/10' : ''}
278
278
  "
279
279
  bind:value
@@ -2,7 +2,7 @@
2
2
  import { Ban, Check, CircleAlert, X } from "lucide-svelte";
3
3
  import Button from "../ui/button/button.svelte";
4
4
  import Input from "../ui/input/input.svelte";
5
- import * as Select from "../../components/ui/select/index";
5
+ import * as Select from "../ui/select/index";
6
6
  import Textarea from "../ui/textarea/textarea.svelte";
7
7
  import type { EntryField } from "./detailViewForm.svelte";
8
8
  import type { Snippet } from "svelte";
@@ -49,7 +49,7 @@
49
49
  placeholder={field.placeholder ? field.placeholder : "NULL"}
50
50
  type="text"
51
51
  class="
52
- bg-muted/30 text-xs
52
+ bg-muted-soft text-xs
53
53
  {destructive ? 'border-destructive bg-destructive/10' : ''}
54
54
  "
55
55
  bind:value
@@ -64,7 +64,7 @@
64
64
  <Select.Trigger
65
65
  placeholder={field.placeholder ? field.placeholder : "NULL"}
66
66
  class="
67
- h-9 w-full bg-muted/30 pr-8
67
+ h-9 w-full bg-muted-soft pr-8
68
68
  {destructive ? 'border-destructive bg-destructive/10' : ''}
69
69
  "
70
70
  >
@@ -84,7 +84,7 @@
84
84
  placeholder={field.placeholder ? field.placeholder : value === "" ? "EMPTY STRING" : "NULL"}
85
85
  rows={5}
86
86
  class="
87
- bg-muted/30 text-xs
87
+ bg-muted-soft text-xs
88
88
  {destructive ? 'border-destructive bg-destructive/10' : ''}
89
89
  "
90
90
  bind:value
@@ -98,7 +98,7 @@
98
98
  <Input
99
99
  type="date"
100
100
  class="
101
- dateInput block w-full bg-muted/30 pr-9 text-xs
101
+ dateInput block w-full bg-muted-soft pr-9 text-xs
102
102
  {destructive ? 'border-destructive bg-destructive/10' : ''}
103
103
  "
104
104
  bind:value={
@@ -116,7 +116,7 @@
116
116
  <Input
117
117
  type="time"
118
118
  class="
119
- dateInput block w-full bg-muted/30 pr-9 text-xs
119
+ dateInput block w-full bg-muted-soft pr-9 text-xs
120
120
  {destructive ? 'border-destructive bg-destructive/10' : ''}
121
121
  "
122
122
  bind:value={
@@ -133,7 +133,7 @@
133
133
  <Input
134
134
  type="datetime-local"
135
135
  class="
136
- dateInput block w-full bg-muted/30 pr-9 text-xs
136
+ dateInput block w-full bg-muted-soft pr-9 text-xs
137
137
  {destructive ? 'border-destructive bg-destructive/10' : ''}
138
138
  "
139
139
  bind:value={
@@ -154,7 +154,7 @@
154
154
  <Select.Root type="single" bind:value>
155
155
  <Select.Trigger
156
156
  class="
157
- bg-muted/30 pr-9
157
+ bg-muted-soft pr-9
158
158
  {destructive ? 'border-destructive bg-destructive/10' : ''}
159
159
  "
160
160
  >
@@ -21,7 +21,7 @@
21
21
  <Input
22
22
  type="password"
23
23
  placeholder="••••••"
24
- class="bg-muted/30 text-xs {destructive ? 'border-destructive bg-destructive/10' : ''}"
24
+ class="bg-muted-soft text-xs {destructive ? 'border-destructive bg-destructive/10' : ''}"
25
25
  value={displayValue}
26
26
  oninput={onInput}
27
27
  />