@dative-gpi/foundation-shared-components 0.0.126 → 0.0.128

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.
@@ -10,7 +10,6 @@
10
10
  :validateOn="validateOn"
11
11
  :modelValue="$props.modelValue"
12
12
  @click.prevent.stop="onToggle"
13
- @blur="blurred = true"
14
13
  v-bind="$attrs"
15
14
  >
16
15
  <template
@@ -122,7 +121,7 @@ export default defineComponent({
122
121
  },
123
122
  emits: ["update:modelValue"],
124
123
  setup(props, { emit }) {
125
- const { validateOn, blurred, getMessages } = useRules();
124
+ const { validateOn, getMessages } = useRules();
126
125
  const { getColors } = useColors();
127
126
 
128
127
  const colors = computed(() => getColors(props.color));
@@ -168,7 +167,6 @@ export default defineComponent({
168
167
  return {
169
168
  validateOn,
170
169
  messages,
171
- blurred,
172
170
  style,
173
171
  icon,
174
172
  font,
@@ -22,7 +22,7 @@ export default defineComponent({
22
22
  default: null
23
23
  },
24
24
  variant: {
25
- type: String as PropType<"standard" | "lazy" | "submit">,
25
+ type: String as PropType<"standard" | "submit">,
26
26
  required: false,
27
27
  default: "submit"
28
28
  }
@@ -32,10 +32,9 @@ export default defineComponent({
32
32
  const formRef = ref<HTMLFormElement | null>(null);
33
33
  const submitted = ref(false);
34
34
 
35
- const validateOn = computed((): "submit" | "blur" | "input" => {
35
+ const validateOn = computed((): "submit" | "input" => {
36
36
  switch (props.variant) {
37
37
  case "standard": return "input";
38
- case "lazy": return "blur";
39
38
  default: return "submit";
40
39
  }
41
40
  });
@@ -72,10 +71,10 @@ export default defineComponent({
72
71
  validateOn,
73
72
  submitted,
74
73
  formRef,
75
- reset,
76
- validate,
74
+ resetValidation,
77
75
  onSubmit,
78
- resetValidation
76
+ validate,
77
+ reset
79
78
  };
80
79
  }
81
80
  });
@@ -9,7 +9,6 @@
9
9
  :validateOn="validateOn"
10
10
  :modelValue="$props.selected"
11
11
  @click.prevent.stop
12
- @blur="blurred = true"
13
12
  v-bind="$attrs"
14
13
  >
15
14
  <template
@@ -126,7 +125,7 @@ export default defineComponent({
126
125
  },
127
126
  emits: ["update:modelValue"],
128
127
  setup(props, { emit }) {
129
- const { validateOn, blurred, getMessages } = useRules();
128
+ const { validateOn, getMessages } = useRules();
130
129
  const { getColors } = useColors();
131
130
 
132
131
  const colors = computed(() => getColors(props.color));
@@ -174,7 +173,6 @@ export default defineComponent({
174
173
  return {
175
174
  validateOn,
176
175
  messages,
177
- blurred,
178
176
  style,
179
177
  icon,
180
178
  font,
@@ -99,7 +99,7 @@ export default defineComponent({
99
99
  },
100
100
  emits: ["update:modelValue"],
101
101
  setup(props, { emit }) {
102
- const { validateOn, blurred, getMessages } = useRules();
102
+ const { validateOn, getMessages } = useRules();
103
103
  const { getColors } = useColors();
104
104
 
105
105
  const colors = computed(() => getColors(props.color));
@@ -150,7 +150,6 @@ export default defineComponent({
150
150
  return {
151
151
  validateOn,
152
152
  messages,
153
- blurred,
154
153
  style,
155
154
  font,
156
155
  onToggle
@@ -1,9 +1,7 @@
1
1
  <template>
2
2
  <v-input
3
3
  class="fs-toggle-set"
4
- ref="inputRef"
5
4
  :modelValue="$props.modelValue"
6
- :rules="$props.rules"
7
5
  >
8
6
  <FSWrapGroup
9
7
  v-if="['wrap'].includes($props.variant)"
@@ -97,8 +95,7 @@
97
95
  <script lang="ts">
98
96
  import { defineComponent, PropType, ref } from "vue";
99
97
 
100
- import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
101
- import { FSToggle } from "@dative-gpi/foundation-shared-components/models";
98
+ import { ColorBase, ColorEnum, FSToggle } from "@dative-gpi/foundation-shared-components/models";
102
99
 
103
100
  import FSSlideGroup from "./FSSlideGroup.vue";
104
101
  import FSWrapGroup from "./FSWrapGroup.vue";
@@ -157,11 +154,6 @@ export default defineComponent({
157
154
  required: false,
158
155
  default: ColorEnum.Primary
159
156
  },
160
- errorColor: {
161
- type: String as PropType<ColorBase>,
162
- required: false,
163
- default: ColorEnum.Error
164
- },
165
157
  padding: {
166
158
  type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
167
159
  required: false,
@@ -172,11 +164,6 @@ export default defineComponent({
172
164
  required: false,
173
165
  default: "8px"
174
166
  },
175
- rules: {
176
- type: Array as PropType<any[]>,
177
- required: false,
178
- default: () => []
179
- },
180
167
  multiple: {
181
168
  type: Boolean,
182
169
  required: false,
@@ -194,9 +181,8 @@ export default defineComponent({
194
181
  }
195
182
  },
196
183
  emits: ["update:modelValue"],
197
- setup(props, { emit }) {
184
+ setup(props, { emit }) {
198
185
  const toggleSetRef = ref(null);
199
- const inputRef = ref(null);
200
186
 
201
187
  const getVariant = (value: FSToggle): "standard" | "full" | "icon" => {
202
188
  if (Array.isArray(props.modelValue) && props.modelValue.some(v => v === value.id)) {
@@ -215,9 +201,6 @@ export default defineComponent({
215
201
  if (!Array.isArray(props.modelValue) && props.modelValue === value.id) {
216
202
  return props.activeColor;
217
203
  }
218
- if (inputRef.value && (inputRef.value as any).errorMessages.length) {
219
- return props.errorColor;
220
- }
221
204
  return props.buttonColor;
222
205
  };
223
206
 
@@ -302,7 +285,6 @@ export default defineComponent({
302
285
 
303
286
  return {
304
287
  toggleSetRef,
305
- inputRef,
306
288
  getVariant,
307
289
  goToStart,
308
290
  getColor,
@@ -1,7 +1,6 @@
1
1
  <template>
2
2
  <FSAutocompleteField
3
3
  :toggleSet="!$props.toggleSetDisabled && toggleSet"
4
- :customFilter="customFilter"
5
4
  :multiple="$props.multiple"
6
5
  :loading="loading"
7
6
  :items="timeZones"
@@ -128,10 +127,6 @@ export default defineComponent({
128
127
  return getManyTimeZones({ ...props.timeZoneFilters, search: search ?? undefined });
129
128
  };
130
129
 
131
- const customFilter = (_: any, search: string, item: any): boolean => {
132
- return item.raw.id.toLowerCase().includes(search.toLowerCase());
133
- };
134
-
135
130
  const { toggleSet, search, init, onUpdate } = useAutocomplete(
136
131
  timeZones,
137
132
  [() => props.timeZoneFilters],
@@ -147,7 +142,6 @@ export default defineComponent({
147
142
  toggleSet,
148
143
  loading,
149
144
  search,
150
- customFilter,
151
145
  onUpdate
152
146
  };
153
147
  }
@@ -1,9 +1,19 @@
1
1
  <template>
2
- <FSLoader
2
+ <template
3
3
  v-if="$props.loading"
4
- width="100%"
5
- :height="['40px', '36px']"
6
- />
4
+ >
5
+ <FSCol>
6
+ <FSLoader
7
+ v-if="!$props.hideHeader"
8
+ variant="text-overline"
9
+ />
10
+ <FSLoader
11
+ v-if="$props.loading"
12
+ width="100%"
13
+ :height="['40px', '36px']"
14
+ />
15
+ </FSCol>
16
+ </template>
7
17
  <template
8
18
  v-else
9
19
  >
@@ -25,7 +35,6 @@
25
35
  :modelValue="mobileValue"
26
36
  @update:modelValue="$emit('update:modelValue', $event)"
27
37
  @click="openMobileOverlay"
28
- @blur="blurred = true"
29
38
  v-bind="$attrs"
30
39
  >
31
40
  <template
@@ -123,7 +132,34 @@
123
132
  <template
124
133
  v-else
125
134
  >
135
+ <FSToggleField
136
+ v-if="$props.toggleSet"
137
+ :label="$props.label"
138
+ :description="$props.description"
139
+ :hideHeader="$props.hideHeader"
140
+ :items="$props.items"
141
+ :returnObject="$props.returnObject"
142
+ :required="$props.required"
143
+ :editable="$props.editable"
144
+ :multiple="$props.multiple"
145
+ :rules="$props.rules"
146
+ :validateOn="validateOn"
147
+ :modelValue="$props.modelValue"
148
+ @update:modelValue="onUpdate"
149
+ v-bind="$attrs"
150
+ >
151
+ <template
152
+ v-for="(_, name) in toggleSetSlots"
153
+ v-slot:[name]="slotData"
154
+ >
155
+ <slot
156
+ :name="`toggle-set-${name}`"
157
+ v-bind="slotData"
158
+ />
159
+ </template>
160
+ </FSToggleField>
126
161
  <FSBaseField
162
+ v-else
127
163
  :label="$props.label"
128
164
  :description="$props.description"
129
165
  :hideHeader="$props.hideHeader"
@@ -131,28 +167,7 @@
131
167
  :editable="$props.editable"
132
168
  :messages="messages"
133
169
  >
134
- <FSToggleSet
135
- v-if="$props.toggleSet"
136
- variant="slide"
137
- :values="$props.items"
138
- :multiple="$props.multiple"
139
- :rules="$props.rules"
140
- :modelValue="$props.modelValue"
141
- @update:modelValue="onUpdate"
142
- v-bind="$attrs"
143
- >
144
- <template
145
- v-for="(_, name) in toggleSetSlots"
146
- v-slot:[name]="slotData"
147
- >
148
- <slot
149
- :name="`toggle-set-${name}`"
150
- v-bind="slotData"
151
- />
152
- </template>
153
- </FSToggleSet>
154
170
  <v-autocomplete
155
- v-else
156
171
  class="fs-autocomplete-field"
157
172
  variant="outlined"
158
173
  :menuIcon="null"
@@ -167,7 +182,6 @@
167
182
  :itemTitle="$props.itemTitle"
168
183
  :itemValue="$props.itemValue"
169
184
  :readonly="!$props.editable"
170
- :loading="$props.loading"
171
185
  :clearable="$props.clearable && $props.editable && !!$props.modelValue"
172
186
  :returnObject="$props.returnObject"
173
187
  :rules="$props.rules"
@@ -175,7 +189,6 @@
175
189
  :modelValue="$props.modelValue"
176
190
  @update:modelValue="onUpdate"
177
191
  @click="onClick"
178
- @blur="blurred = true"
179
192
  v-model:search="search"
180
193
  v-bind="$attrs"
181
194
  >
@@ -285,9 +298,9 @@ import { useBreakpoints, useColors, useRules, useSlots } from "@dative-gpi/found
285
298
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
286
299
 
287
300
  import FSSearchField from "./FSSearchField.vue";
301
+ import FSToggleField from "./FSToggleField.vue";
288
302
  import FSDialogMenu from "../FSDialogMenu.vue";
289
303
  import FSRadioGroup from "../FSRadioGroup.vue";
290
- import FSToggleSet from "../FSToggleSet.vue";
291
304
  import FSBaseField from "./FSBaseField.vue";
292
305
  import FSTextField from "./FSTextField.vue";
293
306
  import FSCheckbox from "../FSCheckbox.vue";
@@ -302,9 +315,9 @@ export default defineComponent({
302
315
  name: "FSAutocompleteField",
303
316
  components: {
304
317
  FSSearchField,
318
+ FSToggleField,
305
319
  FSDialogMenu,
306
320
  FSRadioGroup,
307
- FSToggleSet,
308
321
  FSBaseField,
309
322
  FSTextField,
310
323
  FSCheckbox,
@@ -399,7 +412,7 @@ export default defineComponent({
399
412
  emits: ["update:modelValue", "update:search"],
400
413
  setup: (props, { emit }) => {
401
414
  const { isExtraSmall, isMobileSized } = useBreakpoints();
402
- const { validateOn, blurred, getMessages } = useRules();
415
+ const { validateOn, getMessages } = useRules();
403
416
  const { getColors } = useColors();
404
417
  const { slots } = useSlots();
405
418
 
@@ -537,26 +550,59 @@ export default defineComponent({
537
550
  dialog.value = true;
538
551
  };
539
552
 
540
- const onRadioChange = (value: any) => {
541
- emit("update:modelValue", value);
553
+ const onRadioChange = (value: string | null) => {
554
+ if (props.returnObject) {
555
+ emit("update:modelValue", props.items.find((item: any) => item[props.itemValue] === value) ?? null);
556
+ }
557
+ else {
558
+ emit("update:modelValue", value);
559
+ }
542
560
  dialog.value = false;
543
561
  };
544
562
 
545
- const onCheckboxChange = (value: any) => {
546
- if (Array.isArray(props.modelValue)) {
547
- if (props.modelValue.includes(value)) {
548
- emit("update:modelValue", props.modelValue.filter((item: any) => item !== value));
563
+ const onCheckboxChange = (value: string) => {
564
+ if (props.returnObject) {
565
+ const item = props.items.find(item => item[props.itemValue] === value);
566
+ if (Array.isArray(props.modelValue)) {
567
+ if (props.modelValue.find(item => item[props.itemValue] === value)) {
568
+ emit("update:modelValue", props.modelValue.filter((item: any) => item[props.itemValue] !== value));
569
+ }
570
+ else {
571
+ if (item) {
572
+ emit("update:modelValue", [...props.modelValue, item]);
573
+ }
574
+ }
549
575
  }
550
576
  else {
551
- emit("update:modelValue", [...props.modelValue, value]);
577
+ if (props.modelValue) {
578
+ if (props.modelValue[props.itemValue] === value) {
579
+ emit("update:modelValue", []);
580
+ }
581
+ else {
582
+ emit("update:modelValue", [props.modelValue, item]);
583
+ }
584
+ }
585
+ else {
586
+ emit("update:modelValue", [item]);
587
+ }
552
588
  }
553
589
  }
554
590
  else {
555
- if (props.modelValue === value) {
556
- emit("update:modelValue", []);
591
+ if (Array.isArray(props.modelValue)) {
592
+ if (props.modelValue.includes(value)) {
593
+ emit("update:modelValue", props.modelValue.filter((item: any) => item !== value));
594
+ }
595
+ else {
596
+ emit("update:modelValue", [...props.modelValue, value]);
597
+ }
557
598
  }
558
599
  else {
559
- emit("update:modelValue", [props.modelValue, value]);
600
+ if (props.modelValue === value) {
601
+ emit("update:modelValue", []);
602
+ }
603
+ else {
604
+ emit("update:modelValue", [props.modelValue, value]);
605
+ }
560
606
  }
561
607
  }
562
608
  };
@@ -586,7 +632,6 @@ export default defineComponent({
586
632
  ColorEnum,
587
633
  listStyle,
588
634
  messages,
589
- blurred,
590
635
  classes,
591
636
  dialog,
592
637
  height,
@@ -19,7 +19,6 @@
19
19
  :modelValue="epochToLongDateFormat($props.modelValue)"
20
20
  @update:modelValue="onClear"
21
21
  @click="openMobileOverlay"
22
- @blur="blurred = true"
23
22
  >
24
23
  <template
25
24
  #prepend-inner
@@ -95,7 +94,6 @@
95
94
  :validationValue="$props.modelValue"
96
95
  :modelValue="epochToLongDateFormat($props.modelValue)"
97
96
  @update:modelValue="onClear"
98
- @blur="blurred = true"
99
97
  v-bind="props"
100
98
  >
101
99
  <template
@@ -151,7 +149,7 @@
151
149
  <script lang="ts">
152
150
  import { computed, defineComponent, PropType, ref } from "vue";
153
151
 
154
- import { useBreakpoints, useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
152
+ import { useBreakpoints, useRules } from "@dative-gpi/foundation-shared-components/composables";
155
153
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
156
154
  import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
157
155
 
@@ -216,31 +214,14 @@ export default defineComponent({
216
214
  },
217
215
  emits: ["update:modelValue"],
218
216
  setup(props, { emit }) {
219
- const { validateOn, blurred, getMessages} = useRules();
220
217
  const { epochToLongDateFormat } = useAppTimeZone();
218
+ const { validateOn, getMessages} = useRules();
221
219
  const { isExtraSmall } = useBreakpoints();
222
- const { getColors } = useColors();
223
220
 
224
221
  const dialog = ref(false);
225
222
  const menu = ref(false);
226
223
  const innerDate = ref<number | null>(props.modelValue);
227
224
 
228
- const errors = getColors(ColorEnum.Error);
229
- const lights = getColors(ColorEnum.Light);
230
- const darks = getColors(ColorEnum.Dark);
231
-
232
- const style = computed((): { [key: string] : string | null | undefined } => {
233
- if (!props.editable) {
234
- return {
235
- "--fs-date-field-color": lights.dark
236
- };
237
- }
238
- return {
239
- "--fs-date-field-color" : darks.base,
240
- "--fs-date-field-error-color": errors.base
241
- };
242
- });
243
-
244
225
  const messages = computed((): string[] => getMessages(props.modelValue, props.rules));
245
226
 
246
227
  const openMobileOverlay = () => {
@@ -267,9 +248,7 @@ export default defineComponent({
267
248
  ColorEnum,
268
249
  innerDate,
269
250
  messages,
270
- blurred,
271
251
  dialog,
272
- style,
273
252
  menu,
274
253
  epochToLongDateFormat,
275
254
  openMobileOverlay,
@@ -15,7 +15,6 @@
15
15
  :modelValue="toShortDateFormat"
16
16
  @click="onClick"
17
17
  @update:modelValue="onClear"
18
- @blur="blurred = true"
19
18
  >
20
19
  <template
21
20
  #prepend-inner
@@ -61,9 +60,9 @@
61
60
  <script lang="ts">
62
61
  import { computed, defineComponent, PropType, ref } from "vue";
63
62
 
64
- import { useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
65
63
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
66
64
  import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
65
+ import { useRules } from "@dative-gpi/foundation-shared-components/composables";
67
66
 
68
67
  import FSDialogSubmit from "../FSDialogSubmit.vue";
69
68
  import FSCalendarTwin from "../FSCalendarTwin.vue";
@@ -122,29 +121,12 @@ export default defineComponent({
122
121
  },
123
122
  emits: ["update:modelValue"],
124
123
  setup(props, { emit }) {
125
- const { validateOn, blurred, getMessages } = useRules();
124
+ const { validateOn, getMessages } = useRules();
126
125
  const { epochToShortDateFormat } = useAppTimeZone();
127
- const { getColors } = useColors();
128
-
129
- const errors = getColors(ColorEnum.Error);
130
- const lights = getColors(ColorEnum.Light);
131
- const darks = getColors(ColorEnum.Dark);
132
126
 
133
127
  const dialog = ref(false);
134
128
  const innerDateRange = ref<number[] | null>(props.modelValue);
135
129
 
136
- const style = computed((): { [key: string] : string | null | undefined } => {
137
- if (!props.editable) {
138
- return {
139
- "--fs-date-field-color": lights.dark
140
- };
141
- }
142
- return {
143
- "--fs-date-field-color" : darks.base,
144
- "--fs-date-field-error-color": errors.base
145
- };
146
- });
147
-
148
130
  const toShortDateFormat = computed((): string => {
149
131
  if (!props.modelValue || !Array.isArray(props.modelValue) || !props.modelValue.length) {
150
132
  return "";
@@ -171,14 +153,12 @@ export default defineComponent({
171
153
  };
172
154
 
173
155
  return {
174
- ColorEnum,
156
+ toShortDateFormat,
157
+ innerDateRange,
175
158
  validateOn,
159
+ ColorEnum,
176
160
  messages,
177
- blurred,
178
- style,
179
161
  dialog,
180
- toShortDateFormat,
181
- innerDateRange,
182
162
  onClick,
183
163
  onClear,
184
164
  onSubmit
@@ -19,7 +19,6 @@
19
19
  :modelValue="epochToLongTimeFormat($props.modelValue)"
20
20
  @update:modelValue="onClear"
21
21
  @click="openMobileOverlay"
22
- @blur="blurred = true"
23
22
  >
24
23
  <template
25
24
  #prepend-inner
@@ -115,7 +114,6 @@
115
114
  :validationValue="$props.modelValue"
116
115
  :modelValue="epochToLongTimeFormat($props.modelValue)"
117
116
  @update:modelValue="onClear"
118
- @blur="blurred = true"
119
117
  v-bind="props"
120
118
  >
121
119
  <template
@@ -197,7 +195,7 @@
197
195
  <script lang="ts">
198
196
  import { computed, defineComponent, PropType, ref, watch } from "vue";
199
197
 
200
- import { useBreakpoints, useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
198
+ import { useBreakpoints, useRules } from "@dative-gpi/foundation-shared-components/composables";
201
199
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
202
200
  import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
203
201
 
@@ -267,9 +265,8 @@ export default defineComponent({
267
265
  emits: ["update:modelValue"],
268
266
  setup(props, { emit }) {
269
267
  const { getUserOffsetMillis, epochToLongTimeFormat } = useAppTimeZone();
270
- const { validateOn, blurred, getMessages } = useRules();
268
+ const { validateOn, getMessages } = useRules();
271
269
  const { isExtraSmall } = useBreakpoints();
272
- const { getColors } = useColors();
273
270
 
274
271
  const dialog = ref(false);
275
272
  const menu = ref(false);
@@ -277,10 +274,6 @@ export default defineComponent({
277
274
  const innerDate = ref<number | null>(null);
278
275
  const innerTime = ref(0);
279
276
 
280
- const errors = getColors(ColorEnum.Error);
281
- const lights = getColors(ColorEnum.Light);
282
- const darks = getColors(ColorEnum.Dark);
283
-
284
277
  if (props.modelValue) {
285
278
  // FSClock just gives two numbers without consideration for the time zone
286
279
  // We must adjust the time to the user's time zone
@@ -288,18 +281,6 @@ export default defineComponent({
288
281
  innerDate.value = props.modelValue - innerTime.value;
289
282
  }
290
283
 
291
- const style = computed((): { [key: string] : string | null | undefined } => {
292
- if (!props.editable) {
293
- return {
294
- "--fs-date-field-color": lights.dark
295
- };
296
- }
297
- return {
298
- "--fs-date-field-color" : darks.base,
299
- "--fs-date-field-error-color": errors.base
300
- };
301
- });
302
-
303
284
  const messages = computed((): string[] => getMessages(props.modelValue, props.rules));
304
285
 
305
286
  const openMobileOverlay = () => {
@@ -334,9 +315,7 @@ export default defineComponent({
334
315
  innerDate,
335
316
  innerTime,
336
317
  messages,
337
- blurred,
338
318
  dialog,
339
- style,
340
319
  menu,
341
320
  tabs,
342
321
  epochToLongTimeFormat,
@@ -15,7 +15,6 @@
15
15
  :modelValue="toShortTimeFormat"
16
16
  @click="onClick"
17
17
  @update:modelValue="onClear"
18
- @blur="blurred = true"
19
18
  >
20
19
  <template
21
20
  #prepend-inner
@@ -79,9 +78,9 @@
79
78
  <script lang="ts">
80
79
  import { computed, defineComponent, PropType, ref } from "vue";
81
80
 
82
- import { useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
83
81
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
84
82
  import { useAppTimeZone } from "@dative-gpi/foundation-shared-services/composables";
83
+ import { useRules } from "@dative-gpi/foundation-shared-components/composables";
85
84
 
86
85
  import FSDialogSubmit from "../FSDialogSubmit.vue";
87
86
  import FSCalendarTwin from "../FSCalendarTwin.vue";
@@ -147,12 +146,7 @@ export default defineComponent({
147
146
  emits: ["update:modelValue"],
148
147
  setup(props, { emit }) {
149
148
  const { getUserOffsetMillis, epochToShortTimeFormat } = useAppTimeZone();
150
- const { validateOn, blurred, getMessages } = useRules();
151
- const { getColors } = useColors();
152
-
153
- const errors = getColors(ColorEnum.Error);
154
- const lights = getColors(ColorEnum.Light);
155
- const darks = getColors(ColorEnum.Dark);
149
+ const { validateOn, getMessages } = useRules();
156
150
 
157
151
  const dialog = ref(false);
158
152
  const innerDateRange = ref<number[] | null>(null);
@@ -180,18 +174,6 @@ export default defineComponent({
180
174
  }
181
175
  }
182
176
 
183
- const style = computed((): { [key: string] : string | null | undefined } => {
184
- if (!props.editable) {
185
- return {
186
- "--fs-date-field-color": lights.dark
187
- };
188
- }
189
- return {
190
- "--fs-date-field-color" : darks.base,
191
- "--fs-date-field-error-color": errors.base
192
- };
193
- });
194
-
195
177
  const toShortTimeFormat = computed((): string => {
196
178
  if (!props.modelValue || !Array.isArray(props.modelValue) || !props.modelValue.length) {
197
179
  return "";
@@ -236,21 +218,19 @@ export default defineComponent({
236
218
  };
237
219
 
238
220
  return {
239
- ColorEnum,
240
- validateOn,
241
- messages,
242
- blurred,
243
- style,
244
- dialog,
245
221
  toShortTimeFormat,
246
222
  innerDateLeft,
247
223
  innerTimeLeft,
248
224
  innerDateRight,
249
225
  innerTimeRight,
250
226
  innerDateRange,
251
- onClick,
227
+ validateOn,
228
+ ColorEnum,
229
+ messages,
230
+ dialog,
231
+ onSubmit,
252
232
  onClear,
253
- onSubmit
233
+ onClick
254
234
  };
255
235
  }
256
236
  });
@@ -10,7 +10,6 @@
10
10
  :messages="messages"
11
11
  :validateOn="validateOn"
12
12
  :validationValue="$props.modelValue"
13
- @blur="blurred = true"
14
13
  v-model="innerValue"
15
14
  v-bind="$attrs"
16
15
  >
@@ -125,7 +124,7 @@ export default defineComponent({
125
124
  },
126
125
  emits: ["update:modelValue"],
127
126
  setup(props) {
128
- const { validateOn, blurred, getMessages } = useRules();
127
+ const { validateOn, getMessages } = useRules();
129
128
  const { getColors } = useColors();
130
129
 
131
130
  const errors = getColors(ColorEnum.Error);
@@ -201,7 +200,6 @@ export default defineComponent({
201
200
  innerValue,
202
201
  validateOn,
203
202
  messages,
204
- blurred,
205
203
  style,
206
204
  icons
207
205
  };
@@ -18,7 +18,6 @@
18
18
  :modelValue="mobileValue"
19
19
  @update:modelValue="$emit('update:modelValue', $event)"
20
20
  @click="openMobileOverlay"
21
- @blur="blurred = true"
22
21
  v-bind="$attrs"
23
22
  >
24
23
  <template
@@ -140,7 +139,6 @@
140
139
  :multiple="$props.multiple"
141
140
  :modelValue="$props.modelValue"
142
141
  @update:modelValue="$emit('update:modelValue', $event)"
143
- @blur="blurred = true"
144
142
  v-bind="$attrs"
145
143
  >
146
144
  <template
@@ -346,7 +344,7 @@ export default defineComponent({
346
344
  },
347
345
  emits: ["update:modelValue"],
348
346
  setup(props, { emit }) {
349
- const { validateOn, blurred, getMessages } = useRules();
347
+ const { validateOn, getMessages } = useRules();
350
348
  const { isExtraSmall } = useBreakpoints();
351
349
  const { getColors } = useColors();
352
350
 
@@ -450,26 +448,59 @@ export default defineComponent({
450
448
  dialog.value = true;
451
449
  };
452
450
 
453
- const onRadioChange = (value: any) => {
454
- emit('update:modelValue', value);
451
+ const onRadioChange = (value: string | null) => {
452
+ if (props.returnObject) {
453
+ emit("update:modelValue", props.items.find((item: any) => item[props.itemValue] === value) ?? null);
454
+ }
455
+ else {
456
+ emit("update:modelValue", value);
457
+ }
455
458
  dialog.value = false;
456
459
  };
457
460
 
458
- const onCheckboxChange = (value: any) => {
459
- if (Array.isArray(props.modelValue)) {
460
- if (props.modelValue.includes(value)) {
461
- emit('update:modelValue', props.modelValue.filter((item: any) => item !== value));
461
+ const onCheckboxChange = (value: string) => {
462
+ if (props.returnObject) {
463
+ const item = props.items.find(item => item[props.itemValue] === value);
464
+ if (Array.isArray(props.modelValue)) {
465
+ if (props.modelValue.find(item => item[props.itemValue] === value)) {
466
+ emit("update:modelValue", props.modelValue.filter((item: any) => item[props.itemValue] !== value));
467
+ }
468
+ else {
469
+ if (item) {
470
+ emit("update:modelValue", [...props.modelValue, item]);
471
+ }
472
+ }
462
473
  }
463
474
  else {
464
- emit('update:modelValue', [...props.modelValue, value]);
475
+ if (props.modelValue) {
476
+ if (props.modelValue[props.itemValue] === value) {
477
+ emit("update:modelValue", []);
478
+ }
479
+ else {
480
+ emit("update:modelValue", [props.modelValue, item]);
481
+ }
482
+ }
483
+ else {
484
+ emit("update:modelValue", [item]);
485
+ }
465
486
  }
466
487
  }
467
488
  else {
468
- if (props.modelValue === value) {
469
- emit('update:modelValue', []);
489
+ if (Array.isArray(props.modelValue)) {
490
+ if (props.modelValue.includes(value)) {
491
+ emit("update:modelValue", props.modelValue.filter((item: any) => item !== value));
492
+ }
493
+ else {
494
+ emit("update:modelValue", [...props.modelValue, value]);
495
+ }
470
496
  }
471
497
  else {
472
- emit('update:modelValue', [props.modelValue, value]);
498
+ if (props.modelValue === value) {
499
+ emit("update:modelValue", []);
500
+ }
501
+ else {
502
+ emit("update:modelValue", [props.modelValue, value]);
503
+ }
473
504
  }
474
505
  }
475
506
  };
@@ -482,7 +513,6 @@ export default defineComponent({
482
513
  ColorEnum,
483
514
  listStyle,
484
515
  messages,
485
- blurred,
486
516
  dialog,
487
517
  height,
488
518
  style,
@@ -11,7 +11,6 @@
11
11
  :validateOn="validateOn"
12
12
  :validationValue="$props.modelValue"
13
13
  @keydown.enter="onAdd"
14
- @blur="blurred = true"
15
14
  v-model="innerValue"
16
15
  v-bind="$attrs"
17
16
  >
@@ -118,7 +117,7 @@ export default defineComponent({
118
117
  },
119
118
  emits: ["update:modelValue"],
120
119
  setup(props, { emit }) {
121
- const {validateOn, blurred, getMessages} = useRules();
120
+ const {validateOn, getMessages} = useRules();
122
121
  const { getColors } = useColors();
123
122
 
124
123
  const errors = getColors(ColorEnum.Error);
@@ -171,7 +170,6 @@ export default defineComponent({
171
170
  validateOn,
172
171
  ColorEnum,
173
172
  messages,
174
- blurred,
175
173
  style,
176
174
  onRemove,
177
175
  onAdd
@@ -23,7 +23,6 @@
23
23
  :validateOn="validateOn"
24
24
  :modelValue="$props.modelValue"
25
25
  @update:modelValue="$emit('update:modelValue', $event)"
26
- @blur="blurred = true"
27
26
  v-bind="$attrs"
28
27
  >
29
28
  <template
@@ -128,7 +127,7 @@ export default defineComponent({
128
127
  },
129
128
  emits: ["update:modelValue"],
130
129
  setup(props) {
131
- const { validateOn, blurred, getMessages } = useRules();
130
+ const { validateOn, getMessages } = useRules();
132
131
  const { isMobileSized } = useBreakpoints();
133
132
  const { getColors } = useColors();
134
133
 
@@ -185,7 +184,6 @@ export default defineComponent({
185
184
  validateOn,
186
185
  ColorEnum,
187
186
  messages,
188
- blurred,
189
187
  classes,
190
188
  style
191
189
  };
@@ -20,7 +20,6 @@
20
20
  :validateOn="validateOn"
21
21
  :modelValue="$props.modelValue"
22
22
  @update:modelValue="$emit('update:modelValue', $event)"
23
- @blur="blurred = true"
24
23
  v-bind="$attrs"
25
24
  >
26
25
  <template
@@ -116,7 +115,7 @@ export default defineComponent({
116
115
  },
117
116
  emits: ["update:modelValue"],
118
117
  setup(props) {
119
- const { validateOn, blurred, getMessages } = useRules();
118
+ const { validateOn, getMessages } = useRules();
120
119
  const { getColors } = useColors();
121
120
 
122
121
  const errors = getColors(ColorEnum.Error);
@@ -147,7 +146,6 @@ export default defineComponent({
147
146
  validateOn,
148
147
  ColorEnum,
149
148
  messages,
150
- blurred,
151
149
  style
152
150
  };
153
151
  }
@@ -106,7 +106,7 @@ export default defineComponent({
106
106
  },
107
107
  emits: ["update:modelValue"],
108
108
  setup(props, { emit }) {
109
- const { validateOn, blurred, getMessages } = useRules();
109
+ const { validateOn, getMessages } = useRules();
110
110
  const { getColors } = useColors();
111
111
 
112
112
  const errors = getColors(ColorEnum.Error);
@@ -163,7 +163,6 @@ export default defineComponent({
163
163
  innerTime,
164
164
  timeScale,
165
165
  messages,
166
- blurred,
167
166
  style,
168
167
  onSubmitTimeScale,
169
168
  onSubmitValue
@@ -0,0 +1,148 @@
1
+ <template>
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
+ <FSToggleSet
11
+ variant="slide"
12
+ :buttonColor="buttonColor"
13
+ :values="$props.items"
14
+ :multiple="$props.multiple"
15
+ :required="$props.required"
16
+ :editable="$props.editable"
17
+ :modelValue="$props.modelValue"
18
+ @update:modelValue="onUpdate"
19
+ v-bind="$attrs"
20
+ >
21
+ <template
22
+ v-for="(_, name) in $slots"
23
+ v-slot:[name]="slotData"
24
+ >
25
+ <slot
26
+ :name="name"
27
+ v-bind="slotData"
28
+ />
29
+ </template>
30
+ </FSToggleSet>
31
+ </FSBaseField>
32
+ </template>
33
+
34
+ <script lang="ts">
35
+ import { computed, defineComponent, PropType, ref } from "vue";
36
+
37
+ import { useRules } from "../../composables";
38
+ import { ColorEnum } from "../../models";
39
+
40
+ import FSToggleSet from "../FSToggleSet.vue";
41
+ import FSBaseField from "./FSBaseField.vue";
42
+
43
+ export default defineComponent({
44
+ name: "FSTextField",
45
+ components: {
46
+ FSBaseField,
47
+ FSToggleSet
48
+ },
49
+ props: {
50
+ label: {
51
+ type: String as PropType<string | null>,
52
+ required: false,
53
+ default: null
54
+ },
55
+ description: {
56
+ type: String as PropType<string | null>,
57
+ required: false,
58
+ default: null
59
+ },
60
+ items: {
61
+ type: Array as PropType<any[]>,
62
+ required: true
63
+ },
64
+ itemValue: {
65
+ type: String,
66
+ required: false,
67
+ default: "id"
68
+ },
69
+ itemTitle: {
70
+ type: String,
71
+ required: false,
72
+ default: "label"
73
+ },
74
+ modelValue: {
75
+ type: [Array, String] as PropType<string[] | string | null>,
76
+ required: false,
77
+ default: null
78
+ },
79
+ multiple: {
80
+ type: Boolean,
81
+ required: false,
82
+ default: false
83
+ },
84
+ hideHeader: {
85
+ type: Boolean,
86
+ required: false,
87
+ default: false
88
+ },
89
+ returnObject: {
90
+ type: Boolean,
91
+ required: false,
92
+ default: false
93
+ },
94
+ required: {
95
+ type: Boolean,
96
+ required: false,
97
+ default: false
98
+ },
99
+ rules: {
100
+ type: Array as PropType<any[]>,
101
+ required: false,
102
+ default: () => []
103
+ },
104
+ editable: {
105
+ type: Boolean,
106
+ required: false,
107
+ default: true
108
+ }
109
+ },
110
+ emits: ["update:modelValue"],
111
+ setup(props, { emit }) {
112
+ const { forceErrors, getMessages } = useRules();
113
+
114
+ const updated = ref(false);
115
+
116
+ const messages = computed((): string[] => getMessages(props.modelValue, props.rules));
117
+
118
+ const buttonColor = computed((): ColorEnum => {
119
+ if (forceErrors(messages.value.length, updated.value)) {
120
+ return ColorEnum.Error;
121
+ }
122
+ return ColorEnum.Light;
123
+ });
124
+
125
+ const onUpdate = (value: string[] | string | null) => {
126
+ updated.value = true;
127
+ if (props.returnObject) {
128
+ if (Array.isArray(value)) {
129
+ emit("update:modelValue", props.items.filter((item: any) => value.includes(item[props.itemValue])));
130
+ }
131
+ else {
132
+ emit("update:modelValue", props.items.find((item: any) => item[props.itemValue] === value) ?? null);
133
+ }
134
+ }
135
+ else {
136
+ emit("update:modelValue", value);
137
+ }
138
+ };
139
+
140
+ return {
141
+ buttonColor,
142
+ ColorEnum,
143
+ messages,
144
+ onUpdate
145
+ };
146
+ }
147
+ });
148
+ </script>
@@ -110,20 +110,20 @@
110
110
  <v-data-table
111
111
  v-if="!isExtraSmall"
112
112
  :selectStrategy="$props.singleSelect ? 'single' : 'all'"
113
- :itemValue="$props.itemValue"
114
- :showSelect="$props.showSelect"
115
- :headers="extraHeaders.concat(innerHeaders)"
116
113
  :groupBy="$props.groupBy ? [$props.groupBy] : []"
114
+ :headers="extraHeaders.concat(innerHeaders)"
117
115
  :sortBy="innerSortBy ? [innerSortBy] : []"
118
- :items="innerItems"
116
+ :itemsPerPage="innerRowsPerPage"
117
+ :showSelect="$props.showSelect"
118
+ :hover="!$props.sortDraggable"
119
+ :itemValue="$props.itemValue"
120
+ :rowProps="rowProps"
119
121
  :fixedHeader="true"
122
+ :items="innerItems"
120
123
  :multiSort="false"
121
- :hover="!$props.sortDraggable"
122
- :style="style"
123
- :row-props="rowProps"
124
- :class="classes"
125
124
  :page="innerPage"
126
- :itemsPerPage="innerRowsPerPage"
125
+ :class="classes"
126
+ :style="style"
127
127
  :modelValue="$props.modelValue"
128
128
  @auxclick:row="onClickLibrary.row"
129
129
  @click:row="onClickLibrary.row"
@@ -404,9 +404,9 @@
404
404
  <v-data-iterator
405
405
  v-else
406
406
  class="fs-data-table-iterator"
407
+ :itemsPerPage="innerRowsPerPage"
407
408
  :items="innerItems"
408
409
  :page="innerPage"
409
- :itemsPerPage="innerRowsPerPage"
410
410
  >
411
411
  <template
412
412
  #default="{ items }"
@@ -644,7 +644,7 @@
644
644
  </template>
645
645
 
646
646
  <script lang="ts">
647
- import { computed, defineComponent, onMounted, onUnmounted, PropType, ref, Ref, Slot, watch } from "vue";
647
+ import { computed, defineComponent, nextTick, onMounted, onUnmounted, PropType, ref, Ref, Slot, watch } from "vue";
648
648
  import { useRouter } from "vue-router";
649
649
 
650
650
  import { ColorEnum, FSDataTableColumn, FSDataTableFilter, FSDataTableOrder, FSToggle } from "@dative-gpi/foundation-shared-components/models";
@@ -1110,9 +1110,6 @@ export default defineComponent({
1110
1110
  const toggleFilter = (header: string, value: FSDataTableFilter[]): void => {
1111
1111
  filters.value[header] = value;
1112
1112
  emit("update:filters", filters.value);
1113
- // If a filter is hidden, the associated filter is reseted
1114
- resetable.value = Object.keys(filters.value)
1115
- .some((key) => filters.value[key].some((filter) => filter.hidden));
1116
1113
  };
1117
1114
 
1118
1115
  const resetFilter = (): void => {
@@ -1120,7 +1117,6 @@ export default defineComponent({
1120
1117
  filters.value[key] = filters.value[key].map((filter) => ({ ...filter, hidden: false }));
1121
1118
  }
1122
1119
  emit("update:filters", filters.value);
1123
- resetable.value = false;
1124
1120
  };
1125
1121
 
1126
1122
  const filterSlot = (header: FSDataTableColumn): string => {
@@ -1136,8 +1132,6 @@ export default defineComponent({
1136
1132
  innerColumn.hidden = value as boolean;
1137
1133
  if (value && filters.value[header.value!]) {
1138
1134
  filters.value[header.value!] = filters.value[header.value!].map((filter) => ({ ...filter, hidden: false }));
1139
- resetable.value = Object.keys(filters.value)
1140
- .some((key) => filters.value[key].some((filter) => filter.hidden));
1141
1135
  emit("update:filters", filters.value);
1142
1136
  }
1143
1137
  break;
@@ -1432,6 +1426,11 @@ export default defineComponent({
1432
1426
  innerPage.value = 1;
1433
1427
  });
1434
1428
 
1429
+ watch(filters, () => {
1430
+ resetable.value = Object.keys(filters.value)
1431
+ .some((key) => filters.value[key].some((filter) => filter.hidden));
1432
+ }, { deep: true });
1433
+
1435
1434
  watch(innerMode, () => {
1436
1435
  emit("update:mode", innerMode.value);
1437
1436
  size.value = props.sizeIterator;
@@ -1450,8 +1449,18 @@ export default defineComponent({
1450
1449
  emit("update:rowsPerPage", innerRowsPerPage.value);
1451
1450
  });
1452
1451
 
1453
- watch([() => props.headers, () => props.items], () => {
1452
+ watch(() => props.headers, () => {
1453
+ computeFilters();
1454
+ });
1455
+
1456
+ watch(() => props.items, async () => {
1454
1457
  computeFilters();
1458
+ if (innerPage.value !== 1) {
1459
+ const formerPage = innerPage.value;
1460
+ innerPage.value = 1;
1461
+ await nextTick();
1462
+ innerPage.value = formerPage;
1463
+ }
1455
1464
  });
1456
1465
 
1457
1466
  return {
@@ -1,19 +1,26 @@
1
1
  import { Ref, computed, inject, ref } from "vue";
2
2
 
3
3
  export const useRules = () => {
4
- const innerValidateOn = inject<Ref<"submit" | "blur" | "input">>("validateOn", ref('input'));
4
+ const innerValidateOn = inject<Ref<"submit" | "input">>("validateOn", ref('input'));
5
5
  const submitted = inject<Ref<boolean>>("submitted", ref(false));
6
6
 
7
- const blurred = ref(false);
8
-
9
- const validateOn = computed((): "input" | "submit" | "blur" => {
7
+ const validateOn = computed((): "input" | "submit" => {
10
8
  switch (innerValidateOn.value) {
11
9
  case "submit": return submitted.value ? "input" : "submit";
12
- case "blur": return blurred.value ? "input" : "blur";
13
10
  case "input": return "input";
14
11
  }
15
12
  });
16
13
 
14
+ const forceErrors = (messagesLength: number, updated: boolean): boolean => {
15
+ if (messagesLength <= 0) {
16
+ return false;
17
+ }
18
+ switch (innerValidateOn.value) {
19
+ case "submit": return submitted.value;
20
+ case "input": return submitted.value || updated;
21
+ }
22
+ }
23
+
17
24
  const getMessages = (modelValue: any, rules: any[], checkArray: boolean = false): string[] => {
18
25
  if (!rules || !rules.length) {
19
26
  return [];
@@ -24,11 +31,6 @@ export const useRules = () => {
24
31
  return [];
25
32
  }
26
33
  break;
27
- case "blur":
28
- if (!blurred.value) {
29
- return [];
30
- }
31
- break;
32
34
  case "input":
33
35
  break;
34
36
  }
@@ -69,7 +71,7 @@ export const useRules = () => {
69
71
 
70
72
  return {
71
73
  validateOn,
72
- blurred,
74
+ forceErrors,
73
75
  getMessages
74
76
  };
75
77
  }
package/models/rules.ts CHANGED
@@ -13,7 +13,7 @@ export const TextRules = {
13
13
  min: (min: number, message: string | undefined = undefined) => (value: string) => value.length >= min || (message ?? $tr("ui.rules.text-min", "Must be at least {0} characters", min.toString())),
14
14
  max: (max: number, message: string | undefined = undefined) => (value: string) => value.length <= max || (message ?? $tr("ui.rules.text-max", "Must be at most {0} characters", max.toString())),
15
15
  email: (message: string | undefined = undefined) => (value: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || (message ?? $tr("ui.rules.text-email", "Must be a valid email")),
16
- phone: (message: string | undefined = undefined) => (value: string) => /^[+]?([0-9]+[ -]?)+$/.test(value) || (message ?? $tr("ui.rules.text-phone", "Must be a valid phone number")),
16
+ phone: (message: string | undefined = undefined) => (value: string) => /^[+]?([0-9]+[ -]?){7,}$/.test(value) || (message ?? $tr("ui.rules.text-phone", "Must be a valid phone number")),
17
17
  digit: (message: string | undefined = undefined) => (value: string) => /(?=.*\d)/.test(value) || (message ?? $tr("ui.rules.text-digit", "Must contain a digit")),
18
18
  uppercase: (message: string | undefined = undefined) => (value: string) => /(?=.*[A-Z])/.test(value) || (message ?? $tr("ui.rules.text-uppercase", "Must contain an uppercase letter")),
19
19
  lowercase: (message: string | undefined = undefined) => (value: string) => /(?=.*[a-z])/.test(value) || (message ?? $tr("ui.rules.text-lowercase", "Must contain a lowercase letter")),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dative-gpi/foundation-shared-components",
3
3
  "sideEffects": false,
4
- "version": "0.0.126",
4
+ "version": "0.0.128",
5
5
  "description": "",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -10,8 +10,8 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
- "@dative-gpi/foundation-shared-domain": "0.0.126",
14
- "@dative-gpi/foundation-shared-services": "0.0.126",
13
+ "@dative-gpi/foundation-shared-domain": "0.0.128",
14
+ "@dative-gpi/foundation-shared-services": "0.0.128",
15
15
  "@fontsource/montserrat": "^5.0.16",
16
16
  "@lexical/clipboard": "^0.12.5",
17
17
  "@lexical/history": "^0.12.5",
@@ -32,5 +32,5 @@
32
32
  "sass": "^1.69.5",
33
33
  "sass-loader": "^13.3.2"
34
34
  },
35
- "gitHead": "f82b3f9604201db4e53ee4c03e6344fc289eb35f"
35
+ "gitHead": "29d087178fe21c8c415df60c4466755789860cbb"
36
36
  }