@vcmap/ui 5.2.4 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/config/base.config.json +82 -0
  2. package/dist/assets/cesium.js +1 -1
  3. package/dist/assets/{core.83d353.js → core.7ca6f7.js} +3498 -3347
  4. package/dist/assets/core.js +1 -1
  5. package/dist/assets/index-0eb860e7.js +1 -0
  6. package/dist/assets/ol.js +1 -1
  7. package/dist/assets/{ui.300809.css → ui.a9e21c.css} +1 -1
  8. package/dist/assets/{ui.300809.js → ui.a9e21c.js} +5691 -5181
  9. package/dist/assets/ui.js +1 -1
  10. package/dist/assets/vue.js +2 -2
  11. package/dist/assets/{vuetify.b3de7a.js → vuetify.ecc326.js} +1 -1
  12. package/dist/assets/vuetify.js +2 -2
  13. package/dist/index.html +1 -1
  14. package/package.json +2 -2
  15. package/src/application/VcsApp.vue +154 -1
  16. package/src/application/VcsApp.vue.d.ts +14 -0
  17. package/src/application/VcsCustomScreen.vue +45 -0
  18. package/src/application/VcsCustomScreen.vue.d.ts +15 -0
  19. package/src/application/VcsSettings.vue +67 -0
  20. package/src/application/VcsSettings.vue.d.ts +2 -0
  21. package/src/application/VcsSplashScreen.vue +133 -0
  22. package/src/application/VcsSplashScreen.vue.d.ts +31 -0
  23. package/src/application/markdownHelper.js +19 -1
  24. package/src/components/icons/+all.js +4 -0
  25. package/src/components/icons/CrosshairIcon.vue +33 -0
  26. package/src/components/icons/CrosshairIcon.vue.d.ts +2 -0
  27. package/src/i18n/de.d.ts +41 -18
  28. package/src/i18n/de.js +22 -0
  29. package/src/i18n/en.d.ts +41 -18
  30. package/src/i18n/en.js +22 -0
  31. package/src/navigation/MapNavigation.vue +74 -4
  32. package/src/navigation/MapNavigation.vue.d.ts +36 -0
  33. package/src/navigation/ObliqueRotation.vue +8 -0
  34. package/src/navigation/ObliqueRotation.vue.d.ts +13 -1
  35. package/src/navigation/TiltSlider.vue +8 -1
  36. package/src/navigation/TiltSlider.vue.d.ts +13 -1
  37. package/src/navigation/VcsCompass.vue +7 -1
  38. package/src/navigation/VcsCompass.vue.d.ts +11 -0
  39. package/src/navigation/VcsZoomButton.vue +10 -0
  40. package/src/navigation/VcsZoomButton.vue.d.ts +15 -1
  41. package/src/navigation/locatorHelper.d.ts +9 -0
  42. package/src/navigation/locatorHelper.js +294 -0
  43. package/src/navigation/overviewMap.d.ts +21 -20
  44. package/src/navigation/overviewMap.js +51 -39
  45. package/src/uiConfig.d.ts +67 -0
  46. package/src/uiConfig.js +30 -0
  47. package/dist/assets/index-69733149.js +0 -1
  48. /package/dist/assets/{cesium.162cd3.js → cesium.8ce891.js} +0 -0
  49. /package/dist/assets/{ol.7cdede.js → ol.f313ea.js} +0 -0
  50. /package/dist/assets/{vue.27f25a.js → vue.d7a2f9.js} +0 -0
  51. /package/dist/assets/{vuetify.b3de7a.css → vuetify.ecc326.css} +0 -0
package/dist/assets/ui.js CHANGED
@@ -1 +1 @@
1
- export * from "./ui.300809.js";
1
+ export * from "./ui.a9e21c.js";
@@ -1,5 +1,5 @@
1
- export * from "./vue.27f25a.js";
2
- import { default as f } from "./vue.27f25a.js";
1
+ export * from "./vue.d7a2f9.js";
2
+ import { default as f } from "./vue.d7a2f9.js";
3
3
  export {
4
4
  f as default
5
5
  };
