DropdownItem.mjs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. import { withDirectives as _withDirectives, mergeProps as _mergeProps, vShow as _vShow, createVNode as _createVNode } from "vue";
  2. import { reactive, Teleport, defineComponent } from "vue";
  3. import { truthProp, unknownProp, getZIndexStyle, createNamespace, makeArrayProp } from "../utils/index.mjs";
  4. import { DROPDOWN_KEY } from "../dropdown-menu/DropdownMenu.mjs";
  5. import { useParent } from "@vant/use";
  6. import { useExpose } from "../composables/use-expose.mjs";
  7. import { Cell } from "../cell/index.mjs";
  8. import { Icon } from "../icon/index.mjs";
  9. import { Popup } from "../popup/index.mjs";
  10. const [name, bem] = createNamespace("dropdown-item");
  11. const dropdownItemProps = {
  12. title: String,
  13. options: makeArrayProp(),
  14. disabled: Boolean,
  15. teleport: [String, Object],
  16. lazyRender: truthProp,
  17. modelValue: unknownProp,
  18. titleClass: unknownProp
  19. };
  20. var stdin_default = defineComponent({
  21. name,
  22. inheritAttrs: false,
  23. props: dropdownItemProps,
  24. emits: ["open", "opened", "close", "closed", "change", "update:modelValue"],
  25. setup(props, {
  26. emit,
  27. slots,
  28. attrs
  29. }) {
  30. const state = reactive({
  31. showPopup: false,
  32. transition: true,
  33. showWrapper: false
  34. });
  35. const {
  36. parent,
  37. index
  38. } = useParent(DROPDOWN_KEY);
  39. if (!parent) {
  40. if (process.env.NODE_ENV !== "production") {
  41. console.error("[Vant] <DropdownItem> must be a child component of <DropdownMenu>.");
  42. }
  43. return;
  44. }
  45. const getEmitter = (name2) => () => emit(name2);
  46. const onOpen = getEmitter("open");
  47. const onClose = getEmitter("close");
  48. const onOpened = getEmitter("opened");
  49. const onClosed = () => {
  50. state.showWrapper = false;
  51. emit("closed");
  52. };
  53. const onClickWrapper = (event) => {
  54. if (props.teleport) {
  55. event.stopPropagation();
  56. }
  57. };
  58. const toggle = (show = !state.showPopup, options = {}) => {
  59. if (show === state.showPopup) {
  60. return;
  61. }
  62. state.showPopup = show;
  63. state.transition = !options.immediate;
  64. if (show) {
  65. state.showWrapper = true;
  66. }
  67. };
  68. const renderTitle = () => {
  69. if (slots.title) {
  70. return slots.title();
  71. }
  72. if (props.title) {
  73. return props.title;
  74. }
  75. const match = props.options.find((option) => option.value === props.modelValue);
  76. return match ? match.text : "";
  77. };
  78. const renderOption = (option) => {
  79. const {
  80. activeColor
  81. } = parent.props;
  82. const active = option.value === props.modelValue;
  83. const onClick = () => {
  84. state.showPopup = false;
  85. if (option.value !== props.modelValue) {
  86. emit("update:modelValue", option.value);
  87. emit("change", option.value);
  88. }
  89. };
  90. const renderIcon = () => {
  91. if (active) {
  92. return _createVNode(Icon, {
  93. "class": bem("icon"),
  94. "color": activeColor,
  95. "name": "success"
  96. }, null);
  97. }
  98. };
  99. return _createVNode(Cell, {
  100. "role": "menuitem",
  101. "key": option.value,
  102. "icon": option.icon,
  103. "title": option.text,
  104. "class": bem("option", {
  105. active
  106. }),
  107. "style": {
  108. color: active ? activeColor : ""
  109. },
  110. "tabindex": active ? 0 : -1,
  111. "clickable": true,
  112. "onClick": onClick
  113. }, {
  114. value: renderIcon
  115. });
  116. };
  117. const renderContent = () => {
  118. const {
  119. offset
  120. } = parent;
  121. const {
  122. zIndex,
  123. overlay,
  124. duration,
  125. direction,
  126. closeOnClickOverlay
  127. } = parent.props;
  128. const style = getZIndexStyle(zIndex);
  129. if (direction === "down") {
  130. style.top = `${offset.value}px`;
  131. } else {
  132. style.bottom = `${offset.value}px`;
  133. }
  134. return _withDirectives(_createVNode("div", _mergeProps({
  135. "style": style,
  136. "class": bem([direction]),
  137. "onClick": onClickWrapper
  138. }, attrs), [_createVNode(Popup, {
  139. "show": state.showPopup,
  140. "onUpdate:show": ($event) => state.showPopup = $event,
  141. "role": "menu",
  142. "class": bem("content"),
  143. "overlay": overlay,
  144. "position": direction === "down" ? "top" : "bottom",
  145. "duration": state.transition ? duration : 0,
  146. "lazyRender": props.lazyRender,
  147. "overlayStyle": {
  148. position: "absolute"
  149. },
  150. "aria-labelledby": `${parent.id}-${index.value}`,
  151. "closeOnClickOverlay": closeOnClickOverlay,
  152. "onOpen": onOpen,
  153. "onClose": onClose,
  154. "onOpened": onOpened,
  155. "onClosed": onClosed
  156. }, {
  157. default: () => {
  158. var _a;
  159. return [props.options.map(renderOption), (_a = slots.default) == null ? void 0 : _a.call(slots)];
  160. }
  161. })]), [[_vShow, state.showWrapper]]);
  162. };
  163. useExpose({
  164. state,
  165. toggle,
  166. renderTitle
  167. });
  168. return () => {
  169. if (props.teleport) {
  170. return _createVNode(Teleport, {
  171. "to": props.teleport
  172. }, {
  173. default: () => [renderContent()]
  174. });
  175. }
  176. return renderContent();
  177. };
  178. }
  179. });
  180. export {
  181. stdin_default as default,
  182. dropdownItemProps
  183. };