@dative-gpi/foundation-shared-components 0.0.87 → 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 +61 -72
  14. package/components/FSOptionItem.vue +22 -7
  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 +433 -181
  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,102 +1,194 @@
1
1
  <template>
2
2
  <FSCol>
3
- <slot v-if="!$props.hideHeader" name="label">
4
- <FSRow
5
- :wrap="false"
3
+ <template
4
+ v-if="isExtraSmall"
5
+ >
6
+ <FSTextField
7
+ :label="$props.label"
8
+ :description="$props.description"
9
+ :hideHeader="$props.hideHeader"
10
+ :required="$props.required"
11
+ :clearable="$props.clearable"
12
+ :editable="$props.editable"
13
+ :readonly="true"
14
+ :rules="$props.rules"
15
+ :messages="messages"
16
+ :validateOn="validateOn"
17
+ :validationValue="$props.modelValue"
18
+ :modelValue="mobileValue"
19
+ @update:modelValue="$emit('update:modelValue', $event)"
20
+ @click="openMobileOverlay"
21
+ @blur="blurred = true"
22
+ v-bind="$attrs"
6
23
  >
7
- <FSSpan
8
- v-if="$props.label"
9
- class="fs-select-field-label"
10
- font="text-overline"
11
- :style="style"
24
+ <template
25
+ v-for="(_, name) in $slots"
26
+ v-slot:[name]="slotData"
12
27
  >
13
- {{ $props.label }}
14
- </FSSpan>
15
- <FSSpan
16
- v-if="$props.label && $props.required"
17
- class="fs-select-field-label"
18
- style="margin-left: -8px;"
19
- font="text-overline"
20
- :ellipsis="false"
21
- :style="style"
28
+ <slot
29
+ :name="name"
30
+ v-bind="slotData"
31
+ />
32
+ </template>
33
+ <template
34
+ #append-inner
22
35
  >
23
- *
24
- </FSSpan>
25
- <v-spacer style="min-width: 40px;" />
26
- <FSSpan
27
- v-if="messages.length > 0"
28
- class="fs-select-field-messages"
29
- font="text-overline"
30
- :style="style"
36
+ <slot
37
+ name="append-inner"
38
+ >
39
+ <FSButton
40
+ icon="mdi-chevron-down"
41
+ variant="icon"
42
+ :editable="$props.editable"
43
+ :color="ColorEnum.Dark"
44
+ @click="openMobileOverlay"
45
+ />
46
+ </slot>
47
+ </template>
48
+ </FSTextField>
49
+ <FSDialogMenu
50
+ v-model="dialog"
51
+ >
52
+ <template
53
+ #body
31
54
  >
32
- {{ messages.join(", ") }}
33
- </FSSpan>
34
- </FSRow>
35
- </slot>
36
- <v-select
37
- class="fs-select-field"
38
- variant="outlined"
39
- :menuIcon="null"
40
- :style="style"
41
- :listProps="listStyle"
42
- :hideDetails="true"
43
- :items="$props.items"
44
- :itemTitle="$props.itemTitle"
45
- :itemValue="$props.itemValue"
46
- :readonly="!$props.editable"
47
- :clearable="$props.editable && !!$props.modelValue"
48
- :returnObject="$props.returnObject"
49
- :rules="$props.rules"
50
- :validateOn="validateOn"
51
- :modelValue="$props.modelValue"
52
- @update:modelValue="(value) => $emit('update:modelValue', value)"
53
- @blur="blurred = true"
54
- v-bind="$attrs"
55
+ <FSFadeOut
56
+ height="calc(90vh - 164px)"
57
+ >
58
+ <FSCol
59
+ v-if="$props.multiple"
60
+ gap="12px"
61
+ >
62
+ <FSRow
63
+ v-for="(item, index) in $props.items"
64
+ :key="index"
65
+ >
66
+ <FSCheckbox
67
+ :label="item[$props.itemTitle]"
68
+ :editable="$props.editable"
69
+ :modelValue="$props.modelValue?.includes(item[$props.itemValue])"
70
+ @update:modelValue="() => onCheckboxChange(item[$props.itemValue])"
71
+ />
72
+ </FSRow>
73
+ </FSCol>
74
+ <FSRadioGroup
75
+ v-else
76
+ gap="12px"
77
+ :values="$props.items.map((item: any) => ({ value: item[$props.itemValue], label: item[$props.itemTitle] }))"
78
+ :modelValue="$props.modelValue"
79
+ :editable="$props.editable"
80
+ @update:modelValue="onRadioChange"
81
+ />
82
+ </FSFadeOut>
83
+ </template>
84
+ </FSDialogMenu>
85
+ </template>
86
+ <template
87
+ v-else
55
88
  >
