@dmitryvim/form-builder 0.5.4 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/browser/formbuilder.min.js +136 -154
- package/dist/browser/formbuilder.v0.6.4.min.js +1472 -0
- package/dist/cjs/index.cjs +423 -445
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +368 -394
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +136 -154
- package/dist/types/components/container.d.ts +0 -7
- package/dist/types/components/index.d.ts +1 -2
- package/dist/types/instance/FormBuilderInstance.d.ts +17 -4
- package/dist/types/instance/state.d.ts +8 -0
- package/dist/types/types/component-operations.d.ts +15 -0
- package/dist/types/types/config.d.ts +2 -0
- package/dist/types/types/state.d.ts +8 -0
- package/dist/types/utils/helpers.d.ts +18 -1
- package/dist/types/utils/styles.d.ts +13 -7
- package/package.json +1 -1
- package/dist/browser/formbuilder.v0.5.4.min.js +0 -1490
|
@@ -2,13 +2,6 @@ import type { ContainerElement, RenderContext, ComponentContext, ValidationResul
|
|
|
2
2
|
export declare function setRenderElement(fn: (element: any, ctx: RenderContext) => HTMLElement): void;
|
|
3
3
|
export declare function renderSingleContainerElement(element: ContainerElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
4
4
|
export declare function renderMultipleContainerElement(element: ContainerElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
5
|
-
export declare function setValidateElement(fn: (element: Element, ctx: {
|
|
6
|
-
path: string;
|
|
7
|
-
}, customScopeRoot?: HTMLElement | null) => {
|
|
8
|
-
value: any;
|
|
9
|
-
spread: boolean;
|
|
10
|
-
skip?: boolean;
|
|
11
|
-
}): void;
|
|
12
5
|
/**
|
|
13
6
|
* Validate container field and return extracted value with errors
|
|
14
7
|
*/
|
|
@@ -7,10 +7,9 @@ import { renderSwitcherElement, renderMultipleSwitcherElement } from "./switcher
|
|
|
7
7
|
import { renderFileElement, renderFilesElement, renderMultipleFileElement } from "./file.js";
|
|
8
8
|
import { renderColourElement, renderMultipleColourElement } from "./colour.js";
|
|
9
9
|
import { renderSliderElement, renderMultipleSliderElement } from "./slider.js";
|
|
10
|
-
import { renderSingleContainerElement, renderMultipleContainerElement
|
|
10
|
+
import { renderSingleContainerElement, renderMultipleContainerElement } from "./container.js";
|
|
11
11
|
import { renderGroupElement } from "./group.js";
|
|
12
12
|
import { renderTableElement } from "./table.js";
|
|
13
13
|
import { renderRichInputElement } from "./richinput.js";
|
|
14
14
|
export declare function renderElement(element: Element, ctx: RenderContext): HTMLElement;
|
|
15
|
-
export { setContainerValidateElement };
|
|
16
15
|
export { renderTextElement, renderMultipleTextElement, renderTextareaElement, renderMultipleTextareaElement, renderNumberElement, renderMultipleNumberElement, renderSelectElement, renderMultipleSelectElement, renderSwitcherElement, renderMultipleSwitcherElement, renderFileElement, renderFilesElement, renderMultipleFileElement, renderColourElement, renderMultipleColourElement, renderSliderElement, renderMultipleSliderElement, renderSingleContainerElement, renderMultipleContainerElement, renderGroupElement, renderTableElement, renderRichInputElement, };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Schema, ExternalAction, FormData as FormDataResult, Config, State } from "../types/index.js";
|
|
1
|
+
import type { Schema, ExternalAction, FormData as FormDataResult, Config, Locale, State } from "../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* FormBuilderInstance - Encapsulates all form state and operations
|
|
4
4
|
* Allows multiple independent forms on the same page without state collisions
|
|
@@ -6,6 +6,7 @@ import type { Schema, ExternalAction, FormData as FormDataResult, Config, State
|
|
|
6
6
|
export declare class FormBuilderInstance {
|
|
7
7
|
private state;
|
|
8
8
|
private instanceId;
|
|
9
|
+
private prefillHintHandler;
|
|
9
10
|
constructor(config?: Partial<Config>);
|
|
10
11
|
/**
|
|
11
12
|
* Get instance ID (useful for debugging and resource prefixing)
|
|
@@ -20,7 +21,9 @@ export declare class FormBuilderInstance {
|
|
|
20
21
|
*/
|
|
21
22
|
setFormRoot(element: HTMLElement): void;
|
|
22
23
|
/**
|
|
23
|
-
* Configure the form builder
|
|
24
|
+
* Configure the form builder. Translations deep-merge per locale (same as
|
|
25
|
+
* the constructor); a locale without translations — configured or default —
|
|
26
|
+
* is rejected, matching setLocale.
|
|
24
27
|
*/
|
|
25
28
|
configure(config: Partial<Config>): void;
|
|
26
29
|
/**
|
|
@@ -44,9 +47,10 @@ export declare class FormBuilderInstance {
|
|
|
44
47
|
*/
|
|
45
48
|
setMode(mode: "edit" | "readonly"): void;
|
|
46
49
|
/**
|
|
47
|
-
* Set locale
|
|
50
|
+
* Set locale. Custom locales are allowed — their translations must have
|
|
51
|
+
* been provided via the constructor or configure() first.
|
|
48
52
|
*/
|
|
49
|
-
setLocale(locale:
|
|
53
|
+
setLocale(locale: Locale): void;
|
|
50
54
|
/**
|
|
51
55
|
* Trigger onChange callbacks with debouncing
|
|
52
56
|
* @param fieldPath - Optional field path for field-specific change events
|
|
@@ -139,6 +143,13 @@ export declare class FormBuilderInstance {
|
|
|
139
143
|
* Save draft without validation
|
|
140
144
|
*/
|
|
141
145
|
saveDraft(): FormDataResult;
|
|
146
|
+
/**
|
|
147
|
+
* Post form data to the parent frame — only when the host opted in via
|
|
148
|
+
* `postMessageTarget`. Outside an iframe `window.parent === window`, so an
|
|
149
|
+
* unconditional post broadcast form data and the full schema to any
|
|
150
|
+
* embedding page (targetOrigin "*") on every submit. See CHANGELOG 0.6.0.
|
|
151
|
+
*/
|
|
152
|
+
private postToParent;
|
|
142
153
|
/**
|
|
143
154
|
* Clear the form - reset all field values to empty while preserving form structure
|
|
144
155
|
* This is done by re-rendering the form with empty data
|
|
@@ -191,5 +202,7 @@ export declare class FormBuilderInstance {
|
|
|
191
202
|
*/
|
|
192
203
|
destroy(): void;
|
|
193
204
|
private disconnectEnableIfObservers;
|
|
205
|
+
private disconnectAutoExpandObservers;
|
|
206
|
+
private removePrefillHintListener;
|
|
194
207
|
private removeTooltipElements;
|
|
195
208
|
}
|
|
@@ -3,6 +3,14 @@ import type { State, Config } from "../types/index.js";
|
|
|
3
3
|
* Default configuration for new instances
|
|
4
4
|
*/
|
|
5
5
|
export declare const defaultConfig: Config;
|
|
6
|
+
/**
|
|
7
|
+
* Merge user-provided translations over a base map, per locale — the base
|
|
8
|
+
* packs survive, and each provided locale merges over the base's same-locale
|
|
9
|
+
* pack. Used by the constructor and configure(); a wholesale replacement
|
|
10
|
+
* (Object.assign) dropped the default en/ru packs and made t() return key
|
|
11
|
+
* names.
|
|
12
|
+
*/
|
|
13
|
+
export declare function mergeTranslations(base: Config["translations"], overrides: Partial<Config>["translations"]): Config["translations"];
|
|
6
14
|
/**
|
|
7
15
|
* Create a new isolated state object for a FormBuilderInstance
|
|
8
16
|
* Uses deep merge for translations to preserve default en/ru fallbacks
|
|
@@ -15,6 +15,21 @@ export interface ComponentContext {
|
|
|
15
15
|
path: string;
|
|
16
16
|
/** Skip validation checks (for draft mode) */
|
|
17
17
|
skipValidation?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Recursive element validator, threaded per validateForm pass by
|
|
20
|
+
* FormBuilderInstance. Containers use it to validate children with the
|
|
21
|
+
* instance's full context. Threaded through the context — never a module
|
|
22
|
+
* global — so per-instance state cannot leak between instances (the old
|
|
23
|
+
* setContainerValidateElement setter only worked because validateForm is
|
|
24
|
+
* synchronous and re-set it before every pass).
|
|
25
|
+
*/
|
|
26
|
+
validateElement?: (element: Element, ctx: {
|
|
27
|
+
path: string;
|
|
28
|
+
}, customScopeRoot?: HTMLElement | null) => {
|
|
29
|
+
value: any;
|
|
30
|
+
spread: boolean;
|
|
31
|
+
skip?: boolean;
|
|
32
|
+
};
|
|
18
33
|
}
|
|
19
34
|
/**
|
|
20
35
|
* Validation result from a component validator
|
|
@@ -23,6 +23,7 @@ export interface Translations {
|
|
|
23
23
|
openInNewTab: string;
|
|
24
24
|
changeButton: string;
|
|
25
25
|
placeholderText: string;
|
|
26
|
+
selectPlaceholder?: string;
|
|
26
27
|
previewAlt: string;
|
|
27
28
|
previewUnavailable: string;
|
|
28
29
|
previewError: string;
|
|
@@ -110,6 +111,7 @@ export interface Config {
|
|
|
110
111
|
onDownloadError: ((error: Error, resourceId: string, fileName: string) => void) | null;
|
|
111
112
|
debounceMs: number;
|
|
112
113
|
verboseErrors: boolean;
|
|
114
|
+
postMessageTarget: string | null;
|
|
113
115
|
enableFilePreview: boolean;
|
|
114
116
|
maxPreviewSize: string;
|
|
115
117
|
readonly: boolean;
|
|
@@ -23,6 +23,14 @@ export interface State {
|
|
|
23
23
|
* with a torn-down ctx. Reproducible under React StrictMode (double mount).
|
|
24
24
|
*/
|
|
25
25
|
enableIfObservers: Set<MutationObserver>;
|
|
26
|
+
/**
|
|
27
|
+
* ResizeObservers created by applyAutoExpand (text/textarea/richinput
|
|
28
|
+
* auto-height). Each observer's own callback disconnects it when its
|
|
29
|
+
* textarea has left the DOM — but that check only runs if the observer ever
|
|
30
|
+
* fires again, so a silently removed field held its observer forever.
|
|
31
|
+
* destroy() and every renderForm() disconnect the whole set.
|
|
32
|
+
*/
|
|
33
|
+
autoExpandObservers: Set<ResizeObserver>;
|
|
26
34
|
/**
|
|
27
35
|
* Info-button tooltip nodes created by this instance. They live on
|
|
28
36
|
* document.body (position: fixed, moved there so tile overflow can't clip
|
|
@@ -47,11 +47,16 @@ export declare function clear(node: HTMLElement): void;
|
|
|
47
47
|
export declare function formatFileSize(bytes: number): string;
|
|
48
48
|
/**
|
|
49
49
|
* Serialize a value for storage in a hidden input's value attribute.
|
|
50
|
-
*
|
|
50
|
+
* undefined → "", everything else — null included — → JSON.
|
|
51
51
|
*
|
|
52
52
|
* JSON for every type — including strings — so deserialization is exact.
|
|
53
53
|
* The previous String() form was lossy: a hidden text field prefilled with
|
|
54
54
|
* "true" or "123" came back from getFormData() as a boolean/number.
|
|
55
|
+
*
|
|
56
|
+
* null serializes as JSON "null" (not "") so that an explicit null survives
|
|
57
|
+
* the round-trip: "" used to be re-read as "unset", which let the hidden
|
|
58
|
+
* validator substitute element.default — updateField(key, null) on a field
|
|
59
|
+
* with a default could never actually produce null.
|
|
55
60
|
*/
|
|
56
61
|
export declare function serializeHiddenValue(value: any): string;
|
|
57
62
|
/**
|
|
@@ -62,6 +67,18 @@ export declare function serializeHiddenValue(value: any): string;
|
|
|
62
67
|
* (not through serializeHiddenValue) — hosts poking the input by hand.
|
|
63
68
|
*/
|
|
64
69
|
export declare function deserializeHiddenValue(raw: string): any;
|
|
70
|
+
/**
|
|
71
|
+
* Read an input's value the way typed extraction reports it — the DOM
|
|
72
|
+
* scrapers feeding enableIf (extractDOMValue, extractRootFormData) must
|
|
73
|
+
* agree with getFormData() for SCALAR fields, or a condition flips on the
|
|
74
|
+
* keystroke and is corrected only by the debounced pass (visible flicker):
|
|
75
|
+
* empty scalar -> null, number/range -> number (rounded per data-decimals),
|
|
76
|
+
* checkbox -> boolean, data-hidden-field -> JSON. Radio stays with the
|
|
77
|
+
* callers (needs a :checked query against a scope). Composite fields (file,
|
|
78
|
+
* table, richinput) extract arrays/objects that no single input carries —
|
|
79
|
+
* the parity guarantee does not extend to them.
|
|
80
|
+
*/
|
|
81
|
+
export declare function readTypedInputValue(input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): any;
|
|
65
82
|
/**
|
|
66
83
|
* Create a hidden input element for a hidden form field.
|
|
67
84
|
*/
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type { State } from "../types/index.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
* Mark an input's validity: toggle the `invalid` class/title and create,
|
|
4
|
+
* update or remove the paired `.error-message` node. Shared by every scalar
|
|
5
|
+
* component's validator — this used to be six near-identical copies, each
|
|
6
|
+
* with its own `error-${Math.random()}` fallback id.
|
|
7
|
+
*/
|
|
8
|
+
export declare function markFieldValidity(input: HTMLElement | null, errorMessage: string | null): void;
|
|
9
|
+
/**
|
|
10
|
+
* Strip the `.error-message` node paired with an input. Called from
|
|
11
|
+
* updateField paths so a programmatic update to a valid value clears any
|
|
12
|
+
* stale error surface left over from the previous validation pass —
|
|
13
|
+
* otherwise the field stays visibly "invalid" until the next validate cycle.
|
|
9
14
|
*/
|
|
10
15
|
export declare function clearFieldError(input: HTMLElement): void;
|
|
11
16
|
/**
|
|
@@ -53,8 +58,9 @@ export declare function ensureThemingHooks(doc: Document): void;
|
|
|
53
58
|
* where width hasn't moved — otherwise our own height writes would feed back
|
|
54
59
|
* into the observer.
|
|
55
60
|
*/
|
|
56
|
-
export declare function applyAutoExpand(textarea: HTMLTextAreaElement, options
|
|
61
|
+
export declare function applyAutoExpand(textarea: HTMLTextAreaElement, options: {
|
|
57
62
|
minRows?: number;
|
|
63
|
+
observers: Set<ResizeObserver>;
|
|
58
64
|
}): void;
|
|
59
65
|
/**
|
|
60
66
|
* Enforce single-line semantics on a textarea: block the Enter key and
|