@dative-gpi/foundation-shared-components 1.1.24-unit-formatter → 1.1.24-unit-formatter-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/assets/images/map/open-street-map.png +0 -0
  2. package/components/FSAccordionPanel.vue +2 -0
  3. package/components/FSButton.vue +43 -87
  4. package/components/FSCard.vue +208 -100
  5. package/components/FSCardPlaceholder.vue +29 -25
  6. package/components/FSChip.vue +54 -127
  7. package/components/FSChipGroup.vue +141 -23
  8. package/components/FSClickable.vue +24 -326
  9. package/components/FSColor.vue +3 -3
  10. package/components/FSColorIcon.vue +1 -0
  11. package/components/FSDialogContent.vue +39 -28
  12. package/components/FSDialogFormBody.vue +2 -0
  13. package/components/FSDialogMenu.vue +8 -1
  14. package/components/FSDialogMultiFormBody.vue +6 -5
  15. package/components/FSDivider.vue +5 -1
  16. package/components/FSEditImageUI.vue +21 -30
  17. package/components/FSGridMosaic.vue +2 -0
  18. package/components/FSGroupingChip.vue +115 -0
  19. package/components/FSIconCard.vue +3 -1
  20. package/components/FSIconCheck.vue +8 -0
  21. package/components/FSImageCard.vue +4 -4
  22. package/components/FSInstantPicker.vue +2 -0
  23. package/components/FSLink.vue +1 -13
  24. package/components/FSOptionItem.vue +4 -4
  25. package/components/FSOptionsMenu.vue +6 -6
  26. package/components/FSPlayButtons.vue +11 -9
  27. package/components/FSProgressBar.vue +142 -28
  28. package/components/FSRangePicker.vue +2 -0
  29. package/components/FSRouterLink.vue +84 -14
  30. package/components/FSSlideGroup.vue +5 -1
  31. package/components/FSSnackbar.vue +146 -0
  32. package/components/FSSubgroupingChip.vue +138 -0
  33. package/components/FSWindow.vue +2 -0
  34. package/components/agenda/FSAgendaHorizontalEvent.vue +4 -4
  35. package/components/agenda/FSAgendaVerticalEvent.vue +4 -4
  36. package/components/deviceOrganisations/FSStatusRichCard.vue +4 -7
  37. package/components/fields/FSAutocompleteField.vue +1 -0
  38. package/components/fields/FSDurationField.vue +184 -0
  39. package/components/fields/FSEntityFieldUI.vue +12 -0
  40. package/components/fields/FSRichTextField.vue +2 -0
  41. package/components/lists/FSDataIteratorItem.vue +2 -0
  42. package/components/lists/FSDataTableUI.vue +12 -0
  43. package/components/lists/FSFilterButton.vue +34 -23
  44. package/components/lists/FSHeaderButton.vue +6 -3
  45. package/components/lists/FSTileList.vue +23 -6
  46. package/components/map/FSMap.vue +1 -1
  47. package/components/map/FSMapMarker.vue +4 -3
  48. package/components/selects/FSSelectMapLayer.vue +5 -0
  49. package/components/tiles/FSChartTileUI.vue +2 -0
  50. package/components/tiles/FSFolderTileUI.vue +2 -2
  51. package/components/tiles/FSLocationTileUI.vue +2 -0
  52. package/components/tiles/FSPlaylistTileUI.vue +149 -0
  53. package/components/tiles/FSServiceAccountOrganisationTileUI.vue +2 -0
  54. package/components/tiles/FSSubgroupingTileUI.vue +97 -0
  55. package/components/tiles/FSTile.vue +32 -64
  56. package/components/tiles/FSUserOrganisationTileUI.vue +2 -0
  57. package/components/toggleSets/FSToggleSetPosition.vue +5 -0
  58. package/composables/useMapLayers.ts +12 -0
  59. package/models/index.ts +2 -1
  60. package/models/map.ts +2 -1
  61. package/models/tables.ts +1 -0
  62. package/models/variants.ts +33 -0
  63. package/package.json +4 -4
  64. package/styles/components/fs_button.scss +1 -7
  65. package/styles/components/fs_card.scss +75 -4
  66. package/styles/components/fs_chip.scss +0 -29
  67. package/styles/components/fs_filter_button.scss +6 -1
  68. package/styles/components/fs_map.scss +7 -1
  69. package/styles/components/fs_progress_bar.scss +62 -6
  70. package/styles/components/fs_snackbar.scss +7 -0
  71. package/styles/components/index.scss +1 -2
  72. package/styles/globals/overrides.scss +1 -1
  73. package/styles/components/fs_clickable.scss +0 -69
  74. package/styles/components/fs_color_icon.scss +0 -3
