@dative-gpi/foundation-shared-components 1.0.63 → 1.0.65
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.
- package/components/FSButton.vue +5 -7
- package/components/FSColorIcon.vue +13 -10
- package/components/FSIcon.vue +2 -1
- package/components/FSOptionGroup.vue +51 -3
- package/components/deviceOrganisations/FSStatusesCarousel.vue +1 -0
- package/components/fields/FSColorField.vue +40 -38
- package/components/fields/FSTermField.vue +0 -1
- package/components/lists/FSDataTableUI.vue +29 -16
- package/components/lists/FSSimpleList.vue +2 -1
- package/models/rules.ts +1 -1
- package/models/tables.ts +3 -1
- package/package.json +4 -4
- package/styles/components/fs_option_group.scss +15 -5
- package/utils/filter.ts +3 -3
package/components/FSButton.vue
CHANGED
|
@@ -230,7 +230,7 @@ export default defineComponent({
|
|
|
230
230
|
iconSize: {
|
|
231
231
|
type: [Array, String, Number] as PropType<"s" | "m" | "l" | string[] | number[] | string | number | null>,
|
|
232
232
|
required: false,
|
|
233
|
-
default: () => ["
|
|
233
|
+
default: () => ["24px", "20px"]
|
|
234
234
|
},
|
|
235
235
|
variant: {
|
|
236
236
|
type: String as PropType<"standard" | "full" | "icon">,
|
|
@@ -310,7 +310,7 @@ export default defineComponent({
|
|
|
310
310
|
});
|
|
311
311
|
|
|
312
312
|
const padding = computed(() => {
|
|
313
|
-
if(props.padding !== DEFAULT_PADDING){
|
|
313
|
+
if (props.padding !== DEFAULT_PADDING) {
|
|
314
314
|
return props.padding;
|
|
315
315
|
}
|
|
316
316
|
|
|
@@ -319,16 +319,14 @@ export default defineComponent({
|
|
|
319
319
|
|
|
320
320
|
const hasLabel = props.label || !!slots.default;
|
|
321
321
|
|
|
322
|
-
if(!hasLabel && hasIcon){
|
|
322
|
+
if (!hasLabel && hasIcon) {
|
|
323
323
|
return PADDING_ICON_ONLY;
|
|
324
324
|
}
|
|
325
|
-
else if(hasLabel && !hasIcon)
|
|
326
|
-
{
|
|
325
|
+
else if (hasLabel && !hasIcon) {
|
|
327
326
|
return PADDING_LABEL_ONLY;
|
|
328
327
|
}
|
|
329
|
-
|
|
330
328
|
return DEFAULT_PADDING;
|
|
331
|
-
})
|
|
329
|
+
});
|
|
332
330
|
|
|
333
331
|
const onClick = (event: MouseEvent) => {
|
|
334
332
|
if (!props.to && !props.href && props.editable && !props.load) {
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
class="fs-color-icon"
|
|
4
4
|
:color="$props.color"
|
|
5
5
|
:border="false"
|
|
6
|
-
:height="
|
|
7
|
-
:width="
|
|
6
|
+
:height="actualSize"
|
|
7
|
+
:width="actualSize"
|
|
8
8
|
>
|
|
9
9
|
<FSRow
|
|
10
10
|
align="center-center"
|
|
@@ -52,13 +52,13 @@ export default defineComponent({
|
|
|
52
52
|
padding: {
|
|
53
53
|
type: [String, Number] as PropType<string | number>,
|
|
54
54
|
required: false,
|
|
55
|
-
default: "
|
|
55
|
+
default: "8px"
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
setup(props) {
|
|
59
59
|
const { isMobileSized } = useBreakpoints();
|
|
60
60
|
|
|
61
|
-
const
|
|
61
|
+
const actualSize = computed((): string[] | number[] | string | number | null => {
|
|
62
62
|
switch(props.size) {
|
|
63
63
|
case "s": return isMobileSized.value ? "18px" : "20px";
|
|
64
64
|
case "m": return isMobileSized.value ? "20px" : "26px";
|
|
@@ -67,16 +67,19 @@ export default defineComponent({
|
|
|
67
67
|
}
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
const iconSize = computed(() => {
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
const iconSize = computed((): string => {
|
|
71
|
+
switch(props.size) {
|
|
72
|
+
case "s":
|
|
73
|
+
case "m":
|
|
74
|
+
case "l":
|
|
75
|
+
return props.size;
|
|
76
|
+
default: return `calc(${sizeToVar(props.size)} - ${sizeToVar(props.padding)})`;
|
|
73
77
|
}
|
|
74
|
-
return `calc(${sizeToVar(size.value)} - ${sizeToVar(props.padding)})`;
|
|
75
78
|
});
|
|
76
79
|
|
|
77
80
|
return {
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
actualSize,
|
|
82
|
+
iconSize
|
|
80
83
|
};
|
|
81
84
|
}
|
|
82
85
|
});
|
package/components/FSIcon.vue
CHANGED
|
@@ -14,7 +14,8 @@ import { computed, defineComponent, type PropType, type StyleValue } from "vue";
|
|
|
14
14
|
|
|
15
15
|
import { useBreakpoints, useColors } from "@dative-gpi/foundation-shared-components/composables";
|
|
16
16
|
import { type ColorBase } from "@dative-gpi/foundation-shared-components/models";
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
import { sizeToVar } from "../utils";
|
|
18
19
|
|
|
19
20
|
export default defineComponent({
|
|
20
21
|
name: "FSIcon",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<FSWrapGroup
|
|
3
|
-
v-if="
|
|
3
|
+
v-if="props.variant === 'wrap'"
|
|
4
4
|
class="fs-option-group"
|
|
5
5
|
:padding="props.padding"
|
|
6
6
|
:gap="props.gap"
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
/>
|
|
47
47
|
</FSWrapGroup>
|
|
48
48
|
<FSSlideGroup
|
|
49
|
-
v-else
|
|
49
|
+
v-else-if="props.variant === 'slide'"
|
|
50
50
|
class="fs-option-group"
|
|
51
51
|
:padding="props.padding"
|
|
52
52
|
:gap="props.gap"
|
|
@@ -91,6 +91,54 @@
|
|
|
91
91
|
v-bind="{ toggle, getVariant, getColor, getClass }"
|
|
92
92
|
/>
|
|
93
93
|
</FSSlideGroup>
|
|
94
|
+
<FSRow
|
|
95
|
+
v-else
|
|
96
|
+
class="fs-option-group-full-width"
|
|
97
|
+
width="100%"
|
|
98
|
+
:padding="props.padding"
|
|
99
|
+
:gap="props.gap"
|
|
100
|
+
:style="style"
|
|
101
|
+
:wrap="false"
|
|
102
|
+
>
|
|
103
|
+
<template
|
|
104
|
+
v-if="props.values.length"
|
|
105
|
+
>
|
|
106
|
+
<template
|
|
107
|
+
v-if="!$slots.item"
|
|
108
|
+
>
|
|
109
|
+
<FSOptionItem
|
|
110
|
+
v-for="(item, index) in props.values"
|
|
111
|
+
:padding="props.optionPadding"
|
|
112
|
+
:editable="props.editable"
|
|
113
|
+
:prependIcon="item.prependIcon"
|
|
114
|
+
:appendIcon="item.appendIcon"
|
|
115
|
+
:variant="getVariant(item)"
|
|
116
|
+
:color="getColor(item)"
|
|
117
|
+
:class="getClass(item)"
|
|
118
|
+
:label="item.label"
|
|
119
|
+
:icon="item.icon"
|
|
120
|
+
:key="index"
|
|
121
|
+
@click="toggle(item)"
|
|
122
|
+
/>
|
|
123
|
+
</template>
|
|
124
|
+
<template
|
|
125
|
+
v-else
|
|
126
|
+
>
|
|
127
|
+
<template
|
|
128
|
+
v-for="item in props.values"
|
|
129
|
+
>
|
|
130
|
+
<slot
|
|
131
|
+
name="item"
|
|
132
|
+
v-bind="{ item, toggle, getVariant, getColor, getClass }"
|
|
133
|
+
/>
|
|
134
|
+
</template>
|
|
135
|
+
</template>
|
|
136
|
+
</template>
|
|
137
|
+
<slot
|
|
138
|
+
v-else
|
|
139
|
+
v-bind="{ toggle, getVariant, getColor, getClass }"
|
|
140
|
+
/>
|
|
141
|
+
</FSRow>
|
|
94
142
|
</template>
|
|
95
143
|
|
|
96
144
|
<script lang="ts">
|
|
@@ -128,7 +176,7 @@ export default defineComponent({
|
|
|
128
176
|
default: "4px"
|
|
129
177
|
},
|
|
130
178
|
variant: {
|
|
131
|
-
type: String as PropType<"wrap" | "slide">,
|
|
179
|
+
type: String as PropType<"wrap" | "slide" | "fullwidth">,
|
|
132
180
|
required: false,
|
|
133
181
|
default: "wrap"
|
|
134
182
|
},
|
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
|
|
3
|
+
<FSBaseField
|
|
4
|
+
class="fs-color-field"
|
|
5
|
+
:description="$props.description"
|
|
6
|
+
:hideHeader="$props.hideHeader"
|
|
7
|
+
:editable="$props.editable"
|
|
8
|
+
:required="$props.required"
|
|
9
|
+
:label="$props.label"
|
|
10
|
+
:width="$props.width"
|
|
11
|
+
:style="style"
|
|
12
|
+
:modelValue="innerColor"
|
|
13
|
+
v-bind="$attrs"
|
|
14
|
+
>
|
|
15
|
+
<FSCard
|
|
16
|
+
:id="activatorId"
|
|
17
|
+
padding="8px"
|
|
18
|
+
width="100%"
|
|
19
|
+
:class="{ 'fs-color-field-disabled': !$props.editable }"
|
|
20
|
+
>
|
|
21
|
+
<FSRow
|
|
22
|
+
align="center-center"
|
|
23
|
+
>
|
|
24
|
+
<FSIcon
|
|
25
|
+
icon="mdi-circle-half"
|
|
26
|
+
size="20px"
|
|
27
|
+
:color="innerColor"
|
|
28
|
+
/>
|
|
29
|
+
<FSText
|
|
30
|
+
font="text-overline"
|
|
31
|
+
>
|
|
32
|
+
{{ innerColor }}
|
|
33
|
+
</FSText>
|
|
34
|
+
</FSRow>
|
|
35
|
+
</FSCard>
|
|
36
|
+
</FSBaseField>
|
|
2
37
|
<v-menu
|
|
38
|
+
origin="top left"
|
|
39
|
+
min-width="300px"
|
|
40
|
+
:activator="`#${activatorId}`"
|
|
3
41
|
:closeOnContentClick="false"
|
|
4
42
|
:modelValue="menu && $props.editable"
|
|
5
43
|
@update:modelValue="menu = $event"
|
|
6
44
|
>
|
|
7
|
-
<template
|
|
8
|
-
#activator="{ props }"
|
|
9
|
-
>
|
|
10
|
-
<FSBaseField
|
|
11
|
-
class="fs-color-field"
|
|
12
|
-
:description="$props.description"
|
|
13
|
-
:hideHeader="$props.hideHeader"
|
|
14
|
-
:editable="$props.editable"
|
|
15
|
-
:required="$props.required"
|
|
16
|
-
:label="$props.label"
|
|
17
|
-
:width="$props.width"
|
|
18
|
-
:style="style"
|
|
19
|
-
:modelValue="innerColor"
|
|
20
|
-
v-bind="$attrs"
|
|
21
|
-
>
|
|
22
|
-
<FSCard
|
|
23
|
-
padding="8px"
|
|
24
|
-
width="100%"
|
|
25
|
-
:class="{ 'fs-color-field-disabled': !$props.editable }"
|
|
26
|
-
v-bind="props"
|
|
27
|
-
>
|
|
28
|
-
<FSRow
|
|
29
|
-
align="center-center"
|
|
30
|
-
>
|
|
31
|
-
<FSIcon
|
|
32
|
-
icon="mdi-circle-half"
|
|
33
|
-
size="20px"
|
|
34
|
-
:color="innerColor"
|
|
35
|
-
/>
|
|
36
|
-
<FSText
|
|
37
|
-
font="text-overline"
|
|
38
|
-
>
|
|
39
|
-
{{ innerColor }}
|
|
40
|
-
</FSText>
|
|
41
|
-
</FSRow>
|
|
42
|
-
</FSCard>
|
|
43
|
-
</FSBaseField>
|
|
44
|
-
</template>
|
|
45
45
|
<FSCard
|
|
46
46
|
:elevation="true"
|
|
47
47
|
:border="false"
|
|
@@ -156,6 +156,7 @@ export default defineComponent({
|
|
|
156
156
|
setup(props, { emit }) {
|
|
157
157
|
const { getColors, getBasePaletteColors } = useColors();
|
|
158
158
|
const { slots } = useSlots();
|
|
159
|
+
const activatorId = `activator-${Math.random().toString(36).substring(7)}`;
|
|
159
160
|
|
|
160
161
|
delete slots.description;
|
|
161
162
|
|
|
@@ -214,6 +215,7 @@ export default defineComponent({
|
|
|
214
215
|
getPercentageFromHex,
|
|
215
216
|
getBasePaletteColors,
|
|
216
217
|
innerOpacity,
|
|
218
|
+
activatorId,
|
|
217
219
|
innerColor,
|
|
218
220
|
fullColor,
|
|
219
221
|
ColorEnum,
|
|
@@ -1212,6 +1212,8 @@ export default defineComponent({
|
|
|
1212
1212
|
const key = header.value!;
|
|
1213
1213
|
const currentFilters = filters.value[key];
|
|
1214
1214
|
|
|
1215
|
+
const getPath = (object: any, keys: string[]) => keys.reduce((acc, key) => acc[key] ?? null, object);
|
|
1216
|
+
|
|
1215
1217
|
let value: FSDataTableFilter[] = [];
|
|
1216
1218
|
|
|
1217
1219
|
if (header.fixedFilters) {
|
|
@@ -1219,32 +1221,43 @@ export default defineComponent({
|
|
|
1219
1221
|
hidden: currentFilters?.find((cf) => cf.value == (ff.value || null))?.hidden ?? false,
|
|
1220
1222
|
text: ff.text?.toString() ?? "—",
|
|
1221
1223
|
value: ff.value || null,
|
|
1222
|
-
filter: header.methodFilter ?? ((
|
|
1223
|
-
|
|
1224
|
-
|
|
1224
|
+
filter: header.methodFilter ?? ((_, property, item) => {
|
|
1225
|
+
if (header.methodFilterRaw) {
|
|
1226
|
+
return header.methodFilterRaw(ff.value, item);
|
|
1227
|
+
}
|
|
1228
|
+
const flat = property = [property].flat();
|
|
1229
|
+
return Array.isArray(flat) ? flat.includes(ff.value) || (!ff.value && flat.length == 0) : (!ff.value && !flat) || ff.value == flat;
|
|
1225
1230
|
})
|
|
1226
1231
|
}));
|
|
1232
|
+
filterDictionary[key] = value;
|
|
1227
1233
|
}
|
|
1228
1234
|
else {
|
|
1229
1235
|
if (props.items && props.items.length) {
|
|
1230
1236
|
const mapToInnerValue = header.innerValue ? header.innerValue : (i: any) => i;
|
|
1231
|
-
const itemValues = props.items.flatMap((item) =>
|
|
1237
|
+
const itemValues = props.items.flatMap((item) => {
|
|
1238
|
+
return Array.isArray(getPath(item, key.split("."))) && getPath(item, key.split(".")).length == 0 ? undefined : getPath(item, key.split("."))
|
|
1239
|
+
}).map(mapToInnerValue);
|
|
1232
1240
|
const distinctValues = [...new Set(itemValues)];
|
|
1233
1241
|
|
|
1234
|
-
value = distinctValues.map((dv): FSDataTableFilter =>
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1242
|
+
value = distinctValues.map((dv): FSDataTableFilter => {
|
|
1243
|
+
return {
|
|
1244
|
+
hidden: currentFilters?.find((cf) => cf.value == (dv || null))?.hidden ?? false,
|
|
1245
|
+
text: dv?.toString() ?? "—",
|
|
1246
|
+
value: dv || null,
|
|
1247
|
+
filter: header.methodFilter ?? ((_, property, item) => {
|
|
1248
|
+
if (header.methodFilterRaw) {
|
|
1249
|
+
return header.methodFilterRaw(dv, item);
|
|
1250
|
+
}
|
|
1251
|
+
const flat = [property].flat().map(mapToInnerValue);
|
|
1252
|
+
return Array.isArray(flat) ? flat.includes(dv) || (!dv && flat.length == 0) : (!dv && !flat) || dv == flat;
|
|
1253
|
+
})
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1243
1256
|
}
|
|
1257
|
+
filterDictionary[key] = value.sort((v1, v2) => {
|
|
1258
|
+
return v1.text.localeCompare(v2.text, undefined, { numeric: true });
|
|
1259
|
+
});
|
|
1244
1260
|
}
|
|
1245
|
-
filterDictionary[key] = value.sort((v1, v2) => {
|
|
1246
|
-
return v1.text.localeCompare(v2.text, undefined, { numeric: true });
|
|
1247
|
-
});
|
|
1248
1261
|
}
|
|
1249
1262
|
for (const [key, filters] of Object.entries(props.filters)) {
|
|
1250
1263
|
for (const filter of filters) {
|
package/models/rules.ts
CHANGED
|
@@ -76,6 +76,6 @@ export const ToggleRules = {
|
|
|
76
76
|
|
|
77
77
|
export const TreeViewRules = {
|
|
78
78
|
required: (message: string | undefined = undefined) => (value: string) => !!value || (message ?? $tr("ui.rules.required", "Required")),
|
|
79
|
-
min: (min: number, message: string | undefined = undefined) => (value: string[]) =>
|
|
79
|
+
min: (min: number, message: string | undefined = undefined) => (value: string[]) => (Array.isArray(value) && value.length >= min) || (message ?? $tr("ui.rules.tree-view-min", "Must select at least {0} elements", min.toString())),
|
|
80
80
|
max: (max: number, message: string | undefined = undefined) => (value: string[]) => (Array.isArray(value) && value.length <= max) || (message ?? $tr("ui.rules.tree-view-max", "Must select at most {0} elements", max.toString()))
|
|
81
81
|
};
|
package/models/tables.ts
CHANGED
|
@@ -8,10 +8,12 @@ export interface FSDataTableColumn {
|
|
|
8
8
|
|
|
9
9
|
sortable?: boolean | null;
|
|
10
10
|
sort?: ((a: any, b: any) => number) | null;
|
|
11
|
+
sortRaw?: ((a: any, b: any) => number) | null;
|
|
11
12
|
|
|
12
13
|
filterable?: boolean | null;
|
|
13
14
|
fixedFilters?: { value: any, text: string }[] | null;
|
|
14
|
-
methodFilter?: ((value: any,
|
|
15
|
+
methodFilter?: ((value: any, property: any) => boolean) | null;
|
|
16
|
+
methodFilterRaw?: ((value: any, item: any) => boolean) | null;
|
|
15
17
|
filter?: ((value: any, search: string, item: any) => boolean) | null;
|
|
16
18
|
|
|
17
19
|
innerValue?: ((value: any) => any) | null;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dative-gpi/foundation-shared-components",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.65",
|
|
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": "1.0.
|
|
14
|
-
"@dative-gpi/foundation-shared-services": "1.0.
|
|
13
|
+
"@dative-gpi/foundation-shared-domain": "1.0.65",
|
|
14
|
+
"@dative-gpi/foundation-shared-services": "1.0.65"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
17
|
"@dative-gpi/bones-ui": "^0.0.75",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"sass": "1.71.1",
|
|
36
36
|
"sass-loader": "13.3.2"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "942a36ea827fcf856d357a4ad826a6d4e3acf53c"
|
|
39
39
|
}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
.fs-option-group {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
border-radius: var(--fs-option-group-border-radius) !important;
|
|
3
|
+
border: var(--fs-option-group-border-size) solid !important;
|
|
4
|
+
background-color: var(--fs-option-group-background-color) !important;
|
|
5
|
+
border-color: var(--fs-option-group-border-color) !important;
|
|
6
|
+
width: fit-content;
|
|
7
|
+
}
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
.fs-option-group-full-width {
|
|
10
|
+
border-radius: var(--fs-option-group-border-radius) !important;
|
|
11
|
+
border: var(--fs-option-group-border-size) solid !important;
|
|
12
|
+
background-color: var(--fs-option-group-background-color) !important;
|
|
13
|
+
border-color: var(--fs-option-group-border-color) !important;
|
|
14
|
+
|
|
15
|
+
& > * {
|
|
16
|
+
width: 100% !important;
|
|
17
|
+
}
|
|
8
18
|
}
|
package/utils/filter.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export const containsSearchTerm = (obj: any, searchTerm: string): boolean => {
|
|
2
|
-
if (typeof obj
|
|
3
|
-
return
|
|
2
|
+
if (typeof obj === 'object') {
|
|
3
|
+
return Object.values(obj).some(value => containsSearchTerm(value, searchTerm));
|
|
4
4
|
}
|
|
5
5
|
if (Array.isArray(obj)) {
|
|
6
6
|
return obj.some(element => containsSearchTerm(element, searchTerm));
|
|
7
7
|
}
|
|
8
|
-
return
|
|
8
|
+
return String(obj).toLowerCase().includes(searchTerm);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export const filterItems = <T>(items: T[], filter: string): T[] => {
|