UNPKG

bootstrap-vue-next

Version:

Seamless integration of Vue 3, Bootstrap 5, and TypeScript for modern, type-safe UI development

441 lines (440 loc) 15.7 kB
import { h as useFocus, o as onKeyStroke, z as useToNumber } from "./dist-B10a-gZ8.mjs"; import { i as getSafeDocument } from "./dom-AhkaSoh8.mjs"; import { t as useDefaults } from "./useDefaults-BKgBaqOV.mjs"; import { t as useId$1 } from "./useId-BKZFSYm8.mjs"; import { a as CODE_PAGEUP, i as CODE_PAGEDOWN, n as CODE_HOME, s as CODE_UP, t as CODE_DOWN } from "./constants-BSIK14yA.mjs"; import { t as useRtl } from "./useRtl-DpwU_RM8.mjs"; import { computed, createCommentVNode, createElementBlock, createElementVNode, defineComponent, guardReactiveProps, mergeModels, mergeProps, normalizeClass, normalizeProps, onUnmounted, openBlock, renderSlot, toDisplayString, unref, useModel, useTemplateRef } from "vue"; //#region src/components/BFormSpinbutton/BFormSpinbutton.vue?vue&type=script&setup=true&lang.ts var _hoisted_1 = [ "lang", "tabindex", "title" ]; var _hoisted_2 = [ "name", "form", "value" ]; var _hoisted_3 = [ "id", "dir", "tabindex", "aria-label", "aria-invalid", "aria-required", "aria-valuemin", "aria-valuemax", "aria-valuenow", "aria-valuetext" ]; var defaultValues = { min: 1, max: 100, step: 1, repeatDelay: 500, repeatInterval: 100, repeatThreshold: 10, repeatMultiplier: 4 }; //#endregion //#region src/components/BFormSpinbutton/BFormSpinbutton.vue var BFormSpinbutton_default = /* @__PURE__ */ defineComponent({ __name: "BFormSpinbutton", props: /* @__PURE__ */ mergeModels({ ariaControls: { default: void 0 }, ariaLabel: { default: void 0 }, disabled: { type: Boolean, default: false }, form: { default: void 0 }, formatterFn: { type: Function, default: void 0 }, id: { default: void 0 }, inline: { type: Boolean, default: false }, labelDecrement: { default: "Decrement" }, labelIncrement: { default: "Increment" }, locale: { default: void 0 }, max: { default: defaultValues.max }, min: { default: defaultValues.min }, name: { default: void 0 }, placeholder: { default: void 0 }, readonly: { type: Boolean, default: false }, repeatDelay: { default: defaultValues.repeatDelay }, repeatInterval: { default: defaultValues.repeatInterval }, repeatStepMultiplier: { default: defaultValues.repeatMultiplier }, repeatThreshold: { default: defaultValues.repeatThreshold }, required: { type: Boolean, default: false }, size: { default: void 0 }, state: { type: [Boolean, null], default: null }, step: { default: defaultValues.step }, vertical: { type: Boolean, default: false }, wrap: { type: Boolean, default: false } }, { "modelValue": { default: null }, "modelModifiers": {} }), emits: /* @__PURE__ */ mergeModels(["change"], ["update:modelValue"]), setup(__props, { emit: __emit }) { const KEY_CODES = [ CODE_UP, CODE_DOWN, CODE_HOME, "End", CODE_PAGEUP, CODE_PAGEDOWN ]; const props = useDefaults(__props, "BFormSpinbutton"); const emit = __emit; const modelValue = useModel(__props, "modelValue"); const element = useTemplateRef("_element"); const { focused } = useFocus(element); const computedId = useId$1(() => props.id, "spinbutton"); const computedClasses = computed(() => ({ "disabled": props.disabled, "readonly": props.readonly, "focus": focused.value, "d-inline-flex": props.inline || props.vertical, "d-flex": !props.inline && !props.vertical, "align-items-stretch": !props.vertical, "flex-column": props.vertical, [`form-control-${props.size}`]: props.size !== void 0 })); const computedSpinClasses = computed(() => ({ "d-flex": props.vertical, "align-self-center": !props.vertical, "align-items-center": props.vertical, "border-top": props.vertical, "border-bottom": props.vertical, "border-start": !props.vertical, "border-end": !props.vertical })); let $_autoDelayTimer; let $_autoRepeatTimer; let $_keyIsDown = false; const stepNumber = useToNumber(() => props.step); const computedStep = computed(() => Number.isNaN(stepNumber.value) ? defaultValues.step : stepNumber.value); const minNumber = useToNumber(() => props.min); const computedMin = computed(() => Number.isNaN(minNumber.value) ? defaultValues.min : minNumber.value); const maxNumber = useToNumber(() => props.max); const computedMax = computed(() => { const step = computedStep.value; const min = computedMin.value; return Math.floor((maxNumber.value - min) / step) * step + min; }); const repeatDelayNumber = useToNumber(() => props.repeatDelay, { nanToZero: true, method: "parseInt" }); const computedDelay = computed(() => repeatDelayNumber.value > 0 ? repeatDelayNumber.value : defaultValues.repeatDelay); const repeatIntervalNumber = useToNumber(() => props.repeatInterval, { nanToZero: true, method: "parseInt" }); const computedInterval = computed(() => repeatIntervalNumber.value > 0 ? repeatIntervalNumber.value : defaultValues.repeatInterval); const repeatThresholdNumber = useToNumber(() => props.repeatThreshold, { nanToZero: true, method: "parseInt" }); const computedThreshold = computed(() => Math.max(Number.isNaN(repeatThresholdNumber.value) ? defaultValues.repeatThreshold : repeatThresholdNumber.value, 1)); const repeatStepMultiplierNumber = useToNumber(() => props.repeatStepMultiplier, { nanToZero: true, method: "parseInt" }); const computedStepMultiplier = computed(() => Math.max(Number.isNaN(repeatStepMultiplierNumber.value) ? defaultValues.repeatMultiplier : repeatStepMultiplierNumber.value, 1)); const computedPrecision = computed(() => { const step = computedStep.value; return Math.floor(step) === step ? 0 : (step.toString().split(".")[1] || "").length; }); const computedMultiplier = computed(() => Math.pow(10, computedPrecision.value || 0)); const valueAsFixed = computed(() => modelValue.value === null ? "" : modelValue.value.toFixed(computedPrecision.value)); const { isRtl, locale: globalLocale } = useRtl(); const computedLocale = computed(() => { const locales = [(props.locale ?? globalLocale?.value) || "locale"]; return new Intl.NumberFormat(locales).resolvedOptions().locale; }); const defaultFormatter = () => new Intl.NumberFormat(computedLocale.value, { style: "decimal", useGrouping: false, minimumIntegerDigits: 1, minimumFractionDigits: computedPrecision.value, maximumFractionDigits: computedPrecision.value, notation: "standard" }).format; const computedFormatter = computed(() => props.formatterFn ?? defaultFormatter()); const stepValue = (direction) => { let { value } = modelValue; if (!props.disabled && value !== null) { const step = computedStep.value * direction; const min = computedMin.value; const max = computedMax.value; const multiplier = computedMultiplier.value; const { wrap } = props; value = Math.round((value - min) / step) * step + min + step; value = Math.round(value * multiplier) / multiplier; modelValue.value = value > max ? wrap ? min : max : value < min ? wrap ? max : min : value; } }; const stepUp = (multiplier = 1) => { if (modelValue.value === null) { modelValue.value = computedMin.value; return; } stepValue(1 * multiplier); }; const stepDown = (multiplier = 1) => { if (modelValue.value === null) { modelValue.value = props.wrap ? computedMax.value : computedMin.value; return; } stepValue(-1 * multiplier); }; const stopEvent = (event) => { event.preventDefault(); event.stopImmediatePropagation(); }; onKeyStroke(KEY_CODES, (event) => { const { code, altKey, ctrlKey, metaKey } = event; if (props.disabled || props.readonly || altKey || ctrlKey || metaKey) return; stopEvent(event); if ($_keyIsDown) return; resetTimers(); if (["ArrowUp", "ArrowDown"].includes(code)) { $_keyIsDown = true; if (code === "ArrowUp") { handleStepRepeat(event, stepUp); return; } if (code === "ArrowDown") handleStepRepeat(event, stepDown); return; } if (code === "PageUp") { stepUp(computedStepMultiplier.value); return; } if (code === "PageDown") { stepDown(computedStepMultiplier.value); return; } if (code === "Home") { modelValue.value = computedMin.value; return; } if (code === "End") modelValue.value = computedMax.value; }, { target: element, eventName: "keydown" }); onKeyStroke(KEY_CODES, (event) => { const { altKey, ctrlKey, metaKey } = event; if (props.disabled || props.readonly || altKey || ctrlKey || metaKey) return; stopEvent(event); resetTimers(); $_keyIsDown = false; emit("change", modelValue.value); }, { target: element, eventName: "keyup" }); const handleStepRepeat = (event, stepper) => { const { type } = event || {}; if (!props.disabled && !props.readonly) { if (isMouseEvent(event)) { if (type === "mousedown" && event.button) return; } resetTimers(); stepper(1); const threshold = computedThreshold.value; const multiplier = computedStepMultiplier.value; const delay = computedDelay.value; const interval = computedInterval.value; $_autoDelayTimer = setTimeout(() => { let count = 0; $_autoRepeatTimer = setInterval(() => { stepper(count < threshold ? 1 : multiplier); count++; }, interval); }, delay); } }; const isMouseEvent = (evt) => evt.type === "mouseup" || evt.type === "mousedown"; const onMouseup = (event) => { if (isMouseEvent(event)) { if (event.type === "mouseup" && event.button) return; } stopEvent(event); resetTimers(); setMouseup("removeEventListener"); emit("change", modelValue.value); }; const setMouseup = (operation) => { const doc = getSafeDocument(); if (doc === null) return; if (operation === "addEventListener") { doc.body.addEventListener("mouseup", onMouseup); doc.body.addEventListener("touchend", onMouseup, { passive: false }); } else { doc.body.removeEventListener("mouseup", onMouseup); doc.body.removeEventListener("touchend", onMouseup); } }; const resetTimers = () => { clearTimeout($_autoDelayTimer); clearInterval($_autoRepeatTimer); $_autoDelayTimer = void 0; $_autoRepeatTimer = void 0; }; const buttons = computed(() => { const incrementSvgAttrs = { svg: { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "currentColor", class: "bi bi-plus", viewBox: "0 0 16 16" }, path: { d: "M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z" } }; const decrementSvgAttrs = { svg: { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", fill: "currentColor", class: "bi bi-dash", viewBox: "0 0 16 16" }, path: { d: "M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z" } }; const sharedButtonAttrs = { "class": [ { "py-0": !props.vertical }, "btn", "btn-sm", "border-0", "rounded-0" ], "tabindex": "-1", "type": "button", "disabled": props.disabled || props.readonly, "aria-disabled": props.disabled || props.readonly ? true : void 0, "aria-controls": computedId.value }; const sharedSvgAttrs = { "aria-hidden": true, "scale": focused.value ? 1.5 : 1.25 }; const handler = (event, stepper) => { if (!props.disabled && !props.readonly) { stopEvent(event); setMouseup("addEventListener"); focused.value = true; handleStepRepeat(event, stepper); } }; const incrementAttrs = { button: { ...sharedButtonAttrs, "aria-label": props.labelIncrement || void 0, "aria-keyshortcuts": "ArrowUp" }, svg: { ...sharedSvgAttrs, ...incrementSvgAttrs.svg }, path: { ...incrementSvgAttrs.path }, slot: { name: "increment" }, handler: (e) => handler(e, stepUp) }; const decrementAttrs = { button: { ...sharedButtonAttrs, "aria-label": props.labelDecrement || void 0, "aria-keyshortcuts": "ArrowDown" }, svg: { ...sharedSvgAttrs, ...decrementSvgAttrs.svg }, path: { ...decrementSvgAttrs.path }, slot: { name: "decrement" }, handler: (e) => handler(e, stepDown) }; return { top: { ...props.vertical ? incrementAttrs : decrementAttrs }, bottom: { ...!props.vertical ? incrementAttrs : decrementAttrs } }; }); onUnmounted(() => { setMouseup("removeEventListener"); }); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { ref: "_element", class: normalizeClass(["b-form-spinbutton form-control", computedClasses.value]), role: "group", lang: computedLocale.value, tabindex: unref(props).disabled ? void 0 : "-1", title: unref(props).ariaLabel, onClick: _cache[4] || (_cache[4] = ($event) => focused.value = true) }, [ renderSlot(_ctx.$slots, buttons.value.top.slot.name, { hasFocus: unref(focused) }, () => [createElementVNode("button", mergeProps(buttons.value.top.button, { onMousedown: _cache[0] || (_cache[0] = (...args) => buttons.value.top.handler && buttons.value.top.handler(...args)), onTouchstart: _cache[1] || (_cache[1] = (...args) => buttons.value.top.handler && buttons.value.top.handler(...args)) }), [(openBlock(), createElementBlock("svg", normalizeProps(guardReactiveProps(buttons.value.top.svg)), [createElementVNode("path", normalizeProps(guardReactiveProps(buttons.value.top.path)), null, 16)], 16))], 16)]), unref(props).name && !unref(props).disabled ? (openBlock(), createElementBlock("input", { key: "hidden", type: "hidden", name: unref(props).name, form: unref(props).form, value: valueAsFixed.value }, null, 8, _hoisted_2)) : createCommentVNode("", true), createElementVNode("output", { id: unref(computedId), key: "output", class: normalizeClass(["flex-grow-1", computedSpinClasses.value]), dir: unref(isRtl) ?? false ? "rtl" : "ltr", tabindex: unref(props).disabled ? void 0 : "0", role: "spinbutton", "aria-live": "off", "aria-label": unref(props).ariaLabel || void 0, "aria-invalid": unref(props).state === false || !modelValue.value !== null && unref(props).required ? true : void 0, "aria-required": unref(props).required ? true : void 0, "aria-valuemin": computedMin.value, "aria-valuemax": computedMax.value, "aria-valuenow": modelValue.value !== null ? modelValue.value : void 0, "aria-valuetext": modelValue.value !== null ? computedFormatter.value(modelValue.value) : void 0 }, [createElementVNode("bdi", null, toDisplayString((modelValue.value !== null ? computedFormatter.value(modelValue.value) : unref(props).placeholder) || ""), 1)], 10, _hoisted_3), renderSlot(_ctx.$slots, buttons.value.bottom.slot.name, { hasFocus: unref(focused) }, () => [createElementVNode("button", mergeProps(buttons.value.bottom.button, { onMousedown: _cache[2] || (_cache[2] = (...args) => buttons.value.bottom.handler && buttons.value.bottom.handler(...args)), onTouchstart: _cache[3] || (_cache[3] = (...args) => buttons.value.bottom.handler && buttons.value.bottom.handler(...args)) }), [(openBlock(), createElementBlock("svg", normalizeProps(guardReactiveProps(buttons.value.bottom.svg)), [createElementVNode("path", normalizeProps(guardReactiveProps(buttons.value.bottom.path)), null, 16)], 16))], 16)]) ], 10, _hoisted_1); }; } }); //#endregion export { BFormSpinbutton_default as t }; //# sourceMappingURL=BFormSpinbutton-BLO0Yf36.mjs.map