@cocoar/vue-ui 3.1.0 → 3.2.0-beta.11

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.
Files changed (180) hide show
  1. package/bin/cli.mjs +53 -0
  2. package/dist/components/checkbox/CoarCheckbox.vue.d.ts +1 -1
  3. package/dist/components/checkbox/CoarCheckbox.vue.d.ts.map +1 -1
  4. package/dist/components/code-block/CoarCodeBlock.vue.d.ts +1 -1
  5. package/dist/components/code-block/CoarCodeBlock.vue.d.ts.map +1 -1
  6. package/dist/components/data-list/CoarDataList.vue.d.ts +158 -0
  7. package/dist/components/data-list/CoarDataList.vue.d.ts.map +1 -0
  8. package/dist/components/data-list/CoarDataListToolbar.vue.d.ts +30 -0
  9. package/dist/components/data-list/CoarDataListToolbar.vue.d.ts.map +1 -0
  10. package/dist/components/data-list/data-list-builder.d.ts +288 -0
  11. package/dist/components/data-list/data-list-builder.d.ts.map +1 -0
  12. package/dist/components/data-list/index.d.ts +12 -0
  13. package/dist/components/data-list/index.d.ts.map +1 -0
  14. package/dist/components/data-list/internal/compare.d.ts +14 -0
  15. package/dist/components/data-list/internal/compare.d.ts.map +1 -0
  16. package/dist/components/data-list/internal/reorder-core.d.ts +46 -0
  17. package/dist/components/data-list/internal/reorder-core.d.ts.map +1 -0
  18. package/dist/components/data-list/internal/search.d.ts +16 -0
  19. package/dist/components/data-list/internal/search.d.ts.map +1 -0
  20. package/dist/components/data-list/internal/useDataListLines.d.ts +92 -0
  21. package/dist/components/data-list/internal/useDataListLines.d.ts.map +1 -0
  22. package/dist/components/data-list/internal/useDataListReorder.d.ts +68 -0
  23. package/dist/components/data-list/internal/useDataListReorder.d.ts.map +1 -0
  24. package/dist/components/data-list/internal/useSearchHighlight.d.ts +19 -0
  25. package/dist/components/data-list/internal/useSearchHighlight.d.ts.map +1 -0
  26. package/dist/components/data-list/types.d.ts +185 -0
  27. package/dist/components/data-list/types.d.ts.map +1 -0
  28. package/dist/components/data-list/useDataListModel.d.ts +79 -0
  29. package/dist/components/data-list/useDataListModel.d.ts.map +1 -0
  30. package/dist/components/date-time/_shared/maskito-config.d.ts +7 -2
  31. package/dist/components/date-time/_shared/maskito-config.d.ts.map +1 -1
  32. package/dist/components/date-time/_shared/time-helpers.d.ts +11 -4
  33. package/dist/components/date-time/_shared/time-helpers.d.ts.map +1 -1
  34. package/dist/components/date-time/_shared/use-date-picker-base.d.ts +1 -1
  35. package/dist/components/date-time/plain-date-picker/CoarPlainDatePicker.vue.d.ts +1 -1
  36. package/dist/components/date-time/plain-date-picker/CoarPlainDatePicker.vue.d.ts.map +1 -1
  37. package/dist/components/date-time/plain-date-time-picker/CoarPlainDateTimePicker.vue.d.ts +1 -1
  38. package/dist/components/date-time/plain-date-time-picker/CoarPlainDateTimePicker.vue.d.ts.map +1 -1
  39. package/dist/components/date-time/zoned-date-time-picker/CoarZonedDateTimePicker.vue.d.ts +1 -1
  40. package/dist/components/date-time/zoned-date-time-picker/CoarZonedDateTimePicker.vue.d.ts.map +1 -1
  41. package/dist/components/dual-listbox/CoarDualListbox.vue.d.ts +3 -0
  42. package/dist/components/dual-listbox/CoarDualListbox.vue.d.ts.map +1 -1
  43. package/dist/components/form-field/CoarFormField.vue.d.ts +1 -1
  44. package/dist/components/form-field/CoarFormField.vue.d.ts.map +1 -1
  45. package/dist/components/icon/CoarIcon.vue.d.ts +2 -2
  46. package/dist/components/icon/CoarIcon.vue.d.ts.map +1 -1
  47. package/dist/components/listbox/CoarListbox.vue.d.ts +7 -0
  48. package/dist/components/listbox/CoarListbox.vue.d.ts.map +1 -1
  49. package/dist/components/number-input/CoarNumberInput.vue.d.ts +1 -1
  50. package/dist/components/number-input/CoarNumberInput.vue.d.ts.map +1 -1
  51. package/dist/components/otp-input/CoarOtpInput.vue.d.ts +1 -1
  52. package/dist/components/otp-input/CoarOtpInput.vue.d.ts.map +1 -1
  53. package/dist/components/password-input/CoarPasswordInput.vue.d.ts +1 -1
  54. package/dist/components/password-input/CoarPasswordInput.vue.d.ts.map +1 -1
  55. package/dist/components/switch/CoarSwitch.vue.d.ts +1 -1
  56. package/dist/components/switch/CoarSwitch.vue.d.ts.map +1 -1
  57. package/dist/components/text-input/CoarTextInput.vue.d.ts +1 -1
  58. package/dist/components/text-input/CoarTextInput.vue.d.ts.map +1 -1
  59. package/dist/composables/dragRegistry.d.ts +12 -0
  60. package/dist/composables/dragRegistry.d.ts.map +1 -1
  61. package/dist/composables/index.d.ts +2 -2
  62. package/dist/composables/index.d.ts.map +1 -1
  63. package/dist/composables/useDragDrop.d.ts +62 -6
  64. package/dist/composables/useDragDrop.d.ts.map +1 -1
  65. package/dist/composables/useVirtualList.d.ts +21 -1
  66. package/dist/composables/useVirtualList.d.ts.map +1 -1
  67. package/dist/index.css +1 -1
  68. package/dist/index.d.ts +4 -2
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +4508 -2039
  71. package/package.json +9 -3
  72. package/skills/cocoar-vue-ui/SKILL.md +244 -0
  73. package/skills/cocoar-vue-ui/references/components/avatar.md +178 -0
  74. package/skills/cocoar-vue-ui/references/components/badge.md +290 -0
  75. package/skills/cocoar-vue-ui/references/components/breadcrumb.md +238 -0
  76. package/skills/cocoar-vue-ui/references/components/button.md +252 -0
  77. package/skills/cocoar-vue-ui/references/components/calendar/agenda-view.md +372 -0
  78. package/skills/cocoar-vue-ui/references/components/calendar/coar-calendar.md +1647 -0
  79. package/skills/cocoar-vue-ui/references/components/calendar/day-view.md +361 -0
  80. package/skills/cocoar-vue-ui/references/components/calendar/index.md +312 -0
  81. package/skills/cocoar-vue-ui/references/components/calendar/month-view.md +486 -0
  82. package/skills/cocoar-vue-ui/references/components/calendar/performance.md +186 -0
  83. package/skills/cocoar-vue-ui/references/components/calendar/timeline-view.md +301 -0
  84. package/skills/cocoar-vue-ui/references/components/calendar/week-view.md +382 -0
  85. package/skills/cocoar-vue-ui/references/components/calendar/work-week-view.md +145 -0
  86. package/skills/cocoar-vue-ui/references/components/calendar/year-view.md +63 -0
  87. package/skills/cocoar-vue-ui/references/components/card.md +151 -0
  88. package/skills/cocoar-vue-ui/references/components/checkbox-group.md +103 -0
  89. package/skills/cocoar-vue-ui/references/components/checkbox.md +279 -0
  90. package/skills/cocoar-vue-ui/references/components/code-block.md +241 -0
  91. package/skills/cocoar-vue-ui/references/components/context-menu.md +355 -0
  92. package/skills/cocoar-vue-ui/references/components/data-grid/checkbox.md +213 -0
  93. package/skills/cocoar-vue-ui/references/components/data-grid/date-columns.md +272 -0
  94. package/skills/cocoar-vue-ui/references/components/data-grid/editing.md +236 -0
  95. package/skills/cocoar-vue-ui/references/components/data-grid/multi-select.md +193 -0
  96. package/skills/cocoar-vue-ui/references/components/data-grid/number.md +147 -0
  97. package/skills/cocoar-vue-ui/references/components/data-grid/select.md +202 -0
  98. package/skills/cocoar-vue-ui/references/components/data-grid/text.md +127 -0
  99. package/skills/cocoar-vue-ui/references/components/data-grid.md +1225 -0
  100. package/skills/cocoar-vue-ui/references/components/data-list.md +2121 -0
  101. package/skills/cocoar-vue-ui/references/components/date-or-time-picker.md +200 -0
  102. package/skills/cocoar-vue-ui/references/components/date-picker.md +203 -0
  103. package/skills/cocoar-vue-ui/references/components/date-time-picker.md +154 -0
  104. package/skills/cocoar-vue-ui/references/components/date-views.md +212 -0
  105. package/skills/cocoar-vue-ui/references/components/dialog.md +148 -0
  106. package/skills/cocoar-vue-ui/references/components/divider.md +157 -0
  107. package/skills/cocoar-vue-ui/references/components/document-viewer/annotations.md +400 -0
  108. package/skills/cocoar-vue-ui/references/components/document-viewer/coar-document-viewer.md +327 -0
  109. package/skills/cocoar-vue-ui/references/components/document-viewer/index.md +234 -0
  110. package/skills/cocoar-vue-ui/references/components/document-viewer/toolbar.md +221 -0
  111. package/skills/cocoar-vue-ui/references/components/drag-drop.md +267 -0
  112. package/skills/cocoar-vue-ui/references/components/dual-listbox.md +449 -0
  113. package/skills/cocoar-vue-ui/references/components/file-explorer/asset-store.md +327 -0
  114. package/skills/cocoar-vue-ui/references/components/file-explorer/in-memory-store.md +176 -0
  115. package/skills/cocoar-vue-ui/references/components/file-explorer/index.md +311 -0
  116. package/skills/cocoar-vue-ui/references/components/file-explorer/use-file-explorer.md +300 -0
  117. package/skills/cocoar-vue-ui/references/components/form-field.md +1025 -0
  118. package/skills/cocoar-vue-ui/references/components/fragment-parser.md +298 -0
  119. package/skills/cocoar-vue-ui/references/components/link.md +235 -0
  120. package/skills/cocoar-vue-ui/references/components/listbox.md +575 -0
  121. package/skills/cocoar-vue-ui/references/components/map/editor.md +448 -0
  122. package/skills/cocoar-vue-ui/references/components/map/index.md +351 -0
  123. package/skills/cocoar-vue-ui/references/components/markdown-diagrams.md +210 -0
  124. package/skills/cocoar-vue-ui/references/components/markdown-editor.md +1478 -0
  125. package/skills/cocoar-vue-ui/references/components/markdown-embeds.md +387 -0
  126. package/skills/cocoar-vue-ui/references/components/markdown-form.md +447 -0
  127. package/skills/cocoar-vue-ui/references/components/markdown.md +276 -0
  128. package/skills/cocoar-vue-ui/references/components/menu.md +380 -0
  129. package/skills/cocoar-vue-ui/references/components/mermaid.md +172 -0
  130. package/skills/cocoar-vue-ui/references/components/navbar.md +147 -0
  131. package/skills/cocoar-vue-ui/references/components/note.md +96 -0
  132. package/skills/cocoar-vue-ui/references/components/notice.md +131 -0
  133. package/skills/cocoar-vue-ui/references/components/number-input.md +215 -0
  134. package/skills/cocoar-vue-ui/references/components/otp-input.md +324 -0
  135. package/skills/cocoar-vue-ui/references/components/page-builder/authoring-contract.md +271 -0
  136. package/skills/cocoar-vue-ui/references/components/page-builder/coar-page-builder.md +476 -0
  137. package/skills/cocoar-vue-ui/references/components/page-builder/coar-page-renderer.md +677 -0
  138. package/skills/cocoar-vue-ui/references/components/page-builder/custom-elements.md +441 -0
  139. package/skills/cocoar-vue-ui/references/components/page-builder/idp-integration.md +122 -0
  140. package/skills/cocoar-vue-ui/references/components/page-builder/index.md +573 -0
  141. package/skills/cocoar-vue-ui/references/components/pagination.md +150 -0
  142. package/skills/cocoar-vue-ui/references/components/panel-layout.md +372 -0
  143. package/skills/cocoar-vue-ui/references/components/password-input.md +175 -0
  144. package/skills/cocoar-vue-ui/references/components/popconfirm.md +186 -0
  145. package/skills/cocoar-vue-ui/references/components/popover.md +173 -0
  146. package/skills/cocoar-vue-ui/references/components/progress-bar.md +178 -0
  147. package/skills/cocoar-vue-ui/references/components/radio-group.md +225 -0
  148. package/skills/cocoar-vue-ui/references/components/script-editor.md +1271 -0
  149. package/skills/cocoar-vue-ui/references/components/segmented-control.md +238 -0
  150. package/skills/cocoar-vue-ui/references/components/select.md +463 -0
  151. package/skills/cocoar-vue-ui/references/components/sidebar.md +421 -0
  152. package/skills/cocoar-vue-ui/references/components/spinner.md +132 -0
  153. package/skills/cocoar-vue-ui/references/components/switch.md +195 -0
  154. package/skills/cocoar-vue-ui/references/components/table.md +170 -0
  155. package/skills/cocoar-vue-ui/references/components/tabs.md +382 -0
  156. package/skills/cocoar-vue-ui/references/components/tag.md +178 -0
  157. package/skills/cocoar-vue-ui/references/components/text-input.md +256 -0
  158. package/skills/cocoar-vue-ui/references/components/toast.md +160 -0
  159. package/skills/cocoar-vue-ui/references/components/tooltip.md +121 -0
  160. package/skills/cocoar-vue-ui/references/components/transitions.md +193 -0
  161. package/skills/cocoar-vue-ui/references/components/tree.md +2388 -0
  162. package/skills/cocoar-vue-ui/references/components/virtual-list.md +212 -0
  163. package/skills/cocoar-vue-ui/references/components/wizard.md +251 -0
  164. package/skills/cocoar-vue-ui/references/components/zoned-date-time-picker.md +177 -0
  165. package/skills/cocoar-vue-ui/references/foundations/colors.md +708 -0
  166. package/skills/cocoar-vue-ui/references/foundations/design-principles.md +115 -0
  167. package/skills/cocoar-vue-ui/references/foundations/icons.md +381 -0
  168. package/skills/cocoar-vue-ui/references/foundations/localization/formatting.md +530 -0
  169. package/skills/cocoar-vue-ui/references/foundations/localization/setup.md +86 -0
  170. package/skills/cocoar-vue-ui/references/foundations/localization/timezones.md +182 -0
  171. package/skills/cocoar-vue-ui/references/foundations/localization/translations.md +305 -0
  172. package/skills/cocoar-vue-ui/references/foundations/motion.md +549 -0
  173. package/skills/cocoar-vue-ui/references/foundations/spacing.md +330 -0
  174. package/skills/cocoar-vue-ui/references/foundations/theming.md +140 -0
  175. package/skills/cocoar-vue-ui/references/foundations/typography.md +206 -0
  176. package/skills/cocoar-vue-ui/references/guide/error-handling.md +162 -0
  177. package/skills/cocoar-vue-ui/references/guide/getting-started.md +116 -0
  178. package/skills/cocoar-vue-ui/references/guide/migration-page-builder-3.md +207 -0
  179. package/skills/cocoar-vue-ui/references/guide/migration.md +140 -0
  180. package/skills/cocoar-vue-ui/references/guide/theming.md +98 -0
