@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,8 +1,14 @@
1
1
  <template>
2
2
  <FSCol>
3
- <FSRow v-if="!readonly">
4
- <slot name="label">
5
- <FSRow :wrap="false">
3
+ <FSRow
4
+ v-if="!readonly"
5
+ >
6
+ <slot
7
+ name="label"
8
+ >
9
+ <FSRow
10
+ :wrap="false"
11
+ >
6
12
  <FSSpan
7
13
  v-if="$props.label"
8
14
  class="fs-rich-text-field-label"
@@ -24,7 +30,9 @@
24
30
  </FSRow>
25
31
  </slot>
26
32
  <v-spacer />
27
- <template v-if="$props.editable">
33
+ <template
34
+ v-if="$props.editable"
35
+ >
28
36
  <FSIcon
29
37
  class="fs-rich-text-field-icon"
30
38
  :color="toolbarColors.undo"
@@ -33,7 +41,9 @@
33
41
  >
34
42
  mdi-undo-variant
35
43
  </FSIcon>
36
- <v-divider vertical />
44
+ <v-divider
45
+ vertical
46
+ />
37
47
  <FSIcon
38
48
  class="fs-rich-text-field-icon"
39
49
  :style="style"
@@ -62,7 +72,9 @@
62
72
  >
63
73
  mdi-format-paragraph
64
74
  </FSIcon>
65
- <v-divider vertical />
75
+ <v-divider
76
+ vertical
77
+ />
66
78
  <FSIcon
67
79
  class="fs-rich-text-field-icon"
68
80
  :color="toolbarColors.bold"
@@ -103,7 +115,9 @@
103
115
  >
104
116
  mdi-link
105
117
  </FSIcon>
106
- <v-divider vertical />
118
+ <v-divider
119
+ vertical
120
+ />
107
121
  <FSIcon
108
122
  class="fs-rich-text-field-icon"
109
123
  :style="style"
@@ -146,7 +160,9 @@
146
160
  @keypress.enter.stop="toggleLink"
147
161
  v-model="linkUrl"
148
162
  />
149
- <slot name="description">
163
+ <slot
164
+ name="description"
165
+ >
150
166
  <FSSpan
151
167
  v-if="!readonly && $props.description"
152
168
  class="fs-rich-text-field-description"
@@ -211,9 +227,9 @@ export default defineComponent({
211
227
  default: false
212
228
  },
213
229
  rows: {
214
- type: Number,
215
- required: false,
216
- default: 5
230
+ type: Number,
231
+ required: false,
232
+ default: 5
217
233
  },
218
234
  variant: {
219
235
  type: String as PropType<"standard" | "readonly">,
@@ -326,7 +342,7 @@ export default defineComponent({
326
342
  }
327
343
  else {
328
344
  return {
329
- "--fs-rich-text-field-undo-cursor" : canUndo ? "pointer" : "default",
345
+ "--fs-rich-text-field-undo-cursor" : canUndo.value ? "pointer" : "default",
330
346
  "--fs-rich-text-field-icon-cursor" : "pointer",
331
347
  "--fs-rich-text-field-border-color" : lights.dark,
332
348
  "--fs-rich-text-field-color" : darks.base,
@@ -335,13 +351,13 @@ export default defineComponent({
335
351
  "--fs-rich-text-field-min-height" : minHeight
336
352
  };
337
353
  }
338
- };
354
+ }
339
355
  case "readonly": return {
340
- "--fs-rich-text-field-border-color" : "transparent",
341
- "--fs-rich-text-field-color" : darks.base,
342
- "--fs-rich-text-field-active-border-color": "transparent",
343
- "--fs-rich-text-field-link-color" : linkColors.value.dark,
344
- "--fs-rich-text-field-min-height" : minHeight
356
+ "--fs-rich-text-field-border-color" : "transparent",
357
+ "--fs-rich-text-field-color" : darks.base,
358
+ "--fs-rich-text-field-active-border-color": "transparent",
359
+ "--fs-rich-text-field-link-color" : linkColors.value.dark,
360
+ "--fs-rich-text-field-min-height" : minHeight
345
361
  }
346
362
  }
347
363
  });
@@ -11,8 +11,13 @@
11
11
  v-model="innerValue"
12
12
  v-bind="$attrs"
13
13
  >
14
- <template v-if="$props.prependInnerIcon" #prepend-inner>
15
- <slot name="prepend-inner">
14
+ <template
15
+ v-if="$props.prependInnerIcon"
16
+ #prepend-inner
17
+ >
18
+ <slot
19
+ name="prepend-inner"
20
+ >
16
21
  <FSButton
17
22
  variant="icon"
18
23
  :icon="$props.prependInnerIcon"
@@ -22,8 +27,13 @@
22
27
  />
23
28
  </slot>
24
29
  </template>
25
- <template v-if="!['instant'].includes($props.variant)" #append>
26
- <slot name="append">
30
+ <template
31
+ v-if="!['instant'].includes($props.variant)"
32
+ #append
33
+ >
34
+ <slot
35
+ name="append"
36
+ >
27
37
  <FSButton
28
38
  :prependIcon="$props.buttonPrependIcon"
29
39
  :label="buttonLabel"
@@ -35,8 +45,14 @@
35
45
  />
36
46
  </slot>
37
47
  </template>
38
- <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
39
- <slot :name="name" v-bind="slotData" />
48
+ <template
49
+ v-for="(_, name) in $slots"
50
+ v-slot:[name]="slotData"
51
+ >
52
+ <slot
53
+ :name="name"
54
+ v-bind="slotData"
55
+ />
40
56
  </template>
41
57
  </FSTextField>
42
58
  </template>
@@ -154,10 +170,10 @@ export default defineComponent({
154
170
  });
155
171
 
156
172
  return {
157
- ColorEnum,
158
173
  placeholder,
159
174
  buttonLabel,
160
- innerValue
175
+ innerValue,
176
+ ColorEnum
161
177
  };
162
178
  }
163
179
  });
@@ -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: {