@dative-gpi/foundation-shared-components 1.0.129 → 1.0.130-maps2

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 (54) hide show
  1. package/components/FSBreadcrumbs.vue +20 -12
  2. package/components/FSChip.vue +2 -2
  3. package/components/FSDialogMenu.vue +17 -8
  4. package/components/FSDialogRemove.vue +1 -1
  5. package/components/FSFadeOut.vue +1 -1
  6. package/components/FSIconCard.vue +26 -3
  7. package/components/FSInstantPicker.vue +266 -0
  8. package/components/FSPlayButtons.vue +72 -0
  9. package/components/FSProgressBar.vue +94 -0
  10. package/components/FSSpan.vue +8 -5
  11. package/components/FSText.vue +7 -5
  12. package/components/deviceOrganisations/FSStatusRichCard.vue +170 -0
  13. package/components/fields/FSAutocompleteField.vue +36 -52
  14. package/components/fields/FSDateField.vue +1 -0
  15. package/components/fields/FSSelectField.vue +41 -53
  16. package/components/fields/FSTermField.vue +11 -8
  17. package/components/fields/FSTranslateRichTextField.vue +17 -2
  18. package/components/fields/periodicField/FSPeriodicWeeklyField.vue +21 -11
  19. package/components/lists/FSDataTableUI.vue +30 -19
  20. package/components/map/FSMap.vue +19 -10
  21. package/components/map/FSMapMarker.vue +4 -4
  22. package/components/map/FSMapMarkerClusterGroup.vue +1 -1
  23. package/components/map/FSMapOverlay.vue +34 -19
  24. package/components/tiles/FSGroupTileUI.vue +14 -1
  25. package/components/tiles/FSLocationTileUI.vue +1 -1
  26. package/components/tiles/FSSimpleTileUI.vue +1 -1
  27. package/components/views/desktop/FSBaseDefaultDesktopView.vue +8 -7
  28. package/components/views/desktop/FSBaseEntityDesktopView.vue +1 -0
  29. package/components/views/mobile/FSBaseDefaultMobileView.vue +8 -7
  30. package/components/views/mobile/FSBaseEntityMobileView.vue +1 -0
  31. package/composables/useSlots.ts +2 -1
  32. package/models/rules.ts +5 -2
  33. package/package.json +4 -4
  34. package/styles/components/fs_breadcrumbs.scss +19 -31
  35. package/styles/components/fs_button.scss +7 -5
  36. package/styles/components/fs_chip.scss +8 -6
  37. package/styles/components/fs_clickable.scss +14 -12
  38. package/styles/components/fs_data_iterator_item.scss +12 -10
  39. package/styles/components/fs_dialog.scss +1 -1
  40. package/styles/components/fs_dialog_menu.scss +4 -2
  41. package/styles/components/fs_image_card.scss +5 -3
  42. package/styles/components/fs_map.scss +48 -16
  43. package/styles/components/fs_password_field.scss +4 -2
  44. package/styles/components/fs_progress_bar.scss +14 -0
  45. package/styles/components/fs_select_field.scss +4 -0
  46. package/styles/components/fs_span.scss +12 -4
  47. package/styles/components/fs_status_rich_card.scss +13 -0
  48. package/styles/components/fs_tabs.scss +9 -5
  49. package/styles/components/fs_tag.scss +9 -7
  50. package/styles/components/index.scss +2 -0
  51. package/styles/globals/overrides.scss +11 -4
  52. package/styles/globals/scrollbars.scss +10 -0
  53. package/utils/index.ts +1 -0
  54. package/utils/operations.ts +69 -0
@@ -4,13 +4,13 @@
4
4
  style="position: relative;"
5
5
  >
6
6
  <FSRow
7
- v-if="$props.showSearch || (!isExtraSmall && ($slots.prependToolbar || $slots.toolbar )) || (!$props.disableTable && !$props.disableIterator)"
7
+ v-if="$props.showSearch || (!isMobileSized && ($slots['prepend-toolbar'] || $slots['toolbar'] || $slots['append-toolbar'])) || (!$props.disableTable && !$props.disableIterator)"
8
8
  align="bottom-left"
