renusify 2.5.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 (212) hide show
  1. package/components/app/index.vue +74 -22
  2. package/components/app/toast/index.vue +76 -71
  3. package/components/app/toast/toast.vue +62 -44
  4. package/components/avatar/index.vue +207 -84
  5. package/components/button/buttonConfirm.vue +53 -26
  6. package/components/button/buttonGroup.js +0 -2
  7. package/components/button/buttonGroup.vue +310 -62
  8. package/components/button/index.vue +584 -100
  9. package/components/calendar/index.js +0 -2
  10. package/components/calendar/index.vue +326 -262
  11. package/components/calendar/month.vue +64 -55
  12. package/components/calendar/year.vue +30 -25
  13. package/components/card/index.vue +139 -59
  14. package/components/codeEditor/highlightCss.vue +38 -39
  15. package/components/codeEditor/highlightHtml.vue +64 -64
  16. package/components/codeEditor/highlightJs.vue +37 -38
  17. package/components/codeEditor/index.vue +129 -79
  18. package/components/codeEditor/run.vue +225 -39
  19. package/components/codeEditor/useCodeFormatter.js +150 -0
  20. package/components/confirm/index.vue +139 -80
  21. package/components/container/col.vue +5 -4
  22. package/components/container/divider.vue +28 -19
  23. package/components/container/index.vue +34 -15
  24. package/components/container/row.vue +26 -9
  25. package/components/container/spacer.vue +2 -4
  26. package/components/container/style.scss +3 -0
  27. package/components/content/index.vue +49 -32
  28. package/components/cropper/index.vue +401 -244
  29. package/components/float/index.vue +542 -415
  30. package/components/form/addressInput/index.vue +184 -109
  31. package/components/form/camInput/index.vue +370 -244
  32. package/components/form/checkInput/index.vue +138 -71
  33. package/components/form/checkboxInput/index.vue +93 -49
  34. package/components/form/colorInput/Alpha.vue +81 -83
  35. package/components/form/colorInput/Hue.vue +91 -68
  36. package/components/form/colorInput/Preview.vue +43 -47
  37. package/components/form/colorInput/Saturation.vue +101 -86
  38. package/components/form/colorInput/index.vue +71 -39
  39. package/components/form/colorInput/picker.vue +111 -106
  40. package/components/form/colorInput/useColor.js +153 -0
  41. package/components/form/dateInput/index.vue +691 -356
  42. package/components/form/dateInput/month.vue +63 -54
  43. package/components/form/dateInput/year.vue +35 -25
  44. package/components/form/fileInput/index.js +0 -1
  45. package/components/form/fileInput/index.vue +263 -106
  46. package/components/form/fileInput/single.vue +332 -168
  47. package/components/form/groupInput/index.vue +199 -101
  48. package/components/form/index.vue +189 -83
  49. package/components/form/input/index.vue +416 -377
  50. package/components/form/jsonInput/JsonView.vue +54 -56
  51. package/components/form/jsonInput/index.vue +247 -165
  52. package/components/form/maskInput/index.vue +252 -132
  53. package/components/form/numberInput/index.js +0 -1
  54. package/components/form/numberInput/index.vue +226 -117
  55. package/components/form/passwordInput/index.js +2 -1
  56. package/components/form/passwordInput/index.vue +269 -102
  57. package/components/form/radioInput/index.vue +143 -72
  58. package/components/form/rangeInput/index.vue +280 -167
  59. package/components/form/ratingInput/index.vue +57 -57
  60. package/components/form/selectInput/index.js +1 -3
  61. package/components/form/selectInput/index.vue +584 -296
  62. package/components/form/switchInput/index.vue +73 -59
  63. package/components/form/telInput/index.js +0 -1
  64. package/components/form/telInput/index.vue +238 -135
  65. package/components/form/textArea/index.vue +72 -35
  66. package/components/form/textEditor/index.vue +739 -0
  67. package/components/form/{text-editor → textEditor}/style.scss +8 -16
  68. package/components/form/textInput/index.vue +54 -32
  69. package/components/form/timeInput/index.vue +82 -55
  70. package/components/form/timeInput/range.vue +115 -94
  71. package/components/form/timeInput/timepicker.vue +382 -449
  72. package/components/form/uniqueInput/index.vue +105 -48
  73. package/components/form/unitInput/index.vue +139 -84
  74. package/components/formCreator/index.js +0 -1
  75. package/components/formCreator/index.vue +314 -148
  76. package/components/highlight/index.vue +41 -25
  77. package/components/highlight/style.scss +2 -2
  78. package/components/highlight/{mixin.js → useHighlight.js} +181 -160
  79. package/components/icon/index.vue +79 -33
  80. package/components/img/index.vue +250 -147
  81. package/components/img/preview.vue +180 -198
  82. package/components/img/svgImg.vue +42 -39
  83. package/components/index.js +5 -20
  84. package/components/infinite/index.js +3 -3
  85. package/components/infinite/index.vue +290 -66
  86. package/components/map/index.vue +428 -261
  87. package/components/map/route.vue +794 -487
  88. package/components/map/select.vue +118 -58
  89. package/components/menu/index.vue +206 -94
  90. package/components/meta/meta.js +26 -3
  91. package/components/modal/index.vue +382 -156
  92. package/components/notify/index.vue +204 -86
  93. package/components/notify/notification.vue +38 -55
  94. package/components/progress/circle.vue +189 -70
  95. package/components/progress/line.vue +266 -46
  96. package/components/searchBox/index.js +1 -3
  97. package/components/searchBox/index.vue +194 -101
  98. package/components/skeleton/index.vue +45 -20
  99. package/components/slider/index.vue +319 -156
  100. package/components/swiper/index.vue +237 -108
  101. package/components/table/crud/footer.vue +77 -53
  102. package/components/table/crud/header.vue +71 -72
  103. package/components/table/crud/index.vue +629 -399
  104. package/components/table/index.vue +721 -278
  105. package/components/timeAgo/index.vue +145 -96
  106. package/components/tour/index.vue +338 -235
  107. package/components/tree/index.vue +235 -89
  108. package/components/tree/tree-element.vue +106 -106
  109. package/directive/animate/index.js +77 -0
  110. package/directive/clickOutSide/index.js +98 -0
  111. package/directive/drag/index.js +153 -0
  112. package/directive/index.js +11 -13
  113. package/directive/intersect/index.js +263 -0
  114. package/directive/mask/index.js +67 -0
  115. package/directive/parallax/index.js +78 -0
  116. package/directive/ripple/index.js +14 -0
  117. package/directive/scroll/index.js +272 -24
  118. package/directive/sortable/index.js +274 -0
  119. package/directive/title/index.js +75 -0
  120. package/directive/touch/index.js +268 -0
  121. package/index.js +11 -19
  122. package/package.json +5 -2
  123. package/plugins/validation/Validate.js +88 -79
  124. package/scripts/generate-docs.mjs +226 -0
  125. package/scripts/menu.mjs +240 -0
  126. package/scripts/parser.mjs +1086 -0
  127. package/style/_index.scss +7 -0
  128. package/style/app.scss +13 -65
  129. package/style/colors.scss +5 -22
  130. package/style/functions/index.scss +8 -0
  131. package/style/mixins/index.scss +17 -5
  132. package/style/variables/base.scss +155 -178
  133. package/style/variables/color.scss +0 -12
  134. package/style/variables/utilities.scss +0 -180
  135. package/tools/helper.js +0 -8
  136. package/tools/icons.js +7 -2
  137. package/tools/root.js +71 -0
  138. package/components/app/style.scss +0 -41
  139. package/components/app/toast/style.scss +0 -20
  140. package/components/avatar/style.scss +0 -32
  141. package/components/bar/bottomNav.js +0 -1
  142. package/components/bar/bottomNav.vue +0 -28
  143. package/components/bar/bottomNavigationCircle.js +0 -2
  144. package/components/bar/bottomNavigationCircle.vue +0 -99
  145. package/components/bar/scss/bottomNav.scss +0 -67
  146. package/components/bar/scss/toolbar.scss +0 -174
  147. package/components/bar/toolbar/index.js +0 -8
  148. package/components/bar/toolbar/index.vue +0 -35
  149. package/components/bar/toolbar/laptop.vue +0 -33
  150. package/components/bar/toolbar/menuChilds.vue +0 -41
  151. package/components/bar/toolbar/menuLaptop.vue +0 -41
  152. package/components/bar/toolbar/menuMob.vue +0 -39
  153. package/components/bar/toolbar/mixin.js +0 -43
  154. package/components/bar/toolbar/mobile.vue +0 -34
  155. package/components/breadcrumb/bredcrumbItem.vue +0 -39
  156. package/components/breadcrumb/index.js +0 -3
  157. package/components/breadcrumb/index.vue +0 -71
  158. package/components/breadcrumb/style.scss +0 -51
  159. package/components/button/style.scss +0 -411
  160. package/components/card/style.scss +0 -86
  161. package/components/chart/chart.js +0 -1
  162. package/components/chart/chart.vue +0 -69
  163. package/components/chart/worldMap.js +0 -2
  164. package/components/chart/worldMap.vue +0 -1112
  165. package/components/chat/MessageList.vue +0 -163
  166. package/components/chat/chatInput.vue +0 -150
  167. package/components/chat/chatMsg.vue +0 -276
  168. package/components/chat/index.js +0 -11
  169. package/components/chat/index.vue +0 -113
  170. package/components/chip/index.js +0 -3
  171. package/components/chip/index.vue +0 -77
  172. package/components/chip/style.scss +0 -199
  173. package/components/codeEditor/mixin.js +0 -145
  174. package/components/countdown/index.js +0 -1
  175. package/components/countdown/index.vue +0 -105
  176. package/components/form/colorInput/mixin.js +0 -132
  177. package/components/form/fileInput/file.js +0 -148
  178. package/components/form/telInput/assets/flags.png +0 -0
  179. package/components/form/telInput/assets/flags@2x.png +0 -0
  180. package/components/form/text-editor/index.vue +0 -705
  181. package/components/icon/style.scss +0 -17
  182. package/components/infinite/div.js +0 -6
  183. package/components/infinite/div.vue +0 -193
  184. package/components/infinite/page.js +0 -3
  185. package/components/infinite/page.vue +0 -105
  186. package/components/list/index.js +0 -3
  187. package/components/list/index.vue +0 -122
  188. package/components/list/style.scss +0 -66
  189. package/components/message/index.js +0 -4
  190. package/components/message/index.vue +0 -40
  191. package/components/modal/style.scss +0 -146
  192. package/components/nestable/NestableItem.vue +0 -307
  193. package/components/nestable/editable.js +0 -44
  194. package/components/nestable/index.js +0 -1
  195. package/components/nestable/index.vue +0 -226
  196. package/components/nestable/methods.js +0 -416
  197. package/components/progress/style.scss +0 -229
  198. package/components/table/style.scss +0 -338
  199. package/components/tabs/index.js +0 -3
  200. package/components/tabs/index.vue +0 -151
  201. package/components/timeline/index.js +0 -6
  202. package/components/timeline/index.vue +0 -76
  203. package/directive/resize/index.js +0 -30
  204. package/directive/skeleton/index.js +0 -27
  205. package/directive/skeleton/style.scss +0 -37
  206. package/plugins/request/Request.js +0 -68
  207. package/style/animation.scss +0 -94
  208. package/style/style.scss +0 -8
  209. package/tools/rootable.js +0 -75
  210. /package/components/form/{text-editor → textEditor}/index.js +0 -0
  211. /package/components/form/{text-editor → textEditor}/preview.js +0 -0
  212. /package/components/form/{text-editor → textEditor}/preview.vue +0 -0
