VCarousel.mjs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import { createVNode as _createVNode, mergeProps as _mergeProps, Fragment as _Fragment } from "vue";
  2. // Styles
  3. import "./VCarousel.css";
  4. // Components
  5. import { VBtn } from "../VBtn/index.mjs";
  6. import { VDefaultsProvider } from "../VDefaultsProvider/index.mjs";
  7. import { VProgressLinear } from "../VProgressLinear/index.mjs";
  8. import { makeVWindowProps, VWindow } from "../VWindow/VWindow.mjs"; // Composables
  9. import { IconValue } from "../../composables/icons.mjs";
  10. import { useLocale } from "../../composables/locale.mjs";
  11. import { useProxiedModel } from "../../composables/proxiedModel.mjs"; // Utilities
  12. import { onMounted, ref, watch } from 'vue';
  13. import { convertToUnit, genericComponent, propsFactory, useRender } from "../../util/index.mjs"; // Types
  14. export const makeVCarouselProps = propsFactory({
  15. color: String,
  16. cycle: Boolean,
  17. delimiterIcon: {
  18. type: IconValue,
  19. default: '$delimiter'
  20. },
  21. height: {
  22. type: [Number, String],
  23. default: 500
  24. },
  25. hideDelimiters: Boolean,
  26. hideDelimiterBackground: Boolean,
  27. interval: {
  28. type: [Number, String],
  29. default: 6000,
  30. validator: value => Number(value) > 0
  31. },
  32. progress: [Boolean, String],
  33. verticalDelimiters: [Boolean, String],
  34. ...makeVWindowProps({
  35. continuous: true,
  36. mandatory: 'force',
  37. showArrows: true
  38. })
  39. }, 'VCarousel');
  40. export const VCarousel = genericComponent()({
  41. name: 'VCarousel',
  42. props: makeVCarouselProps(),
  43. emits: {
  44. 'update:modelValue': value => true
  45. },
  46. setup(props, _ref) {
  47. let {
  48. slots
  49. } = _ref;
  50. const model = useProxiedModel(props, 'modelValue');
  51. const {
  52. t
  53. } = useLocale();
  54. const windowRef = ref();
  55. let slideTimeout = -1;
  56. watch(model, restartTimeout);
  57. watch(() => props.interval, restartTimeout);
  58. watch(() => props.cycle, val => {
  59. if (val) restartTimeout();else window.clearTimeout(slideTimeout);
  60. });
  61. onMounted(startTimeout);
  62. function startTimeout() {
  63. if (!props.cycle || !windowRef.value) return;
  64. slideTimeout = window.setTimeout(windowRef.value.group.next, +props.interval > 0 ? +props.interval : 6000);
  65. }
  66. function restartTimeout() {
  67. window.clearTimeout(slideTimeout);
  68. window.requestAnimationFrame(startTimeout);
  69. }
  70. useRender(() => {
  71. const windowProps = VWindow.filterProps(props);
  72. return _createVNode(VWindow, _mergeProps({
  73. "ref": windowRef
  74. }, windowProps, {
  75. "modelValue": model.value,
  76. "onUpdate:modelValue": $event => model.value = $event,
  77. "class": ['v-carousel', {
  78. 'v-carousel--hide-delimiter-background': props.hideDelimiterBackground,
  79. 'v-carousel--vertical-delimiters': props.verticalDelimiters
  80. }, props.class],
  81. "style": [{
  82. height: convertToUnit(props.height)
  83. }, props.style]
  84. }), {
  85. default: slots.default,
  86. additional: _ref2 => {
  87. let {
  88. group
  89. } = _ref2;
  90. return _createVNode(_Fragment, null, [!props.hideDelimiters && _createVNode("div", {
  91. "class": "v-carousel__controls",
  92. "style": {
  93. left: props.verticalDelimiters === 'left' && props.verticalDelimiters ? 0 : 'auto',
  94. right: props.verticalDelimiters === 'right' ? 0 : 'auto'
  95. }
  96. }, [group.items.value.length > 0 && _createVNode(VDefaultsProvider, {
  97. "defaults": {
  98. VBtn: {
  99. color: props.color,
  100. icon: props.delimiterIcon,
  101. size: 'x-small',
  102. variant: 'text'
  103. }
  104. },
  105. "scoped": true
  106. }, {
  107. default: () => [group.items.value.map((item, index) => {
  108. const props = {
  109. id: `carousel-item-${item.id}`,
  110. 'aria-label': t('$vuetify.carousel.ariaLabel.delimiter', index + 1, group.items.value.length),
  111. class: ['v-carousel__controls__item', group.isSelected(item.id) && 'v-btn--active'],
  112. onClick: () => group.select(item.id, true)
  113. };
  114. return slots.item ? slots.item({
  115. props,
  116. item
  117. }) : _createVNode(VBtn, _mergeProps(item, props), null);
  118. })]
  119. })]), props.progress && _createVNode(VProgressLinear, {
  120. "class": "v-carousel__progress",
  121. "color": typeof props.progress === 'string' ? props.progress : undefined,
  122. "modelValue": (group.getItemIndex(model.value) + 1) / group.items.value.length * 100
  123. }, null)]);
  124. },
  125. prev: slots.prev,
  126. next: slots.next
  127. });
  128. });
  129. return {};
  130. }
  131. });
  132. //# sourceMappingURL=VCarousel.mjs.map