@dative-gpi/foundation-shared-components 0.0.229 → 0.1.68

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 (228) hide show
  1. package/components/FSAccordionPanel.vue +8 -10
  2. package/components/FSBadge.vue +2 -4
  3. package/components/FSBreadcrumbs.vue +9 -10
  4. package/components/FSButton.vue +81 -31
  5. package/components/FSCalendar.vue +35 -33
  6. package/components/FSCalendarTwin.vue +77 -84
  7. package/components/FSCard.vue +29 -16
  8. package/components/FSCardPlaceholder.vue +1 -2
  9. package/components/FSCheckbox.vue +5 -7
  10. package/components/FSChip.vue +9 -11
  11. package/components/FSClickable.vue +67 -57
  12. package/components/FSClock.vue +4 -4
  13. package/components/FSCol.vue +2 -3
  14. package/components/FSColor.vue +13 -31
  15. package/components/FSColorIcon.vue +25 -9
  16. package/components/FSDialog.vue +1 -2
  17. package/components/FSDialogFormBody.vue +4 -4
  18. package/components/FSDialogMenu.vue +2 -4
  19. package/components/FSDialogMultiFormBody.vue +63 -50
  20. package/components/FSDialogRemove.vue +1 -0
  21. package/components/FSDialogSubmit.vue +5 -7
  22. package/components/FSDivider.vue +7 -9
  23. package/components/FSEditImage.vue +27 -274
  24. package/components/FSEditImageUI.vue +303 -0
  25. package/components/FSErrorToast.vue +3 -4
  26. package/components/FSFadeOut.vue +18 -13
  27. package/components/FSGrid.vue +6 -9
  28. package/components/FSGridMosaic.vue +1 -2
  29. package/components/FSIcon.vue +7 -8
  30. package/components/FSIconCard.vue +23 -30
  31. package/components/FSIconCheck.vue +1 -2
  32. package/components/FSImage.vue +21 -193
  33. package/components/FSImageCard.vue +2 -2
  34. package/components/FSImageUI.vue +212 -0
  35. package/components/FSLabel.vue +18 -20
  36. package/components/FSLink.vue +19 -21
  37. package/components/FSLoader.vue +10 -14
  38. package/components/FSOptionGroup.vue +58 -12
  39. package/components/FSPagination.vue +3 -5
  40. package/components/FSRadio.vue +5 -7
  41. package/components/FSRadioGroup.vue +2 -4
  42. package/components/FSRow.vue +3 -4
  43. package/components/FSSlideGroup.vue +15 -4
  44. package/components/FSSlider.vue +9 -11
  45. package/components/FSSpan.vue +11 -9
  46. package/components/FSSwitch.vue +65 -37
  47. package/components/FSTab.vue +2 -4
  48. package/components/FSTabs.vue +36 -16
  49. package/components/FSTag.vue +23 -14
  50. package/components/FSTagGroup.vue +3 -5
  51. package/components/FSText.vue +8 -12
  52. package/components/FSWindow.vue +11 -5
  53. package/components/FSWrapGroup.vue +15 -4
  54. package/components/agenda/FSAgenda.vue +204 -0
  55. package/components/agenda/FSAgendaDialogCalendar.vue +76 -0
  56. package/components/agenda/FSAgendaHeader.vue +190 -0
  57. package/components/agenda/FSAgendaHorizontalEvent.vue +162 -0
  58. package/components/agenda/FSAgendaHorizontalTimeLineMarker.vue +46 -0
  59. package/components/agenda/FSAgendaHoursCol.vue +103 -0
  60. package/components/agenda/FSAgendaHoursRow.vue +124 -0
  61. package/components/agenda/FSAgendaVerticalEvent.vue +160 -0
  62. package/components/agenda/FSAgendaVerticalTimeLineMarker.vue +46 -0
  63. package/components/agenda/FSDayAgenda.vue +200 -0
  64. package/components/agenda/FSMonthAgenda.vue +257 -0
  65. package/components/agenda/FSSelectAgendaMode.vue +54 -0
  66. package/components/agenda/FSWeekAgenda.vue +328 -0
  67. package/components/autocompletes/FSAutocompleteLanguage.vue +18 -39
  68. package/components/autocompletes/FSAutocompleteTimeZone.vue +20 -38
  69. package/components/buttons/FSButtonCancelMini.vue +1 -0
  70. package/components/buttons/FSButtonCopy.vue +28 -0
  71. package/components/buttons/FSButtonCopyIcon.vue +28 -0
  72. package/components/buttons/FSButtonCopyLabel.vue +27 -0
  73. package/components/buttons/FSButtonCopyMini.vue +28 -0
  74. package/components/buttons/FSButtonDragIcon.vue +27 -0
  75. package/components/buttons/FSButtonDuplicateMini.vue +1 -0
  76. package/components/buttons/FSButtonEditMini.vue +1 -0
  77. package/components/buttons/FSButtonFileMini.vue +1 -0
  78. package/components/buttons/FSButtonNextMini.vue +1 -0
  79. package/components/buttons/FSButtonPreviousMini.vue +1 -0
  80. package/components/buttons/FSButtonRedoMini.vue +1 -0
  81. package/components/buttons/FSButtonRemoveMini.vue +1 -0
  82. package/components/buttons/FSButtonSaveMini.vue +1 -0
  83. package/components/buttons/FSButtonSearchMini.vue +1 -0
  84. package/components/buttons/FSButtonUndoMini.vue +1 -0
  85. package/components/buttons/FSButtonUpdateMini.vue +1 -0
  86. package/components/buttons/FSButtonValidateMini.vue +1 -0
  87. package/components/deviceOrganisations/FSConnectivity.vue +11 -1
  88. package/components/deviceOrganisations/FSConnectivityCard.vue +20 -49
  89. package/components/deviceOrganisations/FSStatus.vue +11 -1
  90. package/components/deviceOrganisations/FSStatusCard.vue +40 -60
  91. package/components/deviceOrganisations/FSStatusesCarousel.vue +1 -0
  92. package/components/deviceOrganisations/FSStatusesRow.vue +10 -5
  93. package/components/deviceOrganisations/FSWorstAlert.vue +19 -13
  94. package/components/deviceOrganisations/FSWorstAlertCard.vue +36 -47
  95. package/components/fields/FSAutocompleteField.vue +501 -323
  96. package/components/fields/FSAutocompleteTag.vue +100 -0
  97. package/components/fields/FSBaseField.vue +26 -16
  98. package/components/fields/FSColorField.vue +63 -55
  99. package/components/fields/FSCommentField.vue +93 -0
  100. package/components/fields/FSDateField.vue +2 -2
  101. package/components/fields/FSDateRangeField.vue +2 -2
  102. package/components/fields/FSDateTimeField.vue +4 -3
  103. package/components/fields/FSDateTimeRangeField.vue +7 -6
  104. package/components/fields/FSEntityFieldUI.vue +271 -0
  105. package/components/fields/FSGradientField.vue +27 -33
  106. package/components/fields/FSIconField.vue +2 -3
  107. package/components/fields/FSMagicConfigField.vue +28 -19
  108. package/components/fields/FSMagicField.vue +25 -17
  109. package/components/fields/FSNumberField.vue +9 -7
  110. package/components/fields/FSPasswordField.vue +2 -3
  111. package/components/fields/FSRichTextField.vue +32 -5
  112. package/components/fields/FSSearchField.vue +2 -2
  113. package/components/fields/FSSelectField.vue +483 -251
  114. package/components/fields/FSTagField.vue +4 -6
  115. package/components/fields/FSTermField.vue +25 -13
  116. package/components/fields/FSTextArea.vue +18 -6
  117. package/components/fields/FSTextField.vue +13 -10
  118. package/components/fields/FSTimeField.vue +1 -1
  119. package/components/fields/FSTimeSlotField.vue +3 -4
  120. package/components/fields/FSTimeStepField.vue +157 -0
  121. package/components/fields/FSTranslateField.vue +3 -2
  122. package/components/fields/FSTranslateRichTextField.vue +4 -3
  123. package/components/fields/FSTranslateTextArea.vue +233 -0
  124. package/components/fields/FSTreeViewField.vue +7 -9
  125. package/components/fields/periodicField/FSPeriodicDailyField.vue +120 -0
  126. package/components/fields/periodicField/FSPeriodicField.vue +131 -0
  127. package/components/fields/periodicField/FSPeriodicMonthlyField.vue +222 -0
  128. package/components/fields/periodicField/FSPeriodicWeeklyField.vue +120 -0
  129. package/components/fields/periodicField/FSPeriodicYearlyField.vue +144 -0
  130. package/components/lists/FSDataIteratorItem.vue +8 -10
  131. package/components/lists/FSDataTableUI.vue +47 -39
  132. package/components/lists/FSFilterButton.vue +20 -22
  133. package/components/lists/FSHiddenButton.vue +10 -12
  134. package/components/lists/FSLoadDataTable.vue +4 -6
  135. package/components/lists/FSSimpleList.vue +229 -0
  136. package/components/map/FSMap.vue +256 -405
  137. package/components/map/FSMapFeatureGroup.vue +51 -0
  138. package/components/map/FSMapLayerButton.vue +6 -3
  139. package/components/map/FSMapMarker.vue +116 -0
  140. package/components/map/FSMapMarkerClusterGroup.vue +72 -0
  141. package/components/map/FSMapOverlay.vue +69 -83
  142. package/components/map/FSMapPolygon.vue +81 -0
  143. package/components/map/FSMapTileLayer.vue +50 -0
  144. package/components/map/keys.ts +4 -0
  145. package/components/selects/FSSelectAutoRefresh.vue +1 -1
  146. package/components/selects/FSSelectDashboardVariableType.vue +1 -1
  147. package/components/selects/FSSelectDateSetting.vue +3 -3
  148. package/components/selects/FSSelectDays.vue +1 -1
  149. package/components/selects/FSSelectListMode.vue +51 -0
  150. package/components/selects/FSSelectMonths.vue +67 -0
  151. package/components/tiles/FSChartTileUI.vue +116 -0
  152. package/components/tiles/FSCommentTileUI.vue +149 -0
  153. package/components/tiles/FSDashboardOrganisationTileUI.vue +6 -8
  154. package/components/tiles/FSDashboardOrganisationTypeTileUI.vue +6 -8
  155. package/components/tiles/FSDashboardShallowTileUI.vue +6 -8
  156. package/components/tiles/FSDeviceOrganisationTileUI.vue +30 -18
  157. package/components/tiles/FSFolderTileUI.vue +6 -6
  158. package/components/tiles/FSGroupTileUI.vue +31 -22
  159. package/components/tiles/FSLoadTile.vue +5 -7
  160. package/components/tiles/FSLocationTileUI.vue +157 -0
  161. package/components/tiles/FSModelTileUI.vue +18 -0
  162. package/components/tiles/FSServiceAccountOrganisationTileUI.vue +142 -0
  163. package/components/tiles/FSSimpleTileUI.vue +57 -36
  164. package/components/tiles/FSTile.vue +115 -55
  165. package/components/tiles/FSUserOrganisationTileUI.vue +25 -35
  166. package/components/toggleSets/FSToggleSetPosition.vue +1 -1
  167. package/components/views/FSEntityHeader.vue +343 -0
  168. package/components/views/FSEntityView.vue +163 -0
  169. package/components/views/FSListHeader.vue +83 -0
  170. package/components/views/FSListView.vue +83 -0
  171. package/components/views/FSSkeletonView.vue +100 -0
  172. package/composables/useAddress.ts +2 -2
  173. package/composables/useColors.ts +15 -5
  174. package/composables/useMagicFieldProvider.ts +7 -6
  175. package/composables/useSlots.ts +51 -28
  176. package/models/agenda.ts +9 -0
  177. package/models/deviceAlerts.ts +1 -1
  178. package/models/deviceConnectivities.ts +1 -1
  179. package/models/index.ts +1 -0
  180. package/models/magicFields.ts +1 -0
  181. package/models/map.ts +2 -2
  182. package/models/rules.ts +10 -5
  183. package/models/tables.ts +3 -1
  184. package/package.json +4 -4
  185. package/styles/components/fs_agenda.scss +32 -0
  186. package/styles/components/fs_agenda_event.scss +41 -0
  187. package/styles/components/fs_agenda_hours_col.scss +4 -0
  188. package/styles/components/fs_agenda_hours_row.scss +13 -0
  189. package/styles/components/fs_agenda_time_line_marker.scss +19 -0
  190. package/styles/components/fs_card.scss +0 -1
  191. package/styles/components/fs_clickable.scss +5 -3
  192. package/styles/components/fs_color_field.scss +1 -0
  193. package/styles/components/fs_data_table.scss +2 -0
  194. package/styles/components/fs_dialog.scss +11 -15
  195. package/styles/components/fs_edit_image.scss +8 -0
  196. package/styles/components/fs_fade_out.scss +2 -1
  197. package/styles/components/fs_filter_button.scss +1 -6
  198. package/styles/components/fs_gradient_field.scss +11 -11
  199. package/styles/components/fs_magic_config_field.scss +2 -2
  200. package/styles/components/fs_map.scss +36 -30
  201. package/styles/components/fs_option_group.scss +15 -5
  202. package/styles/components/fs_radio.scss +11 -0
  203. package/styles/components/fs_rich_text_field.scss +2 -1
  204. package/styles/components/fs_search_field.scss +3 -0
  205. package/styles/components/fs_select_date_settings.scss +3 -0
  206. package/styles/components/fs_slide_group.scss +5 -0
  207. package/styles/components/fs_span.scss +2 -1
  208. package/styles/components/fs_switch.scss +1 -0
  209. package/styles/components/fs_tabs.scss +9 -0
  210. package/styles/components/fs_text_area.scss +15 -1
  211. package/styles/components/fs_tile.scss +22 -6
  212. package/styles/components/fs_window.scss +5 -0
  213. package/styles/components/fs_wrap_group.scss +4 -0
  214. package/styles/components/index.scss +6 -1
  215. package/styles/globals/overrides.scss +22 -19
  216. package/styles/globals/text_fonts.scss +17 -55
  217. package/tools/alertsTools.ts +54 -0
  218. package/tools/chartsTools.ts +300 -0
  219. package/tools/index.ts +2 -0
  220. package/utils/badge.ts +9 -0
  221. package/utils/filter.ts +18 -0
  222. package/utils/index.ts +2 -0
  223. package/utils/leafletMarkers.ts +8 -2
  224. package/utils/statuses.ts +1 -1
  225. package/utils/time.ts +27 -1
  226. package/components/autocompletes/FSAutocompleteTag.vue +0 -138
  227. package/components/map/FSMapEditPointAddressOverlay.vue +0 -164
  228. package/styles/components/fs_map_overlay.scss +0 -38
