@bagelink/vue 0.0.464 → 0.0.471
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/components/Accordion.vue.d.ts.map +1 -1
- package/dist/components/AccordionItem.vue.d.ts.map +1 -1
- package/dist/components/Alert.vue.d.ts +2 -2
- package/dist/components/Alert.vue.d.ts.map +1 -1
- package/dist/components/Avatar.vue.d.ts.map +1 -1
- package/dist/components/Badge.vue.d.ts +2 -2
- package/dist/components/Badge.vue.d.ts.map +1 -1
- package/dist/components/BglVideo.vue.d.ts +2 -2
- package/dist/components/BglVideo.vue.d.ts.map +1 -1
- package/dist/components/Btn.vue.d.ts.map +1 -1
- package/dist/components/Card.vue.d.ts.map +1 -1
- package/dist/components/Carousel.vue.d.ts +4 -2
- package/dist/components/Carousel.vue.d.ts.map +1 -1
- package/dist/components/DataPreview.vue.d.ts.map +1 -1
- package/dist/components/Drop.vue.d.ts +34 -0
- package/dist/components/Drop.vue.d.ts.map +1 -0
- package/dist/components/FileUploader.vue.d.ts +60 -0
- package/dist/components/FileUploader.vue.d.ts.map +1 -0
- package/dist/components/Flag.vue.d.ts +2 -2
- package/dist/components/Flag.vue.d.ts.map +1 -1
- package/dist/components/ListItem.vue.d.ts.map +1 -1
- package/dist/components/ListView.vue.d.ts.map +1 -1
- package/dist/components/MapEmbed.vue.d.ts +2 -2
- package/dist/components/MapEmbed.vue.d.ts.map +1 -1
- package/dist/components/MaterialIcon.vue.d.ts.map +1 -1
- package/dist/components/Modal.vue.d.ts +2 -1
- package/dist/components/Modal.vue.d.ts.map +1 -1
- package/dist/components/ModalConfirm.vue.d.ts.map +1 -1
- package/dist/components/ModalForm.vue.d.ts.map +1 -1
- package/dist/components/NavBar.vue.d.ts.map +1 -1
- package/dist/components/PageTitle.vue.d.ts.map +1 -1
- package/dist/components/TableSchema.vue.d.ts.map +1 -1
- package/dist/components/Title.vue.d.ts.map +1 -1
- package/dist/components/dashboard/Lineart.vue.d.ts.map +1 -1
- package/dist/components/dashboard/index.d.ts.map +1 -1
- package/dist/components/form/BglField.vue.d.ts.map +1 -1
- package/dist/components/form/BglForm.vue.d.ts +4 -2
- package/dist/components/form/BglForm.vue.d.ts.map +1 -1
- package/dist/components/form/ItemRef.vue.d.ts +1 -0
- package/dist/components/form/ItemRef.vue.d.ts.map +1 -1
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/inputs/CheckInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/Checkbox.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/ColorPicker.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/FileUpload.vue.d.ts +2 -1
- package/dist/components/form/inputs/FileUpload.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/JSONInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RadioPillsInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectField.vue.d.ts +1 -4
- package/dist/components/form/inputs/SelectField.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SignaturePad.vue.d.ts +56 -0
- package/dist/components/form/inputs/SignaturePad.vue.d.ts.map +1 -0
- package/dist/components/form/inputs/TableField.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/TelInput.vue.d.ts +2 -2
- package/dist/components/form/inputs/TelInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/TextInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/ToggleInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/index.d.ts +1 -0
- package/dist/components/form/inputs/index.d.ts.map +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layout/BottomMenu.vue.d.ts.map +1 -1
- package/dist/components/layout/Layout.vue.d.ts +2 -2
- package/dist/components/layout/Layout.vue.d.ts.map +1 -1
- package/dist/components/layout/SidebarMenu.vue.d.ts.map +1 -1
- package/dist/components/layout/TabbedLayout.vue.d.ts.map +1 -1
- package/dist/components/layout/Tabs.vue.d.ts.map +1 -1
- package/dist/components/layout/TabsBody.vue.d.ts.map +1 -1
- package/dist/components/layout/TabsNav.vue.d.ts.map +1 -1
- package/dist/components/layout/index.d.ts.map +1 -1
- package/dist/index.cjs +17616 -20818
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +17616 -20818
- package/dist/plugins/bagel.d.ts +1 -1
- package/dist/plugins/bagel.d.ts.map +1 -1
- package/dist/plugins/modal.d.ts +14 -14
- package/dist/plugins/modal.d.ts.map +1 -1
- package/dist/style.css +330 -309
- package/dist/types/BagelForm.d.ts +16 -16
- package/dist/types/BagelForm.d.ts.map +1 -1
- package/dist/types/BtnOptions.d.ts +1 -1
- package/dist/types/BtnOptions.d.ts.map +1 -1
- package/dist/types/NavLink.d.ts +2 -2
- package/dist/types/NavLink.d.ts.map +1 -1
- package/dist/types/file.d.ts +2 -2
- package/dist/types/file.d.ts.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/materialIcons.d.ts.map +1 -1
- package/dist/utils/BagelFormUtils.d.ts.map +1 -1
- package/dist/utils/allCountries.d.ts +2 -2
- package/dist/utils/allCountries.d.ts.map +1 -1
- package/dist/utils/clickOutside.d.ts.map +1 -1
- package/dist/utils/index.d.ts +5 -5
- package/dist/utils/index.d.ts.map +1 -1
- package/package.json +19 -17
- package/src/components/Accordion.vue +10 -10
- package/src/components/AccordionItem.vue +47 -47
- package/src/components/Alert.vue +21 -21
- package/src/components/Avatar.vue +15 -15
- package/src/components/Badge.vue +17 -16
- package/src/components/BglVideo.vue +43 -43
- package/src/components/Btn.vue +64 -65
- package/src/components/Card.vue +26 -26
- package/src/components/Carousel.vue +130 -134
- package/src/components/DataPreview.vue +30 -30
- package/src/components/Flag.vue +26 -26
- package/src/components/ListItem.vue +13 -13
- package/src/components/ListView.vue +2 -2
- package/src/components/MapEmbed.vue +33 -33
- package/src/components/MaterialIcon.vue +12 -12
- package/src/components/Modal.vue +73 -66
- package/src/components/ModalConfirm.vue +18 -18
- package/src/components/ModalForm.vue +79 -76
- package/src/components/NavBar.vue +33 -30
- package/src/components/PageTitle.vue +10 -8
- package/src/components/TableSchema.vue +123 -113
- package/src/components/Title.vue +8 -8
- package/src/components/dashboard/Lineart.vue +103 -96
- package/src/components/dashboard/index.ts +1 -1
- package/src/components/form/BglField.vue +61 -61
- package/src/components/form/BglFieldSet.vue +9 -8
- package/src/components/form/BglForm.vue +71 -70
- package/src/components/form/index.ts +4 -4
- package/src/components/form/inputs/CheckInput.vue +25 -23
- package/src/components/form/inputs/Checkbox.vue +10 -10
- package/src/components/form/inputs/ColorPicker.vue +26 -24
- package/src/components/form/inputs/DateInput.vue +39 -39
- package/src/components/form/inputs/DatePicker.vue +37 -36
- package/src/components/form/inputs/FileUpload.vue +165 -161
- package/src/components/form/inputs/FileUploadURL.vue +134 -132
- package/src/components/form/inputs/JSONInput.vue +29 -29
- package/src/components/form/inputs/RadioPillsInput.vue +49 -49
- package/src/components/form/inputs/RichText.vue +62 -63
- package/src/components/form/inputs/SelectInput.vue +173 -167
- package/src/components/form/inputs/SignaturePad.vue +150 -0
- package/src/components/form/inputs/TableField.vue +77 -76
- package/src/components/form/inputs/TelInput.vue +280 -285
- package/src/components/form/inputs/TextInput.vue +81 -76
- package/src/components/form/inputs/ToggleInput.vue +13 -13
- package/src/components/form/inputs/index.ts +17 -15
- package/src/components/formkit/FileUploader.vue +162 -158
- package/src/components/formkit/MiscFields.vue +20 -20
- package/src/components/formkit/Toggle.vue +13 -13
- package/src/components/index.ts +28 -28
- package/src/components/layout/BottomMenu.vue +25 -21
- package/src/components/layout/Layout.vue +29 -29
- package/src/components/layout/SidebarMenu.vue +31 -27
- package/src/components/layout/TabbedLayout.vue +47 -45
- package/src/components/layout/Tabs.vue +32 -32
- package/src/components/layout/TabsBody.vue +10 -10
- package/src/components/layout/TabsNav.vue +44 -44
- package/src/components/layout/index.ts +7 -7
- package/src/components/layout/tabsManager.ts +6 -6
- package/src/index.ts +13 -8
- package/src/plugins/bagel.ts +37 -37
- package/src/plugins/modal.ts +66 -67
- package/src/styles/layout.css +5 -3
- package/src/styles/mobilLayout.css +7 -0
- package/src/types/BagelForm.ts +27 -27
- package/src/types/BtnOptions.ts +13 -13
- package/src/types/NavLink.ts +8 -8
- package/src/types/file.ts +11 -11
- package/src/types/index.ts +16 -12
- package/src/types/materialIcons.ts +3249 -3249
- package/src/utils/BagelFormUtils.ts +23 -23
- package/src/utils/allCountries.ts +11 -12
- package/src/utils/clickOutside.ts +6 -6
- package/src/utils/index.ts +39 -41
- package/src/utils/lang.ts +13 -13
- package/src/utils/strings.ts +9 -9
- package/tsconfig.json +0 -1
- package/vite.config.ts +8 -8
- package/dist/components/Popover.vue.d.ts +0 -10
- package/dist/components/Popover.vue.d.ts.map +0 -1
- package/dist/types/materialIcon.d.ts +0 -2
- package/dist/types/materialIcon.d.ts.map +0 -1
|
@@ -1,8 +1,82 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { onMounted, watch } from 'vue'
|
|
3
|
+
import {
|
|
4
|
+
MaterialIcon,
|
|
5
|
+
type MaterialIcons,
|
|
6
|
+
debounce,
|
|
7
|
+
} from '@bagelink/vue'
|
|
8
|
+
|
|
9
|
+
const props = withDefaults(
|
|
10
|
+
defineProps<{
|
|
11
|
+
id?: string
|
|
12
|
+
title?: string
|
|
13
|
+
helptext?: string
|
|
14
|
+
placeholder?: string
|
|
15
|
+
modelValue?: string | number
|
|
16
|
+
label?: string
|
|
17
|
+
small?: boolean
|
|
18
|
+
dense?: boolean
|
|
19
|
+
required?: boolean
|
|
20
|
+
pattern?: string
|
|
21
|
+
shrink?: boolean
|
|
22
|
+
disabled?: boolean
|
|
23
|
+
type?: string
|
|
24
|
+
nativeInputAttrs?: Record<string, any>
|
|
25
|
+
icon?: MaterialIcons
|
|
26
|
+
iconStart?: MaterialIcons
|
|
27
|
+
multiline?: boolean
|
|
28
|
+
autoheight?: boolean
|
|
29
|
+
code?: boolean
|
|
30
|
+
lines?: number
|
|
31
|
+
autocomplete?: AutoFillField
|
|
32
|
+
autofocus?: boolean
|
|
33
|
+
debounceDelay?: number
|
|
34
|
+
}>(),
|
|
35
|
+
{
|
|
36
|
+
type: 'text',
|
|
37
|
+
modelValue: '',
|
|
38
|
+
debounceDelay: 300,
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
const emit = defineEmits(['update:modelValue', 'debounce'])
|
|
42
|
+
let inputVal = $ref<string | number>()
|
|
43
|
+
|
|
44
|
+
const input = $ref<HTMLInputElement>()
|
|
45
|
+
|
|
46
|
+
const rows = $computed(() => {
|
|
47
|
+
if (props.lines) return props.lines
|
|
48
|
+
if (props.autoheight) return `${inputVal}`.split('\n').length || 1
|
|
49
|
+
if (props.multiline || props.code) return 4
|
|
50
|
+
return 1
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
function updateInputVal() {
|
|
54
|
+
if (props.disabled) return
|
|
55
|
+
emit('update:modelValue', inputVal as string)
|
|
56
|
+
debounce(() => { emit('debounce', inputVal) }, props.debounceDelay)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
watch(
|
|
60
|
+
() => props.modelValue,
|
|
61
|
+
(newVal) => {
|
|
62
|
+
if (newVal !== inputVal) inputVal = newVal
|
|
63
|
+
},
|
|
64
|
+
{ immediate: true },
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
onMounted(() => {
|
|
68
|
+
if (props.autofocus) setTimeout(() => input?.focus(), 10)
|
|
69
|
+
})
|
|
70
|
+
</script>
|
|
71
|
+
|
|
1
72
|
<template>
|
|
2
73
|
<div
|
|
3
74
|
class="bagel-input text-input"
|
|
4
75
|
:class="{
|
|
5
|
-
dense,
|
|
76
|
+
dense,
|
|
77
|
+
small,
|
|
78
|
+
shrink,
|
|
79
|
+
code,
|
|
6
80
|
textInputIconWrap: icon,
|
|
7
81
|
txtInputIconStart: iconStart,
|
|
8
82
|
}"
|
|
@@ -13,13 +87,13 @@
|
|
|
13
87
|
|
|
14
88
|
<input
|
|
15
89
|
v-if="!multiline && !autoheight && !code"
|
|
16
|
-
:title="title"
|
|
17
|
-
:autocomplete="autocomplete"
|
|
18
90
|
:id="id"
|
|
91
|
+
ref="input"
|
|
19
92
|
v-model="inputVal"
|
|
93
|
+
:title="title"
|
|
94
|
+
:autocomplete="autocomplete"
|
|
20
95
|
:type="type"
|
|
21
96
|
:rows="1"
|
|
22
|
-
ref="input"
|
|
23
97
|
:placeholder="placeholder || label"
|
|
24
98
|
:disabled
|
|
25
99
|
:required="required"
|
|
@@ -29,12 +103,12 @@
|
|
|
29
103
|
>
|
|
30
104
|
<textarea
|
|
31
105
|
v-else
|
|
32
|
-
:title="title"
|
|
33
106
|
:id="id"
|
|
107
|
+
ref="input"
|
|
34
108
|
v-model="inputVal"
|
|
109
|
+
:title="title"
|
|
35
110
|
:type="type"
|
|
36
111
|
:rows="rows"
|
|
37
|
-
ref="input"
|
|
38
112
|
:placeholder="placeholder || label"
|
|
39
113
|
:disabled
|
|
40
114
|
:required="required"
|
|
@@ -46,8 +120,8 @@
|
|
|
46
120
|
</label>
|
|
47
121
|
|
|
48
122
|
<MaterialIcon
|
|
49
|
-
class="iconStart"
|
|
50
123
|
v-if="iconStart"
|
|
124
|
+
class="iconStart"
|
|
51
125
|
:icon="iconStart"
|
|
52
126
|
/>
|
|
53
127
|
<MaterialIcon
|
|
@@ -57,75 +131,6 @@
|
|
|
57
131
|
</div>
|
|
58
132
|
</template>
|
|
59
133
|
|
|
60
|
-
<script setup lang="ts">
|
|
61
|
-
import { onMounted, watch } from 'vue';
|
|
62
|
-
import {
|
|
63
|
-
debounce, type MaterialIcons, MaterialIcon,
|
|
64
|
-
} from '@bagelink/vue';
|
|
65
|
-
|
|
66
|
-
const emit = defineEmits(['update:modelValue', 'debounce']);
|
|
67
|
-
const props = withDefaults(
|
|
68
|
-
defineProps<{
|
|
69
|
-
id?: string;
|
|
70
|
-
title?: string;
|
|
71
|
-
helptext?: string;
|
|
72
|
-
placeholder?: string;
|
|
73
|
-
modelValue?: string | number;
|
|
74
|
-
label?: string;
|
|
75
|
-
small?: boolean;
|
|
76
|
-
dense?: boolean;
|
|
77
|
-
required?: boolean;
|
|
78
|
-
pattern?: string;
|
|
79
|
-
shrink?: boolean;
|
|
80
|
-
disabled?: boolean;
|
|
81
|
-
type?: string;
|
|
82
|
-
nativeInputAttrs?: Record<string, any>;
|
|
83
|
-
icon?: MaterialIcons;
|
|
84
|
-
iconStart?: MaterialIcons;
|
|
85
|
-
multiline?: boolean;
|
|
86
|
-
autoheight?: boolean;
|
|
87
|
-
code?: boolean;
|
|
88
|
-
lines?: number;
|
|
89
|
-
autocomplete?: AutoFillField;
|
|
90
|
-
autofocus?: boolean;
|
|
91
|
-
debounceDelay?: number;
|
|
92
|
-
}>(),
|
|
93
|
-
{
|
|
94
|
-
type: 'text',
|
|
95
|
-
modelValue: '',
|
|
96
|
-
debounceDelay: 300,
|
|
97
|
-
},
|
|
98
|
-
);
|
|
99
|
-
let inputVal = $ref<string | number>();
|
|
100
|
-
|
|
101
|
-
const input = $ref<HTMLInputElement>();
|
|
102
|
-
|
|
103
|
-
const rows = $computed(() => {
|
|
104
|
-
if (props.lines) return props.lines;
|
|
105
|
-
if (props.autoheight) return `${inputVal}`?.split('\n').length || 1;
|
|
106
|
-
if (props.multiline || props.code) return 4;
|
|
107
|
-
return 1;
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
function updateInputVal() {
|
|
111
|
-
if (props.disabled) return;
|
|
112
|
-
emit('update:modelValue', inputVal as string);
|
|
113
|
-
debounce(() => emit('debounce', inputVal), props.debounceDelay);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
watch(
|
|
117
|
-
() => props.modelValue,
|
|
118
|
-
(newVal) => {
|
|
119
|
-
if (newVal !== inputVal) inputVal = newVal;
|
|
120
|
-
},
|
|
121
|
-
{ immediate: true },
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
onMounted(() => {
|
|
125
|
-
if (props.autofocus) setTimeout(() => input?.focus(), 10);
|
|
126
|
-
});
|
|
127
|
-
</script>
|
|
128
|
-
|
|
129
134
|
<style>
|
|
130
135
|
.bagel-input.shrink,
|
|
131
136
|
.bagel-input.shrink input {
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{
|
|
3
|
+
label: string
|
|
4
|
+
id?: string
|
|
5
|
+
title?: string
|
|
6
|
+
small?: boolean
|
|
7
|
+
}>()
|
|
8
|
+
|
|
9
|
+
const checked = defineModel<boolean>('modelValue', { default: false })
|
|
10
|
+
</script>
|
|
11
|
+
|
|
1
12
|
<template>
|
|
2
|
-
<div class="bagel-input bgl-checkbox justify-content-center gap-1" :title="title" :class="{ small
|
|
13
|
+
<div class="bagel-input bgl-checkbox justify-content-center gap-1" :title="title" :class="{ small }">
|
|
3
14
|
<div class="switch" :class="{ checked }">
|
|
4
15
|
<span class="slider round" />
|
|
5
16
|
</div>
|
|
6
17
|
<label>
|
|
7
18
|
{{ label }}
|
|
8
|
-
<input :id="id"
|
|
19
|
+
<input :id="id" v-model="checked" type="checkbox">
|
|
9
20
|
</label>
|
|
10
21
|
</div>
|
|
11
22
|
</template>
|
|
12
23
|
|
|
13
|
-
<script setup lang="ts">
|
|
14
|
-
defineProps<{
|
|
15
|
-
label: string;
|
|
16
|
-
id?: string;
|
|
17
|
-
title?: string;
|
|
18
|
-
small?: boolean;
|
|
19
|
-
}>();
|
|
20
|
-
|
|
21
|
-
const checked = defineModel<boolean>('modelValue', { default: false });
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
24
|
<style scoped>
|
|
25
25
|
.bgl-checkbox {
|
|
26
26
|
position: relative;
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
export { default as CheckInput } from './CheckInput.vue'
|
|
2
|
-
export { default as DateInput } from './DateInput.vue'
|
|
3
|
-
export { default as JSONInput } from './JSONInput.vue'
|
|
4
|
-
export { default as SelectInput } from './SelectInput.vue'
|
|
5
|
-
export { default as TableField } from './TableField.vue'
|
|
6
|
-
export { default as TextInput } from './TextInput.vue'
|
|
7
|
-
export { default as Checkbox } from './Checkbox.vue'
|
|
8
|
-
export { default as ColorPicker } from './ColorPicker.vue'
|
|
9
|
-
export { default as DatePicker } from './DatePicker.vue'
|
|
10
|
-
export { default as RadioPillsInput } from './RadioPillsInput.vue'
|
|
11
|
-
export { default as FileUpload } from './FileUpload.vue'
|
|
12
|
-
export { default as ToggleInput } from './ToggleInput.vue'
|
|
13
|
-
export { default as RichText } from './RichText.vue'
|
|
14
|
-
export { default as TelInput } from './TelInput.vue'
|
|
15
|
-
export {
|
|
1
|
+
export { default as CheckInput } from './CheckInput.vue'
|
|
2
|
+
export { default as DateInput } from './DateInput.vue'
|
|
3
|
+
export { default as JSONInput } from './JSONInput.vue'
|
|
4
|
+
export { default as SelectInput } from './SelectInput.vue'
|
|
5
|
+
export { default as TableField } from './TableField.vue'
|
|
6
|
+
export { default as TextInput } from './TextInput.vue'
|
|
7
|
+
export { default as Checkbox } from './Checkbox.vue'
|
|
8
|
+
export { default as ColorPicker } from './ColorPicker.vue'
|
|
9
|
+
export { default as DatePicker } from './DatePicker.vue'
|
|
10
|
+
export { default as RadioPillsInput } from './RadioPillsInput.vue'
|
|
11
|
+
export { default as FileUpload } from './FileUpload.vue'
|
|
12
|
+
export { default as ToggleInput } from './ToggleInput.vue'
|
|
13
|
+
export { default as RichText } from './RichText.vue'
|
|
14
|
+
export { default as TelInput } from './TelInput.vue'
|
|
15
|
+
export { default as SignaturePad } from './SignaturePad.vue'
|
|
16
|
+
|
|
17
|
+
export { Dropdown } from 'floating-vue'
|
|
@@ -1,3 +1,155 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
interface UploadFile {
|
|
3
|
+
dataUrl: string
|
|
4
|
+
progress: number
|
|
5
|
+
uploading: boolean
|
|
6
|
+
file?: File
|
|
7
|
+
name: string
|
|
8
|
+
serverFile?: any
|
|
9
|
+
uploaded: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
import { onMounted, onUnmounted } from 'vue'
|
|
13
|
+
|
|
14
|
+
import { Btn, MaterialIcon, useBagel } from '@bagelink/vue'
|
|
15
|
+
|
|
16
|
+
const props = withDefaults(
|
|
17
|
+
defineProps<{
|
|
18
|
+
context: Record<string, any>
|
|
19
|
+
dragDropLabel?: string
|
|
20
|
+
browseLabel?: string
|
|
21
|
+
multiple?: boolean
|
|
22
|
+
}>(),
|
|
23
|
+
{
|
|
24
|
+
dragDropLabel: 'Drag and drop your files here',
|
|
25
|
+
browseLabel: 'or browse',
|
|
26
|
+
multiple: false,
|
|
27
|
+
},
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
const bagel = useBagel()
|
|
31
|
+
|
|
32
|
+
let draggingOver = $ref(false)
|
|
33
|
+
const dropCircle = $ref<HTMLElement>()
|
|
34
|
+
const dropZoneEl = $ref<HTMLElement>()
|
|
35
|
+
const fileInputEl = $ref<HTMLInputElement>()
|
|
36
|
+
|
|
37
|
+
const files = $ref<UploadFile[]>([])
|
|
38
|
+
|
|
39
|
+
const computedDragDropLabel = $computed(() => props.context.attrs?.dragDropLabel || props.dragDropLabel)
|
|
40
|
+
const computedDrowseLabel = $computed(() => props.context.attrs?.browseLabel || props.browseLabel)
|
|
41
|
+
const computedMultiple = $computed(() => !!(props.context.attrs?.multiple || props.multiple))
|
|
42
|
+
|
|
43
|
+
const allowUpload = $computed(() => {
|
|
44
|
+
const tooManyFiles = !computedMultiple && files.length > 0
|
|
45
|
+
return !tooManyFiles
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const openFileDialog = () => (allowUpload ? fileInputEl?.click() : '')
|
|
49
|
+
|
|
50
|
+
function animateCircle(e: DragEvent) {
|
|
51
|
+
e.preventDefault()
|
|
52
|
+
const zoneRect = dropZoneEl?.getBoundingClientRect()
|
|
53
|
+
if (!zoneRect) return
|
|
54
|
+
draggingOver = true
|
|
55
|
+
const left = e.clientX - zoneRect.left
|
|
56
|
+
const top = e.clientY - zoneRect.top
|
|
57
|
+
dropCircle?.style.setProperty('left', `${left}px`)
|
|
58
|
+
dropCircle?.style.setProperty('top', `${top}px`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function emitValue() {
|
|
62
|
+
// const fileValues = files.map((f) => f.serverFile?.id);
|
|
63
|
+
const relationshipObjKey = props.context.attrs?.relationshipObjKey
|
|
64
|
+
if (!computedMultiple) return props.context.node.input(relationshipObjKey ? files[0].serverFile.id : files[0].serverFile)
|
|
65
|
+
// eslint-disable-next-line no-alert
|
|
66
|
+
alert('not implemented')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isImg(file: UploadFile) {
|
|
70
|
+
return file.file?.type.includes('image')
|
|
71
|
+
|| file.serverFile?.mimetype?.match(/image\/|jpg|png|gif|bmp|jpeg/i)
|
|
72
|
+
|| file.serverFile.extension?.match(/jpg|png|gif|bmp|jpeg/i)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function uploadFiles() {
|
|
76
|
+
files.forEach(async (file) => {
|
|
77
|
+
if (file.uploaded || file.uploading || !file.file) return
|
|
78
|
+
file.uploading = true
|
|
79
|
+
file.serverFile = await bagel.uploadFile(file.file, {
|
|
80
|
+
onUploadProgress: (e: any) => (file.progress = e.progress * 100 - 1),
|
|
81
|
+
})
|
|
82
|
+
file.progress += 1
|
|
83
|
+
emitValue()
|
|
84
|
+
file.uploaded = true
|
|
85
|
+
file.uploading = false
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function deleteImg(file: UploadFile) {
|
|
90
|
+
await bagel.delete(`files/${file.serverFile.id}`)
|
|
91
|
+
const index = files.indexOf(file)
|
|
92
|
+
files.splice(index, 1)
|
|
93
|
+
emitValue()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function readAsDataURL(file: File): Promise<any> {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
const reader = new FileReader()
|
|
99
|
+
reader.onload = () => { resolve(reader.result) }
|
|
100
|
+
reader.onerror = reject
|
|
101
|
+
reader.readAsDataURL(file)
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function addFiles(addedFiles: FileList) {
|
|
106
|
+
if (!allowUpload) return
|
|
107
|
+
for (let i = 0; i < addedFiles.length; i++) {
|
|
108
|
+
const f = addedFiles[i]
|
|
109
|
+
const file: UploadFile = {
|
|
110
|
+
// eslint-disable-next-line no-await-in-loop
|
|
111
|
+
dataUrl: await readAsDataURL(f),
|
|
112
|
+
file: f,
|
|
113
|
+
name: f.name,
|
|
114
|
+
progress: 0,
|
|
115
|
+
uploading: false,
|
|
116
|
+
uploaded: false,
|
|
117
|
+
}
|
|
118
|
+
files.push(file)
|
|
119
|
+
}
|
|
120
|
+
uploadFiles()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
onMounted(() => {
|
|
124
|
+
dropZoneEl?.addEventListener('dragover', animateCircle)
|
|
125
|
+
const relationshipObjKey = props.context.attrs?.relationshipObjKey
|
|
126
|
+
const imageObj = relationshipObjKey ? props.context.node?.parent?.value[relationshipObjKey] : props.context.node?.value
|
|
127
|
+
if (!computedMultiple && imageObj) {
|
|
128
|
+
files.push({
|
|
129
|
+
serverFile: imageObj,
|
|
130
|
+
uploaded: true,
|
|
131
|
+
uploading: false,
|
|
132
|
+
progress: 100,
|
|
133
|
+
dataUrl: imageObj?.url,
|
|
134
|
+
name: imageObj?.name,
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
onUnmounted(() => dropZoneEl?.removeEventListener('dragover', animateCircle))
|
|
139
|
+
|
|
140
|
+
function handleFileInput(e: Event) {
|
|
141
|
+
const filesToAdd: FileList = (e.target as any).files
|
|
142
|
+
void addFiles(filesToAdd) // TODO: Nati: should be awaited?
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function onDrop(e: DragEvent) {
|
|
146
|
+
draggingOver = false
|
|
147
|
+
e.preventDefault()
|
|
148
|
+
const filesToAdd = e.dataTransfer?.files
|
|
149
|
+
if (filesToAdd) void addFiles(filesToAdd) // TODO: Nati: should be awaited?
|
|
150
|
+
}
|
|
151
|
+
</script>
|
|
152
|
+
|
|
1
153
|
<template>
|
|
2
154
|
<div class="files-wrapper flex">
|
|
3
155
|
<div
|
|
@@ -9,14 +161,14 @@
|
|
|
9
161
|
>
|
|
10
162
|
<Transition name="pop">
|
|
11
163
|
<div
|
|
12
|
-
ref="dropCircle"
|
|
13
164
|
v-if="draggingOver"
|
|
165
|
+
ref="dropCircle"
|
|
14
166
|
class="drop-circle"
|
|
15
167
|
/>
|
|
16
168
|
</Transition>
|
|
17
169
|
<div
|
|
18
|
-
class="img-label"
|
|
19
170
|
v-if="allowUpload"
|
|
171
|
+
class="img-label"
|
|
20
172
|
>
|
|
21
173
|
<p>
|
|
22
174
|
{{ computedDragDropLabel }} <span>{{ computedDrowseLabel }}</span>
|
|
@@ -25,14 +177,14 @@
|
|
|
25
177
|
<div class="uploading-wrap">
|
|
26
178
|
<div
|
|
27
179
|
v-for="(item, index) in files"
|
|
28
|
-
:class="{ uploading: item.uploading }"
|
|
29
180
|
:key="index"
|
|
181
|
+
:class="{ uploading: item.uploading }"
|
|
30
182
|
>
|
|
31
183
|
<div class="load-file-bar">
|
|
32
184
|
<!-- Preview File if image -->
|
|
33
185
|
<img
|
|
34
|
-
width="40"
|
|
35
186
|
v-if="isImg(item)"
|
|
187
|
+
width="40"
|
|
36
188
|
:src="item.dataUrl"
|
|
37
189
|
:alt="item.name"
|
|
38
190
|
style="margin-inline-end: 10px"
|
|
@@ -48,8 +200,8 @@
|
|
|
48
200
|
:class="{ complete: item.progress === 100 }"
|
|
49
201
|
>
|
|
50
202
|
<span
|
|
51
|
-
class="progress"
|
|
52
203
|
v-if="item.progress < 100"
|
|
204
|
+
class="progress"
|
|
53
205
|
>{{
|
|
54
206
|
`${item.progress.toFixed(0)}`
|
|
55
207
|
}}</span>
|
|
@@ -59,11 +211,11 @@
|
|
|
59
211
|
/>
|
|
60
212
|
</div>
|
|
61
213
|
<Btn
|
|
214
|
+
v-if="item.progress === 100"
|
|
62
215
|
thin
|
|
63
216
|
class="delete-btn"
|
|
64
|
-
@click.stop="deleteImg(item)"
|
|
65
217
|
icon="delete"
|
|
66
|
-
|
|
218
|
+
@click.stop="deleteImg(item)"
|
|
67
219
|
/>
|
|
68
220
|
</div>
|
|
69
221
|
</div>
|
|
@@ -71,164 +223,15 @@
|
|
|
71
223
|
</div>
|
|
72
224
|
</div>
|
|
73
225
|
<input
|
|
226
|
+
ref="fileInputEl"
|
|
74
227
|
class="file-input"
|
|
75
228
|
type="file"
|
|
76
|
-
@change="handleFileInput"
|
|
77
|
-
ref="fileInputEl"
|
|
78
229
|
:multiple="computedMultiple"
|
|
230
|
+
@change="handleFileInput"
|
|
79
231
|
>
|
|
80
232
|
</div>
|
|
81
233
|
</template>
|
|
82
234
|
|
|
83
|
-
<script setup lang="ts">
|
|
84
|
-
interface UploadFile {
|
|
85
|
-
dataUrl: string;
|
|
86
|
-
progress: number;
|
|
87
|
-
uploading: boolean;
|
|
88
|
-
file?: File;
|
|
89
|
-
name: string;
|
|
90
|
-
serverFile?: any;
|
|
91
|
-
uploaded: boolean;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
import { onMounted, onUnmounted } from 'vue';
|
|
95
|
-
|
|
96
|
-
import { MaterialIcon, Btn, useBagel } from '@bagelink/vue';
|
|
97
|
-
|
|
98
|
-
const bagel = useBagel();
|
|
99
|
-
|
|
100
|
-
let draggingOver = $ref(false);
|
|
101
|
-
const dropCircle = $ref<HTMLElement>();
|
|
102
|
-
const dropZoneEl = $ref<HTMLElement>();
|
|
103
|
-
const fileInputEl = $ref<HTMLInputElement>();
|
|
104
|
-
|
|
105
|
-
const files = $ref<UploadFile[]>([]);
|
|
106
|
-
|
|
107
|
-
const props = withDefaults(
|
|
108
|
-
defineProps<{
|
|
109
|
-
context: Record<string, any>;
|
|
110
|
-
dragDropLabel?: string;
|
|
111
|
-
browseLabel?: string;
|
|
112
|
-
multiple?: boolean;
|
|
113
|
-
}>(),
|
|
114
|
-
{
|
|
115
|
-
dragDropLabel: 'Drag and drop your files here',
|
|
116
|
-
browseLabel: 'or browse',
|
|
117
|
-
multiple: false,
|
|
118
|
-
},
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
const computedDragDropLabel = $computed(() => props?.context?.attrs?.dragDropLabel || props?.dragDropLabel);
|
|
122
|
-
const computedDrowseLabel = $computed(() => props?.context?.attrs?.browseLabel || props?.browseLabel);
|
|
123
|
-
const computedMultiple = $computed(() => !!(props?.context?.attrs?.multiple || props?.multiple));
|
|
124
|
-
|
|
125
|
-
const allowUpload = $computed(() => {
|
|
126
|
-
const tooManyFiles = !computedMultiple && files.length > 0;
|
|
127
|
-
return !tooManyFiles;
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const openFileDialog = () => (allowUpload ? fileInputEl?.click() : '');
|
|
131
|
-
|
|
132
|
-
function animateCircle(e: DragEvent) {
|
|
133
|
-
e.preventDefault();
|
|
134
|
-
const zoneRect = dropZoneEl?.getBoundingClientRect?.();
|
|
135
|
-
if (!zoneRect) return;
|
|
136
|
-
draggingOver = true;
|
|
137
|
-
const left = e.clientX - zoneRect.left;
|
|
138
|
-
const top = e.clientY - zoneRect.top;
|
|
139
|
-
dropCircle?.style?.setProperty?.('left', `${left}px`);
|
|
140
|
-
dropCircle?.style?.setProperty?.('top', `${top}px`);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function emitValue() {
|
|
144
|
-
// const fileValues = files.map((f) => f.serverFile?.id);
|
|
145
|
-
const relationshipObjKey = props.context?.attrs?.relationshipObjKey;
|
|
146
|
-
if (!computedMultiple) return props.context?.node.input(relationshipObjKey ? files[0].serverFile.id : files[0].serverFile);
|
|
147
|
-
// eslint-disable-next-line no-alert
|
|
148
|
-
return alert('not implemented');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const isImg = (file: UploadFile) => file.file?.type.includes('image') ||
|
|
152
|
-
file.serverFile?.mimetype?.match(/image\/|jpg|png|gif|bmp|jpeg/i) ||
|
|
153
|
-
file.serverFile.extension?.match(/jpg|png|gif|bmp|jpeg/i);
|
|
154
|
-
|
|
155
|
-
function uploadFiles() {
|
|
156
|
-
files.forEach(async (file) => {
|
|
157
|
-
if (file.uploaded || file.uploading || !file.file) return;
|
|
158
|
-
file.uploading = true;
|
|
159
|
-
file.serverFile = await bagel.uploadFile(file.file, {
|
|
160
|
-
onUploadProgress: (e: any) => (file.progress = e.progress * 100 - 1),
|
|
161
|
-
});
|
|
162
|
-
file.progress += 1;
|
|
163
|
-
emitValue();
|
|
164
|
-
file.uploaded = true;
|
|
165
|
-
file.uploading = false;
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const deleteImg = async (file: UploadFile) => {
|
|
170
|
-
await bagel.delete(`files/${file.serverFile.id}`);
|
|
171
|
-
const index = files.indexOf(file);
|
|
172
|
-
files.splice(index, 1);
|
|
173
|
-
emitValue();
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
function readAsDataURL(file: File): Promise<any> {
|
|
177
|
-
return new Promise((resolve, reject) => {
|
|
178
|
-
const reader = new FileReader();
|
|
179
|
-
reader.onload = () => resolve(reader.result);
|
|
180
|
-
reader.onerror = reject;
|
|
181
|
-
reader.readAsDataURL(file);
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async function addFiles(addedFiles: FileList) {
|
|
186
|
-
if (!allowUpload) return;
|
|
187
|
-
for (let i = 0; i < addedFiles.length; i++) {
|
|
188
|
-
const f = addedFiles[i];
|
|
189
|
-
const file: UploadFile = {
|
|
190
|
-
// eslint-disable-next-line no-await-in-loop
|
|
191
|
-
dataUrl: await readAsDataURL(f),
|
|
192
|
-
file: f,
|
|
193
|
-
name: f.name,
|
|
194
|
-
progress: 0,
|
|
195
|
-
uploading: false,
|
|
196
|
-
uploaded: false,
|
|
197
|
-
};
|
|
198
|
-
files.push(file);
|
|
199
|
-
}
|
|
200
|
-
uploadFiles();
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
onMounted(() => {
|
|
204
|
-
dropZoneEl?.addEventListener('dragover', animateCircle);
|
|
205
|
-
const relationshipObjKey = props.context?.attrs?.relationshipObjKey;
|
|
206
|
-
const imageObj = relationshipObjKey ? props.context?.node?.parent?.value[relationshipObjKey] : props.context?.node?.value;
|
|
207
|
-
if (!computedMultiple && imageObj) {
|
|
208
|
-
files.push({
|
|
209
|
-
serverFile: imageObj,
|
|
210
|
-
uploaded: true,
|
|
211
|
-
uploading: false,
|
|
212
|
-
progress: 100,
|
|
213
|
-
dataUrl: imageObj?.url,
|
|
214
|
-
name: imageObj?.name,
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
onUnmounted(() => dropZoneEl?.removeEventListener('dragover', animateCircle));
|
|
219
|
-
|
|
220
|
-
function handleFileInput(e: Event) {
|
|
221
|
-
const filesToAdd: FileList = (e.target as any).files;
|
|
222
|
-
void addFiles(filesToAdd); // TODO: Nati: should be awaited?
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function onDrop(e: DragEvent) {
|
|
226
|
-
draggingOver = false;
|
|
227
|
-
e.preventDefault();
|
|
228
|
-
const filesToAdd = e.dataTransfer?.files;
|
|
229
|
-
if (filesToAdd) void addFiles(filesToAdd); // TODO: Nati: should be awaited?
|
|
230
|
-
}
|
|
231
|
-
</script>
|
|
232
235
|
<style>
|
|
233
236
|
.uploading-wrap {
|
|
234
237
|
width: 100%;
|
|
@@ -375,6 +378,7 @@ function onDrop(e: DragEvent) {
|
|
|
375
378
|
color: var(--bgl-green);
|
|
376
379
|
}
|
|
377
380
|
</style>
|
|
381
|
+
|
|
378
382
|
<style>
|
|
379
383
|
.pop-enter-active {
|
|
380
384
|
transition: scale 0.2s cubic-bezier(0.55, 0, 0.1, 1);
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { Btn } from '@bagelink/vue'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
context: Record<string, any>
|
|
6
|
+
addBtnLabel: string
|
|
7
|
+
}>()
|
|
8
|
+
|
|
9
|
+
const fields = $computed(() => props.context.node?.parent?.children || [])
|
|
10
|
+
|
|
11
|
+
function addToField(field: any) {
|
|
12
|
+
field.input([{}])
|
|
13
|
+
console.log(fields)
|
|
14
|
+
}
|
|
15
|
+
</script>
|
|
16
|
+
|
|
1
17
|
<template>
|
|
2
18
|
<div class="misc-wrap">
|
|
3
19
|
<Btn
|
|
4
|
-
class="add-btn"
|
|
5
|
-
color="gray"
|
|
6
|
-
flat
|
|
7
|
-
@click="addToField(field)"
|
|
8
20
|
v-for="(field, i) in fields.filter(
|
|
9
21
|
(field: any) => field.value?.length === 0,
|
|
10
22
|
)"
|
|
11
23
|
:key="i"
|
|
24
|
+
class="add-btn"
|
|
25
|
+
color="gray"
|
|
26
|
+
flat
|
|
12
27
|
thin
|
|
28
|
+
@click="addToField(field)"
|
|
13
29
|
>
|
|
14
30
|
{{ addBtnLabel }} {{ field.context?.label }}
|
|
15
31
|
</Btn>
|
|
16
32
|
</div>
|
|
17
33
|
</template>
|
|
18
34
|
|
|
19
|
-
<script lang="ts" setup>
|
|
20
|
-
import { Btn } from '@bagelink/vue';
|
|
21
|
-
|
|
22
|
-
const props = defineProps<{
|
|
23
|
-
context: Record<string, any>;
|
|
24
|
-
addBtnLabel: string;
|
|
25
|
-
}>();
|
|
26
|
-
|
|
27
|
-
const fields = $computed(() => props.context?.node?.parent?.children || []);
|
|
28
|
-
|
|
29
|
-
const addToField = (field: any) => {
|
|
30
|
-
field.input([{}]);
|
|
31
|
-
console.log(fields);
|
|
32
|
-
};
|
|
33
|
-
</script>
|
|
34
|
-
|
|
35
35
|
<style scoped>
|
|
36
36
|
.misc-wrap {
|
|
37
37
|
display: flex;
|