@dmitryvim/form-builder 0.2.30 → 0.2.34

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.
@@ -5,6 +5,7 @@ export interface ColourElement extends BaseElement {
5
5
  multiple?: boolean;
6
6
  minCount?: number;
7
7
  maxCount?: number;
8
+ addLabel?: string;
8
9
  }
9
10
  export declare function renderColourElement(element: ColourElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
10
11
  export declare function renderMultipleColourElement(element: ColourElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
@@ -1,16 +1,15 @@
1
1
  import type { State } from "../../types/state.js";
2
- export declare const TILE_SIZE = "160px";
3
2
  /**
4
- * Create a base square tile element (TILE_SIZE × TILE_SIZE).
5
- * Applies .fb-tile so theme variables control background/radius.
3
+ * Create a base square tile element. Sizing comes from CSS — `.fb-tile` and
4
+ * its descendants resolve aspect-ratio/dimensions via the theme variables.
6
5
  */
7
6
  export declare function createFileTile(): HTMLElement;
8
7
  /**
9
- * Show an inline error message below the nearest .space-y-2 ancestor.
8
+ * Show an inline error message below the nearest [data-files-wrapper] ancestor.
10
9
  */
11
10
  export declare function showFileError(container: HTMLElement, message: string): void;
12
11
  /**
13
- * Remove any inline file error message below the nearest .space-y-2 ancestor.
12
+ * Remove any inline file error message below the nearest [data-files-wrapper] ancestor.
14
13
  */
15
14
  export declare function clearFileError(container: HTMLElement): void;
16
15
  /**
@@ -14,6 +14,10 @@ export interface TileActionOptions {
14
14
  * just-uploaded file.
15
15
  */
16
16
  meta?: ResourceMetadata;
17
+ /** Single-only: replace current file by triggering the upload picker. */
18
+ replaceHandler?: (() => void) | null;
19
+ /** Single-only: open the host-owned library picker to pick a replacement. */
20
+ libraryHandler?: (() => void) | null;
17
21
  }
18
22
  /**
19
23
  * Build a horizontal row of icon-only action buttons for a file tile.
@@ -22,6 +26,7 @@ export interface TileActionOptions {
22
26
  * Remove is rendered only in edit mode.
23
27
  */
24
28
  export declare function createTileActions(options: TileActionOptions): HTMLElement;
29
+ export declare function getLocalFileUrl(file: File): string;
25
30
  export declare function releaseLocalFileUrl(file: File | undefined | null): void;
26
31
  /**
27
32
  * Populate a single-file edit-mode container with a file preview.
@@ -1,6 +1,5 @@
1
1
  import type { State } from "../../types/state.js";
2
2
  import type { FileElement, FilesElement, RenderContext } from "../../types/index.js";
3
- export { TILE_SIZE } from "./dom.js";
4
3
  export interface RenderPillsOptions {
5
4
  container: HTMLElement;
6
5
  rids: string[] | null;
@@ -11,8 +10,16 @@ export interface RenderPillsOptions {
11
10
  maxCount?: number;
12
11
  isReadonly?: boolean;
13
12
  onLibraryPick?: (() => void) | null;
13
+ element?: {
14
+ maxSize?: number;
15
+ accept?: unknown;
16
+ };
17
+ onClearAll?: () => void;
18
+ openPicker?: () => void;
14
19
  }
15
20
  export declare function renderResourcePills(opts: RenderPillsOptions): void;
16
21
  export declare function renderFileElementEdit(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
22
+ /** Legacy `files` element — multi-file with no upper bound. */
17
23
  export declare function renderFilesElementEdit(element: FilesElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
24
+ /** `file` element with `multiple: true` — multi-file honouring maxCount. */
18
25
  export declare function renderMultipleFileElementEdit(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
@@ -1,18 +1,15 @@
1
1
  import type { State } from "../../types/state.js";
2
2
  import type { FileElement, FilesElement, RenderContext } from "../../types/index.js";
3
3
  /**
4
- * Render a compact 160×160 readonly tile for a single-file field.
4
+ * Render a 220px readonly single-file container (object-contain preview + filename pill).
5
5
  * If no prefill: shows a styled empty placeholder.
6
6
  */
7
7
  export declare function renderFileElementReadonly(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
8
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.
9
+ * Render a CSS grid of readonly preview tiles.
10
+ * No add tile, no remove buttons, no drag handles.
14
11
  */
15
- export declare function renderMultiFileReadonly(rids: string[], state: State, wrapper: HTMLElement, pathKey: string, marginTop?: string): void;
12
+ export declare function renderMultiFileReadonly(rids: string[], state: State, wrapper: HTMLElement, pathKey: string, _marginTop?: string): void;
16
13
  /**
17
14
  * Render legacy `files` element in readonly mode.
18
15
  */
@@ -8,6 +8,12 @@ export interface FileDeps {
8
8
  setupDrop?: (container: HTMLElement) => void;
9
9
  /** Called by the tile's remove button in single-file edit mode */
10
10
  onRemove?: () => void;
11
+ /**
12
+ * Optional override for post-upload rendering of a single-file field.
13
+ * When provided, called instead of renderSingleFileEditTile so the
14
+ * render-edit layer can use the new 220px filled-state container.
15
+ */
16
+ onAfterUpload?: (container: HTMLElement, rid: string) => void;
11
17
  }
12
18
  export interface HandleFileSelectOptions {
13
19
  file: File;
@@ -21,5 +27,9 @@ export interface HandleFileSelectOptions {
21
27
  maxSizeMB?: number;
22
28
  }
23
29
  export declare function handleFileSelect(opts: HandleFileSelectOptions): Promise<void>;
30
+ export interface UploadBatchFailure {
31
+ file: File;
32
+ error: Error;
33
+ }
24
34
  export declare function setupFilesDropHandler(filesContainer: HTMLElement, resourceIds: string[], state: State, updateCallback: () => void, constraints: FileUploadConstraints, pathKey?: string, instance?: FormBuilderInstance | null): void;
25
35
  export declare function setupFilesPickerHandler(filesPicker: HTMLInputElement, resourceIds: string[], state: State, updateCallback: () => void, constraints: FileUploadConstraints, pathKey?: string, instance?: FormBuilderInstance | null): void;
@@ -1,6 +1,6 @@
1
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";
2
+ export { getAllowedExtensions, isFileExtensionAllowed, isFileSizeAllowed, } from "./file/constraints.js";
3
+ export { renderFilePreview, renderFilePreviewReadonly, } from "./file/preview.js";
4
4
  export { renderResourcePills } from "./file/render-edit.js";
5
5
  export { validateFileElement } from "./file/validate.js";
6
6
  export declare function renderFileElement(element: FileElement, ctx: RenderContext, wrapper: HTMLElement, pathKey: string): void;
@@ -38,6 +38,7 @@ export interface Translations {
38
38
  hintPattern: string;
39
39
  fileCountSingle: string;
40
40
  fileCountPlural: string;
41
+ fileCountWithMax: string;
41
42
  fileCountRange: string;
42
43
  uploadingFile: string;
43
44
  filesCounter: string;
@@ -45,6 +46,9 @@ export interface Translations {
45
46
  libraryEmpty: string;
46
47
  libraryHint: string;
47
48
  pickerError: string;
49
+ dropToUpload: string;
50
+ replaceFile: string;
51
+ clearAll: string;
48
52
  required: string;
49
53
  minItems: string;
50
54
  maxItems: string;
@@ -61,6 +65,7 @@ export interface Translations {
61
65
  invalidFileExtension: string;
62
66
  invalidFileMime: string;
63
67
  fileTooLarge: string;
68
+ uploadFailed: string;
64
69
  filesLimitExceeded: string;
65
70
  unsupportedFieldType: string;
66
71
  invalidOption: string;
@@ -44,6 +44,7 @@ export interface TextElement extends BaseElement {
44
44
  multiple?: boolean;
45
45
  minCount?: number;
46
46
  maxCount?: number;
47
+ addLabel?: string;
47
48
  }
48
49
  export interface TextareaElement extends BaseElement {
49
50
  type: "textarea";
@@ -56,6 +57,7 @@ export interface TextareaElement extends BaseElement {
56
57
  minCount?: number;
57
58
  maxCount?: number;
58
59
  autoExpand?: boolean;
60
+ addLabel?: string;
59
61
  }
60
62
  export interface NumberElement extends BaseElement {
61
63
  type: "number";
@@ -67,6 +69,7 @@ export interface NumberElement extends BaseElement {
67
69
  multiple?: boolean;
68
70
  minCount?: number;
69
71
  maxCount?: number;
72
+ addLabel?: string;
70
73
  }
71
74
  export interface SelectElement extends BaseElement {
72
75
  type: "select";
@@ -75,6 +78,7 @@ export interface SelectElement extends BaseElement {
75
78
  multiple?: boolean;
76
79
  minCount?: number;
77
80
  maxCount?: number;
81
+ addLabel?: string;
78
82
  }
79
83
  /**
80
84
  * File accept constraint — either a legacy comma-separated string (e.g. ".jpg,.png")
@@ -110,6 +114,15 @@ export interface ContainerElement extends BaseElement {
110
114
  maxCount?: number;
111
115
  columns?: 1 | 2 | 3 | 4;
112
116
  prefillHints?: PrefillHint[];
117
+ /**
118
+ * How items are arranged when `multiple: true`.
119
+ * - "stack" (default): vertical list, one item per row (current behavior).
120
+ * - "slides": horizontal grid, multiple items per row, auto-wrap.
121
+ * Each item card has min-width 280px and grows to fill available width.
122
+ * Ignored when `multiple: false`.
123
+ */
124
+ displayMode?: "stack" | "slides";
125
+ addLabel?: string;
113
126
  }
114
127
  export interface ColourElement extends BaseElement {
115
128
  type: "colour";
@@ -117,6 +130,7 @@ export interface ColourElement extends BaseElement {
117
130
  multiple?: boolean;
118
131
  minCount?: number;
119
132
  maxCount?: number;
133
+ addLabel?: string;
120
134
  }
121
135
  export interface SliderElement extends BaseElement {
122
136
  type: "slider";
@@ -127,6 +141,7 @@ export interface SliderElement extends BaseElement {
127
141
  multiple?: boolean;
128
142
  minCount?: number;
129
143
  maxCount?: number;
144
+ addLabel?: string;
130
145
  }
131
146
  export interface SwitcherElement extends BaseElement {
132
147
  type: "switcher";
@@ -134,6 +149,7 @@ export interface SwitcherElement extends BaseElement {
134
149
  multiple?: boolean;
135
150
  minCount?: number;
136
151
  maxCount?: number;
152
+ addLabel?: string;
137
153
  }
138
154
  export interface GroupElement extends BaseElement {
139
155
  type: "group";
@@ -7,6 +7,48 @@ export declare function applyInputStyles(element: HTMLInputElement | HTMLTextAre
7
7
  * Apply themed hint/description styles to a paragraph element
8
8
  */
9
9
  export declare function applyHintStyles(element: HTMLParagraphElement): void;
10
+ /**
11
+ * Mount a counter element into the field's label row so it sits inline with
12
+ * the heading (e.g. `Tags 3/5`) instead of below the field. The label row is
13
+ * marked with `[data-fb-label-row]` by `createLabelContainer` — the data
14
+ * attribute is the stable hook; layout utility classes may change.
15
+ *
16
+ * No-op when the wrapper has no label row (e.g. nested anonymous wrappers).
17
+ */
18
+ export declare function mountCounterInLabel(wrapper: HTMLElement, counter: HTMLElement): void;
19
+ /**
20
+ * Visual: full-width dashed pill button, optional `+ {label}` centered.
21
+ * Used by every multi-value field type.
22
+ *
23
+ * The counter is returned separately so callers can place it inline with the
24
+ * field label (saving a row). At maxCount both the button and the row are
25
+ * hidden — the counter stays visible wherever the caller mounted it.
26
+ *
27
+ * `classNameSuffix` becomes `add-{suffix}-btn` to preserve test-targetable
28
+ * class names that the existing test suite already queries.
29
+ */
30
+ export interface AddItemRowHandle {
31
+ row: HTMLDivElement;
32
+ button: HTMLButtonElement;
33
+ counter: HTMLSpanElement;
34
+ update: (current: number, max: number) => void;
35
+ }
36
+ export declare function createAddItemRow(classNameSuffix: string, onClick: () => void, options?: {
37
+ label?: string;
38
+ showCounter?: boolean;
39
+ }): AddItemRowHandle;
40
+ /**
41
+ * Slide-sized add tile rendered inside a slides-displayMode container grid.
42
+ * Sits as another grid cell next to existing slides at the same dimensions.
43
+ */
44
+ export interface SlideAddTileHandle {
45
+ tile: HTMLButtonElement;
46
+ counter: HTMLSpanElement;
47
+ update: (current: number, max: number) => void;
48
+ }
49
+ export declare function createSlideAddTile(onClick: () => void, options?: {
50
+ label?: string;
51
+ }): SlideAddTileHandle;
10
52
  /**
11
53
  * Create a styled add button with theme support
12
54
  */
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.2.30",
6
+ "version": "0.2.34",
7
7
  "description": "A reusable JSON schema form builder library",
8
8
  "main": "./dist/cjs/index.cjs",
9
9
  "module": "./dist/esm/index.js",