Cascader.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. var __defProp = Object.defineProperty;
  2. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  3. var __getOwnPropNames = Object.getOwnPropertyNames;
  4. var __hasOwnProp = Object.prototype.hasOwnProperty;
  5. var __export = (target, all) => {
  6. for (var name2 in all)
  7. __defProp(target, name2, { get: all[name2], enumerable: true });
  8. };
  9. var __copyProps = (to, from, except, desc) => {
  10. if (from && typeof from === "object" || typeof from === "function") {
  11. for (let key of __getOwnPropNames(from))
  12. if (!__hasOwnProp.call(to, key) && key !== except)
  13. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  14. }
  15. return to;
  16. };
  17. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  18. var stdin_exports = {};
  19. __export(stdin_exports, {
  20. default: () => stdin_default
  21. });
  22. module.exports = __toCommonJS(stdin_exports);
  23. var import_vue = require("vue");
  24. var import_vue2 = require("vue");
  25. var import_utils = require("../utils");
  26. var import_tab = require("../tab");
  27. var import_tabs = require("../tabs");
  28. var import_icon = require("../icon");
  29. const [name, bem, t] = (0, import_utils.createNamespace)("cascader");
  30. const cascaderProps = {
  31. title: String,
  32. options: (0, import_utils.makeArrayProp)(),
  33. closeable: import_utils.truthProp,
  34. swipeable: import_utils.truthProp,
  35. closeIcon: (0, import_utils.makeStringProp)("cross"),
  36. showHeader: import_utils.truthProp,
  37. modelValue: import_utils.numericProp,
  38. fieldNames: Object,
  39. placeholder: String,
  40. activeColor: String
  41. };
  42. var stdin_default = (0, import_vue2.defineComponent)({
  43. name,
  44. props: cascaderProps,
  45. emits: ["close", "change", "finish", "click-tab", "update:modelValue"],
  46. setup(props, {
  47. slots,
  48. emit
  49. }) {
  50. const tabs = (0, import_vue2.ref)([]);
  51. const activeTab = (0, import_vue2.ref)(0);
  52. const {
  53. text: textKey,
  54. value: valueKey,
  55. children: childrenKey
  56. } = (0, import_utils.extend)({
  57. text: "text",
  58. value: "value",
  59. children: "children"
  60. }, props.fieldNames);
  61. const getSelectedOptionsByValue = (options, value) => {
  62. for (const option of options) {
  63. if (option[valueKey] === value) {
  64. return [option];
  65. }
  66. if (option[childrenKey]) {
  67. const selectedOptions = getSelectedOptionsByValue(option[childrenKey], value);
  68. if (selectedOptions) {
  69. return [option, ...selectedOptions];
  70. }
  71. }
  72. }
  73. };
  74. const updateTabs = () => {
  75. const {
  76. options,
  77. modelValue
  78. } = props;
  79. if (modelValue !== void 0) {
  80. const selectedOptions = getSelectedOptionsByValue(options, modelValue);
  81. if (selectedOptions) {
  82. let optionsCursor = options;
  83. tabs.value = selectedOptions.map((option) => {
  84. const tab = {
  85. options: optionsCursor,
  86. selected: option
  87. };
  88. const next = optionsCursor.find((item) => item[valueKey] === option[valueKey]);
  89. if (next) {
  90. optionsCursor = next[childrenKey];
  91. }
  92. return tab;
  93. });
  94. if (optionsCursor) {
  95. tabs.value.push({
  96. options: optionsCursor,
  97. selected: null
  98. });
  99. }
  100. (0, import_vue2.nextTick)(() => {
  101. activeTab.value = tabs.value.length - 1;
  102. });
  103. return;
  104. }
  105. }
  106. tabs.value = [{
  107. options,
  108. selected: null
  109. }];
  110. };
  111. const onSelect = (option, tabIndex) => {
  112. if (option.disabled) {
  113. return;
  114. }
  115. tabs.value[tabIndex].selected = option;
  116. if (tabs.value.length > tabIndex + 1) {
  117. tabs.value = tabs.value.slice(0, tabIndex + 1);
  118. }
  119. if (option[childrenKey]) {
  120. const nextTab = {
  121. options: option[childrenKey],
  122. selected: null
  123. };
  124. if (tabs.value[tabIndex + 1]) {
  125. tabs.value[tabIndex + 1] = nextTab;
  126. } else {
  127. tabs.value.push(nextTab);
  128. }
  129. (0, import_vue2.nextTick)(() => {
  130. activeTab.value++;
  131. });
  132. }
  133. const selectedOptions = tabs.value.map((tab) => tab.selected).filter(Boolean);
  134. emit("update:modelValue", option[valueKey]);
  135. const params = {
  136. value: option[valueKey],
  137. tabIndex,
  138. selectedOptions
  139. };
  140. emit("change", params);
  141. if (!option[childrenKey]) {
  142. emit("finish", params);
  143. }
  144. };
  145. const onClose = () => emit("close");
  146. const onClickTab = ({
  147. name: name2,
  148. title
  149. }) => emit("click-tab", name2, title);
  150. const renderHeader = () => props.showHeader ? (0, import_vue.createVNode)("div", {
  151. "class": bem("header")
  152. }, [(0, import_vue.createVNode)("h2", {
  153. "class": bem("title")
  154. }, [slots.title ? slots.title() : props.title]), props.closeable ? (0, import_vue.createVNode)(import_icon.Icon, {
  155. "name": props.closeIcon,
  156. "class": [bem("close-icon"), import_utils.HAPTICS_FEEDBACK],
  157. "onClick": onClose
  158. }, null) : null]) : null;
  159. const renderOption = (option, selectedOption, tabIndex) => {
  160. const {
  161. disabled
  162. } = option;
  163. const selected = !!(selectedOption && option[valueKey] === selectedOption[valueKey]);
  164. const color = option.color || (selected ? props.activeColor : void 0);
  165. const Text = slots.option ? slots.option({
  166. option,
  167. selected
  168. }) : (0, import_vue.createVNode)("span", null, [option[textKey]]);
  169. return (0, import_vue.createVNode)("li", {
  170. "role": "menuitemradio",
  171. "class": [bem("option", {
  172. selected,
  173. disabled
  174. }), option.className],
  175. "style": {
  176. color
  177. },
  178. "tabindex": disabled ? void 0 : selected ? 0 : -1,
  179. "aria-checked": selected,
  180. "aria-disabled": disabled || void 0,
  181. "onClick": () => onSelect(option, tabIndex)
  182. }, [Text, selected ? (0, import_vue.createVNode)(import_icon.Icon, {
  183. "name": "success",
  184. "class": bem("selected-icon")
  185. }, null) : null]);
  186. };
  187. const renderOptions = (options, selectedOption, tabIndex) => (0, import_vue.createVNode)("ul", {
  188. "role": "menu",
  189. "class": bem("options")
  190. }, [options.map((option) => renderOption(option, selectedOption, tabIndex))]);
  191. const renderTab = (tab, tabIndex) => {
  192. const {
  193. options,
  194. selected
  195. } = tab;
  196. const placeholder = props.placeholder || t("select");
  197. const title = selected ? selected[textKey] : placeholder;
  198. return (0, import_vue.createVNode)(import_tab.Tab, {
  199. "title": title,
  200. "titleClass": bem("tab", {
  201. unselected: !selected
  202. })
  203. }, {
  204. default: () => {
  205. var _a, _b;
  206. return [(_a = slots["options-top"]) == null ? void 0 : _a.call(slots, {
  207. tabIndex
  208. }), renderOptions(options, selected, tabIndex), (_b = slots["options-bottom"]) == null ? void 0 : _b.call(slots, {
  209. tabIndex
  210. })];
  211. }
  212. });
  213. };
  214. const renderTabs = () => (0, import_vue.createVNode)(import_tabs.Tabs, {
  215. "active": activeTab.value,
  216. "onUpdate:active": ($event) => activeTab.value = $event,
  217. "shrink": true,
  218. "animated": true,
  219. "class": bem("tabs"),
  220. "color": props.activeColor,
  221. "swipeable": props.swipeable,
  222. "onClick-tab": onClickTab
  223. }, {
  224. default: () => [tabs.value.map(renderTab)]
  225. });
  226. updateTabs();
  227. (0, import_vue2.watch)(() => props.options, updateTabs, {
  228. deep: true
  229. });
  230. (0, import_vue2.watch)(() => props.modelValue, (value) => {
  231. if (value !== void 0) {
  232. const values = tabs.value.map((tab) => {
  233. var _a;
  234. return (_a = tab.selected) == null ? void 0 : _a[valueKey];
  235. });
  236. if (values.includes(value)) {
  237. return;
  238. }
  239. }
  240. updateTabs();
  241. });
  242. return () => (0, import_vue.createVNode)("div", {
  243. "class": bem()
  244. }, [renderHeader(), renderTabs()]);
  245. }
  246. });