@dmitryvim/form-builder 0.2.25 → 0.2.27
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 +68 -14
- package/dist/browser/formbuilder.min.js +461 -193
- package/dist/browser/formbuilder.v0.2.27.min.js +874 -0
- package/dist/cjs/index.cjs +1793 -1098
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +1773 -1091
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +461 -193
- package/dist/types/components/file/constraints.d.ts +26 -0
- package/dist/types/components/file/dom.d.ts +44 -0
- package/dist/types/components/file/preview.d.ts +69 -0
- package/dist/types/components/file/render-edit.d.ts +15 -0
- package/dist/types/components/file/render-readonly.d.ts +23 -0
- package/dist/types/components/file/styles.d.ts +1 -0
- package/dist/types/components/file/upload.d.ts +13 -0
- package/dist/types/components/file/validate.d.ts +13 -0
- package/dist/types/components/file.d.ts +5 -27
- package/dist/types/types/config.d.ts +4 -0
- package/dist/types/types/schema.d.ts +2 -0
- package/dist/types/utils/helpers.d.ts +6 -0
- package/package.json +1 -1
- package/dist/browser/formbuilder.v0.2.25.min.js +0 -606
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface FileUploadConstraints {
|
|
2
|
+
maxCount: number;
|
|
3
|
+
allowedExtensions: string[];
|
|
4
|
+
maxSize: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Extract allowed file extensions from the `accept` schema property.
|
|
8
|
+
* Returns lowercase extension strings without leading dots.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getAllowedExtensions(accept: string | {
|
|
11
|
+
extensions: string[];
|
|
12
|
+
} | undefined): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Return true if fileName's extension is in the allowed list,
|
|
15
|
+
* or if the list is empty (no restriction).
|
|
16
|
+
*/
|
|
17
|
+
export declare function isFileExtensionAllowed(fileName: string, allowedExtensions: string[]): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Return true if file is within the size limit.
|
|
20
|
+
* maxSizeMB === Infinity means no limit.
|
|
21
|
+
*/
|
|
22
|
+
export declare function isFileSizeAllowed(file: File, maxSizeMB: number): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Add prefill resource IDs to resourceIndex with type inferred from filename extension.
|
|
25
|
+
*/
|
|
26
|
+
export declare function addPrefillFilesToIndex(initialFiles: string[], resourceIndex: Map<string, any>): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { State } from "../../types/state.js";
|
|
2
|
+
export declare const TILE_SIZE = "160px";
|
|
3
|
+
/**
|
|
4
|
+
* Create a base square tile element (TILE_SIZE × TILE_SIZE).
|
|
5
|
+
* Applies .fb-tile so theme variables control background/radius.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createFileTile(): HTMLElement;
|
|
8
|
+
/**
|
|
9
|
+
* Show an inline error message below the nearest .space-y-2 ancestor.
|
|
10
|
+
*/
|
|
11
|
+
export declare function showFileError(container: HTMLElement, message: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Remove any inline file error message below the nearest .space-y-2 ancestor.
|
|
14
|
+
*/
|
|
15
|
+
export declare function clearFileError(container: HTMLElement): void;
|
|
16
|
+
/**
|
|
17
|
+
* Render (or replace) a delete-overlay with a centred "Delete" button on a tile.
|
|
18
|
+
* Used by the single-file edit-mode path.
|
|
19
|
+
*/
|
|
20
|
+
export declare function addDeleteButton(container: HTMLElement, state: State, onDelete: () => void): void;
|
|
21
|
+
/**
|
|
22
|
+
* Find the hidden <input type="file"> picker by traversing up to the
|
|
23
|
+
* nearest [data-files-wrapper] ancestor.
|
|
24
|
+
*/
|
|
25
|
+
export declare function findFilePicker(container: HTMLElement): HTMLInputElement | null;
|
|
26
|
+
/**
|
|
27
|
+
* Build a compact uploading-state tile (spinner + filename label).
|
|
28
|
+
*/
|
|
29
|
+
export declare function createUploadingTile(fileName: string, state: State): HTMLElement;
|
|
30
|
+
/**
|
|
31
|
+
* Ensure a .fb-tiles-wrap + .fb-add-tile scaffold exists inside `list`.
|
|
32
|
+
* When the field starts empty, the list only has a .fb-file-dropzone; this
|
|
33
|
+
* function replaces it with the tile-row layout so upload placeholders land
|
|
34
|
+
* in the correct flex container.
|
|
35
|
+
*/
|
|
36
|
+
export declare function ensureTilesWrap(list: HTMLElement): HTMLElement;
|
|
37
|
+
/**
|
|
38
|
+
* Render a placeholder empty-container (single-file edit mode).
|
|
39
|
+
*/
|
|
40
|
+
export declare function setEmptyFileContainer(fileContainer: HTMLElement, state: State, hint?: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* Set up drag-and-drop on an element, calling dropHandler with the dropped FileList.
|
|
43
|
+
*/
|
|
44
|
+
export declare function setupDragAndDrop(element: HTMLElement, dropHandler: (files: FileList) => void): void;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { State } from "../../types/state.js";
|
|
2
|
+
import type { ResourceMetadata } from "../../types/config.js";
|
|
3
|
+
import type { FileDeps } from "./upload.js";
|
|
4
|
+
export interface TileActionOptions {
|
|
5
|
+
canRemove: boolean;
|
|
6
|
+
removeHandler: (() => void) | null;
|
|
7
|
+
state: State;
|
|
8
|
+
resourceId: string;
|
|
9
|
+
fileName: string;
|
|
10
|
+
/**
|
|
11
|
+
* The resource metadata. Used both to drive capability gating (a local
|
|
12
|
+
* `meta.file` is a valid download/open source even without network handlers)
|
|
13
|
+
* and as a fallback at click time so the user can always download/open a
|
|
14
|
+
* just-uploaded file.
|
|
15
|
+
*/
|
|
16
|
+
meta?: ResourceMetadata;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build a horizontal row of icon-only action buttons for a file tile.
|
|
20
|
+
* Download and Open-in-new-tab are capability-gated — they're rendered only
|
|
21
|
+
* when the configured handlers (or a local meta.file) can fulfil them.
|
|
22
|
+
* Remove is rendered only in edit mode.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createTileActions(options: TileActionOptions): HTMLElement;
|
|
25
|
+
export declare function releaseLocalFileUrl(file: File | undefined | null): void;
|
|
26
|
+
/**
|
|
27
|
+
* Populate a single-file edit-mode container with a file preview.
|
|
28
|
+
* Handles both local (pre-upload) Files and uploaded resource IDs.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderFilePreview(container: HTMLElement, resourceId: string, state: State, options?: {
|
|
31
|
+
fileName?: string;
|
|
32
|
+
isReadonly?: boolean;
|
|
33
|
+
deps?: FileDeps | null;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Build and return a compact 160×160 readonly tile for a single resource.
|
|
37
|
+
* Click opens the resource via getDownloadUrl / getThumbnail / downloadFile.
|
|
38
|
+
* Action icon buttons (download, open, optional remove) appear on hover.
|
|
39
|
+
*/
|
|
40
|
+
export declare function renderFilePreviewReadonly(resourceId: string, state: State, fileName?: string, options?: {
|
|
41
|
+
canRemove?: boolean;
|
|
42
|
+
removeHandler?: (() => void) | null;
|
|
43
|
+
}): Promise<HTMLElement>;
|
|
44
|
+
/**
|
|
45
|
+
* Render (or replace) the single-file edit container with a compact 160×160 tile.
|
|
46
|
+
* Called after a file is selected/uploaded, or when the field has prefill data.
|
|
47
|
+
* Mirrors renderFilePreviewReadonly but always includes a remove (✕) action button.
|
|
48
|
+
*
|
|
49
|
+
* Delegates entirely to renderFilePreviewReadonly with canRemove:true.
|
|
50
|
+
* getThumbnail (if configured) provides image/video thumbnails; otherwise the
|
|
51
|
+
* standard icon fallback is shown — same UX as the post-upload path had before.
|
|
52
|
+
*
|
|
53
|
+
* Local image files (just-uploaded, meta.file still set) are treated as uploaded
|
|
54
|
+
* resources: getThumbnail is tried first; if absent the 🖼️ icon is shown.
|
|
55
|
+
* This avoids running FileReader in single-file edit mode (consistent behaviour).
|
|
56
|
+
*
|
|
57
|
+
* Video files (local or uploaded) are NOT handled here; the caller keeps them
|
|
58
|
+
* on the old native-<video> path (see render-edit.ts and upload.ts).
|
|
59
|
+
*
|
|
60
|
+
* The outer `fileContainer` wrapper is cleared and the tile inserted as its only child.
|
|
61
|
+
* Removing the tile restores the dropzone via deps.onRemove().
|
|
62
|
+
*/
|
|
63
|
+
export declare function renderSingleFileEditTile(fileContainer: HTMLElement, resourceId: string, state: State, deps: FileDeps): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Populate a tile element with thumbnail / icon content for a resource.
|
|
66
|
+
* Used by renderResourcePills for both edit and readonly multi-file tiles.
|
|
67
|
+
* actionsEl: pre-built action button group to attach to the tile (and zoom popup).
|
|
68
|
+
*/
|
|
69
|
+
export declare function fillTileContent(tile: HTMLElement, rid: string, meta: ResourceMetadata | undefined, state: State, actionsEl?: HTMLElement): Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { State } from "../../types/state.js";
|
|
2
|
+
import type { FileElement, FilesElement, RenderContext } from "../../types/index.js";
|
|
3
|
+
export { TILE_SIZE } from "./dom.js";
|
|
4
|
+
/**
|
|
5
|
+
* Populate `container` with the tile grid for multi-file fields.
|
|
6
|
+
* In edit mode: renders tiles + hover-X removal + "+" add tile.
|
|
7
|
+
* In readonly mode (isReadonly=true): renders tiles only (no add tile, no X).
|
|
8
|
+
*
|
|
9
|
+
* Also writes `data-resource-ids` JSON on the nearest [data-files-wrapper]
|
|
10
|
+
* ancestor so that validateFileElement can read IDs without touching pills.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renderResourcePills(container: HTMLElement, rids: string[] | null, state: State, onRemove: ((rid: string) => void) | null, hint?: string, countInfo?: string, maxCount?: number, isReadonly?: boolean): void;
|
|
13
|
+
export declare function renderFileElementEdit(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
14
|
+
export declare function renderFilesElementEdit(element: FilesElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
15
|
+
export declare function renderMultipleFileElementEdit(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { State } from "../../types/state.js";
|
|
2
|
+
import type { FileElement, FilesElement, RenderContext } from "../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Render a compact 160×160 readonly tile for a single-file field.
|
|
5
|
+
* If no prefill: shows a styled empty placeholder.
|
|
6
|
+
*/
|
|
7
|
+
export declare function renderFileElementReadonly(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
8
|
+
/**
|
|
9
|
+
* Render a tile row for a readonly multi-file field.
|
|
10
|
+
*
|
|
11
|
+
* Issue 2 fix: exactly N tile elements for N files — no hidden pill stubs.
|
|
12
|
+
* The [data-files-wrapper] element carries data-resource-ids so validation
|
|
13
|
+
* can read IDs without touching the tile DOM.
|
|
14
|
+
*/
|
|
15
|
+
export declare function renderMultiFileReadonly(rids: string[], state: State, wrapper: HTMLElement, pathKey: string, marginTop?: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Render legacy `files` element in readonly mode.
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderFilesElementReadonly(element: FilesElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Render `file` element with `multiple:true` in readonly mode.
|
|
22
|
+
*/
|
|
23
|
+
export declare function renderMultipleFileElementReadonly(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ensureFileStyles(): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { State } from "../../types/state.js";
|
|
2
|
+
import { type FileUploadConstraints } from "./constraints.js";
|
|
3
|
+
export interface FileDeps {
|
|
4
|
+
picker: HTMLInputElement;
|
|
5
|
+
fileUploadHandler: () => void;
|
|
6
|
+
dragHandler: (files: FileList) => void;
|
|
7
|
+
setupDrop?: (container: HTMLElement) => void;
|
|
8
|
+
/** Called by the tile's remove button in single-file edit mode */
|
|
9
|
+
onRemove?: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function handleFileSelect(file: File, container: HTMLElement, fieldName: string, state: State, deps?: FileDeps | null, instance?: any, allowedExtensions?: string[], maxSizeMB?: number): Promise<void>;
|
|
12
|
+
export declare function setupFilesDropHandler(filesContainer: HTMLElement, resourceIds: string[], state: State, updateCallback: () => void, constraints: FileUploadConstraints, pathKey?: string, instance?: any): void;
|
|
13
|
+
export declare function setupFilesPickerHandler(filesPicker: HTMLInputElement, resourceIds: string[], state: State, updateCallback: () => void, constraints: FileUploadConstraints, pathKey?: string, instance?: any): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Element, ValidationResult } from "../../types/index.js";
|
|
2
|
+
import type { ComponentContext } from "../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Read the resource ID list for a multi-file field.
|
|
5
|
+
* Source of truth: `data-resource-ids` JSON attribute on [data-files-wrapper].
|
|
6
|
+
* Throws if the attribute is present but unparseable — that indicates a render bug.
|
|
7
|
+
*/
|
|
8
|
+
export declare function readMultiFileResourceIds(scopeRoot: HTMLElement, fullKey: string): string[];
|
|
9
|
+
/**
|
|
10
|
+
* Validate file field and return extracted value with errors.
|
|
11
|
+
* Reads from state (resourceIndex + data-resource-ids attribute) — no DOM shape dependency.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateFileElement(element: Element, key: string, context: ComponentContext): ValidationResult;
|
|
@@ -1,31 +1,9 @@
|
|
|
1
|
-
import type { FileElement, FilesElement, RenderContext, ComponentContext,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
dragHandler: (files: FileList) => void;
|
|
7
|
-
}
|
|
8
|
-
export declare function getAllowedExtensions(accept: string | {
|
|
9
|
-
extensions: string[];
|
|
10
|
-
} | undefined): string[];
|
|
11
|
-
export declare function isFileExtensionAllowed(fileName: string, allowedExtensions: string[]): boolean;
|
|
12
|
-
export declare function isFileSizeAllowed(file: File, maxSizeMB: number): boolean;
|
|
13
|
-
export declare function renderFilePreview(container: HTMLElement, resourceId: string, state: State, options?: {
|
|
14
|
-
fileName?: string;
|
|
15
|
-
isReadonly?: boolean;
|
|
16
|
-
deps?: FileDeps | null;
|
|
17
|
-
}): Promise<void>;
|
|
18
|
-
export declare function renderFilePreviewReadonly(resourceId: string, state: State, fileName?: string): Promise<HTMLElement>;
|
|
19
|
-
export declare function renderResourcePills(container: HTMLElement, rids: string[] | null, state: State, onRemove: ((rid: string) => void) | null, hint?: string, countInfo?: string): void;
|
|
1
|
+
import type { FileElement, FilesElement, RenderContext, ComponentContext, Element } from "../types/index.js";
|
|
2
|
+
export { getAllowedExtensions, isFileExtensionAllowed, isFileSizeAllowed } from "./file/constraints.js";
|
|
3
|
+
export { renderFilePreview, renderFilePreviewReadonly } from "./file/preview.js";
|
|
4
|
+
export { renderResourcePills } from "./file/render-edit.js";
|
|
5
|
+
export { validateFileElement } from "./file/validate.js";
|
|
20
6
|
export declare function renderFileElement(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
21
7
|
export declare function renderFilesElement(element: FilesElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
22
8
|
export declare function renderMultipleFileElement(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
23
|
-
/**
|
|
24
|
-
* Validate file field and return extracted value with errors
|
|
25
|
-
*/
|
|
26
|
-
export declare function validateFileElement(element: Element, key: string, context: ComponentContext): ValidationResult;
|
|
27
|
-
/**
|
|
28
|
-
* Update file field value in DOM without re-render
|
|
29
|
-
*/
|
|
30
9
|
export declare function updateFileField(element: Element, fieldPath: string, value: any, context: ComponentContext): void;
|
|
31
|
-
export {};
|
|
@@ -7,6 +7,8 @@ export interface Translations {
|
|
|
7
7
|
noFileSelected: string;
|
|
8
8
|
noFilesSelected: string;
|
|
9
9
|
downloadButton: string;
|
|
10
|
+
downloadFile: string;
|
|
11
|
+
openInNewTab: string;
|
|
10
12
|
changeButton: string;
|
|
11
13
|
placeholderText: string;
|
|
12
14
|
previewAlt: string;
|
|
@@ -27,6 +29,8 @@ export interface Translations {
|
|
|
27
29
|
fileCountSingle: string;
|
|
28
30
|
fileCountPlural: string;
|
|
29
31
|
fileCountRange: string;
|
|
32
|
+
uploadingFile: string;
|
|
33
|
+
filesCounter: string;
|
|
30
34
|
required: string;
|
|
31
35
|
minItems: string;
|
|
32
36
|
maxItems: string;
|
|
@@ -30,6 +30,7 @@ export interface BaseElement {
|
|
|
30
30
|
hint?: string;
|
|
31
31
|
required?: boolean;
|
|
32
32
|
hidden?: boolean;
|
|
33
|
+
readonly?: boolean;
|
|
33
34
|
default?: any;
|
|
34
35
|
actions?: ElementAction[];
|
|
35
36
|
enableIf?: EnableCondition;
|
|
@@ -216,4 +217,5 @@ export interface RenderContext {
|
|
|
216
217
|
formData?: Record<string, any>;
|
|
217
218
|
state: import("./state.js").State;
|
|
218
219
|
instance?: any;
|
|
220
|
+
inheritedReadonly?: boolean;
|
|
219
221
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import type { State } from "../types/state.js";
|
|
2
|
+
export declare function isElementReadonly(element: {
|
|
3
|
+
readonly?: boolean;
|
|
4
|
+
}, state: State, ctx?: {
|
|
5
|
+
inheritedReadonly?: boolean;
|
|
6
|
+
}): boolean;
|
|
1
7
|
export declare function isPlainObject(obj: any): obj is Record<string, any>;
|
|
2
8
|
/**
|
|
3
9
|
* Escape HTML special characters to prevent XSS
|