import { n as __exportAll } from "./chunk-B-1-B7_t.js";
import { n as cn } from "./utils-DXzSsU1e.js";
import { i as Avatar_default, n as AvatarImage_default, r as AvatarFallback_default } from "./avatar-DlTHFl6x.js";
import { n as Badge_default } from "./badge-BbQrSqE-.js";
import { n as CardTitle_default, o as CardContent_default, r as CardHeader_default, s as Card_default } from "./card-X74FuL7B.js";
import { t as Input_default } from "./input-CwDp-vE8.js";
import { t as Skeleton_default } from "./skeleton-9Qm1V-Ys.js";
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, onMounted, openBlock, ref, renderList, resolveDynamicComponent, toDisplayString, unref, watch, withCtx } from "vue";
import { ArrowRight, GitMerge, GitPullRequest, GitPullRequestDraft, Search, XCircle } from "@lucide/vue";
//#region src/components/compositions/elements/code/PullRequestsList.vue?vue&type=script&setup=true&lang.ts
var _hoisted_1 = { class: "flex flex-wrap items-center gap-2" };
var _hoisted_2 = { class: "flex flex-wrap items-center gap-1" };
var _hoisted_3 = [
	"data-testid",
	"aria-pressed",
	"onClick"
];
var _hoisted_4 = { class: "relative flex-1 min-w-48" };
var _hoisted_5 = {
	key: 0,
	class: "text-sm text-muted-foreground",
	"data-testid": "pull-requests-list-help"
};
var _hoisted_6 = {
	key: 0,
	class: "flex flex-col gap-2 px-2 py-2",
	"data-testid": "pull-requests-list-loading"
};
var _hoisted_7 = {
	key: 1,
	class: "px-2 py-2 text-sm text-destructive",
	"data-testid": "pull-requests-list-error",
	role: "alert"
};
var _hoisted_8 = {
	key: 2,
	class: "px-2 py-4 text-center text-sm text-muted-foreground",
	"data-testid": "pull-requests-list-empty"
};
var _hoisted_9 = {
	key: 3,
	class: "flex flex-col",
	role: "list",
	"data-testid": "pull-requests-list-rows"
};
var _hoisted_10 = [
	"data-testid",
	"aria-selected",
	"onClick"
];
var _hoisted_11 = { class: "flex min-w-0 flex-1 flex-col gap-0.5" };
var _hoisted_12 = { class: "flex items-center gap-2" };
var _hoisted_13 = { class: "truncate text-sm font-medium" };
var _hoisted_14 = {
	key: 0,
	class: "text-xs text-muted-foreground"
};
var _hoisted_15 = { class: "flex flex-wrap items-center gap-2 text-xs text-muted-foreground" };
var _hoisted_16 = {
	key: 0,
	class: "flex items-center gap-1.5"
};
var _hoisted_17 = {
	key: 1,
	class: "flex items-center gap-1"
};
var _hoisted_18 = {
	key: 0,
	class: "font-mono"
};
var _hoisted_19 = {
	key: 2,
	class: "font-mono"
};
var _hoisted_20 = { key: 2 };
var _hoisted_21 = {
	key: 4,
	class: "px-2 pt-2 text-sm text-destructive",
	"data-testid": "pull-requests-list-errors",
	role: "alert"
};
var PullRequestsList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
	__name: "PullRequestsList",
	props: {
		onLoadPullRequests: {},
		defaultFilter: {},
		selectedId: {},
		onSelect: {},
		label: { default: "Pull Requests" },
		name: {},
		helpText: {},
		errors: { default: () => [] },
		classList: {}
	},
	emits: ["update:selectedId"],
	setup(__props, { expose: __expose, emit: __emit }) {
		/**
		* Props-driven pull-request list composition. Renders a toolbar with
		* status-filter chips + a search input, then a list of PR rows. The
		* composition makes no HTTP calls — the consumer supplies a single
		* Promise-returning `onLoadPullRequests` callback that receives the
		* current filter object.
		*
		*   <PullRequestsList
		*     :on-load-pull-requests="(f) => fetch(`/api/prs?...`).then(r => r.json())"
		*     v-model:selected-id="selectedPr"
		*     @select="(pr) => router.push(pr.url)"
		*   />
		*/
		const props = __props;
		const emit = __emit;
		const status = ref(props.defaultFilter?.status ?? "all");
		const query = ref(props.defaultFilter?.query ?? "");
		const items = ref([]);
		const loading = ref(false);
		const error = ref(null);
		let token = 0;
		const STATUS_CHIPS = [
			{
				value: "all",
				label: "All"
			},
			{
				value: "open",
				label: "Open"
			},
			{
				value: "draft",
				label: "Draft"
			},
			{
				value: "merged",
				label: "Merged"
			},
			{
				value: "closed",
				label: "Closed"
			}
		];
		function statusVariant(s) {
			switch (s) {
				case "open": return "success";
				case "merged": return "info";
				case "closed": return "destructive";
				default: return "secondary";
			}
		}
		function statusIcon(s) {
			if (s === "merged") return GitMerge;
			if (s === "closed") return XCircle;
			if (s === "draft") return GitPullRequestDraft;
			return GitPullRequest;
		}
		function relativeTime(value) {
			if (!value) return "";
			const d = value instanceof Date ? value : new Date(value);
			const diff = Date.now() - d.getTime();
			if (Number.isNaN(diff)) return "";
			const sec = Math.round(diff / 1e3);
			if (sec < 60) return `${sec}s ago`;
			const min = Math.round(sec / 60);
			if (min < 60) return `${min}m ago`;
			const hr = Math.round(min / 60);
			if (hr < 24) return `${hr}h ago`;
			const day = Math.round(hr / 24);
			if (day < 30) return `${day}d ago`;
			const month = Math.round(day / 30);
			if (month < 12) return `${month}mo ago`;
			return `${Math.round(month / 12)}y ago`;
		}
		function currentFilter() {
			const f = {};
			if (status.value !== "all") f.status = status.value;
			if (query.value) f.query = query.value;
			return f;
		}
		async function reload() {
			const myToken = ++token;
			loading.value = true;
			error.value = null;
			try {
				const next = await props.onLoadPullRequests(currentFilter());
				if (myToken !== token) return;
				items.value = Array.isArray(next) ? next : [];
			} catch (err) {
				if (myToken !== token) return;
				error.value = err instanceof Error ? err.message : String(err);
				items.value = [];
			} finally {
				if (myToken === token) loading.value = false;
			}
		}
		let debounceTimer = null;
		function scheduleReload() {
			if (debounceTimer !== null) clearTimeout(debounceTimer);
			debounceTimer = setTimeout(() => {
				debounceTimer = null;
				reload();
			}, 200);
		}
		function setStatus(next) {
			if (status.value === next) return;
			status.value = next;
			reload();
		}
		function onQueryInput(e) {
			query.value = e.target.value;
			scheduleReload();
		}
		function selectRow(pr) {
			emit("update:selectedId", pr.id);
			if (props.onSelect) props.onSelect(pr);
		}
		function authorFallback(name) {
			if (!name) return "?";
			return name.split(/\s+/).filter(Boolean).slice(0, 2).map((s) => s[0]?.toUpperCase() ?? "").join("");
		}
		const selectedIdRef = computed(() => props.selectedId);
		onMounted(() => {
			reload();
		});
		watch(() => props.defaultFilter, (next) => {
			if (!next) return;
			status.value = next.status ?? "all";
			query.value = next.query ?? "";
			reload();
		}, { deep: true });
		__expose({ reload });
		return (_ctx, _cache) => {
			return openBlock(), createBlock(unref(Card_default), {
				class: normalizeClass(unref(cn)(props.classList)),
				"data-element-name": props.name ?? void 0,
				"data-testid": "pull-requests-list"
			}, {
				default: withCtx(() => [createVNode(unref(CardHeader_default), { class: "flex flex-col gap-3 pb-3" }, {
					default: withCtx(() => [
						createVNode(unref(CardTitle_default), { class: "flex items-center gap-2 text-base" }, {
							default: withCtx(() => [createVNode(unref(GitPullRequest), { class: "size-5 text-muted-foreground" }), createElementVNode("span", null, toDisplayString(props.label), 1)]),
							_: 1
						}),
						createElementVNode("div", _hoisted_1, [createElementVNode("div", _hoisted_2, [(openBlock(), createElementBlock(Fragment, null, renderList(STATUS_CHIPS, (chip) => {
							return createElementVNode("button", {
								key: chip.value,
								type: "button",
								class: normalizeClass(unref(cn)("rounded-full border px-3 py-1 text-xs font-medium transition-colors", status.value === chip.value ? "border-primary bg-primary text-primary-foreground" : "border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground")),
								"data-testid": `pull-requests-list-chip-${chip.value}`,
								"aria-pressed": status.value === chip.value,
								onClick: ($event) => setStatus(chip.value)
							}, toDisplayString(chip.label), 11, _hoisted_3);
						}), 64))]), createElementVNode("div", _hoisted_4, [createVNode(unref(Search), { class: "absolute left-2 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" }), createVNode(unref(Input_default), {
							"model-value": query.value,
							placeholder: "Search…",
							class: "pl-8",
							"data-testid": "pull-requests-list-search",
							onInput: onQueryInput
						}, null, 8, ["model-value"])])]),
						props.helpText ? (openBlock(), createElementBlock("p", _hoisted_5, toDisplayString(props.helpText), 1)) : createCommentVNode("", true)
					]),
					_: 1
				}), createVNode(unref(CardContent_default), { class: "flex flex-col gap-1 p-2" }, {
					default: withCtx(() => [loading.value ? (openBlock(), createElementBlock("div", _hoisted_6, [
						createVNode(unref(Skeleton_default), { class: "h-12 w-full" }),
						createVNode(unref(Skeleton_default), { class: "h-12 w-full" }),
						createVNode(unref(Skeleton_default), { class: "h-12 w-full" })
					])) : error.value ? (openBlock(), createElementBlock("p", _hoisted_7, toDisplayString(error.value), 1)) : items.value.length === 0 ? (openBlock(), createElementBlock("p", _hoisted_8, " No pull requests. ")) : (openBlock(), createElementBlock("ul", _hoisted_9, [(openBlock(true), createElementBlock(Fragment, null, renderList(items.value, (pr) => {
						return openBlock(), createElementBlock("li", {
							key: pr.id,
							class: normalizeClass(unref(cn)("flex cursor-pointer items-center gap-3 rounded-md border border-transparent px-2 py-2 hover:bg-accent", selectedIdRef.value === pr.id ? "border-primary bg-accent" : "")),
							"data-testid": `pull-requests-list-row-${pr.id}`,
							"aria-selected": selectedIdRef.value === pr.id,
							onClick: ($event) => selectRow(pr)
						}, [
							(openBlock(), createBlock(resolveDynamicComponent(statusIcon(pr.status)), { class: "size-4 shrink-0 text-muted-foreground" })),
							createElementVNode("div", _hoisted_11, [createElementVNode("div", _hoisted_12, [
								createElementVNode("span", _hoisted_13, toDisplayString(pr.title), 1),
								pr.number !== void 0 ? (openBlock(), createElementBlock("span", _hoisted_14, " #" + toDisplayString(pr.number), 1)) : createCommentVNode("", true),
								createVNode(unref(Badge_default), {
									variant: statusVariant(pr.status),
									size: "sm",
									class: "capitalize"
								}, {
									default: withCtx(() => [createTextVNode(toDisplayString(pr.status), 1)]),
									_: 2
								}, 1032, ["variant"])
							]), createElementVNode("div", _hoisted_15, [
								pr.authorName ? (openBlock(), createElementBlock("span", _hoisted_16, [createVNode(unref(Avatar_default), {
									size: "sm",
									class: "size-5 text-[10px]"
								}, {
									default: withCtx(() => [pr.authorAvatarUrl ? (openBlock(), createBlock(unref(AvatarImage_default), {
										key: 0,
										src: pr.authorAvatarUrl,
										alt: pr.authorName
									}, null, 8, ["src", "alt"])) : createCommentVNode("", true), createVNode(unref(AvatarFallback_default), null, {
										default: withCtx(() => [createTextVNode(toDisplayString(authorFallback(pr.authorName)), 1)]),
										_: 2
									}, 1024)]),
									_: 2
								}, 1024), createElementVNode("span", null, toDisplayString(pr.authorName), 1)])) : createCommentVNode("", true),
								pr.branchName || pr.targetBranch ? (openBlock(), createElementBlock("span", _hoisted_17, [
									pr.branchName ? (openBlock(), createElementBlock("span", _hoisted_18, toDisplayString(pr.branchName), 1)) : createCommentVNode("", true),
									pr.branchName && pr.targetBranch ? (openBlock(), createBlock(unref(ArrowRight), {
										key: 1,
										class: "size-3"
									})) : createCommentVNode("", true),
									pr.targetBranch ? (openBlock(), createElementBlock("span", _hoisted_19, toDisplayString(pr.targetBranch), 1)) : createCommentVNode("", true)
								])) : createCommentVNode("", true),
								pr.updatedAt || pr.createdAt ? (openBlock(), createElementBlock("span", _hoisted_20, toDisplayString(relativeTime(pr.updatedAt ?? pr.createdAt)), 1)) : createCommentVNode("", true)
							])]),
							createCommentVNode("", true)
						], 10, _hoisted_10);
					}), 128))])), props.errors.length ? (openBlock(), createElementBlock("ul", _hoisted_21, [(openBlock(true), createElementBlock(Fragment, null, renderList(props.errors, (err, i) => {
						return openBlock(), createElementBlock("li", { key: i }, toDisplayString(err), 1);
					}), 128))])) : createCommentVNode("", true)]),
					_: 1
				})]),
				_: 1
			}, 8, ["class", "data-element-name"]);
		};
	}
});
//#endregion
//#region src/components/compositions/elements/code/PullRequestsList.vue
var PullRequestsList_exports = /* @__PURE__ */ __exportAll({ default: () => PullRequestsList_default });
var PullRequestsList_default = PullRequestsList_vue_vue_type_script_setup_true_lang_default;
//#endregion
export { PullRequestsList_exports as n, PullRequestsList_default as t };

//# sourceMappingURL=PullRequestsList-Bns4Zqba.js.map