import { n as __exportAll } from "./chunk-B-1-B7_t.js";
import { n as cn } from "./utils-DXzSsU1e.js";
import { n as Badge_default } from "./badge-BbQrSqE-.js";
import { n as Button_default } from "./button-B9CnnuTu.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 { n as Label_default } from "./label-C5K3zowH.js";
import { l as SelectContent_default, n as SelectTrigger_default, s as SelectItem_default, t as SelectValue_default, u as Select_default } from "./select-Dwoxq29k.js";
import { r as Switch_default } from "./switch-E1QdwZg_.js";
import { t as Textarea_default } from "./textarea-Bi7Nstc4.js";
import { a as useObjectBuilder, i as toRecord, r as recordToSchema } from "./objectBuilderStore-DLGsjOjW.js";
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, normalizeClass, onMounted, openBlock, ref, renderList, toDisplayString, unref, useModel, watch, withCtx } from "vue";
import { ArrowDown, ArrowUp, Plus, Trash2, X } from "@lucide/vue";
//#region src/components/compositions/elements/builder/ObjectBuilder.vue?vue&type=script&setup=true&lang.ts
var _hoisted_1 = ["data-element-name"];
var _hoisted_2 = {
	class: "flex flex-col gap-2 border-r p-3 overflow-y-auto",
	"data-testid": "object-builder-palette"
};
var _hoisted_3 = { class: "text-xs font-semibold uppercase tracking-wide text-muted-foreground" };
var _hoisted_4 = { class: "flex flex-col gap-1" };
var _hoisted_5 = ["data-testid", "onClick"];
var _hoisted_6 = { class: "flex min-w-0 flex-col gap-0.5" };
var _hoisted_7 = { class: "font-medium" };
var _hoisted_8 = { class: "line-clamp-2 text-[10px] text-muted-foreground" };
var _hoisted_9 = {
	class: "flex flex-col gap-3 overflow-y-auto p-3",
	"data-testid": "object-builder-canvas"
};
var _hoisted_10 = { class: "flex items-center justify-between" };
var _hoisted_11 = {
	key: 0,
	class: "rounded-md border border-dashed bg-background py-6 text-center text-xs text-muted-foreground",
	"data-testid": "object-builder-canvas-empty"
};
var _hoisted_12 = {
	key: 1,
	class: "flex flex-col gap-1 text-xs",
	"data-testid": "object-builder-canvas-list"
};
var _hoisted_13 = ["data-testid", "onClick"];
var _hoisted_14 = { class: "w-6 text-right tabular-nums text-muted-foreground" };
var _hoisted_15 = { class: "font-medium" };
var _hoisted_16 = { class: "ml-auto max-w-[12rem] truncate font-mono text-[10px] text-muted-foreground" };
var _hoisted_17 = {
	class: "flex flex-col gap-2 overflow-y-auto border-l p-3",
	"data-testid": "object-builder-inspector"
};
var _hoisted_18 = { class: "flex items-center justify-between" };
var _hoisted_19 = {
	key: 0,
	class: "py-3 text-xs text-muted-foreground",
	"data-testid": "object-builder-inspector-empty"
};
var _hoisted_20 = {
	key: 1,
	class: "flex flex-col gap-3",
	"data-testid": "object-builder-inspector-fields"
};
var _hoisted_21 = { class: "flex flex-col gap-1" };
var _hoisted_22 = { class: "flex flex-col gap-1" };
var _hoisted_23 = {
	key: 0,
	class: "flex flex-col gap-1"
};
var _hoisted_24 = {
	key: 1,
	class: "flex flex-col gap-1"
};
var _hoisted_25 = {
	key: 2,
	class: "flex items-center justify-between rounded border bg-background px-2 py-1"
};
var _hoisted_26 = {
	key: 3,
	class: "flex flex-col gap-1"
};
var _hoisted_27 = {
	key: 0,
	class: "text-[11px] text-destructive",
	"data-testid": "object-builder-inspector-value-json-error"
};
var _hoisted_28 = {
	key: 4,
	class: "rounded border bg-background px-2 py-1 text-xs text-muted-foreground",
	"data-testid": "object-builder-inspector-value-null"
};
var _hoisted_29 = { class: "flex items-center gap-1" };
var ObjectBuilder_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
	__name: "ObjectBuilder",
	props: /* @__PURE__ */ mergeModels({
		modelValue: {},
		builderId: {},
		label: { default: "Object Builder" },
		name: {},
		classList: {}
	}, {
		"modelValue": {},
		"modelModifiers": {}
	}),
	emits: ["update:modelValue"],
	setup(__props, { expose: __expose }) {
		/**
		* ObjectBuilder — visually compose a JSON object as a list of typed
		* key / value entries.
		*
		* Three-pane layout:
		*   - LEFT  (Palette):    Buttons for each entry type
		*                         (string / number / boolean / array / object /
		*                         null). Clicking appends a new entry of that
		*                         type.
		*   - MIDDLE (Canvas):    Ordered list of entries. Each row shows the
		*                         key, a type badge, and a value preview.
		*                         Click to select.
		*   - RIGHT (Inspector):  Edits the selected entry's key, type, and
		*                         value. The editor swaps based on `type`.
		*
		* The schema is owned by `objectBuilderStore`. The builder accepts an
		* initial value via `modelValue` (either an `ObjectBuilderSchema` or a
		* plain `Record<string, unknown>`) and emits the current schema
		* through `update:modelValue` on every mutation.
		*/
		const props = __props;
		const model = useModel(__props, "modelValue");
		let nextAutoId = 0;
		function makeAutoId() {
			nextAutoId += 1;
			return `object-builder-${Date.now()}-${nextAutoId}`;
		}
		const fallbackId = ref(makeAutoId());
		const builder = useObjectBuilder(computed(() => props.builderId ?? fallbackId.value).value);
		const PALETTE_TYPES = [
			{
				type: "string",
				displayLabel: "String",
				description: "A text value."
			},
			{
				type: "number",
				displayLabel: "Number",
				description: "A numeric value."
			},
			{
				type: "boolean",
				displayLabel: "Boolean",
				description: "true or false."
			},
			{
				type: "array",
				displayLabel: "Array",
				description: "A JSON array (edit as JSON)."
			},
			{
				type: "object",
				displayLabel: "Object",
				description: "A nested object (edit as JSON)."
			},
			{
				type: "null",
				displayLabel: "Null",
				description: "Explicit null."
			}
		];
		function isObjectBuilderSchema(value) {
			if (typeof value !== "object" || value === null) return false;
			const v = value;
			return Array.isArray(v.entries);
		}
		/** Seed the store from the initial modelValue. */
		onMounted(() => {
			const seed = model.value;
			if (seed === void 0 || seed === null) return;
			if (isObjectBuilderSchema(seed)) builder.loadSchema(seed);
			else if (typeof seed === "object") builder.loadSchema(recordToSchema(seed));
		});
		/** Push schema changes back via v-model. */
		watch(() => builder.schema.value, (next) => {
			model.value = { entries: next.entries.map((e) => ({ ...e })) };
		}, { deep: true });
		const entries = computed(() => builder.schema.value.entries);
		const selectedEntry = computed(() => {
			const sel = builder.selection.value;
			if (!sel.id) return null;
			return entries.value.find((e) => e.id === sel.id) ?? null;
		});
		const selectedIndex = computed(() => {
			const sel = builder.selection.value;
			if (!sel.id) return -1;
			return entries.value.findIndex((e) => e.id === sel.id);
		});
		const canMoveDown = computed(() => {
			return selectedIndex.value >= 0 && selectedIndex.value < entries.value.length - 1;
		});
		function onPaletteClick(type) {
			const newId = builder.addEntry(type);
			builder.select(newId);
		}
		function onRowClick(entryId) {
			builder.select(entryId);
		}
		function onMoveUp() {
			if (selectedIndex.value <= 0) return;
			builder.reorderEntry(selectedIndex.value, selectedIndex.value - 1);
		}
		function onMoveDown() {
			if (!canMoveDown.value) return;
			builder.reorderEntry(selectedIndex.value, selectedIndex.value + 1);
		}
		function onRemove() {
			const sel = builder.selection.value;
			if (sel.id) builder.removeEntry(sel.id);
		}
		function onClearSelection() {
			builder.select(null);
		}
		function patchSelected(patch) {
			const sel = builder.selection.value;
			if (sel.id) builder.updateEntry(sel.id, patch);
		}
		function previewValue(entry) {
			switch (entry.type) {
				case "null": return "null";
				case "boolean": return entry.value ? "true" : "false";
				case "string": return entry.value === "" ? "\"\"" : String(entry.value);
				case "number": return String(entry.value);
				case "array":
				case "object": try {
					return JSON.stringify(entry.value);
				} catch {
					return "(invalid)";
				}
			}
		}
		const keyValue = computed(() => selectedEntry.value?.key ?? "");
		const stringValue = computed(() => selectedEntry.value && selectedEntry.value.type === "string" ? String(selectedEntry.value.value ?? "") : "");
		const numberValue = computed(() => selectedEntry.value && selectedEntry.value.type === "number" ? String(selectedEntry.value.value ?? 0) : "");
		const booleanValue = computed(() => selectedEntry.value && selectedEntry.value.type === "boolean" ? Boolean(selectedEntry.value.value) : false);
		const jsonDraft = ref("");
		const jsonError = ref("");
		watch(() => selectedEntry.value, (next) => {
			if (!next) {
				jsonDraft.value = "";
				jsonError.value = "";
				return;
			}
			if (next.type === "array" || next.type === "object") {
				try {
					jsonDraft.value = JSON.stringify(next.value, null, 2);
				} catch {
					jsonDraft.value = "";
				}
				jsonError.value = "";
			}
		}, { immediate: true });
		function onJsonInput(raw) {
			jsonDraft.value = raw;
			try {
				const parsed = JSON.parse(raw);
				const entry = selectedEntry.value;
				if (!entry) return;
				if (entry.type === "array" && !Array.isArray(parsed)) {
					jsonError.value = "Value must be a JSON array.";
					return;
				}
				if (entry.type === "object" && (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))) {
					jsonError.value = "Value must be a JSON object.";
					return;
				}
				jsonError.value = "";
				patchSelected({ value: parsed });
			} catch (err) {
				jsonError.value = err instanceof Error ? err.message : "Invalid JSON.";
			}
		}
		function onTypeChange(next) {
			patchSelected({ type: next });
		}
		/** Re-export the flattening helper so consumers can `toRecord(schema)`. */
		__expose({ toRecord });
		return (_ctx, _cache) => {
			return openBlock(), createElementBlock("div", {
				class: normalizeClass(unref(cn)("gxp-object-builder grid gap-3 rounded-lg border bg-card", props.classList)),
				style: {
					"grid-template-columns": "200px 1fr 300px",
					"min-height": "22rem"
				},
				"data-testid": "object-builder",
				"data-element-name": props.name ?? void 0
			}, [
				createElementVNode("aside", _hoisted_2, [createElementVNode("h4", _hoisted_3, toDisplayString(props.label), 1), createElementVNode("div", _hoisted_4, [(openBlock(), createElementBlock(Fragment, null, renderList(PALETTE_TYPES, (entry) => {
					return createElementVNode("button", {
						key: entry.type,
						type: "button",
						class: "flex items-start gap-2 rounded-md border bg-background px-2 py-1.5 text-left text-xs transition-colors hover:border-primary hover:bg-accent/40",
						"data-testid": `object-builder-palette-${entry.type}`,
						onClick: ($event) => onPaletteClick(entry.type)
					}, [createVNode(unref(Plus), { class: "mt-0.5 h-3.5 w-3.5 shrink-0" }), createElementVNode("span", _hoisted_6, [createElementVNode("span", _hoisted_7, toDisplayString(entry.displayLabel), 1), createElementVNode("span", _hoisted_8, toDisplayString(entry.description), 1)])], 8, _hoisted_5);
				}), 64))])]),
				createElementVNode("section", _hoisted_9, [createElementVNode("header", _hoisted_10, [_cache[7] || (_cache[7] = createElementVNode("h4", { class: "text-xs font-semibold uppercase tracking-wide text-muted-foreground" }, " Entries ", -1)), createVNode(unref(Badge_default), {
					variant: "outline",
					class: "font-mono text-[10px]"
				}, {
					default: withCtx(() => [..._cache[6] || (_cache[6] = [createTextVNode(" builder/object-builder ", -1)])]),
					_: 1
				})]), entries.value.length === 0 ? (openBlock(), createElementBlock("p", _hoisted_11, " Click an entry type in the palette to add one. ")) : (openBlock(), createElementBlock("ul", _hoisted_12, [(openBlock(true), createElementBlock(Fragment, null, renderList(entries.value, (entry, index) => {
					return openBlock(), createElementBlock("li", {
						key: entry.id,
						class: normalizeClass(["flex cursor-pointer items-center gap-2 rounded border bg-background px-2 py-1.5 transition-colors", unref(builder).selection.value.id === entry.id ? "border-primary bg-accent/30" : ""]),
						"data-testid": `object-builder-row-${entry.id}`,
						onClick: ($event) => onRowClick(entry.id)
					}, [
						createElementVNode("span", _hoisted_14, toDisplayString(index + 1) + ". ", 1),
						createElementVNode("span", _hoisted_15, toDisplayString(entry.key || "(unnamed)"), 1),
						createVNode(unref(Badge_default), {
							variant: "secondary",
							class: "font-mono text-[9px]"
						}, {
							default: withCtx(() => [createTextVNode(toDisplayString(entry.type), 1)]),
							_: 2
						}, 1024),
						createElementVNode("span", _hoisted_16, toDisplayString(previewValue(entry)), 1)
					], 10, _hoisted_13);
				}), 128))]))]),
				createElementVNode("aside", _hoisted_17, [createElementVNode("header", _hoisted_18, [_cache[8] || (_cache[8] = createElementVNode("h4", { class: "text-xs font-semibold uppercase tracking-wide text-muted-foreground" }, " Inspector ", -1)), unref(builder).selection.value.id ? (openBlock(), createBlock(unref(Button_default), {
					key: 0,
					variant: "ghost",
					size: "icon-sm",
					"aria-label": "Clear selection",
					onClick: onClearSelection
				}, {
					default: withCtx(() => [createVNode(unref(X), { class: "h-3.5 w-3.5" })]),
					_: 1
				})) : createCommentVNode("", true)]), !selectedEntry.value ? (openBlock(), createElementBlock("p", _hoisted_19, " Select an entry to edit its key, type, and value. ")) : (openBlock(), createElementBlock("div", _hoisted_20, [createVNode(unref(Card_default), { class: "border-dashed" }, {
					default: withCtx(() => [createVNode(unref(CardHeader_default), { class: "py-2" }, {
						default: withCtx(() => [createVNode(unref(CardTitle_default), { class: "font-mono text-xs uppercase tracking-wide" }, {
							default: withCtx(() => [createTextVNode(toDisplayString(selectedEntry.value.type), 1)]),
							_: 1
						})]),
						_: 1
					}), createVNode(unref(CardContent_default), { class: "flex flex-col gap-2 pb-3" }, {
						default: withCtx(() => [
							createElementVNode("div", _hoisted_21, [createVNode(unref(Label_default), { for: "ob-key" }, {
								default: withCtx(() => [..._cache[9] || (_cache[9] = [createTextVNode("Key", -1)])]),
								_: 1
							}), createVNode(unref(Input_default), {
								id: "ob-key",
								"model-value": keyValue.value,
								"data-testid": "object-builder-inspector-key",
								onInput: _cache[0] || (_cache[0] = (e) => patchSelected({ key: e.target.value }))
							}, null, 8, ["model-value"])]),
							createElementVNode("div", _hoisted_22, [createVNode(unref(Label_default), { for: "ob-type" }, {
								default: withCtx(() => [..._cache[10] || (_cache[10] = [createTextVNode("Type", -1)])]),
								_: 1
							}), createVNode(unref(Select_default), {
								"model-value": selectedEntry.value.type,
								"onUpdate:modelValue": _cache[1] || (_cache[1] = (v) => onTypeChange(v))
							}, {
								default: withCtx(() => [createVNode(unref(SelectTrigger_default), {
									id: "ob-type",
									"data-testid": "object-builder-inspector-type"
								}, {
									default: withCtx(() => [createVNode(unref(SelectValue_default))]),
									_: 1
								}), createVNode(unref(SelectContent_default), null, {
									default: withCtx(() => [(openBlock(), createElementBlock(Fragment, null, renderList(PALETTE_TYPES, (opt) => {
										return createVNode(unref(SelectItem_default), {
											key: opt.type,
											value: opt.type
										}, {
											default: withCtx(() => [createTextVNode(toDisplayString(opt.displayLabel), 1)]),
											_: 2
										}, 1032, ["value"]);
									}), 64))]),
									_: 1
								})]),
								_: 1
							}, 8, ["model-value"])]),
							selectedEntry.value.type === "string" ? (openBlock(), createElementBlock("div", _hoisted_23, [createVNode(unref(Label_default), { for: "ob-value-string" }, {
								default: withCtx(() => [..._cache[11] || (_cache[11] = [createTextVNode("Value", -1)])]),
								_: 1
							}), createVNode(unref(Input_default), {
								id: "ob-value-string",
								"model-value": stringValue.value,
								"data-testid": "object-builder-inspector-value-string",
								onInput: _cache[2] || (_cache[2] = (e) => patchSelected({ value: e.target.value }))
							}, null, 8, ["model-value"])])) : selectedEntry.value.type === "number" ? (openBlock(), createElementBlock("div", _hoisted_24, [createVNode(unref(Label_default), { for: "ob-value-number" }, {
								default: withCtx(() => [..._cache[12] || (_cache[12] = [createTextVNode("Value", -1)])]),
								_: 1
							}), createVNode(unref(Input_default), {
								id: "ob-value-number",
								type: "number",
								"model-value": numberValue.value,
								"data-testid": "object-builder-inspector-value-number",
								onInput: _cache[3] || (_cache[3] = (e) => {
									const v = e.target.value;
									const parsed = v === "" ? 0 : Number(v);
									patchSelected({ value: Number.isNaN(parsed) ? 0 : parsed });
								})
							}, null, 8, ["model-value"])])) : selectedEntry.value.type === "boolean" ? (openBlock(), createElementBlock("div", _hoisted_25, [createVNode(unref(Label_default), { for: "ob-value-boolean" }, {
								default: withCtx(() => [..._cache[13] || (_cache[13] = [createTextVNode("Value", -1)])]),
								_: 1
							}), createVNode(unref(Switch_default), {
								id: "ob-value-boolean",
								"model-value": booleanValue.value,
								"data-testid": "object-builder-inspector-value-boolean",
								"onUpdate:modelValue": _cache[4] || (_cache[4] = (v) => patchSelected({ value: v }))
							}, null, 8, ["model-value"])])) : selectedEntry.value.type === "array" || selectedEntry.value.type === "object" ? (openBlock(), createElementBlock("div", _hoisted_26, [
								createVNode(unref(Label_default), { for: "ob-value-json" }, {
									default: withCtx(() => [..._cache[14] || (_cache[14] = [createTextVNode("Value (JSON)", -1)])]),
									_: 1
								}),
								createVNode(unref(Textarea_default), {
									id: "ob-value-json",
									"model-value": jsonDraft.value,
									rows: "6",
									"data-testid": "object-builder-inspector-value-json",
									onInput: _cache[5] || (_cache[5] = (e) => onJsonInput(e.target.value))
								}, null, 8, ["model-value"]),
								jsonError.value ? (openBlock(), createElementBlock("p", _hoisted_27, toDisplayString(jsonError.value), 1)) : createCommentVNode("", true)
							])) : selectedEntry.value.type === "null" ? (openBlock(), createElementBlock("div", _hoisted_28, [..._cache[15] || (_cache[15] = [
								createTextVNode(" Value is fixed to ", -1),
								createElementVNode("code", { class: "font-mono" }, "null", -1),
								createTextVNode(". ", -1)
							])])) : createCommentVNode("", true)
						]),
						_: 1
					})]),
					_: 1
				}), createElementVNode("div", _hoisted_29, [
					createVNode(unref(Button_default), {
						variant: "outline",
						size: "sm",
						disabled: selectedIndex.value <= 0,
						"data-testid": "object-builder-move-up",
						onClick: onMoveUp
					}, {
						default: withCtx(() => [createVNode(unref(ArrowUp), { class: "h-3.5 w-3.5" })]),
						_: 1
					}, 8, ["disabled"]),
					createVNode(unref(Button_default), {
						variant: "outline",
						size: "sm",
						disabled: !canMoveDown.value,
						"data-testid": "object-builder-move-down",
						onClick: onMoveDown
					}, {
						default: withCtx(() => [createVNode(unref(ArrowDown), { class: "h-3.5 w-3.5" })]),
						_: 1
					}, 8, ["disabled"]),
					createVNode(unref(Button_default), {
						variant: "destructive",
						size: "sm",
						class: "ml-auto",
						"data-testid": "object-builder-remove",
						onClick: onRemove
					}, {
						default: withCtx(() => [createVNode(unref(Trash2), { class: "h-3.5 w-3.5" }), _cache[16] || (_cache[16] = createTextVNode(" Remove ", -1))]),
						_: 1
					})
				])]))])
			], 10, _hoisted_1);
		};
	}
});
//#endregion
//#region src/components/compositions/elements/builder/ObjectBuilder.vue
var ObjectBuilder_exports = /* @__PURE__ */ __exportAll({ default: () => ObjectBuilder_default });
var ObjectBuilder_default = ObjectBuilder_vue_vue_type_script_setup_true_lang_default;
//#endregion
export { ObjectBuilder_exports as n, ObjectBuilder_default as t };

//# sourceMappingURL=ObjectBuilder-DKLj9zFh.js.map