@dative-gpi/foundation-shared-components 0.0.88 → 0.0.89

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 (55) hide show
  1. package/components/FSButton.vue +23 -7
  2. package/components/FSCalendar.vue +3 -1
  3. package/components/FSCalendarTwin.vue +16 -6
  4. package/components/FSCard.vue +9 -3
  5. package/components/FSCheckbox.vue +6 -2
  6. package/components/FSClickable.vue +33 -9
  7. package/components/FSDialog.vue +9 -5
  8. package/components/FSDialogMenu.vue +80 -0
  9. package/components/FSDialogSubmit.vue +0 -1
  10. package/components/FSEditImage.vue +196 -34
  11. package/components/FSImage.vue +21 -7
  12. package/components/FSLink.vue +4 -2
  13. package/components/FSOptionGroup.vue +51 -69
  14. package/components/FSOptionItem.vue +15 -6
  15. package/components/FSRadioGroup.vue +11 -3
  16. package/components/FSToggleSet.vue +22 -60
  17. package/components/FSWindow.vue +2 -0
  18. package/components/autocompletes/FSAutocompleteLanguage.vue +28 -22
  19. package/components/autocompletes/FSAutocompleteTimeZone.vue +117 -17
  20. package/components/buttons/FSButtonFileMini.vue +6 -1
  21. package/components/fields/FSAutocompleteField.vue +139 -72
  22. package/components/fields/FSBaseField.vue +134 -0
  23. package/components/fields/FSColorField.vue +1 -1
  24. package/components/fields/FSDateField.vue +124 -35
  25. package/components/fields/FSDateTimeField.vue +171 -63
  26. package/components/fields/FSIconField.vue +4 -2
  27. package/components/fields/FSNumberField.vue +9 -3
  28. package/components/fields/FSPasswordField.vue +15 -5
  29. package/components/fields/FSRichTextField.vue +34 -18
  30. package/components/fields/FSSearchField.vue +24 -8
  31. package/components/fields/FSSelectField.vue +254 -93
  32. package/components/fields/FSTagField.vue +15 -9
  33. package/components/fields/FSTextArea.vue +31 -59
  34. package/components/fields/FSTextField.vue +22 -70
  35. package/components/fields/FSTimeField.vue +20 -55
  36. package/components/fields/FSTimeSlotField.vue +13 -59
  37. package/components/lists/FSDataIteratorItem.vue +16 -4
  38. package/components/lists/FSDataTableUI.vue +420 -184
  39. package/components/lists/FSDraggable.vue +26 -13
  40. package/components/lists/FSFilterButton.vue +10 -4
  41. package/components/lists/FSHeaderButton.vue +3 -1
  42. package/components/lists/FSHiddenButton.vue +3 -1
  43. package/composables/useAutocomplete.ts +6 -7
  44. package/composables/useSlots.ts +6 -18
  45. package/package.json +4 -4
  46. package/styles/components/fs_base_field.scss +12 -0
  47. package/styles/components/fs_dialog.scss +10 -2
  48. package/styles/components/fs_dialog_menu.scss +11 -0
  49. package/styles/components/fs_draggable.scss +12 -0
  50. package/styles/components/fs_edit_image.scss +29 -2
  51. package/styles/components/fs_text_area.scss +0 -13
  52. package/styles/components/fs_text_field.scss +1 -14
  53. package/styles/components/index.scss +2 -0
  54. package/styles/globals/overrides.scss +4 -0
  55. package/components/autocompletes/FSAutocompleteOrganisation.vue +0 -77
@@ -1,49 +1,149 @@
1
1
  <template>
2
2
  <FSAutocompleteField
3
- :loading="fetchingTimeZones"
3
+ :toggleSet="!$props.toggleSetDisabled && toggleSet"
4
+ :multiple="$props.multiple"
5
+ :loading="loading"
4
6
  :items="timeZones"
5
- v-model:search="search"
7
+ :modelValue="$props.modelValue"
8
+ @update:modelValue="onUpdate"
6
9
  v-bind="$attrs"
