quasar-ui-sellmate-ui-kit 2.3.2 → 3.0.1

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.
Files changed (68) hide show
  1. package/.eslintrc.cjs +73 -0
  2. package/.prettierrc +25 -0
  3. package/README.md +156 -142
  4. package/dist/index.common.js +2 -2
  5. package/dist/index.css +3 -8
  6. package/dist/index.esm.js +2 -2
  7. package/dist/index.min.css +2 -2
  8. package/dist/index.rtl.css +3 -8
  9. package/dist/index.rtl.min.css +2 -2
  10. package/dist/index.umd.js +3820 -3822
  11. package/dist/index.umd.min.js +2 -2
  12. package/package.json +83 -75
  13. package/src/assets/icons.js +28 -28
  14. package/src/components/SBreadcrumbs.vue +55 -55
  15. package/src/components/SButton.vue +206 -206
  16. package/src/components/SButtonGroup.vue +41 -41
  17. package/src/components/SButtonToggle.vue +200 -200
  18. package/src/components/SCaution.vue +102 -102
  19. package/src/components/SCheckbox.vue +123 -123
  20. package/src/components/SChip.vue +99 -99
  21. package/src/components/SDate.vue +717 -717
  22. package/src/components/SDateAutoRangePicker.vue +341 -341
  23. package/src/components/SDatePicker.vue +472 -472
  24. package/src/components/SDateRange.vue +470 -470
  25. package/src/components/SDateRangePicker.vue +660 -660
  26. package/src/components/SDateTimePicker.vue +349 -349
  27. package/src/components/SDialog.vue +250 -250
  28. package/src/components/SDropdown.vue +216 -216
  29. package/src/components/SEditor.vue +490 -490
  30. package/src/components/SFilePicker.vue +207 -207
  31. package/src/components/SHelp.vue +146 -146
  32. package/src/components/SInput.vue +343 -343
  33. package/src/components/SInputCounter.vue +46 -46
  34. package/src/components/SInputNumber.vue +179 -179
  35. package/src/components/SList.vue +29 -29
  36. package/src/components/SMarkupTable.vue +141 -141
  37. package/src/components/SPagination.vue +266 -266
  38. package/src/components/SRadio.vue +78 -78
  39. package/src/components/SRouteTab.vue +67 -67
  40. package/src/components/SSelect.vue +294 -294
  41. package/src/components/SSelectCheckbox.vue +222 -222
  42. package/src/components/SSelectCustom.vue +189 -189
  43. package/src/components/SSelectGroupCheckbox.vue +235 -235
  44. package/src/components/SSelectSearch.vue +261 -261
  45. package/src/components/SSelectSearchAutoComplete.vue +172 -172
  46. package/src/components/SSelectSearchCheckbox.vue +356 -356
  47. package/src/components/SStringToInput.vue +66 -66
  48. package/src/components/STab.vue +77 -77
  49. package/src/components/STable.vue +425 -425
  50. package/src/components/STableTree.vue +210 -208
  51. package/src/components/STabs.vue +32 -32
  52. package/src/components/STimePicker.vue +159 -159
  53. package/src/components/SToggle.vue +68 -68
  54. package/src/components/STooltip.vue +209 -209
  55. package/src/components/SelelctItem.vue +21 -21
  56. package/src/components/TimePickerCard.vue +352 -352
  57. package/src/composables/date.js +11 -11
  58. package/src/composables/modelBinder.js +13 -13
  59. package/src/composables/table/use-navigator.js +110 -110
  60. package/src/composables/table/use-resizable.js +80 -80
  61. package/src/css/app.scss +90 -90
  62. package/src/css/default.scss +875 -875
  63. package/src/css/extends.scss +154 -154
  64. package/src/css/quasar.variables.scss +189 -189
  65. package/src/directives/Directive.js +7 -8
  66. package/src/index.scss +3 -9
  67. package/src/vue-plugin.js +91 -92
  68. package/tsconfig.json +35 -0
