@dative-gpi/foundation-shared-components 0.0.38 → 0.0.39

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.
@@ -96,7 +96,7 @@
96
96
 
97
97
  <script lang="ts">
98
98
  import { computed, defineComponent, PropType } from "vue";
99
- import { RouteLocation, useRouter } from "vue-router";
99
+ import { RouteLocation } from "vue-router";
100
100
 
101
101
  import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
102
102
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
@@ -170,7 +170,6 @@ export default defineComponent({
170
170
  setup(props, { emit }) {
171
171
  const { getColors } = useColors();
172
172
  const { slots } = useSlots();
173
- const router = useRouter();
174
173
 
175
174
  const colors = computed(() => getColors(props.color));
176
175
  const lights = getColors(ColorEnum.Light);
@@ -232,18 +231,6 @@ export default defineComponent({
232
231
  return "fit-content";
233
232
  });
234
233
 
235
- const href = computed((): string | null => {
236
- if (!props.to || !props.editable || props.load) {
237
- return null;
238
- }
239
- if (typeof props.to === "string") {
240
- return props.to;
241
- }
242
- else {
243
- return router.resolve(props.to).href;
244
- }
245
- });
246
-
247
234
  const onClick = (event: MouseEvent) => {
248
235
  if (!props.to && props.editable && !props.load) {
249
236
  emit("click", event);
@@ -85,41 +85,34 @@ export default defineComponent({
85
85
  }
86
86
  },
87
87
  setup(props) {
88
- const { getColors, getContrasts } = useColors();
88
+ const { getColors } = useColors();
89
89
 
90
90
  const colors = computed(() => getColors(props.color));
91
91
  const backgrounds = getColors(ColorEnum.Background);
92
92
 
93
- const textColors = computed(() => {
94
- switch (props.variant) {
95
- case "standard": return colors.value;
96
- case "full": return getContrasts(props.color);
97
- }
98
- });
99
-
100
93
  const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => {
101
94
  switch (props.variant) {
102
95
  case "standard": return {
103
96
  "--fs-chip-background-color" : backgrounds.base,
104
97
  "--fs-chip-border-color" : colors.value.base,
105
- "--fs-chip-color" : textColors.value.base,
98
+ "--fs-chip-color" : colors.value.base,
106
99
  "--fs-chip-hover-background-color" : backgrounds.base,
107
100
  "--fs-chip-hover-border-color" : colors.value.base,
108
- "--fs-chip-hover-color" : textColors.value.base,
101
+ "--fs-chip-hover-color" : colors.value.base,
109
102
  "--fs-chip-active-background-color": backgrounds.base,
110
103
  "--fs-chip-active-border-color" : colors.value.dark,
111
- "--fs-chip-active-color" : textColors.value.dark
104
+ "--fs-chip-active-color" : colors.value.dark
112
105
  };
113
106
  case "full": return {
114
107
  "--fs-chip-background-color" : colors.value.base,
115
- "--fs-chip-border-color" : colors.value.base,
116
- "--fs-chip-color" : textColors.value.light,
108
+ "--fs-chip-border-color" : colors.value.baseContrast,
109
+ "--fs-chip-color" : colors.value.baseContrast,
117
110
  "--fs-chip-hover-background-color" : colors.value.base,
118
- "--fs-chip-hover-border-color" : colors.value.base,
119
- "--fs-chip-hover-color" : textColors.value.light,
111
+ "--fs-chip-hover-border-color" : colors.value.baseContrast,
112
+ "--fs-chip-hover-color" : colors.value.baseContrast,
120
113
  "--fs-chip-active-background-color": colors.value.dark,
121
- "--fs-chip-active-border-color" : colors.value.dark,
122
- "--fs-chip-active-color" : textColors.value.light
114
+ "--fs-chip-active-border-color" : colors.value.darkContrast,
115
+ "--fs-chip-active-color" : colors.value.darkContrast
123
116
  };
124
117
  }
125
118
  });
@@ -116,10 +116,9 @@ export default defineComponent({
116
116
  },
117
117
  emits: ["click"],
118
118
  setup(props, { emit }) {
119
- const { getColors, getContrasts } = useColors();
119
+ const { getColors } = useColors();
120
120
  const router = useRouter();
121
121
 
122
- const textColors = computed(() => getContrasts(props.color));
123
122
  const colors = computed(() => getColors(props.color));
124
123
  const lights = getColors(ColorEnum.Light);
125
124
  const darks = getColors(ColorEnum.Dark);
@@ -129,7 +128,7 @@ export default defineComponent({
129
128
  return {
130
129
  "--fs-clickable-border-size" : props.border ? "1px" : "0",
131
130
  "--fs-clickable-border-radius" : sizeToVar(props.borderRadius),
132
- "--fs-clickable-background-color": lights.base,
131
+ "--fs-clickable-background-color": lights.light,
133
132
  "--fs-clickable-border-color" : lights.dark,
134
133
  "--fs-clickable-color" : lights.dark
135
134
  };
@@ -139,27 +138,27 @@ export default defineComponent({
139
138
  "--fs-clickable-border-size" : props.border ? "1px" : "0",
140
139
  "--fs-clickable-border-radius" : sizeToVar(props.borderRadius),
141
140
  "--fs-clickable-background-color" : colors.value.light,
142
- "--fs-clickable-border-color" : colors.value.base,
143
- "--fs-clickable-color" : textColors.value.base,
141
+ "--fs-clickable-border-color" : colors.value.lightContrast,
142
+ "--fs-clickable-color" : colors.value.lightContrast,
144
143
  "--fs-clickable-hover-background-color" : colors.value.base,
145
- "--fs-clickable-hover-border-color" : colors.value.base,
146
- "--fs-clickable-hover-color" : textColors.value.light,
144
+ "--fs-clickable-hover-border-color" : colors.value.baseContrast,
145
+ "--fs-clickable-hover-color" : colors.value.baseContrast,
147
146
  "--fs-clickable-active-background-color": colors.value.dark,
148
- "--fs-clickable-active-border-color" : colors.value.dark,
149
- "--fs-clickable-active-color" : textColors.value.light
147
+ "--fs-clickable-active-border-color" : colors.value.darkContrast,
148
+ "--fs-clickable-active-color" : colors.value.darkContrast
150
149
  };
151
150
  case "full": return {
152
151
  "--fs-clickable-border-size" : props.border ? "1px" : "0",
153
152
  "--fs-clickable-border-radius" : sizeToVar(props.borderRadius),
154
153
  "--fs-clickable-background-color" : colors.value.base,
155
154
  "--fs-clickable-border-color" : colors.value.base,
156
- "--fs-clickable-color" : textColors.value.light,
155
+ "--fs-clickable-color" : colors.value.baseContrast,
157
156
  "--fs-clickable-hover-background-color" : colors.value.base,
158
157
  "--fs-clickable-hover-border-color" : colors.value.base,
159
- "--fs-clickable-hover-color" : textColors.value.light,
158
+ "--fs-clickable-hover-color" : colors.value.baseContrast,
160
159
  "--fs-clickable-active-background-color": colors.value.dark,
161
160
  "--fs-clickable-active-border-color" : colors.value.dark,
162
- "--fs-clickable-active-color" : textColors.value.light
161
+ "--fs-clickable-active-color" : colors.value.darkContrast
163
162
  };
164
163
  }
165
164
  });
@@ -41,8 +41,8 @@ export default defineComponent({
41
41
 
42
42
  const style: Ref<{ [code: string]: string } & Partial<CSSStyleDeclaration>> = ref({
43
43
  "--fs-color-background-color": colors.value.light,
44
- "--fs-color-border-color" : colors.value.base,
45
- "--fs-color-color" : colors.value.base,
44
+ "--fs-color-border-color" : colors.value.lightContrast,
45
+ "--fs-color-color" : colors.value.lightContrast,
46
46
  "--fs-color-light" : colors.value.light,
47
47
  "--fs-color-base" : colors.value.base,
48
48
  "--fs-color-dark" : colors.value.dark
@@ -32,7 +32,7 @@
32
32
  import { computed, defineComponent, PropType } from "vue";
33
33
 
34
34
  import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
35
- import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
35
+ import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
36
36
  import { sizeToVar } from "@dative-gpi/foundation-shared-components/utils";
37
37
 
38
38
  import FSText from "./FSText.vue";
@@ -43,32 +43,52 @@ export default defineComponent({
43
43
  FSText
44
44
  },
45
45
  props: {
46
- width: {
47
- type: [String, Number],
48
- required: false,
49
- default: "100%"
50
- },
51
46
  label: {
52
47
  type: String,
53
48
  required: false,
54
49
  default: null
55
50
  },
51
+ width: {
52
+ type: [String, Number],
53
+ required: false,
54
+ default: "100%"
55
+ },
56
56
  font: {
57
57
  type: String as PropType<"text-h1" | "text-h2" | "text-h3" | "text-h4" | "text-body" | "text-button" | "text-overline" | "text-underline">,
58
58
  required: false,
59
59
  default: "text-body"
60
+ },
61
+ color: {
62
+ type: String as PropType<ColorBase>,
63
+ required: false,
64
+ default: ColorEnum.Light
65
+ },
66
+ variant: {
67
+ type: String as PropType<"base" | "light" | "dark">,
68
+ required: false,
69
+ default: "dark"
60
70
  }
61
71
  },
62
72
  setup(props) {
63
73
  const { getColors } = useColors();
64
74
  const { slots } = useSlots();
65
75
 
66
- const lights = getColors(ColorEnum.Light);
76
+ const colors = computed(() => getColors(props.color));
67
77
 
68
78
  const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => {
69
- return {
70
- "--fs-divider-width": sizeToVar(props.width),
71
- "--fs-divider-color": lights.dark
79
+ switch (props.variant) {
80
+ case "base": return {
81
+ "--fs-divider-width": sizeToVar(props.width),
82
+ "--fs-divider-color": colors.value.base
83
+ };
84
+ case "light": return {
85
+ "--fs-divider-width": sizeToVar(props.width),
86
+ "--fs-divider-color": colors.value.light
87
+ };
88
+ case "dark": return {
89
+ "--fs-divider-width": sizeToVar(props.width),
90
+ "--fs-divider-color": colors.value.dark
91
+ };
72
92
  }
73
93
  });
74
94
 
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <FSRow
3
+ padding="18px 0 18px 32px"
4
+ class="fs-error-toast"
5
+ align="center-left"
6
+ :style="style"
7
+ >
8
+ <FSIcon>
9
+ mdi-alert-outline
10
+ </FSIcon>
11
+ <FSSpan>
12
+ {{ $tr(error.code, error.default) }}
13
+ </FSSpan>
14
+ </FSRow>
15
+ </template>
16
+
17
+ <script lang="ts">
18
+ import { computed, defineComponent } from "vue";
19
+
20
+ import { getError, sizeToVar } from "@dative-gpi/foundation-shared-components/utils";
21
+ import { useColors } from "@dative-gpi/foundation-shared-components/composables";
22
+ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
23
+
24
+ import FSIcon from "./FSIcon.vue";
25
+ import FSSpan from "./FSSpan.vue";
26
+ import FSRow from "./FSRow.vue";
27
+
28
+ export default defineComponent({
29
+ name: "FSErrorToast",
30
+ components: {
31
+ FSIcon,
32
+ FSSpan,
33
+ FSRow
34
+ },
35
+ props: {
36
+ errorCode: {
37
+ type: String,
38
+ required: true
39
+ },
40
+ borderRadius: {
41
+ type: [String, Number],
42
+ required: false,
43
+ default: "4px"
44
+ }
45
+ },
46
+ setup(props) {
47
+ const { getColors } = useColors();
48
+
49
+ const errors = getColors(ColorEnum.Error);
50
+
51
+ const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => {
52
+ return {
53
+ "--fs-error-toast-border-radius" : sizeToVar(props.borderRadius),
54
+ "--fs-error-toast-background-color": errors.base,
55
+ "--fs-error-toast-color" : errors.light
56
+ };
57
+ });
58
+
59
+ const error = computed((): { code: string, default: string, status: number } => getError(props.errorCode));
60
+
61
+ return {
62
+ error,
63
+ style
64
+ };
65
+ }
66
+ });
67
+ </script>
@@ -66,10 +66,18 @@ export default defineComponent({
66
66
  case "number": return sizeToVar(props.padding);
67
67
  default:
68
68
  const paddings = props.padding.split(" ");
69
+ let tempPadding = "0px";
69
70
  switch (paddings.length) {
70
- case 0 : return "0px";
71
- default: return "-" + sizeToVar(paddings[0]);
71
+ case 0 :
72
+ break;
73
+ default:
74
+ tempPadding = "-" + sizeToVar(paddings[0]);
75
+ break;
72
76
  }
77
+ if (tempPadding === "0px") {
78
+ return "-1px";
79
+ }
80
+ return tempPadding;
73
81
  }
74
82
  });
75
83
 
@@ -78,12 +86,22 @@ export default defineComponent({
78
86
  case "number": return sizeToVar(props.padding);
79
87
  default:
80
88
  const paddings = props.padding.split(" ");
89
+ let tempPadding = "0px";
81
90
  switch (paddings.length) {
82
- case 0 : return "0px";
91
+ case 0 :
92
+ break;
83
93
  case 1 :
84
- case 2 : return "-" + sizeToVar(paddings[0]);
85
- default: return "-" + sizeToVar(paddings[2]);
94
+ case 2 :
95
+ tempPadding = "-" + sizeToVar(paddings[0]);
96
+ break;
97
+ default:
98
+ tempPadding = "-" + sizeToVar(paddings[2]);
99
+ break;
100
+ }
101
+ if (tempPadding === "0px") {
102
+ return "-1px";
86
103
  }
104
+ return tempPadding;
87
105
  }
88
106
  });
89
107
 
@@ -0,0 +1,311 @@
1
+ <template>
2
+ <FSWrapGroup
3
+ v-if="['wrap'].includes($props.variant)"
4
+ class="fs-option-group"
5
+ :padding="$props.padding"
6
+ :gap="$props.gap"
7
+ :style="style"
8
+ >
9
+ <template v-if="$props.values.length">
10
+ <template v-if="!firstChild">
11
+ <FSOptionItem
12
+ v-for="(item, index) in $props.values"
13
+ :prependIcon="item.prependIcon"
14
+ :appendIcon="item.appendIcon"
15
+ :editable="$props.editable"
16
+ :variant="getVariant(item)"
17
+ :color="getColor(item)"
18
+ :class="getClass(item)"
19
+ :label="item.label"
20
+ :icon="item.icon"
21
+ :key="index"
22
+ @click="toggle(item)"
23
+ />
24
+ </template>
25
+ <template v-else>
26
+ <component
27
+ v-for="(item, index) in $props.values"
28
+ :key="index"
29
+ :is="firstChild"
30
+ :prependIcon="getFromFirstChild('prependIcon', item)"
31
+ :appendIcon="getFromFirstChild('appendIcon', item)"
32
+ :variant="getFromFirstChild('variant', item)"
33
+ :color="getFromFirstChild('color', item)"
34
+ :class="getFromFirstChild('class', item)"
35
+ :label="getFromFirstChild('label', item)"
36
+ :icon="getFromFirstChild('icon', item)"
37
+ :editable="$props.editable"
38
+ @click="toggle(item)"
39
+ />
40
+ </template>
41
+ </template>
42
+ <slot v-else />
43
+ </FSWrapGroup>
44
+ <FSSlideGroup
45
+ v-else
46
+ class="fs-option-group"
47
+ :padding="$props.padding"
48
+ :gap="$props.gap"
49
+ :style="style"
50
+ >
51
+ <template v-if="$props.values.length">
52
+ <template v-if="!firstChild">
53
+ <FSOptionItem
54
+ v-for="(item, index) in $props.values"
55
+ :prependIcon="item.prependIcon"
56
+ :appendIcon="item.appendIcon"
57
+ :editable="$props.editable"
58
+ :variant="getVariant(item)"
59
+ :color="getColor(item)"
60
+ :class="getClass(item)"
61
+ :label="item.label"
62
+ :icon="item.icon"
63
+ :key="index"
64
+ @click="toggle(item)"
65
+ />
66
+ </template>
67
+ <template v-else>
68
+ <component
69
+ v-for="(item, index) in $props.values"
70
+ :key="index"
71
+ :is="firstChild"
72
+ :prependIcon="getFromFirstChild('prependIcon', item)"
73
+ :appendIcon="getFromFirstChild('appendIcon', item)"
74
+ :variant="getFromFirstChild('variant', item)"
75
+ :color="getFromFirstChild('color', item)"
76
+ :class="getFromFirstChild('class', item)"
77
+ :label="getFromFirstChild('label', item)"
78
+ :icon="getFromFirstChild('icon', item)"
79
+ :editable="$props.editable"
80
+ @click="toggle(item)"
81
+ />
82
+ </template>
83
+ </template>
84
+ <slot v-else />
85
+ </FSSlideGroup>
86
+ </template>
87
+
88
+ <script lang="ts">
89
+ import { computed, defineComponent, PropType } from "vue";
90
+
91
+ import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
92
+ import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
93
+ import { sizeToVar } from "@dative-gpi/foundation-shared-components/utils";
94
+ import { FSToggle } from "@dative-gpi/foundation-shared-components/models";
95
+
96
+ import FSOptionItem from "./FSOptionItem.vue";
97
+ import FSSlideGroup from "./FSSlideGroup.vue";
98
+ import FSWrapGroup from "./FSWrapGroup.vue";
99
+
100
+ export default defineComponent({
101
+ name: "FSOptionGroup",
102
+ components: {
103
+ FSOptionItem,
104
+ FSSlideGroup,
105
+ FSWrapGroup
106
+ },
107
+ props: {
108
+ values: {
109
+ type: Array as PropType<FSToggle[]>,
110
+ required: false,
111
+ default: () => []
112
+ },
113
+ border: {
114
+ type: Boolean,
115
+ required: false,
116
+ default: true
117
+ },
118
+ borderRadius: {
119
+ type: [String, Number],
120
+ required: false,
121
+ default: "4px"
122
+ },
123
+ variant: {
124
+ type: String as PropType<"wrap" | "slide">,
125
+ required: false,
126
+ default: "wrap"
127
+ },
128
+ optionVariant: {
129
+ type: String as PropType<"standard" | "full">,
130
+ required: false,
131
+ default: "full"
132
+ },
133
+ activeVariant: {
134
+ type: String as PropType<"standard" | "full">,
135
+ required: false,
136
+ default: "full"
137
+ },
138
+ optionClass: {
139
+ type: [Array, String] as PropType<string[] | string>,
140
+ required: false,
141
+ default: null
142
+ },
143
+ activeClass: {
144
+ type: [Array, String] as PropType<string[] | string>,
145
+ required: false,
146
+ default: null
147
+ },
148
+ modelValue: {
149
+ type: [Array, String, Number] as PropType<(string | number)[] | string | number>,
150
+ required: false,
151
+ default: false
152
+ },
153
+ optionColor: {
154
+ type: String as PropType<ColorBase>,
155
+ required: false,
156
+ default: ColorEnum.Background
157
+ },
158
+ activeColor: {
159
+ type: String as PropType<ColorBase>,
160
+ required: false,
161
+ default: ColorEnum.Primary
162
+ },
163
+ padding: {
164
+ type: [String, Number],
165
+ required: false,
166
+ default: "3px"
167
+ },
168
+ gap: {
169
+ type: [String, Number],
170
+ required: false,
171
+ default: "0"
172
+ },
173
+ multiple: {
174
+ type: Boolean,
175
+ required: false,
176
+ default: false
177
+ },
178
+ required: {
179
+ type: Boolean,
180
+ required: false,
181
+ default: true
182
+ },
183
+ editable: {
184
+ type: Boolean,
185
+ required: false,
186
+ default: true
187
+ }
188
+ },
189
+ emits: ["update:modelValue"],
190
+ setup(props, { emit }) {
191
+ const { getFirstChild } = useSlots();
192
+ const { getColors } = useColors();
193
+
194
+ const lights = getColors(ColorEnum.Light);
195
+
196
+ const firstChild = getFirstChild("item");
197
+
198
+ const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => {
199
+ return {
200
+ "--fs-option-group-border-size" : props.border ? "1px" : "0",
201
+ "--fs-option-group-border-radius": sizeToVar(props.borderRadius),
202
+ "--fs-option-group-border-color" : lights.base
203
+ };
204
+ })
205
+
206
+ const getFromFirstChild = (prop: string, value: FSToggle): any => {
207
+ switch (prop) {
208
+ case "prependIcon":
209
+ return firstChild.props.prependIcon ?? value.prependIcon;
210
+ case "label":
211
+ return firstChild.props.label ?? value.label;
212
+ case "appendIcon":
213
+ return firstChild.props.appendIcon ?? value.appendIcon;
214
+ case "icon":
215
+ return firstChild.props.icon ?? value.icon;
216
+ case "variant":
217
+ return firstChild.props.variant ?? getVariant(value);
218
+ case "color":
219
+ return firstChild.props.color ?? getColor(value);
220
+ default:
221
+ return firstChild.props[prop];
222
+ }
223
+ }
224
+
225
+ const getVariant = (value: FSToggle): "standard" | "full" => {
226
+ if (Array.isArray(props.modelValue) && props.modelValue.some(v => v === value.id)) {
227
+ return props.activeVariant;
228
+ }
229
+ if (!Array.isArray(props.modelValue) && props.modelValue === value.id) {
230
+ return props.activeVariant;
231
+ }
232
+ return props.optionVariant;
233
+ };
234
+
235
+ const getColor = (value: FSToggle): ColorBase => {
236
+ if (Array.isArray(props.modelValue) && props.modelValue.some(v => v === value.id)) {
237
+ return props.activeColor;
238
+ }
239
+ if (!Array.isArray(props.modelValue) && props.modelValue === value.id) {
240
+ return props.activeColor;
241
+ }
242
+ return props.optionColor;
243
+ };
244
+
245
+ const getClass = (value: FSToggle): string[] | string => {
246
+ if (Array.isArray(props.modelValue) && props.modelValue.some(v => v === value.id)) {
247
+ return props.activeClass;
248
+ }
249
+ if (!Array.isArray(props.modelValue) && props.modelValue === value.id) {
250
+ return props.activeClass;
251
+ }
252
+ return props.optionClass;
253
+ };
254
+
255
+ const toggle = (value: FSToggle): void => {
256
+ if (Array.isArray(props.modelValue)) {
257
+ if (props.multiple) {
258
+ if (props.modelValue.length && props.modelValue.every(v => v === value.id)) {
259
+ if (!props.required) {
260
+ emit("update:modelValue", []);
261
+ return;
262
+ }
263
+ }
264
+ else if (props.modelValue.some(v => v === value.id)) {
265
+ emit("update:modelValue", props.modelValue.filter(v => v !== value.id));
266
+ return;
267
+ }
268
+ else {
269
+ emit("update:modelValue", [...props.modelValue, value.id]);
270
+ return;
271
+ }
272
+ }
273
+ else {
274
+ if (props.modelValue.some(v => v === value.id)) {
275
+ if (!props.required) {
276
+ emit("update:modelValue", []);
277
+ return;
278
+ }
279
+ }
280
+ else {
281
+ emit("update:modelValue", [value.id]);
282
+ return;
283
+ }
284
+ }
285
+ }
286
+ else {
287
+ if (props.modelValue === value.id) {
288
+ if (!props.required) {
289
+ emit("update:modelValue", null);
290
+ return;
291
+ }
292
+ }
293
+ else {
294
+ emit("update:modelValue", value.id);
295
+ return;
296
+ }
297
+ }
298
+ };
299
+
300
+ return {
301
+ firstChild,
302
+ style,
303
+ getFromFirstChild,
304
+ getVariant,
305
+ getColor,
306
+ getClass,
307
+ toggle
308
+ };
309
+ }
310
+ })
311
+ </script>
@@ -0,0 +1,132 @@
1
+ <template>
2
+ <FSClickable
3
+ padding="12px 0"
4
+ :editable="$props.editable"
5
+ :height="['32px', '28px']"
6
+ :variant="$props.variant"
7
+ :color="$props.color"
8
+ :load="$props.load"
9
+ :width="width"
10
+ @click.stop="onClick"
11
+ v-bind="$attrs"
12
+ >
13
+ <FSRow
14
+ align="center-center"
15
+ width="fill"
16
+ :wrap="false"
17
+ >
18
+ <slot name="prepend" v-bind="{ color: $props.color, colors }">
19
+ <FSIcon
20
+ v-if="$props.prependIcon || $props.icon"
21
+ size="l"
22
+ >
23
+ {{ $props.prependIcon ?? $props.icon }}
24
+ </FSIcon>
25
+ </slot>
26
+ <slot v-bind="{ color: $props.color, colors }">
27
+ <FSSpan
28
+ v-if="$props.label"
29
+ >
30
+ {{ $props.label }}
31
+ </FSSpan>
32
+ </slot>
33
+ <slot name="append" v-bind="{ color: $props.color, colors }">
34
+ <FSIcon
35
+ v-if="$props.appendIcon"
36
+ size="l"
37
+ >
38
+ {{ $props.appendIcon }}
39
+ </FSIcon>
40
+ </slot>
41
+ </FSRow>
42
+ </FSClickable>
43
+ </template>
44
+
45
+ <script lang="ts">
46
+ import { computed, defineComponent, PropType } from "vue";
47
+
48
+ import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
49
+ import { useColors } from "@dative-gpi/foundation-shared-components/composables";
50
+
51
+ import FSClickable from "./FSClickable.vue";
52
+ import FSSpan from "./FSSpan.vue";
53
+ import FSIcon from "./FSIcon.vue";
54
+ import FSRow from "./FSRow.vue";
55
+
56
+ export default defineComponent({
57
+ name: "FSOptionItem",
58
+ components: {
59
+ FSClickable,
60
+ FSSpan,
61
+ FSIcon,
62
+ FSRow
63
+ },
64
+ props: {
65
+ prependIcon: {
66
+ type: String,
67
+ required: false,
68
+ default: null
69
+ },
70
+ label: {
71
+ type: [String, Function],
72
+ required: false,
73
+ default: null
74
+ },
75
+ appendIcon: {
76
+ type: String,
77
+ required: false,
78
+ default: null
79
+ },
80
+ icon: {
81
+ type: String,
82
+ required: false,
83
+ default: null
84
+ },
85
+ variant: {
86
+ type: String as PropType<"standard" | "full">,
87
+ required: false,
88
+ default: "full"
89
+ },
90
+ color: {
91
+ type: String as PropType<ColorBase>,
92
+ required: false,
93
+ default: ColorEnum.Primary
94
+ },
95
+ load: {
96
+ type: Boolean,
97
+ required: false,
98
+ default: false
99
+ },
100
+ editable: {
101
+ type: Boolean,
102
+ required: false,
103
+ default: true
104
+ }
105
+ },
106
+ emits: ["click"],
107
+ setup(props, { emit }) {
108
+ const { getColors } = useColors();
109
+
110
+ const colors = computed(() => getColors(props.color));
111
+
112
+ const width = computed((): string => {
113
+ if (props.label) {
114
+ return "fit-content";
115
+ }
116
+ return "72px";
117
+ });
118
+
119
+ const onClick = (event: MouseEvent) => {
120
+ if (props.editable && !props.load) {
121
+ emit("click", event);
122
+ }
123
+ };
124
+
125
+ return {
126
+ colors,
127
+ width,
128
+ onClick
129
+ };
130
+ }
131
+ })
132
+ </script>
@@ -15,6 +15,7 @@
15
15
  />
16
16
  <FSButtonPreviousIcon
17
17
  :color="ColorEnum.Dark"
18
+ @click="goToPrev"
18
19
  />
19
20
  </template>
20
21
  <template #default>
@@ -28,6 +29,7 @@
28
29
  <template #next>
29
30
  <FSButtonNextIcon
30
31
  :color="ColorEnum.Dark"
32
+ @click="goToNext"
31
33
  />
32
34
  <FSButton
33
35
  v-if="$props.dash"
@@ -71,7 +73,12 @@ export default defineComponent({
71
73
  dash: {
72
74
  type: Boolean,
73
75
  required: false,
74
- default: true
76
+ default: false
77
+ },
78
+ speed: {
79
+ type: Number,
80
+ required: false,
81
+ default: 250
75
82
  }
76
83
  },
77
84
  setup(props) {
@@ -96,6 +103,12 @@ export default defineComponent({
96
103
  }
97
104
  };
98
105
 
106
+ const goToPrev = () => {
107
+ if (slideGroupRef.value) {
108
+ slideGroupRef.value.scrollOffset = Math.max(0, slideGroupRef.value.scrollOffset - props.speed);
109
+ }
110
+ };
111
+
99
112
  const goToEnd = () => {
100
113
  if (slideGroupRef.value) {
101
114
  const contentSize = slideGroupRef.value.$el.children[1].children[0].clientWidth;
@@ -105,12 +118,23 @@ export default defineComponent({
105
118
  }
106
119
  };
107
120
 
121
+ const goToNext = () => {
122
+ if (slideGroupRef.value) {
123
+ const contentSize = slideGroupRef.value.$el.children[1].children[0].clientWidth;
124
+ const containerSize = slideGroupRef.value.$el.clientWidth;
125
+ const arrowsOffset = props.dash ? 104 : 64;
126
+ slideGroupRef.value.scrollOffset = Math.min(contentSize - containerSize + arrowsOffset, slideGroupRef.value.scrollOffset + props.speed);
127
+ }
128
+ };
129
+
108
130
  return {
109
131
  slideGroupRef,
110
132
  ColorEnum,
111
133
  style,
112
134
  getChildren,
113
135
  goToStart,
136
+ goToPrev,
137
+ goToNext,
114
138
  goToEnd
115
139
  };
116
140
  }
@@ -40,23 +40,22 @@ export default defineComponent({
40
40
  }
41
41
  },
42
42
  setup(props) {
43
- const { getColors, getContrasts } = useColors();
44
43
  const { getChildren } = useSlots();
44
+ const { getColors } = useColors();
45
45
 
46
- const textColors = computed(() => getContrasts(props.color));
47
46
  const colors = computed(() => getColors(props.color));
48
47
  const darks = getColors(ColorEnum.Dark);
49
48
 
50
49
  const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => ({
51
50
  "--fs-group-color" : darks.base,
51
+ "--fs-group-disabled-color" : darks.light,
52
52
  "--fs-group-hover-background-color": colors.value.light,
53
53
  "--fs-group-hover-color" : darks.dark,
54
- "--fs-group-disabled-color" : darks.light,
55
54
  "--fs-group-light" : colors.value.light,
56
55
  "--fs-group-base" : colors.value.base,
57
56
  "--fs-group-dark" : colors.value.dark,
58
57
  "--fs-tab-tag-background-color" : colors.value.base,
59
- "--fs-tab-tag-color" : textColors.value.light
58
+ "--fs-tab-tag-color" : colors.value.baseContrast
60
59
  }));
61
60
 
62
61
  return {
@@ -73,28 +73,27 @@ export default defineComponent({
73
73
  },
74
74
  emits: ["remove"],
75
75
  setup(props) {
76
- const { getColors, getContrasts } = useColors();
76
+ const { getColors } = useColors();
77
77
 
78
- const textColors = computed(() => getContrasts(props.color));
79
78
  const colors = computed(() => getColors(props.color));
80
79
 
81
80
  const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => {
82
81
  switch (props.variant) {
83
82
  case "standard": return {
84
83
  "--fs-tag-background-color" : colors.value.light,
85
- "--fs-tag-color" : textColors.value.base,
84
+ "--fs-tag-color" : colors.value.lightContrast,
86
85
  "--fs-tag-hover-background-color" : colors.value.base,
87
- "--fs-tag-hover-color" : textColors.value.light,
86
+ "--fs-tag-hover-color" : colors.value.baseContrast,
88
87
  "--fs-tag-active-background-color": colors.value.dark,
89
- "--fs-tag-active-color" : textColors.value.light
88
+ "--fs-tag-active-color" : colors.value.darkContrast
90
89
  };
91
90
  case "full": return {
92
91
  "--fs-tag-background-color" : colors.value.base,
93
- "--fs-tag-color" : textColors.value.light,
92
+ "--fs-tag-color" : colors.value.baseContrast,
94
93
  "--fs-tag-hover-background-color" : colors.value.base,
95
- "--fs-tag-hover-color" : textColors.value.light,
94
+ "--fs-tag-hover-color" : colors.value.baseContrast,
96
95
  "--fs-tag-active-background-color": colors.value.dark,
97
- "--fs-tag-active-color" : textColors.value.light
96
+ "--fs-tag-active-color" : colors.value.darkContrast
98
97
  };
99
98
  }
100
99
  });
@@ -16,6 +16,7 @@
16
16
  :color="getColor(item)"
17
17
  :class="getClass(item)"
18
18
  :label="item.label"
19
+ :icon="item.icon"
19
20
  :key="index"
20
21
  @click="toggle(item)"
21
22
  />
@@ -56,6 +57,7 @@
56
57
  :color="getColor(item)"
57
58
  :class="getClass(item)"
58
59
  :label="item.label"
60
+ :icon="label.icon"
59
61
  :key="index"
60
62
  @click="toggle(item)"
61
63
  />
@@ -50,26 +50,10 @@ export default defineComponent({
50
50
  "--fs-group-hover-color": darks.dark
51
51
  }));
52
52
 
53
- const goToStart = () => {
54
- if (wrapGroupRef.value) {
55
- wrapGroupRef.value.scrollOffset = 0;
56
- }
57
- };
58
-
59
- const goToEnd = () => {
60
- if (wrapGroupRef.value) {
61
- const contentSize = wrapGroupRef.value.$el.children[1].children[0].clientWidth;
62
- const containerSize = wrapGroupRef.value.$el.clientWidth;
63
- wrapGroupRef.value.scrollOffset = (contentSize - containerSize);
64
- }
65
- };
66
-
67
53
  return {
68
54
  wrapGroupRef,
69
55
  style,
70
- getChildren,
71
- goToStart,
72
- goToEnd
56
+ getChildren
73
57
  };
74
58
  }
75
59
  });
@@ -123,7 +123,7 @@ export default defineComponent({
123
123
  },
124
124
  emits: ["update:modelValue"],
125
125
  setup(props) {
126
- const {validateOn, blurred, getMessages} = useRules();
126
+ const { validateOn, blurred, getMessages } = useRules();
127
127
  const { getColors } = useColors();
128
128
 
129
129
  const errors = getColors(ColorEnum.Error);
@@ -16,59 +16,89 @@ export const useColors = () => {
16
16
  return maxDiff < 10;
17
17
  };
18
18
 
19
- const lighten = (base: Color): Color => {
19
+ const isPastel = (color: Color): boolean => {
20
+ return color.saturationv() <= 15 && color.value() >= 85;
21
+ };
22
+
23
+ const getLight = (base: Color): Color => {
20
24
  if (isGrayScale(base)) {
21
25
  return base.value(Math.min(base.value() + 10, 100));
22
26
  }
23
27
  return base.saturationv(10).value(100);
24
28
  };
25
29
 
26
- const soften = (base: Color): Color => {
30
+ const getSoft = (base: Color): Color => {
27
31
  return base.value(Math.min(base.value() + 10, 100));
28
32
  };
29
33
 
30
- const darken = (base: Color): Color => {
31
- return base.value(Math.max(base.value() - 15, 0));
34
+ const getBase = (base: Color): Color => {
35
+ if (isGrayScale(base)) {
36
+ return base.saturationv(1);
37
+ }
38
+ return base.saturationv(((base.saturationv() * 30) / 100) + 70).value(90);
32
39
  };
33
40
 
34
- const getColors = (color: ColorBase): ColorVariations => {
35
- const themed = (Object as any).values(ColorEnum).includes(color);
36
-
37
- const base = themed ? new Color(theme.colors[color as ColorEnum]) : new Color(color);
38
- const light = lighten(base);
39
- const soft = soften(base);
40
- const dark = darken(base);
41
-
42
- return {
43
- light: light.hex(),
44
- soft: soft.hex(),
45
- base: base.hex(),
46
- dark: dark.hex()
47
- };
41
+ const getDark = (base: Color): Color => {
42
+ return base.value(Math.max(base.value() - 15, 0));
48
43
  };
49
44
 
50
- const getContrasts = (color: ColorBase): ColorVariations => {
45
+ const getContrast = (color: Color, fallback: Color): Color => {
46
+ if (isGrayScale(color)) {
47
+ if (color.value() > 50) {
48
+ return color.value(Math.max(0, color.value() - 75));
49
+ }
50
+ else {
51
+ return color.value(Math.min(100, color.value() + 75));
52
+ }
53
+ }
54
+ return fallback;
55
+ }
56
+
57
+ const getColors = (color: ColorBase): ColorVariations => {
51
58
  const themed = (Object as any).values(ColorEnum).includes(color);
52
59
 
53
- let base = themed ? new Color(theme.colors[color as ColorEnum]) : new Color(color);
60
+ const seed = themed ? new Color(theme.colors[color as ColorEnum]) : new Color(color);
61
+
62
+ const base = getBase(seed);
63
+ const light = getLight(base);
64
+ const soft = getSoft(base);
65
+ const dark = getDark(base);
66
+
67
+ if (isPastel(seed)) {
68
+ return {
69
+ light: getLight(seed).hex(),
70
+ lightContrast: getContrast(light, dark).hex(),
71
+ soft: getSoft(seed).hex(),
72
+ softContrast: getContrast(seed, dark).hex(),
73
+ base: seed.hex(),
74
+ baseContrast: getContrast(seed, base).hex(),
75
+ dark: dark.hex(),
76
+ darkContrast: getContrast(dark, light).hex()
77
+ };
78
+ }
54
79
 
55
- if (isGrayScale(base)) {
56
- switch (color) {
57
- case ColorEnum.Light:
58
- return getColors(ColorEnum.Dark);
59
- case ColorEnum.Dark:
60
- return getColors(ColorEnum.Light);
61
- default:
62
- if (base.value() > 50) {
63
- base = base.value(Math.max(base.value() - 65, 0));
64
- }
65
- else {
66
- base = base.value(Math.min(base.value() + 65, 100));
67
- }
68
- break;
69
- }
80
+ switch (color) {
81
+ case ColorEnum.Background: return {
82
+ light: base.hex(),
83
+ lightContrast: getContrast(base, base).hex(),
84
+ soft: base.hex(),
85
+ softContrast: getContrast(base, base).hex(),
86
+ base: base.hex(),
87
+ baseContrast: getContrast(base, base).hex(),
88
+ dark: dark.hex(),
89
+ darkContrast: getContrast(dark, base).hex()
90
+ };
91
+ default: return {
92
+ light: light.hex(),
93
+ lightContrast: getContrast(light, dark).hex(),
94
+ soft: soft.hex(),
95
+ softContrast: getContrast(soft, light).hex(),
96
+ base: base.hex(),
97
+ baseContrast: getContrast(base, light).hex(),
98
+ dark: dark.hex(),
99
+ darkContrast: getContrast(dark, light).hex()
100
+ };
70
101
  }
71
- return getColors(base.hex());
72
102
  };
73
103
 
74
104
  const getGradients = (colors: ColorBase | ColorBase[]): ColorVariations => {
@@ -87,7 +117,6 @@ export const useColors = () => {
87
117
 
88
118
  return {
89
119
  getColors,
90
- getContrasts,
91
120
  getGradients
92
121
  };
93
122
  }
@@ -61,6 +61,9 @@ export const useRules = () => {
61
61
  }
62
62
  }
63
63
  }
64
+ for (let i = 1; i < messages.length; i++) {
65
+ messages[i] = messages[i].toLowerCase();
66
+ }
64
67
  return [...new Set(messages)];
65
68
  }
66
69
 
package/models/colors.ts CHANGED
@@ -10,9 +10,13 @@ export enum ColorEnum {
10
10
 
11
11
  export interface ColorVariations {
12
12
  light: string;
13
+ lightContrast?: string;
13
14
  soft: string;
15
+ softContrast?: string;
14
16
  base: string;
17
+ baseContrast?: string;
15
18
  dark: string;
19
+ darkContrast?: string;
16
20
  };
17
21
 
18
22
  export type ColorBase = (String | ColorEnum);
@@ -0,0 +1,36 @@
1
+ export const Errors = [
2
+ { code: "errors.missingorganisation", default: "Missing organisation header", status: 400 },
3
+ { code: "errors.missinglanguage", default: "Missing language header", status: 400 },
4
+ { code: "errors.invalidchart", default: "Invalid chart configuration", status: 400 },
5
+ { code: "errors.invalidscenario", default: "Invalid scenario configuration", status: 400 },
6
+ { code: "errors.passwordtooshort", default: "Password too short", status: 400 },
7
+ { code: "errors.passwordtoolong", default: "Password too long", status: 400 },
8
+ { code: "errors.passwordlowercase", default: "Lowercase character required", status: 400 },
9
+ { code: "errors.passworduppercase", default: "Uppercase character required", status: 400 },
10
+ { code: "errors.passwordnumber", default: "Number required", status: 400 },
11
+ { code: "errors.passwordspecial", default: "Special character required", status: 400 },
12
+ { code: "errors.authenticationfailed", default: "Authentication failed", status: 401 },
13
+ { code: "errors.noregistereduser", default: "No registered user", status: 401 },
14
+ { code: "errors.badcredentials", default: "Bad credentials", status: 401 },
15
+ { code: "errors.unauthorizedorganisation", default: "Unauthorized organisation", status: 403 },
16
+ { code: "errors.unauthorizedextension", default: "Unauthorized extension", status: 403 },
17
+ { code: "errors.unauthorizeduser", default: "Unauthorized user", status: 403 },
18
+ { code: "errors.usernotinorganisation", default: "User not in organisation", status: 403 },
19
+ { code: "errors.noadminprivilege", default: "No admin privilege", status: 403 },
20
+ { code: "errors.dashboardLocked", default: "Dashboard locked", status: 403 },
21
+ { code: "errors.entitynotfound", default: "Entity not found", status: 404 },
22
+ { code: "errors.imagenotfound", default: "Image not found", status: 404 },
23
+ { code: "errors.tokennotfound", default: "Token not found", status: 404 },
24
+ { code: "errors.alreadyregistereduser", default: "Already registered user", status: 409 },
25
+ { code: "errors.devicealreadyinorganisation", default: "Device already in organisation", status: 409 },
26
+ { code: "errors.devicealreadywatched", default: "Device already watched", status: 409 },
27
+ { code: "errors.useralreadyinorganisation", default: "User already in organisation", status: 409 },
28
+ { code: "errors.emailfailure", default: "Email failure", status: 422 },
29
+ { code: "errors.requirevalidation", default: "Require validation", status: 422 },
30
+ { code: "errors.databaseerror", default: "Database error", status: 449 },
31
+ { code: "errors.graphsettingserror", default: "Microsoft graph settings error", status: 500 },
32
+ { code: "errors.graphusererror", default: "Microsoft graph user error", status: 500 },
33
+ { code: "errors.nomappableproperty", default: "No mappable property", status: 500 },
34
+ { code: "errors.unvalidextensioncookie", default: "Unvalid extension cookie", status: 500 },
35
+ { code: "errors.unexpectederror", default: "Unexpected error", status: 500 }
36
+ ];
package/models/index.ts CHANGED
@@ -3,6 +3,7 @@ export * from "./colors";
3
3
  export * from "./deviceAlerts";
4
4
  export * from "./deviceConnectivities";
5
5
  export * from "./deviceStatuses";
6
+ export * from "./errors";
6
7
  export * from "./modelStatuses";
7
8
  export * from "./rules";
8
9
  export * from "./tables";
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.38",
4
+ "version": "0.0.39",
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.38",
14
- "@dative-gpi/foundation-shared-services": "0.0.38",
13
+ "@dative-gpi/foundation-shared-domain": "0.0.39",
14
+ "@dative-gpi/foundation-shared-services": "0.0.39",
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": "6dbe0959177629f0285f2eae895690376a6fa0e1"
35
+ "gitHead": "f4259f72e37e80ea5276d61fa030956976738397"
36
36
  }
@@ -1,6 +1,6 @@
1
1
  .fs-color {
2
- display: flex;
3
2
  background-color: var(--fs-color-background-color) !important;
4
3
  border-color: var(--fs-color-border-color) !important;
5
4
  color: var(--fs-color-color);
5
+ display: flex;
6
6
  }
@@ -1,16 +1,16 @@
1
1
  .fs-container {
2
- display: flex;
3
- padding: var(--fs-container-padding);
4
2
  background-color: var(--fs-container-background-color);
3
+ padding: var(--fs-container-padding);
4
+ display: flex;
5
5
 
6
6
  &-border {
7
- border-radius: 4px;
8
7
  border: 1px solid var(--fs-container-border-color);
8
+ border-radius: 4px;
9
9
  }
10
10
 
11
11
  &-elevation {
12
- margin: 4px;
13
- border-radius: 4px;
14
12
  box-shadow: 0px 1px 8px 0px #00000029;
13
+ border-radius: 4px;
14
+ margin: 4px;
15
15
  }
16
16
  }
@@ -0,0 +1,5 @@
1
+ .fs-error-toast {
2
+ border-radius: var(--fs-error-toast-border-radius);
3
+ background-color: var(--fs-error-toast-background-color);
4
+ color: var(--fs-error-toast-color);
5
+ }
@@ -0,0 +1,7 @@
1
+ .fs-option-group {
2
+ border-radius: var(--fs-option-group-border-radius) !important;
3
+ border: var(--fs-option-group-border-size) solid !important;
4
+ width: fit-content;
5
+
6
+ border-color: var(--fs-option-group-border-color) !important;
7
+ }
@@ -19,6 +19,7 @@
19
19
  @import "fs_date_field.scss";
20
20
  @import "fs_dialog.scss";
21
21
  @import "fs_divider.scss";
22
+ @import "fs_error_toast.scss";
22
23
  @import "fs_fade_out.scss";
23
24
  @import "fs_filter_button.scss";
24
25
  @import "fs_form.scss";
@@ -32,6 +33,7 @@
32
33
  @import "fs_load_data_table.scss";
33
34
  @import "fs_load_tile.scss";
34
35
  @import "fs_loader.scss";
36
+ @import "fs_option_group.scss";
35
37
  @import "fs_pagination.scss";
36
38
  @import "fs_password_field.scss";
37
39
  @import "fs_radio.scss";
package/utils/error.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { Errors } from "../models/errors";
2
+
3
+ export const getError = (code: string): { code: string, default: string, status: number } => {
4
+ return Errors.find(e => e.code === code) || { code: "errors.unexpectederror", default: "Unexpected error", status: 500 };
5
+ };
package/utils/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./color";
2
2
  export * from "./css";
3
3
  export * from "./icons";
4
+ export * from "./error";
4
5
  export * from "./levenshtein";
5
6
  export * from "./lexical";
6
7
  export * from "./sort";