7
- />
10
+ >
11
+ <template
12
+ #autocomplete-selection="{ item }"
13
+ >
14
+ <FSRow
15
+ v-if="$props.modelValue"
16
+ align="center-center"
17
+ :wrap="false"
18
+ >
19
+ <FSChip
20
+ :label="item.raw.offset"
21
+ />
22
+ <FSSpan>
23
+ {{ item.raw.id }}
24
+ </FSSpan>
25
+ </FSRow>
26
+ </template>
27
+ <template
28
+ #autocomplete-item="{ props, item }"
29
+ >
30
+ <v-list-item
31
+ v-bind="{ ...props, title: '' }"
32
+ >
33
+ <FSRow
34
+ align="center-left"
35
+ >
36
+ <FSCheckbox
37
+ v-if="$props.multiple"
38
+ :modelValue="$props.modelValue?.includes(item.value)"
39
+ @click="props.onClick"
40
+ />
41
+ <FSChip
42
+ :label="item.raw.offset"
43
+ />
44
+ <FSSpan>
45
+ {{ item.raw.id }}
46
+ </FSSpan>
47
+ </FSRow>
48
+ </v-list-item>
49
+ </template>
50
+ <template
51
+ #toggle-set-item="props"
52
+ >
53
+ <FSButton
54
+ :variant="props.getVariant(props.item)"
55
+ :color="props.getColor(props.item)"
56
+ :class="props.getClass(props.item)"
57
+ :label="props.item.id"
58
+ @click="props.toggle(props.item)"
59
+ >
60
+ <template
61
+ #prepend
62
+ >
63
+ <FSChip
64
+ :label="props.item.offset.split(':')[0]"
65
+ />
66
+ </template>
67
+ </FSButton>
68
+ </template>
69
+ </FSAutocompleteField>
8
70
  </template>
9
71
 
10
72
  <script lang="ts">
11
- import { defineComponent, PropType, ref, watch } from "vue";
12
- import _ from "lodash";
73
+ import { computed, defineComponent, PropType } from "vue";
13
74
 
75
+ import { TimeZoneFilters, TimeZoneInfos } from "@dative-gpi/foundation-shared-domain/models";
76
+ import { useAutocomplete } from "@dative-gpi/foundation-shared-components/composables";
14
77
  import { useTimeZones } from "@dative-gpi/foundation-shared-services/composables";
15
- import { TimeZoneFilters } from "@dative-gpi/foundation-shared-domain/models";
16
78
 
17
79
  import FSAutocompleteField from "../fields/FSAutocompleteField.vue";
80
+ import FSCheckbox from "../FSCheckbox.vue"
81
+ import FSButton from "../FSButton.vue";
82
+ import FSChip from "../FSChip.vue";
83
+ import FSSpan from "../FSSpan.vue";
84
+ import FSRow from "../FSRow.vue";
18
85
 
19
86
  export default defineComponent({
20
87
  name: "FSAutocompleteTimeZone",
21
88
  components: {
22
- FSAutocompleteField
89
+ FSAutocompleteField,
90
+ FSCheckbox,
91
+ FSButton,
92
+ FSChip,
93
+ FSSpan,
94
+ FSRow
23
95
  },
24
96
  props: {
25
97
  timeZoneFilters: {
26
98
  type: Object as PropType<TimeZoneFilters>,
27
99
  required: false,
28
100
  default: null
101
+ },
102
+ modelValue: {
103
+ type: [Array, String] as PropType<string[] | string | null>,
104
+ required: false,
105
+ default: null
106
+ },
107
+ multiple: {
108
+ type: Boolean,
109
+ required: false,
110
+ default: false
111
+ },
112
+ toggleSetDisabled: {
113
+ type: Boolean,
114
+ required: false,
115
+ default: false
29
116
  }
30
117
  },
31
- setup(props) {
118
+ emits: ["update:modelValue"],
119
+ setup(props, { emit }) {
32
120
  const { getMany: getManyTimeZones, fetching: fetchingTimeZones, entities: timeZones } = useTimeZones();
33
121
 
34
- const search = ref<string | null>(null);
122
+ const loading = computed((): boolean => {
123
+ return init.value && fetchingTimeZones.value;
124
+ });
35
125
 
36
- watch([() => props.timeZoneFilters, () => search.value], async (newValue, oldValue) => {
37
- if (!_.isEqual(newValue, oldValue)) {
38
- await getManyTimeZones({ ...props.timeZoneFilters, search: search.value ?? undefined });
39
- }
40
- }, { immediate: true });
126
+ const innerFetch = (search: string | null) => {
127
+ return getManyTimeZones({ ...props.timeZoneFilters, search: search ?? undefined });
128
+ };
129
+
130
+ const { toggleSet, search, init, onUpdate } = useAutocomplete(
131
+ timeZones,
132
+ [() => props.timeZoneFilters],
133
+ emit,
134
+ innerFetch,
135
+ null,
136
+ (item: TimeZoneInfos) => item.id,
137
+ (item: TimeZoneInfos) => item.id
138
+ );
41
139
 
42
140
  return {
43
- fetchingTimeZones,
44
141
  timeZones,
45
- search
46
- }
142
+ toggleSet,
143
+ loading,
144
+ search,
145
+ onUpdate
146
+ };
47
147
  }
48
148
  });