@@ -1,386 +1,659 @@
1
1
  <template>
2
- <r-input v-bind="$attrs" :readonly="readonly" :model-value="modelValue" @click.prevent="show=true">
3
- <div :class="`${$r.prefix}date-color-input`">
4
- {{ modelValue ? $d(modelValueDate, withTime ? 'long' : 'medium', locale) : null }}
2
+ <r-input :model-value="displayValue" @click.prevent="show=true">
3
+ <div :class="`${$r.prefix}date-color-input`" class="date-range-display">
4
+ {{ displayValue }}
5
5
  </div>
6
- </r-input>
7
- <r-modal :model-value="show" class="text-center" no-close-btn @update:model-value="close()">
8
- <div v-if="!showTime" :class="`${$r.prefix}date-input`">
9
- <div>
10
- <r-container>
11
- <r-row>
12
- <r-col class="col-auto">
13
- <r-btn v-if="tab!=='month'" icon
14
- @click.prevent="tab==='day'?incrementMonth(-1):incrementYear(-12)">
15
- <r-icon v-html="$r.icons.arrow_left"></r-icon>
16
- </r-btn>
17
- </r-col>
18
- <r-col class="text-center">
19
- <r-btn class="me-2" text @click.prevent="tab==='month'?tab='day':tab='month'">
20
- <r-icon v-html="tab==='month'?$r.icons.chevron_up:$r.icons.chevron_down"></r-icon>
21
- {{
22
- $d(new
23
- Date(currentPeriod.year, currentPeriod.month, 1, 0, lang_zone_offset - timezoneOffset), 'month', locale)
24
- }}
25
- </r-btn>
26
-
27
- <r-btn text @click.prevent="tab==='year'?tab='day':tab='year'">
28
- <r-icon v-html="tab==='year'?$r.icons.chevron_up:$r.icons.chevron_down"></r-icon>
29
- {{
30
- $d(new
31
- Date(currentPeriod.year, currentPeriod.month, 1, 0, lang_zone_offset - timezoneOffset), 'year', locale)
32
- }}
33
- </r-btn>
34
- </r-col>
35
- <r-col class="col-auto">
36
- <r-btn v-if="tab!=='month'" icon
37
- @click.prevent="tab==='day'?incrementMonth(1):incrementYear(12)">
38
- <r-icon v-html="$r.icons.arrow_right"></r-icon>
39
- </r-btn>
40
- </r-col>
41
- </r-row>
42
- </r-container>
43
- <year-tab v-if="tab==='year'"
44
- :model-value='currentPeriod.year'
45
- @update:model-value="(tab='month',incrementYear($event))"
46
- :timezoneOffset="lang_zone_offset-timezoneOffset"
47
- :locale="locale"
48
- :month="currentPeriod.month"></year-tab>
49
- <month-tab v-if="tab==='month'"
50
- :model-value='currentPeriod.month'
51
- @update:model-value="(tab='day',setMonth($event))"
52
- :timezoneOffset="lang_zone_offset-timezoneOffset"
53
- :locale="locale"
54
- :month="currentPeriod.month"
55
- :year="currentPeriod.year"></month-tab>
56
- <table v-if="tab==='day'" class="table">
57
- <thead>
58
- <tr>
59
- <th class="headCell" v-for="(weekday, weekdayIndex) in weekDays" :key="weekdayIndex">
60
- <span class="headCellContent">{{ weekday }}</span>
61
- </th>
62
- </tr>
63
- </thead>
64
- <transition :name="direction==='next'?'slide-start-to-end':'slide-end-to-start'" mode="out-in">
65
- <tbody
66
- :key="currentPeriod.year + '-' + currentPeriod.month"
67
- >
68
- <tr class="table-row" v-for="(week, weekIndex) in currentPeriodDates" :key="weekIndex">
69
- <td
70
- class="cell"
71
- v-for="item in week"
72
- :class="{
73
- selectable: !readonly && !item.disabled,
6
+ <r-modal :model-value="show" class="text-center" no-close-btn @update:model-value="close()">
7
+ <div v-if="!showTime" :class="`${$r.prefix}date-input`">
8
+ <div>
9
+ <r-container>
10
+ <r-row>
11
+ <r-col class="col-auto">
12
+ <r-btn v-if="tab!=='month'" icon
13
+ @click.prevent="tab==='day'?incrementMonth(-1):incrementYear(-12)">
14
+ <r-icon v-html="$r.icons.arrow_left"></r-icon>
15
+ </r-btn>
16
+ </r-col>
17
+ <r-col class="text-center">
18
+ <r-btn class="me-2 title-2" text @click.prevent="tab==='month'?tab='day':tab='month'">
19
+ <r-icon v-html="tab==='month'?$r.icons.chevron_up:$r.icons.chevron_down"></r-icon>
20
+ {{
21
+ $d(new
22
+ Date(currentPeriod.year, currentPeriod.month, 1, 0, lang_zone_offset - timezoneOffset), 'month', locale)
23
+ }}
24
+ </r-btn>
25
+
26
+ <r-btn class="title-2" text @click.prevent="tab==='year'?tab='day':tab='year'">
27
+ <r-icon v-html="tab==='year'?$r.icons.chevron_up:$r.icons.chevron_down"></r-icon>
28
+ {{
29
+ $d(new
30
+ Date(currentPeriod.year, currentPeriod.month, 1, 0, lang_zone_offset - timezoneOffset), 'year', locale)
31
+ }}
32
+ </r-btn>
33
+ </r-col>
34
+ <r-col class="col-auto">
35
+ <r-btn v-if="tab!=='month'" icon
36
+ @click.prevent="tab==='day'?incrementMonth(1):incrementYear(12)">
37
+ <r-icon v-html="$r.icons.arrow_right"></r-icon>
38
+ </r-btn>
39
+ </r-col>
40
+ </r-row>
41
+ </r-container>
42
+
43
+ <year v-if="tab==='year'"
44
+ :model-value='currentPeriod.year'
45
+ @update:model-value="(tab='month',incrementYear($event))"
46
+ :timezoneOffset="lang_zone_offset-timezoneOffset"
47
+ :locale="locale"
48
+ :month="currentPeriod.month"></year>
49
+ <month v-if="tab==='month'"
50
+ :model-value='currentPeriod.month'
51
+ @update:model-value="(tab='day',setMonth($event))"
52
+ :timezoneOffset="lang_zone_offset-timezoneOffset"
53
+ :locale="locale"
54
+ :month="currentPeriod.month"
55
+ :year="currentPeriod.year"></month>
56
+
57
+ <div v-if="isRangeMode && rangeSelection.startDate && rangeSelection.endDate" class="range-info">
58
+ <div class="title-3">
59
+ {{ $d(rangeSelection.startDate, withTime ? 'long' : 'medium', locale) }} -
60
+ {{ $d(rangeSelection.endDate, withTime ? 'long' : 'medium', locale) }}
61
+ </div>
62
+ </div>
63
+
64
+ <table v-if="tab==='day'" class="table">
65
+ <thead>
66
+ <tr>
67
+ <th class="headCell" v-for="(weekday, weekdayIndex) in weekDays" :key="weekdayIndex">
68
+ <span class="headCellContent">{{ weekday }}</span>
69
+ </th>
70
+ </tr>
71
+ </thead>
72
+ <transition :name="direction==='next'?'slide-start-to-end':'slide-end-to-start'" mode="out-in">
73
+ <tbody
74
+ :key="currentPeriod.year + '-' + currentPeriod.month"
75
+ >
76
+ <tr class="table-row" v-for="(week, weekIndex) in currentPeriodDates" :key="weekIndex">
77
+ <td
78
+ class="cell"
79
+ v-for="item in week"
80
+ :class="{
81
+ selectable:!item.disabled,
74
82
  selected: item.selected,
