@cocoar/vue-page-builder 2.19.0 → 2.20.0-beta.19
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/IDP_INTEGRATION.md +355 -0
- package/README.md +352 -12
- package/dist/BuilderElementCodeDialog-ByhAkwmS.js +64 -0
- package/dist/BuilderExpressionDialog-DjGebYyv.js +61 -0
- package/dist/BuilderLogicPanel-Cxd04A93.js +68 -0
- package/dist/BuilderPageRootCodeDialog-7uXyUGGD.js +61 -0
- package/dist/CoarPageBuilder.vue.d.ts +60 -1
- package/dist/CoarPageBuilder.vue.d.ts.map +1 -1
- package/dist/CoarPageRenderer.vue.d.ts +38 -1
- package/dist/CoarPageRenderer.vue.d.ts.map +1 -1
- package/dist/PageNode.vue.d.ts +9 -1
- package/dist/PageNode.vue.d.ts.map +1 -1
- package/dist/VisualMarkupInspector-DGjFuyMS.js +54 -0
- package/dist/_plugin-vue_export-helper-BTgDAbhb.js +8 -0
- package/dist/actionValues.d.ts +21 -0
- package/dist/actionValues.d.ts.map +1 -0
- package/dist/assets/pageScriptRuntime.worker-Cll8Lm_I.js +25 -0
- package/dist/builder/BuilderCanvas.vue.d.ts.map +1 -1
- package/dist/builder/BuilderCanvasNode.vue.d.ts.map +1 -1
- package/dist/builder/BuilderCompositionsPanel.vue.d.ts +3 -0
- package/dist/builder/BuilderCompositionsPanel.vue.d.ts.map +1 -0
- package/dist/builder/BuilderElementCodeDialog.vue.d.ts +14 -0
- package/dist/builder/BuilderElementCodeDialog.vue.d.ts.map +1 -0
- package/dist/builder/BuilderExpressionDialog.vue.d.ts +11 -0
- package/dist/builder/BuilderExpressionDialog.vue.d.ts.map +1 -0
- package/dist/builder/BuilderFxButton.vue.d.ts +28 -0
- package/dist/builder/BuilderFxButton.vue.d.ts.map +1 -0
- package/dist/builder/BuilderLogicPanel.vue.d.ts +3 -0
- package/dist/builder/BuilderLogicPanel.vue.d.ts.map +1 -0
- package/dist/builder/BuilderOutlineNode.vue.d.ts.map +1 -1
- package/dist/builder/BuilderPageRootCodeDialog.vue.d.ts +13 -0
- package/dist/builder/BuilderPageRootCodeDialog.vue.d.ts.map +1 -0
- package/dist/builder/BuilderPalette.vue.d.ts +3 -0
- package/dist/builder/BuilderPalette.vue.d.ts.map +1 -0
- package/dist/builder/BuilderPropsPanel.vue.d.ts.map +1 -1
- package/dist/builder/BuilderTranslationsPanel.vue.d.ts +6 -0
- package/dist/builder/BuilderTranslationsPanel.vue.d.ts.map +1 -0
- package/dist/builder/builderContext.d.ts +44 -2
- package/dist/builder/builderContext.d.ts.map +1 -1
- package/dist/builder/expressionAuthoring.d.ts +7 -0
- package/dist/builder/expressionAuthoring.d.ts.map +1 -0
- package/dist/builder/nodeDefaults.d.ts +10 -5
- package/dist/builder/nodeDefaults.d.ts.map +1 -1
- package/dist/builder/pageCodeAuthoring.d.ts +11 -0
- package/dist/builder/pageCodeAuthoring.d.ts.map +1 -0
- package/dist/builder/props/ActionPropsEditor.vue.d.ts +9 -0
- package/dist/builder/props/ActionPropsEditor.vue.d.ts.map +1 -0
- package/dist/builder/props/StyleProps.vue.d.ts +1 -0
- package/dist/builder/props/StyleProps.vue.d.ts.map +1 -1
- package/dist/builder/schemaMigrateV1.d.ts.map +1 -1
- package/dist/builder/schemaNormalize.d.ts.map +1 -1
- package/dist/builder/useBuilderDnd.d.ts +8 -1
- package/dist/builder/useBuilderDnd.d.ts.map +1 -1
- package/dist/builder/usePageBuilder.d.ts +4 -0
- package/dist/builder/usePageBuilder.d.ts.map +1 -1
- package/dist/builder/usePageCompositions.d.ts +71 -0
- package/dist/builder/usePageCompositions.d.ts.map +1 -0
- package/dist/builder/useSchemaValidation.d.ts.map +1 -1
- package/dist/builderContext-5hKJ8y8r.js +4 -0
- package/dist/compositions.d.ts +79 -0
- package/dist/compositions.d.ts.map +1 -0
- package/dist/conditions.d.ts +9 -0
- package/dist/conditions.d.ts.map +1 -0
- package/dist/context.d.ts +17 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/documentValidation.d.ts +12 -0
- package/dist/documentValidation.d.ts.map +1 -0
- package/dist/elements/builtins.d.ts.map +1 -1
- package/dist/elements/button/ButtonInspector.vue.d.ts.map +1 -1
- package/dist/elements/button/ButtonRenderer.vue.d.ts.map +1 -1
- package/dist/elements/button/index.d.ts +2 -2
- package/dist/elements/button/index.d.ts.map +1 -1
- package/dist/elements/card/CardInspector.vue.d.ts.map +1 -1
- package/dist/elements/card/index.d.ts.map +1 -1
- package/dist/elements/checkbox/CheckboxDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/checkbox/CheckboxInspector.vue.d.ts.map +1 -1
- package/dist/elements/checkbox/CheckboxRenderer.vue.d.ts.map +1 -1
- package/dist/elements/checkbox/index.d.ts.map +1 -1
- package/dist/elements/date-input/DateInputDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/date-input/DateInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/date-input/index.d.ts.map +1 -1
- package/dist/elements/datetime-input/DateTimeInputDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/datetime-input/DateTimeInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/datetime-input/index.d.ts.map +1 -1
- package/dist/elements/feedback/FeedbackInspector.vue.d.ts +8 -0
- package/dist/elements/feedback/FeedbackInspector.vue.d.ts.map +1 -0
- package/dist/elements/feedback/FeedbackPreview.vue.d.ts +7 -0
- package/dist/elements/feedback/FeedbackPreview.vue.d.ts.map +1 -0
- package/dist/elements/{stack/StackInspector.vue.d.ts → feedback/FeedbackRenderer.vue.d.ts} +3 -4
- package/dist/elements/feedback/FeedbackRenderer.vue.d.ts.map +1 -0
- package/dist/elements/feedback/index.d.ts +6 -0
- package/dist/elements/feedback/index.d.ts.map +1 -0
- package/dist/elements/heading/HeadingInspector.vue.d.ts.map +1 -1
- package/dist/elements/heading/index.d.ts.map +1 -1
- package/dist/elements/image/ImageInspector.vue.d.ts.map +1 -1
- package/dist/elements/link/LinkInspector.vue.d.ts +1 -1
- package/dist/elements/link/LinkInspector.vue.d.ts.map +1 -1
- package/dist/elements/link/index.d.ts +1 -2
- package/dist/elements/link/index.d.ts.map +1 -1
- package/dist/elements/multi-select/MultiSelectDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/multi-select/MultiSelectInspector.vue.d.ts.map +1 -1
- package/dist/elements/multi-select/index.d.ts.map +1 -1
- package/dist/elements/note/NoteInspector.vue.d.ts.map +1 -1
- package/dist/elements/number-input/NumberInputDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/number-input/NumberInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/number-input/index.d.ts.map +1 -1
- package/dist/elements/otp-input/OtpInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/otp-input/index.d.ts.map +1 -1
- package/dist/elements/paragraph/index.d.ts.map +1 -1
- package/dist/elements/password-input/PasswordInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/password-input/index.d.ts.map +1 -1
- package/dist/elements/radio-group/RadioGroupDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/radio-group/RadioGroupInspector.vue.d.ts.map +1 -1
- package/dist/elements/radio-group/index.d.ts.map +1 -1
- package/dist/elements/registry.d.ts +109 -0
- package/dist/elements/registry.d.ts.map +1 -1
- package/dist/elements/repeat/RepeatInspector.vue.d.ts +8 -0
- package/dist/elements/repeat/RepeatInspector.vue.d.ts.map +1 -0
- package/dist/elements/repeat/RepeatRenderer.vue.d.ts +29 -0
- package/dist/elements/repeat/RepeatRenderer.vue.d.ts.map +1 -0
- package/dist/elements/repeat/index.d.ts +10 -0
- package/dist/elements/repeat/index.d.ts.map +1 -0
- package/dist/elements/section/SectionInspector.vue.d.ts.map +1 -1
- package/dist/elements/select/SelectDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/select/SelectInspector.vue.d.ts.map +1 -1
- package/dist/elements/select/index.d.ts.map +1 -1
- package/dist/elements/spacer/SpacerInspector.vue.d.ts.map +1 -1
- package/dist/elements/stack/StackRenderer.vue.d.ts.map +1 -1
- package/dist/elements/stack/index.d.ts.map +1 -1
- package/dist/elements/switch/SwitchDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/switch/SwitchInspector.vue.d.ts.map +1 -1
- package/dist/elements/switch/index.d.ts.map +1 -1
- package/dist/elements/text-input/TextInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/text-input/index.d.ts.map +1 -1
- package/dist/elements/usePageElement.d.ts +6 -2
- package/dist/elements/usePageElement.d.ts.map +1 -1
- package/dist/elements/visual-markup/VisualMarkupInspector.vue.d.ts +10 -0
- package/dist/elements/visual-markup/VisualMarkupInspector.vue.d.ts.map +1 -0
- package/dist/elements/visual-markup/VisualMarkupPreview.vue.d.ts +7 -0
- package/dist/elements/visual-markup/VisualMarkupPreview.vue.d.ts.map +1 -0
- package/dist/elements/visual-markup/VisualMarkupRenderer.vue.d.ts +7 -0
- package/dist/elements/visual-markup/VisualMarkupRenderer.vue.d.ts.map +1 -0
- package/dist/elements/visual-markup/index.d.ts +6 -0
- package/dist/elements/visual-markup/index.d.ts.map +1 -0
- package/dist/elements/visual-markup/visualDocument.d.ts +13 -0
- package/dist/elements/visual-markup/visualDocument.d.ts.map +1 -0
- package/dist/expressionAuthoring-DHVx3i-G.js +74 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +22 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9306 -3676
- package/dist/pageCode-hhTSp3xO.js +447 -0
- package/dist/pageCode.d.ts +93 -0
- package/dist/pageCode.d.ts.map +1 -0
- package/dist/pageCodeAuthoring-Fg3yqXt3.js +126 -0
- package/dist/presets/authCustomization.d.ts +33 -0
- package/dist/presets/authCustomization.d.ts.map +1 -0
- package/dist/responsive.d.ts +7 -0
- package/dist/responsive.d.ts.map +1 -0
- package/dist/runtime/PageRuntimeHost.d.ts +57 -0
- package/dist/runtime/PageRuntimeHost.d.ts.map +1 -0
- package/dist/runtime/PageScriptRuntime.d.ts +62 -0
- package/dist/runtime/PageScriptRuntime.d.ts.map +1 -0
- package/dist/runtime/pageScriptRuntime.worker.d.ts +1 -0
- package/dist/runtime/pageScriptRuntime.worker.d.ts.map +1 -0
- package/dist/runtime/runtimeProtocol.d.ts +150 -0
- package/dist/runtime/runtimeProtocol.d.ts.map +1 -0
- package/dist/runtime/usePageCodeRuntime.d.ts +33 -0
- package/dist/runtime/usePageCodeRuntime.d.ts.map +1 -0
- package/dist/runtime-worker.js +240 -0
- package/dist/runtimeBindings.d.ts +33 -0
- package/dist/runtimeBindings.d.ts.map +1 -0
- package/dist/runtimeExpressions.d.ts +16 -0
- package/dist/runtimeExpressions.d.ts.map +1 -0
- package/dist/runtimeProtocol-Bg1C-O0c.js +36 -0
- package/dist/runtimeWorkerEntry.d.ts +2 -0
- package/dist/runtimeWorkerEntry.d.ts.map +1 -0
- package/dist/schema.d.ts +301 -25
- package/dist/schema.d.ts.map +1 -1
- package/dist/styleMapping.d.ts +4 -0
- package/dist/styleMapping.d.ts.map +1 -1
- package/dist/stylePresets.d.ts +4 -0
- package/dist/stylePresets.d.ts.map +1 -0
- package/dist/translations.d.ts +8 -0
- package/dist/translations.d.ts.map +1 -0
- package/dist/visualDocument-DPb3svLG.js +139 -0
- package/package.json +24 -6
- package/dist/elements/stack/StackInspector.vue.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -15,16 +15,23 @@ JSON.
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
pnpm add @cocoar/vue-page-builder @cocoar/vue-ui
|
|
18
|
+
pnpm add @cocoar/vue-page-builder @cocoar/vue-ui \
|
|
19
|
+
@cocoar/vue-localization @cocoar/vue-script-editor monaco-editor
|
|
19
20
|
```
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
The UI, localization, ScriptEditor, Monaco and Vue packages are peers so the
|
|
23
|
+
host owns their single application-wide instances. Import the stylesheet once —
|
|
22
24
|
it carries the builder chrome **and** the renderer's layout styles:
|
|
23
25
|
|
|
24
26
|
```ts
|
|
25
27
|
import '@cocoar/vue-page-builder/styles';
|
|
26
28
|
```
|
|
27
29
|
|
|
30
|
+
The Builder uses Monaco in JavaScript and JSON mode. Register the TypeScript /
|
|
31
|
+
JavaScript and JSON workers before the first Builder mounts; the complete Vite
|
|
32
|
+
and SSR configurations are documented in
|
|
33
|
+
[IDP_INTEGRATION.md](./IDP_INTEGRATION.md#register-all-monaco-workers-used-by-the-builder).
|
|
34
|
+
|
|
28
35
|
## Usage
|
|
29
36
|
|
|
30
37
|
```vue
|
|
@@ -58,19 +65,22 @@ const config: PageConfig = {
|
|
|
58
65
|
</template>
|
|
59
66
|
```
|
|
60
67
|
|
|
61
|
-
## Schema (
|
|
68
|
+
## Schema (v5)
|
|
62
69
|
|
|
63
70
|
The persisted document is a tree of one uniform node grammar: `type` is an
|
|
64
71
|
open registry key (built-in or consumer), everything element-specific lives in
|
|
65
72
|
the `props` bag, and the host vocabulary — `id`, `style`, the value-model trio
|
|
66
73
|
`name` / `defaultValue` / `validation`, and `children` for containers — stays
|
|
67
|
-
at node level. The `page` root carries `schemaVersion:
|
|
74
|
+
at node level. The `page` root carries `schemaVersion: 5`. Version 4 gives every
|
|
75
|
+
element a stable, page-wide `name`; value elements use that same name as their
|
|
76
|
+
form/DTO property and Element Code uses it as its authoring identity. Version 5
|
|
77
|
+
adds builder-only origin metadata for reusable, versioned compositions.
|
|
68
78
|
|
|
69
79
|
```jsonc
|
|
70
80
|
{
|
|
71
81
|
"id": "3f6c…",
|
|
72
82
|
"type": "page",
|
|
73
|
-
"schemaVersion":
|
|
83
|
+
"schemaVersion": 5,
|
|
74
84
|
"style": { "gap": "16px", "padding": "24px" },
|
|
75
85
|
"children": [
|
|
76
86
|
{ "id": "a1b2…", "type": "heading", "props": { "text": "Sign in", "level": 2 } },
|
|
@@ -91,10 +101,204 @@ at node level. The `page` root carries `schemaVersion: 2`.
|
|
|
91
101
|
}
|
|
92
102
|
```
|
|
93
103
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
104
|
+
Older documents are normalized transparently on every ingest path: pre-v2 flat
|
|
105
|
+
props move into the `props` bag, v3 runtime-composition documents keep their
|
|
106
|
+
meaning, and v4 deterministically adds missing element names. Unknown or
|
|
107
|
+
unregistered types stay losslessly in the tree (flagged in the builder, skipped
|
|
108
|
+
with a one-time warning at runtime).
|
|
109
|
+
|
|
110
|
+
## Reusable compositions
|
|
111
|
+
|
|
112
|
+
Any non-page subtree can be stored and reused: a brand panel, header, form
|
|
113
|
+
section, footer, product card or a consumer element. Compositions are generic;
|
|
114
|
+
there are no auth-specific categories or runtime components.
|
|
115
|
+
|
|
116
|
+
The host owns persistence by implementing `PageCompositionRepository`. It may
|
|
117
|
+
use an API, IndexedDB or another store, and every method may be sync or async:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import type { PageCompositionRepository } from '@cocoar/vue-page-builder';
|
|
121
|
+
|
|
122
|
+
const compositionRepository: PageCompositionRepository = {
|
|
123
|
+
list: () => api.get('/page-compositions'),
|
|
124
|
+
get: (id, version) => api.get(`/page-compositions/${id}/${version ?? 'latest'}`),
|
|
125
|
+
create: (input) => api.post('/page-compositions', input),
|
|
126
|
+
publish: (input) => api.post(`/page-compositions/${input.id}/versions`, input),
|
|
127
|
+
};
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Pass it only to the Builder:
|
|
131
|
+
|
|
132
|
+
```vue
|
|
133
|
+
<CoarPageBuilder
|
|
134
|
+
v-model="authoringDocument"
|
|
135
|
+
:config="config"
|
|
136
|
+
:composition-repository="compositionRepository"
|
|
137
|
+
composition-management="consume"
|
|
138
|
+
@open-composition="({ id, version }) => openCompositionEditor(id, version)"
|
|
139
|
+
/>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`composition-management="consume"` is intended for a host with separate
|
|
143
|
+
**Pages** and **Compositions** areas. Page editors can insert an exact pinned
|
|
144
|
+
version, update it or detach it, but cannot create or publish definitions. The
|
|
145
|
+
host edits a definition as a standalone element subtree (usually inside a
|
|
146
|
+
temporary Page root) and calls `create()` / `publish()` itself. The default
|
|
147
|
+
`inline` mode additionally exposes create/publish in the Builder tab and is
|
|
148
|
+
useful for compact tools or bootstrapping a definition from an existing page.
|
|
149
|
+
|
|
150
|
+
Every repository summary is also exposed in the normal element palette under
|
|
151
|
+
**Compositions**. Dragging one to a valid tree/canvas drop zone loads its
|
|
152
|
+
displayed `latestVersion`, materializes the definition and pins that exact
|
|
153
|
+
version. Selecting the linked instance root exposes its name, pinned-version
|
|
154
|
+
selector, update, detach and open controls in Properties. `open-composition`
|
|
155
|
+
is the host navigation seam: the Builder emits the exact pinned `{ id,
|
|
156
|
+
version }`, while the host decides where its independent definition editor
|
|
157
|
+
lives. The existing Compositions tab remains the overview for references,
|
|
158
|
+
updates and repository problems.
|
|
159
|
+
|
|
160
|
+
Instances are fully materialized normal node trees. This gives drafts an
|
|
161
|
+
offline-safe snapshot and lets the Builder preserve page-local node ids and
|
|
162
|
+
public names across updates. Nested compositions keep a small origin chain so
|
|
163
|
+
each linked level can be updated or detached independently. Deleting an instance
|
|
164
|
+
from one page never deletes the repository definition or instances on other pages.
|
|
165
|
+
|
|
166
|
+
Before persisting a runtime document, remove authoring links deterministically:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import { compilePageCompositions } from '@cocoar/vue-page-builder';
|
|
170
|
+
|
|
171
|
+
const runtimeDocument = compilePageCompositions(authoringDocument.value);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The compiled result has no repository ids, versions or source-node metadata and
|
|
175
|
+
requires no composition repository at runtime. Use
|
|
176
|
+
`validatePageCompositionReferences(authoringDocument, repository)` before
|
|
177
|
+
publication to report missing versions and nested cycles. The package also
|
|
178
|
+
exports `createInMemoryPageCompositionRepository()` for tests and local demos.
|
|
179
|
+
|
|
180
|
+
## Action payloads
|
|
181
|
+
|
|
182
|
+
Every action-capable element uses the same optional `ActionProps` contract:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
interface ActionProps {
|
|
186
|
+
action?: string;
|
|
187
|
+
actionValues?: Record<string, unknown>;
|
|
188
|
+
actionValueField?: string;
|
|
189
|
+
actionValue?: unknown;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
`actionValues` contains JSON-safe defaults. Every individual entry can be
|
|
194
|
+
switched to **fx** or bound through `bindings["actionValues.<key>"]` to a host
|
|
195
|
+
context value, customer Page State, form field, named Repeat selection, current
|
|
196
|
+
Repeat item/index, or a sandbox expression. `actionValue` /
|
|
197
|
+
`actionValueField` remain as the backwards-compatible single-dynamic-value
|
|
198
|
+
shape. The handler receives one snapshot with deterministic precedence:
|
|
199
|
+
**form values < resolved `actionValues` < dynamic `actionValue`**. Explicit
|
|
200
|
+
action arguments therefore win key collisions with form fields.
|
|
201
|
+
|
|
202
|
+
```jsonc
|
|
203
|
+
{
|
|
204
|
+
"props": {
|
|
205
|
+
"action": "auth:consent-allow",
|
|
206
|
+
"actionValues": { "approvedScopes": [] }
|
|
207
|
+
},
|
|
208
|
+
"bindings": {
|
|
209
|
+
"actionValues.approvedScopes": {
|
|
210
|
+
"source": "selection",
|
|
211
|
+
"path": "approvedScopes"
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The builder supplies this editor automatically to built-in buttons/links and
|
|
218
|
+
to consumer elements registered with `action: true`. A custom action renderer
|
|
219
|
+
should call `usePageElement().triggerElementAction(node.props)` so it follows
|
|
220
|
+
the identical merge, validation and async-action path.
|
|
221
|
+
|
|
222
|
+
## Host themes and style presets
|
|
223
|
+
|
|
224
|
+
Runtime applications wrap the renderer in the generic `CoarThemeScope` from
|
|
225
|
+
`@cocoar/vue-ui`. For authoring, pass the same theme as `previewTheme`; it is
|
|
226
|
+
applied only to the preview canvas, never to the builder chrome.
|
|
227
|
+
|
|
228
|
+
Host CSS can be exposed as controlled presets through `PageConfig`:
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
const config: PageConfig = {
|
|
232
|
+
stylePresets: [{
|
|
233
|
+
id: 'brand-auth-visual',
|
|
234
|
+
label: 'Brand Auth Visual',
|
|
235
|
+
className: 'brand-auth-visual',
|
|
236
|
+
allowedOn: ['page', 'stack', 'card'],
|
|
237
|
+
}],
|
|
238
|
+
};
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
The page document stores only `stylePreset: 'brand-auth-visual'`; it never
|
|
242
|
+
stores raw CSS or an arbitrary class. The host must load the matching CSS in
|
|
243
|
+
both administration and runtime. Unknown, unsafe, or disallowed presets are an
|
|
244
|
+
authoring error and are safely ignored by the renderer.
|
|
245
|
+
|
|
246
|
+
## Decorative visual markup
|
|
247
|
+
|
|
248
|
+
The built-in `visual-markup` element is the deliberately narrow escape hatch
|
|
249
|
+
for branded, animated decoration that cannot reasonably be expressed through
|
|
250
|
+
individual PageBuilder primitives. It renders HTML, inline SVG and local CSS in
|
|
251
|
+
an opaque-origin iframe. It is **not** a general custom-code element:
|
|
252
|
+
|
|
253
|
+
- the iframe has an empty `sandbox`, `aria-hidden="true"`, `tabindex="-1"` and
|
|
254
|
+
`pointer-events: none`;
|
|
255
|
+
- JavaScript, forms, links, navigation, network access, parent-DOM access and
|
|
256
|
+
interactive controls are rejected or blocked by CSP;
|
|
257
|
+
- markup and CSS use strict allowlists and hard size limits;
|
|
258
|
+
- invalid visuals are hidden locally; siblings and the page form keep working;
|
|
259
|
+
- Builder Preview and Runtime use the same renderer and security policy.
|
|
260
|
+
|
|
261
|
+
Functional content must remain native PageBuilder elements. A visual node can
|
|
262
|
+
use local `@keyframes`, transforms, media queries, `prefers-reduced-motion`, CSS
|
|
263
|
+
custom properties and inline SVG. Its outer PageBuilder `style` controls its
|
|
264
|
+
size, including responsive `width`, `height`, `minHeight`, `maxHeight`,
|
|
265
|
+
`aspectRatio` and `size`.
|
|
266
|
+
|
|
267
|
+
Select the node to edit its HTML and CSS source with the dedicated Monaco
|
|
268
|
+
inspectors. These source editors remain available in code-driven authoring
|
|
269
|
+
mode; ordinary computed properties still use Element Code and Quick
|
|
270
|
+
Properties. Invalid source is reported on the node and in the inspector.
|
|
271
|
+
|
|
272
|
+
The host may inject only explicitly approved theme values and font files:
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import type { PageConfig } from '@cocoar/vue-page-builder';
|
|
276
|
+
|
|
277
|
+
const config: PageConfig = {
|
|
278
|
+
allowedElements: ['page', 'row', 'column', 'visual-markup', 'text-input', 'button'],
|
|
279
|
+
visualMarkup: {
|
|
280
|
+
themeVariables: {
|
|
281
|
+
'--coar-accent': '#10b981',
|
|
282
|
+
'--visual-surface': '#ffffff',
|
|
283
|
+
'--visual-text': '#16202e',
|
|
284
|
+
},
|
|
285
|
+
fonts: [{
|
|
286
|
+
id: 'brand-variable',
|
|
287
|
+
family: 'Brand Sans Variable',
|
|
288
|
+
source: approvedFontDataUrl, // data:font/...;base64 or a host-created blob URL
|
|
289
|
+
format: 'woff2',
|
|
290
|
+
weight: '100 900',
|
|
291
|
+
style: 'normal',
|
|
292
|
+
display: 'swap',
|
|
293
|
+
}],
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Font storage, tenant authorization and URL creation remain host
|
|
299
|
+
responsibilities. For deterministic opaque-iframe loading, a `data:font/...`
|
|
300
|
+
URL is the simplest option. Do not place secrets in theme values, fonts, markup
|
|
301
|
+
or CSS: they become part of the generated `srcdoc`.
|
|
98
302
|
|
|
99
303
|
## Custom elements
|
|
100
304
|
|
|
@@ -130,9 +334,14 @@ const config: PageConfig = {
|
|
|
130
334
|
|
|
131
335
|
## Field contract
|
|
132
336
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
337
|
+
Every element has one page-wide unique `name`, which is its exact Page-Code
|
|
338
|
+
key (`elements.pageTitle`). For value elements, the same name is also the form
|
|
339
|
+
and DTO property (`elements.username` and `fields.username`); there is no
|
|
340
|
+
second field-name or identifier property.
|
|
341
|
+
|
|
342
|
+
Pages are usually projections of a DTO — the value-element names and types are
|
|
343
|
+
known up front. Declare them as `config.fields` and authors *pick* fields instead
|
|
344
|
+
of inventing names: the props panel's Name becomes a select filtered to the
|
|
136
345
|
value types each element can edit (`ElementValueSpec.types`; the rating above
|
|
137
346
|
declares `types: ['number']` and shows up for number fields), the palette
|
|
138
347
|
gains a draggable **Fields** group that drops pre-bound default elements, an
|
|
@@ -154,6 +363,137 @@ const config: PageConfig = {
|
|
|
154
363
|
};
|
|
155
364
|
```
|
|
156
365
|
|
|
366
|
+
## Page-owned translations
|
|
367
|
+
|
|
368
|
+
Human-readable element properties use stable translation keys instead of
|
|
369
|
+
embedding one object per language into every node. The root owns the editable
|
|
370
|
+
catalogue and Element Code keeps only a data-safe reference:
|
|
371
|
+
|
|
372
|
+
```jsonc
|
|
373
|
+
{
|
|
374
|
+
"type": "page",
|
|
375
|
+
"translations": {
|
|
376
|
+
"de": { "page.submit.label": "Anmelden" },
|
|
377
|
+
"en": { "page.submit.label": "Sign in" }
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
```js
|
|
383
|
+
element.props.label = i18n.text('page.submit.label', undefined, 'Sign in');
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
The Builder's **Translations** tab edits the catalogue, reports missing/unused
|
|
387
|
+
keys and shares its language with the preview. Localizability is explicit
|
|
388
|
+
element metadata (`valueKind: 'localized-text'`), so layout strings such as
|
|
389
|
+
`style.width` never accidentally get translation UI. Monaco completes the
|
|
390
|
+
keys present in the page document. At runtime page messages win, then the
|
|
391
|
+
host's `@cocoar/vue-localization` store is consulted, followed by the binding
|
|
392
|
+
fallback and finally the key itself. The legacy `LocalizedValue` shape remains
|
|
393
|
+
readable for existing documents, but new authoring uses translation bindings.
|
|
394
|
+
|
|
395
|
+
## JavaScript property bindings
|
|
396
|
+
|
|
397
|
+
Bindable properties can retain a static fallback and opt into a pure
|
|
398
|
+
JavaScript expression. In the right-hand Properties panel, a compact `fx`
|
|
399
|
+
control in the property's label row switches modes without opening an editor
|
|
400
|
+
(struck through = static, accent colour = expression). Its explicit Edit action
|
|
401
|
+
opens the shared lazy Monaco dialog. Disabled expressions remain persisted with
|
|
402
|
+
`enabled: false`, so switching modes never loses authored code. The optional
|
|
403
|
+
Logic overview opens that same dialog and edits the same record:
|
|
404
|
+
|
|
405
|
+
```ts
|
|
406
|
+
const submit = {
|
|
407
|
+
id: 'submit',
|
|
408
|
+
type: 'button',
|
|
409
|
+
props: { label: 'Sign in', disabled: false },
|
|
410
|
+
bindings: {
|
|
411
|
+
disabled: {
|
|
412
|
+
source: 'expression',
|
|
413
|
+
expression: '!fields.username?.trim() || !fields.password',
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
The builder never evaluates this source. A host-owned sandbox session extracts
|
|
420
|
+
definitions with `collectPageRuntimeExpressions()`, evaluates them, and passes
|
|
421
|
+
the data-only result map to `CoarPageRenderer.expressionValues` (or
|
|
422
|
+
`CoarPageBuilder.previewExpressionValues`). Static props remain active during
|
|
423
|
+
startup and after runtime failures. Monaco is lazy-loaded in JavaScript mode;
|
|
424
|
+
host field/context contracts provide its IntelliSense declarations.
|
|
425
|
+
|
|
426
|
+
## Browser Page Runtime
|
|
427
|
+
|
|
428
|
+
The package contains the SES Worker runtime used by Page State, constrained Page
|
|
429
|
+
Root Code and per-element code.
|
|
430
|
+
Create the host once in the consumer application. It is a capability catalogue,
|
|
431
|
+
not shared page state; every `usePageCodeRuntime()` call owns an isolated Worker
|
|
432
|
+
session and disposes it with the Vue component.
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
import {
|
|
436
|
+
definePageRuntimeHost,
|
|
437
|
+
withRuntimeEndowmentContext,
|
|
438
|
+
} from '@cocoar/vue-page-builder';
|
|
439
|
+
|
|
440
|
+
export const pageRuntimeHost = definePageRuntimeHost({
|
|
441
|
+
endowments: {
|
|
442
|
+
api: {
|
|
443
|
+
loadOptions: withRuntimeEndowmentContext(
|
|
444
|
+
({ signal, tenantId }, source: unknown) =>
|
|
445
|
+
applicationApi.loadOptions(String(source), { tenantId, signal }),
|
|
446
|
+
),
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
grants: ({ pageId, definition }) =>
|
|
450
|
+
pageId.startsWith('auth:') && definition.id.startsWith('element-action:')
|
|
451
|
+
? ['api']
|
|
452
|
+
: [],
|
|
453
|
+
});
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
```ts
|
|
457
|
+
const runtime = usePageCodeRuntime({
|
|
458
|
+
pageId,
|
|
459
|
+
tenantId,
|
|
460
|
+
schema,
|
|
461
|
+
context,
|
|
462
|
+
viewport,
|
|
463
|
+
runtimeHost: pageRuntimeHost,
|
|
464
|
+
});
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Pass `runtime.pageCodeValues` and `runtime.onRuntimeChange` to the renderer and
|
|
468
|
+
route unknown action ids through `runtime.runPageAction`. If no host is passed,
|
|
469
|
+
the package uses a no-capability host: there is no ambient `fetch`, `window`, DOM
|
|
470
|
+
or application API inside tenant code.
|
|
471
|
+
|
|
472
|
+
The consuming Vite build emits the SES runtime as a same-origin
|
|
473
|
+
`pageScriptRuntime.worker-<hash>.js` module asset. Keep the document CSP free of
|
|
474
|
+
`unsafe-eval`; see `IDP_INTEGRATION.md` for the Worker-response CSP requirement.
|
|
475
|
+
For Vite development, exclude only the dedicated runtime entry from dependency
|
|
476
|
+
pre-bundling:
|
|
477
|
+
|
|
478
|
+
```ts
|
|
479
|
+
optimizeDeps: { exclude: ['@cocoar/vue-page-builder/runtime-worker'] }
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
`CoarPageBuilder` owns its embedded preview runtime. A selected fixture now
|
|
483
|
+
provides context, view state, locale and viewport as one effective preview
|
|
484
|
+
contract; the Builder evaluates Page State, Page Root Code and Element Code in
|
|
485
|
+
that same isolated session. Pass `previewRuntimeHost` only when preview actions
|
|
486
|
+
need the application's explicitly granted capabilities.
|
|
487
|
+
|
|
488
|
+
The package also exports four optional integration presets:
|
|
489
|
+
`createAuthPageDocument()` and `createAuthPageConfig()` for `login`,
|
|
490
|
+
`password-forgot`, `logout` and `consent`. They are example/default documents;
|
|
491
|
+
all underlying elements, repeaters, feedback zones and runtime APIs remain
|
|
492
|
+
generic.
|
|
493
|
+
|
|
494
|
+
See [IDP_INTEGRATION.md](./IDP_INTEGRATION.md) for the complete draft/publish,
|
|
495
|
+
host-action and security contract.
|
|
496
|
+
|
|
157
497
|
## Documentation
|
|
158
498
|
|
|
159
499
|
Full docs — schema reference, `PageConfig` contract, element registry guide,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { t as e } from "./_plugin-vue_export-helper-BTgDAbhb.js";
|
|
2
|
+
import { c as t, o as n } from "./pageCode-hhTSp3xO.js";
|
|
3
|
+
import { n as r, t as i } from "./pageCodeAuthoring-Fg3yqXt3.js";
|
|
4
|
+
import { computed as a, createElementBlock as o, createElementVNode as s, createTextVNode as c, createVNode as l, defineComponent as u, openBlock as d, ref as f, toDisplayString as p, unref as m, withCtx as h } from "vue";
|
|
5
|
+
import { CoarButton as g } from "@cocoar/vue-ui";
|
|
6
|
+
import { CoarScriptEditor as _ } from "@cocoar/vue-script-editor";
|
|
7
|
+
//#region src/builder/BuilderElementCodeDialog.vue?vue&type=script&setup=true&lang.ts
|
|
8
|
+
var v = { class: "pb-element-code-dialog" }, y = { class: "pb-element-code-dialog__meta" }, b = { class: "pb-element-code-dialog__editor" }, x = /* @__PURE__ */ e(/* @__PURE__ */ u({
|
|
9
|
+
__name: "BuilderElementCodeDialog",
|
|
10
|
+
props: {
|
|
11
|
+
schema: {},
|
|
12
|
+
node: {},
|
|
13
|
+
source: {},
|
|
14
|
+
stateCode: {},
|
|
15
|
+
config: {},
|
|
16
|
+
hostLibs: {},
|
|
17
|
+
close: { type: Function }
|
|
18
|
+
},
|
|
19
|
+
setup(e) {
|
|
20
|
+
let u = e, x = f(n(u.source)), S = a(() => i(t(u.stateCode), u.node)), C = a(() => [...r(u.schema, u.node, u.config), ...u.hostLibs ?? []]);
|
|
21
|
+
return (t, n) => (d(), o("div", v, [
|
|
22
|
+
s("div", y, [s("div", null, [n[3] ||= s("span", null, "Element", -1), s("strong", null, p(e.node.name) + " · " + p(e.node.type), 1)]), n[4] ||= s("div", null, [s("span", null, "Mutable target"), s("code", null, "element")], -1)]),
|
|
23
|
+
s("div", b, [l(m(_), {
|
|
24
|
+
modelValue: x.value,
|
|
25
|
+
"onUpdate:modelValue": n[0] ||= (e) => x.value = e,
|
|
26
|
+
language: "javascript",
|
|
27
|
+
"script-mode": !0,
|
|
28
|
+
preamble: S.value,
|
|
29
|
+
"extra-libs": C.value,
|
|
30
|
+
height: "clamp(360px, 58vh, 620px)",
|
|
31
|
+
placeholder: "defineElement({ compute, actions })"
|
|
32
|
+
}, null, 8, [
|
|
33
|
+
"modelValue",
|
|
34
|
+
"preamble",
|
|
35
|
+
"extra-libs"
|
|
36
|
+
])]),
|
|
37
|
+
n[7] ||= s("p", { class: "pb-element-code-dialog__hint" }, [
|
|
38
|
+
c(" Locked lines belong to the PageBuilder and cannot be renamed or deleted. Edit only the "),
|
|
39
|
+
s("code", null, "compute"),
|
|
40
|
+
c(" and "),
|
|
41
|
+
s("code", null, "click"),
|
|
42
|
+
c(" bodies between them. Configuration and runtime inputs are separated: "),
|
|
43
|
+
s("code", null, "element.*"),
|
|
44
|
+
c(" is only this element, shared inputs live on "),
|
|
45
|
+
s("code", null, "page.*"),
|
|
46
|
+
c(", and the event payload lives on "),
|
|
47
|
+
s("code", null, "action.payload"),
|
|
48
|
+
c(". ")
|
|
49
|
+
], -1),
|
|
50
|
+
s("footer", null, [l(m(g), {
|
|
51
|
+
variant: "secondary",
|
|
52
|
+
onClick: n[1] ||= (t) => e.close()
|
|
53
|
+
}, {
|
|
54
|
+
default: h(() => [...n[5] ||= [c("Cancel", -1)]]),
|
|
55
|
+
_: 1
|
|
56
|
+
}), l(m(g), { onClick: n[2] ||= (t) => e.close(x.value) }, {
|
|
57
|
+
default: h(() => [...n[6] ||= [c("Apply element code", -1)]]),
|
|
58
|
+
_: 1
|
|
59
|
+
})])
|
|
60
|
+
]));
|
|
61
|
+
}
|
|
62
|
+
}), [["__scopeId", "data-v-037d2ed2"]]);
|
|
63
|
+
//#endregion
|
|
64
|
+
export { x as default };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { t as e } from "./_plugin-vue_export-helper-BTgDAbhb.js";
|
|
2
|
+
import { i as t, n, t as r } from "./expressionAuthoring-DHVx3i-G.js";
|
|
3
|
+
import { computed as i, createElementBlock as a, createElementVNode as o, createTextVNode as s, createVNode as c, defineComponent as l, openBlock as u, ref as d, toDisplayString as f, unref as p, withCtx as m } from "vue";
|
|
4
|
+
import { CoarButton as h } from "@cocoar/vue-ui";
|
|
5
|
+
import { CoarScriptEditor as g } from "@cocoar/vue-script-editor";
|
|
6
|
+
//#region src/builder/BuilderExpressionDialog.vue?vue&type=script&setup=true&lang.ts
|
|
7
|
+
var _ = { class: "pb-expression-dialog" }, v = { class: "pb-expression-dialog__meta" }, y = { class: "pb-expression-dialog__editor" }, b = /* @__PURE__ */ e(/* @__PURE__ */ l({
|
|
8
|
+
__name: "BuilderExpressionDialog",
|
|
9
|
+
props: {
|
|
10
|
+
nodeId: {},
|
|
11
|
+
target: {},
|
|
12
|
+
expression: {},
|
|
13
|
+
config: {},
|
|
14
|
+
close: { type: Function }
|
|
15
|
+
},
|
|
16
|
+
setup(e) {
|
|
17
|
+
let l = e, b = d(l.expression), x = i(() => t(l.config)), S = i(() => n(l.target));
|
|
18
|
+
return (t, n) => (u(), a("div", _, [
|
|
19
|
+
o("div", v, [o("div", null, [n[3] ||= o("span", null, "Property", -1), o("strong", null, f(e.nodeId) + " · " + f(e.target), 1)]), o("div", null, [n[4] ||= o("span", null, "Result", -1), o("code", null, f(S.value), 1)])]),
|
|
20
|
+
o("div", y, [c(p(g), {
|
|
21
|
+
modelValue: b.value,
|
|
22
|
+
"onUpdate:modelValue": n[0] ||= (e) => b.value = e,
|
|
23
|
+
language: "javascript",
|
|
24
|
+
"script-mode": !0,
|
|
25
|
+
preamble: p(r),
|
|
26
|
+
"extra-libs": x.value,
|
|
27
|
+
height: "clamp(320px, 52vh, 520px)",
|
|
28
|
+
placeholder: "Enter a JavaScript expression…"
|
|
29
|
+
}, null, 8, [
|
|
30
|
+
"modelValue",
|
|
31
|
+
"preamble",
|
|
32
|
+
"extra-libs"
|
|
33
|
+
])]),
|
|
34
|
+
n[7] ||= o("p", { class: "pb-expression-dialog__hint" }, [
|
|
35
|
+
s(" Available: "),
|
|
36
|
+
o("code", null, "fields"),
|
|
37
|
+
s(", "),
|
|
38
|
+
o("code", null, "form"),
|
|
39
|
+
s(", "),
|
|
40
|
+
o("code", null, "context"),
|
|
41
|
+
s(", "),
|
|
42
|
+
o("code", null, "resources"),
|
|
43
|
+
s(", "),
|
|
44
|
+
o("code", null, "viewport"),
|
|
45
|
+
s(". IntelliSense shows the fields and context allowed by this page's host configuration. ")
|
|
46
|
+
], -1),
|
|
47
|
+
o("footer", null, [c(p(h), {
|
|
48
|
+
variant: "secondary",
|
|
49
|
+
onClick: n[1] ||= (t) => e.close()
|
|
50
|
+
}, {
|
|
51
|
+
default: m(() => [...n[5] ||= [s("Cancel", -1)]]),
|
|
52
|
+
_: 1
|
|
53
|
+
}), c(p(h), { onClick: n[2] ||= (t) => e.close(b.value) }, {
|
|
54
|
+
default: m(() => [...n[6] ||= [s("Apply expression", -1)]]),
|
|
55
|
+
_: 1
|
|
56
|
+
})])
|
|
57
|
+
]));
|
|
58
|
+
}
|
|
59
|
+
}), [["__scopeId", "data-v-463025ca"]]);
|
|
60
|
+
//#endregion
|
|
61
|
+
export { b as default };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { t as e } from "./_plugin-vue_export-helper-BTgDAbhb.js";
|
|
2
|
+
import { a as t, c as n, t as r } from "./builderContext-5hKJ8y8r.js";
|
|
3
|
+
import { c as i } from "./pageCode-hhTSp3xO.js";
|
|
4
|
+
import { a } from "./pageCodeAuthoring-Fg3yqXt3.js";
|
|
5
|
+
import { computed as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createTextVNode as u, createVNode as d, defineComponent as f, inject as p, openBlock as m, ref as h, unref as g, watch as _, withCtx as v } from "vue";
|
|
6
|
+
import { CoarButton as y } from "@cocoar/vue-ui";
|
|
7
|
+
import { CoarScriptEditor as b } from "@cocoar/vue-script-editor";
|
|
8
|
+
//#region src/builder/BuilderLogicPanel.vue?vue&type=script&setup=true&lang.ts
|
|
9
|
+
var x = { class: "pb-page-code" }, S = { class: "pb-page-code__toolbar" }, C = { class: "pb-page-code__actions" }, w = {
|
|
10
|
+
key: 0,
|
|
11
|
+
class: "pb-page-code__dirty"
|
|
12
|
+
}, T = { class: "pb-page-code__editor" }, E = /* @__PURE__ */ e(/* @__PURE__ */ f({
|
|
13
|
+
__name: "BuilderLogicPanel",
|
|
14
|
+
setup(e) {
|
|
15
|
+
let f = p(r), E = p(t), D = p(n), O = o(() => i(f.schema.value.stateCode)), k = h(O.value), A = o(() => k.value !== O.value), j = o(() => [...a(E.value), ...D?.value ?? []]);
|
|
16
|
+
_(O, (e) => {
|
|
17
|
+
A.value || (k.value = e);
|
|
18
|
+
});
|
|
19
|
+
function M() {
|
|
20
|
+
f.patch([], { stateCode: k.value });
|
|
21
|
+
}
|
|
22
|
+
function N() {
|
|
23
|
+
k.value = O.value;
|
|
24
|
+
}
|
|
25
|
+
return (e, t) => (m(), c("section", x, [
|
|
26
|
+
l("header", S, [t[3] ||= l("div", null, [l("strong", null, "Page State"), l("span", null, "Customer-authored shared state for this page and all of its element scripts.")], -1), l("div", C, [
|
|
27
|
+
A.value ? (m(), c("span", w, "Unsaved changes")) : s("", !0),
|
|
28
|
+
d(g(y), {
|
|
29
|
+
size: "s",
|
|
30
|
+
variant: "secondary",
|
|
31
|
+
disabled: !A.value,
|
|
32
|
+
onClick: N
|
|
33
|
+
}, {
|
|
34
|
+
default: v(() => [...t[1] ||= [u("Revert", -1)]]),
|
|
35
|
+
_: 1
|
|
36
|
+
}, 8, ["disabled"]),
|
|
37
|
+
d(g(y), {
|
|
38
|
+
size: "s",
|
|
39
|
+
disabled: !A.value,
|
|
40
|
+
onClick: M
|
|
41
|
+
}, {
|
|
42
|
+
default: v(() => [...t[2] ||= [u("Apply state", -1)]]),
|
|
43
|
+
_: 1
|
|
44
|
+
}, 8, ["disabled"])
|
|
45
|
+
])]),
|
|
46
|
+
l("div", T, [d(g(b), {
|
|
47
|
+
modelValue: k.value,
|
|
48
|
+
"onUpdate:modelValue": t[0] ||= (e) => k.value = e,
|
|
49
|
+
language: "javascript",
|
|
50
|
+
"script-mode": !0,
|
|
51
|
+
"extra-libs": j.value,
|
|
52
|
+
height: "100%",
|
|
53
|
+
placeholder: "definePageState({ ... })"
|
|
54
|
+
}, null, 8, ["modelValue", "extra-libs"])]),
|
|
55
|
+
t[4] ||= l("footer", null, [l("span", null, [
|
|
56
|
+
u("The locked "),
|
|
57
|
+
l("code", null, "definePageState"),
|
|
58
|
+
u(" frame belongs to the Builder; only its object body is editable.")
|
|
59
|
+
]), l("span", null, [
|
|
60
|
+
u("Element actions may mutate "),
|
|
61
|
+
l("code", null, "state"),
|
|
62
|
+
u("; dependent element scripts update reactively.")
|
|
63
|
+
])], -1)
|
|
64
|
+
]));
|
|
65
|
+
}
|
|
66
|
+
}), [["__scopeId", "data-v-d2484ca8"]]);
|
|
67
|
+
//#endregion
|
|
68
|
+
export { E as default };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { t as e } from "./_plugin-vue_export-helper-BTgDAbhb.js";
|
|
2
|
+
import { c as t, s as n } from "./pageCode-hhTSp3xO.js";
|
|
3
|
+
import { i as r, r as i } from "./pageCodeAuthoring-Fg3yqXt3.js";
|
|
4
|
+
import { computed as a, createElementBlock as o, createElementVNode as s, createTextVNode as c, createVNode as l, defineComponent as u, openBlock as d, ref as f, unref as p, withCtx as m } from "vue";
|
|
5
|
+
import { CoarButton as h } from "@cocoar/vue-ui";
|
|
6
|
+
import { CoarScriptEditor as g } from "@cocoar/vue-script-editor";
|
|
7
|
+
//#region src/builder/BuilderPageRootCodeDialog.vue?vue&type=script&setup=true&lang.ts
|
|
8
|
+
var _ = { class: "pb-page-root-code-dialog" }, v = { class: "pb-page-root-code-dialog__editor" }, y = /* @__PURE__ */ e(/* @__PURE__ */ u({
|
|
9
|
+
__name: "BuilderPageRootCodeDialog",
|
|
10
|
+
props: {
|
|
11
|
+
schema: {},
|
|
12
|
+
source: {},
|
|
13
|
+
stateCode: {},
|
|
14
|
+
config: {},
|
|
15
|
+
hostLibs: {},
|
|
16
|
+
close: { type: Function }
|
|
17
|
+
},
|
|
18
|
+
setup(e) {
|
|
19
|
+
let u = e, y = f(n(u.source)), b = a(() => i(t(u.stateCode))), x = a(() => [...r(u.schema, u.config), ...u.hostLibs ?? []]);
|
|
20
|
+
return (t, n) => (d(), o("div", _, [
|
|
21
|
+
n[5] ||= s("div", { class: "pb-page-root-code-dialog__meta" }, [s("div", null, [s("span", null, "Element"), s("strong", null, "Page Root")]), s("div", null, [s("span", null, "Mutable target"), s("code", null, "page")])], -1),
|
|
22
|
+
s("div", v, [l(p(g), {
|
|
23
|
+
modelValue: y.value,
|
|
24
|
+
"onUpdate:modelValue": n[0] ||= (e) => y.value = e,
|
|
25
|
+
language: "javascript",
|
|
26
|
+
"script-mode": !0,
|
|
27
|
+
preamble: b.value,
|
|
28
|
+
"extra-libs": x.value,
|
|
29
|
+
height: "clamp(360px, 58vh, 620px)",
|
|
30
|
+
placeholder: "definePageRoot({ compute })"
|
|
31
|
+
}, null, 8, [
|
|
32
|
+
"modelValue",
|
|
33
|
+
"preamble",
|
|
34
|
+
"extra-libs"
|
|
35
|
+
])]),
|
|
36
|
+
n[6] ||= s("p", { class: "pb-page-root-code-dialog__hint" }, [
|
|
37
|
+
c(" Page Root Code can configure only "),
|
|
38
|
+
s("code", null, "page.style"),
|
|
39
|
+
c(", "),
|
|
40
|
+
s("code", null, "page.responsive"),
|
|
41
|
+
c(", and "),
|
|
42
|
+
s("code", null, "page.enterSubmits"),
|
|
43
|
+
c(". The tree, element types, names, and children remain owned by the visual builder. Reactive inputs are available on "),
|
|
44
|
+
s("code", null, "runtime.*"),
|
|
45
|
+
c(". ")
|
|
46
|
+
], -1),
|
|
47
|
+
s("footer", null, [l(p(h), {
|
|
48
|
+
variant: "secondary",
|
|
49
|
+
onClick: n[1] ||= (t) => e.close()
|
|
50
|
+
}, {
|
|
51
|
+
default: m(() => [...n[3] ||= [c("Cancel", -1)]]),
|
|
52
|
+
_: 1
|
|
53
|
+
}), l(p(h), { onClick: n[2] ||= (t) => e.close(y.value) }, {
|
|
54
|
+
default: m(() => [...n[4] ||= [c("Apply Page Code", -1)]]),
|
|
55
|
+
_: 1
|
|
56
|
+
})])
|
|
57
|
+
]));
|
|
58
|
+
}
|
|
59
|
+
}), [["__scopeId", "data-v-f361c916"]]);
|
|
60
|
+
//#endregion
|
|
61
|
+
export { y as default };
|