// src/vue/components/GnAccordion.js
import { defineComponent, h as h2, ref } from "vue";

// src/vue/utils.js
import { h } from "vue";
var variants = /* @__PURE__ */ new Set([
  "primary",
  "secondary",
  "accent",
  "success",
  "warning",
  "danger",
  "error",
  "info"
]);
function cx(...items) {
  return items.flatMap((item) => {
    if (!item) {
      return [];
    }
    if (Array.isArray(item)) {
      return item;
    }
    if (typeof item === "object") {
      return Object.entries(item).filter(([, enabled]) => enabled).map(([name]) => name);
    }
    return [item];
  }).filter(Boolean).join(" ");
}
function normalizeVariant(value, fallback = "primary") {
  return variants.has(value) ? value : fallback;
}
function iconNode(icon, extraClass = "") {
  if (!icon) {
    return null;
  }
  const hasPrefix = icon.includes("ph ") || icon.startsWith("ph-");
  if (!hasPrefix) {
    if (typeof process !== "undefined" && process.env && true) {
      console.warn(`[gnexus-ui-kit] Icon "${icon}" is missing the required "ph-" prefix. Use "ph-${icon}" instead.`);
    }
  }
  const iconClass = hasPrefix ? icon : `ph-${icon}`;
  return h("i", {
    class: cx("ph", iconClass, extraClass),
    "aria-hidden": "true"
  });
}
function eventValue(event) {
  const target = event.target;
  if (target.type === "checkbox") {
    return target.checked;
  }
  return target.value;
}
var focusableSelector = [
  "a[href]",
  "button:not([disabled])",
  "input:not([disabled])",
  "select:not([disabled])",
  "textarea:not([disabled])",
  "[tabindex]:not([tabindex='-1'])"
].join(",");
function trapFocus(event, root) {
  if (event.key !== "Tab" || !root) {
    return;
  }
  const focusable = [...root.querySelectorAll(focusableSelector)].filter((node) => !node.hasAttribute("disabled") && node.offsetParent !== null);
  if (!focusable.length) {
    event.preventDefault();
    root.focus();
    return;
  }
  const first = focusable[0];
  const last = focusable[focusable.length - 1];
  if (event.shiftKey && document.activeElement === first) {
    event.preventDefault();
    last.focus();
  } else if (!event.shiftKey && document.activeElement === last) {
    event.preventDefault();
    first.focus();
  }
}

// src/vue/components/GnAccordion.js
var GnAccordion_default = defineComponent({
  name: "GnAccordion",
  props: {
    items: { type: Array, required: true },
    modelValue: { type: [String, Array], default: "" },
    multiple: { type: Boolean, default: false }
  },
  emits: ["update:modelValue"],
  setup(props, { emit, slots }) {
    const localOpen = ref(props.multiple ? [] : "");
    const getOpen = () => props.modelValue || localOpen.value;
    const isOpen = (id) => props.multiple ? getOpen().includes(id) : getOpen() === id;
    const toggle = (id) => {
      let next;
      if (props.multiple) {
        const current = [...getOpen()];
        next = current.includes(id) ? current.filter((item) => item !== id) : [...current, id];
      } else {
        next = isOpen(id) ? "" : id;
      }
      localOpen.value = next;
      emit("update:modelValue", next);
    };
    return () => h2("div", { class: "accordion" }, props.items.map((item) => {
      var _a;
      const open = isOpen(item.id);
      return h2("section", { class: "accordion-item", open: open ? "" : void 0 }, [
        h2("button", {
          class: "accordion-summary",
          type: "button",
          "aria-expanded": open ? "true" : "false",
          onClick: () => toggle(item.id)
        }, [
          h2("span", { class: "accordion-summary-content" }, [
            iconNode(item.icon),
            item.label
          ]),
          h2("i", { class: cx("ph ph-caret-down accordion-icon", { "is-open": open }), "aria-hidden": "true" })
        ]),
        open && h2("div", { class: "accordion-panel" }, ((_a = slots[item.id]) == null ? void 0 : _a.call(slots, { item, open })) || item.content)
      ]);
    }));
  }
});

// src/vue/components/GnActionCard.js
import { defineComponent as defineComponent2, h as h3 } from "vue";
var GnActionCard_default = defineComponent2({
  name: "GnActionCard",
  props: {
    kicker: { type: String, default: "" },
    title: { type: String, required: true },
    text: { type: String, default: "" }
  },
  setup(props, { slots }) {
    return () => {
      var _a, _b, _c;
      return h3("article", { class: "card action-card" }, [
        h3("div", { class: "card-content" }, [
          (props.kicker || slots.kicker) && h3("span", { class: "action-card-kicker" }, ((_a = slots.kicker) == null ? void 0 : _a.call(slots)) || props.kicker),
          h3("h3", { class: "action-card-title" }, ((_b = slots.title) == null ? void 0 : _b.call(slots)) || props.title),
          (props.text || slots.default) && h3("p", { class: "action-card-text" }, ((_c = slots.default) == null ? void 0 : _c.call(slots)) || props.text),
          slots.actions && h3("div", { class: "action-card-actions" }, slots.actions())
        ])
      ]);
    };
  }
});

// src/vue/components/GnActionList.js
import { defineComponent as defineComponent3, h as h4 } from "vue";
var GnActionList_default = defineComponent3({
  name: "GnActionList",
  props: {
    items: { type: Array, default: () => [] }
  },
  setup(props, { attrs, slots }) {
    return () => h4("ul", { ...attrs, class: cx("list list-actions", attrs.class) }, props.items.map((item) => {
      var _a, _b;
      return h4("li", {
        class: cx("list-item", item.muted && "list-item-muted")
      }, [
        h4("div", { class: "list-content" }, [
          h4("div", { class: "list-title" }, ((_a = slots.title) == null ? void 0 : _a.call(slots, { item })) || item.title),
          (item.subtitle || slots.subtitle) && h4("div", { class: "list-subtitle" }, ((_b = slots.subtitle) == null ? void 0 : _b.call(slots, { item })) || item.subtitle)
        ]),
        slots.controls && h4("div", { class: "list-controls" }, slots.controls({ item }))
      ]);
    }));
  }
});

// src/vue/components/GnActivityLog.js
import { defineComponent as defineComponent4, h as h5 } from "vue";
var GnActivityLog_default = defineComponent4({
  name: "GnActivityLog",
  props: {
    items: { type: Array, default: () => [] }
  },
  setup(props, { attrs, slots }) {
    return () => h5("div", { ...attrs, class: cx("activity-log", attrs.class) }, props.items.map((item) => {
      var _a;
      return h5("div", {
        class: "activity-log-row"
      }, [
        h5("time", { class: "activity-log-time" }, item.time),
        h5("span", { class: "activity-log-title" }, ((_a = slots[item.key]) == null ? void 0 : _a.call(slots, { item })) || item.title),
        slots.actions && h5("span", {}, slots.actions({ item }))
      ]);
    }));
  }
});

// src/vue/components/GnAlert.js
import { defineComponent as defineComponent5, h as h6 } from "vue";
var GnAlert_default = defineComponent5({
  name: "GnAlert",
  props: {
    variant: { type: String, default: "primary" },
    role: { type: String, default: "status" }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a;
      const variant = normalizeVariant(props.variant);
      return h6("div", {
        ...attrs,
        role: props.role,
        class: cx("alert", `alert-${variant}`, attrs.class)
      }, (_a = slots.default) == null ? void 0 : _a.call(slots));
    };
  }
});

// src/vue/components/GnAvatar.js
import { defineComponent as defineComponent6, h as h7 } from "vue";
var GnAvatar_default = defineComponent6({
  name: "GnAvatar",
  props: {
    src: { type: String, default: "" },
    alt: { type: String, default: "" },
    initials: { type: String, default: "" },
    icon: { type: String, default: "" },
    size: { type: String, default: "md" },
    variant: { type: String, default: "primary" },
    outline: { type: Boolean, default: false },
    status: { type: String, default: "" }
  },
  setup(props, { attrs }) {
    return () => {
      const variant = normalizeVariant(props.variant);
      return h7("span", {
        ...attrs,
        class: cx("avatar", `avatar-${variant}`, {
          "avatar-sm": props.size === "sm",
          "avatar-lg": props.size === "lg",
          "avatar-outline": props.outline,
          "is-online": props.status === "online",
          "is-busy": props.status === "busy",
          "is-offline": props.status === "offline"
        }, attrs.class)
      }, [
        props.src ? h7("img", { src: props.src, alt: props.alt }) : iconNode(props.icon) || props.initials,
        props.status && h7("span", { class: "avatar-status", "aria-hidden": "true" })
      ]);
    };
  }
});

// src/vue/components/GnAvatarStack.js
import { defineComponent as defineComponent7, h as h8 } from "vue";
var GnAvatarStack_default = defineComponent7({
  name: "GnAvatarStack",
  props: {
    items: { type: Array, default: () => [] },
    count: { type: [Number, String], default: "" }
  },
  setup(props, { slots }) {
    return () => {
      var _a;
      return h8("span", { class: "avatar-stack" }, [
        props.items.map((item) => h8(GnAvatar_default, { ...item, size: item.size || "sm" })),
        (_a = slots.default) == null ? void 0 : _a.call(slots),
        props.count && h8("span", { class: "avatar-stack-count" }, `+${props.count}`)
      ]);
    };
  }
});

// src/vue/components/GnBadge.js
import { defineComponent as defineComponent8, h as h9 } from "vue";
var GnBadge_default = defineComponent8({
  name: "GnBadge",
  props: {
    variant: { type: String, default: "primary" },
    outline: { type: Boolean, default: false }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a;
      const variant = normalizeVariant(props.variant);
      return h9("span", {
        ...attrs,
        class: cx(
          "badge",
          props.outline && variant === "primary" ? "badge-primary-outline" : `badge-${variant}`,
          attrs.class
        )
      }, (_a = slots.default) == null ? void 0 : _a.call(slots));
    };
  }
});

// src/vue/components/GnButton.js
import { defineComponent as defineComponent9, h as h10 } from "vue";
var GnButton_default = defineComponent9({
  name: "GnButton",
  props: {
    variant: { type: String, default: "primary" },
    size: { type: String, default: "md" },
    icon: { type: String, default: "" },
    loading: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
    type: { type: String, default: "button" }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a;
      const hasIcon = Boolean(props.icon || props.loading);
      const variant = normalizeVariant(props.variant);
      return h10("button", {
        ...attrs,
        type: props.type,
        disabled: props.disabled || props.loading,
        class: cx(
          "btn",
          `btn-${variant}`,
          {
            "btn-small": props.size === "sm",
            "btn-large": props.size === "lg",
            "with-icon": hasIcon,
            "loading-state": props.loading
          },
          attrs.class
        )
      }, [
        props.loading ? iconNode("ph-bold ph-spinner") : iconNode(props.icon),
        (_a = slots.default) == null ? void 0 : _a.call(slots)
      ]);
    };
  }
});

// src/vue/components/GnCard.js
import { defineComponent as defineComponent10, h as h11 } from "vue";
var GnCard_default = defineComponent10({
  name: "GnCard",
  props: {
    title: { type: String, default: "" },
    variant: { type: String, default: "" }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a, _b;
      return h11("article", {
        ...attrs,
        class: cx("card", props.variant && `card-${props.variant}`, attrs.class)
      }, [
        (props.title || slots.title) && h11("header", { class: "card-title" }, ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title),
        h11("div", { class: "card-content" }, (_b = slots.default) == null ? void 0 : _b.call(slots)),
        slots.footer && h11("footer", { class: "card-footer" }, slots.footer())
      ]);
    };
  }
});

