@lobb-js/studio 0.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +1 -0
- package/.storybook/main.ts +31 -0
- package/.storybook/preview.ts +21 -0
- package/.storybook/vitest.setup.ts +7 -0
- package/README.md +47 -0
- package/components.json +16 -0
- package/docker-entrypoint.sh +7 -0
- package/dockerfile +27 -0
- package/index.html +13 -0
- package/package.json +77 -0
- package/public/lobb.svg +15 -0
- package/src/Studio.svelte +150 -0
- package/src/app.css +121 -0
- package/src/components-export.ts +21 -0
- package/src/extensions/extension.types.ts +93 -0
- package/src/extensions/extensionUtils.ts +192 -0
- package/src/lib/Lobb.ts +241 -0
- package/src/lib/components/LlmButton.svelte +136 -0
- package/src/lib/components/alertView.svelte +20 -0
- package/src/lib/components/breadCrumbs.svelte +60 -0
- package/src/lib/components/combobox.svelte +92 -0
- package/src/lib/components/confirmationDialog/confirmationDialog.svelte +33 -0
- package/src/lib/components/confirmationDialog/store.svelte.ts +28 -0
- package/src/lib/components/createManyButton.svelte +107 -0
- package/src/lib/components/dataTable/childRecords.svelte +140 -0
- package/src/lib/components/dataTable/dataTable.svelte +223 -0
- package/src/lib/components/dataTable/fieldCell.svelte +74 -0
- package/src/lib/components/dataTable/filter.svelte +282 -0
- package/src/lib/components/dataTable/filterButton.svelte +39 -0
- package/src/lib/components/dataTable/footer.svelte +84 -0
- package/src/lib/components/dataTable/header.svelte +154 -0
- package/src/lib/components/dataTable/sort.svelte +171 -0
- package/src/lib/components/dataTable/sortButton.svelte +36 -0
- package/src/lib/components/dataTable/table.svelte +337 -0
- package/src/lib/components/dataTable/utils.ts +127 -0
- package/src/lib/components/detailView/create/children.svelte +68 -0
- package/src/lib/components/detailView/create/createDetailView.svelte +226 -0
- package/src/lib/components/detailView/create/createDetailViewButton.svelte +32 -0
- package/src/lib/components/detailView/create/createManyView.svelte +250 -0
- package/src/lib/components/detailView/create/subRecords.svelte +48 -0
- package/src/lib/components/detailView/detailViewForm.svelte +104 -0
- package/src/lib/components/detailView/fieldCustomInput.svelte +23 -0
- package/src/lib/components/detailView/fieldInput.svelte +287 -0
- package/src/lib/components/detailView/fieldInputReplacement.svelte +199 -0
- package/src/lib/components/detailView/store.svelte.ts +61 -0
- package/src/lib/components/detailView/update/children.svelte +94 -0
- package/src/lib/components/detailView/update/updateDetailView.svelte +175 -0
- package/src/lib/components/detailView/update/updateDetailViewButton.svelte +32 -0
- package/src/lib/components/detailView/utils.ts +177 -0
- package/src/lib/components/diffViewer.svelte +102 -0
- package/src/lib/components/drawer.svelte +28 -0
- package/src/lib/components/extensionsComponents.svelte +31 -0
- package/src/lib/components/foreingKeyInput.svelte +80 -0
- package/src/lib/components/header.svelte +45 -0
- package/src/lib/components/loadingTypesForMonacoEditor.ts +36 -0
- package/src/lib/components/miniSidebar.svelte +238 -0
- package/src/lib/components/monacoEditor.svelte +181 -0
- package/src/lib/components/rangeCalendarButton.svelte +257 -0
- package/src/lib/components/selectRecord.svelte +126 -0
- package/src/lib/components/setServerPage.svelte +48 -0
- package/src/lib/components/sidebar/index.ts +4 -0
- package/src/lib/components/sidebar/sidebar.svelte +149 -0
- package/src/lib/components/sidebar/sidebarElements.svelte +144 -0
- package/src/lib/components/sidebar/sidebarTrigger.svelte +33 -0
- package/src/lib/components/singletone.svelte +69 -0
- package/src/lib/components/ui/accordion/accordion-content.svelte +22 -0
- package/src/lib/components/ui/accordion/accordion-item.svelte +12 -0
- package/src/lib/components/ui/accordion/accordion-trigger.svelte +31 -0
- package/src/lib/components/ui/accordion/index.ts +17 -0
- package/src/lib/components/ui/alert/alert-description.svelte +16 -0
- package/src/lib/components/ui/alert/alert-title.svelte +24 -0
- package/src/lib/components/ui/alert/alert.svelte +39 -0
- package/src/lib/components/ui/alert/index.ts +14 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte +13 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte +17 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte +26 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte +16 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte +20 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte +19 -0
- package/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte +18 -0
- package/src/lib/components/ui/alert-dialog/index.ts +40 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +23 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-item.svelte +16 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-link.svelte +31 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-list.svelte +23 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-page.svelte +23 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb-separator.svelte +27 -0
- package/src/lib/components/ui/breadcrumb/breadcrumb.svelte +15 -0
- package/src/lib/components/ui/breadcrumb/index.ts +25 -0
- package/src/lib/components/ui/button/button.svelte +110 -0
- package/src/lib/components/ui/button/index.ts +17 -0
- package/src/lib/components/ui/checkbox/checkbox.svelte +35 -0
- package/src/lib/components/ui/checkbox/index.ts +6 -0
- package/src/lib/components/ui/command/command-dialog.svelte +35 -0
- package/src/lib/components/ui/command/command-empty.svelte +12 -0
- package/src/lib/components/ui/command/command-group.svelte +31 -0
- package/src/lib/components/ui/command/command-input.svelte +25 -0
- package/src/lib/components/ui/command/command-item.svelte +19 -0
- package/src/lib/components/ui/command/command-link-item.svelte +19 -0
- package/src/lib/components/ui/command/command-list.svelte +16 -0
- package/src/lib/components/ui/command/command-separator.svelte +12 -0
- package/src/lib/components/ui/command/command-shortcut.svelte +20 -0
- package/src/lib/components/ui/command/command.svelte +21 -0
- package/src/lib/components/ui/command/index.ts +40 -0
- package/src/lib/components/ui/dialog/dialog-content.svelte +38 -0
- package/src/lib/components/ui/dialog/dialog-description.svelte +16 -0
- package/src/lib/components/ui/dialog/dialog-footer.svelte +20 -0
- package/src/lib/components/ui/dialog/dialog-header.svelte +20 -0
- package/src/lib/components/ui/dialog/dialog-overlay.svelte +19 -0
- package/src/lib/components/ui/dialog/dialog-title.svelte +16 -0
- package/src/lib/components/ui/dialog/index.ts +37 -0
- package/src/lib/components/ui/input/index.ts +7 -0
- package/src/lib/components/ui/input/input.svelte +46 -0
- package/src/lib/components/ui/label/index.ts +7 -0
- package/src/lib/components/ui/label/label.svelte +19 -0
- package/src/lib/components/ui/popover/index.ts +17 -0
- package/src/lib/components/ui/popover/popover-content.svelte +28 -0
- package/src/lib/components/ui/range-calendar/index.ts +30 -0
- package/src/lib/components/ui/range-calendar/range-calendar-cell.svelte +19 -0
- package/src/lib/components/ui/range-calendar/range-calendar-day.svelte +35 -0
- package/src/lib/components/ui/range-calendar/range-calendar-grid-body.svelte +12 -0
- package/src/lib/components/ui/range-calendar/range-calendar-grid-head.svelte +12 -0
- package/src/lib/components/ui/range-calendar/range-calendar-grid-row.svelte +12 -0
- package/src/lib/components/ui/range-calendar/range-calendar-grid.svelte +16 -0
- package/src/lib/components/ui/range-calendar/range-calendar-head-cell.svelte +16 -0
- package/src/lib/components/ui/range-calendar/range-calendar-header.svelte +16 -0
- package/src/lib/components/ui/range-calendar/range-calendar-heading.svelte +16 -0
- package/src/lib/components/ui/range-calendar/range-calendar-months.svelte +20 -0
- package/src/lib/components/ui/range-calendar/range-calendar-next-button.svelte +27 -0
- package/src/lib/components/ui/range-calendar/range-calendar-prev-button.svelte +27 -0
- package/src/lib/components/ui/range-calendar/range-calendar.svelte +57 -0
- package/src/lib/components/ui/select/index.ts +34 -0
- package/src/lib/components/ui/select/select-content.svelte +38 -0
- package/src/lib/components/ui/select/select-group-heading.svelte +16 -0
- package/src/lib/components/ui/select/select-item.svelte +37 -0
- package/src/lib/components/ui/select/select-scroll-down-button.svelte +19 -0
- package/src/lib/components/ui/select/select-scroll-up-button.svelte +19 -0
- package/src/lib/components/ui/select/select-separator.svelte +13 -0
- package/src/lib/components/ui/select/select-trigger.svelte +24 -0
- package/src/lib/components/ui/separator/index.ts +7 -0
- package/src/lib/components/ui/separator/separator.svelte +22 -0
- package/src/lib/components/ui/skeleton/index.ts +7 -0
- package/src/lib/components/ui/skeleton/skeleton.svelte +22 -0
- package/src/lib/components/ui/sonner/index.ts +1 -0
- package/src/lib/components/ui/sonner/sonner.svelte +20 -0
- package/src/lib/components/ui/switch/index.ts +7 -0
- package/src/lib/components/ui/switch/switch.svelte +27 -0
- package/src/lib/components/ui/textarea/index.ts +7 -0
- package/src/lib/components/ui/textarea/textarea.svelte +22 -0
- package/src/lib/components/ui/tooltip/index.ts +18 -0
- package/src/lib/components/ui/tooltip/tooltip-content.svelte +21 -0
- package/src/lib/components/workflowEditor.svelte +187 -0
- package/src/lib/eventSystem.ts +38 -0
- package/src/lib/index.ts +40 -0
- package/src/lib/store.svelte.ts +21 -0
- package/src/lib/store.types.ts +28 -0
- package/src/lib/utils.ts +84 -0
- package/src/main.ts +18 -0
- package/src/routes/collections/collection.svelte +46 -0
- package/src/routes/collections/collections.svelte +43 -0
- package/src/routes/data_model/dataModel.svelte +40 -0
- package/src/routes/data_model/flow.css +22 -0
- package/src/routes/data_model/flow.svelte +82 -0
- package/src/routes/data_model/syncManager.svelte +93 -0
- package/src/routes/data_model/utils.ts +35 -0
- package/src/routes/extensions/extension.svelte +16 -0
- package/src/routes/home.svelte +36 -0
- package/src/routes/workflows/workflows.svelte +135 -0
- package/src/stories/Configure.mdx +364 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/detailView/detailViewForm.stories.svelte +79 -0
- package/src/stories/examples/Button.stories.svelte +31 -0
- package/src/stories/examples/Button.svelte +30 -0
- package/src/stories/examples/Header.stories.svelte +26 -0
- package/src/stories/examples/Header.svelte +45 -0
- package/src/stories/examples/Page.stories.svelte +29 -0
- package/src/stories/examples/Page.svelte +70 -0
- package/src/stories/examples/button.css +30 -0
- package/src/stories/examples/header.css +32 -0
- package/src/stories/examples/page.css +68 -0
- package/src/vite-env.d.ts +2 -0
- package/svelte.config.js +7 -0
- package/todo.md +24 -0
- package/tsconfig.app.json +25 -0
- package/tsconfig.json +14 -0
- package/tsconfig.node.json +24 -0
- package/vite-plugin-contextual-lib.js +66 -0
- package/vite.build.svelte.config.ts +18 -0
- package/vite.config.ts +84 -0
- package/vite.extension.config.ts +81 -0
- package/vite_utils.ts +28 -0
- package/vitest.shims.d.ts +1 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Input from "./ui/input/input.svelte";
|
|
3
|
+
import SelectRecord from "./selectRecord.svelte";
|
|
4
|
+
import UpdateDetailViewButton from "./detailView/update/updateDetailViewButton.svelte";
|
|
5
|
+
import { ExternalLink } from "lucide-svelte";
|
|
6
|
+
|
|
7
|
+
interface LocalProps {
|
|
8
|
+
parentCollectionName: string;
|
|
9
|
+
collectionName: string;
|
|
10
|
+
fieldName: string;
|
|
11
|
+
value?: any;
|
|
12
|
+
destructive?: boolean;
|
|
13
|
+
entry: Record<string, any>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
parentCollectionName,
|
|
18
|
+
collectionName,
|
|
19
|
+
fieldName,
|
|
20
|
+
value = $bindable(),
|
|
21
|
+
destructive,
|
|
22
|
+
entry,
|
|
23
|
+
}: LocalProps = $props();
|
|
24
|
+
|
|
25
|
+
const idIsZero = $derived(value?.id === 0);
|
|
26
|
+
const refrenceId = $derived(value ? value.id : null);
|
|
27
|
+
const primaryField = $derived(value ? Object.values(value)[1] : null);
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<!-- THE SELECT BUTTON -->
|
|
31
|
+
{#if !idIsZero}
|
|
32
|
+
<div class="relative">
|
|
33
|
+
<div
|
|
34
|
+
class="flex gap-2 absolute right-0 top-0 mr-9 h-full items-center text-xs"
|
|
35
|
+
>
|
|
36
|
+
{#if value !== null}
|
|
37
|
+
<UpdateDetailViewButton
|
|
38
|
+
collectionName={collectionName}
|
|
39
|
+
recordId={value.id}
|
|
40
|
+
variant="ghost"
|
|
41
|
+
class="h-5 w-5 px-0 py-0 text-muted-foreground hover:bg-transparent"
|
|
42
|
+
Icon={ExternalLink}
|
|
43
|
+
></UpdateDetailViewButton>
|
|
44
|
+
{/if}
|
|
45
|
+
{#if primaryField}
|
|
46
|
+
<div
|
|
47
|
+
class="flex items-center bg-background rounded-full border h-6 px-3 shadow-sm"
|
|
48
|
+
>
|
|
49
|
+
{primaryField}
|
|
50
|
+
</div>
|
|
51
|
+
{/if}
|
|
52
|
+
<SelectRecord
|
|
53
|
+
class="h-6 px-2 font-normal text-xs"
|
|
54
|
+
variant="outline"
|
|
55
|
+
{parentCollectionName}
|
|
56
|
+
{collectionName}
|
|
57
|
+
{fieldName}
|
|
58
|
+
bind:value
|
|
59
|
+
{entry}
|
|
60
|
+
/>
|
|
61
|
+
</div>
|
|
62
|
+
<Input
|
|
63
|
+
placeholder={"NULL"}
|
|
64
|
+
type="number"
|
|
65
|
+
class="
|
|
66
|
+
bg-soft text-xs
|
|
67
|
+
{destructive ? 'border-destructive bg-destructive/10' : ''}
|
|
68
|
+
"
|
|
69
|
+
bind:value={() => refrenceId, (v) => (value.id = v)}
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
{:else}
|
|
73
|
+
<div class="relative z-10">
|
|
74
|
+
<Input
|
|
75
|
+
placeholder={"PARENT ID"}
|
|
76
|
+
class="bg-soft text-xs"
|
|
77
|
+
disabled={true}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
{/if}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import * as Tooltip from "./ui/tooltip";
|
|
3
|
+
import Button from "./ui/button/button.svelte";
|
|
4
|
+
import { Menu, Moon, Sun } from "lucide-svelte";
|
|
5
|
+
import BreadCrumbs from "./breadCrumbs.svelte";
|
|
6
|
+
import { toggleMode, mode } from "mode-watcher";
|
|
7
|
+
import { mediaQueries } from "$lib/utils";
|
|
8
|
+
import { expandMiniSideBar } from "./miniSidebar.svelte";
|
|
9
|
+
|
|
10
|
+
let isSmallScreen = $derived(!mediaQueries.sm.current);
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div
|
|
14
|
+
class="flex items-center justify-between border-b border-input bg-background px-3"
|
|
15
|
+
>
|
|
16
|
+
<div class="flex items-center gap-4">
|
|
17
|
+
{#if isSmallScreen}
|
|
18
|
+
<Menu
|
|
19
|
+
class="h-10 text-muted-foreground hover:bg-transparent cursor-pointer hover:text-foreground"
|
|
20
|
+
style="left: 0.6rem; top: 0rem;"
|
|
21
|
+
size="18"
|
|
22
|
+
onclick={() => expandMiniSideBar()}
|
|
23
|
+
/>
|
|
24
|
+
{/if}
|
|
25
|
+
<BreadCrumbs />
|
|
26
|
+
</div>
|
|
27
|
+
<div class="flex h-full items-center gap-3">
|
|
28
|
+
<Tooltip.Root>
|
|
29
|
+
<Tooltip.Trigger>
|
|
30
|
+
<Button
|
|
31
|
+
class="h-6 w-6 text-muted-foreground hover:bg-transparent"
|
|
32
|
+
variant="ghost"
|
|
33
|
+
size="icon"
|
|
34
|
+
onclick={toggleMode}
|
|
35
|
+
Icon={$mode === "light" ? Moon : Sun}
|
|
36
|
+
></Button>
|
|
37
|
+
</Tooltip.Trigger>
|
|
38
|
+
<Tooltip.Content side="bottom" sideOffset={7.5}
|
|
39
|
+
>{$mode === "light"
|
|
40
|
+
? "Night Mode"
|
|
41
|
+
: "Light Mode"}</Tooltip.Content
|
|
42
|
+
>
|
|
43
|
+
</Tooltip.Root>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TODO
|
|
3
|
+
*
|
|
4
|
+
* this file shows an example of downloading the types files of a library from npm to use them in adding type support of that library in the vscode editor
|
|
5
|
+
* so the whole point is that for users to be able to paste a url from npm or jsr of a library and have all ts support from its types
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { gunzipSync } from "fflate";
|
|
9
|
+
import { untar } from "@andrewbranch/untar.js";
|
|
10
|
+
|
|
11
|
+
async function extractTgz(buffer: ArrayBuffer) {
|
|
12
|
+
const tarBuffer = gunzipSync(new Uint8Array(buffer));
|
|
13
|
+
|
|
14
|
+
const cleanBuffer = tarBuffer.buffer.slice(
|
|
15
|
+
tarBuffer.byteOffset,
|
|
16
|
+
tarBuffer.byteOffset + tarBuffer.byteLength,
|
|
17
|
+
);
|
|
18
|
+
const files = await untar(cleanBuffer as ArrayBuffer);
|
|
19
|
+
|
|
20
|
+
const dtsFiles = [];
|
|
21
|
+
|
|
22
|
+
for (const file of files) {
|
|
23
|
+
if (file.filename.endsWith(".d.ts")) {
|
|
24
|
+
const content = new TextDecoder().decode(file.fileData);
|
|
25
|
+
dtsFiles.push({ name: file.filename, content });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return dtsFiles;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const tgzURL = "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz";
|
|
33
|
+
const response = await fetch(tgzURL);
|
|
34
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
35
|
+
|
|
36
|
+
const files = await extractTgz(arrayBuffer);
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
let isSmallScreen = $derived(!mediaQueries.sm.current);
|
|
3
|
+
let isCollapsed = $derived(isSmallScreen);
|
|
4
|
+
|
|
5
|
+
export let collapseMiniSideBar = () => {
|
|
6
|
+
isCollapsed = true;
|
|
7
|
+
};
|
|
8
|
+
export let expandMiniSideBar = () => {
|
|
9
|
+
isCollapsed = false;
|
|
10
|
+
};
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
import { House, Layers, Library, LogOut, Workflow, X } from "lucide-svelte";
|
|
15
|
+
import Button from "$lib/components/ui/button/button.svelte";
|
|
16
|
+
import Separator from "$lib/components/ui/separator/separator.svelte";
|
|
17
|
+
import * as Tooltip from "$lib/components/ui/tooltip";
|
|
18
|
+
import * as Accordion from "$lib/components/ui/accordion/index.js";
|
|
19
|
+
|
|
20
|
+
import { ctx } from "$lib/store.svelte";
|
|
21
|
+
import { getDashboardNavs } from "../../extensions/extensionUtils";
|
|
22
|
+
import { mediaQueries } from "$lib/utils";
|
|
23
|
+
import * as Popover from "./ui/popover";
|
|
24
|
+
import { location } from "@wjfe/n-savant";
|
|
25
|
+
|
|
26
|
+
const sections: any = [
|
|
27
|
+
[
|
|
28
|
+
{
|
|
29
|
+
label: "Home",
|
|
30
|
+
href: "/",
|
|
31
|
+
icon: House,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: "Collections",
|
|
35
|
+
href: "/collections",
|
|
36
|
+
icon: Library,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: "Data Model",
|
|
40
|
+
href: "/datamodel/graph",
|
|
41
|
+
icon: Layers,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
label: "Workflows",
|
|
45
|
+
href: "/workflows",
|
|
46
|
+
icon: Workflow,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
[],
|
|
50
|
+
[],
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
const navs = getDashboardNavs();
|
|
54
|
+
|
|
55
|
+
if (navs.top) {
|
|
56
|
+
sections[0] = [...sections[0], ...navs.top];
|
|
57
|
+
}
|
|
58
|
+
if (navs.middle) {
|
|
59
|
+
sections[1] = [...sections[1], ...navs.middle];
|
|
60
|
+
}
|
|
61
|
+
if (navs.bottom) {
|
|
62
|
+
sections[2] = [...sections[2], ...navs.bottom];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// adding the logout server button
|
|
66
|
+
if (!window.APP_ENV.LOBB_URL) {
|
|
67
|
+
sections[2] = [
|
|
68
|
+
...sections[2],
|
|
69
|
+
{
|
|
70
|
+
label: "Log out of the server",
|
|
71
|
+
onclick: () => {
|
|
72
|
+
localStorage.removeItem("lobb_url");
|
|
73
|
+
ctx.lobbUrl = null;
|
|
74
|
+
},
|
|
75
|
+
icon: LogOut,
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
</script>
|
|
80
|
+
|
|
81
|
+
{#snippet section(section: any)}
|
|
82
|
+
<div class="flex flex-col {isSmallScreen ? 'gap-0' : 'gap-2'}">
|
|
83
|
+
{#each section as item}
|
|
84
|
+
{#if isSmallScreen}
|
|
85
|
+
{#if !item.navs}
|
|
86
|
+
<Button
|
|
87
|
+
onclick={() => {
|
|
88
|
+
if (item.onclick) {
|
|
89
|
+
item.onclick();
|
|
90
|
+
} else {
|
|
91
|
+
location.navigate(item.href);
|
|
92
|
+
}
|
|
93
|
+
isCollapsed = true;
|
|
94
|
+
}}
|
|
95
|
+
class="flex items-center justify-start flex-nowrap text-muted-foreground text-nowrap h-10 w-full"
|
|
96
|
+
variant="ghost"
|
|
97
|
+
size="icon"
|
|
98
|
+
Icon={item.icon}
|
|
99
|
+
>
|
|
100
|
+
{item.label}
|
|
101
|
+
</Button>
|
|
102
|
+
{:else}
|
|
103
|
+
<Accordion.Root type="single">
|
|
104
|
+
<Accordion.Item class="border-b-0">
|
|
105
|
+
<Accordion.Trigger class="justify-between p-0 h-10">
|
|
106
|
+
<div
|
|
107
|
+
class="flex items-center gap-2 text-muted-foreground"
|
|
108
|
+
>
|
|
109
|
+
<item.icon size="18" />
|
|
110
|
+
<div class="text-nowrap">{item.label}</div>
|
|
111
|
+
</div>
|
|
112
|
+
</Accordion.Trigger>
|
|
113
|
+
<Accordion.Content class="pl-2 border-l">
|
|
114
|
+
{#each item.navs as childItem}
|
|
115
|
+
<Button
|
|
116
|
+
onclick={() => {
|
|
117
|
+
if (childItem.onclick) {
|
|
118
|
+
childItem.onclick();
|
|
119
|
+
} else {
|
|
120
|
+
location.navigate(item.href);
|
|
121
|
+
}
|
|
122
|
+
isCollapsed = true;
|
|
123
|
+
}}
|
|
124
|
+
class="flex items-center justify-start flex-nowrap text-muted-foreground text-nowrap h-8 w-full"
|
|
125
|
+
variant="ghost"
|
|
126
|
+
size="icon"
|
|
127
|
+
Icon={childItem.icon}
|
|
128
|
+
>
|
|
129
|
+
{childItem.label}
|
|
130
|
+
</Button>
|
|
131
|
+
{/each}
|
|
132
|
+
</Accordion.Content>
|
|
133
|
+
</Accordion.Item>
|
|
134
|
+
</Accordion.Root>
|
|
135
|
+
{/if}
|
|
136
|
+
{:else}
|
|
137
|
+
<Tooltip.Root>
|
|
138
|
+
<Tooltip.Trigger>
|
|
139
|
+
{#if !item.navs}
|
|
140
|
+
<Button
|
|
141
|
+
onclick={() => {
|
|
142
|
+
if (item.onclick) {
|
|
143
|
+
item.onclick();
|
|
144
|
+
}
|
|
145
|
+
isCollapsed = true;
|
|
146
|
+
}}
|
|
147
|
+
href={item.href}
|
|
148
|
+
class="text-muted-foreground"
|
|
149
|
+
variant="ghost"
|
|
150
|
+
size="icon"
|
|
151
|
+
Icon={item.icon}
|
|
152
|
+
></Button>
|
|
153
|
+
{:else}
|
|
154
|
+
<Popover.Root>
|
|
155
|
+
<Popover.Trigger>
|
|
156
|
+
<Button
|
|
157
|
+
class="text-muted-foreground"
|
|
158
|
+
variant="ghost"
|
|
159
|
+
size="icon"
|
|
160
|
+
Icon={item.icon}
|
|
161
|
+
></Button>
|
|
162
|
+
</Popover.Trigger>
|
|
163
|
+
<Popover.Content
|
|
164
|
+
sideOffset={17.5}
|
|
165
|
+
side="right"
|
|
166
|
+
class="popover_content w-60 mb-4 p-0"
|
|
167
|
+
>
|
|
168
|
+
<div class="py-1">
|
|
169
|
+
{#each item.navs as childItem}
|
|
170
|
+
<div
|
|
171
|
+
class="px-1 text-xs text-muted-foreground"
|
|
172
|
+
>
|
|
173
|
+
<Button
|
|
174
|
+
variant="ghost"
|
|
175
|
+
class="flex h-7 w-full justify-start p-2 text-xs font-normal text-muted-foreground"
|
|
176
|
+
Icon={childItem.icon}
|
|
177
|
+
onclick={() => {
|
|
178
|
+
if (childItem.onclick) {
|
|
179
|
+
childItem.onclick();
|
|
180
|
+
}
|
|
181
|
+
}}
|
|
182
|
+
href={childItem.href}
|
|
183
|
+
>
|
|
184
|
+
{childItem.label}
|
|
185
|
+
</Button>
|
|
186
|
+
</div>
|
|
187
|
+
{/each}
|
|
188
|
+
</div>
|
|
189
|
+
</Popover.Content>
|
|
190
|
+
</Popover.Root>
|
|
191
|
+
{/if}
|
|
192
|
+
</Tooltip.Trigger>
|
|
193
|
+
<Tooltip.Content side="right" sideOffset={15}>
|
|
194
|
+
{item.label}
|
|
195
|
+
</Tooltip.Content>
|
|
196
|
+
</Tooltip.Root>
|
|
197
|
+
{/if}
|
|
198
|
+
{/each}
|
|
199
|
+
</div>
|
|
200
|
+
{/snippet}
|
|
201
|
+
|
|
202
|
+
<div
|
|
203
|
+
class="
|
|
204
|
+
{isSmallScreen ? 'fixed top-0 left-0 h-full z-50' : 'relative'}
|
|
205
|
+
border-r bg-background w-screen
|
|
206
|
+
{isCollapsed
|
|
207
|
+
? 'max-w-0 p-0'
|
|
208
|
+
: `max-w-14 ${isSmallScreen ? 'px-3 pb-3' : 'p-2'}`}"
|
|
209
|
+
style="transition: max-width 150ms, padding 150ms; {isSmallScreen &&
|
|
210
|
+
!isCollapsed
|
|
211
|
+
? 'max-width: 100vw'
|
|
212
|
+
: ''}"
|
|
213
|
+
>
|
|
214
|
+
{#if isSmallScreen}
|
|
215
|
+
{#if !isCollapsed}
|
|
216
|
+
<X
|
|
217
|
+
class="absolute h-10 text-muted-foreground hover:bg-transparent cursor-pointer hover:text-foreground"
|
|
218
|
+
style="left: 0.6rem; top: 0rem;"
|
|
219
|
+
size="18"
|
|
220
|
+
onclick={() => (isCollapsed = !isCollapsed)}
|
|
221
|
+
/>
|
|
222
|
+
{/if}
|
|
223
|
+
{/if}
|
|
224
|
+
<div
|
|
225
|
+
class="flex h-full flex-col justify-between gap-2 w-full overflow-hidden"
|
|
226
|
+
>
|
|
227
|
+
<!-- upper part -->
|
|
228
|
+
<div class="flex flex-col gap-2 {isSmallScreen ? 'pt-8' : ''}">
|
|
229
|
+
{@render section(sections[0])}
|
|
230
|
+
<Separator />
|
|
231
|
+
{@render section(sections[1])}
|
|
232
|
+
</div>
|
|
233
|
+
<div class="flex flex-col gap-2">
|
|
234
|
+
<Separator />
|
|
235
|
+
{@render section(sections[2])}
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
@@ -0,0 +1,181 @@
|
|
|
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 "$lib/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>
|