@@ -1,229 +1,57 @@
1
1
  <template>
2
- <v-img
3
- class="fs-image"
4
- ref="imageRef"
5
- :height="computedHeight"
6
- :width="computedWidth"
7
- :cover="$props.cover"
8
- :src="realSource"
9
- :style="style"
2
+ <FSImageUI
3
+ :blurHash="image"
4
+ :source="source"
10
5
  @error="onError"
11
6
  v-bind="$attrs"
12
- >
13
- <template
14
- #placeholder
15
- >
16
- <FSLoader
17
- v-if="$props.imageId"
18
- class="fs-image-load"
19
- height="100%"
20
- width="100%"
21
- :borderRadius="$props.borderRadius"
22
- />
23
- </template>
24
- <template
25
- #error
26
- >
27
- <FSLoader
28
- v-if="!blurHash"
29
- class="fs-image-load"
30
- height="100%"
31
- width="100%"
32
- :borderRadius="$props.borderRadius"
33
- />
34
- <canvas
35
- ref="canvasRef"
36
- />
37
- </template>
38
- </v-img>
7
+ />
39
8
  </template>
40
9
 
41
10
  <script lang="ts">
42
- import type { PropType} from "vue";
43
- import { computed, defineComponent, ref, watch } from "vue";
44
- import { decode, isBlurhashValid } from "blurhash";
11
+ import { computed, defineComponent, type PropType } from "vue";
45
12
 
