native-document 1.0.189 → 1.0.191

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/CHANGELOG.md CHANGED
@@ -247,7 +247,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
247
247
  - **Data**: `DataTable` + `Column` + `ColumnGroup`, `SimpleTable`, `Accordion` + `AccordionItem`, `List`
248
248
  - **Interaction**: `Button`, `Switch`, `Slider`
249
249
  - **Media**: `Avatar`, `AvatarGroup`, `Card`
250
- - **Forms**: `FormControl`, `FieldCollection`, `StringField`, `EmailField`, `PasswordField`, `TelField`, `UrlField`, `HiddenField`, `NumberField`, `RangeField`, `TextAreaField`, `CheckboxField`, `CheckboxGroupField`, `RadioField`, `SelectField`, `AutocompleteField`, `DateField`, `TimeField`, `ColorField`, `SliderField`, `ImageField`, `FileField` (with `FileNativeMode`, `FileDropzoneMode`, `FileUploadButtonMode`, `FileWallMode`, `FileAvatarMode`)
250
+ - **Forms**: `FormControl`, `FieldCollection`, `StringField`, `EmailField`, `PasswordField`, `TelField`, `UrlField`, `HiddenField`, `NumberField`, `RangeField`, `TextAreaField`, `CheckboxField`, `CheckboxGroupField`, `RadioField`, `SelectField`, `AutocompleteField`, `DateField`, `TimeField`, `ColorField`, `SliderField`, `ImageField`, `FileField` (with `FileNativeMode`, `FileDropzoneMode`, `FileUploadButtonMode`, `FileWallMode`, `FileImagePreviewMode`)
251
251
  - **Traits**: `HasEventEmitter`, `HasDraggable`, `HasResizable`, `HasItems`, `HasPosition`, `HasFullPosition`, `HasValidation`
252
252
 
253
253
  #### CLI (`@native-document/cli`)
@@ -9,7 +9,7 @@ description: File upload component with multiple modes - native, dropzone, butto
9
9
  import {
10
10
  FileField,
11
11
  FileNativeMode, FileDropzoneMode,
12
- FileUploadButtonMode, FileWallMode, FileAvatarMode
12
+ FileUploadButtonMode, FileWallMode, FileImagePreviewMode
13
13
  } from 'native-document/components';
14
14
  ```
15
15
 
@@ -19,7 +19,7 @@ import {
19
19
  import {
20
20
  FileFieldRender,
21
21
  FileNativeModeRender, FileDropzoneModeRender,
22
- FileUploadButtonModeRender, FileWallModeRender, FileAvatarModeRender
22
+ FileUploadButtonModeRender, FileWallModeRender, FileImagePreviewModeRender
23
23
  } from 'native-document/ui';
24
24
 
25
25
  FileField.use(FileFieldRender);
@@ -27,7 +27,7 @@ FileNativeMode.use(FileNativeModeRender);
27
27
  FileDropzoneMode.use(FileDropzoneModeRender);
28
28
  FileUploadButtonMode.use(FileUploadButtonModeRender);
29
29
  FileWallMode.use(FileWallModeRender);
30
- FileAvatarMode.use(FileAvatarModeRender);
30
+ FileImagePreviewMode.use(FileImagePreviewModeRender);
31
31
  ```
32
32
 
33
33
  ## Methods
@@ -66,11 +66,11 @@ FileAvatarMode.use(FileAvatarModeRender);
66
66
 
67
67
  ### Events
68
68
 
69
- | Method | Parameters | Description |
70
- |---|---|---|
71
- | `.onFileAdd(handler)` | `handler: (file, files) => void` | Fires when a file is added |
72
- | `.onFileRemove(handler)` | `handler: (file, files) => void` | Fires when a file is removed |
73
- | `.onReset(handler)` | `handler: () => void` | Fires when files are cleared |
69
+ | Method | Parameters | Description |
70
+ |--------------------------|---|---|
71
+ | `.onAddFile(handler)` | `handler: (file, files) => void` | Fires when a file is added |
72
+ | `.onRemoveFile(handler)` | `handler: (file, files) => void` | Fires when a file is removed |
73
+ | `.onReset(handler)` | `handler: () => void` | Fires when files are cleared |
74
74
 
