@dative-gpi/foundation-shared-components 0.0.12 → 0.0.14

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 (77) hide show
  1. package/components/FSButton.vue +1 -1
  2. package/components/FSCalendarTwin.vue +2 -0
  3. package/components/FSCheckbox.vue +3 -3
  4. package/components/FSClock.vue +47 -40
  5. package/components/FSCol.vue +2 -2
  6. package/components/FSDivider.vue +46 -7
  7. package/components/FSForm.vue +52 -0
  8. package/components/FSImage.vue +41 -32
  9. package/components/FSLabel.vue +105 -0
  10. package/components/FSPagination.vue +25 -9
  11. package/components/FSPermissions.vue +0 -0
  12. package/components/FSRadio.vue +3 -3
  13. package/components/FSSlideGroup.vue +10 -11
  14. package/components/FSSubmitDialog.vue +1 -1
  15. package/components/FSSwitch.vue +3 -3
  16. package/components/FSText.vue +1 -1
  17. package/components/FSWrapGroup.vue +10 -11
  18. package/components/{FSAutocompleteField.vue → fields/FSAutocompleteField.vue} +26 -19
  19. package/components/fields/FSColorField.vue +205 -0
  20. package/components/{FSDateField.vue → fields/FSDateField.vue} +15 -50
  21. package/components/{FSDateRangeField.vue → fields/FSDateRangeField.vue} +17 -67
  22. package/components/{FSDateTimeField.vue → fields/FSDateTimeField.vue} +17 -52
  23. package/components/{FSDateTimeRangeField.vue → fields/FSDateTimeRangeField.vue} +45 -81
  24. package/components/{FSIconField.vue → fields/FSIconField.vue} +16 -55
  25. package/components/{FSNumberField.vue → fields/FSNumberField.vue} +17 -27
  26. package/components/{FSPasswordField.vue → fields/FSPasswordField.vue} +5 -29
  27. package/components/{FSRichTextField.vue → fields/FSRichTextField.vue} +13 -11
  28. package/components/{FSSearchField.vue → fields/FSSearchField.vue} +1 -1
  29. package/components/{FSSelectField.vue → fields/FSSelectField.vue} +17 -21
  30. package/components/{FSTagField.vue → fields/FSTagField.vue} +18 -53
  31. package/components/{FSTextArea.vue → fields/FSTextArea.vue} +26 -26
  32. package/components/{FSTextField.vue → fields/FSTextField.vue} +18 -18
  33. package/components/fields/FSTimeField.vue +202 -0
  34. package/components/fields/FSTimeSlotField.vue +269 -0
  35. package/components/lists/FSDataTableUI.vue +10 -12
  36. package/components/lists/FSFilterButton.vue +1 -1
  37. package/components/tiles/FSDeviceOrganisationTileUI.vue +4 -9
  38. package/components/tiles/FSGroupTileUI.vue +4 -9
  39. package/composables/index.ts +1 -0
  40. package/composables/useBreakpoints.ts +7 -5
  41. package/composables/useRules.ts +72 -0
  42. package/elements/FSFormElement.ts +17 -0
  43. package/icons/flags/France.vue +9 -0
  44. package/icons/flags/Germany.vue +7 -0
  45. package/icons/flags/GreatBritain.vue +9 -0
  46. package/icons/flags/Italy.vue +9 -0
  47. package/icons/flags/Portugal.vue +59 -0
  48. package/icons/flags/Spain.vue +546 -0
  49. package/icons/flags/UnitedStates.vue +12 -0
  50. package/icons/sets.ts +17 -0
  51. package/models/rules.ts +8 -0
  52. package/package.json +4 -4
  53. package/styles/components/fs_autocomplete_field.scss +3 -60
  54. package/styles/components/fs_clock.scss +4 -0
  55. package/styles/components/fs_color_field.scss +21 -0
  56. package/styles/components/fs_data_table.scss +7 -2
  57. package/styles/components/fs_divider.scss +5 -0
  58. package/styles/components/fs_image.scss +12 -1
  59. package/styles/components/fs_label.scss +86 -0
  60. package/styles/components/fs_pagination.scss +3 -3
  61. package/styles/components/fs_rich_text_field.scss +1 -1
  62. package/styles/components/fs_select_field.scss +3 -4
  63. package/styles/components/fs_switch.scss +4 -4
  64. package/styles/components/fs_text_area.scss +2 -0
  65. package/styles/components/fs_text_field.scss +1 -0
  66. package/styles/components/fs_time_field.scss +16 -0
  67. package/styles/components/fs_timeslot_field.scss +12 -0
  68. package/styles/components/index.scss +4 -0
  69. package/styles/globals/overrides.scss +8 -6
  70. package/styles/globals/text_fonts.scss +18 -0
  71. package/utils/color.ts +7 -0
  72. package/utils/css.ts +2 -1
  73. package/utils/icons.ts +88 -2
  74. package/utils/index.ts +3 -1
  75. package/utils/time.ts +29 -0
  76. package/components/FSHeaderButton.vue +0 -17
  77. package/components/lists/FSDataIteratorGroup.vue +0 -7
