@dmitryvim/form-builder 0.2.27 → 0.2.28
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 +57 -1
- package/dist/browser/formbuilder.min.js +207 -125
- package/dist/browser/formbuilder.v0.2.28.min.js +956 -0
- package/dist/cjs/index.cjs +542 -133
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +528 -122
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +207 -125
- package/dist/types/components/file/constraints.d.ts +39 -3
- package/dist/types/components/file/library.d.ts +49 -0
- package/dist/types/components/file/render-edit.d.ts +12 -9
- package/dist/types/components/file/upload.d.ts +15 -3
- package/dist/types/index.d.ts +1 -1
- package/dist/types/types/config.d.ts +33 -0
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/schema.d.ts +13 -6
- package/package.json +1 -1
- package/dist/browser/formbuilder.v0.2.27.min.js +0 -874
|
@@ -1,25 +1,61 @@
|
|
|
1
|
+
import type { FileAccept } from "../../types/schema.js";
|
|
1
2
|
export interface FileUploadConstraints {
|
|
2
3
|
maxCount: number;
|
|
3
4
|
allowedExtensions: string[];
|
|
5
|
+
allowedMimes: string[];
|
|
4
6
|
maxSize: number;
|
|
5
7
|
}
|
|
6
8
|
/**
|
|
7
9
|
* Extract allowed file extensions from the `accept` schema property.
|
|
8
10
|
* Returns lowercase extension strings without leading dots.
|
|
11
|
+
* Convention: this getter normalizes to lowercase; checkers assume the list is normalized.
|
|
9
12
|
*/
|
|
10
|
-
export declare function getAllowedExtensions(accept:
|
|
11
|
-
extensions: string[];
|
|
12
|
-
} | undefined): string[];
|
|
13
|
+
export declare function getAllowedExtensions(accept: FileAccept | undefined): string[];
|
|
13
14
|
/**
|
|
14
15
|
* Return true if fileName's extension is in the allowed list,
|
|
15
16
|
* or if the list is empty (no restriction).
|
|
16
17
|
*/
|
|
17
18
|
export declare function isFileExtensionAllowed(fileName: string, allowedExtensions: string[]): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Return true if a byte count is within the size limit.
|
|
21
|
+
* maxSizeMB === Infinity means no limit.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isSizeWithinLimit(bytes: number, maxSizeMB: number): boolean;
|
|
18
24
|
/**
|
|
19
25
|
* Return true if file is within the size limit.
|
|
20
26
|
* maxSizeMB === Infinity means no limit.
|
|
21
27
|
*/
|
|
22
28
|
export declare function isFileSizeAllowed(file: File, maxSizeMB: number): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Extract allowed MIME types from the `accept` schema property.
|
|
31
|
+
* Returns empty array for the legacy string form (no mime in that form).
|
|
32
|
+
* Returns empty array when accept is undefined or has no mime key.
|
|
33
|
+
* Convention: this getter normalizes to lowercase; checkers assume the list is normalized.
|
|
34
|
+
*/
|
|
35
|
+
export declare function getAllowedMimes(accept: FileAccept | undefined): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Return true if mimeType is allowed by the allowedMimes list.
|
|
38
|
+
* Empty allowedMimes = no mime restriction → always return true.
|
|
39
|
+
* Supports wildcards (image/*, application/*, etc.).
|
|
40
|
+
* Comparison is case-insensitive per RFC 2045.
|
|
41
|
+
*
|
|
42
|
+
* Convention: allowedMimes is assumed to be pre-normalized to lowercase
|
|
43
|
+
* (by getAllowedMimes). Only mimeType (the host-provided input) is lowercased here.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isMimeAllowed(mimeType: string, allowedMimes: string[]): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Infer MIME type from a resource ID's filename extension.
|
|
48
|
+
* Returns "application/octet-stream" when the extension is unrecognised.
|
|
49
|
+
* This is the single source of truth for the extension→mime mapping used by
|
|
50
|
+
* prefill, handleInitialFileData, and the API-update path.
|
|
51
|
+
*/
|
|
52
|
+
export declare function inferMimeFromResourceId(resourceId: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Seed resourceIndex with inferred metadata for a single resource ID.
|
|
55
|
+
* Skips IDs that already have an entry (does not overwrite authoritative data).
|
|
56
|
+
* Sets inferredFromExtension: true so that mime validation is skipped at submit time.
|
|
57
|
+
*/
|
|
58
|
+
export declare function seedInferredResource(resourceId: string, resourceIndex: Map<string, any>): void;
|
|
23
59
|
/**
|
|
24
60
|
* Add prefill resource IDs to resourceIndex with type inferred from filename extension.
|
|
25
61
|
*/
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { FormBuilderInstance } from "../../instance/FormBuilderInstance.js";
|
|
2
|
+
import type { State } from "../../types/state.js";
|
|
3
|
+
import type { FileElement, FilesElement } from "../../types/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Handle a library pick action for a MULTI-file field.
|
|
6
|
+
*
|
|
7
|
+
* End-to-end handler (mirrors upload.ts pattern):
|
|
8
|
+
* 1. Calls pickExistingFiles with context
|
|
9
|
+
* 2. Validates, deduplicates, enforces slot limit
|
|
10
|
+
* 3. Registers in resourceIndex, mutates resourceIds array
|
|
11
|
+
* 4. Updates data-resource-ids attribute
|
|
12
|
+
* 5. Calls updateCallback() to re-render tiles
|
|
13
|
+
* 6. Fires triggerOnChange
|
|
14
|
+
*
|
|
15
|
+
* @param state Form builder state
|
|
16
|
+
* @param element File / FilesElement schema definition
|
|
17
|
+
* @param wrapper The [data-files-wrapper] element
|
|
18
|
+
* @param fieldPath Bracket-notation field path (e.g. "slides[2].image")
|
|
19
|
+
* @param resourceIds The mutable live array of current resource IDs (mutated in-place)
|
|
20
|
+
* @param maxCount Maximum files allowed (Infinity = no limit)
|
|
21
|
+
* @param updateCallback Re-render callback (same pattern as upload.ts)
|
|
22
|
+
* @param instance FormBuilderInstance (for onChange events)
|
|
23
|
+
*/
|
|
24
|
+
export declare function handleLibraryPickMulti(state: State, element: FileElement | FilesElement, wrapper: HTMLElement, fieldPath: string, resourceIds: string[], maxCount: number, updateCallback: () => void, instance: FormBuilderInstance): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Handle a library pick action for a SINGLE-file field.
|
|
27
|
+
*
|
|
28
|
+
* End-to-end handler (mirrors upload.ts and handleLibraryPickMulti patterns):
|
|
29
|
+
* 1. Calls pickExistingFiles with context
|
|
30
|
+
* 2. Validates the first returned resource
|
|
31
|
+
* 3. Registers in resourceIndex
|
|
32
|
+
* 4. Creates/updates the hidden input inside fileWrapper (only on success — not on cancel)
|
|
33
|
+
* 5. Calls renderCallback(resourceId) to render the tile
|
|
34
|
+
* 6. Fires triggerOnChange
|
|
35
|
+
*
|
|
36
|
+
* The hidden input is managed here (not in the caller) to mirror how
|
|
37
|
+
* handleFileSelect in upload.ts manages it, and to match the multi-file
|
|
38
|
+
* pattern where data-resource-ids is updated inside handleLibraryPickMulti.
|
|
39
|
+
*
|
|
40
|
+
* @param state Form builder state
|
|
41
|
+
* @param element FileElement schema definition
|
|
42
|
+
* @param container The .file-preview-container element
|
|
43
|
+
* @param fileWrapper The .space-y-2 wrapper that contains the hidden input
|
|
44
|
+
* @param pathKey Field name / bracket-notation path for the hidden input
|
|
45
|
+
* @param fieldPath Bracket-notation field path (for onChange context)
|
|
46
|
+
* @param renderCallback Called with the accepted resource ID; caller renders the tile
|
|
47
|
+
* @param instance FormBuilderInstance (for onChange events)
|
|
48
|
+
*/
|
|
49
|
+
export declare function handleLibraryPickSingle(state: State, element: FileElement, container: HTMLElement, fileWrapper: HTMLElement, pathKey: string, fieldPath: string, renderCallback: (resourceId: string) => Promise<void>, instance: FormBuilderInstance): Promise<void>;
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type { State } from "../../types/state.js";
|
|
2
2
|
import type { FileElement, FilesElement, RenderContext } from "../../types/index.js";
|
|
3
3
|
export { TILE_SIZE } from "./dom.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
export interface RenderPillsOptions {
|
|
5
|
+
container: HTMLElement;
|
|
6
|
+
rids: string[] | null;
|
|
7
|
+
state: State;
|
|
8
|
+
onRemove: ((rid: string) => void) | null;
|
|
9
|
+
hint?: string;
|
|
10
|
+
countInfo?: string;
|
|
11
|
+
maxCount?: number;
|
|
12
|
+
isReadonly?: boolean;
|
|
13
|
+
onLibraryPick?: (() => void) | null;
|
|
14
|
+
}
|
|
15
|
+
export declare function renderResourcePills(opts: RenderPillsOptions): void;
|
|
13
16
|
export declare function renderFileElementEdit(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
14
17
|
export declare function renderFilesElementEdit(element: FilesElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
15
18
|
export declare function renderMultipleFileElementEdit(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { State } from "../../types/state.js";
|
|
2
|
+
import type { FormBuilderInstance } from "../../instance/FormBuilderInstance.js";
|
|
2
3
|
import { type FileUploadConstraints } from "./constraints.js";
|
|
3
4
|
export interface FileDeps {
|
|
4
5
|
picker: HTMLInputElement;
|
|
@@ -8,6 +9,17 @@ export interface FileDeps {
|
|
|
8
9
|
/** Called by the tile's remove button in single-file edit mode */
|
|
9
10
|
onRemove?: () => void;
|
|
10
11
|
}
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
export interface HandleFileSelectOptions {
|
|
13
|
+
file: File;
|
|
14
|
+
container: HTMLElement;
|
|
15
|
+
fieldName: string;
|
|
16
|
+
state: State;
|
|
17
|
+
deps?: FileDeps | null;
|
|
18
|
+
instance?: FormBuilderInstance | null;
|
|
19
|
+
allowedExtensions?: string[];
|
|
20
|
+
allowedMimes?: string[];
|
|
21
|
+
maxSizeMB?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function handleFileSelect(opts: HandleFileSelectOptions): Promise<void>;
|
|
24
|
+
export declare function setupFilesDropHandler(filesContainer: HTMLElement, resourceIds: string[], state: State, updateCallback: () => void, constraints: FileUploadConstraints, pathKey?: string, instance?: FormBuilderInstance | null): void;
|
|
25
|
+
export declare function setupFilesPickerHandler(filesPicker: HTMLInputElement, resourceIds: string[], state: State, updateCallback: () => void, constraints: FileUploadConstraints, pathKey?: string, instance?: FormBuilderInstance | null): void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { FormBuilderInstance } from "./instance/FormBuilderInstance.js";
|
|
7
7
|
import { validateSchema } from "./utils/validation.js";
|
|
8
|
-
export type { SelectOption, ElementAction, BaseElement, TextElement, TextareaElement, NumberElement, SelectElement, FileElement, FilesElement, ContainerElement, GroupElement, RichInputElement, Element, Schema, ExternalAction, FormData, RenderContext, Translations, Locale, Config, ResourceMetadata, State, } from "./types/index.js";
|
|
8
|
+
export type { SelectOption, ElementAction, BaseElement, TextElement, TextareaElement, NumberElement, SelectElement, FileElement, FilesElement, ContainerElement, GroupElement, RichInputElement, Element, Schema, ExternalAction, FormData, RenderContext, Translations, Locale, Config, ResourceMetadata, PickedResource, State, } from "./types/index.js";
|
|
9
9
|
export type { Theme } from "./styles/theme.js";
|
|
10
10
|
export { defaultTheme, exampleThemes } from "./styles/theme.js";
|
|
11
11
|
/**
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import type { Theme } from "../styles/theme.js";
|
|
2
2
|
import type { TableMerge } from "./schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* A file resource returned by the host's library picker.
|
|
5
|
+
* The host validates/provides these fields; the library re-validates on resolve.
|
|
6
|
+
*/
|
|
7
|
+
export interface PickedResource {
|
|
8
|
+
resourceId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
type: string;
|
|
11
|
+
size: number;
|
|
12
|
+
}
|
|
3
13
|
export interface Translations {
|
|
4
14
|
removeElement: string;
|
|
5
15
|
clickDragText: string;
|
|
@@ -31,6 +41,10 @@ export interface Translations {
|
|
|
31
41
|
fileCountRange: string;
|
|
32
42
|
uploadingFile: string;
|
|
33
43
|
filesCounter: string;
|
|
44
|
+
fromLibrary: string;
|
|
45
|
+
libraryEmpty: string;
|
|
46
|
+
libraryHint: string;
|
|
47
|
+
pickerError: string;
|
|
34
48
|
required: string;
|
|
35
49
|
minItems: string;
|
|
36
50
|
maxItems: string;
|
|
@@ -45,6 +59,7 @@ export interface Translations {
|
|
|
45
59
|
minFiles: string;
|
|
46
60
|
maxFiles: string;
|
|
47
61
|
invalidFileExtension: string;
|
|
62
|
+
invalidFileMime: string;
|
|
48
63
|
fileTooLarge: string;
|
|
49
64
|
filesLimitExceeded: string;
|
|
50
65
|
unsupportedFieldType: string;
|
|
@@ -90,6 +105,17 @@ export interface Config {
|
|
|
90
105
|
readonly: boolean;
|
|
91
106
|
locale: Locale;
|
|
92
107
|
translations: Record<string, Partial<Translations>>;
|
|
108
|
+
pickExistingFiles: ((context: {
|
|
109
|
+
fieldPath: string;
|
|
110
|
+
mode: "single" | "multiple";
|
|
111
|
+
accept?: {
|
|
112
|
+
extensions?: string[];
|
|
113
|
+
mime?: string[];
|
|
114
|
+
};
|
|
115
|
+
maxSizeMB?: number;
|
|
116
|
+
remainingSlots?: number;
|
|
117
|
+
selectedResourceIds?: string[];
|
|
118
|
+
}) => Promise<PickedResource[]>) | null;
|
|
93
119
|
parseTableFile: ((file: File) => Promise<{
|
|
94
120
|
cells: string[][];
|
|
95
121
|
merges?: TableMerge[];
|
|
@@ -102,4 +128,11 @@ export interface ResourceMetadata {
|
|
|
102
128
|
size: number;
|
|
103
129
|
uploadedAt: Date;
|
|
104
130
|
file?: File;
|
|
131
|
+
/**
|
|
132
|
+
* True when `type` was inferred from the filename extension rather than
|
|
133
|
+
* provided authoritatively by the host (e.g. via uploadFile or pickExistingFiles).
|
|
134
|
+
* When true, mime validation is skipped at submit time because we cannot
|
|
135
|
+
* validate against fabricated data — extension validation still applies.
|
|
136
|
+
*/
|
|
137
|
+
inferredFromExtension?: boolean;
|
|
105
138
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export type { SelectOption, ElementAction, EnableCondition, BaseElement, TextElement, TextareaElement, NumberElement, SelectElement, SwitcherElement, FileElement, FilesElement, ColourElement, SliderElement, ContainerElement, GroupElement, TableElement, TableMerge, TableData, RichInputElement, Element, Schema, ExternalAction, FormData, RenderContext, } from "./schema.js";
|
|
2
|
-
export type { Translations, Locale, Config, ResourceMetadata, } from "./config.js";
|
|
2
|
+
export type { Translations, Locale, Config, ResourceMetadata, PickedResource, } from "./config.js";
|
|
3
3
|
export type { State } from "./state.js";
|
|
4
4
|
export type { ComponentContext, ValidationResult, ComponentValidator, ComponentUpdater, ComponentOperations, } from "./component-operations.js";
|
|
@@ -76,24 +76,31 @@ export interface SelectElement extends BaseElement {
|
|
|
76
76
|
minCount?: number;
|
|
77
77
|
maxCount?: number;
|
|
78
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* File accept constraint — either a legacy comma-separated string (e.g. ".jpg,.png")
|
|
81
|
+
* or a structured object with extension list, mime list, or both.
|
|
82
|
+
* `undefined` on the schema field is handled by the optional `?` marker.
|
|
83
|
+
*/
|
|
84
|
+
export type FileAccept = string | {
|
|
85
|
+
extensions?: string[];
|
|
86
|
+
mime?: string[];
|
|
87
|
+
};
|
|
79
88
|
export interface FileElement extends BaseElement {
|
|
80
89
|
type: "file";
|
|
81
|
-
accept?:
|
|
82
|
-
extensions: string[];
|
|
83
|
-
};
|
|
90
|
+
accept?: FileAccept;
|
|
84
91
|
maxSize?: number;
|
|
85
92
|
multiple?: boolean;
|
|
86
93
|
minCount?: number;
|
|
87
94
|
maxCount?: number;
|
|
95
|
+
disableLibrary?: boolean;
|
|
88
96
|
}
|
|
89
97
|
export interface FilesElement extends BaseElement {
|
|
90
98
|
type: "files";
|
|
91
|
-
accept?:
|
|
92
|
-
extensions: string[];
|
|
93
|
-
};
|
|
99
|
+
accept?: FileAccept;
|
|
94
100
|
maxSize?: number;
|
|
95
101
|
minCount?: number;
|
|
96
102
|
maxCount?: number;
|
|
103
|
+
disableLibrary?: boolean;
|
|
97
104
|
}
|
|
98
105
|
export interface ContainerElement extends BaseElement {
|
|
99
106
|
type: "container";
|