aloha-vue 2.80.1 → 2.82.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 (41) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/aloha-vue.css +7 -0
  3. package/dist/aloha-vue.css.map +1 -1
  4. package/dist/aloha-vue.es.js +361 -24
  5. package/dist/aloha-vue.umd.js +17 -17
  6. package/package.json +1 -1
  7. package/scss/components/AMenu.scss +634 -627
  8. package/src/AMenu/AMenu.js +592 -581
  9. package/src/AMenu/__tests__/AMenu.test.js +54 -0
  10. package/src/AMenu/compositionAPI/SearchAPI.js +45 -2
  11. package/src/AMenu/compositionAPI/__tests__/SearchAPI.test.js +108 -0
  12. package/src/ui/ACheckbox/ACheckbox.js +6 -0
  13. package/src/ui/ACheckbox/ACheckboxItem/ACheckboxItem.js +6 -0
  14. package/src/ui/ADatepicker/ADatepicker.js +6 -0
  15. package/src/ui/ADatepickerRange/ADatepickerRange.js +6 -1
  16. package/src/ui/AFieldset/AFieldset.js +7 -1
  17. package/src/ui/AForm/AForm.js +6 -0
  18. package/src/ui/AFormElement/AFormElement.js +5 -0
  19. package/src/ui/AFormReadonly/AFormReadonly.js +1 -1
  20. package/src/ui/AGroup/AGroup.js +8 -1
  21. package/src/ui/AInput/AInput.js +6 -0
  22. package/src/ui/AInputCurrency/AInputCurrency.js +6 -0
  23. package/src/ui/AInputFile/AInputFile.js +40 -5
  24. package/src/ui/AInputNumber/AInputNumber.js +6 -0
  25. package/src/ui/AInputNumberRange/AInputNumberRange.js +6 -1
  26. package/src/ui/AJson/AJson.js +6 -0
  27. package/src/ui/AMultiselectOrdered/AMultiselectOrdered.js +30 -24
  28. package/src/ui/AOneCheckbox/AOneCheckbox.js +6 -0
  29. package/src/ui/ARadio/ARadio.js +6 -0
  30. package/src/ui/ARadio/ARadioItem/ARadioItem.js +6 -0
  31. package/src/ui/ARouterLinkConfig/ARouterLinkConfig.js +7 -0
  32. package/src/ui/ASelect/ASelect.js +6 -0
  33. package/src/ui/ASelectIcon/ASelectIcon.js +16 -11
  34. package/src/ui/ASelectStyle/ASelectStyle.js +16 -11
  35. package/src/ui/ASlider/ASlider.js +6 -0
  36. package/src/ui/ASwitch/ASwitch.js +11 -5
  37. package/src/ui/ATemplate/ATemplate.js +7 -2
  38. package/src/ui/ATextarea/ATextarea.js +6 -0
  39. package/src/ui/AValidatedJson/AValidatedJson.js +10 -2
  40. package/src/ui/AValidatedJson/AValidatedJsonItem/AValidatedJsonItem.js +6 -0
  41. package/src/ui/__tests__/ReadonlyValueParentClass.test.js +217 -0
@@ -119,17 +119,17 @@ export default {
119
119
  required: false,
120
120
  default: undefined,
121
121
  },