@@ -135,36 +135,25 @@
135
135
  />
136
136
  </FSRow>
137
137
  </FSRow>
138
- <FSClickable
138
+ <template
139
139
  v-else
140
- borderStyle="dashed"
141
- variant="background"
142
- :height="$props.height"
143
- :width="$props.width"
144
- @click="() => invisibleButtonRef.input.click()"
145
140
  >
146
- <FSRow
147
- align="center-center"
148
- :wrap="false"
149
- >
150
- <FSIcon>
151
- mdi-plus-box-outline
152
- </FSIcon>
153
- <FSText
154
- font="text-body"
155
- :lineClamp="2"
156
- >
157
- {{ $tr('edit-image.add-image', 'Add an image.') }}
158
- </FSText>
159
- <FSButtonFileMini
160
- class="fs-edit-image-hidden-button"
161
- ref="invisibleButtonRef"
162
- accept=".jpg,.jpeg,.png"
163
- :readFile="false"
164
- @update:metadata="onUpload"
165
- />
166
- </FSRow>
167
- </FSClickable>
141
+ <FSButtonFileMini
142
+ class="fs-edit-image-hidden-button"
143
+ ref="invisibleButtonRef"
144
+ accept=".jpg,.jpeg,.png"
145
+ :readFile="false"
146
+ @update:metadata="onUpload"
147
+ />
148
+ <FSCardPlaceholder
149
+ v-if="invisibleButtonRef"
150
+ :height="$props.height"
151
+ :width="$props.width"
152
+ icon="mdi-plus-box-outline"
153
+ :label="$tr('edit-image.add-image', 'Add an image.')"
154
+ @click="() => invisibleButtonRef!.input.click()"
155
+ />
156
+ </template>
168
157
  </FSCol>
169
158
  </template>
170
159
 
@@ -177,10 +166,11 @@ import { useFiles } from "@dative-gpi/foundation-shared-services/composables";
177
166
 
178
167
  import FSButtonRemoveMini from "./buttons/FSButtonRemoveMini.vue";
179
168
  import FSButtonFileMini from "./buttons/FSButtonFileMini.vue";
180
- import FSClickable from "./FSClickable.vue";
169
+ import FSCardPlaceholder from "./FSCardPlaceholder.vue";
181
170
  import FSImageUI from "./FSImageUI.vue";
182
171
  import FSCard from "./FSCard.vue";
183
172
  import FSText from "./FSText.vue";
173
+ import FSSpan from "./FSSpan.vue";
184
174
  import FSCol from "./FSCol.vue";
185
175
  import FSRow from "./FSRow.vue";
186
176
 
