@lobb-js/studio 0.1.41 → 0.1.43

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.
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
- import { lobb } from "..";
2
+ import { lobb, ctx } from "../store.svelte";
3
3
  import { Brain, LoaderIcon, Send } from "lucide-svelte";
4
4
  import Button, { type ButtonProps } from "./ui/button/button.svelte";
5
5
  import * as Popover from "./ui/popover";
6
6
  import Textarea from "./ui/textarea/textarea.svelte";
7
7
  import { toast } from "svelte-sonner";
8
- import { ctx } from "../store.svelte";
9
8
 
10
9
  interface LocalProp {
11
10
  value?: any;
@@ -2,8 +2,7 @@
2
2
  import { Toaster } from "./ui/sonner";
3
3
  import { onMount, onDestroy } from "svelte";
4
4
  import { ModeWatcher } from "mode-watcher";
5
- import { ctx } from "../store.svelte";
6
- import { lobb } from "..";
5
+ import { lobb, ctx } from "../store.svelte";
7
6
  import Header from "./header.svelte";
8
7
  import { LoaderCircle, ServerOff } from "lucide-svelte";
9
8
  import Dialog from "./confirmationDialog/confirmationDialog.svelte";
@@ -0,0 +1,152 @@
1
+ <script lang="ts">
2
+ import { onMount, onDestroy } from 'svelte';
3
+ import { keymap } from '@codemirror/view';
4
+ import { EditorState } from '@codemirror/state';
5
+ import { basicSetup, EditorView } from 'codemirror';
6
+ import { javascript } from '@codemirror/lang-javascript';
7
+ import { sql } from '@codemirror/lang-sql';
8
+ import { oneDark } from '@codemirror/theme-one-dark';
9
+ import { cn } from '../utils.js';
10
+
11
+ interface Props {
12
+ type: 'javascript' | 'typescript' | 'json' | 'sql';
13
+ name: string;
14
+ value?: string;
15
+ default?: string;
16
+ types?: string;
17
+ class?: string;
18
+ handleCtrlSave?: () => void;
19
+ onChange?: (value: string) => void;
20
+ }
21
+
22
+ let {
23
+ type,
24
+ name,
25
+ value = $bindable(''),
26
+ class: className,
27
+ types,
28
+ handleCtrlSave,
29
+ onChange,
30
+ ...props
31
+ }: Props = $props();
32
+
33
+ if (props.default) {
34
+ value = props.default;
35
+ }
36
+
37
+ let editorContainer: HTMLDivElement;
38
+ let editorView: EditorView | null = null;
39
+
40
+ const getLanguageExtension = () => {
41
+ switch (type) {
42
+ case 'javascript':
43
+ case 'typescript':
44
+ case 'json':
45
+ return javascript();
46
+ case 'sql':
47
+ return sql();
48
+ default:
49
+ return javascript();
50
+ }
51
+ };
52
+
53
+ const createEditor = () => {
54
+ if (!editorContainer) return;
55
+
56
+ const extensions = [
57
+ basicSetup,
58
+ getLanguageExtension(),
59
+ EditorView.updateListener.of((update) => {
60
+ if (update.docChanged) {
61
+ const newValue = update.state.doc.toString();
62
+ value = newValue;
63
+ onChange?.(newValue);
64
+ }
65
+ }),
66
+ EditorView.theme({
67
+ '&': {
68
+ backgroundColor: 'transparent',
69
+ },
70
+ '.cm-gutters': {
71
+ backgroundColor: 'transparent',
72
+ border: 'none',
73
+ },
74
+ '.cm-content': {
75
+ paddingTop: '10px',
76
+ paddingBottom: '1px',
77
+ }
78
+ })
79
+ ];
80
+
81
+ // Add Ctrl+S / Cmd+S handler if provided
82
+ if (handleCtrlSave) {
83
+ extensions.push(
84
+ keymap.of([
85
+ {
86
+ key: 'Mod-s',
87
+ run: () => {
88
+ handleCtrlSave();
89
+ return true;
90
+ }
91
+ }
92
+ ])
93
+ );
94
+ }
95
+
96
+ const state = EditorState.create({
97
+ doc: value,
98
+ extensions
99
+ });
100
+
101
+ editorView = new EditorView({
102
+ state,
103
+ parent: editorContainer
104
+ });
105
+ };
106
+
107
+ const updateEditor = () => {
108
+ if (!editorView) return;
109
+
110
+ const currentValue = editorView.state.doc.toString();
111
+ if (currentValue !== value) {
112
+ editorView.dispatch({
113
+ changes: {
114
+ from: 0,
115
+ to: currentValue.length,
116
+ insert: value
117
+ }
118
+ });
119
+ }
120
+ };
121
+
122
+ onMount(() => {
123
+ createEditor();
124
+ });
125
+
126
+ onDestroy(() => {
127
+ editorView?.destroy();
128
+ });
129
+
130
+ $effect(() => {
131
+ updateEditor();
132
+ });
133
+ </script>
134
+
135
+ <div class={cn('resize-y rounded-md border bg-soft shadow-sm h-60', className)}>
136
+ <div bind:this={editorContainer} class="h-full w-full pl-2" />
137
+ </div>
138
+
139
+ <style>
140
+ :global(.cm-editor) {
141
+ height: 100%;
142
+ font-size: 14px;
143
+ }
144
+
145
+ :global(.cm-scroller) {
146
+ overflow: auto;
147
+ }
148
+
149
+ :global(.cm-focused) {
150
+ outline: none !important;
151
+ }
152
+ </style>
@@ -0,0 +1,13 @@
1
+ interface Props {
2
+ type: 'javascript' | 'typescript' | 'json' | 'sql';
3
+ name: string;
4
+ value?: string;
5
+ default?: string;
6
+ types?: string;
7
+ class?: string;
8
+ handleCtrlSave?: () => void;
9
+ onChange?: (value: string) => void;
10
+ }
11
+ declare const CodeEditor: import("svelte").Component<Props, {}, "value">;
12
+ type CodeEditor = ReturnType<typeof CodeEditor>;
13
+ export default CodeEditor;
@@ -3,8 +3,8 @@
3
3
  import { ArrowLeft, Plus, X } from "lucide-svelte";
4
4
  import Button, { type ButtonProps } from "./ui/button/button.svelte";
5
5
  import { toast } from "svelte-sonner";
6
- import MonacoEditor from "./monacoEditor.svelte";
7
- import { lobb } from "..";
6
+ import CodeEditor from "./codeEditor.svelte";
7
+ import { lobb } from "../store.svelte";
8
8
  import { calculateDrawerWidth } from "../utils";
9
9
  import Drawer from "./drawer.svelte";
10
10
 
@@ -76,7 +76,7 @@
76
76
  </div>
77
77
  </div>
78
78
  <div class="flex-1 overflow-y-auto">
79
- <MonacoEditor
79
+ <CodeEditor
80
80
  name={collectionName}
81
81
  type="json"
82
82
  bind:value={createManyPayload}
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import _ from "lodash";
3
- import { lobb } from "../..";
3
+ import { lobb, ctx } from "../../store.svelte";
4
4
  import Footer from "./footer.svelte";
5
5
  import Header from "./header.svelte";
6
6
  import Table, { type TableProps } from "./table.svelte";
@@ -10,7 +10,6 @@
10
10
  import ChildRecords from "./childRecords.svelte";
11
11
  import FieldCell from "./fieldCell.svelte";
12
12
  import Skeleton from "../ui/skeleton/skeleton.svelte";
13
- import { ctx } from "../../store.svelte";
14
13
  import Button from "../ui/button/button.svelte";
15
14
  import { showDialog } from "../confirmationDialog/store.svelte";
16
15
  import UpdateDetailViewButton from "../detailView/update/updateDetailViewButton.svelte";
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import { ctx } from "../../store.svelte";
2
+ import { lobb, ctx } from "../../store.svelte";
3
3
  import { ListRestart, Plus, SquareStack, Trash } from "lucide-svelte";
4
4
  import LlmButton from "../LlmButton.svelte";
5
5
  import FilterButton from "./filterButton.svelte";
@@ -7,7 +7,6 @@
7
7
  import Button from "../ui/button/button.svelte";
8
8
  import CreateManyButton from "../createManyButton.svelte";
9
9
  import { showDialog } from "../confirmationDialog/store.svelte";
10
- import { lobb } from "../..";
11
10
  import CreateDetailViewButton from "../detailView/create/createDetailViewButton.svelte";
12
11
  import type { Snippet } from "svelte";
13
12
 
@@ -19,9 +19,8 @@
19
19
  <script lang="ts">
20
20
  import { ArrowLeft, Plus, X } from "lucide-svelte";
21
21
  import Button from "../../ui/button/button.svelte";
22
- import { lobb } from "../../..";
22
+ import { lobb, ctx } from "../../../store.svelte";
23
23
  import { toast } from "svelte-sonner";
24
- import { ctx } from "../../../store.svelte";
25
24
  import ExtensionsComponents from "../../extensionsComponents.svelte";
26
25
  import { getExtensionUtils } from "../../../extensions/extensionUtils";
27
26
  import { getField, getFieldIcon } from "../../dataTable/utils";
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import MonacoEditor from "../monacoEditor.svelte";
2
+ import CodeEditor from "../codeEditor.svelte";
3
3
 
4
4
  interface Props {
5
5
  value: any;
@@ -19,5 +19,5 @@
19
19
  </script>
20
20
 
21
21
  {#if type === "code"}
22
- <MonacoEditor name={field.key} {...args} bind:value />
22
+ <CodeEditor name={field.key} {...args} bind:value />
23
23
  {/if}
@@ -47,7 +47,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
47
47
  };
48
48
  import CreateDetailView from "./create/createDetailView.svelte";
49
49
  import UpdateDetailView from "./update/updateDetailView.svelte";
50
- import { lobb } from "../..";
50
+ import { lobb } from "../../store.svelte";
51
51
  import { getCollectionParamsFields } from "../dataTable/utils";
52
52
  import { mount, unmount } from "svelte";
53
53
  export function openCreateDetailView(props) {
@@ -21,9 +21,8 @@
21
21
  import { ArrowLeft, Pencil, X } from "lucide-svelte";
22
22
  import Button from "../../ui/button/button.svelte";
23
23
  import { fade, fly } from "svelte/transition";
24
- import { lobb } from "../../..";
24
+ import { lobb, ctx } from "../../../store.svelte";
25
25
  import { toast } from "svelte-sonner";
26
- import { ctx } from "../../../store.svelte";
27
26
  import ExtensionsComponents from "../../extensionsComponents.svelte";
28
27
  import { getExtensionUtils } from "../../../extensions/extensionUtils";
29
28
  import { calculateDrawerWidth, getChangedProperties } from "../../../utils";
@@ -1,15 +1,15 @@
1
1
  <script lang="ts">
2
2
  import { onMount, onDestroy } from "svelte";
3
- import * as monaco from "monaco-editor";
4
- import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
5
- import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
6
- import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
7
- import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
8
- import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
3
+ import { MergeView } from "@codemirror/merge";
4
+ import { EditorView } from "@codemirror/view";
5
+ import { EditorState } from "@codemirror/state";
6
+ import { basicSetup } from "codemirror";
7
+ import { javascript } from "@codemirror/lang-javascript";
8
+ import { sql } from "@codemirror/lang-sql";
9
9
  import { cn } from "../utils";
10
10
 
11
11
  interface Props {
12
- type: "javascript" | "typescript" | "json";
12
+ type: "javascript" | "typescript" | "json" | "sql";
13
13
  original: string;
14
14
  modified: string;
15
15
  class?: string;
@@ -24,76 +24,79 @@
24
24
  }: Props = $props();
25
25
 
26
26
  let editorContainer: HTMLDivElement;
27
- let editor: monaco.editor.IStandaloneDiffEditor;
28
- let originalModel: monaco.editor.ITextModel;
29
- let modifiedModel: monaco.editor.ITextModel;
27
+ let mergeView: MergeView | null = null;
30
28
 
31
- self.MonacoEnvironment = {
32
- getWorker(_, label) {
33
- if (label === "json") {
34
- return new jsonWorker();
35
- }
36
- if (label === "css" || label === "scss" || label === "less") {
37
- return new cssWorker();
38
- }
39
- if (
40
- label === "html" ||
41
- label === "handlebars" ||
42
- label === "razor"
43
- ) {
44
- return new htmlWorker();
45
- }
46
- if (label === "typescript" || label === "javascript") {
47
- return new tsWorker();
48
- }
49
- return new editorWorker();
50
- },
29
+ const getLanguageExtension = () => {
30
+ switch (type) {
31
+ case 'javascript':
32
+ case 'typescript':
33
+ case 'json':
34
+ return javascript();
35
+ case 'sql':
36
+ return sql();
37
+ default:
38
+ return javascript();
39
+ }
51
40
  };
52
41
 
53
- onMount(async () => {
54
- monaco.editor.defineTheme("transparentTheme", {
55
- base: "vs",
56
- inherit: true,
57
- rules: [],
58
- colors: {
59
- "editor.background": "#EFEFEF00",
60
- focusBorder: "#00000000",
61
- },
62
- });
63
-
64
- originalModel = monaco.editor.createModel(original, type);
65
-
66
- modifiedModel = monaco.editor.createModel(modified, type);
42
+ onMount(() => {
43
+ const langExtension = getLanguageExtension();
67
44
 
68
- editor = monaco.editor.createDiffEditor(editorContainer, {
69
- renderSideBySide: true,
70
- readOnly: true,
71
- automaticLayout: true,
72
- theme: "transparentTheme",
73
- minimap: { enabled: false },
74
- glyphMargin: false,
75
- overviewRulerLanes: 0,
76
- hideCursorInOverviewRuler: true,
77
- stickyScroll: { enabled: false },
78
- lineNumbersMinChars: 2,
79
- scrollBeyondLastLine: false,
80
- padding: { top: 10, bottom: 1 },
81
- });
82
-
83
- editor.setModel({
84
- original: originalModel,
85
- modified: modifiedModel,
45
+ mergeView = new MergeView({
46
+ a: {
47
+ doc: original,
48
+ extensions: [
49
+ basicSetup,
50
+ langExtension,
51
+ EditorView.editable.of(false),
52
+ EditorState.readOnly.of(true),
53
+ EditorView.theme({
54
+ '&': {
55
+ backgroundColor: 'transparent',
56
+ },
57
+ '.cm-gutters': {
58
+ backgroundColor: 'transparent',
59
+ border: 'none',
60
+ },
61
+ '.cm-content': {
62
+ paddingTop: '10px',
63
+ paddingBottom: '1px',
64
+ }
65
+ })
66
+ ]
67
+ },
68
+ b: {
69
+ doc: modified,
70
+ extensions: [
71
+ basicSetup,
72
+ langExtension,
73
+ EditorView.editable.of(false),
74
+ EditorState.readOnly.of(true),
75
+ EditorView.theme({
76
+ '&': {
77
+ backgroundColor: 'transparent',
78
+ },
79
+ '.cm-gutters': {
80
+ backgroundColor: 'transparent',
81
+ border: 'none',
82
+ },
83
+ '.cm-content': {
84
+ paddingTop: '10px',
85
+ paddingBottom: '1px',
86
+ }
87
+ })
88
+ ]
89
+ },
90
+ parent: editorContainer
86
91
  });
87
92
  });
88
93
 
89
94
  onDestroy(() => {
90
- editor?.dispose();
91
- originalModel.dispose();
92
- modifiedModel.dispose();
95
+ mergeView?.destroy();
93
96
  });
94
97
  </script>
95
98
 
96
- <div class={cn("resize-y rounded-md border bg-soft shadow-sm h-60", className)}>
99
+ <div class={cn("w-full resize-y rounded-md border bg-soft shadow-sm", className)}>
97
100
  <div
98
101
  bind:this={editorContainer}
99
102
  class="editor pl-2"
@@ -1,5 +1,5 @@
1
1
  interface Props {
2
- type: "javascript" | "typescript" | "json";
2
+ type: "javascript" | "typescript" | "json" | "sql";
3
3
  original: string;
4
4
  modified: string;
5
5
  class?: string;
@@ -1,13 +1,12 @@
1
1
  <script lang="ts">
2
2
  import DiffViewer from "../../diffViewer.svelte";
3
- import { ctx } from "../../../store.svelte";
3
+ import { lobb, ctx } from "../../../store.svelte";
4
4
  import { onMount } from "svelte";
5
5
  import stringify from "json-stable-stringify";
6
- import MonacoEditor from "../../monacoEditor.svelte";
6
+ import CodeEditor from "../../codeEditor.svelte";
7
7
  import Table from "../../dataTable/table.svelte";
8
8
  import Button from "../../ui/button/button.svelte";
9
9
  import { LoaderCircle, SendHorizontal } from "lucide-svelte";
10
- import { lobb } from "../../..";
11
10
 
12
11
  let configSchema: string = $state("");
13
12
  let dbSchema: string = $state("");
@@ -41,7 +40,7 @@
41
40
  }
42
41
  </script>
43
42
 
44
- <div class="h-[50%] border-b">
43
+ <div class="h-[50%] border-b overflow-auto">
45
44
  {#if configSchema && dbSchema}
46
45
  <DiffViewer
47
46
  type="json"
@@ -70,7 +69,7 @@
70
69
  Execute
71
70
  </Button>
72
71
  </div>
73
- <MonacoEditor
72
+ <CodeEditor
74
73
  type="sql"
75
74
  name="prompt"
76
75
  bind:value={sqlPrompt}
@@ -3,10 +3,9 @@
3
3
  import WorkflowEditor, {
4
4
  type WorkflowEntry,
5
5
  } from "../../workflowEditor.svelte";
6
- import { lobb } from "../../..";
6
+ import { lobb, ctx } from "../../../store.svelte";
7
7
  import Sidebar from "../../sidebar/sidebar.svelte";
8
8
  import Button from "../../ui/button/button.svelte";
9
- import { ctx } from "../../../store.svelte";
10
9
  import { location } from "@wjfe/n-savant";
11
10
  import { CircleSlash2, Plus, Trash2 } from "lucide-svelte";
12
11
  import { onMount } from "svelte";
@@ -5,7 +5,7 @@
5
5
  import SidebarTrigger from "./sidebar/sidebarTrigger.svelte";
6
6
  import Button from "./ui/button/button.svelte";
7
7
  import { onMount } from "svelte";
8
- import { lobb } from "..";
8
+ import { lobb } from "../store.svelte";
9
9
  import { toast } from "svelte-sonner";
10
10
  import Skeleton from "./ui/skeleton/skeleton.svelte";
11
11
 
@@ -11,11 +11,10 @@
11
11
  </script>
12
12
 
13
13
  <script lang="ts">
14
- import { lobb } from "..";
15
- import MonacoEditor from "./monacoEditor.svelte";
14
+ import { lobb, ctx } from "../store.svelte";
15
+ import CodeEditor from "./codeEditor.svelte";
16
16
  import Button from "./ui/button/button.svelte";
17
17
  import Input from "./ui/input/input.svelte";
18
- import { ctx } from "../store.svelte";
19
18
  import { location } from "@wjfe/n-savant";
20
19
  import { Edit, Plus } from "lucide-svelte";
21
20
  import { toast } from "svelte-sonner";
@@ -175,7 +174,7 @@
175
174
  </div>
176
175
  </div>
177
176
  {#key types}
178
- <MonacoEditor
177
+ <CodeEditor
179
178
  type="typescript"
180
179
  name="workflow"
181
180
  class="h-full rounded-none border-none"
@@ -43,8 +43,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
43
43
  }
44
44
  return to.concat(ar || Array.prototype.slice.call(from));
45
45
  };
46
- import { lobb } from "..";
47
- import { ctx } from "../store.svelte";
46
+ import { lobb, ctx } from "../store.svelte";
48
47
  import { toast } from "svelte-sonner";
49
48
  import { showDialog } from "../components/confirmationDialog/store.svelte";
50
49
  import { Button } from "../components/ui/button";
package/dist/index.d.ts CHANGED
@@ -1,9 +1,24 @@
1
+ export type { ExtensionProps, Extension, ExtensionUtils } from "./extensions/extension.types";
2
+ export type { Lobb } from "./Lobb";
1
3
  export { default as Studio } from "./components/Studio.svelte";
2
- export { Lobb } from "./Lobb";
3
- export * from "./utils";
4
- export * from "./eventSystem";
5
- export { ctx, lobb } from "./store.svelte";
6
- export type * from "./store.types";
7
- export declare function createSet(lastNumber: number): Set<number>;
8
- export declare function moveElement<T>(array: T[], fromIndex: number, toIndex: number): T[];
9
- export declare function pxToRem(px: number): number;
4
+ export { Button } from "./components/ui/button";
5
+ export { Input } from "./components/ui/input";
6
+ export { Separator } from "./components/ui/separator";
7
+ export { Skeleton } from "./components/ui/skeleton";
8
+ export { default as LlmButton } from "./components/LlmButton.svelte";
9
+ export { default as Sidebar } from "./components/sidebar/sidebar.svelte";
10
+ export { default as SidebarTrigger } from "./components/sidebar/sidebarTrigger.svelte";
11
+ export { default as CreateDetailViewButton } from "./components/detailView/create/createDetailViewButton.svelte";
12
+ export { default as UpdateDetailViewButton } from "./components/detailView/update/updateDetailViewButton.svelte";
13
+ export * as Tooltip from "./components/ui/tooltip";
14
+ export * as Breadcrumb from "./components/ui/breadcrumb";
15
+ export { ContextMenu } from "bits-ui";
16
+ export * as Popover from "./components/ui/popover";
17
+ export * as Icons from "lucide-svelte";
18
+ export * as Dialog from "./components/ui/dialog/index";
19
+ export { default as Table } from "./components/dataTable/table.svelte";
20
+ export { default as RangeCalendarButton } from "./components/rangeCalendarButton.svelte";
21
+ export { default as DataTable } from "./components/dataTable/dataTable.svelte";
22
+ export { default as Drawer } from "./components/drawer.svelte";
23
+ export { default as SelectRecord } from "./components/selectRecord.svelte";
24
+ export { Switch } from "./components/ui/switch";
package/dist/index.js CHANGED
@@ -1,27 +1,22 @@
1
- // Main Studio component
2
1
  export { default as Studio } from "./components/Studio.svelte";
3
- // Lobb client and utilities
4
- export { Lobb } from "./Lobb";
5
- export * from "./utils";
6
- export * from "./eventSystem";
7
- export { ctx, lobb } from "./store.svelte";
8
- export function createSet(lastNumber) {
9
- var set = new Set();
10
- for (var i = 0; i <= lastNumber; i++) {
11
- set.add(i);
12
- }
13
- return set;
14
- }
15
- export function moveElement(array, fromIndex, toIndex) {
16
- if (fromIndex < 0 || fromIndex >= array.length || toIndex < 0 ||
17
- toIndex >= array.length) {
18
- throw new Error("Index out of bounds");
19
- }
20
- var element = array.splice(fromIndex, 1)[0];
21
- array.splice(toIndex, 0, element);
22
- return array;
23
- }
24
- export function pxToRem(px) {
25
- var rootFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize);
26
- return px / rootFontSize;
27
- }
2
+ export { Button } from "./components/ui/button";
3
+ export { Input } from "./components/ui/input";
4
+ export { Separator } from "./components/ui/separator";
5
+ export { Skeleton } from "./components/ui/skeleton";
6
+ export { default as LlmButton } from "./components/LlmButton.svelte";
7
+ export { default as Sidebar } from "./components/sidebar/sidebar.svelte";
8
+ export { default as SidebarTrigger } from "./components/sidebar/sidebarTrigger.svelte";
9
+ export { default as CreateDetailViewButton } from "./components/detailView/create/createDetailViewButton.svelte";
10
+ export { default as UpdateDetailViewButton } from "./components/detailView/update/updateDetailViewButton.svelte";
11
+ export * as Tooltip from "./components/ui/tooltip";
12
+ export * as Breadcrumb from "./components/ui/breadcrumb";
13
+ export { ContextMenu } from "bits-ui";
14
+ export * as Popover from "./components/ui/popover";
15
+ export * as Icons from "lucide-svelte";
16
+ export * as Dialog from "./components/ui/dialog/index";
17
+ export { default as Table } from "./components/dataTable/table.svelte";
18
+ export { default as RangeCalendarButton } from "./components/rangeCalendarButton.svelte";
19
+ export { default as DataTable } from "./components/dataTable/dataTable.svelte";
20
+ export { default as Drawer } from "./components/drawer.svelte";
21
+ export { default as SelectRecord } from "./components/selectRecord.svelte";
22
+ export { Switch } from "./components/ui/switch";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobb-js/studio",
3
- "version": "0.1.41",
3
+ "version": "0.1.43",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -11,19 +11,11 @@
11
11
  ],
12
12
  "exports": {
13
13
  ".": {
14
- "svelte": "./dist/components/Studio.svelte"
14
+ "svelte": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./src/lib/index.ts"
15
17
  },
16
- "./internal": {
17
- "svelte": "./src/lib/components/Studio.svelte"
18
- },
19
- "./*": {
20
- "svelte": "./dist/components/*"
21
- },
22
- "./internal/*": {
23
- "svelte": "./src/lib/components/*"
24
- },
25
- "./vite-plugins": "./vite-plugins/index.js",
26
- "./components": "./src/components-export.ts"
18
+ "./vite-plugins": "./vite-plugins/index.js"
27
19
  },
28
20
  "scripts": {
29
21
  "dev": "vite",
@@ -46,31 +38,38 @@
46
38
  "@storybook/svelte-vite": "^10.0.1",
47
39
  "@sveltejs/package": "^2.5.7",
48
40
  "@sveltejs/vite-plugin-svelte": "6.2.1",
41
+ "@tsconfig/svelte": "^5.0.6",
49
42
  "@types/lodash": "^4.17.17",
50
43
  "@types/mustache": "^4.2.6",
51
44
  "@types/node": "^24.10.1",
52
45
  "@types/qs": "^6.9.18",
53
- "@tsconfig/svelte": "^5.0.6",
54
46
  "@vitest/browser-playwright": "^4.0.5",
55
47
  "@vitest/coverage-v8": "^4.0.5",
56
48
  "autoprefixer": "^10.4.23",
57
49
  "dts-bundle-generator": "^9.5.1",
58
50
  "playwright": "^1.56.1",
59
51
  "storybook": "^10.0.1",
52
+ "svelte": "^5.49.1",
60
53
  "svelte-check": "^4.3.4",
54
+ "tailwindcss": "4.1.18",
61
55
  "tailwindcss-animate": "^1.0.7",
62
56
  "tw-animate-css": "^1.4.0",
63
57
  "typescript": "~5.9.3",
58
+ "vite": "6.3.3",
64
59
  "vite-plugin-css-injected-by-js": "^3.5.2",
65
- "vitest": "^4.0.5",
66
- "tailwindcss": "4.1.18",
67
- "vite": "6.3.3"
60
+ "vitest": "^4.0.5"
68
61
  },
69
62
  "peerDependencies": {
70
63
  "svelte": "^5.0.0"
71
64
  },
72
65
  "dependencies": {
73
66
  "@andrewbranch/untar.js": "^1.0.3",
67
+ "@codemirror/lang-javascript": "^6.2.4",
68
+ "@codemirror/lang-sql": "^6.10.0",
69
+ "@codemirror/merge": "^6.11.2",
70
+ "@codemirror/state": "^6.5.4",
71
+ "@codemirror/theme-one-dark": "^6.1.3",
72
+ "@codemirror/view": "^6.39.12",
74
73
  "@dagrejs/dagre": "^1.1.5",
75
74
  "@lucide/svelte": "^0.563.1",
76
75
  "@tailwindcss/vite": "^4.1.18",
@@ -78,12 +77,12 @@
78
77
  "@xyflow/svelte": "^1.2.0",
79
78
  "bits-ui": "^1.8.0",
80
79
  "clsx": "^2.1.1",
80
+ "codemirror": "^6.0.2",
81
81
  "fflate": "^0.8.2",
82
82
  "json-stable-stringify": "^1.3.0",
83
83
  "lodash": "^4.17.21",
84
84
  "lucide-svelte": "^0.488.0",
85
85
  "mode-watcher": "^0.5.1",
86
- "monaco-editor": "^0.52.2",
87
86
  "mustache": "^4.2.0",
88
87
  "qs": "^6.14.1",
89
88
  "svelte-sonner": "^0.3.28",
@@ -12,7 +12,7 @@ import { monorepoImportResolver } from "./monorepo-import-resolver.js";
12
12
  */
13
13
  export function lobbStudioPlugins() {
14
14
  return [
15
- monorepoImportResolver(),
15
+ // monorepoImportResolver(),
16
16
  contextualLibAlias(),
17
17
  ];
18
18
  }
@@ -1,150 +0,0 @@
1
- <script lang="ts">
2
- import { Toaster } from "./components/ui/sonner";
3
- import { onMount, onDestroy } from "svelte";
4
- import { ModeWatcher } from "mode-watcher";
5
- import { ctx } from "./store.svelte";
6
- import { lobb } from "./";
7
- import Header from "./components/header.svelte";
8
- import { LoaderCircle, ServerOff } from "lucide-svelte";
9
- import Dialog from "./components/confirmationDialog/confirmationDialog.svelte";
10
- import MiniSidebar from "./components/miniSidebar.svelte";
11
- import SetServerPage from "./components/setServerPage.svelte";
12
- import * as Tooltip from "./components/ui/tooltip";
13
- import { Router, Route, Fallback, init as initRouter, } from "@wjfe/n-savant";
14
- import {
15
- executeExtensionsOnStartup,
16
- loadExtensions,
17
- } from "./extensions/extensionUtils";
18
- import { mediaQueries } from "./utils";
19
- import Home from "../../routes/home.svelte";
20
- import DataModel from "../../routes/data_model/dataModel.svelte";
21
- import Collections from "../../routes/collections/collections.svelte";
22
- import Workflows from "../../routes/workflows/workflows.svelte";
23
- import Extension from "../../routes/extensions/extension.svelte";
24
-
25
- interface StudioProps {
26
- extensions?: any[];
27
- }
28
-
29
- const props: StudioProps = $props()
30
-
31
- let error: string | null = $state(null);
32
- let loaded = $state(false);
33
- let isSmallScreen = $derived(!mediaQueries.sm.current);
34
- let cleanupRouter: (() => void) | undefined;
35
-
36
- onMount(async () => {
37
- cleanupRouter = initRouter();
38
-
39
- if (ctx.lobbUrl) {
40
- try {
41
- ctx.meta = await lobb.getMeta();
42
- ctx.extensions = await loadExtensions(props.extensions);
43
- await executeExtensionsOnStartup();
44
- } catch (err) {
45
- console.error(err);
46
- error = "CANT_CONNECT";
47
- }
48
- }
49
- loaded = true;
50
- });
51
-
52
- onDestroy(() => {
53
- if (cleanupRouter) {
54
- cleanupRouter();
55
- }
56
- });
57
- </script>
58
-
59
- <ModeWatcher defaultMode="light" />
60
- <Toaster position="top-right" class="z-50" />
61
- {#if loaded}
62
- {#if ctx.lobbUrl}
63
- <Tooltip.Provider delayDuration={0} disableHoverableContent={true}>
64
- <main
65
- class="bg-muted h-screen w-screen"
66
- style="display: grid; grid-template-columns: {isSmallScreen
67
- ? '1fr'
68
- : '3.5rem 1fr'};"
69
- >
70
- <MiniSidebar />
71
- <div class="second_grid">
72
- <Header />
73
- <Router id="root-router">
74
- <Route key="home" path="/">
75
- {#snippet children(params)}
76
- <Home />
77
- {/snippet}
78
- </Route>
79
- <Route
80
- key="collections"
81
- path="/collections/:collection?"
82
- >
83
- {#snippet children(params)}
84
- <Collections
85
- collectionName={params?.collection}
86
- />
87
- {/snippet}
88
- </Route>
89
- <Route key="datamodel" path="/datamodel/*">
90
- {#snippet children(params)}
91
- <DataModel />
92
- {/snippet}
93
- </Route>
94
- <Route key="workflows" path="/workflows/:workflow?">
95
- {#snippet children(params)}
96
- <Workflows workflowName={params?.workflow} />
97
- {/snippet}
98
- </Route>
99
- <Route
100
- key="extensions"
101
- path="/extensions/:extension?/:page?/*"
102
- >
103
- {#snippet children(params)}
104
- <Extension
105
- extension={params?.extension}
106
- page={params?.page}
107
- />
108
- {/snippet}
109
- </Route>
110
- <Fallback>Not Found</Fallback>
111
- </Router>
112
- </div>
113
- </main>
114
- </Tooltip.Provider>
115
- {:else}
116
- <SetServerPage />
117
- {/if}
118
- {:else if !error}
119
- <div
120
- class="flex h-screen w-full flex-col items-center justify-center gap-4 text-muted-foreground"
121
- >
122
- <LoaderCircle class="animate-spin opacity-50" size="50" />
123
- <div class="flex flex-col items-center justify-center">
124
- <div>Loading the dashboard, please wait...</div>
125
- <div class="text-xs">
126
- Loading and importing all necessary data and components from the
127
- lobb server.
128
- </div>
129
- </div>
130
- </div>
131
- {:else}
132
- <div
133
- class="flex h-full w-full flex-col items-center justify-center gap-4 text-muted-foreground"
134
- >
135
- <ServerOff class="opacity-50" size="50" />
136
- <div class="flex flex-col items-center justify-center">
137
- <div>Could not connect to the server</div>
138
- <div class="text-xs">
139
- Could not connect to the lobb server at this endpoint ({ctx.lobbUrl})
140
- </div>
141
- </div>
142
- </div>
143
- {/if}
144
-
145
- <style>
146
- .second_grid {
147
- display: grid;
148
- grid-template-rows: 2.5rem 1fr;
149
- }
150
- </style>
@@ -1,6 +0,0 @@
1
- interface StudioProps {
2
- extensions?: any[];
3
- }
4
- declare const Studio: import("svelte").Component<StudioProps, {}, "">;
5
- type Studio = ReturnType<typeof Studio>;
6
- export default Studio;
@@ -1,181 +0,0 @@
1
- <script lang="ts">
2
- import { onMount, onDestroy } from "svelte";
3
- import * as monaco from "monaco-editor";
4
- import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker";
5
- import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker";
6
- import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker";
7
- import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker";
8
- import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker";
9
- import { cn } from "../utils";
10
-
11
- interface Props {
12
- type: "javascript" | "typescript" | "json" | "sql";
13
- name: string;
14
- value?: string;
15
- default?: string;
16
- types?: string;
17
- class?: string;
18
- handleCtrlSave?: () => void;
19
- onChange?: (value: string) => void;
20
- }
21
-
22
- let {
23
- type,
24
- name,
25
- value = $bindable(""),
26
- class: className,
27
- types,
28
- handleCtrlSave,
29
- onChange,
30
- ...props
31
- }: Props = $props();
32
-
33
- let editorContainer: HTMLDivElement;
34
- let editor: monaco.editor.IStandaloneCodeEditor;
35
- let model: monaco.editor.ITextModel;
36
-
37
- if (props.default) {
38
- value = props.default;
39
- }
40
-
41
- $effect(() => {
42
- if (value !== undefined && editor && value !== editor.getValue()) {
43
- editor.setValue(value);
44
- }
45
- });
46
-
47
- self.MonacoEnvironment = {
48
- getWorker(_, label) {
49
- if (label === "json") {
50
- return new jsonWorker();
51
- }
52
- if (label === "css" || label === "scss" || label === "less") {
53
- return new cssWorker();
54
- }
55
- if (
56
- label === "html" ||
57
- label === "handlebars" ||
58
- label === "razor"
59
- ) {
60
- return new htmlWorker();
61
- }
62
- if (label === "typescript" || label === "javascript") {
63
- return new tsWorker();
64
- }
65
- return new editorWorker();
66
- },
67
- };
68
-
69
- onMount(async () => {
70
- monaco.editor.defineTheme("transparentTheme", {
71
- base: "vs",
72
- inherit: true,
73
- rules: [],
74
- colors: {
75
- "editor.background": "#EFEFEF00",
76
- focusBorder: "#00000000",
77
- },
78
- });
79
-
80
- if (type === "typescript") {
81
- monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
82
- target: monaco.languages.typescript.ScriptTarget.ESNext,
83
- moduleResolution:
84
- monaco.languages.typescript.ModuleResolutionKind.NodeJs,
85
- esModuleInterop: true,
86
- });
87
- monaco.languages.typescript.typescriptDefaults.addExtraLib(
88
- types ?? "",
89
- "file:///global.d.ts",
90
- );
91
-
92
- // this is an example of importing the picocolors library types
93
- // with this you can easily use the picolo types in the web editor like this
94
- // import type Pico from "picocolors"
95
- // function work(pc: typeof Pico) {
96
- // pc.bold(`How are ${pc.italic(`you`)} doing?`)
97
- // }
98
-
99
- monaco.languages.typescript.typescriptDefaults.addExtraLib(
100
- `export type Formatter = (input: string | number | null | undefined) => string
101
- export interface Colors {
102
- isColorSupported: boolean
103
-
104
- reset: Formatter
105
- bold: Formatter
106
- dim: Formatter
107
- italic: Formatter
108
- underline: Formatter
109
- inverse: Formatter
110
- hidden: Formatter
111
- strikethrough: Formatter
112
- }`,
113
- "file:///node_modules/picocolors/types.d.ts",
114
- );
115
- monaco.languages.typescript.typescriptDefaults.addExtraLib(
116
- `import { Colors } from "./types.d.ts"
117
- declare const picocolors: Colors & { createColors: (enabled?: boolean) => Colors }
118
- export = picocolors`,
119
- "file:///node_modules/picocolors/index.d.ts",
120
- );
121
- }
122
-
123
- model = monaco.editor.createModel(
124
- value,
125
- type,
126
- monaco.Uri.parse(`file:///${name}.ts`),
127
- );
128
-
129
- editor = monaco.editor.create(editorContainer, {
130
- model: model,
131
- value: value,
132
- language: type,
133
- automaticLayout: true,
134
- theme: "transparentTheme",
135
- minimap: { enabled: false },
136
- glyphMargin: false,
137
- overviewRulerLanes: 0,
138
- hideCursorInOverviewRuler: true,
139
- stickyScroll: { enabled: false },
140
- lineNumbersMinChars: 2,
141
- scrollBeyondLastLine: false,
142
- padding: { top: 10, bottom: 1 },
143
- });
144
-
145
- editor.onDidChangeModelContent(() => {
146
- value = editor.getValue();
147
- if (onChange) {
148
- onChange(value);
149
- }
150
- });
151
-
152
- // adding duplicate line shortcut
153
- editor.addCommand(
154
- monaco.KeyMod.Shift | monaco.KeyMod.Alt | monaco.KeyCode.DownArrow,
155
- () => editor.trigger("", "editor.action.copyLinesDownAction", null),
156
- );
157
- editor.addCommand(
158
- monaco.KeyMod.Shift | monaco.KeyMod.Alt | monaco.KeyCode.UpArrow,
159
- () => editor.trigger("", "editor.action.copyLinesUpAction", null),
160
- );
161
-
162
- editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
163
- if (handleCtrlSave) {
164
- handleCtrlSave();
165
- }
166
- });
167
- });
168
-
169
- onDestroy(() => {
170
- editor?.dispose();
171
- model.dispose();
172
- });
173
- </script>
174
-
175
- <div class={cn("resize-y rounded-md border bg-soft shadow-sm h-60", className)}>
176
- <div
177
- bind:this={editorContainer}
178
- class="editor pl-2"
179
- style="height: 100%; width: 100%;"
180
- ></div>
181
- </div>
@@ -1,13 +0,0 @@
1
- interface Props {
2
- type: "javascript" | "typescript" | "json" | "sql";
3
- name: string;
4
- value?: string;
5
- default?: string;
6
- types?: string;
7
- class?: string;
8
- handleCtrlSave?: () => void;
9
- onChange?: (value: string) => void;
10
- }
11
- declare const MonacoEditor: import("svelte").Component<Props, {}, "value">;
12
- type MonacoEditor = ReturnType<typeof MonacoEditor>;
13
- export default MonacoEditor;