@koumoul/vjsf 2.22.1 → 3.0.0-alpha.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/package.json +50 -86
- package/src/compat/v2.js +82 -0
- package/src/compile/index.js +32 -0
- package/src/compile/v-jsf-compiled.vue.ejs +83 -0
- package/src/components/fragments/node-slot.vue +49 -0
- package/src/components/fragments/section-header.vue +52 -0
- package/src/components/fragments/text-field-menu.vue +68 -0
- package/src/components/node.vue +60 -0
- package/src/components/nodes/checkbox.vue +27 -0
- package/src/components/nodes/color-picker.vue +43 -0
- package/src/components/nodes/date-picker.vue +45 -0
- package/src/components/nodes/date-time-picker.vue +20 -0
- package/src/components/nodes/expansion-panels.vue +52 -0
- package/src/components/nodes/list.vue +112 -0
- package/src/components/nodes/number-field.vue +35 -0
- package/src/components/nodes/one-of-select.vue +56 -0
- package/src/components/nodes/section.vue +30 -0
- package/src/components/nodes/select.vue +59 -0
- package/src/components/nodes/slider.vue +34 -0
- package/src/components/nodes/switch.vue +29 -0
- package/src/components/nodes/tabs.vue +63 -0
- package/src/components/nodes/text-field.vue +29 -0
- package/src/components/nodes/textarea.vue +29 -0
- package/src/components/nodes/time-picker.vue +7 -0
- package/src/components/nodes/vertical-tabs.vue +70 -0
- package/src/components/options.js +25 -0
- package/src/components/tree.vue +25 -0
- package/src/components/types.ts +59 -0
- package/src/components/vjsf.vue +168 -0
- package/src/index.js +2 -0
- package/src/utils/clone.js +3 -0
- package/src/utils/dates.js +52 -0
- package/src/utils/props.js +79 -0
- package/src/utils/slots.js +19 -0
- package/types/compat/v2.d.ts +10 -0
- package/types/compat/v2.d.ts.map +1 -0
- package/types/compile/index.d.ts +7 -0
- package/types/compile/index.d.ts.map +1 -0
- package/types/components/fragments/node-slot.vue.d.ts +47 -0
- package/types/components/fragments/node-slot.vue.d.ts.map +1 -0
- package/types/components/fragments/section-header.vue.d.ts +8 -0
- package/types/components/fragments/section-header.vue.d.ts.map +1 -0
- package/types/components/fragments/text-field-menu.vue.d.ts +20 -0
- package/types/components/fragments/text-field-menu.vue.d.ts.map +1 -0
- package/types/components/node.vue.d.ts +10 -0
- package/types/components/node.vue.d.ts.map +1 -0
- package/types/components/nodes/checkbox.vue.d.ts +10 -0
- package/types/components/nodes/checkbox.vue.d.ts.map +1 -0
- package/types/components/nodes/color-picker.vue.d.ts +10 -0
- package/types/components/nodes/color-picker.vue.d.ts.map +1 -0
- package/types/components/nodes/date-picker.vue.d.ts +10 -0
- package/types/components/nodes/date-picker.vue.d.ts.map +1 -0
- package/types/components/nodes/date-time-picker.vue.d.ts +10 -0
- package/types/components/nodes/date-time-picker.vue.d.ts.map +1 -0
- package/types/components/nodes/expansion-panels.vue.d.ts +10 -0
- package/types/components/nodes/expansion-panels.vue.d.ts.map +1 -0
- package/types/components/nodes/list.vue.d.ts +10 -0
- package/types/components/nodes/list.vue.d.ts.map +1 -0
- package/types/components/nodes/number-field.vue.d.ts +27 -0
- package/types/components/nodes/number-field.vue.d.ts.map +1 -0
- package/types/components/nodes/one-of-select.vue.d.ts +10 -0
- package/types/components/nodes/one-of-select.vue.d.ts.map +1 -0
- package/types/components/nodes/section.vue.d.ts +10 -0
- package/types/components/nodes/section.vue.d.ts.map +1 -0
- package/types/components/nodes/select.vue.d.ts +10 -0
- package/types/components/nodes/select.vue.d.ts.map +1 -0
- package/types/components/nodes/slider.vue.d.ts +10 -0
- package/types/components/nodes/slider.vue.d.ts.map +1 -0
- package/types/components/nodes/switch.vue.d.ts +10 -0
- package/types/components/nodes/switch.vue.d.ts.map +1 -0
- package/types/components/nodes/tabs.vue.d.ts +10 -0
- package/types/components/nodes/tabs.vue.d.ts.map +1 -0
- package/types/components/nodes/text-field copy.vue.d.ts +10 -0
- package/types/components/nodes/text-field copy.vue.d.ts.map +1 -0
- package/types/components/nodes/text-field.vue.d.ts +27 -0
- package/types/components/nodes/text-field.vue.d.ts.map +1 -0
- package/types/components/nodes/textarea.vue.d.ts +27 -0
- package/types/components/nodes/textarea.vue.d.ts.map +1 -0
- package/types/components/nodes/time-picker.vue.d.ts +3 -0
- package/types/components/nodes/time-picker.vue.d.ts.map +1 -0
- package/types/components/nodes/vertical-tabs.vue.d.ts +10 -0
- package/types/components/nodes/vertical-tabs.vue.d.ts.map +1 -0
- package/types/components/options.d.ts +3 -0
- package/types/components/options.d.ts.map +1 -0
- package/types/components/tree.vue.d.ts +10 -0
- package/types/components/tree.vue.d.ts.map +1 -0
- package/types/components/types.d.ts +71 -0
- package/types/components/types.d.ts.map +1 -0
- package/types/components/v-jsf.vue.d.ts +13 -0
- package/types/components/v-jsf.vue.d.ts.map +1 -0
- package/types/components/vjsf.vue.d.ts +13 -0
- package/types/components/vjsf.vue.d.ts.map +1 -0
- package/types/index.d.ts +3 -0
- package/types/index.d.ts.map +1 -0
- package/types/utils/clone.d.ts +3 -0
- package/types/utils/clone.d.ts.map +1 -0
- package/types/utils/dates.d.ts +7 -0
- package/types/utils/dates.d.ts.map +1 -0
- package/types/utils/props.d.ts +20 -0
- package/types/utils/props.d.ts.map +1 -0
- package/types/utils/slots.d.ts +7 -0
- package/types/utils/slots.d.ts.map +1 -0
- package/.eslintignore +0 -9
- package/.eslintrc.js +0 -38
- package/.github/workflows/scrape-doc.yml +0 -14
- package/.nvmrc +0 -1
- package/CONTRIBUTE.md +0 -61
- package/FUNDING.yml +0 -1
- package/README.md +0 -19
- package/babel.config.js +0 -4
- package/dist/main.css +0 -67
- package/dist/main.js +0 -2
- package/dist/main.js.LICENSE.txt +0 -10
- package/dist/third-party.js +0 -8
- package/dist/third-party.js.LICENSE.txt +0 -8
- package/lib/VJsf.css +0 -67
- package/lib/VJsf.js +0 -117
- package/lib/VJsfNoDeps.js +0 -517
- package/lib/deps/third-party.js +0 -16
- package/lib/mixins/ColorProperty.js +0 -45
- package/lib/mixins/DateProperty.js +0 -170
- package/lib/mixins/Dependent.js +0 -69
- package/lib/mixins/EditableArray.js +0 -418
- package/lib/mixins/FileProperty.js +0 -81
- package/lib/mixins/MarkdownEditor.js +0 -183
- package/lib/mixins/ObjectContainer.js +0 -351
- package/lib/mixins/SelectProperty.js +0 -400
- package/lib/mixins/SimpleProperty.js +0 -165
- package/lib/mixins/Tooltip.js +0 -42
- package/lib/mixins/Validatable.js +0 -119
- package/lib/utils/expr-eval-parser.js +0 -21
- package/lib/utils/is-cyclic.js +0 -34
- package/lib/utils/json-refs.js +0 -209
- package/lib/utils/options.js +0 -328
- package/lib/utils/rules.js +0 -81
- package/lib/utils/schema.js +0 -100
- package/lib/utils/select.js +0 -141
- package/webpack.config.js +0 -46
package/lib/VJsfNoDeps.js
DELETED
|
@@ -1,517 +0,0 @@
|
|
|
1
|
-
import copy from 'fast-copy'
|
|
2
|
-
import { deepEqual } from 'fast-equals'
|
|
3
|
-
import jrefs from './utils/json-refs'
|
|
4
|
-
import schemaUtils from './utils/schema'
|
|
5
|
-
import { defaultOptions, iconSets, localizedMessages, formats } from './utils/options'
|
|
6
|
-
import { getRules } from './utils/rules'
|
|
7
|
-
// import isCyclic from './utils/is-cyclic'
|
|
8
|
-
import ObjectContainer from './mixins/ObjectContainer'
|
|
9
|
-
import DateProperty from './mixins/DateProperty'
|
|
10
|
-
import SimpleProperty from './mixins/SimpleProperty'
|
|
11
|
-
import FileProperty from './mixins/FileProperty'
|
|
12
|
-
import ColorProperty from './mixins/ColorProperty'
|
|
13
|
-
import SelectProperty from './mixins/SelectProperty'
|
|
14
|
-
import EditableArray from './mixins/EditableArray'
|
|
15
|
-
import MarkdownEditor from './mixins/MarkdownEditor'
|
|
16
|
-
import Tooltip from './mixins/Tooltip'
|
|
17
|
-
import Validatable from './mixins/Validatable'
|
|
18
|
-
import Dependent from './mixins/Dependent'
|
|
19
|
-
import exprEvalParser from './utils/expr-eval-parser'
|
|
20
|
-
import expr from 'property-expr'
|
|
21
|
-
import debug from 'debug'
|
|
22
|
-
|
|
23
|
-
const debugExpr = debug('vjsf:expr')
|
|
24
|
-
debugExpr.log = console.log.bind(console)
|
|
25
|
-
|
|
26
|
-
const mountingIncs = {}
|
|
27
|
-
|
|
28
|
-
export default {
|
|
29
|
-
name: 'VJsf',
|
|
30
|
-
// components,
|
|
31
|
-
mixins: [
|
|
32
|
-
ObjectContainer,
|
|
33
|
-
SimpleProperty,
|
|
34
|
-
DateProperty,
|
|
35
|
-
ColorProperty,
|
|
36
|
-
SelectProperty,
|
|
37
|
-
FileProperty,
|
|
38
|
-
EditableArray,
|
|
39
|
-
MarkdownEditor,
|
|
40
|
-
Tooltip,
|
|
41
|
-
Validatable,
|
|
42
|
-
Dependent
|
|
43
|
-
],
|
|
44
|
-
inject: ['theme'],
|
|
45
|
-
props: {
|
|
46
|
-
schema: { type: Object, required: true },
|
|
47
|
-
value: { required: true },
|
|
48
|
-
options: { type: Object },
|
|
49
|
-
optionsRoot: { type: Object },
|
|
50
|
-
modelRoot: { type: [Object, Array, String, Number, Boolean] },
|
|
51
|
-
modelKey: { type: [String, Number], default: 'root' },
|
|
52
|
-
parentKey: { type: String, default: '' },
|
|
53
|
-
required: { type: Boolean, default: false },
|
|
54
|
-
sectionDepth: { type: Number, default: 0 },
|
|
55
|
-
sharedData: { type: Object, default: () => ({}) },
|
|
56
|
-
showSectionTitle: { type: Boolean, default: false }
|
|
57
|
-
},
|
|
58
|
-
data() {
|
|
59
|
-
return {
|
|
60
|
-
loading: false,
|
|
61
|
-
fullSchema: null
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
computed: {
|
|
65
|
-
initialOptions() {
|
|
66
|
-
return this.fullKey === 'root' ? (this.options || {}) : this.optionsRoot
|
|
67
|
-
},
|
|
68
|
-
fullOptions() {
|
|
69
|
-
const _global = (typeof window !== 'undefined' && window) || (typeof global !== 'undefined' && global) || {}
|
|
70
|
-
defaultOptions.locale = (this.$vuetify.lang && this.$vuetify.lang.current) || 'en'
|
|
71
|
-
defaultOptions.defaultLocale = (this.$vuetify.lang && this.$vuetify.lang.defaultLocale) || 'en'
|
|
72
|
-
const fullOptions = Object.assign({}, defaultOptions, this.options || {}, this.resolvedSchema['x-options'] || {})
|
|
73
|
-
|
|
74
|
-
fullOptions.markdown = fullOptions.markdown ||
|
|
75
|
-
(_global.markdownit && (text => text ? _global.markdownit(fullOptions.markdownit).render(text) : '')) ||
|
|
76
|
-
((text) => text || '')
|
|
77
|
-
fullOptions.memMarkdown = fullOptions.memMarkdown || (text => {
|
|
78
|
-
this._vjsf_markdown = this._vjsf_markdown || {}
|
|
79
|
-
const key = text + ''
|
|
80
|
-
this._vjsf_markdown[key] = this._vjsf_markdown[key] || fullOptions.markdown(text)
|
|
81
|
-
return this._vjsf_markdown[key]
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
fullOptions.httpLib = fullOptions.httpLib || this.axios || this.$http || this.$axios || _global.axios
|
|
85
|
-
|
|
86
|
-
// validator function generator is either given or prepared using ajv if present in the context
|
|
87
|
-
if (!fullOptions.validator) {
|
|
88
|
-
const ajvLocalize = fullOptions.ajvLocalize || _global.ajvLocalize
|
|
89
|
-
const ajvAddFormats = fullOptions.ajvAddFormats || _global.ajvAddFormats
|
|
90
|
-
const localizeAjv = !!ajvLocalize && fullOptions.locale && ajvLocalize[fullOptions.locale]
|
|
91
|
-
let ajv = fullOptions.ajv
|
|
92
|
-
if (!ajv) {
|
|
93
|
-
const Ajv = fullOptions.Ajv || _global.Ajv || (_global.ajv7 && _global.ajv7.default) || (_global.ajv2019 && _global.ajv2019.default)
|
|
94
|
-
// TODO: use strict mode but remove our x-* annotations before
|
|
95
|
-
if (Ajv) {
|
|
96
|
-
ajv = new Ajv(localizeAjv ? { allErrors: true, messages: false, strict: false } : { strict: false })
|
|
97
|
-
if (ajvAddFormats) ajvAddFormats(ajv)
|
|
98
|
-
ajv.addFormat('hexcolor', /^#[0-9A-Fa-f]{6,8}$/)
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (ajv) {
|
|
102
|
-
fullOptions.validator = (schema) => {
|
|
103
|
-
const validate = ajv.compile(schema)
|
|
104
|
-
return (model) => {
|
|
105
|
-
const valid = validate(model)
|
|
106
|
-
if (!valid) {
|
|
107
|
-
if (localizeAjv) {
|
|
108
|
-
ajvLocalize[fullOptions.locale](validate.errors)
|
|
109
|
-
}
|
|
110
|
-
return ajv.errorsText(validate.errors, { dataVar: '' })
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
fullOptions.iconfont = (this.$vuetify.icons && this.$vuetify.icons.iconfont) || 'mdi'
|
|
117
|
-
// importing default icon fonts from vuetify
|
|
118
|
-
if (!fullOptions.defaultIcons) {
|
|
119
|
-
const vuetifyCustomIcons = {}
|
|
120
|
-
for (const [key, value] of Object.entries(this.$vuetify.icons.values)) {
|
|
121
|
-
vuetifyCustomIcons[key] = value.props ? value.props.name : value
|
|
122
|
-
}
|
|
123
|
-
fullOptions.defaultIcons = { ...iconSets[fullOptions.iconfont], ...vuetifyCustomIcons }
|
|
124
|
-
fullOptions.icons = { ...fullOptions.defaultIcons, ...fullOptions.icons }
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
fullOptions.messages = { ...(localizedMessages[fullOptions.defaultLocale] || localizedMessages.en), ...(localizedMessages[fullOptions.locale] || localizedMessages.en), ...fullOptions.messages }
|
|
128
|
-
fullOptions.formats = { ...formats, ...fullOptions.formats }
|
|
129
|
-
if (fullOptions.deleteReadOnly) fullOptions.hideReadOnly = true
|
|
130
|
-
return fullOptions
|
|
131
|
-
},
|
|
132
|
-
resolvedSchema() {
|
|
133
|
-
if (this.modelKey === 'root') {
|
|
134
|
-
const options = this.options || {}
|
|
135
|
-
const locale = options.locale || options.defaultLocale || 'en'
|
|
136
|
-
const defaultLocale = options.defaultLocale || 'en'
|
|
137
|
-
return jrefs.resolve(
|
|
138
|
-
this.schema,
|
|
139
|
-
{ '~$locale~': locale === defaultLocale ? locale : [locale, defaultLocale] }
|
|
140
|
-
)
|
|
141
|
-
} else {
|
|
142
|
-
return this.schema
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
htmlDescription() {
|
|
146
|
-
return this.fullOptions.markdown(this.fullSchema && this.fullSchema.description)
|
|
147
|
-
},
|
|
148
|
-
fullKey() {
|
|
149
|
-
return (this.parentKey + this.modelKey).replace('root.', '')
|
|
150
|
-
},
|
|
151
|
-
label() {
|
|
152
|
-
if (!this.fullSchema) return
|
|
153
|
-
if ((this.fullSchema.readOnly || this.fullOptions.readOnlyArrayItem) && this.fullOptions.hideReadOnlyLabels) return
|
|
154
|
-
return this.fullSchema.title || (typeof this.modelKey === 'string' ? this.modelKey : '')
|
|
155
|
-
},
|
|
156
|
-
display() {
|
|
157
|
-
if (!this.fullSchema) return
|
|
158
|
-
return this.modelKey === 'root' && this.fullOptions.rootDisplay ? this.fullOptions.rootDisplay : this.fullSchema['x-display']
|
|
159
|
-
},
|
|
160
|
-
customTag() {
|
|
161
|
-
if (!this.fullSchema) return
|
|
162
|
-
return this.fullSchema['x-tag']
|
|
163
|
-
},
|
|
164
|
-
rules() {
|
|
165
|
-
if (!this.fullSchema) return
|
|
166
|
-
return getRules(this.schema, this.fullSchema, this.fullOptions, this.required, this.isOneOfSelect)
|
|
167
|
-
},
|
|
168
|
-
disabled() {
|
|
169
|
-
if (!this.fullSchema) return
|
|
170
|
-
return this.fullOptions.disableAll || this.fullSchema.readOnly
|
|
171
|
-
},
|
|
172
|
-
separator() {
|
|
173
|
-
if (!this.fullSchema && this.fullSchema.type !== 'string') return
|
|
174
|
-
return this.fullSchema.separator || this.fullSchema['x-separator']
|
|
175
|
-
},
|
|
176
|
-
slotName() {
|
|
177
|
-
if (!this.fullSchema) return
|
|
178
|
-
return this.fullSchema['x-display'] && this.fullSchema['x-display'].startsWith('custom-') ? this.fullSchema['x-display'] : this.fullKey
|
|
179
|
-
},
|
|
180
|
-
slotParams() {
|
|
181
|
-
if (!this.fullSchema) return
|
|
182
|
-
return {
|
|
183
|
-
value: this.value,
|
|
184
|
-
modelKey: this.modelKey,
|
|
185
|
-
schema: this.schema,
|
|
186
|
-
fullKey: this.fullKey,
|
|
187
|
-
fullSchema: this.fullSchema,
|
|
188
|
-
label: this.label,
|
|
189
|
-
disabled: this.disabled,
|
|
190
|
-
required: this.required,
|
|
191
|
-
rules: this.rules,
|
|
192
|
-
options: this.fullOptions,
|
|
193
|
-
htmlDescription: this.htmlDescription,
|
|
194
|
-
on: {
|
|
195
|
-
input: (e) => this.input(e instanceof Event ? e.target.value : e),
|
|
196
|
-
change: () => this.change()
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
dashKey() {
|
|
201
|
-
return this.fullKey.replace(/\./g, '-')
|
|
202
|
-
},
|
|
203
|
-
// props common to many vuetify fields
|
|
204
|
-
commonFieldProps() {
|
|
205
|
-
if (!this.fullSchema) return
|
|
206
|
-
const value = this.separator && typeof this.value === 'string' ? this.value.split(this.separator) : this.value
|
|
207
|
-
return {
|
|
208
|
-
value,
|
|
209
|
-
inputValue: value,
|
|
210
|
-
label: this.label,
|
|
211
|
-
name: this.fullKey,
|
|
212
|
-
id: this.fullOptions.idPrefix + this.dashKey,
|
|
213
|
-
disabled: this.disabled,
|
|
214
|
-
rules: this.rules,
|
|
215
|
-
required: this.required,
|
|
216
|
-
autofocus: this.fullOptions.autofocus,
|
|
217
|
-
...((this.fullSchema.readOnly || this.fullOptions.readOnlyArrayItem) ? this.fullOptions.readOnlyFieldProps : {}),
|
|
218
|
-
...this.fullOptions.fieldProps,
|
|
219
|
-
...this.fullSchema['x-props']
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
|
-
propertyClass() {
|
|
223
|
-
if (!this.fullSchema) return
|
|
224
|
-
return `vjsf-property vjsf-property-${this.dashKey} pa-0 ${this.fullSchema['x-class'] || ''} ${(this.fullSchema.readOnly || this.fullOptions.readOnlyArrayItem) ? 'read-only' : ''}`
|
|
225
|
-
.replace(/ {2}/g, ' ').trim()
|
|
226
|
-
},
|
|
227
|
-
xSlots() {
|
|
228
|
-
if (!this.fullSchema) return
|
|
229
|
-
return { ...this.fullSchema['x-slots'] }
|
|
230
|
-
},
|
|
231
|
-
formattedValue() {
|
|
232
|
-
if (!this.fullSchema) return
|
|
233
|
-
return this.value && this.fullSchema.format && this.fullOptions.formats[this.fullSchema.format] && this.fullOptions.formats[this.fullSchema.format](this.value, this.fullOptions.locale)
|
|
234
|
-
},
|
|
235
|
-
directives() {
|
|
236
|
-
if (!this.fullSchema) return
|
|
237
|
-
return this.fullSchema['x-directives']
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
watch: {
|
|
241
|
-
fullSchema: {
|
|
242
|
-
handler() {
|
|
243
|
-
if (!this.fullSchema) return
|
|
244
|
-
this.initFromSchema()
|
|
245
|
-
this.initValidation()
|
|
246
|
-
this.updateSelectItems()
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
mounted() {
|
|
251
|
-
mountingIncs[this.fullKey] = (mountingIncs[this.fullKey] || 0) + 1
|
|
252
|
-
// DEVS NOTE: uncomment this when fighting against infinite loops
|
|
253
|
-
// if infinite loop occurs again have a look here https://github.com/koumoul-dev/vuetify-jsonschema-form/issues/289
|
|
254
|
-
// and here https://github.com/koumoul-dev/vuetify-jsonschema-form/commit/fba002dea2438f5ea2ff5be1622ac79b35056eff
|
|
255
|
-
/* if (mountingIncs[this.fullKey] === 100) {
|
|
256
|
-
console.log(mountingIncs)
|
|
257
|
-
throw new Error('detected infinite mounting loop: ' + this.fullKey)
|
|
258
|
-
} */
|
|
259
|
-
|
|
260
|
-
// optimize the watcher used to reprocess fullSchema so that we trigger less re-render of components
|
|
261
|
-
let watcher = 'resolvedSchema'
|
|
262
|
-
if (this.resolvedSchema.dependencies || this.resolvedSchema.if) {
|
|
263
|
-
watcher = (vm) => [vm.resolvedSchema, vm.value]
|
|
264
|
-
}
|
|
265
|
-
this.$watch(watcher, () => {
|
|
266
|
-
const fullSchema = schemaUtils.prepareFullSchema(this.resolvedSchema, this.value, this.fullOptions)
|
|
267
|
-
// kinda hackish but prevents triggering large rendering chains when nothing meaningful changes
|
|
268
|
-
if (!deepEqual(fullSchema, this.fullSchema)) this.fullSchema = fullSchema
|
|
269
|
-
}, {
|
|
270
|
-
immediate: true,
|
|
271
|
-
deep: true
|
|
272
|
-
})
|
|
273
|
-
},
|
|
274
|
-
render(h) {
|
|
275
|
-
this.renderInc = (this.renderInc || 0) + 1
|
|
276
|
-
// DEVS NOTE: uncomment this when fighting against infinite loops
|
|
277
|
-
/* if (this.renderInc === 100) {
|
|
278
|
-
throw new Error('detected infinite rendering loop: ' + this.fullKey)
|
|
279
|
-
} */
|
|
280
|
-
|
|
281
|
-
// a few cases where we don't render anything
|
|
282
|
-
if (!this.fullSchema) return
|
|
283
|
-
if (this.fullSchema.const !== undefined) return
|
|
284
|
-
if (this.display === 'hidden') return
|
|
285
|
-
if (this.fullSchema.readOnly && this.fullOptions.hideReadOnly) return
|
|
286
|
-
if (this.fullOptions.readOnlyArrayItem && this.fullOptions.hideInArrayItem) return
|
|
287
|
-
if ((this.fullSchema.readOnly || this.fullOptions.readOnlyArrayItem) && this.fullOptions.hideReadOnlyEmpty && [null, undefined, ''].includes(this.value)) return
|
|
288
|
-
if (this.fullSchema['x-if'] && !this.getFromExpr(this.fullSchema['x-if'])) return
|
|
289
|
-
|
|
290
|
-
const children = []
|
|
291
|
-
if (this.$scopedSlots.before) children.push(this.$scopedSlots.before(this.slotParams))
|
|
292
|
-
else if (this.$slots.before) this.$slots.before.forEach(node => children.push(node))
|
|
293
|
-
else if (this.xSlots.before) children.push(h('div', { domProps: { innerHTML: this.fullOptions.memMarkdown(this.xSlots.before) } }))
|
|
294
|
-
|
|
295
|
-
if (this.$scopedSlots.default) {
|
|
296
|
-
children.push(this.$scopedSlots.default(this.slotParams))
|
|
297
|
-
} else if (this.fullSchema['x-display'] && this.fullSchema['x-display'] && this.$scopedSlots[this.fullSchema['x-display']]) {
|
|
298
|
-
children.push(this.$scopedSlots[this.fullSchema['x-display']](this.slotParams))
|
|
299
|
-
} else {
|
|
300
|
-
const mainChildren = this.renderDateProp(h) ||
|
|
301
|
-
this.renderColorProp(h) ||
|
|
302
|
-
this.renderSelectProp(h) ||
|
|
303
|
-
this.renderFileProp(h) ||
|
|
304
|
-
this.renderMarkdownProp(h) ||
|
|
305
|
-
this.renderSimpleProp(h) ||
|
|
306
|
-
this.renderObjectContainer(h) ||
|
|
307
|
-
this.renderEditableArray(h) || []
|
|
308
|
-
mainChildren.forEach(child => children.push(child))
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (this.$scopedSlots.after) children.push(this.$scopedSlots.after(this.slotParams))
|
|
312
|
-
else if (this.$slots.after) this.$slots.after.forEach(node => children.push(node))
|
|
313
|
-
else if (this.xSlots.after) {
|
|
314
|
-
children.push(h('div', { domProps: { innerHTML: this.fullOptions.memMarkdown(this.xSlots.after) } }))
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
let colProps = { ...this.fullOptions.fieldColProps }
|
|
318
|
-
if (this.fullSchema['x-cols']) {
|
|
319
|
-
if (typeof this.fullSchema['x-cols'] === 'object') {
|
|
320
|
-
colProps = { ...colProps, ...this.fullSchema['x-cols'] }
|
|
321
|
-
} else {
|
|
322
|
-
colProps.cols = this.fullSchema['x-cols']
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return h('v-col', { props: colProps, class: this.propertyClass, style: this.fullSchema['x-style'] || '' }, children)
|
|
326
|
-
},
|
|
327
|
-
methods: {
|
|
328
|
-
cached(key, params, fn) {
|
|
329
|
-
this._vjsf_cache = this._vjsf_cache || {}
|
|
330
|
-
if (!this._vjsf_cache[key] || !deepEqual(this._vjsf_cache[key].params, params)) {
|
|
331
|
-
// console.log('fill cache', key, this.fullKey)
|
|
332
|
-
this._vjsf_cache[key] = { params: copy(params), value: fn() }
|
|
333
|
-
} else {
|
|
334
|
-
// console.log('use cache', key, this.fullKey)
|
|
335
|
-
}
|
|
336
|
-
return this._vjsf_cache[key].value
|
|
337
|
-
},
|
|
338
|
-
// used by all functionalities that require looking into the data or the context (x-if, fromData, etc)
|
|
339
|
-
getFromExpr(exp) {
|
|
340
|
-
const expData = this.getExprNode()
|
|
341
|
-
expData.modelRoot = this.modelRoot
|
|
342
|
-
expData.root = this.modelRoot
|
|
343
|
-
expData.model = this.value
|
|
344
|
-
expData.context = this.options.context
|
|
345
|
-
|
|
346
|
-
this._vjsf_getters = this._vjsf_getters || {}
|
|
347
|
-
|
|
348
|
-
// newFunction can only be defined on main options (not x-options to prevent injection)
|
|
349
|
-
if (this.initialOptions.evalMethod === 'newFunction') {
|
|
350
|
-
debugExpr(`evaluate expression "${exp}" with newFunction method`, expData)
|
|
351
|
-
// use a powerful meta-programming approach with "new Function", not safe if the schema is user-submitted
|
|
352
|
-
// eslint-disable-next-line no-new-func
|
|
353
|
-
this._vjsf_getters[exp] = this._vjsf_getters[exp] || new Function(...Object.keys(expData), `return ${exp}`)
|
|
354
|
-
const result = this._vjsf_getters[exp](...Object.values(expData))
|
|
355
|
-
debugExpr(`result`, result)
|
|
356
|
-
return result
|
|
357
|
-
} else if (this.fullOptions.evalMethod === 'evalExpr') {
|
|
358
|
-
debugExpr(`evaluate expression "${exp}" with exprEval method`, expData)
|
|
359
|
-
// TODO: conserve compiled expression for reuse ?
|
|
360
|
-
const result = exprEvalParser.evaluate(exp, expData)
|
|
361
|
-
debugExpr(result)
|
|
362
|
-
return result
|
|
363
|
-
} else {
|
|
364
|
-
exp = this.prefixExpr(exp)
|
|
365
|
-
debugExpr(`evaluate expression "${exp}" with propertyExpr method`, expData)
|
|
366
|
-
// otherwise a safer but not as powerful deep getter method
|
|
367
|
-
this._vjsf_getters[exp] = this._vjsf_getters[exp] || expr.getter(exp, true)
|
|
368
|
-
const result = this._vjsf_getters[exp](expData)
|
|
369
|
-
debugExpr(`result`, result)
|
|
370
|
-
return result
|
|
371
|
-
}
|
|
372
|
-
},
|
|
373
|
-
// used by getFromExpr to support simpler expressions that look into the root model by default
|
|
374
|
-
prefixExpr(key) {
|
|
375
|
-
if (key.startsWith('context.') || key.startsWith('model.') || key.startsWith('value.') || key.startsWith('modelRoot.') || key.startsWith('root.') || key.startsWith('parent.')) return key
|
|
376
|
-
// no specific prefix found, we use modelRoot for retro-compatibility
|
|
377
|
-
if (this.modelRoot) return 'root.' + key
|
|
378
|
-
return 'model.' + key
|
|
379
|
-
},
|
|
380
|
-
renderPropSlots(h) {
|
|
381
|
-
const slots = []
|
|
382
|
-
Object.keys(this.xSlots).forEach(slot => {
|
|
383
|
-
slots.push(h('div', { slot, domProps: { innerHTML: this.fullOptions.memMarkdown(this.xSlots[slot]) } }))
|
|
384
|
-
})
|
|
385
|
-
Object.keys(this.$slots).forEach(slot => {
|
|
386
|
-
slots.push(h('template', { slot }, this.$slots[slot]))
|
|
387
|
-
})
|
|
388
|
-
return slots
|
|
389
|
-
},
|
|
390
|
-
async change(fastForward = true) {
|
|
391
|
-
if (!this.changed) return
|
|
392
|
-
// let input events be interpreted before sending this.value in change event
|
|
393
|
-
await this.$nextTick()
|
|
394
|
-
|
|
395
|
-
// store all current promises in sharedData.asyncOperations so that we can delay change events
|
|
396
|
-
// until after a user interaction has finished having async consequencies
|
|
397
|
-
this.sharedData.asyncOperations = this.sharedData.asyncOperations || {}
|
|
398
|
-
while (Object.keys(this.sharedData.asyncOperations).length) {
|
|
399
|
-
for (const key in this.sharedData.asyncOperations) {
|
|
400
|
-
await this.sharedData.asyncOperations[key]
|
|
401
|
-
}
|
|
402
|
-
await this.$nextTick()
|
|
403
|
-
}
|
|
404
|
-
this.updateSelectItems()
|
|
405
|
-
if (fastForward) this.fastForwardEvent('change-child', { fullKey: this.fullKey, value: this.value })
|
|
406
|
-
this.$emit('change', this.value)
|
|
407
|
-
this.changed = false
|
|
408
|
-
},
|
|
409
|
-
input(value, initial = false, fastForward = true) {
|
|
410
|
-
if (Array.isArray(value) && this.separator) value = value.join(this.separator)
|
|
411
|
-
if (value === null || value === undefined) {
|
|
412
|
-
if (this.fullSchema.nullable) {
|
|
413
|
-
if (this.value !== null) {
|
|
414
|
-
this.changed = true
|
|
415
|
-
if (fastForward) this.fastForwardEvent('input-child', { fullKey: this.fullKey, value: null, oldValue: this.value })
|
|
416
|
-
this.$emit('input', null)
|
|
417
|
-
} else if (initial) {
|
|
418
|
-
if (fastForward) this.fastForwardEvent('input-child', { fullKey: this.fullKey, value: null, oldValue: this.value })
|
|
419
|
-
this.$emit('input', null)
|
|
420
|
-
}
|
|
421
|
-
} else {
|
|
422
|
-
if (this.value !== undefined) {
|
|
423
|
-
this.changed = true
|
|
424
|
-
if (fastForward) this.fastForwardEvent('input-child', { fullKey: this.fullKey, value: undefined, oldValue: this.value })
|
|
425
|
-
this.$emit('input', undefined)
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
} else {
|
|
429
|
-
if (!deepEqual(value, this.value)) {
|
|
430
|
-
this.changed = true
|
|
431
|
-
// console.log(this.fullKey, isCyclic(value), value)
|
|
432
|
-
if (fastForward) this.fastForwardEvent('input-child', { fullKey: this.fullKey, value, oldValue: this.value })
|
|
433
|
-
this.$emit('input', value)
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
},
|
|
437
|
-
fixValueType(value, schema) {
|
|
438
|
-
if ([null, undefined].includes(value)) return value
|
|
439
|
-
if (schema.type === 'string' && typeof value !== 'string') return undefined
|
|
440
|
-
if (schema.type === 'integer' && typeof value !== 'number') return undefined
|
|
441
|
-
if (schema.type === 'number' && typeof value !== 'number') return undefined
|
|
442
|
-
if (schema.type === 'boolean' && typeof value !== 'boolean') return undefined
|
|
443
|
-
if (schema.type === 'array' && !Array.isArray(value)) return undefined
|
|
444
|
-
if (schema.type === 'object' && (typeof value !== 'object' || Array.isArray(value))) return undefined
|
|
445
|
-
return value
|
|
446
|
-
},
|
|
447
|
-
defaultValue(schema) {
|
|
448
|
-
if (schema.readOnly && this.fullOptions.deleteReadOnly) return undefined
|
|
449
|
-
if (schema.type === 'object' && !schema['x-fromUrl'] && !schema['x-fromData'] && !schema.enum) return {}
|
|
450
|
-
if (schema.type === 'array') return []
|
|
451
|
-
return null
|
|
452
|
-
},
|
|
453
|
-
fixProperties(value) {
|
|
454
|
-
if (this.fullSchema.type !== 'object' || !value) return value
|
|
455
|
-
|
|
456
|
-
const nonSchematized = (!this.fullSchema.properties || !this.fullSchema.properties.length) && (!Object.keys(this.subModels).length || !!this.fullSchema['x-fromData'] || !!this.fullSchema['x-fromUrl'])
|
|
457
|
-
if (nonSchematized) return value
|
|
458
|
-
|
|
459
|
-
value = { ...value }
|
|
460
|
-
|
|
461
|
-
// cleanup extra properties
|
|
462
|
-
if (this.fullOptions.removeAdditionalProperties || this.fullSchema.additionalProperties === false) {
|
|
463
|
-
Object.keys(value).forEach(key => {
|
|
464
|
-
if (!(this.fullSchema.properties || []).find(p => p.key === key)) {
|
|
465
|
-
// console.log(`Remove key ${this.modelKey}.${key}`)
|
|
466
|
-
delete value[key]
|
|
467
|
-
}
|
|
468
|
-
})
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// apply submodels
|
|
472
|
-
Object.keys(this.subModels).forEach(subModel => {
|
|
473
|
-
Object.keys(this.subModels[subModel]).forEach(key => {
|
|
474
|
-
// special case, ignore subschema switch key coming from another submodel
|
|
475
|
-
const localProperty = this.fullSchema.properties.find(p => p.key === key)
|
|
476
|
-
if (localProperty && localProperty.const) return
|
|
477
|
-
|
|
478
|
-
if (value[key] === this.subModels[subModel][key]) return
|
|
479
|
-
value[key] = this.subModels[subModel][key]
|
|
480
|
-
})
|
|
481
|
-
})
|
|
482
|
-
return value
|
|
483
|
-
},
|
|
484
|
-
initFromSchema() {
|
|
485
|
-
// initiallyDefined will by used in Validatable.js to perform initial validation or not
|
|
486
|
-
this.initiallyDefined = this.value !== undefined && this.value !== null
|
|
487
|
-
// we cannot consider empty objects and empty arrays as "defined" as they might have been initialized by vjsf itself
|
|
488
|
-
if (this.fullSchema.type === 'array') this.initiallyDefined = !!(this.value && this.value.length)
|
|
489
|
-
if (this.fullSchema.type === 'object') this.initiallyDefined = !!(this.value && Object.keys(this.value).length)
|
|
490
|
-
|
|
491
|
-
// console.log('Init from schema', this.modelKey)
|
|
492
|
-
if (this.fullSchema.readOnly && this.fullOptions.deleteReadOnly) {
|
|
493
|
-
return this.input(undefined)
|
|
494
|
-
}
|
|
495
|
-
let value = this.value
|
|
496
|
-
|
|
497
|
-
// create empty objects
|
|
498
|
-
if (this.fullSchema.type === 'object' && [undefined, null].includes(value) && !this.isSelectProp) {
|
|
499
|
-
value = {}
|
|
500
|
-
}
|
|
501
|
-
// in the special case of objects based on select remove empty objects
|
|
502
|
-
if (this.fullSchema.type === 'object' && this.isSelectProp && value && Object.keys(value).length === 0) {
|
|
503
|
-
value = undefined
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// const always wins
|
|
507
|
-
if (this.fullSchema.const !== undefined) value = this.fullSchema.const
|
|
508
|
-
this.initSelectProp(value)
|
|
509
|
-
this.initObjectContainer(value)
|
|
510
|
-
// Cleanup arrays of empty items
|
|
511
|
-
if (this.fullSchema.type === 'array') {
|
|
512
|
-
value = this.value.filter(item => ![undefined, null].includes(item))
|
|
513
|
-
}
|
|
514
|
-
return this.input(this.fixProperties(value), true)
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
}
|
package/lib/deps/third-party.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// import this module if you want to be sure that you get all dependancies
|
|
2
|
-
// used by vjsf functionalities (color picker, etc.)
|
|
3
|
-
|
|
4
|
-
import Vue from 'vue'
|
|
5
|
-
import Draggable from 'vuedraggable'
|
|
6
|
-
import markdownIt from 'markdown-it'
|
|
7
|
-
import ajv from 'ajv'
|
|
8
|
-
import ajvI18n from 'ajv-i18n'
|
|
9
|
-
import ajvFormats from 'ajv-formats'
|
|
10
|
-
|
|
11
|
-
const _global = (typeof window !== 'undefined' && window) || (typeof global !== 'undefined' && global) || {}
|
|
12
|
-
_global.markdownit = markdownIt
|
|
13
|
-
Vue.component('Draggable', Draggable)
|
|
14
|
-
_global.Ajv = ajv
|
|
15
|
-
_global.ajvLocalize = ajvI18n
|
|
16
|
-
_global.ajvAddFormats = ajvFormats
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
computed: {
|
|
3
|
-
isColorProp() {
|
|
4
|
-
return this.resolvedSchema.type === 'string' && (this.resolvedSchema.format === 'hexcolor' || this.display === 'color-picker')
|
|
5
|
-
}
|
|
6
|
-
},
|
|
7
|
-
methods: {
|
|
8
|
-
renderColorProp(h) {
|
|
9
|
-
if (!this.isColorProp) return
|
|
10
|
-
|
|
11
|
-
const children = [this.renderTooltip(h, 'append')]
|
|
12
|
-
|
|
13
|
-
children.push(h('v-menu', {
|
|
14
|
-
props: { closeOnContentClick: false, closeOneClick: true, direction: 'bottom', offsetY: true },
|
|
15
|
-
scopedSlots: {
|
|
16
|
-
activator: ({ on }) => h('div', {
|
|
17
|
-
on,
|
|
18
|
-
style: `background-color: ${this.value};margin-left: 10px;`,
|
|
19
|
-
class: this.value ? 'color-picker-trigger' : 'color-picker-trigger color-picker-trigger-empty'
|
|
20
|
-
}),
|
|
21
|
-
default: () => h('v-color-picker', {
|
|
22
|
-
props: { flat: true, ...this.fullOptions.colorPickerProps, ...this.fullSchema['x-props'], value: this.value || '' },
|
|
23
|
-
on: {
|
|
24
|
-
input: val => {
|
|
25
|
-
this.input(val)
|
|
26
|
-
this.change()
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
}))
|
|
32
|
-
return [h('v-input', {
|
|
33
|
-
props: {
|
|
34
|
-
value: this.value,
|
|
35
|
-
name: this.fullKey,
|
|
36
|
-
label: this.label,
|
|
37
|
-
required: this.required,
|
|
38
|
-
rules: this.rules,
|
|
39
|
-
disabled: this.disabled,
|
|
40
|
-
...this.fullOptions.fieldProps
|
|
41
|
-
}
|
|
42
|
-
}, children)]
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|