@dative-gpi/foundation-shared-components 1.0.12 → 1.0.14
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/FSImage.vue +16 -195
- package/components/FSImageUI.vue +219 -0
- package/package.json +4 -4
package/components/FSImage.vue
CHANGED
|
@@ -1,228 +1,49 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
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 { computed, defineComponent, type PropType
|
|
43
|
-
import { decode, isBlurhashValid } from "blurhash";
|
|
11
|
+
import { computed, defineComponent, type PropType } from "vue";
|
|
44
12
|
|
|
45
|
-
import {
|
|
46
|
-
import { useExtensionJwt, useImageBlurHash } from "@dative-gpi/foundation-shared-services/composables";
|
|
47
|
-
import { sizeToVar, varToSize } from "@dative-gpi/foundation-shared-components/utils";
|
|
13
|
+
import { IMAGE_RAW_URL } from "@dative-gpi/foundation-shared-services/config/urls";
|
|
48
14
|
|
|
49
|
-
import
|
|
15
|
+
import { useImage } from "@dative-gpi/foundation-shared-services/composables";
|
|
16
|
+
|
|
17
|
+
import FSImageUI from "./FSImageUI.vue";
|
|
50
18
|
|
|
51
19
|
export default defineComponent({
|
|
52
20
|
name: "FSImage",
|
|
53
21
|
components: {
|
|
54
|
-
|
|
22
|
+
FSImageUI
|
|
55
23
|
},
|
|
56
24
|
props: {
|
|
57
|
-
height: {
|
|
58
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
59
|
-
required: false,
|
|
60
|
-
default: null
|
|
61
|
-
},
|
|
62
|
-
width: {
|
|
63
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
64
|
-
required: false,
|
|
65
|
-
default: null
|
|
66
|
-
},
|
|
67
25
|
imageId: {
|
|
68
26
|
type: String as PropType<string | null>,
|
|
69
27
|
required: false,
|
|
70
28
|
default: null
|
|
71
|
-
},
|
|
72
|
-
imageB64: {
|
|
73
|
-
type: String as PropType<string | null>,
|
|
74
|
-
required: false,
|
|
75
|
-
default: null
|
|
76
|
-
},
|
|
77
|
-
source: {
|
|
78
|
-
type: String as PropType<string | null>,
|
|
79
|
-
required: false,
|
|
80
|
-
default: null
|
|
81
|
-
},
|
|
82
|
-
aspectRatio: {
|
|
83
|
-
type: String as PropType<string | null>,
|
|
84
|
-
required: false,
|
|
85
|
-
default: null
|
|
86
|
-
},
|
|
87
|
-
borderRadius: {
|
|
88
|
-
type: [String, Number],
|
|
89
|
-
required: false,
|
|
90
|
-
default: "4px"
|
|
91
|
-
},
|
|
92
|
-
cover: {
|
|
93
|
-
type: Boolean,
|
|
94
|
-
required: false,
|
|
95
|
-
default: true
|
|
96
29
|
}
|
|
97
30
|
},
|
|
98
31
|
setup(props) {
|
|
99
|
-
const {
|
|
100
|
-
const { jwt } = useExtensionJwt();
|
|
32
|
+
const { get: getImage, entity: image } = useImage();
|
|
101
33
|
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const signatures = ref<{ [key: string]: string }>({
|
|
106
|
-
JVBERi0 : "application/pdf",
|
|
107
|
-
R0lGODdh : "image/gif",
|
|
108
|
-
R0lGODlh : "image/gif",
|
|
109
|
-
iVBORw0KGgo: "image/png",
|
|
110
|
-
"/9j/" : "image/jpg",
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
const style = computed((): StyleValue => ({
|
|
114
|
-
"--fs-image-border-radius" : sizeToVar(props.borderRadius),
|
|
115
|
-
"--fs-image-blurhash-opacity": blurHash.value ? "1" : "0"
|
|
116
|
-
}));
|
|
117
|
-
|
|
118
|
-
const computedHeight = computed((): string | undefined => {
|
|
119
|
-
if (props.height) {
|
|
120
|
-
return sizeToVar(props.height);
|
|
121
|
-
}
|
|
122
|
-
if (props.width) {
|
|
123
|
-
if (typeof (props.width) === "string") {
|
|
124
|
-
return undefined;
|
|
125
|
-
}
|
|
126
|
-
if (props.aspectRatio) {
|
|
127
|
-
const split = props.aspectRatio.split('/');
|
|
128
|
-
if (split.length === 2 && !isNaN(parseFloat(split[0])) && !isNaN(parseFloat(split[1]))) {
|
|
129
|
-
return sizeToVar(varToSize(props.width) * (parseFloat(split[1]) / parseFloat(split[0])));
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return sizeToVar(props.width);
|
|
133
|
-
}
|
|
134
|
-
return undefined;
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
const computedWidth = computed((): string | undefined => {
|
|
138
|
-
if (props.width) {
|
|
139
|
-
return sizeToVar(props.width);
|
|
140
|
-
}
|
|
141
|
-
if (props.height) {
|
|
142
|
-
if (typeof (props.height) === "string") {
|
|
143
|
-
return undefined;
|
|
144
|
-
}
|
|
145
|
-
if (props.aspectRatio) {
|
|
146
|
-
const split = props.aspectRatio.split('/');
|
|
147
|
-
if (split.length === 2 && !isNaN(parseFloat(split[0])) && !isNaN(parseFloat(split[1]))) {
|
|
148
|
-
return sizeToVar(varToSize(props.height) * (parseFloat(split[0]) / parseFloat(split[1])));
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return sizeToVar(props.height);
|
|
152
|
-
}
|
|
153
|
-
return undefined;
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
const realSource = computed((): string | undefined => {
|
|
157
|
-
if (props.imageB64) {
|
|
158
|
-
if (imageType.value && imageData.value) {
|
|
159
|
-
return `${imageType.value},${imageData.value}`;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
else if (props.imageId) {
|
|
163
|
-
if (jwt.value) {
|
|
164
|
-
return IMAGE_RAW_EXTENSION_URL(props.imageId, jwt.value);
|
|
165
|
-
}
|
|
166
|
-
return IMAGE_RAW_URL(props.imageId);
|
|
167
|
-
}
|
|
168
|
-
else if (props.source) {
|
|
169
|
-
return props.source;
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
const imageData = computed((): string | null => {
|
|
174
|
-
if (props.imageB64 && props.imageB64.includes(",")) {
|
|
175
|
-
return props.imageB64.split(",")[1];
|
|
176
|
-
}
|
|
177
|
-
return props.imageB64;
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const imageType = computed((): string | null => {
|
|
181
|
-
if (props.imageB64 && props.imageB64.includes(",")) {
|
|
182
|
-
return props.imageB64.split(",")[0];
|
|
183
|
-
}
|
|
184
|
-
if (props.imageB64) {
|
|
185
|
-
for (const s in signatures.value) {
|
|
186
|
-
if (props.imageB64.startsWith(s)) {
|
|
187
|
-
return `data:${signatures.value[s]};base64`;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return null;
|
|
34
|
+
const source = computed(() => {
|
|
35
|
+
return props.imageId ? IMAGE_RAW_URL(props.imageId) : null;
|
|
192
36
|
});
|
|
193
37
|
|
|
194
38
|
const onError = (): void => {
|
|
195
39
|
if (props.imageId) {
|
|
196
|
-
|
|
40
|
+
getImage(props.imageId);
|
|
197
41
|
}
|
|
198
42
|
};
|
|
199
43
|
|
|
200
|
-
watch(() => blurHash.value, () => {
|
|
201
|
-
if (canvasRef.value && imageRef.value) {
|
|
202
|
-
if (blurHash.value && isBlurhashValid(blurHash.value.blurHash).result) {
|
|
203
|
-
const ctx = canvasRef.value.getContext("2d");
|
|
204
|
-
if (ctx) {
|
|
205
|
-
const width = (imageRef.value as any).$el.clientWidth;
|
|
206
|
-
const height = (imageRef.value as any).$el.clientHeight;
|
|
207
|
-
const pixels = decode(blurHash.value.blurHash, width, height);
|
|
208
|
-
const imageData = ctx.createImageData(width, height);
|
|
209
|
-
canvasRef.value.width = width;
|
|
210
|
-
canvasRef.value.height = height;
|
|
211
|
-
imageData.data.set(pixels);
|
|
212
|
-
ctx.putImageData(imageData, 0, 0);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
|
|
218
44
|
return {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
realSource,
|
|
222
|
-
canvasRef,
|
|
223
|
-
imageRef,
|
|
224
|
-
blurHash,
|
|
225
|
-
style,
|
|
45
|
+
source,
|
|
46
|
+
image,
|
|
226
47
|
onError
|
|
227
48
|
};
|
|
228
49
|
}
|
|
@@ -0,0 +1,219 @@
|
|
|
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 type { ImageDetails } from "@dative-gpi/foundation-shared-domain/models";
|
|
46
|
+
|
|
47
|
+
import { sizeToVar, varToSize } from "@dative-gpi/foundation-shared-components/utils";
|
|
48
|
+
|
|
49
|
+
import FSLoader from "./FSLoader.vue";
|
|
50
|
+
|
|
51
|
+
export default defineComponent({
|
|
52
|
+
name: "FSImageUI",
|
|
53
|
+
components: {
|
|
54
|
+
FSLoader
|
|
55
|
+
},
|
|
56
|
+
props: {
|
|
57
|
+
height: {
|
|
58
|
+
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
59
|
+
required: false,
|
|
60
|
+
default: null
|
|
61
|
+
},
|
|
62
|
+
width: {
|
|
63
|
+
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
64
|
+
required: false,
|
|
65
|
+
default: null
|
|
66
|
+
},
|
|
67
|
+
imageB64: {
|
|
68
|
+
type: String as PropType<string | null>,
|
|
69
|
+
required: false,
|
|
70
|
+
default: null
|
|
71
|
+
},
|
|
72
|
+
source: {
|
|
73
|
+
type: String as PropType<string | null>,
|
|
74
|
+
required: false,
|
|
75
|
+
default: null
|
|
76
|
+
},
|
|
77
|
+
blurHash: {
|
|
78
|
+
type: Object as PropType<ImageDetails | null>,
|
|
79
|
+
required: false,
|
|
80
|
+
default: null
|
|
81
|
+
},
|
|
82
|
+
aspectRatio: {
|
|
83
|
+
type: String as PropType<string | null>,
|
|
84
|
+
required: false,
|
|
85
|
+
default: null
|
|
86
|
+
},
|
|
87
|
+
borderRadius: {
|
|
88
|
+
type: [String, Number],
|
|
89
|
+
required: false,
|
|
90
|
+
default: "4px"
|
|
91
|
+
},
|
|
92
|
+
cover: {
|
|
93
|
+
type: Boolean,
|
|
94
|
+
required: false,
|
|
95
|
+
default: true
|
|
96
|
+
},
|
|
97
|
+
loading: {
|
|
98
|
+
type: Boolean,
|
|
99
|
+
required: false,
|
|
100
|
+
default: false
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
setup(props) {
|
|
104
|
+
|
|
105
|
+
const imageRef = ref<HTMLFormElement | null>(null);
|
|
106
|
+
const canvasRef = ref<HTMLCanvasElement | null>(null);
|
|
107
|
+
|
|
108
|
+
const signatures = ref<{ [key: string]: string }>({
|
|
109
|
+
JVBERi0 : "application/pdf",
|
|
110
|
+
R0lGODdh : "image/gif",
|
|
111
|
+
R0lGODlh : "image/gif",
|
|
112
|
+
iVBORw0KGgo: "image/png",
|
|
113
|
+
"/9j/" : "image/jpg",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const style = computed((): StyleValue => ({
|
|
117
|
+
"--fs-image-border-radius" : sizeToVar(props.borderRadius),
|
|
118
|
+
"--fs-image-blurhash-opacity": props.blurHash ? "1" : "0"
|
|
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 | undefined => {
|
|
160
|
+
if (props.imageB64) {
|
|
161
|
+
if (imageType.value && imageData.value) {
|
|
162
|
+
return `${imageType.value},${imageData.value}`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else if (props.source) {
|
|
166
|
+
return props.source;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const imageData = computed((): string | null => {
|
|
171
|
+
if (props.imageB64 && props.imageB64.includes(",")) {
|
|
172
|
+
return props.imageB64.split(",")[1];
|
|
173
|
+
}
|
|
174
|
+
return props.imageB64;
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const imageType = computed((): string | null => {
|
|
178
|
+
if (props.imageB64 && props.imageB64.includes(",")) {
|
|
179
|
+
return props.imageB64.split(",")[0];
|
|
180
|
+
}
|
|
181
|
+
if (props.imageB64) {
|
|
182
|
+
for (const s in signatures.value) {
|
|
183
|
+
if (props.imageB64.startsWith(s)) {
|
|
184
|
+
return `data:${signatures.value[s]};base64`;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
watch(() => props.blurHash, () => {
|
|
192
|
+
if (canvasRef.value && imageRef.value) {
|
|
193
|
+
if (props.blurHash && isBlurhashValid(props.blurHash.blurHash).result) {
|
|
194
|
+
const ctx = canvasRef.value.getContext("2d");
|
|
195
|
+
if (ctx) {
|
|
196
|
+
const width = (imageRef.value as any).$el.clientWidth;
|
|
197
|
+
const height = (imageRef.value as any).$el.clientHeight;
|
|
198
|
+
const pixels = decode(props.blurHash.blurHash, width, height);
|
|
199
|
+
const imageData = ctx.createImageData(width, height);
|
|
200
|
+
canvasRef.value.width = width;
|
|
201
|
+
canvasRef.value.height = height;
|
|
202
|
+
imageData.data.set(pixels);
|
|
203
|
+
ctx.putImageData(imageData, 0, 0);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
computedHeight,
|
|
211
|
+
computedWidth,
|
|
212
|
+
realSource,
|
|
213
|
+
canvasRef,
|
|
214
|
+
imageRef,
|
|
215
|
+
style
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
</script>
|
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.14",
|
|
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.14",
|
|
14
|
+
"@dative-gpi/foundation-shared-services": "1.0.14"
|
|
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": "e073c5a79111956c451fe05f19c7829246d4784e"
|
|
39
39
|
}
|