@u-krupaveho-kraba/form-editor-schemas 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +2 -0
- package/package.json +2 -2
- package/schemas/editorTheme.js +102 -0
- package/schemas/notification.js +36 -0
- package/schemas/options.js +33 -0
- package/types/index.d.ts +2 -0
- package/types/schemas/campaignItem.d.ts +969 -105
- package/types/schemas/editorTheme.d.ts +72 -0
- package/types/schemas/notification.d.ts +38 -0
- package/types/schemas/options.d.ts +1370 -120
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@u-krupaveho-kraba/form-editor-schemas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Zod schemas for the Topol Form Editor's host-facing init/save contract",
|
|
5
5
|
"author": "Topol.io",
|
|
6
6
|
"license": "ISC",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@u-krupaveho-kraba/form-schemas": "^0.
|
|
27
|
+
"@u-krupaveho-kraba/form-schemas": "^0.5.0",
|
|
28
28
|
"zod": "^4.1.11"
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as z from "zod/mini";
|
|
2
|
+
/**
|
|
3
|
+
* The Host-settable look of the **editor's own UI chrome** -- the accent
|
|
4
|
+
* colour on buttons, active states and the canvas selection outline, the
|
|
5
|
+
* gray ramp every panel and toolbar is built from, the corner radii and the
|
|
6
|
+
* UI font.
|
|
7
|
+
*
|
|
8
|
+
* Not to be confused with `themes` (`./theme.ts`), which is the Brand Kit /
|
|
9
|
+
* Theme Panel library that styles *the form being built* (ADR 0022). The
|
|
10
|
+
* two are unrelated concerns that happen to share the word "theme": this
|
|
11
|
+
* one never reaches a published form, and `themes` never touches the
|
|
12
|
+
* editor's chrome.
|
|
13
|
+
*
|
|
14
|
+
* Deliberately the same shape as email-editor's and LPE's `theme` option
|
|
15
|
+
* (`apps/email-editor/src/schemas/theme/themeSchema.ts`), so a Host
|
|
16
|
+
* embedding more than one editor passes one object to all of them and they
|
|
17
|
+
* match. Applied as CSS custom properties on `<html>` by `setTheme()`
|
|
18
|
+
* (`@topol/utils`) -- no recompile, no store.
|
|
19
|
+
*
|
|
20
|
+
* The one key dropped from email-editor's shape is `canvasColor`, which
|
|
21
|
+
* sets `--c-email-canvas`: that is the paper colour behind an *email*
|
|
22
|
+
* template, a var no form-editor stylesheet reads. Everything else is kept
|
|
23
|
+
* even where form-editor happens not to read the var today, so that this
|
|
24
|
+
* and email-editor's option stay one shape rather than two that drift.
|
|
25
|
+
*/
|
|
26
|
+
export const EditorThemeSchema = z.object({
|
|
27
|
+
/**
|
|
28
|
+
* Which built-in gray ramp and accent to start from before any `colors`
|
|
29
|
+
* override. Defaults to `"dark"`, which is how the editor has always
|
|
30
|
+
* looked; `"light"` is the same ramp inverted.
|
|
31
|
+
*
|
|
32
|
+
* **`"light"` is accepted but not yet audited in the Form Editor**
|
|
33
|
+
* (ticket 196). The mechanism works -- the ramp inverts, the accent
|
|
34
|
+
* swaps -- but the Form Editor's own chrome was authored against the
|
|
35
|
+
* dark ramp only, so some utilities mean "a light surface" and get a
|
|
36
|
+
* dark one. Measured examples: the element-tile label drops to 3.28:1
|
|
37
|
+
* (below WCAG AA), and the band framing the canvas (`bg-gray-100`)
|
|
38
|
+
* inverts from light to dark. Kept in the contract rather than rejected
|
|
39
|
+
* so a Host can pass one theme object to every editor it embeds, per
|
|
40
|
+
* this schema's whole purpose.
|
|
41
|
+
*/
|
|
42
|
+
preset: z.optional(z.enum(["light", "dark"])),
|
|
43
|
+
/**
|
|
44
|
+
* Corner radii for the editor's own controls, as CSS lengths ("4px",
|
|
45
|
+
* "0.5rem"). `small`/`large` also set `--b-radius-small`/`--b-radius-large`
|
|
46
|
+
* for `@topol/ui`'s older components.
|
|
47
|
+
*/
|
|
48
|
+
borderRadius: z.optional(z.object({
|
|
49
|
+
extraSmall: z.optional(z.string()),
|
|
50
|
+
small: z.optional(z.string()),
|
|
51
|
+
large: z.optional(z.string()),
|
|
52
|
+
extraLarge: z.optional(z.string()),
|
|
53
|
+
})),
|
|
54
|
+
/**
|
|
55
|
+
* The editor UI's font. `url` is injected as a stylesheet link (a Google
|
|
56
|
+
* Fonts href, say) and `family` becomes `--font-family-primary`; a
|
|
57
|
+
* `family` with no comma gets a `, sans-serif` fallback appended.
|
|
58
|
+
*/
|
|
59
|
+
font: z.optional(z.object({
|
|
60
|
+
family: z.optional(z.string()),
|
|
61
|
+
url: z.optional(z.string()),
|
|
62
|
+
})),
|
|
63
|
+
/**
|
|
64
|
+
* Individual overrides on top of `preset`. The numeric keys are the gray
|
|
65
|
+
* ramp, `"900"` being the darkest surface under `preset: "dark"`.
|
|
66
|
+
*
|
|
67
|
+
* The primary/accent knob most Hosts want is `active` -- it drives
|
|
68
|
+
* `--c-accent-1`, which is the editor's buttons, active states, focus
|
|
69
|
+
* outlines and the canvas selection outline.
|
|
70
|
+
*/
|
|
71
|
+
colors: z.optional(z.object({
|
|
72
|
+
"900": z.optional(z.string()),
|
|
73
|
+
"800": z.optional(z.string()),
|
|
74
|
+
"700": z.optional(z.string()),
|
|
75
|
+
"600": z.optional(z.string()),
|
|
76
|
+
"500": z.optional(z.string()),
|
|
77
|
+
"400": z.optional(z.string()),
|
|
78
|
+
"300": z.optional(z.string()),
|
|
79
|
+
"200": z.optional(z.string()),
|
|
80
|
+
"100": z.optional(z.string()),
|
|
81
|
+
"50": z.optional(z.string()),
|
|
82
|
+
"10": z.optional(z.string()),
|
|
83
|
+
white: z.optional(z.string()),
|
|
84
|
+
primary: z.optional(z.string()),
|
|
85
|
+
"primary-light": z.optional(z.string()),
|
|
86
|
+
"primary-light-2": z.optional(z.string()),
|
|
87
|
+
"primary-dark": z.optional(z.string()),
|
|
88
|
+
secondary: z.optional(z.string()),
|
|
89
|
+
"secondary-light": z.optional(z.string()),
|
|
90
|
+
"secondary-light-2": z.optional(z.string()),
|
|
91
|
+
error: z.optional(z.string()),
|
|
92
|
+
"error-light": z.optional(z.string()),
|
|
93
|
+
success: z.optional(z.string()),
|
|
94
|
+
"success-light": z.optional(z.string()),
|
|
95
|
+
/** The editor's primary accent -- `--c-accent-1`. */
|
|
96
|
+
active: z.optional(z.string()),
|
|
97
|
+
"active-2": z.optional(z.string()),
|
|
98
|
+
"active-3": z.optional(z.string()),
|
|
99
|
+
"locked-structure": z.optional(z.string()),
|
|
100
|
+
"locked-content": z.optional(z.string()),
|
|
101
|
+
})),
|
|
102
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as z from "zod/mini";
|
|
2
|
+
/**
|
|
3
|
+
* A transient, app-level message -- the Form Editor's notifications, declared
|
|
4
|
+
* here rather than app-locally because a Host can receive them: with
|
|
5
|
+
* `disableAlerts`, every notification is routed to the Host's `onAlert`
|
|
6
|
+
* instead of being rendered in the editor, so this shape crosses the wire.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately identical to the Email Editor's and Landing Page Editor's
|
|
9
|
+
* `INotification`, minus two fields:
|
|
10
|
+
*
|
|
11
|
+
* - `expectSideEffect` is set at four call sites across those two apps and
|
|
12
|
+
* read at none. Carrying a field nothing consumes into a *new* published
|
|
13
|
+
* contract would mean hosts writing against something that does nothing.
|
|
14
|
+
* - `extarnalUse` (sic) means "render in-editor even when alerts are
|
|
15
|
+
* disabled". It has real consumers there -- init/auth failures a Host may
|
|
16
|
+
* not be listening for yet -- but none here, and it would arrive with its
|
|
17
|
+
* typo preserved or with a silent rename. When the Form Editor grows a
|
|
18
|
+
* notification that must survive `disableAlerts`, add it then, spelled
|
|
19
|
+
* correctly.
|
|
20
|
+
*/
|
|
21
|
+
export const NotificationTypeSchema = z.enum(["info", "success", "error"]);
|
|
22
|
+
export const EditorNotificationSchema = z.object({
|
|
23
|
+
/** Optional bold first line. Rendered above `text` when present. */
|
|
24
|
+
title: z.optional(z.string()),
|
|
25
|
+
/** The message itself, already translated -- callers own i18n. */
|
|
26
|
+
text: z.string(),
|
|
27
|
+
type: NotificationTypeSchema,
|
|
28
|
+
/** Suppresses the auto-dismiss timer; the notification stays until closed. */
|
|
29
|
+
persistent: z.optional(z.boolean()),
|
|
30
|
+
/**
|
|
31
|
+
* Assigned by the editor when the notification is created, not by the
|
|
32
|
+
* caller -- optional here because it only exists once a notification is
|
|
33
|
+
* live. A Host receiving one through `onAlert` always sees it set.
|
|
34
|
+
*/
|
|
35
|
+
id: z.optional(z.string()),
|
|
36
|
+
});
|
package/schemas/options.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as z from "zod/mini";
|
|
2
2
|
import { FormThemeSchema, InputFieldSchema, PreferenceSchema, } from "@u-krupaveho-kraba/form-schemas";
|
|
3
3
|
import { CampaignItemSchema, } from "./campaignItem.js";
|
|
4
|
+
import { EditorThemeSchema } from "./editorTheme.js";
|
|
4
5
|
import { FileManagerOptionsSchema } from "./fileManager.js";
|
|
5
6
|
import { ThemeGroupSchema, } from "./theme.js";
|
|
6
7
|
/**
|
|
@@ -61,6 +62,17 @@ export const EditorCallbacksSchema = z.object({
|
|
|
61
62
|
onCreatePreference: z.optional(callback()),
|
|
62
63
|
/** Fired when the editor fails to initialize, or when a payload the Host sent fails validation (ADR 0029 decision 3). */
|
|
63
64
|
onError: z.optional(callback()),
|
|
65
|
+
/**
|
|
66
|
+
* Receives every notification the editor would otherwise have rendered
|
|
67
|
+
* itself, so a Host can surface them in its own UI -- same `{ notification }`
|
|
68
|
+
* argument shape LPE's `onAlert` uses, so a Host already embedding that
|
|
69
|
+
* editor can reuse its handler.
|
|
70
|
+
*
|
|
71
|
+
* Only called when `disableAlerts` is on. Unlike every other optional
|
|
72
|
+
* callback here, its *presence* is not the affordance: the editor keeps
|
|
73
|
+
* rendering its own notifications until a Host explicitly asks it to stop.
|
|
74
|
+
*/
|
|
75
|
+
onAlert: z.optional(callback()),
|
|
64
76
|
/** Fired when the user clicks the WindowBar's close button (requires `"close"` in `windowBar`). The Host is responsible for tearing down/hiding the editor -- the child does not attempt its own teardown. */
|
|
65
77
|
onEditorClose: z.optional(callback()),
|
|
66
78
|
/**
|
|
@@ -164,6 +176,17 @@ export const TopolFormEditorOptionsSchema = z
|
|
|
164
176
|
language: z.optional(EditorLanguageSchema),
|
|
165
177
|
/** Per-key overrides for editor UI strings, keyed by dot-path (e.g. "controls.autosaves.title"). Applied once at bootstrap, merged into whichever locale ends up active. */
|
|
166
178
|
textOverride: z.optional(z.record(z.string(), z.string())),
|
|
179
|
+
/**
|
|
180
|
+
* The look of the editor's own UI chrome -- accent colour, gray ramp,
|
|
181
|
+
* corner radii, UI font. Same option name and shape as email-editor's
|
|
182
|
+
* and LPE's `theme`, so a Host embedding several editors passes one
|
|
183
|
+
* object to all of them. Omit it and the editor looks exactly as it
|
|
184
|
+
* always has (`preset: "dark"`).
|
|
185
|
+
*
|
|
186
|
+
* Note the neighbour below: `theme` is the *editor*, `themes` is the
|
|
187
|
+
* *form being built*. They are unrelated (see `./editorTheme.ts`).
|
|
188
|
+
*/
|
|
189
|
+
theme: z.optional(EditorThemeSchema),
|
|
167
190
|
/** Accepts the legacy flat shape for backward compatibility; a Host App is encouraged to move to `ThemeGroup[]` to supply locked/Brand Kit themes. */
|
|
168
191
|
themes: z.optional(z.union([z.array(FormThemeSchema), z.array(ThemeGroupSchema)])),
|
|
169
192
|
previewUrl: z.optional(z.string()),
|
|
@@ -214,5 +237,15 @@ export const TopolFormEditorOptionsSchema = z
|
|
|
214
237
|
])),
|
|
215
238
|
comments: z.optional(CommentsConfigSchema),
|
|
216
239
|
autosaves: z.optional(AutosaveConfigSchema),
|
|
240
|
+
/**
|
|
241
|
+
* Stops the editor rendering its own notifications and routes them to
|
|
242
|
+
* `callbacks.onAlert` instead, for a Host that wants them in its own UI
|
|
243
|
+
* (same option name and meaning as LPE's `disableAlerts`).
|
|
244
|
+
*
|
|
245
|
+
* Honoured only when `onAlert` is actually wired up -- a Host that sets
|
|
246
|
+
* this without it would otherwise silence the editor into a black hole,
|
|
247
|
+
* which is strictly worse than the notifications it asked to be rid of.
|
|
248
|
+
*/
|
|
249
|
+
disableAlerts: z.optional(z.boolean()),
|
|
217
250
|
})
|
|
218
251
|
.check(z.refine(onlyOneOfItemAndItems, ITEM_AND_ITEMS_EXCLUSIVE_MESSAGE));
|
package/types/index.d.ts
CHANGED