// src/vue/components/GnCheckbox.js
import { defineComponent as defineComponent11, h as h12 } from "vue";
var GnCheckbox_default = defineComponent11({
  name: "GnCheckbox",
  inheritAttrs: false,
  props: {
    modelValue: { type: Boolean, default: false },
    label: { type: String, default: "" },
    disabled: { type: Boolean, default: false }
  },
  emits: ["update:modelValue"],
  setup(props, { attrs, emit, slots }) {
    return () => {
      var _a;
      return h12("label", { class: cx("checkbox", attrs.class) }, [
        h12("input", {
          ...attrs,
          type: "checkbox",
          checked: props.modelValue,
          disabled: props.disabled,
          onChange: (event) => emit("update:modelValue", event.target.checked)
        }),
        h12("span", { class: "checkbox-control", "aria-hidden": "true" }),
        h12("span", { class: "checkbox-label" }, ((_a = slots.default) == null ? void 0 : _a.call(slots)) || props.label)
      ]);
    };
  }
});

// src/vue/components/GnChip.js
import { defineComponent as defineComponent12, h as h13 } from "vue";
var GnChip_default = defineComponent12({
  name: "GnChip",
  props: {
    variant: { type: String, default: "" },
    icon: { type: String, default: "" },
    selected: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false },
    removable: { type: Boolean, default: false }
  },
  emits: ["remove"],
  setup(props, { attrs, emit, slots }) {
    return () => {
      var _a;
      const tag = attrs.onClick ? "button" : "span";
      const variant = props.variant ? normalizeVariant(props.variant) : "";
      return h13(tag, {
        ...attrs,
        type: tag === "button" ? "button" : void 0,
        disabled: tag === "button" ? props.disabled : void 0,
        "aria-pressed": tag === "button" ? String(props.selected) : void 0,
        class: cx("chip", variant && `chip-${variant}`, {
          "chip-selected": props.selected,
          "chip-disabled": props.disabled
        }, attrs.class)
      }, [
        iconNode(props.icon),
        (_a = slots.default) == null ? void 0 : _a.call(slots),
        props.removable && h13("button", {
          class: "chip-remove",
          type: "button",
          "aria-label": "Remove",
          onClick: (event) => {
            event.stopPropagation();
            emit("remove");
          }
        }, [iconNode("ph-x")])
      ]);
    };
  }
});

// src/vue/components/GnChipGroup.js
import { defineComponent as defineComponent13, h as h14 } from "vue";
var GnChipGroup_default = defineComponent13({
  name: "GnChipGroup",
  setup(_, { attrs, slots }) {
    return () => {
      var _a;
      return h14("div", { ...attrs, class: cx("chip-group", attrs.class) }, (_a = slots.default) == null ? void 0 : _a.call(slots));
    };
  }
});

// src/vue/components/GnCombobox.js
import { computed, defineComponent as defineComponent14, h as h15, nextTick, ref as ref2 } from "vue";
var comboboxId = 0;
var GnCombobox_default = defineComponent14({
  name: "GnCombobox",
  inheritAttrs: false,
  props: {
    modelValue: { type: [String, Number], default: "" },
    label: { type: String, default: "" },
    icon: { type: String, default: "" },
    options: { type: Array, default: () => [] },
    placeholder: { type: String, default: "Search" },
    notFoundText: { type: String, default: "Nothing found" },
    state: { type: String, default: "" },
    help: { type: String, default: "" }
  },
  emits: ["update:modelValue", "select"],
  setup(props, { attrs, emit }) {
    const id = `gn-combobox-${++comboboxId}`;
    const listboxId = `${id}-listbox`;
    const open = ref2(false);
    const focused = ref2(-1);
    const inputRef = ref2(null);
    const normalized = computed(() => props.options.map((option) => typeof option === "object" ? option : {
      value: option,
      label: option
    }));
    const query = computed(() => {
      var _a;
      return String((_a = props.modelValue) != null ? _a : "").toLowerCase();
    });
    const filtered = computed(() => normalized.value.filter((option) => String(option.label).toLowerCase().includes(query.value)));
    const select = (option) => {
      if (!option) {
        return;
      }
      emit("update:modelValue", option.label);
      emit("select", option);
      open.value = false;
      focused.value = -1;
    };
    const move = (direction) => {
      if (!filtered.value.length) {
        return;
      }
      open.value = true;
      focused.value = (focused.value + direction + filtered.value.length) % filtered.value.length;
      nextTick(() => {
        var _a, _b, _c;
        const container = (_b = (_a = inputRef.value) == null ? void 0 : _a.closest(".form-group")) == null ? void 0 : _b.querySelector(".advanced-select");
        (_c = container == null ? void 0 : container.querySelector(".option.focus")) == null ? void 0 : _c.scrollIntoView({ block: "nearest" });
      });
    };
    const onKeydown = (event) => {
      if (event.key === "ArrowDown") {
        event.preventDefault();
        move(1);
      } else if (event.key === "ArrowUp") {
        event.preventDefault();
        move(-1);
      } else if (event.key === "Enter") {
        event.preventDefault();
        select(filtered.value[focused.value]);
      } else if (event.key === "Escape") {
        open.value = false;
        focused.value = -1;
      }
    };
    return () => h15("div", { class: "form-group" }, [
      h15("label", { class: cx("label", props.state) }, [
        props.label,
        iconNode(props.icon),
        h15("input", {
          ...attrs,
          ref: inputRef,
          id,
          type: "text",
          value: props.modelValue,
          placeholder: props.placeholder,
          autocomplete: "off",
          role: "combobox",
          "aria-autocomplete": "list",
          "aria-expanded": open.value ? "true" : "false",
          "aria-controls": listboxId,
          "aria-activedescendant": focused.value >= 0 ? `${id}-option-${focused.value}` : void 0,
          class: cx("input", attrs.class),
          onFocus: () => {
            open.value = true;
          },
          onBlur: () => {
            setTimeout(() => {
              open.value = false;
            }, 120);
          },
          onInput: (event) => {
            focused.value = -1;
            open.value = true;
            emit("update:modelValue", eventValue(event));
          },
          onKeydown
        })
      ]),
      h15("div", { class: "advanced-select-container" }, [
        h15("div", { class: cx("advanced-select", { "a-show": open.value }) }, [
          h15("div", { class: "popup-options-container" }, [
            h15("div", { class: cx("not-found", { show: !filtered.value.length }) }, props.notFoundText),
            h15("div", {
              id: listboxId,
              class: cx("options", { show: filtered.value.length }),
              role: "listbox"
            }, filtered.value.map((option, index) => h15("div", {
              id: `${id}-option-${index}`,
              class: cx("option", { focus: index === focused.value }),
              role: "option",
              "aria-selected": index === focused.value ? "true" : "false",
              "data-value": option.value,
              "data-display-value": option.label,
              onMousedown: (event) => {
                event.preventDefault();
                select(option);
              }
            }, option.label)))
          ])
        ])
      ]),
      props.help && h15("div", { class: cx("input-info", props.state === "error" && "error") }, props.help)
    ]);
  }
});

// src/vue/components/GnConfirmDialog.js
import { defineComponent as defineComponent16, h as h17 } from "vue";

// src/vue/components/GnModal.js
import { defineComponent as defineComponent15, h as h16, nextTick as nextTick2, onBeforeUnmount, ref as ref3, Teleport, watch } from "vue";
var modalId = 0;
var GnModal_default = defineComponent15({
  name: "GnModal",
  props: {
    open: { type: Boolean, default: false },
    title: { type: String, default: "" },
    closeOnBackdrop: { type: Boolean, default: true }
  },
  emits: ["update:open", "close"],
  setup(props, { emit, slots }) {
    const titleId = `gn-modal-title-${++modalId}`;
    const dialogRef = ref3(null);
    const visible = ref3(false);
    const closing = ref3(false);
    let previousFocus = null;
    let closeTimer = null;
    const close = () => {
      emit("update:open", false);
      emit("close");
    };
    const onKeydown = (event) => {
      if (event.key === "Escape") {
        event.preventDefault();
        close();
      } else {
        trapFocus(event, dialogRef.value);
      }
    };
    const focusDialog = () => {
      nextTick2(() => {
        var _a;
        (_a = dialogRef.value) == null ? void 0 : _a.focus();
      });
    };
    watch(() => props.open, (open) => {
      var _a;
      if (open) {
        closing.value = false;
        visible.value = true;
        previousFocus = document.activeElement;
        document.addEventListener("keydown", onKeydown);
        focusDialog();
      } else {
        closing.value = true;
        document.removeEventListener("keydown", onKeydown);
        (_a = previousFocus == null ? void 0 : previousFocus.focus) == null ? void 0 : _a.call(previousFocus);
        previousFocus = null;
        closeTimer = window.setTimeout(() => {
          visible.value = false;
          closing.value = false;
        }, 300);
      }
    }, { flush: "post" });
    onBeforeUnmount(() => {
      document.removeEventListener("keydown", onKeydown);
      window.clearTimeout(closeTimer);
    });
    return () => {
      var _a, _b, _c;
      return visible.value ? h16(Teleport, { to: "body" }, [
        h16("div", { class: cx("modal", closing.value ? "a-hide" : "a-show"), "aria-hidden": "false" }, [
          h16("div", {
            class: "modal-backdrop",
            onClick: () => props.closeOnBackdrop && close()
          }),
          h16("div", {
            ref: dialogRef,
            class: "modal-dialog",
            role: "dialog",
            "aria-modal": "true",
            "aria-labelledby": titleId,
            tabindex: "-1"
          }, [
            h16("header", { class: "modal-header" }, [
              h16("h4", { class: "modal-title", id: titleId }, ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title),
              h16("button", {
                class: "btn-icon modal-close",
                type: "button",
                "aria-label": "Close",
                onClick: close
              }, [iconNode("ph-x")])
            ]),
            h16("div", { class: "modal-panel" }, [
              h16("div", { class: "modal-body" }, (_b = slots.default) == null ? void 0 : _b.call(slots)),
              (slots.footer || slots.actions) && h16("footer", { class: "modal-footer" }, [
                (_c = slots.footer) == null ? void 0 : _c.call(slots),
                slots.actions && h16("div", { class: "actions" }, slots.actions({ close }))
              ])
            ])
          ])
        ])
      ]) : null;
    };
  }
});

// src/vue/components/GnConfirmDialog.js
var GnConfirmDialog_default = defineComponent16({
  name: "GnConfirmDialog",
  props: {
    open: { type: Boolean, default: false },
    title: { type: String, default: "Requires confirmation" },
    message: { type: String, default: "" },
    confirmText: { type: String, default: "YES" },
    cancelText: { type: String, default: "NO" },
    confirmVariant: { type: String, default: "warning" }
  },
  emits: ["update:open", "confirm", "cancel"],
  setup(props, { emit, slots }) {
    const close = () => emit("update:open", false);
    const cancel = () => {
      emit("cancel");
      close();
    };
    const confirm = () => {
      emit("confirm");
      close();
    };
    return () => h17(GnModal_default, {
      open: props.open,
      title: props.title,
      "onUpdate:open": (value) => emit("update:open", value)
    }, {
      default: () => {
        var _a;
        return ((_a = slots.default) == null ? void 0 : _a.call(slots)) || h17("p", {}, props.message);
      },
      actions: () => [
        h17(GnButton_default, { variant: "primary", onClick: cancel }, () => props.cancelText),
        h17(GnButton_default, { variant: props.confirmVariant, onClick: confirm }, () => props.confirmText)
      ]
    });
  }
});

