@golemui/gui-mcp 1.4.0 → 1.5.0-rc.1

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.
@@ -1,94 +1,360 @@
1
1
  import Ajv2020 from "ajv/dist/2020.js";
2
2
  import addFormats from "ajv-formats";
3
- const $schema$J = "https://json-schema.org/draft/2020-12/schema";
4
- const $id$J = "https://golemui.com/schemas/gui/core/common.schema.json";
3
+ function lintReactiveExpressions(formDefinition) {
4
+ const findings = [];
5
+ walk$2(formDefinition, "", findings, false, false);
6
+ return findings;
7
+ }
8
+ function checkReactiveExpression(expression, path = "", options = {}) {
9
+ const out = [];
10
+ checkExpression(expression, path, out, options.inRepeaterTemplate === true);
11
+ return out;
12
+ }
13
+ function walk$2(node, path, out, inTemplate, propsOfRepeater) {
14
+ if (node === null || typeof node !== "object") return;
15
+ if (Array.isArray(node)) {
16
+ node.forEach((item, i) => walk$2(item, `${path}/${i}`, out, inTemplate, false));
17
+ return;
18
+ }
19
+ const obj = node;
20
+ for (const key of ["include", "exclude"]) {
21
+ const child = obj[key];
22
+ if (child && typeof child === "object" && "when" in child) {
23
+ const expr = child.when;
24
+ if (typeof expr === "string") {
25
+ checkExpression(expr, `${path}/${key}/when`, out, inTemplate);
26
+ }
27
+ }
28
+ }
29
+ if (path === "" && obj["states"] && typeof obj["states"] === "object") {
30
+ for (const [name, expr] of Object.entries(obj["states"])) {
31
+ if (typeof expr === "string") {
32
+ checkExpression(expr, `/states/${name}`, out, false);
33
+ }
34
+ }
35
+ }
36
+ for (const [k, v] of Object.entries(obj)) {
37
+ if (v && typeof v === "object" && !Array.isArray(v) && "when" in v) {
38
+ const expr = v.when;
39
+ if (typeof expr === "string" && k !== "include" && k !== "exclude") {
40
+ checkExpression(expr, `${path}/${k}/when`, out, inTemplate);
41
+ }
42
+ }
43
+ if (typeof v === "object" && v !== null) {
44
+ const childInTemplate = inTemplate || propsOfRepeater && k === "template";
45
+ walk$2(v, `${path}/${k}`, out, childInTemplate, obj["type"] === "repeater" && k === "props");
46
+ }
47
+ }
48
+ }
49
+ function checkExpression(expr, path, out, inTemplate) {
50
+ const trimmed = expr.trim();
51
+ if (!trimmed) {
52
+ out.push({ path, expression: expr, message: "Expression is empty." });
53
+ return;
54
+ }
55
+ const stack = [];
56
+ const pairs = { ")": "(", "]": "[", "}": "{" };
57
+ for (const ch of trimmed) {
58
+ if ("([{".includes(ch)) stack.push(ch);
59
+ else if (")]}".includes(ch)) {
60
+ if (stack.pop() !== pairs[ch]) {
61
+ out.push({
62
+ path,
63
+ expression: expr,
64
+ message: `Unbalanced \`${ch}\` in reactive expression.`
65
+ });
66
+ return;
67
+ }
68
+ }
69
+ }
70
+ if (stack.length) {
71
+ out.push({
72
+ path,
73
+ expression: expr,
74
+ message: `Unclosed \`${stack[stack.length - 1]}\` in reactive expression.`
75
+ });
76
+ return;
77
+ }
78
+ const referencesItemScope = /\$item\b|\$index\b/.test(trimmed);
79
+ const hasGlobalRoot = /\$form\b|\$meta\b|\$formIsInvalid\b|\$fn\b/.test(trimmed);
80
+ if (referencesItemScope && !inTemplate) {
81
+ out.push({
82
+ path,
83
+ expression: expr,
84
+ message: "Expression references `$item` or `$index`, which are only available inside a repeater `props.template`.",
85
+ suggestion: "Move the widget inside the repeater template, or read the data through `$form` (e.g. `$form.lineItems?.[0]?.quantity`)."
86
+ });
87
+ } else if (!hasGlobalRoot && !(inTemplate && referencesItemScope)) {
88
+ out.push({
89
+ path,
90
+ expression: expr,
91
+ message: "Expression does not reference `$form`, `$meta`, `$formIsInvalid`, or `$fn`.",
92
+ suggestion: "GolemUI expressions read form data via `$form.fieldName`, form metadata via `$meta.key`, or the built-in `$formIsInvalid` boolean. Host-provided pure functions are callable via `$fn.functionName(...)` when the host passes a `functions` map in the form init config. Inside a repeater `props.template` the current item is available via `$item` and its position via `$index`. Did you forget the prefix?"
93
+ });
94
+ }
95
+ if (/(?<![=!<>])=(?![=>])/.test(trimmed)) {
96
+ out.push({
97
+ path,
98
+ expression: expr,
99
+ message: "Expression contains a single `=` (assignment). Reactive expressions are read-only.",
100
+ suggestion: "Use `===` for equality comparison."
101
+ });
102
+ }
103
+ if (/(?<![&])&(?![&])/.test(trimmed) || /(?<![|])\|(?![|])/.test(trimmed)) {
104
+ out.push({
105
+ path,
106
+ expression: expr,
107
+ message: "Expression contains a single `&` or `|` (bitwise).",
108
+ suggestion: "Use `&&` for logical AND, `||` for logical OR."
109
+ });
110
+ }
111
+ if (/(?<![=!])==(?!=)/.test(trimmed) || /(?<![!])!=(?!=)/.test(trimmed)) {
112
+ out.push({
113
+ path,
114
+ expression: expr,
115
+ message: "Expression uses loose equality (`==` or `!=`).",
116
+ suggestion: "Use strict equality `===` / `!==` to avoid type coercion (e.g. `$form.x !== undefined` rather than `$form.x != null`)."
117
+ });
118
+ }
119
+ if (/(?<![=!])!\s*\$(?:form|meta|item)\b/.test(trimmed)) {
120
+ out.push({
121
+ path,
122
+ expression: expr,
123
+ message: "Expression negates a `$form`/`$meta`/`$item` reference (relies on truthy/falsy coercion).",
124
+ suggestion: 'Form data values can be `undefined`. Pick the case you actually mean and write it explicitly — `$form.x === undefined`, `$form.x === null`, `$form.x === 0`, `$form.x === ""` — instead of `!$form.x`.'
125
+ });
126
+ }
127
+ const refChainRe = /\$(?:form|meta|item)\b((?:\.[\w?]+)*)/g;
128
+ let chainFlagged = false;
129
+ let chainMatch;
130
+ while ((chainMatch = refChainRe.exec(trimmed)) !== null) {
131
+ const chain = chainMatch[1];
132
+ if (!chain) continue;
133
+ const segments = chain.split(".").filter(Boolean);
134
+ let unsafe = false;
135
+ for (let i = 0; i < segments.length - 1; i++) {
136
+ const segment = segments[i];
137
+ if (!segment || !segment.endsWith("?")) {
138
+ unsafe = true;
139
+ break;
140
+ }
141
+ }
142
+ if (unsafe && !chainFlagged) {
143
+ out.push({
144
+ path,
145
+ expression: expr,
146
+ message: "Expression chains nested property access without optional chaining (e.g. `$form.user.name`).",
147
+ suggestion: "Treat every nested property as possibly `undefined`. Use `?.` between segments: `$form.user?.name` instead of `$form.user.name`. The runtime throws if `$form.user` is undefined."
148
+ });
149
+ chainFlagged = true;
150
+ }
151
+ }
152
+ const refOnly = /^\$(?:form|meta|item)(?:\.[\w?]+)*$/;
153
+ const refBeforeBool = /\$(?:form|meta|item)(?:\.[\w?]+)*\s*(?:&&|\|\||\?(?![.?]))/;
154
+ const refAfterBool = /(?:&&|\|\|)\s*\$(?:form|meta|item)(?:\.[\w?]+)*\s*$/;
155
+ if (refOnly.test(trimmed) || refBeforeBool.test(trimmed) || refAfterBool.test(trimmed)) {
156
+ out.push({
157
+ path,
158
+ expression: expr,
159
+ message: "Expression uses `$form`/`$meta` directly as a boolean (relies on truthy/falsy coercion).",
160
+ suggestion: 'Form data values can be `undefined`. Compare explicitly: `$form.x !== undefined`, `$form.x === "value"`, `$form.items?.length > 0`. For default values use nullish coalescing: `$form.x ?? defaultValue`.'
161
+ });
162
+ }
163
+ const refForCmpRe = /\$(?:form|meta|item)(?:\.[\w?]+)+/g;
164
+ let r5Flagged = false;
165
+ let cmpMatch;
166
+ while ((cmpMatch = refForCmpRe.exec(trimmed)) !== null) {
167
+ const start = cmpMatch.index;
168
+ const end = start + cmpMatch[0].length;
169
+ const before = trimmed.slice(0, start).trimEnd();
170
+ const after = trimmed.slice(end).trimStart();
171
+ const opAfter = /^(?:<=?|>=?|[+\-*/%])(?!=)/.test(after);
172
+ const opBefore = /(?<![=!])[<>+\-*/%]$/.test(before);
173
+ if (!(opAfter || opBefore)) continue;
174
+ if (/&&|\|\|/.test(before)) continue;
175
+ if (!r5Flagged) {
176
+ out.push({
177
+ path,
178
+ expression: expr,
179
+ message: "Expression applies a comparison or arithmetic operator to a `$form`/`$meta` reference whose leaf may be `undefined`.",
180
+ suggestion: "Guard the value first: `$form.x !== undefined && $form.x > 180`. Or default it: `($form.x ?? 0) > 180`. Strict equality (`$form.x === 180`) is also safe since it evaluates to `false` when undefined."
181
+ });
182
+ r5Flagged = true;
183
+ }
184
+ }
185
+ }
186
+ function checkBooleanValidatorRules(validator, path) {
187
+ const findings = [];
188
+ const requiredIsTrue = validator.required === true;
189
+ const constPresent = "const" in validator && validator.const !== void 0;
190
+ if (requiredIsTrue && !constPresent) {
191
+ findings.push({
192
+ path,
193
+ message: "Boolean validator has `required: true` but no `const` — this does NOT force the checkbox to be checked: `false` is a valid boolean and passes; `required` only rejects a missing value (`undefined`/`null`).",
194
+ suggestion: "If this checkbox must be checked (e.g. terms acceptance), add `const: true` and set `messages.invalid` and `messages.const` to the same user-facing text. If a false value is genuinely acceptable, ignore this warning."
195
+ });
196
+ }
197
+ if (constPresent && !requiredIsTrue) {
198
+ findings.push({
199
+ path,
200
+ message: "Boolean validator has `const` but no `required: true` — the pristine value passes: a never-touched checkbox holds `undefined`, and non-required validators skip validation entirely for `undefined`.",
201
+ suggestion: "Add `required: true` so the untouched state fails too, and set `messages.invalid` and `messages.const` to the same user-facing text."
202
+ });
203
+ }
204
+ return findings;
205
+ }
206
+ function lintBooleanValidators(formDefinition) {
207
+ const findings = [];
208
+ walk$1(formDefinition, "", findings);
209
+ return findings;
210
+ }
211
+ function walk$1(node, path, out) {
212
+ if (node === null || typeof node !== "object") return;
213
+ if (Array.isArray(node)) {
214
+ node.forEach((item, i) => walk$1(item, `${path}/${i}`, out));
215
+ return;
216
+ }
217
+ const obj = node;
218
+ for (const [key, value] of Object.entries(obj)) {
219
+ if ((key === "validator" || key.startsWith("validator.")) && value !== null && typeof value === "object" && !Array.isArray(value) && value["type"] === "boolean") {
220
+ out.push(...checkBooleanValidatorRules(value, `${path}/${key}`));
221
+ }
222
+ walk$1(value, `${path}/${key}`, out);
223
+ }
224
+ }
225
+ const $schema$L = "https://json-schema.org/draft/2020-12/schema";
226
+ const $id$L = "https://golemui.com/schemas/gui/core/common.schema.json";
5
227
  const $comment$5 = "Owned by @golemui/schemas (libs/schemas/src/lib/core/). Implementation trees contain a generated vendored copy, identical apart from an `$id` rebased onto the implementation's own tree. Edit the source file, then run `npm run generate:schemas`.";
6
- const title$J = "Golem Common Definitions";
7
- const $defs$H = { "reactiveExpression": { "type": "string", "description": "A reactive expression string. Use `$form` to access form data e.g. `$form.termsAccepted === true`" }, "dotPath": { "type": "string", "description": "A dot-separated path to a property in the form data" }, "uid": { "type": "string", "description": "Unique identifier for the widget" }, "chunkRef": { "type": "object", "description": "A reference to an external chunk file whose widget array will be inlined at this position in the form", "properties": { "$ref": { "type": "string", "description": "Relative path to a JSON chunk file" } }, "required": ["$ref"], "additionalProperties": false }, "localizable": { "description": "A value that can be a plain string or an i18n key object. Use a plain string for static text, or `{key, default, params}` to reference a translation key.", "oneOf": [{ "type": "string" }, { "type": "object", "properties": { "key": { "type": "string", "description": "The i18n translation key" }, "default": { "type": "string", "description": "Fallback text shown when the translation key is not found" }, "params": { "type": "object", "description": "Interpolation parameters passed to the translation function" } }, "required": ["key"], "additionalProperties": false }] }, "include": { "description": "Show this widget only in certain form states (`{in: [stateNames]}`) or when a reactive expression is true (`{when: expr}`). If omitted the widget is always shown.", "oneOf": [{ "type": "object", "properties": { "in": { "type": "array", "items": { "type": "string" }, "description": "List of state names (defined in the form `states` map) in which this widget should be visible" } }, "required": ["in"], "additionalProperties": false }, { "type": "object", "properties": { "when": { "$ref": "#/$defs/reactiveExpression" } }, "required": ["when"], "additionalProperties": false }] }, "exclude": { "description": "Hide this widget in certain form states (`{from: [stateNames]}`) or when a reactive expression is true (`{when: expr}`). If omitted the widget is never hidden.", "oneOf": [{ "type": "object", "properties": { "from": { "type": "array", "items": { "type": "string" }, "description": "List of state names (defined in the form `states` map) in which this widget should be hidden" } }, "required": ["from"], "additionalProperties": false }, { "type": "object", "properties": { "when": { "$ref": "#/$defs/reactiveExpression" } }, "required": ["when"], "additionalProperties": false }] }, "boolOrWhen": { "description": "A static boolean or a conditional `{when: reactiveExpression}` object evaluated at runtime. Use `{when: '$form.someField === true'}` for dynamic behavior.", "oneOf": [{ "type": "boolean" }, { "type": "object", "properties": { "when": { "$ref": "#/$defs/reactiveExpression" } }, "required": ["when"], "additionalProperties": false }] }, "on": { "type": "object", "description": 'Event handlers for this widget. Values are action names dispatched to the form\'s event bus. Each key also accepts a state-suffixed variant (`"click.<stateName>"`) that overrides the base handler when the named state is active.', "properties": { "load": { "type": "string", "description": "Action dispatched when the widget is first mounted" }, "click": { "type": "string", "description": "Action dispatched when the user clicks the widget" }, "change": { "type": "string", "description": "Action dispatched when the widget value changes" }, "filter": { "type": "string", "description": "Action dispatched on search/filter input, typically used with async data sources" }, "blur": { "type": "string", "description": "Action dispatched when the widget loses focus" } }, "patternProperties": { "^load\\.[^.]+$": { "type": "string", "description": 'State-suffixed load handler: used instead of `load` when the named state is active (e.g. `"load.myState"`)' }, "^click\\.[^.]+$": { "type": "string", "description": 'State-suffixed click handler: used instead of `click` when the named state is active (e.g. `"click.myState"`)' }, "^change\\.[^.]+$": { "type": "string", "description": 'State-suffixed change handler: used instead of `change` when the named state is active (e.g. `"change.myState"`)' }, "^filter\\.[^.]+$": { "type": "string", "description": 'State-suffixed filter handler: used instead of `filter` when the named state is active (e.g. `"filter.myState"`)' }, "^blur\\.[^.]+$": { "type": "string", "description": 'State-suffixed blur handler: used instead of `blur` when the named state is active (e.g. `"blur.myState"`)' } }, "additionalProperties": false }, "baseWidget": { "type": "object", "description": 'Base properties shared by all widgets. Root-level props that support state-suffixing (e.g. `"label.myState"`) are: `label`, `disabled`, `readonly`, `validator`, `size`. Any key inside `props` can also be suffixed. State names must be declared in the form `states` map.', "properties": { "$schema": { "type": "string" }, "uid": { "$ref": "#/$defs/uid" }, "type": { "type": "string" }, "size": { "type": "number", "description": "Relative width of the widget inside its layout, from 1 to 12, where 12 is the full width. Defaults to full width when omitted. gui maps it to a 12-column grid, other widget sets may map it to a flex ratio.", "minimum": 1, "maximum": 12 }, "include": { "$ref": "#/$defs/include" }, "exclude": { "$ref": "#/$defs/exclude" } }, "required": ["type"] } };
228
+ const title$L = "Golem Common Definitions";
229
+ const $defs$J = { "reactiveExpression": { "type": "string", "description": "A reactive expression string. Use `$form` to access form data e.g. `$form.termsAccepted === true`" }, "dotPath": { "type": "string", "description": "A dot-separated path to a property in the form data" }, "uid": { "type": "string", "description": "Unique identifier for the widget" }, "chunkRef": { "type": "object", "description": "A reference to an external chunk file whose widget array will be inlined at this position in the form", "properties": { "$ref": { "type": "string", "description": "Relative path to a JSON chunk file" } }, "required": ["$ref"], "additionalProperties": false }, "localizable": { "description": "A value that can be a plain string or an i18n key object. Use a plain string for static text, or `{key, default, params}` to reference a translation key.", "oneOf": [{ "type": "string" }, { "type": "object", "properties": { "key": { "type": "string", "description": "The i18n translation key" }, "default": { "type": "string", "description": "Fallback text shown when the translation key is not found" }, "params": { "type": "object", "description": "Interpolation parameters passed to the translation function" } }, "required": ["key"], "additionalProperties": false }] }, "include": { "description": "Show this widget only in certain form states (`{in: [stateNames]}`) or when a reactive expression is true (`{when: expr}`). If omitted the widget is always shown.", "oneOf": [{ "type": "object", "properties": { "in": { "type": "array", "items": { "type": "string" }, "description": "List of state names (defined in the form `states` map) in which this widget should be visible" } }, "required": ["in"], "additionalProperties": false }, { "type": "object", "properties": { "when": { "$ref": "#/$defs/reactiveExpression" } }, "required": ["when"], "additionalProperties": false }] }, "exclude": { "description": "Hide this widget in certain form states (`{from: [stateNames]}`) or when a reactive expression is true (`{when: expr}`). If omitted the widget is never hidden.", "oneOf": [{ "type": "object", "properties": { "from": { "type": "array", "items": { "type": "string" }, "description": "List of state names (defined in the form `states` map) in which this widget should be hidden" } }, "required": ["from"], "additionalProperties": false }, { "type": "object", "properties": { "when": { "$ref": "#/$defs/reactiveExpression" } }, "required": ["when"], "additionalProperties": false }] }, "boolOrWhen": { "description": "A static boolean or a conditional `{when: reactiveExpression}` object evaluated at runtime. Use `{when: '$form.someField === true'}` for dynamic behavior.", "oneOf": [{ "type": "boolean" }, { "type": "object", "properties": { "when": { "$ref": "#/$defs/reactiveExpression" } }, "required": ["when"], "additionalProperties": false }] }, "on": { "type": "object", "description": 'Event handlers for this widget. Values are action names dispatched to the form\'s event bus. Each key also accepts a state-suffixed variant (`"click.<stateName>"`) that overrides the base handler when the named state is active.', "properties": { "load": { "type": "string", "description": "Action dispatched when the widget is first mounted" }, "click": { "type": "string", "description": "Action dispatched when the user clicks the widget" }, "change": { "type": "string", "description": "Action dispatched when the widget value changes" }, "filter": { "type": "string", "description": "Action dispatched on search/filter input, typically used with async data sources" }, "blur": { "type": "string", "description": "Action dispatched when the widget loses focus" } }, "patternProperties": { "^load\\.[^.]+$": { "type": "string", "description": 'State-suffixed load handler: used instead of `load` when the named state is active (e.g. `"load.myState"`)' }, "^click\\.[^.]+$": { "type": "string", "description": 'State-suffixed click handler: used instead of `click` when the named state is active (e.g. `"click.myState"`)' }, "^change\\.[^.]+$": { "type": "string", "description": 'State-suffixed change handler: used instead of `change` when the named state is active (e.g. `"change.myState"`)' }, "^filter\\.[^.]+$": { "type": "string", "description": 'State-suffixed filter handler: used instead of `filter` when the named state is active (e.g. `"filter.myState"`)' }, "^blur\\.[^.]+$": { "type": "string", "description": 'State-suffixed blur handler: used instead of `blur` when the named state is active (e.g. `"blur.myState"`)' } }, "additionalProperties": false }, "baseWidget": { "type": "object", "description": 'Base properties shared by all widgets. Root-level props that support state-suffixing (e.g. `"label.myState"`) are: `label`, `disabled`, `readonly`, `validator`, `size`. Any key inside `props` can also be suffixed. State names must be declared in the form `states` map.', "properties": { "$schema": { "type": "string" }, "uid": { "$ref": "#/$defs/uid" }, "type": { "type": "string" }, "size": { "type": "number", "description": "Relative width of the widget inside its layout, from 1 to 12, where 12 is the full width. Defaults to full width when omitted. gui maps it to a 12-column grid, other widget sets may map it to a flex ratio.", "minimum": 1, "maximum": 12 }, "include": { "$ref": "#/$defs/include" }, "exclude": { "$ref": "#/$defs/exclude" } }, "required": ["type"] } };
8
230
  const commonSchemaJson = {
9
- $schema: $schema$J,
10
- $id: $id$J,
231
+ $schema: $schema$L,
232
+ $id: $id$L,
11
233
  $comment: $comment$5,
12
- title: title$J,
13
- $defs: $defs$H
234
+ title: title$L,
235
+ $defs: $defs$J
14
236
  };
15
- const $schema$I = "https://json-schema.org/draft/2020-12/schema";
16
- const $id$I = "https://golemui.com/schemas/gui/ranges.schema.json";
237
+ const $schema$K = "https://json-schema.org/draft/2020-12/schema";
238
+ const $id$K = "https://golemui.com/schemas/gui/ranges.schema.json";
17
239
  const $comment$4 = "Owned by @golemui/gui-schemas (libs/gui/schemas/src/lib/). Handwritten, edit directly. Shared date and time range definitions used by the gui component schemas.";
