CollapseItem.mjs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import { ref, watch, computed, nextTick, defineComponent, mergeProps as _mergeProps, createVNode as _createVNode, vShow as _vShow, withDirectives as _withDirectives } from "vue";
  2. import { cellSharedProps } from "../cell/Cell.mjs";
  3. import { pick, extend, truthProp, numericProp, createNamespace } from "../utils/index.mjs";
  4. import { COLLAPSE_KEY } from "../collapse/Collapse.mjs";
  5. import { raf, doubleRaf, useParent } from "@vant/use";
  6. import { useExpose } from "../composables/use-expose.mjs";
  7. import { useLazyRender } from "../composables/use-lazy-render.mjs";
  8. import { Cell } from "../cell/index.mjs";
  9. const [name, bem] = createNamespace("collapse-item");
  10. const CELL_SLOTS = ["icon", "title", "value", "label", "right-icon"];
  11. const collapseItemProps = extend({}, cellSharedProps, {
  12. name: numericProp,
  13. isLink: truthProp,
  14. disabled: Boolean,
  15. readonly: Boolean,
  16. lazyRender: truthProp
  17. });
  18. var stdin_default = defineComponent({
  19. name,
  20. props: collapseItemProps,
  21. setup(props, {
  22. slots
  23. }) {
  24. const wrapperRef = ref();
  25. const contentRef = ref();
  26. const {
  27. parent,
  28. index
  29. } = useParent(COLLAPSE_KEY);
  30. if (!parent) {
  31. if (process.env.NODE_ENV !== "production") {
  32. console.error("[Vant] <CollapseItem> must be a child component of <Collapse>.");
  33. }
  34. return;
  35. }
  36. const name2 = computed(() => {
  37. var _a;
  38. return (_a = props.name) != null ? _a : index.value;
  39. });
  40. const expanded = computed(() => parent.isExpanded(name2.value));
  41. const show = ref(expanded.value);
  42. const lazyRender = useLazyRender(() => show.value || !props.lazyRender);
  43. const onTransitionEnd = () => {
  44. if (!expanded.value) {
  45. show.value = false;
  46. } else if (wrapperRef.value) {
  47. wrapperRef.value.style.height = "";
  48. }
  49. };
  50. watch(expanded, (value, oldValue) => {
  51. if (oldValue === null) {
  52. return;
  53. }
  54. if (value) {
  55. show.value = true;
  56. }
  57. const tick = value ? nextTick : raf;
  58. tick(() => {
  59. if (!contentRef.value || !wrapperRef.value) {
  60. return;
  61. }
  62. const {
  63. offsetHeight
  64. } = contentRef.value;
  65. if (offsetHeight) {
  66. const contentHeight = `${offsetHeight}px`;
  67. wrapperRef.value.style.height = value ? "0" : contentHeight;
  68. doubleRaf(() => {
  69. if (wrapperRef.value) {
  70. wrapperRef.value.style.height = value ? contentHeight : "0";
  71. }
  72. });
  73. } else {
  74. onTransitionEnd();
  75. }
  76. });
  77. });
  78. const toggle = (newValue = !expanded.value) => {
  79. parent.toggle(name2.value, newValue);
  80. };
  81. const onClickTitle = () => {
  82. if (!props.disabled && !props.readonly) {
  83. toggle();
  84. }
  85. };
  86. const renderTitle = () => {
  87. const {
  88. border,
  89. disabled,
  90. readonly
  91. } = props;
  92. const attrs = pick(props, Object.keys(cellSharedProps));
  93. if (readonly) {
  94. attrs.isLink = false;
  95. }
  96. if (disabled || readonly) {
  97. attrs.clickable = false;
  98. }
  99. return _createVNode(Cell, _mergeProps({
  100. "role": "button",
  101. "class": bem("title", {
  102. disabled,
  103. expanded: expanded.value,
  104. borderless: !border
  105. }),
  106. "aria-expanded": String(expanded.value),
  107. "onClick": onClickTitle
  108. }, attrs), pick(slots, CELL_SLOTS));
  109. };
  110. const renderContent = lazyRender(() => {
  111. var _a;
  112. return _withDirectives(_createVNode("div", {
  113. "ref": wrapperRef,
  114. "class": bem("wrapper"),
  115. "onTransitionend": onTransitionEnd
  116. }, [_createVNode("div", {
  117. "ref": contentRef,
  118. "class": bem("content")
  119. }, [(_a = slots.default) == null ? void 0 : _a.call(slots)])]), [[_vShow, show.value]]);
  120. });
  121. useExpose({
  122. toggle,
  123. expanded,
  124. itemName: name2
  125. });
  126. return () => _createVNode("div", {
  127. "class": [bem({
  128. border: index.value && props.border
  129. })]
  130. }, [renderTitle(), renderContent()]);
  131. }
  132. });
  133. export {
  134. collapseItemProps,
  135. stdin_default as default
  136. };