native-document 1.0.247 → 1.0.249
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/package.json +1 -1
- package/src/components/form/field/FieldCollection.js +44 -10
- package/src/components/form/field/types/AddressSearchField.js +60 -0
- package/src/components/form/field/types/SearchField.js +10 -1
- package/src/components/form/types/FieldCollection.d.ts +1 -0
- package/src/components/form/types/fields/SelectField.d.ts +1 -1
- package/src/components/list/ListGroup.js +1 -0
- package/src/components/map/address-map-picker/AddressMapPicker.js +15 -0
- package/src/core/data/ObservableArray.js +2 -1
- package/src/core/data/ObservableItem.js +33 -1
- package/src/core/data/ObservableObject.js +6 -2
- package/src/ui/components/form/FieldCollectionRender.js +2 -1
- package/src/ui/components/popover/PopoverRender.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "native-document",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.249",
|
|
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",
|
|
@@ -45,6 +45,7 @@ export default function FieldCollection(name, props = {}) {
|
|
|
45
45
|
layout: null,
|
|
46
46
|
transition: null,
|
|
47
47
|
label: null,
|
|
48
|
+
filter: null,
|
|
48
49
|
props,
|
|
49
50
|
};
|
|
50
51
|
|
|
@@ -79,7 +80,7 @@ FieldCollection.use = function(template) {
|
|
|
79
80
|
};
|
|
80
81
|
|
|
81
82
|
/**
|
|
82
|
-
* @param {(
|
|
83
|
+
* @param {(index: number) => Record<string, NdChild>} fieldBuilder
|
|
83
84
|
* @returns {this}
|
|
84
85
|
*/
|
|
85
86
|
FieldCollection.prototype.fields = function(fieldBuilder) {
|
|
@@ -148,32 +149,49 @@ FieldCollection.prototype.transition = function(transitionName) {
|
|
|
148
149
|
FieldCollection.prototype.model = function(observable) {
|
|
149
150
|
if(Validator.isObservable(observable)) {
|
|
150
151
|
this.$description.value = observable;
|
|
151
|
-
this.$description.value.interceptMutations((items) =>
|
|
152
|
-
items.map(item => Validator.isObservable(item) ? item : $.object(item))
|
|
153
|
-
);
|
|
152
|
+
this.$description.value.interceptMutations((items) => {
|
|
153
|
+
return items.map(item => Validator.isObservable(item) ? item : $.object(item));
|
|
154
|
+
});
|
|
154
155
|
return this;
|
|
155
156
|
}
|
|
156
157
|
this.$description.value.set(observable);
|
|
157
158
|
return this;
|
|
158
159
|
};
|
|
159
160
|
|
|
161
|
+
|
|
160
162
|
/**
|
|
163
|
+
* @param {*} data
|
|
161
164
|
* @returns {this}
|
|
162
165
|
*/
|
|
163
|
-
FieldCollection.prototype.add = function() {
|
|
166
|
+
FieldCollection.prototype.add = function(data) {
|
|
164
167
|
if(!this.$description.fieldBuilder) {
|
|
165
168
|
throw new NativeDocumentError('FieldCollection: fields() must be defined before add()');
|
|
166
169
|
}
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
const item = this.$dataSet(data);
|
|
171
|
+
if(!item) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
171
174
|
|
|
172
175
|
this.$description.value.push(item);
|
|
173
176
|
this.emit('add', item);
|
|
174
177
|
return this;
|
|
175
178
|
};
|
|
176
179
|
|
|
180
|
+
FieldCollection.prototype.$dataSet = function(data) {
|
|
181
|
+
const dataBuilder = this.$description.defaultItem;
|
|
182
|
+
|
|
183
|
+
let raw = {};
|
|
184
|
+
if(dataBuilder) {
|
|
185
|
+
const dataSet =this.$description.defaultItem(data);
|
|
186
|
+
if(!dataSet) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
raw = dataSet;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return Validator.isObservable(raw) ? raw : $.object(raw);
|
|
193
|
+
};
|
|
194
|
+
|
|
177
195
|
/**
|
|
178
196
|
* @param {*} item
|
|
179
197
|
* @returns {this}
|
|
@@ -204,9 +222,25 @@ FieldCollection.prototype.reset = function() {
|
|
|
204
222
|
* @returns {*[]}
|
|
205
223
|
*/
|
|
206
224
|
FieldCollection.prototype.value = function() {
|
|
207
|
-
|
|
225
|
+
const raw = this.$description.value.map(item =>
|
|
208
226
|
Validator.isObservable(item) ? item.val() : item,
|
|
209
227
|
);
|
|
228
|
+
const filter = this.$description.filter;
|
|
229
|
+
return filter ? raw.filter(filter) : raw;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Predicate applied on value() export to filter out unwanted items.
|
|
234
|
+
*
|
|
235
|
+
* @param {(item: *) => boolean} fn
|
|
236
|
+
* @returns {this}
|
|
237
|
+
*/
|
|
238
|
+
FieldCollection.prototype.filter = function(fn) {
|
|
239
|
+
if (typeof fn !== 'function') {
|
|
240
|
+
throw new NativeDocumentError('FieldCollection.filter() expects a function');
|
|
241
|
+
}
|
|
242
|
+
this.$description.filter = fn;
|
|
243
|
+
return this;
|
|
210
244
|
};
|
|
211
245
|
|
|
212
246
|
/**
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { $ } from '../../../../core/data/Observable';
|
|
2
|
+
import Field from '../Field';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export default function AddressSearchField(name, props = {}) {
|
|
6
|
+
if(!(this instanceof AddressSearchField)) {
|
|
7
|
+
return new AddressSearchField(name, props);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
Field.call(this, name, 'input', props);
|
|
11
|
+
|
|
12
|
+
Object.assign(this.$description, {
|
|
13
|
+
renderSuggestion: null
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
AddressSearchField.defaultTemplate = null;
|
|
19
|
+
|
|
20
|
+
AddressSearchField.prototype = Object.create(Field.prototype);
|
|
21
|
+
AddressSearchField.prototype.constructor = AddressSearchField;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Registers the render template for AddressSearchField.
|
|
25
|
+
* @param {(description: {
|
|
26
|
+
* value: Observable<string>,
|
|
27
|
+
* placeholder: string|null,
|
|
28
|
+
* debounceMs: number,
|
|
29
|
+
* disabled: Observable<boolean>|null,
|
|
30
|
+
* loading: Observable<boolean>|null,
|
|
31
|
+
* props: GlobalAttributes,
|
|
32
|
+
* }, instance: AddressSearchField) => NdChild} template
|
|
33
|
+
*/
|
|
34
|
+
AddressSearchField.use = function(template) {
|
|
35
|
+
AddressSearchField.defaultTemplate = template;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {Observable} $loading
|
|
41
|
+
* @return {this}
|
|
42
|
+
*/
|
|
43
|
+
AddressSearchField.prototype.loading = function($loading){
|
|
44
|
+
this.$description.loading = $loading;
|
|
45
|
+
return this;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {(sugesstion: *) => {}} callback
|
|
50
|
+
* @return {AddressSearchField}
|
|
51
|
+
*/
|
|
52
|
+
AddressSearchField.prototype.onSuggestions = function(callback){
|
|
53
|
+
this.$description.callback = callback;
|
|
54
|
+
return this;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
AddressSearchField.prototype.renderSuggestion = function(renderFn){
|
|
58
|
+
this.$description.renderSuggestion = renderFn;
|
|
59
|
+
return this;
|
|
60
|
+
};
|
|
@@ -63,4 +63,13 @@ SearchField.prototype.constructor = SearchField;
|
|
|
63
63
|
SearchField.prototype.debounce = function(ms) {
|
|
64
64
|
this.$description.debounce = ms;
|
|
65
65
|
return this;
|
|
66
|
-
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {Observable} $loading
|
|
70
|
+
* @return {this}
|
|
71
|
+
*/
|
|
72
|
+
SearchField.prototype.loading = function($loading){
|
|
73
|
+
this.$description.loading = $loading;
|
|
74
|
+
return this;
|
|
75
|
+
};
|
|
@@ -34,6 +34,7 @@ export interface FieldCollectionInterface extends Omit<BaseComponent, 'onChange'
|
|
|
34
34
|
value(): unknown[];
|
|
35
35
|
count(): number;
|
|
36
36
|
isEmpty(): boolean;
|
|
37
|
+
filter(handler: (item: any) => boolean): this;
|
|
37
38
|
onChange(handler: () => void): this;
|
|
38
39
|
onAdd(handler: () => void): this;
|
|
39
40
|
onRemove(handler: (item: unknown) => void): this;
|
|
@@ -40,7 +40,7 @@ export type SelectFieldDescription = {
|
|
|
40
40
|
props: GlobalAttributes;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
export interface SelectFieldInterface extends Omit<FieldInterface, 'render'> {
|
|
43
|
+
export interface SelectFieldInterface extends Omit<FieldInterface, 'render' | 'onChange'> {
|
|
44
44
|
render(renderFn: (description: SelectFieldDescription, instance: SelectFieldInterface) => ValidChild): this;
|
|
45
45
|
options(opts: SelectOption[]): this;
|
|
46
46
|
option(value: unknown, label: ValidChild, props?: GlobalAttributes): this;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import BaseComponent from '../../BaseComponent';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export default function AddressMapPicker() {
|
|
5
|
+
if(!(this instanceof AddressMapPicker)) {
|
|
6
|
+
return new AddressMapPicker();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
this.$description = {
|
|
10
|
+
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
BaseComponent.extends(AddressMapPicker);
|
|
@@ -466,6 +466,7 @@ ObservableArray.prototype.deepSubscribe = function(callback) {
|
|
|
466
466
|
};
|
|
467
467
|
};
|
|
468
468
|
|
|
469
|
+
|
|
469
470
|
/**
|
|
470
471
|
* Keeps this array in sync with another ObservableArray.
|
|
471
472
|
* All mutations are mirrored to the target array in real time.
|
|
@@ -539,7 +540,7 @@ ObservableArray.prototype.fnClear = function () {
|
|
|
539
540
|
return () => this.clear();
|
|
540
541
|
};
|
|
541
542
|
|
|
542
|
-
ObservableArray.prototype.
|
|
543
|
+
ObservableArray.prototype.rawValue = function () {
|
|
543
544
|
const result = [];
|
|
544
545
|
for(const element of this.$currentValue) {
|
|
545
546
|
result.push(element?.__$Observable ? element.val() : element);
|
|
@@ -88,7 +88,17 @@ ObservableItem.prototype.intercept = function(callback) {
|
|
|
88
88
|
* @returns {ObservableItem} this
|
|
89
89
|
*/
|
|
90
90
|
ObservableItem.prototype.interceptMutations = function(callback) {
|
|
91
|
-
|
|
91
|
+
if (typeof callback !== 'function') {
|
|
92
|
+
throw new NativeDocumentError('interceptMutations expects a function');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const previousMutationInterceptor = this.$mutationInterceptor;
|
|
96
|
+
this.$mutationInterceptor = (data, ...args) => {
|
|
97
|
+
const prevResult = previousMutationInterceptor ? previousMutationInterceptor(data, ...args) : undefined;
|
|
98
|
+
const nextData = prevResult !== undefined ? prevResult : data;
|
|
99
|
+
const result = callback(nextData, ...args);
|
|
100
|
+
return result !== undefined ? result : nextData;
|
|
101
|
+
};
|
|
92
102
|
return this;
|
|
93
103
|
};
|
|
94
104
|
|
|
@@ -646,6 +656,28 @@ ObservableItem.prototype.clone = function() {
|
|
|
646
656
|
return new ObservableItem(clonedValue);
|
|
647
657
|
};
|
|
648
658
|
|
|
659
|
+
/**
|
|
660
|
+
* @param {ObservableItem} targetObservable
|
|
661
|
+
* @return {(function())|*}
|
|
662
|
+
*/
|
|
663
|
+
ObservableItem.prototype.sync = function(targetObservable) {
|
|
664
|
+
if(this === targetObservable) {
|
|
665
|
+
return () => {};
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
const updateTargetObservable = (newValue) => targetObservable.set(newValue);
|
|
669
|
+
const updateCurrentObservable = (newValue) => this.set(newValue);
|
|
670
|
+
|
|
671
|
+
this.subscribe(updateTargetObservable);
|
|
672
|
+
targetObservable.subscribe(updateCurrentObservable);
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
return () => {
|
|
676
|
+
this.unsubscribe(updateTargetObservable);
|
|
677
|
+
targetObservable.unsubscribe(updateCurrentObservable);
|
|
678
|
+
};
|
|
679
|
+
};
|
|
680
|
+
|
|
649
681
|
|
|
650
682
|
ObservableItem.prototype.fnSet = function(value) {
|
|
651
683
|
return () => this.set(value);
|
|
@@ -16,10 +16,14 @@ import ObservableArray from './ObservableArray';
|
|
|
16
16
|
* const user = Observable.object({ name: 'John', age: 25 });
|
|
17
17
|
* user.name.$value = 'Jane'; // triggers reactivity on name only
|
|
18
18
|
*/
|
|
19
|
-
export const ObservableObject = function(target, configs) {
|
|
19
|
+
export const ObservableObject = function(target, configs = { }) {
|
|
20
20
|
ObservableItem.call(this, target);
|
|
21
21
|
this.$observables = {};
|
|
22
|
-
this.configs =
|
|
22
|
+
this.configs = {
|
|
23
|
+
deep: true,
|
|
24
|
+
propagation: true,
|
|
25
|
+
...configs,
|
|
26
|
+
};
|
|
23
27
|
|
|
24
28
|
for(const key in target) {
|
|
25
29
|
this.$addKey(key);
|
|
@@ -4,6 +4,8 @@ import { $ } from '../../../core/data/Observable';
|
|
|
4
4
|
import {H2} from '../../../core/elements';
|
|
5
5
|
|
|
6
6
|
import './field-collection.css';
|
|
7
|
+
import {buildRow} from '../table/data-table/tables';
|
|
8
|
+
import {items} from 'happy-dom/lib/PropertySymbol';
|
|
7
9
|
|
|
8
10
|
export default function FieldCollectionRender($desc, instance) {
|
|
9
11
|
const props = instance.getEditableProps();
|
|
@@ -116,7 +118,6 @@ export default function FieldCollectionRender($desc, instance) {
|
|
|
116
118
|
return Div(instance.resolveProps(), layout({ button, rows, label }));
|
|
117
119
|
}
|
|
118
120
|
|
|
119
|
-
|
|
120
121
|
const defaultLayout = ({ label, button, rows }) => {
|
|
121
122
|
|
|
122
123
|
return [
|
|
@@ -80,7 +80,7 @@ export default function PopoverRender($desc, instance, classPrefix = 'popover')
|
|
|
80
80
|
if($desc.showIf && $desc.showIf.val() === false) {
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
|
-
if(isSupportsPopover) {
|
|
83
|
+
if(isSupportsPopover && popover.isConnected) {
|
|
84
84
|
popover.showPopover();
|
|
85
85
|
}
|
|
86
86
|
|