@vcmap/ui 5.0.0-rc.26 → 5.0.0-rc.27

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 (102) hide show
  1. package/build/buildCesium.js +7 -0
  2. package/config/dev.config.json +4 -0
  3. package/dist/assets/cesium/ThirdParty/Workers/basis_transcoder.js +21 -0
  4. package/dist/assets/cesium/ThirdParty/Workers/draco_decoder_nodejs.js +117 -0
  5. package/dist/assets/cesium/ThirdParty/Workers/package.json +1 -0
  6. package/dist/assets/cesium/ThirdParty/Workers/pako_deflate.min.js +2 -0
  7. package/dist/assets/cesium/ThirdParty/Workers/pako_inflate.min.js +2 -0
  8. package/dist/assets/cesium/ThirdParty/Workers/z-worker-pako.js +1 -0
  9. package/dist/assets/cesium/ThirdParty/basis_transcoder.wasm +0 -0
  10. package/dist/assets/cesium/ThirdParty/draco_decoder.wasm +0 -0
  11. package/dist/assets/cesium/ThirdParty/google-earth-dbroot-parser.js +8337 -0
  12. package/dist/assets/{cesium.305b7c.js → cesium.82fdbe.js} +4 -4
  13. package/dist/assets/cesium.js +1 -1
  14. package/dist/assets/{core.f3d6d4.js → core.df069a.js} +2 -2
  15. package/dist/assets/core.js +1 -1
  16. package/dist/assets/index-1cff371d.js +1 -0
  17. package/dist/assets/ol.js +1 -1
  18. package/dist/assets/style/icon-marker-blue.534e37.png +0 -0
  19. package/dist/assets/style/icon-marker-green.0b6a92.png +0 -0
  20. package/dist/assets/style/icon-marker-o-blue.7b6d62.png +0 -0
  21. package/dist/assets/style/icon-marker-o-green.c863c0.png +0 -0
  22. package/dist/assets/style/icon-marker-o-red.93ff58.png +0 -0
  23. package/dist/assets/style/icon-marker-o.036477.png +0 -0
  24. package/dist/assets/style/icon-marker-red.313d03.png +0 -0
  25. package/dist/assets/style/icon-marker.70960f.png +0 -0
  26. package/dist/assets/style/icon-pin-blue.7be369.png +0 -0
  27. package/dist/assets/style/icon-pin-green.cbb935.png +0 -0
  28. package/dist/assets/style/icon-pin-red.3f25b2.png +0 -0
  29. package/dist/assets/style/icon-pin.b7ce77.png +0 -0
  30. package/dist/assets/{ui.74022f.css → ui.3ed7ff.css} +2 -2
  31. package/dist/assets/ui.3ed7ff.js +14763 -0
  32. package/dist/assets/ui.js +1 -1
  33. package/dist/assets/vue.js +2 -2
  34. package/dist/assets/{vuetify.30486f.js → vuetify.614278.js} +1 -1
  35. package/dist/assets/vuetify.js +2 -2
  36. package/dist/index.html +1 -1
  37. package/index.js +17 -1
  38. package/package.json +1 -1
  39. package/plugins/@vcmap/create-link/index.js +8 -8
  40. package/plugins/@vcmap-show-case/collection-manager-example/index.js +6 -1
  41. package/plugins/@vcmap-show-case/form-inputs-example/FormInputsExample.vue +36 -8
  42. package/plugins/@vcmap-show-case/form-inputs-example/exampleActions.js +0 -19
  43. package/plugins/@vcmap-show-case/form-inputs-example/index.js +1 -2
  44. package/plugins/@vcmap-show-case/style-input-example/README.md +4 -0
  45. package/plugins/@vcmap-show-case/style-input-example/index.js +42 -0
  46. package/plugins/@vcmap-show-case/style-input-example/package.json +5 -0
  47. package/plugins/@vcmap-show-case/style-input-example/styleExample.vue +191 -0
  48. package/plugins/@vcmap-show-case/window-tester/WindowExample.vue +12 -13
  49. package/plugins/@vcmap-show-case/window-tester/windowExampleToggleChild.vue +44 -0
  50. package/public/assets/style/icon-marker-blue.png +0 -0
  51. package/public/assets/style/icon-marker-green.png +0 -0
  52. package/public/assets/style/icon-marker-o-blue.png +0 -0
  53. package/public/assets/style/icon-marker-o-green.png +0 -0
  54. package/public/assets/style/icon-marker-o-red.png +0 -0
  55. package/public/assets/style/icon-marker-o.png +0 -0
  56. package/public/assets/style/icon-marker-red.png +0 -0
  57. package/public/assets/style/icon-marker.png +0 -0
  58. package/public/assets/style/icon-pin-blue.png +0 -0
  59. package/public/assets/style/icon-pin-green.png +0 -0
  60. package/public/assets/style/icon-pin-red.png +0 -0
  61. package/public/assets/style/icon-pin.png +0 -0
  62. package/src/actions/actionHelper.js +1 -0
  63. package/src/application/VcsApp.vue +7 -1
  64. package/src/components/buttons/VcsActionButtonList.vue +1 -0
  65. package/src/components/form-inputs-controls/VcsCheckbox.vue +3 -2
  66. package/src/components/form-inputs-controls/VcsFormSection.vue +59 -9
  67. package/src/components/form-inputs-controls/VcsLabel.vue +10 -0
  68. package/src/components/form-inputs-controls/VcsRadioGrid.vue +175 -0
  69. package/src/components/form-inputs-controls/VcsSelect.vue +3 -0
  70. package/src/components/form-inputs-controls/VcsTextField.vue +12 -0
  71. package/src/components/icons/+all.js +4 -0
  72. package/src/components/icons/EditVerticesIcon.vue +39 -0
  73. package/src/components/lists/VcsActionList.vue +2 -0
  74. package/src/components/style/MenuWrapper.vue +138 -0
  75. package/src/components/style/VcsFillMenu.vue +61 -0
  76. package/src/components/style/VcsFillSelector.vue +45 -0
  77. package/src/components/style/VcsImageMenu.vue +84 -0
  78. package/src/components/style/VcsImageSelector.vue +609 -0
  79. package/src/components/style/VcsStrokeMenu.vue +73 -0
  80. package/src/components/style/VcsStrokeSelector.vue +87 -0
  81. package/src/components/style/VcsTextMenu.vue +81 -0
  82. package/src/components/style/VcsTextSelector.vue +271 -0
  83. package/src/components/style/VcsVectorStyleComponent.vue +119 -0
  84. package/src/components/style/composables.js +84 -0
  85. package/src/contentTree/contentTreeCollection.js +1 -0
  86. package/src/i18n/de.js +51 -17
  87. package/src/i18n/en.js +56 -22
  88. package/src/legend/vcsLegend.vue +7 -5
  89. package/src/manager/collectionManager/CollectionComponent.vue +9 -17
  90. package/src/manager/collectionManager/CollectionComponentList.vue +22 -9
  91. package/src/manager/collectionManager/CollectionManager.vue +20 -1
  92. package/src/manager/collectionManager/collectionComponent.js +11 -0
  93. package/src/manager/window/WindowComponent.vue +2 -1
  94. package/src/manager/window/WindowManager.vue +23 -9
  95. package/src/manager/window/windowHelper.js +76 -4
  96. package/src/manager/window/windowManager.js +38 -6
  97. package/src/vcsUiApp.js +1 -0
  98. package/dist/assets/index-f94d5be3.js +0 -1
  99. package/dist/assets/ui.74022f.js +0 -13466
  100. /package/dist/assets/{ol.39cc05.js → ol.90a5d0.js} +0 -0
  101. /package/dist/assets/{vue.9b8c6e.js → vue.537ff3.js} +0 -0
  102. /package/dist/assets/{vuetify.30486f.css → vuetify.614278.css} +0 -0
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <v-sheet>
3
+ <v-container class="px-1 py-0">
4
+ <v-row no-gutters>
5
+ <v-col>
6
+ <VcsLabel html-for="draw-stroke-width">
7
+ {{ $t('components.style.lineWidth') }}
8
+ </VcsLabel>
9
+ </v-col>
10
+ <v-col cols="3">
11
+ <VcsTextField
12
+ id="draw-stroke-width"
13
+ v-model.number="width"
14
+ type="number"
15
+ unit="px"
16
+ :disabled="!value"
17
+ />
18
+ </v-col>
19
+ </v-row>
20
+ </v-container>
21
+ <v-color-picker
22
+ :value="rgbaObject"
23
+ @input="updateColor"
24
+ mode="rgba"
25
+ :hide-mode-switch="true"
26
+ :disabled="!value"
27
+ />
28
+ </v-sheet>
29
+ </template>
30
+
31
+ <script>
32
+ import { computed } from 'vue';
33
+ import { VSheet, VColorPicker, VContainer, VRow, VCol } from 'vuetify/lib';
34
+ import { VcsLabel, VcsTextField } from '@vcmap/ui';
35
+ import { useColorObject } from './composables.js';
36
+
37
+ /**
38
+ * @description Allows to model a JSON representation of ol/Stroke vector style with a vuetify VColorPicker.
39
+ * @vue-prop {import("ol/style/Stroke").Options} value - The Stroke Options
40
+ */
41
+ export default {
42
+ name: 'VcsFillSelector',
43
+ components: {
44
+ VSheet,
45
+ VColorPicker,
46
+ VContainer,
47
+ VRow,
48
+ VCol,
49
+ VcsLabel,
50
+ VcsTextField,
51
+ },
52
+ props: {
53
+ value: {
54
+ type: Object,
55
+ default: undefined,
56
+ },
57
+ },
58
+ setup(props, { emit }) {
59
+ return {
60
+ rgbaObject: useColorObject(() => props.value?.color),
61
+ width: computed({
62
+ get() {
63
+ return props.value?.width;
64
+ },
65
+ set(value) {
66
+ if (value > 0 && value !== props.value?.width) {
67
+ const stroke = {
68
+ width: value,
69
+ };
70
+ if (props.value?.color) {
71
+ stroke.color = [...props.value.color];
72
+ }
73
+ emit('input', stroke);
74
+ }
75
+ },
76
+ }),
77
+ updateColor(rgba) {
78
+ const stroke = {
79
+ color: [rgba.r, rgba.g, rgba.b, rgba.a],
80
+ width: props.value?.width,
81
+ };
82
+ emit('input', stroke);
83
+ },
84
+ };
85
+ },
86
+ };
87
+ </script>
@@ -0,0 +1,81 @@
1
+ <template>
2
+ <MenuWrapper
3
+ v-bind="{ value, valueDefault }"
4
+ :value-fallback="fallbackStyle"
5
+ v-on="$listeners"
6
+ name="components.style.text"
7
+ >
8
+ <template #preview>
9
+ <div v-if="value" class="d-flex justify-center align-center">
10
+ <span id="text-preview">T</span>
11
+ </div>
12
+ </template>
13
+ <template #content>
14
+ <VcsTextSelector v-bind="{ value, valueDefault }" v-on="$listeners" />
15
+ </template>
16
+ </MenuWrapper>
17
+ </template>
18
+
19
+ <script>
20
+ import { computed } from 'vue';
21
+ import { VcsTextSelector } from '@vcmap/ui';
22
+ import MenuWrapper from './MenuWrapper.vue';
23
+ import { rgbaObjectToString, useColorObject } from './composables.js';
24
+
25
+ export const fallbackStyle = {
26
+ font: '10px Arial, Helvetica, sans-serif',
27
+ fill: { color: [0, 0, 0, 1] },
28
+ stroke: { color: [255, 255, 255, 1], width: 2 },
29
+ offsetX: 0,
30
+ offsetY: 0,
31
+ };
32
+
33
+ /**
34
+ * @description A wrapper for the VcsTextSelector, that has a small shape/icon preview and a menu that pops up when clicking the preview, containing the text style selector.
35
+ * @vue-prop {import("ol/style/Text").Options} value - The ol Text style options
36
+ * @vue-prop {import("ol/style/Text").Options} valueDefault - The default ol Text style options
37
+ */
38
+ export default {
39
+ name: 'VcsTextMenu',
40
+ components: {
41
+ MenuWrapper,
42
+ VcsTextSelector,
43
+ },
44
+ props: {
45
+ value: {
46
+ type: Object,
47
+ default: undefined,
48
+ },
49
+ valueDefault: {
50
+ type: Object,
51
+ default: undefined,
52
+ },
53
+ },
54
+ setup(props) {
55
+ const fillColorObject = useColorObject(() => props.value?.fill?.color);
56
+ const strokeColorObject = useColorObject(
57
+ () => props.value?.stroke?.color,
58
+ );
59
+
60
+ return {
61
+ strokeColor: computed(() =>
62
+ rgbaObjectToString(strokeColorObject.value),
63
+ ),
64
+ fillColor: computed(() => rgbaObjectToString(fillColorObject.value)),
65
+ fontStyle: computed(() => props.value?.font),
66
+ fallbackStyle,
67
+ };
68
+ },
69
+ };
70
+ </script>
71
+
72
+ <style>
73
+ #text-preview {
74
+ font: v-bind(fontStyle) !important;
75
+ font-size: 20px !important;
76
+ -webkit-text-stroke-color: v-bind(strokeColor);
77
+ -webkit-text-stroke-width: 1px;
78
+ -webkit-text-fill-color: v-bind(fillColor);
79
+ line-height: 1;
80
+ }
81
+ </style>
@@ -0,0 +1,271 @@
1
+ <template>
2
+ <v-sheet>
3
+ <v-container class="px-1 py-0">
4
+ <v-row no-gutters>
5
+ <v-col>
6
+ <VcsTextField
7
+ v-model="selectedText"
8
+ :placeholder="$t('components.style.enterText')"
9
+ />
10
+ </v-col>
11
+ </v-row>
12
+ <v-row no-gutters>
13
+ <v-col>
14
+ <VcsSelect
15
+ :items="
16
+ Object.keys(fonts).map((font) => ({
17
+ text: font,
18
+ value: fonts[font],
19
+ }))
20
+ "
21
+ v-model="fontFamily"
22
+ >
23
+ <template #item="{ item }">
24
+ <span :style="`font-family: ${item.value} !important`">{{
25
+ item.text
26
+ }}</span>
27
+ </template>
28
+ </VcsSelect>
29
+ </v-col>
30
+ <v-col cols="2">
31
+ <VcsTextField
32
+ type="number"
33
+ unit="px"
34
+ v-model="fontSize"
35
+ :rules="[(v) => (!!v && v > 0) || 'components.style.notValid']"
36
+ />
37
+ </v-col>
38
+ </v-row>
39
+ <div class="px-1 py-3">
40
+ <VcsButton
41
+ :active="isBold"
42
+ @click="isBold = !isBold"
43
+ class="pr-1"
44
+ tooltip="components.style.bold"
45
+ >
46
+ {{ $t('components.style.bold') }}
47
+ </VcsButton>
48
+ <VcsButton
49
+ :active="isItalic"
50
+ @click="isItalic = !isItalic"
51
+ class="px-2"
52
+ tooltip="components.style.italic"
53
+ >
54
+ {{ $t('components.style.italic') }}
55
+ </VcsButton>
56
+ </div>
57
+ <VcsStrokeMenu
58
+ v-model="selectedStroke"
59
+ :value-default="valueDefault.stroke"
60
+ :disabled="!value"
61
+ />
62
+ <VcsFillMenu
63
+ v-model="selectedFill"
64
+ :value-default="valueDefault.fill"
65
+ :disabled="!value"
66
+ />
67
+ <v-row no-gutters>
68
+ <v-col cols="6">
69
+ <VcsLabel>{{ $t('components.style.offset') }}</VcsLabel>
70
+ </v-col>
71
+ <v-col cols="3">
72
+ <VcsTextField
73
+ type="number"
74
+ v-model.number="selectedOffsetX"
75
+ tooltip-position="top"
76
+ prefix="X"
77
+ unit="px"
78
+ tooltip="components.style.offsetX"
79
+ />
80
+ </v-col>
81
+ <v-col cols="3">
82
+ <VcsTextField
83
+ type="number"
84
+ v-model.number="selectedOffsetY"
85
+ tooltip-position="top"
86
+ prefix="Y"
87
+ unit="px"
88
+ tooltip="components.style.offsetY"
89
+ />
90
+ </v-col>
91
+ </v-row>
92
+ </v-container>
93
+ </v-sheet>
94
+ </template>
95
+
96
+ <script>
97
+ import { computed } from 'vue';
98
+ import { VSheet, VContainer, VRow, VCol } from 'vuetify/lib';
99
+ import {
100
+ VcsSelect,
101
+ VcsTextField,
102
+ VcsButton,
103
+ VcsStrokeMenu,
104
+ VcsFillMenu,
105
+ VcsLabel,
106
+ } from '@vcmap/ui';
107
+ import { useSelectedKey } from './composables.js';
108
+
109
+ export const fonts = {
110
+ Georgia: 'Georgia, serif',
111
+ Palatino: '"Palatino Linotype", "Book Antiqua", Palatino, serif',
112
+ 'Times New Roman': '"Times New Roman", Times, serif',
113
+ Arial: 'Arial, Helvetica, sans-serif',
114
+ Impact: 'Impact, Charcoal, sans-serif',
115
+ 'Comic Sans': '"Comic Sans MS", cursive, sans-serif',
116
+ Trebuchet: '"Trebuchet MS", Helvetica, sans-serif',
117
+ Verdana: 'Verdana, Geneva, sans-serif',
118
+ Courier: '"Courier New", Courier, monospace',
119
+ Lucida: '"Lucida Console", Monaco, monospace',
120
+ };
121
+
122
+ /**
123
+ * @description Allows to model a JSON representation of ol/style/Text style. It makes use of VcsStrokeMenu and VcsFillMenu.
124
+ * @vue-prop {import("ol/style/Text").Options} value - The ol Text style options
125
+ * @vue-prop {import("ol/style/Text").Options} valueDefault - The default ol Text style options
126
+ */
127
+ export default {
128
+ name: 'VcsTextSelector',
129
+ components: {
130
+ VSheet,
131
+ VContainer,
132
+ VRow,
133
+ VCol,
134
+ VcsSelect,
135
+ VcsTextField,
136
+ VcsButton,
137
+ VcsStrokeMenu,
138
+ VcsFillMenu,
139
+ VcsLabel,
140
+ },
141
+ props: {
142
+ value: {
143
+ type: Object,
144
+ default: undefined,
145
+ },
146
+ valueDefault: {
147
+ type: Object,
148
+ required: true,
149
+ },
150
+ },
151
+ setup(props, { emit }) {
152
+ const font = computed({
153
+ get() {
154
+ let fontStyle = {
155
+ // fontStyle: 'normal',
156
+ // fontWeight: 'normal',
157
+ };
158
+ if (props.value) {
159
+ const el = document.createElement('span');
160
+ el.setAttribute('style', `font: ${props.value.font}`);
161
+ fontStyle = el.style;
162
+ el.remove();
163
+ }
164
+ return fontStyle;
165
+ },
166
+ });
167
+
168
+ function emitNewFont(key, value) {
169
+ font.value[key] = value;
170
+ const newModelObject = JSON.parse(JSON.stringify(props.value));
171
+ const fontPropertyArray = [
172
+ font.value.fontStyle,
173
+ font.value.fontWeight,
174
+ font.value.fontSize,
175
+ font.value.fontFamily,
176
+ ];
177
+ emit(
178
+ 'input',
179
+ Object.assign(newModelObject, {
180
+ font: fontPropertyArray
181
+ .filter((prop) => prop && prop !== 'normal')
182
+ .join(' '),
183
+ }),
184
+ );
185
+ }
186
+
187
+ const fontFamily = computed({
188
+ get() {
189
+ return font.value.fontFamily;
190
+ },
191
+ set(newFamily) {
192
+ emitNewFont('fontFamily', newFamily);
193
+ },
194
+ });
195
+
196
+ const fontSize = computed({
197
+ get() {
198
+ return parseInt(font.value.fontSize, 10);
199
+ },
200
+ set(newSize) {
201
+ if (!newSize || newSize < 1) {
202
+ return;
203
+ }
204
+ emitNewFont('fontSize', `${newSize}px`);
205
+ },
206
+ });
207
+
208
+ const isBold = computed({
209
+ get() {
210
+ return font.value.fontWeight === 'bold';
211
+ },
212
+ set(newValue) {
213
+ emitNewFont('fontWeight', newValue ? 'bold' : 'normal');
214
+ },
215
+ });
216
+ const isItalic = computed({
217
+ get() {
218
+ return font.value.fontStyle === 'italic';
219
+ },
220
+ set(newValue) {
221
+ emitNewFont('fontStyle', newValue ? 'italic' : 'normal');
222
+ },
223
+ });
224
+
225
+ const selectedFill = useSelectedKey(
226
+ () => props.value,
227
+ 'fill',
228
+ props.valueDefault.fill,
229
+ emit,
230
+ );
231
+ const selectedStroke = useSelectedKey(
232
+ () => props.value,
233
+ 'stroke',
234
+ props.valueDefault.stroke,
235
+ emit,
236
+ );
237
+ const selectedOffsetX = useSelectedKey(
238
+ () => props.value,
239
+ 'offsetX',
240
+ props.valueDefault.offsetX,
241
+ emit,
242
+ );
243
+ const selectedOffsetY = useSelectedKey(
244
+ () => props.value,
245
+ 'offsetY',
246
+ props.valueDefault.offsetY,
247
+ emit,
248
+ );
249
+ const selectedText = useSelectedKey(
250
+ () => props.value,
251
+ 'text',
252
+ props.valueDefault.text,
253
+ emit,
254
+ );
255
+ return {
256
+ fonts,
257
+ font,
258
+ fontFamily,
259
+ fontSize,
260
+ selectedFill,
261
+ selectedStroke,
262
+ emitNewFont,
263
+ isBold,
264
+ isItalic,
265
+ selectedOffsetX,
266
+ selectedOffsetY,
267
+ selectedText,
268
+ };
269
+ },
270
+ };
271
+ </script>
@@ -0,0 +1,119 @@
1
+ <template>
2
+ <v-sheet>
3
+ <component
4
+ v-for="key in styleComponents"
5
+ :key="key"
6
+ :is="componentMap[key]"
7
+ :value-default="valueDefault[key]"
8
+ v-model="selectedKeys[key].value"
9
+ @input="(value) => $emit(`update:${key}`, value)"
10
+ v-bind="specificProps[key]"
11
+ />
12
+ </v-sheet>
13
+ </template>
14
+
15
+ <script>
16
+ import { computed } from 'vue';
17
+ import {
18
+ VcsFillMenu,
19
+ VcsImageMenu,
20
+ VcsStrokeMenu,
21
+ VcsTextMenu,
22
+ } from '@vcmap/ui';
23
+ import { VSheet } from 'vuetify/lib';
24
+ import { useSelectedKey } from './composables.js';
25
+
26
+ /**
27
+ * @enum {string}
28
+ * @property {string} FILL
29
+ * @property {string} STROKE
30
+ * @property {string} IMAGE
31
+ * @property {string} TEXT
32
+ */
33
+ export const VectorStyleMenus = {
34
+ FILL: 'fill',
35
+ STROKE: 'stroke',
36
+ IMAGE: 'image',
37
+ TEXT: 'text',
38
+ };
39
+
40
+ /**
41
+ * @enum{string}
42
+ */
43
+ const componentMap = {
44
+ fill: 'VcsFillMenu',
45
+ stroke: 'VcsStrokeMenu',
46
+ image: 'VcsImageMenu',
47
+ text: 'VcsTextMenu',
48
+ };
49
+
50
+ /**
51
+ * @description Wraps the style component into a single component so whole @vcmap/core/VectorStyleItemOptions can be modelled.
52
+ * @vue-prop {import("@vcmap/core").VectorStyleItemOptions} value - The VectorStyleItemOptions that should be modelled.
53
+ * @vue-prop {import("@vcmap/core").VectorStyleItemOptions} valueDefault - The default VectorStyleItemOptions.
54
+ * @vue-prop {VectorStyleMenus[]} styleComponents - The style component that should be rendered.
55
+ * @vue-prop {boolean} [extendedShapeSettings=false] - If true, there are all the input fields needed to create arbitrary ol RegularShapes.
56
+ * @vue-prop {Array<import("ol/style/Icon").Options>} [iconOptions] - The icon options in the image component too choose from. Scale and opacity are ignored. The defaults are 3 different icon types with 4 different colors.
57
+ */
58
+ export default {
59
+ name: 'VcsVectorStyleComponent',
60
+ components: {
61
+ VcsFillMenu,
62
+ VcsImageMenu,
63
+ VcsStrokeMenu,
64
+ VcsTextMenu,
65
+ VSheet,
66
+ },
67
+ props: {
68
+ value: {
69
+ type: Object,
70
+ default: undefined,
71
+ },
72
+ valueDefault: {
73
+ type: Object,
74
+ default: undefined,
75
+ },
76
+ styleComponents: {
77
+ type: Array,
78
+ default: () => Object.values(VectorStyleMenus),
79
+ validator: (array) =>
80
+ array.every((component) =>
81
+ Object.values(VectorStyleMenus).includes(component),
82
+ ),
83
+ },
84
+ extendedShapeSettings: {
85
+ type: Boolean,
86
+ default: false,
87
+ },
88
+ iconOptions: {
89
+ type: Array,
90
+ default: undefined,
91
+ },
92
+ },
93
+ setup(props, { emit }) {
94
+ const selectedKeys = computed(() =>
95
+ // convert to Object with style prop names as keys and computed props as value to allow v-model.
96
+ props.styleComponents.reduce((acc, key) => {
97
+ acc[key] = useSelectedKey(
98
+ () => props.value,
99
+ key,
100
+ props.valueDefault[key],
101
+ emit,
102
+ );
103
+ return acc;
104
+ }, {}),
105
+ );
106
+ const specificProps = computed(() => ({
107
+ [VectorStyleMenus.IMAGE]: {
108
+ extendedShapeSettings: props.extendedShapeSettings,
109
+ iconOptions: props.iconOptions,
110
+ },
111
+ }));
112
+ return {
113
+ selectedKeys,
114
+ specificProps,
115
+ componentMap,
116
+ };
117
+ },
118
+ };
119
+ </script>
@@ -0,0 +1,84 @@
1
+ import { computed } from 'vue';
2
+
3
+ /**
4
+ * Computes a color object from a color array.
5
+ * @param {function():Array<number>} colorGetter Getter that returns an array containing rgba values.
6
+ * @returns {{r: number, g: number, b: number, a: number}} An object with rgba keys.
7
+ */
8
+ export function useColorObject(colorGetter) {
9
+ return computed(() => {
10
+ const rgbaArray = colorGetter();
11
+ if (rgbaArray) {
12
+ return {
13
+ r: rgbaArray[0],
14
+ g: rgbaArray[1],
15
+ b: rgbaArray[2],
16
+ a: rgbaArray[3],
17
+ };
18
+ } else {
19
+ return { r: 255, g: 255, b: 255, a: 0 };
20
+ }
21
+ });
22
+ }
23
+
24
+ /**
25
+ * Checks if a value is in a value range.
26
+ * @param {number} value Value checked to see if it is in the allowed range.
27
+ * @param {number[]} range Min and max value
28
+ * @returns {boolean} If value is between min and max.
29
+ */
30
+ export function between(value, range) {
31
+ return value >= range[0] && value <= range[1];
32
+ }
33
+
34
+ /**
35
+ * Creates a computed property with a getter and a setter for a specific object property/key of the value prop. If the value prop is an object, this composable allows to pass this computed to an v-model of a sub component. The getter returns the value of the key or, if it is undefined, a default value. The setter merges the passed value with the other object properties of the value prop and emits the whole object as a input event.
36
+ * @param {function():Object} modelObject Getter for the property that is modelled by the component and should be updated with input event, usually this is the 'value' prop.
37
+ * @param {string} key The key of the modelObject that should be return on get and updated on set.
38
+ * @param {*} defaultValue Default value for the key of the modelObject.
39
+ * @param {function(event: string, ...args: any[]):void} emit The emit function of the component context that is using this composable.
40
+ * @param {Array<number>} [range] The allowed range of numbers.
41
+ * @param {Array<number>} [isRequired] If value is required.
42
+ * @returns {*} The value to the key param if the getter is called.
43
+ */
44
+ export function useSelectedKey(
45
+ modelObject,
46
+ key,
47
+ defaultValue,
48
+ emit,
49
+ range,
50
+ isRequired,
51
+ ) {
52
+ return computed({
53
+ get() {
54
+ if (modelObject()?.[key] === undefined && isRequired) {
55
+ return defaultValue;
56
+ }
57
+ return modelObject()?.[key];
58
+ },
59
+ set(value) {
60
+ if (
61
+ ((value === null || value === undefined) && isRequired) ||
62
+ (value !== null &&
63
+ value !== undefined &&
64
+ range &&
65
+ !between(value, range))
66
+ ) {
67
+ return;
68
+ }
69
+ const newModelObject = JSON.parse(JSON.stringify(modelObject()));
70
+ // is needed to get e.g. from square shape to x by setting radius2 from 0 to undefined
71
+ const newValue = value === '' ? undefined : value;
72
+ emit('input', Object.assign(newModelObject, { [key]: newValue }));
73
+ },
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Creates a string from a color object.
79
+ * @param {{r: number, g: number, b: number, a: number}} rgbaObject An object with rgba keys.
80
+ * @returns {string} A string looking like this: rgba(0,0,0,0).
81
+ */
82
+ export function rgbaObjectToString(rgbaObject) {
83
+ return `rgba(${Object.values(rgbaObject).toString()})`;
84
+ }
@@ -72,6 +72,7 @@ class ContentTreeCollection extends IndexedCollection {
72
72
  this._weightListeners.delete(child.name);
73
73
  }
74
74
  }),
75
+ this.moved.addEventListener(recreateTree),
75
76
  ];
76
77
  /**
77
78
  * This is the default content tree.