9
- :wrap="isExtraSmall ? false : true"
9
+ :wrap="isMobileSized ? false : true"
10
10
  width="fill"
11
11
  >
12
12
  <slot
13
- v-if="!isExtraSmall"
13
+ v-if="!isMobileSized"
14
14
  name="prepend-toolbar"
15
15
  />
16
16
  <template
@@ -28,16 +28,22 @@
28
28
  />
29
29
  </template>
30
30
  <slot
31
- v-if="!isExtraSmall"
31
+ v-if="!isMobileSized"
32
32
  name="toolbar"
33
33
  />
34
34
  <template
35
- v-if="!$props.disableTable && !$props.disableIterator"
35
+ v-if="$slots['append-toolbar'] || (!$props.disableTable && !$props.disableIterator)"
36
36
  >
37
37
  <FSRow
38
38
  align="center-right"
39
+ :width="isExtraSmall ? 'hug' : 'fill'"
39
40
  >
41
+ <slot
42
+ v-if="!isMobileSized"
43
+ name="append-toolbar"
44
+ />
40
45
  <FSOptionGroup
46
+ v-if="!$props.disableTable && !$props.disableIterator"
41
47
  :values="modeOptions"
42
48
  :singleColor="true"
43
49
  :required="true"
@@ -48,13 +54,19 @@
48
54
  </template>
49
55
  </FSRow>
50
56
  <FSRow
51
- v-if="isExtraSmall && hasToolbar"
57
+ v-if="isMobileSized && ($slots['prepend-toolbar'] || $slots['toolbar'] || $slots['append-toolbar'])"
52
58
  >
53
- <FSWrapGroup>
59
+ <FSSlideGroup>
60
+ <slot
61
+ name="prepend-toolbar"
62
+ />
54
63
  <slot
55
64
  name="toolbar"
56
65
  />
57
- </FSWrapGroup>
66
+ <slot
67
+ name="append-toolbar"
68
+ />
69
+ </FSSlideGroup>
58
70
  </FSRow>
59
71
  <FSRow
60
72
  v-if="showFiltersRow"