// src/vue/components/GnCopyButton.js
import { defineComponent as defineComponent17, h as h18, ref as ref4 } from "vue";
var GnCopyButton_default = defineComponent17({
  name: "GnCopyButton",
  props: {
    text: { type: String, required: true },
    icon: { type: String, default: "ph-copy" },
    successIcon: { type: String, default: "ph-check" },
    duration: { type: Number, default: 3e3 },
    label: { type: String, default: "Copy" },
    size: { type: String, default: null }
  },
  emits: ["copy"],
  setup(props, { emit }) {
    const copied = ref4(false);
    let timer = null;
    const copy = async () => {
      try {
        await navigator.clipboard.writeText(props.text);
      } catch (e) {
        const textarea = document.createElement("textarea");
        textarea.value = props.text;
        textarea.style.position = "fixed";
        textarea.style.opacity = "0";
        document.body.appendChild(textarea);
        textarea.select();
        document.execCommand("copy");
        document.body.removeChild(textarea);
      }
      copied.value = true;
      window.clearTimeout(timer);
      timer = window.setTimeout(() => {
        copied.value = false;
      }, props.duration);
      emit("copy", props.text);
    };
    return () => h18("button", {
      class: cx("btn-icon", { "btn-icon-sm": props.size === "sm" }),
      type: "button",
      "aria-label": props.label,
      onClick: copy
    }, [iconNode(copied.value ? props.successIcon : props.icon)]);
  }
});

// src/vue/components/GnDescriptionList.js
import { defineComponent as defineComponent18, h as h19 } from "vue";
var GnDescriptionList_default = defineComponent18({
  name: "GnDescriptionList",
  props: {
    items: { type: Array, default: () => [] },
    compact: { type: Boolean, default: false }
  },
  setup(props, { attrs, slots }) {
    return () => h19("dl", {
      ...attrs,
      class: cx("description-list", { "description-list-compact": props.compact }, attrs.class)
    }, props.items.map((item) => {
      var _a;
      return h19("div", { class: "description-list-row" }, [
        h19("dt", { class: "description-list-term" }, item.term || item.label),
        h19(
          "dd",
          { class: cx("description-list-value", item.muted && "description-list-value-muted") },
          ((_a = slots[item.key]) == null ? void 0 : _a.call(slots, { item })) || item.value
        )
      ]);
    }));
  }
});

// src/vue/components/GnDefinitionList.js
import { defineComponent as defineComponent19, h as h20 } from "vue";
var GnDefinitionList_default = defineComponent19({
  name: "GnDefinitionList",
  props: {
    items: { type: Array, default: () => [] }
  },
  setup(props, { attrs, slots }) {
    return () => h20("dl", { ...attrs, class: cx("list list-definition", attrs.class) }, props.items.map((item) => {
      var _a;
      return h20("div", {
        class: "list-row"
      }, [
        h20("dt", { class: "list-term" }, item.term || item.label),
        h20("dd", { class: "list-desc" }, ((_a = slots[item.key]) == null ? void 0 : _a.call(slots, { item })) || item.description || item.value)
      ]);
    }));
  }
});

// src/vue/components/GnDropdown.js
import { defineComponent as defineComponent20, h as h21, onBeforeUnmount as onBeforeUnmount2, ref as ref5 } from "vue";
var GnDropdown_default = defineComponent20({
  name: "GnDropdown",
  props: {
    label: { type: String, default: "Actions" },
    icon: { type: String, default: "ph-dots-three-outline" },
    variant: { type: String, default: "secondary" },
    items: { type: Array, default: () => [] }
  },
  emits: ["select"],
  setup(props, { emit, slots }) {
    const open = ref5(false);
    const root = ref5(null);
    const close = () => {
      open.value = false;
      document.removeEventListener("click", onOutsideClick);
      document.removeEventListener("keydown", onKeydown);
    };
    const onOutsideClick = (event) => {
      if (root.value && !root.value.contains(event.target)) {
        close();
      }
    };
    const onKeydown = (event) => {
      if (event.key === "Escape") {
        event.preventDefault();
        close();
      }
    };
    const toggle = () => {
      open.value = !open.value;
      if (open.value) {
        setTimeout(() => document.addEventListener("click", onOutsideClick), 0);
        document.addEventListener("keydown", onKeydown);
      } else {
        close();
      }
    };
    const select = (item) => {
      var _a;
      if (item.disabled) {
        return;
      }
      (_a = item.onSelect) == null ? void 0 : _a.call(item, item);
      emit("select", item);
      close();
    };
    onBeforeUnmount2(close);
    return () => {
      var _a, _b;
      return h21("div", { ref: root, class: cx("dropdown", { "is-open": open.value }) }, [
        ((_a = slots.trigger) == null ? void 0 : _a.call(slots, { open: open.value, toggle })) || h21(GnButton_default, {
          variant: props.variant,
          icon: props.icon,
          "aria-expanded": open.value ? "true" : "false",
          onClick: toggle
        }, () => props.label),
        h21("div", { class: "dropdown-menu", role: "menu" }, ((_b = slots.default) == null ? void 0 : _b.call(slots, { close })) || props.items.map((item) => h21("button", {
          class: cx("dropdown-item", item.danger && "dropdown-item-danger"),
          type: "button",
          role: "menuitem",
          disabled: item.disabled,
          onClick: () => select(item)
        }, [
          iconNode(item.icon),
          item.label
        ])))
      ]);
    };
  }
});

// src/vue/components/GnDrawer.js
import { defineComponent as defineComponent21, h as h22, nextTick as nextTick3, onBeforeUnmount as onBeforeUnmount3, ref as ref6, Teleport as Teleport2, watch as watch2 } from "vue";
var drawerId = 0;
var GnDrawer_default = defineComponent21({
  name: "GnDrawer",
  props: {
    open: { type: Boolean, default: false },
    title: { type: String, default: "" },
    position: { type: String, default: "right" }
  },
  emits: ["update:open", "close"],
  setup(props, { emit, slots }) {
    const titleId = `gn-drawer-title-${++drawerId}`;
    const panelRef = ref6(null);
    const visible = ref6(false);
    const closing = ref6(false);
    let previousFocus = null;
    let closeTimer = null;
    const close = () => {
      emit("update:open", false);
      emit("close");
    };
    const onKeydown = (event) => {
      if (event.key === "Escape") {
        event.preventDefault();
        close();
      } else {
        trapFocus(event, panelRef.value);
      }
    };
    watch2(() => props.open, (open) => {
      var _a;
      if (open) {
        closing.value = false;
        visible.value = true;
        previousFocus = document.activeElement;
        document.addEventListener("keydown", onKeydown);
        nextTick3(() => {
          var _a2;
          return (_a2 = panelRef.value) == null ? void 0 : _a2.focus();
        });
      } else {
        closing.value = true;
        document.removeEventListener("keydown", onKeydown);
        (_a = previousFocus == null ? void 0 : previousFocus.focus) == null ? void 0 : _a.call(previousFocus);
        previousFocus = null;
        closeTimer = window.setTimeout(() => {
          visible.value = false;
          closing.value = false;
        }, 300);
      }
    }, { flush: "post" });
    onBeforeUnmount3(() => {
      document.removeEventListener("keydown", onKeydown);
      window.clearTimeout(closeTimer);
    });
    return () => {
      var _a, _b;
      return visible.value ? h22(Teleport2, { to: "body" }, [
        h22("div", {
          class: cx("drawer", closing.value ? "a-hide" : "a-show", { "drawer-left": props.position === "left" }),
          "aria-hidden": "false"
        }, [
          h22("div", { class: "drawer-backdrop", onClick: close }),
          h22("aside", {
            ref: panelRef,
            class: "drawer-panel",
            role: "dialog",
            "aria-modal": "true",
            "aria-labelledby": titleId,
            tabindex: "-1"
          }, [
            h22("header", { class: "drawer-header" }, [
              h22("h4", { class: "drawer-title", id: titleId }, ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title),
              h22("button", {
                class: "btn-icon drawer-close",
                type: "button",
                "aria-label": "Close",
                onClick: close
              }, [iconNode("ph-x")])
            ]),
            h22("div", { class: "drawer-body" }, (_b = slots.default) == null ? void 0 : _b.call(slots)),
            slots.footer && h22("footer", { class: "drawer-footer" }, slots.footer({ close }))
          ])
        ])
      ]) : null;
    };
  }
});

// src/vue/components/GnEmptyState.js
import { defineComponent as defineComponent22, h as h23 } from "vue";
var GnEmptyState_default = defineComponent22({
  name: "GnEmptyState",
  props: {
    title: { type: String, required: true },
    text: { type: String, default: "" },
    icon: { type: String, default: "ph-package" },
    variant: { type: String, default: "" }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a, _b;
      return h23("div", {
        ...attrs,
        class: cx("empty-state", props.variant && `empty-state-${props.variant}`, attrs.class)
      }, [
        h23("div", { class: "empty-state-icon" }, [iconNode(props.icon)]),
        h23("h3", { class: "empty-state-title" }, ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title),
        (props.text || slots.default) && h23("p", { class: "empty-state-text" }, ((_b = slots.default) == null ? void 0 : _b.call(slots)) || props.text),
        slots.actions && h23("div", { class: "empty-state-actions" }, slots.actions())
      ]);
    };
  }
});