18
- const title$I = "GolemUI Range Definitions";
19
- const $defs$G = { "dateRange": { "type": "object", "description": "A single date range. Used as the value of the range calendar and range date widgets, and by calendar/date-picker widgets to mark days as disabled.", "properties": { "start": { "type": "string", "description": "ISO-8601 date string for the start of the range (inclusive)" }, "end": { "type": "string", "description": "ISO-8601 date string for the end of the range (inclusive). Omit to cover a single day." } }, "required": ["start"], "additionalProperties": false }, "dateTimeRange": { "type": "object", "description": "A single date-time range (two ISO date-times). Used as the value of the range date-time widgets, and by those widgets for disabled instant spans.", "properties": { "start": { "type": "string", "description": "ISO-8601 date-time string for the start of the range (inclusive)" }, "end": { "type": "string", "description": "ISO-8601 date-time string for the end of the range (inclusive). Omit to cover the single instant at start." } }, "required": ["start"], "additionalProperties": false }, "isoTime": { "type": "string", "description": "A time of day as HH:MM or HH:MM:SS on a 24-hour clock", "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$" }, "timeRange": { "type": "object", "description": "A single time-of-day range. Used as the value of the range time widgets, and by time-picker widgets to mark times as disabled.", "properties": { "start": { "$ref": "#/$defs/isoTime" }, "end": { "$ref": "#/$defs/isoTime" } }, "required": ["start", "end"], "additionalProperties": false }, "scopedTimeRange": { "type": "object", "description": "A time-of-day range that optionally applies only on one date or on given weekdays. Used by date-time widgets to mark times as disabled.", "properties": { "start": { "$ref": "#/$defs/isoTime" }, "end": { "$ref": "#/$defs/isoTime" }, "date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "ISO date: the range only applies on that date" }, "weekdays": { "type": "array", "items": { "type": "integer", "minimum": 0, "maximum": 6 }, "description": "Date.prototype.getDay() numbering: 0=Sunday to 6=Saturday" } }, "required": ["start", "end"], "additionalProperties": false } };
240
+ const title$K = "GolemUI Range Definitions";
241
+ const $defs$I = { "dateRange": { "type": "object", "description": "A single date range. Used as the value of the range calendar and range date widgets, and by calendar/date-picker widgets to mark days as disabled.", "properties": { "start": { "type": "string", "description": "ISO-8601 date string for the start of the range (inclusive)" }, "end": { "type": "string", "description": "ISO-8601 date string for the end of the range (inclusive). Omit to cover a single day." } }, "required": ["start"], "additionalProperties": false }, "dateTimeRange": { "type": "object", "description": "A single date-time range (two ISO date-times). Used as the value of the range date-time widgets, and by those widgets for disabled instant spans.", "properties": { "start": { "type": "string", "description": "ISO-8601 date-time string for the start of the range (inclusive)" }, "end": { "type": "string", "description": "ISO-8601 date-time string for the end of the range (inclusive). Omit to cover the single instant at start." } }, "required": ["start"], "additionalProperties": false }, "isoTime": { "type": "string", "description": "A time of day as HH:MM or HH:MM:SS on a 24-hour clock", "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$" }, "timeRange": { "type": "object", "description": "A single time-of-day range. Used as the value of the range time widgets, and by time-picker widgets to mark times as disabled.", "properties": { "start": { "$ref": "#/$defs/isoTime" }, "end": { "$ref": "#/$defs/isoTime" } }, "required": ["start", "end"], "additionalProperties": false }, "scopedTimeRange": { "type": "object", "description": "A time-of-day range that optionally applies only on one date or on given weekdays. Used by date-time widgets to mark times as disabled.", "properties": { "start": { "$ref": "#/$defs/isoTime" }, "end": { "$ref": "#/$defs/isoTime" }, "date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "description": "ISO date: the range only applies on that date" }, "weekdays": { "type": "array", "items": { "type": "integer", "minimum": 0, "maximum": 6 }, "description": "Date.prototype.getDay() numbering: 0=Sunday to 6=Saturday" } }, "required": ["start", "end"], "additionalProperties": false } };
20
242
  const rangesSchemaJson = {
21
- $schema: $schema$I,
22
- $id: $id$I,
243
+ $schema: $schema$K,
244
+ $id: $id$K,
23
245
  $comment: $comment$4,
24
- title: title$I,
25
- $defs: $defs$G
246
+ title: title$K,
247
+ $defs: $defs$I
26
248
  };
27
- const $schema$H = "https://json-schema.org/draft/2020-12/schema";
28
- const $id$H = "https://golemui.com/schemas/gui/validators.schema.json";
249
+ const $schema$J = "https://json-schema.org/draft/2020-12/schema";
250
+ const $id$J = "https://golemui.com/schemas/gui/validators.schema.json";
29
251
  const $comment$3 = "Owned by @golemui/gui-schemas (libs/gui/schemas/src/lib/). Handwritten, edit directly. Each implementation publishes its own validators schema exposing the #/$defs/validator entry pointer.";
30
- const title$H = "GolemUI Validator Definitions";
31
- const $defs$F = { "localizable": { "$ref": "./core/common.schema.json#/$defs/localizable" }, "stringValidator": { "type": "object", "properties": { "type": { "const": "string" }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the value is empty or absent" }, "minLength": { "type": "number", "description": "Minimum number of characters the string must contain" }, "maxLength": { "type": "number", "description": "Maximum number of characters the string may contain" }, "pattern": { "type": "string", "description": "A regular expression pattern the value must match" }, "format": { "type": "string", "description": "A named format the string must conform to (e.g. `email`, `url`, `date`, `uuid`)", "enum": ["email", "hostname", "ipv4", "ipv6", "url", "uuid", "date", "time", "date-time", "duration"] }, "const": { "description": "The string must equal exactly this value" }, "enum": { "type": "array", "description": "The string must be one of these allowed values" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value fails general type validation" }, "required": { "$ref": "#/$defs/localizable", "description": "Shown when a required field is empty" }, "minLength": { "$ref": "#/$defs/localizable", "description": "Shown when the value is shorter than `minLength`" }, "maxLength": { "$ref": "#/$defs/localizable", "description": "Shown when the value is longer than `maxLength`" }, "pattern": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not match the `pattern` regex" }, "format": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not conform to the specified `format`" }, "enum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not in the `enum` list" }, "const": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not equal `const`" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "numberValidator": { "type": "object", "properties": { "type": { "type": "string", "enum": ["number", "integer"] }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the value is absent" }, "minimum": { "type": "number", "description": "The value must be greater than or equal to this number (inclusive)" }, "maximum": { "type": "number", "description": "The value must be less than or equal to this number (inclusive)" }, "exclusiveMinimum": { "type": "number", "description": "The value must be strictly greater than this number (exclusive)" }, "exclusiveMaximum": { "type": "number", "description": "The value must be strictly less than this number (exclusive)" }, "multipleOf": { "type": "number", "description": "The value must be a multiple of this number" }, "const": { "description": "The value must equal exactly this number" }, "enum": { "type": "array", "description": "The value must be one of these allowed numbers" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value fails general type validation" }, "minimum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is below `minimum`" }, "maximum": { "$ref": "#/$defs/localizable", "description": "Shown when the value exceeds `maximum`" }, "exclusiveMinimum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not strictly above `exclusiveMinimum`" }, "exclusiveMaximum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not strictly below `exclusiveMaximum`" }, "multipleOf": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not a multiple of `multipleOf`" }, "enum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not in the `enum` list" }, "const": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not equal `const`" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "booleanValidator": { "type": "object", "properties": { "type": { "const": "boolean" }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the value is absent or false (e.g. an unchecked required checkbox)" }, "const": { "description": "The value must equal exactly this boolean (e.g. `true` to require acceptance)" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value fails general type validation" }, "const": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not equal `const`" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "arrayValidator": { "type": "object", "properties": { "type": { "const": "array" }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the array is empty or absent" }, "minItems": { "type": "number", "description": "The array must contain at least this many items" }, "maxItems": { "type": "number", "description": "The array must contain no more than this many items" }, "uniqueItems": { "type": "boolean", "description": "When true, all items in the array must be distinct values" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value fails general type validation" }, "required": { "$ref": "#/$defs/localizable", "description": "Shown when a required array is empty or absent" }, "minItems": { "$ref": "#/$defs/localizable", "description": "Shown when the array has fewer items than `minItems`" }, "maxItems": { "$ref": "#/$defs/localizable", "description": "Shown when the array has more items than `maxItems`" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "customValidator": { "type": "object", "description": "A custom validator that delegates validation to application code. The registered validator function receives these constraint keys and must return a Standard Schema V1-compliant schema object (https://standardschema.dev). Add arbitrary constraint keys alongside `type` - they are passed as-is to the registered validator function.", "properties": { "type": { "const": "custom" }, "required": { "type": "boolean", "description": "Makes the field mandatory - evaluation is still delegated to the custom validator" } }, "required": ["type"], "additionalProperties": true }, "validator": { "description": "Validation rules for this field. The `type` discriminant selects the validator: `string`, `number`, `integer`, `boolean`, `array`, or `custom`.", "oneOf": [{ "$ref": "#/$defs/stringValidator" }, { "$ref": "#/$defs/numberValidator" }, { "$ref": "#/$defs/booleanValidator" }, { "$ref": "#/$defs/arrayValidator" }, { "$ref": "#/$defs/customValidator" }] } };
252
+ const title$J = "GolemUI Validator Definitions";
253
+ const $defs$H = { "localizable": { "$ref": "./core/common.schema.json#/$defs/localizable" }, "stringValidator": { "type": "object", "properties": { "type": { "const": "string" }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the value is empty or absent" }, "minLength": { "type": "number", "description": "Minimum number of characters the string must contain" }, "maxLength": { "type": "number", "description": "Maximum number of characters the string may contain" }, "pattern": { "type": "string", "description": "A regular expression pattern the value must match" }, "format": { "type": "string", "description": "A named format the string must conform to (e.g. `email`, `url`, `date`, `uuid`)", "enum": ["email", "hostname", "ipv4", "ipv6", "url", "uuid", "date", "time", "date-time", "duration"] }, "const": { "description": "The string must equal exactly this value" }, "enum": { "type": "array", "description": "The string must be one of these allowed values" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value fails general type validation" }, "required": { "$ref": "#/$defs/localizable", "description": "Shown when a required field is empty" }, "minLength": { "$ref": "#/$defs/localizable", "description": "Shown when the value is shorter than `minLength`" }, "maxLength": { "$ref": "#/$defs/localizable", "description": "Shown when the value is longer than `maxLength`" }, "pattern": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not match the `pattern` regex" }, "format": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not conform to the specified `format`" }, "enum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not in the `enum` list" }, "const": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not equal `const`" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "numberValidator": { "type": "object", "properties": { "type": { "type": "string", "enum": ["number", "integer"] }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the value is absent" }, "minimum": { "type": "number", "description": "The value must be greater than or equal to this number (inclusive)" }, "maximum": { "type": "number", "description": "The value must be less than or equal to this number (inclusive)" }, "exclusiveMinimum": { "type": "number", "description": "The value must be strictly greater than this number (exclusive)" }, "exclusiveMaximum": { "type": "number", "description": "The value must be strictly less than this number (exclusive)" }, "multipleOf": { "type": "number", "description": "The value must be a multiple of this number" }, "const": { "description": "The value must equal exactly this number" }, "enum": { "type": "array", "description": "The value must be one of these allowed numbers" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value fails general type validation" }, "minimum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is below `minimum`" }, "maximum": { "$ref": "#/$defs/localizable", "description": "Shown when the value exceeds `maximum`" }, "exclusiveMinimum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not strictly above `exclusiveMinimum`" }, "exclusiveMaximum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not strictly below `exclusiveMaximum`" }, "multipleOf": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not a multiple of `multipleOf`" }, "enum": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not in the `enum` list" }, "const": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not equal `const`" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "booleanValidator": { "type": "object", "properties": { "type": { "const": "boolean" }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the value is absent or false (e.g. an unchecked required checkbox)" }, "const": { "description": "The value must equal exactly this boolean (e.g. `true` to require acceptance)" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value fails general type validation" }, "const": { "$ref": "#/$defs/localizable", "description": "Shown when the value does not equal `const`" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "arrayValidator": { "type": "object", "properties": { "type": { "const": "array" }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the array is empty or absent" }, "minItems": { "type": "number", "description": "The array must contain at least this many items" }, "maxItems": { "type": "number", "description": "The array must contain no more than this many items" }, "uniqueItems": { "type": "boolean", "description": "When true, all items in the array must be distinct values" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value fails general type validation" }, "required": { "$ref": "#/$defs/localizable", "description": "Shown when a required array is empty or absent" }, "minItems": { "$ref": "#/$defs/localizable", "description": "Shown when the array has fewer items than `minItems`" }, "maxItems": { "$ref": "#/$defs/localizable", "description": "Shown when the array has more items than `maxItems`" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "fileValidator": { "type": "object", "description": "Validates the file envelope stored by the `fileUpload` widget (`{ id, name, size, type, status, error?, data? }` or `null`).", "properties": { "type": { "const": "file" }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if no file is set" }, "blockPendingUploads": { "type": "boolean", "description": "When true (the default), validation fails while the file's status is `uploading` or `error`, so an unfinished upload cannot be submitted" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not a file envelope" }, "required": { "$ref": "#/$defs/localizable", "description": "Shown when a required field has no file" }, "pendingUploads": { "$ref": "#/$defs/localizable", "description": "Shown while the file is still uploading or failed to upload" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "filesValidator": { "type": "object", "description": "Validates the array of file envelopes stored by the `multiFileUpload` widget.", "properties": { "type": { "const": "files" }, "required": { "type": "boolean", "description": "Makes the field mandatory - validation fails if the array is empty or absent" }, "minItems": { "type": "number", "description": "The array must contain at least this many files" }, "maxItems": { "type": "number", "description": "The array must contain no more than this many files" }, "blockPendingUploads": { "type": "boolean", "description": "When true (the default), validation fails while any file's status is `uploading` or `error`, so an unfinished upload cannot be submitted" }, "messages": { "type": "object", "description": "Custom error messages that override the default text for each constraint violation", "properties": { "invalid": { "$ref": "#/$defs/localizable", "description": "Shown when the value is not an array of file envelopes" }, "required": { "$ref": "#/$defs/localizable", "description": "Shown when a required array is empty or absent" }, "minItems": { "$ref": "#/$defs/localizable", "description": "Shown when the array has fewer files than `minItems`" }, "maxItems": { "$ref": "#/$defs/localizable", "description": "Shown when the array has more files than `maxItems`" }, "pendingUploads": { "$ref": "#/$defs/localizable", "description": "Shown while any file is still uploading or failed to upload" } }, "additionalProperties": false } }, "required": ["type"], "additionalProperties": false }, "customValidator": { "type": "object", "description": "A custom validator that delegates validation to application code. The registered validator function receives these constraint keys and must return a Standard Schema V1-compliant schema object (https://standardschema.dev). Add arbitrary constraint keys alongside `type` - they are passed as-is to the registered validator function.", "properties": { "type": { "const": "custom" }, "required": { "type": "boolean", "description": "Makes the field mandatory - evaluation is still delegated to the custom validator" } }, "required": ["type"], "additionalProperties": true }, "validator": { "description": "Validation rules for this field. The `type` discriminant selects the validator: `string`, `number`, `integer`, `boolean`, `array`, `file`, `files`, or `custom`.", "oneOf": [{ "$ref": "#/$defs/stringValidator" }, { "$ref": "#/$defs/numberValidator" }, { "$ref": "#/$defs/booleanValidator" }, { "$ref": "#/$defs/arrayValidator" }, { "$ref": "#/$defs/fileValidator" }, { "$ref": "#/$defs/filesValidator" }, { "$ref": "#/$defs/customValidator" }] } };
32
254
  const validatorsSchemaJson = {
33
- $schema: $schema$H,
34
- $id: $id$H,
255
+ $schema: $schema$J,
256
+ $id: $id$J,
35
257
  $comment: $comment$3,
36
- title: title$H,
37
- $defs: $defs$F
258
+ title: title$J,
259
+ $defs: $defs$H
38
260
  };
39
- const $schema$G = "https://json-schema.org/draft/2020-12/schema";
40
- const $id$G = "https://golemui.com/schemas/gui/form.schema.json";
261
+ const $schema$I = "https://json-schema.org/draft/2020-12/schema";
262
+ const $id$I = "https://golemui.com/schemas/gui/form.schema.json";
41
263
  const $comment$2 = "GENERATED by libs/gui/schemas/tools/generate-schemas.ts from src/lib/widget-manifest.ts. DO NOT EDIT. Regenerate with `npm run generate:schemas`.";
42
- const title$G = "Golem Form DSL";
43
- const type$E = "object";
44
- const properties$D = { "$schema": { "type": "string" }, "states": { "type": "object", "description": 'Named boolean conditions keyed by state name, each mapping to a reactive expression. States serve two purposes: (1) gating widget visibility via `include.in` / `exclude.from`; (2) overriding individual widget properties when a state is active by appending `".<stateName>"` to any property key - e.g. `"label.myState": "Active label"` or `"props.hint.myState": "Active hint"`. Root-level suffixable props: `label`, `disabled`, `readonly`, `validator`, `size`. Any key inside `props` can also be suffixed.', "additionalProperties": { "$ref": "./core/common.schema.json#/$defs/reactiveExpression" } }, "form": { "type": "array", "description": "The ordered list of widgets that make up the form body", "items": { "$ref": "./widgets.schema.json#/$defs/formWidget" } }, "autocomplete": { "type": "string", "description": "HTML `autocomplete` attribute applied to the `<form>` element (e.g. `on`, `off`)" } };
45
- const required$D = ["form"];
264
+ const title$I = "Golem Form DSL";
265
+ const type$G = "object";
266
+ const properties$F = { "$schema": { "type": "string" }, "states": { "type": "object", "description": 'Named boolean conditions keyed by state name, each mapping to a reactive expression. States serve two purposes: (1) gating widget visibility via `include.in` / `exclude.from`; (2) overriding individual widget properties when a state is active by appending `".<stateName>"` to any property key - e.g. `"label.myState": "Active label"` or `"props.hint.myState": "Active hint"`. Root-level suffixable props: `label`, `disabled`, `readonly`, `validator`, `size`. Any key inside `props` can also be suffixed.', "additionalProperties": { "$ref": "./core/common.schema.json#/$defs/reactiveExpression" } }, "form": { "type": "array", "description": "The ordered list of widgets that make up the form body", "items": { "$ref": "./widgets.schema.json#/$defs/formWidget" } }, "autocomplete": { "type": "string", "description": "HTML `autocomplete` attribute applied to the `<form>` element (e.g. `on`, `off`)" } };
267
+ const required$F = ["form"];
46
268
  const additionalProperties = false;
47
269
  const formSchemaJson = {
48
- $schema: $schema$G,
49
- $id: $id$G,
270
+ $schema: $schema$I,
271
+ $id: $id$I,
50
272
  $comment: $comment$2,
51
- title: title$G,
52
- type: type$E,
53
- properties: properties$D,
54
- required: required$D,
273
+ title: title$I,
274
+ type: type$G,
275
+ properties: properties$F,
276
+ required: required$F,
55
277
  additionalProperties
56
278
  };
57
- const $schema$F = "https://json-schema.org/draft/2020-12/schema";
58
- const $id$F = "https://golemui.com/schemas/gui/layout-widget.schema.json";
279
+ const $schema$H = "https://json-schema.org/draft/2020-12/schema";
280
+ const $id$H = "https://golemui.com/schemas/gui/layout-widget.schema.json";
59
281
  const $comment$1 = "GENERATED by libs/gui/schemas/tools/generate-schemas.ts from src/lib/widget-manifest.ts. DO NOT EDIT. Regenerate with `npm run generate:schemas`.";
60
- const title$F = "Golem Layout Widget";
282
+ const title$H = "Golem Layout Widget";
61
283
  const oneOf$1 = [{ "$ref": "./components/accordion.schema.json" }, { "$ref": "./components/flex.schema.json" }, { "$ref": "./components/grid.schema.json" }, { "$ref": "./components/tabs.schema.json" }];
62
284
  const layoutWidgetSchemaJson = {
63
- $schema: $schema$F,
64
- $id: $id$F,
285
+ $schema: $schema$H,
286
+ $id: $id$H,
65
287
  $comment: $comment$1,
66
- title: title$F,
288
+ title: title$H,
67
289
  oneOf: oneOf$1
68
290
  };
69
- const $schema$E = "https://json-schema.org/draft/2020-12/schema";
70
- const $id$E = "https://golemui.com/schemas/gui/widgets.schema.json";
291
+ const $schema$G = "https://json-schema.org/draft/2020-12/schema";
292
+ const $id$G = "https://golemui.com/schemas/gui/widgets.schema.json";
71
293
  const $comment = "GENERATED by libs/gui/schemas/tools/generate-schemas.ts from src/lib/widget-manifest.ts. DO NOT EDIT. Regenerate with `npm run generate:schemas`.";
72
- const title$E = "Golem gui widgets";
73
- const $defs$E = { "knownWidgetTypes": { "description": "Built-in widget `type` identifiers. Used to exclude built-ins from the custom-widget fallback so every widget matches exactly one schema. Types listed here without a component schema are not expressible in JSON and are rejected entirely instead of validating as custom widgets.", "enum": ["calendar", "dateTimeCalendar", "checkbox", "currency", "dateInput", "datePicker", "dateTimeInput", "dateTimePicker", "dropdown", "list", "markdown", "multiDropdown", "multiList", "number", "password", "radiogroup", "rangeCalendar", "rangeDateInput", "rangeDatePicker", "rangeDateTimeInput", "rangeDateTimeCalendar", "rangeDateTimePicker", "rangeTimeInput", "rangeTimePicker", "repeater", "select", "tags", "textarea", "textinput", "timeInput", "timePicker", "toggle", "accordion", "flex", "grid", "tabs", "alert", "markdownText", "renderer", "button"] }, "formWidget": { "description": "A form widget: one of the built-in component schemas, the custom-widget fallback, or a reference to an external chunk file.", "oneOf": [{ "$ref": "./components/calendar.schema.json" }, { "$ref": "./components/datetimecalendar.schema.json" }, { "$ref": "./components/checkbox.schema.json" }, { "$ref": "./components/currency.schema.json" }, { "$ref": "./components/dateinput.schema.json" }, { "$ref": "./components/datepicker.schema.json" }, { "$ref": "./components/datetimeinput.schema.json" }, { "$ref": "./components/datetimepicker.schema.json" }, { "$ref": "./components/dropdown.schema.json" }, { "$ref": "./components/list.schema.json" }, { "$ref": "./components/markdown.schema.json" }, { "$ref": "./components/multidropdown.schema.json" }, { "$ref": "./components/multilist.schema.json" }, { "$ref": "./components/number.schema.json" }, { "$ref": "./components/password.schema.json" }, { "$ref": "./components/radiogroup.schema.json" }, { "$ref": "./components/rangecalendar.schema.json" }, { "$ref": "./components/rangedateinput.schema.json" }, { "$ref": "./components/rangedatepicker.schema.json" }, { "$ref": "./components/rangedatetimeinput.schema.json" }, { "$ref": "./components/rangedatetimecalendar.schema.json" }, { "$ref": "./components/rangedatetimepicker.schema.json" }, { "$ref": "./components/rangetimeinput.schema.json" }, { "$ref": "./components/rangetimepicker.schema.json" }, { "$ref": "./components/repeater.schema.json" }, { "$ref": "./components/select.schema.json" }, { "$ref": "./components/tags.schema.json" }, { "$ref": "./components/textarea.schema.json" }, { "$ref": "./components/textinput.schema.json" }, { "$ref": "./components/timeinput.schema.json" }, { "$ref": "./components/timepicker.schema.json" }, { "$ref": "./components/toggle.schema.json" }, { "$ref": "./components/accordion.schema.json" }, { "$ref": "./components/flex.schema.json" }, { "$ref": "./components/grid.schema.json" }, { "$ref": "./components/tabs.schema.json" }, { "$ref": "./components/alert.schema.json" }, { "$ref": "./components/markdowntext.schema.json" }, { "$ref": "./components/button.schema.json" }, { "$ref": "./components/custom.schema.json" }, { "$ref": "./core/common.schema.json#/$defs/chunkRef" }] } };
294
+ const title$G = "Golem gui widgets";
295
+ const $defs$G = { "knownWidgetTypes": { "description": "Built-in widget `type` identifiers. Used to exclude built-ins from the custom-widget fallback so every widget matches exactly one schema. Types listed here without a component schema are not expressible in JSON and are rejected entirely instead of validating as custom widgets.", "enum": ["calendar", "dateTimeCalendar", "checkbox", "currency", "dateInput", "datePicker", "dateTimeInput", "dateTimePicker", "dropdown", "fileUpload", "list", "markdown", "multiDropdown", "multiFileUpload", "multiList", "number", "password", "radiogroup", "rangeCalendar", "rangeDateInput", "rangeDatePicker", "rangeDateTimeInput", "rangeDateTimeCalendar", "rangeDateTimePicker", "rangeTimeInput", "rangeTimePicker", "repeater", "select", "tags", "textarea", "textinput", "timeInput", "timePicker", "toggle", "accordion", "flex", "grid", "tabs", "alert", "markdownText", "renderer", "button"] }, "formWidget": { "description": "A form widget: one of the built-in component schemas, the custom-widget fallback, or a reference to an external chunk file.", "oneOf": [{ "$ref": "./components/calendar.schema.json" }, { "$ref": "./components/datetimecalendar.schema.json" }, { "$ref": "./components/checkbox.schema.json" }, { "$ref": "./components/currency.schema.json" }, { "$ref": "./components/dateinput.schema.json" }, { "$ref": "./components/datepicker.schema.json" }, { "$ref": "./components/datetimeinput.schema.json" }, { "$ref": "./components/datetimepicker.schema.json" }, { "$ref": "./components/dropdown.schema.json" }, { "$ref": "./components/fileupload.schema.json" }, { "$ref": "./components/list.schema.json" }, { "$ref": "./components/markdown.schema.json" }, { "$ref": "./components/multidropdown.schema.json" }, { "$ref": "./components/multifileupload.schema.json" }, { "$ref": "./components/multilist.schema.json" }, { "$ref": "./components/number.schema.json" }, { "$ref": "./components/password.schema.json" }, { "$ref": "./components/radiogroup.schema.json" }, { "$ref": "./components/rangecalendar.schema.json" }, { "$ref": "./components/rangedateinput.schema.json" }, { "$ref": "./components/rangedatepicker.schema.json" }, { "$ref": "./components/rangedatetimeinput.schema.json" }, { "$ref": "./components/rangedatetimecalendar.schema.json" }, { "$ref": "./components/rangedatetimepicker.schema.json" }, { "$ref": "./components/rangetimeinput.schema.json" }, { "$ref": "./components/rangetimepicker.schema.json" }, { "$ref": "./components/repeater.schema.json" }, { "$ref": "./components/select.schema.json" }, { "$ref": "./components/tags.schema.json" }, { "$ref": "./components/textarea.schema.json" }, { "$ref": "./components/textinput.schema.json" }, { "$ref": "./components/timeinput.schema.json" }, { "$ref": "./components/timepicker.schema.json" }, { "$ref": "./components/toggle.schema.json" }, { "$ref": "./components/accordion.schema.json" }, { "$ref": "./components/flex.schema.json" }, { "$ref": "./components/grid.schema.json" }, { "$ref": "./components/tabs.schema.json" }, { "$ref": "./components/alert.schema.json" }, { "$ref": "./components/markdowntext.schema.json" }, { "$ref": "./components/button.schema.json" }, { "$ref": "./components/custom.schema.json" }, { "$ref": "./core/common.schema.json#/$defs/chunkRef" }] } };
74
296
  const widgetsSchemaJson = {
297
+ $schema: $schema$G,
298
+ $id: $id$G,
299
+ $comment,
300
+ title: title$G,
301
+ $defs: $defs$G
302
+ };
303
+ const $schema$F = "https://json-schema.org/draft/2020-12/schema";
304
+ const $id$F = "https://golemui.com/schemas/gui/components/calendar.schema.json";
305
+ const title$F = "Calendar Widget";
306
+ const type$F = "object";
307
+ const $defs$F = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "prevMonthIconProp": { "type": "string" }, "nextMonthIconProp": { "type": "string" }, "prevMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "nextMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "selectYearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearGridAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayFormatProp": { "description": "Formatting of day numbers in the calendar grid (`numeric` = 1-31, `2-digit` = 01-31)", "enum": ["numeric", "2-digit"] }, "weekdayFormatProp": { "description": "Formatting of weekday column headers (`short` = Mon, `long` = Monday, `narrow` = M)", "enum": ["short", "long", "narrow"] }, "monthFormatProp": { "description": "Formatting of the month heading (`long` = January, `short` = Jan, `narrow` = J, `numeric` = 1, `2-digit` = 01)", "enum": ["numeric", "2-digit", "long", "short", "narrow"] }, "minDateProp": { "type": "string", "description": "ISO-8601 date string for the earliest selectable date (inclusive)" }, "maxDateProp": { "type": "string", "description": "ISO-8601 date string for the latest selectable date (inclusive)" }, "numberOfMonthsProp": { "type": "number", "description": "Number of month panels to display side by side. Defaults to 1." }, "disabledRangesProp": { "type": "array", "description": "Date ranges that are shown but cannot be selected", "items": { "$ref": "../ranges.schema.json#/$defs/dateRange" } } };
308
+ const allOf$F = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
309
+ const properties$E = { "kind": { "const": "input" }, "type": { "const": "calendar" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "hint": { "$ref": "#/$defs/hintProp" }, "prevMonthIcon": { "$ref": "#/$defs/prevMonthIconProp" }, "nextMonthIcon": { "$ref": "#/$defs/nextMonthIconProp" }, "prevMonthAriaLabel": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "nextMonthAriaLabel": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "selectYearAriaLabel": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "yearGridAriaLabel": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "dayFormat": { "$ref": "#/$defs/dayFormatProp" }, "weekdayFormat": { "$ref": "#/$defs/weekdayFormatProp" }, "monthFormat": { "$ref": "#/$defs/monthFormatProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "numberOfMonths": { "$ref": "#/$defs/numberOfMonthsProp" }, "disabledRanges": { "$ref": "#/$defs/disabledRangesProp" } }, "patternProperties": { "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^prevMonthIcon\\.[^.]+$": { "$ref": "#/$defs/prevMonthIconProp" }, "^nextMonthIcon\\.[^.]+$": { "$ref": "#/$defs/nextMonthIconProp" }, "^prevMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "^nextMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "^selectYearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "^yearGridAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "^dayFormat\\.[^.]+$": { "$ref": "#/$defs/dayFormatProp" }, "^weekdayFormat\\.[^.]+$": { "$ref": "#/$defs/weekdayFormatProp" }, "^monthFormat\\.[^.]+$": { "$ref": "#/$defs/monthFormatProp" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^numberOfMonths\\.[^.]+$": { "$ref": "#/$defs/numberOfMonthsProp" }, "^disabledRanges\\.[^.]+$": { "$ref": "#/$defs/disabledRangesProp" } }, "additionalProperties": false } };
310
+ const patternProperties$y = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
311
+ const required$E = ["kind", "type", "path"];
312
+ const unevaluatedProperties$F = false;
313
+ const calendarSchemaJson = {
314
+ $schema: $schema$F,
315
+ $id: $id$F,
316
+ title: title$F,
317
+ type: type$F,
318
+ $defs: $defs$F,
319
+ allOf: allOf$F,
320
+ properties: properties$E,
321
+ patternProperties: patternProperties$y,
322
+ required: required$E,
323
+ unevaluatedProperties: unevaluatedProperties$F
324
+ };
325
+ const $schema$E = "https://json-schema.org/draft/2020-12/schema";
326
+ const $id$E = "https://golemui.com/schemas/gui/components/datetimecalendar.schema.json";
327
+ const title$E = "DateTimeCalendar Widget";
328
+ const type$E = "object";
329
+ const $defs$E = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "prevMonthIconProp": { "type": "string" }, "nextMonthIconProp": { "type": "string" }, "prevMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "nextMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "selectYearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearGridAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayFormatProp": { "description": "Formatting of day numbers in the calendar grid (`numeric` = 1-31, `2-digit` = 01-31)", "enum": ["numeric", "2-digit"] }, "weekdayFormatProp": { "description": "Formatting of weekday column headers (`short` = Mon, `long` = Monday, `narrow` = M)", "enum": ["short", "long", "narrow"] }, "monthFormatProp": { "description": "Formatting of the month heading (`long` = January, `short` = Jan, `narrow` = J, `numeric` = 1, `2-digit` = 01)", "enum": ["numeric", "2-digit", "long", "short", "narrow"] }, "minDateProp": { "type": "string", "description": "ISO-8601 date string for the earliest selectable date (inclusive)" }, "maxDateProp": { "type": "string", "description": "ISO-8601 date string for the latest selectable date (inclusive)" }, "numberOfMonthsProp": { "type": "number", "description": "Number of month panels to display side by side. Defaults to 1. The time row and grid render on the first panel only." }, "disabledRangesProp": { "type": "array", "description": "Date ranges that are shown but cannot be selected", "items": { "$ref": "../ranges.schema.json#/$defs/dateRange" } }, "hourFormatProp": { "enum": ["12", "24"] }, "allowCustomTimeProp": { "type": "boolean" }, "minuteStepProp": { "type": "number", "minimum": 1 }, "isoTimeProp": { "$ref": "../ranges.schema.json#/$defs/isoTime" }, "disabledTimeRangesProp": { "type": "array", "description": "Time ranges rendered disabled. Entries optionally scope to a date or given weekdays", "items": { "$ref": "../ranges.schema.json#/$defs/scopedTimeRange" } } };
330
+ const allOf$E = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
331
+ const properties$D = { "kind": { "const": "input" }, "type": { "const": "dateTimeCalendar" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "minTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledTimeRangeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "noAvailableTimesMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "hint": { "$ref": "#/$defs/hintProp" }, "prevMonthIcon": { "$ref": "#/$defs/prevMonthIconProp" }, "nextMonthIcon": { "$ref": "#/$defs/nextMonthIconProp" }, "prevMonthAriaLabel": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "nextMonthAriaLabel": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "selectYearAriaLabel": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "yearGridAriaLabel": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "dayFormat": { "$ref": "#/$defs/dayFormatProp" }, "weekdayFormat": { "$ref": "#/$defs/weekdayFormatProp" }, "monthFormat": { "$ref": "#/$defs/monthFormatProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "numberOfMonths": { "$ref": "#/$defs/numberOfMonthsProp" }, "disabledRanges": { "$ref": "#/$defs/disabledRangesProp" }, "hourFormat": { "$ref": "#/$defs/hourFormatProp" }, "minuteStep": { "$ref": "#/$defs/minuteStepProp" }, "minTime": { "$ref": "#/$defs/isoTimeProp" }, "maxTime": { "$ref": "#/$defs/isoTimeProp" }, "disabledTimeRanges": { "$ref": "#/$defs/disabledTimeRangesProp" }, "allowCustomTime": { "$ref": "#/$defs/allowCustomTimeProp" } }, "patternProperties": { "^minTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^disabledTimeRangeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^noAvailableTimesMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^prevMonthIcon\\.[^.]+$": { "$ref": "#/$defs/prevMonthIconProp" }, "^nextMonthIcon\\.[^.]+$": { "$ref": "#/$defs/nextMonthIconProp" }, "^prevMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "^nextMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "^selectYearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "^yearGridAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "^dayFormat\\.[^.]+$": { "$ref": "#/$defs/dayFormatProp" }, "^weekdayFormat\\.[^.]+$": { "$ref": "#/$defs/weekdayFormatProp" }, "^monthFormat\\.[^.]+$": { "$ref": "#/$defs/monthFormatProp" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^numberOfMonths\\.[^.]+$": { "$ref": "#/$defs/numberOfMonthsProp" }, "^disabledRanges\\.[^.]+$": { "$ref": "#/$defs/disabledRangesProp" }, "^hourFormat\\.[^.]+$": { "$ref": "#/$defs/hourFormatProp" }, "^minuteStep\\.[^.]+$": { "$ref": "#/$defs/minuteStepProp" }, "^minTime\\.[^.]+$": { "$ref": "#/$defs/isoTimeProp" }, "^maxTime\\.[^.]+$": { "$ref": "#/$defs/isoTimeProp" }, "^disabledTimeRanges\\.[^.]+$": { "$ref": "#/$defs/disabledTimeRangesProp" }, "^allowCustomTime\\.[^.]+$": { "$ref": "#/$defs/allowCustomTimeProp" } }, "additionalProperties": false } };
332
+ const patternProperties$x = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
333
+ const required$D = ["kind", "type", "path"];
334
+ const unevaluatedProperties$E = false;
335
+ const datetimecalendarSchemaJson = {
75
336
  $schema: $schema$E,
76
337
  $id: $id$E,
77
- $comment,
78
338
  title: title$E,
79
- $defs: $defs$E
339
+ type: type$E,
340
+ $defs: $defs$E,
341
+ allOf: allOf$E,
342
+ properties: properties$D,
343
+ patternProperties: patternProperties$x,
344
+ required: required$D,
345
+ unevaluatedProperties: unevaluatedProperties$E
80
346
  };
81
347
  const $schema$D = "https://json-schema.org/draft/2020-12/schema";
82
- const $id$D = "https://golemui.com/schemas/gui/components/calendar.schema.json";
83
- const title$D = "Calendar Widget";
348
+ const $id$D = "https://golemui.com/schemas/gui/components/checkbox.schema.json";
349
+ const title$D = "Checkbox Widget";
84
350
  const type$D = "object";
85
- const $defs$D = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "prevMonthIconProp": { "type": "string" }, "nextMonthIconProp": { "type": "string" }, "prevMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "nextMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "selectYearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearGridAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayFormatProp": { "description": "Formatting of day numbers in the calendar grid (`numeric` = 1-31, `2-digit` = 01-31)", "enum": ["numeric", "2-digit"] }, "weekdayFormatProp": { "description": "Formatting of weekday column headers (`short` = Mon, `long` = Monday, `narrow` = M)", "enum": ["short", "long", "narrow"] }, "monthFormatProp": { "description": "Formatting of the month heading (`long` = January, `short` = Jan, `narrow` = J, `numeric` = 1, `2-digit` = 01)", "enum": ["numeric", "2-digit", "long", "short", "narrow"] }, "minDateProp": { "type": "string", "description": "ISO-8601 date string for the earliest selectable date (inclusive)" }, "maxDateProp": { "type": "string", "description": "ISO-8601 date string for the latest selectable date (inclusive)" }, "numberOfMonthsProp": { "type": "number", "description": "Number of month panels to display side by side. Defaults to 1." }, "disabledRangesProp": { "type": "array", "description": "Date ranges that are shown but cannot be selected", "items": { "$ref": "../ranges.schema.json#/$defs/dateRange" } } };
351
+ const $defs$D = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "checkboxPositionProp": { "enum": ["left", "right"], "default": "left" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
86
352
  const allOf$D = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
87
- const properties$C = { "kind": { "const": "input" }, "type": { "const": "calendar" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "hint": { "$ref": "#/$defs/hintProp" }, "prevMonthIcon": { "$ref": "#/$defs/prevMonthIconProp" }, "nextMonthIcon": { "$ref": "#/$defs/nextMonthIconProp" }, "prevMonthAriaLabel": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "nextMonthAriaLabel": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "selectYearAriaLabel": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "yearGridAriaLabel": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "dayFormat": { "$ref": "#/$defs/dayFormatProp" }, "weekdayFormat": { "$ref": "#/$defs/weekdayFormatProp" }, "monthFormat": { "$ref": "#/$defs/monthFormatProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "numberOfMonths": { "$ref": "#/$defs/numberOfMonthsProp" }, "disabledRanges": { "$ref": "#/$defs/disabledRangesProp" } }, "patternProperties": { "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^prevMonthIcon\\.[^.]+$": { "$ref": "#/$defs/prevMonthIconProp" }, "^nextMonthIcon\\.[^.]+$": { "$ref": "#/$defs/nextMonthIconProp" }, "^prevMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "^nextMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "^selectYearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "^yearGridAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "^dayFormat\\.[^.]+$": { "$ref": "#/$defs/dayFormatProp" }, "^weekdayFormat\\.[^.]+$": { "$ref": "#/$defs/weekdayFormatProp" }, "^monthFormat\\.[^.]+$": { "$ref": "#/$defs/monthFormatProp" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^numberOfMonths\\.[^.]+$": { "$ref": "#/$defs/numberOfMonthsProp" }, "^disabledRanges\\.[^.]+$": { "$ref": "#/$defs/disabledRangesProp" } }, "additionalProperties": false } };
353
+ const properties$C = { "kind": { "const": "input" }, "type": { "const": "checkbox" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "boolean" }, "props": { "type": "object", "properties": { "checkboxPosition": { "$ref": "#/$defs/checkboxPositionProp" }, "hint": { "$ref": "#/$defs/hintProp" } }, "patternProperties": { "^checkboxPosition\\.[^.]+$": { "$ref": "#/$defs/checkboxPositionProp" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" } }, "additionalProperties": false } };
88
354
  const patternProperties$w = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
89
355
  const required$C = ["kind", "type", "path"];
90
356
  const unevaluatedProperties$D = false;
91
- const calendarSchemaJson = {
357
+ const checkboxSchemaJson = {
92
358
  $schema: $schema$D,
93
359
  $id: $id$D,
94
360
  title: title$D,
@@ -101,16 +367,16 @@ const calendarSchemaJson = {
101
367
  unevaluatedProperties: unevaluatedProperties$D
102
368
  };
103
369
  const $schema$C = "https://json-schema.org/draft/2020-12/schema";
104
- const $id$C = "https://golemui.com/schemas/gui/components/datetimecalendar.schema.json";
105
- const title$C = "DateTimeCalendar Widget";
370
+ const $id$C = "https://golemui.com/schemas/gui/components/currency.schema.json";
371
+ const title$C = "Currency Widget";
106
372
  const type$C = "object";
107
- const $defs$C = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "prevMonthIconProp": { "type": "string" }, "nextMonthIconProp": { "type": "string" }, "prevMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "nextMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "selectYearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearGridAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayFormatProp": { "description": "Formatting of day numbers in the calendar grid (`numeric` = 1-31, `2-digit` = 01-31)", "enum": ["numeric", "2-digit"] }, "weekdayFormatProp": { "description": "Formatting of weekday column headers (`short` = Mon, `long` = Monday, `narrow` = M)", "enum": ["short", "long", "narrow"] }, "monthFormatProp": { "description": "Formatting of the month heading (`long` = January, `short` = Jan, `narrow` = J, `numeric` = 1, `2-digit` = 01)", "enum": ["numeric", "2-digit", "long", "short", "narrow"] }, "minDateProp": { "type": "string", "description": "ISO-8601 date string for the earliest selectable date (inclusive)" }, "maxDateProp": { "type": "string", "description": "ISO-8601 date string for the latest selectable date (inclusive)" }, "numberOfMonthsProp": { "type": "number", "description": "Number of month panels to display side by side. Defaults to 1. The time row and grid render on the first panel only." }, "disabledRangesProp": { "type": "array", "description": "Date ranges that are shown but cannot be selected", "items": { "$ref": "../ranges.schema.json#/$defs/dateRange" } }, "hourFormatProp": { "enum": ["12", "24"] }, "allowCustomTimeProp": { "type": "boolean" }, "minuteStepProp": { "type": "number", "minimum": 1 }, "isoTimeProp": { "$ref": "../ranges.schema.json#/$defs/isoTime" }, "disabledTimeRangesProp": { "type": "array", "description": "Time ranges rendered disabled. Entries optionally scope to a date or given weekdays", "items": { "$ref": "../ranges.schema.json#/$defs/scopedTimeRange" } } };
373
+ const $defs$C = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "currencyProp": { "type": "string" }, "stepProp": { "type": "number" }, "maximumFractionDigitsProp": { "type": "number" }, "minimumFractionDigitsProp": { "type": "number" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "placeholderProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "autocompleteProp": { "type": "string" } };
108
374
  const allOf$C = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
109
- const properties$B = { "kind": { "const": "input" }, "type": { "const": "dateTimeCalendar" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "minTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledTimeRangeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "noAvailableTimesMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "hint": { "$ref": "#/$defs/hintProp" }, "prevMonthIcon": { "$ref": "#/$defs/prevMonthIconProp" }, "nextMonthIcon": { "$ref": "#/$defs/nextMonthIconProp" }, "prevMonthAriaLabel": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "nextMonthAriaLabel": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "selectYearAriaLabel": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "yearGridAriaLabel": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "dayFormat": { "$ref": "#/$defs/dayFormatProp" }, "weekdayFormat": { "$ref": "#/$defs/weekdayFormatProp" }, "monthFormat": { "$ref": "#/$defs/monthFormatProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "numberOfMonths": { "$ref": "#/$defs/numberOfMonthsProp" }, "disabledRanges": { "$ref": "#/$defs/disabledRangesProp" }, "hourFormat": { "$ref": "#/$defs/hourFormatProp" }, "minuteStep": { "$ref": "#/$defs/minuteStepProp" }, "minTime": { "$ref": "#/$defs/isoTimeProp" }, "maxTime": { "$ref": "#/$defs/isoTimeProp" }, "disabledTimeRanges": { "$ref": "#/$defs/disabledTimeRangesProp" }, "allowCustomTime": { "$ref": "#/$defs/allowCustomTimeProp" } }, "patternProperties": { "^minTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^disabledTimeRangeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^noAvailableTimesMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^prevMonthIcon\\.[^.]+$": { "$ref": "#/$defs/prevMonthIconProp" }, "^nextMonthIcon\\.[^.]+$": { "$ref": "#/$defs/nextMonthIconProp" }, "^prevMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "^nextMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "^selectYearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "^yearGridAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "^dayFormat\\.[^.]+$": { "$ref": "#/$defs/dayFormatProp" }, "^weekdayFormat\\.[^.]+$": { "$ref": "#/$defs/weekdayFormatProp" }, "^monthFormat\\.[^.]+$": { "$ref": "#/$defs/monthFormatProp" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^numberOfMonths\\.[^.]+$": { "$ref": "#/$defs/numberOfMonthsProp" }, "^disabledRanges\\.[^.]+$": { "$ref": "#/$defs/disabledRangesProp" }, "^hourFormat\\.[^.]+$": { "$ref": "#/$defs/hourFormatProp" }, "^minuteStep\\.[^.]+$": { "$ref": "#/$defs/minuteStepProp" }, "^minTime\\.[^.]+$": { "$ref": "#/$defs/isoTimeProp" }, "^maxTime\\.[^.]+$": { "$ref": "#/$defs/isoTimeProp" }, "^disabledTimeRanges\\.[^.]+$": { "$ref": "#/$defs/disabledTimeRangesProp" }, "^allowCustomTime\\.[^.]+$": { "$ref": "#/$defs/allowCustomTimeProp" } }, "additionalProperties": false } };
375
+ const properties$B = { "kind": { "const": "input" }, "type": { "const": "currency" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "number" }, "props": { "type": "object", "properties": { "currency": { "$ref": "#/$defs/currencyProp" }, "step": { "$ref": "#/$defs/stepProp" }, "maximumFractionDigits": { "$ref": "#/$defs/maximumFractionDigitsProp" }, "minimumFractionDigits": { "$ref": "#/$defs/minimumFractionDigitsProp" }, "hint": { "$ref": "#/$defs/hintProp" }, "placeholder": { "$ref": "#/$defs/placeholderProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "autocomplete": { "$ref": "#/$defs/autocompleteProp" } }, "patternProperties": { "^currency\\.[^.]+$": { "$ref": "#/$defs/currencyProp" }, "^step\\.[^.]+$": { "$ref": "#/$defs/stepProp" }, "^maximumFractionDigits\\.[^.]+$": { "$ref": "#/$defs/maximumFractionDigitsProp" }, "^minimumFractionDigits\\.[^.]+$": { "$ref": "#/$defs/minimumFractionDigitsProp" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^placeholder\\.[^.]+$": { "$ref": "#/$defs/placeholderProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^autocomplete\\.[^.]+$": { "$ref": "#/$defs/autocompleteProp" } }, "additionalProperties": false } };
110
376
  const patternProperties$v = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
111
377
  const required$B = ["kind", "type", "path"];
112
378
  const unevaluatedProperties$C = false;
113
- const datetimecalendarSchemaJson = {
379
+ const currencySchemaJson = {
114
380
  $schema: $schema$C,
115
381
  $id: $id$C,
116
382
  title: title$C,
@@ -123,16 +389,16 @@ const datetimecalendarSchemaJson = {
123
389
  unevaluatedProperties: unevaluatedProperties$C
124
390
  };
125
391
  const $schema$B = "https://json-schema.org/draft/2020-12/schema";
126
- const $id$B = "https://golemui.com/schemas/gui/components/checkbox.schema.json";
127
- const title$B = "Checkbox Widget";
392
+ const $id$B = "https://golemui.com/schemas/gui/components/dateinput.schema.json";
393
+ const title$B = "DateInput Widget";
128
394
  const type$B = "object";
129
- const $defs$B = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "checkboxPositionProp": { "enum": ["left", "right"], "default": "left" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
395
+ const $defs$B = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "minDateProp": { "type": "string" }, "maxDateProp": { "type": "string" }, "dayAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "monthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
130
396
  const allOf$B = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
131
- const properties$A = { "kind": { "const": "input" }, "type": { "const": "checkbox" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "boolean" }, "props": { "type": "object", "properties": { "checkboxPosition": { "$ref": "#/$defs/checkboxPositionProp" }, "hint": { "$ref": "#/$defs/hintProp" } }, "patternProperties": { "^checkboxPosition\\.[^.]+$": { "$ref": "#/$defs/checkboxPositionProp" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" } }, "additionalProperties": false } };
397
+ const properties$A = { "kind": { "const": "input" }, "type": { "const": "dateInput" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "invalidDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "minDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "dayAriaLabel": { "$ref": "#/$defs/dayAriaLabelProp" }, "monthAriaLabel": { "$ref": "#/$defs/monthAriaLabelProp" }, "yearAriaLabel": { "$ref": "#/$defs/yearAriaLabelProp" } }, "patternProperties": { "^invalidDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^minDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^dayAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayAriaLabelProp" }, "^monthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/monthAriaLabelProp" }, "^yearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearAriaLabelProp" } }, "additionalProperties": false } };
132
398
  const patternProperties$u = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
133
399
  const required$A = ["kind", "type", "path"];
134
400
  const unevaluatedProperties$B = false;
135
- const checkboxSchemaJson = {
401
+ const dateinputSchemaJson = {
136
402
  $schema: $schema$B,
137
403
  $id: $id$B,
138
404
  title: title$B,
@@ -145,16 +411,16 @@ const checkboxSchemaJson = {
145
411
  unevaluatedProperties: unevaluatedProperties$B
146
412
  };
147
413
  const $schema$A = "https://json-schema.org/draft/2020-12/schema";
148
- const $id$A = "https://golemui.com/schemas/gui/components/currency.schema.json";
149
- const title$A = "Currency Widget";
414
+ const $id$A = "https://golemui.com/schemas/gui/components/datepicker.schema.json";
415
+ const title$A = "DatePicker Widget";
150
416
  const type$A = "object";
151
- const $defs$A = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "currencyProp": { "type": "string" }, "stepProp": { "type": "number" }, "maximumFractionDigitsProp": { "type": "number" }, "minimumFractionDigitsProp": { "type": "number" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "placeholderProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "autocompleteProp": { "type": "string" } };
417
+ const $defs$A = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "prevMonthIconProp": { "type": "string" }, "nextMonthIconProp": { "type": "string" }, "prevMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "nextMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "toggleAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "selectYearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearGridAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "monthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayFormatProp": { "enum": ["numeric", "2-digit"] }, "weekdayFormatProp": { "enum": ["short", "long", "narrow"] }, "monthFormatProp": { "enum": ["numeric", "2-digit", "long", "short", "narrow"] }, "minDateProp": { "type": "string" }, "maxDateProp": { "type": "string" }, "numberOfMonthsProp": { "type": "number" }, "disabledRangesProp": { "type": "array", "items": { "$ref": "../ranges.schema.json#/$defs/dateRange" } } };
152
418
  const allOf$A = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
153
- const properties$z = { "kind": { "const": "input" }, "type": { "const": "currency" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "number" }, "props": { "type": "object", "properties": { "currency": { "$ref": "#/$defs/currencyProp" }, "step": { "$ref": "#/$defs/stepProp" }, "maximumFractionDigits": { "$ref": "#/$defs/maximumFractionDigitsProp" }, "minimumFractionDigits": { "$ref": "#/$defs/minimumFractionDigitsProp" }, "hint": { "$ref": "#/$defs/hintProp" }, "placeholder": { "$ref": "#/$defs/placeholderProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "autocomplete": { "$ref": "#/$defs/autocompleteProp" } }, "patternProperties": { "^currency\\.[^.]+$": { "$ref": "#/$defs/currencyProp" }, "^step\\.[^.]+$": { "$ref": "#/$defs/stepProp" }, "^maximumFractionDigits\\.[^.]+$": { "$ref": "#/$defs/maximumFractionDigitsProp" }, "^minimumFractionDigits\\.[^.]+$": { "$ref": "#/$defs/minimumFractionDigitsProp" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^placeholder\\.[^.]+$": { "$ref": "#/$defs/placeholderProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^autocomplete\\.[^.]+$": { "$ref": "#/$defs/autocompleteProp" } }, "additionalProperties": false } };
419
+ const properties$z = { "kind": { "const": "input" }, "type": { "const": "datePicker" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "invalidDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDateRangeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "prevMonthIcon": { "$ref": "#/$defs/prevMonthIconProp" }, "nextMonthIcon": { "$ref": "#/$defs/nextMonthIconProp" }, "prevMonthAriaLabel": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "nextMonthAriaLabel": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "toggleAriaLabel": { "$ref": "#/$defs/toggleAriaLabelProp" }, "selectYearAriaLabel": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "yearGridAriaLabel": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "dayAriaLabel": { "$ref": "#/$defs/dayAriaLabelProp" }, "monthAriaLabel": { "$ref": "#/$defs/monthAriaLabelProp" }, "yearAriaLabel": { "$ref": "#/$defs/yearAriaLabelProp" }, "dayFormat": { "$ref": "#/$defs/dayFormatProp" }, "weekdayFormat": { "$ref": "#/$defs/weekdayFormatProp" }, "monthFormat": { "$ref": "#/$defs/monthFormatProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "numberOfMonths": { "$ref": "#/$defs/numberOfMonthsProp" }, "disabledRanges": { "$ref": "#/$defs/disabledRangesProp" } }, "patternProperties": { "^invalidDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^disabledDateRangeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^prevMonthIcon\\.[^.]+$": { "$ref": "#/$defs/prevMonthIconProp" }, "^nextMonthIcon\\.[^.]+$": { "$ref": "#/$defs/nextMonthIconProp" }, "^prevMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "^nextMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "^toggleAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toggleAriaLabelProp" }, "^selectYearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "^yearGridAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "^dayAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayAriaLabelProp" }, "^monthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/monthAriaLabelProp" }, "^yearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearAriaLabelProp" }, "^dayFormat\\.[^.]+$": { "$ref": "#/$defs/dayFormatProp" }, "^weekdayFormat\\.[^.]+$": { "$ref": "#/$defs/weekdayFormatProp" }, "^monthFormat\\.[^.]+$": { "$ref": "#/$defs/monthFormatProp" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^numberOfMonths\\.[^.]+$": { "$ref": "#/$defs/numberOfMonthsProp" }, "^disabledRanges\\.[^.]+$": { "$ref": "#/$defs/disabledRangesProp" } }, "additionalProperties": false } };
154
420
  const patternProperties$t = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
155
421
  const required$z = ["kind", "type", "path"];
156
422
  const unevaluatedProperties$A = false;
157
- const currencySchemaJson = {
423
+ const datepickerSchemaJson = {
158
424
  $schema: $schema$A,
159
425
  $id: $id$A,
160
426
  title: title$A,
@@ -167,16 +433,16 @@ const currencySchemaJson = {
167
433
  unevaluatedProperties: unevaluatedProperties$A
168
434
  };
169
435
  const $schema$z = "https://json-schema.org/draft/2020-12/schema";
170
- const $id$z = "https://golemui.com/schemas/gui/components/dateinput.schema.json";
171
- const title$z = "DateInput Widget";
436
+ const $id$z = "https://golemui.com/schemas/gui/components/datetimeinput.schema.json";
437
+ const title$z = "DateTimeInput Widget";
172
438
  const type$z = "object";
173
- const $defs$z = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "minDateProp": { "type": "string" }, "maxDateProp": { "type": "string" }, "dayAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "monthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
439
+ const $defs$z = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "hourFormatProp": { "enum": ["12", "24"] }, "minuteStepProp": { "type": "number", "minimum": 1 }, "minDateProp": { "type": "string" }, "maxDateProp": { "type": "string" }, "minTimeProp": { "type": "string" }, "maxTimeProp": { "type": "string" }, "dayAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "monthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hourAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minuteAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayPeriodAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
174
440
  const allOf$z = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
175
- const properties$y = { "kind": { "const": "input" }, "type": { "const": "dateInput" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "invalidDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "minDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "dayAriaLabel": { "$ref": "#/$defs/dayAriaLabelProp" }, "monthAriaLabel": { "$ref": "#/$defs/monthAriaLabelProp" }, "yearAriaLabel": { "$ref": "#/$defs/yearAriaLabelProp" } }, "patternProperties": { "^invalidDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^minDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^dayAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayAriaLabelProp" }, "^monthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/monthAriaLabelProp" }, "^yearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearAriaLabelProp" } }, "additionalProperties": false } };
441
+ const properties$y = { "kind": { "const": "input" }, "type": { "const": "dateTimeInput" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "invalidDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "hourFormat": { "$ref": "#/$defs/hourFormatProp" }, "minuteStep": { "$ref": "#/$defs/minuteStepProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "minTime": { "$ref": "#/$defs/minTimeProp" }, "maxTime": { "$ref": "#/$defs/maxTimeProp" }, "minDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "dayAriaLabel": { "$ref": "#/$defs/dayAriaLabelProp" }, "monthAriaLabel": { "$ref": "#/$defs/monthAriaLabelProp" }, "yearAriaLabel": { "$ref": "#/$defs/yearAriaLabelProp" }, "hourAriaLabel": { "$ref": "#/$defs/hourAriaLabelProp" }, "minuteAriaLabel": { "$ref": "#/$defs/minuteAriaLabelProp" }, "dayPeriodAriaLabel": { "$ref": "#/$defs/dayPeriodAriaLabelProp" } }, "patternProperties": { "^invalidDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^minTime\\.[^.]+$": { "$ref": "#/$defs/minTimeProp" }, "^maxTime\\.[^.]+$": { "$ref": "#/$defs/maxTimeProp" }, "^minDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^hourFormat\\.[^.]+$": { "$ref": "#/$defs/hourFormatProp" }, "^minuteStep\\.[^.]+$": { "$ref": "#/$defs/minuteStepProp" }, "^dayAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayAriaLabelProp" }, "^monthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/monthAriaLabelProp" }, "^yearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearAriaLabelProp" }, "^hourAriaLabel\\.[^.]+$": { "$ref": "#/$defs/hourAriaLabelProp" }, "^minuteAriaLabel\\.[^.]+$": { "$ref": "#/$defs/minuteAriaLabelProp" }, "^dayPeriodAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayPeriodAriaLabelProp" } }, "additionalProperties": false } };
176
442
  const patternProperties$s = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
177
443
  const required$y = ["kind", "type", "path"];
178
444
  const unevaluatedProperties$z = false;
179
- const dateinputSchemaJson = {
445
+ const datetimeinputSchemaJson = {
180
446
  $schema: $schema$z,
181
447
  $id: $id$z,
182
448
  title: title$z,
@@ -189,16 +455,16 @@ const dateinputSchemaJson = {
189
455
  unevaluatedProperties: unevaluatedProperties$z
190
456
  };
191
457
  const $schema$y = "https://json-schema.org/draft/2020-12/schema";
192
- const $id$y = "https://golemui.com/schemas/gui/components/datepicker.schema.json";
193
- const title$y = "DatePicker Widget";
458
+ const $id$y = "https://golemui.com/schemas/gui/components/datetimepicker.schema.json";
459
+ const title$y = "DateTimePicker Widget";
194
460
  const type$y = "object";
195
- const $defs$y = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "prevMonthIconProp": { "type": "string" }, "nextMonthIconProp": { "type": "string" }, "prevMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "nextMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "toggleAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "selectYearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearGridAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "monthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayFormatProp": { "enum": ["numeric", "2-digit"] }, "weekdayFormatProp": { "enum": ["short", "long", "narrow"] }, "monthFormatProp": { "enum": ["numeric", "2-digit", "long", "short", "narrow"] }, "minDateProp": { "type": "string" }, "maxDateProp": { "type": "string" }, "numberOfMonthsProp": { "type": "number" }, "disabledRangesProp": { "type": "array", "items": { "$ref": "../ranges.schema.json#/$defs/dateRange" } } };
461
+ const $defs$y = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "prevMonthIconProp": { "type": "string" }, "nextMonthIconProp": { "type": "string" }, "prevMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "nextMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "toggleAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "selectYearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearGridAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "monthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hourAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minuteAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayPeriodAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayFormatProp": { "description": "Formatting of day numbers in the calendar grid (`numeric` = 1-31, `2-digit` = 01-31)", "enum": ["numeric", "2-digit"] }, "weekdayFormatProp": { "description": "Formatting of weekday column headers (`short` = Mon, `long` = Monday, `narrow` = M)", "enum": ["short", "long", "narrow"] }, "monthFormatProp": { "description": "Formatting of the month heading (`long` = January, `short` = Jan, `narrow` = J, `numeric` = 1, `2-digit` = 01)", "enum": ["numeric", "2-digit", "long", "short", "narrow"] }, "minDateProp": { "type": "string", "description": "ISO-8601 date string for the earliest selectable date (inclusive)" }, "maxDateProp": { "type": "string", "description": "ISO-8601 date string for the latest selectable date (inclusive)" }, "numberOfMonthsProp": { "type": "number", "description": "Number of month panels to display side by side. Defaults to 1. The time row and grid render on the first panel only." }, "disabledRangesProp": { "type": "array", "description": "Date ranges that are shown but cannot be selected", "items": { "$ref": "../ranges.schema.json#/$defs/dateRange" } }, "hourFormatProp": { "enum": ["12", "24"] }, "allowCustomTimeProp": { "type": "boolean" }, "minuteStepProp": { "type": "number", "minimum": 1 }, "isoTimeProp": { "$ref": "../ranges.schema.json#/$defs/isoTime" }, "disabledTimeRangesProp": { "type": "array", "description": "Time ranges rendered disabled. Entries optionally scope to a date or given weekdays", "items": { "$ref": "../ranges.schema.json#/$defs/scopedTimeRange" } } };
196
462
  const allOf$y = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
197
- const properties$x = { "kind": { "const": "input" }, "type": { "const": "datePicker" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "invalidDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDateRangeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "prevMonthIcon": { "$ref": "#/$defs/prevMonthIconProp" }, "nextMonthIcon": { "$ref": "#/$defs/nextMonthIconProp" }, "prevMonthAriaLabel": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "nextMonthAriaLabel": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "toggleAriaLabel": { "$ref": "#/$defs/toggleAriaLabelProp" }, "selectYearAriaLabel": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "yearGridAriaLabel": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "dayAriaLabel": { "$ref": "#/$defs/dayAriaLabelProp" }, "monthAriaLabel": { "$ref": "#/$defs/monthAriaLabelProp" }, "yearAriaLabel": { "$ref": "#/$defs/yearAriaLabelProp" }, "dayFormat": { "$ref": "#/$defs/dayFormatProp" }, "weekdayFormat": { "$ref": "#/$defs/weekdayFormatProp" }, "monthFormat": { "$ref": "#/$defs/monthFormatProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "numberOfMonths": { "$ref": "#/$defs/numberOfMonthsProp" }, "disabledRanges": { "$ref": "#/$defs/disabledRangesProp" } }, "patternProperties": { "^invalidDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^disabledDateRangeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^prevMonthIcon\\.[^.]+$": { "$ref": "#/$defs/prevMonthIconProp" }, "^nextMonthIcon\\.[^.]+$": { "$ref": "#/$defs/nextMonthIconProp" }, "^prevMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "^nextMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "^toggleAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toggleAriaLabelProp" }, "^selectYearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "^yearGridAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "^dayAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayAriaLabelProp" }, "^monthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/monthAriaLabelProp" }, "^yearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearAriaLabelProp" }, "^dayFormat\\.[^.]+$": { "$ref": "#/$defs/dayFormatProp" }, "^weekdayFormat\\.[^.]+$": { "$ref": "#/$defs/weekdayFormatProp" }, "^monthFormat\\.[^.]+$": { "$ref": "#/$defs/monthFormatProp" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^numberOfMonths\\.[^.]+$": { "$ref": "#/$defs/numberOfMonthsProp" }, "^disabledRanges\\.[^.]+$": { "$ref": "#/$defs/disabledRangesProp" } }, "additionalProperties": false } };
463
+ const properties$x = { "kind": { "const": "input" }, "type": { "const": "dateTimePicker" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "invalidDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDateRangeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledTimeRangeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "noAvailableTimesMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "prevMonthIcon": { "$ref": "#/$defs/prevMonthIconProp" }, "nextMonthIcon": { "$ref": "#/$defs/nextMonthIconProp" }, "prevMonthAriaLabel": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "nextMonthAriaLabel": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "toggleAriaLabel": { "$ref": "#/$defs/toggleAriaLabelProp" }, "selectYearAriaLabel": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "yearGridAriaLabel": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "dayAriaLabel": { "$ref": "#/$defs/dayAriaLabelProp" }, "monthAriaLabel": { "$ref": "#/$defs/monthAriaLabelProp" }, "yearAriaLabel": { "$ref": "#/$defs/yearAriaLabelProp" }, "hourAriaLabel": { "$ref": "#/$defs/hourAriaLabelProp" }, "minuteAriaLabel": { "$ref": "#/$defs/minuteAriaLabelProp" }, "dayPeriodAriaLabel": { "$ref": "#/$defs/dayPeriodAriaLabelProp" }, "dayFormat": { "$ref": "#/$defs/dayFormatProp" }, "weekdayFormat": { "$ref": "#/$defs/weekdayFormatProp" }, "monthFormat": { "$ref": "#/$defs/monthFormatProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "numberOfMonths": { "$ref": "#/$defs/numberOfMonthsProp" }, "disabledRanges": { "$ref": "#/$defs/disabledRangesProp" }, "hourFormat": { "$ref": "#/$defs/hourFormatProp" }, "minuteStep": { "$ref": "#/$defs/minuteStepProp" }, "minTime": { "$ref": "#/$defs/isoTimeProp" }, "maxTime": { "$ref": "#/$defs/isoTimeProp" }, "disabledTimeRanges": { "$ref": "#/$defs/disabledTimeRangesProp" }, "allowCustomTime": { "$ref": "#/$defs/allowCustomTimeProp" } }, "patternProperties": { "^invalidDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^disabledDateRangeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^disabledTimeRangeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^noAvailableTimesMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^prevMonthIcon\\.[^.]+$": { "$ref": "#/$defs/prevMonthIconProp" }, "^nextMonthIcon\\.[^.]+$": { "$ref": "#/$defs/nextMonthIconProp" }, "^prevMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "^nextMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "^toggleAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toggleAriaLabelProp" }, "^selectYearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "^yearGridAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "^dayAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayAriaLabelProp" }, "^monthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/monthAriaLabelProp" }, "^yearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearAriaLabelProp" }, "^hourAriaLabel\\.[^.]+$": { "$ref": "#/$defs/hourAriaLabelProp" }, "^minuteAriaLabel\\.[^.]+$": { "$ref": "#/$defs/minuteAriaLabelProp" }, "^dayPeriodAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayPeriodAriaLabelProp" }, "^dayFormat\\.[^.]+$": { "$ref": "#/$defs/dayFormatProp" }, "^weekdayFormat\\.[^.]+$": { "$ref": "#/$defs/weekdayFormatProp" }, "^monthFormat\\.[^.]+$": { "$ref": "#/$defs/monthFormatProp" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^numberOfMonths\\.[^.]+$": { "$ref": "#/$defs/numberOfMonthsProp" }, "^disabledRanges\\.[^.]+$": { "$ref": "#/$defs/disabledRangesProp" }, "^hourFormat\\.[^.]+$": { "$ref": "#/$defs/hourFormatProp" }, "^minuteStep\\.[^.]+$": { "$ref": "#/$defs/minuteStepProp" }, "^minTime\\.[^.]+$": { "$ref": "#/$defs/isoTimeProp" }, "^maxTime\\.[^.]+$": { "$ref": "#/$defs/isoTimeProp" }, "^disabledTimeRanges\\.[^.]+$": { "$ref": "#/$defs/disabledTimeRangesProp" }, "^allowCustomTime\\.[^.]+$": { "$ref": "#/$defs/allowCustomTimeProp" } }, "additionalProperties": false } };
198
464
  const patternProperties$r = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
199
465
  const required$x = ["kind", "type", "path"];
200
466
  const unevaluatedProperties$y = false;
201
- const datepickerSchemaJson = {
467
+ const datetimepickerSchemaJson = {
202
468
  $schema: $schema$y,
203
469
  $id: $id$y,
204
470
  title: title$y,
@@ -211,16 +477,16 @@ const datepickerSchemaJson = {
211
477
  unevaluatedProperties: unevaluatedProperties$y
212
478
  };
213
479
  const $schema$x = "https://json-schema.org/draft/2020-12/schema";
214
- const $id$x = "https://golemui.com/schemas/gui/components/datetimeinput.schema.json";
215
- const title$x = "DateTimeInput Widget";
480
+ const $id$x = "https://golemui.com/schemas/gui/components/dropdown.schema.json";
481
+ const title$x = "Dropdown Widget";
216
482
  const type$x = "object";
217
- const $defs$x = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "hourFormatProp": { "enum": ["12", "24"] }, "minuteStepProp": { "type": "number", "minimum": 1 }, "minDateProp": { "type": "string" }, "maxDateProp": { "type": "string" }, "minTimeProp": { "type": "string" }, "maxTimeProp": { "type": "string" }, "dayAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "monthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hourAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minuteAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayPeriodAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
483
+ const $defs$x = { "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "placeholderProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "itemsProp": { "type": "array", "description": "Items are either primitive values (string/number) or arbitrary record objects (paired with `labelField`/`valueField`/`itemRenderer` for custom rendering). Note: widget templates inside items are only supported on `repeater`, not here.", "items": { "type": ["string", "number", "object"] } }, "labelFieldProp": { "type": "string", "description": 'Object property used as the display label when items are objects (e.g. `"name"` reads `item.name`)' }, "valueFieldProp": { "type": "string", "description": 'Object property used as the stored value when items are objects (e.g. `"id"` stores `item.id`)' }, "searchFieldsProp": { "type": "array", "description": "Object properties searched when the user types in the filter box. Defaults to `labelField` when omitted.", "items": { "type": "string" } }, "heightProp": { "type": "number", "description": "Fixed pixel height of the dropdown list panel (enables virtual scrolling for large lists)" }, "itemHeightProp": { "type": "number", "description": "Fixed pixel height of each item row, required for virtual scrolling when `height` is set" }, "itemRendererProp": { "type": "string", "description": "Name of a registered custom item renderer component used to display each option" }, "inputDebounceProp": { "type": "number", "description": "Milliseconds to debounce the filter input before firing the `on.filter` event (default: 0)" }, "autocompleteProp": { "type": "string", "description": "HTML `autocomplete` attribute applied to the underlying input element" }, "iconProp": { "type": "string" }, "toggleAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
218
484
  const allOf$x = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
219
- const properties$w = { "kind": { "const": "input" }, "type": { "const": "dateTimeInput" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "invalidDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "hourFormat": { "$ref": "#/$defs/hourFormatProp" }, "minuteStep": { "$ref": "#/$defs/minuteStepProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "minTime": { "$ref": "#/$defs/minTimeProp" }, "maxTime": { "$ref": "#/$defs/maxTimeProp" }, "minDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "dayAriaLabel": { "$ref": "#/$defs/dayAriaLabelProp" }, "monthAriaLabel": { "$ref": "#/$defs/monthAriaLabelProp" }, "yearAriaLabel": { "$ref": "#/$defs/yearAriaLabelProp" }, "hourAriaLabel": { "$ref": "#/$defs/hourAriaLabelProp" }, "minuteAriaLabel": { "$ref": "#/$defs/minuteAriaLabelProp" }, "dayPeriodAriaLabel": { "$ref": "#/$defs/dayPeriodAriaLabelProp" } }, "patternProperties": { "^invalidDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^minTime\\.[^.]+$": { "$ref": "#/$defs/minTimeProp" }, "^maxTime\\.[^.]+$": { "$ref": "#/$defs/maxTimeProp" }, "^minDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^hourFormat\\.[^.]+$": { "$ref": "#/$defs/hourFormatProp" }, "^minuteStep\\.[^.]+$": { "$ref": "#/$defs/minuteStepProp" }, "^dayAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayAriaLabelProp" }, "^monthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/monthAriaLabelProp" }, "^yearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearAriaLabelProp" }, "^hourAriaLabel\\.[^.]+$": { "$ref": "#/$defs/hourAriaLabelProp" }, "^minuteAriaLabel\\.[^.]+$": { "$ref": "#/$defs/minuteAriaLabelProp" }, "^dayPeriodAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayPeriodAriaLabelProp" } }, "additionalProperties": false } };
485
+ const properties$w = { "kind": { "const": "input" }, "type": { "const": "dropdown" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": ["string", "number"] }, "props": { "type": "object", "required": ["items"], "properties": { "placeholder": { "$ref": "#/$defs/placeholderProp" }, "hint": { "$ref": "#/$defs/hintProp" }, "items": { "$ref": "#/$defs/itemsProp" }, "labelField": { "$ref": "#/$defs/labelFieldProp" }, "valueField": { "$ref": "#/$defs/valueFieldProp" }, "searchFields": { "$ref": "#/$defs/searchFieldsProp" }, "height": { "$ref": "#/$defs/heightProp" }, "itemHeight": { "$ref": "#/$defs/itemHeightProp" }, "itemRenderer": { "$ref": "#/$defs/itemRendererProp" }, "inputDebounce": { "$ref": "#/$defs/inputDebounceProp" }, "autocomplete": { "$ref": "#/$defs/autocompleteProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "toggleAriaLabel": { "$ref": "#/$defs/toggleAriaLabelProp" } }, "patternProperties": { "^placeholder\\.[^.]+$": { "$ref": "#/$defs/placeholderProp" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^items\\.[^.]+$": { "$ref": "#/$defs/itemsProp" }, "^labelField\\.[^.]+$": { "$ref": "#/$defs/labelFieldProp" }, "^valueField\\.[^.]+$": { "$ref": "#/$defs/valueFieldProp" }, "^searchFields\\.[^.]+$": { "$ref": "#/$defs/searchFieldsProp" }, "^height\\.[^.]+$": { "$ref": "#/$defs/heightProp" }, "^itemHeight\\.[^.]+$": { "$ref": "#/$defs/itemHeightProp" }, "^itemRenderer\\.[^.]+$": { "$ref": "#/$defs/itemRendererProp" }, "^inputDebounce\\.[^.]+$": { "$ref": "#/$defs/inputDebounceProp" }, "^autocomplete\\.[^.]+$": { "$ref": "#/$defs/autocompleteProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^toggleAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toggleAriaLabelProp" } }, "additionalProperties": false } };
220
486
  const patternProperties$q = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
221
- const required$w = ["kind", "type", "path"];
487
+ const required$w = ["kind", "type", "path", "props"];
222
488
  const unevaluatedProperties$x = false;
223
- const datetimeinputSchemaJson = {
489
+ const dropdownSchemaJson = {
224
490
  $schema: $schema$x,
225
491
  $id: $id$x,
226
492
  title: title$x,
@@ -233,16 +499,16 @@ const datetimeinputSchemaJson = {
233
499
  unevaluatedProperties: unevaluatedProperties$x
234
500
  };
235
501
  const $schema$w = "https://json-schema.org/draft/2020-12/schema";
236
- const $id$w = "https://golemui.com/schemas/gui/components/datetimepicker.schema.json";
237
- const title$w = "DateTimePicker Widget";
502
+ const $id$w = "https://golemui.com/schemas/gui/components/fileupload.schema.json";
503
+ const title$w = "File Upload Widget";
238
504
  const type$w = "object";
239
- const $defs$w = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "prevMonthIconProp": { "type": "string" }, "nextMonthIconProp": { "type": "string" }, "prevMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "nextMonthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "toggleAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "selectYearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearGridAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "monthAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "yearAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hourAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minuteAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayPeriodAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "dayFormatProp": { "description": "Formatting of day numbers in the calendar grid (`numeric` = 1-31, `2-digit` = 01-31)", "enum": ["numeric", "2-digit"] }, "weekdayFormatProp": { "description": "Formatting of weekday column headers (`short` = Mon, `long` = Monday, `narrow` = M)", "enum": ["short", "long", "narrow"] }, "monthFormatProp": { "description": "Formatting of the month heading (`long` = January, `short` = Jan, `narrow` = J, `numeric` = 1, `2-digit` = 01)", "enum": ["numeric", "2-digit", "long", "short", "narrow"] }, "minDateProp": { "type": "string", "description": "ISO-8601 date string for the earliest selectable date (inclusive)" }, "maxDateProp": { "type": "string", "description": "ISO-8601 date string for the latest selectable date (inclusive)" }, "numberOfMonthsProp": { "type": "number", "description": "Number of month panels to display side by side. Defaults to 1. The time row and grid render on the first panel only." }, "disabledRangesProp": { "type": "array", "description": "Date ranges that are shown but cannot be selected", "items": { "$ref": "../ranges.schema.json#/$defs/dateRange" } }, "hourFormatProp": { "enum": ["12", "24"] }, "allowCustomTimeProp": { "type": "boolean" }, "minuteStepProp": { "type": "number", "minimum": 1 }, "isoTimeProp": { "$ref": "../ranges.schema.json#/$defs/isoTime" }, "disabledTimeRangesProp": { "type": "array", "description": "Time ranges rendered disabled. Entries optionally scope to a date or given weekdays", "items": { "$ref": "../ranges.schema.json#/$defs/scopedTimeRange" } } };
505
+ const $defs$w = { "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "fileItem": { "type": "object", "description": 'One uploaded file as stored in the form value. `data` is whatever the host\'s `uploadService.upload` resolved with, verbatim. Preloaded values should carry `status: "uploaded"`.', "properties": { "id": { "type": "string", "description": "Synthetic id, stable for the life of the item" }, "name": { "type": "string" }, "size": { "type": "number", "description": "Size in bytes" }, "type": { "type": "string", "description": "MIME type" }, "status": { "enum": ["uploading", "uploaded", "error"] }, "error": { "type": "string", "description": "Human-readable reason when `status` is `error`" }, "data": { "description": "The server response, verbatim" } }, "required": ["id", "name", "size", "type", "status"], "additionalProperties": false }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "acceptProp": { "type": "array", "description": 'Accepted file types, e.g. `["image/*", ".pdf"]`. Files that do not match are refused before uploading.', "items": { "type": "string" } }, "maxSizeProp": { "type": "number", "description": "Maximum size per file, in bytes. Larger files are refused before uploading." }, "buttonLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removeAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "cancelAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "retryAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removeIconProp": { "type": "string" }, "retryIconProp": { "type": "string" }, "maxSizeMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "acceptMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "interruptedMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "missingServiceMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "uploadedMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removedMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "failedMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
240
506
  const allOf$w = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
241
- const properties$v = { "kind": { "const": "input" }, "type": { "const": "dateTimePicker" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "invalidDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxDateMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDateRangeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "minTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "maxTimeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledTimeRangeMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "noAvailableTimesMessage": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "incompleteMessage": { "$ref": "../core/common.schema.json#/$defs/localizable", "description": "Error surfaced when focus leaves the widget with a partially filled entry behind; the value goes to null so validators report it even on non-required fields." }, "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "prevMonthIcon": { "$ref": "#/$defs/prevMonthIconProp" }, "nextMonthIcon": { "$ref": "#/$defs/nextMonthIconProp" }, "prevMonthAriaLabel": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "nextMonthAriaLabel": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "toggleAriaLabel": { "$ref": "#/$defs/toggleAriaLabelProp" }, "selectYearAriaLabel": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "yearGridAriaLabel": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "dayAriaLabel": { "$ref": "#/$defs/dayAriaLabelProp" }, "monthAriaLabel": { "$ref": "#/$defs/monthAriaLabelProp" }, "yearAriaLabel": { "$ref": "#/$defs/yearAriaLabelProp" }, "hourAriaLabel": { "$ref": "#/$defs/hourAriaLabelProp" }, "minuteAriaLabel": { "$ref": "#/$defs/minuteAriaLabelProp" }, "dayPeriodAriaLabel": { "$ref": "#/$defs/dayPeriodAriaLabelProp" }, "dayFormat": { "$ref": "#/$defs/dayFormatProp" }, "weekdayFormat": { "$ref": "#/$defs/weekdayFormatProp" }, "monthFormat": { "$ref": "#/$defs/monthFormatProp" }, "minDate": { "$ref": "#/$defs/minDateProp" }, "maxDate": { "$ref": "#/$defs/maxDateProp" }, "numberOfMonths": { "$ref": "#/$defs/numberOfMonthsProp" }, "disabledRanges": { "$ref": "#/$defs/disabledRangesProp" }, "hourFormat": { "$ref": "#/$defs/hourFormatProp" }, "minuteStep": { "$ref": "#/$defs/minuteStepProp" }, "minTime": { "$ref": "#/$defs/isoTimeProp" }, "maxTime": { "$ref": "#/$defs/isoTimeProp" }, "disabledTimeRanges": { "$ref": "#/$defs/disabledTimeRangesProp" }, "allowCustomTime": { "$ref": "#/$defs/allowCustomTimeProp" } }, "patternProperties": { "^invalidDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxDateMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^disabledDateRangeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^minTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^maxTimeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^disabledTimeRangeMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^noAvailableTimesMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^incompleteMessage\\.[^.]+$": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^prevMonthIcon\\.[^.]+$": { "$ref": "#/$defs/prevMonthIconProp" }, "^nextMonthIcon\\.[^.]+$": { "$ref": "#/$defs/nextMonthIconProp" }, "^prevMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/prevMonthAriaLabelProp" }, "^nextMonthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/nextMonthAriaLabelProp" }, "^toggleAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toggleAriaLabelProp" }, "^selectYearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/selectYearAriaLabelProp" }, "^yearGridAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearGridAriaLabelProp" }, "^dayAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayAriaLabelProp" }, "^monthAriaLabel\\.[^.]+$": { "$ref": "#/$defs/monthAriaLabelProp" }, "^yearAriaLabel\\.[^.]+$": { "$ref": "#/$defs/yearAriaLabelProp" }, "^hourAriaLabel\\.[^.]+$": { "$ref": "#/$defs/hourAriaLabelProp" }, "^minuteAriaLabel\\.[^.]+$": { "$ref": "#/$defs/minuteAriaLabelProp" }, "^dayPeriodAriaLabel\\.[^.]+$": { "$ref": "#/$defs/dayPeriodAriaLabelProp" }, "^dayFormat\\.[^.]+$": { "$ref": "#/$defs/dayFormatProp" }, "^weekdayFormat\\.[^.]+$": { "$ref": "#/$defs/weekdayFormatProp" }, "^monthFormat\\.[^.]+$": { "$ref": "#/$defs/monthFormatProp" }, "^minDate\\.[^.]+$": { "$ref": "#/$defs/minDateProp" }, "^maxDate\\.[^.]+$": { "$ref": "#/$defs/maxDateProp" }, "^numberOfMonths\\.[^.]+$": { "$ref": "#/$defs/numberOfMonthsProp" }, "^disabledRanges\\.[^.]+$": { "$ref": "#/$defs/disabledRangesProp" }, "^hourFormat\\.[^.]+$": { "$ref": "#/$defs/hourFormatProp" }, "^minuteStep\\.[^.]+$": { "$ref": "#/$defs/minuteStepProp" }, "^minTime\\.[^.]+$": { "$ref": "#/$defs/isoTimeProp" }, "^maxTime\\.[^.]+$": { "$ref": "#/$defs/isoTimeProp" }, "^disabledTimeRanges\\.[^.]+$": { "$ref": "#/$defs/disabledTimeRangesProp" }, "^allowCustomTime\\.[^.]+$": { "$ref": "#/$defs/allowCustomTimeProp" } }, "additionalProperties": false } };
242
- const patternProperties$p = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
507
+ const properties$v = { "kind": { "const": "input" }, "type": { "const": "fileUpload" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "oneOf": [{ "$ref": "#/$defs/fileItem" }, { "type": "null" }] }, "props": { "type": "object", "properties": { "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "accept": { "$ref": "#/$defs/acceptProp" }, "maxSize": { "$ref": "#/$defs/maxSizeProp" }, "buttonLabel": { "$ref": "#/$defs/buttonLabelProp" }, "removeAriaLabel": { "$ref": "#/$defs/removeAriaLabelProp" }, "cancelAriaLabel": { "$ref": "#/$defs/cancelAriaLabelProp" }, "retryAriaLabel": { "$ref": "#/$defs/retryAriaLabelProp" }, "removeIcon": { "$ref": "#/$defs/removeIconProp" }, "retryIcon": { "$ref": "#/$defs/retryIconProp" }, "maxSizeMessage": { "$ref": "#/$defs/maxSizeMessageProp" }, "acceptMessage": { "$ref": "#/$defs/acceptMessageProp" }, "interruptedMessage": { "$ref": "#/$defs/interruptedMessageProp" }, "missingServiceMessage": { "$ref": "#/$defs/missingServiceMessageProp" }, "uploadedMessage": { "$ref": "#/$defs/uploadedMessageProp" }, "removedMessage": { "$ref": "#/$defs/removedMessageProp" }, "failedMessage": { "$ref": "#/$defs/failedMessageProp" } }, "patternProperties": { "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^accept\\.[^.]+$": { "$ref": "#/$defs/acceptProp" }, "^maxSize\\.[^.]+$": { "$ref": "#/$defs/maxSizeProp" }, "^buttonLabel\\.[^.]+$": { "$ref": "#/$defs/buttonLabelProp" }, "^removeAriaLabel\\.[^.]+$": { "$ref": "#/$defs/removeAriaLabelProp" }, "^cancelAriaLabel\\.[^.]+$": { "$ref": "#/$defs/cancelAriaLabelProp" }, "^retryAriaLabel\\.[^.]+$": { "$ref": "#/$defs/retryAriaLabelProp" }, "^removeIcon\\.[^.]+$": { "$ref": "#/$defs/removeIconProp" }, "^retryIcon\\.[^.]+$": { "$ref": "#/$defs/retryIconProp" }, "^maxSizeMessage\\.[^.]+$": { "$ref": "#/$defs/maxSizeMessageProp" }, "^acceptMessage\\.[^.]+$": { "$ref": "#/$defs/acceptMessageProp" }, "^interruptedMessage\\.[^.]+$": { "$ref": "#/$defs/interruptedMessageProp" }, "^missingServiceMessage\\.[^.]+$": { "$ref": "#/$defs/missingServiceMessageProp" }, "^uploadedMessage\\.[^.]+$": { "$ref": "#/$defs/uploadedMessageProp" }, "^removedMessage\\.[^.]+$": { "$ref": "#/$defs/removedMessageProp" }, "^failedMessage\\.[^.]+$": { "$ref": "#/$defs/failedMessageProp" } }, "additionalProperties": false } };
508
+ const patternProperties$p = { "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
243
509
  const required$v = ["kind", "type", "path"];
244
510
  const unevaluatedProperties$w = false;
245
- const datetimepickerSchemaJson = {
511
+ const fileuploadSchemaJson = {
246
512
  $schema: $schema$w,
247
513
  $id: $id$w,
248
514
  title: title$w,
@@ -255,16 +521,16 @@ const datetimepickerSchemaJson = {
255
521
  unevaluatedProperties: unevaluatedProperties$w
256
522
  };
257
523
  const $schema$v = "https://json-schema.org/draft/2020-12/schema";
258
- const $id$v = "https://golemui.com/schemas/gui/components/dropdown.schema.json";
259
- const title$v = "Dropdown Widget";
524
+ const $id$v = "https://golemui.com/schemas/gui/components/list.schema.json";
525
+ const title$v = "List Widget";
260
526
  const type$v = "object";
261
- const $defs$v = { "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "placeholderProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "itemsProp": { "type": "array", "description": "Items are either primitive values (string/number) or arbitrary record objects (paired with `labelField`/`valueField`/`itemRenderer` for custom rendering). Note: widget templates inside items are only supported on `repeater`, not here.", "items": { "type": ["string", "number", "object"] } }, "labelFieldProp": { "type": "string", "description": 'Object property used as the display label when items are objects (e.g. `"name"` reads `item.name`)' }, "valueFieldProp": { "type": "string", "description": 'Object property used as the stored value when items are objects (e.g. `"id"` stores `item.id`)' }, "searchFieldsProp": { "type": "array", "description": "Object properties searched when the user types in the filter box. Defaults to `labelField` when omitted.", "items": { "type": "string" } }, "heightProp": { "type": "number", "description": "Fixed pixel height of the dropdown list panel (enables virtual scrolling for large lists)" }, "itemHeightProp": { "type": "number", "description": "Fixed pixel height of each item row, required for virtual scrolling when `height` is set" }, "itemRendererProp": { "type": "string", "description": "Name of a registered custom item renderer component used to display each option" }, "inputDebounceProp": { "type": "number", "description": "Milliseconds to debounce the filter input before firing the `on.filter` event (default: 0)" }, "autocompleteProp": { "type": "string", "description": "HTML `autocomplete` attribute applied to the underlying input element" }, "iconProp": { "type": "string" }, "toggleAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
527
+ const $defs$v = { "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "itemsProp": { "type": "array", "description": "Items are either primitive values (string/number) or arbitrary record objects (paired with `labelField`/`valueField`/`itemRenderer` for custom rendering). Note: widget templates inside items are only supported on `repeater`, not here.", "items": { "type": ["string", "number", "object"] } }, "labelFieldProp": { "type": "string" }, "valueFieldProp": { "type": "string" }, "heightProp": { "type": "number" }, "itemHeightProp": { "type": "number" }, "itemRendererProp": { "type": "string" } };
262
528
  const allOf$v = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
263
- const properties$u = { "kind": { "const": "input" }, "type": { "const": "dropdown" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": ["string", "number"] }, "props": { "type": "object", "required": ["items"], "properties": { "placeholder": { "$ref": "#/$defs/placeholderProp" }, "hint": { "$ref": "#/$defs/hintProp" }, "items": { "$ref": "#/$defs/itemsProp" }, "labelField": { "$ref": "#/$defs/labelFieldProp" }, "valueField": { "$ref": "#/$defs/valueFieldProp" }, "searchFields": { "$ref": "#/$defs/searchFieldsProp" }, "height": { "$ref": "#/$defs/heightProp" }, "itemHeight": { "$ref": "#/$defs/itemHeightProp" }, "itemRenderer": { "$ref": "#/$defs/itemRendererProp" }, "inputDebounce": { "$ref": "#/$defs/inputDebounceProp" }, "autocomplete": { "$ref": "#/$defs/autocompleteProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "toggleAriaLabel": { "$ref": "#/$defs/toggleAriaLabelProp" } }, "patternProperties": { "^placeholder\\.[^.]+$": { "$ref": "#/$defs/placeholderProp" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^items\\.[^.]+$": { "$ref": "#/$defs/itemsProp" }, "^labelField\\.[^.]+$": { "$ref": "#/$defs/labelFieldProp" }, "^valueField\\.[^.]+$": { "$ref": "#/$defs/valueFieldProp" }, "^searchFields\\.[^.]+$": { "$ref": "#/$defs/searchFieldsProp" }, "^height\\.[^.]+$": { "$ref": "#/$defs/heightProp" }, "^itemHeight\\.[^.]+$": { "$ref": "#/$defs/itemHeightProp" }, "^itemRenderer\\.[^.]+$": { "$ref": "#/$defs/itemRendererProp" }, "^inputDebounce\\.[^.]+$": { "$ref": "#/$defs/inputDebounceProp" }, "^autocomplete\\.[^.]+$": { "$ref": "#/$defs/autocompleteProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^toggleAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toggleAriaLabelProp" } }, "additionalProperties": false } };
529
+ const properties$u = { "kind": { "const": "input" }, "type": { "const": "list" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": ["string", "number"] }, "props": { "type": "object", "properties": { "hint": { "$ref": "#/$defs/hintProp" }, "items": { "$ref": "#/$defs/itemsProp" }, "labelField": { "$ref": "#/$defs/labelFieldProp" }, "valueField": { "$ref": "#/$defs/valueFieldProp" }, "height": { "$ref": "#/$defs/heightProp" }, "itemHeight": { "$ref": "#/$defs/itemHeightProp" }, "itemRenderer": { "$ref": "#/$defs/itemRendererProp" } }, "patternProperties": { "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^items\\.[^.]+$": { "$ref": "#/$defs/itemsProp" }, "^labelField\\.[^.]+$": { "$ref": "#/$defs/labelFieldProp" }, "^valueField\\.[^.]+$": { "$ref": "#/$defs/valueFieldProp" }, "^height\\.[^.]+$": { "$ref": "#/$defs/heightProp" }, "^itemHeight\\.[^.]+$": { "$ref": "#/$defs/itemHeightProp" }, "^itemRenderer\\.[^.]+$": { "$ref": "#/$defs/itemRendererProp" } }, "additionalProperties": false } };
264
530
  const patternProperties$o = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
265
- const required$u = ["kind", "type", "path", "props"];
531
+ const required$u = ["kind", "type", "path"];
266
532
  const unevaluatedProperties$v = false;
267
- const dropdownSchemaJson = {
533
+ const listSchemaJson = {
268
534
  $schema: $schema$v,
269
535
  $id: $id$v,
270
536
  title: title$v,
@@ -277,16 +543,16 @@ const dropdownSchemaJson = {
277
543
  unevaluatedProperties: unevaluatedProperties$v
278
544
  };
279
545
  const $schema$u = "https://json-schema.org/draft/2020-12/schema";
280
- const $id$u = "https://golemui.com/schemas/gui/components/list.schema.json";
281
- const title$u = "List Widget";
546
+ const $id$u = "https://golemui.com/schemas/gui/components/markdown.schema.json";
547
+ const title$u = "Markdown Widget";
282
548
  const type$u = "object";
283
- const $defs$u = { "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "itemsProp": { "type": "array", "description": "Items are either primitive values (string/number) or arbitrary record objects (paired with `labelField`/`valueField`/`itemRenderer` for custom rendering). Note: widget templates inside items are only supported on `repeater`, not here.", "items": { "type": ["string", "number", "object"] } }, "labelFieldProp": { "type": "string" }, "valueFieldProp": { "type": "string" }, "heightProp": { "type": "number" }, "itemHeightProp": { "type": "number" }, "itemRendererProp": { "type": "string" } };
549
+ const $defs$u = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "placeholderProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "counterModeProp": { "enum": ["remaining", "current"] }, "minimumHeightProp": { "type": "number" }, "autoGrowProp": { "type": "boolean" }, "defaultOpenPreviewProp": { "type": "boolean" }, "maxLengthProp": { "type": "number" }, "toolsProp": { "type": "array", "items": { "enum": ["H", "B", "I", "Q", "L", "OL", "UL", "|"] } }, "splitViewTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "toolbarAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "headingTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "boldTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "italicTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "strikethroughTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "quoteTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "linkTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "orderedListTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "unorderedListTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "autocompleteProp": { "type": "string" } };
284
550
  const allOf$u = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
285
- const properties$t = { "kind": { "const": "input" }, "type": { "const": "list" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": ["string", "number"] }, "props": { "type": "object", "properties": { "hint": { "$ref": "#/$defs/hintProp" }, "items": { "$ref": "#/$defs/itemsProp" }, "labelField": { "$ref": "#/$defs/labelFieldProp" }, "valueField": { "$ref": "#/$defs/valueFieldProp" }, "height": { "$ref": "#/$defs/heightProp" }, "itemHeight": { "$ref": "#/$defs/itemHeightProp" }, "itemRenderer": { "$ref": "#/$defs/itemRendererProp" } }, "patternProperties": { "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^items\\.[^.]+$": { "$ref": "#/$defs/itemsProp" }, "^labelField\\.[^.]+$": { "$ref": "#/$defs/labelFieldProp" }, "^valueField\\.[^.]+$": { "$ref": "#/$defs/valueFieldProp" }, "^height\\.[^.]+$": { "$ref": "#/$defs/heightProp" }, "^itemHeight\\.[^.]+$": { "$ref": "#/$defs/itemHeightProp" }, "^itemRenderer\\.[^.]+$": { "$ref": "#/$defs/itemRendererProp" } }, "additionalProperties": false } };
551
+ const properties$t = { "kind": { "const": "input" }, "type": { "const": "markdown" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "hint": { "$ref": "#/$defs/hintProp" }, "placeholder": { "$ref": "#/$defs/placeholderProp" }, "counterMode": { "$ref": "#/$defs/counterModeProp" }, "minimumHeight": { "$ref": "#/$defs/minimumHeightProp" }, "autoGrow": { "$ref": "#/$defs/autoGrowProp" }, "defaultOpenPreview": { "$ref": "#/$defs/defaultOpenPreviewProp" }, "maxLength": { "$ref": "#/$defs/maxLengthProp" }, "tools": { "$ref": "#/$defs/toolsProp" }, "splitViewTitle": { "$ref": "#/$defs/splitViewTitleProp" }, "toolbarAriaLabel": { "$ref": "#/$defs/toolbarAriaLabelProp" }, "headingTitle": { "$ref": "#/$defs/headingTitleProp" }, "boldTitle": { "$ref": "#/$defs/boldTitleProp" }, "italicTitle": { "$ref": "#/$defs/italicTitleProp" }, "strikethroughTitle": { "$ref": "#/$defs/strikethroughTitleProp" }, "quoteTitle": { "$ref": "#/$defs/quoteTitleProp" }, "linkTitle": { "$ref": "#/$defs/linkTitleProp" }, "orderedListTitle": { "$ref": "#/$defs/orderedListTitleProp" }, "unorderedListTitle": { "$ref": "#/$defs/unorderedListTitleProp" }, "autocomplete": { "$ref": "#/$defs/autocompleteProp" } }, "patternProperties": { "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^placeholder\\.[^.]+$": { "$ref": "#/$defs/placeholderProp" }, "^counterMode\\.[^.]+$": { "$ref": "#/$defs/counterModeProp" }, "^minimumHeight\\.[^.]+$": { "$ref": "#/$defs/minimumHeightProp" }, "^autoGrow\\.[^.]+$": { "$ref": "#/$defs/autoGrowProp" }, "^defaultOpenPreview\\.[^.]+$": { "$ref": "#/$defs/defaultOpenPreviewProp" }, "^maxLength\\.[^.]+$": { "$ref": "#/$defs/maxLengthProp" }, "^tools\\.[^.]+$": { "$ref": "#/$defs/toolsProp" }, "^splitViewTitle\\.[^.]+$": { "$ref": "#/$defs/splitViewTitleProp" }, "^toolbarAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toolbarAriaLabelProp" }, "^headingTitle\\.[^.]+$": { "$ref": "#/$defs/headingTitleProp" }, "^boldTitle\\.[^.]+$": { "$ref": "#/$defs/boldTitleProp" }, "^italicTitle\\.[^.]+$": { "$ref": "#/$defs/italicTitleProp" }, "^strikethroughTitle\\.[^.]+$": { "$ref": "#/$defs/strikethroughTitleProp" }, "^quoteTitle\\.[^.]+$": { "$ref": "#/$defs/quoteTitleProp" }, "^linkTitle\\.[^.]+$": { "$ref": "#/$defs/linkTitleProp" }, "^orderedListTitle\\.[^.]+$": { "$ref": "#/$defs/orderedListTitleProp" }, "^unorderedListTitle\\.[^.]+$": { "$ref": "#/$defs/unorderedListTitleProp" }, "^autocomplete\\.[^.]+$": { "$ref": "#/$defs/autocompleteProp" } }, "additionalProperties": false } };
286
552
  const patternProperties$n = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
287
553
  const required$t = ["kind", "type", "path"];
288
554
  const unevaluatedProperties$u = false;
289
- const listSchemaJson = {
555
+ const markdownSchemaJson = {
290
556
  $schema: $schema$u,
291
557
  $id: $id$u,
292
558
  title: title$u,
@@ -299,16 +565,16 @@ const listSchemaJson = {
299
565
  unevaluatedProperties: unevaluatedProperties$u
300
566
  };
301
567
  const $schema$t = "https://json-schema.org/draft/2020-12/schema";
302
- const $id$t = "https://golemui.com/schemas/gui/components/markdown.schema.json";
303
- const title$t = "Markdown Widget";
568
+ const $id$t = "https://golemui.com/schemas/gui/components/multidropdown.schema.json";
569
+ const title$t = "MultiDropdown Widget";
304
570
  const type$t = "object";
305
- const $defs$t = { "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "placeholderProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "counterModeProp": { "enum": ["remaining", "current"] }, "minimumHeightProp": { "type": "number" }, "autoGrowProp": { "type": "boolean" }, "defaultOpenPreviewProp": { "type": "boolean" }, "maxLengthProp": { "type": "number" }, "toolsProp": { "type": "array", "items": { "enum": ["H", "B", "I", "Q", "L", "OL", "UL", "|"] } }, "splitViewTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "toolbarAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "headingTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "boldTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "italicTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "strikethroughTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "quoteTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "linkTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "orderedListTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "unorderedListTitleProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "autocompleteProp": { "type": "string" } };
571
+ const $defs$t = { "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "placeholderProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "itemsProp": { "type": "array", "description": "Items are either primitive values (string/number) or arbitrary record objects (paired with `labelField`/`valueField`/`itemRenderer` for custom rendering). Note: widget templates inside items are only supported on `repeater`, not here.", "items": { "type": ["string", "number", "object"] } }, "labelFieldProp": { "type": "string", "description": 'Object property used as the display label when items are objects (e.g. `"name"` reads `item.name`)' }, "valueFieldProp": { "type": "string", "description": 'Object property used as the stored value when items are objects (e.g. `"id"` stores `item.id`)' }, "searchFieldsProp": { "type": "array", "description": "Object properties searched when the user types in the filter box. Defaults to `labelField` when omitted.", "items": { "type": "string" } }, "heightProp": { "type": "number", "description": "Fixed pixel height of the dropdown list panel (enables virtual scrolling for large lists)" }, "itemHeightProp": { "type": "number", "description": "Fixed pixel height of each item row, required for virtual scrolling when `height` is set" }, "itemRendererProp": { "type": "string", "description": "Name of a registered custom item renderer component used to display each option" }, "inputDebounceProp": { "type": "number", "description": "Milliseconds to debounce the filter input before firing the `on.filter` event (default: 0)" }, "autocompleteProp": { "type": "string", "description": "HTML `autocomplete` attribute applied to the underlying input element" }, "iconProp": { "type": "string" }, "toggleAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removeAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removeIconProp": { "type": "string" } };
306
572
  const allOf$t = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
307
- const properties$s = { "kind": { "const": "input" }, "type": { "const": "markdown" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "string" }, "props": { "type": "object", "properties": { "hint": { "$ref": "#/$defs/hintProp" }, "placeholder": { "$ref": "#/$defs/placeholderProp" }, "counterMode": { "$ref": "#/$defs/counterModeProp" }, "minimumHeight": { "$ref": "#/$defs/minimumHeightProp" }, "autoGrow": { "$ref": "#/$defs/autoGrowProp" }, "defaultOpenPreview": { "$ref": "#/$defs/defaultOpenPreviewProp" }, "maxLength": { "$ref": "#/$defs/maxLengthProp" }, "tools": { "$ref": "#/$defs/toolsProp" }, "splitViewTitle": { "$ref": "#/$defs/splitViewTitleProp" }, "toolbarAriaLabel": { "$ref": "#/$defs/toolbarAriaLabelProp" }, "headingTitle": { "$ref": "#/$defs/headingTitleProp" }, "boldTitle": { "$ref": "#/$defs/boldTitleProp" }, "italicTitle": { "$ref": "#/$defs/italicTitleProp" }, "strikethroughTitle": { "$ref": "#/$defs/strikethroughTitleProp" }, "quoteTitle": { "$ref": "#/$defs/quoteTitleProp" }, "linkTitle": { "$ref": "#/$defs/linkTitleProp" }, "orderedListTitle": { "$ref": "#/$defs/orderedListTitleProp" }, "unorderedListTitle": { "$ref": "#/$defs/unorderedListTitleProp" }, "autocomplete": { "$ref": "#/$defs/autocompleteProp" } }, "patternProperties": { "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^placeholder\\.[^.]+$": { "$ref": "#/$defs/placeholderProp" }, "^counterMode\\.[^.]+$": { "$ref": "#/$defs/counterModeProp" }, "^minimumHeight\\.[^.]+$": { "$ref": "#/$defs/minimumHeightProp" }, "^autoGrow\\.[^.]+$": { "$ref": "#/$defs/autoGrowProp" }, "^defaultOpenPreview\\.[^.]+$": { "$ref": "#/$defs/defaultOpenPreviewProp" }, "^maxLength\\.[^.]+$": { "$ref": "#/$defs/maxLengthProp" }, "^tools\\.[^.]+$": { "$ref": "#/$defs/toolsProp" }, "^splitViewTitle\\.[^.]+$": { "$ref": "#/$defs/splitViewTitleProp" }, "^toolbarAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toolbarAriaLabelProp" }, "^headingTitle\\.[^.]+$": { "$ref": "#/$defs/headingTitleProp" }, "^boldTitle\\.[^.]+$": { "$ref": "#/$defs/boldTitleProp" }, "^italicTitle\\.[^.]+$": { "$ref": "#/$defs/italicTitleProp" }, "^strikethroughTitle\\.[^.]+$": { "$ref": "#/$defs/strikethroughTitleProp" }, "^quoteTitle\\.[^.]+$": { "$ref": "#/$defs/quoteTitleProp" }, "^linkTitle\\.[^.]+$": { "$ref": "#/$defs/linkTitleProp" }, "^orderedListTitle\\.[^.]+$": { "$ref": "#/$defs/orderedListTitleProp" }, "^unorderedListTitle\\.[^.]+$": { "$ref": "#/$defs/unorderedListTitleProp" }, "^autocomplete\\.[^.]+$": { "$ref": "#/$defs/autocompleteProp" } }, "additionalProperties": false } };
573
+ const properties$s = { "kind": { "const": "input" }, "type": { "const": "multiDropdown" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "array", "items": { "type": ["string", "number"] } }, "props": { "type": "object", "required": ["items"], "properties": { "placeholder": { "$ref": "#/$defs/placeholderProp" }, "hint": { "$ref": "#/$defs/hintProp" }, "items": { "$ref": "#/$defs/itemsProp" }, "labelField": { "$ref": "#/$defs/labelFieldProp" }, "valueField": { "$ref": "#/$defs/valueFieldProp" }, "searchFields": { "$ref": "#/$defs/searchFieldsProp" }, "height": { "$ref": "#/$defs/heightProp" }, "itemHeight": { "$ref": "#/$defs/itemHeightProp" }, "itemRenderer": { "$ref": "#/$defs/itemRendererProp" }, "inputDebounce": { "$ref": "#/$defs/inputDebounceProp" }, "autocomplete": { "$ref": "#/$defs/autocompleteProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "toggleAriaLabel": { "$ref": "#/$defs/toggleAriaLabelProp" }, "removeAriaLabel": { "$ref": "#/$defs/removeAriaLabelProp" }, "removeIcon": { "$ref": "#/$defs/removeIconProp" } }, "patternProperties": { "^placeholder\\.[^.]+$": { "$ref": "#/$defs/placeholderProp" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^items\\.[^.]+$": { "$ref": "#/$defs/itemsProp" }, "^labelField\\.[^.]+$": { "$ref": "#/$defs/labelFieldProp" }, "^valueField\\.[^.]+$": { "$ref": "#/$defs/valueFieldProp" }, "^searchFields\\.[^.]+$": { "$ref": "#/$defs/searchFieldsProp" }, "^height\\.[^.]+$": { "$ref": "#/$defs/heightProp" }, "^itemHeight\\.[^.]+$": { "$ref": "#/$defs/itemHeightProp" }, "^itemRenderer\\.[^.]+$": { "$ref": "#/$defs/itemRendererProp" }, "^inputDebounce\\.[^.]+$": { "$ref": "#/$defs/inputDebounceProp" }, "^autocomplete\\.[^.]+$": { "$ref": "#/$defs/autocompleteProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^toggleAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toggleAriaLabelProp" }, "^removeAriaLabel\\.[^.]+$": { "$ref": "#/$defs/removeAriaLabelProp" }, "^removeIcon\\.[^.]+$": { "$ref": "#/$defs/removeIconProp" } }, "additionalProperties": false } };
308
574
  const patternProperties$m = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
309
- const required$s = ["kind", "type", "path"];
575
+ const required$s = ["kind", "type", "path", "props"];
310
576
  const unevaluatedProperties$t = false;
311
- const markdownSchemaJson = {
577
+ const multidropdownSchemaJson = {
312
578
  $schema: $schema$t,
313
579
  $id: $id$t,
314
580
  title: title$t,
@@ -321,16 +587,16 @@ const markdownSchemaJson = {
321
587
  unevaluatedProperties: unevaluatedProperties$t
322
588
  };
323
589
  const $schema$s = "https://json-schema.org/draft/2020-12/schema";
324
- const $id$s = "https://golemui.com/schemas/gui/components/multidropdown.schema.json";
325
- const title$s = "MultiDropdown Widget";
590
+ const $id$s = "https://golemui.com/schemas/gui/components/multifileupload.schema.json";
591
+ const title$s = "Multi File Upload Widget";
326
592
  const type$s = "object";
327
- const $defs$s = { "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "placeholderProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "itemsProp": { "type": "array", "description": "Items are either primitive values (string/number) or arbitrary record objects (paired with `labelField`/`valueField`/`itemRenderer` for custom rendering). Note: widget templates inside items are only supported on `repeater`, not here.", "items": { "type": ["string", "number", "object"] } }, "labelFieldProp": { "type": "string", "description": 'Object property used as the display label when items are objects (e.g. `"name"` reads `item.name`)' }, "valueFieldProp": { "type": "string", "description": 'Object property used as the stored value when items are objects (e.g. `"id"` stores `item.id`)' }, "searchFieldsProp": { "type": "array", "description": "Object properties searched when the user types in the filter box. Defaults to `labelField` when omitted.", "items": { "type": "string" } }, "heightProp": { "type": "number", "description": "Fixed pixel height of the dropdown list panel (enables virtual scrolling for large lists)" }, "itemHeightProp": { "type": "number", "description": "Fixed pixel height of each item row, required for virtual scrolling when `height` is set" }, "itemRendererProp": { "type": "string", "description": "Name of a registered custom item renderer component used to display each option" }, "inputDebounceProp": { "type": "number", "description": "Milliseconds to debounce the filter input before firing the `on.filter` event (default: 0)" }, "autocompleteProp": { "type": "string", "description": "HTML `autocomplete` attribute applied to the underlying input element" }, "iconProp": { "type": "string" }, "toggleAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removeAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removeIconProp": { "type": "string" } };
593
+ const $defs$s = { "disabledDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "readonlyDef": { "$ref": "../core/common.schema.json#/$defs/boolOrWhen" }, "labelDef": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "fileItem": { "type": "object", "description": 'One uploaded file as stored in the form value. `data` is whatever the host\'s `uploadService.upload` resolved with, verbatim. Preloaded values should carry `status: "uploaded"`.', "properties": { "id": { "type": "string", "description": "Synthetic id, stable for the life of the item" }, "name": { "type": "string" }, "size": { "type": "number", "description": "Size in bytes" }, "type": { "type": "string", "description": "MIME type" }, "status": { "enum": ["uploading", "uploaded", "error"] }, "error": { "type": "string", "description": "Human-readable reason when `status` is `error`" }, "data": { "description": "The server response, verbatim" } }, "required": ["id", "name", "size", "type", "status"], "additionalProperties": false }, "hintProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "iconProp": { "type": "string" }, "acceptProp": { "type": "array", "description": 'Accepted file types, e.g. `["image/*", ".pdf"]`. Files that do not match are refused before uploading.', "items": { "type": "string" } }, "maxSizeProp": { "type": "number", "description": "Maximum size per file, in bytes. Larger files are refused before uploading." }, "buttonLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removeAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "cancelAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "retryAriaLabelProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removeIconProp": { "type": "string" }, "retryIconProp": { "type": "string" }, "maxSizeMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "acceptMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "interruptedMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "missingServiceMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "uploadedMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "removedMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" }, "failedMessageProp": { "$ref": "../core/common.schema.json#/$defs/localizable" } };
328
594
  const allOf$s = [{ "$ref": "../core/common.schema.json#/$defs/baseWidget" }];
329
- const properties$r = { "kind": { "const": "input" }, "type": { "const": "multiDropdown" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "array", "items": { "type": ["string", "number"] } }, "props": { "type": "object", "required": ["items"], "properties": { "placeholder": { "$ref": "#/$defs/placeholderProp" }, "hint": { "$ref": "#/$defs/hintProp" }, "items": { "$ref": "#/$defs/itemsProp" }, "labelField": { "$ref": "#/$defs/labelFieldProp" }, "valueField": { "$ref": "#/$defs/valueFieldProp" }, "searchFields": { "$ref": "#/$defs/searchFieldsProp" }, "height": { "$ref": "#/$defs/heightProp" }, "itemHeight": { "$ref": "#/$defs/itemHeightProp" }, "itemRenderer": { "$ref": "#/$defs/itemRendererProp" }, "inputDebounce": { "$ref": "#/$defs/inputDebounceProp" }, "autocomplete": { "$ref": "#/$defs/autocompleteProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "toggleAriaLabel": { "$ref": "#/$defs/toggleAriaLabelProp" }, "removeAriaLabel": { "$ref": "#/$defs/removeAriaLabelProp" }, "removeIcon": { "$ref": "#/$defs/removeIconProp" } }, "patternProperties": { "^placeholder\\.[^.]+$": { "$ref": "#/$defs/placeholderProp" }, "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^items\\.[^.]+$": { "$ref": "#/$defs/itemsProp" }, "^labelField\\.[^.]+$": { "$ref": "#/$defs/labelFieldProp" }, "^valueField\\.[^.]+$": { "$ref": "#/$defs/valueFieldProp" }, "^searchFields\\.[^.]+$": { "$ref": "#/$defs/searchFieldsProp" }, "^height\\.[^.]+$": { "$ref": "#/$defs/heightProp" }, "^itemHeight\\.[^.]+$": { "$ref": "#/$defs/itemHeightProp" }, "^itemRenderer\\.[^.]+$": { "$ref": "#/$defs/itemRendererProp" }, "^inputDebounce\\.[^.]+$": { "$ref": "#/$defs/inputDebounceProp" }, "^autocomplete\\.[^.]+$": { "$ref": "#/$defs/autocompleteProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^toggleAriaLabel\\.[^.]+$": { "$ref": "#/$defs/toggleAriaLabelProp" }, "^removeAriaLabel\\.[^.]+$": { "$ref": "#/$defs/removeAriaLabelProp" }, "^removeIcon\\.[^.]+$": { "$ref": "#/$defs/removeIconProp" } }, "additionalProperties": false } };
330
- const patternProperties$l = { "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
331
- const required$r = ["kind", "type", "path", "props"];
595
+ const properties$r = { "kind": { "const": "input" }, "type": { "const": "multiFileUpload" }, "path": { "$ref": "../core/common.schema.json#/$defs/dotPath" }, "label": { "$ref": "#/$defs/labelDef" }, "disabled": { "$ref": "#/$defs/disabledDef" }, "readonly": { "$ref": "#/$defs/readonlyDef" }, "on": { "$ref": "../core/common.schema.json#/$defs/on" }, "validator": { "$ref": "../validators.schema.json#/$defs/validator" }, "defaultValue": { "type": "array", "items": { "$ref": "#/$defs/fileItem" } }, "props": { "type": "object", "properties": { "hint": { "$ref": "#/$defs/hintProp" }, "icon": { "$ref": "#/$defs/iconProp" }, "accept": { "$ref": "#/$defs/acceptProp" }, "maxSize": { "$ref": "#/$defs/maxSizeProp" }, "buttonLabel": { "$ref": "#/$defs/buttonLabelProp" }, "removeAriaLabel": { "$ref": "#/$defs/removeAriaLabelProp" }, "cancelAriaLabel": { "$ref": "#/$defs/cancelAriaLabelProp" }, "retryAriaLabel": { "$ref": "#/$defs/retryAriaLabelProp" }, "removeIcon": { "$ref": "#/$defs/removeIconProp" }, "retryIcon": { "$ref": "#/$defs/retryIconProp" }, "maxSizeMessage": { "$ref": "#/$defs/maxSizeMessageProp" }, "acceptMessage": { "$ref": "#/$defs/acceptMessageProp" }, "interruptedMessage": { "$ref": "#/$defs/interruptedMessageProp" }, "missingServiceMessage": { "$ref": "#/$defs/missingServiceMessageProp" }, "uploadedMessage": { "$ref": "#/$defs/uploadedMessageProp" }, "removedMessage": { "$ref": "#/$defs/removedMessageProp" }, "failedMessage": { "$ref": "#/$defs/failedMessageProp" } }, "patternProperties": { "^hint\\.[^.]+$": { "$ref": "#/$defs/hintProp" }, "^icon\\.[^.]+$": { "$ref": "#/$defs/iconProp" }, "^accept\\.[^.]+$": { "$ref": "#/$defs/acceptProp" }, "^maxSize\\.[^.]+$": { "$ref": "#/$defs/maxSizeProp" }, "^buttonLabel\\.[^.]+$": { "$ref": "#/$defs/buttonLabelProp" }, "^removeAriaLabel\\.[^.]+$": { "$ref": "#/$defs/removeAriaLabelProp" }, "^cancelAriaLabel\\.[^.]+$": { "$ref": "#/$defs/cancelAriaLabelProp" }, "^retryAriaLabel\\.[^.]+$": { "$ref": "#/$defs/retryAriaLabelProp" }, "^removeIcon\\.[^.]+$": { "$ref": "#/$defs/removeIconProp" }, "^retryIcon\\.[^.]+$": { "$ref": "#/$defs/retryIconProp" }, "^maxSizeMessage\\.[^.]+$": { "$ref": "#/$defs/maxSizeMessageProp" }, "^acceptMessage\\.[^.]+$": { "$ref": "#/$defs/acceptMessageProp" }, "^interruptedMessage\\.[^.]+$": { "$ref": "#/$defs/interruptedMessageProp" }, "^missingServiceMessage\\.[^.]+$": { "$ref": "#/$defs/missingServiceMessageProp" }, "^uploadedMessage\\.[^.]+$": { "$ref": "#/$defs/uploadedMessageProp" }, "^removedMessage\\.[^.]+$": { "$ref": "#/$defs/removedMessageProp" }, "^failedMessage\\.[^.]+$": { "$ref": "#/$defs/failedMessageProp" } }, "additionalProperties": false } };
596
+ const patternProperties$l = { "^disabled\\.[^.]+$": { "$ref": "#/$defs/disabledDef" }, "^readonly\\.[^.]+$": { "$ref": "#/$defs/readonlyDef" }, "^label\\.[^.]+$": { "$ref": "#/$defs/labelDef" }, "^validator\\.[^.]+$": { "$ref": "../validators.schema.json#/$defs/validator" } };
597
+ const required$r = ["kind", "type", "path"];
332
598
  const unevaluatedProperties$s = false;
333
- const multidropdownSchemaJson = {
599
+ const multifileuploadSchemaJson = {
334
600
  $schema: $schema$s,
335
601
  $id: $id$s,
336
602
  title: title$s,
@@ -959,9 +1225,11 @@ const datepickerSchema = datepickerSchemaJson;
959
1225
  const datetimeinputSchema = datetimeinputSchemaJson;
960
1226
  const datetimepickerSchema = datetimepickerSchemaJson;
961
1227
  const dropdownSchema = dropdownSchemaJson;
1228
+ const fileuploadSchema = fileuploadSchemaJson;
962
1229
  const listSchema = listSchemaJson;
963
1230
  const markdownSchema = markdownSchemaJson;
964
1231
  const multidropdownSchema = multidropdownSchemaJson;
1232
+ const multifileuploadSchema = multifileuploadSchemaJson;
965
1233
  const multilistSchema = multilistSchemaJson;
966
1234
  const numberSchema = numberSchemaJson;
967
1235
  const passwordSchema = passwordSchemaJson;
@@ -1000,9 +1268,11 @@ const COMPONENT_SCHEMAS_BY_TYPE = {
1000
1268
  dateTimeInput: datetimeinputSchema,
1001
1269
  dateTimePicker: datetimepickerSchema,
1002
1270
  dropdown: dropdownSchema,
1271
+ fileUpload: fileuploadSchema,
1003
1272
  list: listSchema,
1004
1273
  markdown: markdownSchema,
1005
1274
  multiDropdown: multidropdownSchema,
1275
+ multiFileUpload: multifileuploadSchema,
1006
1276
  multiList: multilistSchema,
1007
1277
  number: numberSchema,
1008
1278
  password: passwordSchema,
@@ -1089,6 +1359,8 @@ const VALIDATOR_TYPE_TO_DEF = {
1089
1359
  integer: "numberValidator",
1090
1360
  boolean: "booleanValidator",
1091
1361
  array: "arrayValidator",
1362
+ file: "fileValidator",
1363
+ files: "filesValidator",
1092
1364
  custom: "customValidator"
1093
1365
  };
1094
1366
  function getValidatorBranches() {
@@ -1425,388 +1697,166 @@ function collapseOneOfErrors(errors, dataRoot) {
1425
1697
  }
1426
1698
  const widgetErrors = [];
1427
1699
  const warnings = [];
1428
- const form = dataRoot?.form;
1429
- if (Array.isArray(form)) {
1430
- form.forEach((widget, i) => {
1431
- collectWidgetErrors(widget, `/form/${i}`, widgetErrors, warnings);
1432
- });
1433
- }
1434
- return { errors: [...topLevel, ...widgetErrors], warnings };
1435
- }
1436
- function isChunkRef(widget) {
1437
- return typeof widget === "object" && widget !== null && !Array.isArray(widget) && "$ref" in widget;
1438
- }
1439
- function collectWidgetErrors(widget, widgetPath, out, warnings) {
1440
- if (isChunkRef(widget)) {
1441
- const chunkRefValidator2 = getChunkRefValidator();
1442
- chunkRefValidator2(widget);
1443
- for (const e of chunkRefValidator2.errors ?? []) {
1444
- out.push({ ...e, instancePath: widgetPath + e.instancePath });
1445
- }
1446
- return;
1447
- }
1448
- const declaredType = widget?.type;
1449
- if (typeof declaredType === "string" && SCHEMALESS_WIDGET_TYPES.has(declaredType)) {
1450
- out.push({
1451
- keyword: "schemalessType",
1452
- instancePath: `${widgetPath}/type`,
1453
- schemaPath: "",
1454
- params: { type: declaredType },
1455
- message: `Widget type \`${declaredType}\` has no JSON representation`
1456
- });
1457
- recurseIntoChildren(widget, widgetPath, out, warnings);
1458
- return;
1459
- }
1460
- const intended = pickIntendedBranch(widget);
1461
- if (!intended) {
1462
- const widgetType = widget?.type;
1463
- if (typeof widgetType !== "string" || !widgetType) {
1464
- out.push({
1465
- keyword: "required",
1466
- instancePath: widgetPath,
1467
- schemaPath: "",
1468
- params: { missingProperty: "type" },
1469
- message: `Widget at ${widgetPath} is missing or has an invalid \`type\``
1470
- });
1471
- } else {
1472
- warnings.push({
1473
- path: `${widgetPath}/type`,
1474
- keyword: "customWidget",
1475
- message: `Widget type \`${widgetType}\` at \`${widgetPath}\` is not a built-in GolemUI widget - assumed custom. Its props were not validated.`,
1476
- suggestion: "Built-in widget types: " + Object.keys(COMPONENT_SCHEMAS).join(", ") + ". If this is intentional (a custom widget registered via the framework loader), you can ignore this warning.",
1477
- params: { type: widgetType }
1478
- });
1479
- collectCustomWidgetErrors(widget, widgetPath, out);
1480
- }
1481
- recurseIntoChildren(widget, widgetPath, out, warnings);
1482
- return;
1483
- }
1484
- const validator = getShallowWidgetValidator(intended.type);
1485
- if (validator) {
1486
- validator(widget);
1487
- for (const e of validator.errors ?? []) {
1488
- out.push({
1489
- ...e,
1490
- instancePath: widgetPath + e.instancePath
1491
- });
1492
- }
1493
- }
1494
- collectValidatorFieldErrors(widget, widgetPath, out);
1495
- recurseIntoChildren(widget, widgetPath, out, warnings, intended.type);
1496
- }
1497
- function collectCustomWidgetErrors(widget, widgetPath, out) {
1498
- const kind = widget?.kind;
1499
- if (typeof kind !== "string") {
1500
- out.push({
1501
- keyword: "required",
1502
- instancePath: widgetPath,
1503
- schemaPath: "",
1504
- params: { missingProperty: "kind" },
1505
- message: `Widget at ${widgetPath} is missing or has an invalid \`kind\``
1506
- });
1507
- return;
1508
- }
1509
- const validator = getCustomWidgetValidator(kind);
1510
- if (!validator) {
1511
- out.push({
1512
- keyword: "enum",
1513
- instancePath: `${widgetPath}/kind`,
1514
- schemaPath: "",
1515
- params: { allowedValues: getCustomWidgetKinds() },
1516
- message: `Widget kind is not one of ${getCustomWidgetKinds().join(", ")}`,
1517
- data: kind
1518
- });
1519
- return;
1520
- }
1521
- validator(widget);
1522
- const branchErrors = validator.errors ?? [];
1523
- const hasSpecificError = branchErrors.some((e) => e.keyword !== "unevaluatedProperties");
1524
- for (const e of branchErrors) {
1525
- if (hasSpecificError && e.keyword === "unevaluatedProperties") continue;
1526
- out.push({ ...e, instancePath: widgetPath + e.instancePath });
1527
- }
1528
- if (kind === "input") {
1529
- collectValidatorFieldErrors(widget, widgetPath, out);
1530
- }
1531
- }
1532
- function collectValidatorFieldErrors(widget, widgetPath, out) {
1533
- if (!widget || typeof widget !== "object" || Array.isArray(widget)) return;
1534
- const w = widget;
1535
- if (w["validator"] && typeof w["validator"] === "object") {
1536
- collectValidatorErrors(w["validator"], `${widgetPath}/validator`, out);
1537
- }
1538
- for (const [key, value] of Object.entries(w)) {
1539
- if (key.startsWith("validator.") && value && typeof value === "object") {
1540
- collectValidatorErrors(value, `${widgetPath}/${key}`, out);
1541
- }
1542
- }
1543
- }
1544
- function recurseIntoChildren(widget, widgetPath, out, warnings, resolvedType) {
1545
- const w = widget;
1546
- if (Array.isArray(w?.children)) {
1547
- w.children.forEach((child, i) => {
1548
- collectWidgetErrors(child, `${widgetPath}/children/${i}`, out, warnings);
1549
- });
1550
- }
1551
- if ((resolvedType ?? w?.type) === "repeater" && w?.props?.template) {
1552
- collectWidgetErrors(w.props.template, `${widgetPath}/props/template`, out, warnings);
1553
- }
1554
- }
1555
- function collectValidatorErrors(validator, path, out) {
1556
- const v = validator;
1557
- const t = typeof v.type === "string" ? v.type : null;
1558
- const branches = getValidatorBranches();
1559
- const matchedType = t && branches.includes(t) ? t : t ? nearest(t, branches) : void 0;
1560
- if (!matchedType) {
1561
- out.push({
1562
- keyword: "enum",
1563
- instancePath: `${path}/type`,
1564
- schemaPath: "",
1565
- params: { allowedValues: branches },
1566
- message: `Validator type is not one of ${branches.join(", ")}`,
1567
- data: t
1568
- });
1569
- return;
1570
- }
1571
- const compiled = getValidatorBranchValidator(matchedType);
1572
- if (!compiled) return;
1573
- compiled(validator);
1574
- for (const e of compiled.errors ?? []) {
1575
- out.push({ ...e, instancePath: path + e.instancePath });
1576
- }
1577
- }
1578
- function dedupe(errors) {
1579
- const seen = /* @__PURE__ */ new Set();
1580
- const result = [];
1581
- for (const e of errors) {
1582
- const key = `${e.path}|${e.keyword}|${e.message}`;
1583
- if (seen.has(key)) continue;
1584
- seen.add(key);
1585
- result.push(e);
1586
- }
1587
- return result;
1588
- }
1589
- function lintReactiveExpressions(formDefinition) {
1590
- const findings = [];
1591
- walk$2(formDefinition, "", findings, false, false);
1592
- return findings;
1593
- }
1594
- function checkReactiveExpression(expression, path = "", options = {}) {
1595
- const out = [];
1596
- checkExpression(expression, path, out, options.inRepeaterTemplate === true);
1597
- return out;
1598
- }
1599
- function walk$2(node, path, out, inTemplate, propsOfRepeater) {
1600
- if (node === null || typeof node !== "object") return;
1601
- if (Array.isArray(node)) {
1602
- node.forEach((item, i) => walk$2(item, `${path}/${i}`, out, inTemplate, false));
1603
- return;
1604
- }
1605
- const obj = node;
1606
- for (const key of ["include", "exclude"]) {
1607
- const child = obj[key];
1608
- if (child && typeof child === "object" && "when" in child) {
1609
- const expr = child.when;
1610
- if (typeof expr === "string") {
1611
- checkExpression(expr, `${path}/${key}/when`, out, inTemplate);
1612
- }
1613
- }
1614
- }
1615
- if (path === "" && obj["states"] && typeof obj["states"] === "object") {
1616
- for (const [name, expr] of Object.entries(obj["states"])) {
1617
- if (typeof expr === "string") {
1618
- checkExpression(expr, `/states/${name}`, out, false);
1619
- }
1620
- }
1621
- }
1622
- for (const [k, v] of Object.entries(obj)) {
1623
- if (v && typeof v === "object" && !Array.isArray(v) && "when" in v) {
1624
- const expr = v.when;
1625
- if (typeof expr === "string" && k !== "include" && k !== "exclude") {
1626
- checkExpression(expr, `${path}/${k}/when`, out, inTemplate);
1627
- }
1628
- }
1629
- if (typeof v === "object" && v !== null) {
1630
- const childInTemplate = inTemplate || propsOfRepeater && k === "template";
1631
- walk$2(v, `${path}/${k}`, out, childInTemplate, obj["type"] === "repeater" && k === "props");
1632
- }
1633
- }
1634
- }
1635
- function checkExpression(expr, path, out, inTemplate) {
1636
- const trimmed = expr.trim();
1637
- if (!trimmed) {
1638
- out.push({ path, expression: expr, message: "Expression is empty." });
1639
- return;
1640
- }
1641
- const stack = [];
1642
- const pairs = { ")": "(", "]": "[", "}": "{" };
1643
- for (const ch of trimmed) {
1644
- if ("([{".includes(ch)) stack.push(ch);
1645
- else if (")]}".includes(ch)) {
1646
- if (stack.pop() !== pairs[ch]) {
1647
- out.push({
1648
- path,
1649
- expression: expr,
1650
- message: `Unbalanced \`${ch}\` in reactive expression.`
1651
- });
1652
- return;
1653
- }
1654
- }
1655
- }
1656
- if (stack.length) {
1657
- out.push({
1658
- path,
1659
- expression: expr,
1660
- message: `Unclosed \`${stack[stack.length - 1]}\` in reactive expression.`
1661
- });
1662
- return;
1663
- }
1664
- const referencesItemScope = /\$item\b|\$index\b/.test(trimmed);
1665
- const hasGlobalRoot = /\$form\b|\$meta\b|\$formIsInvalid\b|\$fn\b/.test(trimmed);
1666
- if (referencesItemScope && !inTemplate) {
1667
- out.push({
1668
- path,
1669
- expression: expr,
1670
- message: "Expression references `$item` or `$index`, which are only available inside a repeater `props.template`.",
1671
- suggestion: "Move the widget inside the repeater template, or read the data through `$form` (e.g. `$form.lineItems?.[0]?.quantity`)."
1672
- });
1673
- } else if (!hasGlobalRoot && !(inTemplate && referencesItemScope)) {
1674
- out.push({
1675
- path,
1676
- expression: expr,
1677
- message: "Expression does not reference `$form`, `$meta`, `$formIsInvalid`, or `$fn`.",
1678
- suggestion: "GolemUI expressions read form data via `$form.fieldName`, form metadata via `$meta.key`, or the built-in `$formIsInvalid` boolean. Host-provided pure functions are callable via `$fn.functionName(...)` when the host passes a `functions` map in the form init config. Inside a repeater `props.template` the current item is available via `$item` and its position via `$index`. Did you forget the prefix?"
1679
- });
1680
- }
1681
- if (/(?<![=!<>])=(?![=>])/.test(trimmed)) {
1682
- out.push({
1683
- path,
1684
- expression: expr,
1685
- message: "Expression contains a single `=` (assignment). Reactive expressions are read-only.",
1686
- suggestion: "Use `===` for equality comparison."
1687
- });
1688
- }
1689
- if (/(?<![&])&(?![&])/.test(trimmed) || /(?<![|])\|(?![|])/.test(trimmed)) {
1690
- out.push({
1691
- path,
1692
- expression: expr,
1693
- message: "Expression contains a single `&` or `|` (bitwise).",
1694
- suggestion: "Use `&&` for logical AND, `||` for logical OR."
1695
- });
1696
- }
1697
- if (/(?<![=!])==(?!=)/.test(trimmed) || /(?<![!])!=(?!=)/.test(trimmed)) {
1698
- out.push({
1699
- path,
1700
- expression: expr,
1701
- message: "Expression uses loose equality (`==` or `!=`).",
1702
- suggestion: "Use strict equality `===` / `!==` to avoid type coercion (e.g. `$form.x !== undefined` rather than `$form.x != null`)."
1700
+ const form = dataRoot?.form;
1701
+ if (Array.isArray(form)) {
1702
+ form.forEach((widget, i) => {
1703
+ collectWidgetErrors(widget, `/form/${i}`, widgetErrors, warnings);
1703
1704
  });
1704
1705
  }
1705
- if (/(?<![=!])!\s*\$(?:form|meta|item)\b/.test(trimmed)) {
1706
+ return { errors: [...topLevel, ...widgetErrors], warnings };
1707
+ }
1708
+ function isChunkRef(widget) {
1709
+ return typeof widget === "object" && widget !== null && !Array.isArray(widget) && "$ref" in widget;
1710
+ }
1711
+ function collectWidgetErrors(widget, widgetPath, out, warnings) {
1712
+ if (isChunkRef(widget)) {
1713
+ const chunkRefValidator2 = getChunkRefValidator();
1714
+ chunkRefValidator2(widget);
1715
+ for (const e of chunkRefValidator2.errors ?? []) {
1716
+ out.push({ ...e, instancePath: widgetPath + e.instancePath });
1717
+ }
1718
+ return;
1719
+ }
1720
+ const declaredType = widget?.type;
1721
+ if (typeof declaredType === "string" && SCHEMALESS_WIDGET_TYPES.has(declaredType)) {
1706
1722
  out.push({
1707
- path,
1708
- expression: expr,
1709
- message: "Expression negates a `$form`/`$meta`/`$item` reference (relies on truthy/falsy coercion).",
1710
- suggestion: 'Form data values can be `undefined`. Pick the case you actually mean and write it explicitly — `$form.x === undefined`, `$form.x === null`, `$form.x === 0`, `$form.x === ""` — instead of `!$form.x`.'
1723
+ keyword: "schemalessType",
1724
+ instancePath: `${widgetPath}/type`,
1725
+ schemaPath: "",
1726
+ params: { type: declaredType },
1727
+ message: `Widget type \`${declaredType}\` has no JSON representation`
1711
1728
  });
1729
+ recurseIntoChildren(widget, widgetPath, out, warnings);
1730
+ return;
1712
1731
  }
1713
- const refChainRe = /\$(?:form|meta|item)\b((?:\.[\w?]+)*)/g;
1714
- let chainFlagged = false;
1715
- let chainMatch;
1716
- while ((chainMatch = refChainRe.exec(trimmed)) !== null) {
1717
- const chain = chainMatch[1];
1718
- if (!chain) continue;
1719
- const segments = chain.split(".").filter(Boolean);
1720
- let unsafe = false;
1721
- for (let i = 0; i < segments.length - 1; i++) {
1722
- const segment = segments[i];
1723
- if (!segment || !segment.endsWith("?")) {
1724
- unsafe = true;
1725
- break;
1726
- }
1727
- }
1728
- if (unsafe && !chainFlagged) {
1732
+ const intended = pickIntendedBranch(widget);
1733
+ if (!intended) {
1734
+ const widgetType = widget?.type;
1735
+ if (typeof widgetType !== "string" || !widgetType) {
1729
1736
  out.push({
1730
- path,
1731
- expression: expr,
1732
- message: "Expression chains nested property access without optional chaining (e.g. `$form.user.name`).",
1733
- suggestion: "Treat every nested property as possibly `undefined`. Use `?.` between segments: `$form.user?.name` instead of `$form.user.name`. The runtime throws if `$form.user` is undefined."
1737
+ keyword: "required",
1738
+ instancePath: widgetPath,
1739
+ schemaPath: "",
1740
+ params: { missingProperty: "type" },
1741
+ message: `Widget at ${widgetPath} is missing or has an invalid \`type\``
1734
1742
  });
1735
- chainFlagged = true;
1743
+ } else {
1744
+ warnings.push({
1745
+ path: `${widgetPath}/type`,
1746
+ keyword: "customWidget",
1747
+ message: `Widget type \`${widgetType}\` at \`${widgetPath}\` is not a built-in GolemUI widget - assumed custom. Its props were not validated.`,
1748
+ suggestion: "Built-in widget types: " + Object.keys(COMPONENT_SCHEMAS).join(", ") + ". If this is intentional (a custom widget registered via the framework loader), you can ignore this warning.",
1749
+ params: { type: widgetType }
1750
+ });
1751
+ collectCustomWidgetErrors(widget, widgetPath, out);
1736
1752
  }
1753
+ recurseIntoChildren(widget, widgetPath, out, warnings);
1754
+ return;
1737
1755
  }
1738
- const refOnly = /^\$(?:form|meta|item)(?:\.[\w?]+)*$/;
1739
- const refBeforeBool = /\$(?:form|meta|item)(?:\.[\w?]+)*\s*(?:&&|\|\||\?(?![.?]))/;
1740
- const refAfterBool = /(?:&&|\|\|)\s*\$(?:form|meta|item)(?:\.[\w?]+)*\s*$/;
1741
- if (refOnly.test(trimmed) || refBeforeBool.test(trimmed) || refAfterBool.test(trimmed)) {
1742
- out.push({
1743
- path,
1744
- expression: expr,
1745
- message: "Expression uses `$form`/`$meta` directly as a boolean (relies on truthy/falsy coercion).",
1746
- suggestion: 'Form data values can be `undefined`. Compare explicitly: `$form.x !== undefined`, `$form.x === "value"`, `$form.items?.length > 0`. For default values use nullish coalescing: `$form.x ?? defaultValue`.'
1747
- });
1748
- }
1749
- const refForCmpRe = /\$(?:form|meta|item)(?:\.[\w?]+)+/g;
1750
- let r5Flagged = false;
1751
- let cmpMatch;
1752
- while ((cmpMatch = refForCmpRe.exec(trimmed)) !== null) {
1753
- const start = cmpMatch.index;
1754
- const end = start + cmpMatch[0].length;
1755
- const before = trimmed.slice(0, start).trimEnd();
1756
- const after = trimmed.slice(end).trimStart();
1757
- const opAfter = /^(?:<=?|>=?|[+\-*/%])(?!=)/.test(after);
1758
- const opBefore = /(?<![=!])[<>+\-*/%]$/.test(before);
1759
- if (!(opAfter || opBefore)) continue;
1760
- if (/&&|\|\|/.test(before)) continue;
1761
- if (!r5Flagged) {
1756
+ const validator = getShallowWidgetValidator(intended.type);
1757
+ if (validator) {
1758
+ validator(widget);
1759
+ for (const e of validator.errors ?? []) {
1762
1760
  out.push({
1763
- path,
1764
- expression: expr,
1765
- message: "Expression applies a comparison or arithmetic operator to a `$form`/`$meta` reference whose leaf may be `undefined`.",
1766
- suggestion: "Guard the value first: `$form.x !== undefined && $form.x > 180`. Or default it: `($form.x ?? 0) > 180`. Strict equality (`$form.x === 180`) is also safe since it evaluates to `false` when undefined."
1761
+ ...e,
1762
+ instancePath: widgetPath + e.instancePath
1767
1763
  });
1768
- r5Flagged = true;
1769
1764
  }
1770
1765
  }
1766
+ collectValidatorFieldErrors(widget, widgetPath, out);
1767
+ recurseIntoChildren(widget, widgetPath, out, warnings, intended.type);
1771
1768
  }
1772
- function checkBooleanValidatorRules(validator, path) {
1773
- const findings = [];
1774
- const requiredIsTrue = validator.required === true;
1775
- const constPresent = "const" in validator && validator.const !== void 0;
1776
- if (requiredIsTrue && !constPresent) {
1777
- findings.push({
1778
- path,
1779
- message: "Boolean validator has `required: true` but no `const` — this does NOT force the checkbox to be checked: `false` is a valid boolean and passes; `required` only rejects a missing value (`undefined`/`null`).",
1780
- suggestion: "If this checkbox must be checked (e.g. terms acceptance), add `const: true` and set `messages.invalid` and `messages.const` to the same user-facing text. If a false value is genuinely acceptable, ignore this warning."
1769
+ function collectCustomWidgetErrors(widget, widgetPath, out) {
1770
+ const kind = widget?.kind;
1771
+ if (typeof kind !== "string") {
1772
+ out.push({
1773
+ keyword: "required",
1774
+ instancePath: widgetPath,
1775
+ schemaPath: "",
1776
+ params: { missingProperty: "kind" },
1777
+ message: `Widget at ${widgetPath} is missing or has an invalid \`kind\``
1781
1778
  });
1779
+ return;
1782
1780
  }
1783
- if (constPresent && !requiredIsTrue) {
1784
- findings.push({
1785
- path,
1786
- message: "Boolean validator has `const` but no `required: true` — the pristine value passes: a never-touched checkbox holds `undefined`, and non-required validators skip validation entirely for `undefined`.",
1787
- suggestion: "Add `required: true` so the untouched state fails too, and set `messages.invalid` and `messages.const` to the same user-facing text."
1781
+ const validator = getCustomWidgetValidator(kind);
1782
+ if (!validator) {
1783
+ out.push({
1784
+ keyword: "enum",
1785
+ instancePath: `${widgetPath}/kind`,
1786
+ schemaPath: "",
1787
+ params: { allowedValues: getCustomWidgetKinds() },
1788
+ message: `Widget kind is not one of ${getCustomWidgetKinds().join(", ")}`,
1789
+ data: kind
1788
1790
  });
1791
+ return;
1792
+ }
1793
+ validator(widget);
1794
+ const branchErrors = validator.errors ?? [];
1795
+ const hasSpecificError = branchErrors.some((e) => e.keyword !== "unevaluatedProperties");
1796
+ for (const e of branchErrors) {
1797
+ if (hasSpecificError && e.keyword === "unevaluatedProperties") continue;
1798
+ out.push({ ...e, instancePath: widgetPath + e.instancePath });
1799
+ }
1800
+ if (kind === "input") {
1801
+ collectValidatorFieldErrors(widget, widgetPath, out);
1789
1802
  }
1790
- return findings;
1791
1803
  }
1792
- function lintBooleanValidators(formDefinition) {
1793
- const findings = [];
1794
- walk$1(formDefinition, "", findings);
1795
- return findings;
1804
+ function collectValidatorFieldErrors(widget, widgetPath, out) {
1805
+ if (!widget || typeof widget !== "object" || Array.isArray(widget)) return;
1806
+ const w = widget;
1807
+ if (w["validator"] && typeof w["validator"] === "object") {
1808
+ collectValidatorErrors(w["validator"], `${widgetPath}/validator`, out);
1809
+ }
1810
+ for (const [key, value] of Object.entries(w)) {
1811
+ if (key.startsWith("validator.") && value && typeof value === "object") {
1812
+ collectValidatorErrors(value, `${widgetPath}/${key}`, out);
1813
+ }
1814
+ }
1796
1815
  }
1797
- function walk$1(node, path, out) {
1798
- if (node === null || typeof node !== "object") return;
1799
- if (Array.isArray(node)) {
1800
- node.forEach((item, i) => walk$1(item, `${path}/${i}`, out));
1816
+ function recurseIntoChildren(widget, widgetPath, out, warnings, resolvedType) {
1817
+ const w = widget;
1818
+ if (Array.isArray(w?.children)) {
1819
+ w.children.forEach((child, i) => {
1820
+ collectWidgetErrors(child, `${widgetPath}/children/${i}`, out, warnings);
1821
+ });
1822
+ }
1823
+ if ((resolvedType ?? w?.type) === "repeater" && w?.props?.template) {
1824
+ collectWidgetErrors(w.props.template, `${widgetPath}/props/template`, out, warnings);
1825
+ }
1826
+ }
1827
+ function collectValidatorErrors(validator, path, out) {
1828
+ const v = validator;
1829
+ const t = typeof v.type === "string" ? v.type : null;
1830
+ const branches = getValidatorBranches();
1831
+ const matchedType = t && branches.includes(t) ? t : t ? nearest(t, branches) : void 0;
1832
+ if (!matchedType) {
1833
+ out.push({
1834
+ keyword: "enum",
1835
+ instancePath: `${path}/type`,
1836
+ schemaPath: "",
1837
+ params: { allowedValues: branches },
1838
+ message: `Validator type is not one of ${branches.join(", ")}`,
1839
+ data: t
1840
+ });
1801
1841
  return;
1802
1842
  }
1803
- const obj = node;
1804
- for (const [key, value] of Object.entries(obj)) {
1805
- if ((key === "validator" || key.startsWith("validator.")) && value !== null && typeof value === "object" && !Array.isArray(value) && value["type"] === "boolean") {
1806
- out.push(...checkBooleanValidatorRules(value, `${path}/${key}`));
1807
- }
1808
- walk$1(value, `${path}/${key}`, out);
1843
+ const compiled = getValidatorBranchValidator(matchedType);
1844
+ if (!compiled) return;
1845
+ compiled(validator);
1846
+ for (const e of compiled.errors ?? []) {
1847
+ out.push({ ...e, instancePath: path + e.instancePath });
1848
+ }
1849
+ }
1850
+ function dedupe(errors) {
1851
+ const seen = /* @__PURE__ */ new Set();
1852
+ const result = [];
1853
+ for (const e of errors) {
1854
+ const key = `${e.path}|${e.keyword}|${e.message}`;
1855
+ if (seen.has(key)) continue;
1856
+ seen.add(key);
1857
+ result.push(e);
1809
1858
  }
1859
+ return result;
1810
1860
  }
1811
1861
  function lintStringInterpolations(formDefinition) {
1812
1862
  const findings = [];
@@ -2662,6 +2712,45 @@ const EXAMPLES = {
2662
2712
  items: ["Cheese", "Bacon", "Mushrooms"]
2663
2713
  }
2664
2714
  },
2715
+ fileUpload: {
2716
+ kind: "input",
2717
+ type: "fileUpload",
2718
+ path: "cv",
2719
+ label: "CV",
2720
+ props: {
2721
+ accept: ["application/pdf", ".docx"],
2722
+ maxSize: 5242880,
2723
+ buttonLabel: "Upload CV",
2724
+ hint: "PDF or Word, 5 MB max"
2725
+ },
2726
+ validator: {
2727
+ type: "file",
2728
+ required: true,
2729
+ messages: {
2730
+ required: "Please upload your CV",
2731
+ pendingUploads: "Wait for the upload to finish"
2732
+ }
2733
+ }
2734
+ },
2735
+ multiFileUpload: {
2736
+ kind: "input",
2737
+ type: "multiFileUpload",
2738
+ path: "attachments",
2739
+ label: "Attachments",
2740
+ props: {
2741
+ accept: ["image/*"],
2742
+ buttonLabel: "Upload images"
2743
+ },
2744
+ validator: {
2745
+ type: "files",
2746
+ required: true,
2747
+ maxItems: 3,
2748
+ messages: {
2749
+ required: "Add at least one image",
2750
+ maxItems: "No more than 3 images"
2751
+ }
2752
+ }
2753
+ },
2665
2754
  select: {
2666
2755
  kind: "input",
2667
2756
  type: "select",
@@ -2796,6 +2885,18 @@ const NOTES = {
2796
2885
  '`props.separators` controls which keys/characters commit a new tag. Defaults emit on `Enter` and `,`; you can also include `"Tab"` or `"blur"`. `props.trim` strips whitespace from each tag; `props.allowDuplicates: false` rejects repeats.',
2797
2886
  'Validate with an `arrayValidator`: `{ type: "array", minItems, maxItems, uniqueItems }`. Entry is never silently blocked — cap the tag count with `maxItems` so the user is told why.'
2798
2887
  ],
2888
+ fileUpload: [
2889
+ "Single-file upload rendered as a one-line input: the box is the drop target and holds the upload button; while the file uploads the box itself becomes the progress bar; once done it shows the file name with a remove button.",
2890
+ 'REQUIRES a host transport in the form init config: `dependencies: { uploadService: { upload(file, { id, path, onProgress, signal }) => Promise<unknown>, remove?(item) => Promise<void> } }` (a sibling of `dependencies.markdown`). Keep the object reference stable — a new config identity re-initializes the form. Without it the widget renders disabled with an inline error. Call `get_concept({ concept: "host-services" })`.',
2891
+ 'The value is a plain envelope, never the `File`: `{ id, name, size, type, status: "uploading" | "uploaded" | "error", error?, data? }` where `data` is exactly what `upload` resolved with. Preload from the server with `status: "uploaded"`. Removing awaits `uploadService.remove(item)` (when provided) before clearing. An item restored with `status: "uploading"` cannot resume — the `File` only existed in the session that picked it — so the widget commits it back as `"error"` with `props.interruptedMessage` (default: `{name} was not uploaded. Remove it and pick the file again.`).',
2892
+ 'Validate with a `fileValidator`: `{ type: "file", required, blockPendingUploads }`. `blockPendingUploads` defaults to true and fails while the file is uploading or failed, so an unfinished upload cannot be submitted. Message keys: `invalid`, `required`, `pendingUploads`.',
2893
+ '`props.accept` (`[".pdf", "image/*"]`) and `props.maxSize` (bytes) are checked BEFORE uploading; a refused or failed file stays in the box with retry/remove icon buttons — never dropped silently. The reason (server `reject(new Error(...))` message, or the default) surfaces in the standard error area below the input, like a date widget\'s invalid-date error. Text props: `buttonLabel`, `acceptMessage`, `maxSizeMessage`, `missingServiceMessage`, `removeAriaLabel`, `cancelAriaLabel`, `retryAriaLabel`, `uploadedMessage`, `removedMessage`, `failedMessage` (`{name}` token); icon overrides: `removeIcon`, `retryIcon`.'
2894
+ ],
2895
+ multiFileUpload: [
2896
+ "The array variant of `fileUpload`: same box, button, progress bar and `uploadService`. Files upload ONE AT A TIME; every finished file becomes a pill inside the box and the value is an array of envelopes.",
2897
+ "A failed file pauses the queue until it is retried or removed. The count is never silently blocked — cap it with `maxItems` so the user is told why.",
2898
+ 'Validate with a `filesValidator`: `{ type: "files", required, minItems, maxItems, blockPendingUploads }`. Message keys: `invalid`, `required`, `minItems`, `maxItems`, `pendingUploads`.'
2899
+ ],
2799
2900
  dropdown: [
2800
2901
  "PREFER `select` for plain label/value lists (countries, plans, sizes). `dropdown` is for richer item shapes: when each item has extra fields (icons, flags, metadata) that an `itemRenderer` or `labelField`/`valueField` can use.",
2801
2902
  '`props.items` is EITHER primitives `["one", 2, ...]` OR arbitrary objects `[{ label, value, ...extras }]`. Pair the object form with `labelField`/`valueField` to tell the dropdown which fields to render as label and which to use as the value. **Widget templates inside items (the `{template, value}` shape) are NOT supported — only `repeater` accepts widget templates.**'
@@ -3360,7 +3461,7 @@ const VALIDATION_CONCEPT = {
3360
3461
  patterns: [
3361
3462
  {
3362
3463
  name: "Custom error messages per rule (`messages`)",
3363
- description: 'Every validator accepts a `messages` object mapping rule names to custom error text. The allowed keys depend on the validator type — string: `invalid`, `required`, `minLength`, `maxLength`, `pattern`, `format`, `enum`, `const`; number/integer: `invalid`, `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`, `enum`, `const`; boolean: `invalid`, `const`; array: `invalid`, `required`, `minItems`, `maxItems`. The special key `invalid` customizes the base type check (wrong type, or `undefined`/`null` on a required field). Note that only string and array validators have a `required` message key — they are the only types with a present-but-empty state (`""` / `[]`); for number/integer/boolean a missing value can only ever show the `invalid` message. Values are plain strings or i18n descriptors `{ key, params?, default? }`. Without `messages`, failures surface library-default text (e.g. "Invalid input: expected string, received undefined") that is not written for end users — production forms should set custom messages for every rule they use, and ALWAYS set `invalid` whenever `required: true` is set (see the next patterns for why).',
3464
+ description: 'Every validator accepts a `messages` object mapping rule names to custom error text. The allowed keys depend on the validator type — string: `invalid`, `required`, `minLength`, `maxLength`, `pattern`, `format`, `enum`, `const`; number/integer: `invalid`, `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`, `enum`, `const`; boolean: `invalid`, `const`; array: `invalid`, `required`, `minItems`, `maxItems`; file (the `fileUpload` envelope): `invalid`, `required`, `pendingUploads`; files (the `multiFileUpload` array): `invalid`, `required`, `minItems`, `maxItems`, `pendingUploads`. The special key `invalid` customizes the base type check (wrong type, or `undefined`/`null` on a required field). Note that only string and array validators have a `required` message key — they are the only types with a present-but-empty state (`""` / `[]`); for number/integer/boolean a missing value can only ever show the `invalid` message. Values are plain strings or i18n descriptors `{ key, params?, default? }`. Without `messages`, failures surface library-default text (e.g. "Invalid input: expected string, received undefined") that is not written for end users — production forms should set custom messages for every rule they use, and ALWAYS set `invalid` whenever `required: true` is set (see the next patterns for why).',
3364
3465
  example: {
3365
3466
  $schema: FORM_SCHEMA_URL,
3366
3467
  form: [
@@ -3564,12 +3665,51 @@ const ICONS_CONCEPT = {
3564
3665
  "Do not set `props.icon` on widgets that do not support it — the schema will reject it and `json_validate_form_definition` will report an error."
3565
3666
  ]
3566
3667
  };
3668
+ const HOST_SERVICES_CONCEPT = {
3669
+ concept: "host-services",
3670
+ summary: 'Some widgets need a service the library deliberately does not ship: a markdown parser, or an HTTP transport for file uploads. The host application injects them through the `dependencies` entry of the form init config (a sibling of `functions`). The object is passed by reference to the widgets that read it and never enters the form state — so it may hold async functions and closures over tokens. Known keys: `markdown` (`{ parse(markdown) => html }`, read by the `markdown` and `markdownText` widgets) and `uploadService` (read by `fileUpload` and `multiFileUpload`). This is unrelated to the "dependencies between fields" feature (a field reacting to another field\'s value), which is expressed with reactive expressions.',
3671
+ patterns: [
3672
+ {
3673
+ name: "Inject an upload transport for the file upload widgets",
3674
+ description: "`uploadService.upload(file, ctx)` is called as soon as a file is picked; whatever it resolves with is stored verbatim in the field value as `item.data` (a URL, an id, an object). `ctx` carries the item `id`, the form `path`, an `onProgress(percentage)` callback for the progress bar, and an `AbortSignal` that fires when the user cancels. The optional `remove(item)` is awaited when the user removes an uploaded file, before the value is cleared; if it rejects the file stays with the error and a retry. Rejecting `upload` marks the file as failed (the message becomes `item.error`).",
3675
+ example: {
3676
+ // Host side (TypeScript), not part of the form definition:
3677
+ // const uploadService = {
3678
+ // async upload(file, { id, path, onProgress, signal }) {
3679
+ // const body = new FormData(); body.append('file', file);
3680
+ // const res = await fetch(`/api/uploads?field=${path}`, { method: 'POST', body, signal });
3681
+ // if (!res.ok) throw new Error('Upload rejected'); return res.json(); // → item.data
3682
+ // },
3683
+ // async remove(item) { await fetch(`/api/uploads/${item.data.key}`, { method: 'DELETE' }); },
3684
+ // };
3685
+ // <gui-form .config=${{ formDef, dependencies: { uploadService, markdown } }}>
3686
+ $schema: FORM_SCHEMA_URL,
3687
+ form: [
3688
+ {
3689
+ kind: "input",
3690
+ type: "fileUpload",
3691
+ path: "cv",
3692
+ label: "CV",
3693
+ validator: { type: "file", required: true }
3694
+ }
3695
+ ]
3696
+ }
3697
+ }
3698
+ ],
3699
+ rules: [
3700
+ "Keep the `dependencies` object reference stable (module level or memoized): the form re-initializes whenever its `config` identity changes, and an inline object literal in JSX or a template is a new identity on every render.",
3701
+ 'A widget that needs a missing service does not break the form: `fileUpload` renders disabled with an inline "not configured" error and logs to the console; `markdown` renders blank.',
3702
+ "Never put a `File` object in the form value — the value is the plain envelope the widget builds from the `upload` result; form events and submit payloads deep-clone data, which turns non-plain objects into `{}`.",
3703
+ "`dependencies` is merged shallowly: widget-set defaults, then the DX `formConfig.dependencies`, then the init config `dependencies`; the last one wins per key."
3704
+ ]
3705
+ };
3567
3706
  const CONCEPTS = {
3568
3707
  states: STATES_CONCEPT,
3569
3708
  "string-interpolation": STRING_INTERPOLATION_CONCEPT,
3570
3709
  "reactive-scope": REACTIVE_SCOPE_CONCEPT,
3571
3710
  validation: VALIDATION_CONCEPT,
3572
- icons: ICONS_CONCEPT
3711
+ icons: ICONS_CONCEPT,
3712
+ "host-services": HOST_SERVICES_CONCEPT
3573
3713
  };
3574
3714
  function getConcept(input) {
3575
3715
  const result = CONCEPTS[input.concept];