@@ -1,660 +1,660 @@
1
- <template>
2
- <q-input
3
- dense
4
- outlined
5
- :class="{
6
- 'text-Grey_Default bg-Grey_Lighten-5': isDisable,
7
- 's-date-range-picker--inside': insideLabel,
8
- }"
9
- readonly
10
- class="q-pa-none s-date-range-picker bg-white"
11
- v-model="inputDate"
12
- :disable="isDisable"
13
- @click="calendarOpen = true"
14
- data-cy="rangeCalendar"
15
- >
16
- <template #before v-if="insideLabel">
17
- <div class="date-picker-label">
18
- {{ insideLabel }}
19
- </div>
20
- </template>
21
- <template #prepend>
22
- <q-btn
23
- :icon="dateRangeIcon"
24
- dense
25
- :ripple="false"
26
- flat
27
- class="q-pa-none no-hover"
28
- color="Grey_Darken-4"
29
- >
30
- <q-menu
31
- v-model="calendarOpen"
32
- fit
33
- class="date-picker-range-wrapper"
34
- ref="dateMenuRef"
35
- >
36
- <q-date
37
- v-model="dateValue.from"
38
- minimal
39
- square
40
- color="positive"
41
- class="q-pa-none"
42
- mask="YYYY-MM-DD"
43
- :locale="lang ? locale[lang] : {}"
44
- :options="optionsStartFn"
45
- @range-start="getRangeStartDay"
46
- />
47
- <q-separator vertical />
48
- <q-date
49
- v-model="dateValue.to"
50
- minimal
51
- square
52
- color="positive"
53
- class="q-pa-none"
54
- mask="YYYY-MM-DD"
55
- :locale="lang ? locale[lang] : {}"
56
- :options="optionsEndFn"
57
- @range-end="getRangeEndDay"
58
- >
59
- <q-btn
60
- class="reset-to-today-btn no-shadow no-hover"
61
- unelevated
62
- text-color="black"
63
- :label="lang ? locale[lang].today : '오늘'"
64
- @click="resetDate"
65
- />
66
- </q-date>
67
- </q-menu>
68
- </q-btn>
69
- </template>
70
- <template #default>
71
- <div class="flex no-wrap items-center">
72
- <q-input
73
- v-if="useInput"
74
- dense
75
- borderless
76
- v-model="dateValue.from"
77
- autocomplete="off"
78
- mask="####-##-##"
79
- class="inner-input"
80
- />
81
- <span v-else class="text-center text-Grey_Darken-4 date-str">{{
82
- dateValue.from
83
- }}</span>
84
- <span class="q-mx-sm" style="min-width: 0">~</span>
85
- <q-input
86
- v-if="useInput"
87
- dense
88
- borderless
89
- v-model="dateValue.to"
90
- autocomplete="off"
91
- mask="####-##-##"
92
- class="inner-input"
93
- />
94
- <span v-else class="text-center text-Grey_Darken-4 date-str">{{
95
- dateValue.to
96
- }}</span>
97
- </div>
98
- </template>
99
- <template #append v-if="useDelete">
100
- <q-icon
101
- :name="closeIcon"
102
- size="16px"
103
- class="cursor-pointer"
104
- @click="deleteDate"
105
- data-cy="delete-icon"
106
- />
107
- </template>
108
- </q-input>
109
- </template>
110
-
111
- <script>
112
- const locale = {
113
- ko: {
114
- today: '오늘',
115
- daysShort: ['일', '월', '화', '수', '목', '금', '토'],
116
- months: [
117
- '1월',
118
- '2월',
119
- '3월',
120
- '4월',
121
- '5월',
122
- '6월',
123
- '7월',
124
- '8월',
125
- '9월',
126
- '10월',
127
- '11월',
128
- '12월',
129
- ],
130
- monthsShort: [
131
- '1월',
132
- '2월',
133
- '3월',
134
- '4월',
135
- '5월',
136
- '6월',
137
- '7월',
138
- '8월',
139
- '9월',
140
- '10월',
141
- '11월',
142
- '12월',
143
- ],
144
- },
145
- ja: {
146
- today: '今日',
147
- daysShort: ['日', '月', '火', '水', '木', '金', '土'],
148
- months: [
149
- '1月',
150
- '2月',
151
- '3月',
152
- '4月',
153
- '5月',
154
- '6月',
155
- '7月',
156
- '8月',
157
- '9月',
158
- '10月',
159
- '11月',
160
- '12月',
161
- ],
162
- monthsShort: [
163
- '1月',
164
- '2月',
165
- '3月',
166
- '4月',
167
- '5月',
168
- '6月',
169
- '7月',
170
- '8月',
171
- '9月',
172
- '10月',
173
- '11月',
174
- '12月',
175
- ],
176
- },
177
- };
178
- import { defineComponent, ref, watch } from 'vue';
179
- import { QInput, QBtn, QDate, QMenu, QIcon, QSeparator, date } from 'quasar';
180
- import { dateRangeIcon, closeIcon } from '../assets/icons.js';
181
- import { useModelBinder } from '../composables/modelBinder';
182
-
183
- export default defineComponent({
184
- name: 'SDateRangePicker',
185
- components: {
186
- QInput,
187
- QBtn,
188
- QDate,
189
- QMenu,
190
- QIcon,
191
- QSeparator,
192
- },
193
- props: {
194
- isDisable: Boolean,
195
- insideLabel: String,
196
- useInput: Boolean,
197
- rangeDate: {
198
- type: [Number, Object, null],
199
- /**
200
- * 얼마 후인지 제한
201
- * 기본 디폴트 month
202
- * day, month, year
203
- */
204
- default: () => 1,
205
- },
206
- modelValue: {
207
- type: [String, Object],
208
- },
209
- useDelete: {
210
- type: Boolean,
211
- default: false,
212
- },
213
- lang: {
214
- type: String,
215
- default: '',
216
- require: false,
217
- },
218
- // 날짜 제한
219
- dateLimit: {
220
- type: Object,
221
- default: () => ({ from: '', to: '' }),
222
- },
223
- },
224
- setup(props, { emit }) {
225
- const calendarOpen = ref(false);
226
- const dateValue = useModelBinder(props);
227
- const inputDate = ref(`${dateValue.value.from} ~ ${dateValue.value.to}`);
228
- const dateMenuRef = ref(null);
229
-
230
- function resetDate() {
231
- const todayReset = date.formatDate(new Date(), 'YYYY/MM/DD');
232
- dateValue.value.from = date.formatDate(todayReset, 'YYYY-MM-DD');
233
- dateValue.value.to = date.formatDate(todayReset, 'YYYY-MM-DD');
234
- }
235
-
236
- function deleteDate() {
237
- if (dateValue.value.from && dateValue.value.to) {
238
- dateValue.value.from = null;
239
- dateValue.value.to = null;
240
- emit('update:modelValue', dateValue.value);
241
- }
242
- }
243
-
244
- watch(
245
- () => props.isDisable,
246
- val => {
247
- if (val) {
248
- dateMenuRef.value.hide();
249
- }
250
- },
251
- );
252
-
253
- const startDate = date.formatDate(new Date(), 'YYYY/MM/DD');
254
- const endDate = date.formatDate(new Date(), 'YYYY/MM/DD');
255
-
256
- function getRangeStartDay(from) {
257
- startDate.value = from;
258
- }
259
- function getRangeEndDay(to) {
260
- endDate.value = to;
261
- }
262
-
263
- function optionsStartFn(day) {
264
- if (props.rangeDate === null) return true;
265
- let maxFromDate = date.formatDate(
266
- date.subtractFromDate(
267
- new Date(dateValue.value.to),
268
- typeof props.rangeDate === 'number'
269
- ? { month: props.rangeDate }
270
- : props.rangeDate,
271
- ),
272
- 'YYYY/MM/DD',
273
- );
274
-
275
- if (props.dateLimit.from) {
276
- maxFromDate = date.formatDate(
277
- new Date(
278
- Math.max(new Date(maxFromDate), new Date(props.dateLimit.from)),
279
- ),
280
- 'YYYY/MM/DD',
281
- );
282
- }
283
-
284
- if (!dateValue.value.to) {
285
- return true;
286
- }
287
-
288
- const dayTo = date.formatDate(dateValue.value.to, 'YYYY/MM/DD');
289
- return maxFromDate <= day && day <= dayTo;
290
- }
291
-
292
- function optionsEndFn(day) {
293
- const todayForat = date.formatDate(new Date(), 'YYYY/MM/DD');
294
- if (props.rangeDate === null) return day <= todayForat;
295
- const dayFrom = date.formatDate(dateValue.value.from, 'YYYY/MM/DD');
296
- let maxToDate = date.formatDate(
297
- date.addToDate(
298
- new Date(dateValue.value.from),
299
- typeof props.rangeDate === 'number'
300
- ? { month: props.rangeDate }
301
- : props.rangeDate,
302
- ),
303
- 'YYYY/MM/DD',
304
- );
305
-
306
- if (props.dateLimit.to) {
307
- maxToDate = date.formatDate(
308
- new Date(
309
- Math.min(new Date(maxToDate), new Date(props.dateLimit.to)),
310
- ),
311
- 'YYYY/MM/DD',
312
- );
313
- }
314
- if (!dateValue.value.from) {
315
- return true;
316
- }
317
- return dayFrom <= day && day <= maxToDate;
318
- }
319
-
320
- return {
321
- dateRangeIcon,
322
- locale,
323
- calendarOpen,
324
- dateValue,
325
- inputDate,
326
- resetDate,
327
- getRangeStartDay,
328
- getRangeEndDay,
329
- optionsStartFn,
330
- optionsEndFn,
331
- closeIcon,
332
- deleteDate,
333
- dateMenuRef,
334
- };
335
- },
336
- });
337
- </script>
338
-
339
- <style lang="scss">
340
- @import '../css/quasar.variables.scss';
341
-
342
- .s-date-range-picker {
343
- width: fit-content;
344
- height: $default-height;
345
-
346
- &.q-field--dense .q-field__before {
347
- padding: 0;
348
- height: 100%;
349
- }
350
-
351
- .q-field__inner {
352
- font-size: 12px;
353
-
354
- .q-field__control {
355
- padding: 4px 0 4px 8px !important;
356
- align-items: center;
357
- height: 100%;
358
-
359
- .q-field__prepend {
360
- .q-icon {
361
- width: 20px;
362
- height: 20px;
363
- color: $Grey_Darken-1;
364
- }
365
- }
366
-
367
- &:after {
368
- border: 1px solid $Grey_Lighten-1;
369
- box-shadow: none;
370
- }
371
-
372
- &:hover,
373
- &:active {
374
- background: $Grey_Lighten-5;
375
- }
376
-
377
- .q-field__prepend {
378
- height: $default-content-height;
379
- padding: 0;
380
-
381
- > div {
382
- min-height: 0;
383
- height: 100%;
384
- display: flex !important;
385
- align-items: center;
386
- justify-content: center;
387
-
388
- .q-btn {
389
- width: $default-content-size;
390
- height: $default-content-size;
391
- min-height: $default-content-size;
392
-
393
- .q-icon {
394
- font-size: $icon-size-lg;
395
- }
396
- }
397
- }
398
- }
399
-
400
- &-container {
401
- > input {
402
- display: none;
403
- }
404
-
405
- display: flex;
406
- justify-content: center;
407
- height: $default-content-height;
408
- margin-left: 12px;
409
- margin-right: 16px;
410
-
411
- .q-field__native {
412
- height: 100%;
413
- line-height: $default-line-height;
414
- text-align: center;
415
- padding: 0 !important;
416
- display: none;
417
-
418
- font: {
419
- size: $default-font;
420
- weight: $default-font-weight;
421
- }
422
-
423
- input::placeholder {
424
- color: $Grey_Darken-4;
425
- }
426
- }
427
- }
428
-
429
- .q-field__append {
430
- padding: 0 6px 0 0;
431
- }
432
- }
433
- }
434
-
435
- .inner-input {
436
- > .q-field__inner {
437
- > .q-field__control {
438
- width: 70px;
439
- padding: 0px !important;
440
-
441
- &::before,
442
- &::after {
443
- border: none;
444
- }
445
-
446
- > .q-field__control-container {
447
- margin: 0px;
448
-
449
- input {
450
- display: block !important;
451
- }
452
- }
453
- }
454
- }
455
- }
456
-
457
- .date-str {
458
- width: 70px;
459
- line-height: $default-content-height;
460
- justify-content: center;
461
- }
462
-
463
- &--inside {
464
- .q-field__before {
465
- height: 100%;
466
- padding: 4px 12px !important;
467
- border: 1px solid $Grey_Lighten-1;
468
- border-right: none;
469
- border-radius: $generic-border-radius 0 0 $generic-border-radius;
470
- background: $Grey_Lighten-5;
471
-
472
- .date-picker-label {
473
- font-size: $default-font;
474
- font-weight: $default-font-weight;
475
- color: $Grey_Darken-4;
476
- }
477
- }
478
-
479
- .q-field__inner {
480
- .q-field__control {
481
- border-radius: 0 2px 2px 0;
482
- width: 220px;
483
-
484
- .q-field__prepend {
485
- .q-icon {
486
- width: 20px;
487
- height: 20px;
488
- color: $Grey_Darken-1;
489
- }
490
- }
491
-
492
- &-container {
493
- > input {
494
- display: none;
495
- }
496
-
497
- > div {
498
- margin-left: 6.5px;
499
-
500
- > span {
501
- display: inline-flex;
502
- min-width: 70px;
503
- font-size: 12px !important;
504
- }
505
- }
506
- }
507
- }
508
- }
509
-
510
- &.q-field--disabled {
511
- .q-field__before {
512
- border: 1px solid $Grey_Lighten-2;
513
- border-right: none;
514
-
515
- .date-picker-label {
516
- color: $Grey_Default;
517
- }
518
- }
519
- }
520
- }
521
- }
522
-
523
- .date-picker-range-wrapper.q-menu {
524
- width: 609px;
525
- height: 330px;
526
- max-height: 330px;
527
- overflow: hidden;
528
- border-radius: 8px;
529
- position: relative;
530
-
531
- min: {
532
- width: 0 !important;
533
- height: 0 !important;
534
- }
535
-
536
- .q-separator {
537
- position: absolute;
538
- height: 244px;
539
- left: 304px;
540
- top: 62px;
541
- }
542
-
543
- .q-date {
544
- position: absolute;
545
- min-height: 330px;
546
- top: 0;
547
- box-shadow: none;
548
- width: 304px;
549
-
550
- &:first-of-type {
551
- left: 0;
552
- }
553
-
554
- &:last-of-type {
555
- right: 0;
556
- }
557
-
558
- &__main {
559
- .q-date__actions {
560
- padding: 0 !important;
561
-
562
- > .reset-to-today-btn {
563
- padding: 0;
564
- width: 28px;
565
- height: 22px;
566
- min-height: 22px;
567
- position: absolute;
568
- background: transparent;
569
- top: 20px;
570
- right: 24px;
571
-
572
- > span {
573
- color: $Grey_Darken-4;
574
- text-decoration: underline;
575
- color: $Grey_Darken-4;
576
- }
577
- }
578
-
579
- &:hover {
580
- .q-btn__content {
581
- text-decoration: underline;
582
- color: $positive;
583
- }
584
- }
585
- }
586
-
587
- .q-date__content {
588
- margin-top: 42px;
589
-
590
- .q-date__view {
591
- min-height: 0 !important;
592
- padding-bottom: 0;
593
-
594
- .q-date__navigation {
595
- div {
596
- height: 28px;
597
-
598
- .q-btn {
599
- .q-icon {
600
- font-size: $default-font;
601
- }
602
- }
603
- }
604
-
605
- .relative-position {
606
- div {
607
- .q-btn--dense {
608
- padding: 0 !important;
609
-
610
- .q-btn__content {
611
- > span {
612
- font-size: 14px;
613
- }
614
- }
615
- }
616
- }
617
- }
618
- }
619
-
620
- .q-date__calendar-days-container {
621
- min-height: 172px;
622
-
623
- .q-date__calendar-days {
624
- .q-date__calendar-item {
625
- .q-btn {
626
- padding: 0;
627
-
628
- .q-btn__content {
629
- > span {
630
- font-size: 14px;
631
- }
632
- }
633
-
634
- &:hover {
635
- .q-focus-helper {
636
- background: $positive;
637
- opacity: 1;
638
-
639
- &:before,
640
- &:after {
641
- display: none;
642
- }
643
- }
644
-
645
- .q-btn__content {
646
- > span {
647
- color: white;
648
- }
649
- }
650
- }
651
- }
652
- }
653
- }
654
- }
655
- }
656
- }
657
- }
658
- }
659
- }
660
- </style>
1
+ <template>
2
+ <q-input
3
+ dense
4
+ outlined
5
+ :class="{
6
+ 'text-Grey_Default bg-Grey_Lighten-5': isDisable,
7
+ 's-date-range-picker--inside': insideLabel,
8
+ }"
9
+ readonly
10
+ class="q-pa-none s-date-range-picker bg-white"
11
+ v-model="inputDate"
12
+ :disable="isDisable"
13
+ @click="calendarOpen = true"
14
+ data-cy="rangeCalendar"
15
+ >
16
+ <template #before v-if="insideLabel">
17
+ <div class="date-picker-label">
18
+ {{ insideLabel }}
19
+ </div>
20
+ </template>
21
+ <template #prepend>
22
+ <q-btn
23
+ :icon="dateRangeIcon"
24
+ dense
25
+ :ripple="false"
26
+ flat
27
+ class="q-pa-none no-hover"
28
+ color="Grey_Darken-4"
29
+ >
30
+ <q-menu
31
+ v-model="calendarOpen"
32
+ fit
33
+ class="date-picker-range-wrapper"
34
+ ref="dateMenuRef"
35
+ >
36
+ <q-date
37
+ v-model="dateValue.from"
38
+ minimal
39
+ square
40
+ color="positive"
41
+ class="q-pa-none"
42
+ mask="YYYY-MM-DD"
43
+ :locale="lang ? locale[lang] : {}"
44
+ :options="optionsStartFn"
45
+ @range-start="getRangeStartDay"
46
+ />
47
+ <q-separator vertical />
48
+ <q-date
49
+ v-model="dateValue.to"
50
+ minimal
51
+ square
52
+ color="positive"
53
+ class="q-pa-none"
54
+ mask="YYYY-MM-DD"
55
+ :locale="lang ? locale[lang] : {}"
56
+ :options="optionsEndFn"
57
+ @range-end="getRangeEndDay"
58
+ >
59
+ <q-btn
60
+ class="reset-to-today-btn no-shadow no-hover"
61
+ unelevated
62
+ text-color="black"
63
+ :label="lang ? locale[lang].today : '오늘'"
64
+ @click="resetDate"
65
+ />
66
+ </q-date>
67
+ </q-menu>
68
+ </q-btn>
69
+ </template>
70
+ <template #default>
71
+ <div class="flex no-wrap items-center">
72
+ <q-input
73
+ v-if="useInput"
74
+ dense
75
+ borderless
76
+ v-model="dateValue.from"
77
+ autocomplete="off"
78
+ mask="####-##-##"
79
+ class="inner-input"
80
+ />
81
+ <span v-else class="text-center text-Grey_Darken-4 date-str">{{
82
+ dateValue.from
83
+ }}</span>
84
+ <span class="q-mx-sm" style="min-width: 0">~</span>
85
+ <q-input
86
+ v-if="useInput"
87
+ dense
88
+ borderless
89
+ v-model="dateValue.to"
90
+ autocomplete="off"
91
+ mask="####-##-##"
92
+ class="inner-input"
93
+ />
94
+ <span v-else class="text-center text-Grey_Darken-4 date-str">{{
95
+ dateValue.to
96
+ }}</span>
97
+ </div>
98
+ </template>
99
+ <template #append v-if="useDelete">
100
+ <q-icon
101
+ :name="closeIcon"
102
+ size="16px"
103
+ class="cursor-pointer"
104
+ @click="deleteDate"
105
+ data-cy="delete-icon"
106
+ />
107
+ </template>
108
+ </q-input>
109
+ </template>
110
+
111
+ <script>
112
+ const locale = {
113
+ ko: {
114
+ today: '오늘',
115
+ daysShort: ['일', '월', '화', '수', '목', '금', '토'],
116
+ months: [
117
+ '1월',
118
+ '2월',
119
+ '3월',
120
+ '4월',
121
+ '5월',
122
+ '6월',
123
+ '7월',
124
+ '8월',
125
+ '9월',
126
+ '10월',
127
+ '11월',
128
+ '12월',
129
+ ],
130
+ monthsShort: [
131
+ '1월',
132
+ '2월',
133
+ '3월',
134
+ '4월',
135
+ '5월',
136
+ '6월',
137
+ '7월',
138
+ '8월',
139
+ '9월',
140
+ '10월',
141
+ '11월',
142
+ '12월',
143
+ ],
144
+ },
145
+ ja: {
146
+ today: '今日',
147
+ daysShort: ['日', '月', '火', '水', '木', '金', '土'],
148
+ months: [
149
+ '1月',
150
+ '2月',
151
+ '3月',
152
+ '4月',
153
+ '5月',
154
+ '6月',
155
+ '7月',
156
+ '8月',
157
+ '9月',
158
+ '10月',
159
+ '11月',
160
+ '12月',
161
+ ],
162
+ monthsShort: [
163
+ '1月',
164
+ '2月',
165
+ '3月',
166
+ '4月',
167
+ '5月',
168
+ '6月',
169
+ '7月',
170
+ '8月',
171
+ '9月',
172
+ '10月',
173
+ '11月',
174
+ '12月',
175
+ ],
176
+ },
177
+ };
178
+ import { defineComponent, ref, watch } from 'vue';
179
+ import { QInput, QBtn, QDate, QMenu, QIcon, QSeparator, date } from 'quasar';
180
+ import { dateRangeIcon, closeIcon } from '../assets/icons.js';
181
+ import { useModelBinder } from '../composables/modelBinder';
182
+
183
+ export default defineComponent({
184
+ name: 'SDateRangePicker',
185
+ components: {
186
+ QInput,
187
+ QBtn,
188
+ QDate,
189
+ QMenu,
190
+ QIcon,
191
+ QSeparator,
192
+ },
193
+ props: {
194
+ isDisable: Boolean,
195
+ insideLabel: String,
196
+ useInput: Boolean,
197
+ rangeDate: {
198
+ type: [Number, Object, null],
199
+ /**
200
+ * 얼마 후인지 제한
201
+ * 기본 디폴트 month
202
+ * day, month, year
203
+ */
204
+ default: () => 1,
205
+ },
206
+ modelValue: {
207
+ type: [String, Object],
208
+ },
209
+ useDelete: {
210
+ type: Boolean,
211
+ default: false,
212
+ },
213
+ lang: {
214
+ type: String,
215
+ default: '',
216
+ require: false,
217
+ },
218
+ // 날짜 제한
219
+ dateLimit: {
220
+ type: Object,
221
+ default: () => ({ from: '', to: '' }),
222
+ },
223
+ },
224
+ setup(props, { emit }) {
225
+ const calendarOpen = ref(false);
226
+ const dateValue = useModelBinder(props);
227
+ const inputDate = ref(`${dateValue.value.from} ~ ${dateValue.value.to}`);
228
+ const dateMenuRef = ref(null);
229
+
230
+ function resetDate() {
231
+ const todayReset = date.formatDate(new Date(), 'YYYY/MM/DD');
232
+ dateValue.value.from = date.formatDate(todayReset, 'YYYY-MM-DD');
233
+ dateValue.value.to = date.formatDate(todayReset, 'YYYY-MM-DD');
234
+ }
235
+
236
+ function deleteDate() {
237
+ if (dateValue.value.from && dateValue.value.to) {
238
+ dateValue.value.from = null;
239
+ dateValue.value.to = null;
240
+ emit('update:modelValue', dateValue.value);
241
+ }
242
+ }
243
+
244
+ watch(
245
+ () => props.isDisable,
246
+ val => {
247
+ if (val) {
248
+ dateMenuRef.value.hide();
249
+ }
250
+ },
251
+ );
252
+
253
+ const startDate = date.formatDate(new Date(), 'YYYY/MM/DD');
254
+ const endDate = date.formatDate(new Date(), 'YYYY/MM/DD');
255
+
256
+ function getRangeStartDay(from) {
257
+ startDate.value = from;
258
+ }
259
+ function getRangeEndDay(to) {
260
+ endDate.value = to;
261
+ }
262
+
263
+ function optionsStartFn(day) {
264
+ if (props.rangeDate === null) return true;
265
+ let maxFromDate = date.formatDate(
266
+ date.subtractFromDate(
267
+ new Date(dateValue.value.to),
268
+ typeof props.rangeDate === 'number'
269
+ ? { month: props.rangeDate }
270
+ : props.rangeDate,
271
+ ),
272
+ 'YYYY/MM/DD',
273
+ );
274
+
275
+ if (props.dateLimit.from) {
276
+ maxFromDate = date.formatDate(
277
+ new Date(
278
+ Math.max(new Date(maxFromDate), new Date(props.dateLimit.from)),
279
+ ),
280
+ 'YYYY/MM/DD',
281
+ );
282
+ }
283
+
284
+ if (!dateValue.value.to) {
285
+ return true;
286
+ }
287
+
288
+ const dayTo = date.formatDate(dateValue.value.to, 'YYYY/MM/DD');
289
+ return maxFromDate <= day && day <= dayTo;
290
+ }
291
+
292
+ function optionsEndFn(day) {
293
+ const todayForat = date.formatDate(new Date(), 'YYYY/MM/DD');
294
+ if (props.rangeDate === null) return day <= todayForat;
295
+ const dayFrom = date.formatDate(dateValue.value.from, 'YYYY/MM/DD');
296
+ let maxToDate = date.formatDate(
297
+ date.addToDate(
298
+ new Date(dateValue.value.from),
299
+ typeof props.rangeDate === 'number'
300
+ ? { month: props.rangeDate }
301
+ : props.rangeDate,
302
+ ),
303
+ 'YYYY/MM/DD',
304
+ );
305
+
306
+ if (props.dateLimit.to) {
307
+ maxToDate = date.formatDate(
308
+ new Date(
309
+ Math.min(new Date(maxToDate), new Date(props.dateLimit.to)),
310
+ ),
311
+ 'YYYY/MM/DD',
312
+ );
313
+ }
314
+ if (!dateValue.value.from) {
315
+ return true;
316
+ }
317
+ return dayFrom <= day && day <= maxToDate;
318
+ }
319
+
320
+ return {
321
+ dateRangeIcon,
322
+ locale,
323
+ calendarOpen,
324
+ dateValue,
325
+ inputDate,
326
+ resetDate,
327
+ getRangeStartDay,
328
+ getRangeEndDay,
329
+ optionsStartFn,
330
+ optionsEndFn,
331
+ closeIcon,
332
+ deleteDate,
333
+ dateMenuRef,
334
+ };
335
+ },
336
+ });
337
+ </script>
338
+
339
+ <style lang="scss">
340
+ @import '../css/quasar.variables.scss';
341
+
342
+ .s-date-range-picker {
343
+ width: fit-content;
344
+ height: $default-height;
345
+
346
+ &.q-field--dense .q-field__before {
347
+ padding: 0;
348
+ height: 100%;
349
+ }
350
+
351
+ .q-field__inner {
352
+ font-size: 12px;
353
+
354
+ .q-field__control {
355
+ padding: 4px 0 4px 8px !important;
356
+ align-items: center;
357
+ height: 100%;
358
+
359
+ .q-field__prepend {
360
+ .q-icon {
361
+ width: 20px;
362
+ height: 20px;
363
+ color: $Grey_Darken-1;
364
+ }
365
+ }
366
+
367
+ &:after {
368
+ border: 1px solid $Grey_Lighten-1;
369
+ box-shadow: none;
370
+ }
371
+
372
+ &:hover,
373
+ &:active {
374
+ background: $Grey_Lighten-5;
375
+ }
376
+
377
+ .q-field__prepend {
378
+ height: $default-content-height;
379
+ padding: 0;
380
+
381
+ > div {
382
+ min-height: 0;
383
+ height: 100%;
384
+ display: flex !important;
385
+ align-items: center;
386
+ justify-content: center;
387
+
388
+ .q-btn {
389
+ width: $default-content-size;
390
+ height: $default-content-size;
391
+ min-height: $default-content-size;
392
+
393
+ .q-icon {
394
+ font-size: $icon-size-lg;
395
+ }
396
+ }
397
+ }
398
+ }
399
+
400
+ &-container {
401
+ > input {
402
+ display: none;
403
+ }
404
+
405
+ display: flex;
406
+ justify-content: center;
407
+ height: $default-content-height;
408
+ margin-left: 12px;
409
+ margin-right: 16px;
410
+
411
+ .q-field__native {
412
+ height: 100%;
413
+ line-height: $default-line-height;
414
+ text-align: center;
415
+ padding: 0 !important;
416
+ display: none;
417
+
418
+ font: {
419
+ size: $default-font;
420
+ weight: $default-font-weight;
421
+ }
422
+
423
+ input::placeholder {
424
+ color: $Grey_Darken-4;
425
+ }
426
+ }
427
+ }
428
+
429
+ .q-field__append {
430
+ padding: 0 6px 0 0;
431
+ }
432
+ }
433
+ }
434
+
435
+ .inner-input {
436
+ > .q-field__inner {
437
+ > .q-field__control {
438
+ width: 70px;
439
+ padding: 0px !important;
440
+
441
+ &::before,
442
+ &::after {
443
+ border: none;
444
+ }
445
+
446
+ > .q-field__control-container {
447
+ margin: 0px;
448
+
449
+ input {
450
+ display: block !important;
451
+ }
452
+ }
453
+ }
454
+ }
455
+ }
456
+
457
+ .date-str {
458
+ width: 70px;
459
+ line-height: $default-content-height;
460
+ justify-content: center;
461
+ }
462
+
463
+ &--inside {
464
+ .q-field__before {
465
+ height: 100%;
466
+ padding: 4px 12px !important;
467
+ border: 1px solid $Grey_Lighten-1;
468
+ border-right: none;
469
+ border-radius: $generic-border-radius 0 0 $generic-border-radius;
470
+ background: $Grey_Lighten-5;
471
+
472
+ .date-picker-label {
473
+ font-size: $default-font;
474
+ font-weight: $default-font-weight;
475
+ color: $Grey_Darken-4;
476
+ }
477
+ }
478
+
479
+ .q-field__inner {
480
+ .q-field__control {
481
+ border-radius: 0 2px 2px 0;
482
+ width: 220px;
483
+
484
+ .q-field__prepend {
485
+ .q-icon {
486
+ width: 20px;
487
+ height: 20px;
488
+ color: $Grey_Darken-1;
489
+ }
490
+ }
491
+
492
+ &-container {
493
+ > input {
494
+ display: none;
495
+ }
496
+
497
+ > div {
498
+ margin-left: 6.5px;
499
+
500
+ > span {
501
+ display: inline-flex;
502
+ min-width: 70px;
503
+ font-size: 12px !important;
504
+ }
505
+ }
506
+ }
507
+ }
508
+ }
509
+
510
+ &.q-field--disabled {
511
+ .q-field__before {
512
+ border: 1px solid $Grey_Lighten-2;
513
+ border-right: none;
514
+
515
+ .date-picker-label {
516
+ color: $Grey_Default;
517
+ }
518
+ }
519
+ }
520
+ }
521
+ }
522
+
523
+ .date-picker-range-wrapper.q-menu {
524
+ width: 609px;
525
+ height: 330px;
526
+ max-height: 330px;
527
+ overflow: hidden;
528
+ border-radius: 8px;
529
+ position: relative;
530
+
531
+ min: {
532
+ width: 0 !important;
533
+ height: 0 !important;
534
+ }
535
+
536
+ .q-separator {
537
+ position: absolute;
538
+ height: 244px;
539
+ left: 304px;
540
+ top: 62px;
541
+ }
542
+
543
+ .q-date {
544
+ position: absolute;
545
+ min-height: 330px;
546
+ top: 0;
547
+ box-shadow: none;
548
+ width: 304px;
549
+
550
+ &:first-of-type {
551
+ left: 0;
552
+ }
553
+
554
+ &:last-of-type {
555
+ right: 0;
556
+ }
557
+
558
+ &__main {
559
+ .q-date__actions {
560
+ padding: 0 !important;
561
+
562
+ > .reset-to-today-btn {
563
+ padding: 0;
564
+ width: 28px;
565
+ height: 22px;
566
+ min-height: 22px;
567
+ position: absolute;
568
+ background: transparent;
569
+ top: 20px;
570
+ right: 24px;
571
+
572
+ > span {
573
+ color: $Grey_Darken-4;
574
+ text-decoration: underline;
575
+ color: $Grey_Darken-4;
576
+ }
577
+ }
578
+
579
+ &:hover {
580
+ .q-btn__content {
581
+ text-decoration: underline;
582
+ color: $positive;
583
+ }
584
+ }
585
+ }
586
+
587
+ .q-date__content {
588
+ margin-top: 42px;
589
+
590
+ .q-date__view {
591
+ min-height: 0 !important;
592
+ padding-bottom: 0;
593
+
594
+ .q-date__navigation {
595
+ div {
596
+ height: 28px;
597
+
598
+ .q-btn {
599
+ .q-icon {
600
+ font-size: $default-font;
601
+ }
602
+ }
603
+ }
604
+
605
+ .relative-position {
606
+ div {
607
+ .q-btn--dense {
608
+ padding: 0 !important;
609
+
610
+ .q-btn__content {
611
+ > span {
612
+ font-size: 14px;
613
+ }
614
+ }
615
+ }
616
+ }
617
+ }
618
+ }
619
+
620
+ .q-date__calendar-days-container {
621
+ min-height: 172px;
622
+
623
+ .q-date__calendar-days {
624
+ .q-date__calendar-item {
625
+ .q-btn {
626
+ padding: 0;
627
+
628
+ .q-btn__content {
629
+ > span {
630
+ font-size: 14px;
631
+ }
632
+ }
633
+
634
+ &:hover {
635
+ .q-focus-helper {
636
+ background: $positive;
637
+ opacity: 1;
638
+
639
+ &:before,
640
+ &:after {
641
+ display: none;
642
+ }
643
+ }
644
+
645
+ .q-btn__content {
646
+ > span {
647
+ color: white;
648
+ }
649
+ }
650
+ }
651
+ }
652
+ }
653
+ }
654
+ }
655
+ }
656
+ }
657
+ }
658
+ }
659
+ }
660
+ </style>