UNPKG

@react-form-builder/core

Version:

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

363 lines (362 loc) 10.4 kB
import v from "clsx"; import { makeAutoObservable as A } from "mobx"; import { calculateProperties as w } from "../features/calculation/propertyCalculator.js"; import { silentTransformCssString as p } from "../features/css-style/cssTransform.js"; import { cfRequiredProperties as O, cfEventHandlers as P } from "../features/define/utils/integratedComponentFeatures.js"; import { isFunctionArgumentValue as E, getArgumentFunction as N } from "../features/event/consts/functionArgument.js"; import { DidMountEvent as m, WillUnmountEvent as g } from "../features/event/eventNames.js"; import { ActionEventArgs as h } from "../features/event/utils/ActionEventArgs.js"; import { getDefaultPropertiesContext as j } from "../features/properties-context/getDefaultPropertiesContext.js"; import { isPromise as S } from "../utils/isPromise.js"; import { nameObservable as x } from "../utils/observableNaming.js"; import { ComponentStore as D } from "./ComponentStore.js"; import { generateClass as f, reactStylesToCss as y, flattenNestedCSS as R } from "./css.js"; const F = (o) => { const t = o.features[P]; if (t) return t; }, q = (o) => o.htmlAttributes?.reduce((t, { name: e, value: s }) => { try { t[e] = JSON.parse(s); } catch { t[e] = s; } return t; }, {}), H = (o, t) => { const e = []; for (const [r, n] of Object.entries(t)) if (E(n)) { const i = N(n.body || ""); e.push([r, i]); } const s = { ...t }; for (const [r, n] of e) s[r] = (i, a, ...l) => !(i instanceof h) && a !== s ? n(o, s, ...l) : n(i, a, ...l); return s; }; function k(o, t) { const e = t.map((s) => ({ func: o.findAction(s).func, args: { ...s.args } })); return async (s) => { try { for (const { func: r, args: n } of e) { const i = H(s, n), a = r(s, i); S(a) && await a; } } catch (r) { console.info("Action handler throws an error", r); } }; } const b = (o, t) => async (...e) => { const { data: s, store: r } = o, n = s.store.events?.[t] ?? [], i = k(r, n), a = o.get, l = new h(t, s, r, e, a, o.context.cellInfo); await i(l); }, V = (o) => { const t = {}, { data: e } = o, s = F(e.model) ?? o.context.eventHandlers ?? {}, r = [ ...Object.keys(e.store.events ?? {}), ...Object.keys(s) ], n = new Set(r); return n.delete(m), n.delete(g), n.forEach((i) => { t[i] = async (...a) => { const l = s[i]; if (l) { const c = new h( i, e, o.store, a, o.get, o.context.cellInfo ), d = l(c); S(d) && await d; } await b(o, i)(...a); }; }), t; }; class X { /** * Creates an instance that calculates the properties of the form viewer component. * @param data the data needed to display the component. * @param store the form viewer settings. * @param localizer the function to localize the properties of a component, returns a Record with localized properties. * @param computeChildren the function that calculates all child properties of a component. * @param context the context for working with component properties. */ constructor(t, e, s, r, n) { this.data = t, this.store = e, this.localizer = s, this.computeChildren = r, this.context = n ?? j(t), this.#e = null, A(this, void 0, { name: x("ComponentState", { key: t.key }) }); } data; store; localizer; computeChildren; #t = { css: { className: f() }, wrapperCss: { className: f("wc-") } }; /** * The ref object associated with this component in the viewer. **Internal use only.** */ #e; /** * The context for working with component properties. */ context; /** * @inheritDoc */ get get() { const t = this.propsWithoutChildren; return Object.assign({}, t, { className: this.className }, this.children(t)); } /** * @inheritDoc */ get ownProps() { return { ...this.propsWithoutChildren, className: this.className }; } /** * @inheritDoc */ get propsWithoutChildren() { const { htmlAttributes: t, ...e } = this.calculatedProps; return Object.assign( { key: this.data.store.key }, this.data.model.defaultProps, e, this.localizedProps, this.value, this.readOnly, this.required, this.disabled, this.events, t ?? this.htmlAttributes, this.style, this.data.userDefinedProps ); } /** * @returns the component's field value data, if the component can have a field value. */ get value() { const t = this.context.valueProperty; if (t) return { [t.propertyName]: t.propertyValue }; } /** * @returns the read-only property of a component if the component has a read-only flag. */ get readOnly() { if (this.data.model.readOnly) return { [this.data.model.readOnly]: this.isReadOnly }; } /** * @returns the required property of a component if the component has a required flag. */ get required() { const t = this.data.model.features[O]; if (!t || !this.hasRequiredValidation) return; const e = {}; return t.forEach((s) => e[s] = !0), e; } /** * @inheritDoc */ get isReadOnly() { const t = this.data.model.readOnly && this.selfProps[this.data.model.readOnly]; return this.store.formViewerPropsStore.readOnly || this.data.parent?.componentState.isReadOnly || (t ?? !1); } /** * @returns the disabled property of a component if the component has a disabled flag. */ get disabled() { if (this.data.model.disabled) return { [this.data.model.disabled]: this.isDisabled }; } /** * @inheritDoc */ get isDisabled() { const t = this.data.model.disabled && this.selfProps[this.data.model.disabled]; return this.store.formViewerPropsStore.disabled || this.data.parent?.componentState.isDisabled || (t ?? !1); } /** * @returns the values for all properties of the component, calculates the values of the calculated properties. */ get calculatedProps() { return w(this.data.store, this.data.dataRoot); } /** * @returns component localized properties. */ get localizedProps() { return this.localizer(this.data.store); } /** * @returns the component event handlers that send events to the event bus. */ get events() { return V(this); } /** * Calculates and returns className property. * @returns the Record that contains the className property for the component. */ get className() { return v( this.requiredClassName, this.propsWithoutChildren.className, this.#t.css.className ); } /** * @inheritDoc */ get wrapperClassName() { return this.#t.wrapperCss.className; } /** * @returns the Record that contains the style property for the component. */ get style() { return this.getStyleFromStylePart(this.data.store.style); } /** * @inheritDoc */ get wrapperStyle() { return this.getStyleFromStylePart(this.data.store.wrapperStyle); } /** * @returns all arbitrary HTML attributes of the component. */ get htmlAttributes() { return q(this.data.store); } /** * Calculates and returns all child components. * @param props the React component properties. * @returns the Record that contains the child components of a component. */ children(t) { return this.computeChildren(this.data, t); } /** * @inheritDoc */ onDidMount() { this.executeLifecycleEvent(m), this.applyAllStyles(); } /** * @inheritDoc */ onWillUnmount() { this.executeLifecycleEvent(g), this.cleanStyles(); } /** * @inheritDoc */ applyStyles(t, e) { e && this.updateAdoptedStyleSheets(t, e); } applyAllStyles() { this.applyStyles("css", this.flatCss), this.applyStyles("wrapperCss", this.flatWrapperCss); } /** * Clears component styles. */ cleanStyles() { const t = []; Object.values(this.#t).forEach((e) => { e.styleSheet && t.push(e.styleSheet), e.styleSheet = void 0, e.flatCss = void 0; }), t.length && (document.adoptedStyleSheets = document.adoptedStyleSheets.filter((e) => !t.includes(e))); } /** * @inheritDoc */ setRef = (t) => { this.#e = t; }; /** * @inheritDoc */ getRefValue = () => this.#e; executeLifecycleEvent(t) { const e = b(this, t), s = new h(t, this.data, this.store, [], this.get, this.context.cellInfo); e(s).catch(console.error); } getStyleFromStylePart(t) { const { viewMode: e } = this.store, s = p(t?.any?.string), r = p(t?.[e]?.string); if (s || r) return { style: { ...s, ...r } }; } /** * @inheritDoc */ get flatCss() { return this.computeFlatCssForPart("css"); } /** * @inheritDoc */ get flatWrapperCss() { return this.computeFlatCssForPart("wrapperCss"); } computeFlatCssForPart(t) { const { model: e, store: s } = this.data, { viewMode: r } = this.store, n = y(Object.assign( {}, e[t]?.any?.object, s[t]?.any?.object )), i = y(Object.assign( {}, e[t]?.[r]?.object, s[t]?.[r]?.object )), a = s[t]?.any?.string ? s[t]?.any?.string?.replaceAll(` `, " ") : "", l = s[t]?.[r]?.string ? s[t]?.[r]?.string?.replaceAll(` `, " ") : "", u = [n, i, a, l].map((C) => C?.trim()).filter(Boolean); if (!u.length) return ""; const c = this.#t[t].className, d = `.${c}.${c} {` + u.join(` `) + "}"; return R(d); } updateAdoptedStyleSheets(t, e) { try { const s = this.#t[t], r = s.styleSheet; if (r) { s.flatCss !== e && (r.replaceSync(e), s.flatCss = e); return; } const n = new CSSStyleSheet(); n.replaceSync(e), s.styleSheet = n, s.flatCss = e, document.adoptedStyleSheets.push(n); } catch (s) { console.error(s); } } get selfProps() { const { htmlAttributes: t, ...e } = this.calculatedProps; return { ...this.data.model.defaultProps, ...e, ...this.localizedProps, ...this.value, ...this.style, ...this.data.userDefinedProps }; } get hasRequiredValidation() { return D.hasValidationRule(this.data.store, "required"); } get requiredClassName() { if (this.hasRequiredValidation) return { required: !0 }; } } export { X as ComponentState }; //# sourceMappingURL=ComponentState.js.map