import { defineComponent, useSlots, computed, createBlock, openBlock, resolveDynamicComponent, unref, normalizeClass, withCtx, createElementVNode, createCommentVNode, renderSlot, createTextVNode, toDisplayString, mergeModels, useModel, useTemplateRef, ref, createElementBlock, Fragment, renderList, mergeProps } from "vue";
import { c as useFocus, o as onKeyStroke } from "./index-nMtnPEP0.mjs";
import { u as useDefaults } from "./useDefaults-DvqfKEoD.mjs";
import { e as escapeRegExpChars } from "./stringUtils-BRGdLBKx.mjs";
import { u as useId } from "./useId-9_HUwM96.mjs";
import { _ as _sfc_main$2 } from "./BCloseButton.vue_vue_type_script_setup_true_lang-CezXiDAc.mjs";
import { u as useColorVariantClasses } from "./useColorVariantClasses-ZDE19TZw.mjs";
import { u as useStateClass } from "./useStateClass-BGbSLWFN.mjs";
import { s as syncRef, u as useToNumber } from "./index-DX8Yoi0C.mjs";
const _hoisted_1$1 = ["id"];
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
  __name: "BFormTag",
  props: {
    disabled: { type: Boolean, default: false },
    id: { default: void 0 },
    noRemove: { type: Boolean, default: false },
    pill: { type: Boolean, default: false },
    removeLabel: { default: "Remove tag" },
    tag: { default: "span" },
    title: { default: void 0 },
    variant: { default: "secondary" }
  },
  emits: ["remove"],
  setup(__props, { emit: __emit }) {
    const _props = __props;
    const props = useDefaults(_props, "BFormTag");
    const emit = __emit;
    const slots = useSlots();
    const computedId = useId(() => props.id);
    const tagText = computed(
      () => ((slots.default?.({})[0].children ?? "").toString() || props.title) ?? ""
    );
    const taglabelId = computed(() => `${computedId.value}taglabel__`);
    const colorClasses = useColorVariantClasses(props);
    const computedClasses = computed(() => [
      colorClasses.value,
      {
        "rounded-pill": props.pill,
        "disabled": props.disabled
      }
    ]);
    return (_ctx, _cache) => {
      return openBlock(), createBlock(resolveDynamicComponent(unref(props).tag), {
        id: unref(computedId),
        title: tagText.value,
        class: normalizeClass(["badge b-form-tag d-inline-flex align-items-center mw-100", computedClasses.value]),
        "aria-labelledby": taglabelId.value
      }, {
        default: withCtx(() => [
          createElementVNode("span", {
            id: taglabelId.value,
            class: "b-form-tag-content flex-grow-1 text-truncate"
          }, [
            renderSlot(_ctx.$slots, "default", {}, () => [
              createTextVNode(toDisplayString(tagText.value), 1)
            ])
          ], 8, _hoisted_1$1),
          !unref(props).disabled && !unref(props).noRemove ? (openBlock(), createBlock(_sfc_main$2, {
            key: 0,
            "aria-keyshortcuts": "Delete",
            "aria-label": unref(props).removeLabel,
            class: "b-form-tag-remove",
            "aria-describedby": taglabelId.value,
            "aria-controls": unref(props).id,
            onClick: _cache[0] || (_cache[0] = ($event) => emit("remove", tagText.value))
          }, null, 8, ["aria-label", "aria-describedby", "aria-controls"])) : createCommentVNode("", true)
        ]),
        _: 3
      }, 8, ["id", "title", "class", "aria-labelledby"]);
    };
  }
});
const _hoisted_1 = ["id"];
const _hoisted_2 = ["id", "for", "aria-live"];
const _hoisted_3 = ["id", "aria-live"];
const _hoisted_4 = ["id"];
const _hoisted_5 = ["aria-controls"];
const _hoisted_6 = {
  role: "group",
  class: "d-flex"
};
const _hoisted_7 = ["id", "disabled", "value", "type", "placeholder", "form", "required", "aria-required"];
const _hoisted_8 = ["disabled"];
const _hoisted_9 = ["aria-live"];
const _hoisted_10 = {
  key: 0,
  class: "d-block invalid-feedback"
};
const _hoisted_11 = {
  key: 1,
  class: "form-text text-body-secondary"
};
const _hoisted_12 = {
  key: 2,
  class: "form-text text-body-secondary"
};
const _hoisted_13 = ["name", "value"];
const _sfc_main = /* @__PURE__ */ defineComponent({
  __name: "BFormTags",
  props: /* @__PURE__ */ mergeModels({
    addButtonText: { default: "Add" },
    addButtonVariant: { default: "outline-secondary" },
    addOnChange: { type: Boolean, default: false },
    autofocus: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
    duplicateTagText: { default: "Duplicate tag(s)" },
    feedbackAriaLive: { default: "assertive" },
    form: { default: void 0 },
    ignoreInputFocusSelector: { default: () => [".b-form-tag", "button", "input", "select"] },
    inputAttrs: { default: void 0 },
    inputClass: { default: void 0 },
    inputId: { default: void 0 },
    inputType: { default: "text" },
    invalidTagText: { default: "Invalid tag(s)" },
    limit: { default: void 0 },
    limitTagsText: { default: "Tag limit reached" },
    name: { default: void 0 },
    noAddOnEnter: { type: Boolean, default: false },
    noOuterFocus: { type: Boolean, default: false },
    noTagRemove: { type: Boolean, default: false },
    placeholder: { default: "Add tag..." },
    removeOnDelete: { type: Boolean, default: false },
    required: { type: Boolean, default: false },
    separator: { default: void 0 },
    size: { default: "md" },
    state: { type: [Boolean, null], default: null },
    tagClass: { default: void 0 },
    tagPills: { type: Boolean, default: false },
    tagRemoveLabel: { default: void 0 },
    tagRemovedLabel: { default: "Tag removed" },
    tagValidator: { type: Function, default: () => true },
    tagVariant: { default: "secondary" }
  }, {
    "modelValue": {
      default: () => []
    },
    "modelModifiers": {}
  }),
  emits: /* @__PURE__ */ mergeModels(["blur", "focus", "focusin", "focusout", "tag-state"], ["update:modelValue"]),
  setup(__props, { expose: __expose, emit: __emit }) {
    const _props = __props;
    const props = useDefaults(_props, "BFormTags");
    const emit = __emit;
    const modelValue = useModel(__props, "modelValue");
    const computedId = useId();
    const limitNumber = useToNumber(() => props.limit ?? Number.NaN);
    const stateClass = useStateClass(() => props.state);
    const input = useTemplateRef("_input");
    const { focused } = useFocus(input, {
      initialValue: props.autofocus
    });
    const _inputId = computed(() => props.inputId || `${computedId.value}input__`);
    const tags = ref([...modelValue.value]);
    const inputValue = ref("");
    const shouldRemoveOnDelete = ref(modelValue.value.length > 0);
    const lastRemovedTag = ref("");
    const validTags = ref([]);
    const invalidTags = ref([]);
    const duplicateTags = ref([]);
    syncRef(modelValue, tags, {
      direction: "ltr",
      transform: {
        ltr: (v) => [...v]
      }
    });
    const computedClasses = computed(() => [
      stateClass.value,
      {
        [`form-control-${props.size}`]: props.size !== "md",
        disabled: props.disabled,
        focus: focused.value
      }
    ]);
    const isDuplicate = computed(() => tags.value.includes(inputValue.value));
    const isInvalid = computed(
      () => inputValue.value === "" ? false : !props.tagValidator(inputValue.value)
    );
    const isLimitReached = computed(() => tags.value.length === limitNumber.value);
    const disableAddButton = computed(() => !isInvalid.value && !isDuplicate.value);
    const onFocusin = (e) => {
      if (props.disabled) {
        const target = e.target;
        target.blur();
        return;
      }
      emit("focusin", e);
    };
    const onClick = (e) => {
      if (props.disabled || props.noOuterFocus) {
        return;
      }
      const { target } = e;
      const ignoreSelectors = props.ignoreInputFocusSelector;
      if (ignoreSelectors && target instanceof Element) {
        const selector = typeof ignoreSelectors === "string" ? ignoreSelectors : ignoreSelectors.join(",");
        if (selector && target.closest(selector)) {
          return;
        }
      }
      focused.value = true;
    };
    const onFocus = (e) => {
      if (props.disabled || props.noOuterFocus) {
        return;
      }
      focused.value = true;
      emit("focus", e);
    };
    const onBlur = (e) => {
      focused.value = false;
      emit("blur", e);
    };
    const onInput = (e) => {
      const value = typeof e === "string" ? e : e.target.value;
      shouldRemoveOnDelete.value = false;
      if (props.separator?.includes(value.charAt(0)) && value.length > 0) {
        if (input.value) {
          input.value.value = "";
        }
        return;
      }
      inputValue.value = value;
      if (props.separator?.includes(value.charAt(value.length - 1))) {
        addTag(value.slice(0, value.length - 1));
        return;
      }
      validTags.value = props.tagValidator(value) && !isDuplicate.value ? [value] : [];
      invalidTags.value = props.tagValidator(value) ? [] : [value];
      duplicateTags.value = isDuplicate.value ? [value] : [];
      emit("tag-state", validTags.value, invalidTags.value, duplicateTags.value);
    };
    const onChange = (e) => {
      if (props.addOnChange) {
        onInput(e);
        if (!isDuplicate.value) {
          addTag(inputValue.value);
        }
      }
    };
    const onKeydown = (e) => {
      if ((e.key === "Enter" || e.code === "NumpadEnter") && !props.noAddOnEnter) {
        addTag(inputValue.value);
        return;
      }
      if ((e.key === "Backspace" || e.key === "Delete") && props.removeOnDelete && inputValue.value === "" && shouldRemoveOnDelete.value && tags.value.length > 0) {
        removeTag(tags.value[tags.value.length - 1]);
      } else {
        shouldRemoveOnDelete.value = true;
      }
    };
    onKeyStroke(onKeydown, { target: input });
    const separator = computed(() => {
      if (!props.separator) {
        return;
      }
      return typeof props.separator === "string" ? props.separator : props.separator.join("");
    });
    const separatorRegExp = computed(() => {
      if (!separator.value) {
        return;
      }
      return new RegExp(`[${escapeRegExpChars(separator.value)}]+`);
    });
    const addTag = (tag) => {
      tag = (tag ?? inputValue.value).trim();
      const newTags = separatorRegExp.value ? tag.split(separatorRegExp.value).map((t) => t.trim()) : [tag];
      const validTags2 = [];
      for (const newTag of newTags) {
        if (newTag === "" || isDuplicate.value || !props.tagValidator(newTag)) {
          continue;
        }
        if (limitNumber.value && isLimitReached.value) {
          break;
        }
        validTags2.push(newTag);
      }
      const newValue = [...modelValue.value, ...validTags2];
      inputValue.value = "";
      shouldRemoveOnDelete.value = true;
      modelValue.value = newValue;
      focused.value = true;
    };
    const removeTag = (tag) => {
      const tagIndex = tags.value.indexOf(tag?.toString() ?? "");
      if (tagIndex === -1) return;
      lastRemovedTag.value = tags.value.splice(tagIndex, 1).toString();
      modelValue.value = tags.value;
    };
    __expose({
      blur: () => {
        focused.value = false;
      },
      element: input,
      focus: () => {
        focused.value = true;
      },
      inputValue
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock("div", {
        id: unref(computedId),
        class: normalizeClass(["b-form-tags form-control h-auto", computedClasses.value]),
        role: "group",
        tabindex: "-1",
        onClick,
        onFocusin,
        onFocusout: _cache[1] || (_cache[1] = ($event) => emit("focusout", $event))
      }, [
        createElementVNode("output", {
          id: `${unref(computedId)}selected_tags__`,
          class: "visually-hidden",
          for: _inputId.value,
          "aria-live": unref(focused) ? "polite" : "off",
          "aria-atomic": "true",
          "aria-relevant": "additions text"
        }, toDisplayString(tags.value.join(", ")), 9, _hoisted_2),
        createElementVNode("div", {
          id: `${unref(computedId)}removed_tags__`,
          role: "status",
          "aria-live": unref(focused) ? "assertive" : "off",
          "aria-atomic": "true",
          class: "visually-hidden"
        }, " (" + toDisplayString(unref(props).tagRemovedLabel) + ") " + toDisplayString(lastRemovedTag.value), 9, _hoisted_3),
        renderSlot(_ctx.$slots, "default", {
          addButtonText: unref(props).addButtonText,
          addButtonVariant: unref(props).addButtonVariant,
          addTag,
          disableAddButton: disableAddButton.value,
          disabled: unref(props).disabled,
          duplicateTagText: unref(props).duplicateTagText,
          duplicateTags: duplicateTags.value,
          form: unref(props).form,
          inputAttrs: {
            ...unref(props).inputAttrs,
            disabled: unref(props).disabled,
            form: unref(props).form,
            id: _inputId.value,
            value: inputValue.value
          },
          inputClass: unref(props).inputClass,
          inputHandlers: {
            input: onInput,
            keydown: onKeydown,
            change: onChange
          },
          inputId: _inputId.value,
          inputType: unref(props).inputType,
          invalidTagText: unref(props).invalidTagText,
          invalidTags: invalidTags.value,
          isDuplicate: isDuplicate.value,
          isInvalid: isInvalid.value,
          isLimitReached: isLimitReached.value,
          limitTagsText: unref(props).limitTagsText,
          limit: unref(limitNumber),
          noTagRemove: unref(props).noTagRemove,
          placeholder: unref(props).placeholder,
          removeTag,
          required: unref(props).required,
          separator: unref(props).separator,
          size: unref(props).size,
          state: unref(props).state,
          tagClass: unref(props).tagClass,
          tagPills: unref(props).tagPills,
          tagRemoveLabel: unref(props).tagRemoveLabel,
          tagVariant: unref(props).tagVariant,
          tags: tags.value
        }, () => [
          createElementVNode("ul", {
            id: `${unref(computedId)}tag_list__`,
            class: "b-form-tags-list list-unstyled mb-0 d-flex flex-wrap align-items-center"
          }, [
            (openBlock(true), createElementBlock(Fragment, null, renderList(tags.value, (tag, index) => {
              return renderSlot(_ctx.$slots, "tag", {
                key: index,
                tag,
                tagClass: unref(props).tagClass,
                tagVariant: unref(props).tagVariant,
                tagPills: unref(props).tagPills,
                removeTag
              }, () => [
                (openBlock(), createBlock(_sfc_main$1, {
                  key: tag,
                  class: normalizeClass(unref(props).tagClass),
                  tag: "li",
                  variant: unref(props).tagVariant,
                  pill: unref(props).tagPills,
                  "no-remove": unref(props).noTagRemove,
                  disabled: unref(props).disabled,
                  onRemove: removeTag
                }, {
                  default: withCtx(() => [
                    createTextVNode(toDisplayString(tag), 1)
                  ]),
                  _: 2
                }, 1032, ["class", "variant", "pill", "no-remove", "disabled"]))
              ]);
            }), 128)),
            createElementVNode("li", {
              role: "none",
              "aria-live": "off",
              class: "b-from-tags-field flex-grow-1",
              "aria-controls": `${unref(computedId)}tag_list__`
            }, [
              createElementVNode("div", _hoisted_6, [
                createElementVNode("input", mergeProps({
                  id: _inputId.value,
                  ref: "_input",
                  disabled: unref(props).disabled,
                  value: inputValue.value,
                  type: unref(props).inputType,
                  placeholder: unref(props).placeholder,
                  class: "b-form-tags-input w-100 flex-grow-1 p-0 m-0 bg-transparent border-0",
                  style: { "outline": "currentcolor none 0px", "min-width": "5rem" }
                }, unref(props).inputAttrs, {
                  form: unref(props).form,
                  required: unref(props).required || void 0,
                  "aria-required": unref(props).required || void 0,
                  onInput,
                  onChange,
                  onFocus,
                  onBlur
                }), null, 16, _hoisted_7),
                disableAddButton.value ? (openBlock(), createElementBlock("button", {
                  key: 0,
                  type: "button",
                  class: normalizeClass(["btn b-form-tags-button py-0", [
                    __props.inputClass,
                    {
                      [`btn-${unref(props).addButtonVariant}`]: unref(props).addButtonVariant !== null,
                      "disabled invisible": inputValue.value.length === 0
                    }
                  ]]),
                  style: { "font-size": "90%" },
                  disabled: unref(props).disabled || inputValue.value.length === 0 || isLimitReached.value,
                  onClick: _cache[0] || (_cache[0] = ($event) => addTag(inputValue.value))
                }, [
                  renderSlot(_ctx.$slots, "add-button-text", {}, () => [
                    createTextVNode(toDisplayString(unref(props).addButtonText), 1)
                  ])
                ], 10, _hoisted_8)) : createCommentVNode("", true)
              ])
            ], 8, _hoisted_5)
          ], 8, _hoisted_4),
          createElementVNode("div", {
            "aria-live": unref(props).feedbackAriaLive,
            "aria-atomic": "true"
          }, [
            isInvalid.value ? (openBlock(), createElementBlock("div", _hoisted_10, toDisplayString(unref(props).invalidTagText) + ": " + toDisplayString(inputValue.value), 1)) : createCommentVNode("", true),
            isDuplicate.value ? (openBlock(), createElementBlock("small", _hoisted_11, toDisplayString(unref(props).duplicateTagText) + ": " + toDisplayString(inputValue.value), 1)) : createCommentVNode("", true),
            tags.value.length === unref(props).limit ? (openBlock(), createElementBlock("small", _hoisted_12, toDisplayString(unref(props).limitTagsText), 1)) : createCommentVNode("", true)
          ], 8, _hoisted_9)
        ]),
        unref(props).name ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(tags.value, (tag, index) => {
          return openBlock(), createElementBlock("input", {
            key: index,
            type: "hidden",
            name: unref(props).name,
            value: tag
          }, null, 8, _hoisted_13);
        }), 128)) : createCommentVNode("", true)
      ], 42, _hoisted_1);
    };
  }
});
export {
  _sfc_main as _,
  _sfc_main$1 as a
};
//# sourceMappingURL=BFormTags.vue_vue_type_script_setup_true_lang-BlilXZ_0.mjs.map
