@ulu/frontend-vue 0.1.0-beta.17 → 0.1.0-beta.19
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/dist/{breakpoints-Cd3pu0Is.js → breakpoints-yajtVs6n.js} +1 -1
- package/dist/frontend-vue.js +7 -6
- package/dist/{index-Cdy3vpXx.js → index-RLrfaaN1.js} +1677 -1593
- package/lib/components/elements/UluBadge.vue +27 -28
- package/lib/components/elements/UluBadgeStack.vue +8 -13
- package/lib/components/elements/UluDefinitionList.vue +14 -17
- package/lib/components/elements/UluExternalLink.vue +21 -27
- package/lib/components/elements/UluIcon.vue +11 -1
- package/lib/components/elements/UluList.vue +53 -55
- package/lib/components/elements/UluSpokeSpinner.vue +12 -18
- package/lib/components/elements/UluTag.vue +35 -35
- package/lib/components/forms/UluCheckboxMenu.vue +32 -31
- package/lib/components/forms/UluFileDisplay.vue +40 -31
- package/lib/components/forms/UluFormFile.vue +22 -24
- package/lib/components/forms/UluFormMessage.vue +7 -10
- package/lib/components/forms/UluFormSelect.vue +16 -16
- package/lib/components/forms/UluFormText.vue +15 -15
- package/lib/components/forms/UluSearchForm.vue +8 -10
- package/lib/components/navigation/UluMenu.vue +2 -2
- package/lib/components/systems/scroll-anchors/UluScrollAnchors.vue +2 -1
- package/lib/components/systems/slider/UluImageSlideShow.vue +1 -1
- package/lib/components/systems/slider/UluSlideShow.vue +8 -3
- package/lib/components/systems/table-sticky/UluTableSticky.vue +7 -7
- package/lib/components/systems/table-sticky/UluTableStickyTable.vue +3 -3
- package/lib/index.js +1 -0
- package/lib/plugins/core/index.js +4 -1
- package/lib/plugins/toast/UluToast.vue +1 -1
- package/lib/utils/index.js +2 -0
- package/lib/utils/{vue-router.js → router.js} +46 -11
- package/package.json +7 -8
- package/types/index.d.ts +1 -0
- package/types/plugins/core/index.d.ts.map +1 -1
- package/types/utils/index.d.ts +3 -0
- package/types/utils/index.d.ts.map +1 -0
- package/types/utils/router.d.ts +126 -0
- package/types/utils/router.d.ts.map +1 -0
- package/lib/utils/placeholder.js +0 -6
|
@@ -26,33 +26,32 @@
|
|
|
26
26
|
</component>
|
|
27
27
|
</template>
|
|
28
28
|
|
|
29
|
-
<script>
|
|
29
|
+
<script setup>
|
|
30
|
+
import { computed } from "vue";
|
|
30
31
|
import { RouterLink } from "vue-router";
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
};
|
|
32
|
+
|
|
33
|
+
const props = defineProps({
|
|
34
|
+
skeleton: Boolean,
|
|
35
|
+
size: String,
|
|
36
|
+
text: String,
|
|
37
|
+
alt: String,
|
|
38
|
+
type: String,
|
|
39
|
+
click: Function,
|
|
40
|
+
to: [Object, String],
|
|
41
|
+
href: String,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const isInteractive = computed(() => {
|
|
45
|
+
return Boolean(props.to || props.click);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const element = computed(() => {
|
|
49
|
+
const { click, to, href } = props;
|
|
50
|
+
/* eslint-disable */
|
|
51
|
+
return click ? "button" :
|
|
52
|
+
to ? RouterLink :
|
|
53
|
+
href ? "a" :
|
|
54
|
+
"span";
|
|
55
|
+
/* eslint-enable */
|
|
56
|
+
});
|
|
58
57
|
</script>
|
|
@@ -10,18 +10,13 @@
|
|
|
10
10
|
</ul>
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
|
-
<script>
|
|
13
|
+
<script setup>
|
|
14
14
|
import UluBadge from "./UluBadge.vue";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* Array of props for each badge
|
|
23
|
-
*/
|
|
24
|
-
items: Array
|
|
25
|
-
}
|
|
26
|
-
}
|
|
15
|
+
|
|
16
|
+
defineProps({
|
|
17
|
+
/**
|
|
18
|
+
* Array of props for each badge
|
|
19
|
+
*/
|
|
20
|
+
items: Array
|
|
21
|
+
});
|
|
27
22
|
</script>
|
|
@@ -19,22 +19,19 @@
|
|
|
19
19
|
</dl>
|
|
20
20
|
</template>
|
|
21
21
|
|
|
22
|
-
<script>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
type: Object,
|
|
36
|
-
default: () => ({})
|
|
37
|
-
}
|
|
22
|
+
<script setup>
|
|
23
|
+
defineProps({
|
|
24
|
+
/**
|
|
25
|
+
* Array of term, and description (props in object)
|
|
26
|
+
* - Can use slots also
|
|
27
|
+
*/
|
|
28
|
+
items: Array,
|
|
29
|
+
/**
|
|
30
|
+
* Classes object for different elements { list, item, term, description }
|
|
31
|
+
*/
|
|
32
|
+
classes: {
|
|
33
|
+
type: Object,
|
|
34
|
+
default: () => ({})
|
|
38
35
|
}
|
|
39
|
-
};
|
|
36
|
+
});
|
|
40
37
|
</script>
|
|
@@ -10,37 +10,31 @@
|
|
|
10
10
|
</a>
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
|
-
<script>
|
|
13
|
+
<script setup>
|
|
14
14
|
import UluIcon from "./UluIcon.vue";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Component for external links (adds icon after link text)
|
|
18
18
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
defineProps({
|
|
20
|
+
/**
|
|
21
|
+
* Text for link or use slot
|
|
22
|
+
*/
|
|
23
|
+
text: String,
|
|
24
|
+
/**
|
|
25
|
+
* Link href
|
|
26
|
+
*/
|
|
27
|
+
href: String,
|
|
28
|
+
/**
|
|
29
|
+
* Link target
|
|
30
|
+
*/
|
|
31
|
+
target: {
|
|
32
|
+
type: String,
|
|
33
|
+
default: "_blank"
|
|
23
34
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Link href
|
|
31
|
-
*/
|
|
32
|
-
href: String,
|
|
33
|
-
/**
|
|
34
|
-
* Link target
|
|
35
|
-
*/
|
|
36
|
-
target: {
|
|
37
|
-
type: String,
|
|
38
|
-
default: "_blank"
|
|
39
|
-
},
|
|
40
|
-
/**
|
|
41
|
-
* Override default icon
|
|
42
|
-
*/
|
|
43
|
-
icon: String
|
|
44
|
-
}
|
|
45
|
-
};
|
|
35
|
+
/**
|
|
36
|
+
* Override default icon
|
|
37
|
+
*/
|
|
38
|
+
icon: String
|
|
39
|
+
});
|
|
46
40
|
</script>
|
|
@@ -3,15 +3,17 @@
|
|
|
3
3
|
v-if="customIconComponent"
|
|
4
4
|
:is="customIconComponent"
|
|
5
5
|
v-bind="customIconProps"
|
|
6
|
+
:class="commonClasses"
|
|
6
7
|
/>
|
|
7
8
|
<component
|
|
8
9
|
v-else-if="!useStaticFa && faIconComponent && resolvedDefinition"
|
|
9
10
|
:is="faIconComponent"
|
|
10
11
|
v-bind="iconProps"
|
|
12
|
+
:class="commonClasses"
|
|
11
13
|
/>
|
|
12
14
|
<span
|
|
13
15
|
v-else-if="useStaticFa && resolvedDefinition"
|
|
14
|
-
:class="staticIconClasses"
|
|
16
|
+
:class="[staticIconClasses, commonClasses]"
|
|
15
17
|
aria-hidden="true"
|
|
16
18
|
></span>
|
|
17
19
|
</template>
|
|
@@ -32,6 +34,10 @@
|
|
|
32
34
|
* - This will override the 'type' prop if both are provided
|
|
33
35
|
*/
|
|
34
36
|
icon: [String, Array, Object, Boolean],
|
|
37
|
+
/**
|
|
38
|
+
* Whether the icon should use flow inline
|
|
39
|
+
*/
|
|
40
|
+
spaced: Boolean
|
|
35
41
|
});
|
|
36
42
|
|
|
37
43
|
const useStaticFa = computed(() => {
|
|
@@ -76,6 +82,10 @@
|
|
|
76
82
|
return getClassesFromDefinition(resolvedDefinition.value);
|
|
77
83
|
});
|
|
78
84
|
|
|
85
|
+
const commonClasses = computed(() => ({
|
|
86
|
+
'flow-inline': props.spaced
|
|
87
|
+
}));
|
|
88
|
+
|
|
79
89
|
// Watch for changes to prop
|
|
80
90
|
// - Use watchEffect because we are watching reactive object property access (props)
|
|
81
91
|
// - Load FA if needed (so it's not included if it's unneeded)
|
|
@@ -28,60 +28,58 @@
|
|
|
28
28
|
</component>
|
|
29
29
|
</template>
|
|
30
30
|
|
|
31
|
-
<script>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
/**
|
|
48
|
-
* Use list-ordered class, and sets element to <ol>
|
|
49
|
-
*/
|
|
50
|
-
ordered: Boolean,
|
|
51
|
-
/**
|
|
52
|
-
* Use list-unordered class
|
|
53
|
-
*/
|
|
54
|
-
unordered: Boolean,
|
|
55
|
-
/**
|
|
56
|
-
* Use list-lines class
|
|
57
|
-
*/
|
|
58
|
-
lines: Boolean,
|
|
59
|
-
/**
|
|
60
|
-
* Use list-compact class
|
|
61
|
-
*/
|
|
62
|
-
compact: Boolean,
|
|
63
|
-
/**
|
|
64
|
-
* If setting up custom ordered list this will ensure the correct element type
|
|
65
|
-
* - Note: 'ordered' prop sets the ordered list class, this does not
|
|
66
|
-
*/
|
|
67
|
-
forceOrdered: Boolean,
|
|
68
|
-
/**
|
|
69
|
-
* Define the start value for <ol>
|
|
70
|
-
*/
|
|
71
|
-
start: String,
|
|
72
|
-
/**
|
|
73
|
-
* Reverse ordered list
|
|
74
|
-
*/
|
|
75
|
-
reversed: Boolean,
|
|
76
|
-
/**
|
|
77
|
-
* Define list style type (ie. disc, decimal, etc)
|
|
78
|
-
*/
|
|
79
|
-
listStyleType: String,
|
|
31
|
+
<script setup>
|
|
32
|
+
import { computed } from "vue";
|
|
33
|
+
|
|
34
|
+
const props = defineProps({
|
|
35
|
+
/**
|
|
36
|
+
* Array of list items, output as is or use slot to template the item
|
|
37
|
+
*/
|
|
38
|
+
items: Array,
|
|
39
|
+
/**
|
|
40
|
+
* Classes object (keys are list and listItem to be applied to <ul> and <li>)
|
|
41
|
+
* - Any valid class binding for each
|
|
42
|
+
*/
|
|
43
|
+
classes: {
|
|
44
|
+
type: Object,
|
|
45
|
+
default: () => ({})
|
|
80
46
|
},
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Use list-ordered class, and sets element to <ol>
|
|
49
|
+
*/
|
|
50
|
+
ordered: Boolean,
|
|
51
|
+
/**
|
|
52
|
+
* Use list-unordered class
|
|
53
|
+
*/
|
|
54
|
+
unordered: Boolean,
|
|
55
|
+
/**
|
|
56
|
+
* Use list-lines class
|
|
57
|
+
*/
|
|
58
|
+
lines: Boolean,
|
|
59
|
+
/**
|
|
60
|
+
* Use list-compact class
|
|
61
|
+
*/
|
|
62
|
+
compact: Boolean,
|
|
63
|
+
/**
|
|
64
|
+
* If setting up custom ordered list this will ensure the correct element type
|
|
65
|
+
* - Note: 'ordered' prop sets the ordered list class, this does not
|
|
66
|
+
*/
|
|
67
|
+
forceOrdered: Boolean,
|
|
68
|
+
/**
|
|
69
|
+
* Define the start value for <ol>
|
|
70
|
+
*/
|
|
71
|
+
start: String,
|
|
72
|
+
/**
|
|
73
|
+
* Reverse ordered list
|
|
74
|
+
*/
|
|
75
|
+
reversed: Boolean,
|
|
76
|
+
/**
|
|
77
|
+
* Define list style type (ie. disc, decimal, etc)
|
|
78
|
+
*/
|
|
79
|
+
listStyleType: String,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const listElement = computed(() => {
|
|
83
|
+
return props.ordered || props.forceOrdered ? "ol" : "ul";
|
|
84
|
+
});
|
|
87
85
|
</script>
|
|
@@ -1,25 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="spoke-spinner"
|
|
4
|
+
:class="{ [`spoke-spinner--${ type }`] : type }"
|
|
5
|
+
>
|
|
3
6
|
<div class="spoke-spinner__spinner">
|
|
4
|
-
<div></div
|
|
7
|
+
<div v-for="n in 12" :key="n"></div>
|
|
5
8
|
</div>
|
|
6
9
|
</div>
|
|
7
10
|
</template>
|
|
8
11
|
|
|
9
|
-
<script>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
type: String
|
|
17
|
-
},
|
|
18
|
-
computed: {
|
|
19
|
-
modifierClass() {
|
|
20
|
-
const { type } = this;
|
|
21
|
-
return type ? `spoke-spinner--${ type }` : null;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
};
|
|
12
|
+
<script setup>
|
|
13
|
+
const props = defineProps({
|
|
14
|
+
/**
|
|
15
|
+
* Type modifier for spinner (ie match scss style name)
|
|
16
|
+
*/
|
|
17
|
+
type: String
|
|
18
|
+
});
|
|
25
19
|
</script>
|
|
@@ -3,51 +3,51 @@
|
|
|
3
3
|
class="tag"
|
|
4
4
|
:class="[
|
|
5
5
|
{
|
|
6
|
-
'tag--
|
|
7
|
-
|
|
6
|
+
'tag--counter' : counter,
|
|
7
|
+
[`tag--${ size }`] : size,
|
|
8
8
|
[`tag--${ type }`] : type
|
|
9
9
|
},
|
|
10
10
|
resolvedModifiers
|
|
11
11
|
]"
|
|
12
12
|
>
|
|
13
|
-
<UluIcon v-if="icon" :icon="icon" />
|
|
13
|
+
<UluIcon v-if="icon" :icon="icon" spaced />
|
|
14
14
|
<slot>
|
|
15
|
-
{{ text }}
|
|
15
|
+
<span>{{ text }}</span>
|
|
16
16
|
</slot>
|
|
17
17
|
</span>
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
|
-
<script>
|
|
20
|
+
<script setup>
|
|
21
21
|
import UluIcon from "./UluIcon.vue";
|
|
22
22
|
import { useModifiers } from "../../composables/useModifiers.js";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
};
|
|
23
|
+
|
|
24
|
+
const props = defineProps({
|
|
25
|
+
/**
|
|
26
|
+
* Type (corresponds with styles setup for tag in scss module)
|
|
27
|
+
*/
|
|
28
|
+
type: [String],
|
|
29
|
+
/**
|
|
30
|
+
* Size (corresponds with sizes setup for tag in scss module)
|
|
31
|
+
*/
|
|
32
|
+
size: String,
|
|
33
|
+
/**
|
|
34
|
+
* Use counter style (for numbers, etc)
|
|
35
|
+
*/
|
|
36
|
+
counter: Boolean,
|
|
37
|
+
/**
|
|
38
|
+
* Text for tag, or use slot
|
|
39
|
+
*/
|
|
40
|
+
text: [String, Number],
|
|
41
|
+
/**
|
|
42
|
+
* Icon prop, if used will set the icon for the button, will use UluIcon (which uses font-awesome icons conditionally)
|
|
43
|
+
* - If using custom icons use slot instead
|
|
44
|
+
*/
|
|
45
|
+
icon: [String, Array],
|
|
46
|
+
/**
|
|
47
|
+
* Modifiers for tag class
|
|
48
|
+
*/
|
|
49
|
+
modifiers: [String, Array]
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const { resolvedModifiers } = useModifiers({ props, baseClass: "tag" });
|
|
53
53
|
</script>
|
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
2
|
+
<div class="menu-stack form-theme">
|
|
3
|
+
<ul class="menu-stack__list">
|
|
4
|
+
<li
|
|
5
|
+
class="menu-stack__item"
|
|
6
|
+
v-for="(option, index) in options"
|
|
7
|
+
:key="index"
|
|
8
|
+
>
|
|
9
|
+
<div class="menu-stack__selectable">
|
|
10
|
+
<input
|
|
11
|
+
type="checkbox"
|
|
12
|
+
:id="getId(index)"
|
|
13
|
+
v-model="option.checked"
|
|
14
|
+
>
|
|
15
|
+
<label :for="getId(index)">
|
|
16
|
+
<slot>
|
|
17
|
+
{{ option?.title || option?.text }}
|
|
18
|
+
</slot>
|
|
19
|
+
</label>
|
|
20
|
+
</div>
|
|
21
|
+
</li>
|
|
22
|
+
</ul>
|
|
23
|
+
</div>
|
|
22
24
|
</template>
|
|
23
25
|
|
|
24
|
-
<script>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
26
|
+
<script setup>
|
|
27
|
+
defineProps({
|
|
28
|
+
/**
|
|
29
|
+
* Checkbox items in [{ title|text, checked }, ...]
|
|
30
|
+
*/
|
|
31
|
+
options: Array
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const getId = (index) => {
|
|
35
|
+
return `checkbox-menu-opt-${ index }`;
|
|
35
36
|
};
|
|
36
37
|
</script>
|
|
@@ -1,39 +1,48 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<a class="layout-flex-baseline" :href="fileUrl" :download="file.name">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
<slot :fileName="file.name" :fileSize="fileSize">
|
|
4
|
+
<UluIcon class="ui-icon" :icon="icon"/>
|
|
5
|
+
<span class="margin-left-small-x">
|
|
6
|
+
{{ file.name }}
|
|
7
|
+
<UluTag v-if="!noFileSize" :text="fileSize" small outline />
|
|
8
|
+
</span>
|
|
9
|
+
</slot>
|
|
8
10
|
</a>
|
|
9
11
|
</template>
|
|
10
12
|
|
|
11
|
-
<script>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
<script setup>
|
|
14
|
+
import { computed } from "vue";
|
|
15
|
+
import UluIcon from "../elements/UluIcon.vue";
|
|
16
|
+
import UluTag from "../elements/UluTag.vue";
|
|
17
|
+
|
|
18
|
+
const props = defineProps({
|
|
19
|
+
file: {
|
|
20
|
+
required: true,
|
|
21
|
+
type: Object,
|
|
19
22
|
},
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
},
|
|
24
|
-
fileSize() {
|
|
25
|
-
const { size } = this.file;
|
|
26
|
-
const Mbs = size / 1000000;
|
|
27
|
-
const Kbs = size / 1000;
|
|
28
|
-
const format = n => parseFloat(n.toFixed(2));
|
|
29
|
-
// Either display Mbs or Kbs if less than 1 Mb
|
|
30
|
-
/* eslint-disable */
|
|
31
|
-
return Mbs > 1 ?
|
|
32
|
-
`${ format(Mbs) }Mb` : Kbs > 1 ?
|
|
33
|
-
`${ format(Kbs) }Kb` :
|
|
34
|
-
`${ format(size) }B`;
|
|
35
|
-
/* eslint-enable */
|
|
36
|
-
}
|
|
23
|
+
icon: {
|
|
24
|
+
type: String,
|
|
25
|
+
default: "type:file"
|
|
37
26
|
},
|
|
38
|
-
|
|
27
|
+
noFileSize: Boolean
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const fileUrl = computed(() => {
|
|
31
|
+
if (typeof window === 'undefined') return '';
|
|
32
|
+
return window.URL.createObjectURL(props.file);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const fileSize = computed(() => {
|
|
36
|
+
const { size } = props.file;
|
|
37
|
+
const Mbs = size / 1000000;
|
|
38
|
+
const Kbs = size / 1000;
|
|
39
|
+
const format = n => parseFloat(n.toFixed(2));
|
|
40
|
+
// Either display Mbs or Kbs if less than 1 Mb
|
|
41
|
+
/* eslint-disable */
|
|
42
|
+
return Mbs > 1 ?
|
|
43
|
+
`${ format(Mbs) }Mb` : Kbs > 1 ?
|
|
44
|
+
`${ format(Kbs) }Kb` :
|
|
45
|
+
`${ format(size) }B`;
|
|
46
|
+
/* eslint-enable */
|
|
47
|
+
});
|
|
39
48
|
</script>
|
|
@@ -18,30 +18,28 @@
|
|
|
18
18
|
</div>
|
|
19
19
|
</template>
|
|
20
20
|
|
|
21
|
-
<script>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
noClasses: Boolean,
|
|
32
|
-
multiple: Boolean,
|
|
33
|
-
inputAttrs: Object
|
|
34
|
-
},
|
|
35
|
-
emits: ["filesChange"],
|
|
36
|
-
data() {
|
|
37
|
-
return {
|
|
38
|
-
id: `file-input-id-${ ++count }`
|
|
39
|
-
};
|
|
21
|
+
<script setup>
|
|
22
|
+
const getNextId = (() => {
|
|
23
|
+
let count = 0;
|
|
24
|
+
return () => `file-input-id-${++count}`;
|
|
25
|
+
})();
|
|
26
|
+
|
|
27
|
+
defineProps({
|
|
28
|
+
label: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: "Select File"
|
|
40
31
|
},
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
labelHidden: Boolean,
|
|
33
|
+
noClasses: Boolean,
|
|
34
|
+
multiple: Boolean,
|
|
35
|
+
inputAttrs: Object
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const emit = defineEmits(["file-change"]);
|
|
39
|
+
|
|
40
|
+
const id = getNextId();
|
|
41
|
+
|
|
42
|
+
const onChangeFile = (event) => {
|
|
43
|
+
emit("file-change", event.target.files);
|
|
46
44
|
};
|
|
47
45
|
</script>
|