// src/vue/components/GnFileUpload.js
import { defineComponent as defineComponent23, h as h24, onBeforeUnmount as onBeforeUnmount4, ref as ref7, watch as watch3 } from "vue";
function fileType(file) {
  const ext = file.name.split(".").pop();
  return ext ? ext.slice(0, 6).toUpperCase() : "FILE";
}
function fileSize(file) {
  if (!file.size) {
    return "0 B";
  }
  const units = ["B", "KB", "MB", "GB"];
  const index = Math.min(Math.floor(Math.log(file.size) / Math.log(1024)), units.length - 1);
  const value = file.size / Math.pow(1024, index);
  return `${value.toFixed(value >= 10 || index === 0 ? 0 : 1)} ${units[index]}`;
}
var GnFileUpload_default = defineComponent23({
  name: "GnFileUpload",
  props: {
    modelValue: { type: Array, default: () => [] },
    title: { type: String, default: "Upload files" },
    description: { type: String, default: "Attach documents, archives or images." },
    primary: { type: String, default: "Choose files" },
    secondary: { type: String, default: "Images get thumbnails, other files show their type" },
    badge: { type: String, default: "" },
    multiple: { type: Boolean, default: true },
    accept: { type: String, default: "" }
  },
  emits: ["update:modelValue", "change"],
  setup(props, { emit, slots }) {
    const urls = ref7(/* @__PURE__ */ new Map());
    const revokeFile = (file) => {
      const url = urls.value.get(file);
      if (url) {
        URL.revokeObjectURL(url);
        urls.value.delete(file);
      }
    };
    const revokeAll = () => {
      urls.value.forEach((url) => URL.revokeObjectURL(url));
      urls.value.clear();
    };
    const setFiles = (fileList) => {
      const files = Array.from(fileList || []);
      emit("update:modelValue", files);
      emit("change", files);
    };
    const remove = (index) => {
      revokeFile(props.modelValue[index]);
      const files = props.modelValue.filter((_, itemIndex) => itemIndex !== index);
      emit("update:modelValue", files);
      emit("change", files);
    };
    const previewUrl = (file) => {
      var _a;
      if (!((_a = file.type) == null ? void 0 : _a.startsWith("image/"))) {
        return "";
      }
      if (!urls.value.has(file)) {
        urls.value.set(file, URL.createObjectURL(file));
      }
      return urls.value.get(file);
    };
    watch3(() => props.modelValue, (files) => {
      const active = new Set(files);
      [...urls.value.keys()].forEach((file) => {
        if (!active.has(file)) {
          revokeFile(file);
        }
      });
    });
    onBeforeUnmount4(revokeAll);
    return () => {
      var _a, _b;
      return h24("div", { class: "file-upload-panel" }, [
        h24("div", { class: "file-upload-form" }, [
          h24("div", { class: "file-upload-header" }, [
            h24("div", { class: "file-upload-heading" }, [
              h24("h3", { class: "file-upload-title" }, ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title),
              h24("p", { class: "file-upload-description" }, ((_b = slots.description) == null ? void 0 : _b.call(slots)) || props.description)
            ]),
            props.badge && h24(GnBadge_default, { variant: "info" }, () => props.badge)
          ]),
          h24("label", { class: "file-upload-dropzone" }, [
            h24("span", { class: "file-upload-icon", "aria-hidden": "true" }, [iconNode("ph-cloud-arrow-up")]),
            h24("span", { class: "file-upload-body" }, [
              h24("span", { class: "file-upload-primary" }, props.primary),
              h24("span", { class: "file-upload-secondary" }, props.secondary)
            ]),
            h24("input", {
              type: "file",
              multiple: props.multiple,
              accept: props.accept || void 0,
              onChange: (event) => setFiles(event.target.files)
            })
          ]),
          h24("div", { class: "file-upload-preview", hidden: !props.modelValue.length }, props.modelValue.map((file, index) => h24("figure", {
            class: "file-upload-preview-item"
          }, [
            h24("button", {
              class: "file-upload-preview-remove",
              type: "button",
              "aria-label": `Remove ${file.name}`,
              onClick: () => remove(index)
            }, [iconNode("ph-x")]),
            h24(
              "div",
              { class: "file-upload-preview-visual" },
              previewUrl(file) ? h24("img", { src: previewUrl(file), alt: "" }) : h24("span", { class: "file-upload-preview-type" }, fileType(file))
            ),
            h24("figcaption", {}, [
              h24("span", { class: "file-upload-preview-name" }, file.name),
              h24("span", { class: "file-upload-preview-meta" }, `${fileType(file)} / ${fileSize(file)}`)
            ])
          ]))),
          slots.actions && h24("div", { class: "file-upload-actions" }, slots.actions()),
          !slots.actions && props.modelValue.length > 0 && h24("div", { class: "file-upload-actions" }, [
            h24(GnButton_default, {
              variant: "secondary",
              size: "sm",
              onClick: () => {
                revokeAll();
                setFiles([]);
              }
            }, () => "Reset")
          ])
        ])
      ]);
    };
  }
});

// src/vue/components/GnIconButton.js
import { defineComponent as defineComponent24, h as h25 } from "vue";
var GnIconButton_default = defineComponent24({
  name: "GnIconButton",
  props: {
    icon: { type: String, required: true },
    label: { type: String, required: true },
    type: { type: String, default: "button" },
    size: { type: String, default: null },
    withoutHover: { type: Boolean, default: false }
  },
  setup(props, { attrs }) {
    return () => h25("button", {
      ...attrs,
      type: props.type,
      "aria-label": props.label,
      class: cx("btn-icon", { "btn-icon-sm": props.size === "sm", "without-hover": props.withoutHover }, attrs.class)
    }, [iconNode(props.icon)]);
  }
});

// src/vue/components/GnIdentity.js
import { defineComponent as defineComponent25, h as h26 } from "vue";
var GnIdentity_default = defineComponent25({
  name: "GnIdentity",
  props: {
    title: { type: String, required: true },
    meta: { type: String, default: "" },
    avatar: { type: Object, default: () => ({}) }
  },
  setup(props, { slots }) {
    return () => {
      var _a, _b, _c;
      return h26("span", { class: "identity" }, [
        ((_a = slots.avatar) == null ? void 0 : _a.call(slots)) || h26(GnAvatar_default, props.avatar),
        h26("span", { class: "identity-content" }, [
          h26("span", { class: "identity-title" }, ((_b = slots.title) == null ? void 0 : _b.call(slots)) || props.title),
          (props.meta || slots.meta) && h26("span", { class: "identity-meta" }, ((_c = slots.meta) == null ? void 0 : _c.call(slots)) || props.meta)
        ])
      ]);
    };
  }
});

// src/vue/components/GnInput.js
import { defineComponent as defineComponent26, h as h27 } from "vue";
var GnInput_default = defineComponent26({
  name: "GnInput",
  inheritAttrs: false,
  props: {
    modelValue: { type: [String, Number], default: "" },
    label: { type: String, default: "" },
    type: { type: String, default: "text" },
    icon: { type: String, default: "" },
    state: { type: String, default: "" },
    help: { type: String, default: "" }
  },
  emits: ["update:modelValue"],
  setup(props, { attrs, emit }) {
    return () => h27("div", { class: "form-group" }, [
      h27("label", { class: cx("label", props.state) }, [
        props.label,
        iconNode(props.icon),
        h27("input", {
          ...attrs,
          type: props.type,
          value: props.modelValue,
          class: cx("input", attrs.class),
          onInput: (event) => emit("update:modelValue", eventValue(event))
        })
      ]),
      props.help && h27("div", { class: cx("input-info", props.state === "error" && "error") }, props.help)
    ]);
  }
});

// src/vue/components/GnInputGroup.js
import { defineComponent as defineComponent27, h as h28 } from "vue";
var GnInputGroup_default = defineComponent27({
  name: "GnInputGroup",
  props: {
    compact: { type: Boolean, default: false },
    addon: { type: String, default: "" },
    icon: { type: String, default: "" }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a, _b;
      return h28("div", {
        ...attrs,
        class: cx("input-group", { "input-group-compact": props.compact }, attrs.class)
      }, [
        (props.addon || props.icon || slots.addon) && h28("span", { class: "input-group-addon" }, ((_a = slots.addon) == null ? void 0 : _a.call(slots)) || iconNode(props.icon) || props.addon),
        (_b = slots.default) == null ? void 0 : _b.call(slots),
        slots.action && h28("span", { class: "input-group-action" }, slots.action())
      ]);
    };
  }
});

// src/vue/components/GnList.js
import { defineComponent as defineComponent28, h as h29 } from "vue";
var GnList_default = defineComponent28({
  name: "GnList",
  props: {
    items: { type: Array, default: () => [] },
    ordered: { type: Boolean, default: false },
    icons: { type: Boolean, default: false }
  },
  setup(props, { attrs, slots }) {
    const tag = props.ordered ? "ol" : "ul";
    return () => h29(tag, {
      ...attrs,
      class: cx("list", {
        "list-ordered": props.ordered,
        "with-icons": props.icons
      }, attrs.class)
    }, props.items.map((item) => {
      var _a;
      return h29("li", { class: "list-item" }, [
        iconNode(item.icon),
        ((_a = slots.item) == null ? void 0 : _a.call(slots, { item })) || item.label || item
      ]);
    }));
  }
});

// src/vue/components/GnLoader.js
import { defineComponent as defineComponent29, h as h30 } from "vue";
var GnLoader_default = defineComponent29({
  name: "GnLoader",
  props: {
    circle: { type: Boolean, default: false },
    label: { type: String, default: "Loading" }
  },
  setup(props, { attrs }) {
    return () => props.circle ? h30("div", { ...attrs, class: cx("circle-loader", attrs.class) }, [
      iconNode("ph-bold ph-spinner normalize"),
      props.label
    ]) : h30("div", { ...attrs, class: cx("loader", attrs.class), role: "status", "aria-label": props.label });
  }
});

// src/vue/components/GnLoginCard.js
import { defineComponent as defineComponent30, h as h31, ref as ref8 } from "vue";
var GnLoginCard_default = defineComponent30({
  name: "GnLoginCard",
  props: {
    title: { type: String, default: "Sign in" },
    logoSrc: { type: String, default: "" },
    logoIcon: { type: String, default: "" },
    usernameLabel: { type: String, default: "Username" },
    usernameIcon: { type: String, default: "ph-user" },
    passwordLabel: { type: String, default: "Password" },
    passwordIcon: { type: String, default: "ph-lock-key" },
    rememberMe: { type: Boolean, default: false },
    rememberLabel: { type: String, default: "Remember me" },
    submitText: { type: String, default: "Sign in" },
    submitVariant: { type: String, default: "primary" },
    loading: { type: Boolean, default: false },
    error: { type: String, default: "" },
    forgotHref: { type: String, default: "" },
    forgotText: { type: String, default: "Forgot password?" },
    signupHref: { type: String, default: "" },
    signupText: { type: String, default: "Create account" }
  },
  emits: ["submit"],
  setup(props, { emit }) {
    const username = ref8("");
    const password = ref8("");
    const remember = ref8(false);
    const onSubmit = (event) => {
      event.preventDefault();
      emit("submit", {
        username: username.value,
        password: password.value,
        remember: remember.value
      });
    };
    return () => h31("article", { class: "card login-card" }, [
      (props.title || props.logoSrc || props.logoIcon) && h31("header", { class: "card-title login-card-header" }, [
        props.logoSrc && h31("img", { src: props.logoSrc, alt: "", class: "login-card-logo" }),
        props.logoIcon && !props.logoSrc && iconNode(props.logoIcon, "login-card-logo-icon"),
        props.title && h31("span", { class: "login-card-title" }, props.title)
      ]),
      h31("div", { class: "card-content" }, [
        props.error && h31(GnAlert_default, { variant: "danger", class: "login-card-error" }, () => props.error),
        h31("form", { class: "login-card-form", onSubmit }, [
          h31(GnInput_default, {
            modelValue: username.value,
            "onUpdate:modelValue": (v) => {
              username.value = v;
            },
            label: props.usernameLabel,
            icon: props.usernameIcon,
            type: "text",
            autocomplete: "username"
          }),
          h31(GnInput_default, {
            modelValue: password.value,
            "onUpdate:modelValue": (v) => {
              password.value = v;
            },
            label: props.passwordLabel,
            icon: props.passwordIcon,
            type: "password",
            autocomplete: "current-password"
          }),
          props.rememberMe && h31(GnCheckbox_default, {
            modelValue: remember.value,
            "onUpdate:modelValue": (v) => {
              remember.value = v;
            }
          }, () => props.rememberLabel),
          h31(GnButton_default, {
            variant: props.submitVariant,
            loading: props.loading,
            disabled: props.loading,
            type: "submit",
            class: "login-card-submit"
          }, () => props.submitText),
          (props.forgotHref || props.signupHref) && h31("div", { class: "login-card-links" }, [
            props.forgotHref && h31("a", { href: props.forgotHref, class: "login-card-link" }, props.forgotText),
            props.signupHref && h31("a", { href: props.signupHref, class: "login-card-link" }, props.signupText)
          ])
        ])
      ])
    ]);
  }
});

