@dative-gpi/foundation-shared-components 1.0.126 → 1.0.128-dvh

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 (45) hide show
  1. package/components/FSBreadcrumbs.vue +20 -12
  2. package/components/FSDialogFormBody.vue +6 -6
  3. package/components/FSDialogMenu.vue +12 -2
  4. package/components/FSDialogMultiFormBody.vue +1 -1
  5. package/components/FSDialogRemove.vue +1 -1
  6. package/components/FSDialogSubmit.vue +1 -1
  7. package/components/FSFadeOut.vue +24 -9
  8. package/components/FSSpan.vue +8 -5
  9. package/components/FSText.vue +7 -5
  10. package/components/FSWindow.vue +10 -5
  11. package/components/agenda/FSAgendaHorizontalEvent.vue +14 -4
  12. package/components/calendar/FSSimpleCalendar.vue +6 -10
  13. package/components/fields/FSAutocompleteField.vue +37 -53
  14. package/components/fields/FSSelectField.vue +37 -53
  15. package/components/fields/FSTreeViewField.vue +1 -1
  16. package/components/lists/FSDataTableUI.vue +22 -14
  17. package/components/map/FSMap.vue +18 -8
  18. package/components/map/FSMapOverlay.vue +46 -18
  19. package/components/tiles/FSLocationTileUI.vue +1 -1
  20. package/components/views/desktop/FSBaseDefaultDesktopView.vue +9 -9
  21. package/components/views/desktop/FSBaseEntityDesktopView.vue +1 -0
  22. package/components/views/mobile/FSBaseDefaultMobileView.vue +9 -9
  23. package/components/views/mobile/FSBaseEntityMobileView.vue +1 -0
  24. package/composables/useBreakpoints.ts +6 -0
  25. package/composables/useSlots.ts +2 -1
  26. package/package.json +4 -4
  27. package/styles/components/fs_agenda_event.scss +1 -1
  28. package/styles/components/fs_breadcrumbs.scss +19 -31
  29. package/styles/components/fs_button.scss +7 -5
  30. package/styles/components/fs_chip.scss +8 -6
  31. package/styles/components/fs_clickable.scss +14 -12
  32. package/styles/components/fs_data_iterator_item.scss +12 -10
  33. package/styles/components/fs_dialog.scss +1 -1
  34. package/styles/components/fs_dialog_menu.scss +2 -2
  35. package/styles/components/fs_image_card.scss +5 -3
  36. package/styles/components/fs_map.scss +11 -7
  37. package/styles/components/fs_password_field.scss +4 -2
  38. package/styles/components/fs_span.scss +12 -4
  39. package/styles/components/fs_tabs.scss +9 -5
  40. package/styles/components/fs_tag.scss +9 -7
  41. package/styles/globals/overrides.scss +11 -4
  42. package/styles/globals/scrollbars.scss +10 -0
  43. package/tools/chartsTools.ts +3 -3
  44. package/utils/time.ts +13 -13
  45. package/components/tiles/FSChartTile.vue +0 -73
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <v-breadcrumbs
3
3
  class="fs-breadcrumbs"
4
- :items="$props.items"
4
+ :items="items"
5
5
  :style="style"
6
6
  v-bind="$attrs"
7
7
  >
@@ -9,7 +9,7 @@
9
9
  #title="{ item }"
10
10
  >
11
11
  <FSSpan
12
- :class="classes(item)"
12
+ class="fs-breadcrumbs-label"
13
13
  >
14
14
  {{ item.title }}
15
15
  </FSSpan>
@@ -31,7 +31,9 @@
31
31
  import { computed, defineComponent, type PropType, type StyleValue } from "vue";
32
32
 
33
33
  import { ColorEnum, type FSBreadcrumbItem } from "@dative-gpi/foundation-shared-components/models";
34
- import { useColors } from "@dative-gpi/foundation-shared-components/composables";
34
+ import { useBreakpoints, useColors } from "@dative-gpi/foundation-shared-components/composables";
35
+
36
+ import { sizeToVar } from "../utils";
35
37
 
36
38
  import FSSpan from "./FSSpan.vue";
37
39
  import FSIcon from "./FSIcon.vue";