122
- dataExtra: {
123
- type: Array,
124
- required: false,
125
- default: () => [],
126
- },
127
- mergeData: {
128
- type: Boolean,
129
- required: false,
130
- default: false,
131
- },
132
- dependencies: {
122
+ dataExtra: {
123
+ type: Array,
124
+ required: false,
125
+ default: () => [],
126
+ },
127
+ mergeData: {
128
+ type: Boolean,
129
+ required: false,
130
+ default: false,
131
+ },
132
+ dependencies: {
133
133
  type: [Array, Object],
134
134
  required: false,
135
135
  default: undefined,
@@ -294,6 +294,11 @@ export default {
294
294
  type: Boolean,
295
295
  required: false,
296
296
  },
297
+ readonlyValueParentClass: {
298
+ type: [String, Object, Array],
299
+ required: false,
300
+ default: undefined,
301
+ },
297
302
  readonlyDefault: {
298
303
  type: String,
299
304
  required: false,
@@ -443,16 +448,16 @@ export default {
443
448
  required: false,
444
449
  default: () => AMultiselectOrderedPluginOptions.propsDefault.texts,
445
450
  },
446
- translateData: {
447
- type: Boolean,
448
- required: false,
449
- default: () => AMultiselectOrderedPluginOptions.propsDefault.translateData,
450
- },
451
- translateGroup: {
452
- type: Boolean,
453
- required: false,
454
- default: () => AMultiselectOrderedPluginOptions.propsDefault.translateGroup,
455
- },
451
+ translateData: {
452
+ type: Boolean,
453
+ required: false,
454
+ default: () => AMultiselectOrderedPluginOptions.propsDefault.translateData,
455
+ },
456
+ translateGroup: {
457
+ type: Boolean,
458
+ required: false,
459
+ default: () => AMultiselectOrderedPluginOptions.propsDefault.translateGroup,
460
+ },
456
461
  url: {
457
462
  type: String,
458
463
  required: false,
@@ -680,6 +685,7 @@ export default {
680
685
  if (this.readonly) {
681
686
  return h(AFormReadonly, {
682
687
  ...this.$attrs,
688
+ valueParentClass: this.readonlyValueParentClass,
683
689
  id: this.htmlIdLocal,
684
690
  alwaysTranslate: this.alwaysTranslate,
685
691
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -929,9 +935,9 @@ export default {
929
935
  searchTimeout: this.searchTimeout,
930
936
  searchTextInHtml: this.searchTextInHtml,
931
937
  selectMenuClass: this.selectMenuClass,
932
- slotName: this.slotName,
933
- translateGroup: this.translateGroup,
934
- type: "multiselect",
938
+ slotName: this.slotName,
939
+ translateGroup: this.translateGroup,
940
+ type: "multiselect",
935
941
  }, this.$slots),
936
942
  ]),
937
943
  ]),
@@ -157,6 +157,11 @@ export default {
157
157
  type: Boolean,
158
158
  required: false,
159
159
  },
160
+ readonlyValueParentClass: {
161
+ type: [String, Object, Array],
162
+ required: false,
163
+ default: undefined,
164
+ },
160
165
  readonlyDefault: {
161
166
  type: String,
162
167
  required: false,
@@ -249,6 +254,7 @@ export default {
249
254
  if (this.readonly) {
250
255
  return h(AFormReadonly, {
251
256
  ...this.$attrs,
257
+ valueParentClass: this.readonlyValueParentClass,
252
258
  id: this.htmlIdLocal,
253
259
  alwaysTranslate: this.alwaysTranslate,
254
260
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -285,6 +285,11 @@ export default {
285
285
  type: Boolean,
286
286
  required: false,
287
287
  },
288
+ readonlyValueParentClass: {
289
+ type: [String, Object, Array],
290
+ required: false,
291
+ default: undefined,
292
+ },
288
293
  readonlyDefault: {
289
294
  type: String,
290
295
  required: false,
@@ -626,6 +631,7 @@ export default {
626
631
  if (this.readonly) {
627
632
  return h(AFormReadonly, {
628
633
  ...this.$attrs,
634
+ valueParentClass: this.readonlyValueParentClass,
629
635
  id: this.htmlIdLocal,
630
636
  alwaysTranslate: this.alwaysTranslate,
631
637
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -97,6 +97,11 @@ export default {
97
97
  type: Boolean,
98
98
  required: false,
99
99
  },
100
+ readonlyValueParentClass: {
101
+ type: [String, Object, Array],
102
+ required: false,
103
+ default: undefined,
104
+ },
100
105
  searching: {
101
106
  type: Boolean,
102
107
  required: false,
@@ -191,6 +196,7 @@ export default {
191
196
  render() {
192
197
  if (this.readonly) {
193
198
  return h(AElement, {
199
+ class: this.readonlyValueParentClass,
194
200
  alwaysTranslate: this.alwaysTranslate,
195
201
  classDefault: "",
196
202
  extra: {
@@ -206,6 +206,11 @@ export default {
206
206
  type: Boolean,
207
207
  required: false,
208
208
  },
209
+ readonlyValueParentClass: {
210
+ type: [String, Object, Array],
211
+ required: false,
212
+ default: undefined,
213
+ },
209
214
  readonlyDefault: {
210
215
  type: String,
211
216
  required: false,
@@ -353,6 +358,7 @@ export default {
353
358
  modelDependencies: this.modelDependencies,
354
359
  modelValue: this.modelLocal,
355
360
  readonly: this.readonly,
361
+ readonlyValueParentClass: this.readonlyValueParentClass,
356
362
  readonlyDefault: this.readonlyDefault,
357
363
  required: this.required,
358
364
  slotName: this.slotName,
@@ -387,6 +393,7 @@ export default {
387
393
  modelDependencies: this.modelDependencies,
388
394
  modelValue: this.modelLocal,
389
395
  readonly: this.readonly,
396
+ readonlyValueParentClass: this.readonlyValueParentClass,
390
397
  readonlyDefault: this.readonlyDefault,
391
398
  required: this.required,
392
399
  search: true,
@@ -409,6 +409,11 @@ export default {
409
409
  type: Boolean,
410
410
  required: false,
411
411
  },
412
+ readonlyValueParentClass: {
413
+ type: [String, Object, Array],
414
+ required: false,
415
+ default: undefined,
416
+ },
412
417
  readonlyDefault: {
413
418
  type: String,
414
419
  required: false,
@@ -1007,6 +1012,7 @@ export default {
1007
1012
  if (this.readonly) {
1008
1013
  return h(AFormReadonly, {
1009
1014
  ...this.$attrs,
1015
+ valueParentClass: this.readonlyValueParentClass,
1010
1016
  id: this.htmlIdLocal,
1011
1017
  alwaysTranslate: this.alwaysTranslate,
1012
1018
  class: this.class,
@@ -279,6 +279,11 @@ export default {
279
279
  type: Boolean,
280
280
  required: false,
281
281
  },
282
+ readonlyValueParentClass: {
283
+ type: [String, Object, Array],
284
+ required: false,
285
+ default: undefined,
286
+ },
282
287
  readonlyDefault: {
283
288
  type: String,
284
289
  required: false,
@@ -325,17 +330,17 @@ export default {
325
330
  required: false,
326
331
  default: () => ASelectPluginOptions.propsDefault.textDeselectAll,
327
332
  },
328
- textSelectAll: {
329
- type: String,
330
- required: false,
331
- default: () => ASelectPluginOptions.propsDefault.textSelectAll,
332
- },
333
- translateGroup: {
334
- type: Boolean,
335
- required: false,
336
- default: () => ASelectPluginOptions.propsDefault.translateGroup,
337
- },
338
- type: {
333
+ textSelectAll: {
334
+ type: String,
335
+ required: false,
336
+ default: () => ASelectPluginOptions.propsDefault.textSelectAll,
337
+ },
338
+ translateGroup: {
339
+ type: Boolean,
340
+ required: false,
341
+ default: () => ASelectPluginOptions.propsDefault.translateGroup,
342
+ },
343
+ type: {
339
344
  type: String,
340
345
  required: false,
341
346
  default: () => ASelectPluginOptions.propsDefault.type,
@@ -282,6 +282,11 @@ export default {
282
282
  type: Boolean,
283
283
  required: false,
284
284
  },
285
+ readonlyValueParentClass: {
286
+ type: [String, Object, Array],
287
+ required: false,
288
+ default: undefined,
289
+ },
285
290
  readonlyDefault: {
286
291
  type: String,
287
292
  required: false,
@@ -329,17 +334,17 @@ export default {
329
334
  required: false,
330
335
  default: () => ASelectPluginOptions.propsDefault.textDeselectAll,
331
336
  },
332
- textSelectAll: {
333
- type: String,
334
- required: false,
335
- default: () => ASelectPluginOptions.propsDefault.textSelectAll,
336
- },
337
- translateGroup: {
338
- type: Boolean,
339
- required: false,
340
- default: () => ASelectPluginOptions.propsDefault.translateGroup,
341
- },
342
- type: {
337
+ textSelectAll: {
338
+ type: String,
339
+ required: false,
340
+ default: () => ASelectPluginOptions.propsDefault.textSelectAll,
341
+ },
342
+ translateGroup: {
343
+ type: Boolean,
344
+ required: false,
345
+ default: () => ASelectPluginOptions.propsDefault.translateGroup,
346
+ },
347
+ type: {
343
348
  type: String,
344
349
  required: false,
345
350
  default: () => ASelectPluginOptions.propsDefault.type,
@@ -216,6 +216,11 @@ export default {
216
216
  type: Boolean,
217
217
  required: false,
218
218
  },
219
+ readonlyValueParentClass: {
220
+ type: [String, Object, Array],
221
+ required: false,
222
+ default: undefined,
223
+ },
219
224
  readonlyDefault: {
220
225
  type: String,
221
226
  required: false,
@@ -474,6 +479,7 @@ export default {
474
479
  if (this.readonly) {
475
480
  return h(AFormReadonly, {
476
481
  ...this.$attrs,
482
+ valueParentClass: this.readonlyValueParentClass,
477
483
  id: this.htmlIdLocal,
478
484
  alwaysTranslate: this.alwaysTranslate,
479
485
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -192,6 +192,11 @@ export default {
192
192
  type: Boolean,
193
193
  required: false,
194
194
  },
195
+ readonlyValueParentClass: {
196
+ type: [String, Object, Array],
197
+ required: false,
198
+ default: undefined,
199
+ },
195
200
  readonlyDefault: {
196
201
  type: String,
197
202
  required: false,
@@ -321,6 +326,7 @@ export default {
321
326
  if (this.readonly) {
322
327
  return h(AFormReadonly, {
323
328
  ...this.$attrs,
329
+ valueParentClass: this.readonlyValueParentClass,
324
330
  id: this.htmlIdLocal,
325
331
  alwaysTranslate: this.alwaysTranslate,
326
332
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -348,11 +354,11 @@ export default {
348
354
  }],
349
355
  }, [
350
356
  (this.label || this.labelScreenReader) ?
351
- h(ALabel, {
352
- id: this.htmlIdLocal,
353
- alwaysTranslate: this.alwaysTranslate,
354
- extra: this.extra,
355
- label: this.label,
357
+ h(ALabel, {
358
+ id: this.htmlIdLocal,
359
+ alwaysTranslate: this.alwaysTranslate,
360
+ extra: this.extra,
361
+ label: this.label,
356
362
  labelClass: this.labelClass,
357
363
  labelScreenReader: this.labelScreenReader,
358
364
  required: this.required,
@@ -105,6 +105,11 @@ export default {
105
105
  type: Boolean,
106
106
  required: false,
107
107
  },
108
+ readonlyValueParentClass: {
109
+ type: [String, Object, Array],
110
+ required: false,
111
+ default: undefined,
112
+ },
108
113
  readonlyDefault: {
109
114
  type: String,
110
115
  required: false,
@@ -148,7 +153,7 @@ export default {
148
153
  }, [
149
154
  this.$slots[this.slotName] ?
150
155
  h("div", {
151
- class: "a_template",
156
+ class: ["a_template", this.readonly && this.readonlyValueParentClass],
152
157
  }, this.$slots[this.slotName]({
153
158
  options: this.options,
154
159
  props: this.$props,
@@ -156,7 +161,7 @@ export default {
156
161
  "",
157
162
  this.html ?
158
163
  withDirectives(h("div", {
159
- class: "a_template",
164
+ class: ["a_template", this.readonly && this.readonlyValueParentClass],
160
165
  }), [
161
166
  [ASafeHtml, this.html],
162
167
  ]) :
@@ -186,6 +186,11 @@ export default {
186
186
  type: Boolean,
187
187
  required: false,
188
188
  },
189
+ readonlyValueParentClass: {
190
+ type: [String, Object, Array],
191
+ required: false,
192
+ default: undefined,
193
+ },
189
194
  readonlyDefault: {
190
195
  type: String,
191
196
  required: false,
@@ -314,6 +319,7 @@ export default {
314
319
  if (this.readonly) {
315
320
  return h(AFormReadonly, {
316
321
  ...this.$attrs,
322
+ valueParentClass: this.readonlyValueParentClass,
317
323
  id: this.htmlIdLocal,
318
324
  alwaysTranslate: this.alwaysTranslate,
319
325
  excludeRenderAttributes: this.excludeRenderAttributes,
@@ -194,6 +194,11 @@ export default {
194
194
  required: false,
195
195
  default: undefined,
196
196
  },
197
+ readonlyValueParentClass: {
198
+ type: [String, Object, Array],
199
+ required: false,
200
+ default: undefined,
201
+ },
197
202
  required: {
198
203
  type: Boolean,
199
204
  required: false,
@@ -385,6 +390,7 @@ export default {
385
390
  modelDependencies: this.modelDependencies,
386
391
  modelValue: this.modelValue,
387
392
  readonly: this.readonly,
393
+ readonlyValueParentClass: this.readonlyValueParentClass,
388
394
  required: this.required,
389
395
  skipOwnIdInModelPath: true,
390
396
  slotNamePrepend: `singlePrepend_${ this.id }`,
@@ -428,7 +434,7 @@ export default {
428
434
  class: "a_column a_column_12",
429
435
  }, [
430
436
  h("ul", {
431
- class: "a_list_group",
437
+ class: ["a_list_group", this.readonly && this.readonlyValueParentClass],
432
438
  }, [
433
439
  this.modelListMode.length > 0 ?
434
440
  this.listModeItems.map((item, index) => {
@@ -449,6 +455,7 @@ export default {
449
455
  parentHtmlId: this.htmlIdLocal,
450
456
  parentId: this.id,
451
457
  readonly: this.readonly,
458
+ readonlyValueParentClass: this.readonlyValueParentClass,
452
459
  typedBaseId: this.typedBaseId,
453
460
  typedChildren: this.typedChildren,
454
461
  uniqueChildrenIds: this.uniqueChildrenIds,
@@ -534,7 +541,7 @@ export default {
534
541
  class: "a_column a_column_12",
535
542
  }, [
536
543
  h("ul", {
537
- class: "a_list_group",
544
+ class: ["a_list_group", this.readonly && this.readonlyValueParentClass],
538
545
  }, [
539
546
  this.isModelJsonModeEmpty ?
540
547
  h(ATranslation, {
@@ -560,6 +567,7 @@ export default {
560
567
  parentHtmlId: this.htmlIdLocal,
561
568
  parentId: this.id,
562
569
  readonly: this.readonly,
570
+ readonlyValueParentClass: this.readonlyValueParentClass,
563
571
  typedBaseId: this.typedBaseId,
564
572
  typedChildren: this.typedChildren,
565
573
  uniqueChildrenIds: this.uniqueChildrenIds,
@@ -103,6 +103,11 @@ export default {
103
103
  required: false,
104
104
  default: undefined,
105
105
  },
106
+ readonlyValueParentClass: {
107
+ type: [String, Object, Array],
108
+ required: false,
109
+ default: undefined,
110
+ },
106
111
  typedBaseId: {
107
112
  type: String,
108
113
  required: false,
@@ -279,6 +284,7 @@ export default {
279
284
  idPrefix: this.parentHtmlId,
280
285
  modelValue: this.modelItem,
281
286
  readonly: true,
287
+ readonlyValueParentClass: this.readonlyValueParentClass,
282
288
  skipOwnIdInModelPath: true,
283
289
  slotNamePrepend: "singlePrepend",
284
290
  useFlatModel: this.useFlatModel,
@@ -0,0 +1,217 @@
1
+ import {
2
+ h,
3
+ nextTick,
4
+ } from "vue";
5
+ import {
6
+ afterEach,
7
+ beforeEach,
8
+ describe,
9
+ expect,
10
+ it,
11
+ } from "vitest";
12
+ import {
13
+ mount,
14
+ } from "@vue/test-utils";
15
+ import {
16
+ ACheckbox,
17
+ ADatepicker,
18
+ ADatepickerRange,
19
+ AFieldset,
20
+ AForm,
21
+ AFormElement,
22
+ AGroup,
23
+ AInput,
24
+ AInputCurrency,
25
+ AInputFile,
26
+ AInputNumber,
27
+ AInputNumberRange,
28
+ AJson,
29
+ AMultiselectOrdered,
30
+ AOneCheckbox,
31
+ ARadio,
32
+ ARouterLinkConfig,
33
+ ASelect,
34
+ ASelectIcon,
35
+ ASelectStyle,
36
+ ASlider,
37
+ ASwitch,
38
+ ATemplate,
39
+ ATextarea,
40
+ AValidatedJson,
41
+ } from "../../index";
42
+
43
+ import ACheckboxItem from "../ACheckbox/ACheckboxItem/ACheckboxItem";
44
+ import ARadioItem from "../ARadio/ARadioItem/ARadioItem";
45
+
46
+ import {
47
+ setI18n,
48
+ updateTranslation,
49
+ } from "../../ATranslation/compositionAPI/ATranslationAPI";
50
+
51
+ const wrappers = [];
52
+
53
+ beforeEach(async() => {
54
+ setI18n({ de: {} });
55
+ updateTranslation();
56
+ await nextTick();
57
+ });
58
+
59
+ afterEach(() => {
60
+ wrappers.forEach(wrapper => wrapper.unmount());
61
+ wrappers.length = 0;
62
+ });
63
+
64
+ function mountReadonly(component, props = {}, slots = {}) {
65
+ const wrapper = mount(component, {
66
+ props: {
67
+ id: "test",
68
+ readonly: true,
69
+ readonlyValueParentClass: ["custom_value", { custom_object: true }],
70
+ ...props,
71
+ },
72
+ slots,
73
+ });
74
+ wrappers.push(wrapper);
75
+ return wrapper;
76
+ }
77
+
78
+ describe("readonlyValueParentClass", () => {
79
+ it.each([
80
+ ACheckbox,
81
+ ADatepicker,
82
+ ADatepickerRange,
83
+ AFieldset,
84
+ AInput,
85
+ AInputCurrency,
86
+ AInputFile,
87
+ AInputNumber,
88
+ AInputNumberRange,
89
+ AJson,
90
+ AMultiselectOrdered,
91
+ AOneCheckbox,
92
+ ARadio,
93
+ ASelect,
94
+ ASelectIcon,
95
+ ASelectStyle,
96
+ ASlider,
97
+ ASwitch,
98
+ ATextarea,
99
+ ])("styles the value wrapper in $name and reacts to class/readonly changes", async component => {
100
+ const wrapper = mountReadonly(component);
101
+ await nextTick();
102
+ const value = wrapper.get(".a_form_element_readonly_value");
103
+ expect(value.classes()).toContain("custom_value");
104
+ expect(value.classes()).toContain("custom_object");
105
+ expect(wrapper.classes()).not.toContain("custom_value");
106
+ await wrapper.setProps({ readonlyValueParentClass: "updated_value" });
107
+ expect(value.classes()).toContain("updated_value");
108
+ expect(value.classes()).not.toContain("custom_value");
109
+ await wrapper.setProps({ readonly: false });
110
+ expect(wrapper.find(".updated_value").exists()).toBe(false);
111
+ });
112
+
113
+ it.each([ADatepickerRange, AInputNumberRange])("preserves range layout in $name", component => {
114
+ const wrapper = mountReadonly(component);
115
+ expect(wrapper.get(".custom_value").classes()).toContain("a_form_element_readonly_value_range");
116
+ });
117
+
118
+ it("preserves fieldset columns and propagates defaults with per-child overrides", () => {
119
+ const wrapper = mountReadonly(AFieldset, {
120
+ children: [
121
+ { id: "first", type: "text" },
122
+ { id: "second", type: "text", readonlyValueParentClass: "child_value" },
123
+ ],
124
+ modelValue: {},
125
+ });
126
+ const value = wrapper.get(".a_form_element_readonly_value");
127
+ expect(value.classes()).toContain("a_columns");
128
+ const inputs = wrapper.findAllComponents(AInput);
129
+ expect(inputs[0].get(".a_form_element_readonly_value").classes()).toContain("custom_value");
130
+ expect(inputs[1].get(".a_form_element_readonly_value").classes()).toContain("child_value");
131
+ expect(inputs[1].get(".a_form_element_readonly_value").classes()).not.toContain("custom_value");
132
+ });
133
+
134
+ it("propagates defaults through AForm and nested groups", () => {
135
+ const wrapper = mountReadonly(AForm, {
136
+ modelValue: { group: {} },
137
+ data: [{
138
+ id: "group",
139
+ type: "group",
140
+ children: [
141
+ { id: "first", type: "text" },
142
+ { id: "second", type: "text", readonlyValueParentClass: "child_value" },
143
+ ],
144
+ }],
145
+ });
146
+ const group = wrapper.findComponent(AGroup);
147
+ expect(group.get(".a_columns").classes()).toContain("custom_value");
148
+ const inputs = group.findAllComponents(AInput);
149
+ expect(inputs[0].get(".a_form_element_readonly_value").classes()).toContain("custom_value");
150
+ expect(inputs[1].get(".a_form_element_readonly_value").classes()).toContain("child_value");
151
+ });
152
+
153
+ it("passes the class through AFormElement", () => {
154
+ const wrapper = mountReadonly(AFormElement, { type: "text" });
155
+ expect(wrapper.get(".a_form_element_readonly_value").classes()).toContain("custom_value");
156
+ });
157
+
158
+ it.each(["routerLinkConfig", "selectRoute", "multiselectRoute"])("passes the class through ARouterLinkConfig (%s)", async type => {
159
+ const wrapper = mountReadonly(ARouterLinkConfig, { type });
160
+ await nextTick();
161
+ expect(wrapper.get(".a_form_element_readonly_value").classes()).toContain("custom_value");
162
+ });
163
+
164
+ it("styles template HTML and slot content only in readonly mode", async() => {
165
+ const wrapper = mountReadonly(ATemplate, { html: "Value", slotName: "content" }, {
166
+ content: () => h("span", "Slot"),
167
+ });
168
+ expect(wrapper.findAll(".a_template.custom_value")).toHaveLength(2);
169
+ await wrapper.setProps({ readonly: false });
170
+ expect(wrapper.find(".custom_value").exists()).toBe(false);
171
+ });
172
+
173
+ it.each(["list", "json"])("styles AValidatedJson values and previews in %s mode", async mode => {
174
+ const wrapper = mountReadonly(AValidatedJson, {
175
+ mode,
176
+ children: [{ id: "value", type: "text" }],
177
+ modelValue: mode === "list" ? [{ value: "Hello" }] : { first: { value: "Hello" } },
178
+ });
179
+ expect(wrapper.get("ul.a_list_group").classes()).toContain("custom_value");
180
+ await wrapper.get(".test_toggle_details").trigger("click");
181
+ expect(wrapper.get(".a_form_element_readonly_value").classes()).toContain("custom_value");
182
+ await wrapper.setProps({ readonly: false });
183
+ expect(wrapper.get("ul.a_list_group").classes()).not.toContain("custom_value");
184
+ });
185
+
186
+ it("styles AValidatedJson values in single mode", () => {
187
+ const wrapper = mountReadonly(AValidatedJson, {
188
+ mode: "single",
189
+ children: [{ id: "value", type: "text" }],
190
+ modelValue: { value: "Hello" },
191
+ });
192
+ expect(wrapper.get(".a_form_element_readonly_value").classes()).toContain("custom_value");
193
+ });
194
+
195
+ it.each([ACheckboxItem, ARadioItem])("styles standalone readonly $name", async component => {
196
+ const wrapper = mountReadonly(component, { itemIndex: 0, dataItem: { label: "Value", value: 1 } });
197
+ expect(wrapper.classes()).toContain("custom_value");
198
+ await wrapper.setProps({ readonly: false });
199
+ expect(wrapper.find(".custom_value").exists()).toBe(false);
200
+ });
201
+
202
+ it.each([false, true])("shows file names without file input (multiple: %s)", isMultiple => {
203
+ const files = [{ name: "<first>.txt" }, { name: "second.txt" }];
204
+ const wrapper = mountReadonly(AInputFile, {
205
+ isMultiple,
206
+ modelValue: isMultiple ? files : files[0],
207
+ });
208
+ expect(wrapper.findAll("li").map(item => item.text())).toEqual(isMultiple ? ["<first>.txt", "second.txt"] : ["<first>.txt"]);
209
+ expect(wrapper.find("input[type=file]").exists()).toBe(false);
210
+ expect(wrapper.find("first").exists()).toBe(false);
211
+ });
212
+
213
+ it("shows readonlyDefault for an empty file value", () => {
214
+ const wrapper = mountReadonly(AInputFile, { readonlyDefault: "No files" });
215
+ expect(wrapper.get(".a_form_element_readonly_value").text()).toBe("No files");
216
+ });
217
+ });