// src/vue/components/GnMetricCard.js
import { defineComponent as defineComponent31, h as h32 } from "vue";
var GnMetricCard_default = defineComponent31({
  name: "GnMetricCard",
  props: {
    label: { type: String, required: true },
    value: { type: [String, Number], required: true },
    icon: { type: String, default: "ph-chart-line-up" },
    delta: { type: String, default: "" },
    negative: { type: Boolean, default: false },
    meta: { type: String, default: "" }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a, _b, _c;
      return h32("article", { ...attrs, class: cx("card metric-card", attrs.class) }, [
        h32("div", { class: "card-content" }, [
          h32("div", { class: "metric-card-header" }, [
            h32("p", { class: "metric-card-label" }, ((_a = slots.label) == null ? void 0 : _a.call(slots)) || props.label),
            h32("span", { class: "metric-card-icon" }, [iconNode(props.icon)])
          ]),
          h32("p", { class: "metric-card-value" }, ((_b = slots.value) == null ? void 0 : _b.call(slots)) || props.value),
          (props.delta || props.meta || slots.meta) && h32("div", { class: "metric-card-meta" }, [
            props.delta && h32("span", {
              class: cx("metric-card-delta", { "metric-card-delta-negative": props.negative })
            }, props.delta),
            ((_c = slots.meta) == null ? void 0 : _c.call(slots)) || props.meta
          ])
        ])
      ]);
    };
  }
});

// src/vue/components/GnNavList.js
import { computed as computed2, defineComponent as defineComponent32, h as h33 } from "vue";

// src/vue/composables/useVueRouter.js
import { getCurrentInstance } from "vue";
function tryUseRouter() {
  var _a;
  const instance = getCurrentInstance();
  return ((_a = instance == null ? void 0 : instance.proxy) == null ? void 0 : _a.$router) || null;
}
function tryUseRoute() {
  var _a;
  const instance = getCurrentInstance();
  return ((_a = instance == null ? void 0 : instance.proxy) == null ? void 0 : _a.$route) || null;
}
function isRouteActive(currentRoute, to, strategy = "prefix") {
  if (!currentRoute) {
    return false;
  }
  const route = currentRoute.value || currentRoute;
  if (typeof to === "string") {
    if (strategy === "exact") {
      return route.path === to;
    }
    return route.path === to || route.path.startsWith(to + "/");
  }
  if (to.path) {
    if (strategy === "exact") {
      return route.path === to.path;
    }
    return route.path === to.path || route.path.startsWith(to.path + "/");
  }
  if (to.name) {
    return route.name === to.name;
  }
  return false;
}

// src/vue/components/GnNavList.js
var GnNavList_default = defineComponent32({
  name: "GnNavList",
  props: {
    items: { type: Array, default: () => [] },
    activeMatch: { type: String, default: "prefix" }
  },
  emits: ["select"],
  setup(props, { attrs, emit, slots }) {
    const router = tryUseRouter();
    const route = tryUseRoute();
    const hasRouter = Boolean(router && route);
    const resolveHref = (to) => {
      if (!to) {
        return void 0;
      }
      if (typeof to === "string") {
        return to;
      }
      if (to.path) {
        return to.path;
      }
      return void 0;
    };
    const navItems = computed2(() => props.items.map((item) => {
      const hasTo = Boolean(item.to);
      const resolvedHref = hasTo ? hasRouter ? router.resolve(item.to).href : resolveHref(item.to) : item.href;
      const isActive = hasTo && hasRouter ? isRouteActive(route, item.to, props.activeMatch) : Boolean(item.active);
      return {
        ...item,
        resolvedHref,
        isActive,
        hasTo
      };
    }));
    return () => h33("ul", { ...attrs, class: cx("list list-nav", attrs.class) }, navItems.value.map((item) => {
      var _a, _b;
      return h33("li", {
        class: cx("list-item", { "list-item-active": item.isActive })
      }, [
        h33(item.resolvedHref ? "a" : "button", {
          class: "list-action",
          href: item.resolvedHref,
          type: item.resolvedHref ? void 0 : "button",
          onClick: (event) => {
            var _a2;
            if (item.hasTo && hasRouter) {
              event.preventDefault();
              router.push(item.to);
            }
            (_a2 = item.onSelect) == null ? void 0 : _a2.call(item, item, event);
            emit("select", item);
          }
        }, [
          h33("span", { class: "list-label" }, [
            iconNode(item.icon),
            ((_a = slots.label) == null ? void 0 : _a.call(slots, { item })) || item.label
          ]),
          (item.meta || slots.meta) && h33("span", { class: "list-meta" }, ((_b = slots.meta) == null ? void 0 : _b.call(slots, { item })) || item.meta)
        ])
      ]);
    }));
  }
});

// src/vue/components/GnNavigationShell.js
import { defineComponent as defineComponent33, h as h34, nextTick as nextTick4, onBeforeUnmount as onBeforeUnmount5, ref as ref9, watch as watch4 } from "vue";
var shellId = 0;
var GnNavigationShell_default = defineComponent33({
  name: "GnNavigationShell",
  props: {
    brand: { type: String, default: "GNexus UI Kit" },
    logoSrc: { type: String, default: "/assets/imgs/gnexus-mark.svg" },
    current: { type: String, default: "" },
    title: { type: String, default: "Sections" },
    subtitle: { type: String, default: "Navigation" },
    footerLeft: { type: String, default: "" },
    footerRight: { type: String, default: "" },
    items: { type: Array, default: () => [] },
    activeMatch: { type: String, default: "prefix" }
  },
  emits: ["select"],
  setup(props, { emit, slots }) {
    const open = ref9(false);
    const drawerId2 = `gn-nav-drawer-${++shellId}`;
    const drawerRef = ref9(null);
    let previousFocus = null;
    const close = () => {
      open.value = false;
    };
    const toggle = () => {
      open.value = !open.value;
    };
    const onKeydown = (event) => {
      if (event.key === "Escape") {
        event.preventDefault();
        close();
      }
    };
    watch4(open, (isOpen) => {
      var _a;
      if (isOpen) {
        previousFocus = document.activeElement;
        document.body.classList.add("nav-drawer-open");
        document.addEventListener("keydown", onKeydown);
        nextTick4(() => {
          var _a2;
          return (_a2 = drawerRef.value) == null ? void 0 : _a2.focus();
        });
      } else {
        document.body.classList.remove("nav-drawer-open");
        document.removeEventListener("keydown", onKeydown);
        (_a = previousFocus == null ? void 0 : previousFocus.focus) == null ? void 0 : _a.call(previousFocus);
        previousFocus = null;
      }
    });
    onBeforeUnmount5(() => {
      document.body.classList.remove("nav-drawer-open");
      document.removeEventListener("keydown", onKeydown);
    });
    return () => {
      var _a, _b, _c, _d, _e, _f, _g;
      return [
        h34("header", { class: "nav-topbar" }, [
          h34("button", {
            class: "nav-topbar-toggle",
            type: "button",
            "aria-controls": drawerId2,
            "aria-expanded": open.value ? "true" : "false",
            onClick: toggle
          }, [
            iconNode("ph-sidebar-simple"),
            h34("span", {}, "Menu")
          ]),
          h34("div", { class: "nav-topbar-brand" }, [
            props.logoSrc && h34("img", { src: props.logoSrc, alt: "", "aria-hidden": "true" }),
            h34("span", {}, ((_a = slots.brand) == null ? void 0 : _a.call(slots)) || props.brand)
          ]),
          h34("div", { class: "nav-topbar-current" }, ((_b = slots.current) == null ? void 0 : _b.call(slots)) || props.current)
        ]),
        h34("div", { class: "nav-drawer-backdrop", onClick: close }),
        h34("aside", {
          ref: drawerRef,
          class: ["nav-drawer", { "is-open": open.value }],
          id: drawerId2,
          "aria-label": "Navigation",
          "aria-hidden": open.value ? "false" : "true",
          tabindex: "-1"
        }, [
          h34("header", { class: "nav-drawer-header" }, [
            h34("div", {}, [
              h34("div", { class: "nav-drawer-title" }, ((_c = slots.title) == null ? void 0 : _c.call(slots)) || props.title),
              h34("div", { class: "nav-drawer-subtitle" }, ((_d = slots.subtitle) == null ? void 0 : _d.call(slots)) || props.subtitle)
            ]),
            h34("button", {
              class: "nav-drawer-close",
              type: "button",
              "aria-label": "Close navigation",
              onClick: close
            }, [iconNode("ph-x")])
          ]),
          h34("nav", { class: "nav-drawer-body" }, [
            ((_e = slots.default) == null ? void 0 : _e.call(slots, { close })) || h34(GnNavList_default, {
              items: props.items,
              activeMatch: props.activeMatch,
              onSelect: (item) => {
                emit("select", item);
                close();
              }
            })
          ]),
          (slots.footer || props.footerLeft || props.footerRight) && h34(
            "footer",
            { class: "nav-drawer-footer" },
            ((_f = slots.footer) == null ? void 0 : _f.call(slots)) || [
              h34("span", {}, props.footerLeft),
              h34("span", {}, props.footerRight)
            ]
          )
        ]),
        (_g = slots.content) == null ? void 0 : _g.call(slots)
      ];
    };
  }
});

// src/vue/components/GnPageHeader.js
import { defineComponent as defineComponent34, h as h35 } from "vue";
var GnPageHeader_default = defineComponent34({
  name: "GnPageHeader",
  props: {
    title: { type: String, required: true },
    subtitle: { type: String, default: "" },
    kicker: { type: String, default: "" },
    compact: { type: Boolean, default: false },
    accent: { type: Boolean, default: false }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a, _b, _c;
      return h35("header", {
        ...attrs,
        class: cx("page-header", {
          "page-header-compact": props.compact,
          "page-header-accent": props.accent
        }, attrs.class)
      }, [
        h35("div", { class: "page-header-content" }, [
          (props.kicker || slots.kicker) && h35("div", { class: "page-header-kicker" }, ((_a = slots.kicker) == null ? void 0 : _a.call(slots)) || props.kicker),
          h35("h1", { class: "page-header-title" }, ((_b = slots.title) == null ? void 0 : _b.call(slots)) || props.title),
          (props.subtitle || slots.subtitle) && h35("p", { class: "page-header-subtitle" }, ((_c = slots.subtitle) == null ? void 0 : _c.call(slots)) || props.subtitle),
          slots.meta && h35("div", { class: "page-header-meta" }, slots.meta())
        ]),
        slots.actions && h35("div", { class: "page-header-actions" }, slots.actions())
      ]);
    };
  }
});

// src/vue/components/GnHorizontalCard.js
import { defineComponent as defineComponent35, h as h36 } from "vue";
var GnHorizontalCard_default = defineComponent35({
  name: "GnHorizontalCard",
  props: {
    image: { type: String, default: "" },
    title: { type: String, default: "" },
    titleHref: { type: String, default: "" },
    icon: { type: String, default: "" }
  },
  setup(props, { attrs, slots }) {
    const titleNode = () => {
      var _a;
      const content = [iconNode(props.icon), ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title];
      if (props.titleHref) {
        return h36("a", { href: props.titleHref, class: "card-title-link" }, content);
      }
      return content;
    };
    return () => {
      var _a;
      return h36("article", {
        ...attrs,
        class: cx("card card-horizontal", attrs.class)
      }, [
        props.image && h36("div", { class: "card-media" }, [
          h36("img", { src: props.image, alt: "" })
        ]),
        h36("div", { class: "card-body" }, [
          (props.title || props.icon || slots.title) && h36("h3", { class: "card-title" }, titleNode()),
          h36("div", { class: "card-content" }, (_a = slots.default) == null ? void 0 : _a.call(slots)),
          slots.footer && h36("footer", { class: "card-footer" }, slots.footer())
        ])
      ]);
    };
  }
});

