import { n as cn } from "./utils-DXzSsU1e.js";
import { r as getElementComponent, t as shouldRender } from "./useDisplayConditions-DNEDur9S.js";
import { computed, createBlock, createCommentVNode, createElementBlock, defineComponent, inject, mergeProps, normalizeClass, openBlock, provide, ref, resolveDynamicComponent } from "vue";
import { defineStore } from "pinia";
//#region src/stores/formDataStore.ts
var useFormDataStore = defineStore("gx-modui/formData", () => {
	const forms = ref({});
	function ensureForm(formId) {
		if (!forms.value[formId]) forms.value[formId] = {
			values: {},
			errors: {},
			touched: {},
			dirty: false
		};
		return forms.value[formId];
	}
	function setInitialValues(formId, values) {
		const form = ensureForm(formId);
		form.values = { ...values };
		form.errors = {};
		form.touched = {};
		form.dirty = false;
	}
	function setValue(formId, name, value) {
		const form = ensureForm(formId);
		form.values[name] = value;
		form.touched[name] = true;
		form.dirty = true;
	}
	function setErrors(formId, errors) {
		const form = ensureForm(formId);
		const normalised = {};
		for (const [k, v] of Object.entries(errors)) normalised[k] = Array.isArray(v) ? v : [v];
		form.errors = normalised;
	}
	function clearErrors(formId, name) {
		const form = ensureForm(formId);
		if (name === void 0) form.errors = {};
		else delete form.errors[name];
	}
	function getForm(formId) {
		return ensureForm(formId);
	}
	function resetForm(formId) {
		delete forms.value[formId];
	}
	return {
		forms,
		ensureForm,
		setInitialValues,
		setValue,
		setErrors,
		clearErrors,
		getForm,
		resetForm
	};
});
//#endregion
//#region src/engine/useFormData.ts
/**
* Vue inject key used by the page-level component (ShowPage / IndexPage
* / FormPanel) to advertise which formId child renderers should bind
* to. Avoids prop-drilling `formId` through every nested card/element.
*/
var FORM_ID_KEY = Symbol("gx-modui:formId");
/**
* Provide a formId to descendants. Call once at the page boundary.
*/
function provideFormId(formId) {
	provide(FORM_ID_KEY, formId);
}
/**
* Bind an element's `name` to the form-data store. Returns reactive
* value, errors, and a setter. Renderers typically:
*
*   const { value, errors, setValue } = useFormData(props.element.name)
*   <input :value="value" @input="setValue(($event.target as HTMLInputElement).value)" />
*/
function useFormData(name, formIdOverride) {
	const formId = formIdOverride ?? inject(FORM_ID_KEY, void 0) ?? "default";
	const store = useFormDataStore();
	store.ensureForm(formId);
	return {
		value: computed(() => store.forms[formId]?.values[name]),
		errors: computed(() => store.forms[formId]?.errors[name] ?? []),
		touched: computed(() => Boolean(store.forms[formId]?.touched[name])),
		setValue: (value) => store.setValue(formId, name, value),
		clearError: () => store.clearErrors(formId, name)
	};
}
//#endregion
//#region src/engine/legacyPropRemap.ts
/**
* Legacy-JSON → composition-prop remapping.
*
* The composition layer was refactored to use shadcn-style normalised
* prop names, but plenty of JSON in the wild still uses the old v2
* names (`triggerButtonLabel` instead of `triggerLabel`, GxP variant
* aliases like `"primary"` instead of `"default"`, etc).
*
* This module is consulted by `ElementRenderer` after stripping
* schema-only keys and before spreading the result onto the resolved
* composition. It's a thin compatibility layer — every entry here is
* a known legacy form. Renderers themselves stay schema-agnostic.
*
* Adding a new alias:
*   - For a prop-name rename, add to `PROP_RENAMES[<category>]`.
*   - For a value-only alias (e.g. variant strings), add to
*     `VALUE_ALIASES[<category>].<prop>`.
*/
/**
* Per-category prop-name renames. The string on the left is the legacy
* JSON key; the string on the right is the new composition prop name.
*
* Matched against the element's category prefix (`element.type` split
* at the dot). `*` is a wildcard that applies to every element.
*/
var PROP_RENAMES = {
	"configuration-block": {
		selectOptions: "nestedElements",
		triggerButtonLabel: "triggerLabel",
		dialogTitle: "title",
		modalTitle: "title",
		addOptionButtonLabel: "addButtonLabel"
	},
	display: { icon: "iconName" }
};
/**
* Per-(category, prop) value aliases. Used when a prop's accepted value
* union changed and we want legacy JSON to still resolve. Lookups are
* case-sensitive; unknown values pass through untouched.
*/
var VALUE_ALIASES = {
	action: { variant: {
		primary: "default",
		danger: "destructive",
		"outline-primary": "outline",
		"outline-danger": "outline",
		"outline-secondary": "outline",
		"btn-success": "success",
		"btn-warning": "warning",
		"btn-info": "info",
		light: "ghost",
		dark: "default"
	} },
	boolean: { variant: {} }
};
/**
* Apply prop renames + value aliases for an element. Returns a NEW
* object — never mutates input. Pass the result through `v-bind`.
*/
function applyLegacyRemaps(type, props) {
	const dot = type.indexOf(".");
	const category = dot < 0 ? type : type.slice(0, dot);
	const renames = PROP_RENAMES[category];
	const aliases = VALUE_ALIASES[category];
	if (!renames && !aliases) return props;
	const out = {};
	for (const [key, value] of Object.entries(props)) {
		const renamedKey = renames?.[key] ?? key;
		if (renamedKey !== key && renamedKey in props) continue;
		const aliasMap = aliases?.[renamedKey];
		out[renamedKey] = typeof value === "string" && aliasMap && aliasMap[value] !== void 0 ? aliasMap[value] : value;
	}
	return out;
}
//#endregion
//#region src/engine/ElementRenderer.vue?vue&type=script&setup=true&lang.ts
var _hoisted_1 = ["data-element-id", "data-element-type"];
//#endregion
//#region src/engine/ElementRenderer.vue
var ElementRenderer_default = /* @__PURE__ */ defineComponent({
	__name: "ElementRenderer",
	props: {
		element: {},
		item: { default: () => ({}) },
		evaluationContext: { default: () => ({}) }
	},
	setup(__props) {
		/**
		* Renders a single CardElement by dispatching its JSON definition into
		* the matching composition under `components/compositions/elements/`.
		*
		* The renderer is the bridge layer:
		*   - resolves the composition by `element.type` via the registry
		*   - evaluates the element's visibility (`shouldRender`)
		*   - applies responsive layout + classList chrome at the wrapper level
		*   - binds `useFormData(element.name)` to the form-data store and
		*     forwards `modelValue` + `errors` + the `@update:modelValue`
		*     handler to the composition
		*   - strips schema-only keys (type, conditionParams, columns*, ...)
		*     and passes the rest through as Vue props
		*
		* Compositions don't know about the form-data store, the JSON schema,
		* or this renderer's layout — they receive normal Vue props and emit
		* `update:modelValue`. They're directly mountable in any app.
		*/
		const props = __props;
		const visible = computed(() => shouldRender(props.element, props.item, props.evaluationContext));
		const resolved = computed(() => getElementComponent(props.element.type));
		const bindings = computed(() => useFormData(props.element.name ?? ""));
		/**
		* Keys that live on every CardElement and are NOT meant to flow
		* through to the composition as props. These are either consumed by
		* this renderer (`columns*`, `conditionParams`, ...) or used only by
		* the engine (`type`, `id` — well, `id` IS passed through, see below).
		*/
		const STRIPPED_KEYS = new Set([
			"type",
			"conditionParams",
			"conditionGroupLogic",
			"condition",
			"features",
			"permissions",
			"columns",
			"columnsSm",
			"columnsMd",
			"columnsLg",
			"columnsXl",
			"columnsXxl",
			"wrapperClassList",
			"columnClassList",
			"labelClassList",
			"classList",
			"previewMode",
			"order",
			"defaultValue",
			"modelValue"
		]);
		/**
		* Compute the props object to pass to the resolved composition.
		*
		* - `modelValue` comes from the form-data store, falling back to
		*   `item[element.name]`, then `element.defaultValue`. Compositions
		*   declare `modelValue` and Vue picks it up.
		* - `errors` comes from the form-data store.
		* - All other element keys (label, placeholder, required, ...) are
		*   passed through; Vue's prop validation silently drops anything the
		*   composition doesn't declare.
		*/
		const compositionProps = computed(() => {
			const el = props.element;
			const result = {};
			for (const [key, value] of Object.entries(el)) if (!STRIPPED_KEYS.has(key)) result[key] = value;
			const fieldName = props.element.name ?? "";
			const storeValue = fieldName ? bindings.value.value.value : void 0;
			const itemValue = fieldName ? props.item[fieldName] : void 0;
			const defaultValue = el.defaultValue;
			if (storeValue !== void 0 && storeValue !== null) result.modelValue = storeValue;
			else if (itemValue !== void 0 && itemValue !== null) result.modelValue = itemValue;
			else if (defaultValue !== void 0 && defaultValue !== null) result.modelValue = defaultValue;
			else result.modelValue = "";
			result.errors = bindings.value.errors.value;
			return applyLegacyRemaps(props.element.type, result);
		});
		function onUpdateModelValue(value) {
			if (!props.element.name) return;
			bindings.value.setValue(value);
		}
		const wrapperClass = computed(() => cn("gxp-element", `gxp-element--${props.element.type.replace(/\./g, "-")}`, columnClass("col", props.element.columns), columnClass("col-sm", props.element.columnsSm), columnClass("col-md", props.element.columnsMd), columnClass("col-lg", props.element.columnsLg), columnClass("col-xl", props.element.columnsXl), normalizeClasses(props.element.columnClassList), normalizeClasses(props.element.wrapperClassList)));
		function columnClass(prefix, n) {
			if (typeof n !== "number") return;
			const pct = Math.max(0, Math.min(12, n)) / 12;
			return prefix === "col" ? `basis-[${(pct * 100).toFixed(4)}%]` : `${prefix}:basis-[${(pct * 100).toFixed(4)}%]`;
		}
		function normalizeClasses(value) {
			if (!value) return "";
			return Array.isArray(value) ? value.join(" ") : value;
		}
		return (_ctx, _cache) => {
			return visible.value ? (openBlock(), createElementBlock("div", {
				key: 0,
				class: normalizeClass(wrapperClass.value),
				"data-element-id": __props.element.id,
				"data-element-type": __props.element.type
			}, [(openBlock(), createBlock(resolveDynamicComponent(resolved.value), mergeProps(compositionProps.value, { "onUpdate:modelValue": onUpdateModelValue }), null, 16))], 10, _hoisted_1)) : createCommentVNode("", true);
		};
	}
});
//#endregion
export { useFormDataStore as a, useFormData as i, FORM_ID_KEY as n, provideFormId as r, ElementRenderer_default as t };

//# sourceMappingURL=ElementRenderer-DV1pZRd4.js.map