@dative-gpi/foundation-shared-components 1.0.194 → 1.1.0

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.
@@ -1,6 +1,7 @@
1
1
  <template>
2
- <FSClickable
2
+ <FSCard
3
3
  v-if="$props.variant !== 'icon'"
4
+ :clickable="true"
4
5
  :disabled="$props.disabled"
5
6
  :padding="padding"
6
7
  :variant="$props.variant"
@@ -8,7 +9,6 @@
8
9
  :load="$props.load"
9
10
  :href="$props.href"
10
11
  :to="$props.to"
11
- :style="style"
12
12
  @click.stop="onClick"
13
13
  v-bind="$attrs"
14
14
  >
@@ -87,93 +87,62 @@
87
87
  </FSIcon>
88
88
  </slot>
89
89
  </FSCol>
90
- </FSClickable>
91
- <FSRow
90
+ </FSCard>
91
+ <FSRouterLink
92
92
  v-else
93
- width="hug"
93
+ :to="$props.to"
94
+ :href="$props.href"
94
95
  :class="iconClasses"
95
- :style="style"
96
96
  @click.stop="onClick"
97
- v-bind="$attrs"
98
97
  >
99
- <template
100
- v-if="$props.load"
101
- >
102
- <v-progress-circular
103
- class="fs-button-load"
104
- width="2"
105
- size="20"
106
- :indeterminate="true"
107
- :color="loadColor"
108
- />
109
- </template>
110
- <template
111
- v-else-if="$props.href"
98
+ <FSRow
99
+ width="hug"
100
+ align="center-left"
101
+ v-bind="$attrs"
112
102
  >
113
- <a
114
- :href="$props.href"
103
+ <template
104
+ v-if="$props.load"
115
105
  >
116
- <FSIcon
117
- v-if="$props.icon"
118
- :size="$props.iconSize"
119
- >
120
- {{ $props.icon }}
121
- </FSIcon>
122
- <FSSpan
123
- v-if="$props.label"
124
- >
125
- {{ $props.label }}
126
- </FSSpan>
127
- </a>
128
- </template>
129
- <template
130
- v-else-if="$props.to"
131
- >
132
- <FSRouterLink
133
- :to="$props.to"
106
+ <v-progress-circular
107
+ class="fs-button-load"
108
+ width="2"
109
+ size="20"
110
+ :indeterminate="true"
111
+ :color="loadColor"
112
+ />
113
+ </template>
114
+ <template
115
+ v-else
134
116
  >
135
117
  <FSIcon
136
118
  v-if="$props.icon"
119
+ :color="iconVariantColor"
137
120
  :size="$props.iconSize"
138
121
  >
139
122
  {{ $props.icon }}
140
123
  </FSIcon>
141
- <FSSpan
124
+ <FSText
142
125
  v-if="$props.label"
126
+ :color="iconVariantColor"
143
127
  >
144
128
  {{ $props.label }}
145
- </FSSpan>
146
- </FSRouterLink>
147
- </template>
148
- <template
149
- v-else
150
- >
151
- <FSIcon
152
- v-if="$props.icon"
153
- :size="$props.iconSize"
154
- >
155
- {{ $props.icon }}
156
- </FSIcon>
157
- <FSSpan
158
- v-if="$props.label"
159
- >
160
- {{ $props.label }}
161
- </FSSpan>
162
- </template>
163
- </FSRow>
129
+ </FSText>
130
+ </template>
131
+ </FSRow>
132
+ </FSRouterLink>
164
133
  </template>
165
134
 
166
135
  <script lang="ts">
167
- import { computed, defineComponent, type PropType, type StyleValue, useSlots } from "vue";
136
+ import { computed, defineComponent, type PropType, useSlots } from "vue";
168
137
  import { type RouteLocation } from "vue-router";
169
138
 
170
139
  import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
171
140
  import { useColors } from "@dative-gpi/foundation-shared-components/composables";
172
141
 
173
- import FSRouterLink from "./FSRouterLink.vue";
174
- import FSClickable from "./FSClickable.vue";
175
- import FSSpan from "./FSSpan.vue";
142
+ import FSRouterLink from './FSRouterLink.vue';
143
+ import FSText from "./FSText.vue";
176
144
  import FSIcon from "./FSIcon.vue";
145
+ import FSCard from './FSCard.vue';
177
146
  import FSCol from "./FSCol.vue";
178
147
  import FSRow from "./FSRow.vue";
179
148
 
