@dative-gpi/foundation-shared-components 0.0.6 → 0.0.8

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 (37) hide show
  1. package/components/FSButton.vue +170 -164
  2. package/components/FSCalendar.vue +171 -0
  3. package/components/FSCalendarTwin.vue +394 -0
  4. package/components/FSCard.vue +63 -0
  5. package/components/FSCheckbox.vue +7 -8
  6. package/components/FSClock.vue +38 -0
  7. package/components/FSDatePicker.vue +226 -0
  8. package/components/FSIcon.vue +1 -1
  9. package/components/FSNumberField.vue +4 -4
  10. package/components/FSPasswordField.vue +14 -12
  11. package/components/FSRadio.vue +0 -1
  12. package/components/FSRadioGroup.vue +6 -6
  13. package/components/FSRichTextField.vue +558 -0
  14. package/components/FSSearchField.vue +103 -102
  15. package/components/FSSlider.vue +132 -0
  16. package/components/FSSwitch.vue +9 -9
  17. package/components/FSTagField.vue +186 -127
  18. package/components/FSTextArea.vue +207 -0
  19. package/components/FSTextField.vue +151 -146
  20. package/composables/index.ts +2 -1
  21. package/composables/useBreakpoints.ts +14 -0
  22. package/composables/useDates.ts +39 -0
  23. package/models/FSTextFields.ts +12 -6
  24. package/package.json +12 -4
  25. package/styles/components/fs_button.scss +2 -10
  26. package/styles/components/fs_calendar.scss +115 -0
  27. package/styles/components/fs_card.scss +7 -0
  28. package/styles/components/fs_date_picker.scss +0 -0
  29. package/styles/components/fs_icon.scss +3 -9
  30. package/styles/components/fs_rich_text_field.scss +67 -0
  31. package/styles/components/fs_slider.scss +20 -0
  32. package/styles/components/fs_tag_field.scss +9 -0
  33. package/styles/components/fs_text_area.scss +105 -0
  34. package/styles/components/index.scss +6 -0
  35. package/utils/FSRichTextField.ts +27 -0
  36. package/utils/index.ts +1 -0
  37. package/composables/useTouch.ts +0 -9