@@ -13,7 +13,7 @@ function loadCss(href) {
13
13
  elem.onerror = reject;
14
14
  document.head.appendChild(elem);
15
15
  });
16
- } await loadCss('./assets/vuetify.b3de7a.css');import v from "./vue.27f25a.js";
16
+ } await loadCss('./assets/vuetify.ecc326.css');import v from "./vue.d7a2f9.js";
17
17
  const Ne = v.extend().extend({
18
18
  name: "themeable",
19
19
  provide() {
@@ -1,5 +1,5 @@
1
- export * from "./vuetify.b3de7a.js";
2
- import { default as f } from "./vuetify.b3de7a.js";
1
+ export * from "./vuetify.ecc326.js";
2
+ import { default as f } from "./vuetify.ecc326.js";
3
3
  export {
4
4
  f as default
5
5
  };
package/dist/index.html CHANGED
@@ -95,7 +95,7 @@
95
95
  }
96
96
  }
97
97
  </style>
98
- <script type="module" crossorigin src="./assets/index-69733149.js"></script>
98
+ <script type="module" crossorigin src="./assets/index-0eb860e7.js"></script>
99
99
  </head>
100
100
  <body style="height: 100vh; margin: 0;">
101
101
  <noscript>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/ui",
3
- "version": "5.2.4",
3
+ "version": "5.3.0",
4
4
  "author": "Virtual City Systems",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@vcmap-cesium/engine": "^4.0.3",
56
- "@vcmap/core": "^5.2.0",
56
+ "@vcmap/core": "^5.3.0",
57
57
  "ol": "^7.5.2",
58
58
  "vue": "~2.7.3",
59
59
  "vuetify": "~2.6.7"
@@ -1,5 +1,10 @@
1
1
  <template>
2
2
  <v-container class="fill-height pa-0" absolute fluid>
3
+ <VcsSplashScreen
4
+ v-if="splashScreen"
5
+ :text-page="splashScreen"
6
+ :window-id="'splashScreen'"
7
+ ></VcsSplashScreen>
3
8
  <VcsNavbar />
4
9
  <VcsContainer :attribution-action="attributionAction" />
5
10
  <v-footer
@@ -68,6 +73,10 @@
68
73
  import { getLegendEntries } from '../legend/legendHelper.js';
69
74
  import VcsAttributionsFooter from './VcsAttributionsFooter.vue';
70
75
  import VcsTextPageFooter from './VcsTextPageFooter.vue';
76
+ import VcsSplashScreen, {
77
+ createSplashScreenAction,
78
+ } from './VcsSplashScreen.vue';
79
+ import VcsCustomScreen from './VcsCustomScreen.vue';
71
80
  import VcsAttributions from './VcsAttributions.vue';
72
81
  import { getAttributions } from './attributionsHelper.js';
73
82
  import VcsDefaultLogoMobile from '../logo-mobile.svg';
@@ -254,6 +263,103 @@
254
263
  };
255
264
  }
256
265
 
