@koumoul/vjsf 2.22.0 → 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.
Files changed (138) hide show
  1. package/package.json +50 -86
  2. package/src/compat/v2.js +82 -0
  3. package/src/compile/index.js +32 -0
  4. package/src/compile/v-jsf-compiled.vue.ejs +83 -0
  5. package/src/components/fragments/node-slot.vue +49 -0
  6. package/src/components/fragments/section-header.vue +52 -0
  7. package/src/components/fragments/text-field-menu.vue +68 -0
  8. package/src/components/node.vue +60 -0
  9. package/src/components/nodes/checkbox.vue +27 -0
  10. package/src/components/nodes/color-picker.vue +43 -0
  11. package/src/components/nodes/date-picker.vue +45 -0
  12. package/src/components/nodes/date-time-picker.vue +20 -0
  13. package/src/components/nodes/expansion-panels.vue +52 -0
  14. package/src/components/nodes/list.vue +112 -0
  15. package/src/components/nodes/number-field.vue +35 -0
  16. package/src/components/nodes/one-of-select.vue +56 -0
  17. package/src/components/nodes/section.vue +30 -0
  18. package/src/components/nodes/select.vue +59 -0
  19. package/src/components/nodes/slider.vue +34 -0
  20. package/src/components/nodes/switch.vue +29 -0
  21. package/src/components/nodes/tabs.vue +63 -0
  22. package/src/components/nodes/text-field.vue +29 -0
  23. package/src/components/nodes/textarea.vue +29 -0
  24. package/src/components/nodes/time-picker.vue +7 -0
  25. package/src/components/nodes/vertical-tabs.vue +70 -0
  26. package/src/components/options.js +25 -0
  27. package/src/components/tree.vue +25 -0
  28. package/src/components/types.ts +59 -0
  29. package/src/components/vjsf.vue +168 -0
  30. package/src/index.js +2 -0
  31. package/src/utils/clone.js +3 -0
  32. package/src/utils/dates.js +52 -0
  33. package/src/utils/props.js +79 -0
  34. package/src/utils/slots.js +19 -0
  35. package/types/compat/v2.d.ts +10 -0
  36. package/types/compat/v2.d.ts.map +1 -0
  37. package/types/compile/index.d.ts +7 -0
  38. package/types/compile/index.d.ts.map +1 -0
  39. package/types/components/fragments/node-slot.vue.d.ts +47 -0
  40. package/types/components/fragments/node-slot.vue.d.ts.map +1 -0
  41. package/types/components/fragments/section-header.vue.d.ts +8 -0
  42. package/types/components/fragments/section-header.vue.d.ts.map +1 -0
  43. package/types/components/fragments/text-field-menu.vue.d.ts +20 -0
  44. package/types/components/fragments/text-field-menu.vue.d.ts.map +1 -0
  45. package/types/components/node.vue.d.ts +10 -0
  46. package/types/components/node.vue.d.ts.map +1 -0
  47. package/types/components/nodes/checkbox.vue.d.ts +10 -0
  48. package/types/components/nodes/checkbox.vue.d.ts.map +1 -0
  49. package/types/components/nodes/color-picker.vue.d.ts +10 -0
  50. package/types/components/nodes/color-picker.vue.d.ts.map +1 -0
  51. package/types/components/nodes/date-picker.vue.d.ts +10 -0
  52. package/types/components/nodes/date-picker.vue.d.ts.map +1 -0
  53. package/types/components/nodes/date-time-picker.vue.d.ts +10 -0
  54. package/types/components/nodes/date-time-picker.vue.d.ts.map +1 -0
  55. package/types/components/nodes/expansion-panels.vue.d.ts +10 -0
  56. package/types/components/nodes/expansion-panels.vue.d.ts.map +1 -0
  57. package/types/components/nodes/list.vue.d.ts +10 -0
  58. package/types/components/nodes/list.vue.d.ts.map +1 -0
  59. package/types/components/nodes/number-field.vue.d.ts +27 -0
  60. package/types/components/nodes/number-field.vue.d.ts.map +1 -0
  61. package/types/components/nodes/one-of-select.vue.d.ts +10 -0
  62. package/types/components/nodes/one-of-select.vue.d.ts.map +1 -0
  63. package/types/components/nodes/section.vue.d.ts +10 -0
  64. package/types/components/nodes/section.vue.d.ts.map +1 -0
  65. package/types/components/nodes/select.vue.d.ts +10 -0
  66. package/types/components/nodes/select.vue.d.ts.map +1 -0
  67. package/types/components/nodes/slider.vue.d.ts +10 -0
  68. package/types/components/nodes/slider.vue.d.ts.map +1 -0
  69. package/types/components/nodes/switch.vue.d.ts +10 -0
  70. package/types/components/nodes/switch.vue.d.ts.map +1 -0
  71. package/types/components/nodes/tabs.vue.d.ts +10 -0
  72. package/types/components/nodes/tabs.vue.d.ts.map +1 -0
  73. package/types/components/nodes/text-field copy.vue.d.ts +10 -0
  74. package/types/components/nodes/text-field copy.vue.d.ts.map +1 -0
  75. package/types/components/nodes/text-field.vue.d.ts +27 -0
  76. package/types/components/nodes/text-field.vue.d.ts.map +1 -0
  77. package/types/components/nodes/textarea.vue.d.ts +27 -0
  78. package/types/components/nodes/textarea.vue.d.ts.map +1 -0
  79. package/types/components/nodes/time-picker.vue.d.ts +3 -0
  80. package/types/components/nodes/time-picker.vue.d.ts.map +1 -0
  81. package/types/components/nodes/vertical-tabs.vue.d.ts +10 -0
  82. package/types/components/nodes/vertical-tabs.vue.d.ts.map +1 -0
  83. package/types/components/options.d.ts +3 -0
  84. package/types/components/options.d.ts.map +1 -0
  85. package/types/components/tree.vue.d.ts +10 -0
  86. package/types/components/tree.vue.d.ts.map +1 -0
  87. package/types/components/types.d.ts +71 -0
  88. package/types/components/types.d.ts.map +1 -0
  89. package/types/components/v-jsf.vue.d.ts +13 -0
  90. package/types/components/v-jsf.vue.d.ts.map +1 -0
  91. package/types/components/vjsf.vue.d.ts +13 -0
  92. package/types/components/vjsf.vue.d.ts.map +1 -0
  93. package/types/index.d.ts +3 -0
  94. package/types/index.d.ts.map +1 -0
  95. package/types/utils/clone.d.ts +3 -0
  96. package/types/utils/clone.d.ts.map +1 -0
  97. package/types/utils/dates.d.ts +7 -0
  98. package/types/utils/dates.d.ts.map +1 -0
  99. package/types/utils/props.d.ts +20 -0
  100. package/types/utils/props.d.ts.map +1 -0
  101. package/types/utils/slots.d.ts +7 -0
  102. package/types/utils/slots.d.ts.map +1 -0
  103. package/.eslintignore +0 -9
  104. package/.eslintrc.js +0 -38
  105. package/.github/workflows/scrape-doc.yml +0 -14
  106. package/.nvmrc +0 -1
  107. package/CONTRIBUTE.md +0 -61
  108. package/FUNDING.yml +0 -1
  109. package/README.md +0 -19
  110. package/babel.config.js +0 -4
  111. package/dist/main.css +0 -63
  112. package/dist/main.js +0 -2
  113. package/dist/main.js.LICENSE.txt +0 -10
  114. package/dist/third-party.js +0 -8
  115. package/dist/third-party.js.LICENSE.txt +0 -8
  116. package/lib/VJsf.css +0 -63
  117. package/lib/VJsf.js +0 -117
  118. package/lib/VJsfNoDeps.js +0 -517
  119. package/lib/deps/third-party.js +0 -16
  120. package/lib/mixins/ColorProperty.js +0 -45
  121. package/lib/mixins/DateProperty.js +0 -170
  122. package/lib/mixins/Dependent.js +0 -69
  123. package/lib/mixins/EditableArray.js +0 -418
  124. package/lib/mixins/FileProperty.js +0 -81
  125. package/lib/mixins/MarkdownEditor.js +0 -183
  126. package/lib/mixins/ObjectContainer.js +0 -351
  127. package/lib/mixins/SelectProperty.js +0 -400
  128. package/lib/mixins/SimpleProperty.js +0 -165
  129. package/lib/mixins/Tooltip.js +0 -42
  130. package/lib/mixins/Validatable.js +0 -119
  131. package/lib/utils/expr-eval-parser.js +0 -21
  132. package/lib/utils/is-cyclic.js +0 -34
  133. package/lib/utils/json-refs.js +0 -209
  134. package/lib/utils/options.js +0 -328
  135. package/lib/utils/rules.js +0 -81
  136. package/lib/utils/schema.js +0 -100
  137. package/lib/utils/select.js +0 -141
  138. package/webpack.config.js +0 -46