83
+ 'range-start': item.isRangeStart,
84
+ 'range-end': item.isRangeEnd,
85
+ 'in-range': item.inRange,
75
86
  disabled: item.disabled,
76
87
  today: item.today
77
88
  }"
78
- :key="item.date"
79
- @click.prevent="item.date!==0 &&!readonly&& selectDateItem(item)"
80
- >
81
- <div
82
- class="cellContent d-flex h-center v-center"
83
- v-if="item.date!==0"
89
+ :key="item.date"
90
+ @click.prevent="item.date!==0 &&selectDateItem(item)"
84
91
  >
85
- {{ $d(item.date, 'day', locale) }}
86
- </div>
87
- </td>
88
- </tr>
89
- </tbody>
90
- </transition>
91
- </table>
92
- </div>
93
- </div>
94
- <div v-else class="d-flex flex-column h-center v-center pa-5">
95
- <timepicker
96
- is24-hour
97
- withSec
98
- v-model="time"
99
- ></timepicker>
100
- <div class="mt-5">
101
- <r-btn class="color-success mx-5" @click.prevent="selectTime">{{ $t('ok', 'renusify') }}</r-btn>
102
- <r-btn class="color-error mx-5" @click.prevent="close">{{ $t('cancel', 'renusify') }}</r-btn>
92
+ <div
93
+ class="cellContent d-flex h-center v-center"
94
+ v-if="item.date!==0"
95
+ >
96
+ {{ $d(item.date, 'day', locale) }}
97
+ </div>
98
+ </td>
99
+ </tr>
100
+ </tbody>
101
+ </transition>
102
+ </table>
103
+ </div>
103
104
  </div>
