VAppBar.mjs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { createVNode as _createVNode, mergeProps as _mergeProps, resolveDirective as _resolveDirective } from "vue";
  2. // Styles
  3. import "./VAppBar.css";
  4. // Components
  5. import { makeVToolbarProps, VToolbar } from "../VToolbar/VToolbar.mjs"; // Composables
  6. import { makeLayoutItemProps, useLayoutItem } from "../../composables/layout.mjs";
  7. import { useProxiedModel } from "../../composables/proxiedModel.mjs";
  8. import { makeScrollProps, useScroll } from "../../composables/scroll.mjs";
  9. import { useSsrBoot } from "../../composables/ssrBoot.mjs";
  10. import { useToggleScope } from "../../composables/toggleScope.mjs"; // Utilities
  11. import { computed, ref, shallowRef, toRef, watchEffect } from 'vue';
  12. import { genericComponent, propsFactory, useRender } from "../../util/index.mjs"; // Types
  13. export const makeVAppBarProps = propsFactory({
  14. scrollBehavior: String,
  15. modelValue: {
  16. type: Boolean,
  17. default: true
  18. },
  19. location: {
  20. type: String,
  21. default: 'top',
  22. validator: value => ['top', 'bottom'].includes(value)
  23. },
  24. ...makeVToolbarProps(),
  25. ...makeLayoutItemProps(),
  26. ...makeScrollProps(),
  27. height: {
  28. type: [Number, String],
  29. default: 64
  30. }
  31. }, 'VAppBar');
  32. export const VAppBar = genericComponent()({
  33. name: 'VAppBar',
  34. props: makeVAppBarProps(),
  35. emits: {
  36. 'update:modelValue': value => true
  37. },
  38. setup(props, _ref) {
  39. let {
  40. slots
  41. } = _ref;
  42. const vToolbarRef = ref();
  43. const isActive = useProxiedModel(props, 'modelValue');
  44. const scrollBehavior = computed(() => {
  45. const behavior = new Set(props.scrollBehavior?.split(' ') ?? []);
  46. return {
  47. hide: behavior.has('hide'),
  48. fullyHide: behavior.has('fully-hide'),
  49. inverted: behavior.has('inverted'),
  50. collapse: behavior.has('collapse'),
  51. elevate: behavior.has('elevate'),
  52. fadeImage: behavior.has('fade-image')
  53. // shrink: behavior.has('shrink'),
  54. };
  55. });
  56. const canScroll = computed(() => {
  57. const behavior = scrollBehavior.value;
  58. return behavior.hide || behavior.fullyHide || behavior.inverted || behavior.collapse || behavior.elevate || behavior.fadeImage ||
  59. // behavior.shrink ||
  60. !isActive.value;
  61. });
  62. const {
  63. currentScroll,
  64. scrollThreshold,
  65. isScrollingUp,
  66. scrollRatio
  67. } = useScroll(props, {
  68. canScroll
  69. });
  70. const canHide = computed(() => scrollBehavior.value.hide || scrollBehavior.value.fullyHide);
  71. const isCollapsed = computed(() => props.collapse || scrollBehavior.value.collapse && (scrollBehavior.value.inverted ? scrollRatio.value > 0 : scrollRatio.value === 0));
  72. const isFlat = computed(() => props.flat || scrollBehavior.value.fullyHide && !isActive.value || scrollBehavior.value.elevate && (scrollBehavior.value.inverted ? currentScroll.value > 0 : currentScroll.value === 0));
  73. const opacity = computed(() => scrollBehavior.value.fadeImage ? scrollBehavior.value.inverted ? 1 - scrollRatio.value : scrollRatio.value : undefined);
  74. const height = computed(() => {
  75. if (scrollBehavior.value.hide && scrollBehavior.value.inverted) return 0;
  76. const height = vToolbarRef.value?.contentHeight ?? 0;
  77. const extensionHeight = vToolbarRef.value?.extensionHeight ?? 0;
  78. if (!canHide.value) return height + extensionHeight;
  79. return currentScroll.value < scrollThreshold.value || scrollBehavior.value.fullyHide ? height + extensionHeight : height;
  80. });
  81. useToggleScope(computed(() => !!props.scrollBehavior), () => {
  82. watchEffect(() => {
  83. if (canHide.value) {
  84. if (scrollBehavior.value.inverted) {
  85. isActive.value = currentScroll.value > scrollThreshold.value;
  86. } else {
  87. isActive.value = isScrollingUp.value || currentScroll.value < scrollThreshold.value;
  88. }
  89. } else {
  90. isActive.value = true;
  91. }
  92. });
  93. });
  94. const {
  95. ssrBootStyles
  96. } = useSsrBoot();
  97. const {
  98. layoutItemStyles
  99. } = useLayoutItem({
  100. id: props.name,
  101. order: computed(() => parseInt(props.order, 10)),
  102. position: toRef(props, 'location'),
  103. layoutSize: height,
  104. elementSize: shallowRef(undefined),
  105. active: isActive,
  106. absolute: toRef(props, 'absolute')
  107. });
  108. useRender(() => {
  109. const toolbarProps = VToolbar.filterProps(props);
  110. return _createVNode(VToolbar, _mergeProps({
  111. "ref": vToolbarRef,
  112. "class": ['v-app-bar', {
  113. 'v-app-bar--bottom': props.location === 'bottom'
  114. }, props.class],
  115. "style": [{
  116. ...layoutItemStyles.value,
  117. '--v-toolbar-image-opacity': opacity.value,
  118. height: undefined,
  119. ...ssrBootStyles.value
  120. }, props.style]
  121. }, toolbarProps, {
  122. "collapse": isCollapsed.value,
  123. "flat": isFlat.value
  124. }), slots);
  125. });
  126. return {};
  127. }
  128. });
  129. //# sourceMappingURL=VAppBar.mjs.map