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.
Files changed (52) hide show
  1. package/{src/devtools/hrm → devtools}/ComponentRegistry.js +2 -2
  2. package/devtools/index.js +8 -0
  3. package/{src/devtools/plugin.js → devtools/plugin/dev-tools-plugin.js} +2 -2
  4. package/{src/devtools/hrm/nd-vite-hot-reload.js → devtools/transformers/nd-vite-devtools.js} +16 -6
  5. package/devtools/transformers/src/transformComponentForHrm.js +74 -0
  6. package/devtools/transformers/src/transformJsFile.js +9 -0
  7. package/devtools/transformers/src/utils.js +79 -0
  8. package/devtools/widget/Widget.js +48 -0
  9. package/devtools/widget/widget.css +81 -0
  10. package/devtools/widget.js +23 -0
  11. package/dist/native-document.components.min.js +2441 -1191
  12. package/dist/native-document.dev.js +2710 -1359
  13. package/dist/native-document.dev.js.map +1 -1
  14. package/dist/native-document.devtools.min.js +1 -1
  15. package/dist/native-document.min.js +1 -1
  16. package/docs/cache.md +1 -1
  17. package/docs/core-concepts.md +1 -1
  18. package/docs/native-document-element.md +51 -15
  19. package/docs/observables.md +310 -306
  20. package/docs/state-management.md +198 -193
  21. package/index.def.js +762 -26
  22. package/package.json +1 -1
  23. package/readme.md +1 -1
  24. package/src/core/data/ObservableChecker.js +2 -0
  25. package/src/core/data/ObservableItem.js +97 -0
  26. package/src/core/data/ObservableObject.js +182 -0
  27. package/src/core/data/Store.js +364 -34
  28. package/src/core/data/observable-helpers/object.js +2 -166
  29. package/src/core/elements/anchor.js +28 -20
  30. package/src/core/elements/control/for-each.js +1 -1
  31. package/src/core/utils/formatters.js +91 -0
  32. package/src/core/utils/localstorage.js +57 -0
  33. package/src/core/utils/validator.js +0 -2
  34. package/src/core/wrappers/DocumentObserver.js +102 -31
  35. package/src/core/wrappers/ElementCreator.js +5 -0
  36. package/src/core/wrappers/NDElement.js +32 -1
  37. package/src/core/wrappers/prototypes/nd-element.transition.extensions.js +83 -0
  38. package/src/devtools.js +9 -0
  39. package/src/fetch/NativeFetch.js +5 -2
  40. package/types/elements.d.ts +580 -2
  41. package/types/nd-element.d.ts +6 -0
  42. package/types/observable.d.ts +71 -15
  43. package/types/plugins-manager.d.ts +1 -1
  44. package/types/store.d.ts +33 -6
  45. package/hrm.js +0 -7
  46. package/src/devtools/app/App.js +0 -66
  47. package/src/devtools/app/app.css +0 -0
  48. package/src/devtools/hrm/transformComponent.js +0 -129
  49. package/src/devtools/index.js +0 -18
  50. package/src/devtools/widget/DevToolsWidget.js +0 -26
  51. /package/{src/devtools/hrm → devtools/transformers/templates}/hrm.hook.template.js +0 -0
  52. /package/{src/devtools/hrm → devtools/transformers/templates}/hrm.orbservable.hook.template.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "native-document",
3
- "version": "1.0.94",
3
+ "version": "1.0.98",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "scripts": {
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 ](docs/getting-started.md)
320
+ **Ready to build with native simplicity?** [Get Started ->](docs/getting-started.md)
@@ -10,6 +10,8 @@ export default function ObservableChecker($observable, $checker) {
10
10
  this.unSubscriptions = [];
11
11
  }
12
12
 
13
+ export const ObservablePipe = ObservableChecker;
14
+
13
15
  ObservableChecker.prototype.__$isObservableChecker = true;
14
16
 
15
17
  /**
@@ -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;