// src/vue/components/GnPagination.js
import { defineComponent as defineComponent36, h as h37 } from "vue";
var GnPagination_default = defineComponent36({
  name: "GnPagination",
  props: {
    page: { type: Number, required: true },
    totalPages: { type: Number, required: true },
    ariaLabel: { type: String, default: "Pagination" }
  },
  emits: ["update:page"],
  setup(props, { emit }) {
    const setPage = (page) => {
      if (page >= 1 && page <= props.totalPages && page !== props.page) {
        emit("update:page", page);
      }
    };
    return () => {
      const pages = Array.from({ length: props.totalPages }, (_, index) => index + 1);
      return h37("nav", { class: "pagination", "aria-label": props.ariaLabel }, [
        h37("button", {
          class: "pagination-item",
          type: "button",
          disabled: props.page <= 1,
          onClick: () => setPage(props.page - 1)
        }, [iconNode("ph-arrow-left")]),
        pages.map((page) => h37("button", {
          class: cx("pagination-item", { "pagination-item-active": page === props.page }),
          type: "button",
          "aria-current": page === props.page ? "page" : void 0,
          onClick: () => setPage(page)
        }, page)),
        h37("button", {
          class: "pagination-item",
          type: "button",
          disabled: props.page >= props.totalPages,
          onClick: () => setPage(props.page + 1)
        }, [iconNode("ph-arrow-right")])
      ]);
    };
  }
});

// src/vue/components/GnPopover.js
import { defineComponent as defineComponent37, h as h38, onBeforeUnmount as onBeforeUnmount6, ref as ref10 } from "vue";
var GnPopover_default = defineComponent37({
  name: "GnPopover",
  props: {
    label: { type: String, default: "Details" },
    title: { type: String, default: "" },
    text: { type: String, default: "" },
    icon: { type: String, default: "ph-info" },
    variant: { type: String, default: "accent" }
  },
  setup(props, { slots }) {
    const open = ref10(false);
    const root = ref10(null);
    const close = () => {
      open.value = false;
      document.removeEventListener("click", onOutsideClick);
      document.removeEventListener("keydown", onKeydown);
    };
    const onOutsideClick = (event) => {
      if (root.value && !root.value.contains(event.target)) {
        close();
      }
    };
    const onKeydown = (event) => {
      if (event.key === "Escape") {
        event.preventDefault();
        close();
      }
    };
    const toggle = () => {
      open.value = !open.value;
      if (open.value) {
        setTimeout(() => document.addEventListener("click", onOutsideClick), 0);
        document.addEventListener("keydown", onKeydown);
      } else {
        close();
      }
    };
    onBeforeUnmount6(close);
    return () => {
      var _a, _b, _c;
      return h38("div", { ref: root, class: cx("popover", { "is-open": open.value }) }, [
        ((_a = slots.trigger) == null ? void 0 : _a.call(slots, { open: open.value, toggle })) || h38(GnButton_default, {
          variant: props.variant,
          icon: props.icon,
          "aria-expanded": open.value ? "true" : "false",
          onClick: toggle
        }, () => props.label),
        h38("div", { class: "popover-panel" }, [
          (props.title || slots.title) && h38("h3", { class: "popover-title" }, ((_b = slots.title) == null ? void 0 : _b.call(slots)) || props.title),
          (props.text || slots.default) && h38("p", { class: "popover-text" }, ((_c = slots.default) == null ? void 0 : _c.call(slots)) || props.text)
        ])
      ]);
    };
  }
});

// src/vue/components/GnProgress.js
import { defineComponent as defineComponent38, h as h39 } from "vue";
var GnProgress_default = defineComponent38({
  name: "GnProgress",
  props: {
    value: { type: Number, required: true },
    max: { type: Number, default: 100 },
    label: { type: String, default: "" },
    variant: { type: String, default: "secondary" },
    striped: { type: Boolean, default: false },
    animated: { type: Boolean, default: false }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a;
      const percent = Math.max(0, Math.min(100, Math.round(props.value / props.max * 100)));
      const variant = normalizeVariant(props.variant, "secondary");
      return h39("div", {
        ...attrs,
        class: cx("progress", `progress-${variant}`, {
          "progress-striped": props.striped,
          "progress-animated": props.animated
        }, attrs.class),
        style: { "--progress-value": `${percent}%` }
      }, [
        (props.label || slots.label) && h39("div", { class: "progress-header" }, [
          h39("span", {}, ((_a = slots.label) == null ? void 0 : _a.call(slots)) || props.label),
          h39("span", { class: "progress-value" }, `${percent}%`)
        ]),
        h39("div", { class: "progress-track" }, [
          h39("span", {
            class: "progress-bar",
            role: "progressbar",
            "aria-valuenow": props.value,
            "aria-valuemin": 0,
            "aria-valuemax": props.max
          })
        ])
      ]);
    };
  }
});

// src/vue/components/GnProgressStages.js
import { defineComponent as defineComponent39, h as h40 } from "vue";
var GnProgressStages_default = defineComponent39({
  name: "GnProgressStages",
  props: {
    items: { type: Array, default: () => [] }
  },
  setup(props, { attrs }) {
    return () => h40("div", { ...attrs, class: cx("progress-stages", attrs.class) }, props.items.map((item) => h40("div", {
      class: cx("progress-stage", {
        "progress-stage-complete": item.status === "complete",
        "progress-stage-current": item.status === "current"
      })
    }, item.label || item)));
  }
});

// src/vue/components/GnRadio.js
import { defineComponent as defineComponent40, h as h41 } from "vue";
var GnRadio_default = defineComponent40({
  name: "GnRadio",
  inheritAttrs: false,
  props: {
    modelValue: { type: [String, Number, Boolean], default: "" },
    value: { type: [String, Number, Boolean], required: true },
    label: { type: String, default: "" },
    name: { type: String, default: "" },
    disabled: { type: Boolean, default: false }
  },
  emits: ["update:modelValue"],
  setup(props, { attrs, emit, slots }) {
    return () => {
      var _a;
      return h41("label", { class: cx("radio", attrs.class) }, [
        h41("input", {
          ...attrs,
          type: "radio",
          name: props.name,
          value: props.value,
          checked: props.modelValue === props.value,
          disabled: props.disabled,
          onChange: () => emit("update:modelValue", props.value)
        }),
        h41("span", { class: "radio-control", "aria-hidden": "true" }),
        h41("span", { class: "radio-label" }, ((_a = slots.default) == null ? void 0 : _a.call(slots)) || props.label)
      ]);
    };
  }
});

// src/vue/components/GnRadioGroup.js
import { defineComponent as defineComponent41, h as h42 } from "vue";
var GnRadioGroup_default = defineComponent41({
  name: "GnRadioGroup",
  props: {
    modelValue: { type: [String, Number, Boolean], default: "" },
    name: { type: String, default: "gn-radio-group" },
    label: { type: String, default: "" },
    options: { type: Array, default: () => [] }
  },
  emits: ["update:modelValue"],
  setup(props, { emit, slots }) {
    return () => {
      var _a;
      return h42("div", { class: "form-group", role: "radiogroup", "aria-label": props.label || void 0 }, [
        props.label && h42("div", { class: "label" }, props.label),
        ((_a = slots.default) == null ? void 0 : _a.call(slots)) || props.options.map((option) => h42(GnRadio_default, {
          modelValue: props.modelValue,
          "onUpdate:modelValue": (value) => emit("update:modelValue", value),
          name: props.name,
          value: option.value,
          label: option.label,
          disabled: option.disabled
        }))
      ]);
    };
  }
});

// src/vue/components/GnRange.js
import { defineComponent as defineComponent42, h as h43 } from "vue";
var GnRange_default = defineComponent42({
  name: "GnRange",
  inheritAttrs: false,
  props: {
    modelValue: { type: [Number, String], default: 0 },
    label: { type: String, default: "" },
    min: { type: [Number, String], default: 0 },
    max: { type: [Number, String], default: 100 },
    step: { type: [Number, String], default: 1 }
  },
  emits: ["update:modelValue"],
  setup(props, { attrs, emit }) {
    return () => h43("div", { class: "range" }, [
      h43("label", { class: "label" }, [
        props.label,
        h43("input", {
          ...attrs,
          type: "range",
          value: props.modelValue,
          min: props.min,
          max: props.max,
          step: props.step,
          onInput: (event) => emit("update:modelValue", eventValue(event))
        })
      ])
    ]);
  }
});

// src/vue/components/GnRouterTabs.js
import { computed as computed4, defineComponent as defineComponent44, h as h45, watch as watch5 } from "vue";

// src/vue/components/GnTabs.js
import { computed as computed3, defineComponent as defineComponent43, h as h44 } from "vue";
var GnTabs_default = defineComponent43({
  name: "GnTabs",
  props: {
    modelValue: { type: String, default: "" },
    items: { type: Array, required: true },
    compact: { type: Boolean, default: false },
    vertical: { type: Boolean, default: false },
    ariaLabel: { type: String, default: "Tabs" }
  },
  emits: ["update:modelValue"],
  setup(props, { emit, slots }) {
    const activeId = computed3(() => {
      var _a, _b;
      return props.modelValue || ((_a = props.items.find((item) => !item.disabled)) == null ? void 0 : _a.id) || ((_b = props.items[0]) == null ? void 0 : _b.id);
    });
    const activate = (item) => {
      if (!item.disabled) {
        emit("update:modelValue", item.id);
      }
    };
    const enabledItems = () => props.items.filter((item) => !item.disabled);
    const move = (item, direction) => {
      const items = enabledItems();
      const index = items.findIndex((enabled) => enabled.id === item.id);
      const next = items[(index + direction + items.length) % items.length];
      activate(next);
    };
    const handleKeydown = (event, item) => {
      if (event.key === "ArrowRight" || event.key === "ArrowDown") {
        event.preventDefault();
        move(item, 1);
      } else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
        event.preventDefault();
        move(item, -1);
      } else if (event.key === "Home") {
        event.preventDefault();
        activate(enabledItems()[0]);
      } else if (event.key === "End") {
        event.preventDefault();
        const items = enabledItems();
        activate(items[items.length - 1]);
      }
    };
    return () => h44("div", {
      class: cx("tabs", {
        "tabs-compact": props.compact,
        "tabs-vertical": props.vertical
      })
    }, [
      h44("div", { class: "tabs-list", role: "tablist", "aria-label": props.ariaLabel }, props.items.map((item) => {
        const active = item.id === activeId.value;
        const panelId = `${item.id}-panel`;
        return h44("button", {
          class: cx("tab", { "tab-active": active }),
          type: "button",
          role: "tab",
          "aria-selected": active ? "true" : "false",
          "aria-controls": panelId,
          "aria-disabled": item.disabled ? "true" : void 0,
          tabindex: active ? "0" : "-1",
          onClick: () => activate(item),
          onKeydown: (event) => handleKeydown(event, item)
        }, [
          iconNode(item.icon),
          item.label
        ]);
      })),
      h44("div", { class: "tabs-panels" }, props.items.map((item) => {
        var _a, _b;
        const active = item.id === activeId.value;
        return h44("div", {
          id: `${item.id}-panel`,
          class: cx("tab-panel", { "tab-panel-active": active }),
          role: "tabpanel",
          hidden: !active
        }, ((_a = slots[item.id]) == null ? void 0 : _a.call(slots, { item, active })) || active && ((_b = slots.default) == null ? void 0 : _b.call(slots, { item, active })));
      }))
    ]);
  }
});