266
+ /**
267
+ * This helper function will add a customScreen action button to the apps NavbarManager MENU location.
268
+ * @param {import("../vcsUiApp.js").default} app
269
+ * @returns {function():void}
270
+ */
271
+ function setupCustomScreen(app) {
272
+ function setupCustomScreenAction() {
273
+ const { customScreen } = app.uiConfig.config.value;
274
+ const { action: customScreenAction, destroy: customScreenDestroy } =
275
+ createToggleAction(
276
+ {
277
+ name: customScreen.name || 'components.customScreen.name',
278
+ icon: customScreen.icon || 'mdi-information',
279
+ title: customScreen.title,
280
+ },
281
+ {
282
+ id: 'customScreenId',
283
+ component: VcsCustomScreen,
284
+ state: {
285
+ headerIcon: customScreen.icon,
286
+ headerTitle: customScreen.name,
287
+ },
288
+ slot: WindowSlot.DETACHED,
289
+ position: customScreen.windowPosition,
290
+ props: customScreen,
291
+ },
292
+ app.windowManager,
293
+ vcsAppSymbol,
294
+ );
295
+ if (app.navbarManager.has('customScreenToggle')) {
296
+ app.navbarManager.remove('customScreenToggle');
297
+ }
298
+ app.navbarManager.add(
299
+ {
300
+ id: 'customScreenToggle',
301
+ action: customScreenAction,
302
+ },
303
+ vcsAppSymbol,
304
+ ButtonLocation.MENU,
305
+ );
306
+ return () => {
307
+ customScreenDestroy();
308
+ };
309
+ }
310
+ let customScreen;
311
+ const stopCustomScreenWatcher = watch(
312
+ () => app.uiConfig.config.value.customScreen,
313
+ (newCustomScreen) => {
314
+ if (newCustomScreen) {
315
+ customScreen = setupCustomScreenAction();
316
+ }
317
+ },
318
+ { immediate: true },
319
+ );
320
+ return () => {
321
+ if (customScreen) {
322
+ customScreen();
323
+ }
324
+ stopCustomScreenWatcher();
325
+ };
326
+ }
327
+ /**
328
+ * This helper function will add a Splash Screen action button to the apps NavbarManager MENU location.
329
+ * @param {import("../vcsUiApp.js").default} app
330
+ */
331
+
332
+ function setupSplashScreen(app) {
333
+ function setupSplashScreenAction() {
334
+ const { splashScreen } = app.uiConfig.config.value;
335
+ const splashScreenAction = createSplashScreenAction({
336
+ name: splashScreen.name || 'components.splashScreen.name',
337
+ icon: splashScreen.icon || 'mdi-alert-box',
338
+ title: splashScreen.title,
339
+ });
340
+ if (app.navbarManager.has('splashScreenToggle')) {
341
+ app.navbarManager.remove('splashScreenToggle');
342
+ }
343
+ app.navbarManager.add(
344
+ {
345
+ id: 'splashScreenToggle',
346
+ action: splashScreenAction,
347
+ },
348
+ vcsAppSymbol,
349
+ ButtonLocation.MENU,
350
+ );
351
+ }
352
+
353
+ return watch(
354
+ () => app.uiConfig.config.value.splashScreen,
355
+ (newSplashScreen) => {
356
+ if (newSplashScreen) {
357
+ setupSplashScreenAction();
358
+ }
359
+ },
360
+ { immediate: true },
361
+ );
362
+ }
257
363
  /**
258
364
  * This helper function will add a settings action button to the apps NavbarManager MENU location.
259
365
  * @param {import("../vcsUiApp.js").default} app
@@ -456,6 +562,33 @@
456
562
  };
457
563
  }
458
564
 
565
+ /**
566
+ * This helper sets up a listener to sync the display quality settings from the {@see UiConfigObject}
567
+ * @param {import("../vcsUiApp.js").default} app
568
+ * @returns {function():void} - call to stop syncing
569
+ */
570
+ export function setupUiConfigDisplayQuality(app) {
571
+ const listeners = [
572
+ app.uiConfig.added.addEventListener((item) => {
573
+ if (item.name === 'displayQuality') {
574
+ app.displayQuality.updateOptions(item.value);
575
+ }
576
+ }),
577
+ app.uiConfig.removed.addEventListener((item) => {
578
+ if (item.name === 'displayQuality') {
579
+ app.displayQuality.updateOptions({});
580
+ }
581
+ }),
582
+ ];
583
+
584
+ return () => {
585
+ listeners.forEach((cb) => {
586
+ cb();
587
+ });
588
+ listeners.splice(0);
589
+ };
590
+ }
591
+
459
592
  /**
460
593
  * This helper gets attributions of all active maps, layers and oblique collections and returns an array of entries.
461
594
  * It also returns a attributionAction to toggle the attributions window and a destroy function.
@@ -507,6 +640,7 @@
507
640
  VcsPositionDisplay,
508
641
  VcsAttributionsFooter,
509
642
  VcsTextPageFooter,
643
+ VcsSplashScreen,
510
644
  VcsNavbar,
511
645
  VContainer,
512
646
  VFooter,
@@ -521,16 +655,18 @@
521
655
  /** @type {import("../vcsUiApp.js").default} */