49
149
  </script>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div>
3
3
  <FSButton
4
- prependIcon="mdi-upload-outline"
4
+ :prependIcon="$props.icon"
5
5
  :color="ColorEnum.Light"
6
6
  @click="onClick"
7
7
  v-bind="$attrs"
@@ -41,6 +41,11 @@ export default defineComponent({
41
41
  type: Boolean,
42
42
  required: false,
43
43
  default: true
44
+ },
45
+ icon: {
46
+ type: String,
47
+ required: false,
48
+ default: "mdi-upload-outline"
44
49
  }
45
50
  },
46
51
  emits: ["update:modelValue"],
@@ -1,44 +1,42 @@
1
1
  <template>
2
- <FSCol>
3
- <slot v-if="!$props.hideHeader"
4
- name="label">
5
- <FSRow :wrap="false">
6
- <FSSpan v-if="$props.label"
7
- class="fs-autocomplete-field-label"
8
- font="text-overline"
9
- :style="style">
10
- {{ $props.label }}
11
- </FSSpan>
12
- <FSSpan v-if="$props.label && $props.required"
13
- class="fs-autocomplete-field-label"
14
- style="margin-left: -8px;"
15
- font="text-overline"
16
- :ellipsis="false"
17
- :style="style">
18
- *
19
- </FSSpan>
20
- <v-spacer style="min-width: 40px;" />
21
- <FSSpan v-if="messages.length > 0"
22
- class="fs-autocomplete-field-messages"
23
- font="text-overline"
24
- :style="style">
25
- {{ messages.join(", ") }}
26
- </FSSpan>
27
- </FSRow>
28
- </slot>
29
- <FSLoader v-if="$props.loading"
2
+ <FSBaseField
3
+ :label="$props.label"
4
+ :description="$props.description"
5
+ :hideHeader="$props.hideHeader"
6
+ :required="$props.required"
7
+ :editable="$props.editable"
8
+ :messages="messages"
9
+ >
10
+ <FSLoader
11
+ v-if="$props.loading"
30
12
  width="100%"
31
- :height="['40px', '36px']" />
32
- <template v-else>
33
- <FSToggleSet v-if="$props.toggleSet"
13
+ :height="['40px', '36px']"
14
+ />
15
+ <template
16
+ v-else
17
+ >
18
+ <FSToggleSet
19
+ v-if="$props.toggleSet"
34
20
  variant="slide"
35
- :multiple="$props.multiple"
36
21
  :values="$props.items"
22
+ :multiple="$props.multiple"
37
23
  :rules="$props.rules"
38
24
  :modelValue="$props.modelValue"
39
25
  @update:modelValue="onUpdate"
40
- v-bind="$attrs" />
41
- <v-autocomplete v-else
26
+ v-bind="$attrs"
27
+ >
28
+ <template
29
+ v-for="(_, name) in toggleSetSlots"
30
+ v-slot:[name]="slotData"
31
+ >
32
+ <slot
33
+ :name="`toggle-set-${name}`"
34
+ v-bind="slotData"
35
+ />
36
+ </template>
37
+ </FSToggleSet>
38
+ <v-autocomplete
39
+ v-else
42
40
  class="fs-autocomplete-field"
43
41
  variant="outlined"