// src/vue/components/GnRouterTabs.js
var GnRouterTabs_default = defineComponent44({
  name: "GnRouterTabs",
  props: {
    items: { type: Array, required: true },
    compact: { type: Boolean, default: false },
    vertical: { type: Boolean, default: false },
    ariaLabel: { type: String, default: "Tabs" },
    activeMatch: { type: String, default: "prefix" }
  },
  setup(props, { slots }) {
    const router = tryUseRouter();
    const route = tryUseRoute();
    const hasRouter = Boolean(router && route);
    if (!hasRouter && typeof process !== "undefined" && process.env && true) {
      console.warn("[gnexus-ui-kit] GnRouterTabs requires vue-router. Falling back to standard tabs.");
    }
    const tabItems = computed4(() => props.items.map((item) => ({
      id: item.id,
      label: item.label,
      icon: item.icon,
      disabled: item.disabled,
      to: item.to
    })));
    const activeId = computed4(() => {
      var _a, _b;
      if (!hasRouter) {
        return ((_a = tabItems.value.find((item) => !item.disabled)) == null ? void 0 : _a.id) || "";
      }
      const matched = tabItems.value.find((item) => {
        if (item.disabled || !item.to) {
          return false;
        }
        return isRouteActive(route, item.to, props.activeMatch);
      });
      return (matched == null ? void 0 : matched.id) || ((_b = tabItems.value.find((item) => !item.disabled)) == null ? void 0 : _b.id) || "";
    });
    const onUpdate = (id) => {
      if (!hasRouter) {
        return;
      }
      const item = tabItems.value.find((i) => i.id === id);
      if (item && item.to) {
        router.push(item.to);
      }
    };
    return () => h45(GnTabs_default, {
      modelValue: activeId.value,
      items: tabItems.value,
      compact: props.compact,
      vertical: props.vertical,
      ariaLabel: props.ariaLabel,
      "onUpdate:modelValue": onUpdate
    }, slots);
  }
});

// src/vue/components/GnSearchField.js
import { defineComponent as defineComponent45, h as h46 } from "vue";
var GnSearchField_default = defineComponent45({
  name: "GnSearchField",
  inheritAttrs: false,
  props: {
    modelValue: { type: String, default: "" },
    placeholder: { type: String, default: "Search" },
    compact: { type: Boolean, default: true },
    clearable: { type: Boolean, default: true }
  },
  emits: ["update:modelValue", "clear"],
  setup(props, { attrs, emit }) {
    const clear = () => {
      emit("update:modelValue", "");
      emit("clear");
    };
    return () => h46("div", {
      class: cx("input-group search-field", { "input-group-compact": props.compact })
    }, [
      h46("span", { class: "input-group-addon" }, [iconNode("ph-magnifying-glass")]),
      h46("input", {
        ...attrs,
        type: "search",
        value: props.modelValue,
        placeholder: props.placeholder,
        class: cx("input-group-input", attrs.class),
        onInput: (event) => emit("update:modelValue", eventValue(event))
      }),
      props.clearable && h46("button", {
        class: "input-group-action",
        type: "button",
        "aria-label": "Clear search",
        onClick: clear
      }, [iconNode("ph-x")])
    ]);
  }
});

// src/vue/components/GnSelect.js
import { defineComponent as defineComponent46, h as h47 } from "vue";
var GnSelect_default = defineComponent46({
  name: "GnSelect",
  inheritAttrs: false,
  props: {
    modelValue: { type: [String, Number], default: "" },
    label: { type: String, default: "" },
    icon: { type: String, default: "" },
    state: { type: String, default: "" },
    help: { type: String, default: "" },
    options: { type: Array, default: () => [] }
  },
  emits: ["update:modelValue"],
  setup(props, { attrs, emit, slots }) {
    const optionNodes = () => props.options.map((option) => {
      const value = typeof option === "object" ? option.value : option;
      const label = typeof option === "object" ? option.label : option;
      return h47("option", { value }, label);
    });
    return () => {
      var _a;
      return h47("div", { class: "form-group" }, [
        h47("label", { class: cx("label", props.state) }, [
          props.label,
          iconNode(props.icon),
          h47("div", { class: "select-wrap" }, [
            h47("select", {
              ...attrs,
              value: props.modelValue,
              class: cx("input select", attrs.class),
              onChange: (event) => emit("update:modelValue", eventValue(event))
            }, ((_a = slots.default) == null ? void 0 : _a.call(slots)) || optionNodes())
          ])
        ]),
        props.help && h47("div", { class: cx("input-info", props.state === "error" && "error") }, props.help)
      ]);
    };
  }
});

// src/vue/components/GnSkeleton.js
import { defineComponent as defineComponent47, h as h48 } from "vue";
var GnSkeleton_default = defineComponent47({
  name: "GnSkeleton",
  props: {
    type: { type: String, default: "line" },
    stack: { type: Boolean, default: false },
    count: { type: Number, default: 1 }
  },
  setup(props, { attrs }) {
    const skeleton = (key) => h48("span", {
      key,
      ...attrs,
      class: cx("skeleton", `skeleton-${props.type}`, attrs.class)
    });
    return () => props.stack ? h48("div", { class: "skeleton-stack" }, Array.from({ length: props.count }, (_, index) => skeleton(index))) : skeleton(0);
  }
});

// src/vue/components/GnSteps.js
import { defineComponent as defineComponent48, h as h49 } from "vue";
var GnSteps_default = defineComponent48({
  name: "GnSteps",
  props: {
    items: { type: Array, required: true },
    vertical: { type: Boolean, default: false }
  },
  setup(props, { attrs }) {
    return () => h49("ol", {
      ...attrs,
      class: cx("steps", { "steps-vertical": props.vertical }, attrs.class)
    }, props.items.map((item, index) => h49("li", {
      class: cx("step", {
        "step-complete": item.status === "complete",
        "step-current": item.status === "current",
        "step-disabled": item.disabled || item.status === "disabled"
      })
    }, [
      h49("span", { class: "step-marker" }, item.marker || String(index + 1)),
      h49("h3", { class: "step-title" }, item.title),
      item.text && h49("p", { class: "step-text" }, item.text)
    ])));
  }
});

// src/vue/components/GnStatusCard.js
import { defineComponent as defineComponent49, h as h50 } from "vue";
var GnStatusCard_default = defineComponent49({
  name: "GnStatusCard",
  props: {
    title: { type: String, required: true },
    text: { type: String, default: "" },
    icon: { type: String, default: "ph-stack" },
    variant: { type: String, default: "primary" }
  },
  setup(props, { attrs, slots }) {
    const variant = normalizeVariant(props.variant);
    return () => {
      var _a, _b, _c;
      return h50("article", { ...attrs, class: cx("card status-card", `card-${variant}`, attrs.class) }, [
        h50("span", { class: "card-title" }, ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title),
        h50("div", { class: "card-content" }, [
          h50("div", { class: "status-icon-container" }, [
            h50("div", { class: "status-icon" }, ((_b = slots.icon) == null ? void 0 : _b.call(slots)) || [iconNode(props.icon)])
          ]),
          (props.text || slots.default) && h50("p", { class: "status-name" }, ((_c = slots.default) == null ? void 0 : _c.call(slots)) || props.text)
        ])
      ]);
    };
  }
});

// src/vue/components/GnTable.js
import { defineComponent as defineComponent50, h as h51 } from "vue";
var GnTable_default = defineComponent50({
  name: "GnTable",
  props: {
    columns: { type: Array, required: true },
    rows: { type: Array, default: () => [] },
    caption: { type: String, default: "" },
    emptyText: { type: String, default: "Empty" }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a;
      return h51("div", { class: "table-wrapper" }, [
        h51("table", { class: cx("table data-list", { "table-empty": !props.rows.length }, attrs.class) }, [
          props.caption && h51("caption", { class: "table-caption" }, props.caption),
          h51("thead", { class: "table-head" }, [
            h51("tr", { class: "table-row" }, props.columns.map((column) => h51("th", { scope: "col" }, column.label)))
          ]),
          h51(
            "tbody",
            { class: "table-body" },
            props.rows.length ? props.rows.map((row) => h51("tr", { class: "table-row" }, props.columns.map((column) => {
              var _a2;
              const name = `cell-${column.key}`;
              return h51("td", {}, ((_a2 = slots[name]) == null ? void 0 : _a2.call(slots, { row, column, value: row[column.key] })) || row[column.key]);
            }))) : h51("tr", {}, [h51("td", { class: "is-empty", colspan: props.columns.length }, ((_a = slots.empty) == null ? void 0 : _a.call(slots)) || props.emptyText)])
          )
        ])
      ]);
    };
  }
});

// src/vue/components/GnTextarea.js
import { defineComponent as defineComponent51, h as h52 } from "vue";
var GnTextarea_default = defineComponent51({
  name: "GnTextarea",
  inheritAttrs: false,
  props: {
    modelValue: { type: String, default: "" },
    label: { type: String, default: "" },
    icon: { type: String, default: "" },
    state: { type: String, default: "" },
    help: { type: String, default: "" }
  },
  emits: ["update:modelValue"],
  setup(props, { attrs, emit }) {
    return () => h52("div", { class: "form-group" }, [
      h52("label", { class: cx("label", props.state) }, [
        props.label,
        iconNode(props.icon),
        h52("textarea", {
          ...attrs,
          value: props.modelValue,
          class: cx("input", attrs.class),
          onInput: (event) => emit("update:modelValue", eventValue(event))
        })
      ]),
      props.help && h52("div", { class: cx("input-info", props.state === "error" && "error") }, props.help)
    ]);
  }
});

// src/vue/components/GnTimeline.js
import { defineComponent as defineComponent52, h as h53 } from "vue";
var GnTimeline_default = defineComponent52({
  name: "GnTimeline",
  props: {
    items: { type: Array, default: () => [] }
  },
  setup(props, { attrs, slots }) {
    return () => h53("ol", { ...attrs, class: cx("timeline", attrs.class) }, props.items.map((item) => {
      var _a, _b;
      const variant = item.variant ? normalizeVariant(item.variant) : "";
      return h53("li", { class: cx("timeline-item", variant && `timeline-item-${variant}`) }, [
        h53("span", { class: "timeline-marker" }, [iconNode(item.icon || "ph-circle")]),
        h53("div", { class: "timeline-content" }, [
          h53("article", { class: "timeline-card" }, [
            h53("header", { class: "timeline-header" }, [
              h53("h3", { class: "timeline-title" }, item.title),
              item.time && h53("time", { class: "timeline-time" }, item.time)
            ]),
            h53("p", { class: "timeline-text" }, ((_a = slots[item.key]) == null ? void 0 : _a.call(slots, { item })) || item.text),
            (item.meta || slots.meta) && h53("div", { class: "timeline-meta" }, ((_b = slots.meta) == null ? void 0 : _b.call(slots, { item })) || item.meta)
          ])
        ])
      ]);
    }));
  }
});

