UNPKG

@react-form-builder/core

Version:

React JSON Schema Form Builder to create complex, validated, reusable forms with no deep React knowledge required

1,876 lines (1,874 loc) 143 kB
import { jsxs as Ke, jsx as y, Fragment as Ut } from "@emotion/react/jsx-runtime"; import * as qr from "react"; import { createContext as Hr, useContext as Jt, useMemo as B, forwardRef as Ur, useEffect as z, useState as _t, useCallback as Zt, createElement as Gt, Fragment as Jr, useRef as _r, useImperativeHandle as Zr } from "react"; import { observer as Me } from "mobx-react"; import { makeAutoObservable as $, reaction as Qt, configure as Gr, observable as S, autorun as Xt, makeObservable as We, runInAction as Be } from "mobx"; import { cx as tt, css as J } from "@emotion/css"; import { CacheProvider as Qr } from "@emotion/react"; import me from "@emotion/cache"; import { z as V } from "zod"; function Xr(e, t) { return e.reduce((r, n, o, i) => ((r[t(n, o, i)] ||= []).push(n), r), {}); } const Lt = {}; function Dt(e) { const t = e.name; if (Lt[t]) throw new Error(`Component feature ${t} is already registered`); Lt[t] = e; } function T(e) { Dt({ name: e, allowMultiple: !1 }); } function qe(e) { const t = Lt[e]; if (!t) throw new Error(`ComponentFeature ${e} is not registered`); return t; } function Yr(e, t, r) { const n = qe(t), o = { ...e }, i = o[t]; return o[t] = n.allowMultiple ? i ? [...i, r] : [r] : r, o; } function Yt(e, ...t) { let r = e ?? {}; return t.forEach((n) => { r = Yr(r, n.name, n.value); }), r; } const tn = "component-is-preset"; T(tn); const te = "component-role"; Dt({ name: te, allowMultiple: !0 }); const en = "disable-main-component-properties"; T(en); const rn = "disable-tooltip-properties"; T(rn); const nn = "disable-style-properties"; T(nn); const on = "disable-additional-properties"; T(on); const sn = "disable-styles-for-classname-editor"; T(sn); const an = "enable-inline-styles-editor"; T(an); const Et = "hide-from-component-palette"; T(Et); const He = "disable-component-remove"; T(He); const Ue = "disable-component-styling"; T(Ue); const Je = "disable-component-wrapper-styling"; T(Je); const _e = "skip-children-during-field-collection"; T(_e); const Ze = "event-handlers"; Dt({ name: Ze, allowMultiple: !1 }); const ln = "disable-action-editors"; T(ln); const Ge = "required-properties"; Dt({ name: Ge, allowMultiple: !0 }); const ye = Symbol("key"); function Qe(e, t, r, n = {}) { const o = Object.keys(n).map((i) => `${i}=${n[i]}`).join("_"); return `${e}_${t}_${r ? `${r}_` : ""}${o}`; } function ee(e, t, r = {}) { return Qe("autorun", e, t, r); } function A(e, t = {}) { return Qe("observable", e, void 0, t); } let ge = 0; function Xe(e) { e[ye] || (++ge, e[ye] = `actionData_${ge}`); } function Ye(e) { const t = e.events; t && Object.values(t).forEach((r) => r.forEach(Xe)), e.children?.forEach(Ye); } function et(e) { return e?.computeType === "function"; } function tr(e) { return e?.computeType === "localization"; } function er(e) { return et(e) || tr(e); } function I(e) { return e.dataKey ?? e.key; } class x { /** * The React component key. */ key = ""; /** * The component data key. */ dataKey; /** * The component type of the form viewer. */ type = ""; /** * The component properties. */ props = {}; /** * The component CSS styles. */ css; /** * The component wrapper CSS styles. */ wrapperCss; /** * The component styles for the `style` attribute. */ style; /** * The component wrapper styles for the `style` attribute. */ wrapperStyle; /** * The set of event handlers. */ events; /** * The array of child components. */ children; /** * The component value validation settings. */ schema; /** * The set of arbitrary HTML attributes added to the component. */ htmlAttributes; /** * The tooltip settings. */ tooltipProps; /** * The modal settings. */ modal; /** * The name of the occupied component property in the parent component. */ slot; /** * The condition for binding a child element to a parent element. */ slotCondition; /** * The expression or function to conditionally render a component. */ renderWhen; /** * Disables data binding for the component. */ disableDataBinding; /** * Creates the component settings. * @param key the React component key. * @param type the component type of the form viewer. */ constructor(t, r) { this.key = t, this.type = r, $(this, void 0, { name: A("ComponentStore", { key: t }) }); } /** * Adds a validation rule to the component. * @param store the component settings. * @param key the validation key. * @param type the validation type. */ static addValidationRule(t, r, n = "internal") { if (x.hasValidationRule(t, r)) return; t.schema ??= { validations: [] }; const o = n === "internal" ? { key: r } : { key: r, type: n }; t.schema.validations?.push(o); } /** * Returns true if the component has a validation rule. * @param store the component settings. * @param key the validation key. * @returns true if the component has a validation rule, otherwise false. */ static hasValidationRule(t, r) { return t.schema?.validations?.some((o) => o.key === r); } /** * Removes a validation rule from the component. * @param store the component settings. * @param key the validation key. */ static removeValidationRule(t, r) { t.schema?.validations?.length && (t.schema.validations = t.schema.validations.filter((n) => n.key !== r)); } /** * Correctly creates the {@link ComponentStore} from deserialized data. * @param value the deserialized data. * @returns the component Store. */ static createFromObject(t) { const r = Object.assign(new x(t.key, t.type), t); return Ye(r), r; } /** * Adds the event handler for component. * @param store the target {@link ComponentStore}. * @param eventName the target event name. * @param data the {@link ActionData}. */ static addEventHandler(t, r, n) { Xe(n), t.events ??= {}, t.events[r] ??= [], t.events[r].push(n); } /** * Returns a clone of the specified component settings. * @param store the component settings. * @returns the clone of the specified component settings. */ static clone(t) { const r = JSON.parse(JSON.stringify(t)); return x.createFromObject(r); } } const cn = { /** * @inheritDoc */ get get() { return {}; }, /** * @inheritDoc */ get wrapperClassName() { return ""; }, /** * @inheritDoc */ get wrapperStyle() { }, /** * @inheritDoc */ get propsWithoutChildren() { return {}; }, /** * @inheritDoc */ get ownProps() { return {}; }, /** * @inheritDoc */ onDidMount() { }, /** * @inheritDoc */ onWillUnmount() { }, /** * @inheritDoc */ get isReadOnly() { return !1; }, /** * @inheritDoc */ get isDisabled() { return !1; } }; function un(e) { return () => { const t = Jt(e); if (!t) throw new Error(`The context ${e.displayName} was not found!`); return t; }; } function dn(e) { return e.Provider; } function St(e, t = null) { const r = Hr(t); r.displayName = e; const n = un(r), o = dn(r); return [n, o, r]; } function H(e) { return typeof e == "object"; } function D(e) { return typeof e > "u"; } function W(e) { return e === null; } function rr(e) { return typeof e == "number"; } function M(e) { return e !== null && typeof e == "object"; } function nr(e) { return W(e) || D(e) ? !0 : typeof e == "string" || Array.isArray(e) ? e.length === 0 : e instanceof Map || e instanceof Set ? e.size === 0 : M(e) ? Object.keys(e).length === 0 : !1; } function hn(e) { if (!e) return ["", ""]; try { if (typeof Intl < "u" && Intl.Segmenter) { const o = new Intl.Segmenter(void 0, { granularity: "grapheme" }).segment(e)[Symbol.iterator]().next(); if (!o.done) { const i = String(o.value.segment); return [i, e.slice(i.length)]; } return ["", ""]; } } catch { } const t = [...e]; return [t[0] ?? "", t.slice(1).join("")]; } function re(e) { if (!e) return ""; const [t, r] = hn(e); return t.toUpperCase() + r; } function or(e) { const t = String(e ?? ""); if (!t) return []; const r = t.replace(new RegExp("(\\p{Ll})(\\p{Lu})", "gu"), "$1 $2"); try { if (typeof Intl < "u" && Intl.Segmenter) { const n = new Intl.Segmenter(void 0, { granularity: "word" }), o = []; for (const i of n.segment(r)) { const s = i, a = String(s.segment); (s.isWordLike ?? /[\p{L}\p{N}]/u.test(a)) && o.push(a); } return o; } } catch { } return r.split(/[^\p{L}\p{N}]+/u).filter(Boolean); } function fn(e) { const t = or(e); if (t.length === 0) return ""; const r = t[0].toLowerCase(), n = t.slice(1).map((o) => re(o.toLowerCase())); return [r, ...n].join(""); } function hs(e) { return re(e); } function ir(e) { const t = or(e); return t.length === 0 ? "" : t.map((r) => re(r.toLowerCase())).join(" "); } function fs(e) { return (e || "").toUpperCase(); } function ne(e = "") { return `${e}${++ne.counter}`; } ne.counter = 0; function Kt(e, ...t) { for (const r of t) { if (!M(e) || !M(r)) { Object.assign(e, r); continue; } for (const n of Object.keys(r)) { const o = r[n], i = e[n]; M(o) && M(i) ? Kt(i, o) : e[n] = o; } } return e; } function pn(e, t = 0) { let r; return (...o) => { D(r) || clearTimeout(r), r = setTimeout(() => e(...o), t); }; } function Mt(e, t) { if (e === t) return !0; if (e == null || t == null) return !1; if (e instanceof Date && t instanceof Date) return e.getTime() === t.getTime(); if (Array.isArray(e) && Array.isArray(t)) { if (e.length !== t.length) return !1; for (let r = 0; r < e.length; r++) if (!Mt(e[r], t[r])) return !1; return !0; } if (typeof e == "object" && typeof t == "object") { const r = Object.keys(e), n = Object.keys(t); if (r.length !== n.length) return !1; for (const o of r) if (!Object.prototype.hasOwnProperty.call(t, o) || !Mt(e[o], t[o])) return !1; return !0; } return !1; } function ve(e, t, r) { if (r) { if (Array.isArray(e) && Array.isArray(t)) { if (e.length !== t.length) return !1; for (let n = 0; n < e.length; n++) { const o = r(e[n], t[n], n); if (!D(o)) { if (!o) return !1; continue; } if (!ve(e[n], t[n], r)) return !1; } return !0; } if (M(e) && M(t)) { const n = /* @__PURE__ */ new Set([...Object.keys(e), ...Object.keys(t)]); for (const o of n) { const i = r(e[o], t[o], o); if (!D(i)) { if (!i) return !1; continue; } if (!ve(e[o], t[o], r)) return !1; } return !0; } } return Mt(e, t); } function Q(e, t = /* @__PURE__ */ new WeakMap()) { if (e === null || typeof e != "object") return e; if (t.has(e)) return t.get(e); if (e instanceof Date) return new Date(e.getTime()); if (e instanceof RegExp) { const o = new RegExp(e.source, e.flags); return o.lastIndex = e.lastIndex, o; } if (e instanceof Map) { const o = /* @__PURE__ */ new Map(); return t.set(e, o), e.forEach((i, s) => { o.set(Q(s, t), Q(i, t)); }), o; } if (e instanceof Set) { const o = /* @__PURE__ */ new Set(); return t.set(e, o), e.forEach((i) => o.add(Q(i, t))), o; } if (ArrayBuffer.isView(e)) return new e.constructor(e); if (e instanceof ArrayBuffer) return e.slice(0); if (Array.isArray(e)) { const o = []; t.set(e, o); for (const i of e) o.push(Q(i, t)); return o; } const r = Object.getPrototypeOf(e), n = Object.create(r); t.set(e, n); for (const o of Reflect.ownKeys(e)) { const i = Object.getOwnPropertyDescriptor(e, o); i && ("value" in i && (i.value = Q(e[o], t)), Object.defineProperty(n, o, i)); } return n; } const mn = (e, t) => { const r = [...e]; return e.forEach((n, o) => { o in t && (r[o] = sr(n, t[o] ?? void 0)); }), r; }, we = (e) => !(!H(e) || e instanceof Date), sr = (e, t) => Array.isArray(e) ? Array.isArray(t) ? mn(e, t) : e : Array.isArray(t) ? e : we(e) && we(t) ? oe(e, t) : e, oe = (e, t) => { const r = { ...e }; return Object.keys(t).forEach((n) => { if (n in e) { if (D(e[n])) return; r[n] = sr(e[n], t[n]); return; } r[n] = t[n]; }), r; }; class be { handlers = []; /** * Adds a handler to the list of subscribers. * @param handler the handler function to be added. */ subscribe(t) { this.handlers.push(t); } /** * Removes the specified event handler from the list of handlers. * @param handler the event handler to remove. */ unsubscribe(t) { this.handlers = this.handlers.filter((r) => r !== t); } /** * Returns true if the object has subscribers, false otherwise. * @returns true if the object has handlers registered for events, otherwise returns false. */ get isSubscribed() { return this.handlers.length > 0; } /** * Invokes the event by calling all registered event handlers. * @param sender the sender of the event. * @param eventArgs the event arguments. */ invoke(t, r) { [...this.handlers].forEach((n) => n(t, r)); } /** * Dispose method to release all handlers. */ dispose() { this.handlers = []; } } function yt(e, t) { t(e), e.children?.forEach((r) => yt(r, t)); } function yn(e, t, r = 0) { if (e === t) return r; if (e.children) { r = r + 1; for (const n of e.children) { const o = yn(n, t, r); if (o) return o; } } } function Ce(e, t) { let r = 1; const n = fn(e.type), o = () => `${n}${r}`; for (; t.has(o()); ) r++; return e.key = o(), e.key; } function ht(e) { return typeof e.disableReaction == "function"; } class gn { /** * Constructs a new instance of the ComponentKeyChangedEventArgs class. * @param oldKey the old key. * @param newKey the new key. */ constructor(t, r) { this.oldKey = t, this.newKey = r; } } class vn { /** * An event that occurs after a component key change. */ onAfterKeyChanged = new be(); /** * An event that occurs before a component is removed from the component tree. */ onBeforeDelete = new be(); /** * Unsubscribe from all events. */ dispose() { this.onAfterKeyChanged.dispose(), this.onBeforeDelete.dispose(); } } const ps = (e) => { const t = {}; return Object.entries(e.data).forEach(([r, n]) => { t[r] = n ?? ""; }), t; }; class wn { #t; #e; #r; _state = {}; /** * The unique identifier. */ id; /** * The component settings. */ store; /** * The component metadata. */ model; /** * The field with the form data. */ field; /** * The parent node in the component data tree. */ parent; /** * The child nodes in the component data tree. */ children = []; /** * User defined properties of the React component. */ userDefinedProps; /** * If true, then validation is in progress. */ validating = !1; /** * Specifies the root component for the data in the component tree. **Internal use only.** */ dataRootProvider; /** * Specifies the index in the array if the component is in the component array. * This is not an index in a parent-child structure. */ index; /** * The state of the component. **Internal use only. */ componentState = cn; /** * The function for getting initial data. **Internal use only.** */ getInitialData; /** * The function for updating initial data. **Internal use only.** */ setInitialData; /** * Constructor. * @param componentStore the component settings. * @param model the component metadata for the form viewer. * @param childFactory the factory function that creates {@link ComponentData} instance. * @param getFormValidationResult the function that returns a form validation results. */ constructor(t, r, n, o) { this.store = t, this.model = r, this.id = ne(`${this.model.type}_`), this.#r = o, t.children?.forEach((s) => { n(s).setParent(this); }), $(this, void 0, { name: A("ComponentData", { key: t.key }) }); const i = () => Qt(() => this.key, (s, a) => { this.invokeOnAfterKeyChanged(this, new gn(a, s)); }); this.#t = [i()]; } /** * Sets the new parent for this node. * @param newParent the new parent. */ setParent(t) { this.parent?.removeChild(this), t.addChild(this), this.parent = t; } /** * Inserts the given node after this node. * @param inserted the node to insert. */ insertAfterMe(t) { this.insert(t, "after"); } /** * Inserts the given node before this node. * @param inserted the node to insert. */ insertBeforeMe(t) { this.insert(t, "before"); } /** * @inheritDoc */ get state() { return this._state; } /** * @inheritDoc */ set state(t) { this._state = t; } /** * @returns the root component for the data in the component tree. */ get dataRoot() { return this.dataRootProvider?.dataRoot ?? this.parent?.dataRoot ?? this; } /** * @returns the initial data. */ get initialData() { return this.dataRoot.getInitialData?.(); } /** * Updates the initial data. **Internal use only.** * @param key the initial data key. * @param value the initial data value. */ updateInitialData(t, r) { this.dataRoot.setInitialData?.(t, r); } /** * @returns the key of this node (same as the key of the ComponentStore). */ get key() { return this.store.key; } /** * @returns the ComponentDataEvents object. */ get events() { return this.#e || (this.#e = new vn()), this.#e; } /** * Find the node with the given key. * @param key the key to find. * @returns the node or undefined if not found. */ findByKey(t) { if (this.key === t) return this; for (let r = 0; r < this.children.length; r++) { const o = this.children[r].findByKey(t); if (o) return o; } } /** * Assigns unique keys to the items in the tree. * @param root the root of the tree to unify keys. Defaults to the root of this tree. * @returns the map of new keys to old keys. */ unifyKeys(t) { const r = /* @__PURE__ */ new Map(), n = []; return yt(t, ({ key: o }) => { n.push(o); }), yt(this, (o) => { const i = Ce(o.store, new Set(n)); r.set(i, o.key), n.push(i); }), r; } /** * Assigns unique keys to the items in the tree. */ unifyTree() { const t = /* @__PURE__ */ new Map(); yt(this, ({ key: o, store: i }) => { const s = t.get(o) ?? /* @__PURE__ */ new Set(); s.add(i), t.set(o, s); }); const n = new Set(t.keys()); t.forEach((o, i) => { if (o.size <= 1) return; [...o].slice(1).forEach((a) => { const c = Ce(a, n); n.add(c); }); }); } /** * @returns all the fields in the tree as a map. Starts from this node. */ get fields() { const t = this.collectAllFields(/* @__PURE__ */ new Map()), r = /* @__PURE__ */ new Map(); return t.forEach((n, o) => { r.set(I(o.store), n); }), r; } /** * @returns an array of all component fields, including non-unique data keys. */ get allComponentFields() { const t = this.collectAllFields(/* @__PURE__ */ new Map()), r = []; return t.forEach((n, o) => { r.push({ dataKey: I(o.store), field: n }); }), r; } /** * @returns an array of all fields, including non-unique data keys. */ get allFields() { return this.allComponentFields.map((t) => t.field); } /** * @returns an array of all children components. */ get allChildren() { return this.collectAllChildren([]); } /** * Deletes this node from the tree. */ delete() { this.parent?.removeChild(this); const t = this.collectAllNodesAsArray([]); this.invokeOnBeforeDeleted(t), this.disposeNodes(t); } /** * @inheritDoc */ get data() { const t = { ...this.generatedData() }, r = H(this.initialData) ? { ...this.initialData } : {}; return oe(t, r); } /** * @returns the generated form data. */ generatedData() { const t = {}; for (const { dataKey: r, field: n } of this.allComponentFields) if (n.storeDataInParentForm) { const o = n.value || {}; Object.keys(o).forEach((i) => t[i] = o[i]); } else t[r] = n.value; return t; } /** * @returns the object to read and modify parent data (available for array elements). */ get parentData() { if (typeof this.nearestIndex == "number") return this.parent?.data ?? this.rootData; } /** * @returns the object to read and modify root form data. */ get rootData() { return this.root.data; } /** * @inheritDoc */ get errors() { const t = {}; for (const { dataKey: r, field: n } of this.allComponentFields) { n.error && (t[r] = n.error); const o = n.errors; o && (Array.isArray(o) ? t[r] = o : (n.storeDataInParentForm && Object.keys(o).forEach((i) => t[i] = o[i]), !n.storeDataInParentForm && Object.keys(o).length > 0 && (t[r] = o))); } return t; } /** * @inheritDoc */ set errors(t) { this.allComponentFields.forEach((r) => { const n = t[r.dataKey]; r.field.setError(n); }); } /** * @inheritDoc */ get hasErrors() { return Object.keys(this.errors).length > 0; } /** * @inheritDoc */ setAllErrors(t) { this.allFields.forEach((r) => r.error = t); } /** * @inheritDoc */ async validate() { return await this.validateForm(), this.errors; } /** * @inheritDoc */ async getValidationResult() { let t; const r = async ({ dataKey: o, field: i }) => { const s = await i.getValidationResult(); if (nr(s)) return; t ??= {}; let a = t; if (!i.storeDataInParentForm) { const c = Array.isArray(s) ? [] : {}; t[o] ??= c, a = t[o]; } Kt(a, s); }; return await Promise.allSettled(this.allComponentFields.map(r)), (await this.#r?.())?.forEach((o) => { t ??= {}, Kt(t, o); }), t; } /** * @inheritDoc */ get isValidating() { return this.validating; } /** * @inheritDoc */ reset(t = !0) { t && this.clearInitialData(), this.allFields.forEach((r) => { ht(r) && r.disableReaction(), r.reset(); }), this.allFields.forEach((r) => { ht(r) && r.enableReaction(); }); } /** * @inheritDoc */ clear(t = !0) { t && this.clearInitialData(), this.allFields.forEach((r) => { ht(r) && r.disableReaction(), r.clear(); }), this.allFields.forEach((r) => { ht(r) && r.enableReaction(); }); } /** * Dispose method that releases resources used by the object. * It disposes the field and all the children objects. */ dispose() { const t = this.collectAllNodesAsArray([]); this.disposeNodes(t); } /** * @returns true if it has no parent {@link ComponentData}, false otherwise. */ get isRoot() { return !this.parent; } /** * @returns the root of the component tree. */ get root() { return this.parent ? this.parent.root : this; } /** * @returns the index in the array if the component is in the component array * (looks for the nearest index in the component hierarchy). */ get nearestIndex() { return D(this.index) ? this.parent?.nearestIndex : this.index; } async validateForm() { this.validating = !0; try { await Promise.allSettled([...this.allFields].map((n) => n.validate())); const t = await this.#r?.(); if (!t?.length) return; const r = this.allComponentFields; t.forEach((n) => { n && r.forEach(({ field: o, dataKey: i }) => { if (n[i]) return o.setError(n[i]); if (o.storeDataInParentForm) return o.setError(n); }); }); } finally { this.validating = !1; } } insert(t, r) { const n = r === "before" ? 0 : 1; if (!this.parent) throw new Error(`Cannot insert without parent. Key = ${this.key}`); t.parent?.removeChild(t), t.parent = this.parent; const o = this.parent.children, i = o.indexOf(this); if (i < 0) throw new Error(`Cannot insert not existing element into ComponentData. Key = ${this.key}`); o.splice(i + n, 0, t), this.parent.store.children ??= []; const s = this.parent.store.children, a = s.indexOf(this.store); if (a < 0) throw new Error(`Cannot insert not existing element into ComponentStore. Key = ${this.key}`); s.splice(a + n, 0, t.store), t.store.slot = this.store.slot, t.store.slotCondition = this.store.slotCondition; } /** * Disposes the nodes by calling the disposers, disposing the field, * and resetting the parent and children properties to undefined and an empty array, respectively. * @param nodes the array of ComponentData objects representing the nodes to dispose. */ disposeNodes(t) { t.forEach((r) => { r.#e?.dispose(), r.#t.forEach((n) => n()), r.field?.dispose(), r.parent = void 0, r.children = []; }); } collectAllNodesAsArray(t) { t.push(this); for (let r = 0; r < this.children.length; r++) this.children[r].collectAllNodesAsArray(t); return t; } collectAllFields(t) { if (this.field && t.set(this, this.field), this.model.isFeatureEnabled(_e)) return t; for (let r = 0; r < this.children.length; r++) this.children[r].collectAllFields(t); return t; } collectAllChildren(t) { t.push(this); for (let r = 0; r < this.children.length; r++) this.children[r].collectAllChildren(t); return t; } addChild(t) { this.children.indexOf(t) < 0 && this.children.push(t), this.store.children ??= [], this.store.children.indexOf(t.store) < 0 && this.store.children.push(t.store); } removeChild(t) { const r = this.children.indexOf(t); r > -1 && this.children.splice(r, 1), this.store.children ??= []; const n = this.store.children.indexOf(t.store); n > -1 && this.store.children.splice(n, 1); } invokeOnAfterKeyChanged(t, r) { this.#e?.onAfterKeyChanged.isSubscribed && this.#e.onAfterKeyChanged.invoke(t, r), this.parent?.invokeOnAfterKeyChanged(t, r); } invokeOnBeforeDeleted(t) { this.#e?.onBeforeDelete.isSubscribed && t.forEach((r) => this.#e?.onBeforeDelete.invoke(r, void 0)), this.parent?.invokeOnBeforeDeleted(t); } clearInitialData() { const t = this.initialData; t && H(t) && Object.keys(t).forEach((r) => delete t[r]); } } const [ /** * @returns the instance of the ComponentData of the currently rendered component. */ rt, /** * Context provider for the useComponentData hook. **Internal use only.** */ bn ] = St("ComponentDataContext"), Cn = (e) => { const { id: t } = rt(); return B(() => { const r = {}; return e.labeled && (r["aria-labelledby"] = `${t}-label`), r["aria-errormessage"] = `${t}-error`, r; }, [t, e.labeled]); }, Vn = () => { const { id: e } = rt(); return B(() => ({ "aria-errormessage": `${e}-error` }), [e]); }, Dn = () => { const { field: e } = rt(), t = !!e?.error; return B(() => ({ "aria-invalid": t }), [t]); }, ms = (e) => { const t = Dn(), r = Cn(e); return B(() => ({ ...r, ...t }), [r, t]); }; class lt { /** * Creates component metadata for the form viewer. * @param component the React component. * @param name the component name. * @param actionsInitializer the function to initialize actions in the component. * @param valued the name of the component property where the component value is stored. * @param valueType the type of the component value. * @param defaultProps the component's default property values. * @param css the component's CSS values. * @param wrapperCss the component's wrapper CSS values. * @param typeName the component type name. * @param kind the component kind. * @param readOnly the name of the component property that stores the read-only flag. * @param propsBindingTypes the component property binding types. * @param uncontrolledValue the value for the uncontrolled (undefined) state. * @param disabled the name of the component property that stores the disabled flag. * @param dataBindingType the type of component data binding. * @param features the component features that provide additional information about component's characteristic. * @template T the type of React component properties. */ constructor(t, r, n, o, i, s, a, c, d, f = "component", g, h = {}, C, w, R = "none", q = {}) { this.actionsInitializer = n, this.valued = o, this.valueType = i, this.defaultProps = s, this.css = a, this.wrapperCss = c, this.typeName = d, this.kind = f, this.readOnly = g, this.propsBindingTypes = h, this.uncontrolledValue = C, this.disabled = w, this.dataBindingType = R, this.features = q, this.valued && this.dataBindingType === "none" && (this.dataBindingType = "twoWay"), this.component = Me(t), this.component.displayName = t.displayName || t.name, this.#t = r; } #t; /** * The React component. */ component; /** * @returns the component name, or type if there is no component name. */ get name() { return this.#t ?? this.type; } /** * @returns the component type name. */ get type() { return this.typeName || this.component.displayName || this.component.name; } /** * Returns true if feature is present in the component feature set and equals value, false otherwise. * @param name the feature name. * @param value the feature value. * @returns true if feature is present in the component feature set and equals value, false otherwise. */ hasFeatureValue(t, r) { const n = this.features[t]; return n ? qe(t).allowMultiple ? Array.isArray(n) ? n.indexOf(r) >= 0 : !1 : n === r : !1; } /** * Returns true if feature is present in the component feature set and equals `true`, false otherwise. * @param name the feature name. * @returns true if feature is present in the component feature set and equals `true`, false otherwise. */ isFeatureEnabled(t) { return this.features[t] === !0; } /** * Returns true if the role is defined in the component's roles, false otherwise. * @param value the component role. * @returns true if the role is defined in the component's roles, false otherwise. */ hasComponentRole(t) { return this.hasFeatureValue(te, t); } } const En = J` font-size: 12px; color: var(--red-600); margin-top: 0.25rem; &:before { content: "❌ "; font-size: 10px; padding: 6px; } @media (prefers-color-scheme: dark) { color: var(--red-300); } `, Sn = J` display: flex; flex-direction: column; width: 100%; height: 100%; `, ar = ({ children: e, error: t, className: r }) => { const n = Vn(); return /* @__PURE__ */ Ke("div", { className: Sn, children: [ e, t && /* @__PURE__ */ y("p", { id: n["aria-errormessage"], className: tt(r, En), children: t }) ] }); }; ar.displayName = "DefaultErrorMessage"; const Pn = Yt( {}, { name: te, value: "error-message" }, { name: Et, value: !0 } ), Ve = new lt( ar, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, void 0, Pn ); class ct { /** * The component property key. */ key; /** * The component property name. */ name; /** * The name of the component's property editor. */ editor; /** * The hint for the component property. */ hint; /** * True if the property value can be localized, false otherwise. */ localizable = !1; /** * True if the property value is bound to form data, false otherwise. */ valued = !1; /** * The type of component data binding. */ dataBindingType = "none"; /** * True if the property value controls a read-only flag, false otherwise. */ readOnly = !1; /** * True if the property value controls a disabled flag, false otherwise. */ disabled = !1; /** * True if the property value controls a required flag, false otherwise. */ controlsRequiredProp = !1; /** * Additional properties for the component property editor. */ editorProps; /** * The default property value. */ default; /** * The property value for the uncontrolled state. */ uncontrolledValue; /** * The data type for the value of the property. */ type; /** * True if the component property is required, false otherwise. */ required = !1; /** * The function for validating the property value. */ validator; /** * Message and/or error code for the validation function. */ errorMap; /** * True if the property value can be a calculated property, false otherwise. */ calculable = !0; /** * A function that returns a string containing the source code of the function to bind child components. * @param props the properties of the component, which are available only inside Form Builder Designer. */ slotConditionBuilder; /** * The component property binding type. */ bindingType; /** * Creates metadata for a React component property. * @param key the property name. * @param name the human-readable property name. */ constructor(t, r) { this.key = t, this.name = r; } /** * @returns the metadata clone. */ clone() { return Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this)); } } class Fn extends ct { /** * The function that checks whether a child component can be inserted into a parent component. */ insertPredicate; /** * The default editor. */ defaultEditor; /** * Returns the node editor type for the component property. * @param componentProperty the component property. * @returns the node editor type for the component property. */ getNodeEditorType(t) { return t?.editorType ?? this.defaultEditor ?? "node"; } } class xn extends ct { } class An extends ct { } class lr extends ct { /** * Possible values for the property. */ data; } const ys = (e) => e instanceof lr; class Tn extends ct { } const gs = "HH:mm:ss", Rn = { Property: lr, Container: Fn, Event: xn, Module: An, Style: Tn }; class On { /** * Type of component property description in the form builder. */ annotationType = "Module"; /** * Flag if true, the property name will be automatically converted in the designer from a camel case string to a human-readable string. */ autoName = !0; } class cr { /** * Partial metadata for a component property. */ annotation; /** * Options for building an annotation. */ options = new On(); /** * @returns the main component property that is used as form data and for validation rules. */ get valued() { return this.setup({ valued: !0, dataBindingType: "twoWay" }); } /** * @returns the main property of the component that uses the form data as data (one-way data binding). */ get dataBound() { return this.setup({ valued: !0, dataBindingType: "oneWay" }); } /** * Sets the value for the property that prevents uncontrolled state. * @param uncontrolledValue the value for the uncontrolled state. * @returns the modified instance of the builder. */ uncontrolledValue(t) { return this.setup({ uncontrolledValue: t }); } /** * @returns the component property that can be localized. */ get localize() { return this.setup({ localizable: !0 }); } /** * @returns the non-localizable component property. */ get notLocalize() { return this.setup({ localizable: !1 }); } /** * Specifies the name of the component property. * @param name the property name. * @returns the modified instance of the builder. */ named(t) { return this.setup({ name: t }); } /** * Adds the hint to the property name of the component. * @param hint the hint. * @returns the modified instance of the builder. */ hinted(t) { return this.setup({ hint: t }); } /** * Marks the component property as calculable. * @param calculable true if the property is calculable. * @returns the modified instance of the builder. */ calculable(t) { return this.setup({ calculable: t }); } /** * Modifies the component property metadata builder with custom options. * @param options the custom options. * @returns the modified instance of the builder. */ setup(t) { const { annotationType: r, autoName: n, ...o } = t, i = this.clone(); return i.options.annotationType = r ?? i.options.annotationType, i.options.autoName = n ?? i.options.autoName, Object.assign(i.annotation, o), i; } /** * Clones the instance of the builder. * @returns the cloned instance of the builder. */ clone() { const t = Q(this); return t.annotation ??= {}, t; } /** * Creates component property metadata for the form builder. * @param key the unique key of the component property. * @returns the instance of the component property metadata for the form builder. */ build(t) { const r = this.getName(t), n = new Rn[this.options.annotationType](t, r); return Object.assign(n, this.annotation), n; } /** * Sets custom properties for the component's property editor. * @param props the custom properties * @returns the modified instance of the builder. */ withEditorProps(t) { const r = this.clone(); return Object.assign(r.annotation, { editorProps: t }), r; } /** * Hides the component property editor. * @returns the modified instance of the builder. */ hideEditor() { const t = this.clone(); return Object.assign(t.annotation, { editor: void 0 }), t; } /** * Returns the annotation name. * @param key the property name * @returns the annotation name. */ getName(t) { return this.annotation.name ?? (this.options.autoName ? ir(t) : t); } } class ie extends cr { /** * Marks the component property as required. * @returns the modified instance of the builder. */ get required() { return this.setup({ required: !0 }); } /** * Sets the default value for the component property. * @param value the default value. * @returns the modified instance of the builder. */ default(t) { return this.setup({ default: t }); } /** * Modifies the component property metadata builder with validation properties. * @param validator the validation function. * @param errorMap the validation error settings. * @returns the modified instance of the builder. */ validated(t, r) { return this.setup({ validator: t, errorMap: r }); } } class gt extends ie { subType; /** * Sets the component's value type to an array of strings. * @returns the modified instance of the builder. */ get ofString() { const t = new gt().setup({ ...this.options, ...this.annotation, type: "array", editor: "arrayOfString" }); return t.subType = "string", t; } /** * Sets the component's value type to an array of objects. * @returns the modified instance of the builder. */ get ofObject() { const t = new gt().setup({ ...this.options, ...this.annotation, type: "array" }); return t.subType = "object", t; } } class ur extends ie { /** * Possible values for the property. */ values; /** * Labels for the possible values of the property. */ labels; /** * Marks the component property as required. * @returns the modified instance of the builder. */ get required() { return super.required; } /** * Sets the labels for predefined values. * @param labels the labels. * @returns the modified instance of the builder. */ labeled(...t) { const r = this.clone(); return r.labels = t, r; } /** * Creates component property metadata for the form builder. * @param key the unique key of the component property. * @returns the instance of the component property metadata for the form builder. */ build(t) { const r = super.build(t); return r.data = this.values.map((n, o) => ({ label: this.labels?.[o] ?? ir(n.toString()), value: n })), r; } /** * Sets the default value for the component property. * @param value the default value, can be an array of values. * @returns the modified instance of the builder. */ default(t) { return this.setup({ default: t }); } } class kn extends ur { /** * Sets the radio buttons as the component's property editor. * @returns the modified instance of the builder. */ radio() { return this.setup({ editor: "radio" }); } /** * Sets the default value for the component property. * @param value the default value. * @returns the modified instance of the builder. */ default(t) { return super.default(t); } } class Nn extends ur { /** * Sets the default value for the component property. * @param value the default value. * @returns the modified instance of the builder. */ default(t) { return super.default(t); } } class jn extends cr { /** * Creates a component property metadata builder. * @param editor the property editor type. * @template T the property type. */ constructor(t) { super(), this.annotation = { editor: t }; } /** * Creates a component property metadata builder. * @param editor the property editor type. * @template T the property type. * @returns the component property metadata builder. */ static create = (t) => new this(t); /** * Sets the property as a "array" property. * @returns the instance of the metadata property builder. */ get array() { return new gt().setup({ ...this.options, ...this.annotation, type: "array" }); } /** * Sets the field type for the component property. * @param type the field type. * @returns the instance of the metadata property builder. */ typed(t) { return new ie().setup({ ...this.options, ...this.annotation, type: t }); } /** * Sets the property as a "single select" property. * @param values the possible values for the property. * @returns the instance of the metadata property builder. */ oneOf(...t) { const r = new kn().setup({ ...this.options, ...this.annotation, type: "enum" }); return r.values = t, r; } /** * Sets the property as a "multiple select" property. * @param values the possible values for the property. * @returns the instance of the metadata property builder. */ someOf(...t) { const r = new Nn().setup({ ...this.options, ...this.annotation, type: "enum" }); return r.values = t, r; } } const se = jn.create, Z = se("size").setup({ calculable: !1 }), De = se("color").setup({ calculable: !1 }), dr = { width: Z.setup({ default: "100%" }), height: Z, marginTop: Z, marginInlineEnd: Z, marginBottom: Z, marginInlineStart: Z, color: De, backgroundColor: De }; function vt(e) { return se(e).setup({ annotationType: "Property" }); } const ft = vt("oneOf").oneOf.bind(vt("oneOf")), In = vt("size").typed("string"), hr = { flexDirection: ft("column", "row", "column-reverse", "row-reverse"), gap: In, alignItems: ft("start", "center", "baseline", "end", "stretch"), justifyContent: ft( "flex-start", "flex-end", "center", "space-between", "space-around", "space-evenly", "start", "end", "left", "right" ), flexWrap: ft("wrap", "nowrap", "wrap-reverse") }, zn = vt("string").typed("string").localize; function $n(e, t = {}) { const r = []; if (D(e)) return r; for (const n of Object.keys(e)) { const i = e[n]?.setup(t)?.build(n) ?? zn.setup(t).build(n); r.push(i); } return r; } function Ln(e) { return $n(e, { annotationType: "Style", calculable: !1 }); } function Kn(e) { return e.reduce((t, r) => (t[r.key] = r.default, t), {}); } function Mn(e) { return { any: { object: Kn(e) } }; } const Wn = parseInt(qr.version, 10), Bn = (e) => Wn >= 19 ? (r) => e(r, r.ref ?? null) : Ur(e), qn = J` display: flex; flex-direction: column; `, ae = Bn((e, t) => { const { className: r, children: n, ...o } = e, i = tt(qn, r); return /* @__PURE__ */ y("div", { className: i, "data-testid": "default-wrapper", ...o, ref: t, children: n }); }); ae.displayName = "Screen"; const { height: Hn } = dr, { flexDirection: Un, gap: Jn } = hr, _n = Ln({ ...hr, ...dr, height: Hn.setup({ default: "100%" }), flexDirection: Un.default("column"), gap: Jn.default("10px") }), Zn = Mn(_n), Gn = Yt( {}, { name: Et, value: !0 }, { name: He, value: !0 } ), wt = new lt( ae, void 0, void 0, void 0, void 0, void 0, Zn, void 0, void 0, "container", "readOnly", void 0, void 0, "disabled", void 0, Gn ), fr = "onDidMount", pr = "onWillUnmount"; function k(e, t) { const r = Me(t); return r.displayName = e, r; } const Qn = () => { z(() => { Gr({ enforceActions: "never" }); }, []); }; var at = /* @__PURE__ */ ((e) => (e.LTR = "ltr", e.RTL = "rtl", e))(at || {}); class Pt { /** * Creates a localization language for the form builder. * @param code the language code, for example, 'en'. * @param dialect the dialect code, for example, 'US'. * @param name the name of the language, for example 'English'. * @param description the description of the language, for example 'American English'. * @param bidi the type of text layout, for example, BiDi.LTR. */ constructor(t, r, n, o, i = at.LTR) { this.code = t, this.dialect = r, this.name = n, this.description = o, this.bidi = i; } /** * @returns the full code of the Language i.e. en-US, en-GB etc. */ get fullCode() { return `${this.code}-${this.dialect}`; } /** * Clones an existing instance of the language. * @param source the cloning object. * @returns the object clone. */ static clone(t) { return new Pt(t.code, t.dialect, t.name, t.description, t.bidi); } } const bt = new Pt("en", "US", "English", "American English"), [ /** * **Internal use only.** */ L, /** * **Internal use only.** */ Xn, /** * **Internal use only.** */ Yn ] = St("StoreContext"), Ee = { LTR: me({ key: at.LTR }), RTL: me({ key: at.RTL, prepend: !0 }) }, to = J` display: flex; width: 100%; height: 100%; `, eo = "optimajet-formviewer", ro = tt(eo, to), mr = ([e, ...t], r, n) => e ? /* @__PURE__ */ y(e, { language: r, children: mr(t, r, n) }) : n, no = (e) => { const t = L(), r = t.displayedLanguage, n = r.bidi == at.RTL ? Ee.RTL : Ee.LTR; z(() => { t.formViewerPropsStore.view.getCssLoaders(r.bidi).forEach((s) => { s().catch((a) => console.error(a)); }); }, [r, t.formViewerPropsStore.view]); const o = /* @__PURE__ */ y("div", { dir: r.bidi, lang: r.fullCode, className: ro, children: /* @__PURE__ */ y(Qr, { value: n, children: e.children }) }); return mr(t.formViewerPropsStore.view.viewerWrappers, r, o); }, oo = k("ViewerLocalizationProvider", no), io = (e) => { if (typeof e == "string") return e; if (e && typeof e == "object" && "message" in e) { const t = e.message; if (typeof t == "string") return t; } return ""; }, so = ({ children: e }) => { const [t] = _t(globalThis.onerror); return z(() => (globalThis.onerror = (r) => { if (io(r).includes("ResizeObserver")) { const o = document.getElementById( "webpack-dev-server-client-overlay-div" ), i = document.getElementById( "webpack-dev-server-client-overlay" ); return i && i.setAttribute("style", "display: none"), o && o.setAttribute("style", "display: none"), !0; } return !1; }, () => { globalThis.onerror = t; }), [t]), /* @__PURE__ */ y(Ut, { children: e }); }; function Ft(e) { return typeof e == "object" && typeof e.then == "function"; } const [ /** * **Internal use only.** */ ut, /** * **Internal use only.** */ ao ] = St("FormViewerPropsContext"); function yr(e) { return e.message ?? `Validation failed: ${e.settings.key}`; } class xt { constructor(t, r, n, o, i) { this.setter = o; const s = (a) => i?.(a) ?? a.map(yr); this.#t = async (a, c = !1) => { const d = await n(a, t, r); if (!(!d || d.length === 0)) return c && !t.showAllValidationErrors ? s([d[0]]) : s(d); }; } #t; /** * Creates a DataValidator instance. * @param store the form viewer settings. * @param getFormData the function that returns a form data. * @param resolver the validation function factory. * @param args the validation function factory arguments. * @param setter the callback function called to set a validation error. * @param localizer the function that localizes validation error messages. * @template T the validation function factory arguments. * @returns the DataValidator instance. */ static create = (t, r, n, o, i, s) => new xt(t, r, n(o), i, s); /** * Generates an event to perform validation. * @param value the validated value. */ sendValidationEvent = (t) => { pn(this.validate, 200)(t)?.catch(console.error); }; /** * Performs a validation of the value. * @param value the validated value. * @returns the Promise with the result of the validation. */ validate = async (t) => { const n = (await this.#t(t, !0))?.join(" "); return this.setter(n), n; }; /** * Returns the validation res