44
42
  :menuIcon="null"
@@ -53,7 +51,7 @@
53
51
  :itemValue="$props.itemValue"
54
52
  :readonly="!$props.editable"
55
53
  :loading="$props.loading"
56
- :clearable="$props.editable && !!$props.modelValue"
54
+ :clearable="$props.clearable && $props.editable && !!$props.modelValue"
57
55
  :returnObject="$props.returnObject"
58
56
  :rules="$props.rules"
59
57
  :validateOn="validateOn"
@@ -61,40 +59,81 @@
61
59
  @update:modelValue="onUpdate"
62
60
  @blur="blurred = true"
63
61
  v-model:search="innerSearch"
64
- v-bind="$attrs">
65
- <template v-for="(_, name) in slots"
66
- v-slot:[name]="slotData">
67
- <slot :name="name"
68
- v-bind="slotData" />
62
+ v-bind="$attrs"
63
+ >
64
+ <template
65
+ #item="{ props, item }"
66
+ >
67
+ <v-list-item
68
+ v-bind="{ ...props, title: '' }"
69
+ >
70
+ <FSRow
71
+ align="center-left"
72
+ :wrap="false"
73
+ >
74
+ <FSCheckbox
75
+ v-if="$props.multiple"
76
+ :modelValue="$props.modelValue?.includes(item.raw[$props.itemValue])"
77
+ @click="test(props, item)"
78
+ />
79
+ <FSSpan>
80
+ {{ item.raw[$props.itemTitle] }}
81
+ </FSSpan>
82
+ </FSRow>
83
+ </v-list-item>
69
84
  </template>
70
- <template #clear>
71
- <slot name="clear">
72
- <FSButton v-if="$props.editable && $props.modelValue"
85
+ <template
86
+ v-for="(_, name) in autocompleteSlots"
87
+ v-slot:[name]="slotData"
88
+ >
89
+ <slot
90
+ :name="`autocomplete-${name}`"
91
+ v-bind="slotData"
92
+ />
93
+ </template>
94
+ <template
95
+ #clear
96
+ >
97
+ <slot
98
+ name="clear"
99
+ >
100
+ <FSButton
101
+ v-if="$props.clearable && $props.editable && !!$props.modelValue"
73
102
  icon="mdi-close"
74
103
  variant="icon"
75
104
  :color="ColorEnum.Dark"
76
- @click="$emit('update:modelValue', null)" />
105
+ @click="$emit('update:modelValue', null)"
106
+ />
77
107
  </slot>
78
108
  </template>
79
- <template #append-inner>
80
- <slot name="append-inner">
81
- <FSButton icon="mdi-chevron-down"
109
+ <template
110
+ #append-inner
111
+ >
112
+ <slot
113
+ name="append-inner"
114
+ >
115
+ <FSButton
116
+ icon="mdi-chevron-down"
82
117
  variant="icon"
83
118
  :editable="$props.editable"
84
- :color="ColorEnum.Dark" />
119
+ :color="ColorEnum.Dark"
120
+ />
85
121
  </slot>
86
122
  </template>
123
+ <template
124
+ #no-data
125
+ >
126
+ <FSRow
127
+ padding="17px"
128
+ >
129
+ <FSSpan>
130
+ {{ $tr("ui.common.no-data", "No data") }}
131
+ </FSSpan>
132
+ </FSRow>
133
+ </template>
87
134
  </v-autocomplete>
88
135
  </template>
89
- <slot name="description">
90
- <FSSpan v-if="$props.description"
91
- class="fs-autocomplete-field-description"
92
- font="text-underline"
93
- :style="style">
94
- {{ $props.description }}
95
- </FSSpan>
96
- </slot>
97
- </FSCol>
136
+ </FSBaseField>
98
137
  </template>
99
138
 
100
139
  <script lang="ts">
@@ -103,22 +142,24 @@ import { computed, defineComponent, PropType, ref, watch } from "vue";
103
142
  import { useColors, useRules, useSlots } from "@dative-gpi/foundation-shared-components/composables";
104
143
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
105
144
 
145
+ import FSToggleSet from "../FSToggleSet.vue";
146
+ import FSBaseField from "./FSBaseField.vue";
147
+ import FSCheckbox from "../FSCheckbox.vue";
106
148
  import FSButton from "../FSButton.vue";