56
- <template v-for="(_, name) in slots" v-slot:[name]="slotData">
57
- <slot :name="name" v-bind="slotData" />
58
- </template>
59
- <template #clear>
60
- <slot name="clear">
61
- <FSButton
62
- v-if="$props.editable && $props.modelValue"
63
- icon="mdi-close"
64
- variant="icon"
65
- :color="ColorEnum.Dark"
66
- @click="$emit('update:modelValue', null)"
67
- />
68
- </slot>
69
- </template>
70
- <template #append-inner>
71
- <slot name="append-inner">
72
- <FSButton
73
- icon="mdi-chevron-down"
74
- variant="icon"
75
- :editable="$props.editable"
76
- :color="ColorEnum.Dark"
77
- />
78
- </slot>
79
- </template>
80
- </v-select>
81
- <slot name="description">
82
- <FSSpan
83
- v-if="$props.description"
84
- class="fs-select-field-description"
85
- font="text-underline"
86
- :style="style"
89
+ <FSBaseField
90
+ :label="$props.label"
91
+ :description="$props.description"
92
+ :hideHeader="$props.hideHeader"
93
+ :required="$props.required"
94
+ :editable="$props.editable"
95
+ :messages="messages"
87
96
  >
88
- {{ $props.description }}
89
- </FSSpan>
90
- </slot>
97
+ <v-select
98
+ class="fs-select-field"
99
+ variant="outlined"
100
+ :menuIcon="null"
101
+ :style="style"
102
+ :listProps="listStyle"
103
+ :hideDetails="true"
104
+ :items="$props.items"
105
+ :itemTitle="$props.itemTitle"
106
+ :itemValue="$props.itemValue"
107
+ :readonly="!$props.editable"
108
+ :clearable="$props.clearable && $props.editable && !!$props.modelValue"
109
+ :returnObject="$props.returnObject"
110
+ :rules="$props.rules"
111
+ :validateOn="validateOn"
112
+ :multiple="$props.multiple"
113
+ :modelValue="$props.modelValue"
114
+ @update:modelValue="$emit('update:modelValue', $event)"
115
+ @blur="blurred = true"
116
+ v-bind="$attrs"
117
+ >
118
+ <template
119
+ #item="{ props, item }"
120
+ >
121
+ <v-list-item
122
+ v-bind="{ ...props, title: '' }"
123
+ >
124
+ <FSRow
125
+ align="center-left"
126
+ >
127
+ <FSCheckbox
128
+ v-if="$props.multiple"
129
+ :modelValue="$props.modelValue?.includes(item.raw.id)"
130
+ />
131
+ <FSSpan>
132
+ {{ item.raw.label }}
133
+ </FSSpan>
134
+ </FSRow>
135
+ </v-list-item>
136
+ </template>
137
+ <template
138
+ v-for="(_, name) in $slots"
139
+ v-slot:[name]="slotData"
140
+ >
141
+ <slot
142
+ :name="name"
143
+ v-bind="slotData"
144
+ />
145
+ </template>
146
+ <template
147
+ #clear
148
+ >
149
+ <slot
150
+ name="clear"
151
+ >
152
+ <FSButton
153
+ v-if="$props.clearable && $props.editable && !!$props.modelValue"
154
+ icon="mdi-close"
155
+ variant="icon"
156
+ :color="ColorEnum.Dark"
157
+ @click="$emit('update:modelValue', null)"
158
+ />
159
+ </slot>
160
+ </template>
161
+ <template
162
+ #append-inner
163
+ >
164
+ <slot
165
+ name="append-inner"
166
+ >
167
+ <FSButton
168
+ icon="mdi-chevron-down"
169
+ variant="icon"
170
+ :editable="$props.editable"
171
+ :color="ColorEnum.Dark"
172
+ />
173
+ </slot>
174
+ </template>
175
+ </v-select>
176
+ </FSBaseField>
177
+ </template>
91
178
  </FSCol>