@@ -900,8 +912,8 @@ export default defineComponent({
900
912
  },
901
913
  emits: ["update:modelValue", "update:headers", "update:search", "update:showFilters", "update:filters", "update:mode", "update:sortBy", "update:rowsPerPage", "update:page", "update:include", "update:items", "click:row"],
902
914
  setup(props, { emit }) {
915
+ const { isExtraSmall, isMobileSized } = useBreakpoints();
903
916
  const { handleRoutingEvent } = useRouting();
904
- const { isExtraSmall } = useBreakpoints();
905
917
  const { $tr } = useTranslationsProvider();
906
918
  const { getColors } = useColors();
907
919
  const router = useRouter();
@@ -962,10 +974,6 @@ export default defineComponent({
962
974
 
963
975
  });
964
976
 
965
- const hasToolbar = computed((): boolean => {
966
- return !!useSlots().slots["toolbar"];
967
- });
968
-
969
977
  const innerSlots = computed((): { [label: string]: Slot<any> } => {
970
978
  const slots = { ...useSlots().slots };
971
979
  delete slots["toolbar"];
@@ -1054,10 +1062,13 @@ export default defineComponent({
1054
1062
  });
1055
1063
 
1056
1064
  const innerItems = computed((): any[] => {
1057
- const activeFilters: { [key: string]: FSDataTableFilter[] } = {};
1058
- for (const property in filters.value) {
1059
- activeFilters[property] = filters.value[property].filter((filter) => !filter.hidden);
1060
- }
1065
+ // Select only the filters where a value is hidden, for others, accept all values
1066
+ const activeFilters: { [key: string]: FSDataTableFilter[] } = Object.keys(filters.value).reduce((acc, key) => {
1067
+ if (filters.value[key].some((filter) => filter.hidden)) {
1068
+ acc[key] = filters.value[key].filter((filter) => !filter.hidden);
1069
+ }
1070
+ return acc;
1071
+ }, {} as { [key: string]: FSDataTableFilter[] });
1061
1072
 
1062
1073
  if (props.items && props.items.length) {
1063
1074
  const innerSearchFormatted = innerSearch.value ? innerSearch.value.toLowerCase() : null;
@@ -1566,7 +1577,7 @@ export default defineComponent({
1566
1577
  await nextTick();
1567
1578
  innerPage.value = formerPage;
1568
1579
  }
1569
- });
1580
+ }, { deep: true });
1570
1581
 
1571
1582
  return {
1572
1583
  ColorEnum,
@@ -1577,7 +1588,6 @@ export default defineComponent({
1577
1588
  innerMode,
1578
1589
  modeOptions,
1579
1590
  innerPage,
1580
- hasToolbar,
1581
1591
  pageOptions,
1582
1592
  innerShowFilters,
1583
1593
  showFiltersRow,
@@ -1596,6 +1606,7 @@ export default defineComponent({
1596
1606
  classes,
1597
1607
  style,
1598
1608
  size,
1609
+ isMobileSized,
1599
1610
  isExtraSmall,
1600
1611
  draggableDisabled,
1601
1612
  elementId,
@@ -22,7 +22,6 @@
22
22
  :color="ColorEnum.Primary"
23
23
  :latlng="gpsPosition"
24
24
  />
25
-
26
25
  <FSMapFeatureGroup
27
26
  v-if="$props.areas"
28
27
  :expected-layers="$props.areas.length"
@@ -36,7 +35,6 @@
36
35
  @click="$emit('update:selectedAreaId', area.id)"
37
36
  />
38
37
  </FSMapFeatureGroup>
39
-
40
38
  <FSMapMarkerClusterGroup
41
39
  v-if="$props.locations"
42
40
  :expected-layers="$props.locations.length"
@@ -54,6 +52,7 @@
54
52
  @click="$emit('update:selectedLocationId', location.id)"
55
53
  />
56
54
  </FSMapMarkerClusterGroup>
55
+ <slot />
57
56
  </template>
58
57
  </div>
59
58
 
@@ -100,17 +99,18 @@
100
99
  </FSCol>
101
100
 
102
101
  <FSMapOverlay
103
- v-if="$slots['overlay']"
104
102
  :mode="$props.overlayMode"
105
103
  @update:mode="$emit('update:overlayMode', $event)"
106
104
  @update:height="(height) => overlayHeight = height"
107
105
  @update:width="(width) => overlayWidth = width"
108
106
  >
109
107
  <template
110
- #body
108
+ v-for="(_, name) in overlaySlots"
109
+ v-slot:[name]="slotData"
111
110
  >
112
111
  <slot
113
- name="overlay"
112
+ :name="'overlay-' + name"
113
+ v-bind="slotData"
114
114
  />
115
115
  </template>
116
116
  </FSMapOverlay>
@@ -126,7 +126,7 @@ import { map as createMap, control, tileLayer, latLngBounds, latLng, type LatLng
126
126
  import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui/composables";
127
127
  import { type FSArea } from '@dative-gpi/foundation-shared-domain/models';
128
128
 
129
- import { useBreakpoints, useColors } from "../../composables";
129
+ import { useBreakpoints, useColors, useSlots } from "../../composables";
130
130
  import { ColorEnum, type FSLocation, type MapLayer } from "../../models";
131
131
 
132
132
  import FSMapLayerButton from "./FSMapLayerButton.vue";
@@ -231,8 +231,9 @@ export default defineComponent({
231
231
  emits: ["update:modelValue", "update:selectedLocationId", "update:selectedAreaId", 'update:overlayMode', 'update:currentLayer', "click:latlng"],
232
232
  setup(props, { emit }) {
233
233
  const { $tr } = useTranslationsProvider();
234
- const { getColors } = useColors();
235
234
  const { isExtraSmall } = useBreakpoints();
235
+ const { getColors } = useColors();
236
+ const { slots } = useSlots();
236
237
 
237
238
  const leafletContainer = ref<HTMLElement>();
238
239
  const locationGroupBounds = ref<LatLngBounds>();
@@ -257,7 +258,7 @@ export default defineComponent({
257
258
  name: "map",
258
259
  label: $tr("ui.map-layer.map", "Map"),
259
260
  image: new URL("../../assets/images/map/map.png", import.meta.url).href,
260
- layer: tileLayer(`http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}&key=${import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? ""}`, {
261
+ layer: tileLayer(`https://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}&key=${import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? ""}`, {
261
262
  maxZoom: 22,
262
263
  subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
263
264
  attribution: '© Google Map Data'
@@ -267,7 +268,7 @@ export default defineComponent({
267
268
  name: "imagery",
268
269
  label: $tr("ui.map-layer.imagery", "Imagery"),
269
270
  image: new URL("../../assets/images/map/imagery.png", import.meta.url).href,
270
- layer: tileLayer(`http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}&key=${import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? ""}`, {
271
+ layer: tileLayer(`https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}&key=${import.meta.env.VITE_GOOGLE_MAPS_API_KEY ?? ""}`, {
271
272
  maxZoom: 22,
272
273
  subdomains: ['mt0', 'mt1', 'mt2', 'mt3'],
273
274
  attribution: '© Google Map Data'
@@ -314,6 +315,13 @@ export default defineComponent({
314
315
  return bounds as LatLngBounds;
315
316
  });
316
317
 
318
+ const overlaySlots = computed(() => {
319
+ return Object.keys(slots).filter((slot) => slot.startsWith("overlay-")).reduce((acc, slot) => {
320
+ acc[slot.replace("overlay-", "")] = slots[slot];
321
+ return acc;
322
+ }, {} as Record<string, unknown>);
323
+ });
324
+
317
325
  const calculateTargetPosition = (target: L.LatLng, zoom?: number) => {
318
326
  if(!map.value) {
319
327
  return target;
@@ -468,7 +476,8 @@ export default defineComponent({
468
476
  actualLayer,
469
477
  mapLayers,
470
478
  gpsPosition,
471
- style
479
+ style,
480
+ overlaySlots
472
481
  };
473
482
  }
474
483
  });
@@ -87,15 +87,15 @@ export default {
87
87
  icon = divIcon({
88
88
  html: locationMarkerHtml(props.icon, getColors(props.color).base, props.label),
89
89
  iconSize: [size, size],
90
- className: props.selected ? 'fs-map-location fs-map-location-selected' : 'fs-map-location',
90
+ className: props.selected ? 'fs-map-marker fs-map-location fs-map-location-selected' : 'fs-map-marker fs-map-location',
91
91
  iconAnchor: [size / 2, size / 2],
92
92
  });
93
93
  } else {
94
- const size = 20;
94
+ const size = 16;
95
95
  icon = divIcon({
96
- html: pinMarkerHtml(getColors(props.color).base),
96
+ html: pinMarkerHtml(getColors(props.color).base, props.label),
97
97
  iconSize: [size, size],
98
- className: props.selected ? 'fs-map-location fs-map-location-selected' : 'fs-map-location',
98
+ className: props.selected ? 'fs-map-marker fs-map-pin fs-map-pin-selected' : 'fs-map-marker fs-map-pin',
99
99
  iconAnchor: [size / 2, size / 2],
100
100
  });
101
101
  }
@@ -45,7 +45,7 @@ export default {
45
45
 
46
46
  return divIcon({
47
47
  html: clusterMarkerHtml(cluster.getChildCount()),
48
- className: 'fs-map-location fs-map-location-full',
48
+ className: 'fs-map-marker fs-map-cluster-marker',
49
49
  iconSize: [size, size],
50
50
  iconAnchor: [size / 2, size / 2],
51
51
  });
@@ -10,7 +10,7 @@
10
10
  v-show="isExtraSmall"
11
11
  ref="mobileOverlayWrapper"
12
12
  class="fs-map-overlay-mobile"
13
- :style="{ height: $props.mode === 'expand' ? '90%' : ($props.mode === 'half' ? '60%' : '20px') }"
13
+ :style="{ height: $props.mode === 'expand' ? '90%' : ($props.mode === 'half' ? '60%' : 'auto') }"
14
14
  >
15
15
  <FSCard
16
16
  width="100%"
@@ -24,14 +24,18 @@
24
24
  >
25
25
  <FSRow
26
26
  align="center-center"
27
- @touchstart="$props.mode === 'expand' ? $emit('update:mode', 'collapse') : $emit('update:mode', 'expand')"
27
+ style="cursor: pointer;"
28
+ @touchstart="onClick"
29
+ @mousedown="onClick"
28
30
  >
29
- <FSButton
30
- variant="icon"
31
- :icon="$props.mode === 'expand' ? 'mdi-chevron-down' : 'mdi-chevron-up'"
32
- @click="$props.mode === 'expand' ? $emit('update:mode', 'collapse') : $emit('update:mode', 'expand')"
33
- />
31
+ <FSIcon>
32
+ {{ $props.mode === 'expand' ? 'mdi-chevron-down' : 'mdi-chevron-up' }}
33
+ </FSIcon>
34
34
  </FSRow>
35
+ <slot
36
+ v-if="$props.mode === 'collapse'"
37
+ name="collapsed"
38
+ />
35
39
  <FSCol
36
40
  v-if="$props.mode !== 'collapse'"
37
41
  height="fill"
@@ -44,7 +48,6 @@
44
48
  </FSCol>
45
49
  </FSCard>
46
50
  </div>
47
-
48
51
  <FSCard
49
52
  v-show="!isExtraSmall"
50
53
  class="fs-map-overlay-desktop"
@@ -64,14 +67,22 @@
64
67
 
65
68
  <script lang="ts">
66
69
  import { defineComponent, type PropType, onUnmounted, onMounted, ref } from "vue";
70
+
67
71
  import { useBreakpoints } from "../../composables";
68
- import FSButton from "../FSButton.vue";
72
+
69
73
  import FSCard from "../FSCard.vue";
74
+ import FSIcon from "../FSIcon.vue";
70
75
  import FSCol from "../FSCol.vue";
71
76
  import FSRow from "../FSRow.vue";
72
77
 
73
78
  export default defineComponent({
74
79
  name: "FSMapOverlay",
80
+ components: {
81
+ FSCard,
82
+ FSIcon,
83
+ FSCol,
84
+ FSRow
85
+ },
75
86
  props: {
76
87
  mode: {
77
88
  type: String as PropType<"collapse" | "half" | "expand">,
@@ -79,15 +90,9 @@ export default defineComponent({
79
90
  default: "collapse"
80
91
  }
81
92
  },
82
- components: {
83
- FSButton,
84
- FSCard,
85
- FSCol,
86
- FSRow
87
- },
88
93
  emits: ["update:mode", "update:height", "update:width"],
89
- setup(_, { emit }) {
90
- const { isExtraSmall } = useBreakpoints();
94
+ setup(props, { emit }) {
95
+ const { isExtraSmall, isTouchScreenEnabled } = useBreakpoints();
91
96
 
92
97
  const mobileOverlayWrapper = ref<HTMLDivElement | null>(null);
93
98
  const desktopOverlay = ref<InstanceType<typeof FSCard> | null>(null);
@@ -95,6 +100,14 @@ export default defineComponent({
95
100
  const mobileResizeObserver = ref<ResizeObserver | null>(null);
96
101
  const desktopResizeObserver = ref<ResizeObserver | null>(null);
97
102
 
103
+ const onClick = (): void => {
104
+ if (props.mode === "expand") {
105
+ emit("update:mode", "collapse");
106
+ return;
107
+ }
108
+ emit("update:mode", "expand");
109
+ }
110
+
98
111
  onMounted(() => {
99
112
  mobileResizeObserver.value = new ResizeObserver(entries => {
100
113
  entries.forEach((entry) => {
@@ -129,9 +142,11 @@ export default defineComponent({
129
142
  });
130
143
 
131
144
  return {
132
- isExtraSmall,
133
145
  mobileOverlayWrapper,
134
- desktopOverlay
146
+ isTouchScreenEnabled,
147
+ desktopOverlay,
148
+ isExtraSmall,
149
+ onClick
135
150
  };
136
151
  }
137
152
  });
@@ -97,6 +97,13 @@
97
97
  :imageId="$props.imageId"
98
98
  :width="imageSize"
99
99
  />
100
+ <FSIconCard
101
+ v-else-if="$props.icon"
102
+ backgroundVariant="standard"
103
+ :backgroundColor="ColorEnum.Background"
104
+ :icon="$props.icon"
105
+ :size="imageSize"
106
+ />
100
107
  </FSRow>
101
108
  </FSCol>
102
109
  </FSTile>
@@ -108,6 +115,7 @@ import { computed, defineComponent, type PropType } from "vue";
108
115
  import { useBreakpoints } from "@dative-gpi/foundation-shared-components/composables";
109
116
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
110
117
 
118
+ import FSIconCard from "../FSIconCard.vue";
111
119
  import FSImage from "../FSImage.vue";
112
120
  import FSColor from "../FSColor.vue";
113
121
  import FSSpan from "../FSSpan.vue";
@@ -118,6 +126,7 @@ import FSRow from "../FSRow.vue";
118
126
  export default defineComponent({
119
127
  name: "FSGroupTileUI",
120
128
  components: {
129
+ FSIconCard,
121
130
  FSImage,
122
131
  FSColor,
123
132
  FSSpan,
@@ -131,6 +140,10 @@ export default defineComponent({
131
140
  required: false,
132
141
  default: null
133
142
  },
143
+ icon: {
144
+ type: String,
145
+ required: false
146
+ },
134
147
  label: {
135
148
  type: String as PropType<string | null>,
136
149
  required: false,
@@ -183,7 +196,7 @@ export default defineComponent({
183
196
  });
184
197
 
185
198
  const infoWidth = computed((): string => {
186
- if (!props.imageId) {
199
+ if (!props.imageId && !props.icon) {
187
200
  return "100%";
188
201
  }
189
202
  return `calc(100% - ${imageSize.value}px - 24px)`;
@@ -46,7 +46,7 @@
46
46
  align="center-left"
47
47
  >
48
48
  <FSColor
49
- width="24px"
49
+ padding="0 8px"
50
50
  height="24px"
51
51
  :color="ColorEnum.Light"
52
52
  :border="false"
@@ -115,7 +115,7 @@ export default defineComponent({
115
115
  iconColor: {
116
116
  type: String as PropType<ColorBase>,
117
117
  required: false,
118
- default: ColorEnum.Dark
118
+ default: ColorEnum.Light
119
119
  },
120
120
  activeColor: {
121
121
  type: String as PropType<ColorBase>,
@@ -12,11 +12,10 @@
12
12
  <slot
13
13
  name="header"
14
14
  >
15
-
16
15
  <FSRow
17
- padding="24px 16px 16px 24px"
18
16
  style="position: sticky; top: 0px; z-index: 3;"
19
17
  :style="{ backgroundColor, marginTop: $props.stickyTitleTopOffset }"
18
+ :padding="`24px ${isTouchScreenEnabled ? '24px' : '16px'} 16px 24px`"
20
19
  >
21
20
  <slot
22
21
  name="title"
@@ -45,8 +44,8 @@
45
44
  </FSCol>
46
45
  <FSRow
47
46
  v-if="$slots.toolbar"
48
- padding="0px 16px 8px 24px"
49
47
  :style="stickyToolbar ? `position: sticky; top: ${$props.toolbarTopOffset}; z-index: 3; background-color: ${backgroundColor}` : undefined"
48
+ :padding="`0px ${isTouchScreenEnabled ? '24px' : '16px'} 8px 24px`"
50
49
  >
51
50
  <FSSlideGroup
52
51
  width="100%"
@@ -60,8 +59,8 @@
60
59
 
61
60
  <FSCol
62
61
  height="fill"
63
- :padding="$slots.toolbar ? '8px 16px 24px 24px' : '16px 16px 24px 24px'"
64
62
  gap="0px"
63
+ :padding="`${$slots.toolbar ? '8px' : '16px'} ${isTouchScreenEnabled ? '24px' : '16px'} 24px 24px`"
65
64
  >
66
65
  <slot />
67
66
  </FSCol>
@@ -74,7 +73,7 @@ import { defineComponent, type PropType, computed } from "vue";
74
73
 
75
74
  import { type FSBreadcrumbItem, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
76
75
 
77
- import { useColors } from "../../../composables"
76
+ import { useBreakpoints, useColors } from "../../../composables"
78
77
 
79
78
  import FSCol from "../../FSCol.vue";
80
79
  import FSRow from "../../FSRow.vue"
@@ -119,7 +118,8 @@ export default defineComponent({
119
118
  default: "0px"
120
119
  }
121
120
  },
122
- setup(){
121
+ setup() {
122
+ const { isTouchScreenEnabled } = useBreakpoints();
123
123
  const { getColors } = useColors();
124
124
 
125
125
  const backgroundColor = computed(() => {
@@ -127,8 +127,9 @@ export default defineComponent({
127
127
  });
128
128
 
129
129
  return {
130
+ isTouchScreenEnabled,
130
131
  backgroundColor
131
- }
132
+ };
132
133
  }
133
134
  });
134
135
  </script>
@@ -36,6 +36,7 @@
36
36
  :icon="$props.icon"
37
37
  />
38
38
  <FSCol
39
+ style="min-width: 0"
39
40
  align="center-left"
40
41
  height="fill"
41
42
  >
@@ -12,11 +12,10 @@
12
12
  <slot
13
13
  name="header"
14
14
  >
15
-
16
15
  <FSRow
17
- padding="24px 16px 16px 24px"
18
16
  style="position: sticky; top: 0px; z-index: 3;"
19
17
  :style="{ backgroundColor, marginTop: $props.stickyTitleTopOffset }"
18
+ :padding="`24px ${isTouchScreenEnabled ? '24px' : '16px'} 16px 24px`"
20
19
  >
21
20
  <slot
22
21
  name="title"
@@ -45,8 +44,8 @@
45
44
  </FSCol>
46
45
  <FSRow
47
46
  v-if="$slots.toolbar"
48
- padding="0px 16px 8px 24px"
49
47
  :style="stickyToolbar ? `position: sticky; top: ${$props.toolbarTopOffset}; z-index: 3; background-color: ${backgroundColor}` : undefined"
48
+ :padding="`0px ${isTouchScreenEnabled ? '24px' : '16px'} 8px 24px`"
50
49
  >
51
50
  <FSSlideGroup>
52
51
  <slot
@@ -58,8 +57,8 @@
58
57
 
59
58
  <FSCol
60
59
  height="fill"
61
- :padding="$slots.toolbar ? '8px 16px 24px 24px' : '16px 16px 24px 24px'"
62
60
  gap="0px"
61
+ :padding="`${$slots.toolbar ? '8px' : '16px'} ${isTouchScreenEnabled ? '24px' : '16px'} 24px 24px`"
63
62
  >
64
63
  <slot />
65
64
  </FSCol>
@@ -72,7 +71,7 @@ import { defineComponent, type PropType, computed } from "vue";
72
71
 
73
72
  import { type FSBreadcrumbItem, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
74
73
 
75
- import { useColors } from "../../../composables"
74
+ import { useBreakpoints, useColors } from "../../../composables"
76
75
 
77
76
  import FSCol from "../../FSCol.vue";
78
77
  import FSRow from "../../FSRow.vue"
@@ -117,7 +116,8 @@ export default defineComponent({
117
116
  default: "0px"
118
117
  }
119
118
  },
120
- setup(){
119
+ setup() {
120
+ const { isTouchScreenEnabled } = useBreakpoints();
121
121
  const { getColors } = useColors();
122
122
 
123
123
  const backgroundColor = computed(() => {
@@ -125,8 +125,9 @@ export default defineComponent({
125
125
  });
126
126
 
127
127
  return {
128
+ isTouchScreenEnabled,
128
129
  backgroundColor
129
- }
130
+ };
130
131
  }
131
132
  });
132
133
  </script>
@@ -28,6 +28,7 @@
28
28
  :size="actualImageSize"
29
29
  />
30
30
  <FSCol
31
+ style="min-width: 0"
31
32
  align="center-left"
32
33
  height="fill"
33
34
  >
@@ -20,11 +20,12 @@ export const useSlots = () => {
20
20
  // Directive wrapper (v-for, v-if)
21
21
  case "symbol":
22
22
  switch (element.type) {
23
+ // On a v-for, we want to get the children of the v-for
23
24
  case Symbol.for("v-fgt"):
24
25
  returnElements.push(...recursiveGetChildren(element.children));
25
26
  break;
27
+ // On a negative v-if, we want to get nothing
26
28
  case Symbol.for("v-cmt"):
27
- returnElements.push(element);
28
29
  break;
29
30
  default:
30
31
  returnElements.push(element);
package/models/rules.ts CHANGED
@@ -2,8 +2,9 @@ import { useTranslations as useTranslationsProvider } from "@dative-gpi/bones-ui
2
2
  import { useDateFormat } from "@dative-gpi/foundation-shared-services/composables";
3
3
  import { validateExpression } from "@dative-gpi/foundation-shared-domain/tools";
4
4
 
5
- import { getTimeBestString } from "../utils";
6
- import type { TimeUnit } from "@/shared/foundation-shared-domain/enums";
5
+ import type { TimeUnit } from "@dative-gpi/foundation-shared-domain/enums";
6
+
7
+ import { getTimeBestString, validateOperation } from "../utils";
7
8
 
8
9
  const { epochToLongDateFormat } = useDateFormat()!;
9
10
  const { $tr } = useTranslationsProvider();
@@ -22,6 +23,8 @@ export const TextRules = {
22
23
  different: (original: string, message: string | undefined = undefined) => (value: string) => value != original || (message ?? $tr("ui.rules.text-different", "Must be different from original")),
23
24
  outside: (values: string[], message: string | undefined = undefined) => (value: string) => !values.includes(value) || (message ?? $tr("ui.rules.text-outside", "Must be different from others")),
24
25
  inside: (values: string[], message: string | undefined = undefined) => (value: string) => values.includes(value) || (message ?? $tr("ui.rules.text-inside", "Must be one of the options")),
26
+ operation: (operands: string[], variables: string[], message: string | undefined = undefined) => (value: string) => validateOperation(value, operands, variables) || (message ?? $tr("ui.rules.text-operation", "Invalid operation")),
27
+ singleWord: (message: string | undefined = undefined) => (value: string) => !value.includes(" ") || (message ?? $tr("ui.rules.text-single-word", "Must be a single word")),
25
28
  };
26
29
 
27
30
  export const TagRules = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dative-gpi/foundation-shared-components",
3
3
  "sideEffects": false,
4
- "version": "1.0.129",
4
+ "version": "1.0.130-maps2",
5
5
  "description": "",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -10,8 +10,8 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
- "@dative-gpi/foundation-shared-domain": "1.0.129",
14
- "@dative-gpi/foundation-shared-services": "1.0.129"
13
+ "@dative-gpi/foundation-shared-domain": "1.0.130-maps2",
14
+ "@dative-gpi/foundation-shared-services": "1.0.130-maps2"
15
15
  },
16
16
  "peerDependencies": {
17
17
  "@dative-gpi/bones-ui": "^1.0.0",
@@ -35,5 +35,5 @@
35
35
  "sass": "1.71.1",
36
36
  "sass-loader": "13.3.2"
37
37
  },
38
- "gitHead": "73ebbdb8cfd158e2748933ec57315bc1b5fc4835"
38
+ "gitHead": "a0739b48282166f721cf6c2376a430e4690d92ef"
39
39
  }