quasar-ui-sellmate-ui-kit 1.4.4 → 1.4.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar-ui-sellmate-ui-kit",
3
- "version": "1.4.4",
3
+ "version": "1.4.5",
4
4
  "author": "Sellmate Dev Team <dev@sellmate.co.kr>",
5
5
  "description": "Sellmate UI Kit",
6
6
  "license": "MIT",
@@ -5,7 +5,7 @@
5
5
  options-dense
6
6
  :dropdown-icon="selectDownArrowIcon"
7
7
  :options-selected-class="selectedOpt"
8
- popup-content-class="s-select-group-opts"
8
+ :popup-content-class="`s-select-opts ${group ? 's-select-group-opts' : ''} ${popupContentClass ?? ''}`"
9
9
  class="s-select"
10
10
  ref="sSelectRef"
11
11
  :class="{ 's-select-multiple': $attrs.multiple }"
@@ -98,6 +98,10 @@ export default defineComponent({
98
98
  options: Array,
99
99
  noSelected: String,
100
100
  emitValue: Boolean,
101
+ popupContentClass: {
102
+ default: () => '',
103
+ type: String,
104
+ },
101
105
  },
102
106
  setup(props, { emit, attrs }) {
103
107
  const filteredOptions = ref(props.options);
@@ -254,6 +258,10 @@ export default defineComponent({
254
258
  }
255
259
  }
256
260
 
261
+ .s-select-opts {
262
+ @extend %select-menu-list;
263
+ }
264
+
257
265
  .s-select-group-opts {
258
266
  padding: 0;
259
267
  .s-select-no-option {
@@ -274,9 +282,11 @@ export default defineComponent({
274
282
  .group-option {
275
283
  padding: 4px 12px 4px 20px !important;
276
284
  &.disabled {
277
- color: $Grey_Lighten-1 !important;
278
285
  background: white !important;
279
286
  border: none !important;
287
+ .q-item__section {
288
+ color: $Grey_Lighten-1 !important;
289
+ }
280
290
  }
281
291
  }
282
292
  }
@@ -10,7 +10,7 @@
10
10
  emit-value
11
11
  map-options
12
12
  color="positive"
13
- popup-content-class="s-select-checkbox-opts"
13
+ :popup-content-class="`s-select-checkbox-opts ${$props?.popupContentClass ?? ''}`"
14
14
  class="s-select-checkbox"
15
15
  :option-label="optionLabel"
16
16
  :option-value="optionValue"
@@ -31,7 +31,7 @@
31
31
  @update:modelValue="toggleOption(opt)"
32
32
  />
33
33
  </q-item-section>
34
- <q-item-section v-if="opt[optionGroup]" class="text-grey-2">
34
+ <q-item-section v-if="opt[optionGroup]" class="text-Grey_Darken-4 group-title">
35
35
  {{ opt[optionGroup] }}
36
36
  </q-item-section>
37
37
  <q-item-section avatar v-if="opt.logo">
@@ -102,6 +102,10 @@ export default defineComponent({
102
102
  type: String,
103
103
  default: '전체',
104
104
  },
105
+ popupContentClass: {
106
+ default: () => '',
107
+ type: String,
108
+ },
105
109
  },
106
110
  setup(props, { emit }) {
107
111
  const model = ref(props.modelValue);
@@ -206,15 +210,21 @@ export default defineComponent({
206
210
 
207
211
  .s-select-checkbox-opts {
208
212
  @extend %select-menu-list;
213
+ > .q-virtual-scroll__content {
214
+ > .q-item.disabled {
215
+ border: none;
216
+ color: $Grey_Darken-4 !important;
217
+ opacity: 1 !important;
218
+ background: $Grey_Lighten-5 !important;
219
+ border-top: 1px solid $Grey_Lighten-3 !important;
220
+ &:not(.q-manual-focusable):first-of-type {
221
+ border-top: none !important;
222
+ }
223
+ }
224
+ }
209
225
  }
210
226
 
211
227
  .custom-select-options {
212
228
  height: $default-height;
213
229
  }
214
-
215
- .disabled.s-select-checkbox-option {
216
- border: none;
217
- background: none !important;
218
- color: $Grey_Default !important;
219
- }
220
230
  </style>
@@ -0,0 +1,252 @@
1
+ <template>
2
+ <q-select
3
+ outlined
4
+ dense
5
+ options-dense
6
+ :dropdown-icon="selectDownArrowIcon"
7
+ v-model="model"
8
+ :options="options"
9
+ multiple
10
+ emit-value
11
+ map-options
12
+ color="positive"
13
+ :popup-content-class="`s-select-group-checkbox-opts ${$props?.popupContentClass ?? ''}`"
14
+ class="s-select-checkbox"
15
+ :option-label="optionLabel"
16
+ :option-value="optionValue"
17
+ :option-group="optionGroup"
18
+ @add="onAddChecked"
19
+ @remove="onRemoveChecked"
20
+ :menu-offset="[0, 4]"
21
+ menu-self="top left"
22
+ menu-anchor="bottom start"
23
+ no-error-icon
24
+ hide-bottom-space
25
+ >
26
+ <template v-slot:option="{ itemProps, opt, selected, toggleOption }">
27
+ <q-item v-bind="itemProps" class="flex column grouping-opt">
28
+ <q-item-section class="s-px-sm s-py-xxs row justify-start text-Grey_Darken-4 group-title">
29
+ <s-checkbox
30
+ class="s-mr-xs"
31
+ :modelValue="selected"
32
+ @update:modelValue="toggleOption(opt.optionLabel)"
33
+ />
34
+ {{ opt[optionLabel] }}
35
+ </q-item-section>
36
+ <template v-for="groupOpt in opt.options" :key="groupOpt.optionValue">
37
+ <q-item-section class="group-content full-width">
38
+ <s-checkbox
39
+ class="s-mr-xs"
40
+ :modelValue="selected"
41
+ @update:modelValue="toggleOption(opt.optionLabel)"
42
+ />
43
+ <q-img
44
+ class="q-pa-none inline-block bg-Grey_Lighten-5 s-border-Grey_Lighten-7 s-border-radius-xxs q-mr-sm"
45
+ :src="groupOpt.logo"
46
+ width="60px"
47
+ height="22px"
48
+ v-if="groupOpt.logo"
49
+ />
50
+ {{ groupOpt[optionLabel] }}
51
+ </q-item-section>
52
+ </template>
53
+ </q-item>
54
+ </template>
55
+ <template v-if="useAll && model.length === options.filter(v => !v.category).length" v-slot:selected>
56
+ <div>
57
+ {{ allPlaceholder }}
58
+ </div>
59
+ </template>
60
+ </q-select>
61
+ </template>
62
+
63
+ <script>
64
+ import {
65
+ defineComponent, onBeforeMount, ref, nextTick, watch,
66
+ } from 'vue';
67
+ import {
68
+ QSelect, QItem, QItemSection, QImg,
69
+ } from 'quasar';
70
+ import { selectDownArrowIcon } from '../assets/icons.js';
71
+
72
+ export default defineComponent({
73
+ name: 'SSelectGroupCheckbox',
74
+ emits: ['update:modelValue'],
75
+ components: {
76
+ QSelect,
77
+ QItem,
78
+ QItemSection,
79
+ QImg,
80
+ },
81
+ props: {
82
+ options: {
83
+ type: Array,
84
+ required: true,
85
+ },
86
+ modelValue: {
87
+ type: Array,
88
+ required: true,
89
+ },
90
+ optionLabel: {
91
+ type: [String, Function],
92
+ default: 'label',
93
+ },
94
+ optionValue: {
95
+ type: String,
96
+ default: 'value',
97
+ },
98
+ optionGroup: {
99
+ type: String,
100
+ default: 'group',
101
+ },
102
+ useAll: {
103
+ type: Boolean,
104
+ default: false,
105
+ },
106
+ allPlaceholder: {
107
+ type: String,
108
+ default: '전체',
109
+ },
110
+ popupContentClass: {
111
+ default: () => '',
112
+ type: String,
113
+ },
114
+ },
115
+ // TODO: 기능 미완성
116
+ setup(props, { emit }) {
117
+ const model = ref(props.modelValue);
118
+ function onRemoveChecked(detail) {
119
+ const idx = model.value.findIndex(v => v[props.optionValue] === '');
120
+ if (detail.value[props.optionValue]?.includes('all')) {
121
+ nextTick(() => {
122
+ model.value = [];
123
+ });
124
+ return;
125
+ }
126
+ if (detail.value[props.optionValue] === '') {
127
+ nextTick(() => {
128
+ model.value = [];
129
+ });
130
+ } else if (idx >= 0) {
131
+ nextTick(() => {
132
+ model.value.splice(idx, 1);
133
+ });
134
+ }
135
+ }
136
+ function onAddChecked(detail) {
137
+ if (detail.value === '') {
138
+ nextTick(() => {
139
+ model.value = props.options;
140
+ });
141
+ } else {
142
+ nextTick(() => {
143
+ if (model.value.length === props.options.length - 1) {
144
+ model.value = props.options;
145
+ }
146
+ });
147
+ }
148
+ }
149
+
150
+ watch(() => props.modelValue, () => {
151
+ model.value = props.modelValue;
152
+ });
153
+ watch(model, () => {
154
+ emit('update:modelValue', model.value);
155
+ });
156
+
157
+ onBeforeMount(() => {
158
+ if (props.useAll && model.value.length === 1 && !props.modelValue[0].value) {
159
+ model.value = props.options.filter(v => !v.category);
160
+ }
161
+ });
162
+
163
+ return {
164
+ model,
165
+ selectDownArrowIcon,
166
+ onRemoveChecked,
167
+ onAddChecked,
168
+ };
169
+ },
170
+ });
171
+ </script>
172
+
173
+ <style lang="scss">
174
+ @import "../css/variable.scss";
175
+ @import "../css/extends.scss";
176
+
177
+ .s-select-checkbox {
178
+ @extend %select;
179
+ .q-field__native {
180
+ display: block;
181
+ min-height: 0;
182
+ height: $default-height;
183
+ width: 100%;
184
+ padding: $select-padding !important;
185
+ color: $Grey_Darken-4;
186
+ white-space: nowrap;
187
+ overflow: hidden;
188
+ text-overflow: ellipsis;
189
+ > span {
190
+ max-height: $default-height;
191
+ }
192
+ > .s-checkbox {
193
+ margin-right: $default-icon-margin;
194
+ }
195
+ }
196
+ }
197
+ .q-field--disabled.s-select {
198
+ .q-field__inner {
199
+ .q-field__control {
200
+ opacity: 1 !important;
201
+ background: $Grey_Lighten-3;
202
+ &:after {
203
+ border: 1px solid $Grey_Lighten-2;
204
+ }
205
+ &-container {
206
+ .q-field__native {
207
+ > span {
208
+ color: $Grey_Default;
209
+ }
210
+ }
211
+ }
212
+ .q-field__append {
213
+ .q-icon {
214
+ color: $Grey_Default;
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ .s-select-group-checkbox-opts {
222
+ @extend %select-menu-list;
223
+ > .q-virtual-scroll__content {
224
+ > .q-item.grouping-opt {
225
+ border: none;
226
+ color: $Grey_Darken-4 !important;
227
+ opacity: 1 !important;
228
+ height: auto;
229
+ padding: 0;
230
+ background-color: white;
231
+ > .group-title, .group-content {
232
+ flex-direction: row !important;
233
+ justify-content: flex-start !important;
234
+ > .s-checkbox {
235
+ margin-right: 10px;
236
+ }
237
+ }
238
+ > .group-title {
239
+ background-color: $Grey_Lighten-5;
240
+ border-top: 1px solid $Grey_Lighten-3 !important;
241
+ &:first-of-type {
242
+ border-top: none !important;
243
+ }
244
+ }
245
+ > .group-content {
246
+ margin: 0;
247
+ padding: 4px 12px 4px 16px;
248
+ }
249
+ }
250
+ }
251
+ }
252
+ </style>
@@ -1,36 +1,19 @@
1
1
  <template>
2
- <q-select
3
- outlined
4
- dense
5
- options-dense
6
- :dropdown-icon="selectDownArrowIcon"
7
- v-model="model"
8
- :options="filteredOptions"
9
- multiple
10
- emit-value
11
- map-options
12
- autocomplete="country"
13
- color="positive"
14
- popup-content-class="s-select-checkbox-opts"
15
- class="s-select-checkbox"
16
- :option-label="optionLabel"
17
- :option-value="optionValue"
18
- :option-group="optionGroup"
19
- @add="onAddChecked"
20
- @remove="onRemoveChecked"
21
- :menu-offset="[0, 4]"
22
- menu-self="top left"
23
- menu-anchor="bottom start"
24
- no-error-icon
25
- hide-bottom-space
26
- >
2
+ <q-select outlined dense options-dense :dropdown-icon="selectDownArrowIcon" v-model="model" :options="filteredOptions"
3
+ multiple emit-value map-options autocomplete="country" color="positive"
4
+ :popup-content-class="`s-select-checkbox-opts ${popupContentClass}`" class="s-select-checkbox"
5
+ :option-label="optionLabel" :option-value="optionValue" :option-group="optionGroup" @add="onAddChecked"
6
+ @remove="onRemoveChecked" :menu-offset="[0, 4]" menu-self="top left" menu-anchor="bottom start" no-error-icon
7
+ hide-bottom-space>
27
8
  <!-- TODO: 아무것도 선택되지 않았을 때 props 값으로 표기 해줘야함 기본 값은 "전체" -->
28
9
  <template v-slot:before-options>
29
- <form class="select-search-input-form">
30
- <q-icon :name="searchIcon" size="20px" />
31
- <input v-model="search" autofocus class="select-search-input" :placeholder="searchPlaceholder"
32
- @input="(data) => { onSearch(data.target.value); }" />
33
- </form>
10
+ <div class="search-input-form-container">
11
+ <form class="select-search-input-form">
12
+ <q-icon :name="searchIcon" size="20px" />
13
+ <input v-model="search" autofocus class="select-search-input" :placeholder="searchPlaceholder"
14
+ @input="(data) => { onSearch(data.target.value); }" />
15
+ </form>
16
+ </div>
34
17
  </template>
35
18
  <template v-slot:option="{ itemProps, opt, selected, toggleOption }">
36
19
  <q-item v-bind="itemProps" class="custom-select-options">
@@ -54,11 +37,13 @@
54
37
  </div>
55
38
  </template>
56
39
  <template v-slot:no-option>
57
- <form class="select-search-input-form">
58
- <q-icon :name="searchIcon" size="20px" />
59
- <input v-model="search" autofocus class="select-search-input" :placeholder="searchPlaceholder"
60
- @input="(data) => { onSearch(data.target.value); }" />
61
- </form>
40
+ <div class="search-input-form-container">
41
+ <form class="select-search-input-form">
42
+ <q-icon :name="searchIcon" size="20px" />
43
+ <input v-model="search" autofocus class="select-search-input" :placeholder="searchPlaceholder"
44
+ @input="(data) => { onSearch(data.target.value); }" />
45
+ </form>
46
+ </div>
62
47
  <q-item class="s-select-no-option">
63
48
  <q-item-section class="text-grey">{{ noData }}</q-item-section>
64
49
  </q-item>
@@ -131,6 +116,9 @@ export default defineComponent({
131
116
  type: String,
132
117
  default: '데이터 없음',
133
118
  },
119
+ popupContentClass: {
120
+ type: String,
121
+ },
134
122
  },
135
123
  setup(props, { emit }) {
136
124
  const model = ref(props.modelValue);
@@ -300,48 +288,50 @@ export default defineComponent({
300
288
  color: $Grey_Default !important;
301
289
  }
302
290
 
303
- .select-search-input-form {
304
- height: 32px;
305
- display: flex;
306
- align-items: center;
307
- padding-left: 8px;
308
- border-bottom: 1px solid rgba(0, 0, 0, 0.24);
309
- position: relative;
310
- border-top-left-radius: 2px;
311
- border-top-right-radius: 2px;
312
- background-color: white;
313
- position: sticky;
314
- top: 0;
315
- z-index: 1;
316
-
317
- &::after {
318
- content: "";
319
- position: absolute;
291
+ .search-input-form-container {
292
+ padding: 4px;
293
+ .select-search-input-form {
294
+ height: 28px;
295
+ display: flex;
296
+ align-items: center;
297
+ padding-left: 8px;
298
+ position: relative;
299
+ border-radius: 2px;
300
+ border:1px solid $Grey_Lighten-1;
301
+ background-color: white;
302
+ position: sticky;
320
303
  top: 0;
321
- right: 0;
322
- bottom: 0;
323
- left: 0;
324
- pointer-events: none;
325
- border: 1px solid transparent;
326
- border-radius: inherit;
327
- }
328
-
329
- &:hover,
330
- &:focus-within {
304
+ z-index: 1;
331
305
 
332
306
  &::after {
333
- border-color: #0075ff;
334
- box-shadow: 0 0 4px #0075ff;
335
- transition: border-color 0.36s cubic-bezier(0.4, 0, 0.2, 1);
307
+ content: "";
308
+ position: absolute;
309
+ top: 0;
310
+ right: 0;
311
+ bottom: 0;
312
+ left: 0;
313
+ pointer-events: none;
314
+ border: 1px solid transparent;
315
+ border-radius: inherit;
316
+ }
317
+
318
+ &:hover,
319
+ &:focus-within {
320
+
321
+ &::after {
322
+ border-color: #0075ff;
323
+ box-shadow: 0 0 4px #0075ff;
324
+ transition: border-color 0.36s cubic-bezier(0.4, 0, 0.2, 1);
325
+ }
336
326
  }
337
- }
338
327
 
339
- .select-search-input {
340
- font-size: 14px;
341
- margin-left: 4px;
342
- flex-grow: 1;
343
- border: none;
344
- outline: none;
328
+ .select-search-input {
329
+ font-size: 12px;
330
+ margin-left: 8px;
331
+ flex-grow: 1;
332
+ border: none;
333
+ outline: none;
334
+ }
345
335
  }
346
336
  }
347
337
  </style>
@@ -284,6 +284,7 @@ export default defineComponent({
284
284
  th {
285
285
  &:first-of-type {
286
286
  padding: 0 8px 0 24px;
287
+ line-height: 100%;
287
288
  > .q-checkbox {
288
289
  @extend %checkbox;
289
290
  }
@@ -296,6 +297,7 @@ export default defineComponent({
296
297
  td {
297
298
  &:first-of-type {
298
299
  padding: 0 8px 0 24px;
300
+ line-height: 100%;
299
301
  > .q-checkbox {
300
302
  @extend %checkbox;
301
303
  }
@@ -6,7 +6,7 @@
6
6
  width: 16px;
7
7
  height: 16px;
8
8
  .q-checkbox__bg {
9
- border: 1px solid $Grey_Lighten-2;
9
+ border: 1px solid $Grey_Default;
10
10
  width: 16px;
11
11
  height: 16px;
12
12
  padding: 0 2.5px;
@@ -95,6 +95,9 @@
95
95
  }
96
96
  }
97
97
  }
98
+ &--active {
99
+ color: $Grey_Darken-4 !important;
100
+ }
98
101
  }
99
102
  .q-manual-focusable--focused {
100
103
  background: $positive;
@@ -107,7 +110,6 @@
107
110
  > span {
108
111
  color: white !important;
109
112
  }
110
-
111
113
  }
112
114
  .q-checkbox {
113
115
  .q-checkbox__inner {
package/src/vue-plugin.js CHANGED
@@ -24,6 +24,7 @@ import SRouteTab from './components/SRouteTab.vue';
24
24
  import SSelect from './components/SSelect.vue';
25
25
  import SSelectCheckbox from './components/SSelectCheckbox.vue';
26
26
  import SSelectSearchCheckbox from './components/SSelectSearchCheckbox.vue';
27
+ import SSelectGroupCheckbox from './components/SSelectGroupCheckbox.vue';
27
28
  import SSelectCustom from './components/SSelectCustom.vue';
28
29
  import SSelectSearch from './components/SSelectSearch.vue';
29
30
  import STab from './components/STab.vue';
@@ -62,6 +63,7 @@ function install(app) {
62
63
  app.component('s-select-custom', SSelectCustom);
63
64
  app.component('s-select-checkbox', SSelectCheckbox);
64
65
  app.component('s-select-search-checkbox', SSelectSearchCheckbox);
66
+ app.component('s-select-group-checkbox', SSelectGroupCheckbox);
65
67
  app.component('s-select-search', SSelectSearch);
66
68
  app.component('s-tab', STab);
67
69
  app.component('s-route-tab', SRouteTab);