@dative-gpi/foundation-shared-components 1.0.16 → 1.0.18
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 +37 -20
- package/components/FSEditImage.vue +27 -272
- package/components/FSEditImageUI.vue +301 -0
- package/components/FSImage.vue +1 -1
- package/components/buttons/FSButtonAddMini.vue +0 -1
- package/components/buttons/FSButtonCancelMini.vue +1 -1
- package/components/buttons/FSButtonDuplicateMini.vue +1 -1
- package/components/buttons/FSButtonEditMini.vue +1 -1
- package/components/buttons/FSButtonFileMini.vue +1 -1
- package/components/buttons/FSButtonNextMini.vue +1 -1
- package/components/buttons/FSButtonPreviousMini.vue +1 -1
- package/components/buttons/FSButtonRedoMini.vue +1 -1
- package/components/buttons/FSButtonRemoveMini.vue +1 -1
- package/components/buttons/FSButtonSaveMini.vue +1 -1
- package/components/buttons/FSButtonSearchMini.vue +1 -1
- package/components/buttons/FSButtonUndoMini.vue +1 -1
- package/components/buttons/FSButtonUpdateMini.vue +1 -1
- package/components/buttons/FSButtonValidateMini.vue +1 -1
- package/components/fields/FSTranslateRichTextField.vue +3 -3
- package/package.json +4 -4
- package/styles/globals/text_fonts.scss +21 -39
package/components/FSButton.vue
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
<FSClickable
|
|
3
3
|
v-if="$props.variant !== 'icon'"
|
|
4
4
|
:editable="$props.editable"
|
|
5
|
-
:padding="
|
|
5
|
+
:padding="padding"
|
|
6
6
|
:variant="$props.variant"
|
|
7
|
-
:height="$props.height"
|
|
8
7
|
:color="$props.color"
|
|
9
|
-
:width="$props.width"
|
|
10
8
|
:load="$props.load"
|
|
11
9
|
:href="$props.href"
|
|
12
10
|
:to="$props.to"
|
|
@@ -15,7 +13,7 @@
|
|
|
15
13
|
v-bind="$attrs"
|
|
16
14
|
>
|
|
17
15
|
<FSRow
|
|
18
|
-
v-if="$props.
|
|
16
|
+
v-if="$props.direction === 'row'"
|
|
19
17
|
align="center-center"
|
|
20
18
|
width="fill"
|
|
21
19
|
:wrap="false"
|
|
@@ -166,7 +164,7 @@
|
|
|
166
164
|
</template>
|
|
167
165
|
|
|
168
166
|
<script lang="ts">
|
|
169
|
-
import { computed, defineComponent, type PropType, type StyleValue } from "vue";
|
|
167
|
+
import { computed, defineComponent, type PropType, type StyleValue, useSlots } from "vue";
|
|
170
168
|
import { type RouteLocation } from "vue-router";
|
|
171
169
|
|
|
172
170
|
import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
|
|
@@ -178,6 +176,12 @@ import FSIcon from "./FSIcon.vue";
|
|
|
178
176
|
import FSCol from "./FSCol.vue";
|
|
179
177
|
import FSRow from "./FSRow.vue";
|
|
180
178
|
|
|
179
|
+
const PADDING_ICON_ONLY = "7px";
|
|
180
|
+
const PADDING_LABEL_ONLY = ["9px 16px", "9px 12px"];
|
|
181
|
+
const PADDING_ICON_LABEL = ["7px 16px", "7px 12px"];
|
|
182
|
+
|
|
183
|
+
const DEFAULT_PADDING = PADDING_ICON_LABEL;
|
|
184
|
+
|
|
181
185
|
export default defineComponent({
|
|
182
186
|
name: "FSButton",
|
|
183
187
|
components: {
|
|
@@ -188,20 +192,10 @@ export default defineComponent({
|
|
|
188
192
|
FSRow
|
|
189
193
|
},
|
|
190
194
|
props: {
|
|
191
|
-
height: {
|
|
192
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
193
|
-
required: false,
|
|
194
|
-
default: () => ["40px", "36px"]
|
|
195
|
-
},
|
|
196
|
-
width: {
|
|
197
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
198
|
-
required: false,
|
|
199
|
-
default: "fit-content"
|
|
200
|
-
},
|
|
201
195
|
padding: {
|
|
202
196
|
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
203
197
|
required: false,
|
|
204
|
-
default:
|
|
198
|
+
default: DEFAULT_PADDING
|
|
205
199
|
},
|
|
206
200
|
to: {
|
|
207
201
|
type: [String, Object] as PropType<string | RouteLocation | null>,
|
|
@@ -236,17 +230,17 @@ export default defineComponent({
|
|
|
236
230
|
iconSize: {
|
|
237
231
|
type: [Array, String, Number] as PropType<"s" | "m" | "l" | string[] | number[] | string | number | null>,
|
|
238
232
|
required: false,
|
|
239
|
-
default: "
|
|
233
|
+
default: () => ["24", "20"]
|
|
240
234
|
},
|
|
241
235
|
variant: {
|
|
242
236
|
type: String as PropType<"standard" | "full" | "icon">,
|
|
243
237
|
required: false,
|
|
244
238
|
default: "standard"
|
|
245
239
|
},
|
|
246
|
-
|
|
247
|
-
type: String as PropType<"
|
|
240
|
+
direction: {
|
|
241
|
+
type: String as PropType<"row" | "column">,
|
|
248
242
|
required: false,
|
|
249
|
-
default: "
|
|
243
|
+
default: "row"
|
|
250
244
|
},
|
|
251
245
|
color: {
|
|
252
246
|
type: String as PropType<ColorBase>,
|
|
@@ -271,6 +265,7 @@ export default defineComponent({
|
|
|
271
265
|
const colors = computed(() => getColors(props.color));
|
|
272
266
|
const lights = getColors(ColorEnum.Light);
|
|
273
267
|
const darks = getColors(ColorEnum.Dark);
|
|
268
|
+
const slots = useSlots();
|
|
274
269
|
|
|
275
270
|
const style = computed((): StyleValue => {
|
|
276
271
|
if (!props.editable) {
|
|
@@ -314,6 +309,27 @@ export default defineComponent({
|
|
|
314
309
|
}
|
|
315
310
|
});
|
|
316
311
|
|
|
312
|
+
const padding = computed(() => {
|
|
313
|
+
if(props.padding !== DEFAULT_PADDING){
|
|
314
|
+
return props.padding;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const hasIcon = props.prependIcon || props.appendIcon || props.icon
|
|
318
|
+
|| !!slots.prepend || !!slots.append;
|
|
319
|
+
|
|
320
|
+
const hasLabel = props.label || !!slots.default;
|
|
321
|
+
|
|
322
|
+
if(!hasLabel && hasIcon){
|
|
323
|
+
return PADDING_ICON_ONLY;
|
|
324
|
+
}
|
|
325
|
+
else if(hasLabel && !hasIcon)
|
|
326
|
+
{
|
|
327
|
+
return PADDING_LABEL_ONLY;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return DEFAULT_PADDING;
|
|
331
|
+
})
|
|
332
|
+
|
|
317
333
|
const onClick = (event: MouseEvent) => {
|
|
318
334
|
if (!props.to && !props.href && props.editable && !props.load) {
|
|
319
335
|
emit("click", event);
|
|
@@ -325,6 +341,7 @@ export default defineComponent({
|
|
|
325
341
|
loadColor,
|
|
326
342
|
colors,
|
|
327
343
|
style,
|
|
344
|
+
padding,
|
|
328
345
|
onClick
|
|
329
346
|
};
|
|
330
347
|
}
|
|
@@ -1,298 +1,53 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<FSRow
|
|
10
|
-
:wrap="false"
|
|
11
|
-
>
|
|
12
|
-
<FSSpan
|
|
13
|
-
v-if="$props.label"
|
|
14
|
-
class="fs-edit-image-label"
|
|
15
|
-
font="text-overline"
|
|
16
|
-
:style="style"
|
|
17
|
-
>
|
|
18
|
-
{{ $props.label }}
|
|
19
|
-
</FSSpan>
|
|
20
|
-
<FSSpan
|
|
21
|
-
v-if="$props.label && $props.required"
|
|
22
|
-
class="fs-edit-image-label"
|
|
23
|
-
style="margin-left: -8px;"
|
|
24
|
-
font="text-overline"
|
|
25
|
-
:ellipsis="false"
|
|
26
|
-
:style="style"
|
|
27
|
-
>
|
|
28
|
-
*
|
|
29
|
-
</FSSpan>
|
|
30
|
-
</FSRow>
|
|
31
|
-
</slot>
|
|
32
|
-
<FSCard
|
|
33
|
-
v-if="['standard'].includes($props.variant)"
|
|
34
|
-
padding="12px"
|
|
35
|
-
width="100%"
|
|
36
|
-
>
|
|
37
|
-
<FSRow
|
|
38
|
-
align="center-left"
|
|
39
|
-
:wrap="false"
|
|
40
|
-
>
|
|
41
|
-
<FSRow
|
|
42
|
-
gap="24px"
|
|
43
|
-
:wrap="false"
|
|
44
|
-
>
|
|
45
|
-
<FSImage
|
|
46
|
-
v-if="$props.imageId || $props.modelValue"
|
|
47
|
-
:aspectRatio="$props.aspectRatio"
|
|
48
|
-
:height="$props.height"
|
|
49
|
-
:width="$props.width"
|
|
50
|
-
:imageId="$props.imageId"
|
|
51
|
-
:imageB64="$props.modelValue"
|
|
52
|
-
/>
|
|
53
|
-
<FSCard
|
|
54
|
-
v-else
|
|
55
|
-
borderStyle="dashed"
|
|
56
|
-
:aspectRatio="$props.aspectRatio"
|
|
57
|
-
:height="$props.height"
|
|
58
|
-
:width="$props.width"
|
|
59
|
-
/>
|
|
60
|
-
<FSCol
|
|
61
|
-
align="center-left"
|
|
62
|
-
height="fill"
|
|
63
|
-
width="hug"
|
|
64
|
-
gap="10px"
|
|
65
|
-
>
|
|
66
|
-
<FSText
|
|
67
|
-
v-if="fileSelected && fileSelected.fileName"
|
|
68
|
-
font="text-body"
|
|
69
|
-
:lineClamp="2"
|
|
70
|
-
>
|
|
71
|
-
{{ fileSelected.fileName }}
|
|
72
|
-
</FSText>
|
|
73
|
-
<FSCol
|
|
74
|
-
gap="0px"
|
|
75
|
-
>
|
|
76
|
-
<FSText
|
|
77
|
-
class="fs-edit-image-overline"
|
|
78
|
-
font="text-overline"
|
|
79
|
-
:style="style"
|
|
80
|
-
>
|
|
81
|
-
{{ $tr('ui.edit-image.format', 'PNG or JPG format') }}
|
|
82
|
-
</FSText>
|
|
83
|
-
<FSText
|
|
84
|
-
class="fs-edit-image-overline"
|
|
85
|
-
font="text-overline"
|
|
86
|
-
:style="style"
|
|
87
|
-
>
|
|
88
|
-
{{ $tr('ui.edit-image.size', '10 MB Maximum') }}
|
|
89
|
-
</FSText>
|
|
90
|
-
</FSCol>
|
|
91
|
-
</FSCol>
|
|
92
|
-
</FSRow>
|
|
93
|
-
<v-spacer />
|
|
94
|
-
<FSRow
|
|
95
|
-
width="hug"
|
|
96
|
-
>
|
|
97
|
-
<FSButtonFileMini
|
|
98
|
-
accept="image/*"
|
|
99
|
-
:readFile="false"
|
|
100
|
-
@update:metadata="onUpload"
|
|
101
|
-
/>
|
|
102
|
-
<FSButtonRemoveMini
|
|
103
|
-
@click="onRemove"
|
|
104
|
-
/>
|
|
105
|
-
</FSRow>
|
|
106
|
-
</FSRow>
|
|
107
|
-
</FSCard>
|
|
108
|
-
<FSRow
|
|
109
|
-
v-else-if="$props.imageId || $props.modelValue"
|
|
110
|
-
:width="$props.width"
|
|
111
|
-
class="fs-edit-image-full"
|
|
112
|
-
>
|
|
113
|
-
<FSImage
|
|
114
|
-
:aspectRatio="$props.aspectRatio"
|
|
115
|
-
:height="$props.height"
|
|
116
|
-
:width="$props.width"
|
|
117
|
-
:imageId="$props.imageId"
|
|
118
|
-
:imageB64="$props.modelValue"
|
|
119
|
-
/>
|
|
120
|
-
<FSRow
|
|
121
|
-
class="fs-edit-image-full-toolbar"
|
|
122
|
-
padding="4px"
|
|
123
|
-
>
|
|
124
|
-
<FSButtonFileMini
|
|
125
|
-
accept="image/*"
|
|
126
|
-
:readFile="false"
|
|
127
|
-
@update:metadata="onUpload"
|
|
128
|
-
/>
|
|
129
|
-
<FSButtonRemoveMini
|
|
130
|
-
@click="onRemove"
|
|
131
|
-
/>
|
|
132
|
-
</FSRow>
|
|
133
|
-
</FSRow>
|
|
134
|
-
<FSClickable
|
|
135
|
-
v-else
|
|
136
|
-
borderStyle="dashed"
|
|
137
|
-
variant="background"
|
|
138
|
-
:height="$props.height"
|
|
139
|
-
:width="$props.width"
|
|
140
|
-
@click="() => invisibleButtonRef.input.click()"
|
|
141
|
-
>
|
|
142
|
-
<FSRow
|
|
143
|
-
align="center-center"
|
|
144
|
-
:wrap="false"
|
|
145
|
-
>
|
|
146
|
-
<FSIcon>
|
|
147
|
-
mdi-plus-box-outline
|
|
148
|
-
</FSIcon>
|
|
149
|
-
<FSText
|
|
150
|
-
font="text-body"
|
|
151
|
-
:lineClamp="2"
|
|
152
|
-
>
|
|
153
|
-
{{ $tr('ui.edit-image.add-image', 'Add an image.') }}
|
|
154
|
-
</FSText>
|
|
155
|
-
<FSButtonFileMini
|
|
156
|
-
class="fs-edit-image-hidden-button"
|
|
157
|
-
ref="invisibleButtonRef"
|
|
158
|
-
accept="image/*"
|
|
159
|
-
:readFile="false"
|
|
160
|
-
@update:metadata="onUpload"
|
|
161
|
-
/>
|
|
162
|
-
</FSRow>
|
|
163
|
-
</FSClickable>
|
|
164
|
-
</FSCol>
|
|
2
|
+
<FSEditImageUI
|
|
3
|
+
:source="source"
|
|
4
|
+
:blurHash="image"
|
|
5
|
+
@error="onError"
|
|
6
|
+
@update:source="$emit('update:imageId', $event)"
|
|
7
|
+
v-bind="$attrs"
|
|
8
|
+
/>
|
|
165
9
|
</template>
|
|
166
10
|
|
|
167
11
|
<script lang="ts">
|
|
168
|
-
import { computed, defineComponent, type PropType
|
|
12
|
+
import { computed, defineComponent, type PropType } from "vue";
|
|
169
13
|
|
|
170
|
-
import {
|
|
171
|
-
import { ColorEnum, type FileImage } from "@dative-gpi/foundation-shared-components/models";
|
|
172
|
-
import { useFiles } from "@dative-gpi/foundation-shared-services/composables";
|
|
14
|
+
import { IMAGE_RAW_URL } from "@dative-gpi/foundation-shared-services/config";
|
|
173
15
|
|
|
174
|
-
import
|
|
175
|
-
|
|
176
|
-
import
|
|
177
|
-
import FSImage from "./FSImage.vue";
|
|
178
|
-
import FSCard from "./FSCard.vue";
|
|
179
|
-
import FSText from "./FSText.vue";
|
|
180
|
-
import FSCol from "./FSCol.vue";
|
|
181
|
-
import FSRow from "./FSRow.vue";
|
|
16
|
+
import { useImage } from "@dative-gpi/foundation-shared-services/composables";
|
|
17
|
+
|
|
18
|
+
import FSEditImageUI from "./FSEditImageUI.vue";
|
|
182
19
|
|
|
183
20
|
export default defineComponent({
|
|
184
21
|
name: "FSEditImage",
|
|
185
22
|
components: {
|
|
186
|
-
|
|
187
|
-
FSButtonFileMini,
|
|
188
|
-
FSClickable,
|
|
189
|
-
FSImage,
|
|
190
|
-
FSCard,
|
|
191
|
-
FSText,
|
|
192
|
-
FSCol,
|
|
193
|
-
FSRow
|
|
23
|
+
FSEditImageUI
|
|
194
24
|
},
|
|
195
25
|
props: {
|
|
196
|
-
height: {
|
|
197
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
198
|
-
required: false,
|
|
199
|
-
default: null
|
|
200
|
-
},
|
|
201
|
-
width: {
|
|
202
|
-
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
203
|
-
required: false,
|
|
204
|
-
default: null
|
|
205
|
-
},
|
|
206
|
-
label: {
|
|
207
|
-
type: String as PropType<string | null>,
|
|
208
|
-
required: false,
|
|
209
|
-
default: null
|
|
210
|
-
},
|
|
211
26
|
imageId: {
|
|
212
27
|
type: String as PropType<string | null>,
|
|
213
28
|
required: false,
|
|
214
29
|
default: null
|
|
215
|
-
},
|
|
216
|
-
aspectRatio: {
|
|
217
|
-
type: String as PropType<string | null>,
|
|
218
|
-
required: false,
|
|
219
|
-
default: null
|
|
220
|
-
},
|
|
221
|
-
modelValue: {
|
|
222
|
-
type: String as PropType<string | null>,
|
|
223
|
-
required: false,
|
|
224
|
-
default: null
|
|
225
|
-
},
|
|
226
|
-
variant: {
|
|
227
|
-
type: String as PropType<"standard" | "full">,
|
|
228
|
-
required: false,
|
|
229
|
-
default: "standard"
|
|
230
|
-
},
|
|
231
|
-
hideHeader: {
|
|
232
|
-
type: Boolean,
|
|
233
|
-
required: false,
|
|
234
|
-
default: false
|
|
235
|
-
},
|
|
236
|
-
required: {
|
|
237
|
-
type: Boolean,
|
|
238
|
-
required: false,
|
|
239
|
-
default: false
|
|
240
30
|
}
|
|
241
31
|
},
|
|
242
|
-
emits: ["update:
|
|
243
|
-
setup(props
|
|
244
|
-
const {
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const errors = getColors(ColorEnum.Error);
|
|
252
|
-
const lights = getColors(ColorEnum.Light);
|
|
253
|
-
const darks = getColors(ColorEnum.Dark);
|
|
254
|
-
|
|
255
|
-
const style = computed((): StyleValue => ({
|
|
256
|
-
"--fs-edit-image-overline-text-color": lights.dark,
|
|
257
|
-
"--fs-edit-image-color" : darks.base,
|
|
258
|
-
"--fs-edit-image-error-color" : errors.base
|
|
259
|
-
}));
|
|
260
|
-
|
|
261
|
-
const onUpload = async (payload: File) => {
|
|
262
|
-
const content = (await readFile(payload)) as string;
|
|
263
|
-
fileSelected.value.fileName = payload.name;
|
|
264
|
-
fileSelected.value.fileContent = content;
|
|
265
|
-
emit("update:modelValue", content.substring(content.indexOf(',') + 1));
|
|
32
|
+
emits: ["update:imageId"],
|
|
33
|
+
setup(props) {
|
|
34
|
+
const { get: getImage, entity: image } = useImage();
|
|
35
|
+
|
|
36
|
+
const source = computed(() => {
|
|
37
|
+
return props.imageId ? IMAGE_RAW_URL(props.imageId) : null;
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const onError = (): void => {
|
|
266
41
|
if (props.imageId) {
|
|
267
|
-
|
|
42
|
+
console.log("onError");
|
|
43
|
+
getImage(props.imageId);
|
|
268
44
|
}
|
|
269
45
|
};
|
|
270
46
|
|
|
271
|
-
const onRemove = () => {
|
|
272
|
-
fileSelected.value.fileName = "";
|
|
273
|
-
fileSelected.value.fileContent = null;
|
|
274
|
-
if (props.modelValue) {
|
|
275
|
-
emit("update:modelValue", null);
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
emit("update:imageId", null);
|
|
279
|
-
}
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
watch(() => props.modelValue, () => {
|
|
283
|
-
if (!props.modelValue) {
|
|
284
|
-
fileSelected.value.fileName = "";
|
|
285
|
-
fileSelected.value.fileContent = null;
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
|
|
289
47
|
return {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
style,
|
|
294
|
-
onUpload,
|
|
295
|
-
onRemove
|
|
48
|
+
image,
|
|
49
|
+
source,
|
|
50
|
+
onError
|
|
296
51
|
};
|
|
297
52
|
}
|
|
298
53
|
});
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FSCol
|
|
3
|
+
gap="8px"
|
|
4
|
+
>
|
|
5
|
+
<slot
|
|
6
|
+
v-if="!$props.hideHeader"
|
|
7
|
+
name="label"
|
|
8
|
+
>
|
|
9
|
+
<FSRow
|
|
10
|
+
:wrap="false"
|
|
11
|
+
>
|
|
12
|
+
<FSSpan
|
|
13
|
+
v-if="$props.label"
|
|
14
|
+
class="fs-edit-image-label"
|
|
15
|
+
font="text-overline"
|
|
16
|
+
:style="style"
|
|
17
|
+
>
|
|
18
|
+
{{ $props.label }}
|
|
19
|
+
</FSSpan>
|
|
20
|
+
<FSSpan
|
|
21
|
+
v-if="$props.label && $props.required"
|
|
22
|
+
class="fs-edit-image-label"
|
|
23
|
+
style="margin-left: -8px;"
|
|
24
|
+
font="text-overline"
|
|
25
|
+
:ellipsis="false"
|
|
26
|
+
:style="style"
|
|
27
|
+
>
|
|
28
|
+
*
|
|
29
|
+
</FSSpan>
|
|
30
|
+
</FSRow>
|
|
31
|
+
</slot>
|
|
32
|
+
<FSCard
|
|
33
|
+
v-if="['standard'].includes($props.variant)"
|
|
34
|
+
padding="12px"
|
|
35
|
+
width="100%"
|
|
36
|
+
>
|
|
37
|
+
<FSRow
|
|
38
|
+
align="center-left"
|
|
39
|
+
:wrap="false"
|
|
40
|
+
>
|
|
41
|
+
<FSRow
|
|
42
|
+
gap="24px"
|
|
43
|
+
:wrap="false"
|
|
44
|
+
>
|
|
45
|
+
<FSImageUI
|
|
46
|
+
v-if="$props.source || $props.modelValue"
|
|
47
|
+
:aspectRatio="$props.aspectRatio"
|
|
48
|
+
:height="$props.height"
|
|
49
|
+
:width="$props.width"
|
|
50
|
+
:source="$props.source"
|
|
51
|
+
:imageB64="$props.modelValue"
|
|
52
|
+
v-bind="$attrs"
|
|
53
|
+
/>
|
|
54
|
+
<FSCard
|
|
55
|
+
v-else
|
|
56
|
+
borderStyle="dashed"
|
|
57
|
+
:aspectRatio="$props.aspectRatio"
|
|
58
|
+
:height="$props.height"
|
|
59
|
+
:width="$props.width"
|
|
60
|
+
/>
|
|
61
|
+
<FSCol
|
|
62
|
+
align="center-left"
|
|
63
|
+
height="fill"
|
|
64
|
+
width="hug"
|
|
65
|
+
gap="10px"
|
|
66
|
+
>
|
|
67
|
+
<FSText
|
|
68
|
+
v-if="fileSelected && fileSelected.fileName"
|
|
69
|
+
font="text-body"
|
|
70
|
+
:lineClamp="2"
|
|
71
|
+
>
|
|
72
|
+
{{ fileSelected.fileName }}
|
|
73
|
+
</FSText>
|
|
74
|
+
<FSCol
|
|
75
|
+
gap="0px"
|
|
76
|
+
>
|
|
77
|
+
<FSText
|
|
78
|
+
class="fs-edit-image-overline"
|
|
79
|
+
font="text-overline"
|
|
80
|
+
:style="style"
|
|
81
|
+
>
|
|
82
|
+
{{ $tr('ui.edit-image.format', 'PNG or JPG format') }}
|
|
83
|
+
</FSText>
|
|
84
|
+
<FSText
|
|
85
|
+
class="fs-edit-image-overline"
|
|
86
|
+
font="text-overline"
|
|
87
|
+
:style="style"
|
|
88
|
+
>
|
|
89
|
+
{{ $tr('ui.edit-image.size', '10 MB Maximum') }}
|
|
90
|
+
</FSText>
|
|
91
|
+
</FSCol>
|
|
92
|
+
</FSCol>
|
|
93
|
+
</FSRow>
|
|
94
|
+
<v-spacer />
|
|
95
|
+
<FSRow
|
|
96
|
+
width="hug"
|
|
97
|
+
>
|
|
98
|
+
<FSButtonFileMini
|
|
99
|
+
accept="image/*"
|
|
100
|
+
:readFile="false"
|
|
101
|
+
@update:metadata="onUpload"
|
|
102
|
+
/>
|
|
103
|
+
<FSButtonRemoveMini
|
|
104
|
+
@click="onRemove"
|
|
105
|
+
/>
|
|
106
|
+
</FSRow>
|
|
107
|
+
</FSRow>
|
|
108
|
+
</FSCard>
|
|
109
|
+
<FSRow
|
|
110
|
+
v-else-if="$props.source || $props.modelValue"
|
|
111
|
+
:width="$props.width"
|
|
112
|
+
class="fs-edit-image-full"
|
|
113
|
+
>
|
|
114
|
+
<FSImageUI
|
|
115
|
+
:aspectRatio="$props.aspectRatio"
|
|
116
|
+
:height="$props.height"
|
|
117
|
+
:width="$props.width"
|
|
118
|
+
:source="$props.source"
|
|
119
|
+
:imageB64="$props.modelValue"
|
|
120
|
+
v-bind="$attrs"
|
|
121
|
+
/>
|
|
122
|
+
<FSRow
|
|
123
|
+
class="fs-edit-image-full-toolbar"
|
|
124
|
+
padding="4px"
|
|
125
|
+
>
|
|
126
|
+
<FSButtonFileMini
|
|
127
|
+
accept="image/*"
|
|
128
|
+
:readFile="false"
|
|
129
|
+
@update:metadata="onUpload"
|
|
130
|
+
/>
|
|
131
|
+
<FSButtonRemoveMini
|
|
132
|
+
@click="onRemove"
|
|
133
|
+
/>
|
|
134
|
+
</FSRow>
|
|
135
|
+
</FSRow>
|
|
136
|
+
<FSClickable
|
|
137
|
+
v-else
|
|
138
|
+
borderStyle="dashed"
|
|
139
|
+
variant="background"
|
|
140
|
+
:height="$props.height"
|
|
141
|
+
:width="$props.width"
|
|
142
|
+
@click="() => invisibleButtonRef.input.click()"
|
|
143
|
+
>
|
|
144
|
+
<FSRow
|
|
145
|
+
align="center-center"
|
|
146
|
+
:wrap="false"
|
|
147
|
+
>
|
|
148
|
+
<FSIcon>
|
|
149
|
+
mdi-plus-box-outline
|
|
150
|
+
</FSIcon>
|
|
151
|
+
<FSText
|
|
152
|
+
font="text-body"
|
|
153
|
+
:lineClamp="2"
|
|
154
|
+
>
|
|
155
|
+
{{ $tr('ui.edit-image.add-image', 'Add an image.') }}
|
|
156
|
+
</FSText>
|
|
157
|
+
<FSButtonFileMini
|
|
158
|
+
class="fs-edit-image-hidden-button"
|
|
159
|
+
ref="invisibleButtonRef"
|
|
160
|
+
accept="image/*"
|
|
161
|
+
:readFile="false"
|
|
162
|
+
@update:metadata="onUpload"
|
|
163
|
+
/>
|
|
164
|
+
</FSRow>
|
|
165
|
+
</FSClickable>
|
|
166
|
+
</FSCol>
|
|
167
|
+
</template>
|
|
168
|
+
|
|
169
|
+
<script lang="ts">
|
|
170
|
+
import { computed, defineComponent, type PropType, ref, type StyleValue, watch } from "vue";
|
|
171
|
+
|
|
172
|
+
import { useBreakpoints, useColors } from "@dative-gpi/foundation-shared-components/composables";
|
|
173
|
+
import { ColorEnum, type FileImage } from "@dative-gpi/foundation-shared-components/models";
|
|
174
|
+
import { useFiles } from "@dative-gpi/foundation-shared-services/composables";
|
|
175
|
+
|
|
176
|
+
import FSButtonRemoveMini from "./buttons/FSButtonRemoveMini.vue";
|
|
177
|
+
import FSButtonFileMini from "./buttons/FSButtonFileMini.vue";
|
|
178
|
+
import FSClickable from "./FSClickable.vue";
|
|
179
|
+
import FSImageUI from "./FSImageUI.vue";
|
|
180
|
+
import FSCard from "./FSCard.vue";
|
|
181
|
+
import FSText from "./FSText.vue";
|
|
182
|
+
import FSCol from "./FSCol.vue";
|
|
183
|
+
import FSRow from "./FSRow.vue";
|
|
184
|
+
|
|
185
|
+
export default defineComponent({
|
|
186
|
+
name: "FSEditImageUI",
|
|
187
|
+
components: {
|
|
188
|
+
FSButtonRemoveMini,
|
|
189
|
+
FSButtonFileMini,
|
|
190
|
+
FSClickable,
|
|
191
|
+
FSImageUI,
|
|
192
|
+
FSCard,
|
|
193
|
+
FSText,
|
|
194
|
+
FSCol,
|
|
195
|
+
FSRow
|
|
196
|
+
},
|
|
197
|
+
props: {
|
|
198
|
+
height: {
|
|
199
|
+
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
200
|
+
required: false,
|
|
201
|
+
default: null
|
|
202
|
+
},
|
|
203
|
+
width: {
|
|
204
|
+
type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
|
|
205
|
+
required: false,
|
|
206
|
+
default: null
|
|
207
|
+
},
|
|
208
|
+
label: {
|
|
209
|
+
type: String as PropType<string | null>,
|
|
210
|
+
required: false,
|
|
211
|
+
default: null
|
|
212
|
+
},
|
|
213
|
+
source: {
|
|
214
|
+
type: String as PropType<string | null>,
|
|
215
|
+
required: false,
|
|
216
|
+
default: null
|
|
217
|
+
},
|
|
218
|
+
aspectRatio: {
|
|
219
|
+
type: String as PropType<string | null>,
|
|
220
|
+
required: false,
|
|
221
|
+
default: null
|
|
222
|
+
},
|
|
223
|
+
modelValue: {
|
|
224
|
+
type: String as PropType<string | null>,
|
|
225
|
+
required: false,
|
|
226
|
+
default: null
|
|
227
|
+
},
|
|
228
|
+
variant: {
|
|
229
|
+
type: String as PropType<"standard" | "full">,
|
|
230
|
+
required: false,
|
|
231
|
+
default: "standard"
|
|
232
|
+
},
|
|
233
|
+
hideHeader: {
|
|
234
|
+
type: Boolean,
|
|
235
|
+
required: false,
|
|
236
|
+
default: false
|
|
237
|
+
},
|
|
238
|
+
required: {
|
|
239
|
+
type: Boolean,
|
|
240
|
+
required: false,
|
|
241
|
+
default: false
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
emits: ["update:modelValue", "update:source"],
|
|
245
|
+
setup(props, { emit }) {
|
|
246
|
+
const { isExtraSmall } = useBreakpoints();
|
|
247
|
+
const { getColors } = useColors();
|
|
248
|
+
const { readFile } = useFiles();
|
|
249
|
+
|
|
250
|
+
const fileSelected = ref<FileImage>({ fileName: "", fileContent: null });
|
|
251
|
+
const invisibleButtonRef = ref<HTMLFormElement | null>(null);
|
|
252
|
+
|
|
253
|
+
const errors = getColors(ColorEnum.Error);
|
|
254
|
+
const lights = getColors(ColorEnum.Light);
|
|
255
|
+
const darks = getColors(ColorEnum.Dark);
|
|
256
|
+
|
|
257
|
+
const style = computed((): StyleValue => ({
|
|
258
|
+
"--fs-edit-image-overline-text-color": lights.dark,
|
|
259
|
+
"--fs-edit-image-color" : darks.base,
|
|
260
|
+
"--fs-edit-image-error-color" : errors.base
|
|
261
|
+
}));
|
|
262
|
+
|
|
263
|
+
const onUpload = async (payload: File) => {
|
|
264
|
+
const content = (await readFile(payload)) as string;
|
|
265
|
+
fileSelected.value.fileName = payload.name;
|
|
266
|
+
fileSelected.value.fileContent = content;
|
|
267
|
+
emit("update:modelValue", content.substring(content.indexOf(',') + 1));
|
|
268
|
+
if (props.source) {
|
|
269
|
+
emit("update:source", null);
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const onRemove = () => {
|
|
274
|
+
fileSelected.value.fileName = "";
|
|
275
|
+
fileSelected.value.fileContent = null;
|
|
276
|
+
if (props.modelValue) {
|
|
277
|
+
emit("update:modelValue", null);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
emit("update:source", null);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
watch(() => props.modelValue, () => {
|
|
285
|
+
if (!props.modelValue) {
|
|
286
|
+
fileSelected.value.fileName = "";
|
|
287
|
+
fileSelected.value.fileContent = null;
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
invisibleButtonRef,
|
|
293
|
+
fileSelected,
|
|
294
|
+
isExtraSmall,
|
|
295
|
+
style,
|
|
296
|
+
onUpload,
|
|
297
|
+
onRemove
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
</script>
|
package/components/FSImage.vue
CHANGED
|
@@ -41,16 +41,16 @@
|
|
|
41
41
|
>
|
|
42
42
|
<FSButton
|
|
43
43
|
prependIcon="mdi-cancel"
|
|
44
|
+
width="100%"
|
|
44
45
|
:label="$tr('ui.translateRichTextField.cancelButton.label', 'Cancel')"
|
|
45
|
-
:fullWidth="true"
|
|
46
46
|
@click="onCancelTranslations"
|
|
47
47
|
/>
|
|
48
48
|
<FSButton
|
|
49
49
|
v-if="$props.editable"
|
|
50
50
|
prependIcon="mdi-check"
|
|
51
51
|
color="primary"
|
|
52
|
+
width="100%"
|
|
52
53
|
:label="$tr('ui.translateRichTextField.validateButton.label', 'Validate translations')"
|
|
53
|
-
:fullWidth="true"
|
|
54
54
|
@click="onSubmitTranslations"
|
|
55
55
|
/>
|
|
56
56
|
</FSRow>
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
<FSButton
|
|
69
69
|
prependIcon="mdi-translate"
|
|
70
70
|
color="primary"
|
|
71
|
+
width="100%"
|
|
71
72
|
:label="$tr('ui.translateRichTextField.translateButton.label', 'Manage translations')"
|
|
72
|
-
:fullWidth="true"
|
|
73
73
|
@click="() => $emit('update:translationsExpanded', true)"
|
|
74
74
|
/>
|
|
75
75
|
</template>
|
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.18",
|
|
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.18",
|
|
14
|
+
"@dative-gpi/foundation-shared-services": "1.0.18"
|
|
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": "8e464715fcb19efb4752474ffcded0508d44da53"
|
|
39
39
|
}
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
@include web {
|
|
11
11
|
font-size: 36px !important;
|
|
12
12
|
line-height: 40px !important;
|
|
13
|
-
letter-spacing: -
|
|
13
|
+
letter-spacing: -2% !important;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
@include mobile {
|
|
17
|
-
font-size:
|
|
17
|
+
font-size: 28px !important;
|
|
18
18
|
line-height: 32px !important;
|
|
19
|
-
letter-spacing: -
|
|
19
|
+
letter-spacing: -5% !important;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -26,15 +26,15 @@
|
|
|
26
26
|
font-weight: 600 !important;
|
|
27
27
|
|
|
28
28
|
@include web {
|
|
29
|
-
font-size:
|
|
29
|
+
font-size: 26px !important;
|
|
30
30
|
line-height: 32px !important;
|
|
31
|
-
letter-spacing: -
|
|
31
|
+
letter-spacing: -3% !important;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
@include mobile {
|
|
35
35
|
font-size: 22px !important;
|
|
36
36
|
line-height: 24px !important;
|
|
37
|
-
letter-spacing: -
|
|
37
|
+
letter-spacing: -4% !important;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -44,33 +44,15 @@
|
|
|
44
44
|
font-weight: 600 !important;
|
|
45
45
|
|
|
46
46
|
@include web {
|
|
47
|
-
font-size:
|
|
47
|
+
font-size: 20px !important;
|
|
48
48
|
line-height: 24px !important;
|
|
49
|
-
letter-spacing: -
|
|
49
|
+
letter-spacing: -3% !important;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
@include mobile {
|
|
53
|
-
font-size: 17px !important;
|
|
54
|
-
line-height: 20px !important;
|
|
55
|
-
letter-spacing: -0.51px !important;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.text-h4 {
|
|
60
|
-
font-family: 'Montserrat', sans-serif !important;
|
|
61
|
-
font-style: normal !important;
|
|
62
|
-
font-weight: 500 !important;
|
|
63
|
-
|
|
64
|
-
@include web {
|
|
65
53
|
font-size: 16px !important;
|
|
66
54
|
line-height: 20px !important;
|
|
67
|
-
letter-spacing: -
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
@include mobile {
|
|
71
|
-
font-size: 14px !important;
|
|
72
|
-
line-height: 16px !important;
|
|
73
|
-
letter-spacing: -0.41px !important;
|
|
55
|
+
letter-spacing: -3% !important;
|
|
74
56
|
}
|
|
75
57
|
}
|
|
76
58
|
|
|
@@ -82,14 +64,14 @@
|
|
|
82
64
|
|
|
83
65
|
@include web {
|
|
84
66
|
font-size: 14px !important;
|
|
85
|
-
line-height:
|
|
86
|
-
letter-spacing: -
|
|
67
|
+
line-height: 20px !important;
|
|
68
|
+
letter-spacing: -3% !important;
|
|
87
69
|
}
|
|
88
70
|
|
|
89
71
|
@include mobile {
|
|
90
72
|
font-size: 12px !important;
|
|
91
|
-
line-height:
|
|
92
|
-
letter-spacing: -
|
|
73
|
+
line-height: 16px !important;
|
|
74
|
+
letter-spacing: -3% !important;
|
|
93
75
|
}
|
|
94
76
|
}
|
|
95
77
|
|
|
@@ -101,14 +83,14 @@
|
|
|
101
83
|
|
|
102
84
|
@include web {
|
|
103
85
|
font-size: 14px !important;
|
|
104
|
-
line-height:
|
|
105
|
-
letter-spacing: -
|
|
86
|
+
line-height: 20px !important;
|
|
87
|
+
letter-spacing: -3% !important;
|
|
106
88
|
}
|
|
107
89
|
|
|
108
90
|
@include mobile {
|
|
109
91
|
font-size: 12px !important;
|
|
110
|
-
line-height:
|
|
111
|
-
letter-spacing: -
|
|
92
|
+
line-height: 16px !important;
|
|
93
|
+
letter-spacing: -3% !important;
|
|
112
94
|
}
|
|
113
95
|
}
|
|
114
96
|
|
|
@@ -121,14 +103,14 @@
|
|
|
121
103
|
font-weight: 600 !important;
|
|
122
104
|
font-size: 12px !important;
|
|
123
105
|
line-height: 16px !important;
|
|
124
|
-
letter-spacing: 0
|
|
106
|
+
letter-spacing: 0 !important;
|
|
125
107
|
}
|
|
126
108
|
|
|
127
109
|
@include mobile {
|
|
128
110
|
font-weight: 500 !important;
|
|
129
111
|
font-size: 10px !important;
|
|
130
112
|
line-height: 16px !important;
|
|
131
|
-
letter-spacing: 0
|
|
113
|
+
letter-spacing: 0 !important;
|
|
132
114
|
}
|
|
133
115
|
}
|
|
134
116
|
|
|
@@ -141,12 +123,12 @@
|
|
|
141
123
|
@include web {
|
|
142
124
|
font-size: 12px !important;
|
|
143
125
|
line-height: 16px !important;
|
|
144
|
-
letter-spacing: 0
|
|
126
|
+
letter-spacing: 0 !important;
|
|
145
127
|
}
|
|
146
128
|
|
|
147
129
|
@include mobile {
|
|
148
130
|
font-size: 10px !important;
|
|
149
131
|
line-height: 16px !important;
|
|
150
|
-
letter-spacing: 0
|
|
132
|
+
letter-spacing: 0 !important;
|
|
151
133
|
}
|
|
152
134
|
}
|