522
656
  const app = getVcsAppById(props.appId);
523
657
  provide('vcsApp', app);
524
-
525
658
  const mapNavbarListener = setupMapNavbar(app);
526
659
  const legendDestroy = setupLegendWindow(app);
527
660
  const settingsDestroy = setupSettingsWindow(app);
661
+ const stopCustomScreen = setupCustomScreen(app);
662
+ const stopSplashScreen = setupSplashScreen(app);
528
663
  setupHelpButton(app);
529
664
  const destroyComponentsWindow = setupCategoryManagerWindow(app);
530
665
  const destroyThemingListener = setupUiConfigTheming(
531
666
  app,
532
667
  getCurrentInstance().proxy.$vuetify,
533
668
  );
669
+ const destroyDisplayQualityListener = setupUiConfigDisplayQuality(app);
534
670
  const { attributionEntries, attributionAction, destroyAttributions } =
535
671
  setupAttributions(app);
536
672
 
@@ -546,9 +682,12 @@
546
682
  mapNavbarListener();
547
683
  legendDestroy();
548
684
  settingsDestroy();
685
+ stopCustomScreen();
686
+ stopSplashScreen();
549
687
  destroyComponentsWindow();
550
688
  destroyThemingListener();
551
689
  destroyAttributions();
690
+ destroyDisplayQualityListener();
552
691
  });
553
692
 
554
693
  return {
@@ -578,6 +717,20 @@
578
717
  }
579
718
  return undefined;
580
719
  }),
720
+ splashScreen: computed(() => {
721
+ if (app.uiConfig.config.value.splashScreen) {
722
+ return {
723
+ title: 'components.splashScreen.name',
724
+ tooltip: 'components.splashScreen.tooltip',
725
+ position: {
726
+ width: '800px',
727
+ height: '400px',
728
+ },
729
+ ...app.uiConfig.config.value.splashScreen,
730
+ };
731
+ }
732
+ return undefined;
733
+ }),
581
734
  attributionEntries,
582
735
  attributionAction,
583
736
  };
