@bagelink/vue 0.0.346 → 0.0.350
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/Btn.vue.d.ts.map +1 -1
- package/dist/components/Carousel.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.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/index.cjs +57 -35
- package/dist/index.mjs +57 -35
- package/dist/style.css +389 -140
- package/dist/types/materialIcons.d.ts +1 -1
- package/dist/types/materialIcons.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Btn.vue +63 -56
- package/src/components/Carousel.vue +157 -141
- package/src/components/RouterWrapper.vue +2 -2
- package/src/components/form/inputs/SelectInput.vue +181 -123
- package/src/components/form/inputs/index.ts +1 -0
- package/src/styles/buttons.css +8 -0
- package/src/styles/layout.css +38 -2
- package/src/styles/mobilLayout.css +37 -0
- package/src/styles/text.css +191 -4
- package/src/types/materialIcons.ts +2 -0
|
@@ -1,53 +1,89 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
2
|
+
<Dropdown
|
|
3
|
+
@hide="updateOpen(false)"
|
|
4
|
+
ref="dropdown"
|
|
5
|
+
placement="bottom-start"
|
|
6
|
+
class="bagel-input selectinput"
|
|
7
|
+
>
|
|
8
|
+
<label>
|
|
9
|
+
{{ label }}
|
|
10
|
+
<button
|
|
11
|
+
@click="updateOpen(true)"
|
|
12
|
+
:disabled="disabled"
|
|
13
|
+
type="button"
|
|
14
|
+
class="selectinput-btn"
|
|
15
|
+
:class="{isEmpty: selectedItems.length ===0}"
|
|
16
|
+
>
|
|
17
|
+
<p>{{ selectedLabel }}</p>
|
|
18
|
+
<Icon v-bind="{ icon: open ? 'unfold_less' : 'unfold_more' }" />
|
|
19
|
+
</button>
|
|
20
|
+
<input
|
|
21
|
+
style="width: 0; height: 0; position: absolute; opacity: 0; z-index: -1"
|
|
22
|
+
v-if="required"
|
|
23
|
+
v-model="selectedItems"
|
|
24
|
+
required
|
|
25
|
+
>
|
|
26
|
+
</label>
|
|
27
|
+
<template #popper="{ hide }">
|
|
28
|
+
<Card
|
|
29
|
+
class="selectinput-options p-05"
|
|
30
|
+
:style="{ width: fullWidth ? '100%' : 'auto' }"
|
|
31
|
+
>
|
|
32
|
+
<TextInput
|
|
33
|
+
v-if="searchable"
|
|
34
|
+
ref="searchInput"
|
|
35
|
+
dense
|
|
36
|
+
:placeholder="'Search'"
|
|
37
|
+
icon="search"
|
|
38
|
+
v-model="search"
|
|
39
|
+
/>
|
|
40
|
+
<div
|
|
41
|
+
class="selectinput-option hover gap-1"
|
|
42
|
+
v-for="(option, i) in filteredOptions"
|
|
43
|
+
:key="`${option}${i}`"
|
|
44
|
+
@click="select(option)"
|
|
45
|
+
:class="{ selected: isSelected(option) }"
|
|
46
|
+
>
|
|
47
|
+
<Icon v-if="isSelected(option)" icon="check" />
|
|
48
|
+
<Icon
|
|
49
|
+
class="opacity-3"
|
|
50
|
+
v-if="!isSelected(option)"
|
|
51
|
+
icon="fiber_manual_record"
|
|
52
|
+
/>
|
|
53
|
+
<span>
|
|
54
|
+
{{ getLabel(option) }}
|
|
55
|
+
</span>
|
|
56
|
+
</div>
|
|
57
|
+
<slot name="last" />
|
|
58
|
+
</Card>
|
|
59
|
+
</template>
|
|
60
|
+
</Dropdown>
|
|
27
61
|
</template>
|
|
28
62
|
|
|
29
63
|
<script lang="ts" setup>
|
|
30
64
|
import { watch } from 'vue';
|
|
31
65
|
import { Dropdown } from 'floating-vue';
|
|
32
66
|
import 'floating-vue/style.css';
|
|
33
|
-
import {
|
|
34
|
-
TextInput, Card, Icon,
|
|
35
|
-
} from '@bagelink/vue';
|
|
67
|
+
import { TextInput, Card, Icon } from '@bagelink/vue';
|
|
36
68
|
|
|
37
|
-
type Option =
|
|
69
|
+
type Option =
|
|
70
|
+
| string
|
|
71
|
+
| number
|
|
72
|
+
| Record<string, any>
|
|
73
|
+
| { label: string; value: string | number };
|
|
38
74
|
|
|
39
75
|
const searchInput = $ref<HTMLInputElement | null>(null);
|
|
40
76
|
|
|
41
77
|
const props = defineProps<{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
78
|
+
options: Option[];
|
|
79
|
+
placeholder?: string;
|
|
80
|
+
disabled?: boolean;
|
|
81
|
+
modelValue?: Option;
|
|
82
|
+
searchable?: boolean;
|
|
83
|
+
required?: boolean;
|
|
84
|
+
label?: string;
|
|
85
|
+
fullWidth?: boolean;
|
|
86
|
+
multiselect?: boolean;
|
|
51
87
|
}>();
|
|
52
88
|
|
|
53
89
|
const selectedItems = $ref<Option[]>([]);
|
|
@@ -58,150 +94,172 @@ const dropdown = $ref<InstanceType<typeof Dropdown> | null>(null);
|
|
|
58
94
|
let open = $ref(false);
|
|
59
95
|
|
|
60
96
|
function updateOpen(visible: boolean) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
97
|
+
open = visible;
|
|
98
|
+
if (!open) search = '';
|
|
99
|
+
else {
|
|
100
|
+
setTimeout(
|
|
101
|
+
() => (searchInput as any)?.$el?.querySelector('input')?.focus(),
|
|
102
|
+
100,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
64
105
|
}
|
|
65
106
|
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
const selectedLabel = $computed(() => {
|
|
108
|
+
if (selectedItems.length === 0) return props.placeholder || 'Select';
|
|
109
|
+
if (selectedItems.length > 4) {
|
|
110
|
+
const str = selectedItems
|
|
111
|
+
.slice(0, 4)
|
|
112
|
+
.map((item) => getLabel(item))
|
|
113
|
+
.join(', ');
|
|
114
|
+
return `${str}... +${selectedItems.length - 4}`;
|
|
115
|
+
}
|
|
116
|
+
return selectedItems.map((item) => getLabel(item)).join(', ');
|
|
73
117
|
});
|
|
74
118
|
|
|
75
119
|
const emit = defineEmits(['update:modelValue']);
|
|
76
120
|
|
|
77
121
|
const getLabel = (option: Option) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
122
|
+
if (typeof option === 'string') return option;
|
|
123
|
+
if (typeof option === 'number') return `${option}`;
|
|
124
|
+
return option.label;
|
|
81
125
|
};
|
|
82
126
|
|
|
83
127
|
const getValue = (option: Option) => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
128
|
+
if (typeof option === 'string') return option;
|
|
129
|
+
if (typeof option === 'number') return option;
|
|
130
|
+
return option.value;
|
|
87
131
|
};
|
|
88
132
|
|
|
89
|
-
const isSelected = (option: Option) => selectedItems.
|
|
133
|
+
const isSelected = (option: Option) => !!selectedItems.find((item) => getValue(option) === getValue(item));
|
|
90
134
|
|
|
91
135
|
const filteredOptions = $computed(() => props.options.filter((option) => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
136
|
+
const searchTerm = new RegExp(search, 'gi');
|
|
137
|
+
return (
|
|
138
|
+
Boolean(option) &&
|
|
139
|
+
(getLabel(option).match(searchTerm) || getValue(option).match(searchTerm))
|
|
140
|
+
);
|
|
96
141
|
}));
|
|
97
142
|
|
|
98
143
|
const select = (option: Option) => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
dropdown?.hide();
|
|
109
|
-
}
|
|
110
|
-
emitUpdate();
|
|
144
|
+
const existingIndex = selectedItems.findIndex((item) => getValue(item) === getValue(option));
|
|
145
|
+
if (existingIndex > -1) selectedItems.splice(existingIndex, 1);
|
|
146
|
+
else if (props.multiselect) {
|
|
147
|
+
selectedItems.push(option);
|
|
148
|
+
} else {
|
|
149
|
+
selectedItems.splice(0, selectedItems.length, option);
|
|
150
|
+
}
|
|
151
|
+
if (!props.multiselect) dropdown?.hide();
|
|
152
|
+
emitUpdate();
|
|
111
153
|
};
|
|
112
154
|
|
|
113
155
|
function emitUpdate() {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
156
|
+
if (props.multiselect) {
|
|
157
|
+
emit('update:modelValue', selectedItems.map(getValue));
|
|
158
|
+
} else {
|
|
159
|
+
selectedItems.splice(1, selectedItems.length - 1);
|
|
160
|
+
const [item] = selectedItems;
|
|
161
|
+
emit('update:modelValue', item ? getValue(item) : null);
|
|
162
|
+
}
|
|
120
163
|
}
|
|
121
164
|
|
|
122
165
|
function compareArrays(arr1: Option[], arr2: Option[]) {
|
|
123
|
-
|
|
124
|
-
|
|
166
|
+
const isSame = arr1.every((item: Option) => arr2.map((a) => getValue(a)).includes(getValue(item)));
|
|
167
|
+
return isSame;
|
|
125
168
|
}
|
|
126
169
|
|
|
127
170
|
watch(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
171
|
+
() => props.modelValue,
|
|
172
|
+
(newVal: Option | Option[]) => {
|
|
173
|
+
if (!newVal) return;
|
|
174
|
+
if (!props.multiselect) {
|
|
175
|
+
if (!isSelected(newVal)) selectedItems.splice(0, selectedItems.length, newVal);
|
|
176
|
+
} else {
|
|
177
|
+
const isSame = compareArrays([newVal].flat(), selectedItems);
|
|
178
|
+
if (!isSame) selectedItems.splice(0, selectedItems.length, [newVal].flat());
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
{ immediate: true },
|
|
139
182
|
);
|
|
183
|
+
|
|
184
|
+
watch(() => props.options, () => {
|
|
185
|
+
const original = JSON.stringify(selectedItems);
|
|
186
|
+
[...selectedItems].forEach((option, i) => {
|
|
187
|
+
const exists = props.options.find((o) => getValue(o) === getValue(option));
|
|
188
|
+
if (!exists) selectedItems.splice(i, 1);
|
|
189
|
+
else selectedItems.splice(i, 1, exists);
|
|
190
|
+
});
|
|
191
|
+
const newSelection = JSON.stringify(selectedItems);
|
|
192
|
+
if (original !== newSelection) emitUpdate();
|
|
193
|
+
});
|
|
140
194
|
</script>
|
|
141
195
|
|
|
142
196
|
<style scoped>
|
|
143
197
|
.selectinput {
|
|
144
|
-
|
|
198
|
+
width: 100%;
|
|
145
199
|
}
|
|
146
200
|
|
|
147
201
|
.selectinput-option {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
202
|
+
padding: 6px 12px;
|
|
203
|
+
cursor: pointer;
|
|
204
|
+
border-radius: 5px;
|
|
205
|
+
transition: all 0.2s;
|
|
206
|
+
display: grid;
|
|
207
|
+
grid-template-columns: 10px 1fr;
|
|
208
|
+
justify-content: space-between;
|
|
209
|
+
width: 100%;
|
|
210
|
+
font-size: var(--input-font-size);
|
|
157
211
|
}
|
|
158
212
|
|
|
159
213
|
.selectinput-options {
|
|
160
|
-
|
|
161
|
-
|
|
214
|
+
max-height: 300px;
|
|
215
|
+
overflow-y: auto;
|
|
162
216
|
}
|
|
163
217
|
|
|
164
218
|
.selectinput-option:hover {
|
|
165
|
-
|
|
219
|
+
background: var(--bgl-gray-20);
|
|
220
|
+
}
|
|
221
|
+
.isEmpty p{
|
|
222
|
+
opacity: 0.3;
|
|
166
223
|
}
|
|
167
224
|
</style>
|
|
168
225
|
|
|
169
226
|
<style>
|
|
170
227
|
.bagel-input label {
|
|
171
|
-
|
|
228
|
+
font-size: var(--label-font-size);
|
|
172
229
|
}
|
|
173
230
|
|
|
174
231
|
.selectinput-btn {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
232
|
+
display: flex;
|
|
233
|
+
justify-content: space-between;
|
|
234
|
+
align-items: center;
|
|
235
|
+
height: var(--input-height);
|
|
236
|
+
border-radius: var(--input-border-radius);
|
|
237
|
+
border: none;
|
|
238
|
+
background: var(--input-bg);
|
|
239
|
+
padding: 0.7rem;
|
|
240
|
+
color: var(--input-color);
|
|
241
|
+
width: 100%;
|
|
242
|
+
font-family: inherit;
|
|
243
|
+
font-size: var(--input-font-size);
|
|
186
244
|
}
|
|
187
245
|
|
|
188
246
|
.selectinput-btn:disabled {
|
|
189
|
-
|
|
190
|
-
color: var(--input-disabled-color);
|
|
247
|
+
color: var(--input-disabled-color);
|
|
191
248
|
}
|
|
192
249
|
|
|
193
250
|
.selectinput-btn:focus {
|
|
194
|
-
|
|
195
|
-
|
|
251
|
+
outline: none;
|
|
252
|
+
box-shadow: inset 0 0 10px #00000012;
|
|
196
253
|
}
|
|
197
254
|
|
|
198
255
|
.v-popper__arrow-container {
|
|
199
|
-
|
|
256
|
+
display: none;
|
|
200
257
|
}
|
|
201
258
|
|
|
202
259
|
.v-popper--theme-dropdown .v-popper__inner {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
260
|
+
border: none;
|
|
261
|
+
background: transparent;
|
|
262
|
+
border-radius: var(--card-border-radius);
|
|
263
|
+
color: var(--input-color);
|
|
206
264
|
}
|
|
207
265
|
</style>
|
|
@@ -11,3 +11,4 @@ export { default as RadioPillsInput } from './RadioPillsInput.vue';
|
|
|
11
11
|
export { default as FileUpload } from './FileUpload.vue';
|
|
12
12
|
export { default as ToggleInput } from './ToggleInput.vue';
|
|
13
13
|
export { default as RichText } from './RichText.vue';
|
|
14
|
+
export { Dropdown } from 'floating-vue';
|
package/src/styles/buttons.css
CHANGED
|
@@ -65,8 +65,16 @@
|
|
|
65
65
|
filter: brightness(80%);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
.border {
|
|
69
|
+
border: 1px solid var(--border-color);
|
|
70
|
+
}
|
|
71
|
+
|
|
68
72
|
@media screen and (max-width: 910px) {
|
|
69
73
|
.bgl_btn {
|
|
70
74
|
padding: 0 20px;
|
|
71
75
|
}
|
|
76
|
+
|
|
77
|
+
.m_border {
|
|
78
|
+
border: 1px solid var(--border-color);
|
|
79
|
+
}
|
|
72
80
|
}
|
package/src/styles/layout.css
CHANGED
|
@@ -1404,11 +1404,11 @@
|
|
|
1404
1404
|
}
|
|
1405
1405
|
|
|
1406
1406
|
.vh-100 {
|
|
1407
|
-
height: 100vh;
|
|
1407
|
+
height: 100vh !important;
|
|
1408
1408
|
}
|
|
1409
1409
|
|
|
1410
1410
|
.h-100px {
|
|
1411
|
-
height: 100px;
|
|
1411
|
+
height: 100px !important;
|
|
1412
1412
|
}
|
|
1413
1413
|
|
|
1414
1414
|
.hm-100px {
|
|
@@ -1517,6 +1517,42 @@
|
|
|
1517
1517
|
overflow-y: hidden;
|
|
1518
1518
|
}
|
|
1519
1519
|
|
|
1520
|
+
.grid-wrap-50 {
|
|
1521
|
+
grid-template-columns: repeat(auto-fit, minmax(min(50px, 100%), 1fr));
|
|
1522
|
+
height: max-content;
|
|
1523
|
+
width: 100%
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
.grid-wrap-100 {
|
|
1527
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100px, 100%), 1fr));
|
|
1528
|
+
height: max-content;
|
|
1529
|
+
width: 100%
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
.grid-wrap-200 {
|
|
1533
|
+
grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
|
|
1534
|
+
height: max-content;
|
|
1535
|
+
width: 100%
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
.grid-wrap-300 {
|
|
1539
|
+
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
|
|
1540
|
+
height: max-content;
|
|
1541
|
+
width: 100%
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
.grid-wrap-400 {
|
|
1545
|
+
grid-template-columns: repeat(auto-fit, minmax(min(400px, 100%), 1fr));
|
|
1546
|
+
height: max-content;
|
|
1547
|
+
width: 100%
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
.grid-wrap-500 {
|
|
1551
|
+
grid-template-columns: repeat(auto-fit, minmax(min(500px, 100%), 1fr));
|
|
1552
|
+
height: max-content;
|
|
1553
|
+
width: 100%
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1520
1556
|
.grid-wrap-1 {
|
|
1521
1557
|
grid-template-columns: repeat(1, 1fr);
|
|
1522
1558
|
height: max-content;
|
|
@@ -1423,6 +1423,43 @@
|
|
|
1423
1423
|
overflow-y: hidden;
|
|
1424
1424
|
}
|
|
1425
1425
|
|
|
1426
|
+
|
|
1427
|
+
.m_grid-wrap-50 {
|
|
1428
|
+
grid-template-columns: repeat(auto-fit, minmax(min(50px, 100%), 1fr));
|
|
1429
|
+
height: max-content;
|
|
1430
|
+
width: 100%
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
.m_grid-wrap-100 {
|
|
1434
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100px, 100%), 1fr));
|
|
1435
|
+
height: max-content;
|
|
1436
|
+
width: 100%
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
.m_grid-wrap-200 {
|
|
1440
|
+
grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
|
|
1441
|
+
height: max-content;
|
|
1442
|
+
width: 100%
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
.m_grid-wrap-300 {
|
|
1446
|
+
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
|
|
1447
|
+
height: max-content;
|
|
1448
|
+
width: 100%
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
.m_grid-wrap-400 {
|
|
1452
|
+
grid-template-columns: repeat(auto-fit, minmax(min(400px, 100%), 1fr));
|
|
1453
|
+
height: max-content;
|
|
1454
|
+
width: 100%
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
.m_grid-wrap-500 {
|
|
1458
|
+
grid-template-columns: repeat(auto-fit, minmax(min(500px, 100%), 1fr));
|
|
1459
|
+
height: max-content;
|
|
1460
|
+
width: 100%
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1426
1463
|
.m_grid-wrap-1 {
|
|
1427
1464
|
grid-template-columns: repeat(1, 1fr);
|
|
1428
1465
|
height: max-content;
|