149
+ import FSLoader from "../FSLoader.vue";
107
150
  import FSSpan from "../FSSpan.vue";
108
- import FSCol from "../FSCol.vue";
109
151
  import FSRow from "../FSRow.vue";
110
- import FSLoader from "../FSLoader.vue";
111
- import FSToggleSet from "../FSToggleSet.vue";
112
152
 
113
153
  export default defineComponent({
114
154
  name: "FSAutocompleteField",
115
155
  components: {
116
156
  FSToggleSet,
157
+ FSBaseField,
158
+ FSCheckbox,
117
159
  FSButton,
118
160
  FSLoader,
119
161
  FSSpan,
120
- FSCol,
121
- FSRow,
162
+ FSRow
122
163
  },
123
164
  props: {
124
165
  label: {
@@ -180,6 +221,11 @@ export default defineComponent({
180
221
  required: false,
181
222
  default: null
182
223
  },
224
+ clearable: {
225
+ type: Boolean,
226
+ required: false,
227
+ default: true
228
+ },
183
229
  editable: {
184
230
  type: Boolean,
185
231
  required: false,
@@ -215,23 +261,37 @@ export default defineComponent({
215
261
  const style = computed((): { [key: string]: string | undefined } => {
216
262
  if (!props.editable) {
217
263
  return {
218
- "--fs-autocomplete-field-cursor": "default",
219
- "--fs-autocomplete-field-border-color": lights.base,
220
- "--fs-autocomplete-field-color": lights.dark,
264
+ "--fs-autocomplete-field-cursor": "default",
265
+ "--fs-autocomplete-field-border-color": lights.base,
266
+ "--fs-autocomplete-field-color": lights.dark,
221
267
  "--fs-autocomplete-field-active-border-color": lights.base
222
268
  };
223
269
  }
224
270
  return {
225
- "--fs-autocomplete-field-cursor": "text",
226
- "--fs-autocomplete-field-background-color": backgrounds.base,
227
- "--fs-autocomplete-field-border-color": lights.dark,
228
- "--fs-autocomplete-field-color": darks.base,
271
+ "--fs-autocomplete-field-cursor": "text",
272
+ "--fs-autocomplete-field-background-color": backgrounds.base,
273
+ "--fs-autocomplete-field-border-color": lights.dark,
274
+ "--fs-autocomplete-field-color": darks.base,
229
275
  "--fs-autocomplete-field-active-border-color": darks.dark,
230
- "--fs-autocomplete-field-error-color": errors.base,
231
- "--fs-autocomplete-field-error-border-color": errors.base
276
+ "--fs-autocomplete-field-error-color": errors.base,
277
+ "--fs-autocomplete-field-error-border-color": errors.base
232
278
  };
233
279
  });
234
280
 
281
+ const autocompleteSlots = computed((): any => {
282
+ return Object.keys(slots).filter(k => k.startsWith("autocomplete-")).reduce((acc, key) => {
283
+ acc[key.substring("autocomplete-".length)] = slots[key];
284
+ return acc;
285
+ }, {});
286
+ });
287
+
288
+ const toggleSetSlots = computed((): any => {
289
+ return Object.keys(slots).filter(k => k.startsWith("toggle-set-")).reduce((acc, key) => {
290
+ acc[key.substring("toggle-set-".length)] = slots[key];
291
+ return acc;
292
+ }, {});
293
+ });
294
+
235
295
  const listStyle = computed((): any => {
236
296
  return {
237
297
  style: style.value
@@ -252,11 +312,17 @@ export default defineComponent({
252
312
  emit('update:modelValue', value);
253
313
  };
254
314
 
315
+ const test = (props: any, item: any) => {
316
+ console.log(props, item);
317
+ };
318
+
255
319
  watch(innerSearch, () => {
256
320
  emit("update:search", innerSearch.value);
257
321
  });
258
322
 
259
323
  return {
324
+ autocompleteSlots,
325
+ toggleSetSlots,
260
326
  innerSearch,
261
327
  validateOn,
262
328
  ColorEnum,
@@ -266,7 +332,8 @@ export default defineComponent({
266
332
  classes,
267
333
  slots,
268
334
  style,
269
- onUpdate
335
+ onUpdate,
336
+ test
270
337
  };
271
338
  }
272
339
  });
@@ -0,0 +1,134 @@
1
+ <template>
2
+ <FSCol>
3
+ <slot
4
+ v-if="!$props.hideHeader"
5
+ name="label"
6
+ >
7
+ <FSRow
8
+ :wrap="false"
9
+ >
10
+ <FSSpan
11
+ class="fs-base-field-label"
12
+ font="text-overline"
13
+ :style="style"
14
+ >
15
+ {{ $props.label }}
16
+ </FSSpan>
17
+ <FSSpan
18
+ v-if="$props.label && $props.required"
19
+ class="fs-base-field-label"
20
+ style="margin-left: -8px;"
21
+ font="text-overline"
22
+ :ellipsis="false"
23
+ :style="style"
24
+ >
25
+ *
26
+ </FSSpan>
27
+ <v-spacer
28
+ style="min-width: 40px;"
29
+ />
30
+ <FSSpan
31
+ v-if="$props.messages.length > 0"
32
+ class="fs-base-field-messages"
33
+ font="text-overline"
34
+ :style="style"
35
+ >
36
+ {{ $props.messages.join(", ") }}
37
+ </FSSpan>
38
+ </FSRow>
39
+ </slot>
40
+ <slot />
41
+ <slot
42
+ name="description"
43
+ >
44
+ <FSSpan
45
+ v-if="$props.description"
46
+ class="fs-base-field-description"
47
+ font="text-underline"
48
+ :style="style"
49
+ >
50
+ {{ $props.description }}
51
+ </FSSpan>
52
+ </slot>
53
+ </FSCol>
54
+ </template>
55
+
56
+ <script lang="ts">
57
+ import { computed, defineComponent, PropType } from "vue";
58
+
59
+ import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
60
+ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
61
+
62
+ import FSSpan from "../FSSpan.vue";
63
+ import FSCol from "../FSCol.vue";
64
+ import FSRow from "../FSRow.vue";
65
+
66
+ export default defineComponent({
67
+ name: "FSBaseField",
68
+ components: {
69
+ FSSpan,
70
+ FSCol,
71
+ FSRow
72
+ },
73
+ props: {
74
+ label: {
75
+ type: String as PropType<string | null>,
76
+ required: false,
77
+ default: null
78
+ },
79
+ description: {
80
+ type: String as PropType<string | null>,
81
+ required: false,
82
+ default: null
83
+ },
84
+ hideHeader: {
85
+ type: Boolean,
86
+ required: false,
87
+ default: false
88
+ },
89
+ required: {
90
+ type: Boolean,
91
+ required: false,
92
+ default: false
93
+ },
94
+ messages: {
95
+ type: Array,
96
+ required: false,
97
+ default: () => []
98
+ },
99
+ editable: {
100
+ type: Boolean,
101
+ required: false,
102
+ default: true
103
+ }
104
+ },
105
+ setup(props) {
106
+ const { getColors } = useColors();
107
+ const { slots } = useSlots();
108
+
109
+ delete slots.label;
110
+ delete slots.description;
111
+
112
+ const errors = getColors(ColorEnum.Error);
113
+ const lights = getColors(ColorEnum.Light);
114
+ const darks = getColors(ColorEnum.Dark);
115
+
116
+ const style = computed((): { [key: string] : string | undefined } => {
117
+ if (!props.editable) {
118
+ return {
119
+ "--fs-base-field-color": lights.dark
120
+ };
121
+ }
122
+ return {
123
+ "--fs-base-field-color" : darks.base,
124
+ "--fs-base-field-error-color": errors.base
125
+ };
126
+ });
127
+
128
+ return {
129
+ style,
130
+ slots
131
+ };
132
+ }
133
+ });
134
+ </script>
@@ -2,7 +2,7 @@
2
2
  <v-menu
3
3
  :closeOnContentClick="false"
4
4
  :modelValue="menu && $props.editable"
5
- @update:modelValue="(value) => menu = value"
5
+ @update:modelValue="menu = $event"
6
6
  >
7
7
  <template
8
8
  #activator="{ props }"