UNPKG

reka-ui

Version:

Vue port for Radix UI Primitives.

350 lines (347 loc) 11.8 kB
const require_rolldown_runtime = require('../rolldown-runtime.cjs'); const require_shared_arrays = require('../shared/arrays.cjs'); const require_shared_createContext = require('../shared/createContext.cjs'); const require_shared_useDirection = require('../shared/useDirection.cjs'); const require_shared_useFormControl = require('../shared/useFormControl.cjs'); const require_shared_useKbd = require('../shared/useKbd.cjs'); const require_shared_useTypeahead = require('../shared/useTypeahead.cjs'); const require_Primitive_Primitive = require('../Primitive/Primitive.cjs'); const require_Primitive_usePrimitiveElement = require('../Primitive/usePrimitiveElement.cjs'); const require_Collection_Collection = require('../Collection/Collection.cjs'); const require_RovingFocus_utils = require('../RovingFocus/utils.cjs'); const require_VisuallyHidden_VisuallyHiddenInput = require('../VisuallyHidden/VisuallyHiddenInput.cjs'); const require_Listbox_utils = require('./utils.cjs'); const vue = require_rolldown_runtime.__toESM(require("vue")); const __vueuse_core = require_rolldown_runtime.__toESM(require("@vueuse/core")); //#region src/Listbox/ListboxRoot.vue?vue&type=script&setup=true&lang.ts const [injectListboxRootContext, provideListboxRootContext] = require_shared_createContext.createContext("ListboxRoot"); var ListboxRoot_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ (0, vue.defineComponent)({ __name: "ListboxRoot", props: { modelValue: { type: null, required: false }, defaultValue: { type: null, required: false }, multiple: { type: Boolean, required: false }, orientation: { type: String, required: false, default: "vertical" }, dir: { type: String, required: false }, disabled: { type: Boolean, required: false }, selectionBehavior: { type: String, required: false, default: "toggle" }, highlightOnHover: { type: Boolean, required: false }, by: { type: [String, Function], required: false }, asChild: { type: Boolean, required: false }, as: { type: null, required: false }, name: { type: String, required: false }, required: { type: Boolean, required: false } }, emits: [ "update:modelValue", "highlight", "entryFocus", "leave" ], setup(__props, { expose: __expose, emit: __emit }) { const props = __props; const emits = __emit; const { multiple, highlightOnHover, orientation, disabled, selectionBehavior, dir: propDir } = (0, vue.toRefs)(props); const { getItems } = require_Collection_Collection.useCollection({ isProvider: true }); const { handleTypeaheadSearch } = require_shared_useTypeahead.useTypeahead(); const { primitiveElement, currentElement } = require_Primitive_usePrimitiveElement.usePrimitiveElement(); const kbd = require_shared_useKbd.useKbd(); const dir = require_shared_useDirection.useDirection(propDir); const isFormControl = require_shared_useFormControl.useFormControl(currentElement); const firstValue = (0, vue.ref)(); const isUserAction = (0, vue.ref)(false); const focusable = (0, vue.ref)(true); const modelValue = (0, __vueuse_core.useVModel)(props, "modelValue", emits, { defaultValue: props.defaultValue ?? (multiple.value ? [] : void 0), passive: props.modelValue === void 0, deep: true }); function onValueChange(val) { isUserAction.value = true; if (props.multiple) { const modelArray = Array.isArray(modelValue.value) ? [...modelValue.value] : []; const index = modelArray.findIndex((i) => require_Listbox_utils.compare(i, val, props.by)); if (props.selectionBehavior === "toggle") { index === -1 ? modelArray.push(val) : modelArray.splice(index, 1); modelValue.value = modelArray; } else { modelValue.value = [val]; firstValue.value = val; } } else if (props.selectionBehavior === "toggle") if (require_Listbox_utils.compare(modelValue.value, val, props.by)) modelValue.value = void 0; else modelValue.value = val; else modelValue.value = val; setTimeout(() => { isUserAction.value = false; }, 1); } const highlightedElement = (0, vue.ref)(null); const previousElement = (0, vue.ref)(null); const isVirtual = (0, vue.ref)(false); const isComposing = (0, vue.ref)(false); const virtualFocusHook = (0, __vueuse_core.createEventHook)(); const virtualKeydownHook = (0, __vueuse_core.createEventHook)(); const virtualHighlightHook = (0, __vueuse_core.createEventHook)(); function getCollectionItem() { return getItems().map((i) => i.ref).filter((i) => i.dataset.disabled !== ""); } function changeHighlight(el, scrollIntoView = true) { if (!el) return; highlightedElement.value = el; if (focusable.value) highlightedElement.value.focus(); if (scrollIntoView) highlightedElement.value.scrollIntoView({ block: "nearest" }); const highlightedItem = getItems().find((i) => i.ref === el); emits("highlight", highlightedItem); } function highlightItem(value) { if (isVirtual.value) virtualHighlightHook.trigger(value); else { const item = getItems().find((i) => require_Listbox_utils.compare(i.value, value, props.by)); if (item) { highlightedElement.value = item.ref; changeHighlight(item.ref); } } } function onKeydownEnter(event) { if (highlightedElement.value && highlightedElement.value.isConnected) { event.preventDefault(); event.stopPropagation(); if (!isComposing.value) highlightedElement.value.click(); } } function onKeydownTypeAhead(event) { if (!focusable.value) return; isUserAction.value = true; if (isVirtual.value) virtualKeydownHook.trigger(event); else { const isMetaKey = event.altKey || event.ctrlKey || event.metaKey; if (isMetaKey && event.key === "a" && multiple.value) { const collection = getItems(); const values = collection.map((i) => i.value); modelValue.value = [...values]; event.preventDefault(); changeHighlight(collection[collection.length - 1].ref); } else if (!isMetaKey) { const el = handleTypeaheadSearch(event.key, getItems()); if (el) changeHighlight(el); } } setTimeout(() => { isUserAction.value = false; }, 1); } function onCompositionStart() { isComposing.value = true; } function onCompositionEnd() { (0, vue.nextTick)(() => { isComposing.value = false; }); } function highlightFirstItem() { (0, vue.nextTick)(() => { const event = new KeyboardEvent("keydown", { key: "PageUp" }); onKeydownNavigation(event); }); } function onLeave(event) { const el = highlightedElement.value; if (el?.isConnected) previousElement.value = el; highlightedElement.value = null; emits("leave", event); } function onEnter(event) { const entryFocusEvent = new CustomEvent("listbox.entryFocus", { bubbles: false, cancelable: true }); event.currentTarget?.dispatchEvent(entryFocusEvent); emits("entryFocus", entryFocusEvent); if (entryFocusEvent.defaultPrevented) return; if (previousElement.value) changeHighlight(previousElement.value); else { const el = getCollectionItem()?.[0]; changeHighlight(el); } } function onKeydownNavigation(event) { const intent = require_RovingFocus_utils.getFocusIntent(event, orientation.value, dir.value); if (!intent) return; let collection = getCollectionItem(); if (highlightedElement.value) { if (intent === "last") collection.reverse(); else if (intent === "prev" || intent === "next") { if (intent === "prev") collection.reverse(); const currentIndex = collection.indexOf(highlightedElement.value); collection = collection.slice(currentIndex + 1); } handleMultipleReplace(event, collection[0]); } if (collection.length) { const index = !highlightedElement.value && intent === "prev" ? collection.length - 1 : 0; changeHighlight(collection[index]); } if (isVirtual.value) return virtualKeydownHook.trigger(event); } function handleMultipleReplace(event, targetEl) { if (isVirtual.value || props.selectionBehavior !== "replace" || !multiple.value || !Array.isArray(modelValue.value)) return; const isMetaKey = event.altKey || event.ctrlKey || event.metaKey; if (isMetaKey && !event.shiftKey) return; if (event.shiftKey) { const collection = getItems().filter((i) => i.ref.dataset.disabled !== ""); let lastValue = collection.find((i) => i.ref === targetEl)?.value; if (event.key === kbd.END) lastValue = collection[collection.length - 1].value; else if (event.key === kbd.HOME) lastValue = collection[0].value; if (!lastValue || !firstValue.value) return; const values = require_shared_arrays.findValuesBetween(collection.map((i) => i.value), firstValue.value, lastValue); modelValue.value = values; } } async function highlightSelected(event) { await (0, vue.nextTick)(); if (isVirtual.value) virtualFocusHook.trigger(event); else { const collection = getCollectionItem(); const item = collection.find((i) => i.dataset.state === "checked"); if (item) changeHighlight(item); else if (collection.length) changeHighlight(collection[0]); } } (0, vue.watch)(modelValue, () => { if (!isUserAction.value) (0, vue.nextTick)(() => { highlightSelected(); }); }, { immediate: true, deep: true }); __expose({ highlightedElement, highlightItem, highlightFirstItem, highlightSelected, getItems }); provideListboxRootContext({ modelValue, onValueChange, multiple, orientation, dir, disabled, highlightOnHover, highlightedElement, isVirtual, virtualFocusHook, virtualKeydownHook, virtualHighlightHook, by: props.by, firstValue, selectionBehavior, focusable, onLeave, onEnter, changeHighlight, onKeydownEnter, onKeydownNavigation, onKeydownTypeAhead, onCompositionStart, onCompositionEnd, highlightFirstItem }); return (_ctx, _cache) => { return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(require_Primitive_Primitive.Primitive), { ref_key: "primitiveElement", ref: primitiveElement, as: _ctx.as, "as-child": _ctx.asChild, dir: (0, vue.unref)(dir), "data-disabled": (0, vue.unref)(disabled) ? "" : void 0, onPointerleave: onLeave, onFocusout: _cache[0] || (_cache[0] = async (event) => { const target = event.relatedTarget || event.target; await (0, vue.nextTick)(); if (highlightedElement.value && (0, vue.unref)(currentElement) && !(0, vue.unref)(currentElement).contains(target)) onLeave(event); }) }, { default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "default", { modelValue: (0, vue.unref)(modelValue) }), (0, vue.unref)(isFormControl) && _ctx.name ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(require_VisuallyHidden_VisuallyHiddenInput.VisuallyHiddenInput_default), { key: 0, name: _ctx.name, value: (0, vue.unref)(modelValue), disabled: (0, vue.unref)(disabled), required: _ctx.required }, null, 8, [ "name", "value", "disabled", "required" ])) : (0, vue.createCommentVNode)("v-if", true)]), _: 3 }, 8, [ "as", "as-child", "dir", "data-disabled" ]); }; } }); //#endregion //#region src/Listbox/ListboxRoot.vue var ListboxRoot_default = ListboxRoot_vue_vue_type_script_setup_true_lang_default; //#endregion Object.defineProperty(exports, 'ListboxRoot_default', { enumerable: true, get: function () { return ListboxRoot_default; } }); Object.defineProperty(exports, 'injectListboxRootContext', { enumerable: true, get: function () { return injectListboxRootContext; } }); //# sourceMappingURL=ListboxRoot.cjs.map