@@ -49,28 +51,34 @@ export default defineComponent({
49
51
  default: () => []
50
52
  }
51
53
  },
52
- setup() {
54
+ setup(props) {
55
+ const { isExtraSmall } = useBreakpoints();
53
56
  const { getColors } = useColors();
54
57
 
55
58
  const darks = getColors(ColorEnum.Dark);
56
59
 
57
60
  const style = computed((): StyleValue => ({
61
+ "--fs-breadcrumbs-height" : sizeToVar(["20px", "16px"]),
58
62
  "--fs-breadcrumbs-color" : darks.dark,
59
63
  "--fs-breadcrumbs-active-color" : darks.base,
60
64
  "--fs-breadcrumbs-disabled-color": darks.soft
61
65
  }));
62
66
 
63
- const classes = (item: FSBreadcrumbItem): string[] => {
64
- const classNames = ["fs-breadcrumbs-label"];
65
- if (item.disabled) {
66
- classNames.push("fs-breadcrumbs-label-disabled");
67
+ const items = computed((): FSBreadcrumbItem[] => {
68
+ if (isExtraSmall.value && props.items.length > 3) {
69
+ const mobileItems: FSBreadcrumbItem[] = [0, -2, -1].map((index) => props.items.at(index)!)
70
+ mobileItems.splice(1, 0, {
71
+ title : "...",
72
+ disabled : true
73
+ });
74
+ return mobileItems;
67
75
  }
68
- return classNames;
69
- };
76
+ return props.items;
77
+ });
70
78
 
71
79
  return {
72
- style,
73
- classes
80
+ items,
81
+ style
74
82
  };
75
83
  }
76
84
  });
@@ -233,7 +233,7 @@ export default defineComponent({
233
233
  + (isMobileSized.value ? 24 : 32) + 24 // Title
234
234
  + (props.subtitle ? (isMobileSized.value ? 16 : 20) + 8 : 0) // Subtitle
235
235
  + (isMobileSized.value ? 36 : 40) + 24; // Footer
236
- return `calc(100vh - 42px - ${other}px)`;
236
+ return `calc(100dvh - 12px - ${other}px)`;
237
237
  });
238
238
 
239
239
  const cancelLabel = computed(() => {
@@ -275,17 +275,17 @@ export default defineComponent({
275
275
  }, { immediate: true });
276
276
 
277
277
  return {
278
- resetFormValidation,
279
278
  validateLabel,
280
- validateForm,
281
279
  isValidForm,
282
280
  cancelLabel,
283
281
  submitLabel,
284
- onValidate,
285
282
  ColorEnum,
286
283
  maxHeight,
287
- onSubmit,
288
- formRef
284
+ formRef,
285
+ resetFormValidation,
286
+ validateForm,
287
+ onValidate,
288
+ onSubmit
289
289
  };
290
290
  }
291
291
  });
@@ -6,8 +6,8 @@
6
6
  >
7
7
  <FSCard
8
8
  width="calc(100vw - 48px)"
9
- padding="8px"
10
- gap="24px"
9
+ :padding="$props.cardPadding"
10
+ :gap="$props.cardGap"
11
11
  :color="$props.color"
12
12
  :class="classes"
13
13
  >
