@structured-field/widget-editor 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/structured-widget-editor.css +1 -1
- package/dist/structured-widget-editor.esm.js +757 -235
- package/dist/structured-widget-editor.esm.js.map +1 -1
- package/dist/structured-widget-editor.iife.js +6 -6
- package/dist/structured-widget-editor.js +5 -5
- package/dist/structured-widget-editor.js.map +1 -1
- package/package.json +3 -1
- package/src/SchemaForm.vue +20 -13
- package/src/editors/BooleanEditor.vue +19 -9
- package/src/editors/DateEditor.vue +95 -0
- package/src/editors/JsonEditor.vue +173 -0
- package/src/editors/NullableEditor.vue +1 -1
- package/src/editors/NumberEditor.vue +23 -10
- package/src/editors/ObjectEditor.vue +14 -0
- package/src/editors/RelationEditor.vue +1 -1
- package/src/editors/SchemaEditor.vue +11 -1
- package/src/editors/SelectEditor.vue +46 -10
- package/src/editors/StringEditor.vue +29 -17
- package/src/editors/UnionEditor.vue +1 -1
- package/src/index.js +1 -0
- package/src/scss/components/editors.scss +114 -0
- package/src/utils.js +18 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var script$
|
|
1
|
+
var script$f = {
|
|
2
2
|
name: 'StringEditor',
|
|
3
3
|
props: {
|
|
4
4
|
schema: { type: Object, required: true },
|
|
@@ -21,6 +21,12 @@ var script$d = {
|
|
|
21
21
|
isLong() {
|
|
22
22
|
return this.schema.maxLength > 255 || this.schema.format === 'textarea';
|
|
23
23
|
},
|
|
24
|
+
isNullable() {
|
|
25
|
+
return !!this.schema._nullable;
|
|
26
|
+
},
|
|
27
|
+
isNullValue() {
|
|
28
|
+
return this.modelValue === null || this.modelValue === undefined;
|
|
29
|
+
},
|
|
24
30
|
fieldErrors() {
|
|
25
31
|
if (!this.form || !this.form.getErrorsForPath) return [];
|
|
26
32
|
return this.form.getErrorsForPath(this.path);
|
|
@@ -6759,7 +6765,7 @@ class VueElement extends BaseClass {
|
|
|
6759
6765
|
_update() {
|
|
6760
6766
|
const vnode = this._createVNode();
|
|
6761
6767
|
if (this._app) vnode.appContext = this._app._context;
|
|
6762
|
-
render$
|
|
6768
|
+
render$f(vnode, this._root);
|
|
6763
6769
|
}
|
|
6764
6770
|
_createVNode() {
|
|
6765
6771
|
const baseProps = {};
|
|
@@ -7026,7 +7032,7 @@ let renderer;
|
|
|
7026
7032
|
function ensureRenderer() {
|
|
7027
7033
|
return renderer || (renderer = createRenderer(rendererOptions));
|
|
7028
7034
|
}
|
|
7029
|
-
const render$
|
|
7035
|
+
const render$f = ((...args) => {
|
|
7030
7036
|
ensureRenderer().render(...args);
|
|
7031
7037
|
});
|
|
7032
7038
|
const createApp = ((...args) => {
|
|
@@ -7067,39 +7073,61 @@ function normalizeContainer(container) {
|
|
|
7067
7073
|
return container;
|
|
7068
7074
|
}
|
|
7069
7075
|
|
|
7070
|
-
const _hoisted_1$
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7076
|
+
const _hoisted_1$d = {
|
|
7077
|
+
key: 0,
|
|
7078
|
+
class: "sf-null-badge"
|
|
7079
|
+
};
|
|
7080
|
+
const _hoisted_2$b = ["value", "placeholder"];
|
|
7081
|
+
const _hoisted_3$b = ["value", "placeholder"];
|
|
7082
|
+
const _hoisted_4$7 = {
|
|
7083
|
+
key: 0,
|
|
7074
7084
|
class: "errorlist"
|
|
7075
7085
|
};
|
|
7076
7086
|
|
|
7077
|
-
function render$
|
|
7087
|
+
function render$e(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7078
7088
|
return (openBlock(), createElementBlock("div", {
|
|
7079
7089
|
class: normalizeClass(["sf-field", { errors: $options.fieldErrors.length }])
|
|
7080
7090
|
}, [
|
|
7081
|
-
createBaseVNode("
|
|
7091
|
+
createBaseVNode("span", {
|
|
7082
7092
|
class: normalizeClass(["sf-label", { required: $options.isRequired }])
|
|
7083
|
-
},
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7093
|
+
}, [
|
|
7094
|
+
createTextVNode(toDisplayString($options.title) + " ", 1 /* TEXT */),
|
|
7095
|
+
($options.isNullable && $options.isNullValue)
|
|
7096
|
+
? (openBlock(), createElementBlock("span", _hoisted_1$d, "null"))
|
|
7097
|
+
: createCommentVNode("v-if", true)
|
|
7098
|
+
], 2 /* CLASS */),
|
|
7099
|
+
createBaseVNode("div", {
|
|
7100
|
+
class: normalizeClass($options.isNullable ? 'sf-input-row' : null)
|
|
7101
|
+
}, [
|
|
7102
|
+
($options.isLong)
|
|
7103
|
+
? (openBlock(), createElementBlock("textarea", {
|
|
7104
|
+
key: 0,
|
|
7105
|
+
class: "sf-input sf-textarea",
|
|
7106
|
+
rows: "3",
|
|
7107
|
+
value: $options.isNullValue ? '' : $props.modelValue,
|
|
7108
|
+
placeholder: $options.isNullValue ? 'null' : ($props.schema.placeholder || ''),
|
|
7109
|
+
onInput: _cache[0] || (_cache[0] = $event => (_ctx.$emit('update:modelValue', $event.target.value)))
|
|
7110
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_2$b))
|
|
7111
|
+
: (openBlock(), createElementBlock("input", {
|
|
7112
|
+
key: 1,
|
|
7113
|
+
type: "text",
|
|
7114
|
+
class: "sf-input",
|
|
7115
|
+
value: $options.isNullValue ? '' : ($props.modelValue != null ? String($props.modelValue) : ''),
|
|
7116
|
+
placeholder: $options.isNullValue ? 'null' : ($props.schema.placeholder || ''),
|
|
7117
|
+
onInput: _cache[1] || (_cache[1] = $event => (_ctx.$emit('update:modelValue', $event.target.value)))
|
|
7118
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_3$b)),
|
|
7119
|
+
($options.isNullable && !$options.isNullValue)
|
|
7120
|
+
? (openBlock(), createElementBlock("button", {
|
|
7121
|
+
key: 2,
|
|
7122
|
+
type: "button",
|
|
7123
|
+
class: "sf-null-clear-btn",
|
|
7124
|
+
title: "Set to null",
|
|
7125
|
+
onClick: _cache[2] || (_cache[2] = $event => (_ctx.$emit('update:modelValue', null)))
|
|
7126
|
+
}, "✕"))
|
|
7127
|
+
: createCommentVNode("v-if", true)
|
|
7128
|
+
], 2 /* CLASS */),
|
|
7101
7129
|
($options.fieldErrors.length)
|
|
7102
|
-
? (openBlock(), createElementBlock("ul",
|
|
7130
|
+
? (openBlock(), createElementBlock("ul", _hoisted_4$7, [
|
|
7103
7131
|
(openBlock(true), createElementBlock(Fragment, null, renderList($options.fieldErrors, (err, i) => {
|
|
7104
7132
|
return (openBlock(), createElementBlock("li", { key: i }, toDisplayString(err), 1 /* TEXT */))
|
|
7105
7133
|
}), 128 /* KEYED_FRAGMENT */))
|
|
@@ -7108,10 +7136,10 @@ function render$c(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
7108
7136
|
], 2 /* CLASS */))
|
|
7109
7137
|
}
|
|
7110
7138
|
|
|
7111
|
-
script$
|
|
7112
|
-
script$
|
|
7139
|
+
script$f.render = render$e;
|
|
7140
|
+
script$f.__file = "src/editors/StringEditor.vue";
|
|
7113
7141
|
|
|
7114
|
-
var script$
|
|
7142
|
+
var script$e = {
|
|
7115
7143
|
name: 'NumberEditor',
|
|
7116
7144
|
props: {
|
|
7117
7145
|
schema: { type: Object, required: true },
|
|
@@ -7131,6 +7159,12 @@ var script$c = {
|
|
|
7131
7159
|
const parentSchema = this.form.getSchemaAtPath(parentPath);
|
|
7132
7160
|
return parentSchema && Array.isArray(parentSchema.required) && parentSchema.required.includes(fieldName);
|
|
7133
7161
|
},
|
|
7162
|
+
isNullable() {
|
|
7163
|
+
return !!this.schema._nullable;
|
|
7164
|
+
},
|
|
7165
|
+
isNullValue() {
|
|
7166
|
+
return this.modelValue === null || this.modelValue === undefined;
|
|
7167
|
+
},
|
|
7134
7168
|
fieldErrors() {
|
|
7135
7169
|
if (!this.form || !this.form.getErrorsForPath) return [];
|
|
7136
7170
|
return this.form.getErrorsForPath(this.path);
|
|
@@ -7152,30 +7186,53 @@ var script$c = {
|
|
|
7152
7186
|
},
|
|
7153
7187
|
};
|
|
7154
7188
|
|
|
7155
|
-
const _hoisted_1$
|
|
7156
|
-
|
|
7189
|
+
const _hoisted_1$c = {
|
|
7190
|
+
key: 0,
|
|
7191
|
+
class: "sf-null-badge"
|
|
7192
|
+
};
|
|
7193
|
+
const _hoisted_2$a = ["step", "min", "max", "value", "placeholder"];
|
|
7194
|
+
const _hoisted_3$a = {
|
|
7157
7195
|
key: 0,
|
|
7158
7196
|
class: "errorlist"
|
|
7159
7197
|
};
|
|
7160
7198
|
|
|
7161
|
-
function render$
|
|
7199
|
+
function render$d(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7162
7200
|
return (openBlock(), createElementBlock("div", {
|
|
7163
7201
|
class: normalizeClass(["sf-field", { errors: $options.fieldErrors.length }])
|
|
7164
7202
|
}, [
|
|
7165
|
-
createBaseVNode("
|
|
7203
|
+
createBaseVNode("span", {
|
|
7166
7204
|
class: normalizeClass(["sf-label", { required: $options.isRequired }])
|
|
7167
|
-
},
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7205
|
+
}, [
|
|
7206
|
+
createTextVNode(toDisplayString($options.title) + " ", 1 /* TEXT */),
|
|
7207
|
+
($options.isNullable && $options.isNullValue)
|
|
7208
|
+
? (openBlock(), createElementBlock("span", _hoisted_1$c, "null"))
|
|
7209
|
+
: createCommentVNode("v-if", true)
|
|
7210
|
+
], 2 /* CLASS */),
|
|
7211
|
+
createBaseVNode("div", {
|
|
7212
|
+
class: normalizeClass($options.isNullable ? 'sf-input-row' : null)
|
|
7213
|
+
}, [
|
|
7214
|
+
createBaseVNode("input", {
|
|
7215
|
+
type: "number",
|
|
7216
|
+
class: "sf-input",
|
|
7217
|
+
step: $props.schema.type === 'integer' ? '1' : 'any',
|
|
7218
|
+
min: $props.schema.minimum != null ? String($props.schema.minimum) : undefined,
|
|
7219
|
+
max: $props.schema.maximum != null ? String($props.schema.maximum) : undefined,
|
|
7220
|
+
value: $options.isNullValue ? '' : $props.modelValue,
|
|
7221
|
+
placeholder: $options.isNullValue ? 'null' : undefined,
|
|
7222
|
+
onInput: _cache[0] || (_cache[0] = (...args) => ($options.onInput && $options.onInput(...args)))
|
|
7223
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_2$a),
|
|
7224
|
+
($options.isNullable && !$options.isNullValue)
|
|
7225
|
+
? (openBlock(), createElementBlock("button", {
|
|
7226
|
+
key: 0,
|
|
7227
|
+
type: "button",
|
|
7228
|
+
class: "sf-null-clear-btn",
|
|
7229
|
+
title: "Set to null",
|
|
7230
|
+
onClick: _cache[1] || (_cache[1] = $event => (_ctx.$emit('update:modelValue', null)))
|
|
7231
|
+
}, "✕"))
|
|
7232
|
+
: createCommentVNode("v-if", true)
|
|
7233
|
+
], 2 /* CLASS */),
|
|
7177
7234
|
($options.fieldErrors.length)
|
|
7178
|
-
? (openBlock(), createElementBlock("ul",
|
|
7235
|
+
? (openBlock(), createElementBlock("ul", _hoisted_3$a, [
|
|
7179
7236
|
(openBlock(true), createElementBlock(Fragment, null, renderList($options.fieldErrors, (err, i) => {
|
|
7180
7237
|
return (openBlock(), createElementBlock("li", { key: i }, toDisplayString(err), 1 /* TEXT */))
|
|
7181
7238
|
}), 128 /* KEYED_FRAGMENT */))
|
|
@@ -7184,10 +7241,10 @@ function render$b(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
7184
7241
|
], 2 /* CLASS */))
|
|
7185
7242
|
}
|
|
7186
7243
|
|
|
7187
|
-
script$
|
|
7188
|
-
script$
|
|
7244
|
+
script$e.render = render$d;
|
|
7245
|
+
script$e.__file = "src/editors/NumberEditor.vue";
|
|
7189
7246
|
|
|
7190
|
-
var script$
|
|
7247
|
+
var script$d = {
|
|
7191
7248
|
name: 'BooleanEditor',
|
|
7192
7249
|
props: {
|
|
7193
7250
|
schema: { type: Object, required: true },
|
|
@@ -7200,6 +7257,12 @@ var script$b = {
|
|
|
7200
7257
|
title() {
|
|
7201
7258
|
return this.schema.title || this.humanize(this.path[this.path.length - 1]) || '';
|
|
7202
7259
|
},
|
|
7260
|
+
isNullable() {
|
|
7261
|
+
return !!this.schema._nullable;
|
|
7262
|
+
},
|
|
7263
|
+
isNullValue() {
|
|
7264
|
+
return this.modelValue === null || this.modelValue === undefined;
|
|
7265
|
+
},
|
|
7203
7266
|
fieldErrors() {
|
|
7204
7267
|
if (!this.form || !this.form.getErrorsForPath) return [];
|
|
7205
7268
|
return this.form.getErrorsForPath(this.path);
|
|
@@ -7213,28 +7276,47 @@ var script$b = {
|
|
|
7213
7276
|
},
|
|
7214
7277
|
};
|
|
7215
7278
|
|
|
7216
|
-
const _hoisted_1$
|
|
7217
|
-
const _hoisted_2$
|
|
7218
|
-
const _hoisted_3$
|
|
7279
|
+
const _hoisted_1$b = { class: "sf-boolean-row" };
|
|
7280
|
+
const _hoisted_2$9 = { class: "sf-checkbox-label" };
|
|
7281
|
+
const _hoisted_3$9 = ["checked"];
|
|
7282
|
+
const _hoisted_4$6 = {
|
|
7283
|
+
key: 0,
|
|
7284
|
+
class: "sf-null-badge"
|
|
7285
|
+
};
|
|
7286
|
+
const _hoisted_5$6 = {
|
|
7219
7287
|
key: 0,
|
|
7220
7288
|
class: "errorlist"
|
|
7221
7289
|
};
|
|
7222
7290
|
|
|
7223
|
-
function render$
|
|
7291
|
+
function render$c(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7224
7292
|
return (openBlock(), createElementBlock("div", {
|
|
7225
7293
|
class: normalizeClass(["sf-field sf-field-boolean", { errors: $options.fieldErrors.length }])
|
|
7226
7294
|
}, [
|
|
7227
|
-
createBaseVNode("
|
|
7228
|
-
createBaseVNode("
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7295
|
+
createBaseVNode("div", _hoisted_1$b, [
|
|
7296
|
+
createBaseVNode("label", _hoisted_2$9, [
|
|
7297
|
+
createBaseVNode("input", {
|
|
7298
|
+
type: "checkbox",
|
|
7299
|
+
class: "sf-checkbox",
|
|
7300
|
+
checked: !!$props.modelValue,
|
|
7301
|
+
onChange: _cache[0] || (_cache[0] = $event => (_ctx.$emit('update:modelValue', $event.target.checked)))
|
|
7302
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_3$9),
|
|
7303
|
+
createTextVNode(" " + toDisplayString($options.title) + " ", 1 /* TEXT */),
|
|
7304
|
+
($options.isNullable && $options.isNullValue)
|
|
7305
|
+
? (openBlock(), createElementBlock("span", _hoisted_4$6, "null"))
|
|
7306
|
+
: createCommentVNode("v-if", true)
|
|
7307
|
+
]),
|
|
7308
|
+
($options.isNullable && !$options.isNullValue)
|
|
7309
|
+
? (openBlock(), createElementBlock("button", {
|
|
7310
|
+
key: 0,
|
|
7311
|
+
type: "button",
|
|
7312
|
+
class: "sf-null-clear-btn",
|
|
7313
|
+
title: "Set to null",
|
|
7314
|
+
onClick: _cache[1] || (_cache[1] = $event => (_ctx.$emit('update:modelValue', null)))
|
|
7315
|
+
}, "✕"))
|
|
7316
|
+
: createCommentVNode("v-if", true)
|
|
7235
7317
|
]),
|
|
7236
7318
|
($options.fieldErrors.length)
|
|
7237
|
-
? (openBlock(), createElementBlock("ul",
|
|
7319
|
+
? (openBlock(), createElementBlock("ul", _hoisted_5$6, [
|
|
7238
7320
|
(openBlock(true), createElementBlock(Fragment, null, renderList($options.fieldErrors, (err, i) => {
|
|
7239
7321
|
return (openBlock(), createElementBlock("li", { key: i }, toDisplayString(err), 1 /* TEXT */))
|
|
7240
7322
|
}), 128 /* KEYED_FRAGMENT */))
|
|
@@ -7243,10 +7325,194 @@ function render$a(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
7243
7325
|
], 2 /* CLASS */))
|
|
7244
7326
|
}
|
|
7245
7327
|
|
|
7246
|
-
script$
|
|
7247
|
-
script$
|
|
7328
|
+
script$d.render = render$c;
|
|
7329
|
+
script$d.__file = "src/editors/BooleanEditor.vue";
|
|
7248
7330
|
|
|
7249
|
-
var script$
|
|
7331
|
+
var script$c = {
|
|
7332
|
+
name: 'DateEditor',
|
|
7333
|
+
props: {
|
|
7334
|
+
schema: { type: Object, required: true },
|
|
7335
|
+
modelValue: { default: '' },
|
|
7336
|
+
path: { type: Array, default: () => [] },
|
|
7337
|
+
form: { type: Object, default: null },
|
|
7338
|
+
},
|
|
7339
|
+
emits: ['update:modelValue'],
|
|
7340
|
+
computed: {
|
|
7341
|
+
isDateTime() {
|
|
7342
|
+
return this.schema.format === 'date-time';
|
|
7343
|
+
},
|
|
7344
|
+
inputType() {
|
|
7345
|
+
return this.isDateTime ? 'datetime-local' : 'date';
|
|
7346
|
+
},
|
|
7347
|
+
displayValue() {
|
|
7348
|
+
if (this.isNullValue) return '';
|
|
7349
|
+
const v = String(this.modelValue);
|
|
7350
|
+
if (this.isDateTime) {
|
|
7351
|
+
// Accept ISO 8601 strings like "2026-04-09T10:30:00[.sss][Z|+00:00]"
|
|
7352
|
+
// datetime-local expects "YYYY-MM-DDTHH:mm" (or with seconds).
|
|
7353
|
+
const match = v.match(/^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2})(?::(\d{2}(?:\.\d+)?))?/);
|
|
7354
|
+
if (match) {
|
|
7355
|
+
return match[3] ? `${match[1]}T${match[2]}:${match[3]}` : `${match[1]}T${match[2]}`;
|
|
7356
|
+
}
|
|
7357
|
+
return v;
|
|
7358
|
+
}
|
|
7359
|
+
// date: expect "YYYY-MM-DD"
|
|
7360
|
+
return v.slice(0, 10);
|
|
7361
|
+
},
|
|
7362
|
+
title() {
|
|
7363
|
+
return this.schema.title || this.humanize(this.path[this.path.length - 1]) || '';
|
|
7364
|
+
},
|
|
7365
|
+
isRequired() {
|
|
7366
|
+
if (this.path.length < 2 || !this.form) return false;
|
|
7367
|
+
const parentPath = this.path.slice(0, -1);
|
|
7368
|
+
const fieldName = this.path[this.path.length - 1];
|
|
7369
|
+
const parentSchema = this.form.getSchemaAtPath(parentPath);
|
|
7370
|
+
return parentSchema && Array.isArray(parentSchema.required) && parentSchema.required.includes(fieldName);
|
|
7371
|
+
},
|
|
7372
|
+
isNullable() {
|
|
7373
|
+
return !!this.schema._nullable;
|
|
7374
|
+
},
|
|
7375
|
+
isNullValue() {
|
|
7376
|
+
return this.modelValue === null || this.modelValue === undefined;
|
|
7377
|
+
},
|
|
7378
|
+
fieldErrors() {
|
|
7379
|
+
if (!this.form || !this.form.getErrorsForPath) return [];
|
|
7380
|
+
return this.form.getErrorsForPath(this.path);
|
|
7381
|
+
},
|
|
7382
|
+
},
|
|
7383
|
+
methods: {
|
|
7384
|
+
onInput(e) {
|
|
7385
|
+
const val = e.target.value;
|
|
7386
|
+
if (val === '') {
|
|
7387
|
+
this.$emit('update:modelValue', this.isNullable ? null : '');
|
|
7388
|
+
return;
|
|
7389
|
+
}
|
|
7390
|
+
// Emit ISO-compatible string. Pydantic accepts both "YYYY-MM-DD"
|
|
7391
|
+
// and "YYYY-MM-DDTHH:mm[:ss]" for date / datetime fields.
|
|
7392
|
+
this.$emit('update:modelValue', val);
|
|
7393
|
+
},
|
|
7394
|
+
humanize(str) {
|
|
7395
|
+
if (!str) return '';
|
|
7396
|
+
return str.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2').replace(/^./, s => s.toUpperCase());
|
|
7397
|
+
},
|
|
7398
|
+
},
|
|
7399
|
+
};
|
|
7400
|
+
|
|
7401
|
+
const _hoisted_1$a = {
|
|
7402
|
+
key: 0,
|
|
7403
|
+
class: "sf-null-badge"
|
|
7404
|
+
};
|
|
7405
|
+
const _hoisted_2$8 = ["type", "value", "placeholder", "min", "max"];
|
|
7406
|
+
const _hoisted_3$8 = {
|
|
7407
|
+
key: 0,
|
|
7408
|
+
class: "errorlist"
|
|
7409
|
+
};
|
|
7410
|
+
|
|
7411
|
+
function render$b(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7412
|
+
return (openBlock(), createElementBlock("div", {
|
|
7413
|
+
class: normalizeClass(["sf-field", { errors: $options.fieldErrors.length }])
|
|
7414
|
+
}, [
|
|
7415
|
+
createBaseVNode("span", {
|
|
7416
|
+
class: normalizeClass(["sf-label", { required: $options.isRequired }])
|
|
7417
|
+
}, [
|
|
7418
|
+
createTextVNode(toDisplayString($options.title) + " ", 1 /* TEXT */),
|
|
7419
|
+
($options.isNullable && $options.isNullValue)
|
|
7420
|
+
? (openBlock(), createElementBlock("span", _hoisted_1$a, "null"))
|
|
7421
|
+
: createCommentVNode("v-if", true)
|
|
7422
|
+
], 2 /* CLASS */),
|
|
7423
|
+
createBaseVNode("div", {
|
|
7424
|
+
class: normalizeClass($options.isNullable ? 'sf-input-row' : null)
|
|
7425
|
+
}, [
|
|
7426
|
+
createBaseVNode("input", {
|
|
7427
|
+
type: $options.inputType,
|
|
7428
|
+
class: "sf-input",
|
|
7429
|
+
value: $options.displayValue,
|
|
7430
|
+
placeholder: $options.isNullValue ? 'null' : ($props.schema.placeholder || ''),
|
|
7431
|
+
min: $props.schema.minimum || $props.schema.formatMinimum || null,
|
|
7432
|
+
max: $props.schema.maximum || $props.schema.formatMaximum || null,
|
|
7433
|
+
onInput: _cache[0] || (_cache[0] = (...args) => ($options.onInput && $options.onInput(...args)))
|
|
7434
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_2$8),
|
|
7435
|
+
($options.isNullable && !$options.isNullValue)
|
|
7436
|
+
? (openBlock(), createElementBlock("button", {
|
|
7437
|
+
key: 0,
|
|
7438
|
+
type: "button",
|
|
7439
|
+
class: "sf-null-clear-btn",
|
|
7440
|
+
title: "Set to null",
|
|
7441
|
+
onClick: _cache[1] || (_cache[1] = $event => (_ctx.$emit('update:modelValue', null)))
|
|
7442
|
+
}, "✕"))
|
|
7443
|
+
: createCommentVNode("v-if", true)
|
|
7444
|
+
], 2 /* CLASS */),
|
|
7445
|
+
($options.fieldErrors.length)
|
|
7446
|
+
? (openBlock(), createElementBlock("ul", _hoisted_3$8, [
|
|
7447
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.fieldErrors, (err, i) => {
|
|
7448
|
+
return (openBlock(), createElementBlock("li", { key: i }, toDisplayString(err), 1 /* TEXT */))
|
|
7449
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
7450
|
+
]))
|
|
7451
|
+
: createCommentVNode("v-if", true)
|
|
7452
|
+
], 2 /* CLASS */))
|
|
7453
|
+
}
|
|
7454
|
+
|
|
7455
|
+
script$c.render = render$b;
|
|
7456
|
+
script$c.__file = "src/editors/DateEditor.vue";
|
|
7457
|
+
|
|
7458
|
+
function debounce(fn, delay) {
|
|
7459
|
+
let timer;
|
|
7460
|
+
return function (...args) {
|
|
7461
|
+
clearTimeout(timer);
|
|
7462
|
+
timer = setTimeout(() => fn.apply(this, args), delay);
|
|
7463
|
+
};
|
|
7464
|
+
}
|
|
7465
|
+
|
|
7466
|
+
function deepClone(obj) {
|
|
7467
|
+
if (obj === null || typeof obj !== 'object') return obj;
|
|
7468
|
+
if (Array.isArray(obj)) return obj.map(deepClone);
|
|
7469
|
+
const clone = {};
|
|
7470
|
+
for (const key of Object.keys(obj)) {
|
|
7471
|
+
clone[key] = deepClone(obj[key]);
|
|
7472
|
+
}
|
|
7473
|
+
return clone;
|
|
7474
|
+
}
|
|
7475
|
+
|
|
7476
|
+
function isChoiceOneOf(list) {
|
|
7477
|
+
// A "choice list" oneOf: every member is a {const, title?} value option
|
|
7478
|
+
// (the shape emitted for enumerated choices, e.g. metaobjects' select
|
|
7479
|
+
// kind), as opposed to a oneOf of alternative sub-schemas.
|
|
7480
|
+
return (
|
|
7481
|
+
Array.isArray(list) &&
|
|
7482
|
+
list.length > 0 &&
|
|
7483
|
+
list.every(
|
|
7484
|
+
(m) =>
|
|
7485
|
+
m &&
|
|
7486
|
+
typeof m === 'object' &&
|
|
7487
|
+
'const' in m &&
|
|
7488
|
+
!('properties' in m) &&
|
|
7489
|
+
m.type !== 'null'
|
|
7490
|
+
)
|
|
7491
|
+
);
|
|
7492
|
+
}
|
|
7493
|
+
|
|
7494
|
+
function getDefaultForSchema(schema) {
|
|
7495
|
+
if ('default' in schema) return deepClone(schema.default);
|
|
7496
|
+
if (schema.type === 'object') {
|
|
7497
|
+
const obj = {};
|
|
7498
|
+
for (const [key, prop] of Object.entries(schema.properties || {})) {
|
|
7499
|
+
if ('default' in prop) obj[key] = deepClone(prop.default);
|
|
7500
|
+
else if (prop.type === 'string') obj[key] = '';
|
|
7501
|
+
else if (prop.type === 'integer' || prop.type === 'number') obj[key] = 0;
|
|
7502
|
+
else if (prop.type === 'boolean') obj[key] = false;
|
|
7503
|
+
else if (prop.type === 'array') obj[key] = [];
|
|
7504
|
+
}
|
|
7505
|
+
return obj;
|
|
7506
|
+
}
|
|
7507
|
+
if (schema.type === 'array') return [];
|
|
7508
|
+
if (schema.type === 'string') return '';
|
|
7509
|
+
if (schema.type === 'integer' || schema.type === 'number') return 0;
|
|
7510
|
+
if (schema.type === 'boolean') return false;
|
|
7511
|
+
if (schema.type === 'relation') return schema.multiple ? [] : null;
|
|
7512
|
+
return null;
|
|
7513
|
+
}
|
|
7514
|
+
|
|
7515
|
+
var script$b = {
|
|
7250
7516
|
name: 'SelectEditor',
|
|
7251
7517
|
props: {
|
|
7252
7518
|
schema: { type: Object, required: true },
|
|
@@ -7256,6 +7522,20 @@ var script$a = {
|
|
|
7256
7522
|
},
|
|
7257
7523
|
emits: ['update:modelValue'],
|
|
7258
7524
|
computed: {
|
|
7525
|
+
options() {
|
|
7526
|
+
// Two source shapes: a choice-list oneOf ({const, title} pairs, e.g.
|
|
7527
|
+
// metaobjects' select kind — labels preserved) or a plain enum.
|
|
7528
|
+
if (isChoiceOneOf(this.schema.oneOf)) {
|
|
7529
|
+
return this.schema.oneOf.map((o) => ({
|
|
7530
|
+
value: o.const,
|
|
7531
|
+
label: o.title != null ? o.title : String(o.const),
|
|
7532
|
+
}));
|
|
7533
|
+
}
|
|
7534
|
+
return (this.schema.enum || []).map((v) => ({ value: v, label: String(v) }));
|
|
7535
|
+
},
|
|
7536
|
+
selectedIndex() {
|
|
7537
|
+
return this.options.findIndex((o) => o.value === this.modelValue);
|
|
7538
|
+
},
|
|
7259
7539
|
title() {
|
|
7260
7540
|
return this.schema.title || this.humanize(this.path[this.path.length - 1]) || '';
|
|
7261
7541
|
},
|
|
@@ -7266,12 +7546,25 @@ var script$a = {
|
|
|
7266
7546
|
const parentSchema = this.form.getSchemaAtPath(parentPath);
|
|
7267
7547
|
return parentSchema && Array.isArray(parentSchema.required) && parentSchema.required.includes(fieldName);
|
|
7268
7548
|
},
|
|
7549
|
+
isNullable() {
|
|
7550
|
+
return !!this.schema._nullable;
|
|
7551
|
+
},
|
|
7552
|
+
isNullValue() {
|
|
7553
|
+
return this.modelValue === null || this.modelValue === undefined;
|
|
7554
|
+
},
|
|
7269
7555
|
fieldErrors() {
|
|
7270
7556
|
if (!this.form || !this.form.getErrorsForPath) return [];
|
|
7271
7557
|
return this.form.getErrorsForPath(this.path);
|
|
7272
7558
|
},
|
|
7273
7559
|
},
|
|
7274
7560
|
methods: {
|
|
7561
|
+
onChange(indexStr) {
|
|
7562
|
+
const opt = this.options[Number(indexStr)];
|
|
7563
|
+
// Emit the ORIGINAL option value (options are addressed by index in
|
|
7564
|
+
// the DOM), so integer/boolean enums keep their native type instead
|
|
7565
|
+
// of being stringified by the <select> element.
|
|
7566
|
+
if (opt !== undefined) this.$emit('update:modelValue', opt.value);
|
|
7567
|
+
},
|
|
7275
7568
|
humanize(str) {
|
|
7276
7569
|
if (!str) return '';
|
|
7277
7570
|
return str.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2').replace(/^./, s => s.toUpperCase());
|
|
@@ -7279,34 +7572,65 @@ var script$a = {
|
|
|
7279
7572
|
},
|
|
7280
7573
|
};
|
|
7281
7574
|
|
|
7282
|
-
const _hoisted_1$
|
|
7283
|
-
|
|
7284
|
-
|
|
7575
|
+
const _hoisted_1$9 = {
|
|
7576
|
+
key: 0,
|
|
7577
|
+
class: "sf-null-badge"
|
|
7578
|
+
};
|
|
7579
|
+
const _hoisted_2$7 = ["value"];
|
|
7580
|
+
const _hoisted_3$7 = {
|
|
7581
|
+
key: 0,
|
|
7582
|
+
value: "",
|
|
7583
|
+
disabled: "",
|
|
7584
|
+
selected: ""
|
|
7585
|
+
};
|
|
7586
|
+
const _hoisted_4$5 = ["value"];
|
|
7587
|
+
const _hoisted_5$5 = {
|
|
7285
7588
|
key: 0,
|
|
7286
7589
|
class: "errorlist"
|
|
7287
7590
|
};
|
|
7288
7591
|
|
|
7289
|
-
function render$
|
|
7592
|
+
function render$a(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7290
7593
|
return (openBlock(), createElementBlock("div", {
|
|
7291
7594
|
class: normalizeClass(["sf-field", { errors: $options.fieldErrors.length }])
|
|
7292
7595
|
}, [
|
|
7293
|
-
createBaseVNode("
|
|
7596
|
+
createBaseVNode("span", {
|
|
7294
7597
|
class: normalizeClass(["sf-label", { required: $options.isRequired }])
|
|
7295
|
-
}, toDisplayString($options.title), 3 /* TEXT, CLASS */),
|
|
7296
|
-
createBaseVNode("select", {
|
|
7297
|
-
class: "sf-input sf-select",
|
|
7298
|
-
value: $props.modelValue != null ? String($props.modelValue) : '',
|
|
7299
|
-
onChange: _cache[0] || (_cache[0] = $event => (_ctx.$emit('update:modelValue', $event.target.value)))
|
|
7300
7598
|
}, [
|
|
7301
|
-
(
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7599
|
+
createTextVNode(toDisplayString($options.title) + " ", 1 /* TEXT */),
|
|
7600
|
+
($options.isNullable && $options.isNullValue)
|
|
7601
|
+
? (openBlock(), createElementBlock("span", _hoisted_1$9, "null"))
|
|
7602
|
+
: createCommentVNode("v-if", true)
|
|
7603
|
+
], 2 /* CLASS */),
|
|
7604
|
+
createBaseVNode("div", {
|
|
7605
|
+
class: normalizeClass($options.isNullable ? 'sf-input-row' : null)
|
|
7606
|
+
}, [
|
|
7607
|
+
createBaseVNode("select", {
|
|
7608
|
+
class: "sf-input sf-select",
|
|
7609
|
+
value: $options.selectedIndex === -1 ? '' : String($options.selectedIndex),
|
|
7610
|
+
onChange: _cache[0] || (_cache[0] = $event => ($options.onChange($event.target.value)))
|
|
7611
|
+
}, [
|
|
7612
|
+
($options.selectedIndex === -1)
|
|
7613
|
+
? (openBlock(), createElementBlock("option", _hoisted_3$7, toDisplayString($options.isNullValue ? 'null' : ''), 1 /* TEXT */))
|
|
7614
|
+
: createCommentVNode("v-if", true),
|
|
7615
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.options, (opt, i) => {
|
|
7616
|
+
return (openBlock(), createElementBlock("option", {
|
|
7617
|
+
key: i,
|
|
7618
|
+
value: String(i)
|
|
7619
|
+
}, toDisplayString(opt.label), 9 /* TEXT, PROPS */, _hoisted_4$5))
|
|
7620
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
7621
|
+
], 40 /* PROPS, NEED_HYDRATION */, _hoisted_2$7),
|
|
7622
|
+
($options.isNullable && !$options.isNullValue)
|
|
7623
|
+
? (openBlock(), createElementBlock("button", {
|
|
7624
|
+
key: 0,
|
|
7625
|
+
type: "button",
|
|
7626
|
+
class: "sf-null-clear-btn",
|
|
7627
|
+
title: "Set to null",
|
|
7628
|
+
onClick: _cache[1] || (_cache[1] = $event => (_ctx.$emit('update:modelValue', null)))
|
|
7629
|
+
}, "✕"))
|
|
7630
|
+
: createCommentVNode("v-if", true)
|
|
7631
|
+
], 2 /* CLASS */),
|
|
7308
7632
|
($options.fieldErrors.length)
|
|
7309
|
-
? (openBlock(), createElementBlock("ul",
|
|
7633
|
+
? (openBlock(), createElementBlock("ul", _hoisted_5$5, [
|
|
7310
7634
|
(openBlock(true), createElementBlock(Fragment, null, renderList($options.fieldErrors, (err, i) => {
|
|
7311
7635
|
return (openBlock(), createElementBlock("li", { key: i }, toDisplayString(err), 1 /* TEXT */))
|
|
7312
7636
|
}), 128 /* KEYED_FRAGMENT */))
|
|
@@ -7315,10 +7639,10 @@ function render$9(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
7315
7639
|
], 2 /* CLASS */))
|
|
7316
7640
|
}
|
|
7317
7641
|
|
|
7318
|
-
script$
|
|
7319
|
-
script$
|
|
7642
|
+
script$b.render = render$a;
|
|
7643
|
+
script$b.__file = "src/editors/SelectEditor.vue";
|
|
7320
7644
|
|
|
7321
|
-
var script$
|
|
7645
|
+
var script$a = {
|
|
7322
7646
|
name: 'HiddenEditor',
|
|
7323
7647
|
props: {
|
|
7324
7648
|
schema: { type: Object, required: true },
|
|
@@ -7346,16 +7670,16 @@ var script$9 = {
|
|
|
7346
7670
|
},
|
|
7347
7671
|
};
|
|
7348
7672
|
|
|
7349
|
-
const _hoisted_1$
|
|
7673
|
+
const _hoisted_1$8 = { style: {"display":"none"} };
|
|
7350
7674
|
|
|
7351
|
-
function render$
|
|
7352
|
-
return (openBlock(), createElementBlock("div", _hoisted_1$
|
|
7675
|
+
function render$9(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7676
|
+
return (openBlock(), createElementBlock("div", _hoisted_1$8))
|
|
7353
7677
|
}
|
|
7354
7678
|
|
|
7355
|
-
script$
|
|
7356
|
-
script$
|
|
7679
|
+
script$a.render = render$9;
|
|
7680
|
+
script$a.__file = "src/editors/HiddenEditor.vue";
|
|
7357
7681
|
|
|
7358
|
-
var script$
|
|
7682
|
+
var script$9 = {
|
|
7359
7683
|
name: 'SfIcon',
|
|
7360
7684
|
props: {
|
|
7361
7685
|
name: { type: String, required: true },
|
|
@@ -7363,17 +7687,17 @@ var script$8 = {
|
|
|
7363
7687
|
},
|
|
7364
7688
|
};
|
|
7365
7689
|
|
|
7366
|
-
const _hoisted_1$
|
|
7367
|
-
const _hoisted_2$
|
|
7690
|
+
const _hoisted_1$7 = ["width", "height"];
|
|
7691
|
+
const _hoisted_2$6 = {
|
|
7368
7692
|
key: 4,
|
|
7369
7693
|
points: "6 9 12 15 18 9"
|
|
7370
7694
|
};
|
|
7371
|
-
const _hoisted_3$
|
|
7695
|
+
const _hoisted_3$6 = {
|
|
7372
7696
|
key: 5,
|
|
7373
7697
|
points: "18 15 12 9 6 15"
|
|
7374
7698
|
};
|
|
7375
7699
|
|
|
7376
|
-
function render$
|
|
7700
|
+
function render$8(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7377
7701
|
return (openBlock(), createElementBlock("svg", {
|
|
7378
7702
|
class: "sf-icon",
|
|
7379
7703
|
width: $props.size,
|
|
@@ -7436,19 +7760,19 @@ function render$7(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
7436
7760
|
_cache[7] || (_cache[7] = createBaseVNode("polyline", { points: "19 12 12 19 5 12" }, null, -1 /* CACHED */))
|
|
7437
7761
|
], 64 /* STABLE_FRAGMENT */))
|
|
7438
7762
|
: ($props.name === 'chevron-down')
|
|
7439
|
-
? (openBlock(), createElementBlock("polyline", _hoisted_2$
|
|
7763
|
+
? (openBlock(), createElementBlock("polyline", _hoisted_2$6))
|
|
7440
7764
|
: ($props.name === 'chevron-up')
|
|
7441
|
-
? (openBlock(), createElementBlock("polyline", _hoisted_3$
|
|
7765
|
+
? (openBlock(), createElementBlock("polyline", _hoisted_3$6))
|
|
7442
7766
|
: ($props.name === 'grip')
|
|
7443
7767
|
? (openBlock(), createElementBlock(Fragment, { key: 6 }, [
|
|
7444
7768
|
_cache[8] || (_cache[8] = createStaticVNode("<circle cx=\"9\" cy=\"7\" r=\"1\" fill=\"currentColor\" stroke=\"none\"></circle><circle cx=\"15\" cy=\"7\" r=\"1\" fill=\"currentColor\" stroke=\"none\"></circle><circle cx=\"9\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\"></circle><circle cx=\"15\" cy=\"12\" r=\"1\" fill=\"currentColor\" stroke=\"none\"></circle><circle cx=\"9\" cy=\"17\" r=\"1\" fill=\"currentColor\" stroke=\"none\"></circle><circle cx=\"15\" cy=\"17\" r=\"1\" fill=\"currentColor\" stroke=\"none\"></circle>", 6))
|
|
7445
7769
|
], 64 /* STABLE_FRAGMENT */))
|
|
7446
7770
|
: createCommentVNode("v-if", true)
|
|
7447
|
-
], 8 /* PROPS */, _hoisted_1$
|
|
7771
|
+
], 8 /* PROPS */, _hoisted_1$7))
|
|
7448
7772
|
}
|
|
7449
7773
|
|
|
7450
|
-
script$
|
|
7451
|
-
script$
|
|
7774
|
+
script$9.render = render$8;
|
|
7775
|
+
script$9.__file = "src/editors/SfIcon.vue";
|
|
7452
7776
|
|
|
7453
7777
|
// JSON Schema conditional evaluation for form rendering.
|
|
7454
7778
|
//
|
|
@@ -7699,12 +8023,12 @@ function hasConditionals(schema) {
|
|
|
7699
8023
|
return false;
|
|
7700
8024
|
}
|
|
7701
8025
|
|
|
7702
|
-
var script$
|
|
8026
|
+
var script$8 = {
|
|
7703
8027
|
name: 'ObjectEditor',
|
|
7704
8028
|
beforeCreate() {
|
|
7705
8029
|
if (!this.$options.components) this.$options.components = {};
|
|
7706
8030
|
this.$options.components.SchemaEditor = script$1;
|
|
7707
|
-
this.$options.components.SfIcon = script$
|
|
8031
|
+
this.$options.components.SfIcon = script$9;
|
|
7708
8032
|
},
|
|
7709
8033
|
props: {
|
|
7710
8034
|
schema: { type: Object, required: true },
|
|
@@ -7716,6 +8040,9 @@ var script$7 = {
|
|
|
7716
8040
|
data() {
|
|
7717
8041
|
return {
|
|
7718
8042
|
collapsed: false,
|
|
8043
|
+
// Values pruned when a conditional rule deactivated their field,
|
|
8044
|
+
// kept so toggling the controller back restores what the user typed.
|
|
8045
|
+
prunedStash: {},
|
|
7719
8046
|
};
|
|
7720
8047
|
},
|
|
7721
8048
|
computed: {
|
|
@@ -7763,10 +8090,21 @@ var script$7 = {
|
|
|
7763
8090
|
const allowed = new Set(Object.keys(effective.properties || {}));
|
|
7764
8091
|
let changed = false;
|
|
7765
8092
|
const out = {};
|
|
8093
|
+
// restore stashed values for fields a rule just re-activated
|
|
8094
|
+
for (const k of allowed) {
|
|
8095
|
+
if (!(k in value) && k in this.prunedStash) {
|
|
8096
|
+
out[k] = this.prunedStash[k];
|
|
8097
|
+
delete this.prunedStash[k];
|
|
8098
|
+
changed = true;
|
|
8099
|
+
}
|
|
8100
|
+
}
|
|
7766
8101
|
for (const k of Object.keys(value)) {
|
|
7767
8102
|
if (allowed.has(k)) {
|
|
7768
8103
|
out[k] = value[k];
|
|
7769
8104
|
} else {
|
|
8105
|
+
// pruned from the emitted value (documented behavior), but kept
|
|
8106
|
+
// locally so a controller toggle round-trip is not destructive
|
|
8107
|
+
this.prunedStash[k] = value[k];
|
|
7770
8108
|
changed = true;
|
|
7771
8109
|
}
|
|
7772
8110
|
}
|
|
@@ -7775,27 +8113,27 @@ var script$7 = {
|
|
|
7775
8113
|
},
|
|
7776
8114
|
};
|
|
7777
8115
|
|
|
7778
|
-
const _hoisted_1$
|
|
8116
|
+
const _hoisted_1$6 = {
|
|
7779
8117
|
key: 0,
|
|
7780
8118
|
class: "sf-object sf-object-root"
|
|
7781
8119
|
};
|
|
7782
|
-
const _hoisted_2$
|
|
7783
|
-
const _hoisted_3$
|
|
7784
|
-
const _hoisted_4$
|
|
7785
|
-
const _hoisted_5$
|
|
8120
|
+
const _hoisted_2$5 = { class: "sf-object-fields" };
|
|
8121
|
+
const _hoisted_3$5 = { class: "sf-object-title" };
|
|
8122
|
+
const _hoisted_4$4 = ["aria-label"];
|
|
8123
|
+
const _hoisted_5$4 = { class: "sf-object-title-text" };
|
|
7786
8124
|
const _hoisted_6$3 = {
|
|
7787
8125
|
key: 0,
|
|
7788
8126
|
class: "sf-object-summary"
|
|
7789
8127
|
};
|
|
7790
8128
|
const _hoisted_7$2 = { class: "sf-object-fields" };
|
|
7791
8129
|
|
|
7792
|
-
function render$
|
|
8130
|
+
function render$7(_ctx, _cache, $props, $setup, $data, $options) {
|
|
7793
8131
|
const _component_SchemaEditor = resolveComponent("SchemaEditor");
|
|
7794
8132
|
const _component_SfIcon = resolveComponent("SfIcon");
|
|
7795
8133
|
|
|
7796
8134
|
return ($options.isRoot)
|
|
7797
|
-
? (openBlock(), createElementBlock("div", _hoisted_1$
|
|
7798
|
-
createBaseVNode("div", _hoisted_2$
|
|
8135
|
+
? (openBlock(), createElementBlock("div", _hoisted_1$6, [
|
|
8136
|
+
createBaseVNode("div", _hoisted_2$5, [
|
|
7799
8137
|
(openBlock(true), createElementBlock(Fragment, null, renderList(($options.effectiveSchema.properties || {}), (propSchema, key) => {
|
|
7800
8138
|
return (openBlock(), createBlock(_component_SchemaEditor, {
|
|
7801
8139
|
key: key,
|
|
@@ -7812,7 +8150,7 @@ function render$6(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
7812
8150
|
key: 1,
|
|
7813
8151
|
class: normalizeClass(["sf-object", { 'sf-object-collapsed': $data.collapsed }])
|
|
7814
8152
|
}, [
|
|
7815
|
-
createBaseVNode("legend", _hoisted_3$
|
|
8153
|
+
createBaseVNode("legend", _hoisted_3$5, [
|
|
7816
8154
|
createBaseVNode("button", {
|
|
7817
8155
|
type: "button",
|
|
7818
8156
|
class: "sf-collapse-btn",
|
|
@@ -7823,8 +8161,8 @@ function render$6(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
7823
8161
|
name: $data.collapsed ? 'chevron-down' : 'chevron-up',
|
|
7824
8162
|
size: 12
|
|
7825
8163
|
}, null, 8 /* PROPS */, ["name"])
|
|
7826
|
-
], 8 /* PROPS */, _hoisted_4$
|
|
7827
|
-
createBaseVNode("span", _hoisted_5$
|
|
8164
|
+
], 8 /* PROPS */, _hoisted_4$4),
|
|
8165
|
+
createBaseVNode("span", _hoisted_5$4, toDisplayString($options.title), 1 /* TEXT */),
|
|
7828
8166
|
($data.collapsed && $options.summary)
|
|
7829
8167
|
? (openBlock(), createElementBlock("span", _hoisted_6$3, toDisplayString($options.summary), 1 /* TEXT */))
|
|
7830
8168
|
: createCommentVNode("v-if", true)
|
|
@@ -7846,56 +8184,17 @@ function render$6(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
7846
8184
|
], 2 /* CLASS */))
|
|
7847
8185
|
}
|
|
7848
8186
|
|
|
7849
|
-
script$
|
|
7850
|
-
script$
|
|
7851
|
-
|
|
7852
|
-
function debounce(fn, delay) {
|
|
7853
|
-
let timer;
|
|
7854
|
-
return function (...args) {
|
|
7855
|
-
clearTimeout(timer);
|
|
7856
|
-
timer = setTimeout(() => fn.apply(this, args), delay);
|
|
7857
|
-
};
|
|
7858
|
-
}
|
|
7859
|
-
|
|
7860
|
-
function deepClone(obj) {
|
|
7861
|
-
if (obj === null || typeof obj !== 'object') return obj;
|
|
7862
|
-
if (Array.isArray(obj)) return obj.map(deepClone);
|
|
7863
|
-
const clone = {};
|
|
7864
|
-
for (const key of Object.keys(obj)) {
|
|
7865
|
-
clone[key] = deepClone(obj[key]);
|
|
7866
|
-
}
|
|
7867
|
-
return clone;
|
|
7868
|
-
}
|
|
7869
|
-
|
|
7870
|
-
function getDefaultForSchema(schema) {
|
|
7871
|
-
if ('default' in schema) return deepClone(schema.default);
|
|
7872
|
-
if (schema.type === 'object') {
|
|
7873
|
-
const obj = {};
|
|
7874
|
-
for (const [key, prop] of Object.entries(schema.properties || {})) {
|
|
7875
|
-
if ('default' in prop) obj[key] = deepClone(prop.default);
|
|
7876
|
-
else if (prop.type === 'string') obj[key] = '';
|
|
7877
|
-
else if (prop.type === 'integer' || prop.type === 'number') obj[key] = 0;
|
|
7878
|
-
else if (prop.type === 'boolean') obj[key] = false;
|
|
7879
|
-
else if (prop.type === 'array') obj[key] = [];
|
|
7880
|
-
}
|
|
7881
|
-
return obj;
|
|
7882
|
-
}
|
|
7883
|
-
if (schema.type === 'array') return [];
|
|
7884
|
-
if (schema.type === 'string') return '';
|
|
7885
|
-
if (schema.type === 'integer' || schema.type === 'number') return 0;
|
|
7886
|
-
if (schema.type === 'boolean') return false;
|
|
7887
|
-
if (schema.type === 'relation') return schema.multiple ? [] : null;
|
|
7888
|
-
return null;
|
|
7889
|
-
}
|
|
8187
|
+
script$8.render = render$7;
|
|
8188
|
+
script$8.__file = "src/editors/ObjectEditor.vue";
|
|
7890
8189
|
|
|
7891
8190
|
let keyCounter = 0;
|
|
7892
8191
|
|
|
7893
|
-
var script$
|
|
8192
|
+
var script$7 = {
|
|
7894
8193
|
name: 'ArrayEditor',
|
|
7895
8194
|
beforeCreate() {
|
|
7896
8195
|
if (!this.$options.components) this.$options.components = {};
|
|
7897
8196
|
this.$options.components.SchemaEditor = script$1;
|
|
7898
|
-
this.$options.components.SfIcon = script$
|
|
8197
|
+
this.$options.components.SfIcon = script$9;
|
|
7899
8198
|
},
|
|
7900
8199
|
props: {
|
|
7901
8200
|
schema: { type: Object, required: true },
|
|
@@ -7995,11 +8294,11 @@ var script$6 = {
|
|
|
7995
8294
|
},
|
|
7996
8295
|
};
|
|
7997
8296
|
|
|
7998
|
-
const _hoisted_1$
|
|
7999
|
-
const _hoisted_2$
|
|
8000
|
-
const _hoisted_3$
|
|
8001
|
-
const _hoisted_4$
|
|
8002
|
-
const _hoisted_5$
|
|
8297
|
+
const _hoisted_1$5 = { class: "sf-array-header" };
|
|
8298
|
+
const _hoisted_2$4 = { class: "sf-label" };
|
|
8299
|
+
const _hoisted_3$4 = { class: "sf-array-count" };
|
|
8300
|
+
const _hoisted_4$3 = ["title"];
|
|
8301
|
+
const _hoisted_5$3 = { class: "sf-array-items" };
|
|
8003
8302
|
const _hoisted_6$2 = ["onDragstart", "onDragover", "onDragleave", "onDrop"];
|
|
8004
8303
|
const _hoisted_7$1 = { class: "sf-array-item-header" };
|
|
8005
8304
|
const _hoisted_8$1 = { class: "sf-array-item-left" };
|
|
@@ -8018,16 +8317,16 @@ const _hoisted_16 = {
|
|
|
8018
8317
|
class: "errorlist"
|
|
8019
8318
|
};
|
|
8020
8319
|
|
|
8021
|
-
function render$
|
|
8320
|
+
function render$6(_ctx, _cache, $props, $setup, $data, $options) {
|
|
8022
8321
|
const _component_SfIcon = resolveComponent("SfIcon");
|
|
8023
8322
|
const _component_SchemaEditor = resolveComponent("SchemaEditor");
|
|
8024
8323
|
|
|
8025
8324
|
return (openBlock(), createElementBlock("div", {
|
|
8026
8325
|
class: normalizeClass(["sf-array", { errors: $options.fieldErrors.length }])
|
|
8027
8326
|
}, [
|
|
8028
|
-
createBaseVNode("div", _hoisted_1$
|
|
8029
|
-
createBaseVNode("span", _hoisted_2$
|
|
8030
|
-
createBaseVNode("span", _hoisted_3$
|
|
8327
|
+
createBaseVNode("div", _hoisted_1$5, [
|
|
8328
|
+
createBaseVNode("span", _hoisted_2$4, toDisplayString($options.title), 1 /* TEXT */),
|
|
8329
|
+
createBaseVNode("span", _hoisted_3$4, toDisplayString($data.items.length), 1 /* TEXT */),
|
|
8031
8330
|
createBaseVNode("button", {
|
|
8032
8331
|
type: "button",
|
|
8033
8332
|
class: "sf-btn sf-btn-add",
|
|
@@ -8046,10 +8345,10 @@ function render$5(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8046
8345
|
createVNode(_component_SfIcon, {
|
|
8047
8346
|
name: $data.allCollapsed ? 'chevron-down' : 'chevron-up'
|
|
8048
8347
|
}, null, 8 /* PROPS */, ["name"])
|
|
8049
|
-
], 8 /* PROPS */, _hoisted_4$
|
|
8348
|
+
], 8 /* PROPS */, _hoisted_4$3))
|
|
8050
8349
|
: createCommentVNode("v-if", true)
|
|
8051
8350
|
]),
|
|
8052
|
-
createBaseVNode("div", _hoisted_5$
|
|
8351
|
+
createBaseVNode("div", _hoisted_5$3, [
|
|
8053
8352
|
(openBlock(true), createElementBlock(Fragment, null, renderList($data.items, (item, index) => {
|
|
8054
8353
|
return (openBlock(), createElementBlock("div", {
|
|
8055
8354
|
key: item._key,
|
|
@@ -8126,15 +8425,15 @@ function render$5(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8126
8425
|
], 2 /* CLASS */))
|
|
8127
8426
|
}
|
|
8128
8427
|
|
|
8129
|
-
script$
|
|
8130
|
-
script$
|
|
8428
|
+
script$7.render = render$6;
|
|
8429
|
+
script$7.__file = "src/editors/ArrayEditor.vue";
|
|
8131
8430
|
|
|
8132
|
-
var script$
|
|
8431
|
+
var script$6 = {
|
|
8133
8432
|
name: 'NullableEditor',
|
|
8134
8433
|
beforeCreate() {
|
|
8135
8434
|
if (!this.$options.components) this.$options.components = {};
|
|
8136
8435
|
this.$options.components.SchemaEditor = script$1;
|
|
8137
|
-
this.$options.components.SfIcon = script$
|
|
8436
|
+
this.$options.components.SfIcon = script$9;
|
|
8138
8437
|
},
|
|
8139
8438
|
props: {
|
|
8140
8439
|
schema: { type: Object, required: true },
|
|
@@ -8194,22 +8493,22 @@ var script$5 = {
|
|
|
8194
8493
|
},
|
|
8195
8494
|
};
|
|
8196
8495
|
|
|
8197
|
-
const _hoisted_1$
|
|
8198
|
-
const _hoisted_2$
|
|
8199
|
-
const _hoisted_3$
|
|
8496
|
+
const _hoisted_1$4 = { class: "sf-nullable-header" };
|
|
8497
|
+
const _hoisted_2$3 = { class: "sf-nullable-body" };
|
|
8498
|
+
const _hoisted_3$3 = {
|
|
8200
8499
|
key: 0,
|
|
8201
8500
|
class: "errorlist"
|
|
8202
8501
|
};
|
|
8203
8502
|
|
|
8204
|
-
function render$
|
|
8503
|
+
function render$5(_ctx, _cache, $props, $setup, $data, $options) {
|
|
8205
8504
|
const _component_SfIcon = resolveComponent("SfIcon");
|
|
8206
8505
|
const _component_SchemaEditor = resolveComponent("SchemaEditor");
|
|
8207
8506
|
|
|
8208
8507
|
return (openBlock(), createElementBlock("div", {
|
|
8209
8508
|
class: normalizeClass(["sf-nullable", { errors: $options.fieldErrors.length }])
|
|
8210
8509
|
}, [
|
|
8211
|
-
createBaseVNode("div", _hoisted_1$
|
|
8212
|
-
createBaseVNode("
|
|
8510
|
+
createBaseVNode("div", _hoisted_1$4, [
|
|
8511
|
+
createBaseVNode("span", {
|
|
8213
8512
|
class: normalizeClass(["sf-label", { required: $options.isRequired }])
|
|
8214
8513
|
}, toDisplayString($options.title), 3 /* TEXT, CLASS */),
|
|
8215
8514
|
createBaseVNode("button", {
|
|
@@ -8228,7 +8527,7 @@ function render$4(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8228
8527
|
], 64 /* STABLE_FRAGMENT */))
|
|
8229
8528
|
], 2 /* CLASS */)
|
|
8230
8529
|
]),
|
|
8231
|
-
createBaseVNode("div", _hoisted_2$
|
|
8530
|
+
createBaseVNode("div", _hoisted_2$3, [
|
|
8232
8531
|
(!$data.isNull)
|
|
8233
8532
|
? (openBlock(), createBlock(_component_SchemaEditor, {
|
|
8234
8533
|
key: 0,
|
|
@@ -8241,7 +8540,7 @@ function render$4(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8241
8540
|
: createCommentVNode("v-if", true)
|
|
8242
8541
|
]),
|
|
8243
8542
|
($options.fieldErrors.length)
|
|
8244
|
-
? (openBlock(), createElementBlock("ul", _hoisted_3$
|
|
8543
|
+
? (openBlock(), createElementBlock("ul", _hoisted_3$3, [
|
|
8245
8544
|
(openBlock(true), createElementBlock(Fragment, null, renderList($options.fieldErrors, (err, i) => {
|
|
8246
8545
|
return (openBlock(), createElementBlock("li", { key: i }, toDisplayString(err), 1 /* TEXT */))
|
|
8247
8546
|
}), 128 /* KEYED_FRAGMENT */))
|
|
@@ -8250,10 +8549,10 @@ function render$4(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8250
8549
|
], 2 /* CLASS */))
|
|
8251
8550
|
}
|
|
8252
8551
|
|
|
8253
|
-
script$
|
|
8254
|
-
script$
|
|
8552
|
+
script$6.render = render$5;
|
|
8553
|
+
script$6.__file = "src/editors/NullableEditor.vue";
|
|
8255
8554
|
|
|
8256
|
-
var script$
|
|
8555
|
+
var script$5 = {
|
|
8257
8556
|
name: 'UnionEditor',
|
|
8258
8557
|
beforeCreate() {
|
|
8259
8558
|
if (!this.$options.components) this.$options.components = {};
|
|
@@ -8314,19 +8613,19 @@ var script$4 = {
|
|
|
8314
8613
|
},
|
|
8315
8614
|
};
|
|
8316
8615
|
|
|
8317
|
-
const _hoisted_1$
|
|
8318
|
-
const _hoisted_2$
|
|
8319
|
-
const _hoisted_3$
|
|
8320
|
-
const _hoisted_4$
|
|
8321
|
-
const _hoisted_5$
|
|
8616
|
+
const _hoisted_1$3 = { class: "sf-union" };
|
|
8617
|
+
const _hoisted_2$2 = { class: "sf-field" };
|
|
8618
|
+
const _hoisted_3$2 = { class: "sf-label" };
|
|
8619
|
+
const _hoisted_4$2 = ["value"];
|
|
8620
|
+
const _hoisted_5$2 = ["value"];
|
|
8322
8621
|
const _hoisted_6$1 = { class: "sf-union-body" };
|
|
8323
8622
|
|
|
8324
|
-
function render$
|
|
8623
|
+
function render$4(_ctx, _cache, $props, $setup, $data, $options) {
|
|
8325
8624
|
const _component_SchemaEditor = resolveComponent("SchemaEditor");
|
|
8326
8625
|
|
|
8327
|
-
return (openBlock(), createElementBlock("div", _hoisted_1$
|
|
8328
|
-
createBaseVNode("div", _hoisted_2$
|
|
8329
|
-
createBaseVNode("
|
|
8626
|
+
return (openBlock(), createElementBlock("div", _hoisted_1$3, [
|
|
8627
|
+
createBaseVNode("div", _hoisted_2$2, [
|
|
8628
|
+
createBaseVNode("span", _hoisted_3$2, toDisplayString($options.title), 1 /* TEXT */),
|
|
8330
8629
|
createBaseVNode("select", {
|
|
8331
8630
|
class: "sf-input sf-select",
|
|
8332
8631
|
value: $data.currentType,
|
|
@@ -8336,9 +8635,9 @@ function render$3(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8336
8635
|
return (openBlock(), createElementBlock("option", {
|
|
8337
8636
|
key: key,
|
|
8338
8637
|
value: key
|
|
8339
|
-
}, toDisplayString($options.humanize(key)), 9 /* TEXT, PROPS */, _hoisted_5$
|
|
8638
|
+
}, toDisplayString($options.humanize(key)), 9 /* TEXT, PROPS */, _hoisted_5$2))
|
|
8340
8639
|
}), 128 /* KEYED_FRAGMENT */))
|
|
8341
|
-
], 40 /* PROPS, NEED_HYDRATION */, _hoisted_4$
|
|
8640
|
+
], 40 /* PROPS, NEED_HYDRATION */, _hoisted_4$2)
|
|
8342
8641
|
]),
|
|
8343
8642
|
createBaseVNode("div", _hoisted_6$1, [
|
|
8344
8643
|
(openBlock(), createBlock(_component_SchemaEditor, {
|
|
@@ -8353,12 +8652,12 @@ function render$3(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8353
8652
|
]))
|
|
8354
8653
|
}
|
|
8355
8654
|
|
|
8356
|
-
script$
|
|
8357
|
-
script$
|
|
8655
|
+
script$5.render = render$4;
|
|
8656
|
+
script$5.__file = "src/editors/UnionEditor.vue";
|
|
8358
8657
|
|
|
8359
|
-
var script$
|
|
8658
|
+
var script$4 = {
|
|
8360
8659
|
name: 'RelationEditor',
|
|
8361
|
-
components: { SfIcon: script$
|
|
8660
|
+
components: { SfIcon: script$9 },
|
|
8362
8661
|
inject: {
|
|
8363
8662
|
language: { from: 'language', default: () => () => '' },
|
|
8364
8663
|
},
|
|
@@ -8526,14 +8825,14 @@ var script$3 = {
|
|
|
8526
8825
|
},
|
|
8527
8826
|
};
|
|
8528
8827
|
|
|
8529
|
-
const _hoisted_1$
|
|
8530
|
-
const _hoisted_2 = {
|
|
8828
|
+
const _hoisted_1$2 = { class: "sf-relation-wrapper" };
|
|
8829
|
+
const _hoisted_2$1 = {
|
|
8531
8830
|
key: 0,
|
|
8532
8831
|
class: "sf-relation-selected"
|
|
8533
8832
|
};
|
|
8534
|
-
const _hoisted_3 = { class: "sf-relation-tag-text" };
|
|
8535
|
-
const _hoisted_4 = ["onClick"];
|
|
8536
|
-
const _hoisted_5 = { class: "sf-relation-search" };
|
|
8833
|
+
const _hoisted_3$1 = { class: "sf-relation-tag-text" };
|
|
8834
|
+
const _hoisted_4$1 = ["onClick"];
|
|
8835
|
+
const _hoisted_5$1 = { class: "sf-relation-search" };
|
|
8537
8836
|
const _hoisted_6 = ["placeholder"];
|
|
8538
8837
|
const _hoisted_7 = { class: "sf-relation-dropdown" };
|
|
8539
8838
|
const _hoisted_8 = {
|
|
@@ -8546,26 +8845,26 @@ const _hoisted_10 = {
|
|
|
8546
8845
|
class: "errorlist"
|
|
8547
8846
|
};
|
|
8548
8847
|
|
|
8549
|
-
function render$
|
|
8848
|
+
function render$3(_ctx, _cache, $props, $setup, $data, $options) {
|
|
8550
8849
|
const _component_SfIcon = resolveComponent("SfIcon");
|
|
8551
8850
|
|
|
8552
8851
|
return (openBlock(), createElementBlock("div", {
|
|
8553
8852
|
class: normalizeClass(["sf-field sf-relation", { errors: $options.fieldErrors.length }]),
|
|
8554
8853
|
ref: "root"
|
|
8555
8854
|
}, [
|
|
8556
|
-
createBaseVNode("
|
|
8855
|
+
createBaseVNode("span", {
|
|
8557
8856
|
class: normalizeClass(["sf-label", { required: $options.isRequired }])
|
|
8558
8857
|
}, toDisplayString($options.title), 3 /* TEXT, CLASS */),
|
|
8559
|
-
createBaseVNode("div", _hoisted_1$
|
|
8858
|
+
createBaseVNode("div", _hoisted_1$2, [
|
|
8560
8859
|
createCommentVNode(" Selected items "),
|
|
8561
8860
|
($data.selected.length)
|
|
8562
|
-
? (openBlock(), createElementBlock("div", _hoisted_2, [
|
|
8861
|
+
? (openBlock(), createElementBlock("div", _hoisted_2$1, [
|
|
8563
8862
|
(openBlock(true), createElementBlock(Fragment, null, renderList($data.selected, (item) => {
|
|
8564
8863
|
return (openBlock(), createElementBlock("div", {
|
|
8565
8864
|
key: $options.itemKey(item),
|
|
8566
8865
|
class: "sf-relation-tag"
|
|
8567
8866
|
}, [
|
|
8568
|
-
createBaseVNode("span", _hoisted_3, toDisplayString($options.getDisplayName(item)), 1 /* TEXT */),
|
|
8867
|
+
createBaseVNode("span", _hoisted_3$1, toDisplayString($options.getDisplayName(item)), 1 /* TEXT */),
|
|
8569
8868
|
($data.isMultiple || $data.allowClear)
|
|
8570
8869
|
? (openBlock(), createElementBlock("button", {
|
|
8571
8870
|
key: 0,
|
|
@@ -8574,14 +8873,14 @@ function render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8574
8873
|
onClick: withModifiers($event => ($options.removeItem(item)), ["stop"])
|
|
8575
8874
|
}, [
|
|
8576
8875
|
createVNode(_component_SfIcon, { name: "times" })
|
|
8577
|
-
], 8 /* PROPS */, _hoisted_4))
|
|
8876
|
+
], 8 /* PROPS */, _hoisted_4$1))
|
|
8578
8877
|
: createCommentVNode("v-if", true)
|
|
8579
8878
|
]))
|
|
8580
8879
|
}), 128 /* KEYED_FRAGMENT */))
|
|
8581
8880
|
]))
|
|
8582
8881
|
: createCommentVNode("v-if", true),
|
|
8583
8882
|
createCommentVNode(" Search box "),
|
|
8584
|
-
withDirectives(createBaseVNode("div", _hoisted_5, [
|
|
8883
|
+
withDirectives(createBaseVNode("div", _hoisted_5$1, [
|
|
8585
8884
|
withDirectives(createBaseVNode("input", {
|
|
8586
8885
|
ref: "searchInput",
|
|
8587
8886
|
type: "text",
|
|
@@ -8631,8 +8930,217 @@ function render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
8631
8930
|
], 2 /* CLASS */))
|
|
8632
8931
|
}
|
|
8633
8932
|
|
|
8933
|
+
script$4.render = render$3;
|
|
8934
|
+
script$4.__file = "src/editors/RelationEditor.vue";
|
|
8935
|
+
|
|
8936
|
+
const ACE_CDN = 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.37.5/ace.min.js';
|
|
8937
|
+
|
|
8938
|
+
function loadAce() {
|
|
8939
|
+
if (window.ace) return Promise.resolve(window.ace);
|
|
8940
|
+
return new Promise((resolve, reject) => {
|
|
8941
|
+
const existing = document.querySelector(`script[src="${ACE_CDN}"]`);
|
|
8942
|
+
if (existing) {
|
|
8943
|
+
existing.addEventListener('load', () => resolve(window.ace));
|
|
8944
|
+
existing.addEventListener('error', reject);
|
|
8945
|
+
return;
|
|
8946
|
+
}
|
|
8947
|
+
const s = document.createElement('script');
|
|
8948
|
+
s.src = ACE_CDN;
|
|
8949
|
+
s.async = true;
|
|
8950
|
+
s.onload = () => resolve(window.ace);
|
|
8951
|
+
s.onerror = () => reject(new Error('Failed to load Ace Editor'));
|
|
8952
|
+
document.head.appendChild(s);
|
|
8953
|
+
});
|
|
8954
|
+
}
|
|
8955
|
+
|
|
8956
|
+
var script$3 = {
|
|
8957
|
+
name: 'JsonEditor',
|
|
8958
|
+
props: {
|
|
8959
|
+
schema: { type: Object, required: true },
|
|
8960
|
+
modelValue: { default: null },
|
|
8961
|
+
path: { type: Array, default: () => [] },
|
|
8962
|
+
form: { type: Object, default: null },
|
|
8963
|
+
},
|
|
8964
|
+
emits: ['update:modelValue'],
|
|
8965
|
+
data() {
|
|
8966
|
+
return {
|
|
8967
|
+
rawValue: this.modelValue != null ? JSON.stringify(this.modelValue, null, 2) : '{}',
|
|
8968
|
+
ready: false,
|
|
8969
|
+
hasErrors: false,
|
|
8970
|
+
loadError: null,
|
|
8971
|
+
_editor: null,
|
|
8972
|
+
_silent: false,
|
|
8973
|
+
};
|
|
8974
|
+
},
|
|
8975
|
+
computed: {
|
|
8976
|
+
title() {
|
|
8977
|
+
return this.schema.title || this.humanize(this.path[this.path.length - 1]) || '';
|
|
8978
|
+
},
|
|
8979
|
+
isRequired() {
|
|
8980
|
+
if (this.path.length < 2 || !this.form) return false;
|
|
8981
|
+
const parentPath = this.path.slice(0, -1);
|
|
8982
|
+
const fieldName = this.path[this.path.length - 1];
|
|
8983
|
+
const parentSchema = this.form.getSchemaAtPath(parentPath);
|
|
8984
|
+
return parentSchema && Array.isArray(parentSchema.required) && parentSchema.required.includes(fieldName);
|
|
8985
|
+
},
|
|
8986
|
+
fieldErrors() {
|
|
8987
|
+
if (!this.form || !this.form.getErrorsForPath) return [];
|
|
8988
|
+
return this.form.getErrorsForPath(this.path);
|
|
8989
|
+
},
|
|
8990
|
+
},
|
|
8991
|
+
watch: {
|
|
8992
|
+
modelValue(val) {
|
|
8993
|
+
if (this._silent) return;
|
|
8994
|
+
const external = val != null ? JSON.stringify(val, null, 2) : '{}';
|
|
8995
|
+
try {
|
|
8996
|
+
if (JSON.stringify(JSON.parse(this.rawValue)) !== JSON.stringify(val)) {
|
|
8997
|
+
this.rawValue = external;
|
|
8998
|
+
if (this._editor) {
|
|
8999
|
+
this._silent = true;
|
|
9000
|
+
this._editor.setValue(external, -1);
|
|
9001
|
+
this._silent = false;
|
|
9002
|
+
}
|
|
9003
|
+
}
|
|
9004
|
+
} catch { /* rawValue is invalid, leave it */ }
|
|
9005
|
+
},
|
|
9006
|
+
},
|
|
9007
|
+
async mounted() {
|
|
9008
|
+
try {
|
|
9009
|
+
const ace = await loadAce();
|
|
9010
|
+
const container = this.$refs.aceContainer;
|
|
9011
|
+
if (!container) return;
|
|
9012
|
+
|
|
9013
|
+
const editor = ace.edit(container);
|
|
9014
|
+
editor.setTheme(this._isDark() ? 'ace/theme/one_dark' : 'ace/theme/chrome');
|
|
9015
|
+
editor.session.setMode('ace/mode/json');
|
|
9016
|
+
editor.session.setTabSize(2);
|
|
9017
|
+
editor.session.setUseSoftTabs(true);
|
|
9018
|
+
editor.setShowPrintMargin(false);
|
|
9019
|
+
editor.setOption('minLines', 5);
|
|
9020
|
+
editor.setOption('maxLines', 20);
|
|
9021
|
+
editor.setValue(this.rawValue, -1);
|
|
9022
|
+
editor.$blockScrolling = Infinity;
|
|
9023
|
+
|
|
9024
|
+
editor.session.on('change', () => {
|
|
9025
|
+
if (this._silent) return;
|
|
9026
|
+
const text = editor.getValue();
|
|
9027
|
+
this.rawValue = text;
|
|
9028
|
+
try {
|
|
9029
|
+
const parsed = JSON.parse(text);
|
|
9030
|
+
this.hasErrors = false;
|
|
9031
|
+
this._silent = true;
|
|
9032
|
+
this.$emit('update:modelValue', parsed);
|
|
9033
|
+
this._silent = false;
|
|
9034
|
+
} catch {
|
|
9035
|
+
this.hasErrors = true;
|
|
9036
|
+
}
|
|
9037
|
+
});
|
|
9038
|
+
|
|
9039
|
+
// Reflect annotation (lint) errors on hasErrors
|
|
9040
|
+
editor.session.on('changeAnnotation', () => {
|
|
9041
|
+
const annotations = editor.session.getAnnotations();
|
|
9042
|
+
this.hasErrors = annotations.some(a => a.type === 'error');
|
|
9043
|
+
});
|
|
9044
|
+
|
|
9045
|
+
this._editor = editor;
|
|
9046
|
+
this.ready = true;
|
|
9047
|
+
} catch (err) {
|
|
9048
|
+
this.loadError = `Editor unavailable: ${err.message}`;
|
|
9049
|
+
}
|
|
9050
|
+
},
|
|
9051
|
+
beforeUnmount() {
|
|
9052
|
+
if (this._editor) {
|
|
9053
|
+
this._editor.destroy();
|
|
9054
|
+
this._editor = null;
|
|
9055
|
+
}
|
|
9056
|
+
},
|
|
9057
|
+
methods: {
|
|
9058
|
+
humanize(str) {
|
|
9059
|
+
if (!str) return '';
|
|
9060
|
+
return str.replace(/_/g, ' ').replace(/([a-z])([A-Z])/g, '$1 $2').replace(/^./, s => s.toUpperCase());
|
|
9061
|
+
},
|
|
9062
|
+
_isDark() {
|
|
9063
|
+
return document.documentElement.dataset.colorScheme === 'dark' ||
|
|
9064
|
+
window.matchMedia?.('(prefers-color-scheme: dark)').matches;
|
|
9065
|
+
},
|
|
9066
|
+
format() {
|
|
9067
|
+
if (!this._editor) return;
|
|
9068
|
+
try {
|
|
9069
|
+
const formatted = JSON.stringify(JSON.parse(this._editor.getValue()), null, 2);
|
|
9070
|
+
this._silent = true;
|
|
9071
|
+
this._editor.setValue(formatted, -1);
|
|
9072
|
+
this._silent = false;
|
|
9073
|
+
this.rawValue = formatted;
|
|
9074
|
+
} catch { /* invalid JSON */ }
|
|
9075
|
+
},
|
|
9076
|
+
onFallbackInput(e) {
|
|
9077
|
+
this.rawValue = e.target.value;
|
|
9078
|
+
try { this.$emit('update:modelValue', JSON.parse(this.rawValue)); } catch { /* ignore */ }
|
|
9079
|
+
},
|
|
9080
|
+
},
|
|
9081
|
+
};
|
|
9082
|
+
|
|
9083
|
+
const _hoisted_1$1 = { class: "sf-json-toolbar" };
|
|
9084
|
+
const _hoisted_2 = {
|
|
9085
|
+
key: 0,
|
|
9086
|
+
class: "sf-json-error-msg"
|
|
9087
|
+
};
|
|
9088
|
+
const _hoisted_3 = {
|
|
9089
|
+
ref: "aceContainer",
|
|
9090
|
+
class: "sf-json-ace-container"
|
|
9091
|
+
};
|
|
9092
|
+
const _hoisted_4 = ["value"];
|
|
9093
|
+
const _hoisted_5 = {
|
|
9094
|
+
key: 0,
|
|
9095
|
+
class: "errorlist"
|
|
9096
|
+
};
|
|
9097
|
+
|
|
9098
|
+
function render$2(_ctx, _cache, $props, $setup, $data, $options) {
|
|
9099
|
+
return (openBlock(), createElementBlock("div", {
|
|
9100
|
+
class: normalizeClass(["sf-field sf-field-json", { errors: $options.fieldErrors.length }])
|
|
9101
|
+
}, [
|
|
9102
|
+
createBaseVNode("span", {
|
|
9103
|
+
class: normalizeClass(["sf-label", { required: $options.isRequired }])
|
|
9104
|
+
}, toDisplayString($options.title), 3 /* TEXT, CLASS */),
|
|
9105
|
+
createBaseVNode("div", {
|
|
9106
|
+
class: normalizeClass(["sf-json-editor", { 'sf-json-error': $data.hasErrors }])
|
|
9107
|
+
}, [
|
|
9108
|
+
createBaseVNode("div", _hoisted_1$1, [
|
|
9109
|
+
($data.loadError)
|
|
9110
|
+
? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString($data.loadError), 1 /* TEXT */))
|
|
9111
|
+
: createCommentVNode("v-if", true),
|
|
9112
|
+
($data.ready)
|
|
9113
|
+
? (openBlock(), createElementBlock("button", {
|
|
9114
|
+
key: 1,
|
|
9115
|
+
type: "button",
|
|
9116
|
+
class: "sf-btn sf-btn-sm sf-json-format-btn",
|
|
9117
|
+
onClick: _cache[0] || (_cache[0] = (...args) => ($options.format && $options.format(...args)))
|
|
9118
|
+
}, " Format "))
|
|
9119
|
+
: createCommentVNode("v-if", true)
|
|
9120
|
+
]),
|
|
9121
|
+
createBaseVNode("div", _hoisted_3, null, 512 /* NEED_PATCH */),
|
|
9122
|
+
(!$data.ready)
|
|
9123
|
+
? (openBlock(), createElementBlock("textarea", {
|
|
9124
|
+
key: 0,
|
|
9125
|
+
class: "sf-input sf-textarea sf-json-textarea-fallback",
|
|
9126
|
+
value: $data.rawValue,
|
|
9127
|
+
spellcheck: "false",
|
|
9128
|
+
onInput: _cache[1] || (_cache[1] = (...args) => ($options.onFallbackInput && $options.onFallbackInput(...args)))
|
|
9129
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_4))
|
|
9130
|
+
: createCommentVNode("v-if", true)
|
|
9131
|
+
], 2 /* CLASS */),
|
|
9132
|
+
($options.fieldErrors.length)
|
|
9133
|
+
? (openBlock(), createElementBlock("ul", _hoisted_5, [
|
|
9134
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.fieldErrors, (err, i) => {
|
|
9135
|
+
return (openBlock(), createElementBlock("li", { key: i }, toDisplayString(err), 1 /* TEXT */))
|
|
9136
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
9137
|
+
]))
|
|
9138
|
+
: createCommentVNode("v-if", true)
|
|
9139
|
+
], 2 /* CLASS */))
|
|
9140
|
+
}
|
|
9141
|
+
|
|
8634
9142
|
script$3.render = render$2;
|
|
8635
|
-
script$3.__file = "src/editors/
|
|
9143
|
+
script$3.__file = "src/editors/JsonEditor.vue";
|
|
8636
9144
|
|
|
8637
9145
|
var script$2 = {
|
|
8638
9146
|
name: 'WebComponentWrapper',
|
|
@@ -8693,16 +9201,18 @@ const MAX_DEPTH = 12;
|
|
|
8693
9201
|
var script$1 = {
|
|
8694
9202
|
name: 'SchemaEditor',
|
|
8695
9203
|
components: {
|
|
8696
|
-
StringEditor: script$
|
|
8697
|
-
NumberEditor: script$
|
|
8698
|
-
BooleanEditor: script$
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
9204
|
+
StringEditor: script$f,
|
|
9205
|
+
NumberEditor: script$e,
|
|
9206
|
+
BooleanEditor: script$d,
|
|
9207
|
+
DateEditor: script$c,
|
|
9208
|
+
SelectEditor: script$b,
|
|
9209
|
+
HiddenEditor: script$a,
|
|
9210
|
+
ObjectEditor: script$8,
|
|
9211
|
+
ArrayEditor: script$7,
|
|
9212
|
+
NullableEditor: script$6,
|
|
9213
|
+
UnionEditor: script$5,
|
|
9214
|
+
RelationEditor: script$4,
|
|
9215
|
+
JsonEditor: script$3,
|
|
8706
9216
|
WebComponentWrapper: script$2,
|
|
8707
9217
|
},
|
|
8708
9218
|
inject: {
|
|
@@ -8744,14 +9254,19 @@ var script$1 = {
|
|
|
8744
9254
|
|
|
8745
9255
|
if (schema.type === 'relation') return 'RelationEditor';
|
|
8746
9256
|
if (schema.oneOf && schema.discriminator) return 'UnionEditor';
|
|
9257
|
+
// Choice-list oneOf ({const, title} options) renders as a select —
|
|
9258
|
+
// must be checked before the 'const' HiddenEditor routing.
|
|
9259
|
+
if (isChoiceOneOf(schema.oneOf)) return 'SelectEditor';
|
|
8747
9260
|
if ('const' in schema) return 'HiddenEditor';
|
|
8748
9261
|
if (schema.enum && schema.enum.length === 1 && schema.type === 'string') return 'HiddenEditor';
|
|
8749
|
-
if (schema._nullable) return 'NullableEditor';
|
|
9262
|
+
if (schema._nullable && (schema.type === 'object' || schema.type === 'array')) return 'NullableEditor';
|
|
8750
9263
|
if (schema.type === 'object' && schema.properties) return 'ObjectEditor';
|
|
9264
|
+
if (schema.type === 'object') return 'JsonEditor';
|
|
8751
9265
|
if (schema.type === 'array') return 'ArrayEditor';
|
|
8752
9266
|
if (schema.enum) return 'SelectEditor';
|
|
8753
9267
|
if (schema.type === 'boolean') return 'BooleanEditor';
|
|
8754
9268
|
if (schema.type === 'number' || schema.type === 'integer') return 'NumberEditor';
|
|
9269
|
+
if (schema.type === 'string' && (schema.format === 'date' || schema.format === 'date-time')) return 'DateEditor';
|
|
8755
9270
|
|
|
8756
9271
|
return 'StringEditor';
|
|
8757
9272
|
},
|
|
@@ -8859,29 +9374,36 @@ var script = {
|
|
|
8859
9374
|
const hasNull = schema.anyOf.some(s => s.type === 'null');
|
|
8860
9375
|
if (hasNull && nonNull.length === 1) {
|
|
8861
9376
|
const resolved = this.resolveSchema(nonNull[0]);
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
};
|
|
9377
|
+
// Carry ALL sibling keys through the nullable collapse: pydantic
|
|
9378
|
+
// emits json_schema_extra (placeholder, minLength/maxLength,
|
|
9379
|
+
// minimum/maximum, format, choice oneOf, ...) as SIBLINGS of
|
|
9380
|
+
// anyOf on Optional fields. Outer keys override the inner branch.
|
|
9381
|
+
const { anyOf, oneOf, ...rest } = schema;
|
|
9382
|
+
const out = { ...resolved, ...rest, _nullable: true };
|
|
9383
|
+
if (!('default' in schema)) out.default = null;
|
|
9384
|
+
if (isChoiceOneOf(oneOf)) out.oneOf = oneOf;
|
|
9385
|
+
return out;
|
|
8868
9386
|
}
|
|
8869
9387
|
if (nonNull.length >= 1) return this.resolveSchema(nonNull[0]);
|
|
8870
9388
|
}
|
|
8871
9389
|
|
|
8872
9390
|
if (schema.oneOf && schema.discriminator) return schema;
|
|
8873
9391
|
|
|
9392
|
+
// A oneOf of {const, title} value options is a choice list (select),
|
|
9393
|
+
// not alternative sub-schemas: keep it intact for SelectEditor instead
|
|
9394
|
+
// of collapsing to the first member (which routed to HiddenEditor and
|
|
9395
|
+
// overwrote stored values on mount).
|
|
9396
|
+
if (isChoiceOneOf(schema.oneOf)) return schema;
|
|
9397
|
+
|
|
8874
9398
|
if (schema.oneOf) {
|
|
8875
9399
|
const nonNull = schema.oneOf.filter(s => s.type !== 'null');
|
|
8876
9400
|
const hasNull = schema.oneOf.some(s => s.type === 'null');
|
|
8877
9401
|
if (hasNull && nonNull.length === 1) {
|
|
8878
9402
|
const resolved = this.resolveSchema(nonNull[0]);
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
default: 'default' in schema ? schema.default : null,
|
|
8884
|
-
};
|
|
9403
|
+
const { anyOf, oneOf, ...rest } = schema;
|
|
9404
|
+
const out = { ...resolved, ...rest, _nullable: true };
|
|
9405
|
+
if (!('default' in schema)) out.default = null;
|
|
9406
|
+
return out;
|
|
8885
9407
|
}
|
|
8886
9408
|
if (nonNull.length >= 1) return this.resolveSchema(nonNull[0]);
|
|
8887
9409
|
}
|
|
@@ -9085,5 +9607,5 @@ function registerCustomElement(tagName = 'schema-form') {
|
|
|
9085
9607
|
}
|
|
9086
9608
|
}
|
|
9087
9609
|
|
|
9088
|
-
export { script$
|
|
9610
|
+
export { script$7 as ArrayEditor, BaseEditorElement, script$d as BooleanEditor, script$c as DateEditor, script$a as HiddenEditor, script$6 as NullableEditor, script$e as NumberEditor, script$8 as ObjectEditor, script$4 as RelationEditor, script$1 as SchemaEditor, script as SchemaForm, SchemaFormElement, script$b as SelectEditor, script$f as StringEditor, script$5 as UnionEditor, script$2 as WebComponentWrapper, applyConditionals, hasConditionals, matchesSchema, registerCustomElement };
|
|
9089
9611
|
//# sourceMappingURL=structured-widget-editor.esm.js.map
|