// src/vue/components/GnTooltip.js
import { defineComponent as defineComponent53, h as h54, ref as ref11 } from "vue";
var GnTooltip_default = defineComponent53({
  name: "GnTooltip",
  props: {
    text: { type: String, default: "" }
  },
  setup(props, { attrs, slots }) {
    const open = ref11(false);
    return () => {
      var _a, _b;
      return h54("span", {
        ...attrs,
        class: cx("tooltip", { "is-open": open.value }, attrs.class),
        onFocusin: () => {
          open.value = true;
        },
        onFocusout: () => {
          open.value = false;
        }
      }, [
        (_a = slots.default) == null ? void 0 : _a.call(slots),
        h54("span", { class: "tooltip-panel", role: "tooltip" }, ((_b = slots.panel) == null ? void 0 : _b.call(slots)) || props.text)
      ]);
    };
  }
});

// src/vue/components/GnToolbar.js
import { defineComponent as defineComponent54, h as h55 } from "vue";
var GnToolbar_default = defineComponent54({
  name: "GnToolbar",
  props: {
    title: { type: String, default: "" },
    meta: { type: String, default: "" }
  },
  setup(props, { attrs, slots }) {
    return () => {
      var _a, _b, _c, _d;
      return h55("div", { ...attrs, class: cx("toolbar", attrs.class) }, [
        h55("div", { class: "toolbar-group" }, [
          h55("div", {}, [
            (props.title || slots.title) && h55("h3", { class: "toolbar-title" }, ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title),
            (props.meta || slots.meta) && h55("span", { class: "toolbar-meta" }, ((_b = slots.meta) == null ? void 0 : _b.call(slots)) || props.meta)
          ])
        ]),
        (slots.default || slots.actions) && h55("div", { class: "toolbar-group" }, ((_c = slots.actions) == null ? void 0 : _c.call(slots)) || ((_d = slots.default) == null ? void 0 : _d.call(slots)))
      ]);
    };
  }
});

// src/vue/components/GnToastProvider.js
import { defineComponent as defineComponent55, h as h56, provide, ref as ref12 } from "vue";

// src/vue/composables/toast-context.js
var toastKey = Symbol("gnexus-ui-kit-toast");

// src/vue/components/GnToastProvider.js
var iconByVariant = {
  info: "ph-info",
  success: "ph-check-circle",
  warning: "ph-warning",
  danger: "ph-warning-octagon",
  error: "ph-warning-octagon",
  primary: "ph-info",
  secondary: "ph-info"
};
var GnToastProvider_default = defineComponent55({
  name: "GnToastProvider",
  props: {
    lifetime: { type: Number, default: 4e3 }
  },
  setup(props, { slots, expose }) {
    const toast = ref12(null);
    const closing = ref12(false);
    let timer = null;
    let closeTimer = null;
    const dismiss = () => {
      window.clearTimeout(closeTimer);
      closing.value = true;
      closeTimer = window.setTimeout(() => {
        toast.value = null;
        closing.value = false;
        window.clearTimeout(timer);
        timer = null;
      }, 300);
    };
    const close = () => {
      window.clearTimeout(closeTimer);
      window.clearTimeout(timer);
      closing.value = false;
      toast.value = null;
    };
    const show = (options) => {
      window.clearTimeout(closeTimer);
      closing.value = false;
      const variant = normalizeVariant(options.variant || options.type || "info", "info");
      toast.value = {
        id: Date.now(),
        variant: variant === "error" ? "danger" : variant,
        title: options.title || "",
        text: options.text || options.message || "",
        icon: options.icon || iconByVariant[variant] || iconByVariant.info
      };
      window.clearTimeout(timer);
      if (options.lifetime !== 0) {
        timer = window.setTimeout(dismiss, options.lifetime || props.lifetime);
      }
    };
    const api = {
      show,
      close,
      info: (options) => show({ ...options, variant: "info" }),
      success: (options) => show({ ...options, variant: "success" }),
      warning: (options) => show({ ...options, variant: "warning" }),
      danger: (options) => show({ ...options, variant: "danger" }),
      error: (options) => show({ ...options, variant: "danger" })
    };
    provide(toastKey, api);
    expose(api);
    return () => {
      var _a;
      return [
        (_a = slots.default) == null ? void 0 : _a.call(slots),
        toast.value && h56("div", {
          class: cx("toast", closing.value ? "a-hide" : "a-show", `toast-${toast.value.variant}`),
          role: "alert"
        }, [
          h56("div", { class: "toast-content" }, [
            h56("h4", { class: "toast-title" }, [
              iconNode(toast.value.icon),
              toast.value.title
            ]),
            h56("p", { class: "toast-text" }, toast.value.text)
          ]),
          h56("button", {
            class: "btn-icon toast-close",
            type: "button",
            "aria-label": "Close",
            onClick: dismiss
          }, [iconNode("ph-x")])
        ])
      ];
    };
  }
});

// src/vue/components/GnUsageMeter.js
import { defineComponent as defineComponent56, h as h57 } from "vue";
var GnUsageMeter_default = defineComponent56({
  name: "GnUsageMeter",
  props: {
    title: { type: String, required: true },
    value: { type: Number, required: true },
    max: { type: Number, default: 100 },
    meta: { type: String, default: "" }
  },
  setup(props, { slots }) {
    return () => {
      var _a, _b;
      const percent = Math.max(0, Math.min(100, Math.round(props.value / props.max * 100)));
      return h57("section", { class: "usage-meter" }, [
        h57("h3", { class: "usage-meter-title" }, [
          ((_a = slots.title) == null ? void 0 : _a.call(slots)) || props.title,
          h57("span", { class: "usage-meter-value" }, `${percent}%`)
        ]),
        h57(GnProgress_default, { value: props.value, max: props.max }),
        (props.meta || slots.meta) && h57("p", { class: "usage-meter-meta" }, ((_b = slots.meta) == null ? void 0 : _b.call(slots)) || props.meta)
      ]);
    };
  }
});

// src/vue/composables/useToast.js
import { inject } from "vue";
function useToast() {
  const api = inject(toastKey, null);
  if (api) {
    return api;
  }
  const missingProvider = () => {
    throw new Error("GNexus UI Kit: useToast() requires <GnToastProvider> near the app root.");
  };
  return {
    show: missingProvider,
    info: missingProvider,
    success: missingProvider,
    warning: missingProvider,
    danger: missingProvider,
    error: missingProvider,
    close: missingProvider
  };
}

// src/vue/plugin.js
var components = {
  GnAccordion: GnAccordion_default,
  GnActionCard: GnActionCard_default,
  GnActionList: GnActionList_default,
  GnActivityLog: GnActivityLog_default,
  GnAlert: GnAlert_default,
  GnAvatar: GnAvatar_default,
  GnAvatarStack: GnAvatarStack_default,
  GnBadge: GnBadge_default,
  GnButton: GnButton_default,
  GnCard: GnCard_default,
  GnCheckbox: GnCheckbox_default,
  GnChip: GnChip_default,
  GnChipGroup: GnChipGroup_default,
  GnCopyButton: GnCopyButton_default,
  GnCombobox: GnCombobox_default,
  GnConfirmDialog: GnConfirmDialog_default,
  GnDescriptionList: GnDescriptionList_default,
  GnDefinitionList: GnDefinitionList_default,
  GnDropdown: GnDropdown_default,
  GnDrawer: GnDrawer_default,
  GnEmptyState: GnEmptyState_default,
  GnFileUpload: GnFileUpload_default,
  GnIconButton: GnIconButton_default,
  GnIdentity: GnIdentity_default,
  GnInput: GnInput_default,
  GnInputGroup: GnInputGroup_default,
  GnList: GnList_default,
  GnLoader: GnLoader_default,
  GnLoginCard: GnLoginCard_default,
  GnMetricCard: GnMetricCard_default,
  GnModal: GnModal_default,
  GnNavList: GnNavList_default,
  GnNavigationShell: GnNavigationShell_default,
  GnPageHeader: GnPageHeader_default,
  GnHorizontalCard: GnHorizontalCard_default,
  GnPagination: GnPagination_default,
  GnPopover: GnPopover_default,
  GnProgress: GnProgress_default,
  GnProgressStages: GnProgressStages_default,
  GnRadio: GnRadio_default,
  GnRadioGroup: GnRadioGroup_default,
  GnRange: GnRange_default,
  GnRouterTabs: GnRouterTabs_default,
  GnSearchField: GnSearchField_default,
  GnSelect: GnSelect_default,
  GnSkeleton: GnSkeleton_default,
  GnSteps: GnSteps_default,
  GnStatusCard: GnStatusCard_default,
  GnSwitch: GnCheckbox_default,
  GnTable: GnTable_default,
  GnTabs: GnTabs_default,
  GnTextarea: GnTextarea_default,
  GnTimeline: GnTimeline_default,
  GnTooltip: GnTooltip_default,
  GnToolbar: GnToolbar_default,
  GnToastProvider: GnToastProvider_default,
  GnUsageMeter: GnUsageMeter_default
};
var plugin_default = {
  install(app) {
    Object.entries(components).forEach(([name, component]) => {
      app.component(name, component);
    });
  }
};
export {
  GnAccordion_default as GnAccordion,
  GnActionCard_default as GnActionCard,
  GnActionList_default as GnActionList,
  GnActivityLog_default as GnActivityLog,
  GnAlert_default as GnAlert,
  GnAvatar_default as GnAvatar,
  GnAvatarStack_default as GnAvatarStack,
  GnBadge_default as GnBadge,
  GnButton_default as GnButton,
  GnCard_default as GnCard,
  GnCheckbox_default as GnCheckbox,
  GnChip_default as GnChip,
  GnChipGroup_default as GnChipGroup,
  GnCombobox_default as GnCombobox,
  GnConfirmDialog_default as GnConfirmDialog,
  GnCopyButton_default as GnCopyButton,
  GnDefinitionList_default as GnDefinitionList,
  GnDescriptionList_default as GnDescriptionList,
  GnDrawer_default as GnDrawer,
  GnDropdown_default as GnDropdown,
  GnEmptyState_default as GnEmptyState,
  GnFileUpload_default as GnFileUpload,
  GnHorizontalCard_default as GnHorizontalCard,
  GnIconButton_default as GnIconButton,
  GnIdentity_default as GnIdentity,
  GnInput_default as GnInput,
  GnInputGroup_default as GnInputGroup,
  GnList_default as GnList,
  GnLoader_default as GnLoader,
  GnLoginCard_default as GnLoginCard,
  GnMetricCard_default as GnMetricCard,
  GnModal_default as GnModal,
  GnNavList_default as GnNavList,
  GnNavigationShell_default as GnNavigationShell,
  GnPageHeader_default as GnPageHeader,
  GnPagination_default as GnPagination,
  GnPopover_default as GnPopover,
  GnProgress_default as GnProgress,
  GnProgressStages_default as GnProgressStages,
  GnRadio_default as GnRadio,
  GnRadioGroup_default as GnRadioGroup,
  GnRange_default as GnRange,
  GnRouterTabs_default as GnRouterTabs,
  GnSearchField_default as GnSearchField,
  GnSelect_default as GnSelect,
  GnSkeleton_default as GnSkeleton,
  GnStatusCard_default as GnStatusCard,
  GnSteps_default as GnSteps,
  GnCheckbox_default as GnSwitch,
  GnTable_default as GnTable,
  GnTabs_default as GnTabs,
  GnTextarea_default as GnTextarea,
  GnTimeline_default as GnTimeline,
  GnToastProvider_default as GnToastProvider,
  GnToolbar_default as GnToolbar,
  GnTooltip_default as GnTooltip,
  GnUsageMeter_default as GnUsageMeter,
  plugin_default as GnexusUiVue,
  components,
  isRouteActive,
  tryUseRoute,
  tryUseRouter,
  useToast
};
//# sourceMappingURL=index.js.map