@@ -43,6 +43,16 @@ export default defineComponent({
43
43
  required: false,
44
44
  default: null
45
45
  },
46
+ cardPadding: {
47
+ type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
48
+ required: false,
49
+ default: "8px"
50
+ },
51
+ cardGap: {
52
+ type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
53
+ required: false,
54
+ default: "24px"
55
+ },
46
56
  modelValue: {
47
57
  type: Boolean,
48
58
  required: false,
@@ -195,7 +195,7 @@ export default defineComponent({
195
195
  + (props.subtitle ? (isMobileSized.value ? 16 : 20) + 8 : 0) // Subtitle
196
196
  + (props.steps > 1 ? 24 + 4 : 0) // Pagination
197
197
  + (isMobileSized.value ? 36 : 40) + 24; // Footer
198
- return `calc(100vh - 42px - ${other}px)`;
198
+ return `calc(100dvh - 12px - ${other}px)`;
199
199
  });
200
200
 
201
201
  const previousButtonLabel = computed(() => {
@@ -21,7 +21,7 @@
21
21
  mdi-alert-outline
22
22
  </FSIcon>
23
23
  <FSRow
24
- gap="2px"
24
+ gap="4px"
25
25
  >
26
26
  <FSSpan>
27
27
  {{ $tr("dialog-remove.body-regular", "This action is") }}
@@ -181,7 +181,7 @@ export default defineComponent({
181
181
  + (isMobileSized.value ? 24 : 32) + 24 // Title
182
182
  + (props.subtitle ? (isMobileSized.value ? 16 : 20) + 8 : 0) // Subtitle
183
183
  + (isMobileSized.value ? 36 : 40) + 24; // Footer
184
- return `calc(100vh - 42px - ${other}px)`;
184
+ return `calc(100dvh - 12px - ${other}px)`;
185
185
  });
186
186
 
187
187
  const cancelLabel = computed(() => {
@@ -3,7 +3,6 @@
3
3
  class="fs-fade-out"
4
4
  ref="fadeOutRef"
5
5
  :id="elementId"
6
- :style="style"
7
6
  @scroll="$emit('scroll', $event); debounceMasks()"
8
7
  >
9
8
  <slot />
@@ -11,7 +10,7 @@
11
10
  </template>
12
11
 
13
12
  <script lang="ts">
14
- import { computed, defineComponent, onMounted, onUnmounted, type PropType, ref, type StyleValue, watch } from "vue";
13
+ import { computed, defineComponent, onMounted, onUnmounted, type PropType, ref, watch } from "vue";
15
14
 
16
15
  import { useBreakpoints, useColors, useDebounce } from "@dative-gpi/foundation-shared-components/composables";
17
16
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
@@ -65,17 +64,21 @@ export default defineComponent({
65
64
  type: Boolean,
66
65
  required: false,
67
66
  default: false
67
+ },
68
+ style:{
69
+ type: Object,
70
+ required: false
68
71
  }
69
72
  },
70
73
  emits: ["scroll"],
71
74
  setup(props) {
72
- const { windowHeight, windowWidth } = useBreakpoints();
75
+ const { windowHeight, windowWidth, isTouchScreenEnabled } = useBreakpoints();
73
76
  const { debounce } = useDebounce();
74
77
  const { getColors } = useColors();
75
78
 
76
79
  const backgrounds = getColors(ColorEnum.Background);
77
80
 
78
- const fadeOutRef = ref(null);
81
+ const fadeOutRef = ref<HTMLElement | null>(null);
79
82
  const bottomMaskHeight = ref("0px");
80
83
  const topMaskHeight = ref("0px");
81
84
  const lastScroll = ref(0);
@@ -84,18 +87,21 @@ export default defineComponent({
84
87
 
85
88
  const elementId = `id${uuidv4()}`;
86
89
 
87
- const style = computed((): StyleValue => ({
90
+ const showOutsideScrollbar = computed(() => props.scrollOutside && !isTouchScreenEnabled.value);
91
+
92
+ const style = computed((): {[index: string]: string} => ({
88
93
  "--fs-fade-out-height" : props.height ? sizeToVar(props.height) : "initial",
89
94
  "--fs-fade-out-max-height" : props.maxHeight ? sizeToVar(props.maxHeight) : "initial",
90
95
  "--fs-fade-out-width" : sizeToVar(props.width),
91
96
  "--fs-fade-out-padding" : sizeToVar(props.padding),
92
- "--fs-fade-out-width-offset" : props.scrollOutside ? '12px' : '0px',
93
- "--fs-fade-out-padding-offset" : props.scrollOutside ? '4px' : '0px',
94
- "--fs-fade-out-margin-right" : props.scrollOutside ? '-12px' : '0px',
97
+ "--fs-fade-out-width-offset" : showOutsideScrollbar.value ? '12px' : '0px',
98
+ "--fs-fade-out-padding-offset" : showOutsideScrollbar.value ? '4px' : '0px',
99
+ "--fs-fade-out-margin-right" : showOutsideScrollbar.value ? '-12px' : '0px',
95
100
  "--fs-fade-out-mask-color" : backgrounds.base,
96
101
  "--fs-fade-out-top-mask-height" : props.disableTopMask ? '0px' : topMaskHeight.value,
97
102
  "--fs-fade-out-bottom-mask-height": props.disableBottomMask ? '0px' : bottomMaskHeight.value,
98
- "--fs-fade-out-x-overflow" : props.hideHorizontalOverflow ? 'hidden' : 'auto'
103
+ "--fs-fade-out-x-overflow" : props.hideHorizontalOverflow ? 'hidden' : 'auto',
104
+ ...props.style
99
105
  }));
100
106
 
101
107
  const handleMasks = () => {
@@ -146,6 +152,15 @@ export default defineComponent({
146
152
 
147
153
  watch([() => windowWidth.value, () => windowHeight.value], debounceMasks);
148
154
 
155
+ watch(() => [style.value, fadeOutRef.value], () => {
156
+ if(!fadeOutRef.value || !style.value) {
157
+ return;
158
+ }
159
+ for(const key in style.value){
160
+ fadeOutRef.value.style.setProperty(key, style.value[key])
161
+ }
162
+ }, { immediate: true})
163
+
149
164
  return {
150
165
  fadeOutRef,
151
166
  elementId,
@@ -1,13 +1,15 @@
1
1
  <template>
2
- <span
2
+ <div
3
3
  :class="classes"
4
4
  :style="style"
5
5
  v-bind="$attrs"
6
6
  >
7
- <slot>
8
- {{ $props.label }}
9
- </slot>
10
- </span>
7
+ <span>
8
+ <slot>
9
+ {{ $props.label }}
10
+ </slot>
11
+ </span>
12
+ </div>
11
13
  </template>
12
14
 
13
15
  <script lang="ts">
@@ -49,6 +51,7 @@ export default defineComponent({
49
51
  const { slots } = useSlots();
50
52
 
51
53
  const style = computed((): StyleValue => ({
54
+ "--fs-span-text-align": props.align,
52
55
  "--fs-span-line-clamp": props.lineClamp.toString(),
53
56
  ...fontStyles.value
54
57
  }));
@@ -1,13 +1,15 @@
1
1
  <template>
2
- <span
2
+ <div
3
3
  :class="classes"
4
4
  :style="style"
5
5
  v-bind="$attrs"
6
6
  >
7
- <slot>
8
- {{ $props.label }}
9
- </slot>
10
- </span>
7
+ <span>
8
+ <slot>
9
+ {{ $props.label }}
10
+ </slot>
11
+ </span>
12
+ </div>
11
13
  </template>
12
14
 
13
15
  <script lang="ts">
@@ -1,9 +1,10 @@
1
1
  <template>
2
2
  <template
3
- v-if="noMatch"
3
+ v-if="showError"
4
4
  >
5
5
  <slot
6
- name="error"
6
+ name="error"
7
+ v-bind="{ goBack, width: $props.width, height: $props.height }"
7
8
  >
8
9
  <FSRow
9
10
  padding="16px"
@@ -144,14 +145,18 @@ export default defineComponent({
144
145
  }, 560);
145
146
  });
146
147
 
147
- const noMatch = computed(() => {
148
+ const showError = computed((): boolean => {
148
149
  if (!windowRef.value) {
149
- return;
150
+ return false;
150
151
  }
151
152
 
152
153
  // https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/components/VWindow/VWindow.tsx
153
154
  // https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/composables/group.ts#L161
154
155
  const group = windowRef.value.group;
156
+
157
+ if (!group.items.value.length) {
158
+ return false;
159
+ }
155
160
  return !group.items.value.find((item: any) => item.value === props.modelValue);
156
161
  });
157
162
 
@@ -172,7 +177,7 @@ export default defineComponent({
172
177
  return {
173
178
  ColorEnum,
174
179
  windowRef,
175
- noMatch,
180
+ showError,
176
181
  slots,
177
182
  style,
178
183
  getChildren,
@@ -44,7 +44,7 @@
44
44
  name="default"
45
45
  :label="label"
46
46
  :icon="icon"
47
- :iconBis="iconBis"
47
+ :iconBis="endToday ? iconBis : null"
48
48
  :timeStart="epochToShortTimeOnlyFormat($props.start)"
49
49
  :timeEnd="epochToShortTimeOnlyFormat($props.end)"
50
50
  :variant="$props.variant"
@@ -120,12 +120,20 @@ export default defineComponent({
120
120
  return dayEnd.value - props.dayStart;
121
121
  });
122
122
 
123
+ const startToday = computed(() => {
124
+ return props.start >= props.dayStart;
125
+ });
126
+
127
+ const endToday = computed(() => {
128
+ return props.end <= dayEnd.value;
129
+ });
130
+
123
131
  const dayDurationOffset = computed(() => {
124
132
  return dayDuration.value - dayToMillisecond(1);
125
133
  });
126
134
 
127
135
  const leftPosition = computed(() => {
128
- if (props.start < props.dayStart) {
136
+ if (!startToday.value) {
129
137
  return 0;
130
138
  }
131
139
  return millisecondToDay(props.start - props.dayStart - dayDurationOffset.value) * 100;
@@ -136,10 +144,10 @@ export default defineComponent({
136
144
  let end = props.end - dayDurationOffset.value;
137
145
  if(props.variant === 'current' && dayEnd.value > props.now) {
138
146
  end = props.now;
139
- } else if (props.end > dayEnd.value) {
147
+ } else if (!endToday.value) {
140
148
  end = dayEnd.value - dayDurationOffset.value;
141
149
  }
142
- if (props.start < props.dayStart) {
150
+ if (!startToday.value) {
143
151
  start = props.dayStart;
144
152
  }
145
153
 
@@ -150,12 +158,14 @@ export default defineComponent({
150
158
  const style = computed((): StyleValue => {
151
159
  return {
152
160
  '--fs-agenda-event-left': `${leftPosition.value}%`,
161
+ '--fs-agenda-event-border-width': startToday.value ? '3px' : '0px',
153
162
  };
154
163
  });
155
164
 
156
165
  return {
157
166
  style,
158
167
  width,
168
+ endToday,
159
169
  epochToShortTimeOnlyFormat
160
170
  };
161
171
  }
@@ -73,7 +73,7 @@ export default defineComponent({
73
73
 
74
74
  const firstDayOfMonth = computed(() => {
75
75
  const date = new Date(props.year, props.month - 1, 1);
76
- const offset = getMachineOffset();
76
+ const offset = getMachineOffset(date.getTime());
77
77
 
78
78
  date.setTime(date.getTime() + offset);
79
79
 
@@ -84,8 +84,7 @@ export default defineComponent({
84
84
  const day = new Date(firstDayOfMonth.value);
85
85
 
86
86
  const date = startOfWeek(day, { weekStartsOn: 1 });
87
-
88
- const offset = getMachineOffset();
87
+ const offset = getMachineOffset(date.getTime());
89
88
 
90
89
  date.setTime(date.getTime() + offset);
91
90
 
@@ -94,10 +93,9 @@ export default defineComponent({
94
93
 
95
94
  const endDayOfMonth = computed(() => {
96
95
  const day = new Date(firstDayOfMonth.value);
97
-
98
- const date = endOfMonth(day);
99
96
 
100
- const offset = getMachineOffset();
97
+ const date = endOfMonth(day);
98
+ const offset = getMachineOffset(date.getTime());
101
99
 
102
100
  date.setTime(date.getTime() + offset);
103
101
 
@@ -106,10 +104,9 @@ export default defineComponent({
106
104
 
107
105
  const lastSunday = computed(() => {
108
106
  const day = new Date(endDayOfMonth.value);
109
-
110
- const date = endOfWeek(day, { weekStartsOn: 1 });
111
107
 
112
- const offset = getMachineOffset();
108
+ const date = endOfWeek(day, { weekStartsOn: 1 });
109
+ const offset = getMachineOffset(date.getTime());
113
110
 
114
111
  date.setTime(date.getTime() + offset);
115
112
 
@@ -143,7 +140,6 @@ export default defineComponent({
143
140
  dayLabel,
144
141
  days
145
142
  };
146
-
147
143
  }
148
144
  });
149
145
  </script>
@@ -121,6 +121,7 @@
121
121
  </FSCard>
122
122
  </FSSlideGroup>
123
123
  <FSDialogMenu
124
+ cardPadding="16px"
124
125
  v-model="dialog"
125
126
  >
126
127
  <template
@@ -139,69 +140,52 @@
139
140
  >
140
141
  <FSRow
141
142
  v-for="(item, index) in searchItems"
143
+ align="center-left"
144
+ height="36px"
145
+ :wrap="false"
142
146
  :key="index"
147
+ @click="$props.multiple ?
148
+ onCheckboxChange(item[$props.itemValue!]) :
149
+ onRadioChange(item[$props.itemValue!])
150
+ "
143
151
  >
144
- <FSCheckbox
145
- v-if="$props.multiple"
146
- :label="item[$props.itemTitle!]"
147
- :editable="$props.editable"
148
- :modelValue="$props.modelValue?.includes(item[$props.itemValue!])"
149
- @update:modelValue="() => onCheckboxChange(item[$props.itemValue!])"
150
- >
151
- <template
152
- #label="{ font }"
153
- >
154
- <FSRow
155
- align="center-left"
156
- :wrap="false"
157
- >
158
- <slot
159
- name="item-prepend"
160
- v-bind="{ item }"
161
- />
162
- <FSSpan
163
- :font="font"
164
- >
165
- {{ item[$props.itemTitle!] }}
166
- </FSSpan>
167
- </FSRow>
168
- </template>
169
- </FSCheckbox>
170
- <FSRadio
171
- v-else
172
- :selected="$props.modelValue === item[$props.itemValue!]"
173
- :label="item[$props.itemTitle!]"
174
- :editable="$props.editable"
175
- :item="item"
176
- :modelValue="item[$props.itemValue!]"
177
- @update:modelValue="() => onRadioChange(item[$props.itemValue!])"
152
+ <FSRow
153
+ style="min-width: 0;"
154
+ :wrap="false"
178
155
  >
179
- <template
180
- #label="{ font }"
156
+ <slot
157
+ name="item-prepend"
158
+ v-bind="{ item }"
159
+ />
160
+ <FSSpan
161
+ :font="selectedItems.includes(item) ? 'text-button' : 'text-body'"
181
162
  >
182
- <FSRow
183
- align="center-left"
184
- :wrap="false"
185
- >
186
- <slot
187
- name="item-prepend"
188
- v-bind="{ item }"
189
- />
190
- <FSSpan
191
- :font="font"
192
- >
193
- {{ item[$props.itemTitle!] }}
194
- </FSSpan>
195
- </FSRow>
196
- </template>
197
- </FSRadio>
163
+ {{ item[$props.itemTitle!] }}
164
+ </FSSpan>
165
+ </FSRow>
198
166
  <FSRow
199
167
  align="center-right"
168
+ width="hug"
169
+ :wrap="false"
200
170
  >
201
171
  <slot
202
172
  name="item-append"
203
173
  v-bind="{ item }"
204
174
  />
175
+ <FSCheckbox
176
+ v-if="$props.multiple"
177
+ :editable="$props.editable"
178
+ :modelValue="$props.modelValue?.includes(item[$props.itemValue!])"
179
+ @update:modelValue="onCheckboxChange(item[$props.itemValue!])"
180
+ />
181
+ <FSRadio
182
+ v-else
183
+ :selected="$props.modelValue === item[$props.itemValue!]"
184
+ :editable="$props.editable"
185
+ :item="item"
186
+ :modelValue="item[$props.itemValue!]"
187
+ @update:modelValue="onRadioChange(item[$props.itemValue!])"
188
+ />
205
189
  </FSRow>
206
190
  </FSRow>
207
191
  </FSCol>
@@ -705,7 +689,7 @@ export default defineComponent({
705
689
  const maxHeight = computed(() => {
706
690
  const other = 8 + 8 // Paddings
707
691
  + (isMobileSized.value ? 36 : 40) + 8; // Header
708
- return `calc(100vh - 40px - ${other}px)`;
692
+ return `calc(100dvh - 40px - ${other}px)`;
709
693
  });
710
694
 
711
695
  const mobileValue = computed((): string | null => {