@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.
@@ -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: () => ["24", "20"]
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="size"
7
- :width="size"
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: "0px"
55
+ default: "8px"
56
56
  }
57
57
  },
58
58
  setup(props) {
59
59
  const { isMobileSized } = useBreakpoints();
60
60
 
61
- const size = computed((): string[] | number[] | string | number | null => {
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
- if (!props.padding) {
72
- return size.value;
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
- iconSize,
79
- size
81
+ actualSize,
82
+ iconSize
80
83
  };
81
84
  }
82
85
  });
@@ -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
- import { sizeToVar } from "@dative-gpi/foundation-shared-components/utils";
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="['wrap'].includes(props.variant)"
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,6 +1,7 @@
1
1
  <template>
2
2
  <FSRow
3
3
  :wrap="false"
4
+ align="center-center"
4
5
  >
5
6
  <FSButton
6
7
  v-if="$props.modelStatuses.length > 1"
@@ -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,
@@ -428,7 +428,6 @@ export default defineComponent({
428
428
  }
429
429
  }
430
430
  else {
431
- console.log(value[0], value[1]);
432
431
  if (value && value[0] != null && epochToISO(value[0]) !== innerStartDate.value) {
433
432
  innerStartDate.value = epochToISO(value[0]);
434
433
  if (valid.value) {
@@ -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 ?? ((value, property) => {
1223
- property = [property].flat();
1224
- return Array.isArray(property) ? property.includes(value) || (!value && property.length == 0) : (!value && !property) || value == property;
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) => Array.isArray(item[key]) && item[key].length == 0 ? undefined : item[key]).map(mapToInnerValue);
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
- hidden: currentFilters?.find((cf) => cf.value == (dv || null))?.hidden ?? false,
1236
- text: dv?.toString() ?? "—",
1237
- value: dv || null,
1238
- filter: header.methodFilter ?? ((_, property) => {
1239
- property = [property].flat().map(mapToInnerValue);
1240
- return Array.isArray(property) ? property.includes(dv) || (!dv && property.length == 0) : (!dv && !property) || dv == property;
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) {
@@ -71,11 +71,12 @@
71
71
  <FSSpan
72
72
  font="text-overline"
73
73
  >
74
- {{ item[itemLabel] }}
74
+ {{ item[$props.itemLabel || 'label'] }}
75
75
  </FSSpan>
76
76
  </slot>
77
77
  <FSRow
78
78
  align="center-right"
79
+ :wrap="false"
79
80
  >
80
81
  <FSButtonEditIcon
81
82
  v-if="showEdit"
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[]) => { console.log(value); return (Array.isArray(value) && value.length >= min) || (message ?? $tr("ui.rules.tree-view-min", "Must select at least {0} elements", min.toString())); },
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, item: any) => boolean) | null;
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.63",
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.63",
14
- "@dative-gpi/foundation-shared-services": "1.0.63"
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": "b2fbfec30ab5c2f3edeaddbc7eed0d3c98fe71c4"
38
+ "gitHead": "942a36ea827fcf856d357a4ad826a6d4e3acf53c"
39
39
  }
@@ -1,8 +1,18 @@
1
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
- background-color: var(--fs-option-group-background-color) !important;
5
- width: fit-content;
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
- border-color: var(--fs-option-group-border-color) !important;
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 !== 'object' || obj === null) {
3
- return String(obj).toLowerCase().includes(searchTerm);
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 Object.values(obj).some(value => containsSearchTerm(value, searchTerm));
8
+ return String(obj).toLowerCase().includes(searchTerm);
9
9
  };
10
10
 
11
11
  export const filterItems = <T>(items: T[], filter: string): T[] => {