75
75
  ## Modes
76
76
 
@@ -156,7 +156,7 @@ FileField('gallery')
156
156
  )
157
157
  ```
158
158
 
159
- ### `FileAvatarMode`
159
+ ### `FileImagePreviewMode`
160
160
 
161
161
  Single image upload styled as a circular avatar.
162
162
 
@@ -177,7 +177,7 @@ Single image upload styled as a circular avatar.
177
177
  FileField('avatar')
178
178
  .accept(['image/*'])
179
179
  .mode(
180
- FileAvatarMode()
180
+ FileImagePreviewMode()
181
181
  .hoverOverlay()
182
182
  .circle()
183
183
  )
@@ -196,7 +196,7 @@ FileField('documents')
196
196
  .text('Drop PDFs here')
197
197
  .icon(PdfIcon)
198
198
  )
199
- .onFileAdd(async (file) => {
199
+ .onAddFile(async (file) => {
200
200
  const url = await uploadFile(file);
201
201
  console.log('Uploaded:', url);
202
202
  })
@@ -23,7 +23,7 @@ ImageField.use(FileFieldRender);
23
23
 
24
24
  ## Methods
25
25
 
26
- All `FileField` methods apply (`accept`, `maxSize`, `mode`, `onFileAdd`…). See **[FileField](./file-field.md)** for the full reference. Image-specific additions:
26
+ All `FileField` methods apply (`accept`, `maxSize`, `mode`, `onAddFile`…). See **[FileField](./file-field.md)** for the full reference. Image-specific additions:
27
27
 
28
28
  | Method | Parameters | Description |
29
29
  |---|---|---|
@@ -64,10 +64,10 @@ ImageField('cover')
64
64
  ## Avatar example
65
65
 
66
66
  ```javascript
67
- import { FileAvatarMode } from 'native-document/components';
68
- import { FileAvatarModeRender } from 'native-document/ui';
67
+ import { FileImagePreviewMode } from 'native-document/components';
68
+ import { FileImagePreviewModeRender } from 'native-document/ui';
69
69
 
70
- FileAvatarMode.use(FileAvatarModeRender);
70
+ FileImagePreviewMode.use(FileImagePreviewModeRender);
71
71
 
72
72
  ImageField('avatar')
73
73
  .label('Profile picture')
@@ -77,7 +77,7 @@ ImageField('avatar')
77
77
  .aspectRatio('1:1', 'Must be square')
78
78
  .crop()
79
79
  .mode(
80
- FileAvatarMode()
80
+ FileImagePreviewMode()
81
81
  .hoverOverlay()
82
82
  .circle()
83
83
  )
@@ -361,7 +361,7 @@ Tokens spécifiques au `Slider` / `RangeField` :
361
361
  }
362
362
  ```
363
363
 
364
- Tokens spécifiques à `FileAvatarMode` :
364
+ Tokens spécifiques à `FileImagePreviewMode` :
365
365
 
366
366
  ```css