104
105
 
105
- </div>
106
-
107
- </r-modal>
106
+ <div v-else class="d-flex flex-column h-center v-center pa-5">
107
+ <timepicker
108
+ is24-hour
109
+ withSec
110
+ v-model="time"
111
+ ></timepicker>
112
+ <div class="mt-5">
113
+ <r-btn class="color-success mx-5" @click.prevent="selectTime">{{ $t('ok', 'renusify') }}</r-btn>
114
+ <r-btn class="color-error mx-5" @click.prevent="close">{{ $t('cancel', 'renusify') }}</r-btn>
115
+ </div>
116
+ </div>
108
117
 
118
+ <div v-if="isRangeMode&&!showTime" class="date-picker-actions mb-3">
119
+ <r-btn class="color-one mx-5" @click.prevent="confirmRange">{{ $t('confirm', 'renusify') }}</r-btn>
120
+ <r-btn class="mx-5" text @click.prevent="resetRange">{{ $t('reset', 'renusify') }}</r-btn>
121
+ </div>
122
+ </r-modal>
123
+ </r-input>
109
124
  </template>
110
125
 
111
- <script>
112
- import {defineAsyncComponent} from 'vue'
126
+ <script setup>
127
+ import {ref, computed, watch, inject} from 'vue'
128
+ import Timepicker from "../timeInput/timepicker.vue";
129
+ import Year from "./year.vue";
130
+ import Month from "./month.vue";
131
+
132
+ const props = defineProps({
133
+ /**
134
+ * The model value for the date picker (v-model)
135
+ * @type {String|Array}
136
+ */
137
+ modelValue: {
138
+ type: [String, Array]
139
+ },
113
140
 
114
- export default {
115
- name: 'datePicker',
116
- components: {
117
- MonthTab: defineAsyncComponent(() => import('./month.vue')),
118
- YearTab: defineAsyncComponent(() => import('./year.vue')),
119
- Timepicker: defineAsyncComponent(() => import('../timeInput/timepicker.vue'))
141
+ /**
142
+ * Language/locale for date formatting
143
+ * @type {String}
144
+ */
145
+ lang: {
146
+ type: String
120
147
  },
121
- inheritAttrs: false,
122
- props: {
123
- modelValue: {
124
- type: String
125
- },
126
- lang: {
127
- type: String
128
- },
129
- readonly: Boolean,
130
- withTime: Boolean,
131
- isDateDisabled: {
132
- type: Function,
133
- default: () => false
134
- }
148
+
149
+ /**
150
+ * Enables time selection alongside date selection
151
+ * @type {Boolean}
152
+ */
153
+ withTime: Boolean,
154
+
155
+ /**
156
+ * Enables date range selection mode
157
+ * @type {Boolean}
158
+ * @default false
159
+ */
160
+ rangeMode: {
161
+ type: Boolean,
162
+ default: false
135
163
  },
136
- emits: ['update:modelValue'],
137
- data() {
138
- return {
139
- tab: 'day',
140
- show: false,
141
- showTime: false,
142
- time: null,
143
- date: null,
144
- direction: undefined,
145
- currentPeriod: {
146
- month: (new Date()).getMonth() + 1,
147
- year: (new Date()).getFullYear()
148
- }
164
+
165
+ /**
166
+ * Function to determine if a date should be disabled
167
+ * @type {Function}
168
+ * @default () => false
169
+ * @param {Date} date - The date to check
170
+ * @returns {Boolean} True if the date should be disabled
171
+ */
172
+ isDateDisabled: {
173
+ type: Function,
174
+ default: () => false
175
+ }
176
+ })
177
+
178
+ const emit = defineEmits([
179
+ /**
180
+ * Emitted when the date value changes
181
+ * @param {String|Array} value - The new date value(s)
182
+ */
183
+ 'update:modelValue'
184
+ ])
185
+
186
+ const {$dateTime, $helper, $r, $d} = inject('renusify')
187
+
188
+ const tab = ref('day')
189
+ const show = ref(false)
190
+ const showTime = ref(false)
191
+ const time = ref(null)
192
+ const date = ref(null)
193
+ const direction = ref(undefined)
194
+ const timeSelectionType = ref('start')
195
+
196
+ const currentPeriod = ref({
197
+ month: new Date().getMonth() + 1,
198
+ year: new Date().getFullYear()
199
+ })
200
+
201
+ const rangeSelection = ref({
202
+ startDate: null,
203
+ endDate: null,
204
+ selecting: false
205
+ })
206
+
207
+ const TODAY = new Date()
208
+
209
+ const locale = computed(() => props.lang || $r.lang)
210
+ const firstDayOfWeek = computed(() =>
211
+ $helper.ifHas($dateTime.langs, 0, locale.value, 'first_day')
212
+ )
213
+
214
+ const modelValueDate = computed(() => {
215
+ if (props.isRangeMode && rangeSelection.value.startDate) {
216
+ return rangeSelection.value.startDate
217
+ }
218
+ if (!props.modelValue || !new Date(props.modelValue)) {
219
+ return new Date()
220
+ }
221
+ return new Date(props.modelValue)
222
+ })
223
+
224
+ const timezoneOffset = computed(() =>
225
+ new Date(currentPeriod.value.year, currentPeriod.value.month, 10).getTimezoneOffset()
226
+ )
227
+
228
+ const lang_zone_offset = computed(() =>
229
+ $helper.ifHas($dateTime.langs, 0, locale.value, 'time_zone_offset') * -1
230
+ )
231
+
232
+ const displayValue = computed(() => {
233
+ if (props.isRangeMode) {
234
+ const {startDate, endDate} = rangeSelection.value
235
+ if (startDate && endDate) {
236
+ const format = props.withTime ? 'long' : 'medium'
237
+ return `${$d(startDate, format, locale.value)} - ${$d(endDate, format, locale.value)}`
149
238
  }
150
- },
151
- created() {
152
- this.$dateTime.set_format({
153
- 'de': {
154
- day: 'numeric',
155
- numberingSystem: 'latn'
156
- },
157
- 'me': {
158
- month: 'numeric',
159
- numberingSystem: 'latn'
160
- },
161
- 'ye': {
162
- year: 'numeric',
163
- numberingSystem: 'latn'
164
- }
165
- })
166
- this.currentPeriod = {
167
- month: this.modelValueDate.getMonth() + 1,
168
- year: this.modelValueDate.getFullYear()
239
+ return null
240
+ }
241
+ return props.modelValue ? $d(modelValueDate.value, props.withTime ? 'long' : 'medium', locale.value) : null
242
+ })
243
+
244
+ const weekDays = computed(() => {
245
+ const first = parseInt(firstDayOfWeek.value, 10)
246
+ return createRange(7).map(i =>
247
+ $d(new Date(2025, 2, first + i + 23, 0, lang_zone_offset.value - timezoneOffset.value, 0), 'narrow', locale.value)
248
+ )
249
+ })
250
+
251
+ const rangeLocalDate = computed(() => {
252
+ const {year, month} = currentPeriod.value
253
+
254
+ const firstDayOfMonth = new Date(year, month, 1, 0, lang_zone_offset.value - timezoneOffset.value, 0)
255
+ const firstDayWeekday = parseInt($d(firstDayOfMonth, 'de', locale.value))
256
+ const calendarStart = new Date(year, month, 1 - firstDayWeekday + 1, 0, lang_zone_offset.value - timezoneOffset.value, 0)
257
+
258
+ const firstDayNextMonth = new Date(year, month + 1, 1, 0, lang_zone_offset.value - timezoneOffset.value, 0)
259
+ const firstDayNextMonthWeekday = parseInt($d(firstDayNextMonth, 'de', locale.value))
260
+ const calendarEnd = new Date(year, month + 1, 1 - firstDayNextMonthWeekday, 23, 59 + lang_zone_offset.value - timezoneOffset.value, 59)
261
+
262
+ return {start: calendarStart, end: calendarEnd}
263
+ })
264
+
265
+ const weekDaysBeforeFirstDayOfTheMonth = computed(() => {
266
+ const {start} = rangeLocalDate.value
267
+ const weekDay = start.getDay()
268
+ return (weekDay - parseInt(firstDayOfWeek.value) + 7) % 7
269
+ })
270
+
271
+ const currentPeriodDates = computed(() => {
272
+ const {start, end} = rangeLocalDate.value
273
+
274
+ function* dateGenerator() {
275
+ const current = new Date(start)
276
+ while (current <= end) {
277
+ yield new Date(current)
278
+ current.setDate(current.getDate() + 1)
169
279
  }
170
- if (this.rangeLocalDate.start > this.modelValueDate) {
171
- this.incrementMonth(-1)
280
+ }
281
+
282
+ const weeks = []
283
+ let currentWeek = []
284
+
285
+ const leadingEmptyDays = weekDaysBeforeFirstDayOfTheMonth.value
286
+ currentWeek.push(...Array(leadingEmptyDays).fill(null).map(() => createEmptyDateCell(null)))
287
+
288
+ for (const date of dateGenerator()) {
289
+ currentWeek.push(createDateCell(date))
290
+
291
+ if (currentWeek.length === 7) {
292
+ weeks.push(currentWeek)
293
+ currentWeek = []
172
294
  }
173
- if (this.rangeLocalDate.end < this.modelValueDate) {
174
- this.incrementMonth(1)
295
+ }
296
+
297
+ if (currentWeek.length > 0) {
298
+ const trailingEmptyDays = 7 - currentWeek.length
299
+ currentWeek.push(...Array(trailingEmptyDays).fill(null).map(() => createEmptyDateCell(null)))
300
+ weeks.push(currentWeek)
301
+ }
302
+
303
+ return weeks
304
+ })
305
+
306
+ const createRange = (number) => Array.from({length: number}, (_, i) => i)
307
+
308
+ const createEmptyDateCell = () => ({
309
+ date: 0,
310
+ disabled: true,
311
+ selected: false,
312
+ today: false,
313
+ isRangeStart: false,
314
+ isRangeEnd: false,
315
+ inRange: false
316
+ })
317
+
318
+ const createDateCell = (date) => {
319
+ const cell = {
320
+ date,
321
+ disabled: props.isDateDisabled(date),
322
+ selected: areSameDates(date, modelValueDate.value),
323
+ today: areSameDates(date, TODAY),
324
+ isRangeStart: false,
325
+ isRangeEnd: false,
326
+ inRange: false
327
+ }
328
+
329
+ if (props.isRangeMode) {
330
+ cell.isRangeStart = rangeSelection.value.startDate ? areSameDates(date, rangeSelection.value.startDate) : false
331
+ cell.isRangeEnd = rangeSelection.value.endDate ? areSameDates(date, rangeSelection.value.endDate) : false
332
+ cell.inRange = isDateInRange(date)
333
+ }
334
+
335
+ return cell
336
+ }
337
+
338
+ /**
339
+ * Checks if two dates are the same day
340
+ * @param {Date} date1 - First date
341
+ * @param {Date} date2 - Second date
342
+ * @returns {Boolean} True if dates are the same day
343
+ */
344
+ const areSameDates = (date1, date2) => {
345
+ if (!date1 || !date2 || typeof date1.getDate !== 'function' || typeof date2.getDate !== 'function') {
346
+ return false
347
+ }
348
+ return date1.getDate() === date2.getDate() &&
349
+ date1.getMonth() === date2.getMonth() &&
350
+ date1.getFullYear() === date2.getFullYear()
351
+ }
352
+
353
+ /**
354
+ * Checks if a date is within the selected range
355
+ * @param {Date} date - Date to check
356
+ * @returns {Boolean} True if date is within range
357
+ */
358
+ const isDateInRange = (date) => {
359
+ const {startDate, endDate} = rangeSelection.value
360
+ if (!startDate || !endDate) return false
361
+ return date > startDate && date < endDate
362
+ }
363
+
364
+ /**
365
+ * Increments the current month view
366
+ * @param {Number} increment - Number of months to increment
367
+ */
368
+ const incrementMonth = (increment = 1) => {
369
+ const incrementDate = new Date(currentPeriod.value.year, currentPeriod.value.month + increment)
370
+ currentPeriod.value = {
371
+ month: incrementDate.getMonth(),
372
+ year: incrementDate.getFullYear()
373
+ }
374
+ }
375
+
376
+ /**
377
+ * Increments the current year view
378
+ * @param {Number} increment - Number of years to increment
379
+ */
380
+ const incrementYear = (increment = 1) => {
381
+ const incrementDate = new Date(currentPeriod.value.year + increment, currentPeriod.value.month)
382
+ currentPeriod.value = {
383
+ month: incrementDate.getMonth(),
384
+ year: incrementDate.getFullYear()
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Sets the current month view
390
+ * @param {Number} monthIndex - Month index (0-11)
391
+ */
392
+ const setMonth = (monthIndex) => {
393
+ const incrementDate = new Date(currentPeriod.value.year, monthIndex)
394
+ currentPeriod.value = {
395
+ month: incrementDate.getMonth(),
396
+ year: incrementDate.getFullYear()
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Closes the date picker
402
+ * @param {Boolean} force - Force close even in range mode
403
+ */
404
+ const close = (force = false) => {
405
+ if (force || !props.isRangeMode) {
406
+ show.value = false
407
+ }
408
+ showTime.value = false
409
+ }
410
+
411
+ /**
412
+ * Handles time selection
413
+ */
414
+ const selectTime = () => {
415
+ const times = (time.value ? time.value : '00:00:00').split(':')
416
+ const [hours, minutes, seconds] = times.map(t => parseInt(t))
417
+
418
+ if (props.isRangeMode) {
419
+ handleRangeTimeSelection(hours, minutes, seconds)
420
+ } else {
421
+ handleSingleTimeSelection(hours, minutes, seconds)
422
+ }
423
+ }
424
+
425
+ /**
426
+ * Handles time selection for range mode
427
+ * @param {Number} hours - Selected hours
428
+ * @param {Number} minutes - Selected minutes
429
+ * @param {Number} seconds - Selected seconds
430
+ */
431
+ const handleRangeTimeSelection = (hours, minutes, seconds) => {
432
+ if (timeSelectionType.value === 'start') {
433
+ const startDate = new Date(rangeSelection.value.startDate)
434
+ startDate.setHours(hours, minutes, seconds)
435
+ rangeSelection.value.startDate = startDate
436
+
437
+ if (rangeSelection.value.endDate) {
438
+ timeSelectionType.value = 'end'
439
+ const endDate = rangeSelection.value.endDate
440
+ time.value = formatTime(endDate.getHours(), endDate.getMinutes(), endDate.getSeconds())
175
441
  }
176
- },
177
- computed: {
178
- firstDayOfWeek() {
179
- return this.$helper.ifHas(this.$dateTime.langs, 0, this.locale, 'first_day')
180
- },
181
- locale() {
182
- return this.lang || this.$r.lang
183
- },
184
- today() {
185
- return new Date()
186
- },
187
-
188
- weekDays() {
189
- const first = parseInt(this.firstDayOfWeek, 10)
190
-
191
- return this.createRange(7).map(i => this.$d(new Date(2025, 2, first + i + 23, 0, this.lang_zone_offset - this.timezoneOffset, 0), 'narrow', this.locale)) // 2017-02-02 is Sunday
192
- },
193
- modelValueDate() {
194
- if (!this.modelValue || !new Date(this.modelValue)) {
195
- return new Date()
196
- }
197
- return new Date(this.modelValue)
198
- },
199
- rangeLocalDate() {
200
- const {year, month} = this.currentPeriod
201
- let firstDay = 1
202
- let firstmonth = month
203
- let firstyear = year
204
- let first = new Date(firstyear, firstmonth, firstDay, 0, this.lang_zone_offset - this.timezoneOffset, 0)
205
- let lc = parseInt(this.$d(first, 'de', this.locale))
206
- first = new Date(firstyear, firstmonth, firstDay - lc + 1, 0, this.lang_zone_offset - this.timezoneOffset, 0)
207
-
208
- firstDay = 1
209
- firstmonth = month + 1
210
- firstyear = year
211
- let last = new Date(firstyear, firstmonth, firstDay, 0, this.lang_zone_offset - this.timezoneOffset, 0)
212
- lc = parseInt(this.$d(last, 'de', this.locale))
213
- last = new Date(firstyear, firstmonth, firstDay - lc, 23, 59 + this.lang_zone_offset - this.timezoneOffset, 59)
214
-
215
- return {start: first, end: last}
216
- },
217
- weekDaysBeforeFirstDayOfTheMonth() {
218
- const {start} = this.rangeLocalDate
219
- const weekDay = start.getDay()
220
- return (weekDay - parseInt(this.firstDayOfWeek) + 7) % 7
221
- },
222
- currentPeriodDates() {
223
- const {start, end} = this.rangeLocalDate
224
- const children = []
225
- let firstday = start.getDate()
226
- let firstmonth = start.getMonth()
227
- let firstyear = start.getFullYear()
228
- let rows = []
229
- let day = this.weekDaysBeforeFirstDayOfTheMonth
230
-
231
- while (day--) {
232
- rows.push({
233
- date: 0,
234
- disabled: true,
235
- selected: false,
236
- today: false
237
- })
238
- }
239
- let doJob = true
240
- while (doJob) {
241
- const date = new Date(firstyear, firstmonth, 1, 24, this.lang_zone_offset - this.timezoneOffset, 0)
242
- date.setDate(firstday)
243
- firstmonth = date.getMonth()
244
- firstyear = date.getFullYear()
245
- firstday = date.getDate() + 1
246
- if (date.getTime() > end.getTime()) {
247
- doJob = false
248
- } else {
249
- rows.push({
250
- date: date,
251
- disabled: this.isDateDisabled(date),
252
- selected: this.areSameDates(date, this.modelValueDate),
253
- today: this.areSameDates(date, this.today)
254
- })
255
-
256
- if (rows.length % 7 === 0) {
257
- children.push(rows)
258
- rows = []
259
- }
260
- }
261
- }
442
+ close()
443
+ } else {
444
+ const endDate = new Date(rangeSelection.value.endDate)
445
+ endDate.setHours(hours, minutes, seconds)
446
+ rangeSelection.value.endDate = endDate
447
+ close()
448
+ }
449
+ }
262
450
 
263
- if (rows.length) {
264
- children.push(rows)
451
+ /**
452
+ * Handles time selection for single date mode
453
+ * @param {Number} hours - Selected hours
454
+ * @param {Number} minutes - Selected minutes
455
+ * @param {Number} seconds - Selected seconds
456
+ */
457
+ const handleSingleTimeSelection = (hours, minutes, seconds) => {
458
+ const selectedDate = new Date(date.value)
459
+ selectedDate.setHours(hours, minutes, seconds)
460
+ emit('update:modelValue', selectedDate.toISOString())
461
+ close()
462
+ }
463
+
464
+ /**
465
+ * Formats time components to HH:MM:SS string
466
+ * @param {Number} hours - Hours
467
+ * @param {Number} minutes - Minutes
468
+ * @param {Number} seconds - Seconds
469
+ * @returns {String} Formatted time string
470
+ */
471
+ const formatTime = (hours, minutes, seconds) => {
472
+ return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`
473
+ }
474
+
475
+ /**
476
+ * Handles date selection
477
+ * @param {Object} item - Date cell object
478
+ */
479
+ const selectDateItem = (item) => {
480
+ if (!item.disabled) {
481
+ if (props.isRangeMode) {
482
+ handleRangeSelection(item.date)
483
+ } else {
484
+ if (props.withTime) {
485
+ date.value = item.date
486
+ showTime.value = true
487
+ } else {
488
+ emit('update:modelValue', item.date.toISOString())
489
+ close()
265
490
  }
491
+ }
492
+ }
493
+ }
266
494
 
267
- return children
268
- },
269
- timezoneOffset() {
270
- return (new Date(this.currentPeriod.year, this.currentPeriod.month, 10)).getTimezoneOffset()
271
- },
272
- lang_zone_offset() {
273
- return this.$helper.ifHas(this.$dateTime.langs, 0, this.locale, 'time_zone_offset') * -1
495
+ /**
496
+ * Handles date range selection
497
+ * @param {Date} date - Selected date
498
+ */
499
+ const handleRangeSelection = (date) => {
500
+ if (!rangeSelection.value.selecting) {
501
+ rangeSelection.value = {
502
+ startDate: date,
503
+ endDate: null,
504
+ selecting: true
274
505
  }
275
- },
276
- watch: {
277
- modelValueDate(newVal) {
278
- this.currentPeriod = {
279
- month: newVal.getMonth() + 1,
280
- year: newVal.getFullYear()
281
- }
282
- if (this.rangeLocalDate.start > this.modelValueDate) {
283
- this.incrementMonth(-1)
284
- }
285
- if (this.rangeLocalDate.end < this.modelValueDate) {
286
- this.incrementMonth(1)
287
- }
288
- },
289
- currentPeriod(currentPeriod, oldPeriod) {
290
- const currentDate = new Date(currentPeriod.year, currentPeriod.month).getTime()
291
- const oldDate = new Date(oldPeriod.year, oldPeriod.month).getTime()
292
- this.direction = currentDate !== oldDate
293
- ? (currentDate > oldDate ? 'next' : 'prev')
294
- : undefined
506
+
507
+ if (props.withTime) {
508
+ timeSelectionType.value = 'start'
509
+ showTime.value = true
510
+ time.value = formatTime(date.getHours(), date.getMinutes(), date.getSeconds())
295
511
  }
296
- },
297
- methods: {
298
- close() {
299
- this.show = false
300
- this.showTime = false
301
- },
302
- createRange(number) {
303
- const res = []
304
- for (let i = 0; i < number; i++) {
305
- res.push(i)
306
- }
307
- return res
308
- },
309
- incrementMonth(increment = 1) {
310
- const incrementDate = new Date(this.currentPeriod.year, this.currentPeriod.month + increment)
311
- this.currentPeriod = {
312
- month: incrementDate.getMonth(),
313
- year: incrementDate.getFullYear()
314
- }
315
- },
316
- incrementYear(increment = 1) {
317
- const incrementDate = new Date(this.currentPeriod.year + increment, this.currentPeriod.month)
318
- this.currentPeriod = {
319
- month: incrementDate.getMonth(),
320
- year: incrementDate.getFullYear()
321
- }
322
- },
323
- setMonth(increment) {
324
- const incrementDate = new Date(this.currentPeriod.year, increment)
325
- this.currentPeriod = {
326
- month: incrementDate.getMonth(),
327
- year: incrementDate.getFullYear()
328
- }
329
- },
330
- selectTime() {
331
- const times = (this.time ? this.time : '00:00:00').split(':')
332
- let d = (new Date(this.date.getFullYear(), this.date.getMonth(), this.date.getDate(),
333
- this.date.getHours() + parseInt(times[0]),
334
- this.date.getMinutes() + parseInt(times[1]),
335
- this.date.getSeconds() + parseInt(times[2])))
336
-
337
- this.$emit('update:modelValue', d.toISOString())
338
- this.close()
339
- },
340
- selectDateItem(item) {
341
- if (!item.disabled) {
342
- if (this.withTime) {
343
- this.date = item.date
344
- this.showTime = true
345
- } else {
346
- this.$emit('update:modelValue', item.date.toISOString())
347
- this.close()
348
- }
349
- }
350
- },
351
- areSameDates(date1, date2) {
352
- if (typeof date1.getDate === 'function' && typeof date2.getDate === 'function') {
353
- return (date1.getDate() === date2.getDate()) &&
354
- (date1.getMonth() === date2.getMonth()) &&
355
- (date1.getFullYear() === date2.getFullYear())
356
- }
357
- return false
512
+ } else {
513
+ const newRange = {...rangeSelection.value}
514
+
515
+ if (date < newRange.startDate) {
516
+ newRange.endDate = newRange.startDate
517
+ newRange.startDate = date
518
+ } else {
519
+ newRange.endDate = date
520
+ }
521
+
522
+ newRange.selecting = false
523
+ rangeSelection.value = newRange
524
+
525
+ if (props.withTime) {
526
+ timeSelectionType.value = 'end'
527
+ showTime.value = true
528
+ time.value = formatTime(newRange.endDate.getHours(), newRange.endDate.getMinutes(), newRange.endDate.getSeconds())
358
529
  }
359
530
  }
360
531
  }
361
532
 
533
+ /**
534
+ * Confirms the selected date range
535
+ */
536
+ const confirmRange = () => {
537
+ const {startDate, endDate} = rangeSelection.value
538
+ if (startDate && endDate) {
539
+ emit('update:modelValue', [
540
+ startDate.toISOString(),
541
+ endDate.toISOString()
542
+ ])
543
+ close(true)
544
+ }
545
+ }
546
+
547
+ /**
548
+ * Resets the date range selection
549
+ */
550
+ const resetRange = () => {
551
+ rangeSelection.value = {
552
+ startDate: null,
553
+ endDate: null,
554
+ selecting: false
555
+ }
556
+ timeSelectionType.value = 'start'
557
+ }
558
+
559
+ watch(modelValueDate, (newVal) => {
560
+ currentPeriod.value = {
561
+ month: newVal.getMonth() + 1,
562
+ year: newVal.getFullYear()
563
+ }
564
+
565
+ const {start, end} = rangeLocalDate.value
566
+ if (start > newVal) incrementMonth(-1)
567
+ if (end < newVal) incrementMonth(1)
568
+ })
569
+
570
+ watch(currentPeriod, (newPeriod, oldPeriod) => {
571
+ const currentDate = new Date(newPeriod.year, newPeriod.month).getTime()
572
+ const oldDate = new Date(oldPeriod.year, oldPeriod.month).getTime()
573
+ direction.value = currentDate !== oldDate
574
+ ? (currentDate > oldDate ? 'next' : 'prev')
575
+ : undefined
576
+ })
577
+
578
+ $dateTime.set_format({
579
+ 'de': {day: 'numeric', numberingSystem: 'latn'},
580
+ 'me': {month: 'numeric', numberingSystem: 'latn'},
581
+ 'ye': {year: 'numeric', numberingSystem: 'latn'}
582
+ })
583
+
584
+ if (props.isRangeMode && Array.isArray(props.modelValue) && props.modelValue.length === 2) {
585
+ rangeSelection.value = {
586
+ startDate: new Date(props.modelValue[0]),
587
+ endDate: new Date(props.modelValue[1]),
588
+ selecting: false
589
+ }
590
+ }
591
+
592
+ const {start, end} = rangeLocalDate.value
593
+ if (start > modelValueDate.value) incrementMonth(-1)
594
+ if (end < modelValueDate.value) incrementMonth(1)
362
595
  </script>
363
596
 
364
597
  <style lang="scss">
365
- @use "../../../style/variables/base";
598
+ @use "../../../style" as *;
366
599
 
367
- .#{base.$prefix}date-color-input {
600
+ .#{$prefix}date-color-input {
368
601
  color: var(--color-on-sheet);
602
+
603
+ &.date-range-display {
604
+ font-weight: 500;
605
+ }
369
606
  }
370
- .#{base.$prefix}date-input {
607
+
608
+ .#{$prefix}date-input {
371
609
  position: relative;
372
610
  display: inline-block;
373
611
  font-size: 10px;
374
- color: var(--color-on-sheet);
375
- background-color: var(--color-sheet-container-high);
612
+ border-radius: 12px;
613
+ padding: 16px;
614
+ overflow: hidden;
615
+
616
+ .date-picker-header {
617
+ margin-bottom: 16px;
618
+ padding-bottom: 12px;
619
+ border-bottom: 1px solid var(--color-border-low);
620
+
621
+ h3 {
622
+ margin: 0;
623
+ color: var(--color-one);
624
+ }
625
+ }
626
+
627
+ .range-info {
628
+ margin: 12px 0;
629
+ padding: 12px;
630
+ background-color: var(--color-one-container);
631
+ border-radius: 8px;
632
+ color: var(--color-on-one-container);
633
+
634
+ .body-2 {
635
+ margin-bottom: 4px;
636
+ opacity: 0.8;
637
+ }
638
+ }
639
+
640
+ .date-picker-actions {
641
+ display: flex;
642
+ justify-content: space-between;
643
+ margin-top: 16px;
644
+ padding-top: 12px;
645
+ border-top: 1px solid var(--color-border-low);
646
+ }
376
647
 
377
648
  .date-picker-year {
378
649
  max-height: 300px;
650
+ overflow: auto;
379
651
  }
380
652
 
381
653
  .cell {
382
654
  &.today {
383
655
  color: var(--color-one);
656
+ font-weight: 600;
384
657
 
385
658
  .cellContent {
386
659
  border: solid 1px var(--color-one);
@@ -391,56 +664,69 @@ export default {
391
664
  .cellContent {
392
665
  color: var(--color-on-one);
393
666
  background: var(--color-one);
667
+ font-weight: 600;
668
+ }
669
+ }
394
670
 
671
+ &.range-start {
672
+ .cellContent {
673
+ color: var(--color-on-one) !important;
674
+ background: var(--color-one) !important;
675
+ font-weight: 600;
395
676
  }
396
677
  }
397
678
 
398
- &.selectable:hover {
679
+ &.range-end {
680
+ .cellContent {
681
+ color: var(--color-on-one) !important;
682
+ background: var(--color-one) !important;
683
+ font-weight: 600;
684
+ }
685
+ }
686
+
687
+ &.in-range {
399
688
  .cellContent {
689
+ background: var(--color-one-container);
690
+ color: var(--color-on-one-container);
691
+ }
692
+ }
400
693
 
694
+ &.selectable:hover {
695
+ .cellContent {
401
696
  color: var(--color-on-one);
402
697
  background: var(--color-one);
403
-
404
698
  }
405
699
  }
406
-
407
700
  }
408
701
 
409
-
410
702
  .table {
411
-
412
703
  width: 100%;
413
704
  table-layout: fixed;
414
705
  position: relative;
415
706
  z-index: 5;
416
-
707
+ margin-top: 16px;
417
708
  }
418
709
 
419
710
  .cell, .headCell {
420
-
421
711
  text-align: center;
422
712
  box-sizing: border-box;
423
-
424
713
  }
425
714
 
426
715
  .cell {
427
-
428
716
  padding: 0.5em 0;
429
-
717
+ position: relative;
430
718
  }
431
719
 
432
720
  .headCell {
433
-
434
721
  padding: 0.3em 0.5em 1.8em;
435
-
436
722
  }
437
723
 
438
724
  .headCellContent {
439
-
440
725
  font-size: 1.3em;
441
- font-weight: normal;
726
+ font-weight: 600;
442
727
  color: var(--color-on-sheet-low);
443
-
728
+ text-transform: uppercase;
729
+ letter-spacing: 0.5px;
444
730
  }
445
731
 
446
732
  .cellContent {
@@ -451,8 +737,55 @@ export default {
451
737
  height: 30px;
452
738
  text-align: center;
453
739
  border-radius: 100%;
454
- transition: background 0.1s, color 0.1s;
740
+ transition: all 0.2s ease;
741
+ position: relative;
742
+ z-index: 2;
743
+ }
455
744
 
745
+ .cell.in-range::after {
746
+ content: '';
747
+ position: absolute;
748
+ top: 0;
749
+ bottom: 0;
750
+ left: 0;
751
+ right: 0;
752
+ background: var(--color-one-container);
753
+ z-index: 1;
754
+ }
755
+
756
+ .cell.range-start::after {
757
+ content: '';
758
+ position: absolute;
759
+ top: 0;
760
+ bottom: 0;
761
+ background: var(--color-one-container);
762
+ z-index: 1;
763
+ @include ltr() {
764
+ left: 50%;
765
+ right: 0;
766
+ }
767
+ @include rtl() {
768
+ left: 0;
769
+ right: 50%;
770
+ }
771
+ }
772
+
773
+ .cell.range-end::after {
774
+ content: '';
775
+ position: absolute;
776
+ top: 0;
777
+ bottom: 0;
778
+ background: var(--color-one-container);
779
+ z-index: 1;
780
+ @include ltr() {
781
+ left: 0;
782
+ right: 50%;
783
+ }
784
+ @include rtl() {
785
+ left: 50%;
786
+ right: 0;
787
+
788
+ }
456
789
  }
457
790
 
458
791
  .cell.outOfRange {
@@ -460,14 +793,16 @@ export default {
460
793
  }
461
794
 
462
795
  .cell.selectable {
463
-
464
796
  cursor: pointer;
465
-
466
797
  }
467
798
 
468
799
  .cell.disabled {
469
800
  opacity: 0.38;
470
801
  }
802
+ }
471
803
 
804
+ .time-selection-title {
805
+ color: var(--color-one);
806
+ font-weight: 600;
472
807
  }
473
808
  </style>