@@ -0,0 +1,394 @@
1
+ <template>
2
+ <FSCol>
3
+ <FSRow>
4
+ <FSSpan
5
+ v-if="$props.label"
6
+ class="fs-calendar-label"
7
+ font="text-overline"
8
+ >
9
+ {{ $props.label }}
10
+ </FSSpan>
11
+ </FSRow>
12
+ <FSRow>
13
+ <FSCol
14
+ :class="leftClasses"
15
+ :style="style"
16
+ >
17
+ <FSRow
18
+ class="fs-calendar-header"
19
+ align="center-center"
20
+ >
21
+ <FSButton
22
+ size="l"
23
+ variant="icon"
24
+ icon="mdi-chevron-left"
25
+ @click="onClickPrevious"
26
+ />
27
+ <FSSpan
28
+ class="fs-calendar-text"
29
+ font="text-h3"
30
+ >
31
+ {{ leftText }}
32
+ </FSSpan>
33
+ <div />
34
+ </FSRow>
35
+ <div
36
+ class="fs-calendar-divider"
37
+ :style="style"
38
+ />
39
+ <v-locale-provider :locale="languageCode">
40
+ <v-date-picker-month
41
+ :month="innerLeftMonth"
42
+ :year="innerLeftYear"
43
+ :multiple="true"
44
+ :modelValue="datesTools.epochToPicker(innerLeftValue)"
45
+ @update:modelValue="onClickLeft"
46
+ @update:month="null"
47
+ @update:year="null"
48
+ />
49
+ </v-locale-provider>
50
+ </FSCol>
51
+ <FSCol
52
+ :class="rightClasses"
53
+ :style="style"
54
+ >
55
+ <FSRow
56
+ class="fs-calendar-header"
57
+ align="center-center"
58
+ >
59
+ <div />
60
+ <FSSpan
61
+ class="fs-calendar-text"
62
+ font="text-h3"
63
+ >
64
+ {{ rightText }}
65
+ </FSSpan>
66
+ <FSButton
67
+ size="l"
68
+ variant="icon"
69
+ icon="mdi-chevron-right"
70
+ @click="onClickNext"
71
+ />
72
+ </FSRow>
73
+ <div
74
+ class="fs-calendar-divider"
75
+ :style="style"
76
+ />
77
+ <v-locale-provider :locale="languageCode">
78
+ <v-date-picker-month
79
+ :month="innerRightMonth"
80
+ :year="innerRightYear"
81
+ :multiple="true"
82
+ :modelValue="datesTools.epochToPicker(innerRightValue)"
83
+ @update:modelValue="onClickRight"
84
+ @update:month="null"
85
+ @update:year="null"
86
+ />
87
+ </v-locale-provider>
88
+ </FSCol>
89
+ </FSRow>
90
+ </FSCol>
91
+ </template>
92
+
93
+ <script lang="ts">
94
+ import { computed, defineComponent, onMounted, PropType, ref, toRefs } from "vue";
95
+ import { useDate as useAdapter } from "vuetify/lib/composables/date/index.mjs";
96
+
97
+ import { useColors, useDates } from "@dative-gpi/foundation-shared-components/composables";
98
+ import { useLanguageCode } from "@dative-gpi/foundation-shared-services/composables";
99
+ import { ColorBase } from "@dative-gpi/foundation-shared-components/themes";
100
+
101
+ import FSButton from "./FSButton.vue";
102
+ import FSSpan from "./FSSpan.vue";
103
+ import FSCol from "./FSCol.vue";
104
+ import FSRow from "./FSRow.vue";
105
+
106
+ export default defineComponent({
107
+ name: "FSCalendarTwin",
108
+ components: {
109
+ FSButton,
110
+ FSSpan,
111
+ FSCol,
112
+ FSRow
113
+ },
114
+ props: {
115
+ label: {
116
+ type: String,
117
+ required: false,
118
+ default: null
119
+ },
120
+ modelValue: {
121
+ type: Array as PropType<Array<number>>,
122
+ required: false,
123
+ default: null
124
+ },
125
+ color: {
126
+ type: String as PropType<ColorBase>,
127
+ required: false,
128
+ default: ColorBase.Dark
129
+ },
130
+ buttonColor: {
131
+ type: String as PropType<ColorBase>,
132
+ required: false,
133
+ default: ColorBase.Primary
134
+ }
135
+ },
136
+ emits: ["update:modelValue"],
137
+ setup(props, { emit }) {
138
+ const { modelValue, color, buttonColor } = toRefs(props);
139
+
140
+ const languageCode = useLanguageCode().languageCode;
141
+ const datesTools = useDates();
142
+ const adapter = useAdapter();
143
+
144
+ const colors = useColors().getColors(color.value);
145
+ const buttonColors = useColors().getColors(buttonColor.value);
146
+
147
+ const backgrounds = useColors().getColors(ColorBase.Background);
148
+
149
+ const innerLeftMonth = ref(new Date().getMonth());
150
+ const innerLeftYear = ref(new Date().getFullYear());
151
+
152
+ const innerRightMonth = ref(new Date().getMonth());
153
+ const innerRightYear = ref(new Date().getFullYear());
154
+
155
+ const toggle = ref(modelValue.value.length % 2);
156
+
157
+ onMounted((): void => {
158
+ switch (modelValue.value.length) {
159
+ case 0:
160
+ innerLeftMonth.value = new Date().getMonth();
161
+ innerLeftYear.value = new Date().getFullYear();
162
+ if (innerLeftMonth.value < 11) {
163
+ innerRightMonth.value = innerLeftMonth.value + 1;
164
+ innerRightYear.value = innerLeftYear.value;
165
+ }
166
+ else {
167
+ innerRightMonth.value = 0;
168
+ innerRightYear.value = innerLeftYear.value + 1;
169
+ }
170
+ break;
171
+ default:
172
+ innerLeftMonth.value = datesTools.epochToPickerHeader(modelValue.value[0]).m;
173
+ innerLeftYear.value = datesTools.epochToPickerHeader(modelValue.value[0]).y;
174
+ if (innerLeftMonth.value < 11) {
175
+ innerRightMonth.value = innerLeftMonth.value + 1;
176
+ innerRightYear.value = innerLeftYear.value;
177
+ }
178
+ else {
179
+ innerRightMonth.value = 0;
180
+ innerRightYear.value = innerLeftYear.value + 1;
181
+ }
182
+ break;
183
+ }
184
+ });
185
+
186
+ const compare = (operator: "before" | "during" | "after", side: "left" | "right", date: { d: number, m: number, y: number }): boolean => {
187
+ switch (operator) {
188
+ case "before":
189
+ switch (side) {
190
+ case "left":
191
+ return innerLeftYear.value > date.y || (innerLeftYear.value === date.y && innerLeftMonth.value > date.m);
192
+ case "right":
193
+ return innerRightYear.value > date.y || (innerRightYear.value === date.y && innerRightMonth.value > date.m);
194
+ }
195
+ case "during":
196
+ switch (side) {
197
+ case "left":
198
+ return innerLeftYear.value === date.y && innerLeftMonth.value === date.m;
199
+ case "right":
200
+ return innerRightYear.value === date.y && innerRightMonth.value === date.m;
201
+ }
202
+ case "after":
203
+ switch (side) {
204
+ case "left":
205
+ return innerLeftYear.value < date.y || (innerLeftYear.value === date.y && innerLeftMonth.value < date.m);
206
+ case "right":
207
+ return innerRightYear.value < date.y || (innerRightYear.value === date.y && innerRightMonth.value < date.m);
208
+ }
209
+ }
210
+ }
211
+
212
+ const style = computed((): {[code: string]: string} & Partial<CSSStyleDeclaration> => {
213
+ return {
214
+ "--fs-calendar-background-color" : backgrounds.base,
215
+ "--fs-calendar-hover-background-color" : buttonColors.light,
216
+ "--fs-calendar-active-background-color": buttonColors.base,
217
+ "--fs-calendar-border-color" : colors.base,
218
+ "--fs-calendar-hover-border-color" : buttonColors.base,
219
+ "--fs-calendar-active-border-color" : buttonColors.base,
220
+ "--fs-calendar-color" : colors.base,
221
+ "--fs-calendar-hover-color" : buttonColors.base,
222
+ "--fs-calendar-active-color" : buttonColors.light
223
+ };
224
+ });
225
+
226
+ const innerLeftValue = computed((): number[] => {
227
+ return modelValue.value.filter(value =>
228
+ compare("during", "left", datesTools.epochToPickerHeader(value)) || compare("before", "left", datesTools.epochToPickerHeader(value))
229
+ );
230
+ });
231
+
232
+ const innerRightValue = computed((): number[] => {
233
+ return modelValue.value.filter(value =>
234
+ compare("during", "right", datesTools.epochToPickerHeader(value)) || compare("after", "right", datesTools.epochToPickerHeader(value))
235
+ );
236
+ });
237
+
238
+ const leftText = computed(() => {
239
+ adapter.locale = languageCode;
240
+ return adapter.format(
241
+ adapter.setYear(adapter.setMonth(adapter.date(), innerLeftMonth.value), innerLeftYear.value),
242
+ 'monthAndYear',
243
+ );
244
+ });
245
+
246
+ const rightText = computed(() => {
247
+ adapter.locale = languageCode;
248
+ return adapter.format(
249
+ adapter.setYear(adapter.setMonth(adapter.date(), innerRightMonth.value), innerRightYear.value),
250
+ 'monthAndYear',
251
+ );
252
+ });
253
+
254
+ const leftClasses = computed((): string[] => {
255
+ const classes = ["fs-calendar", "fs-calendar-left"];
256
+ if (modelValue.value.length > 1) {
257
+ const first = datesTools.epochToPickerHeader(modelValue.value[0]);
258
+ const last = datesTools.epochToPickerHeader(modelValue.value[1]);
259
+ if (compare("before", "left", first) && compare("after", "left", last)) {
260
+ classes.push("fs-calendar-full");
261
+ }
262
+ else if (compare("during", "left", first) && compare("during", "left", last)) {
263
+ if (first.d !== last.d) {
264
+ classes.push("fs-calendar-part");
265
+ }
266
+ }
267
+ else if (compare("during", "left", first)) {
268
+ classes.push("fs-calendar-start");
269
+ }
270
+ else if (compare("during", "left", last)) {
271
+ classes.push("fs-calendar-end");
272
+ }
273
+ }
274
+ return classes;
275
+ });
276
+
277
+ const rightClasses = computed((): string[] => {
278
+ const classes = ["fs-calendar", "fs-calendar-right"];
279
+ if (modelValue.value.length > 1) {
280
+ const first = datesTools.epochToPickerHeader(modelValue.value[0]);
281
+ const last = datesTools.epochToPickerHeader(modelValue.value[1]);
282
+ if (compare("before", "right", first) && compare("after", "right", last)) {
283
+ classes.push("fs-calendar-full");
284
+ }
285
+ else if (compare("during", "right", first) && compare("during", "right", last)) {
286
+ if (first.d !== last.d) {
287
+ classes.push("fs-calendar-part");
288
+ }
289
+ }
290
+ else if (compare("during", "right", first)) {
291
+ classes.push("fs-calendar-start");
292
+ }
293
+ else if (compare("during", "right", last)) {
294
+ classes.push("fs-calendar-end");
295
+ }
296
+ }
297
+ return classes;
298
+ });
299
+
300
+ const onClickPrevious = (): void => {
301
+ if (innerLeftMonth.value === 11) {
302
+ innerLeftMonth.value--;
303
+ innerRightMonth.value = 11;
304
+ innerRightYear.value--;
305
+ }
306
+ else if (innerLeftMonth.value === 0) {
307
+ innerLeftYear.value--;
308
+ innerLeftMonth.value = 11;
309
+ innerRightMonth.value--;
310
+ }
311
+ else {
312
+ innerLeftMonth.value--;
313
+ innerRightMonth.value--;
314
+ }
315
+ };
316
+
317
+ const onClickNext = (): void => {
318
+ if (innerRightMonth.value === 11) {
319
+ innerRightMonth.value = 0;
320
+ innerRightYear.value++;
321
+ innerLeftMonth.value++;
322
+ }
323
+ else if (innerRightMonth.value === 0) {
324
+ innerRightMonth.value++;
325
+ innerLeftMonth.value = 0;
326
+ innerLeftYear.value++;
327
+ }
328
+ else {
329
+ innerRightMonth.value++;
330
+ innerLeftMonth.value++;
331
+ }
332
+ };
333
+
334
+ const onClickLeft = (value: Date[]): void => {
335
+ const clicked = datesTools.pickerToEpoch([value[value.length - 1]])[0];
336
+ if (modelValue.value.length === 0) {
337
+ emit("update:modelValue", [clicked, clicked]);
338
+ }
339
+ else if (modelValue.value.length === 1) {
340
+ emit("update:modelValue", [modelValue.value[0], clicked].sort());
341
+ }
342
+ else {
343
+ if (innerLeftValue.value.length === 0) {
344
+ emit("update:modelValue", [clicked, modelValue.value[1]]);
345
+ }
346
+ else {
347
+ emit("update:modelValue", [clicked, modelValue.value[toggle.value]].sort());
348
+ toggle.value = (++toggle.value) % 2;
349
+ }
350
+ }
351
+ };
352
+
353
+ const onClickRight = (value: Date[]): void => {
354
+ const clicked = datesTools.pickerToEpoch([value[value.length - 1]])[0];
355
+ if (modelValue.value.length === 0) {
356
+ emit("update:modelValue", [clicked, clicked]);
357
+ }
358
+ else if (modelValue.value.length === 1) {
359
+ emit("update:modelValue", [modelValue.value[0], clicked].sort());
360
+ }
361
+ else {
362
+ if (innerRightValue.value.length === 0) {
363
+ emit("update:modelValue", [modelValue.value[0], clicked]);
364
+ }
365
+ else {
366
+ emit("update:modelValue", [clicked, modelValue.value[toggle.value]].sort());
367
+ toggle.value = (++toggle.value) % 2;
368
+ }
369
+ }
370
+ toggle.value = (++toggle.value) % 2;
371
+ };
372
+
373
+ return {
374
+ languageCode,
375
+ style,
376
+ leftClasses,
377
+ leftText,
378
+ innerLeftMonth,
379
+ innerLeftYear,
380
+ innerLeftValue,
381
+ rightClasses,
382
+ rightText,
383
+ innerRightMonth,
384
+ innerRightYear,
385
+ innerRightValue,
386
+ datesTools,
387
+ onClickPrevious,
388
+ onClickNext,
389
+ onClickLeft,
390
+ onClickRight
391
+ };
392
+ }
393
+ });
394
+ </script>
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <div
3
+ class="fs-card"
4
+ :style="style"
5
+ >
6
+ <slot name="default">
7
+ <FSCol>
8
+ <FSRow v-if="$slots.header">
9
+ <slot name="header" />
10
+ </FSRow>
11
+ <FSRow v-if="$slots.body">
12
+ <slot name="body" />
13
+ </FSRow>
14
+ <FSRow v-if="$slots.footer">
15
+ <slot name="footer" />
16
+ </FSRow>
17
+ </FSCol>
18
+ </slot>
19
+ </div>
20
+ </template>
21
+
22
+ <script lang="ts">
23
+ import { computed, defineComponent, PropType, toRefs } from "vue";
24
+
25
+ import { useColors } from "@dative-gpi/foundation-shared-components/composables";
26
+ import { ColorBase } from "@dative-gpi/foundation-shared-components/themes";
27
+
28
+ import FSCol from "./FSCol.vue";
29
+ import FSRow from "./FSRow.vue";
30
+
31
+ export default defineComponent({
32
+ name: "FSCard",
33
+ components: {
34
+ FSCol,
35
+ FSRow
36
+ },
37
+ props: {
38
+ color: {
39
+ type: String as PropType<ColorBase>,
40
+ required: false,
41
+ default: ColorBase.Dark
42
+ },
43
+ },
44
+ setup(props) {
45
+ const { color } = toRefs(props);
46
+
47
+ const colors = useColors().getColors(color.value);
48
+
49
+ const backgrounds = useColors().getColors(ColorBase.Background);
50
+
51
+ const style = computed((): {[code: string]: string} & Partial<CSSStyleDeclaration> => {
52
+ return {
53
+ "--fs-card-background-color": backgrounds.base,
54
+ "--fs-card-border-color" : colors.base
55
+ };
56
+ });
57
+
58
+ return {
59
+ style
60
+ };
61
+ }
62
+ });
63
+ </script>
@@ -3,7 +3,6 @@
3
3
  <FSRow width="hug" align="center-left">
