native-document 1.0.94 → 1.0.98
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/{src/devtools/hrm → devtools}/ComponentRegistry.js +2 -2
- package/devtools/index.js +8 -0
- package/{src/devtools/plugin.js → devtools/plugin/dev-tools-plugin.js} +2 -2
- package/{src/devtools/hrm/nd-vite-hot-reload.js → devtools/transformers/nd-vite-devtools.js} +16 -6
- package/devtools/transformers/src/transformComponentForHrm.js +74 -0
- package/devtools/transformers/src/transformJsFile.js +9 -0
- package/devtools/transformers/src/utils.js +79 -0
- package/devtools/widget/Widget.js +48 -0
- package/devtools/widget/widget.css +81 -0
- package/devtools/widget.js +23 -0
- package/dist/native-document.components.min.js +2441 -1191
- package/dist/native-document.dev.js +2710 -1359
- package/dist/native-document.dev.js.map +1 -1
- package/dist/native-document.devtools.min.js +1 -1
- package/dist/native-document.min.js +1 -1
- package/docs/cache.md +1 -1
- package/docs/core-concepts.md +1 -1
- package/docs/native-document-element.md +51 -15
- package/docs/observables.md +310 -306
- package/docs/state-management.md +198 -193
- package/index.def.js +762 -26
- package/package.json +1 -1
- package/readme.md +1 -1
- package/src/core/data/ObservableChecker.js +2 -0
- package/src/core/data/ObservableItem.js +97 -0
- package/src/core/data/ObservableObject.js +182 -0
- package/src/core/data/Store.js +364 -34
- package/src/core/data/observable-helpers/object.js +2 -166
- package/src/core/elements/anchor.js +28 -20
- package/src/core/elements/control/for-each.js +1 -1
- package/src/core/utils/formatters.js +91 -0
- package/src/core/utils/localstorage.js +57 -0
- package/src/core/utils/validator.js +0 -2
- package/src/core/wrappers/DocumentObserver.js +102 -31
- package/src/core/wrappers/ElementCreator.js +5 -0
- package/src/core/wrappers/NDElement.js +32 -1
- package/src/core/wrappers/prototypes/nd-element.transition.extensions.js +83 -0
- package/src/devtools.js +9 -0
- package/src/fetch/NativeFetch.js +5 -2
- package/types/elements.d.ts +580 -2
- package/types/nd-element.d.ts +6 -0
- package/types/observable.d.ts +71 -15
- package/types/plugins-manager.d.ts +1 -1
- package/types/store.d.ts +33 -6
- package/hrm.js +0 -7
- package/src/devtools/app/App.js +0 -66
- package/src/devtools/app/app.css +0 -0
- package/src/devtools/hrm/transformComponent.js +0 -129
- package/src/devtools/index.js +0 -18
- package/src/devtools/widget/DevToolsWidget.js +0 -26
- /package/{src/devtools/hrm → devtools/transformers/templates}/hrm.hook.template.js +0 -0
- /package/{src/devtools/hrm → devtools/transformers/templates}/hrm.orbservable.hook.template.js +0 -0
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -317,4 +317,4 @@ Thanks to all contributors and the JavaScript community for inspiration.
|
|
|
317
317
|
|
|
318
318
|
---
|
|
319
319
|
|
|
320
|
-
**Ready to build with native simplicity?** [Get Started
|
|
320
|
+
**Ready to build with native simplicity?** [Get Started ->](docs/getting-started.md)
|
|
@@ -6,6 +6,10 @@ import PluginsManager from "../../core/utils/plugins-manager";
|
|
|
6
6
|
import Validator from "../../core/utils/validator";
|
|
7
7
|
import {ObservableWhen} from "./ObservableWhen";
|
|
8
8
|
import {deepClone} from "../utils/helpers";
|
|
9
|
+
import {Store} from "./Store";
|
|
10
|
+
import { Formatters} from "../utils/formatters";
|
|
11
|
+
import {Observable} from "./Observable";
|
|
12
|
+
import {$getFromStorage, $saveToStorage} from "../utils/localstorage";
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
*
|
|
@@ -368,6 +372,11 @@ ObservableItem.prototype.check = function(callback) {
|
|
|
368
372
|
return new ObservableChecker(this, callback)
|
|
369
373
|
};
|
|
370
374
|
|
|
375
|
+
ObservableItem.prototype.transform = ObservableItem.prototype.check;
|
|
376
|
+
ObservableItem.prototype.pluck = ObservableItem.prototype.check;
|
|
377
|
+
ObservableItem.prototype.is = ObservableItem.prototype.check;
|
|
378
|
+
ObservableItem.prototype.select = ObservableItem.prototype.check;
|
|
379
|
+
|
|
371
380
|
/**
|
|
372
381
|
* Gets a property value from the observable's current value.
|
|
373
382
|
* If the property is an observable, returns its value.
|
|
@@ -483,4 +492,92 @@ ObservableItem.prototype.toString = function() {
|
|
|
483
492
|
*/
|
|
484
493
|
ObservableItem.prototype.valueOf = function() {
|
|
485
494
|
return this.$currentValue;
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Creates a derived observable that formats the current value using Intl.
|
|
500
|
+
* Automatically reacts to both value changes and locale changes (Store.__nd.locale).
|
|
501
|
+
*
|
|
502
|
+
* @param {string | Function} type - Format type or custom formatter function
|
|
503
|
+
* @param {Object} [options={}] - Options passed to the formatter
|
|
504
|
+
* @returns {ObservableItem<string>}
|
|
505
|
+
*
|
|
506
|
+
* @example
|
|
507
|
+
* // Currency
|
|
508
|
+
* price.format('currency') // "15 000 FCFA"
|
|
509
|
+
* price.format('currency', { currency: 'EUR' }) // "15 000,00 €"
|
|
510
|
+
* price.format('currency', { notation: 'compact' }) // "15 K FCFA"
|
|
511
|
+
*
|
|
512
|
+
* // Number
|
|
513
|
+
* count.format('number') // "15 000"
|
|
514
|
+
*
|
|
515
|
+
* // Percent
|
|
516
|
+
* rate.format('percent') // "15,0 %"
|
|
517
|
+
* rate.format('percent', { decimals: 2 }) // "15,00 %"
|
|
518
|
+
*
|
|
519
|
+
* // Date
|
|
520
|
+
* date.format('date') // "3 mars 2026"
|
|
521
|
+
* date.format('date', { dateStyle: 'full' }) // "mardi 3 mars 2026"
|
|
522
|
+
* date.format('date', { format: 'DD/MM/YYYY' }) // "03/03/2026"
|
|
523
|
+
* date.format('date', { format: 'DD MMM YYYY' }) // "03 mar 2026"
|
|
524
|
+
* date.format('date', { format: 'DD MMMM YYYY' }) // "03 mars 2026"
|
|
525
|
+
*
|
|
526
|
+
* // Time
|
|
527
|
+
* date.format('time') // "20:30"
|
|
528
|
+
* date.format('time', { second: '2-digit' }) // "20:30:00"
|
|
529
|
+
* date.format('time', { format: 'HH:mm:ss' }) // "20:30:00"
|
|
530
|
+
*
|
|
531
|
+
* // Datetime
|
|
532
|
+
* date.format('datetime') // "3 mars 2026, 20:30"
|
|
533
|
+
* date.format('datetime', { dateStyle: 'full' }) // "mardi 3 mars 2026, 20:30"
|
|
534
|
+
* date.format('datetime', { format: 'DD/MM/YYYY HH:mm' }) // "03/03/2026 20:30"
|
|
535
|
+
*
|
|
536
|
+
* // Relative
|
|
537
|
+
* date.format('relative') // "dans 11 jours"
|
|
538
|
+
* date.format('relative', { unit: 'month' }) // "dans 1 mois"
|
|
539
|
+
*
|
|
540
|
+
* // Plural
|
|
541
|
+
* count.format('plural', { singular: 'billet', plural: 'billets' }) // "3 billets"
|
|
542
|
+
*
|
|
543
|
+
* // Custom formatter
|
|
544
|
+
* price.format(value => `${value.toLocaleString()} FCFA`)
|
|
545
|
+
*
|
|
546
|
+
* // Reacts to locale changes automatically
|
|
547
|
+
* Store.setLocale('en-US');
|
|
548
|
+
*/
|
|
549
|
+
ObservableItem.prototype.format = function(type, options = {}) {
|
|
550
|
+
const self = this;
|
|
551
|
+
|
|
552
|
+
if (typeof type === 'function') {
|
|
553
|
+
return new ObservableChecker(self, type);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (process.env.NODE_ENV === 'development') {
|
|
557
|
+
if (!Formatters[type]) {
|
|
558
|
+
throw new NativeDocumentError(
|
|
559
|
+
`Observable.format : unknown type '${type}'. Available : ${Object.keys(Formatters).join(', ')}.`
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
const formatter = Formatters[type];
|
|
565
|
+
const localeObservable = Store.follow('locale');
|
|
566
|
+
|
|
567
|
+
return Observable.computed(() => formatter(self.val(), localeObservable.val(), options),
|
|
568
|
+
[self, localeObservable]
|
|
569
|
+
);
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
ObservableItem.prototype.persist = function(key, options = {}) {
|
|
573
|
+
let value = $getFromStorage(key, this.$currentValue);
|
|
574
|
+
if(options.get) {
|
|
575
|
+
value = options.get(value);
|
|
576
|
+
}
|
|
577
|
+
this.set(value);
|
|
578
|
+
const saver = $saveToStorage(this.$currentValue);
|
|
579
|
+
this.subscribe((newValue) => {
|
|
580
|
+
saver(key, options.set ? options.set(newValue) : newValue);
|
|
581
|
+
});
|
|
582
|
+
return this;
|
|
486
583
|
};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import ObservableItem from "./ObservableItem";
|
|
2
|
+
import Validator from "../utils/validator";
|
|
3
|
+
import {nextTick} from "../utils/helpers";
|
|
4
|
+
import {Observable} from "./Observable";
|
|
5
|
+
|
|
6
|
+
export const ObservableObject = function(target, configs) {
|
|
7
|
+
ObservableItem.call(this, target);
|
|
8
|
+
this.$observables = {};
|
|
9
|
+
this.configs = configs;
|
|
10
|
+
|
|
11
|
+
this.$load(target);
|
|
12
|
+
|
|
13
|
+
for(const name in target) {
|
|
14
|
+
if(!Object.hasOwn(this, name)) {
|
|
15
|
+
Object.defineProperty(this, name, {
|
|
16
|
+
get: () => this.$observables[name],
|
|
17
|
+
set: (value) => this.$observables[name].set(value)
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
ObservableObject.prototype = Object.create(ObservableItem.prototype);
|
|
25
|
+
|
|
26
|
+
Object.defineProperty(ObservableObject, '$value', {
|
|
27
|
+
get() {
|
|
28
|
+
return this.val();
|
|
29
|
+
},
|
|
30
|
+
set(value) {
|
|
31
|
+
this.set(value);
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
ObservableObject.prototype.__$isObservableObject = true;
|
|
36
|
+
ObservableObject.prototype.__isProxy__ = true;
|
|
37
|
+
|
|
38
|
+
ObservableObject.prototype.$load = function(initialValue) {
|
|
39
|
+
const configs = this.configs;
|
|
40
|
+
for(const key in initialValue) {
|
|
41
|
+
const itemValue = initialValue[key];
|
|
42
|
+
if(Array.isArray(itemValue)) {
|
|
43
|
+
if(configs?.deep !== false) {
|
|
44
|
+
const mappedItemValue = itemValue.map(item => {
|
|
45
|
+
if(Validator.isJson(item)) {
|
|
46
|
+
return Observable.json(item, configs);
|
|
47
|
+
}
|
|
48
|
+
if(Validator.isArray(item)) {
|
|
49
|
+
return Observable.array(item, configs);
|
|
50
|
+
}
|
|
51
|
+
return Observable(item, configs);
|
|
52
|
+
});
|
|
53
|
+
this.$observables[key] = Observable.array(mappedItemValue, configs);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
this.$observables[key] = Observable.array(itemValue, configs);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if(Validator.isObservable(itemValue) || Validator.isProxy(itemValue)) {
|
|
60
|
+
this.$observables[key] = itemValue;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
this.$observables[key] = Observable(itemValue, configs);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
ObservableObject.prototype.val = function() {
|
|
68
|
+
const result = {};
|
|
69
|
+
for(const key in this.$observables) {
|
|
70
|
+
const dataItem = this.$observables[key];
|
|
71
|
+
if(Validator.isObservable(dataItem)) {
|
|
72
|
+
let value = dataItem.val();
|
|
73
|
+
if(Array.isArray(value)) {
|
|
74
|
+
value = value.map(item => {
|
|
75
|
+
if(Validator.isObservable(item)) {
|
|
76
|
+
return item.val();
|
|
77
|
+
}
|
|
78
|
+
if(Validator.isProxy(item)) {
|
|
79
|
+
return item.$value;
|
|
80
|
+
}
|
|
81
|
+
return item;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
result[key] = value;
|
|
85
|
+
} else if(Validator.isProxy(dataItem)) {
|
|
86
|
+
result[key] = dataItem.$value;
|
|
87
|
+
} else {
|
|
88
|
+
result[key] = dataItem;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
};
|
|
93
|
+
ObservableObject.prototype.$val = ObservableObject.prototype.val;
|
|
94
|
+
|
|
95
|
+
ObservableObject.prototype.get = function(property) {
|
|
96
|
+
const item = this.$observables[property];
|
|
97
|
+
if(Validator.isObservable(item)) {
|
|
98
|
+
return item.val();
|
|
99
|
+
}
|
|
100
|
+
if(Validator.isProxy(item)) {
|
|
101
|
+
return item.$value;
|
|
102
|
+
}
|
|
103
|
+
return item;
|
|
104
|
+
};
|
|
105
|
+
ObservableObject.prototype.$get = ObservableObject.prototype.get;
|
|
106
|
+
|
|
107
|
+
ObservableObject.prototype.set = function(newData) {
|
|
108
|
+
const data = Validator.isProxy(newData) ? newData.$value : newData;
|
|
109
|
+
const configs = this.configs;
|
|
110
|
+
|
|
111
|
+
for(const key in data) {
|
|
112
|
+
const targetItem = this.$observables[key];
|
|
113
|
+
const newValueOrigin = newData[key];
|
|
114
|
+
const newValue = data[key];
|
|
115
|
+
|
|
116
|
+
if(Validator.isObservable(targetItem)) {
|
|
117
|
+
if(!Validator.isArray(newValue)) {
|
|
118
|
+
targetItem.set(newValue);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const firstElementFromOriginalValue = newValueOrigin.at(0);
|
|
122
|
+
if(Validator.isObservable(firstElementFromOriginalValue) || Validator.isProxy(firstElementFromOriginalValue)) {
|
|
123
|
+
const newValues = newValue.map(item => {
|
|
124
|
+
if(Validator.isProxy(firstElementFromOriginalValue)) {
|
|
125
|
+
return Observable.init(item, configs);
|
|
126
|
+
}
|
|
127
|
+
return Observable(item, configs);
|
|
128
|
+
});
|
|
129
|
+
targetItem.set(newValues);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
targetItem.set([...newValue]);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if(Validator.isProxy(targetItem)) {
|
|
136
|
+
targetItem.update(newValue);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
this[key] = newValue;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
ObservableObject.prototype.$set = ObservableObject.prototype.set;
|
|
143
|
+
ObservableObject.prototype.$updateWith = ObservableObject.prototype.set;
|
|
144
|
+
|
|
145
|
+
ObservableObject.prototype.observables = function() {
|
|
146
|
+
return Object.values(this.$observables);
|
|
147
|
+
};
|
|
148
|
+
ObservableObject.prototype.$observables = ObservableObject.prototype.observables;
|
|
149
|
+
|
|
150
|
+
ObservableObject.prototype.keys = function() {
|
|
151
|
+
return Object.keys(this.$observables);
|
|
152
|
+
};
|
|
153
|
+
ObservableObject.prototype.$keys = ObservableObject.prototype.keys;
|
|
154
|
+
ObservableObject.prototype.clone = function() {
|
|
155
|
+
return Observable.init(this.val(), this.configs);
|
|
156
|
+
};
|
|
157
|
+
ObservableObject.prototype.$clone = ObservableObject.prototype.clone;
|
|
158
|
+
ObservableObject.prototype.reset = function() {
|
|
159
|
+
for(const key in this.$observables) {
|
|
160
|
+
this.$observables[key].reset();
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
ObservableObject.prototype.originalSubscribe = ObservableObject.prototype.subscribe;
|
|
164
|
+
ObservableObject.prototype.subscribe = function(callback) {
|
|
165
|
+
const observables = this.observables();
|
|
166
|
+
const updatedValue = nextTick(() => {
|
|
167
|
+
this.$currentValue = this.val();
|
|
168
|
+
this.trigger()
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
this.originalSubscribe(callback);
|
|
172
|
+
|
|
173
|
+
for(let i = 0, length = observables.length; i < length; i++) {
|
|
174
|
+
const observable = observables[i];
|
|
175
|
+
observable.subscribe(updatedValue);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
ObservableObject.prototype.configs = function() {
|
|
179
|
+
return this.configs;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
ObservableObject.prototype.update = ObservableObject.prototype.set;
|