@stonecrop/nuxt 0.33.0 → 0.35.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/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stonecrop/nuxt",
3
3
  "configKey": "stonecrop",
4
- "version": "0.33.0",
4
+ "version": "0.35.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "unknown"
@@ -174,5 +174,5 @@ function onRemoveRow(row) {
174
174
  </script>
175
175
 
176
176
  <style scoped>
177
- .actions-panel{padding:.5em 1em}.actions-panel :deep(.atable-row>td){border-top:1px solid var(--sc-row-border-color,#e5e7eb);padding:var(--sc-atable-row-padding,.25rem) .75em;vertical-align:middle}.actions-panel :deep(input[type=text]){border:1px solid var(--sc-gray-20,#d1d5db);border-radius:3px;font-family:inherit;font-size:inherit;padding:.25em .5em;width:100%}.actions-panel :deep(input[type=text]:focus){border-color:var(--sc-blue-40,#3b82f6);outline:none}.cell-readonly{color:var(--sc-gray-60,#4b5563);cursor:default}.badge{border-radius:9999px;display:inline-block;font-size:.75rem;font-weight:500;padding:.125em .5em}.badge-transition{background:#dbeafe;color:#1e40af}.badge-self-transition{background:#fef3c7;color:#92400e}.badge-command{background:#f3e8ff;color:#6b21a8}.badge-trigger{background:#dcfce7;color:#166534}.actions-empty{color:#9ca3af;font-style:italic;padding:1rem 0;text-align:center}.panel-footer{display:flex;gap:.5rem;padding:.75rem 0 .25rem}.add-row{background:var(--sc-blue-40,#3b82f6);border:none;border-radius:.4rem;color:#fff;cursor:pointer;font-size:.8125rem;font-weight:500;padding:.4em .9em}.row-detail{gap:.75rem}.detail-field,.row-detail{display:flex;flex-direction:column}.detail-field{gap:.25rem}.detail-label{color:var(--sc-header-text-color,#374151);font-size:.75rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase}.detail-value{color:var(--sc-gray-60,#4b5563);font-size:.8125rem}.client-handler-editor{display:flex;flex-direction:column;gap:.5rem}.handler-label{color:var(--sc-header-text-color,#374151);font-size:.75rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase}.remove-row{align-self:flex-start;background:none;border:1px solid #fca5a5;border-radius:.3rem;color:#b91c1c;cursor:pointer;font-size:.75rem;padding:.3em .75em}
177
+ .actions-panel{padding:.5em 1em}.actions-panel :deep(.atable-row>td){border-top:1px solid var(--sc-row-border-color);padding:var(--sc-atable-row-padding) .75em;vertical-align:middle}.actions-panel :deep(input[type=text]){border:1px solid var(--sc-gray-20);border-radius:var(--sc-border-radius);font-family:inherit;font-size:inherit;padding:.25em .5em;width:100%}.actions-panel :deep(input[type=text]:focus){border-color:var(--sc-input-active-border-color);outline:none}.cell-readonly{color:var(--sc-gray-60);cursor:default}.badge{border-radius:9999px;display:inline-block;font-size:.75rem;font-weight:500;padding:.125em .5em}.badge-transition{background:var(--sc-badge-brand-bg);color:var(--sc-badge-brand-text)}.badge-command,.badge-self-transition,.badge-trigger{background:var(--sc-badge-neutral-bg);color:var(--sc-badge-neutral-text)}.actions-empty{color:var(--sc-header-text-color);font-style:italic;padding:1rem 0;text-align:center}.panel-footer{display:flex;gap:.5rem;padding:.75rem 0 .25rem}.add-row{background:var(--sc-primary-color);border:none;border-radius:var(--sc-border-radius);color:var(--sc-primary-text-color);cursor:pointer;font-size:.8125rem;font-weight:500;padding:.4em .9em}.row-detail{gap:.75rem}.detail-field,.row-detail{display:flex;flex-direction:column}.detail-field{gap:.25rem}.detail-label{color:var(--sc-header-text-color);font-size:.75rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase}.detail-value{color:var(--sc-gray-60);font-size:.8125rem}.client-handler-editor{display:flex;flex-direction:column;gap:.5rem}.handler-label{color:var(--sc-header-text-color);font-size:.75rem;font-weight:600;letter-spacing:.05em;text-transform:uppercase}.remove-row{align-self:flex-start;background:none;border:1px solid var(--sc-badge-danger-accent);border-radius:var(--sc-border-radius);color:var(--sc-badge-danger-text);cursor:pointer;font-size:.75rem;padding:.3em .75em}
178
178
  </style>
@@ -336,5 +336,5 @@ function bool(v) {
336
336
  </script>
337
337
 
338
338
  <style scoped>
339
- .fields-panel{padding:.5em 1em}.fields-panel :deep(.atable-row>td){border-top:1px solid var(--sc-row-border-color,#e5e7eb);padding:var(--sc-atable-row-padding,.125rem) .75em;vertical-align:middle}.fields-panel :deep(input[type=text]),.fields-panel :deep(select){border:1px solid var(--sc-gray-20,#d1d5db);border-radius:3px;font-family:inherit;font-size:inherit;padding:.25em .5em;width:100%}.fields-panel :deep(input.locked),.fields-panel :deep(select.locked){background:var(--sc-gray-10,#f3f4f6);color:#6b7280;cursor:not-allowed}.fields-panel :deep(input.json-invalid){background:#fef2f2;border-color:#f87171}.center{text-align:center}.badge{border-radius:9999px;display:inline-block;font-size:.75rem;font-weight:500;padding:.125em .5em}.badge-manual{background:#dcfce7;color:#166534}.badge-introspected{background:#e0e7ff;color:#3730a3}.field-detail{display:grid;gap:.75rem 1rem;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));padding:.75rem 1rem}.field-prop{color:var(--sc-header-text-color,#374151);display:flex;flex-direction:column;font-size:.75rem;gap:.25rem}.field-prop-inline{align-items:center;flex-direction:row;gap:.5rem}.field-prop-wide{grid-column:1/-1}.field-detail-actions{align-items:center;display:flex;gap:1rem;justify-content:space-between;padding:0 1rem .75rem}.locked-note{color:#6b7280;font-size:.75rem;font-style:italic}.btn-add{background:none;border:1px dashed var(--sc-gray-20,#d1d5db);border-radius:4px;color:var(--sc-blue-40,#2563eb);cursor:pointer;font-size:.875rem;margin-top:.5rem;padding:.4em 1em}.fields-empty{color:#9ca3af;font-style:italic;padding:1rem 0}
339
+ .fields-panel{padding:.5em 1em}.fields-panel :deep(.atable-row>td){border-top:1px solid var(--sc-row-border-color);padding:var(--sc-atable-row-padding) .75em;vertical-align:middle}.fields-panel :deep(input[type=text]),.fields-panel :deep(select){border:1px solid var(--sc-gray-20);border-radius:var(--sc-border-radius);font-family:inherit;font-size:inherit;padding:.25em .5em;width:100%}.fields-panel :deep(input.locked),.fields-panel :deep(select.locked){background:var(--sc-gray-10);color:var(--sc-header-text-color);cursor:not-allowed}.fields-panel :deep(input.json-invalid){background:var(--sc-badge-danger-bg);border-color:var(--sc-brand-danger)}.center{text-align:center}.badge{border-radius:9999px;display:inline-block;font-size:.75rem;font-weight:500;padding:.125em .5em}.badge-manual{background:var(--sc-badge-brand-bg);color:var(--sc-badge-brand-text)}.badge-introspected{background:var(--sc-badge-neutral-bg);color:var(--sc-badge-neutral-text)}.field-detail{display:grid;gap:.75rem 1rem;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));padding:.75rem 1rem}.field-prop{color:var(--sc-header-text-color);display:flex;flex-direction:column;font-size:.75rem;gap:.25rem}.field-prop-inline{align-items:center;flex-direction:row;gap:.5rem}.field-prop-wide{grid-column:1/-1}.field-detail-actions{align-items:center;display:flex;gap:1rem;justify-content:space-between;padding:0 1rem .75rem}.locked-note{color:var(--sc-header-text-color);font-size:.75rem;font-style:italic}.btn-add{background:none;border:1px dashed var(--sc-gray-20);border-radius:var(--sc-border-radius);color:var(--sc-primary-color);cursor:pointer;font-size:.875rem;margin-top:.5rem;padding:.4em 1em}.fields-empty{color:var(--sc-header-text-color);font-style:italic;padding:1rem 0}
340
340
  </style>
@@ -0,0 +1,11 @@
1
+ import type { RouteAdapter } from '@stonecrop/desktop';
2
+ import { type ComputedRef } from 'vue';
3
+ type DocBuilderRouteAdapterOptions = {
4
+ doctype?: ComputedRef<string | undefined>;
5
+ };
6
+ /**
7
+ * Minimal RouteAdapter for DocBuilder pages hosted inside Desktop.
8
+ * @public
9
+ */
10
+ export declare function useDocBuilderRouteAdapter(options?: DocBuilderRouteAdapterOptions): RouteAdapter;
11
+ export {};
@@ -0,0 +1,21 @@
1
+ import { computed } from "vue";
2
+ import { useRoute, useRouter } from "nuxt/app";
3
+ export function useDocBuilderRouteAdapter(options = {}) {
4
+ const route = useRoute();
5
+ const router = useRouter();
6
+ const doctype = options.doctype ?? computed(() => route.params.doctype);
7
+ return {
8
+ getCurrentDoctype: () => doctype.value ?? "",
9
+ getCurrentRecordId: () => "",
10
+ getCurrentView: () => "doctypes",
11
+ navigate: (target) => {
12
+ if (target.view === "doctypes") {
13
+ void router.push("/");
14
+ } else if (target.view === "records" && target.doctype) {
15
+ void router.push(`/${target.doctype}`);
16
+ } else if (target.view === "record" && target.doctype && target.recordId) {
17
+ void router.push(`/${target.doctype}/${target.recordId}`);
18
+ }
19
+ }
20
+ };
21
+ }
@@ -1,66 +1,65 @@
1
1
  <template>
2
- <div class="docbuilder-page">
3
- <div v-if="loading" style="padding: 2rem; text-align: center">Loading...</div>
4
-
5
- <div v-else>
6
- <!-- Validation Panel -->
7
- <div v-if="validationIssues.length > 0 && !warningsDismissed" class="validation-panel">
8
- <div v-if="errorCount > 0" class="validation-errors">
9
- <strong>⚠️ {{ errorCount }} Error(s) — Cannot Save</strong>
10
- <ul>
11
- <li v-for="(issue, idx) in validationIssues.filter(i => i.severity === 'error')" :key="`err-${idx}`">
12
- <code v-if="issue.fieldname">{{ issue.fieldname }}:</code> {{ issue.message }}
13
- </li>
14
- </ul>
15
- </div>
16
- <div v-if="warningCount > 0" class="validation-warnings">
17
- <strong>⚡ {{ warningCount }} Warning(s)</strong>
18
- <button class="dismiss-button" @click="warningsDismissed = true">Dismiss</button>
2
+ <ClientOnly>
3
+ <Desktop class="docbuilder-desktop" :route-adapter="routeAdapter" :host-actions="docbuilderActions">
4
+ <div v-if="loading" class="docbuilder-loading">Loading...</div>
5
+ <div v-else class="docbuilder-page">
6
+ <div v-if="validationIssues.length > 0 && !warningsDismissed" class="validation-panel">
7
+ <div v-if="errorCount > 0" class="validation-errors">
8
+ <strong>⚠️ {{ errorCount }} Error(s) — Cannot Save</strong>
9
+ <ul>
10
+ <li v-for="(issue, idx) in validationIssues.filter(i => i.severity === 'error')" :key="`err-${idx}`">
11
+ <code v-if="issue.fieldname">{{ issue.fieldname }}:</code> {{ issue.message }}
12
+ </li>
13
+ </ul>
14
+ </div>
15
+ <div v-if="warningCount > 0" class="validation-warnings">
16
+ <strong>⚡ {{ warningCount }} Warning(s)</strong>
17
+ <button class="dismiss-button" @click="warningsDismissed = true">Dismiss</button>
18
+ </div>
19
19
  </div>
20
- </div>
21
20
 
22
- <!-- `schema` is empty on purpose: AFieldset renders an AForm from it only as slot fallback,
23
- and each of these fieldsets fills the slot with its own panel. -->
24
- <AFieldset label="Workflow" :schema="[]" :collapsible="true">
25
- <div class="builder-workflow">
26
- <StateEditor
27
- v-if="workflowConfig && workflowConfig.states && workflowConfig.states.length > 0"
28
- v-model="workflowConfig"
29
- v-model:layout="layout"
30
- node-container-class="node-editor" />
31
- <div v-else class="empty-workflow">
32
- <p class="empty-workflow-hint">No workflow yet. Name the first state to start building the workflow.</p>
33
- <div class="empty-workflow-form">
34
- <input v-model="newStateName" type="text" placeholder="e.g. Draft" @keyup.enter="seedWorkflow" />
35
- <button class="btn-seed" type="button" :disabled="!newStateName.trim()" @click="seedWorkflow">
36
- Add first state
37
- </button>
21
+ <AFieldset label="Workflow" :schema="[]" :collapsible="true">
22
+ <div class="builder-workflow">
23
+ <StateEditor
24
+ v-if="workflowConfig && workflowConfig.states && workflowConfig.states.length > 0"
25
+ v-model="workflowConfig"
26
+ v-model:layout="layout"
27
+ node-container-class="node-editor" />
28
+ <div v-else class="empty-workflow">
29
+ <p class="empty-workflow-hint">No workflow yet. Name the first state to start building the workflow.</p>
30
+ <div class="empty-workflow-form">
31
+ <input v-model="newStateName" type="text" placeholder="e.g. Draft" @keyup.enter="seedWorkflow" />
32
+ <button class="btn-primary" type="button" :disabled="!newStateName.trim()" @click="seedWorkflow">
33
+ Add first state
34
+ </button>
35
+ </div>
38
36
  </div>
39
37
  </div>
40
- </div>
41
- </AFieldset>
38
+ </AFieldset>
42
39
 
43
- <AFieldset label="Actions" :schema="[]" :collapsible="true">
44
- <DocBuilderActionsPanel v-model="workflowConfig" />
45
- </AFieldset>
40
+ <AFieldset label="Actions" :schema="[]" :collapsible="true">
41
+ <DocBuilderActionsPanel v-model="workflowConfig" />
42
+ </AFieldset>
46
43
 
47
- <AFieldset label="Schema" :schema="[]" :collapsible="true">
48
- <DocBuilderFieldsPanel v-model="fields" />
49
- </AFieldset>
44
+ <AFieldset label="Schema" :schema="[]" :collapsible="true">
45
+ <DocBuilderFieldsPanel v-model="fields" />
46
+ </AFieldset>
50
47
 
51
- <div v-if="saveMessage" class="builder-actions">
52
- <span class="save-message" :class="saveMessage.type">{{ saveMessage.text }}</span>
48
+ <div v-if="saveMessage" class="builder-actions">
49
+ <span class="save-message" :class="saveMessage.type">{{ saveMessage.text }}</span>
50
+ </div>
53
51
  </div>
54
-
55
- <ActionSet :elements="docbuilderActions" @action-click="handleAction" />
56
- </div>
57
- </div>
52
+ </Desktop>
53
+ <template #fallback>
54
+ <div class="docbuilder-loading">Loading...</div>
55
+ </template>
56
+ </ClientOnly>
58
57
  </template>
59
58
 
60
59
  <script setup>
61
60
  import { AFieldset } from "@stonecrop/aform";
62
61
  import { StateEditor } from "@stonecrop/node-editor";
63
- import { ActionSet } from "@stonecrop/desktop";
62
+ import { Desktop } from "@stonecrop/desktop";
64
63
  import { WorkflowMeta } from "@stonecrop/schema";
65
64
  import { ref, watch, computed, onMounted } from "vue";
66
65
  import { useRoute, useRouter } from "nuxt/app";
@@ -69,6 +68,7 @@ import DocBuilderFieldsPanel from "../components/DocBuilderFieldsPanel.vue";
69
68
  const route = useRoute();
70
69
  const router = useRouter();
71
70
  const doctypeName = computed(() => route.params.doctype);
71
+ const routeAdapter = useDocBuilderRouteAdapter({ doctype: doctypeName });
72
72
  const loading = ref(true);
73
73
  const saving = ref(false);
74
74
  const warningsDismissed = ref(false);
@@ -128,10 +128,6 @@ async function saveToDisk() {
128
128
  body: {
129
129
  doctype: doctypeName.value,
130
130
  fields: fields.value,
131
- // Merge the author's node arrangement back into the workflow (WorkflowMeta.layout) so it
132
- // persists. The layout ref is kept separate in memory (topology-only workflowConfig) and
133
- // only rejoined here at the I/O boundary; omitted when empty to avoid churn on doctypes
134
- // that were never manually arranged.
135
131
  workflow: workflowConfig.value ? { ...workflowConfig.value, ...Object.keys(layout.value).length > 0 && { layout: layout.value } } : null
136
132
  }
137
133
  });
@@ -151,11 +147,8 @@ const docbuilderActions = computed(() => [
151
147
  },
152
148
  { type: "button", label: "Back", action: () => void router.push("/docbuilder") }
153
149
  ]);
154
- function handleAction(_label, action) {
155
- if (action) void action();
156
- }
157
150
  </script>
158
151
 
159
152
  <style scoped>
160
- .docbuilder-page{background:var(--sc-form-background,#fff);box-sizing:border-box;min-height:100vh;padding:2rem}.builder-workflow{min-height:8rem;padding:.5em 1em}:deep(.node-editor){height:40vh;overflow:hidden;width:100%}.empty-workflow{padding:1rem 0}.empty-workflow-hint{color:#9ca3af;font-style:italic;margin:0 0 .75rem}.empty-workflow-form{align-items:center;display:flex;gap:.5rem}.empty-workflow-form input{border:1px solid var(--sc-gray-20,#d1d5db);border-radius:4px;font-family:inherit;font-size:.875rem;padding:.4em .6em}.btn-seed{background:var(--sc-blue-40,#3b82f6);border:none;border-radius:.4rem;color:#fff;cursor:pointer;font-size:.875rem;font-weight:500;padding:.45em 1em}.btn-seed:disabled{cursor:not-allowed;opacity:.5}.validation-panel{margin-bottom:1rem}.validation-errors{background:#fee2e2;border:1px solid #ef4444;border-radius:6px;color:#991b1b;margin-bottom:.5rem;padding:1rem}.validation-warnings{background:#fef9c3;border:1px solid #eab308;border-radius:6px;color:#713f12;padding:1rem}.dismiss-button{background:none;border:1px solid;border-radius:3px;cursor:pointer;font-size:.75rem;margin-left:1rem;padding:.125em .5em}.builder-actions{align-items:center;display:flex;gap:1rem;padding:1rem}.btn-primary{background:var(--sc-blue-40,#3b82f6);border:none;border-radius:.5rem;color:#fff;cursor:pointer;font-weight:500;padding:.5rem 1.5rem}.btn-primary:disabled{cursor:not-allowed;opacity:.6}.save-message{font-size:.875rem}.save-message.success{color:#065f46}.save-message.error{color:#991b1b}
153
+ .docbuilder-desktop{height:100vh}.docbuilder-loading{color:var(--sc-header-text-color);padding:2rem;text-align:center}.docbuilder-page{box-sizing:border-box;padding:2rem}.builder-workflow{min-height:8rem;padding:.5em 1em}:deep(.node-editor){height:40vh;overflow:hidden;width:100%}.empty-workflow{padding:1rem 0}.empty-workflow-hint{color:var(--sc-header-text-color);font-style:italic;margin:0 0 .75rem}.empty-workflow-form{align-items:center;display:flex;gap:.5rem}.empty-workflow-form input{border:1px solid var(--sc-input-border-color);border-radius:var(--sc-border-radius);font-family:inherit;font-size:.875rem;padding:.4em .6em}.btn-primary{background:var(--sc-primary-color);border:none;border-radius:var(--sc-border-radius);color:var(--sc-primary-text-color);cursor:pointer;font-size:.875rem;font-weight:500;padding:.45em 1em}.btn-primary:disabled{cursor:not-allowed;opacity:.5}.validation-panel{margin-bottom:1rem}.validation-errors{background:var(--sc-badge-danger-bg);border:1px solid var(--sc-badge-danger-accent);border-radius:var(--sc-border-radius);color:var(--sc-badge-danger-text);margin-bottom:.5rem;padding:1rem}.validation-warnings{background:var(--sc-badge-warning-bg);border:1px solid var(--sc-badge-warning-accent);border-radius:var(--sc-border-radius);color:var(--sc-badge-warning-text);padding:1rem}.dismiss-button{background:none;border:1px solid;border-radius:var(--sc-border-radius);cursor:pointer;font-size:.75rem;margin-left:1rem;padding:.125em .5em}.builder-actions{align-items:center;display:flex;gap:1rem;padding:1rem}.save-message{font-size:.875rem}.save-message.success{color:var(--sc-brand-success)}.save-message.error{color:var(--sc-brand-danger)}
161
154
  </style>
@@ -1,38 +1,37 @@
1
1
  <template>
2
- <div class="docbuilder-index">
3
- <div class="docbuilder-index-inner">
4
- <div class="docbuilder-header">
5
- <h1>DocType Builder</h1>
6
- <p class="subtitle">Select a DocType to view and edit its schema</p>
7
- </div>
8
- <div class="docbuilder-create">
9
- <input
10
- v-model="newName"
11
- type="text"
12
- placeholder="New doctype name (e.g. Invoice)"
13
- :disabled="creating"
14
- @keyup.enter="createDoctype" />
15
- <button type="button" class="btn-create" :disabled="creating || !newName.trim()" @click="createDoctype">
16
- {{ creating ? 'Creating\u2026' : '+ New DocType' }}
17
- </button>
18
- </div>
19
- <p v-if="createError" class="create-error">{{ createError }}</p>
20
- <ClientOnly>
2
+ <ClientOnly>
3
+ <Desktop class="docbuilder-desktop" :route-adapter="routeAdapter" :host-actions="indexActions">
4
+ <div class="docbuilder-index-inner">
5
+ <div class="docbuilder-header">
6
+ <h1>DocType Builder</h1>
7
+ <p class="subtitle">Select a DocType to view and edit its schema</p>
8
+ </div>
9
+ <div class="docbuilder-create">
10
+ <input
11
+ v-model="newName"
12
+ type="text"
13
+ placeholder="New doctype name (e.g. Invoice)"
14
+ :disabled="creating"
15
+ @keyup.enter="createDoctype" />
16
+ <button type="button" class="btn-primary" :disabled="creating || !newName.trim()" @click="createDoctype">
17
+ {{ creating ? 'Creating\u2026' : '+ New DocType' }}
18
+ </button>
19
+ </div>
20
+ <p v-if="createError" class="create-error">{{ createError }}</p>
21
21
  <div v-if="loading" class="loading">Loading doctypes...</div>
22
22
  <p v-else-if="!doctypes.length" class="empty">No doctypes yet — create one above.</p>
23
23
  <ATable v-else :columns="columns" :rows="doctypes" :config="config" @row:click="handleRowClick" />
24
- </ClientOnly>
25
- </div>
26
-
27
- <ActionSet :elements="indexActions" @action-click="handleAction" />
28
- </div>
24
+ </div>
25
+ </Desktop>
26
+ </ClientOnly>
29
27
  </template>
30
28
 
31
29
  <script setup>
32
- import { ActionSet } from "@stonecrop/desktop";
30
+ import { Desktop } from "@stonecrop/desktop";
33
31
  import { ref, computed, onMounted } from "vue";
34
32
  import { useRouter } from "nuxt/app";
35
33
  const router = useRouter();
34
+ const routeAdapter = useDocBuilderRouteAdapter();
36
35
  const doctypes = ref([]);
37
36
  const loading = ref(true);
38
37
  async function loadDoctypes() {
@@ -93,11 +92,8 @@ async function createDoctype() {
93
92
  }
94
93
  }
95
94
  const indexActions = computed(() => [{ type: "button", label: "Home", action: () => void router.push("/") }]);
96
- function handleAction(_label, action) {
97
- if (action) void action();
98
- }
99
95
  </script>
100
96
 
101
97
  <style scoped>
102
- .docbuilder-index{background:var(--sc-form-background,#fff);box-sizing:border-box;min-height:100vh}.docbuilder-index-inner{margin:0 auto;max-width:1200px;padding:2rem}.docbuilder-header{padding:2rem 0 3rem;text-align:center}.docbuilder-header h1{font-size:2.5rem;font-weight:700;margin:0 0 1rem}.subtitle{color:#6b7280;font-size:1.125rem;margin:0}.empty,.loading{color:#6b7280;padding:2rem;text-align:center}.docbuilder-create{display:flex;gap:.5rem;margin-bottom:1rem}.docbuilder-create input{border:1px solid var(--sc-gray-20,#d1d5db);border-radius:4px;flex:1;font:inherit;padding:.5em .75em}.btn-create{background:var(--sc-blue-40,#3b82f6);border:none;border-radius:.4rem;color:#fff;cursor:pointer;font-weight:500;padding:.5em 1.25em;white-space:nowrap}.btn-create:disabled{cursor:not-allowed;opacity:.5}.create-error{color:#b91c1c;font-size:.875rem;margin:-.5rem 0 1rem}
98
+ .docbuilder-desktop{height:100vh}.docbuilder-index-inner{margin:0 auto;max-width:1200px;padding:2rem}.docbuilder-header{padding:2rem 0 3rem;text-align:center}.docbuilder-header h1{font-size:2.5rem;font-weight:700;margin:0 0 1rem}.subtitle{font-size:1.125rem;margin:0}.empty,.loading,.subtitle{color:var(--sc-header-text-color)}.empty,.loading{padding:2rem;text-align:center}.docbuilder-create{display:flex;gap:.5rem;margin-bottom:1rem}.docbuilder-create input{border:1px solid var(--sc-input-border-color);border-radius:var(--sc-border-radius);flex:1;font:inherit;padding:.5em .75em}.btn-primary{background:var(--sc-primary-color);border:none;border-radius:var(--sc-border-radius);color:var(--sc-primary-text-color);cursor:pointer;font-weight:500;padding:.5em 1.25em;white-space:nowrap}.btn-primary:disabled{cursor:not-allowed;opacity:.5}.create-error{color:var(--sc-brand-danger);font-size:.875rem;margin:-.5rem 0 1rem}
103
99
  </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/nuxt",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "Nuxt module for Stonecrop",
5
5
  "keywords": [
6
6
  "nuxt",
@@ -60,18 +60,18 @@
60
60
  "pathe": "^2.0.3",
61
61
  "pinia": "^3.0.4",
62
62
  "prompts": "^2.4.2",
63
- "@stonecrop/aform": "0.33.0",
64
- "@stonecrop/casl-middleware": "0.33.0",
65
- "@stonecrop/atable": "0.33.0",
66
- "@stonecrop/code-editor": "0.33.0",
67
- "@stonecrop/desktop": "0.33.0",
68
- "@stonecrop/graphql-client": "0.33.0",
69
- "@stonecrop/graphql-middleware": "0.33.0",
70
- "@stonecrop/node-editor": "0.33.0",
71
- "@stonecrop/schema": "0.33.0",
72
- "@stonecrop/nuxt-grafserv": "0.33.0",
73
- "@stonecrop/stonecrop": "0.33.0",
74
- "@stonecrop/themes": "0.33.0"
63
+ "@stonecrop/aform": "0.35.0",
64
+ "@stonecrop/atable": "0.35.0",
65
+ "@stonecrop/casl-middleware": "0.35.0",
66
+ "@stonecrop/code-editor": "0.35.0",
67
+ "@stonecrop/desktop": "0.35.0",
68
+ "@stonecrop/graphql-client": "0.35.0",
69
+ "@stonecrop/schema": "0.35.0",
70
+ "@stonecrop/node-editor": "0.35.0",
71
+ "@stonecrop/nuxt-grafserv": "0.35.0",
72
+ "@stonecrop/themes": "0.35.0",
73
+ "@stonecrop/stonecrop": "0.35.0",
74
+ "@stonecrop/graphql-middleware": "0.35.0"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@eslint/js": "^10.0.1",
@@ -34,6 +34,7 @@ type StonecropField {
34
34
  validation: JSON
35
35
  cardinality: String
36
36
  source: String
37
+ config: JSON
37
38
  }
38
39
 
39
40
  """