46
- import { IMAGE_RAW_EXTENSION_URL, IMAGE_RAW_URL } from "@dative-gpi/foundation-shared-services/config/urls";
47
- import { useExtensionJwt, useImageBlurHash } from "@dative-gpi/foundation-shared-services/composables";
48
- import { sizeToVar, varToSize } from "@dative-gpi/foundation-shared-components/utils";
13
+ import { IMAGE_THUMBNAIL_URL, IMAGE_RAW_URL } from "@dative-gpi/foundation-shared-services/config/urls";
14
+ import { useAppAuthToken, useImage } from "@dative-gpi/foundation-shared-services/composables";
49
15
 
50
- import FSLoader from "./FSLoader.vue";
16
+ import FSImageUI from "./FSImageUI.vue";
51
17
 
52
18
  export default defineComponent({
53
19
  name: "FSImage",
54
20
  components: {
55
- FSLoader
21
+ FSImageUI
56
22
  },
57
23
  props: {
58
- height: {
59
- type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
60
- required: false,
61
- default: null
62
- },
63
- width: {
64
- type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
65
- required: false,
66
- default: null
67
- },
68
24
  imageId: {
69
25
  type: String as PropType<string | null>,
70
26
  required: false,
71
27
  default: null
72
28
  },
73
- imageB64: {
74
- type: String as PropType<string | null>,
75
- required: false,
76
- default: null
77
- },
78
- source: {
79
- type: String as PropType<string | null>,
29
+ thumbnail: {
30
+ type: Boolean as PropType<boolean>,
80
31
  required: false,
81
- default: null
82
- },
83
- aspectRatio: {
84
- type: String as PropType<string | null>,
85
- required: false,
86
- default: null
87
- },
88
- borderRadius: {
89
- type: [String, Number],
90
- required: false,
91
- default: "4px"
92
- },
93
- cover: {
94
- type: Boolean,
95
- required: false,
96
- default: true
32
+ default: false
97
33
  }
98
34
  },
99
35
  setup(props) {
100
- const { fetch: fetchBlurHash, entity: blurHash } = useImageBlurHash();
101
- const { jwt } = useExtensionJwt();
102
-
103
- const imageRef = ref<HTMLFormElement | null>(null);
104
- const canvasRef = ref<HTMLCanvasElement | null>(null);
105
-
106
- const signatures = ref<{ [key: string]: string }>({
107
- JVBERi0 : "application/pdf",
108
- R0lGODdh : "image/gif",
109
- R0lGODlh : "image/gif",
110
- iVBORw0KGgo: "image/png",
111
- "/9j/" : "image/jpg",
112
- });
36
+ const { get: getImage, entity: image } = useImage();
37
+ const { authToken } = useAppAuthToken();
113
38
 
114
- const style = computed((): { [key: string] : string | null | undefined } => {
115
- return {
116
- "--fs-image-border-radius" : sizeToVar(props.borderRadius),
117
- "--fs-image-blurhash-opacity": blurHash.value ? "1" : "0"
39
+ const source = computed(() => {
40
+ if (props.thumbnail) {
41
+ return props.imageId ? IMAGE_THUMBNAIL_URL(props.imageId, authToken.value) : null;
118
42
  }
119
- });
120
-
121
- const computedHeight = computed((): string | undefined => {
122
- if (props.height) {
123
- return sizeToVar(props.height);
124
- }
125
- if (props.width) {
126
- if (typeof (props.width) === "string") {
127
- return undefined;
128
- }
129
- if (props.aspectRatio) {
130
- const split = props.aspectRatio.split('/');
131
- if (split.length === 2 && !isNaN(parseFloat(split[0])) && !isNaN(parseFloat(split[1]))) {
132
- return sizeToVar(varToSize(props.width) * (parseFloat(split[1]) / parseFloat(split[0])));
133
- }
134
- }
135
- return sizeToVar(props.width);
136
- }
137
- return undefined;
138
- });
139
-
140
- const computedWidth = computed((): string | undefined => {
141
- if (props.width) {
142
- return sizeToVar(props.width);
143
- }
144
- if (props.height) {
145
- if (typeof (props.height) === "string") {
146
- return undefined;
147
- }
148
- if (props.aspectRatio) {
149
- const split = props.aspectRatio.split('/');
150
- if (split.length === 2 && !isNaN(parseFloat(split[0])) && !isNaN(parseFloat(split[1]))) {
151
- return sizeToVar(varToSize(props.height) * (parseFloat(split[0]) / parseFloat(split[1])));
152
- }
153
- }
154
- return sizeToVar(props.height);
155
- }
156
- return undefined;
157
- });
158
-
159
- const realSource = computed((): string | null => {
160
- if (props.imageB64) {
161
- if (imageType.value && imageData.value) {
162
- return `${imageType.value},${imageData.value}`;
163
- }
164
- }
165
- else if (props.imageId) {
166
- if (jwt.value) {
167
- return IMAGE_RAW_EXTENSION_URL(props.imageId, jwt.value);
168
- }
169
- return IMAGE_RAW_URL(props.imageId);
170
- }
171
- return props.source;
172
- });
173
-
174
- const imageData = computed((): string | null => {
175
- if (props.imageB64 && props.imageB64.includes(",")) {
176
- return props.imageB64.split(",")[1];
177
- }
178
- return props.imageB64;
179
- });
180
-
181
- const imageType = computed((): string | null => {
182
- if (props.imageB64 && props.imageB64.includes(",")) {
183
- return props.imageB64.split(",")[0];
184
- }
185
- if (props.imageB64) {
186
- for (const s in signatures.value) {
187
- if (props.imageB64.startsWith(s)) {
188
- return `data:${signatures.value[s]};base64`;
189
- }
190
- }
191
- }
192
- return null;
43
+ return props.imageId ? IMAGE_RAW_URL(props.imageId, authToken.value) : null;
193
44
  });
194
45
 
195
46
  const onError = (): void => {
196
47
  if (props.imageId) {
197
- fetchBlurHash(props.imageId);
48
+ getImage(props.imageId);
198
49
  }
199
50
  };
200
51
 
201
- watch(() => blurHash.value, () => {
202
- if (canvasRef.value && imageRef.value) {
203
- if (blurHash.value && isBlurhashValid(blurHash.value.blurHash).result) {
204
- const ctx = canvasRef.value.getContext("2d");
205
- if (ctx) {
206
- const width = (imageRef.value as any).$el.clientWidth;
207
- const height = (imageRef.value as any).$el.clientHeight;
208
- const pixels = decode(blurHash.value.blurHash, width, height);
209
- const imageData = ctx.createImageData(width, height);
210
- canvasRef.value.width = width;
211
- canvasRef.value.height = height;
212
- imageData.data.set(pixels);
213
- ctx.putImageData(imageData, 0, 0);
214
- }
215
- }
216
- }
217
- });
218
-
219
52
  return {
220
- computedHeight,
221
- computedWidth,
222
- realSource,
223
- canvasRef,
224
- imageRef,
225
- blurHash,
226
- style,
53
+ source,
54
+ image,
227
55
  onError
228
56
  };
229
57
  }
@@ -26,7 +26,7 @@
26
26
  </template>
27
27
 
28
28
  <script lang="ts">
29
- import { computed, defineComponent, type PropType } from "vue";
29
+ import { computed, defineComponent, type PropType, type StyleValue } from "vue";
30
30
 
31
31
  import FSClickable from "./FSClickable.vue";
32
32
  import FSSpan from "./FSSpan.vue";
@@ -60,7 +60,7 @@ export default defineComponent({
60
60
  }
61
61
  },
62
62
  setup(props) {
63
- const style = computed(() => ({
63
+ const style = computed((): StyleValue => ({
64
64
  "--fs-image-card-background": `url(${props.src})`
65
65
  }));
66
66
 
@@ -0,0 +1,212 @@
1
+ <template>
2
+ <v-img
3
+ class="fs-image"
4
+ ref="imageRef"
5
+ :height="computedHeight"
6
+ :width="computedWidth"
7
+ :cover="$props.cover"
8
+ :src="realSource"
9
+ :style="style"
10
+ @error="$emit('error')"
11
+ v-bind="$attrs"
12
+ >
13
+ <template
14
+ #placeholder
15
+ >
16
+ <FSLoader
17
+ v-if="$props.loading"
18
+ class="fs-image-load"
19
+ height="100%"
20
+ width="100%"
21
+ :borderRadius="$props.borderRadius"
22
+ />
23
+ </template>
24
+ <template
25
+ #error
26
+ >
27
+ <FSLoader
28
+ v-if="!$props.blurHash"
29
+ class="fs-image-load"
30
+ height="100%"
31
+ width="100%"
32
+ :borderRadius="$props.borderRadius"
33
+ />
34
+ <canvas
35
+ ref="canvasRef"
36
+ />
37
+ </template>
38
+ </v-img>
39
+ </template>
40
+
41
+ <script lang="ts">
42
+ import { computed, defineComponent, type PropType, ref, type StyleValue, watch } from "vue";
43
+ import { decode, isBlurhashValid } from "blurhash";
44
+
45
+ import { sizeToVar, varToSize } from "@dative-gpi/foundation-shared-components/utils";
46
+ import { type ImageDetails } from "@dative-gpi/foundation-shared-domain/models";
47
+
48
+ import FSLoader from "./FSLoader.vue";
49
+
50
+ export default defineComponent({
51
+ name: "FSImageUI",
52
+ components: {
53
+ FSLoader
54
+ },
55
+ props: {
56
+ height: {
57
+ type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
58
+ required: false,
59
+ default: null
60
+ },
61
+ width: {
62
+ type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
63
+ required: false,
64
+ default: null
65
+ },
66
+ aspectRatio: {
67
+ type: Number as PropType<number | null>,
68
+ required: false,
69
+ default: 1
70
+ },
71
+ imageB64: {
72
+ type: String as PropType<string | null>,
73
+ required: false,
74
+ default: null
75
+ },
76
+ source: {
77
+ type: String as PropType<string | null>,
78
+ required: false,
79
+ default: null
80
+ },
81
+ blurHash: {
82
+ type: Object as PropType<ImageDetails | null>,
83
+ required: false,
84
+ default: null
85
+ },
86
+ borderRadius: {
87
+ type: [String, Number],
88
+ required: false,
89
+ default: "4px"
90
+ },
91
+ cover: {
92
+ type: Boolean,
93
+ required: false,
94
+ default: true
95
+ },
96
+ loading: {
97
+ type: Boolean,
98
+ required: false,
99
+ default: false
100
+ }
101
+ },
102
+ setup(props) {
103
+
104
+ const imageRef = ref<HTMLFormElement | null>(null);
105
+ const canvasRef = ref<HTMLCanvasElement | null>(null);
106
+
107
+ const signatures = ref<{ [key: string]: string }>({
108
+ JVBERi0 : "application/pdf",
109
+ R0lGODdh : "image/gif",
110
+ R0lGODlh : "image/gif",
111
+ iVBORw0KGgo: "image/png",
112
+ "/9j/" : "image/jpg",
113
+ });
114
+
115
+ const style = computed((): StyleValue => ({
116
+ "--fs-image-border-radius" : sizeToVar(props.borderRadius),
117
+ "--fs-image-blurhash-opacity": props.blurHash ? "1" : "0"
118
+ }));
119
+
120
+ const computedHeight = computed((): string | undefined => {
121
+ if (props.height) {
122
+ return sizeToVar(props.height);
123
+ }
124
+ if (props.width) {
125
+ if (typeof (props.width) === "string") {
126
+ return undefined;
127
+ }
128
+ if (props.aspectRatio) {
129
+ return sizeToVar(varToSize(props.width) / props.aspectRatio);
130
+ }
131
+ return sizeToVar(props.width);
132
+ }
133
+ return undefined;
134
+ });
135
+
136
+ const computedWidth = computed((): string | undefined => {
137
+ if (props.width) {
138
+ return sizeToVar(props.width);
139
+ }
140
+ if (props.height) {
141
+ if (typeof (props.height) === "string") {
142
+ return undefined;
143
+ }
144
+ if (props.aspectRatio) {
145
+ return sizeToVar(varToSize(props.height) * props.aspectRatio);
146
+ }
147
+ return sizeToVar(props.height);
148
+ }
149
+ return undefined;
150
+ });
151
+
152
+ const realSource = computed((): string | undefined => {
153
+ if (props.imageB64) {
154
+ if (imageType.value && imageData.value) {
155
+ return `${imageType.value},${imageData.value}`;
156
+ }
157
+ }
158
+ else if (props.source) {
159
+ return props.source;
160
+ }
161
+ });
162
+
163
+ const imageData = computed((): string | null => {
164
+ if (props.imageB64 && props.imageB64.includes(",")) {
165
+ return props.imageB64.split(",")[1];
166
+ }
167
+ return props.imageB64;
168
+ });
169
+
170
+ const imageType = computed((): string | null => {
171
+ if (props.imageB64 && props.imageB64.includes(",")) {
172
+ return props.imageB64.split(",")[0];
173
+ }
174
+ if (props.imageB64) {
175
+ for (const s in signatures.value) {
176
+ if (props.imageB64.startsWith(s)) {
177
+ return `data:${signatures.value[s]};base64`;
178
+ }
179
+ }
180
+ }
181
+ return null;
182
+ });
183
+
184
+ watch(() => props.blurHash, () => {
185
+ if (canvasRef.value && imageRef.value) {
186
+ if (props.blurHash && isBlurhashValid(props.blurHash.blurHash).result) {
187
+ const ctx = canvasRef.value.getContext("2d");
188
+ if (ctx) {
189
+ const width = (imageRef.value as any).$el.clientWidth;
190
+ const height = (imageRef.value as any).$el.clientHeight;
191
+ const pixels = decode(props.blurHash.blurHash, width, height);
192
+ const imageData = ctx.createImageData(width, height);
193
+ canvasRef.value.width = width;
194
+ canvasRef.value.height = height;
195
+ imageData.data.set(pixels);
196
+ ctx.putImageData(imageData, 0, 0);
197
+ }
198
+ }
199
+ }
200
+ });
201
+
202
+ return {
203
+ computedHeight,
204
+ computedWidth,
205
+ realSource,
206
+ canvasRef,
207
+ imageRef,
208
+ style
209
+ };
210
+ }
211
+ });
212
+ </script>
@@ -16,12 +16,10 @@
16
16
  </template>
17
17
 
18
18
  <script lang="ts">
19
- import type { PropType } from "vue";
20
- import { computed, defineComponent } from "vue";
19
+ import { computed, defineComponent, type PropType, type StyleValue } from "vue";
21
20
 
21
+ import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
22
22
  import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
23
- import type { ColorBase} from "@dative-gpi/foundation-shared-components/models";
24
- import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
25
23
 
26
24
  import FSLoader from "./FSLoader.vue";
27
25
 
@@ -37,7 +35,7 @@ export default defineComponent({
37
35
  default: null
38
36
  },
39
37
  font: {
40
- type: String as PropType<"text-h1" | "text-h2" | "text-h3" | "text-h4" | "text-body" | "text-button" | "text-overline" | "text-underline">,
38
+ type: String as PropType<"text-h1" | "text-h2" | "text-h3" | "text-h4" | "text-body" | "text-button" | "text-overline">,
41
39
  required: false,
42
40
  default: "text-body"
43
41
  },
@@ -68,21 +66,7 @@ export default defineComponent({
68
66
 
69
67
  const colors = computed(() => getColors(props.color));
70
68
 
71
- const classes = computed((): string[] => {
72
- const classNames = ["fs-label", props.font];
73
- if (!slots.default) {
74
- classNames.push("fs-span-pre-wrap");
75
- }
76
- if (props.lineClamp > 1) {
77
- classNames.push("fs-span-line-clamp");
78
- }
79
- else if (props.ellipsis) {
80
- classNames.push("fs-span-ellipsis");
81
- }
82
- return classNames;
83
- });
84
-
85
- const style = computed((): { [key: string] : string | null | undefined } => {
69
+ const style = computed((): StyleValue => {
86
70
  switch (props.variant) {
87
71
  case "base": return {
88
72
  "--fs-span-line-clamp": props.lineClamp.toString(),
@@ -99,6 +83,20 @@ export default defineComponent({
99
83
  }
100
84
  });
101
85
 
86
+ const classes = computed((): string[] => {
87
+ const classNames = ["fs-label", props.font];
88
+ if (!slots.default) {
89
+ classNames.push("fs-span-pre-wrap");
90
+ }
91
+ if (props.lineClamp > 1) {
92
+ classNames.push("fs-span-line-clamp");
93
+ }
94
+ else if (props.ellipsis) {
95
+ classNames.push("fs-span-ellipsis");
96
+ }
97
+ return classNames;
98
+ });
99
+
102
100
  return {
103
101
  classes,
104
102
  style
@@ -25,13 +25,11 @@
25
25
  </template>
26
26
 
27
27
  <script lang="ts">
28
- import type { PropType } from "vue";
29
- import { computed, defineComponent } from "vue";
30
- import type { RouteLocation } from "vue-router";
28
+ import { computed, defineComponent, type PropType, type StyleValue } from "vue";
29
+ import { type RouteLocation } from "vue-router";
31
30
 
31
+ import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
32
32
  import { useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
33
- import type { ColorBase} from "@dative-gpi/foundation-shared-components/models";
34
- import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
35
33
 
36
34
  export default defineComponent({
37
35
  name: "FSLink",
@@ -52,7 +50,7 @@ export default defineComponent({
52
50
  default: null
53
51
  },
54
52
  font: {
55
- type: String as PropType<"text-h1" | "text-h2" | "text-h3" | "text-body" | "text-button" | "text-overline" | "text-underline">,
53
+ type: String as PropType<"text-h1" | "text-h2" | "text-h3" | "text-body" | "text-button" | "text-overline">,
56
54
  required: false,
57
55
  default: "text-body"
58
56
  },
@@ -83,21 +81,7 @@ export default defineComponent({
83
81
 
84
82
  const colors = computed(() => getColors(props.color));
85
83
 
86
- const classes = computed((): string[] => {
87
- const classNames = ["fs-link", props.font];
88
- if (!slots.default) {
89
- classNames.push("fs-span-pre-wrap");
90
- }
91
- if (props.lineClamp > 1) {
92
- classNames.push("fs-span-line-clamp");
93
- }
94
- else if (props.ellipsis) {
95
- classNames.push("fs-span-ellipsis");
96
- }
97
- return classNames;
98
- });
99
-
100
- const style = computed((): { [key: string] : string | null | undefined } => {
84
+ const style = computed((): StyleValue => {
101
85
  switch (props.variant) {
102
86
  case "base": return {
103
87
  "--fs-span-line-clamp": props.lineClamp.toString(),
@@ -114,6 +98,20 @@ export default defineComponent({
114
98
  }
115
99
  });
116
100
 
101
+ const classes = computed((): string[] => {
102
+ const classNames = ["fs-link", props.font];
103
+ if (!slots.default) {
104
+ classNames.push("fs-span-pre-wrap");
105
+ }
106
+ if (props.lineClamp > 1) {
107
+ classNames.push("fs-span-line-clamp");
108
+ }
109
+ else if (props.ellipsis) {
110
+ classNames.push("fs-span-ellipsis");
111
+ }
112
+ return classNames;
113
+ });
114
+
117
115
  return {
118
116
  classes,
119
117
  style
@@ -7,8 +7,7 @@
7
7
  </template>
8
8
 
9
9
  <script lang="ts">
10
- import type { PropType } from "vue";
11
- import { computed, defineComponent } from "vue";
10
+ import { computed, defineComponent, type PropType, type StyleValue } from "vue";
12
11
 
13
12
  import { useBreakpoints, useColors } from "@dative-gpi/foundation-shared-components/composables";
14
13
  import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
@@ -33,7 +32,7 @@ export default defineComponent({
33
32
  default: "0"
34
33
  },
35
34
  variant: {
36
- type: String as PropType<"standard" | "button" | "input" | "field" | "chip" | "text-h1" | "text-h2" | "text-h3" | "text-h4" | "text-body" | "text-button" | "text-overline" | "text-underline">,
35
+ type: String as PropType<"standard" | "button" | "input" | "field" | "chip" | "text-h1" | "text-h2" | "text-h3" | "text-h4" | "text-body" | "text-button" | "text-overline">,
37
36
  required: false,
38
37
  default: "standard"
39
38
  },
@@ -49,15 +48,13 @@ export default defineComponent({
49
48
 
50
49
  const backgrounds = getColors(ColorEnum.Background);
51
50
 
52
- const style = computed((): { [key: string] : string | null | undefined } => {
53
- return {
54
- "--fs-loader-background-color": backgrounds.base,
55
- "--fs-loader-border-radius" : ["chip"].includes(props.variant) ? "50px" : sizeToVar(props.borderRadius),
56
- "--fs-loader-padding" : sizeToVar(props.padding),
57
- "--fs-loader-height" : sizeToVar(getHeight.value),
58
- "--fs-loader-width" : sizeToVar(getWidth.value)
59
- };
60
- });
51
+ const style = computed((): StyleValue => ({
52
+ "--fs-loader-background-color": backgrounds.base,
53
+ "--fs-loader-border-radius" : ["chip"].includes(props.variant) ? "50px" : sizeToVar(props.borderRadius),
54
+ "--fs-loader-padding" : sizeToVar(props.padding),
55
+ "--fs-loader-height" : sizeToVar(getHeight.value),
56
+ "--fs-loader-width" : sizeToVar(getWidth.value)
57
+ }));
61
58
 
62
59
  const getHeight = computed((): string | number => {
63
60
  switch (props.variant) {
@@ -72,8 +69,7 @@ export default defineComponent({
72
69
  case "text-h4" : return isMobileSized.value ? "16px" : "20px";
73
70
  case "text-body" :
74
71
  case "text-button" : return isMobileSized.value ? "14px" : "16px";
75
- case "text-overline" :
76
- case "text-underline": return "16px";
72
+ case "text-overline" : return "16px";
77
73
  }
78
74
  });
79
75