92
179
  </template>
93
180
 
94
181
  <script lang="ts">
95
- import { computed, defineComponent, PropType } from "vue";
182
+ import { computed, defineComponent, PropType, ref } from "vue";
96
183
 
97
- import { useColors, useRules, useSlots } from "@dative-gpi/foundation-shared-components/composables";
184
+ import { useBreakpoints, useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
98
185
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
99
186
 
187
+ import FSDialogMenu from "../FSDialogMenu.vue";
188
+ import FSRadioGroup from "../FSRadioGroup.vue";
189
+ import FSBaseField from "./FSBaseField.vue";
190
+ import FSCheckbox from "../FSCheckbox.vue";
191
+ import FSFadeOut from "../FSFadeOut.vue";
100
192
  import FSButton from "../FSButton.vue";
101
193
  import FSSpan from "../FSSpan.vue";
102
194
  import FSCol from "../FSCol.vue";
@@ -105,6 +197,11 @@ import FSRow from "../FSRow.vue";
105
197
  export default defineComponent({
106
198
  name: "FSSelectField",
107
199
  components: {
200
+ FSDialogMenu,
201
+ FSRadioGroup,
202
+ FSBaseField,
203
+ FSCheckbox,
204
+ FSFadeOut,
108
205
  FSButton,
109
206
  FSSpan,
110
207
  FSCol,
@@ -155,6 +252,11 @@ export default defineComponent({
155
252
  required: false,
156
253
  default: false
157
254
  },
255
+ multiple: {
256
+ type: Boolean,
257
+ required: false,
258
+ default: false
259
+ },
158
260
  rules: {
159
261
  type: Array as PropType<any[]>,
160
262
  required: false,
@@ -165,6 +267,11 @@ export default defineComponent({
165
267
  required: false,
166
268
  default: null
167
269
  },
270
+ clearable: {
271
+ type: Boolean,
272
+ required: false,
273
+ default: true
274
+ },
168
275
  editable: {
169
276
  type: Boolean,
170
277
  required: false,
@@ -172,13 +279,12 @@ export default defineComponent({
172
279
  }
173
280
  },
174
281
  emits: ["update:modelValue"],
175
- setup(props) {
282
+ setup(props, { emit }) {
176
283
  const { validateOn, blurred, getMessages } = useRules();
284
+ const { isExtraSmall } = useBreakpoints();
177
285
  const { getColors } = useColors();
178
- const { slots } = useSlots();
179
-
180
- delete slots.label;
181
- delete slots.description;
286
+
287
+ const dialog = ref(false);
182
288
 
183
289
  const backgrounds = getColors(ColorEnum.Background);
184
290
  const errors = getColors(ColorEnum.Error);
@@ -200,12 +306,11 @@ export default defineComponent({
200
306
  "--fs-select-field-border-color" : lights.dark,
201
307
  "--fs-select-field-color" : darks.base,
202
308
  "--fs-select-field-active-border-color": darks.dark,
203
- "--fs-select-field-error-color" : errors.base,
204
309
  "--fs-select-field-error-border-color" : errors.base
205
310
  };
206
311
  });
207
312
 
208
- const listStyle = computed((): any => {
313
+ const listStyle = computed((): { [key: string] : Object } => {
209
314
  return {
210
315
  style: style.value
211
316
  };
@@ -213,14 +318,70 @@ export default defineComponent({
213
318
 
214
319
  const messages = computed((): string[] => props.messages ?? getMessages(props.modelValue, props.rules));
215
320
 
321
+ const mobileValue = computed((): string | null => {
322
+ if (props.multiple) {
323
+ if (Array.isArray(props.modelValue)) {
324
+ return props.modelValue.map((value: any) => {
325
+ const item = props.items.find((item: Object) => item[props.itemValue] === value);
326
+ if (item) {
327
+ return item[props.itemTitle];
328
+ }
329
+ }).filter(value => !!value).join(", ");
330
+ }
331
+ }
332
+ if (props.modelValue) {
333
+ const item = props.items.find((item: Object) => item[props.itemValue] === props.modelValue);
334
+ if (item) {
335
+ return item[props.itemTitle];
336
+ }
337
+ }
338
+ return null;
339
+ });
340
+
341
+ const openMobileOverlay = () => {
342
+ if (!props.editable) {
343
+ return;
344
+ }
345
+ dialog.value = true;
346
+ };
347
+
348
+ const onRadioChange = (value: any) => {
349
+ emit('update:modelValue', value);
350
+ dialog.value = false;
351
+ };
352
+
353
+ const onCheckboxChange = (value: any) => {
354
+ if (Array.isArray(props.modelValue)) {
355
+ if (props.modelValue.includes(value)) {
356
+ emit('update:modelValue', props.modelValue.filter((item: any) => item !== value));
357
+ }
358
+ else {
359
+ emit('update:modelValue', [...props.modelValue, value]);
360
+ }
361
+ }
362
+ else {
363
+ if (props.modelValue === value) {
364
+ emit('update:modelValue', []);
365
+ }
366
+ else {
367
+ emit('update:modelValue', [props.modelValue, value]);
368
+ }
369
+ }
370
+ };
371
+
216
372
  return {
373
+ isExtraSmall,
374
+ mobileValue,
217
375
  validateOn,
218
376
  ColorEnum,
219
377
  listStyle,
220
378
  messages,
221
379
  blurred,
222
- slots,
223
- style
380
+ dialog,
381
+ style,
382
+ openMobileOverlay,
383
+ onCheckboxChange,
384
+ onRadioChange
224
385
  };
225
386
  }
226
387
  });
@@ -15,11 +15,21 @@
15
15
  v-model="innerValue"
16
16
  v-bind="$attrs"
17
17
  >
18
- <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
19
- <slot :name="name" v-bind="slotData" />
18
+ <template
19
+ v-for="(_, name) in $slots"
20
+ v-slot:[name]="slotData"
21
+ >
22
+ <slot
23
+ :name="name"
24
+ v-bind="slotData"
25
+ />
20
26
  </template>
21
- <template #append-inner>
22
- <slot name="append-inner">
27
+ <template
28
+ #append-inner
29
+ >
30
+ <slot
31
+ name="append-inner"
32
+ >
23
33
  <FSButton
24
34
  variant="icon"
25
35
  icon="mdi-tag-outline"
@@ -49,9 +59,7 @@ import { useColors, useRules } from "@dative-gpi/foundation-shared-components/co
49
59
  import FSTextField from "./FSTextField.vue";
50
60
  import FSTagGroup from "../FSTagGroup.vue";
51
61
  import FSButton from "../FSButton.vue";
52
- import FSSpan from "../FSSpan.vue";
53
62
  import FSCol from "../FSCol.vue";
54
- import FSRow from "../FSRow.vue";
55
63
 
56
64
  export default defineComponent({
57
65
  name: "FSTagField",
@@ -59,9 +67,7 @@ export default defineComponent({
59
67
  FSTextField,
60
68
  FSTagGroup,
61
69
  FSButton,
62
- FSSpan,
63
- FSCol,
64
- FSRow
70
+ FSCol
65
71
  },
66
72
  props: {
67
73
  label: {
@@ -1,38 +1,12 @@
1
1
  <template>
2
- <FSCol>
3
- <slot v-if="!$props.hideHeader" name="label">
4
- <FSRow
5
- :wrap="false"
6
- >
7
- <FSSpan
8
- v-if="$props.label"
9
- class="fs-text-area-label"
10
- font="text-overline"
11
- :style="style"
12
- >
13
- {{ $props.label }}
14
- </FSSpan>
15
- <FSSpan
16
- v-if="$props.label && $props.required"
17
- class="fs-text-area-label"
18
- style="margin-left: -8px;"
19
- font="text-overline"
20
- :ellipsis="false"
21
- :style="style"
22
- >
23
- *
24
- </FSSpan>
25
- <v-spacer style="min-width: 40px;" />
26
- <FSSpan
27
- v-if="messages.length > 0"
28
- class="fs-text-area-messages"
29
- font="text-overline"
30
- :style="style"
31
- >
32
- {{ messages.join(", ") }}
33
- </FSSpan>
34
- </FSRow>
35
- </slot>
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
+ >
36
10
  <v-textarea
37
11
  class="fs-text-area"
38
12
  variant="outlined"
@@ -43,20 +17,28 @@
43
17
  :noResize="!$props.resize"
44
18
  :autoGrow="$props.autoGrow"
45
19
  :readonly="!$props.editable"
46
- :clearable="$props.editable && !!$props.modelValue"
20
+ :clearable="$props.clearable && $props.editable && !!$props.modelValue"
47
21
  :rules="$props.rules"
48
22
  :validateOn="validateOn"
49
23
  :modelValue="$props.modelValue"
50
- @update:modelValue="(value) => $emit('update:modelValue', value)"
24
+ @update:modelValue="$emit('update:modelValue', $event)"
51
25
  @blur="blurred = true"
52
26
  v-bind="$attrs"
53
27
  >
54
- <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
55
- <slot :name="name" v-bind="slotData" />
28
+ <template
29
+ v-for="(_, name) in $slots"
30
+ v-slot:[name]="slotData"
31
+ >
32
+ <slot
33
+ :name="name"
34
+ v-bind="slotData"
35
+ />
56
36
  </template>
57
- <template #clear>
37
+ <template
38
+ #clear
39
+ >
58
40
  <FSButton
59
- v-if="$props.editable && $props.modelValue"
41
+ v-if="$props.clearable && $props.editable && !!$props.modelValue"
60
42
  icon="mdi-close"
61
43
  variant="icon"
62
44
  :color="ColorEnum.Dark"
@@ -64,17 +46,7 @@
64
46
  />
65
47
  </template>
66
48
  </v-textarea>
67
- <slot name="description">
68
- <FSSpan
69
- v-if="$props.description"
70
- class="fs-text-area-description"
71
- font="text-underline"
72
- :style="style"
73
- >
74
- {{ $props.description }}
75
- </FSSpan>
76
- </slot>
77
- </FSCol>
49
+ </FSBaseField>
78
50
  </template>
79
51
 
80
52
  <script lang="ts">
@@ -83,16 +55,12 @@ import { computed, defineComponent, PropType } from "vue";
83
55
  import { useColors, useBreakpoints, useRules } from "@dative-gpi/foundation-shared-components/composables";
84
56
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
85
57
 
86
- import FSSpan from "../FSSpan.vue";
87
- import FSCol from "../FSCol.vue";
88
- import FSRow from "../FSRow.vue";
58
+ import FSBaseField from "./FSBaseField.vue";
89
59
 
90
60
  export default defineComponent({
91
61
  name: "FSTextArea",
92
62
  components: {
93
- FSSpan,
94
- FSCol,
95
- FSRow
63
+ FSBaseField
96
64
  },
97
65
  props: {
98
66
  label: {
@@ -145,6 +113,11 @@ export default defineComponent({
145
113
  required: false,
146
114
  default: null
147
115
  },
116
+ clearable: {
117
+ type: Boolean,
118
+ required: false,
119
+ default: true
120
+ },
148
121
  editable: {
149
122
  type: Boolean,
150
123
  required: false,
@@ -165,7 +138,7 @@ export default defineComponent({
165
138
  let height: string | undefined = undefined;
166
139
  let minHeight: string | undefined = undefined;
167
140
  if (!props.autoGrow) {
168
- const base = isMobileSized.value ? 30 : 42;
141
+ const base = isMobileSized.value ? 30 : 34;
169
142
  const row = isMobileSized.value ? 16 : 20;
170
143
  minHeight = `${base}px`;
171
144
  if (props.rows > 1) {
@@ -190,7 +163,6 @@ export default defineComponent({
190
163
  "--fs-text-area-border-color" : lights.dark,
191
164
  "--fs-text-area-color" : darks.base,
192
165
  "--fs-text-area-active-border-color": darks.dark,
193
- "--fs-text-area-error-color" : errors.base,
194
166
  "--fs-text-area-error-border-color" : errors.base,
195
167
  "--fs-text-area-min-height" : minHeight,
196
168
  "--fs-text-area-height" : height