@bagelink/vue 0.0.280 → 0.0.282
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/ComboBox.vue.d.ts.map +1 -1
- package/dist/index.cjs +35 -31
- package/dist/index.mjs +35 -31
- package/dist/style.css +529 -284
- package/package.json +1 -1
- package/src/components/ComboBox.vue +73 -74
- package/src/styles/buttons.css +50 -38
- package/src/styles/layout.css +449 -190
- package/src/styles/text.css +80 -38
package/package.json
CHANGED
|
@@ -1,34 +1,33 @@
|
|
|
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
|
-
</Dropdown>
|
|
2
|
+
<Dropdown placement="auto-start" class="bagel-input combobox">
|
|
3
|
+
<button type="button" class="combobox-btn" @click="toggle">
|
|
4
|
+
{{ valueToLabel(selectedItem) || placeholder || 'Select' }}
|
|
5
|
+
<MaterialIcon v-bind="{ 'icon': open ? 'unfold_less' : 'unfold_more' }" />
|
|
6
|
+
</button>
|
|
7
|
+
<input style="width: 0; height: 0; position: absolute; opacity: 0; z-index: -1;" v-if="required"
|
|
8
|
+
v-model="selectedItem" required>
|
|
9
|
+
<template #popper="{ hide }">
|
|
10
|
+
<Card thin class="combobox-options">
|
|
11
|
+
<TextInput v-if="searchable" ref="searchInput" dense :placeholder="'Search'" icon="search" v-model="search" />
|
|
12
|
+
<div class="combobox-option" v-for="(option, i) in filteredOptions" :key="`${option}${i}`" @click="() => {
|
|
13
|
+
select(option)
|
|
14
|
+
hide();
|
|
15
|
+
}" :class="{ selected: option === selectedItem }">
|
|
16
|
+
<span>
|
|
17
|
+
{{ label(option) }}
|
|
18
|
+
</span>
|
|
19
|
+
<Icon v-if="isSelected(option)" icon="check" />
|
|
20
|
+
</div>
|
|
21
|
+
</Card>
|
|
22
|
+
</template>
|
|
23
|
+
</Dropdown>
|
|
25
24
|
</template>
|
|
26
25
|
|
|
27
26
|
<script lang="ts" setup>
|
|
28
27
|
import { Dropdown } from 'floating-vue';
|
|
29
28
|
import 'floating-vue/style.css';
|
|
30
29
|
import {
|
|
31
|
-
|
|
30
|
+
TextInput, Card, Icon, MaterialIcon,
|
|
32
31
|
} from '@bagelink/vue';
|
|
33
32
|
|
|
34
33
|
type Option = string | number | Record<string, any> | { label: string, value: string | number };
|
|
@@ -38,101 +37,101 @@ let selectedItem = $ref<Option>();
|
|
|
38
37
|
const searchInput = $ref<HTMLInputElement | null>(null);
|
|
39
38
|
|
|
40
39
|
const props = defineProps<{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
options: Option[];
|
|
41
|
+
placeholder?: string;
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
modelValue?: Option;
|
|
44
|
+
searchable?: boolean;
|
|
45
|
+
required?: boolean;
|
|
47
46
|
}>();
|
|
48
47
|
let search = $ref('');
|
|
49
48
|
|
|
50
49
|
const toggle = () => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
open = !open;
|
|
51
|
+
if (!open) search = '';
|
|
52
|
+
if (open) setTimeout(() => (searchInput as any)?.$el?.querySelector('input')?.focus(), 100);
|
|
54
53
|
};
|
|
55
54
|
|
|
56
55
|
const valueToLabel = (value?: Option) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
56
|
+
if (!value) return '';
|
|
57
|
+
const option = props.options.find((option) => {
|
|
58
|
+
if (typeof option === 'string' || typeof option === 'number') return option === value;
|
|
59
|
+
return option.value === value;
|
|
60
|
+
});
|
|
61
|
+
if (!option) return value;
|
|
62
|
+
return label(option);
|
|
64
63
|
};
|
|
65
64
|
|
|
66
65
|
const emit = defineEmits(['update:modelValue']);
|
|
67
66
|
|
|
68
67
|
const label = (option: Option) => {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
if (typeof option === 'string') return option;
|
|
69
|
+
if (typeof option === 'number') return `${option}`;
|
|
70
|
+
return option.label;
|
|
72
71
|
};
|
|
73
72
|
|
|
74
73
|
const isSelected = (option: Option) => {
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
if (typeof option === 'string' || typeof option === 'number') return option === selectedItem;
|
|
75
|
+
return option.value === selectedItem;
|
|
77
76
|
};
|
|
78
77
|
|
|
79
78
|
const filteredOptions = $computed(() => props.options.filter((option) => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
const searchTerm = new RegExp(search, 'gi');
|
|
80
|
+
if (typeof option === 'string') return option.match(searchTerm);
|
|
81
|
+
if (typeof option === 'number') return `${option}`.match(searchTerm);
|
|
82
|
+
return option.label.match(searchTerm);
|
|
84
83
|
}));
|
|
85
84
|
|
|
86
85
|
const select = (option: Option) => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
if (typeof option === 'string') selectedItem = option;
|
|
87
|
+
else if (typeof option === 'number') selectedItem = option;
|
|
88
|
+
else selectedItem = option.value;
|
|
89
|
+
emit('update:modelValue', selectedItem);
|
|
90
|
+
open = false;
|
|
92
91
|
};
|
|
93
92
|
</script>
|
|
94
93
|
|
|
95
94
|
<style scoped>
|
|
96
95
|
.combobox {
|
|
97
|
-
|
|
96
|
+
width: 100%;
|
|
98
97
|
}
|
|
99
98
|
|
|
100
99
|
.combobox-option {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
100
|
+
padding: 6px 12px;
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
border-radius: 5px;
|
|
103
|
+
transition: all 0.2s;
|
|
104
|
+
display: flex;
|
|
105
|
+
justify-content: space-between;
|
|
106
|
+
width: 100%;
|
|
108
107
|
}
|
|
109
108
|
|
|
110
109
|
.combobox-options {
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
max-height: 300px;
|
|
111
|
+
overflow-y: auto;
|
|
113
112
|
}
|
|
114
113
|
|
|
115
114
|
.combobox-option:hover {
|
|
116
|
-
|
|
115
|
+
background: var(--bgl-gray-20);
|
|
117
116
|
}
|
|
118
117
|
</style>
|
|
119
118
|
|
|
120
119
|
<style>
|
|
121
120
|
.combobox-btn {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
121
|
+
display: flex;
|
|
122
|
+
justify-content: space-between;
|
|
123
|
+
align-items: center;
|
|
124
|
+
height: var(--input-height);
|
|
125
|
+
border-radius: var(--input-border-radius);
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
.v-popper__arrow-container {
|
|
130
|
-
|
|
129
|
+
display: none;
|
|
131
130
|
}
|
|
132
131
|
|
|
133
132
|
.v-popper--theme-dropdown .v-popper__inner {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
border: none;
|
|
134
|
+
background: transparent;
|
|
135
|
+
border-radius: var(--card-border-radius);
|
|
137
136
|
}
|
|
138
137
|
</style>
|
package/src/styles/buttons.css
CHANGED
|
@@ -1,59 +1,71 @@
|
|
|
1
1
|
.bgl_btn,
|
|
2
2
|
.bgl_flatBtn,
|
|
3
3
|
.bgl_btn-icon {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
font-family: inherit;
|
|
5
|
+
white-space: nowrap;
|
|
6
|
+
cursor: pointer;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
user-select: none;
|
|
9
|
+
border: none;
|
|
10
|
+
transition: var(--bgl-transition);
|
|
11
|
+
border-radius: var(--btn-border-radius);
|
|
12
|
+
line-height: var(--btn-height);
|
|
13
|
+
font-size: var(--input-font-size);
|
|
14
|
+
display: inline-block;
|
|
15
|
+
height: var(--btn-height);
|
|
16
|
+
padding: 0;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
.btn-close {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
margin-top: -20px;
|
|
21
|
+
margin-inline-end: -20px;
|
|
22
|
+
margin-inline-start: auto;
|
|
23
|
+
margin-bottom: 15px;
|
|
24
|
+
transition: var(--bgl-transition);
|
|
25
|
+
height: 30px;
|
|
26
|
+
width: 30px;
|
|
27
|
+
opacity: 0.6;
|
|
28
|
+
cursor: pointer;
|
|
29
|
+
border-radius: 100%;
|
|
30
|
+
outline: 2px solid transparent;
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
justify-content: center;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
.btn-close:hover {
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
background: var(--bgl-gray-light);
|
|
38
|
+
opacity: 1;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
.btn-close:active {
|
|
42
|
-
|
|
42
|
+
background: var(--bgl-gray);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
.btn-close::before {
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
content: "close";
|
|
47
|
+
font-family: "Material Symbols Outlined", serif;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
.bgl_btn.thin {
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
height: calc(var(--btn-height) * 0.7);
|
|
52
|
+
line-height: calc(var(--btn-height) * 0.7);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
.hover {
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
transition: all 400ms ease;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.hover:hover {
|
|
61
|
+
filter: brightness(90%);
|
|
59
62
|
}
|
|
63
|
+
|
|
64
|
+
.hover:active {
|
|
65
|
+
filter: brightness(80%);
|
|
66
|
+
}
|
|
67
|
+
@media screen and (max-width: 910px) {
|
|
68
|
+
.bgl_btn {
|
|
69
|
+
padding: 0 20px;
|
|
70
|
+
}
|
|
71
|
+
}
|