367
367
  :root {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "native-document",
3
- "version": "1.0.189",
3
+ "version": "1.0.191",
4
4
  "description": "A reactive JavaScript framework that preserves native DOM simplicity without sacrificing modern features",
5
5
  "author": "AfroCodeur <https://github.com/afrocodeur>",
6
6
  "license": "MIT",
@@ -14,8 +14,8 @@ import FileItemPreview from '../../field/types/file-field-mode/FileItemPreview';
14
14
  * .maxSize(5 * 1024 * 1024, 'Max 5MB per file')
15
15
  * .maxFiles(3, 'Max 3 files')
16
16
  * .mode(FileDropzoneMode())
17
- * .onFileAdd((file) => console.log('added', file.name))
18
- * .onFileRemove((file) => console.log('removed', file.name));
17
+ * .onAddFile((file) => console.log('added', file.name))
18
+ * .onRemoveFile((file) => console.log('removed', file.name));
19
19
  *
20
20
  * FileField.use((description, instance) => {
21
21
  * // description.accept, description.multiple, description.mode,
@@ -54,7 +54,7 @@ FileField.defaultTemplate = null;
54
54
  * label: NdChild|null,
55
55
  * accept: string|null,
56
56
  * multiple: boolean,
57
- * mode: FileNativeMode|FileAvatarMode|FileDropzoneMode|FileUploadButtonMode|FileWallMode|null,
57
+ * mode: FileNativeMode|FileImagePreviewMode|FileDropzoneMode|FileUploadButtonMode|FileWallMode|null,
58
58
  * files: Observable<FileItemPreview[]>,
59
59
  * fileIcons: Array<(file: File) => NdChild>,
60
60
  * disabled: boolean|Observable<boolean>,
@@ -91,7 +91,7 @@ FileField.prototype.multiple = function(enabled = true) {
91
91
  };
92
92
 
93
93
  /**
94
- * @param {FileNativeMode|FileAvatarMode|FileDropzoneMode|FileUploadButtonMode|FileWallMode|null} mode
94
+ * @param {FileNativeMode|FileImagePreviewMode|FileDropzoneMode|FileUploadButtonMode|FileWallMode|null} mode
95
95
  * @returns {this}
96
96
  */
97
97
  FileField.prototype.mode = function(mode) {
@@ -154,14 +154,23 @@ FileField.prototype.minFiles = function(min, message) {
154
154
  };
155
155
 
156
156
  /**
157
- * @param {(file: File) => void} handler
157
+ * @param {(file: FileItemPreview) => void} handler
158
158
  * @returns {this}
159
159
  */
160
- FileField.prototype.onFileAdd = function(handler) {
160
+ FileField.prototype.onAddFile = function(handler) {
161
161
  this.on('fileAdd', handler);
162
162
  return this;
163
163
  };
164
164
 
165
+ /**
166
+ * @param {(file: File) => void} handler
167
+ * @returns {this}
168
+ */
169
+ FileField.prototype.onSelectFile = function(handler) {
170
+ this.on('selectFile', handler);
171
+ return this;
172
+ };
173
+
165
174
  /**
166
175
  * @param {() => void} handler
167
176
  * @returns {this}
@@ -175,7 +184,7 @@ FileField.prototype.onReset = function(handler) {
175
184
  * @param {(file: File) => void} handler
176
185
  * @returns {this}
177
186
  */
178
- FileField.prototype.onFileRemove = function(handler) {
187
+ FileField.prototype.onRemoveFile = function(handler) {
179
188
  this.on('fileRemove', handler);
180
189
  return this;
181
190
  };
@@ -189,6 +198,7 @@ FileField.prototype.onFileRemove = function(handler) {
189
198
  FileField.prototype.addFile = function(file, update = true) {
190
199
  const item = new FileItemPreview(file);
191
200
  this.$description.files.push(item);
201
+ this.emit('selectFile', file);
192
202
  this.emit('fileAdd', item);
193
203
  update && this.$update();
194
204
  return this;
@@ -222,7 +232,7 @@ FileField.prototype.addFiles = function(files) {
222
232
 
223
233
  FileField.prototype.$update = function() {
224
234
  const files = this.$description.files.val();
225
- this.$description.value.set(this.$description.multiple ? files.map(i => i.file()) : files[0]?.file() || null);
235
+ this.$description.value?.set(this.$description.multiple ? files.map(i => i.file()) : files[0]?.file() || null);
226
236
  this.validate();
227
237
  };
228
238
 
@@ -0,0 +1,274 @@
1
+ import BaseComponent from '../../../../BaseComponent';
2
+ import HasEventEmitter from '../../../../../core/utils/HasEventEmitter';
3
+
4
+ /**
5
+ * Avatar-style single file upload mode for FileField.
6
+ * Displays a circular or square avatar with hover/badge/button interaction variants.
7
+ * Ideal for profile picture uploads.
8
+ * @example
9
+ * new FileField('avatar')
10
+ * .mode('avatar');
11
+ *
12
+ * FileImagePreviewMode.use((description, instance) => {
13
+ * // description.variant — 'hover-overlay' | 'corner-badge' | 'action-buttons'
14
+ * // description.shape — 'circle' | 'square'
15
+ * // description.size, description.placeholderIcon, description.overlayIcon,
16
+ * // description.editImageIcon, description.changeLabel, description.removeLabel,
17
+ * // description.renderAvatar, description.renderOverlay, description.renderActions
18
+ * return Div({ class: \`avatar-upload avatar-upload--\${description.variant}\`,
19
+ * style: { width: description.size, height: description.size } });
20
+ * });
21
+ *
22
+ * @constructor
23
+ * @param {GlobalAttributes} [props={}]
24
+ */
25
+ export default function FileImagePreviewMode(props = {}) {
26
+ if(!(this instanceof FileImagePreviewMode)) {
27
+ return new FileImagePreviewMode(props);
28
+ }
29
+
30
+ BaseComponent.call(this, props);
31
+
32
+ this.$description = {
33
+ variant: 'hover-overlay',
34
+ shape: 'circle',
35
+ size: null,
36
+ placeholderIcon: null,
37
+ overlayIcon: null,
38
+ editImageIcon: null,
39
+ changeLabel: 'Change photo',
40
+ removeLabel: 'Remove',
41
+ renderAvatar: null,
42
+ renderOverlay: null,
43
+ renderActions: null,
44
+ mode: 'avatar',
45
+ ratio: null,
46
+ props,
47
+ };
48
+ }
49
+
50
+ BaseComponent.extends(FileImagePreviewMode);
51
+ BaseComponent.use(FileImagePreviewMode, HasEventEmitter);
52
+
53
+ FileImagePreviewMode.defaultTemplate = null;
54
+
55
+ /**
56
+ * Registers the render template for FileImagePreviewMode.
57
+ * @param {(description: {
58
+ * variant: 'hover-overlay'|'corner-badge'|'action-buttons',
59
+ * shape: 'circle'|'square',
60
+ * size: number|string,
61
+ * placeholderIcon: NdChild|null,
62
+ * overlayIcon: NdChild|null,
63
+ * editImageIcon: NdChild|null,
64
+ * changeLabel: NdChild,
65
+ * removeLabel: NdChild,
66
+ * renderAvatar: ((desc: *, instance: FileImagePreviewMode) => NdChild)|null,
67
+ * renderOverlay: ((desc: *, instance: FileImagePreviewMode) => NdChild)|null,
68
+ * renderActions: ((desc: *, instance: FileImagePreviewMode) => NdChild)|null,
69
+ * props: GlobalAttributes
70
+ * }, instance: FileImagePreviewMode) => NdChild} template
71
+ */
72
+ FileImagePreviewMode.use = function(template) {
73
+ FileImagePreviewMode.defaultTemplate = template;
74
+ };
75
+
76
+ /** @returns {this} */
77
+ FileImagePreviewMode.prototype.hoverOverlay = function() {
78
+ this.$description.variant = 'hover-overlay';
79
+ return this;
80
+ };
81
+
82
+ /** @returns {this} */
83
+ FileImagePreviewMode.prototype.cornerBadge = function() {
84
+ this.$description.variant = 'corner-badge';
85
+ return this;
86
+ };
87
+
88
+ /** @returns {this} */
89
+ FileImagePreviewMode.prototype.actionButtons = function() {
90
+ this.$description.variant = 'action-buttons';
91
+ return this;
92
+ };
93
+
94
+ /** @returns {this} */
95
+ FileImagePreviewMode.prototype.circle = function() {
96
+ this.$description.shape = 'circle';
97
+ return this;
98
+ };
99
+
100
+ /** @returns {this} */
101
+ FileImagePreviewMode.prototype.square = function() {
102
+ this.$description.shape = 'square';
103
+ return this;
104
+ };
105
+
106
+ /**
107
+ * @param {number|string} size - Size in pixels or CSS value
108
+ * @returns {this}
109
+ */
110
+ FileImagePreviewMode.prototype.size = function(size) {
111
+ this.$description.size = size;
112
+ return this;
113
+ };
114
+
115
+ /**
116
+ * @param {NdChild} icon
117
+ * @returns {this}
118
+ */
119
+ FileImagePreviewMode.prototype.placeholderIcon = function(icon) {
120
+ this.$description.placeholderIcon = icon;
121
+ return this;
122
+ };
123
+
124
+ /**
125
+ * @param {NdChild} icon
126
+ * @returns {this}
127
+ */
128
+ FileImagePreviewMode.prototype.overlayIcon = function(icon) {
129
+ this.$description.overlayIcon = icon;
130
+ return this;
131
+ };
132
+
133
+ /**
134
+ * @param {NdChild} icon
135
+ * @returns {this}
136
+ */
137
+ FileImagePreviewMode.prototype.editImageIcon = function(icon) {
138
+ this.$description.editImageIcon = icon;
139
+ return this;
140
+ };
141
+
142
+ /**
143
+ * @param {NdChild} label
144
+ * @returns {this}
145
+ */
146
+ FileImagePreviewMode.prototype.changeLabel = function(label) {
147
+ this.$description.changeLabel = label;
148
+ return this;
149
+ };
150
+
151
+ /**
152
+ * @param {NdChild} label
153
+ * @returns {this}
154
+ */
155
+ FileImagePreviewMode.prototype.removeLabel = function(label) {
156
+ this.$description.removeLabel = label;
157
+ return this;
158
+ };
159
+
160
+ /**
161
+ * @param {(desc: *, instance: FileImagePreviewMode) => NdChild} fn
162
+ * @returns {this}
163
+ */
164
+ FileImagePreviewMode.prototype.renderAvatar = function(fn) {
165
+ this.$description.renderAvatar = fn;
166
+ return this;
167
+ };
168
+
169
+ /**
170
+ * @param {(desc: *, instance: FileImagePreviewMode) => NdChild} fn
171
+ * @returns {this}
172
+ */
173
+ FileImagePreviewMode.prototype.renderOverlay = function(fn) {
174
+ this.$description.renderOverlay = fn;
175
+ return this;
176
+ };
177
+
178
+ /**
179
+ * @param {(desc: *, instance: FileImagePreviewMode) => NdChild} fn
180
+ * @returns {this}
181
+ */
182
+ FileImagePreviewMode.prototype.renderActions = function(fn) {
183
+ this.$description.renderActions = fn;
184
+ return this;
185
+ };
186
+
187
+ /**
188
+ * Configures the component specifically for avatar preset (circular default).
189
+ * @returns {this}
190
+ */
191
+ FileImagePreviewMode.prototype.asAvatar = function() {
192
+ this.$description.mode = 'avatar';
193
+ return this;
194
+ };
195
+ /**
196
+ * Configures the component specifically for banner/cover preset (square default).
197
+ * @returns {this}
198
+ */
199
+ FileImagePreviewMode.prototype.asCover = function() {
200
+ this.$description.mode = 'cover';
201
+ this.square();
202
+ return this;
203
+ };
204
+
205
+ /**
206
+ * Sets CSS aspect-ratio or ratio string (e.g. '16/9', '3/1', 1.77)
207
+ * @param {string|number} ratio
208
+ * @returns {this}
209
+ */
210
+ FileImagePreviewMode.prototype.ratio = function(ratio) {
211
+ this.$description.ratio = ratio;
212
+ return this;
213
+ };
214
+
215
+ /**
216
+ * Sets aspect ratio to 1:1 (Square).
217
+ * Ideal for avatars, product thumbnails, or Instagram feed items.
218
+ * @returns {this}
219
+ */
220
+ FileImagePreviewMode.prototype.squareRatio = function() {
221
+ this.$description.ratio = '1/1';
222
+ return this;
223
+ };
224
+
225
+ /**
226
+ * Sets aspect ratio to 16:9 (Widescreen).
227
+ * Ideal for video previews, event covers, and standard web banners.
228
+ * @returns {this}
229
+ */
230
+ FileImagePreviewMode.prototype.widescreenRatio = function() {
231
+ this.$description.ratio = '16/9';
232
+ return this;
233
+ };
234
+
235
+ /**
236
+ * Sets aspect ratio to an ultra-wide banner format (defaults to 3:1).
237
+ * Ideal for profile headers (e.g., Twitter, LinkedIn) or hero banners.
238
+ * @param {string} [customRatio='3/1'] - Custom ratio string if different from '3/1' (e.g., '4/1')
239
+ * @returns {this}
240
+ */
241
+ FileImagePreviewMode.prototype.bannerRatio = function(customRatio = '3/1') {
242
+ this.$description.ratio = customRatio;
243
+ return this;
244
+ };
245
+
246
+ /**
247
+ * Sets aspect ratio to 4:3 (Landscape).
248
+ * Ideal for traditional photography, blog thumbnails, or product cards.
249
+ * @returns {this}
250
+ */
251
+ FileImagePreviewMode.prototype.landscapeRatio = function() {
252
+ this.$description.ratio = '4/3';
253
+ return this;
254
+ };
255
+
256
+ /**
257
+ * Sets aspect ratio to 9:16 (Story / Full Mobile).
258
+ * Ideal for mobile-first vertical media (Instagram Stories, Reels, TikTok).
259
+ * @returns {this}
260
+ */
261
+ FileImagePreviewMode.prototype.storyRatio = function() {
262
+ this.$description.ratio = '9/16';
263
+ return this;
264
+ };
265
+
266
+ /**
267
+ * Sets aspect ratio to 4:5 (Social Portrait).
268
+ * Ideal for Instagram or Facebook feed posts optimized for mobile screen height.
269
+ * @returns {this}
270
+ */
271
+ FileImagePreviewMode.prototype.portraitRatio = function() {
272
+ this.$description.ratio = '4/5';
273
+ return this;
274
+ };
@@ -24,7 +24,7 @@ import FileNativeMode from './field/types/file-field-mode/FileNativeMode';
24
24
  import FileDropzoneMode from './field/types/file-field-mode/FileDropzoneMode';
25
25
  import FileUploadButtonMode from './field/types/file-field-mode/FileUploadButtonMode';
26
26
  import FileWallMode from './field/types/file-field-mode/FileWallMode';
27
- import FileAvatarMode from './field/types/file-field-mode/FileAvatarMode';
27
+ import FileImagePreviewMode from './field/types/file-field-mode/FileImagePreviewMode';
28
28
 
29
29
  // import './field/FieldFactory';
30
30
 
@@ -53,7 +53,7 @@ export {
53
53
  FieldCollection,
54
54
 
55
55
  FileNativeMode,
56
- FileAvatarMode,
56
+ FileImagePreviewMode,
57
57
  FileWallMode,
58
58
  FileUploadButtonMode,
59
59
  FileDropzoneMode,
@@ -31,10 +31,10 @@ export interface FileFieldInterface extends Omit<FieldInterface, 'render' | 'res
31
31
  extensions(extensions: string[], message?: string): this;
32
32
  maxFiles(max: number, message?: string): this;
33
33
  minFiles(min: number, message?: string): this;
34
- onFileAdd(handler: (file: File) => void): this;
34
+ onAddFile(handler: (file: File) => void): this;
35
35
  onReset(handler: () => void): this;
36
- onFileRemove(handler: (file: File) => void): this;
37
- addFile(file: File, update?: boolean): this;
36
+ onRemoveFile(handler: (file: File) => void): this;
37
+ addFile(file: FileItemPreviewInterface, update?: boolean): this;
38
38
  setFiles(files: File[]): this;
39
39
  addFiles(files: File[]): this;
40
40
  removeFile(file: File): this;
@@ -0,0 +1,57 @@
1
+ import type { ValidChild } from '../../../../../types/elements';
2
+ import type { GlobalAttributes } from '../../../../../types/globals';
3
+ import type { BaseComponent } from '../../../BaseComponent';
4
+
5
+ export type FileImagePreviewModeDescription = {
6
+ variant: 'hover-overlay' | 'corner-badge' | 'action-buttons';
7
+ shape: 'circle' | 'square';
8
+ size: number | string;
9
+ placeholderIcon: ValidChild | null;
10
+ overlayIcon: ValidChild | null;
11
+ editImageIcon: ValidChild | null;
12
+ changeLabel: ValidChild;
13
+ removeLabel: ValidChild;
14
+ renderAvatar: ((desc: unknown, instance: FileImagePreviewModeInterface) => ValidChild) | null;
15
+ renderOverlay: ((desc: unknown, instance: FileImagePreviewModeInterface) => ValidChild) | null;
16
+ renderActions: ((desc: unknown, instance: FileImagePreviewModeInterface) => ValidChild) | null;
17
+ props: GlobalAttributes;
18
+ };
19
+
20
+ export interface FileImagePreviewModeInterface extends BaseComponent {
21
+ render(renderFn: (description: FileImagePreviewModeDescription, instance: FileImagePreviewModeInterface) => ValidChild): this;
22
+ hoverOverlay(): this;
23
+ cornerBadge(): this;
24
+ actionButtons(): this;
25
+ circle(): this;
26
+ square(): this;
27
+ asAvatar(): this;
28
+ asCover(): this;
29
+ ratio(ratio: string): this;
30
+
31
+ ratio(ratio: string | number): this;
32
+
33
+ squareRatio(): this;
34
+ widescreenRatio(): this;
35
+ bannerRatio(customRatio?: string): this;
36
+ landscapeRatio(): this;
37
+ storyRatio(): this;
38
+ portraitRatio(): this;
39
+
40
+ size(size: number | string): this;
41
+ placeholderIcon(icon: ValidChild): this;
42
+ overlayIcon(icon: ValidChild): this;
43
+ editImageIcon(icon: ValidChild): this;
44
+ changeLabel(label: ValidChild): this;
45
+ removeLabel(label: ValidChild): this;
46
+ renderAvatar(fn: (desc: unknown, instance: FileImagePreviewModeInterface) => ValidChild): this;
47
+ renderOverlay(fn: (desc: unknown, instance: FileImagePreviewModeInterface) => ValidChild): this;
48
+ renderActions(fn: (desc: unknown, instance: FileImagePreviewModeInterface) => ValidChild): this;
49
+ }
50
+
51
+
52
+ export declare function FileImagePreviewMode(props?: GlobalAttributes): FileImagePreviewModeInterface;
53
+ export declare namespace FileImagePreviewMode {
54
+
55
+ function use(template: (description: FileImagePreviewModeDescription, instance: FileImagePreviewModeInterface) => ValidChild): void;
56
+
57
+ }
@@ -78,7 +78,7 @@ export type { RangeField, RangeFieldInterface } from './form/types/fields/RangeF
78
78
  export type { SearchField, SearchFieldInterface } from './form/types/fields/SearchField';
79
79
  export type { FileField, FileFieldInterface } from './form/types/fields/FileField';
80
80
  export type { ImageField, ImageFieldInterface } from './form/types/fields/ImageField';
81
- export type { FileAvatarMode, FileAvatarModeInterface, FileAvatarModeDescription } from './form/types/fields/FileAvatarMode';
81
+ export type { FileImagePreviewMode, FileImagePreviewModeInterface, FileImagePreviewModeDescription } from './form/types/fields/FileImagePreviewMode';
82
82
  export type { FileDropzoneMode, FileDropzoneModeInterface, FileDropzoneModeDescription } from './form/types/fields/FileDropzoneMode';
83
83
  export type { FileItemPreview, FileItemPreviewInterface, FileItemPreviewDescription } from './form/types/fields/FileItemPreview';
84
84
  export type { FileNativeMode, FileNativeModeInterface, FileNativeModeDescription } from './form/types/fields/FileNativeMode';
@@ -176,6 +176,19 @@ Observable.computed = function(callback, dependencies = []) {
176
176
  };
177
177
  ObservableItem.computed = Observable.computed;
178
178
 
179
+ Observable.auto = (value) => {
180
+ if(value == null) {
181
+ return new ObservableItem(value);
182
+ }
183
+ if(Validator.isArray(value)) {
184
+ return new ObservableArray(value);
185
+ } else if(typeof value === 'object') {
186
+ return new ObservableObject(value);
187
+ }
188
+ return new ObservableItem(value);
189
+ };
190
+ ObservableItem.auto = Observable.auto;
191
+
179
192
 
180
193
  Observable.init = function(initialValue, configs = null) {
181
194
  return new ObservableObject(initialValue, configs);
@@ -59,6 +59,7 @@ Object.defineProperty(ObservableItem.prototype, '$value', {
59
59
  ObservableItem.prototype.__$Observable = true;
60
60
  ObservableItem.prototype.__$isObservable = true;
61
61
  ObservableItem.computed = () => {};
62
+ ObservableItem.auto = () => {};
62
63
 
63
64
  const DEFAULT_OPERATIONS = {};
64
65
  const noneTrigger = function() {};
@@ -22,16 +22,7 @@ export const ObservableObject = function(target, configs) {
22
22
  this.configs = configs;
23
23
 
24
24
  for(const key in target) {
25
- if(!Object.hasOwn(this, key)) {
26
- Object.defineProperty(this, key, {
27
- get: () => this.$observables[key],
28
- set: (value) => {
29
- this.$observables[key].set(value);
30
- },
31
- configurable: true,
32
- enumerable: true,
33
- });
34
- }
25
+ this.$addKey(key);
35
26
  }
36
27
 
37
28
  this.$load(target);
@@ -60,6 +51,32 @@ Object.defineProperty(ObservableObject, '$value', {
60
51
  ObservableObject.prototype.__$isObservableObject = true;
61
52
  ObservableObject.prototype.__isProxy__ = true;
62
53
 
54
+ ObservableObject.prototype.$addKey = function(key) {
55
+ if(!Object.hasOwn(this, key)) {
56
+ Object.defineProperty(this, key, {
57
+ get: () => this.$observables[key],
58
+ set: (value) => {
59
+ this.$observables[key].set(value);
60
+ },
61
+ configurable: true,
62
+ enumerable: true,
63
+ });
64
+ }
65
+ };
66
+
67
+
68
+ /**
69
+ *
70
+ * @param {String[]} properties
71
+ */
72
+ ObservableObject.prototype.only = function(properties) {
73
+ const result = {};
74
+ for(const key in properties) {
75
+ result[key] = this.$observables[key]?.val();
76
+ }
77
+ return result;
78
+ };
79
+
63
80
  /**
64
81
  * Initialises (or reinitialize) the internal observables map from a plain object.
65
82
  * Called automatically in the constructor.
@@ -182,7 +199,7 @@ ObservableObject.prototype.set = function(newData) {
182
199
  if(firstElementFromOriginalValue.__$isObservableObject) {
183
200
  return new ObservableObject(item, configs);
184
201
  }
185
- return ObservableItem(item, configs);
202
+ return new ObservableItem(item, configs);
186
203
  });
187
204
  targetItem.set(newValues);
188
205
  continue;
@@ -190,7 +207,9 @@ ObservableObject.prototype.set = function(newData) {
190
207
  targetItem.set([...newValue]);
191
208
  continue;
192
209
  }
193
- this[key] = newValue;
210
+ const value = ObservableItem.auto(newValue);
211
+ this.$observables[key] = value;
212
+ this.$addKey(key);
194
213
  }
195
214
  };
196
215
  ObservableObject.prototype.$set = ObservableObject.prototype.set;