@@ -49,6 +49,12 @@ export function setupCategoryManagerWindow(app: import("../vcsUiApp.js").default
49
49
  * @returns {function():void} - call to stop syncing
50
50
  */
51
51
  export function setupUiConfigTheming(app: import("../vcsUiApp.js").default, vuetify: import("vuetify").Framework): () => void;
52
+ /**
53
+ * This helper sets up a listener to sync the display quality settings from the {@see UiConfigObject}
54
+ * @param {import("../vcsUiApp.js").default} app
55
+ * @returns {function():void} - call to stop syncing
56
+ */
57
+ export function setupUiConfigDisplayQuality(app: import("../vcsUiApp.js").default): () => void;
52
58
  /**
53
59
  * This helper gets attributions of all active maps, layers and oblique collections and returns an array of entries.
54
60
  * It also returns a attributionAction to toggle the attributions window and a destroy function.
@@ -75,6 +81,14 @@ declare const _default: import("vue").DefineComponent<{
75
81
  title: string;
76
82
  tooltip: string;
77
83
  } | undefined>;
84
+ splashScreen: import("vue").ComputedRef<{
85
+ title: string;
86
+ tooltip: string;
87
+ position: {
88
+ width: string;
89
+ height: string;
90
+ };
91
+ } | undefined>;
78
92
  attributionEntries: import("vue").Ref<import("./attributionsHelper.js").AttributionEntry[]>;
79
93
  attributionAction: import("../actions/actionHelper.js").VcsAction;
80
94
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <v-card>
3
+ <div class="px-2 pt-2 pb-1">
4
+ <v-card-text>
5
+ <div v-html="customScreenText"></div>
6
+ </v-card-text>
7
+ </div>
8
+ </v-card>
9
+ </template>
10
+
11
+ <script>
12
+ import { VCard, VCardText } from 'vuetify/lib';
13
+
14
+ import { computed, getCurrentInstance } from 'vue';
15
+ import { parseAndSanitizeMarkdown } from './markdownHelper.js';
16
+
17
+ export default {
18
+ name: 'VcsCustomScreen',
19
+ components: {
20
+ VCard,
21
+ VCardText,
22
+ },
23
+ props: {
24
+ content: {
25
+ type: String,
26
+ required: true,
27
+ },
28
+ },
29
+ setup(props) {
30
+ const vm = getCurrentInstance().proxy;
31
+ const dialog = true;
32
+ const customScreenText = computed(() => {
33
+ const translatedContent = vm.$t(props.content);
34
+ return parseAndSanitizeMarkdown(translatedContent);
35
+ });
36
+
37
+ return {
38
+ dialog,
39
+ customScreenText,
40
+ };
41
+ },
42
+ };
43
+ </script>
44
+
45
+ <style scoped lang="scss"></style>
@@ -0,0 +1,15 @@
1
+ declare const _default: import("vue").DefineComponent<{
2
+ content: {
3
+ type: StringConstructor;
4
+ required: true;
5
+ };
6
+ }, {
7
+ dialog: boolean;
8
+ customScreenText: import("vue").ComputedRef<string>;
9
+ }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{
10
+ content: {
11
+ type: StringConstructor;
12
+ required: true;
13
+ };
14
+ }>>, {}>;
15
+ export default _default;
@@ -14,6 +14,27 @@
14
14
  />
15
15
  </v-col>
16
16
  </v-row>
17
+ <v-row v-if="is3D" no-gutters>
18
+ <VcsLabel html-for="settingsDisplayQuality">
19
+ {{ $t('settings.displayQuality.title') }}
20
+ </VcsLabel>
21
+ </v-row>
22
+ <v-row v-if="is3D" no-gutters class="quality-slider-padding">
23
+ <VcsSlider
24
+ step="1"
25
+ v-model="displaySettings"
26
+ type="number"
27
+ max="2"
28
+ min="0"
29
+ ticks="always"
30
+ tick-size="5"
31
+ :tick-labels="[
32
+ $t('settings.displayQuality.level.low'),
33
+ $t('settings.displayQuality.level.medium'),
34
+ $t('settings.displayQuality.level.high'),
35
+ ]"
36
+ />
37
+ </v-row>
17
38
  <v-row no-gutters>
18
39
  <v-col>
19
40
  <VcsLabel html-for="settingsLanguageSelect">
@@ -38,9 +59,11 @@
38
59
  <script>
39
60
  import { ref, inject, onUnmounted, getCurrentInstance, computed } from 'vue';
40
61
  import { VCol, VContainer, VRow } from 'vuetify/lib';
62
+ import { CesiumMap, DisplayQualityLevel } from '@vcmap/core';
41
63
  import VcsLabel from '../components/form-inputs-controls/VcsLabel.vue';
42
64
  import VcsSelect from '../components/form-inputs-controls/VcsSelect.vue';
43
65
  import VcsRadio from '../components/form-inputs-controls/VcsRadio.vue';
66
+ import VcsSlider from '../components/form-inputs-controls/VcsSlider.vue';
44
67
 
45
68
  /**
46
69
  * @description The settings window of a VcsMap application
@@ -48,6 +71,7 @@
48
71
  export default {
49
72
  name: 'VcsSettings',
50
73
  components: {
74
+ VcsSlider,
51
75
  VcsSelect,
52
76
  VcsRadio,
53
77
  VcsLabel,
@@ -84,15 +108,58 @@
84
108
  const addedListener = app.i18n.added.addEventListener(setupI18n);
85
109
  const removedListener = app.i18n.removed.addEventListener(setupI18n);
86
110
 
111
+ const levels = [
112
+ DisplayQualityLevel.LOW,
113
+ DisplayQualityLevel.MEDIUM,
114
+ DisplayQualityLevel.HIGH,
115
+ ];
116
+ const localDisplaySettings = ref();
117
+ const displaySettings = computed({
118
+ get() {
119
+ return localDisplaySettings.value;
120
+ },
121
+ set(value) {
122
+ app.displayQuality.setLevel(levels[value]);
123
+ },
124
+ });
125
+ const setDisplayQualityLevel = () => {
126
+ localDisplaySettings.value = levels.indexOf(
127
+ app.displayQuality.currentQualityLevel,
128
+ );
129
+ };
130
+ setDisplayQualityLevel();
131
+ const displayQualityListener =
132
+ app.displayQuality.qualityLevelChanged.addEventListener(
133
+ setDisplayQualityLevel,
134
+ );
135
+
136
+ const is3D = ref(false);
137
+ const updateIs3D = () => {
138
+ is3D.value = app.maps.activeMap instanceof CesiumMap;
139
+ };
140
+ const mapActivatedListener =
141
+ app.maps.mapActivated.addEventListener(updateIs3D);
142
+ updateIs3D();
143
+
87
144
  onUnmounted(() => {
88
145
  localeChangedListener();
89
146
  addedListener();
90
147
  removedListener();
148
+ displayQualityListener();
149
+ mapActivatedListener();
91
150
  });
151
+
92
152
  return {
93
153
  language,
94
154
  languages,
155
+ displaySettings,
156
+ is3D,
95
157
  };
96
158
  },
97
159
  };
98
160
  </script>
161
+ <style scoped>
162
+ .quality-slider-padding {
163
+ padding-bottom: 20px !important;
164
+ }
165
+ </style>
@@ -1,5 +1,7 @@
1
1
  declare const _default: import("vue").DefineComponent<{}, {
2
2
  language: import("vue").WritableComputedRef<string>;
3
3
  languages: import("vue").Ref<never[]>;
4
+ displaySettings: import("vue").WritableComputedRef<any>;
5
+ is3D: import("vue").Ref<boolean>;
4
6
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
5
7
  export default _default;
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <v-dialog
3
+ v-model="dialog"
4
+ :width="textPage.position.width"
5
+ :height="textPage.position.height"
6
+ :max-width="textPage.position.maxWidth"
7
+ :max-height="textPage.position.maxHeight"
8
+ persistent
9
+ >
10
+ <v-card>
11
+ <div class="px-2 pt-2 pb-1">
12
+ <v-card-text>
13
+ <div v-html="splashScreenText"></div>
14
+
15
+ <v-row class="mt-2" v-if="acceptInput" no-gutters>
16
+ <v-col class="align-center d-flex">
17
+ <VcsCheckbox
18
+ id="checkbox_splashScreen"
19
+ style="margin-bottom: 16px"
20
+ v-model="checkBox"
21
+ >
22
+ </VcsCheckbox>
23
+
24
+ <VcsLabel>
25
+ <div
26
+ v-html="splashScreenCheckboxText"
27
+ class="marked-checkbox-content"
28
+ ></div>
29
+ </VcsLabel>
30
+ </v-col>
31
+ </v-row>
32
+ </v-card-text>
33
+
34
+ <v-card-actions>
35
+ <v-col class="text-right">
36
+ <VcsFormButton
37
+ color="primary"
38
+ @click="exitScreen"
39
+ :disabled="!checkBox"
40
+ >{{ buttonTitle }}</VcsFormButton
41
+ >
42
+ </v-col>
43
+ </v-card-actions>
44
+ </div>
45
+ </v-card>
46
+ </v-dialog>
47
+ </template>
48
+
49
+ <script>
50
+ import {
51
+ VDialog,
52
+ VCard,
53
+ VCardText,
54
+ VCardActions,
55
+ VRow,
56
+ VCol,
57
+ } from 'vuetify/lib';
58
+ import { computed, getCurrentInstance, ref } from 'vue';
59
+ import { parseAndSanitizeMarkdown } from './markdownHelper.js';
60
+ import VcsFormButton from '../components/buttons/VcsFormButton.vue';
61
+ import VcsCheckbox from '../components/form-inputs-controls/VcsCheckbox.vue';
62
+ import VcsLabel from '../components/form-inputs-controls/VcsLabel.vue';
63
+
64
+ const dialog = ref(true);
65
+ export function createSplashScreenAction(options) {
66
+ return {
67
+ ...options,
68
+ callback() {
69
+ dialog.value = true;
70
+ },
71
+ };
72
+ }
73
+
74
+ export default {
75
+ name: 'VcsSplashScreen',
76
+ components: {
77
+ VcsLabel,
78
+ VDialog,
79
+ VCard,
80
+ VCardText,
81
+ VCardActions,
82
+ VcsFormButton,
83
+ VcsCheckbox,
84
+ VRow,
85
+ VCol,
86
+ },
87
+ props: {
88
+ textPage: {
89
+ type: Object,
90
+ default: () => {},
91
+ },
92
+ windowId: {
93
+ type: String,
94
+ required: true,
95
+ },
96
+ },
97
+ setup(props) {
98
+ const vm = getCurrentInstance().proxy;
99
+ const splashScreenText = computed(() => {
100
+ const translatedContent = vm.$t(props.textPage.content);
101
+ return parseAndSanitizeMarkdown(translatedContent);
102
+ });
103
+ const buttonTitle = vm.$t(props.textPage.buttonTitle);
104
+
105
+ const splashScreenCheckboxText = computed(() => {
106
+ const translatedContent = vm.$t(props.textPage.checkBoxText);
107
+ return parseAndSanitizeMarkdown(translatedContent);
108
+ });
109
+
110
+ const acceptInput = ref(props.textPage.acceptInput);
111
+ const checkBox = ref(!acceptInput.value);
112
+ const exitScreen = () => {
113
+ dialog.value = false;
114
+ };
115
+
116
+ return {
117
+ dialog,
118
+ exitScreen,
119
+ splashScreenText,
120
+ splashScreenCheckboxText,
121
+ checkBox,
122
+ acceptInput,
123
+ buttonTitle,
124
+ };
125
+ },
126
+ };
127
+ </script>
128
+
129
+ <style scoped lang="scss">
130
+ .marked-checkbox-content ::v-deep p {
131
+ margin-bottom: 0;
132
+ }
133
+ </style>
@@ -0,0 +1,31 @@
1
+ export function createSplashScreenAction(options: any): any;
2
+ declare const _default: import("vue").DefineComponent<{
3
+ textPage: {
4
+ type: ObjectConstructor;
5
+ default: () => void;
6
+ };
7
+ windowId: {
8
+ type: StringConstructor;
9
+ required: true;
10
+ };
11
+ }, {
12
+ dialog: import("vue").Ref<boolean>;
13
+ exitScreen: () => void;
14
+ splashScreenText: import("vue").ComputedRef<string>;
15
+ splashScreenCheckboxText: import("vue").ComputedRef<string>;
16
+ checkBox: import("vue").Ref<boolean>;
17
+ acceptInput: any;
18
+ buttonTitle: any;
19
+ }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{
20
+ textPage: {
21
+ type: ObjectConstructor;
22
+ default: () => void;
23
+ };
24
+ windowId: {
25
+ type: StringConstructor;
26
+ required: true;
27
+ };
28
+ }>>, {
29
+ textPage: Record<string, any>;
30
+ }>;
31
+ export default _default;
@@ -1,12 +1,30 @@
1
1
  import { marked } from 'marked';
2
2
  import DOMPurify from 'dompurify';
3
3
 
4
+ // Create a custom renderer
5
+ const renderer = new marked.Renderer();
6
+
7
+ renderer.link = (href, title, text) => {
8
+ const target = '_blank';
9
+ const titleAttr = title ? ` title="${title}"` : '';
10
+ return `<a href="${href}" target="${target}"${titleAttr}>${text}</a>`;
11
+ };
12
+
13
+ // Set options for marked to use the custom renderer
14
+ marked.setOptions({
15
+ renderer,
16
+ breaks: true, // Enable line breaks
17
+ });
18
+
4
19
  /**
5
20
  * @param {string} content
6
21
  * @returns {string}
7
22
  */
8
23
  export function parseAndSanitizeMarkdown(content) {
9
- return DOMPurify.sanitize(marked(content));
24
+ // First, convert the Markdown to HTML using marked
25
+ const html = marked(content);
26
+ // Then sanitize the HTML using DOMPurify
27
+ return DOMPurify.sanitize(html, { ADD_ATTR: ['target'] });
10
28
  }
11
29
 
12
30
  /**