VDatePicker.mjs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. import { Fragment as _Fragment, mergeProps as _mergeProps, resolveDirective as _resolveDirective, createVNode as _createVNode } from "vue";
  2. // Styles
  3. import "./VDatePicker.css";
  4. // Components
  5. import { makeVDatePickerControlsProps, VDatePickerControls } from "./VDatePickerControls.mjs";
  6. import { VDatePickerHeader } from "./VDatePickerHeader.mjs";
  7. import { makeVDatePickerMonthProps, VDatePickerMonth } from "./VDatePickerMonth.mjs";
  8. import { makeVDatePickerMonthsProps, VDatePickerMonths } from "./VDatePickerMonths.mjs";
  9. import { makeVDatePickerYearsProps, VDatePickerYears } from "./VDatePickerYears.mjs";
  10. import { VFadeTransition } from "../transitions/index.mjs";
  11. import { VDefaultsProvider } from "../VDefaultsProvider/index.mjs";
  12. import { makeVPickerProps, VPicker } from "../../labs/VPicker/VPicker.mjs"; // Composables
  13. import { useDate } from "../../composables/date/index.mjs";
  14. import { useLocale } from "../../composables/locale.mjs";
  15. import { useProxiedModel } from "../../composables/proxiedModel.mjs"; // Utilities
  16. import { computed, ref, shallowRef, watch } from 'vue';
  17. import { genericComponent, omit, propsFactory, useRender, wrapInArray } from "../../util/index.mjs"; // Types
  18. // Types
  19. export const makeVDatePickerProps = propsFactory({
  20. // TODO: implement in v3.5
  21. // calendarIcon: {
  22. // type: String,
  23. // default: '$calendar',
  24. // },
  25. // keyboardIcon: {
  26. // type: String,
  27. // default: '$edit',
  28. // },
  29. // inputMode: {
  30. // type: String as PropType<'calendar' | 'keyboard'>,
  31. // default: 'calendar',
  32. // },
  33. // inputText: {
  34. // type: String,
  35. // default: '$vuetify.datePicker.input.placeholder',
  36. // },
  37. // inputPlaceholder: {
  38. // type: String,
  39. // default: 'dd/mm/yyyy',
  40. // },
  41. header: {
  42. type: String,
  43. default: '$vuetify.datePicker.header'
  44. },
  45. ...makeVDatePickerControlsProps(),
  46. ...makeVDatePickerMonthProps({
  47. weeksInMonth: 'static'
  48. }),
  49. ...omit(makeVDatePickerMonthsProps(), ['modelValue']),
  50. ...omit(makeVDatePickerYearsProps(), ['modelValue']),
  51. ...makeVPickerProps({
  52. title: '$vuetify.datePicker.title'
  53. }),
  54. modelValue: null
  55. }, 'VDatePicker');
  56. export const VDatePicker = genericComponent()({
  57. name: 'VDatePicker',
  58. props: makeVDatePickerProps(),
  59. emits: {
  60. 'update:modelValue': date => true,
  61. 'update:month': date => true,
  62. 'update:year': date => true,
  63. // 'update:inputMode': (date: any) => true,
  64. 'update:viewMode': date => true
  65. },
  66. setup(props, _ref) {
  67. let {
  68. emit,
  69. slots
  70. } = _ref;
  71. const adapter = useDate();
  72. const {
  73. t
  74. } = useLocale();
  75. const model = useProxiedModel(props, 'modelValue', undefined, v => wrapInArray(v), v => props.multiple ? v : v[0]);
  76. const viewMode = useProxiedModel(props, 'viewMode');
  77. // const inputMode = useProxiedModel(props, 'inputMode')
  78. const internal = computed(() => {
  79. const value = adapter.date(model.value?.[0]);
  80. return value && adapter.isValid(value) ? value : adapter.date();
  81. });
  82. const month = ref(Number(props.month ?? adapter.getMonth(adapter.startOfMonth(internal.value))));
  83. const year = ref(Number(props.year ?? adapter.getYear(adapter.startOfYear(adapter.setMonth(internal.value, month.value)))));
  84. const isReversing = shallowRef(false);
  85. const header = computed(() => {
  86. if (props.multiple && model.value.length > 1) {
  87. return t('$vuetify.datePicker.itemsSelected', model.value.length);
  88. }
  89. return model.value[0] && adapter.isValid(model.value[0]) ? adapter.format(adapter.date(model.value[0]), 'normalDateWithWeekday') : t(props.header);
  90. });
  91. const text = computed(() => {
  92. let date = adapter.date();
  93. date = adapter.setDate(date, 1);
  94. date = adapter.setMonth(date, month.value);
  95. date = adapter.setYear(date, year.value);
  96. return adapter.format(date, 'monthAndYear');
  97. });
  98. // const headerIcon = computed(() => props.inputMode === 'calendar' ? props.keyboardIcon : props.calendarIcon)
  99. const headerTransition = computed(() => `date-picker-header${isReversing.value ? '-reverse' : ''}-transition`);
  100. const minDate = computed(() => {
  101. const date = adapter.date(props.min);
  102. return props.min && adapter.isValid(date) ? date : null;
  103. });
  104. const maxDate = computed(() => {
  105. const date = adapter.date(props.max);
  106. return props.max && adapter.isValid(date) ? date : null;
  107. });
  108. const disabled = computed(() => {
  109. if (props.disabled) return true;
  110. const targets = [];
  111. if (viewMode.value !== 'month') {
  112. targets.push(...['prev', 'next']);
  113. } else {
  114. let _date = adapter.date();
  115. _date = adapter.setYear(_date, year.value);
  116. _date = adapter.setMonth(_date, month.value);
  117. if (minDate.value) {
  118. const date = adapter.addDays(adapter.startOfMonth(_date), -1);
  119. adapter.isAfter(minDate.value, date) && targets.push('prev');
  120. }
  121. if (maxDate.value) {
  122. const date = adapter.addDays(adapter.endOfMonth(_date), 1);
  123. adapter.isAfter(date, maxDate.value) && targets.push('next');
  124. }
  125. }
  126. return targets;
  127. });
  128. // function onClickAppend () {
  129. // inputMode.value = inputMode.value === 'calendar' ? 'keyboard' : 'calendar'
  130. // }
  131. function onClickNext() {
  132. if (month.value < 11) {
  133. month.value++;
  134. } else {
  135. year.value++;
  136. month.value = 0;
  137. onUpdateYear(year.value);
  138. }
  139. onUpdateMonth(month.value);
  140. }
  141. function onClickPrev() {
  142. if (month.value > 0) {
  143. month.value--;
  144. } else {
  145. year.value--;
  146. month.value = 11;
  147. onUpdateYear(year.value);
  148. }
  149. onUpdateMonth(month.value);
  150. }
  151. function onClickDate() {
  152. viewMode.value = 'month';
  153. }
  154. function onClickMonth() {
  155. viewMode.value = viewMode.value === 'months' ? 'month' : 'months';
  156. }
  157. function onClickYear() {
  158. viewMode.value = viewMode.value === 'year' ? 'month' : 'year';
  159. }
  160. function onUpdateMonth(value) {
  161. if (viewMode.value === 'months') onClickMonth();
  162. emit('update:month', value);
  163. }
  164. function onUpdateYear(value) {
  165. if (viewMode.value === 'year') onClickYear();
  166. emit('update:year', value);
  167. }
  168. watch(model, (val, oldVal) => {
  169. const arrBefore = wrapInArray(oldVal);
  170. const arrAfter = wrapInArray(val);
  171. if (!arrAfter.length) return;
  172. const before = adapter.date(arrBefore[arrBefore.length - 1]);
  173. const after = adapter.date(arrAfter[arrAfter.length - 1]);
  174. const newMonth = adapter.getMonth(after);
  175. const newYear = adapter.getYear(after);
  176. if (newMonth !== month.value) {
  177. month.value = newMonth;
  178. onUpdateMonth(month.value);
  179. }
  180. if (newYear !== year.value) {
  181. year.value = newYear;
  182. onUpdateYear(year.value);
  183. }
  184. isReversing.value = adapter.isBefore(before, after);
  185. });
  186. useRender(() => {
  187. const pickerProps = VPicker.filterProps(props);
  188. const datePickerControlsProps = VDatePickerControls.filterProps(props);
  189. const datePickerHeaderProps = VDatePickerHeader.filterProps(props);
  190. const datePickerMonthProps = VDatePickerMonth.filterProps(props);
  191. const datePickerMonthsProps = omit(VDatePickerMonths.filterProps(props), ['modelValue']);
  192. const datePickerYearsProps = omit(VDatePickerYears.filterProps(props), ['modelValue']);
  193. const headerProps = {
  194. header: header.value,
  195. transition: headerTransition.value
  196. };
  197. return _createVNode(VPicker, _mergeProps(pickerProps, {
  198. "class": ['v-date-picker', `v-date-picker--${viewMode.value}`, {
  199. 'v-date-picker--show-week': props.showWeek
  200. }, props.class],
  201. "style": props.style
  202. }), {
  203. title: () => slots.title?.() ?? _createVNode("div", {
  204. "class": "v-date-picker__title"
  205. }, [t(props.title)]),
  206. header: () => slots.header ? _createVNode(VDefaultsProvider, {
  207. "defaults": {
  208. VDatePickerHeader: {
  209. ...headerProps
  210. }
  211. }
  212. }, {
  213. default: () => [slots.header?.(headerProps)]
  214. }) : _createVNode(VDatePickerHeader, _mergeProps({
  215. "key": "header"
  216. }, datePickerHeaderProps, headerProps, {
  217. "onClick": viewMode.value !== 'month' ? onClickDate : undefined
  218. }), {
  219. ...slots,
  220. default: undefined
  221. }),
  222. default: () => _createVNode(_Fragment, null, [_createVNode(VDatePickerControls, _mergeProps(datePickerControlsProps, {
  223. "disabled": disabled.value,
  224. "text": text.value,
  225. "onClick:next": onClickNext,
  226. "onClick:prev": onClickPrev,
  227. "onClick:month": onClickMonth,
  228. "onClick:year": onClickYear
  229. }), null), _createVNode(VFadeTransition, {
  230. "hideOnLeave": true
  231. }, {
  232. default: () => [viewMode.value === 'months' ? _createVNode(VDatePickerMonths, _mergeProps({
  233. "key": "date-picker-months"
  234. }, datePickerMonthsProps, {
  235. "modelValue": month.value,
  236. "onUpdate:modelValue": [$event => month.value = $event, onUpdateMonth],
  237. "min": minDate.value,
  238. "max": maxDate.value,
  239. "year": year.value
  240. }), null) : viewMode.value === 'year' ? _createVNode(VDatePickerYears, _mergeProps({
  241. "key": "date-picker-years"
  242. }, datePickerYearsProps, {
  243. "modelValue": year.value,
  244. "onUpdate:modelValue": [$event => year.value = $event, onUpdateYear],
  245. "min": minDate.value,
  246. "max": maxDate.value
  247. }), null) : _createVNode(VDatePickerMonth, _mergeProps({
  248. "key": "date-picker-month"
  249. }, datePickerMonthProps, {
  250. "modelValue": model.value,
  251. "onUpdate:modelValue": $event => model.value = $event,
  252. "month": month.value,
  253. "onUpdate:month": [$event => month.value = $event, onUpdateMonth],
  254. "year": year.value,
  255. "onUpdate:year": [$event => year.value = $event, onUpdateYear],
  256. "min": minDate.value,
  257. "max": maxDate.value
  258. }), null)]
  259. })]),
  260. actions: slots.actions
  261. });
  262. });
  263. return {};
  264. }
  265. });
  266. //# sourceMappingURL=VDatePicker.mjs.map