@@ -1,328 +0,0 @@
1
- import { mdiCalendar, mdiClock, mdiInformation, mdiPlus, mdiPencil, mdiDelete, mdiDotsVertical, mdiContentDuplicate, mdiContentCopy, mdiContentPaste } from '@mdi/js'
2
-
3
- export const defaultOptions = {
4
- locale: '',
5
- defaultLocale: '',
6
- rootDisplay: '',
7
- objectContainerClass: '',
8
- sectionsClass: 'pl-2 pt-2',
9
- sectionsTitlesClasses: ['title', 'subtitle-1', 'subtitle-2'],
10
- arrayItemsTitlesClasses: ['title', 'subtitle-1', 'subtitle-2'],
11
- childrenClass: '',
12
- fieldProps: {},
13
- fieldColProps: { cols: 12 },
14
- readOnlyFieldProps: { hideDetails: true },
15
- textFieldProps: {},
16
- textareaProps: { filled: true },
17
- numberProps: {},
18
- sliderProps: {},
19
- checkboxProps: {},
20
- switchProps: {},
21
- comboboxProps: {},
22
- selectProps: {},
23
- fileInputProps: {},
24
- radioGroupProps: {},
25
- radioItemProps: {},
26
- tabsProps: { grow: true },
27
- expansionPanelsProps: { mandatory: true },
28
- dialogProps: { maxWidth: 500 },
29
- dialogCardProps: {},
30
- colorPickerProps: {},
31
- timePickerProps: {},
32
- datePickerProps: { scrollable: true },
33
- arrayItemCardProps: {},
34
- arrayItemColProps: { cols: 12 },
35
- stepperProps: {},
36
- verticalStepperProps: {},
37
- tooltipProps: { left: true, openOnHover: false, openOnClick: true },
38
- removeAdditionalProperties: true,
39
- disableAll: false,
40
- hideReadOnly: false,
41
- hideReadOnlyLabels: false,
42
- hideReadOnlyEmpty: false,
43
- hideReadOnlyTooltips: false,
44
- deleteReadOnly: false,
45
- hideInArrayItem: false,
46
- filesAsDataUrl: false,
47
- hideTooltips: false,
48
- disableSorting: false,
49
- sortableOptions: {},
50
- context: {},
51
- rules: {},
52
- initialValidation: 'defined',
53
- idPrefix: '',
54
- markdownit: {},
55
- editMode: 'dialog',
56
- arrayOperations: ['create', 'update', 'duplicate', 'copy', 'paste', 'delete'],
57
- autofocus: false,
58
- httpOptions: {},
59
- selectAll: false,
60
- autoFixArrayItems: true,
61
- useValidator: false,
62
- evalMethod: 'propertyExpr',
63
- easyMDEOptions: {},
64
- maxLengthCounter: true
65
- }
66
-
67
- export const localizedMessages = {
68
- en: {
69
- required: 'This information is required',
70
- noData: 'No matching value found',
71
- search: 'Search...',
72
- minimum: 'The value must be greater than or equal to {minimum}',
73
- exclusiveMinimum: 'The value must be greater than {exclusiveMinimum}',
74
- maximum: 'The value must be lower than or equal to {maximum}',
75
- exclusiveMaximum: 'The value must be lower than {exclusiveMaximum}',
76
- minLength: '{minLength} characters minimum',
77
- maxLength: '{maxLength} characters maximum',
78
- minItems: 'No less than {minItems} items',
79
- maxItems: 'No more than {maxItems} items',
80
- pattern: 'The expected pattern is not satisfied',
81
- mdeLink1: '[Link title',
82
- mdeLink2: '](link url)',
83
- mdeImg1: '![](',
84
- mdeImg2: 'image url)',
85
- mdeTable1: '',
86
- mdeTable2: '\n\n| Column 1 | Column 2 | ColoColumnnne 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n\n',
87
- bold: 'Bold',
88
- italic: 'Italic',
89
- heading: 'Title',
90
- quote: 'Quote',
91
- unorderedList: 'Unordered list',
92
- orderedList: 'Ordered list',
93
- createLink: 'Create a link',
94
- insertImage: 'Insert an image',
95
- createTable: 'Create a table',
96
- preview: 'Aperçu du rendu',
97
- mdeGuide: 'Documentation de la syntaxe',
98
- undo: 'Undo',
99
- redo: 'Redo',
100
- selectAll: 'Select all',
101
- stepperContinue: 'continue',
102
- openMenu: 'open menu',
103
- delete: 'delete',
104
- duplicate: 'duplicate',
105
- copy: 'copy',
106
- paste: 'paste'
107
- },
108
- fr: {
109
- required: 'Cette information est obligatoire',
110
- noData: 'Aucun élément correspondant',
111
- search: 'Recherchez...',
112
- minimum: 'La valeur doit être supérieure ou égale à {minimum}',
113
- exclusiveMinimum: 'La valeur doit être supérieure {exclusiveMinimum}',
114
- maximum: 'La valeur doit être inférieure ou égale à {maximum}',
115
- exclusiveMaximum: 'La valeur doit être inférieure à {exclusiveMaximum}',
116
- minLength: '{minLength} caractères minimum',
117
- maxLength: '{maxLength} caractères maximum',
118
- minItems: 'Au moins {minItems} éléments',
119
- maxItems: 'Au plus {maxItems} éléments',
120
- pattern: `Le format attendu n'est pas respecté`,
121
- mdeLink1: '[titre du lien',
122
- mdeLink2: '](adresse du lien)',
123
- mdeImg1: '![](',
124
- mdeImg2: 'adresse de l\'image)',
125
- mdeTable1: '',
126
- mdeTable2: '\n\n| Colonne 1 | Colonne 2 | Colonne 3 |\n| -------- | -------- | -------- |\n| Texte | Texte | Texte |\n\n',
127
- bold: 'Gras',
128
- italic: 'Italique',
129
- heading: 'Titre',
130
- quote: 'Citation',
131
- unorderedList: 'Liste à puce',
132
- orderedList: 'Liste numérotée',
133
- createLink: 'Créer un lien',
134
- insertImage: 'Insérer une image',
135
- createTable: 'Créer un tableau',
136
- preview: 'Preview',
137
- mdeGuide: 'Syntax documentation',
138
- undo: 'Défaire',
139
- redo: 'Refaire',
140
- selectAll: 'Tout sélectionner',
141
- stepperContinue: 'continuer',
142
- openMenu: 'ouvrir le menu',
143
- delete: 'supprimer',
144
- duplicate: 'dupliquer',
145
- copy: 'copier',
146
- paste: 'coller'
147
- },
148
- es: {
149
- required: 'Esta información es requerida',
150
- noData: 'No se encontraron valores coincidentes',
151
- search: 'Buscar...',
152
- minimum: 'El valor debe ser mayor o igual que {minimum}',
153
- exclusiveMinimum: 'El valor debe ser mayor que {exclusiveMinimum}',
154
- maximum: 'El valor debe ser menor o igual a {maximum}',
155
- exclusiveMaximum: 'El valor debe ser inferior a {exclusiveMaximum}',
156
- minLength: '{minLength} caracteres mínimo',
157
- maxLength: '{maxLength} caractères máximo',
158
- minItems: 'Al menos {minItems} articulos',
159
- maxItems: 'Hasta {maxItems} articulos',
160
- pattern: 'El formato esperado no se respeta',
161
- selectAll: 'Seleccionar todo',
162
- stepperContinue: 'continuar'
163
- },
164
- de: {
165
- required: 'Diese Informationen sind erforderlich',
166
- noData: 'Keine passenden Artikel',
167
- search: 'Suche...',
168
- minimum: 'Der Wert muss größer oder gleich {minimum} sein',
169
- exclusiveMinimum: 'Der Wert muss größer als {exclusiveMinimum} sein',
170
- maximum: 'Der Wert muss kleiner oder gleich {maximum} sein',
171
- exclusiveMaximum: 'Der Wert muss kleiner als {exclusiveMaximum} sein',
172
- minLength: 'Mindestens {minLength} Zeichen',
173
- maxLength: 'Maximal {maxLength} Zeichen',
174
- minItems: 'Mindestens {minItems} Elemente',
175
- maxItems: 'Bis zu {maxItems} Artikel',
176
- pattern: 'Das erwartete Format wird nicht eingehalten',
177
- selectAll: 'Wählen Sie Alle',
178
- stepperContinue: 'weiter'
179
- },
180
- ar: {
181
- required: 'هذه المعلومة مطلوبة',
182
- noData: 'لم يتم العثور على قيمة',
183
- search: 'جاري البحث...',
184
- minimum: '{exclusiveMinimum} القيمة يجب أن تكون أكبر من', // TODO, same as exclusiveMinimum waiting for a proper translation
185
- exclusiveMinimum: '{exclusiveMinimum} القيمة يجب أن تكون أكبر من',
186
- maximum: '{maximum} القيمة يجب أن تكون أقل من', // TODO, same as exclusiveMaximum waiting for a proper translation
187
- exclusiveMaximum: '{exclusiveMaximum} القيمة يجب أن تكون أقل من',
188
- minLength: '{minLength} الحد الأدنى للحروف المطلوبة هو',
189
- maxLength: '{maxLength} الحد الأقصى للحروف المطلوبة هو',
190
- minItems: 'قطع {minItems} لا يمكن اختيار أقل من ',
191
- maxItems: 'قطع {maxItems} لا يمكن اختيار أكثر من ',
192
- pattern: 'لا يوجد تشابه مع النموذج المطلوب',
193
- selectAll: 'اختر الكل',
194
- stepperContinue: 'استمر'
195
- },
196
- tr: {
197
- required: 'Zorunlu alan',
198
- noData: 'Bilgi yok',
199
- search: 'Arıyor...',
200
- minimum: 'Değer {minimum} dan büyük olmalı',
201
- exclusiveMinimum: 'Değer {exclusiveMinimum} dan büyük olmalı',
202
- maximum: 'Değer, {maximum} değerinden küçük veya ona eşit olmalıdır',
203
- exclusiveMaximum: 'Değer {exclusiveMaximum} dan küçük olmalı',
204
- minLength: '{minLength} asgari karakter sayısı',
205
- maxLength: '{maxLength} azami karakter sayısı',
206
- minItems: 'En az seçenek sayısı {minItems}',
207
- maxItems: 'En çok seçenek sayısı {maxItems}',
208
- pattern: 'İstenilen paten tutmuyor',
209
- selectAll: 'Hepsini seç',
210
- stepperContinue: 'devam et'
211
- },
212
- nl: {
213
- required: 'Deze informatie is vereist',
214
- noData: 'Geen overeenkomstig resultaat gevonden',
215
- search: 'Zoeken...',
216
- minimum: 'De waarde moet groter zijn dan of gelijk zijn aan {minimum}',
217
- exclusiveMinimum: 'Waarde moet meer zijn dan {exclusiveMinimum}',
218
- maximum: 'De waarde moet lager zijn dan of gelijk zijn aan {maximum}',
219
- exclusiveMaximum: 'Waarde moet minder zijn dan {exclusiveMaximum}',
220
- minLength: 'Minimaal {minLength} tekens',
221
- maxLength: 'Maximaal {maxLength} tekens',
222
- minItems: 'Minimaal {minItems} antwoorden',
223
- maxItems: 'Maximaal {maxItems} antwoorden',
224
- pattern: 'Invoer voldoet niet aan verwachte patroon',
225
- selectAll: 'Selecteer alles',
226
- stepperContinue: 'doorgaan'
227
- },
228
- ja: {
229
- required: 'この情報は必須です。',
230
- noData: '一致する値はありません。',
231
- search: '検索...',
232
- minimum: '値は{minimum}以上である必要があります。',
233
- exclusiveMinimum: '値は{exclusiveMinimum}より大きい必要があります。',
234
- maximum: '値は{maximum}以下である必要があります。',
235
- exclusiveMaximum: '値は{exclusiveMaximum}より小さい必要があります。',
236
- minLength: '最小文字数は{minLength}です。',
237
- maxLength: '最大文字数は{maxLength}です。',
238
- minItems: '最小項目数は{minItems}です。',
239
- maxItems: '最大項目数は{maxItems}です。',
240
- pattern: '期待される様式を満たしていません。',
241
- mdeTable2: '\n\n| Column 1 | Column 2 | ColoColumnnne 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n\n',
242
- bold: '太字',
243
- italic: 'イタリック',
244
- heading: 'タイトル',
245
- quote: '引用',
246
- unorderedList: '順序なしリスト',
247
- orderedList: '順序付きリスト',
248
- createLink: 'リンクを生成',
249
- insertImage: '画像を挿入',
250
- createTable: 'テーブル作成',
251
- preview: 'プレビュー',
252
- mdeGuide: '構文に関するドキュメント',
253
- undo: '元に戻す',
254
- redo: 'やり直し',
255
- selectAll: '全選択',
256
- stepperContinue: 'コンティニュー',
257
- openMenu: 'メニューを開く',
258
- delete: '削除',
259
- duplicate: '重複',
260
- copy: 'コーピー',
261
- paste: 'ペースト'
262
- }
263
- }
264
-
265
- export const formats = {
266
- time: (time, locale) => {
267
- const date = new Date(`${new Date().toISOString().split('T')[0]}T${time}`)
268
- return new Date(date.getTime() + (date.getTimezoneOffset() * 60000)).toLocaleTimeString(locale)
269
- },
270
- date: (dateStr, locale) => {
271
- const date = new Date(dateStr)
272
- return new Date(date.getTime() + (date.getTimezoneOffset() * 60000)).toLocaleDateString(locale)
273
- },
274
- 'date-time': (dateTime, locale) => {
275
- return new Date(dateTime).toLocaleString(locale)
276
- }
277
- }
278
-
279
- export const iconSets = {
280
- mdiSvg: {
281
- calendar: mdiCalendar,
282
- clock: mdiClock,
283
- info: mdiInformation,
284
- add: mdiPlus,
285
- edit: mdiPencil,
286
- delete: mdiDelete,
287
- arrayMenu: mdiDotsVertical,
288
- duplicate: mdiContentDuplicate,
289
- copy: mdiContentCopy,
290
- paste: mdiContentPaste
291
- },
292
- mdi: {
293
- calendar: 'mdi-calendar',
294
- clock: 'mdi-clock',
295
- info: 'mdi-information',
296
- add: 'mdi-plus',
297
- edit: 'mdi-pencil',
298
- delete: 'mdi-delete',
299
- arrayMenu: 'mdi-dots-vertical',
300
- duplicate: 'mdi-plus-circle-multiple-outline',
301
- copy: 'mdi-content-copy',
302
- paste: 'mdi-content-paste'
303
- },
304
- md: {
305
- calendar: 'event',
306
- clock: 'clock',
307
- info: 'info',
308
- add: 'add',
309
- edit: 'create',
310
- delete: 'delete',
311
- arrayMenu: 'more_vert',
312
- duplicate: 'control_point_duplicate',
313
- copy: 'copy',
314
- paste: 'paste'
315
- },
316
- fa: {
317
- calendar: 'fa-calendar',
318
- clock: 'fa-clock',
319
- info: 'fa-info',
320
- add: 'fa-plus',
321
- edit: 'fa-edit',
322
- delete: 'fa-trash',
323
- arrayMenu: 'fa-ellipsis-vertical',
324
- duplicate: 'fa-layer-plus',
325
- copy: 'fa-copy',
326
- paste: 'fa-paste'
327
- }
328
- }
@@ -1,81 +0,0 @@
1
- import { deepEqual } from 'fast-equals'
2
-
3
- export const getRules = (schema, fullSchema, options, required, isOneOfSelect) => {
4
- const rules = []
5
- if (required) {
6
- rules.push((val) => (val !== undefined && val !== null && val !== '') || options.messages.required)
7
- }
8
- if (fullSchema.type === 'array' && fullSchema.minItems !== undefined) {
9
- const msg = options.messages.minItems.replace('{minItems}', fullSchema.minItems.toLocaleString(options.locale))
10
- rules.push((val) => (!val || val.length >= fullSchema.minItems) || msg)
11
- }
12
- if (fullSchema.type === 'array' && fullSchema.maxItems !== undefined) {
13
- const msg = options.messages.maxItems.replace('{maxItems}', fullSchema.maxItems.toLocaleString(options.locale))
14
- rules.push((val) => (!val || val.length <= fullSchema.maxItems) || msg)
15
- }
16
- if (fullSchema.type === 'string' && fullSchema.minLength !== undefined) {
17
- const msg = options.messages.minLength.replace('{minLength}', fullSchema.minLength.toLocaleString(options.locale))
18
- rules.push((val) => (val === undefined || val === null || (!required && val === '') || val.length >= fullSchema.minLength) || msg)
19
- }
20
- if (fullSchema.type === 'string' && fullSchema.maxLength !== undefined) {
21
- const msg = options.messages.maxLength.replace('{maxLength}', fullSchema.maxLength.toLocaleString(options.locale))
22
- rules.push((val) => (val === undefined || val === null || val.length <= fullSchema.maxLength) || msg)
23
- }
24
- if (fullSchema.type === 'string' && fullSchema.patternRegexp !== undefined) {
25
- const msg = options.messages.pattern.replace('{pattern}', fullSchema.pattern)
26
- rules.push((val) => (val === undefined || val === null || val === '' || !!val.match(fullSchema.patternRegexp)) || msg)
27
- }
28
- if (['number', 'integer'].includes(fullSchema.type) && fullSchema.maximum !== undefined) {
29
- const msg = options.messages.maximum.replace('{maximum}', fullSchema.maximum.toLocaleString(options.locale))
30
- rules.push((val) => (val === undefined || val === null || val <= fullSchema.maximum) || msg)
31
- }
32
- if (['number', 'integer'].includes(fullSchema.type) && fullSchema.exclusiveMaximum !== undefined) {
33
- const msg = options.messages.exclusiveMaximum.replace('{exclusiveMaximum}', fullSchema.exclusiveMaximum.toLocaleString(options.locale))
34
- rules.push((val) => (val === undefined || val === null || val < fullSchema.exclusiveMaximum) || msg)
35
- }
36
- if (['number', 'integer'].includes(fullSchema.type) && fullSchema.minimum !== undefined) {
37
- const msg = options.messages.minimum.replace('{minimum}', fullSchema.minimum.toLocaleString(options.locale))
38
- rules.push((val) => (val === undefined || val === null || val >= fullSchema.minimum) || msg)
39
- }
40
- if (['number', 'integer'].includes(fullSchema.type) && fullSchema.exclusiveMinimum !== undefined) {
41
- const msg = options.messages.exclusiveMinimum.replace('{exclusiveMinimum}', fullSchema.exclusiveMinimum.toLocaleString(options.locale))
42
- rules.push((val) => (val === undefined || val === null || val > fullSchema.exclusiveMinimum) || msg)
43
- }
44
- if (fullSchema.enum) {
45
- rules.push((val) => (val === undefined || val === null || !!fullSchema.enum.find(item => deepEqual(item, val))) || '')
46
- }
47
- if (fullSchema.type === 'array' && fullSchema.items.enum) {
48
- rules.push((val) => (val === undefined || val === null || !val.find(valItem => !fullSchema.items.enum.find(item => deepEqual(item, valItem)))) || '')
49
- }
50
- if (isOneOfSelect && fullSchema.type !== 'array') {
51
- rules.push((val) => (val === undefined || val === null || !!fullSchema.oneOf.find(item => deepEqual(item.const, val))) || '')
52
- }
53
- if (isOneOfSelect && fullSchema.type === 'array') {
54
- rules.push((val) => (val === undefined || val === null || !val.find(valItem => !fullSchema.items.oneOf.find(item => deepEqual(item.const, valItem)))) || '')
55
- }
56
-
57
- // ajv validation
58
- if (options.validator && options.useValidator) {
59
- rules.push(getAjvRule(schema, options.validator))
60
- }
61
-
62
- const customRules = (fullSchema['x-rules'] || []).map(rule => {
63
- if (typeof rule === 'string') {
64
- const ruleFunction = options.rules && options.rules[rule]
65
- if (!ruleFunction) console.error(`rule ${rule} is referenced but not define in options`)
66
- return ruleFunction
67
- } else {
68
- console.error(`rule should be a string, received ${typeof rule}`)
69
- }
70
- }).filter(rule => !!rule)
71
- return rules.concat(customRules)
72
- }
73
-
74
- const getAjvRule = (schema, validator, locale) => {
75
- const validate = validator(schema)
76
- return (val) => {
77
- if (val === null || val === undefined) return true
78
- const error = validate(val)
79
- return !error || error
80
- }
81
- }
@@ -1,100 +0,0 @@
1
- // Some util functions around schema manipulation to reduce size of the Property component
2
- import copy from 'fast-copy'
3
-
4
- const schemaUtils = {}
5
-
6
- export default schemaUtils
7
-
8
- const objectToArray = (obj) => Object.keys(obj || {}).map(key => ({ ...obj[key], key }))
9
-
10
- const getDeepKey = (obj, key) => {
11
- const keys = key.split('.')
12
- for (let i = 0; i < keys.length; i++) {
13
- if ([null, undefined].includes(obj)) break
14
- obj = obj[keys[i]]
15
- }
16
- return obj
17
- }
18
-
19
- const extendSchema = (schema, subSchema) => {
20
- schema.required = schema.required.concat(subSchema.required || [])
21
- schema.properties = schema.properties.concat(objectToArray(subSchema.properties))
22
- if (subSchema.oneOf) schema.oneOf = (schema.oneOf || []).concat(subSchema.oneOf)
23
- if (subSchema.allOf) schema.allOf = (schema.allOf || []).concat(subSchema.allOf)
24
- }
25
-
26
- schemaUtils.prepareFullSchema = (schema, value, options) => {
27
- const fullSchema = copy(schema)
28
-
29
- if (fullSchema.pattern) fullSchema.patternRegexp = new RegExp(fullSchema.pattern)
30
-
31
- if (!fullSchema.type && fullSchema.properties) fullSchema.type = 'object'
32
-
33
- // detect type from combination info
34
- if (!fullSchema.type) {
35
- const combination = fullSchema.anyOf || fullSchema.oneOf || fullSchema.allOf
36
- const typedCombinationItem = combination && combination.find(c => !!c.type)
37
- if (typedCombinationItem) fullSchema.type = typedCombinationItem.type
38
- }
39
-
40
- // manage null type in an array, for example ['string', 'null']
41
- if (Array.isArray(fullSchema.type)) {
42
- fullSchema.nullable = fullSchema.type.includes('null')
43
- fullSchema.type = fullSchema.type.find(t => t !== 'null')
44
- if (fullSchema.nullable && fullSchema.enum) fullSchema.enum = fullSchema.enum.filter(v => v !== null)
45
- }
46
-
47
- // add index as key in case of tuples
48
- if (fullSchema.items && Array.isArray(fullSchema.items)) {
49
- fullSchema.items.forEach((item, i) => {
50
- item.key = '' + i
51
- })
52
- }
53
-
54
- // enum with a single item can be used as another way to express const
55
- if (fullSchema.enum && fullSchema.enum.length === 1) {
56
- fullSchema.const = fullSchema.enum[0]
57
- delete fullSchema.enum
58
- }
59
-
60
- if (fullSchema.type !== 'object') return fullSchema
61
-
62
- // Properties as array for easier loops
63
- fullSchema.properties = objectToArray(fullSchema.properties)
64
- fullSchema.required = fullSchema.required || []
65
- fullSchema.dependencies = fullSchema.dependencies || {}
66
-
67
- // Extend schema based on satisfied dependencies
68
- if (fullSchema.dependencies) {
69
- Object.keys(fullSchema.dependencies).forEach(depKey => {
70
- const dep = fullSchema.dependencies[depKey]
71
- // cases where dependency does not apply
72
- if (!value) return
73
- const val = getDeepKey(value, depKey)
74
- if ([null, undefined, false].includes(val)) return
75
- if (Array.isArray(val) && val.length === 0) return
76
- if (typeof val === 'object' && Object.keys(val).length === 0) return
77
-
78
- // dependency applies
79
- extendSchema(fullSchema, dep)
80
- })
81
- }
82
-
83
- // extend schema based on conditions
84
- if (fullSchema.if) {
85
- if (!options.validator) {
86
- console.error('v-jsf - The conditional if/then/else syntax requires the ajv or other validator option.')
87
- } else {
88
- // TODO: store this somewhere so that it is not re-compiled many times
89
- const validate = options.validator(fullSchema.if)
90
- const error = validate(value)
91
- if (!error && fullSchema.then) {
92
- extendSchema(fullSchema, fullSchema.then)
93
- }
94
- if (error && fullSchema.else) {
95
- extendSchema(fullSchema, fullSchema.else)
96
- }
97
- }
98
- }
99
- return fullSchema
100
- }
@@ -1,141 +0,0 @@
1
- // Some util functions around select components preparation to reduce size of the component
2
- import { deepEqual } from 'fast-equals'
3
-
4
- const selectUtils = {}
5
- export default selectUtils
6
-
7
- selectUtils.fetchRawItems = async (fullOptions, fullSchema, fromUrl, q) => {
8
- const url = fromUrl.replace('{q}', encodeURIComponent(q || ''))
9
- const res = await fullOptions.httpLib.get(url, fullOptions.httpOptions)
10
- const body = res.data || res.body
11
- const items = fullSchema['x-itemsProp'] ? body[fullSchema['x-itemsProp']] : body
12
- if (!Array.isArray(items)) throw new Error(`Result of http fetch ${url} is not an array`)
13
- return items
14
- }
15
-
16
- // from raw data to items usable in select components
17
- selectUtils.getSelectItems = (rawSelectItems, fullSchema, itemKey, itemIcon) => {
18
- const selectItems = []
19
-
20
- if (!rawSelectItems) {
21
- // nothing to do
22
- } else if (
23
- (fullSchema.type === 'object' && fullSchema.properties && Object.keys(fullSchema.properties).length) ||
24
- (fullSchema.type === 'array' && fullSchema.items && fullSchema.items.type === 'object' && fullSchema.items.properties && Object.keys(fullSchema.items.properties).length)
25
- ) {
26
- const keys = fullSchema.properties ? fullSchema.properties.map(p => p.key) : Object.keys(fullSchema.items.properties)
27
- rawSelectItems.forEach(item => {
28
- const filteredItem = {}
29
- keys.forEach(key => {
30
- const property = fullSchema.properties ? fullSchema.properties.find(p => p.key === key) : fullSchema.items.properties[key]
31
- if (item[key] !== undefined) {
32
- filteredItem[key] = item[key]
33
- // special case as seen in _prefilled_array_wrong_type.js
34
- if (property.type === 'string') filteredItem[key] = '' + filteredItem[key]
35
- }
36
- if ('default' in property && key in filteredItem) filteredItem[key] = property.default
37
- if ('const' in property) filteredItem[key] = property.const
38
- })
39
- selectItems.push(filteredItem)
40
- })
41
- } else {
42
- rawSelectItems.forEach(item => {
43
- if (typeof item === 'object') {
44
- selectItems.push(item)
45
- } else {
46
- const itemObject = { [itemKey]: item }
47
- if (itemIcon) itemObject[itemIcon] = item
48
- selectItems.push(itemObject)
49
- }
50
- })
51
- }
52
- return selectItems
53
- }
54
-
55
- const matchItem = (selectItem, item, itemKey) => {
56
- if ([null, undefined].includes(selectItem)) return false
57
- if ([null, undefined].includes(item)) return false
58
- return deepEqual(selectItem[itemKey], item[itemKey])
59
- }
60
-
61
- // TODO: this is not very rigorous because we have no way of knowing that the stored value will be properly
62
- // matched with a simple "q" params.. but it kinda gets the job done.. let's think about it some more at some point in the future
63
- const missingValuesCache = []
64
- const fetchMissingValue = async (fullOptions, fullSchema, itemKey, fromUrl, value) => {
65
- const valueFromCache = missingValuesCache.find(cv => deepEqual(cv.key, [itemKey, fromUrl, value]))
66
- if (valueFromCache) return valueFromCache.result || value
67
- const rawItems = await selectUtils.fetchRawItems(fullOptions, fullSchema, fromUrl, value[itemKey])
68
- const result = rawItems.find(item => matchItem(item, value, itemKey))
69
- missingValuesCache.push({ key: [itemKey, fromUrl, value], result })
70
- return result || value
71
- }
72
-
73
- // add the current value to the select items so that they can be displayed
74
- selectUtils.fillSelectItems = async (fullOptions, fullSchema, value, selectItems, itemKey, itemTitle, fromUrl, returnObject) => {
75
- if (!value) return
76
- if (Array.isArray(value)) {
77
- for (let val of value.map(item => item).reverse()) {
78
- if (!returnObject) val = { [itemKey]: val }
79
- if (!selectItems.find(selectItem => matchItem(selectItem, val, itemKey))) {
80
- if (!returnObject && fromUrl) val = await fetchMissingValue(fullOptions, fullSchema, itemKey, fromUrl, val)
81
- selectItems.push(val)
82
- }
83
- }
84
- } else {
85
- if (!returnObject) value = { [itemKey]: value }
86
- if (!selectItems.find(selectItem => matchItem(selectItem, value, itemKey))) {
87
- if (!returnObject && fromUrl) value = await fetchMissingValue(fullOptions, fullSchema, itemKey, fromUrl, value)
88
- selectItems.push(value)
89
- }
90
- }
91
- }
92
-
93
- selectUtils.fillList = (fullSchema, value, selectItems, itemKey) => {
94
- if (!value) return
95
- if (!selectItems.length) return []
96
- value = [...value]
97
- // Prefill the lists (not actual select component, but an array instead)
98
- selectItems.forEach(selectItem => {
99
- if (!value.find(modelItem => matchItem(selectItem, modelItem, itemKey))) {
100
- value.push(selectItem)
101
- }
102
- })
103
- // also remove deprecated items
104
- value.forEach((item, i) => {
105
- if (!selectItems.find(selectItem => matchItem(selectItem, item, itemKey))) {
106
- value[i] = null
107
- }
108
- })
109
- return value.filter(item => !!item)
110
- }
111
-
112
- selectUtils.isOneOfSelect = (fullSchema) => {
113
- if (!fullSchema) return
114
- if (fullSchema.type === 'array' && fullSchema.items && ['string', 'integer', 'number'].includes(fullSchema.items.type) && (fullSchema.items.oneOf || fullSchema.items.anyOf)) return true
115
- if (['string', 'integer', 'number'].includes(fullSchema.type) && fullSchema.oneOf && fullSchema.oneOf[0] && fullSchema.oneOf[0].const !== undefined) return true
116
- if (['string', 'integer', 'number'].includes(fullSchema.type) && fullSchema.anyOf && fullSchema.anyOf[0] && fullSchema.anyOf[0].const !== undefined) return true
117
- return false
118
- }
119
-
120
- // get an object title if x-itemTitles is defined, handle direct values or values matched to a label through a oneOf/anyof
121
- selectUtils.getObjectTitle = (item, itemTitle, fullSchema) => {
122
- if (!itemTitle) return null
123
- const titlePropertySchema = fullSchema.items && fullSchema.items.properties && fullSchema.items.properties[itemTitle]
124
- if (titlePropertySchema) {
125
- const oneOfSelect = selectUtils.isOneOfSelect(titlePropertySchema)
126
- if (oneOfSelect) {
127
- const of = titlePropertySchema.anyOf || titlePropertySchema.oneOf
128
- const ofItem = of.find(ofItem => ofItem.const === item[itemTitle] || (ofItem.enum && ofItem.enum[0] === item[itemTitle]))
129
- if (ofItem) return ofItem.title
130
- }
131
- }
132
-
133
- if (fullSchema.items && (fullSchema.items.oneOf || fullSchema.items.anyOf)) {
134
- const of = fullSchema.items.oneOf || fullSchema.items.anyOf
135
- const props = of[0].properties
136
- const key = Object.keys(props).find(p => 'const' in props[p])
137
- const ofItem = of.find(ofItem => ofItem.properties[key].const === item[itemTitle])
138
- if (ofItem) return ofItem.title
139
- }
140
- return item[itemTitle]
141
- }