@varlet/ui
Version:
A Vue3 component library based on Material Design 2 and 3, supporting mobile and desktop.
366 lines (365 loc) • 14 kB
JavaScript
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
};