@r2digisolutions/components 0.1.6 → 0.1.7
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/README.md +1 -1
- package/dist/components/atoms/Checkbox/Checkbox.svelte +10 -3
- package/dist/components/atoms/Checkbox/Checkbox.svelte.d.ts +3 -0
- package/dist/components/atoms/Input/Input.svelte +17 -2
- package/dist/components/atoms/Input/Input.svelte.d.ts +6 -1
- package/dist/components/atoms/MarqueeRect/MarqueeRect.svelte +21 -0
- package/dist/components/atoms/MarqueeRect/MarqueeRect.svelte.d.ts +8 -0
- package/dist/components/atoms/Textarea/Textarea.svelte +4 -1
- package/dist/components/atoms/Textarea/Textarea.svelte.d.ts +1 -0
- package/dist/components/atoms/Toggle/Toggle.svelte +1 -1
- package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte +19 -5
- package/dist/components/molecules/CodeEditor/CodeEditor.svelte +13 -10
- package/dist/components/molecules/ColorPicker/ColorPicker.svelte +166 -96
- package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.stories.d.ts +9 -0
- package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.stories.js +8 -0
- package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.svelte +412 -0
- package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.svelte.d.ts +14 -0
- package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanelStory.svelte +27 -0
- package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanelStory.svelte.d.ts +3 -0
- package/dist/components/molecules/ContextMenu/ContextMenu.svelte +73 -21
- package/dist/components/molecules/ContextMenu/ContextMenu.svelte.d.ts +8 -1
- package/dist/components/molecules/DateTimePicker/DateTimePicker.svelte.d.ts +1 -1
- package/dist/components/molecules/FormDateTimePicker/FormDateTimePicker.svelte.d.ts +1 -1
- package/dist/components/molecules/Gauge/Gauge.stories.d.ts +1 -1
- package/dist/components/molecules/InfiniteScroll/InfiniteScroll.stories.d.ts +1 -1
- package/dist/components/organisms/AssetPickerPage/AssetPickerPage.svelte.d.ts +1 -1
- package/dist/components/organisms/BacklogPage/BacklogPage.svelte.d.ts +1 -1
- package/dist/components/organisms/CalendarApp/CalendarApp.svelte.d.ts +1 -1
- package/dist/components/organisms/DataGrid/DataGrid.stories.d.ts +65 -0
- package/dist/components/organisms/DataGrid/DataGrid.stories.js +95 -0
- package/dist/components/organisms/DataGrid/DataGrid.svelte +2264 -0
- package/dist/components/organisms/DataGrid/DataGrid.svelte.d.ts +99 -0
- package/dist/components/organisms/DataGrid/DataGridStory.svelte +659 -0
- package/dist/components/organisms/DataGrid/DataGridStory.svelte.d.ts +11 -0
- package/dist/components/organisms/DataGrid/breakpoints.d.ts +10 -0
- package/dist/components/organisms/DataGrid/breakpoints.js +20 -0
- package/dist/components/organisms/DataGrid/cellEditors.d.ts +8 -0
- package/dist/components/organisms/DataGrid/cellEditors.js +59 -0
- package/dist/components/organisms/DataGrid/conditionalFormat.d.ts +11 -0
- package/dist/components/organisms/DataGrid/conditionalFormat.js +98 -0
- package/dist/components/organisms/DataGrid/filterRows.d.ts +5 -0
- package/dist/components/organisms/DataGrid/filterRows.js +60 -0
- package/dist/components/organisms/DataGrid/marks.d.ts +9 -0
- package/dist/components/organisms/DataGrid/marks.js +91 -0
- package/dist/components/organisms/DataGrid/types.d.ts +126 -0
- package/dist/components/organisms/DataGrid/types.js +21 -0
- package/dist/components/organisms/ResourceStudio/ResourceStudio.stories.d.ts +33 -0
- package/dist/components/organisms/ResourceStudio/ResourceStudio.stories.js +56 -0
- package/dist/components/organisms/ResourceStudio/ResourceStudio.svelte +830 -0
- package/dist/components/organisms/ResourceStudio/ResourceStudio.svelte.d.ts +68 -0
- package/dist/components/organisms/ResourceStudio/ResourceStudioStory.svelte +600 -0
- package/dist/components/organisms/ResourceStudio/ResourceStudioStory.svelte.d.ts +7 -0
- package/dist/components/organisms/ResourceStudio/fieldsToColumns.d.ts +4 -0
- package/dist/components/organisms/ResourceStudio/fieldsToColumns.js +20 -0
- package/dist/components/organisms/ResourceStudio/fieldsToSchema.d.ts +6 -0
- package/dist/components/organisms/ResourceStudio/fieldsToSchema.js +53 -0
- package/dist/components/organisms/ResourceStudio/types.d.ts +69 -0
- package/dist/components/organisms/ResourceStudio/types.js +15 -0
- package/dist/components/organisms/Scheduler/Scheduler.svelte.d.ts +1 -1
- package/dist/components/organisms/SchemaForm/SchemaForm.svelte +10 -3
- package/dist/components/organisms/SchemaForm/SchemaForm.svelte.d.ts +1 -0
- package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.stories.d.ts +25 -0
- package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.stories.js +18 -0
- package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.svelte +192 -0
- package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.svelte.d.ts +62 -0
- package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplateStory.svelte +129 -0
- package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplateStory.svelte.d.ts +7 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +8 -0
- package/dist/utils/marqueeSelect.d.ts +48 -0
- package/dist/utils/marqueeSelect.js +189 -0
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Map ResourceField[] → DataGrid columns (skips hidden fields). */
|
|
2
|
+
export function fieldsToColumns(fields) {
|
|
3
|
+
return fields
|
|
4
|
+
.filter((f) => !f.hidden)
|
|
5
|
+
.map((f) => ({
|
|
6
|
+
id: f.id,
|
|
7
|
+
header: f.label,
|
|
8
|
+
accessor: f.id,
|
|
9
|
+
sortable: true,
|
|
10
|
+
editable: !f.readonly,
|
|
11
|
+
align: f.type === 'number' ? 'right' : 'left',
|
|
12
|
+
meta: {
|
|
13
|
+
fieldType: f.type,
|
|
14
|
+
options: f.options,
|
|
15
|
+
relation: f.relation,
|
|
16
|
+
required: f.required,
|
|
17
|
+
...f.meta
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SchemaField } from '../SchemaForm/SchemaForm.svelte';
|
|
2
|
+
import type { ResourceField } from './types.js';
|
|
3
|
+
/** Map ResourceField[] → SchemaForm fields (design-system controls). */
|
|
4
|
+
export declare function fieldsToSchema(fields: ResourceField[], options?: {
|
|
5
|
+
mode?: 'create' | 'edit';
|
|
6
|
+
}): SchemaField[];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
function mapFieldType(field) {
|
|
2
|
+
switch (field.type) {
|
|
3
|
+
case 'text':
|
|
4
|
+
case 'json':
|
|
5
|
+
return 'textarea';
|
|
6
|
+
case 'number':
|
|
7
|
+
return 'number';
|
|
8
|
+
case 'boolean':
|
|
9
|
+
return 'toggle';
|
|
10
|
+
case 'date':
|
|
11
|
+
case 'datetime':
|
|
12
|
+
return 'date';
|
|
13
|
+
case 'enum':
|
|
14
|
+
return 'select';
|
|
15
|
+
case 'string':
|
|
16
|
+
case 'relation':
|
|
17
|
+
case 'file':
|
|
18
|
+
case 'custom':
|
|
19
|
+
default:
|
|
20
|
+
return field.options?.length ? 'select' : 'text';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function coerceDefault(field) {
|
|
24
|
+
if (field.defaultValue === undefined)
|
|
25
|
+
return undefined;
|
|
26
|
+
if (field.type === 'boolean')
|
|
27
|
+
return Boolean(field.defaultValue);
|
|
28
|
+
if (field.type === 'number') {
|
|
29
|
+
const n = Number(field.defaultValue);
|
|
30
|
+
return Number.isFinite(n) ? n : undefined;
|
|
31
|
+
}
|
|
32
|
+
return String(field.defaultValue);
|
|
33
|
+
}
|
|
34
|
+
/** Map ResourceField[] → SchemaForm fields (design-system controls). */
|
|
35
|
+
export function fieldsToSchema(fields, options) {
|
|
36
|
+
const mode = options?.mode ?? 'create';
|
|
37
|
+
return fields
|
|
38
|
+
.filter((f) => !f.hidden)
|
|
39
|
+
.filter((f) => mode === 'edit' || !f.readonly)
|
|
40
|
+
.map((f) => ({
|
|
41
|
+
name: f.id,
|
|
42
|
+
label: f.label,
|
|
43
|
+
type: mapFieldType(f),
|
|
44
|
+
required: f.required,
|
|
45
|
+
helperText: f.description,
|
|
46
|
+
options: f.options?.map((o) => ({ value: o.value, label: o.label })),
|
|
47
|
+
defaultValue: coerceDefault(f),
|
|
48
|
+
disabled: mode === 'edit' && Boolean(f.readonly),
|
|
49
|
+
placeholder: f.type === 'enum' || f.options?.length
|
|
50
|
+
? `Select ${f.label.toLowerCase()}…`
|
|
51
|
+
: undefined
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ConditionalFormatRule } from '../DataGrid/types.js';
|
|
2
|
+
export type FieldType = 'string' | 'text' | 'number' | 'boolean' | 'date' | 'datetime' | 'enum' | 'json' | 'relation' | 'file' | 'custom';
|
|
3
|
+
export interface ResourceField {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
type: FieldType;
|
|
7
|
+
description?: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
unique?: boolean;
|
|
10
|
+
readonly?: boolean;
|
|
11
|
+
hidden?: boolean;
|
|
12
|
+
defaultValue?: unknown;
|
|
13
|
+
options?: {
|
|
14
|
+
value: string;
|
|
15
|
+
label: string;
|
|
16
|
+
}[];
|
|
17
|
+
relation?: {
|
|
18
|
+
resourceId: string;
|
|
19
|
+
fieldId: string;
|
|
20
|
+
displayField?: string;
|
|
21
|
+
};
|
|
22
|
+
meta?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
export interface ResourceCapabilities {
|
|
25
|
+
create?: boolean;
|
|
26
|
+
update?: boolean;
|
|
27
|
+
delete?: boolean;
|
|
28
|
+
duplicate?: boolean;
|
|
29
|
+
export?: boolean;
|
|
30
|
+
import?: boolean;
|
|
31
|
+
bulkEdit?: boolean;
|
|
32
|
+
notes?: boolean;
|
|
33
|
+
conditionalFormat?: boolean;
|
|
34
|
+
editable?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface ResourceDefinition {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
group?: string;
|
|
41
|
+
icon?: string;
|
|
42
|
+
fields: ResourceField[];
|
|
43
|
+
primaryKey?: string;
|
|
44
|
+
recordCount?: number;
|
|
45
|
+
capabilities?: ResourceCapabilities;
|
|
46
|
+
defaultFormatRules?: ConditionalFormatRule[];
|
|
47
|
+
}
|
|
48
|
+
export type ResourceStudioMode = 'browse' | 'detail' | 'schema' | 'query' | 'activity';
|
|
49
|
+
export type ResourceStudioLayout = 'sidebar-main' | 'sidebar-main-detail' | 'main-only';
|
|
50
|
+
export interface ResourceStudioLabels {
|
|
51
|
+
resources?: string;
|
|
52
|
+
records?: string;
|
|
53
|
+
addRecord?: string;
|
|
54
|
+
schema?: string;
|
|
55
|
+
runQuery?: string;
|
|
56
|
+
searchPlaceholder?: string;
|
|
57
|
+
detail?: string;
|
|
58
|
+
activity?: string;
|
|
59
|
+
query?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface ResourceStudioView {
|
|
62
|
+
id: string;
|
|
63
|
+
label: string;
|
|
64
|
+
resourceId?: string;
|
|
65
|
+
query?: string;
|
|
66
|
+
formatRuleIds?: string[];
|
|
67
|
+
}
|
|
68
|
+
export declare const DEFAULT_CAPABILITIES: Required<ResourceCapabilities>;
|
|
69
|
+
export declare function resolveCapabilities(caps?: ResourceCapabilities): Required<ResourceCapabilities>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const DEFAULT_CAPABILITIES = {
|
|
2
|
+
create: true,
|
|
3
|
+
update: true,
|
|
4
|
+
delete: true,
|
|
5
|
+
duplicate: false,
|
|
6
|
+
export: true,
|
|
7
|
+
import: false,
|
|
8
|
+
bulkEdit: false,
|
|
9
|
+
notes: true,
|
|
10
|
+
conditionalFormat: true,
|
|
11
|
+
editable: true
|
|
12
|
+
};
|
|
13
|
+
export function resolveCapabilities(caps) {
|
|
14
|
+
return { ...DEFAULT_CAPABILITIES, ...caps };
|
|
15
|
+
}
|
|
@@ -92,6 +92,6 @@ interface SchedulerProps {
|
|
|
92
92
|
onconfirm?: (detail: ScheduleConfirmDetail) => void;
|
|
93
93
|
onclear?: () => void;
|
|
94
94
|
}
|
|
95
|
-
declare const Scheduler: import("svelte").Component<SchedulerProps, {}, "
|
|
95
|
+
declare const Scheduler: import("svelte").Component<SchedulerProps, {}, "date" | "start" | "end" | "duration" | "bookings" | "selectedSlotId" | "slotLayout">;
|
|
96
96
|
type Scheduler = ReturnType<typeof Scheduler>;
|
|
97
97
|
export default Scheduler;
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
placeholder?: string;
|
|
41
41
|
helperText?: string;
|
|
42
42
|
required?: boolean;
|
|
43
|
+
disabled?: boolean;
|
|
43
44
|
options?: SchemaFieldOption[];
|
|
44
45
|
/** Group heading before this field */
|
|
45
46
|
section?: string;
|
|
@@ -151,6 +152,7 @@
|
|
|
151
152
|
placeholder={field.placeholder}
|
|
152
153
|
helperText={field.helperText}
|
|
153
154
|
required={field.required}
|
|
155
|
+
disabled={field.disabled}
|
|
154
156
|
bindData
|
|
155
157
|
/>
|
|
156
158
|
{:else if type === 'select'}
|
|
@@ -160,6 +162,7 @@
|
|
|
160
162
|
placeholder={field.placeholder ?? 'Select…'}
|
|
161
163
|
helperText={field.helperText}
|
|
162
164
|
required={field.required}
|
|
165
|
+
disabled={field.disabled}
|
|
163
166
|
options={field.options ?? []}
|
|
164
167
|
bindData
|
|
165
168
|
/>
|
|
@@ -168,6 +171,7 @@
|
|
|
168
171
|
name={field.name}
|
|
169
172
|
label={field.label}
|
|
170
173
|
helperText={field.helperText}
|
|
174
|
+
disabled={field.disabled}
|
|
171
175
|
bindData
|
|
172
176
|
/>
|
|
173
177
|
{:else if type === 'checkbox'}
|
|
@@ -175,6 +179,7 @@
|
|
|
175
179
|
name={field.name}
|
|
176
180
|
label={field.label}
|
|
177
181
|
helperText={field.helperText}
|
|
182
|
+
disabled={field.disabled}
|
|
178
183
|
bindData
|
|
179
184
|
/>
|
|
180
185
|
{:else if type === 'password'}
|
|
@@ -184,6 +189,7 @@
|
|
|
184
189
|
placeholder={field.placeholder}
|
|
185
190
|
helperText={field.helperText}
|
|
186
191
|
required={field.required}
|
|
192
|
+
disabled={field.disabled}
|
|
187
193
|
bindData
|
|
188
194
|
/>
|
|
189
195
|
{:else if type === 'date'}
|
|
@@ -191,7 +197,7 @@
|
|
|
191
197
|
<DatePicker
|
|
192
198
|
label={field.label}
|
|
193
199
|
placeholder={field.placeholder ?? 'Select date…'}
|
|
194
|
-
disabled={loading}
|
|
200
|
+
disabled={loading || field.disabled}
|
|
195
201
|
value={String(values[field.name] ?? '')}
|
|
196
202
|
onchange={(detail) => setValue(field.name, detail.value)}
|
|
197
203
|
/>
|
|
@@ -207,7 +213,7 @@
|
|
|
207
213
|
label={field.label}
|
|
208
214
|
options={field.options ?? []}
|
|
209
215
|
required={field.required}
|
|
210
|
-
disabled={loading}
|
|
216
|
+
disabled={loading || field.disabled}
|
|
211
217
|
status={fieldError ? 'error' : 'default'}
|
|
212
218
|
helperText={fieldError ?? field.helperText}
|
|
213
219
|
value={String(values[field.name] ?? '')}
|
|
@@ -219,7 +225,7 @@
|
|
|
219
225
|
label={field.label}
|
|
220
226
|
placeholder={field.placeholder ?? 'Select…'}
|
|
221
227
|
options={field.options ?? []}
|
|
222
|
-
disabled={loading}
|
|
228
|
+
disabled={loading || field.disabled}
|
|
223
229
|
value={Array.isArray(values[field.name]) ? (values[field.name] as string[]) : []}
|
|
224
230
|
onchange={(v) => setValue(field.name, v)}
|
|
225
231
|
/>
|
|
@@ -237,6 +243,7 @@
|
|
|
237
243
|
placeholder={field.placeholder}
|
|
238
244
|
helperText={field.helperText}
|
|
239
245
|
required={field.required}
|
|
246
|
+
disabled={field.disabled}
|
|
240
247
|
bindData
|
|
241
248
|
/>
|
|
242
249
|
{/if}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/svelte';
|
|
2
|
+
declare const meta: {
|
|
3
|
+
title: string;
|
|
4
|
+
component: import("svelte").Component<{
|
|
5
|
+
example?: "sql" | "mainOnly" | "crud";
|
|
6
|
+
}, {}, "">;
|
|
7
|
+
tags: string[];
|
|
8
|
+
argTypes: {
|
|
9
|
+
example: {
|
|
10
|
+
control: "select";
|
|
11
|
+
options: string[];
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
args: {
|
|
15
|
+
example: "crud";
|
|
16
|
+
};
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: string;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export default meta;
|
|
22
|
+
type Story = StoryObj<typeof meta>;
|
|
23
|
+
export declare const CrudAdmin: Story;
|
|
24
|
+
export declare const SqlBrowser: Story;
|
|
25
|
+
export declare const MainOnly: Story;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import ResourceStudioTemplateStory from './ResourceStudioTemplateStory.svelte';
|
|
2
|
+
const meta = {
|
|
3
|
+
title: 'Templates/ResourceStudioTemplate',
|
|
4
|
+
component: ResourceStudioTemplateStory,
|
|
5
|
+
tags: ['autodocs'],
|
|
6
|
+
argTypes: {
|
|
7
|
+
example: {
|
|
8
|
+
control: 'select',
|
|
9
|
+
options: ['crud', 'sql', 'mainOnly']
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
args: { example: 'crud' },
|
|
13
|
+
parameters: { layout: 'fullscreen' }
|
|
14
|
+
};
|
|
15
|
+
export default meta;
|
|
16
|
+
export const CrudAdmin = {};
|
|
17
|
+
export const SqlBrowser = { args: { example: 'sql' } };
|
|
18
|
+
export const MainOnly = { args: { example: 'mainOnly' } };
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import ResourceStudio from '../../organisms/ResourceStudio/ResourceStudio.svelte';
|
|
4
|
+
import type {
|
|
5
|
+
ResourceDefinition,
|
|
6
|
+
ResourceStudioLabels,
|
|
7
|
+
ResourceStudioLayout,
|
|
8
|
+
ResourceStudioMode,
|
|
9
|
+
ResourceStudioView
|
|
10
|
+
} from '../../organisms/ResourceStudio/types.js';
|
|
11
|
+
import type {
|
|
12
|
+
CellNote,
|
|
13
|
+
ConditionalFormatRule,
|
|
14
|
+
GridSelection
|
|
15
|
+
} from '../../organisms/DataGrid/types.js';
|
|
16
|
+
import { EMPTY_SELECTION } from '../../organisms/DataGrid/types.js';
|
|
17
|
+
import PageHeader from '../../molecules/PageHeader/PageHeader.svelte';
|
|
18
|
+
|
|
19
|
+
interface ResourceStudioTemplateProps {
|
|
20
|
+
title?: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
resources?: ResourceDefinition[];
|
|
23
|
+
activeResourceId?: string;
|
|
24
|
+
records?: Record<string, unknown>[];
|
|
25
|
+
totalRecords?: number;
|
|
26
|
+
loading?: boolean;
|
|
27
|
+
page?: number;
|
|
28
|
+
pageSize?: number;
|
|
29
|
+
query?: string;
|
|
30
|
+
selection?: GridSelection;
|
|
31
|
+
notes?: CellNote[];
|
|
32
|
+
formatRules?: ConditionalFormatRule[];
|
|
33
|
+
modes?: ResourceStudioMode[];
|
|
34
|
+
activeMode?: ResourceStudioMode;
|
|
35
|
+
layout?: ResourceStudioLayout;
|
|
36
|
+
labels?: ResourceStudioLabels;
|
|
37
|
+
views?: ResourceStudioView[];
|
|
38
|
+
activeViewId?: string;
|
|
39
|
+
showHeader?: boolean;
|
|
40
|
+
class?: string;
|
|
41
|
+
headerActions?: Snippet;
|
|
42
|
+
toolbar?: Snippet;
|
|
43
|
+
sidebarItem?: Snippet<[ResourceDefinition, boolean]>;
|
|
44
|
+
sidebarFooter?: Snippet;
|
|
45
|
+
detail?: Snippet<[record: Record<string, unknown> | null]>;
|
|
46
|
+
schemaPanel?: Snippet<[ResourceDefinition]>;
|
|
47
|
+
queryPanel?: Snippet;
|
|
48
|
+
activityPanel?: Snippet;
|
|
49
|
+
recordForm?: Snippet<[mode: 'create' | 'edit', record: Record<string, unknown> | null]>;
|
|
50
|
+
empty?: Snippet;
|
|
51
|
+
dockExtra?: Snippet;
|
|
52
|
+
cell?: Snippet<[Record<string, unknown>, { id: string; header: string }]>;
|
|
53
|
+
onresourcechange?: (id: string) => void;
|
|
54
|
+
onsearch?: (q: string) => void;
|
|
55
|
+
onpagechange?: (page: number, pageSize: number) => void;
|
|
56
|
+
onsort?: (columnId: string, dir: 'asc' | 'desc') => void;
|
|
57
|
+
oncreate?: () => void;
|
|
58
|
+
oninsert?: (record: Record<string, unknown>) => void;
|
|
59
|
+
onupdate?: (id: string, patch: Record<string, unknown>) => void;
|
|
60
|
+
ondelete?: (ids: string[]) => void;
|
|
61
|
+
onduplicate?: (ids: string[]) => void;
|
|
62
|
+
onexport?: (ids: string[] | 'all') => void;
|
|
63
|
+
onimport?: (file: File) => void;
|
|
64
|
+
oncelledit?: (id: string, fieldId: string, value: unknown) => void;
|
|
65
|
+
onselectionchange?: (s: GridSelection) => void;
|
|
66
|
+
onnoteschange?: (notes: CellNote[]) => void;
|
|
67
|
+
onformatruleschange?: (rules: ConditionalFormatRule[]) => void;
|
|
68
|
+
onmodechange?: (mode: ResourceStudioMode) => void;
|
|
69
|
+
onviewchange?: (viewId: string) => void;
|
|
70
|
+
onrefresh?: () => void;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let {
|
|
74
|
+
title = 'Resource Studio',
|
|
75
|
+
description = 'Browse and edit collections with a moldable CRUD shell.',
|
|
76
|
+
resources = [],
|
|
77
|
+
activeResourceId = $bindable(''),
|
|
78
|
+
records = [],
|
|
79
|
+
totalRecords,
|
|
80
|
+
loading = false,
|
|
81
|
+
page = $bindable(1),
|
|
82
|
+
pageSize = 25,
|
|
83
|
+
query = $bindable(''),
|
|
84
|
+
selection = $bindable<GridSelection>(EMPTY_SELECTION),
|
|
85
|
+
notes = $bindable<CellNote[]>([]),
|
|
86
|
+
formatRules = $bindable<ConditionalFormatRule[]>([]),
|
|
87
|
+
modes,
|
|
88
|
+
activeMode = $bindable<ResourceStudioMode>('browse'),
|
|
89
|
+
layout = 'sidebar-main-detail',
|
|
90
|
+
labels,
|
|
91
|
+
views = [],
|
|
92
|
+
activeViewId = $bindable(''),
|
|
93
|
+
showHeader = true,
|
|
94
|
+
class: className = '',
|
|
95
|
+
headerActions,
|
|
96
|
+
toolbar,
|
|
97
|
+
sidebarItem,
|
|
98
|
+
sidebarFooter,
|
|
99
|
+
detail,
|
|
100
|
+
schemaPanel,
|
|
101
|
+
queryPanel,
|
|
102
|
+
activityPanel,
|
|
103
|
+
recordForm,
|
|
104
|
+
empty,
|
|
105
|
+
dockExtra,
|
|
106
|
+
cell,
|
|
107
|
+
onresourcechange,
|
|
108
|
+
onsearch,
|
|
109
|
+
onpagechange,
|
|
110
|
+
onsort,
|
|
111
|
+
oncreate,
|
|
112
|
+
oninsert,
|
|
113
|
+
onupdate,
|
|
114
|
+
ondelete,
|
|
115
|
+
onduplicate,
|
|
116
|
+
onexport,
|
|
117
|
+
onimport,
|
|
118
|
+
oncelledit,
|
|
119
|
+
onselectionchange,
|
|
120
|
+
onnoteschange,
|
|
121
|
+
onformatruleschange,
|
|
122
|
+
onmodechange,
|
|
123
|
+
onviewchange,
|
|
124
|
+
onrefresh
|
|
125
|
+
}: ResourceStudioTemplateProps = $props();
|
|
126
|
+
</script>
|
|
127
|
+
|
|
128
|
+
<div class={['flex h-svh min-h-0 w-full flex-col bg-surface', className]}>
|
|
129
|
+
{#if showHeader}
|
|
130
|
+
<div class="shrink-0 border-b border-border px-4 py-3 sm:px-6">
|
|
131
|
+
<PageHeader {title} {description}>
|
|
132
|
+
{#snippet actions()}
|
|
133
|
+
{#if headerActions}
|
|
134
|
+
{@render headerActions()}
|
|
135
|
+
{/if}
|
|
136
|
+
{/snippet}
|
|
137
|
+
</PageHeader>
|
|
138
|
+
</div>
|
|
139
|
+
{/if}
|
|
140
|
+
|
|
141
|
+
<div class="min-h-0 flex-1 p-3 sm:p-4">
|
|
142
|
+
<ResourceStudio
|
|
143
|
+
{resources}
|
|
144
|
+
bind:activeResourceId
|
|
145
|
+
{records}
|
|
146
|
+
{totalRecords}
|
|
147
|
+
{loading}
|
|
148
|
+
bind:page
|
|
149
|
+
{pageSize}
|
|
150
|
+
bind:query
|
|
151
|
+
bind:selection
|
|
152
|
+
bind:notes
|
|
153
|
+
bind:formatRules
|
|
154
|
+
{modes}
|
|
155
|
+
bind:activeMode
|
|
156
|
+
{layout}
|
|
157
|
+
{labels}
|
|
158
|
+
{views}
|
|
159
|
+
bind:activeViewId
|
|
160
|
+
class="h-full min-h-0"
|
|
161
|
+
{toolbar}
|
|
162
|
+
{sidebarItem}
|
|
163
|
+
{sidebarFooter}
|
|
164
|
+
{detail}
|
|
165
|
+
{schemaPanel}
|
|
166
|
+
{queryPanel}
|
|
167
|
+
{activityPanel}
|
|
168
|
+
{recordForm}
|
|
169
|
+
{empty}
|
|
170
|
+
{dockExtra}
|
|
171
|
+
{cell}
|
|
172
|
+
{onresourcechange}
|
|
173
|
+
{onsearch}
|
|
174
|
+
{onpagechange}
|
|
175
|
+
{onsort}
|
|
176
|
+
{oncreate}
|
|
177
|
+
{oninsert}
|
|
178
|
+
{onupdate}
|
|
179
|
+
{ondelete}
|
|
180
|
+
{onduplicate}
|
|
181
|
+
{onexport}
|
|
182
|
+
{onimport}
|
|
183
|
+
{oncelledit}
|
|
184
|
+
{onselectionchange}
|
|
185
|
+
{onnoteschange}
|
|
186
|
+
{onformatruleschange}
|
|
187
|
+
{onmodechange}
|
|
188
|
+
{onviewchange}
|
|
189
|
+
{onrefresh}
|
|
190
|
+
/>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { ResourceDefinition, ResourceStudioLabels, ResourceStudioLayout, ResourceStudioMode, ResourceStudioView } from '../../organisms/ResourceStudio/types.js';
|
|
3
|
+
import type { CellNote, ConditionalFormatRule, GridSelection } from '../../organisms/DataGrid/types.js';
|
|
4
|
+
interface ResourceStudioTemplateProps {
|
|
5
|
+
title?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
resources?: ResourceDefinition[];
|
|
8
|
+
activeResourceId?: string;
|
|
9
|
+
records?: Record<string, unknown>[];
|
|
10
|
+
totalRecords?: number;
|
|
11
|
+
loading?: boolean;
|
|
12
|
+
page?: number;
|
|
13
|
+
pageSize?: number;
|
|
14
|
+
query?: string;
|
|
15
|
+
selection?: GridSelection;
|
|
16
|
+
notes?: CellNote[];
|
|
17
|
+
formatRules?: ConditionalFormatRule[];
|
|
18
|
+
modes?: ResourceStudioMode[];
|
|
19
|
+
activeMode?: ResourceStudioMode;
|
|
20
|
+
layout?: ResourceStudioLayout;
|
|
21
|
+
labels?: ResourceStudioLabels;
|
|
22
|
+
views?: ResourceStudioView[];
|
|
23
|
+
activeViewId?: string;
|
|
24
|
+
showHeader?: boolean;
|
|
25
|
+
class?: string;
|
|
26
|
+
headerActions?: Snippet;
|
|
27
|
+
toolbar?: Snippet;
|
|
28
|
+
sidebarItem?: Snippet<[ResourceDefinition, boolean]>;
|
|
29
|
+
sidebarFooter?: Snippet;
|
|
30
|
+
detail?: Snippet<[record: Record<string, unknown> | null]>;
|
|
31
|
+
schemaPanel?: Snippet<[ResourceDefinition]>;
|
|
32
|
+
queryPanel?: Snippet;
|
|
33
|
+
activityPanel?: Snippet;
|
|
34
|
+
recordForm?: Snippet<[mode: 'create' | 'edit', record: Record<string, unknown> | null]>;
|
|
35
|
+
empty?: Snippet;
|
|
36
|
+
dockExtra?: Snippet;
|
|
37
|
+
cell?: Snippet<[Record<string, unknown>, {
|
|
38
|
+
id: string;
|
|
39
|
+
header: string;
|
|
40
|
+
}]>;
|
|
41
|
+
onresourcechange?: (id: string) => void;
|
|
42
|
+
onsearch?: (q: string) => void;
|
|
43
|
+
onpagechange?: (page: number, pageSize: number) => void;
|
|
44
|
+
onsort?: (columnId: string, dir: 'asc' | 'desc') => void;
|
|
45
|
+
oncreate?: () => void;
|
|
46
|
+
oninsert?: (record: Record<string, unknown>) => void;
|
|
47
|
+
onupdate?: (id: string, patch: Record<string, unknown>) => void;
|
|
48
|
+
ondelete?: (ids: string[]) => void;
|
|
49
|
+
onduplicate?: (ids: string[]) => void;
|
|
50
|
+
onexport?: (ids: string[] | 'all') => void;
|
|
51
|
+
onimport?: (file: File) => void;
|
|
52
|
+
oncelledit?: (id: string, fieldId: string, value: unknown) => void;
|
|
53
|
+
onselectionchange?: (s: GridSelection) => void;
|
|
54
|
+
onnoteschange?: (notes: CellNote[]) => void;
|
|
55
|
+
onformatruleschange?: (rules: ConditionalFormatRule[]) => void;
|
|
56
|
+
onmodechange?: (mode: ResourceStudioMode) => void;
|
|
57
|
+
onviewchange?: (viewId: string) => void;
|
|
58
|
+
onrefresh?: () => void;
|
|
59
|
+
}
|
|
60
|
+
declare const ResourceStudioTemplate: import("svelte").Component<ResourceStudioTemplateProps, {}, "query" | "page" | "notes" | "selection" | "formatRules" | "activeResourceId" | "activeMode" | "activeViewId">;
|
|
61
|
+
type ResourceStudioTemplate = ReturnType<typeof ResourceStudioTemplate>;
|
|
62
|
+
export default ResourceStudioTemplate;
|