@@ -187,8 +156,8 @@ export default defineComponent({
187
156
  name: "FSButton",
188
157
  components: {
189
158
  FSRouterLink,
190
- FSClickable,
191
- FSSpan,
159
+ FSCard,
160
+ FSText,
192
161
  FSIcon,
193
162
  FSCol,
194
163
  FSRow
@@ -265,32 +234,17 @@ export default defineComponent({
265
234
  const { getColors } = useColors();
266
235
 
267
236
  const colors = computed(() => getColors(props.color));
268
- const lights = getColors(ColorEnum.Light);
269
237
  const darks = getColors(ColorEnum.Dark);
270
238
  const slots = useSlots();
271
239
 
272
- const style = computed((): StyleValue => {
240
+ const iconVariantColor = computed((): string => {
273
241
  if (props.disabled) {
274
- switch (props.variant) {
275
- case "icon": return {
276
- "--fs-button-color": lights.dark,
277
- };
278
- }
242
+ return ColorEnum.Light;
279
243
  }
280
- switch (props.variant) {
281
- case "icon": switch (props.color) {
282
- case ColorEnum.Dark:
283
- case ColorEnum.Light: return {
284
- "--fs-button-color" : darks.base,
285
- "--fs-button-hover-color": darks.dark,
286
- };
287
- default: return {
288
- "--fs-button-color" : colors.value.base,
289
- "--fs-button-hover-color": colors.value.dark,
290
- };
291
- }
244
+ if (props.color === ColorEnum.Light) {
245
+ return ColorEnum.Dark;
292
246
  }
293
- return {};
247
+ return props.color;
294
248
  });
295
249
 
296
250
  const iconClasses = computed((): string[] => {
@@ -337,11 +291,11 @@ export default defineComponent({
337
291
  };
338
292
 
339
293
  return {
340
- iconClasses,
341
- loadColor,
342
294
  colors,
343
- style,
344
295
  padding,
296
+ loadColor,
297
+ iconClasses,
298
+ iconVariantColor,
345
299
  onClick
346
300
  };
347
301
  }
@@ -1,142 +1,187 @@
1
1
  <template>
2
- <div
3
- :class="classes"
2
+ <FSRouterLink
4
3
  :style="style"
4
+ :to="$props.to"
5
+ :href="$props.href"
6
+ :type="actualWrapperType"
7
+ :passive="actualClickable ? false : true"
8
+ :class="['fs-card-wrapper', $props.class]"
9
+ v-on="wrapperListeners"
5
10
  >
6
- <slot>
7
- <FSCol
8
- :gap="$props.gap"
9
- >
10
- <FSRow
11
- v-if="$slots.header"
12
- >
13
- <slot
14
- name="header"
15
- />
16
- </FSRow>
17
- <FSRow
18
- v-if="$slots.body"
19
- >
20
- <slot
21
- name="body"
22
- />
23
- </FSRow>
24
- <FSRow
25
- v-if="$slots.footer"
26
- >
27
- <slot
28
- name="footer"
29
- />
30
- </FSRow>
31
- </FSCol>
32
- </slot>
33
- <FSRow
34
- v-if="$slots['top-right']"
35
- class="fs-card-top-right"
11
+ <div
12
+ :class="classes"
36
13
  >
37
14
  <slot
38
- name="top-right"
15
+ name="default"
16
+ v-bind="{ contentVariant }"
17
+ />
18
+ <v-progress-circular
19
+ v-if="$props.load"
20
+ class="fs-card-load__spinner"
21
+ width="2"
22
+ size="24"
23
+ :indeterminate="true"
24
+ :color="loadColor"
39
25
  />
40
- </FSRow>
41
- </div>
26
+ <FSRow
27
+ v-if="$slots['top-right'] && !$props.load"
28
+ class="fs-card-top-right"
29
+ >
30
+ <slot
31
+ name="top-right"
32
+ />
33
+ </FSRow>
34
+ </div>
35
+ </FSRouterLink>
42
36
  </template>
43
37
 
44
38
  <script lang="ts">
45
- import { computed, defineComponent, type PropType, type StyleValue } from "vue";
39
+ import { computed, defineComponent, ref, type PropType, type StyleValue } from "vue";
40
+ import { type RouteLocation } from "vue-router";
46
41
 
47
- import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
48
- import { useColors } from "@dative-gpi/foundation-shared-components/composables";
49
42
  import { sizeToVar } from "@dative-gpi/foundation-shared-components/utils";
43
+ import { useColors } from "@dative-gpi/foundation-shared-components/composables";
44
+ import { type CardVariant, type ColorBase, ColorEnum, CardVariants, type ColorBaseVariations } from "@dative-gpi/foundation-shared-components/models";
50
45
 
51
- import FSCol from "./FSCol.vue";
52
46
  import FSRow from "./FSRow.vue";
47
+ import FSRouterLink from "./FSRouterLink.vue";
53
48
 
54
49
  export default defineComponent({
55
50
  name: "FSCard",
56
51
  components: {
57
- FSCol,
52
+ FSRouterLink,
58
53
  FSRow
59
54
  },
60
55
  props: {
61
56
  height: {
62
57
  type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
63
- required: false,
64
58
  default: null
65
59
  },
66
60
  width: {
67
61
  type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
68
- required: false,
69
62
  default: null
70
63
  },
71
64
  maxWidth: {
72
65
  type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
73
- required: false,
74
66
  default: null
75
67
  },
76
68
  padding: {
77
69
  type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
78
- required: false,
79
70
  default: "0"
80
71
  },
81
- gap: {
82
- type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
72
+ class: {
73
+ type: [String, Array] as PropType<string | string[] | null>,
74
+ default: null
75
+ },
76
+ to: {
77
+ type: Object as PropType<RouteLocation | null>,
78
+ default: null
79
+ },
80
+ href: {
81
+ type: String as PropType<string | null>,
82
+ default: null
83
+ },
84
+ onClick: {
85
+ type: Function as PropType<(event: MouseEvent) => void | null>,
83
86
  required: false,
84
- default: "8px"
87
+ default: null
85
88
  },
86
89
  variant: {
87
- type: String as PropType<"background" | "standard" | "full" | "gradient">,
90
+ type: String as PropType<CardVariant>,
88
91
  required: false,
89
- default: "background"
92
+ default: CardVariants.Background
93
+ },
94
+ clickable: {
95
+ type: Boolean as PropType<boolean | null>,
96
+ default: null
90
97
  },
91
98
  color: {
92
99
  type: [Array, String] as PropType<ColorBase | ColorBase[]>,
93
- required: false,
94
100
  default: ColorEnum.Background
95
101
  },
96
102
  border: {
97
103
  type: Boolean,
98
- required: false,
99
104
  default: true
100
105
  },
101
106
  borderRadius: {
102
107
  type: [String, Number],
103
- required: false,
104
108
  default: "4px"
105
109
  },
106
110
  borderStyle: {
107
111
  type: String as PropType<"solid" | "dashed" | "dotted" | "double" | "groove" | "ridge" | "inset" | "outset" | "none">,
108
- required: false,
109
112
  default: "solid"
110
113
  },
111
114
  borderColor: {
112
115
  type: [Array, String] as PropType<ColorBase | null | string>,
113
- required: false,
114
116
  default: null
115
117
  },
116
118
  elevation: {
117
119
  type: Boolean,
118
- required: false,
119
120
  default: false
120
121
  },
121
122
  topRightPadding: {
122
123
  type: [String, Number],
123
- required: false,
124
124
  default: "4px"
125
+ },
126
+ type: {
127
+ type: String as PropType<"button" | "submit" | "reset" | null>,
128
+ default: null
129
+ },
130
+ load: {
131
+ type: Boolean,
132
+ default: false
133
+ },
134
+ disabled: {
135
+ type: Boolean,
136
+ default: false
125
137
  }
126
138
  },
127
- setup(props) {
139
+ setup(props, { emit }) {
128
140
  const { getColors, getGradients } = useColors();
129
141
 
142
+ const active = ref(false);
143
+ const hover = ref(false);
144
+
145
+ const backgrounds = getColors(ColorEnum.Background);
146
+ const lights = getColors(ColorEnum.Light);
147
+
130
148
  const colors = computed(() => {
131
149
  if (Array.isArray(props.color)) {
132
150
  return getColors(props.color[0]);
133
151
  }
134
152
  return getColors(props.color);
135
153
  });
154
+
136
155
  const gradients = computed(() => getGradients(props.color, 135));
137
- const backgrounds = getColors(ColorEnum.Background);
138
- const lights = getColors(ColorEnum.Light);
139
- const darks = getColors(ColorEnum.Dark);
156
+
157
+ const actualClickable = computed((): boolean => {
158
+ if (props.clickable === false || props.disabled) {
159
+ return false;
160
+ }
161
+ return props.clickable || !!props.to || !!props.href || !!props.onClick;
162
+ });
163
+
164
+ const actualWrapperType = computed(() => {
165
+ if (props.type) {
166
+ return props.type;
167
+ }
168
+ return "button";
169
+ });
170
+
171
+ const contentVariant = computed((): ColorBaseVariations => {
172
+ if (active.value) {
173
+ return "darkContrast";
174
+ }
175
+ if (hover.value) {
176
+ return "baseContrast";
177
+ }
178
+ switch (props.variant) {
179
+ case "standard" : return "lightContrast";
180
+ case "background": return "base";
181
+ case "full" : return "baseContrast";
182
+ }
183
+ return "base";
184
+ });
140
185
 
141
186
  const borderColor = computed((): ColorBase => {
142
187
  if (props.borderColor) {
@@ -159,59 +204,76 @@ export default defineComponent({
159
204
  }
160
205
  });
161
206
 
207
+ const loadColor = computed((): string => {
208
+ return colors.value[contentVariant.value] ?? colors.value.baseContrast!;
209
+ });
210
+
162
211
  const style = computed((): StyleValue => {
212
+ const baseStyle = {
213
+ "--fs-card-border-size" : props.border ? "1px" : "0",
214
+ "--fs-card-border-style" : props.borderStyle,
215
+ "--fs-card-border-radius" : sizeToVar(props.borderRadius),
216
+ "--fs-card-padding" : sizeToVar(props.padding),
217
+ "--fs-card-height" : sizeToVar(props.height),
218
+ "--fs-card-width" : sizeToVar(props.width),
219
+ "--fs-card-max-width" : sizeToVar(props.maxWidth, "unset"),
220
+ "--fs-card-top-right-padding": sizeToVar(props.topRightPadding)
221
+ };
222
+ if (props.disabled) {
223
+ return {
224
+ ...baseStyle,
225
+ "--fs-card-background-color": lights.light,
226
+ "--fs-card-border-color" : lights.dark,
227
+ "--fs-card-color" : lights.lightContrast!
228
+ };
229
+ }
230
+
163
231
  switch (props.variant) {
164
232
  case "background": return {
165
- "--fs-card-border-size" : props.border ? "1px" : "0",
166
- "--fs-card-border-style" : props.borderStyle,
167
- "--fs-card-border-radius" : sizeToVar(props.borderRadius),
168
- "--fs-card-padding" : sizeToVar(props.padding),
169
- "--fs-card-height" : sizeToVar(props.height),
170
- "--fs-card-width" : sizeToVar(props.width),
171
- "--fs-card-max-width" : sizeToVar(props.maxWidth, "unset"),
233
+ ...baseStyle,
172
234
  "--fs-card-background-color": backgrounds.base,
173
235
  "--fs-card-border-color" : borderColor.value,
174
- "--fs-card-color" : darks.base,
175
- "--fs-card-top-right-padding": sizeToVar(props.topRightPadding)
236
+ "--fs-card-color" : backgrounds.baseContrast!,
237
+ "--fs-card-hover-background-color" : colors.value.base,
238
+ "--fs-card-hover-border-color" : colors.value.baseContrast!,
239
+ "--fs-card-hover-color" : colors.value.baseContrast!
176
240
  }
177
- case "standard": return {
178
- "--fs-card-border-size" : props.border ? "1px" : "0",
179
- "--fs-card-border-style" : props.borderStyle,
180
- "--fs-card-border-radius" : sizeToVar(props.borderRadius),
181
- "--fs-card-padding" : sizeToVar(props.padding),
182
- "--fs-card-height" : sizeToVar(props.height),
183
- "--fs-card-width" : sizeToVar(props.width),
184
- "--fs-card-max-width" : sizeToVar(props.maxWidth, "unset"),
185
- "--fs-card-background-color": colors.value.light,
186
- "--fs-card-border-color" : borderColor.value,
187
- "--fs-card-color" : colors.value.lightContrast!,
188
- "--fs-card-top-right-padding": sizeToVar(props.topRightPadding)
241
+ case "standard": {
242
+ if (actualClickable.value && !Array.isArray(props.color) && [ColorEnum.Light, ColorEnum.Dark].includes(props.color as ColorEnum)) {
243
+ return {
244
+ ...baseStyle,
245
+ "--fs-card-background-color": backgrounds.base,
246
+ "--fs-card-border-color" : lights.dark,
247
+ "--fs-card-color" : backgrounds.baseContrast!,
248
+ "--fs-card-hover-background-color" : lights.base,
249
+ "--fs-card-hover-border-color" : lights.dark,
250
+ "--fs-card-hover-color" : lights.baseContrast!
251
+ };
252
+ }
253
+ return {
254
+ ...baseStyle,
255
+ "--fs-card-background-color": colors.value.light,
256
+ "--fs-card-border-color" : borderColor.value,
257
+ "--fs-card-color" : colors.value.lightContrast!,
258
+ "--fs-card-hover-background-color" : colors.value.base,
259
+ "--fs-card-hover-border-color" : colors.value.base,
260
+ "--fs-card-hover-color" : colors.value.baseContrast!
261
+ };
189
262
  }
190
263
  case "full": return {
191
- "--fs-card-border-size" : props.border ? "1px" : "0",
192
- "--fs-card-border-style" : props.borderStyle,
193
- "--fs-card-border-radius" : sizeToVar(props.borderRadius),
194
- "--fs-card-padding" : sizeToVar(props.padding),
195
- "--fs-card-height" : sizeToVar(props.height),
196
- "--fs-card-width" : sizeToVar(props.width),
197
- "--fs-card-max-width" : sizeToVar(props.maxWidth, "unset"),
264
+ ...baseStyle,
198
265
  "--fs-card-background-color": colors.value.base,
199
266
  "--fs-card-border-color" : borderColor.value,
200
267
  "--fs-card-color" : colors.value.baseContrast!,
201
- "--fs-card-top-right-padding": sizeToVar(props.topRightPadding)
268
+ "--fs-card-hover-background-color" : colors.value.base,
269
+ "--fs-card-hover-border-color" : colors.value.base,
270
+ "--fs-card-hover-color" : colors.value.baseContrast!
202
271
  }
203
272
  case "gradient": return {
204
- "--fs-card-border-size" : props.border ? "1px" : "0",
205
- "--fs-card-border-style" : props.borderStyle,
206
- "--fs-card-border-radius" : sizeToVar(props.borderRadius),
207
- "--fs-card-padding" : sizeToVar(props.padding),
208
- "--fs-card-height" : sizeToVar(props.height),
209
- "--fs-card-width" : sizeToVar(props.width),
210
- "--fs-card-max-width" : sizeToVar(props.maxWidth, "unset"),
273
+ ...baseStyle,
211
274
  "--fs-card-background-color": gradients.value.base,
212
275
  "--fs-card-border-color" : borderColor.value,
213
- "--fs-card-color" : colors.value.lightContrast!,
214
- "--fs-card-top-right-padding": sizeToVar(props.topRightPadding)
276
+ "--fs-card-color" : colors.value.lightContrast!
215
277
  }
216
278
  }
217
279
  });
@@ -224,21 +286,60 @@ export default defineComponent({
224
286
  break;
225
287
  case "background":
226
288
  classNames.push("fs-card-background");
227
- classNames.push("fs-card-clickable");
228
289
  break;
229
290
  default:
230
291
  classNames.push("fs-card-background");
231
292
  break;
232
293
  }
294
+
295
+ if (actualClickable.value) {
296
+ classNames.push("fs-card-clickable");
297
+ }
298
+ if (props.disabled) {
299
+ classNames.push("fs-card-disabled");
300
+ }
301
+ if (props.load) {
302
+ classNames.push("fs-card-load");
303
+ }
233
304
  if (props.elevation) {
234
305
  classNames.push("fs-card-elevation");
235
306
  }
307
+
236
308
  return classNames;
237
309
  });
310
+
311
+ const wrapperListeners = computed(() => {
312
+ if (actualClickable.value && !props.disabled) {
313
+ return {
314
+ mouseover: () => { hover.value = true },
315
+ mouseleave: () => { hover.value = false },
316
+ mousedown: () => { active.value = true },
317
+ mouseup: () => { active.value = false },
318
+ "click": onClick
319
+ };
320
+ }
321
+ return {};
322
+ });
323
+
324
+ const onClick = (event: MouseEvent) => {
325
+ if (!actualClickable.value || props.disabled || props.load || props.href || props.to) {
326
+ return;
327
+ }
328
+ emit("click", event);
329
+ };
238
330
 
239
331
  return {
332
+ actualWrapperType,
333
+ actualClickable,
334
+ contentVariant,
335
+ FSRouterLink,
336
+ loadColor,
240
337
  classes,
241
- style
338
+ active,
339
+ hover,
340
+ style,
341
+ onClick,
342
+ wrapperListeners
242
343
  };
243
344
  }
244
345
  });