@@ -19,6 +19,7 @@ import { computed, defineComponent } from "vue";
19
19
 
20
20
  import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
21
21
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
22
+ import { sizeToVar } from "@dative-gpi/foundation-shared-components/utils";
22
23
 
23
24
  export default defineComponent({
24
25
  name: "FSSlideGroup",
@@ -26,12 +27,12 @@ export default defineComponent({
26
27
  padding: {
27
28
  type: [String, Number],
28
29
  required: false,
29
- default: 0
30
+ default: "0"
30
31
  },
31
32
  gap: {
32
- type: Number,
33
+ type: [String, Number],
33
34
  required: false,
34
- default: 8
35
+ default: "8px"
35
36
  }
36
37
  },
37
38
  setup(props) {
@@ -40,14 +41,12 @@ export default defineComponent({
40
41
 
41
42
  const darks = getColors(ColorEnum.Dark);
42
43
 
43
- const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => {
44
- return {
45
- "--fs-group-padding" : typeof(props.padding) === "string" ? props.padding : `${props.padding}px`,
46
- "--fs-group-gap" : `${props.gap}px`,
47
- "--fs-group-color" : darks.light,
48
- "--fs-group-hover-color": darks.dark
49
- }
50
- });
44
+ const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => ({
45
+ "--fs-group-padding" : sizeToVar(props.padding),
46
+ "--fs-group-gap" : sizeToVar(props.gap),
47
+ "--fs-group-color" : darks.light,
48
+ "--fs-group-hover-color": darks.dark
49
+ }));
51
50
 
52
51
  return {
53
52
  style,
@@ -143,7 +143,7 @@ export default defineComponent({
143
143
  default: true
144
144
  }
145
145
  },
146
- emits: ["update:modelValue"],
146
+ emits: ["update:modelValue", "click:rightButton"],
147
147
  setup(props) {
148
148
  const { $tr } = useTranslationsProvider();
149
149
 
@@ -48,15 +48,15 @@ import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/m
48
48
  import { useColors } from "@dative-gpi/foundation-shared-components/composables";
49
49
 
50
50
  import FSSpan from "./FSSpan.vue";
51
- import FSRow from "./FSRow.vue";
52
51
  import FSCol from "./FSCol.vue";
52
+ import FSRow from "./FSRow.vue";
53
53
 
54
54
  export default defineComponent({
55
55
  name: "FSSwitch",
56
56
  components: {
57
57
  FSSpan,
58
- FSRow,
59
- FSCol
58
+ FSCol,
59
+ FSRow
60
60
  },
61
61
  props: {
62
62
  label: {
@@ -18,7 +18,7 @@ export default defineComponent({
18
18
  name: "FSText",
19
19
  props: {
20
20
  font: {
21
- type: String as PropType<"text-h1" | "text-h2" | "text-h3" | "text-body" | "text-button" | "text-overline" | "text-underline">,
21
+ type: String as PropType<"text-h1" | "text-h2" | "text-h3" | "text-h4" | "text-body" | "text-button" | "text-overline" | "text-underline">,
22
22
  required: false,
23
23
  default: "text-body"
24
24
  },
@@ -18,6 +18,7 @@ import { computed, defineComponent } from "vue";
18
18
 
19
19
  import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
20
20
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
21
+ import { sizeToVar } from "@dative-gpi/foundation-shared-components/utils";
21
22
 
22
23
  export default defineComponent({
23
24
  name: "FSWrapGroup",
@@ -25,12 +26,12 @@ export default defineComponent({
25
26
  padding: {
26
27
  type: [String, Number],
27
28
  required: false,
28
- default: 0
29
+ default: "0"
29
30
  },
30
31
  gap: {
31
- type: Number,
32
+ type: [String, Number],
32
33
  required: false,
33
- default: 8
34
+ default: "8px"
34
35
  }
35
36
  },
36
37
  setup(props) {
@@ -39,14 +40,12 @@ export default defineComponent({
39
40
 
40
41
  const darks = getColors(ColorEnum.Dark);
41
42
 
42
- const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => {
43
- return {
44
- "--fs-group-padding" : typeof(props.padding) === "string" ? props.padding : `${props.padding}px`,
45
- "--fs-group-gap" : `${props.gap}px`,
46
- "--fs-group-color" : darks.light,
47
- "--fs-group-hover-color": darks.dark
48
- }
49
- });
43
+ const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => ({
44
+ "--fs-group-padding" : sizeToVar(props.padding),
45
+ "--fs-group-gap" : sizeToVar(props.gap),
46
+ "--fs-group-color" : darks.light,
47
+ "--fs-group-hover-color": darks.dark
48
+ }));
50
49
 
51
50
  return {
52
51
  style,
@@ -41,13 +41,15 @@
41
41
  :items="$props.items"
42
42
  :autoSelectFirst="true"
43
43
  :multiple="$props.multiple"
44
- :error="messages.length > 0"
45
44
  :itemTitle="$props.itemTitle"
46
45
  :itemValue="$props.itemValue"
47
46
  :readonly="!$props.editable"
48
- :clearable="$props.editable"
47
+ :clearable="$props.editable && !!$props.modelValue"
48
+ :rules="$props.rules"
49
+ :validateOn="validateOn"
49
50
  :modelValue="$props.modelValue"
50
- @update:modelValue="(value) => $emit('update:modelValue', value)"
51
+ @update:modelValue="onUpdate"
52
+ @blur="blurred = true"
51
53
  v-model:search="innerSearch"
52
54
  v-bind="$attrs"
53
55
  >
@@ -71,12 +73,12 @@
71
73
  <script lang="ts">
72
74
  import { computed, defineComponent, PropType, ref, watch } from "vue";
73
75
 
74
- import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
76
+ import { useColors, useRules, useSlots } from "@dative-gpi/foundation-shared-components/composables";
75
77
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
76
78
 
77
- import FSSpan from "./FSSpan.vue";
78
- import FSCol from "./FSCol.vue";
79
- import FSRow from "./FSRow.vue";
79
+ import FSSpan from "../FSSpan.vue";
80
+ import FSCol from "../FSCol.vue";
81
+ import FSRow from "../FSRow.vue";
80
82
 
81
83
  export default defineComponent({
82
84
  name: "FSAutocompleteField",
@@ -135,6 +137,11 @@ export default defineComponent({
135
137
  required: false,
136
138
  default: () => []
137
139
  },
140
+ messages: {
141
+ type: Array as PropType<string[]>,
142
+ required: false,
143
+ default: null
144
+ },
138
145
  editable: {
139
146
  type: Boolean,
140
147
  required: false,
@@ -143,6 +150,7 @@ export default defineComponent({
143
150
  },
144
151
  emits: ["update:modelValue", "update:search"],
145
152
  setup: (props, { emit }) => {
153
+ const { validateOn, blurred, getMessages } = useRules();
146
154
  const { getColors } = useColors();
147
155
  const { slots } = useSlots();
148
156
 
@@ -174,17 +182,6 @@ export default defineComponent({
174
182
  };
175
183
  });
176
184
 
177
- const messages = computed((): string[] => {
178
- const messages = [];
179
- for (const rule of props.rules) {
180
- const message = rule(props.modelValue ?? "");
181
- if (typeof(message) === "string") {
182
- messages.push(message);
183
- }
184
- }
185
- return messages;
186
- });
187
-
188
185
  const classes = computed((): string[] => {
189
186
  const classNames = ["fs-autocomplete-field"];
190
187
  if (props.multiple) {
@@ -193,16 +190,26 @@ export default defineComponent({
193
190
  return classNames;
194
191
  });
195
192
 
193
+ const messages = computed((): string[] => props.messages ?? getMessages(props.modelValue, props.rules));
194
+
195
+ const onUpdate = (value: string[] | string) => {
196
+ emit('update:modelValue', value);
197
+ innerSearch.value = "";
198
+ };
199
+
196
200
  watch(innerSearch, () => {
197
201
  emit("update:search", innerSearch.value);
198
202
  });
199
203
 
200
204
  return {
205
+ validateOn,
201
206
  messages,
207
+ blurred,
202
208
  slots,
203
209
  style,
204
210
  classes,
205
- innerSearch
211
+ innerSearch,
212
+ onUpdate
206
213
  };
207
214
  }
208
215
  });
@@ -0,0 +1,205 @@
1
+ <template>
2
+ <v-menu
3
+ :closeOnContentClick="false"
4
+ :modelValue="menu && $props.editable"
5
+ @update:modelValue="(value) => menu = value"
6
+ >
7
+ <template #activator="{ props }">
8
+ <FSCol>
9
+ <FSRow
10
+ height="fill"
11
+ v-bind="props"
12
+ >
13
+ <FSTextField
14
+ class="fs-color-field"
15
+ :hideHeader="$props.hideHeader"
16
+ :required="$props.required"
17
+ :editable="$props.editable"
18
+ :clearable="false"
19
+ :readonly="true"
20
+ :modelValue="innerColor"
21
+ v-bind="$attrs"
22
+ >
23
+ <template #prepend-inner>
24
+ <slot name="prepend-inner">
25
+ <FSIcon
26
+ size="xl"
27
+ :color="innerColor"
28
+ >
29
+ mdi-circle
30
+ </FSIcon>
31
+ </slot>
32
+ </template>
33
+ <template #append>
34
+ <FSButton
35
+ prependIcon="mdi-pencil"
36
+ variant="full"
37
+ :editable="$props.editable"
38
+ />
39
+ </template>
40
+ </FSTextField>
41
+ <FSTextField
42
+ class="fs-color-field-opacity"
43
+ :label="$tr('ui.color-field.opacity', 'Opacity')"
44
+ :hideHeader="$props.hideHeader"
45
+ :required="$props.required"
46
+ :editable="$props.editable"
47
+ :clearable="false"
48
+ :readonly="true"
49
+ :modelValue="(Math.round(getPercentageFromHex(innerOpacity)*100)) + ' %'"
50
+ >
51
+ <template #prepend-inner>
52
+ <slot name="prepend-inner">
53
+ <FSIcon
54
+ icon="mdi-circle"
55
+ size="xl"
56
+ :color="ColorEnum.Dark"
57
+ :editable="$props.editable"
58
+ :style="{ opacity: getPercentageFromHex(innerOpacity) }"
59
+ />
60
+ </slot>
61
+ </template>
62
+ <template #append>
63
+ <FSButton
64
+ prependIcon="mdi-pencil"
65
+ variant="full"
66
+ :editable="$props.editable"
67
+ />
68
+ </template>
69
+ </FSTextField>
70
+ </FSRow>
71
+ <slot name="description">
72
+ <FSSpan
73
+ v-if="$props.description"
74
+ class="fs-color-field-description"
75
+ font="text-underline"
76
+ :style="style"
77
+ >
78
+ {{ $props.description }}
79
+ </FSSpan>
80
+ </slot>
81
+ </FSCol>
82
+ </template>
83
+ <FSCard
84
+ :elevation="true"
85
+ :border="false"
86
+ >
87
+ <FSCol
88
+ width="fill"
89
+ >
90
+ <v-color-picker
91
+ class="fs-color-field-picker"
92
+ mode="hexa"
93
+ :elevation="0"
94
+ :modes="['hexa', 'rgba']"
95
+ :modelValue="fullColor"
96
+ @update:modelValue="onSubmit"
97
+ />
98
+ </FSCol>
99
+ </FSCard>
100
+ </v-menu>
101
+ </template>
102
+
103
+ <script lang="ts">
104
+ import { computed, defineComponent, ref } from "vue";
105
+
106
+ import { getPercentageFromHex, getHexFromPercentage } from "@dative-gpi/foundation-shared-components/utils";
107
+ import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
108
+ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
109
+
110
+ import FSTextField from "./FSTextField.vue";
111
+ import FSButton from "../FSButton.vue";
112
+ import FSCard from "../FSCard.vue";
113
+ import FSIcon from "../FSIcon.vue";
114
+ import FSRow from "../FSRow.vue";
115
+ import FSCol from "../FSCol.vue";
116
+
117
+ export default defineComponent({
118
+ name: "FSColorField",
119
+ components: {
120
+ FSTextField,
121
+ FSButton,
122
+ FSCard,
123
+ FSIcon,
124
+ FSCol,
125
+ FSRow
126
+ },
127
+ props: {
128
+ description: {
129
+ type: String,
130
+ required: false,
131
+ default: null
132
+ },
133
+ modelValue: {
134
+ type: String,
135
+ required: false,
136
+ default: "#000000"
137
+ },
138
+ opacityValue: {
139
+ type: Number,
140
+ required: false,
141
+ default: 1
142
+ },
143
+ hideHeader: {
144
+ type: Boolean,
145
+ required: false,
146
+ default: false
147
+ },
148
+ required: {
149
+ type: Boolean,
150
+ required: false,
151
+ default: false
152
+ },
153
+ editable: {
154
+ type: Boolean,
155
+ required: false,
156
+ default: true
157
+ }
158
+ },
159
+ emits: ["update:modelValue", "update:opacity"],
160
+ setup(props, { emit }) {
161
+ const { slots } = useSlots();
162
+
163
+ delete slots.description;
164
+
165
+ const lights = useColors().getColors(ColorEnum.Light);
166
+ const darks = useColors().getColors(ColorEnum.Dark);
167
+
168
+ const menu = ref(false);
169
+ const innerColor = ref(props.modelValue.toString().substring(0, 7));
170
+ const innerOpacity = ref(getHexFromPercentage(props.opacityValue));
171
+ const fullColor = ref(innerColor.value + innerOpacity.value);
172
+
173
+ const style = computed((): {[code: string]: string} & Partial<CSSStyleDeclaration> => {
174
+ if (!props.editable) {
175
+ return {
176
+ "--fs-color-field-color": lights.dark
177
+ };
178
+ }
179
+ return {
180
+ "--fs-color-field-color": darks.base
181
+ };
182
+ });
183
+
184
+
185
+ const onSubmit = (value: string) => {
186
+ innerColor.value = value.substring(0, 7);
187
+ innerOpacity.value = value.length === 9 ? value.substring(7, 9) : "FF";
188
+ fullColor.value = innerColor.value + innerOpacity.value;
189
+ emit("update:modelValue", innerColor.value);
190
+ emit("update:opacity", getPercentageFromHex(innerOpacity.value));
191
+ };
192
+
193
+ return {
194
+ getPercentageFromHex,
195
+ innerOpacity,
196
+ innerColor,
197
+ fullColor,
198
+ ColorEnum,
199
+ onSubmit,
200
+ style,
201
+ menu
202
+ };
203
+ }
204
+ });
205
+ </script>
@@ -13,45 +13,16 @@
13
13
  :hideHeader="$props.hideHeader"
14
14
  :required="$props.required"
15
15
  :editable="$props.editable"
16
- :error="messages.length > 0"
17
16
  :readonly="true"
17
+ :rules="$props.rules"
18
+ :messages="messages"
19
+ :validateOn="validateOn"
20
+ :validationValue="$props.modelValue"
18
21
  :modelValue="epochToLongDateFormat($props.modelValue)"
19
22
  @click:clear="onClear"
23
+ @blur="blurred = true"
20
24
  v-bind="props"
21
25
  >
22
- <template v-if="!$props.hideHeader" #label>
23
- <slot name="label">
24
- <FSRow :wrap="false">
25
- <FSSpan
26
- v-if="$props.label"
27
- class="fs-date-field-label"
28
- font="text-overline"
29
- :style="style"
30
- >
31
- {{ $props.label }}
32
- </FSSpan>
33
- <FSSpan
34
- v-if="$props.label && $props.required"
35
- class="fs-date-field-label"
36
- style="margin-left: -8px;"
37
- font="text-overline"
38
- :ellipsis="false"
39
- :style="style"
40
- >
41
- *
42
- </FSSpan>
43
- <v-spacer style="min-width: 40px;" />
44
- <FSSpan
45
- v-if="messages.length > 0"
46
- class="fs-date-field-messages"
47
- font="text-overline"
48
- :style="style"
49
- >
50
- {{ messages.join(", ") }}
51
- </FSSpan>
52
- </FSRow>
53
- </slot>
54
- </template>
55
26
  <template #prepend-inner>
56
27
  <slot name="prepend-inner">
57
28
  <FSButton
@@ -68,7 +39,7 @@
68
39
  </FSTextField>
69
40
  </template>
70
41
  <FSCard
71
- width="394"
42
+ width="346px"
72
43
  :elevation="true"
73
44
  :border="false"
74
45
  >
@@ -91,15 +62,15 @@
91
62
  <script lang="ts">
92
63
  import { computed, defineComponent, PropType, ref } from "vue";
93
64
 
65
+ import { useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
94
66
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
95
67
  import { useTimeZone } from "@dative-gpi/foundation-shared-services/composables";
96
- import { useColors } from "@dative-gpi/foundation-shared-components/composables";
97
68
 
98
69
  import FSTextField from "./FSTextField.vue";
99
- import FSCalendar from "./FSCalendar.vue";
100
- import FSButton from "./FSButton.vue";
101
- import FSCard from "./FSCard.vue";
102
- import FSCol from "./FSCol.vue";
70
+ import FSCalendar from "../FSCalendar.vue";
71
+ import FSButton from "../FSButton.vue";
72
+ import FSCard from "../FSCard.vue";
73
+ import FSCol from "../FSCol.vue";
103
74
 
104
75
  export default defineComponent({
105
76
  name: "FSDateField",
@@ -154,6 +125,7 @@ export default defineComponent({
154
125
  },
155
126
  emits: ["update:modelValue"],
156
127
  setup(props, { emit }) {
128
+ const {validateOn, blurred, getMessages} = useRules();
157
129
  const { epochToLongDateFormat } = useTimeZone();
158
130
  const { getColors } = useColors();
159
131
 
@@ -176,16 +148,7 @@ export default defineComponent({
176
148
  };
177
149
  });
178
150
 
179
- const messages = computed((): string[] => {
180
- const messages = [];
181
- for (const rule of props.rules) {
182
- const message = rule(props.modelValue ?? null);
183
- if (typeof(message) === "string") {
184
- messages.push(message);
185
- }
186
- }
187
- return messages;
188
- });
151
+ const messages = computed((): string[] => getMessages(props.modelValue, props.rules));
189
152
 
190
153
  const onClear = (): void => {
191
154
  emit("update:modelValue", null);
@@ -200,7 +163,9 @@ export default defineComponent({
200
163
  return {
201
164
  ColorEnum,
202
165
  innerDate,
166
+ validateOn,
203
167
  messages,
168
+ blurred,
204
169
  style,
205
170
  menu,
206
171
  onClear,
@@ -7,45 +7,16 @@
7
7
  :hideHeader="$props.hideHeader"
8
8
  :required="$props.required"
9
9
  :editable="$props.editable"
10
- :error="messages.length > 0"
11
10
  :readonly="true"
12
- :modelValue="placeholder"
11
+ :rules="$props.rules"
12
+ :messages="messages"
13
+ :validateOn="validateOn"
14
+ :validationValue="$props.modelValue"
15
+ :modelValue="toShortDateFormat"
13
16
  @click="onClick"
14
17
  @click:clear="onClear"
18
+ @blur="blurred = true"
15
19
  >
16
- <template v-if="!$props.hideHeader" #label>
17
- <slot name="label">
18
- <FSRow :wrap="false">
19
- <FSSpan
20
- v-if="$props.label"
21
- class="fs-date-field-label"
22
- font="text-overline"
23
- :style="style"
24
- >
25
- {{ $props.label }}
26
- </FSSpan>
27
- <FSSpan
28
- v-if="$props.label && $props.required"
29
- class="fs-date-field-label"
30
- style="margin-left: -8px;"
31
- font="text-overline"
32
- :ellipsis="false"
33
- :style="style"
34
- >
35
- *
36
- </FSSpan>
37
- <v-spacer style="min-width: 40px;" />
38
- <FSSpan
39
- v-if="messages.length > 0"
40
- class="fs-date-field-messages"
41
- font="text-overline"
42
- :style="style"
43
- >
44
- {{ messages.join(", ") }}
45
- </FSSpan>
46
- </FSRow>
47
- </slot>
48
- </template>
49
20
  <template #prepend-inner>
50
21
  <slot name="prepend-inner">
51
22
  <FSButton
@@ -78,16 +49,14 @@
78
49
  <script lang="ts">
79
50
  import { computed, defineComponent, PropType, ref } from "vue";
80
51
 
52
+ import { useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
81
53
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
82
54
  import { useTimeZone } from "@dative-gpi/foundation-shared-services/composables";
83
- import { useColors } from "@dative-gpi/foundation-shared-components/composables";
84
55
 
85
- import FSSubmitDialog from "./FSSubmitDialog.vue";
86
- import FSCalendarTwin from "./FSCalendarTwin.vue";
56
+ import FSSubmitDialog from "../FSSubmitDialog.vue";
57
+ import FSCalendarTwin from "../FSCalendarTwin.vue";
87
58
  import FSTextField from "./FSTextField.vue";
88
- import FSButton from "./FSButton.vue";
89
- import FSCard from "./FSCard.vue";
90
- import FSCol from "./FSCol.vue";
59
+ import FSButton from "../FSButton.vue";
91
60
 
92
61
  export default defineComponent({
93
62
  name: "FSDateRangeField",
@@ -95,9 +64,7 @@ export default defineComponent({
95
64
  FSSubmitDialog,
96
65
  FSCalendarTwin,
97
66
  FSTextField,
98
- FSButton,
99
- FSCard,
100
- FSCol
67
+ FSButton
101
68
  },
102
69
  props: {
103
70
  label: {
@@ -143,6 +110,7 @@ export default defineComponent({
143
110
  },
144
111
  emits: ["update:modelValue"],
145
112
  setup(props, { emit }) {
113
+ const { validateOn, blurred, getMessages } = useRules();
146
114
  const { epochToShortDateFormat } = useTimeZone();
147
115
  const { getColors } = useColors();
148
116
 
@@ -165,34 +133,14 @@ export default defineComponent({
165
133
  };
166
134
  });
167
135
 
168
- const placeholder = computed((): string => {
136
+ const toShortDateFormat = computed((): string => {
169
137
  if (!props.modelValue || !Array.isArray(props.modelValue) || !props.modelValue.length) {
170
138
  return "";
171
139
  }
172
140
  return props.modelValue.map((epoch) => epochToShortDateFormat(epoch)).join(" - ");
173
141
  });
174
142
 
175
- const messages = computed((): string[] => {
176
- const messages = [];
177
- for (const rule of props.rules) {
178
- if (props.modelValue && Array.isArray(props.modelValue)) {
179
- for (const value of props.modelValue) {
180
- const message = rule(value);
181
- if (typeof(message) === "string") {
182
- messages.push(message);
183
- break;
184
- }
185
- }
186
- }
187
- else {
188
- const message = rule(null);
189
- if (typeof(message) === "string") {
190
- messages.push(message);
191
- }
192
- }
193
- }
194
- return messages;
195
- });
143
+ const messages = computed((): string[] => getMessages(props.modelValue, props.rules, true));
196
144
 
197
145
  const onClick = (): void => {
198
146
  if (props.editable) {
@@ -212,10 +160,12 @@ export default defineComponent({
212
160
 
213
161
  return {
214
162
  ColorEnum,
163
+ validateOn,
215
164
  messages,
165
+ blurred,
216
166
  style,
217
167
  dialog,
218
- placeholder,
168
+ toShortDateFormat,
219
169
  innerDateRange,
220
170
  onClick,
221
171
  onClear,