4
4
  <FSIcon
5
5
  class="fs-checkbox"
6
- size="checkbox"
7
6
  :style="style"
8
7
  @click="onToggle"
9
8
  >
@@ -64,7 +63,7 @@ export default defineComponent({
64
63
  required: false,
65
64
  default: null
66
65
  },
67
- value: {
66
+ modelValue: {
68
67
  type: Boolean,
69
68
  required: false,
70
69
  default: false
@@ -80,9 +79,9 @@ export default defineComponent({
80
79
  default: true
81
80
  }
82
81
  },
83
- emits: ["update:value"],
82
+ emits: ["update:modelValue"],
84
83
  setup(props, { emit }) {
85
- const { value, color, editable } = toRefs(props);
84
+ const { modelValue, color, editable } = toRefs(props);
86
85
 
87
86
  const colors = useColors().getColors(color.value);
88
87
 
@@ -99,20 +98,20 @@ export default defineComponent({
99
98
  }
100
99
  return {
101
100
  "--fs-checkbox-cursor": "pointer",
102
- "--fs-checkbox-checkbox-color": value.value ? colors.base : darks.base,
101
+ "--fs-checkbox-checkbox-color": modelValue.value ? colors.base : darks.base,
103
102
  "--fs-checkbox-color": darks.base
104
103
  }
105
104
  });
106
105
 
107
- const icon = computed((): string => value.value ? "mdi-checkbox-marked" : "mdi-checkbox-blank-outline");
106
+ const icon = computed((): string => modelValue.value ? "mdi-checkbox-marked" : "mdi-checkbox-blank-outline");
108
107
 
109
- const font = computed((): string => value.value ? "text-button" : "text-body");
108
+ const font = computed((): string => modelValue.value ? "text-button" : "text-body");
110
109
 
111
110
  const onToggle = (): void => {
112
111
  if (!editable.value) {
113
112
  return;
114
113
  }
115
- emit("update:value", !value.value);
114
+ emit("update:modelValue", !modelValue.value);
116
115
  };
117
116
 
118
117
  return {
@@ -0,0 +1,38 @@
1
+ <template>
2
+
3
+ </template>
4
+
5
+ <script lang="ts">
6
+ import { defineComponent, PropType } from "vue";
7
+
8
+ import { useColors, useDates } from "@dative-gpi/foundation-shared-components/composables";
9
+ import { useLanguageCode } from "@dative-gpi/foundation-shared-services/composables";
10
+ import { ColorBase } from "@dative-gpi/foundation-shared-components/themes";
11
+
12
+ import FSCol from "./FSCol.vue";
13
+ import FSRow from "./FSRow.vue";
14
+
15
+ export default defineComponent({
16
+ name: "FSClock",
17
+ props: {
18
+ modelValue: {
19
+ type: Array as PropType<Array<number>>,
20
+ required: false,
21
+ default: null
22
+ },
23
+ color: {
24
+ type: String as PropType<ColorBase>,
25
+ required: false,
26
+ default: ColorBase.Dark
27
+ },
28
+ buttonColor: {
29
+ type: String as PropType<ColorBase>,
30
+ required: false,
31
+ default: ColorBase.Primary
32
+ }
33
+ },
34
+ setup(props) {
35
+
36
+ }
37
+ });
38
+ </script>