import { n as __exportAll } from "./chunk-B-1-B7_t.js";
import { n as Button_default } from "./button-B9CnnuTu.js";
import { o as CardContent_default, s as Card_default } from "./card-X74FuL7B.js";
import { n as DialogTitle_default, o as DialogContent_default, r as DialogHeader_default, t as DialogTrigger_default, u as Dialog_default } from "./dialog-BGzW4Eil.js";
import { t as Input_default } from "./input-CwDp-vE8.js";
import { t as Skeleton_default } from "./skeleton-9Qm1V-Ys.js";
import { t as FieldFrame_default } from "./field-frame-DhCOWcMP.js";
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, normalizeClass, openBlock, ref, renderList, toDisplayString, unref, useModel, withCtx } from "vue";
import { ImageIcon, Loader2, Upload, X } from "@lucide/vue";
//#region src/components/compositions/elements/file/AssetPickerFile.vue?vue&type=script&setup=true&lang.ts
var _hoisted_1 = ["data-element-name"];
var _hoisted_2 = ["src", "alt"];
var _hoisted_3 = { class: "flex-1 truncate text-sm" };
var _hoisted_4 = { class: "flex items-center gap-2" };
var _hoisted_5 = ["accept"];
var _hoisted_6 = {
	key: 0,
	class: "grid grid-cols-3 gap-3",
	"data-testid": "asset-picker-skeleton"
};
var _hoisted_7 = {
	key: 1,
	class: "py-8 text-center text-sm text-muted-foreground",
	"data-testid": "asset-picker-empty"
};
var _hoisted_8 = {
	key: 2,
	class: "grid max-h-96 grid-cols-3 gap-3 overflow-y-auto",
	"data-testid": "asset-picker-grid"
};
var _hoisted_9 = ["data-testid", "onClick"];
var _hoisted_10 = { class: "flex aspect-square items-center justify-center bg-muted" };
var _hoisted_11 = ["src", "alt"];
var _hoisted_12 = { class: "truncate p-2 text-xs" };
var AssetPickerFile_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
	__name: "AssetPickerFile",
	props: /* @__PURE__ */ mergeModels({
		modelValue: {},
		id: {},
		name: {},
		label: {},
		hideLabel: { type: Boolean },
		required: { type: Boolean },
		readonly: { type: Boolean },
		disabled: { type: Boolean },
		helpText: {},
		errors: { default: () => [] },
		onBrowse: {},
		onUpload: {},
		acceptedFileTypes: { default: () => [] }
	}, {
		"modelValue": {},
		"modelModifiers": {}
	}),
	emits: ["update:modelValue"],
	setup(__props) {
		/**
		* Props-driven asset-picker composition. The consumer supplies
		* Promise-returning `onBrowse` (and optional `onUpload`) callbacks; the
		* composition itself never makes HTTP calls.
		*
		*   <AssetPickerFile
		*     v-model="asset"
		*     label="Hero image"
		*     :on-browse="() => api.assets.list()"
		*     :on-upload="(file) => api.assets.upload(file)"
		*   />
		*/
		const props = __props;
		const model = useModel(__props, "modelValue");
		const open = ref(false);
		const isLoading = ref(false);
		const isUploading = ref(false);
		const assets = ref([]);
		const filter = ref("");
		const fileInput = ref(null);
		let browseToken = 0;
		const selectedAsset = computed(() => {
			const raw = model.value;
			if (!raw) return null;
			if (typeof raw === "string") return {
				id: raw,
				url: raw,
				name: raw
			};
			if (typeof raw === "object") {
				const obj = raw;
				return {
					id: obj.id ?? "",
					url: obj.url ?? "",
					name: obj.name,
					thumbnailUrl: obj.thumbnailUrl
				};
			}
			return null;
		});
		const acceptAttr = computed(() => {
			if (!props.acceptedFileTypes?.length) return;
			return props.acceptedFileTypes.join(",");
		});
		const filteredAssets = computed(() => {
			const q = filter.value.trim().toLowerCase();
			if (!q) return assets.value;
			return assets.value.filter((a) => (a.name ?? a.id).toLowerCase().includes(q));
		});
		async function loadAssets() {
			if (!props.onBrowse) {
				assets.value = [];
				return;
			}
			const myToken = ++browseToken;
			isLoading.value = true;
			try {
				const next = await props.onBrowse();
				if (myToken !== browseToken) return;
				assets.value = Array.isArray(next) ? next : [];
			} catch {
				if (myToken !== browseToken) return;
				assets.value = [];
			} finally {
				if (myToken === browseToken) isLoading.value = false;
			}
		}
		function onOpenChange(next) {
			open.value = next;
			if (next) {
				filter.value = "";
				loadAssets();
			}
		}
		function selectAsset(asset) {
			model.value = asset;
			open.value = false;
		}
		function clearAsset() {
			model.value = null;
		}
		function openUploadPicker() {
			fileInput.value?.click();
		}
		async function onUploadChange(event) {
			const target = event.target;
			const file = target.files?.[0];
			target.value = "";
			if (!file || !props.onUpload) return;
			isUploading.value = true;
			try {
				const asset = await props.onUpload(file);
				if (asset) {
					model.value = asset;
					open.value = false;
				}
			} catch {} finally {
				isUploading.value = false;
			}
		}
		return (_ctx, _cache) => {
			return openBlock(), createBlock(unref(FieldFrame_default), {
				label: __props.label,
				required: __props.required,
				"hide-label": __props.hideLabel,
				for: __props.id,
				"help-text": __props.helpText,
				errors: __props.errors
			}, {
				default: withCtx(() => [createElementVNode("div", {
					"data-element-name": __props.name ?? void 0,
					"data-testid": "asset-picker"
				}, [selectedAsset.value ? (openBlock(), createBlock(unref(Card_default), {
					key: 0,
					"data-testid": "asset-picker-chip"
				}, {
					default: withCtx(() => [createVNode(unref(CardContent_default), { class: "flex items-center gap-3 py-3" }, {
						default: withCtx(() => [
							selectedAsset.value.thumbnailUrl || selectedAsset.value.url ? (openBlock(), createElementBlock("img", {
								key: 0,
								src: selectedAsset.value.thumbnailUrl ?? selectedAsset.value.url,
								alt: selectedAsset.value.name ?? "Selected asset",
								class: "size-10 rounded object-cover",
								"data-testid": "asset-picker-chip-thumb"
							}, null, 8, _hoisted_2)) : (openBlock(), createBlock(unref(ImageIcon), {
								key: 1,
								class: "size-5 text-muted-foreground"
							})),
							createElementVNode("span", _hoisted_3, toDisplayString(selectedAsset.value.name ?? selectedAsset.value.id ?? "Selected asset"), 1),
							createVNode(unref(Button_default), {
								type: "button",
								variant: "ghost",
								size: "icon-sm",
								"aria-label": "Remove asset",
								disabled: __props.disabled || __props.readonly,
								"data-testid": "asset-picker-remove",
								onClick: clearAsset
							}, {
								default: withCtx(() => [createVNode(unref(X), { class: "size-4" })]),
								_: 1
							}, 8, ["disabled"])
						]),
						_: 1
					})]),
					_: 1
				})) : createCommentVNode("", true), createVNode(unref(Dialog_default), {
					open: open.value,
					"onUpdate:open": onOpenChange
				}, {
					default: withCtx(() => [createVNode(unref(DialogTrigger_default), { "as-child": "" }, {
						default: withCtx(() => [createVNode(unref(Button_default), {
							type: "button",
							variant: "outline",
							disabled: __props.disabled || __props.readonly,
							class: normalizeClass(selectedAsset.value ? "mt-2" : ""),
							"data-testid": "asset-picker-browse"
						}, {
							default: withCtx(() => [createVNode(unref(ImageIcon), { class: "mr-2 size-4" }), createTextVNode(" " + toDisplayString(selectedAsset.value ? "Change…" : "Browse…"), 1)]),
							_: 1
						}, 8, ["disabled", "class"])]),
						_: 1
					}), createVNode(unref(DialogContent_default), { class: "sm:max-w-2xl" }, {
						default: withCtx(() => [
							createVNode(unref(DialogHeader_default), null, {
								default: withCtx(() => [createVNode(unref(DialogTitle_default), null, {
									default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode("Select an asset", -1)])]),
									_: 1
								})]),
								_: 1
							}),
							createElementVNode("div", _hoisted_4, [
								createVNode(unref(Input_default), {
									modelValue: filter.value,
									"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => filter.value = $event),
									placeholder: "Search assets…",
									"data-testid": "asset-picker-search"
								}, null, 8, ["modelValue"]),
								__props.onUpload ? (openBlock(), createBlock(unref(Button_default), {
									key: 0,
									type: "button",
									variant: "outline",
									disabled: isUploading.value,
									"data-testid": "asset-picker-upload",
									onClick: openUploadPicker
								}, {
									default: withCtx(() => [isUploading.value ? (openBlock(), createBlock(unref(Loader2), {
										key: 0,
										class: "mr-2 size-4 animate-spin"
									})) : (openBlock(), createBlock(unref(Upload), {
										key: 1,
										class: "mr-2 size-4"
									})), _cache[2] || (_cache[2] = createTextVNode(" Upload new ", -1))]),
									_: 1
								}, 8, ["disabled"])) : createCommentVNode("", true),
								__props.onUpload ? (openBlock(), createElementBlock("input", {
									key: 1,
									ref_key: "fileInput",
									ref: fileInput,
									type: "file",
									class: "sr-only",
									accept: acceptAttr.value,
									"data-testid": "asset-picker-upload-input",
									onChange: onUploadChange
								}, null, 40, _hoisted_5)) : createCommentVNode("", true)
							]),
							isLoading.value ? (openBlock(), createElementBlock("div", _hoisted_6, [(openBlock(), createElementBlock(Fragment, null, renderList(6, (i) => {
								return createVNode(unref(Skeleton_default), {
									key: i,
									class: "aspect-square w-full"
								});
							}), 64))])) : filteredAssets.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_7, " No assets available. ")) : (openBlock(), createElementBlock("div", _hoisted_8, [(openBlock(true), createElementBlock(Fragment, null, renderList(filteredAssets.value, (asset) => {
								return openBlock(), createElementBlock("button", {
									key: asset.id,
									type: "button",
									class: "flex flex-col items-stretch overflow-hidden rounded-md border bg-card text-left hover:border-primary focus:outline-none focus:ring-2 focus:ring-ring",
									"data-testid": `asset-picker-item-${asset.id}`,
									onClick: ($event) => selectAsset(asset)
								}, [createElementVNode("div", _hoisted_10, [asset.thumbnailUrl || asset.url ? (openBlock(), createElementBlock("img", {
									key: 0,
									src: asset.thumbnailUrl ?? asset.url,
									alt: asset.name ?? asset.id,
									class: "size-full object-cover"
								}, null, 8, _hoisted_11)) : (openBlock(), createBlock(unref(ImageIcon), {
									key: 1,
									class: "size-8 text-muted-foreground"
								}))]), createElementVNode("div", _hoisted_12, toDisplayString(asset.name ?? asset.id), 1)], 8, _hoisted_9);
							}), 128))]))
						]),
						_: 1
					})]),
					_: 1
				}, 8, ["open"])], 8, _hoisted_1)]),
				_: 1
			}, 8, [
				"label",
				"required",
				"hide-label",
				"for",
				"help-text",
				"errors"
			]);
		};
	}
});
//#endregion
//#region src/components/compositions/elements/file/AssetPickerFile.vue
var AssetPickerFile_exports = /* @__PURE__ */ __exportAll({ default: () => AssetPickerFile_default });
var AssetPickerFile_default = AssetPickerFile_vue_vue_type_script_setup_true_lang_default;
//#endregion
export { AssetPickerFile_exports as n, AssetPickerFile_default as t };

//# sourceMappingURL=AssetPickerFile-dH5cK_xm.js.map