@@ -188,11 +178,12 @@ export default defineComponent({
188
178
  name: "FSEditImageUI",
189
179
  components: {
190
180
  FSButtonRemoveMini,
181
+ FSCardPlaceholder,
191
182
  FSButtonFileMini,
192
- FSClickable,
193
183
  FSImageUI,
194
184
  FSCard,
195
185
  FSText,
186
+ FSSpan,
196
187
  FSCol,
197
188
  FSRow
198
189
  },
@@ -40,6 +40,7 @@ import { useBreakpoints } from "@dative-gpi/foundation-shared-components/composa
40
40
  import type { FSGridMosaic } from "@dative-gpi/foundation-shared-components/models";
41
41
 
42
42
  import FSGrid from "./FSGrid.vue";
43
+ import FSText from "./FSText.vue";
43
44
  import FSCol from "./FSCol.vue";
44
45
  import FSRow from "./FSRow.vue";
45
46
 
@@ -47,6 +48,7 @@ export default defineComponent({
47
48
  name: "FSGridMosaic",
48
49
  components: {
49
50
  FSGrid,
51
+ FSText,
50
52
  FSCol,
51
53
  FSRow
52
54
  },
@@ -0,0 +1,115 @@
1
+ <template>
2
+ <FSChip
3
+ :height="$props.height"
4
+ :width="$props.width"
5
+ :variant="$props.variant"
6
+ :color="chipColor"
7
+ :disableHoverStyle="$props.disableHoverStyle"
8
+ >
9
+ <FSRow
10
+ align="center-center"
11
+ width="hug"
12
+ :wrap="false"
13
+ >
14
+ <FSRow
15
+ align="center-center"
16
+ width="hug"
17
+ gap="6px"
18
+ :wrap="false"
19
+ >
20
+ <FSIcon
21
+ :color="$props.iconColor"
22
+ :size="$props.iconSize"
23
+ >
24
+ {{ $props.icon }}
25
+ </FSIcon>
26
+ <FSText
27
+ font="text-overline"
28
+ :color="textColor"
29
+ >
30
+ {{ $props.label }}
31
+ </FSText>
32
+ </FSRow>
33
+ </FSRow>
34
+ </FSChip>
35
+ </template>
36
+
37
+ <script lang="ts">
38
+ import { defineComponent, type PropType } from "vue";
39
+
40
+ import { type CardVariant, CardVariants, type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
41
+
42
+ import FSIcon from "./FSIcon.vue";
43
+ import FSText from "./FSText.vue";
44
+ import FSChip from "./FSChip.vue";
45
+ import FSRow from "./FSRow.vue";
46
+
47
+ import { useColors } from "../composables";
48
+
49
+ export default defineComponent({
50
+ name: "FSSubgroupingChip",
51
+ components: {
52
+ FSChip,
53
+ FSIcon,
54
+ FSText,
55
+ FSRow
56
+ },
57
+ props: {
58
+ label: {
59
+ type: String as PropType<string>,
60
+ required: true
61
+ },
62
+ icon: {
63
+ type: String as PropType<string>,
64
+ required: true
65
+ },
66
+ iconColor: {
67
+ type: String as PropType<ColorBase>,
68
+ required: false,
69
+ default: ColorEnum.Dark
70
+ },
71
+ height: {
72
+ type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
73
+ required: false,
74
+ default: () => [24, 20]
75
+ },
76
+ width: {
77
+ type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
78
+ required: false,
79
+ default: "hug"
80
+ },
81
+ color: {
82
+ type: String as PropType<ColorBase>,
83
+ required: false,
84
+ default: ColorEnum.Light
85
+ },
86
+ variant: {
87
+ type: String as PropType<CardVariant>,
88
+ required: false,
89
+ default: CardVariants.Background
90
+ },
91
+ iconSize: {
92
+ type: [Array, String, Number] as PropType<"s" | "m" | "l" | string[] | number[] | string | number | null>,
93
+ required: false,
94
+ default: "18px"
95
+ },
96
+ disableHoverStyle: {
97
+ type: Boolean,
98
+ required: false,
99
+ default: true
100
+ }
101
+ },
102
+ setup(props) {
103
+ const { getColors } = useColors();
104
+
105
+ const chipColor = getColors(props.color).dark;
106
+ const textColor = getColors(ColorEnum.Dark).dark;
107
+
108
+ return {
109
+ chipColor,
110
+ textColor,
111
+ ColorEnum
112
+ };
113
+ }
114
+ });
115
+ </script>
@@ -30,12 +30,14 @@ import { sizeToVar } from "../utils";
30
30
 
31
31
  import FSCard from "./FSCard.vue";
32
32
  import FSIcon from "./FSIcon.vue";
33
+ import FSRow from "./FSRow.vue";
33
34
 
34
35
  export default defineComponent({
35
36
  name: "FSIconCard",
36
37
  components: {
37
38
  FSCard,
38
- FSIcon
39
+ FSIcon,
40
+ FSRow
39
41
  },
40
42
  props: {
41
43
  size: {
@@ -28,10 +28,18 @@ export default defineComponent({
28
28
  type: Boolean,
29
29
  required: false,
30
30
  default: true
31
+ },
32
+ variant: {
33
+ type: String as () => "fill" | "outline",
34
+ required: false,
35
+ default: "outline"
31
36
  }
32
37
  },
33
38
  setup(props) {
34
39
  const icon = computed((): string => {
40
+ if (props.variant === "fill") {
41
+ return props.value ? "mdi-check-circle" : "mdi-close-circle";
42
+ }
35
43
  return props.value ? "mdi-check-circle-outline" : "mdi-close-circle-outline";
36
44
  });
37
45
 
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <FSClickable
2
+ <FSCard
3
3
  class="fs-image-card"
4
4
  :height="height"
5
5
  :width="width"
@@ -22,20 +22,20 @@
22
22
  </FSSpan>
23
23
  </FSRow>
24
24
  </FSRow>
25
- </FSClickable>
25
+ </FSCard>
26
26
  </template>
27
27
 
28
28
  <script lang="ts">
29
29
  import { computed, defineComponent, type PropType, type StyleValue } from "vue";
30
30
 
31
- import FSClickable from "./FSClickable.vue";
31
+ import FSCard from "./FSCard.vue";
32
32
  import FSSpan from "./FSSpan.vue";
33
33
  import FSRow from "./FSRow.vue";
34
34
 
35
35
  export default defineComponent({
36
36
  name: "FSImageCard",
37
37
  components: {
38
- FSClickable,
38
+ FSCard,
39
39
  FSSpan,
40
40
  FSRow
41
41
  },
@@ -89,6 +89,7 @@ import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
89
89
  import { computeTicks, TimePrecision } from '@dative-gpi/foundation-shared-components/utils';
90
90
 
91
91
  import FSCol from '@dative-gpi/foundation-shared-components/components/FSCol.vue';
92
+ import FSRow from '@dative-gpi/foundation-shared-components/components/FSRow.vue';
92
93
  import FSSpan from '@dative-gpi/foundation-shared-components/components/FSSpan.vue';
93
94
  import FSText from '@dative-gpi/foundation-shared-components/components/FSText.vue';
94
95
  import FSSlider from '@dative-gpi/foundation-shared-components/components/FSSlider.vue';
@@ -100,6 +101,7 @@ export default defineComponent({
100
101
  name: "FSInstantPicker",
101
102
  components: {
102
103
  FSCol,
104
+ FSRow,
103
105
  FSSpan,
104
106
  FSText,
105
107
  FSSlider,
@@ -1,19 +1,7 @@
1
1
  <template>
2
- <a
3
- v-if="$props.href"
4
- :href="$props.href"
5
- :class="classes"
6
- :style="style"
7
- >
8
- <slot>
9
- <FSSpan>
10
- {{ $props.label }}
11
- </FSSpan>
12
- </slot>
13
- </a>
14
2
  <FSRouterLink
15
- v-else-if="$props.to"
16
3
  :to="$props.to"
4
+ :href="$props.href"
17
5
  :class="classes"
18
6
  :style="style"
19
7
  v-bind="$attrs"
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <FSClickable
2
+ <FSCard
3
3
  :disabled="$props.disabled"
4
4
  :height="['32px', '28px']"
5
5
  :padding="$props.padding"
@@ -47,7 +47,7 @@
47
47
  </FSIcon>
48
48
  </slot>
49
49
  </FSRow>
50
- </FSClickable>
50
+ </FSCard>
51
51
  </template>
52
52
 
53
53
  <script lang="ts">
@@ -56,7 +56,7 @@ import { computed, defineComponent, type PropType } from "vue";
56
56
  import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
57
57
  import { useColors } from "@dative-gpi/foundation-shared-components/composables";
58
58
 
59
- import FSClickable from "./FSClickable.vue";
59
+ import FSCard from "./FSCard.vue";
60
60
  import FSSpan from "./FSSpan.vue";
61
61
  import FSIcon from "./FSIcon.vue";
62
62
  import FSRow from "./FSRow.vue";
@@ -64,7 +64,7 @@ import FSRow from "./FSRow.vue";
64
64
  export default defineComponent({
65
65
  name: "FSOptionItem",
66
66
  components: {
67
- FSClickable,
67
+ FSCard,
68
68
  FSSpan,
69
69
  FSIcon,
70
70
  FSRow
@@ -41,12 +41,13 @@
41
41
  :scrollOutside="false"
42
42
  maxHeight="80dvh"
43
43
  >
44
- <FSClickable
44
+ <FSCard
45
45
  v-for="(item, index) in $props.items"
46
46
  width="100%"
47
47
  padding="8px"
48
48
  height="40px"
49
49
  :key="index"
50
+ :color="ColorEnum.Light"
50
51
  :border="false"
51
52
  @click="onClickItem(item)"
52
53
  >
@@ -68,7 +69,7 @@
68
69
  </FSText>
69
70
  </FSRow>
70
71
  </slot>
71
- </FSClickable>
72
+ </FSCard>
72
73
  </FSFadeOut>
73
74
  </FSCol>
74
75
  </slot>
@@ -81,7 +82,7 @@ import { defineComponent, ref, type PropType } from "vue";
81
82
 
82
83
  import { useColors } from "@dative-gpi/foundation-shared-components/composables";
83
84
 
84
- import { ColorEnum, type ColorBase } from '@dative-gpi/foundation-shared-components/models';
85
+ import { CardVariants, ColorEnum, type ColorBase } from '@dative-gpi/foundation-shared-components/models';
85
86
 
86
87
  import FSRow from '@dative-gpi/foundation-shared-components/components/FSRow.vue';
87
88
  import FSCol from '@dative-gpi/foundation-shared-components/components/FSCol.vue';
@@ -90,7 +91,6 @@ import FSMenu from '@dative-gpi/foundation-shared-components/components/FSMenu.v
90
91
  import FSCard from '@dative-gpi/foundation-shared-components/components/FSCard.vue';
91
92
  import FSText from '@dative-gpi/foundation-shared-components/components/FSText.vue';
92
93
  import FSButton from '@dative-gpi/foundation-shared-components/components/FSButton.vue';
93
- import FSClickable from '@dative-gpi/foundation-shared-components/components/FSClickable.vue';
94
94
 
95
95
  export default defineComponent({
96
96
  name: "FSInformationsMenu",
@@ -101,8 +101,7 @@ export default defineComponent({
101
101
  FSText,
102
102
  FSButton,
103
103
  FSCol,
104
- FSIcon,
105
- FSClickable
104
+ FSIcon
106
105
  },
107
106
  props: {
108
107
  items: {
@@ -158,6 +157,7 @@ export default defineComponent({
158
157
  ColorEnum,
159
158
  modelValue,
160
159
  lightColors,
160
+ CardVariants,
161
161
  onClickItem
162
162
  };
163
163
  }
@@ -3,7 +3,7 @@
3
3
  width="hug"
4
4
  gap="4px"
5
5
  >
6
- <FSClickable
6
+ <FSCard
7
7
  variant="full"
8
8
  :color="ColorEnum.Light"
9
9
  borderRadius="50%"
@@ -14,8 +14,8 @@
14
14
  size="18px"
15
15
  icon="mdi-skip-backward"
16
16
  />
17
- </FSClickable>
18
- <FSClickable
17
+ </FSCard>
18
+ <FSCard
19
19
  variant="full"
20
20
  :color="ColorEnum.Light"
21
21
  borderRadius="50%"
@@ -26,8 +26,8 @@
26
26
  size="18px"
27
27
  :icon="$props.modelValue ? 'mdi-pause' : 'mdi-play'"
28
28
  />
29
- </FSClickable>
30
- <FSClickable
29
+ </FSCard>
30
+ <FSCard
31
31
  variant="full"
32
32
  :color="ColorEnum.Light"
33
33
  borderRadius="50%"
@@ -38,7 +38,7 @@
38
38
  size="18px"
39
39
  icon="mdi-skip-forward"
40
40
  />
41
- </FSClickable>
41
+ </FSCard>
42
42
  </FSRow>
43
43
  </template>
44
44
 
@@ -48,13 +48,15 @@ import { defineComponent } from "vue";
48
48
  import { ColorEnum } from '@dative-gpi/foundation-shared-components/models';
49
49
 
50
50
  import FSIcon from '@dative-gpi/foundation-shared-components/components/FSIcon.vue';
51
- import FSClickable from '@dative-gpi/foundation-shared-components/components/FSClickable.vue';
51
+ import FSCard from '@dative-gpi/foundation-shared-components/components/FSCard.vue';
52
+ import FSRow from '@dative-gpi/foundation-shared-components/components/FSRow.vue';
52
53
 
53
54
  export default defineComponent({
54
55
  name: "FSPlayButtons",
55
56
  components: {
56
- FSClickable,
57
- FSIcon
57
+ FSCard,
58
+ FSIcon,
59
+ FSRow
58
60
  },
59
61
  props: {
60
62
  modelValue: {
@@ -4,21 +4,62 @@
4
4
  :style="style"
5
5
  >
6
6
  <div
7
- class="fs-progress-bar-gradient"
7
+ class="fs-progress-bar-wrapper"
8
8
  >
9
- <div></div>
9
+ <div
10
+ class="fs-progress-bar-track"
11
+ >
12
+ <div
13
+ v-if="$props.cursor && isValueInRange"
14
+ class="fs-progress-bar-cursor"
15
+ >
16
+ <FSText
17
+ v-if="$props.showValue"
18
+ class="fs-progress-bar-cursor-label"
19
+ font="text-overline"
20
+ :ellipsis="false"
21
+ >
22
+ {{ displayValue }}
23
+ </FSText>
24
+ </div>
25
+ <div
26
+ v-if="!$props.cursor"
27
+ class="fs-progress-bar-fill"
28
+ ></div>
29
+ </div>
30
+ <div
31
+ v-if="positionedLabels.length"
32
+ class="fs-progress-bar-labels"
33
+ >
34
+ <div
35
+ v-for="label in positionedLabels"
36
+ :key="label.value"
37
+ class="fs-progress-bar-label"
38
+ :class="{
39
+ 'fs-progress-bar-label--start': label.percent === 0,
40
+ 'fs-progress-bar-label--end': label.percent === 100
41
+ }"
42
+ :style="{ left: `${label.percent}%` }"
43
+ >
44
+ <FSText
45
+ font="text-overline"
46
+ >
47
+ {{ label.display }}
48
+ </FSText>
49
+ </div>
50
+ </div>
10
51
  </div>
11
52
  <FSText
12
- v-if="$props.showValue"
53
+ v-if="$props.showValue && !$props.cursor"
13
54
  font="text-button"
14
55
  >
15
- {{ fixedRate }}%
56
+ {{ displayValue }}
16
57
  </FSText>
17
58
  </FSRow>
18
59
  </template>
19
60
 
20
61
  <script lang="ts">
21
- import { computed, defineComponent, type StyleValue } from "vue";
62
+ import { computed, defineComponent, type PropType, type StyleValue } from "vue";
22
63
 
23
64
  import { useColors } from '@dative-gpi/foundation-shared-components/composables';
24
65
 
@@ -50,6 +91,31 @@ export default defineComponent({
50
91
  type: Boolean,
51
92
  required: false,
52
93
  default: true
94
+ },
95
+ valueFormat: {
96
+ type: String as PropType<"percentage" | "raw">,
97
+ required: false,
98
+ default: "percentage"
99
+ },
100
+ min: {
101
+ type: Number,
102
+ required: false,
103
+ default: 0
104
+ },
105
+ max: {
106
+ type: Number,
107
+ required: false,
108
+ default: 1
109
+ },
110
+ labels: {
111
+ type: Array as PropType<Array<{ value: number; text?: string }>>,
112
+ required: false,
113
+ default: () => []
114
+ },
115
+ cursor: {
116
+ type: Boolean,
117
+ required: false,
118
+ default: false
53
119
  }
54
120
  },
55
121
  setup(props) {
@@ -58,37 +124,85 @@ export default defineComponent({
58
124
  const lightColors = getColors(ColorEnum.Light);
59
125
  const successColors = getColors(ColorEnum.Success);
60
126
  const errorColors = getColors(ColorEnum.Error);
61
-
62
- const fixedRate = computed(() => {
63
- return (props.modelValue * 100).toFixed(0);
127
+
128
+ const isValid = computed(() => props.max > props.min);
129
+
130
+ const range = computed(() => props.max - props.min);
131
+
132
+ const clampedValue = computed(() => {
133
+ if (!isValid.value) {
134
+ return props.min;
135
+ }
136
+ return Math.min(Math.max(props.modelValue, props.min), props.max);
137
+ });
138
+
139
+ const valuePercent = computed(() => {
140
+ if (!isValid.value) {
141
+ return 0;
142
+ }
143
+ return ((clampedValue.value - props.min) / range.value) * 100;
144
+ });
145
+
146
+ const isValueInRange = computed(() => {
147
+ return props.modelValue >= props.min && props.modelValue <= props.max;
148
+ });
149
+
150
+ const zeroPercent = computed(() => {
151
+ if (!isValid.value) { return 0; }
152
+ const zero = Math.min(Math.max(0, props.min), props.max);
153
+ return ((zero - props.min) / range.value) * 100;
64
154
  });
65
155
 
66
- const relativeWidth = computed(() => {
67
- return props.modelValue ? 100 / props.modelValue : 0;
156
+ const fillLeft = computed(() => Math.min(zeroPercent.value, valuePercent.value));
157
+
158
+ const fillWidth = computed(() => Math.abs(valuePercent.value - zeroPercent.value));
159
+
160
+ const gradientStartStop = computed(() => {
161
+ if (fillWidth.value === 0) { return "0%"; }
162
+ return `${-(fillLeft.value / fillWidth.value) * 100}%`;
68
163
  });
69
-
70
- const startColor = computed(() => {
71
- return props.startColor ?? errorColors.base;
164
+
165
+ const gradientEndStop = computed(() => {
166
+ if (fillWidth.value === 0) { return "100%"; }
167
+ return `${((100 - fillLeft.value) / fillWidth.value) * 100}%`;
72
168
  });
73
169
 
74
- const endColor = computed(() => {
75
- return props.endColor ?? successColors.base;
170
+ const positionedLabels = computed(() => {
171
+ return props.labels.map(label => {
172
+ const percent = isValid.value
173
+ ? ((label.value - props.min) / range.value) * 100
174
+ : 0;
175
+
176
+ return {
177
+ value: label.value,
178
+ display: label.text ?? label.value,
179
+ percent: Math.min(Math.max(percent, 0), 100)
180
+ };
181
+ });
76
182
  });
77
183
 
78
- const style = computed((): StyleValue => {
79
- return {
80
- '--progress-bar-background-color': lightColors.dark,
81
- '--progress-bar-gradient-start-color': startColor.value,
82
- '--progress-bar-gradient-end-color': endColor.value,
83
- '--progress-bar-gradient-width': `min(100%, ${fixedRate.value}%)`,
84
- '--progress-bar-total-relative-width': `${relativeWidth.value}%`
85
- };
184
+ const displayValue = computed(() => {
185
+ if (props.valueFormat === "raw") { return props.modelValue.toFixed(2); }
186
+ return `${Math.round(valuePercent.value)}%`;
86
187
  });
87
188
 
189
+ const style = computed((): StyleValue => ({
190
+ "--progress-bar-background": lightColors.dark,
191
+ "--progress-bar-gradient-start": props.startColor ?? errorColors.base,
192
+ "--progress-bar-gradient-start-stop": gradientStartStop.value,
193
+ "--progress-bar-gradient-end": props.endColor ?? successColors.base,
194
+ "--progress-bar-gradient-end-stop": gradientEndStop.value,
195
+ "--progress-bar-fill-left": `${fillLeft.value}%`,
196
+ "--progress-bar-fill-width": `${fillWidth.value}%`,
197
+ "--progress-bar-cursor-position": `${valuePercent.value}%`
198
+ }));
199
+
88
200
  return {
89
- style,
90
- fixedRate
91
- }
92
- },
201
+ positionedLabels,
202
+ isValueInRange,
203
+ displayValue,
204
+ style
205
+ };
206
+ }
93
207
  });
94
- </script>
208
+ </script>