@@ -0,0 +1,476 @@
1
+ <!-- Generated from apps/docs/components/page-builder/coar-page-builder.md by apps/docs/scripts/sync-skill.mjs. Do not edit; edit the docs page. -->
2
+
3
+ # `<CoarPageBuilder>` (Preview)
4
+
5
+ The visual-editor half of `@cocoar/vue-page-builder`. It renders a three-panel layout: the vertically split Outline and Properties inspector on the left, the canvas in the centre, and a searchable element library on the right. It emits a `PageNode` JSON tree as `v-model`; the same tree is consumed by [`<CoarPageRenderer>`](./coar-page-renderer.md) at runtime.
6
+
7
+ All three panels are resizable via drag handles and collapsible.
8
+
9
+ > **Tip: Stylesheet**
10
+ >
11
+ > Import `@cocoar/vue-page-builder/styles` once in your app — it carries the entire builder chrome (panels, canvas, palette). Without it the builder renders unstyled.
12
+
13
+ ## Playground
14
+
15
+ A live builder with a small starting schema and a restricted `allowedElements` list — note that the palette and the outline's "Add child" menu only offer the permitted types. Drag palette cards onto the canvas, reorder rows in the outline via their grip handles, and try `Ctrl+Z` after an edit. The builder fills its host element, so give it a bounded height.
16
+
17
+ **Demo — `page-builder/demos/BuilderPlayground.vue`**
18
+
19
+ ```vue
20
+ <template>
21
+ <div class="builder-playground">
22
+ <CoarPageBuilder v-model="schema" :config="config" />
23
+ </div>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import { ref } from 'vue';
28
+ import { CoarPageBuilder, type PageNode, type PageConfig } from '@cocoar/vue-page-builder';
29
+ import '@cocoar/vue-page-builder/styles';
30
+
31
+ const schema = ref<PageNode>({
32
+ id: 'root',
33
+ type: 'page',
34
+ schemaVersion: 5,
35
+ style: { gap: '16px', padding: '24px' },
36
+ children: [
37
+ {
38
+ id: 'heading-welcome',
39
+ type: 'heading',
40
+ props: { text: 'Welcome', level: 2 },
41
+ },
42
+ {
43
+ id: 'stack-intro',
44
+ type: 'stack',
45
+ props: { direction: 'column' },
46
+ style: { gap: '12px' },
47
+ children: [
48
+ {
49
+ id: 'paragraph-intro',
50
+ type: 'paragraph',
51
+ props: {
52
+ text: 'Drag elements from the palette onto the canvas, reorder rows in the outline via their grip handles, and press Ctrl+Z to undo.',
53
+ },
54
+ },
55
+ ],
56
+ },
57
+ ],
58
+ });
59
+
60
+ // Only these types show up in the palette and the outline's "Add child" menu —
61
+ // note that Section, Select, Link and Image are gated out.
62
+ const config: PageConfig = {
63
+ allowedElements: ['stack', 'card', 'heading', 'paragraph', 'text-input', 'checkbox', 'button'],
64
+ availableActions: [
65
+ { id: 'demo:submit', label: 'Submit (demo)' },
66
+ ],
67
+ };
68
+ </script>
69
+
70
+ <style scoped>
71
+ .builder-playground {
72
+ height: 560px;
73
+ }
74
+ </style>
75
+ ```
76
+
77
+ ## Props
78
+
79
+ | Prop | Type | Default | Description |
80
+ |------|------|---------|-------------|
81
+ | `modelValue` / `v-model` | `PageNode` | empty `page` | The page schema. Bound two-way; every edit updates the ref. Every tree entering from **outside** — the initial value, a later external replacement, or an initially-`undefined` ref that is filled once an async load resolves — passes through the same normalization as the JSON tab's Apply: legacy `column`/`row` containers become `stack`, v1 flat documents get their `props` bags, a non-`page` root is wrapped in one, missing/duplicate node ids are repaired with fresh `crypto.randomUUID` ids, missing `children` arrays and `props` bags are added, every element receives a unique name, and documents are stamped `schemaVersion: 6`. Repairs log a DEV-only console warning. |
82
+ | `config` | [`PageConfig`](./index.md#pageconfig-the-consumer-contract) | — | Allowed elements, [consumer element registrations](./custom-elements.md), actions, runtime-context contracts, locales, limits and asset callbacks. Pass the same value to the renderer. |
83
+ | `previewContext` | `Record<string, unknown>` | — | Safe host data for the embedded preview. Only paths declared by `config.contextFields` are readable. |
84
+ | `previewInitialValues` | `ActionValues` | — | Field values the embedded preview starts from, merged **over** the schema's own `defaultValue`s exactly as at runtime. The edit-form case, and the case where the host computes a default the author did not write (a per-tenant "remember me" setting). Replacing the object re-seeds the preview. |
85
+ | `previewLocale` | `string` | — | Initial locale for localized schema values in the preview. |
86
+ | `previewTheme` | `CoarTheme` | — | Host-resolved brand primitives applied through the same `CoarThemeScope` used at runtime. Scoped to the Preview canvas; builder chrome and dialogs are unaffected. |
87
+ | `previewThemeMode` | `'auto' \| 'light' \| 'dark'` | `'auto'` | Colour mode for the preview theme. Auto follows the surrounding application/OS mode. |
88
+ | `previewActions` | `Record<string, ActionHandler>` | — | Optional live handlers for action testing in the embedded preview. |
89
+ | `previewFallbackSchema` | `PageNode` | — | Host-owned fallback used by the preview when the customized document violates its contract. |
90
+ | `previewExpressionValues` | `RuntimeExpressionValues` | — | Optional precomputed expression values for the embedded preview. Source code is never evaluated in the builder's main thread. |
91
+ | `authoringMode` | `'properties' \| 'code'` | `'properties'` | In `code` mode the inspector stays structural and Page/Element Code is authoritative for configurable properties. |
92
+ | `previewRuntimeHost` | `PageRuntimeHost` | no-capability host | Application capability catalogue for the Builder-owned isolated preview runtime. |
93
+ | `previewRuntimePageId` | `string` | schema id | Stable page identity used by preview capability grants and diagnostics. |
94
+ | `previewRuntimeTenantId` | `string` | — | Optional tenant identity supplied to preview capability grants. |
95
+ | `pageCodeExtraLibs` | `CoarScriptEditorExtraLib[]` | `[]` | Host capability declarations added to Monaco IntelliSense for Page and Element Code. |
96
+ | `compositionRepository` | `PageCompositionRepository` | — | Optional host-owned repository of reusable, immutable, versioned subtrees. Supplying it enables the Compositions library and management tab. |
97
+ | `compositionManagement` | `'inline' \| 'consume'` | `'inline'` | Whether definitions may be created/published inside this page builder or are managed by a separate host-owned composition editor. |
98
+
99
+ ## Events
100
+
101
+ | Event | Payload | Description |
102
+ |-------|---------|-------------|
103
+ | `update:modelValue` | `PageNode` | Emitted after every schema edit for `v-model`. |
104
+ | `preview-values` | `ActionValues` | Current field-value snapshot from the embedded preview. |
105
+ | `preview-runtime` | `{ fields, form }` | Reactive preview scope for host diagnostics; `form` contains valid, dirty, validating and submitting flags. |
106
+ | `open-composition` | `PageCompositionReference` | Requests host navigation to the independently managed composition definition and exact pinned version. |
107
+ | `validation` | `AuthoringFinding[]` | The authoring findings the builder draws in its own outline and props panel. Fires on mount and whenever the set changes in content, so an edit that leaves the findings alone stays quiet. The payload is a copy — mutating it cannot corrupt the builder. |
108
+
109
+ ## Reaching the validation findings
110
+
111
+ Two layers answer two different questions, and mixing them up leads to either a
112
+ save button that never enables or a document that fails at activation.
113
+
114
+ | | Question | API |
115
+ |---|---|---|
116
+ | **Authoring findings** | "What should I tell the author to fix?" | `@findings` / `useAuthoringFindings()` |
117
+ | **Activation contract** | "May this document go live?" | [`validatePageDocument()`](./idp-integration.md) |
118
+
119
+ The authoring layer is the broader one — it includes hints the runtime does not
120
+ care about (an action that is not in `availableActions`, a required contract
121
+ field nobody put on the page) and it *contains* the hard failures of the
122
+ activation contract, so gating a save on `severity === 'error'` is sound.
123
+
124
+ ```vue
125
+ <script setup lang="ts">
126
+ import { ref, computed } from 'vue';
127
+ import { CoarPageBuilder, type AuthoringFinding, type PageNode } from '@cocoar/vue-page-builder';
128
+
129
+ const schema = ref<PageNode>();
130
+ const findings = ref<AuthoringFinding[]>([]);
131
+ const blocking = computed(() => findings.value.filter((f) => f.severity === 'error'));
132
+ </script>
133
+
134
+ <template>
135
+ <CoarPageBuilder v-model="schema" :config="config" @findings="findings = $event" />
136
+ <button :disabled="blocking.length > 0" @click="save">Save</button>
137
+ <ul>
138
+ <li v-for="(finding, i) in blocking" :key="i">{{ finding.message }}</li>
139
+ </ul>
140
+ </template>
141
+ ```
142
+
143
+ Each finding carries the `nodeId` it belongs to and, where the problem is a
144
+ specific property, the `field` — enough to build your own "jump to node" list.
145
+
146
+ Outside a mounted builder — a document dashboard, a bulk migration check — call
147
+ the composable directly in a component `setup()`. It resolves the element
148
+ registry reactively, honouring `config.elementTypes` and an app-level
149
+ `PAGE_ELEMENT_TYPES_KEY` provide alike:
150
+
151
+ ```ts
152
+ const { findings, byNodeId } = useAuthoringFindings(schema, config);
153
+ ```
154
+
155
+ ## Features
156
+
157
+ - **Searchable element library** — the right panel groups draggable cards under **Fields** (first when a field contract exists), **Containers**, **Elements** and, when a repository is supplied, **Compositions**. Groups are independently collapsible and a single search filters all of them, so repositories with dozens of definitions remain manageable. Registry entries come from built-ins plus [`config.elementTypes`](./custom-elements.md), filtered by `config.allowedElements`. `hideElementPicker` removes value-producing entries from **Elements** and from the outline's separate Inputs add-child group; containers and content/action elements remain available.
158
+ - **Pointer-based drag & drop** — built on pointer events rather than HTML5 drag events, so it works with mouse, touch **and** pen (tablet-first). Mouse drags start after a 5 px movement threshold, so plain clicks keep working; touch/pen drags arm after a 300 ms long-press. A ghost preview follows the pointer, scroll containers auto-scroll near their edges, and `Escape` cancels a drag in flight.
159
+ - **Outline tree** — hierarchical node list with selection and real drag-to-reorder: every row except the root carries a grip handle, thin drop bars light up between rows while dragging, and container rows highlight for drop-**into**. Per-row actions: move up/down, duplicate, delete, plus an inline "Add child" menu. Stacks display "Column" or "Row" based on direction. Warning icons mark nodes with validation issues (hover for the full message).
160
+ - **Canvas** — per-element preview components with dashed selection borders; each node's type tab doubles as its drag handle. A registered element without its own preview renders as a neutral icon+label chip; unregistered or disallowed element types get a red "skipped at runtime" treatment, so the canvas never pretends the runtime renderer will show them. Switches to live preview in the **Preview** tab and to a paste-and-apply JSON editor in the **JSON** tab.
161
+ - **Properties panel** — the lower-left inspector is resolved from the element registry: each definition ships its own inspector component. Value-producing elements additionally get a host-owned **Field** section (field name, Required, default value — with a per-element default-value editor when the definition provides one, e.g. "Checked by default" for checkboxes). With a [field contract](./index.md#field-contract), the field-name input becomes a select over the contract fields the element can edit (clearing it unbinds; binding carries the contract label and required along), an **Element** select switches the node to another representation of the same field, and `allowCustomFields` adds a free-text custom-name input. Every non-page node also gets a host-owned **Visibility** section authoring [`visibleWhen`](./coar-page-renderer.md#conditional-visibility-visiblewhen): a "Visible when" select over the page's named fields plus a typed `equals` editor (checked/unchecked for boolean controllers, the option list for choice controllers, free text otherwise; a JSON-authored `in` condition is surfaced read-only) — conditional nodes carry an **eye marker** on their canvas tab. Selecting the page root shows a **Page** section with the [Enter-to-submit](./coar-page-renderer.md#enter-to-submit) checkbox; the button inspector offers the matching "Default button" checkbox. The choice inputs' inspectors take an **Options source ID** for [API-backed option lists](./coar-page-renderer.md#dynamic-options-optionssource). A linked composition root additionally shows its name, pinned version, version selector, update-to-latest, detach and open actions. Validation issues for the selected node are surfaced at the top with colored banners. Option-based inputs share an **options editor** (add / remove / reorder options; a removed option clears a default that pointed at it).
162
+ - **Reusable compositions** — repository-backed definitions appear beside normal elements and materialize through the same drag-and-drop pipeline. No runtime wrapper or persisted composition element type is introduced: the inserted subtree stays ordinary PageBuilder JSON plus builder-only origin metadata. Version changes are explicit; runtime compilation removes repository metadata and needs no repository access.
163
+ - **Duplicate** — available as an outline row action and a canvas button. Deep-clones the subtree with fresh ids on every node; colliding field names are flagged by the duplicate-name validation.
164
+ - **Stack direction toggle** — change a stack from column to row direction without re-creating it. Children stay put.
165
+ - **Layout controls** — every node's Style section exposes the flex model: container `Justify` (main axis) + `Align items` (cross axis), and per-node `Align self`, `Size` (Fit / Fill / Fixed → Width) and `Min height`. Center a single element, distribute a row, or build a full-screen centered page — and the Editor canvas mirrors the result 1:1 with the Preview.
166
+ - **Asset picker entry point** — when `config.pickAsset` is set, the image element shows a thumbnail + "Choose…" button that defers to your own picker UI.
167
+ - **Responsive authoring and preview** — Mobile-first base styles plus Phone, Tablet and Desktop overrides. The exact Compact 320×568, Phone 390×844, Tablet 768×1024 and Desktop 1280×800 frames use the same resolver as runtime; each override can be reset independently. `hidden` removes the node from rendering, validation and action payloads at that breakpoint. Both the Style section and the code-mode **Quick Properties** show the value that applies at the breakpoint being authored, not the base — a node hidden on Compact and revealed on Desktop reads as visible while you are on Desktop. Where that value came from an override, the Quick Property carries a small breakpoint chip, because editing it writes one assignment that applies everywhere and would flatten the difference.
168
+ - **Runtime bindings and localization** — bind supported element props and individual `actionValues.<key>` entries to allow-listed context paths, customer Page State, named form fields/selections, or the current repeater item/index. Safe expressions use the same targets. Properties explicitly registered as `valueKind: 'localized-text'` reference stable keys; the central **Translations** tab edits the page-owned catalogue for every configured locale and flags unused keys. Legacy embedded `LocalizedValue` objects remain readable.
169
+ - **Conditions, repeaters and feedback zones** — `visibleWhen` supports field/context/state/item sources and bounded `all`/`any` composition. A generic `repeat` renders a child template for an allow-listed context array and can emit a selected-key array under any configured output name. A `feedback` node places form errors, status, loading or authored messages inside the layout.
170
+ - **Host-supplied preview inputs** — the embedded preview and its sandbox session run against `previewContext` and `previewLocale`. Until the host supplies whatever its own `config` declares (`contextFields`, `locales`), the preview stays off and says so rather than rendering against invented data. Swapping `previewContext` restarts the sandbox against the new contract, so a host that wants an “empty / typical / 50 items” picker builds it in its own chrome and simply binds the chosen sample.
171
+ - **Page Root Code** — selecting the page root exposes a separate constrained code editor. It can reactively configure only `page.style`, `page.responsive`, and `page.enterSubmits`; structure, children, ids, types and names remain visual-builder owned. Shared mutable data stays in the independent Page State editor.
172
+ - **Undo / redo** — `Ctrl+Z` / `Ctrl+Y` (or `Cmd+Z` / `Cmd+Shift+Z`), also via toolbar buttons.
173
+ - **Scoped keyboard shortcuts** — undo/redo and `Delete` / `Backspace` (removes the selected node) only act while focus is inside *that builder instance*, and never while focus is in an editable target: the JSON textarea, props-panel inputs and your app's own form fields keep their native undo and delete behavior.
174
+ - **Keyboard navigation** — the outline is an ARIA tree (`role="tree"` / `role="treeitem"` with `aria-level`, `aria-selected`, `aria-expanded`) with a roving tabindex: `Arrow Up` / `Arrow Down` / `Home` / `End` move focus, `Enter` / `Space` selects the focused row. Canvas nodes are focusable too; `Enter` / `Space` selects the focused node.
175
+
176
+ ## JSON tab
177
+
178
+ The JSON tab shows the current schema and lets you paste and **Apply** a replacement. Apply is gated by **issue severity** — the pasted tree runs through the same normalization pass the v-model entry points use:
179
+
180
+ - **Errors block Apply** — structural damage where data would be dropped: non-object nodes (and non-JSON input). The inline message lists what is wrong; nothing reaches the working tree (or, through `v-model`, your storage).
181
+ - **Warnings apply anyway** and are surfaced next to the Apply button: everything healed in place or lossless — legacy `column` / `row` containers (→ `stack`), v1 flat nodes (→ `props` bags), a non-`page` root (wrapped in a `page`), missing or duplicate node ids (fresh ids), missing or non-object `props` bags, out-of-range or non-numeric heading levels, non-array `children` (reset), `children` on a non-container, and **unknown element types**.
182
+
183
+ Unknown element types are deliberately *not* rejected: a document from a newer library version — or one using [consumer elements](./custom-elements.md) this instance hasn't registered — stays pasteable and round-trips **losslessly** (the nodes stay in the tree; the runtime renderer skips them with one console warning per type).
184
+
185
+ A successful Apply lands as a single undoable step; when there were no findings at all, the builder switches back to the Editor tab.
186
+
187
+ > **Info: Exported helpers**
188
+ >
189
+ > The same machinery is exported for hosts that persist or migrate schemas themselves: `normalizePageSchema(value)` → `{ schema, issues, changed }` (issues carry `severity: 'error' | 'warning'`), `migrateLegacyTypes(node)`, `migrateV1PropsBag(node)`, and the `KNOWN_ELEMENT_TYPES` set (built-ins only). See [Legacy schemas & normalization](./coar-page-renderer.md#legacy-schemas-normalization).
190
+
191
+ ## Builder-side findings
192
+
193
+ The builder derives its authoring findings reactively and surfaces them at two layers:
194
+
195
+ - **Outline** — a warning icon next to the affected node row (red ⛔ for errors, yellow ⚠ for warnings). Hover the icon for the full message.
196
+ - **Props panel** — a colored banner at the top of the selected node's properties listing every finding for that node.
197
+
198
+ Built-in rules:
199
+
200
+ | Rule | Severity |
201
+ |------|----------|
202
+ | Element type is not registered (skipped at runtime, but kept losslessly in the tree) | warning |
203
+ | Type not in `config.allowedElements` (skipped at render time) | error |
204
+ | Any registry element with `action: true` has no Action | warning |
205
+ | Action ID is not in `config.availableActions` (only checked when that list is non-empty) | warning |
206
+ | Action values are not JSON-safe, or the dynamic action-value key is empty/reserved | error |
207
+ | `validation.pattern` does not compile as a regular expression | error |
208
+ | Image has no Asset ID | error |
209
+ | Two named inputs share the same `name` | error |
210
+ | Bound field name is not in the [field contract](./index.md#field-contract) (`config.dataContract` set, `allowCustomFields` off) | error |
211
+ | Element cannot edit its bound contract field's value type | error |
212
+ | Required contract field is missing from the page (reported on the root node) | warning |
213
+ | `visibleWhen` is malformed (node stays always visible) | warning |
214
+ | `visibleWhen` references a field that is not on the page | warning |
215
+ | `visibleWhen` chain is circular (incl. self-reference and loops through ancestor containers) — fields can lock each other hidden | warning |
216
+ | `visibleWhen.equals` targets a multi-value (`string[]`) field — the condition can never match | warning |
217
+ | Multiple buttons claim `default` — Enter fires only the first in tree order | warning |
218
+ | Field name is reserved (`__proto__`, `constructor`, `prototype`) — excluded from the value model | error |
219
+ | `optionsSourceId` is set but `config.optionsSource` is not configured | warning |
220
+
221
+ Element definitions can contribute their own findings through the definition's `builder.lint` hook — they are merged into the same outline/props-panel surfaces with their declared severity (see [Custom elements](./custom-elements.md)).
222
+
223
+ Validation is a builder UX scaffold — it does **not** affect what the renderer does, and no severity blocks saving. The renderer is governed by `allowedElements` (the hard security boundary) and by which handlers exist in the `actions` map.
224
+
225
+ ## Per-element architecture
226
+
227
+ Every element type — built-in or consumer-registered — is **one registry definition** (`definePageElement`): a runtime renderer plus optional value spec, canvas preview, inspector, default-value editor and lint hook. Built-ins live one folder per element inside the package and are pre-registered on the same contract consumers use:
228
+
229
+ ```
230
+ packages/page-builder/src/elements/
231
+ ├── registry.ts ← contract types · definePageElement · additive merge
232
+ ├── builtins.ts ← the pre-registered built-in registry
233
+ ├── heading/
234
+ │ ├── index.ts ← the definition (renderer + builder halves)
235
+ │ ├── HeadingRenderer.vue
236
+ │ ├── HeadingPreview.vue
237
+ │ └── HeadingInspector.vue
238
+ ├── text-input/
239
+ └── …
240
+ ```
241
+
242
+ `BuilderPropsPanel.vue` is a thin host shell: it resolves the selected node's definition from the merged registry and renders `<component :is="def.builder.inspector" :node :patch />` between the host-owned **Field** and **Style** sections. The palette, add-child menu, canvas previews and outline icons all derive from the same registry — adding an element type is a single definition, **no central files are touched**. Consumer apps register theirs via `config.elementTypes`; the shared `OptionsEditor` component is exported for reuse in consumer inspectors. See the [Custom elements guide](./custom-elements.md).
243
+
244
+ ## Pairing with the renderer
245
+
246
+ The builder's Preview tab uses `<CoarPageRenderer>` internally with the same `config` — the renderer falls back to `config.assetResolver` on its own, so thumbnails work without extra wiring. For the actual runtime page (outside the builder), you mount the renderer yourself — see [`<CoarPageRenderer>`](./coar-page-renderer.md) and the [integration walkthrough](./index.md#complete-idp-integration-walkthrough).
247
+
248
+ ## i18n Keys
249
+
250
+ All builder chrome — and the runtime renderer's validation messages — resolve through [`@cocoar/vue-localization`](../../foundations/localization/translations.md) (a peer dependency) with keys under `coar.pageBuilder.*`. English fallbacks are built in, so apps without a translation setup render English. Values in `{braces}` are interpolation parameters.
251
+
252
+ ### Chrome (tabs, toolbar, panels, preview widths)
253
+
254
+ | Key | Default (English) |
255
+ |-----|-------------------|
256
+ | `coar.pageBuilder.chrome.outline` | `'Outline'` |
257
+ | `coar.pageBuilder.chrome.collapseOutline` | `'Collapse outline'` |
258
+ | `coar.pageBuilder.chrome.expandOutline` | `'Expand outline'` |
259
+ | `coar.pageBuilder.chrome.collapseProperties` | `'Collapse properties'` |
260
+ | `coar.pageBuilder.chrome.expandProperties` | `'Expand properties'` |
261
+ | `coar.pageBuilder.chrome.tabEditor` | `'Editor'` |
262
+ | `coar.pageBuilder.chrome.tabPreview` | `'Preview'` |
263
+ | `coar.pageBuilder.chrome.tabJson` | `'JSON'` |
264
+ | `coar.pageBuilder.chrome.undo` | `'Undo (Ctrl+Z)'` |
265
+ | `coar.pageBuilder.chrome.redo` | `'Redo (Ctrl+Y)'` |
266
+ | `coar.pageBuilder.chrome.jsonHint` | `'Paste or edit JSON, then click Apply'` |
267
+ | `coar.pageBuilder.chrome.jsonApply` | `'Apply →'` |
268
+ | `coar.pageBuilder.chrome.previewWidth` | `'Preview width'` |
269
+ | `coar.pageBuilder.chrome.previewDesktop` | `'Desktop'` |
270
+ | `coar.pageBuilder.chrome.previewFullTitle` | `'Full width'` |
271
+ | `coar.pageBuilder.chrome.previewTablet` | `'Tablet · 768'` |
272
+ | `coar.pageBuilder.chrome.previewTabletTitle` | `'768px'` |
273
+ | `coar.pageBuilder.chrome.previewMobile` | `'Mobile · 375'` |
274
+ | `coar.pageBuilder.chrome.previewMobileTitle` | `'375px'` |
275
+
276
+ ### Shared row actions
277
+
278
+ | Key | Default (English) |
279
+ |-----|-------------------|
280
+ | `coar.pageBuilder.common.moveUp` | `'Move up'` |
281
+ | `coar.pageBuilder.common.moveDown` | `'Move down'` |
282
+ | `coar.pageBuilder.common.duplicate` | `'Duplicate'` |
283
+ | `coar.pageBuilder.common.delete` | `'Delete'` |
284
+
285
+ ### Outline
286
+
287
+ | Key | Default (English) |
288
+ |-----|-------------------|
289
+ | `coar.pageBuilder.outline.treeLabel` | `'Page structure'` |
290
+ | `coar.pageBuilder.outline.addChild` | `'Add child'` |
291
+ | `coar.pageBuilder.outline.column` | `'Column'` |
292
+ | `coar.pageBuilder.outline.row` | `'Row'` |
293
+ | `coar.pageBuilder.outline.validationIssues` | `'Validation issues'` |
294
+
295
+ ### Palette
296
+
297
+ | Key | Default (English) |
298
+ |-----|-------------------|
299
+ | `coar.pageBuilder.palette.containers` | `'Containers'` |
300
+ | `coar.pageBuilder.palette.inputs` | `'Inputs'` |
301
+ | `coar.pageBuilder.palette.elements` | `'Elements'` |
302
+ | `coar.pageBuilder.palette.fields` | `'Fields'` |
303
+ | `coar.pageBuilder.palette.dragToAdd` | `'Drag to add {label}'` |
304
+ | `coar.pageBuilder.palette.fieldBound` | `'Already on the page'` |
305
+ | `coar.pageBuilder.palette.fieldNoElement` | `'No compatible element available'` |
306
+
307
+ ### Canvas
308
+
309
+ | Key | Default (English) |
310
+ |-----|-------------------|
311
+ | `coar.pageBuilder.canvas.emptyContainer` | `'Empty {type} — drop something here'` |
312
+ | `coar.pageBuilder.canvas.unknownType` | `'Unknown type "{type}" — skipped at runtime'` |
313
+ | `coar.pageBuilder.canvas.notAllowed` | `'Not in allowedElements — skipped at runtime'` |
314
+ | `coar.pageBuilder.canvas.visibleWhen` | `'Shown conditionally — depends on "{field}"'` |
315
+
316
+ ### Element type labels
317
+
318
+ Used by the palette, the outline's add-child menu and the canvas type tabs. These are the built-in elements' `label` keys; consumer-registered elements carry their own `label: { key, fallback }` in the element definition, so their keys live in the consumer's namespace, not under `coar.pageBuilder.*`.
319
+
320
+ | Key | Default (English) |
321
+ |-----|-------------------|
322
+ | `coar.pageBuilder.type.page` | `'Page'` |
323
+ | `coar.pageBuilder.type.stack` | `'Stack'` |
324
+ | `coar.pageBuilder.type.card` | `'Card'` |
325
+ | `coar.pageBuilder.type.section` | `'Section'` |
326
+ | `coar.pageBuilder.type.divider` | `'Divider'` |
327
+ | `coar.pageBuilder.type.spacer` | `'Spacer'` |
328
+ | `coar.pageBuilder.type.heading` | `'Heading'` |
329
+ | `coar.pageBuilder.type.paragraph` | `'Paragraph'` |
330
+ | `coar.pageBuilder.type.note` | `'Note'` |
331
+ | `coar.pageBuilder.type.image` | `'Image'` |
332
+ | `coar.pageBuilder.type.link` | `'Link'` |
333
+ | `coar.pageBuilder.type.button` | `'Button'` |
334
+ | `coar.pageBuilder.type.textInput` | `'Text Input'` |
335
+ | `coar.pageBuilder.type.passwordInput` | `'Password'` |
336
+ | `coar.pageBuilder.type.numberInput` | `'Number Input'` |
337
+ | `coar.pageBuilder.type.checkbox` | `'Checkbox'` |
338
+ | `coar.pageBuilder.type.switch` | `'Switch'` |
339
+ | `coar.pageBuilder.type.select` | `'Select'` |
340
+ | `coar.pageBuilder.type.multiSelect` | `'Multi Select'` |
341
+ | `coar.pageBuilder.type.radioGroup` | `'Radio Group'` |
342
+ | `coar.pageBuilder.type.dateInput` | `'Date'` |
343
+ | `coar.pageBuilder.type.dateTimeInput` | `'Date & Time'` |
344
+ | `coar.pageBuilder.type.otpInput` | `'OTP Input'` |
345
+
346
+ ### Properties panel
347
+
348
+ The host-owned **Field** section (name / required / default value, shown for every value-producing element) uses `props.fieldName`, `props.required` and `props.defaultValue`.
349
+
350
+ | Key | Default (English) |
351
+ |-----|-------------------|
352
+ | `coar.pageBuilder.props.panelTitle` | `'Properties'` |
353
+ | `coar.pageBuilder.props.emptyTitle` | `'No node selected'` |
354
+ | `coar.pageBuilder.props.emptyHint` | `'Click a node in the outline or canvas to edit it.'` |
355
+ | `coar.pageBuilder.props.text` | `'Text'` |
356
+ | `coar.pageBuilder.props.title` | `'Title'` |
357
+ | `coar.pageBuilder.props.label` | `'Label'` |
358
+ | `coar.pageBuilder.props.level` | `'Level'` |
359
+ | `coar.pageBuilder.props.fieldName` | `'Field name'` |
360
+ | `coar.pageBuilder.props.fieldUnbound` | `'Not bound'` |
361
+ | `coar.pageBuilder.props.customFieldName` | `'Custom name'` |
362
+ | `coar.pageBuilder.props.elementType` | `'Element'` |
363
+ | `coar.pageBuilder.props.placeholder` | `'Placeholder'` |
364
+ | `coar.pageBuilder.props.inputType` | `'Input type'` |
365
+ | `coar.pageBuilder.props.rows` | `'Rows'` |
366
+ | `coar.pageBuilder.props.min` | `'Min'` |
367
+ | `coar.pageBuilder.props.max` | `'Max'` |
368
+ | `coar.pageBuilder.props.step` | `'Step'` |
369
+ | `coar.pageBuilder.props.decimals` | `'Decimals'` |
370
+ | `coar.pageBuilder.props.length` | `'Length'` |
371
+ | `coar.pageBuilder.props.mask` | `'Mask input'` |
372
+ | `coar.pageBuilder.props.otpType` | `'Character set'` |
373
+ | `coar.pageBuilder.props.defaultValue` | `'Default value'` |
374
+ | `coar.pageBuilder.props.checkedByDefault` | `'Checked by default'` |
375
+ | `coar.pageBuilder.props.onByDefault` | `'On by default'` |
376
+ | `coar.pageBuilder.props.required` | `'Required'` |
377
+ | `coar.pageBuilder.props.disabled` | `'Disabled'` |
378
+ | `coar.pageBuilder.props.options` | `'Options'` |
379
+ | `coar.pageBuilder.props.addOption` | `'Add option'` |
380
+ | `coar.pageBuilder.props.removeOption` | `'Remove option'` |
381
+ | `coar.pageBuilder.props.optionLabelPlaceholder` | `'label'` |
382
+ | `coar.pageBuilder.props.optionValuePlaceholder` | `'value'` |
383
+ | `coar.pageBuilder.props.action` | `'Action'` |
384
+ | `coar.pageBuilder.props.actionHint` | `'Matched against the actions map at render time'` |
385
+ | `coar.pageBuilder.props.notConfigured` | `'{id} (not configured)'` |
386
+ | `coar.pageBuilder.props.validatesForm` | `'Validates form before firing'` |
387
+ | `coar.pageBuilder.props.defaultButton` | `'Default button (Enter submits here)'` |
388
+ | `coar.pageBuilder.props.enterSubmits` | `'Enter submits (fires the default button)'` |
389
+ | `coar.pageBuilder.props.visibleWhenField` | `'Visible when'` |
390
+ | `coar.pageBuilder.props.alwaysVisible` | `'Always visible'` |
391
+ | `coar.pageBuilder.props.visibleWhenEquals` | `'equals'` |
392
+ | `coar.pageBuilder.props.visibleWhenIn` | `'Multi-value condition (in) — edit it in the JSON tab.'` |
393
+ | `coar.pageBuilder.props.visibleWhenArray` | `'"equals" cannot match a multi-value field — author this condition in the JSON tab.'` |
394
+ | `coar.pageBuilder.props.checked` | `'checked'` |
395
+ | `coar.pageBuilder.props.unchecked` | `'unchecked'` |
396
+ | `coar.pageBuilder.props.optionsSource` | `'Options source ID'` |
397
+ | `coar.pageBuilder.props.optionsSourceHint` | `'Resolved via config.optionsSource at render time — overrides the static options'` |
398
+ | `coar.pageBuilder.props.variant` | `'Variant'` |
399
+ | `coar.pageBuilder.props.iconLeft` | `'Icon (left)'` |
400
+ | `coar.pageBuilder.props.asset` | `'Asset'` |
401
+ | `coar.pageBuilder.props.assetId` | `'Asset ID'` |
402
+ | `coar.pageBuilder.props.assetIdHint` | `'Resolved via assetResolver at render time'` |
403
+ | `coar.pageBuilder.props.altText` | `'Alt text'` |
404
+ | `coar.pageBuilder.props.choose` | `'Choose…'` |
405
+ | `coar.pageBuilder.props.change` | `'Change…'` |
406
+ | `coar.pageBuilder.props.clear` | `'Clear'` |
407
+ | `coar.pageBuilder.props.noImage` | `'No image'` |
408
+ | `coar.pageBuilder.props.noPreview` | `'No preview'` |
409
+ | `coar.pageBuilder.props.stackDirection` | `'Stack direction'` |
410
+ | `coar.pageBuilder.props.direction` | `'Direction'` |
411
+ | `coar.pageBuilder.props.column` | `'Column'` |
412
+ | `coar.pageBuilder.props.row` | `'Row'` |
413
+ | `coar.pageBuilder.props.orientation` | `'Orientation'` |
414
+ | `coar.pageBuilder.props.horizontal` | `'Horizontal'` |
415
+ | `coar.pageBuilder.props.vertical` | `'Vertical'` |
416
+ | `coar.pageBuilder.props.wrapChildren` | `'Wrap children'` |
417
+ | `coar.pageBuilder.props.gap` | `'Gap'` |
418
+ | `coar.pageBuilder.props.padding` | `'Padding'` |
419
+ | `coar.pageBuilder.props.justify` | `'Justify (main axis)'` |
420
+ | `coar.pageBuilder.props.alignItems` | `'Align items (cross axis)'` |
421
+ | `coar.pageBuilder.props.alignSelf` | `'Align self'` |
422
+ | `coar.pageBuilder.props.size` | `'Size'` |
423
+ | `coar.pageBuilder.props.sizeAuto` | `'Auto'` |
424
+ | `coar.pageBuilder.props.sizeFill` | `'Fill'` |
425
+ | `coar.pageBuilder.props.sizeFixedWidth` | `'Fixed width'` |
426
+ | `coar.pageBuilder.props.sizeCss` | `'Size (CSS)'` |
427
+ | `coar.pageBuilder.props.width` | `'Width'` |
428
+ | `coar.pageBuilder.props.minHeight` | `'Min height'` |
429
+ | `coar.pageBuilder.props.spacerSizeHint` | `'Leave empty to fill available space'` |
430
+ | `coar.pageBuilder.props.default` | `'— default'` |
431
+ | `coar.pageBuilder.props.inherit` | `'— inherit'` |
432
+ | `coar.pageBuilder.props.none` | `'— none'` |
433
+
434
+ ### Inspector section titles
435
+
436
+ Headings of the collapsible sections in the properties panel. `props.section.field`, `props.section.page`, `props.section.visibility`, `props.section.style` and `props.section.layout` are host-owned; the per-element titles come from each built-in definition's `inspectorTitle`. Consumer-registered elements provide their own `inspectorTitle: { key, fallback }`, so their keys are not under `coar.pageBuilder.*`.
437
+
438
+ | Key | Default (English) |
439
+ |-----|-------------------|
440
+ | `coar.pageBuilder.props.section.field` | `'Field'` |
441
+ | `coar.pageBuilder.props.section.page` | `'Page'` |
442
+ | `coar.pageBuilder.props.section.visibility` | `'Visibility'` |
443
+ | `coar.pageBuilder.props.section.style` | `'Style'` |
444
+ | `coar.pageBuilder.props.section.layout` | `'Layout'` |
445
+ | `coar.pageBuilder.props.section.card` | `'Card'` |
446
+ | `coar.pageBuilder.props.section.section` | `'Section'` |
447
+ | `coar.pageBuilder.props.section.spacer` | `'Spacer'` |
448
+ | `coar.pageBuilder.props.section.heading` | `'Heading'` |
449
+ | `coar.pageBuilder.props.section.paragraph` | `'Paragraph'` |
450
+ | `coar.pageBuilder.props.section.note` | `'Note'` |
451
+ | `coar.pageBuilder.props.section.image` | `'Image'` |
452
+ | `coar.pageBuilder.props.section.link` | `'Link'` |
453
+ | `coar.pageBuilder.props.section.button` | `'Button'` |
454
+ | `coar.pageBuilder.props.section.textInput` | `'Text input'` |
455
+ | `coar.pageBuilder.props.section.passwordInput` | `'Password input'` |
456
+ | `coar.pageBuilder.props.section.numberInput` | `'Number input'` |
457
+ | `coar.pageBuilder.props.section.checkbox` | `'Checkbox'` |
458
+ | `coar.pageBuilder.props.section.switch` | `'Switch'` |
459
+ | `coar.pageBuilder.props.section.select` | `'Select'` |
460
+ | `coar.pageBuilder.props.section.multiSelect` | `'Multi select'` |
461
+ | `coar.pageBuilder.props.section.radioGroup` | `'Radio group'` |
462
+ | `coar.pageBuilder.props.section.dateInput` | `'Date'` |
463
+ | `coar.pageBuilder.props.section.dateTimeInput` | `'Date & time'` |
464
+ | `coar.pageBuilder.props.section.otpInput` | `'OTP input'` |
465
+
466
+ ### Runtime validation messages
467
+
468
+ Shown by `<CoarPageRenderer>` under invalid fields when a validating button is clicked.
469
+
470
+ | Key | Default (English) |
471
+ |-----|-------------------|
472
+ | `coar.pageBuilder.validation.required` | `'This field is required'` |
473
+ | `coar.pageBuilder.validation.minLength` | `'Minimum {n} characters'` |
474
+ | `coar.pageBuilder.validation.maxLength` | `'Maximum {n} characters'` |
475
+ | `coar.pageBuilder.validation.pattern` | `'Invalid format'` |
476
+ | `coar.pageBuilder.validation.matchField` | `'Does not match'` |