UNPKG

@varlet/ui

Version:

A Vue3 component library based on Material Design 2 and 3, supporting mobile and desktop.

366 lines (365 loc) • 14 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); import { computed, defineComponent, ref } from "vue"; import { call, preventDefault } from "@varlet/shared"; import { useEventListener, useVModel } from "@varlet/use"; import VarMenu from "../menu/index.mjs"; import VarMenuOption from "../menu-option/index.mjs"; import { useSelectController } from "../select/useSelectController.mjs"; import { createNamespace, formatElevation } from "../utils/components.mjs"; import { focusChildElementByKey } from "../utils/elements.mjs"; import VarMenuChildren from "./MenuChildren.mjs"; import { props } from "./props.mjs"; import { useMenuOptions } from "./provide.mjs"; const { name, n, classes } = createNamespace("menu-select"); import { renderSlot as _renderSlot, renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, resolveComponent as _resolveComponent, createBlock as _createBlock, normalizeClass as _normalizeClass, createElementVNode as _createElementVNode, withCtx as _withCtx } from "vue"; function __render__(_ctx, _cache) { const _component_var_menu_children = _resolveComponent("var-menu-children"); const _component_var_menu_option = _resolveComponent("var-menu-option"); const _component_var_menu = _resolveComponent("var-menu"); return _openBlock(), _createBlock(_component_var_menu, { ref: "menu", show: _ctx.show, "onUpdate:show": _cache[1] || (_cache[1] = ($event) => _ctx.show = $event), tabindex: "-1", class: _normalizeClass(_ctx.n()), disabled: _ctx.disabled, trigger: _ctx.trigger, reference: _ctx.reference, placement: _ctx.placement, strategy: _ctx.strategy, "offset-x": _ctx.offsetX, "offset-y": _ctx.offsetY, teleport: _ctx.teleport, "same-width": _ctx.sameWidth, elevation: _ctx.elevation, "default-style": false, "popover-class": _ctx.popoverClass, "close-on-click-reference": _ctx.closeOnClickReference, "close-on-key-escape": false, onOpen: _ctx.onOpen, onOpened: _ctx.onOpened, onClose: _ctx.onClose, onClosed: _ctx.onClosed, onClickOutside: _ctx.onClickOutside }, { menu: _withCtx(() => [ _createElementVNode( "div", { ref: "menuOptionsRef", class: _normalizeClass(_ctx.classes(_ctx.n("menu"), _ctx.formatElevation(_ctx.elevation, 3), [_ctx.scrollable, _ctx.n("--scrollable")])) }, [ (_openBlock(true), _createElementBlock( _Fragment, null, _renderList(_ctx.options, (option) => { return _openBlock(), _createElementBlock( _Fragment, { key: option[_ctx.valueKey] }, [ option[_ctx.childrenKey] ? (_openBlock(), _createBlock(_component_var_menu_children, { key: 0, ref_for: true, ref: "menuChildren", "parent-show": _ctx.show, option, options: option[_ctx.childrenKey], "highlight-options": _ctx.highlightOptions, disabled: option.disabled, onKeyArrowRightOpen: ($event) => _ctx.allowChildrenClose(option), onMouseenter: ($event) => _ctx.allowChildrenClose(option) }, null, 8, ["parent-show", "option", "options", "highlight-options", "disabled", "onKeyArrowRightOpen", "onMouseenter"])) : (_openBlock(), _createBlock(_component_var_menu_option, { key: 1, label: option[_ctx.labelKey], value: option[_ctx.valueKey], option, ripple: option.ripple, disabled: option.disabled, onMouseenter: _cache[0] || (_cache[0] = ($event) => _ctx.allowChildrenClose()) }, null, 8, ["label", "value", "option", "ripple", "disabled"])) ], 64 /* STABLE_FRAGMENT */ ); }), 128 /* KEYED_FRAGMENT */ )), _renderSlot(_ctx.$slots, "options") ], 2 /* CLASS */ ) ]), default: _withCtx(() => [ _renderSlot(_ctx.$slots, "default") ]), _: 3 /* FORWARDED */ }, 8, ["show", "class", "disabled", "trigger", "reference", "placement", "strategy", "offset-x", "offset-y", "teleport", "same-width", "elevation", "popover-class", "close-on-click-reference", "onOpen", "onOpened", "onClose", "onClosed", "onClickOutside"]); } const __sfc__ = defineComponent({ name, components: { VarMenu, VarMenuOption, VarMenuChildren }, props, setup(props2) { const show = useVModel(props2, "show"); const menu = ref(); const menuOptionsRef = ref(); const menuChildren = ref(); const enhancedOptions = computed(() => enhance(props2.options)); const { menuOptions, length, bindMenuOptions } = useMenuOptions(); const { computeLabel, getSelectedValue, getOptionProviderKey } = useSelectController({ modelValue: () => props2.modelValue, multiple: () => props2.multiple, optionProviders: () => menuOptions, optionProvidersLength: () => length.value, optionIsIndeterminate(optionProvider) { var _a; const enhancedOption = getEnhancedOption(optionProvider.value.value); if (!enhancedOption) { return false; } const children = ((_a = enhancedOption._children) != null ? _a : []).filter((option) => !option.disabled); const selectedChildren = children.filter((option) => props2.modelValue.includes(option.value)); return selectedChildren.length > 0 && selectedChildren.length < children.length; } }); const highlightOptions = computed(() => { const { multiple, modelValue } = props2; if (multiple) { return []; } const selectedOption = enhancedOptions.value.find((option) => option.value === modelValue); const highlightOptions2 = []; let parent = selectedOption == null ? void 0 : selectedOption._parent; while (parent) { highlightOptions2.push(parent); parent = parent._parent; } return highlightOptions2; }); const menuSelectProvider = { size: computed(() => props2.size), multiple: computed(() => props2.multiple), computeLabel, onSelect }; bindMenuOptions(menuSelectProvider); useEventListener(() => window, "keydown", handleKeydown); function getEnhancedOption(value) { return enhancedOptions.value.find((option) => option.value === value); } function getOptionProvider(value) { return menuOptions.find((optionProvider) => optionProvider.value.value === value); } function getOptionChildren(option) { return option[props2.childrenKey]; } function flatten(options) { const flattenOptions = []; baseFlatten(options); function baseFlatten(options2) { options2.forEach((option) => { flattenOptions.push(option); const children = getOptionChildren(option); if (children) { baseFlatten(children); } }); } return flattenOptions; } function enhance(options) { function baseEnhance(options2, parent) { return options2.map((option) => { option = __spreadProps(__spreadValues({}, option), { _rawOption: option }); if (parent) { option._parent = parent; } const children = getOptionChildren(option); if (children) { const enhancedChildren = baseEnhance(children, option); option[props2.childrenKey] = enhancedChildren; option._children = flatten(enhancedChildren); } return option; }); } return flatten(baseEnhance(options)); } function onSelect(optionProvider) { var _a, _b; const { multiple, closeOnSelect } = props2; const { value, label, selected, disabled, ripple } = optionProvider; const enhancedOption = getEnhancedOption(value.value); if (enhancedOption) { const childrenValues = ((_a = enhancedOption._children) != null ? _a : []).filter((option) => !option.disabled).map((option) => option.value); if (multiple && selected.value) { menuOptions.forEach((optionProvider2) => { if (childrenValues.includes(optionProvider2.value.value)) { optionProvider2.sync(true, false); } }); broadcastParentOption(enhancedOption); } if (multiple && !selected.value) { menuOptions.forEach((optionProvider2) => { if (childrenValues.includes(optionProvider2.value.value)) { optionProvider2.sync(false, false); } }); broadcastParentOption(enhancedOption); } } const selectedValue = getSelectedValue(optionProvider); const selectedOption = (_b = enhancedOption == null ? void 0 : enhancedOption._rawOption) != null ? _b : { value: value.value, label: label.value, disabled: disabled.value, ripple: ripple.value }; call(props2.onSelect, getOptionProviderKey(optionProvider), selectedOption); call(props2["onUpdate:modelValue"], selectedValue); if (!multiple && closeOnSelect) { menu.value.$el.focus(); close(); } } function broadcastParentOption(enhancedOption) { let parentOption = enhancedOption._parent; while (parentOption) { const parentOptionProvider = getOptionProvider(parentOption.value); const parentOptionChildren = getOptionChildren(parentOption).filter((option) => !option.disabled); const isAllChildrenUnselected = parentOptionChildren.every((option) => { const optionProvider = getOptionProvider(option.value); return !optionProvider.selected.value; }); const isAllChildrenSelected = parentOptionChildren.every((option) => { const optionProvider = getOptionProvider(option.value); return optionProvider.selected.value; }); if (isAllChildrenUnselected) { parentOptionProvider.sync(false, false); } else if (isAllChildrenSelected) { parentOptionProvider.sync(true, false); } else { parentOptionProvider.sync(false, true); } parentOption = parentOption._parent; } } function handleKeydown(event) { if (props2.disabled || !show.value) { return; } const { key } = event; if (["Escape", "ArrowDown", "ArrowUp"].includes(key)) { preventDefault(event); } if (key === "Escape") { menu.value.$el.focus(); close(); call(props2.onKeyEscape); return; } if (key === "ArrowDown" || key === "ArrowUp") { focusChildElementByKey( menu.value.$el, menuOptionsRef.value, key, (activeElement, nextActiveElement, isActiveInReferenceElements) => { if (isActiveInReferenceElements) { return true; } return getActiveElementParent(activeElement) === getActiveElementParent(nextActiveElement); } ); } } function getActiveElementParent(activeElement) { var _a, _b, _c; if (activeElement.classList.contains("var-menu-option--children-trigger")) { return (_a = activeElement.parentNode) == null ? void 0 : _a.parentNode; } if (activeElement.classList.contains("var-checkbox__action")) { const optionElement = (_c = (_b = activeElement.parentNode) == null ? void 0 : _b.parentNode) == null ? void 0 : _c.parentNode; if (optionElement) { return getActiveElementParent(optionElement); } } return activeElement.parentNode; } function allowChildrenClose(option) { var _a; (_a = menuChildren.value) == null ? void 0 : _a.forEach((child) => { child.allowClose(); if (option == null) { child.close(); return; } if (child.option.value === option.value) { return; } child.close(); }); } function open() { var _a; (_a = menu.value) == null ? void 0 : _a.open(); } function close() { var _a; (_a = menu.value) == null ? void 0 : _a.close(); } function resize() { var _a; (_a = menu.value) == null ? void 0 : _a.resize(); } function setReference(reference) { var _a; (_a = menu.value) == null ? void 0 : _a.setReference(reference); } return { show, menu, menuOptionsRef, menuChildren, highlightOptions, n, classes, allowChildrenClose, formatElevation, open, close, resize, setReference }; } }); __sfc__.render = __render__; var stdin_default = __sfc__; export { stdin_default as default };