@lobb-js/studio 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/dataTable/dataTable.svelte +17 -1
- package/dist/components/dataTable/table.svelte +28 -4
- package/dist/components/dataTable/table.svelte.d.ts +1 -0
- package/dist/components/drawer.svelte +17 -14
- package/dist/components/extensionsComponents.svelte +1 -1
- package/dist/components/ui/button/button.svelte +1 -0
- package/dist/extensions/extension.types.d.ts +6 -1
- package/dist/extensions/extensionUtils.d.ts +1 -1
- package/dist/extensions/extensionUtils.js +9 -2
- package/package.json +4 -2
- package/src/lib/components/dataTable/dataTable.svelte +17 -1
- package/src/lib/components/dataTable/table.svelte +28 -4
- package/src/lib/components/drawer.svelte +17 -14
- package/src/lib/components/extensionsComponents.svelte +1 -1
- package/src/lib/components/ui/button/button.svelte +1 -0
- package/src/lib/extensions/extension.types.ts +17 -1
- package/src/lib/extensions/extensionUtils.ts +8 -1
- package/dist/components/loadingTypesForMonacoEditor.d.ts +0 -7
- package/dist/components/loadingTypesForMonacoEditor.js +0 -72
- package/src/lib/components/loadingTypesForMonacoEditor.ts +0 -36
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
import UpdateDetailViewButton from "../detailView/update/updateDetailViewButton.svelte";
|
|
16
16
|
import { emitEvent } from "../../eventSystem";
|
|
17
17
|
import type { Snippet } from "svelte";
|
|
18
|
+
import ExtensionsComponents from "../extensionsComponents.svelte";
|
|
19
|
+
import { getExtensionUtils, loadExtensionComponents } from "../../extensions/extensionUtils";
|
|
18
20
|
|
|
19
21
|
const { lobb, ctx } = getStudioContext();
|
|
20
22
|
|
|
@@ -40,6 +42,10 @@
|
|
|
40
42
|
headerLeft,
|
|
41
43
|
}: Props = $props();
|
|
42
44
|
|
|
45
|
+
const hasRowActions = $derived(
|
|
46
|
+
loadExtensionComponents(ctx, "listView.entry.actions", undefined, { collectionName }).length > 0
|
|
47
|
+
);
|
|
48
|
+
|
|
43
49
|
const fields = getCollectionParamsFields(ctx, collectionName);
|
|
44
50
|
let params = $state({
|
|
45
51
|
fields: fields,
|
|
@@ -130,6 +136,16 @@
|
|
|
130
136
|
{unifiedBgColor ? unifiedBgColor : ''}
|
|
131
137
|
"
|
|
132
138
|
>
|
|
139
|
+
{#snippet rowActionsSnippet(entry: Record<string, any>)}
|
|
140
|
+
<ExtensionsComponents
|
|
141
|
+
name="listView.entry.actions"
|
|
142
|
+
utils={getExtensionUtils(lobb, ctx)}
|
|
143
|
+
{entry}
|
|
144
|
+
{collectionName}
|
|
145
|
+
refresh={() => { params = { ...params }; }}
|
|
146
|
+
/>
|
|
147
|
+
{/snippet}
|
|
148
|
+
|
|
133
149
|
{#if showHeader}
|
|
134
150
|
<Header bind:params {collectionName} bind:selectedRecords>
|
|
135
151
|
{#snippet left()}
|
|
@@ -157,7 +173,7 @@
|
|
|
157
173
|
{unifiedBgColor}
|
|
158
174
|
bind:tableWidth={dataTableWidth}
|
|
159
175
|
{...tableProps}
|
|
160
|
-
|
|
176
|
+
rowActions={hasRowActions ? rowActionsSnippet : undefined}>
|
|
161
177
|
{#snippet tools(entry)}
|
|
162
178
|
<UpdateDetailViewButton
|
|
163
179
|
{collectionName}
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
// snippets
|
|
33
33
|
overrideCell?: Snippet<[any, Column, Entry]>;
|
|
34
34
|
tools?: Snippet<[Entry, number]>;
|
|
35
|
+
rowActions?: Snippet<[Entry, number]>;
|
|
35
36
|
collapsible?: Snippet<[Entry, number]>;
|
|
36
37
|
|
|
37
38
|
// other
|
|
@@ -72,6 +73,7 @@
|
|
|
72
73
|
parentWidth,
|
|
73
74
|
overrideCell,
|
|
74
75
|
tools,
|
|
76
|
+
rowActions,
|
|
75
77
|
collapsible,
|
|
76
78
|
unifiedBgColor,
|
|
77
79
|
select,
|
|
@@ -82,6 +84,7 @@
|
|
|
82
84
|
|
|
83
85
|
// calculate columns count
|
|
84
86
|
const toolsExists = selectedRecords || tools ? 1 : 0;
|
|
87
|
+
const rowActionsExists = $derived(rowActions ? 1 : 0);
|
|
85
88
|
const columnsLength = columns.length + toolsExists;
|
|
86
89
|
|
|
87
90
|
// set table width
|
|
@@ -167,8 +170,7 @@
|
|
|
167
170
|
<div
|
|
168
171
|
style="
|
|
169
172
|
display: grid;
|
|
170
|
-
grid-template-columns: minmax(auto, 7.5rem) repeat({columnsLength -
|
|
171
|
-
1}, minmax(auto, 15rem));
|
|
173
|
+
grid-template-columns: minmax(auto, 7.5rem) repeat({columnsLength - 1}, minmax(auto, 15rem)){rowActionsExists ? ' minmax(auto, 7.5rem)' : ''};
|
|
172
174
|
grid-template-rows: 2.5rem;
|
|
173
175
|
"
|
|
174
176
|
>
|
|
@@ -179,7 +181,7 @@
|
|
|
179
181
|
sticky left-0 top-0 z-20
|
|
180
182
|
flex items-center p-2.5 text-xs h-10
|
|
181
183
|
border-r border-b gap-2
|
|
182
|
-
{unifiedBgColor ? unifiedBgColor : 'bg-muted
|
|
184
|
+
{unifiedBgColor ? unifiedBgColor : 'bg-muted'}
|
|
183
185
|
"
|
|
184
186
|
>
|
|
185
187
|
<!-- collapsable toggle -->
|
|
@@ -225,6 +227,16 @@
|
|
|
225
227
|
</div>
|
|
226
228
|
</button>
|
|
227
229
|
{/each}
|
|
230
|
+
{#if rowActions}
|
|
231
|
+
<div
|
|
232
|
+
class="
|
|
233
|
+
sticky top-0 right-0 z-20
|
|
234
|
+
flex items-center p-2.5 h-10
|
|
235
|
+
{unifiedBgColor ? unifiedBgColor : 'bg-muted'}
|
|
236
|
+
border-l border-b
|
|
237
|
+
"
|
|
238
|
+
></div>
|
|
239
|
+
{/if}
|
|
228
240
|
{#if Object.keys(data).length}
|
|
229
241
|
{#each data as entry, index}
|
|
230
242
|
{@const isDisabled = Boolean(entry.__disabled)}
|
|
@@ -292,9 +304,21 @@
|
|
|
292
304
|
{/if}
|
|
293
305
|
</div>
|
|
294
306
|
{/each}
|
|
307
|
+
{#if rowActions}
|
|
308
|
+
<div
|
|
309
|
+
class="
|
|
310
|
+
sticky right-0 z-10
|
|
311
|
+
flex items-center p-2.5 text-xs h-10
|
|
312
|
+
border-l gap-2
|
|
313
|
+
{unifiedBgColor ? unifiedBgColor : 'bg-background'}
|
|
314
|
+
"
|
|
315
|
+
>
|
|
316
|
+
{@render rowActions?.(entry, index)}
|
|
317
|
+
</div>
|
|
318
|
+
{/if}
|
|
295
319
|
<!-- nested data -->
|
|
296
320
|
<div
|
|
297
|
-
style="grid-column: span {columnsLength};"
|
|
321
|
+
style="grid-column: span {columnsLength + rowActionsExists};"
|
|
298
322
|
class="
|
|
299
323
|
{!showLastColumnBorder ? '' : 'border-r'}
|
|
300
324
|
{lastRow && !showLastRowBorder ? '' : 'border-b'}
|
|
@@ -20,6 +20,7 @@ export interface TableProps {
|
|
|
20
20
|
showLastColumnBorder?: boolean;
|
|
21
21
|
overrideCell?: Snippet<[any, Column, Entry]>;
|
|
22
22
|
tools?: Snippet<[Entry, number]>;
|
|
23
|
+
rowActions?: Snippet<[Entry, number]>;
|
|
23
24
|
collapsible?: Snippet<[Entry, number]>;
|
|
24
25
|
parentWidth?: number;
|
|
25
26
|
unifiedBgColor?: "bg-muted/30" | "bg-background";
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { calculateDrawerWidth } from "../utils";
|
|
3
3
|
import type { Snippet } from "svelte";
|
|
4
4
|
import { fade, fly } from "svelte/transition";
|
|
5
|
+
import Portal from "svelte-portal";
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
8
|
children?: Snippet<[]>;
|
|
@@ -11,18 +12,20 @@
|
|
|
11
12
|
let { onHide, children }: Props = $props();
|
|
12
13
|
</script>
|
|
13
14
|
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
<Portal target="body">
|
|
16
|
+
<button
|
|
17
|
+
transition:fade={{ duration: 250 }}
|
|
18
|
+
onclick={() => onHide?.()}
|
|
19
|
+
class="backgroundDrawerButton fixed left-0 top-0 z-40 h-screen w-screen bg-background opacity-50 cursor-default"
|
|
20
|
+
aria-label="background used to hide the background"
|
|
21
|
+
></button>
|
|
20
22
|
|
|
21
|
-
<!-- the drawer -->
|
|
22
|
-
<div
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
>
|
|
27
|
-
|
|
28
|
-
</div>
|
|
23
|
+
<!-- the drawer -->
|
|
24
|
+
<div
|
|
25
|
+
transition:fly={{ x: "100%", duration: 250 }}
|
|
26
|
+
class="fixed right-0 top-0 z-40 flex h-full w-full flex-col border-l bg-background"
|
|
27
|
+
style="max-width: {calculateDrawerWidth()}px;"
|
|
28
|
+
>
|
|
29
|
+
{@render children?.()}
|
|
30
|
+
</div>
|
|
31
|
+
</Portal>
|
|
@@ -73,10 +73,15 @@ export interface ExtensionProps {
|
|
|
73
73
|
utils: ExtensionUtils;
|
|
74
74
|
[key: string]: any;
|
|
75
75
|
}
|
|
76
|
+
export type ExtensionComponentKey = `pages.${string}` | "studio.listView" | `dvFields.topRight.${string}.${string}` | `detailView.update.subRecords.${string}` | `detailView.create.subRecords.${string}` | `detailView.fields.topRight.${string}.${string}` | `detailView.fields.foreignKey.${string}` | `listView.entry.children.${string}` | `listView.entry.actions`;
|
|
77
|
+
export type ExtensionComponent = any | {
|
|
78
|
+
component: any;
|
|
79
|
+
when: (props: Record<string, any>) => boolean;
|
|
80
|
+
};
|
|
76
81
|
export interface Extension {
|
|
77
82
|
name: string;
|
|
78
83
|
onStartup?: (utils: ExtensionUtils) => Promise<void>;
|
|
79
|
-
components?: Record<
|
|
84
|
+
components?: Partial<Record<ExtensionComponentKey, ExtensionComponent>>;
|
|
80
85
|
dashboardNavs?: DashboardNavs;
|
|
81
86
|
}
|
|
82
87
|
export {};
|
|
@@ -4,6 +4,6 @@ import type { CTX } from "../store.types";
|
|
|
4
4
|
export declare function getComponents(): Components;
|
|
5
5
|
export declare function getExtensionUtils(lobb: LobbClient, ctx: CTX): ExtensionUtils;
|
|
6
6
|
export declare function loadExtensions(lobb: LobbClient, ctx: CTX, extensionMap?: Record<string, any>): Promise<Record<string, Extension>>;
|
|
7
|
-
export declare function loadExtensionComponents(ctx: CTX, name: string, filterByExtensions?: string[]): any[];
|
|
7
|
+
export declare function loadExtensionComponents(ctx: CTX, name: string, filterByExtensions?: string[], props?: Record<string, any>): any[];
|
|
8
8
|
export declare function executeExtensionsOnStartup(lobb: LobbClient, ctx: CTX): Promise<void>;
|
|
9
9
|
export declare function getDashboardNavs(ctx: CTX): DashboardNavs;
|
|
@@ -120,7 +120,7 @@ export function loadExtensions(lobb_1, ctx_1) {
|
|
|
120
120
|
});
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
|
-
export function loadExtensionComponents(ctx, name, filterByExtensions) {
|
|
123
|
+
export function loadExtensionComponents(ctx, name, filterByExtensions, props) {
|
|
124
124
|
var components = [];
|
|
125
125
|
for (var _i = 0, _a = Object.entries(ctx.extensions); _i < _a.length; _i++) {
|
|
126
126
|
var _b = _a[_i], extensionName = _b[0], extensionValue = _b[1];
|
|
@@ -131,7 +131,14 @@ export function loadExtensionComponents(ctx, name, filterByExtensions) {
|
|
|
131
131
|
for (var _c = 0, _d = Object.entries(extensionValue.components); _c < _d.length; _c++) {
|
|
132
132
|
var _e = _d[_c], componentName = _e[0], componentValue = _e[1];
|
|
133
133
|
if (name.startsWith(componentName)) {
|
|
134
|
-
|
|
134
|
+
if (componentValue && typeof componentValue === "object" && "component" in componentValue && "when" in componentValue) {
|
|
135
|
+
if (!props || componentValue.when(props)) {
|
|
136
|
+
components.push(componentValue.component);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
components.push(componentValue);
|
|
141
|
+
}
|
|
135
142
|
}
|
|
136
143
|
}
|
|
137
144
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobb-js/studio",
|
|
3
|
-
"
|
|
3
|
+
"license": "UNLICENSED",
|
|
4
|
+
"version": "0.12.0",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"publishConfig": {
|
|
6
7
|
"access": "public"
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
"postpublish": "./scripts/postpublish.sh"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
|
-
"@lobb-js/core": "^0.
|
|
45
|
+
"@lobb-js/core": "^0.18.0",
|
|
45
46
|
"@chromatic-com/storybook": "^4.1.2",
|
|
46
47
|
"@storybook/addon-a11y": "^10.0.1",
|
|
47
48
|
"@storybook/addon-docs": "^10.0.1",
|
|
@@ -107,6 +108,7 @@
|
|
|
107
108
|
"mode-watcher": "^0.5.1",
|
|
108
109
|
"mustache": "^4.2.0",
|
|
109
110
|
"qs": "^6.14.1",
|
|
111
|
+
"svelte-portal": "^2.2.1",
|
|
110
112
|
"svelte-sonner": "^0.3.28",
|
|
111
113
|
"tailwind-merge": "^3.4.0",
|
|
112
114
|
"tailwind-variants": "^3.2.2"
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
import UpdateDetailViewButton from "../detailView/update/updateDetailViewButton.svelte";
|
|
16
16
|
import { emitEvent } from "../../eventSystem";
|
|
17
17
|
import type { Snippet } from "svelte";
|
|
18
|
+
import ExtensionsComponents from "../extensionsComponents.svelte";
|
|
19
|
+
import { getExtensionUtils, loadExtensionComponents } from "../../extensions/extensionUtils";
|
|
18
20
|
|
|
19
21
|
const { lobb, ctx } = getStudioContext();
|
|
20
22
|
|
|
@@ -40,6 +42,10 @@
|
|
|
40
42
|
headerLeft,
|
|
41
43
|
}: Props = $props();
|
|
42
44
|
|
|
45
|
+
const hasRowActions = $derived(
|
|
46
|
+
loadExtensionComponents(ctx, "listView.entry.actions", undefined, { collectionName }).length > 0
|
|
47
|
+
);
|
|
48
|
+
|
|
43
49
|
const fields = getCollectionParamsFields(ctx, collectionName);
|
|
44
50
|
let params = $state({
|
|
45
51
|
fields: fields,
|
|
@@ -130,6 +136,16 @@
|
|
|
130
136
|
{unifiedBgColor ? unifiedBgColor : ''}
|
|
131
137
|
"
|
|
132
138
|
>
|
|
139
|
+
{#snippet rowActionsSnippet(entry: Record<string, any>)}
|
|
140
|
+
<ExtensionsComponents
|
|
141
|
+
name="listView.entry.actions"
|
|
142
|
+
utils={getExtensionUtils(lobb, ctx)}
|
|
143
|
+
{entry}
|
|
144
|
+
{collectionName}
|
|
145
|
+
refresh={() => { params = { ...params }; }}
|
|
146
|
+
/>
|
|
147
|
+
{/snippet}
|
|
148
|
+
|
|
133
149
|
{#if showHeader}
|
|
134
150
|
<Header bind:params {collectionName} bind:selectedRecords>
|
|
135
151
|
{#snippet left()}
|
|
@@ -157,7 +173,7 @@
|
|
|
157
173
|
{unifiedBgColor}
|
|
158
174
|
bind:tableWidth={dataTableWidth}
|
|
159
175
|
{...tableProps}
|
|
160
|
-
|
|
176
|
+
rowActions={hasRowActions ? rowActionsSnippet : undefined}>
|
|
161
177
|
{#snippet tools(entry)}
|
|
162
178
|
<UpdateDetailViewButton
|
|
163
179
|
{collectionName}
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
// snippets
|
|
33
33
|
overrideCell?: Snippet<[any, Column, Entry]>;
|
|
34
34
|
tools?: Snippet<[Entry, number]>;
|
|
35
|
+
rowActions?: Snippet<[Entry, number]>;
|
|
35
36
|
collapsible?: Snippet<[Entry, number]>;
|
|
36
37
|
|
|
37
38
|
// other
|
|
@@ -72,6 +73,7 @@
|
|
|
72
73
|
parentWidth,
|
|
73
74
|
overrideCell,
|
|
74
75
|
tools,
|
|
76
|
+
rowActions,
|
|
75
77
|
collapsible,
|
|
76
78
|
unifiedBgColor,
|
|
77
79
|
select,
|
|
@@ -82,6 +84,7 @@
|
|
|
82
84
|
|
|
83
85
|
// calculate columns count
|
|
84
86
|
const toolsExists = selectedRecords || tools ? 1 : 0;
|
|
87
|
+
const rowActionsExists = $derived(rowActions ? 1 : 0);
|
|
85
88
|
const columnsLength = columns.length + toolsExists;
|
|
86
89
|
|
|
87
90
|
// set table width
|
|
@@ -167,8 +170,7 @@
|
|
|
167
170
|
<div
|
|
168
171
|
style="
|
|
169
172
|
display: grid;
|
|
170
|
-
grid-template-columns: minmax(auto, 7.5rem) repeat({columnsLength -
|
|
171
|
-
1}, minmax(auto, 15rem));
|
|
173
|
+
grid-template-columns: minmax(auto, 7.5rem) repeat({columnsLength - 1}, minmax(auto, 15rem)){rowActionsExists ? ' minmax(auto, 7.5rem)' : ''};
|
|
172
174
|
grid-template-rows: 2.5rem;
|
|
173
175
|
"
|
|
174
176
|
>
|
|
@@ -179,7 +181,7 @@
|
|
|
179
181
|
sticky left-0 top-0 z-20
|
|
180
182
|
flex items-center p-2.5 text-xs h-10
|
|
181
183
|
border-r border-b gap-2
|
|
182
|
-
{unifiedBgColor ? unifiedBgColor : 'bg-muted
|
|
184
|
+
{unifiedBgColor ? unifiedBgColor : 'bg-muted'}
|
|
183
185
|
"
|
|
184
186
|
>
|
|
185
187
|
<!-- collapsable toggle -->
|
|
@@ -225,6 +227,16 @@
|
|
|
225
227
|
</div>
|
|
226
228
|
</button>
|
|
227
229
|
{/each}
|
|
230
|
+
{#if rowActions}
|
|
231
|
+
<div
|
|
232
|
+
class="
|
|
233
|
+
sticky top-0 right-0 z-20
|
|
234
|
+
flex items-center p-2.5 h-10
|
|
235
|
+
{unifiedBgColor ? unifiedBgColor : 'bg-muted'}
|
|
236
|
+
border-l border-b
|
|
237
|
+
"
|
|
238
|
+
></div>
|
|
239
|
+
{/if}
|
|
228
240
|
{#if Object.keys(data).length}
|
|
229
241
|
{#each data as entry, index}
|
|
230
242
|
{@const isDisabled = Boolean(entry.__disabled)}
|
|
@@ -292,9 +304,21 @@
|
|
|
292
304
|
{/if}
|
|
293
305
|
</div>
|
|
294
306
|
{/each}
|
|
307
|
+
{#if rowActions}
|
|
308
|
+
<div
|
|
309
|
+
class="
|
|
310
|
+
sticky right-0 z-10
|
|
311
|
+
flex items-center p-2.5 text-xs h-10
|
|
312
|
+
border-l gap-2
|
|
313
|
+
{unifiedBgColor ? unifiedBgColor : 'bg-background'}
|
|
314
|
+
"
|
|
315
|
+
>
|
|
316
|
+
{@render rowActions?.(entry, index)}
|
|
317
|
+
</div>
|
|
318
|
+
{/if}
|
|
295
319
|
<!-- nested data -->
|
|
296
320
|
<div
|
|
297
|
-
style="grid-column: span {columnsLength};"
|
|
321
|
+
style="grid-column: span {columnsLength + rowActionsExists};"
|
|
298
322
|
class="
|
|
299
323
|
{!showLastColumnBorder ? '' : 'border-r'}
|
|
300
324
|
{lastRow && !showLastRowBorder ? '' : 'border-b'}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { calculateDrawerWidth } from "../utils";
|
|
3
3
|
import type { Snippet } from "svelte";
|
|
4
4
|
import { fade, fly } from "svelte/transition";
|
|
5
|
+
import Portal from "svelte-portal";
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
8
|
children?: Snippet<[]>;
|
|
@@ -11,18 +12,20 @@
|
|
|
11
12
|
let { onHide, children }: Props = $props();
|
|
12
13
|
</script>
|
|
13
14
|
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
<Portal target="body">
|
|
16
|
+
<button
|
|
17
|
+
transition:fade={{ duration: 250 }}
|
|
18
|
+
onclick={() => onHide?.()}
|
|
19
|
+
class="backgroundDrawerButton fixed left-0 top-0 z-40 h-screen w-screen bg-background opacity-50 cursor-default"
|
|
20
|
+
aria-label="background used to hide the background"
|
|
21
|
+
></button>
|
|
20
22
|
|
|
21
|
-
<!-- the drawer -->
|
|
22
|
-
<div
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
>
|
|
27
|
-
|
|
28
|
-
</div>
|
|
23
|
+
<!-- the drawer -->
|
|
24
|
+
<div
|
|
25
|
+
transition:fly={{ x: "100%", duration: 250 }}
|
|
26
|
+
class="fixed right-0 top-0 z-40 flex h-full w-full flex-col border-l bg-background"
|
|
27
|
+
style="max-width: {calculateDrawerWidth()}px;"
|
|
28
|
+
>
|
|
29
|
+
{@render children?.()}
|
|
30
|
+
</div>
|
|
31
|
+
</Portal>
|
|
@@ -83,10 +83,26 @@ export interface ExtensionProps {
|
|
|
83
83
|
[key: string]: any;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// TODO: instead of doing them this way. you can make the components generic and have static keys and we can pass some dynamic data so that we for example extend the list view
|
|
87
|
+
export type ExtensionComponentKey =
|
|
88
|
+
| `pages.${string}`
|
|
89
|
+
| "studio.listView"
|
|
90
|
+
| `dvFields.topRight.${string}.${string}`
|
|
91
|
+
| `detailView.update.subRecords.${string}`
|
|
92
|
+
| `detailView.create.subRecords.${string}`
|
|
93
|
+
| `detailView.fields.topRight.${string}.${string}`
|
|
94
|
+
| `detailView.fields.foreignKey.${string}`
|
|
95
|
+
| `listView.entry.children.${string}`
|
|
96
|
+
| `listView.entry.actions`;
|
|
97
|
+
|
|
98
|
+
export type ExtensionComponent =
|
|
99
|
+
| any
|
|
100
|
+
| { component: any; when: (props: Record<string, any>) => boolean };
|
|
101
|
+
|
|
86
102
|
// extension exported object
|
|
87
103
|
export interface Extension {
|
|
88
104
|
name: string;
|
|
89
105
|
onStartup?: (utils: ExtensionUtils) => Promise<void>;
|
|
90
|
-
components?: Record<
|
|
106
|
+
components?: Partial<Record<ExtensionComponentKey, ExtensionComponent>>;
|
|
91
107
|
dashboardNavs?: DashboardNavs;
|
|
92
108
|
}
|
|
@@ -88,6 +88,7 @@ export function loadExtensionComponents(
|
|
|
88
88
|
ctx: CTX,
|
|
89
89
|
name: string,
|
|
90
90
|
filterByExtensions?: string[],
|
|
91
|
+
props?: Record<string, any>,
|
|
91
92
|
): any[] {
|
|
92
93
|
const components = [];
|
|
93
94
|
for (const [extensionName, extensionValue] of Object.entries(
|
|
@@ -101,7 +102,13 @@ export function loadExtensionComponents(
|
|
|
101
102
|
extensionValue.components,
|
|
102
103
|
)) {
|
|
103
104
|
if (name.startsWith(componentName)) {
|
|
104
|
-
|
|
105
|
+
if (componentValue && typeof componentValue === "object" && "component" in componentValue && "when" in componentValue) {
|
|
106
|
+
if (!props || componentValue.when(props)) {
|
|
107
|
+
components.push(componentValue.component);
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
components.push(componentValue);
|
|
111
|
+
}
|
|
105
112
|
}
|
|
106
113
|
}
|
|
107
114
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
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
|
-
export {};
|
|
@@ -1,72 +0,0 @@
|
|
|
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
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
-
});
|
|
15
|
-
};
|
|
16
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
17
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
18
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
19
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
20
|
-
function step(op) {
|
|
21
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
22
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
23
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
24
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
25
|
-
switch (op[0]) {
|
|
26
|
-
case 0: case 1: t = op; break;
|
|
27
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
28
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
29
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
30
|
-
default:
|
|
31
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
32
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
33
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
34
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
35
|
-
if (t[2]) _.ops.pop();
|
|
36
|
-
_.trys.pop(); continue;
|
|
37
|
-
}
|
|
38
|
-
op = body.call(thisArg, _);
|
|
39
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
40
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
import { gunzipSync } from "fflate";
|
|
44
|
-
import { untar } from "@andrewbranch/untar.js";
|
|
45
|
-
function extractTgz(buffer) {
|
|
46
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
47
|
-
var tarBuffer, cleanBuffer, files, dtsFiles, _i, files_1, file, content;
|
|
48
|
-
return __generator(this, function (_a) {
|
|
49
|
-
switch (_a.label) {
|
|
50
|
-
case 0:
|
|
51
|
-
tarBuffer = gunzipSync(new Uint8Array(buffer));
|
|
52
|
-
cleanBuffer = tarBuffer.buffer.slice(tarBuffer.byteOffset, tarBuffer.byteOffset + tarBuffer.byteLength);
|
|
53
|
-
return [4 /*yield*/, untar(cleanBuffer)];
|
|
54
|
-
case 1:
|
|
55
|
-
files = _a.sent();
|
|
56
|
-
dtsFiles = [];
|
|
57
|
-
for (_i = 0, files_1 = files; _i < files_1.length; _i++) {
|
|
58
|
-
file = files_1[_i];
|
|
59
|
-
if (file.filename.endsWith(".d.ts")) {
|
|
60
|
-
content = new TextDecoder().decode(file.fileData);
|
|
61
|
-
dtsFiles.push({ name: file.filename, content: content });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return [2 /*return*/, dtsFiles];
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
var tgzURL = "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz";
|
|
70
|
-
var response = await fetch(tgzURL);
|
|
71
|
-
var arrayBuffer = await response.arrayBuffer();
|
|
72
|
-
var files = await extractTgz(arrayBuffer);
|
|
@@ -1,36 +0,0 @@
|
|
|
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);
|