native-document 1.0.47 → 1.0.48

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 (110) hide show
  1. package/dist/native-document.dev.js +270 -116
  2. package/dist/native-document.dev.js.map +1 -1
  3. package/dist/native-document.devtools.min.js +1 -1
  4. package/dist/native-document.min.js +1 -1
  5. package/docs/anchor.md +0 -0
  6. package/docs/conditional-rendering.md +0 -0
  7. package/docs/contributing.md +0 -0
  8. package/docs/core-concepts.md +0 -0
  9. package/docs/elements.md +0 -0
  10. package/docs/extending-native-document-element.md +0 -0
  11. package/docs/getting-started.md +0 -0
  12. package/docs/lifecycle-events.md +0 -0
  13. package/docs/list-rendering.md +0 -0
  14. package/docs/memory-management.md +0 -0
  15. package/docs/native-document-element.md +0 -0
  16. package/docs/observables.md +0 -0
  17. package/docs/routing.md +0 -0
  18. package/docs/state-management.md +0 -0
  19. package/docs/validation.md +0 -0
  20. package/elements.d.ts +0 -0
  21. package/elements.js +0 -0
  22. package/eslint.config.js +0 -0
  23. package/index.d.ts +1 -0
  24. package/index.js +2 -0
  25. package/package.json +3 -2
  26. package/readme.md +0 -0
  27. package/rollup.config.js +0 -0
  28. package/router.js +0 -0
  29. package/src/data/MemoryManager.js +0 -0
  30. package/src/data/Observable.js +17 -0
  31. package/src/data/ObservableArray.js +113 -0
  32. package/src/data/ObservableChecker.js +0 -0
  33. package/src/data/ObservableItem.js +3 -1
  34. package/src/data/ObservableWhen.js +23 -0
  35. package/src/data/Store.js +0 -0
  36. package/src/data/observable-helpers/array.js +4 -100
  37. package/src/data/observable-helpers/batch.js +0 -0
  38. package/src/data/observable-helpers/computed.js +0 -0
  39. package/src/data/observable-helpers/object.js +5 -4
  40. package/src/devtools/app/App.js +0 -0
  41. package/src/devtools/app/app.css +0 -0
  42. package/src/devtools/index.js +0 -0
  43. package/src/devtools/plugin.js +0 -0
  44. package/src/devtools/widget/DevToolsWidget.js +0 -0
  45. package/src/elements/anchor.js +0 -0
  46. package/src/elements/content-formatter.js +0 -0
  47. package/src/elements/control/for-each-array.js +0 -0
  48. package/src/elements/control/for-each.js +0 -0
  49. package/src/elements/control/show-if.js +1 -1
  50. package/src/elements/control/show-when.js +31 -0
  51. package/src/elements/control/switch.js +0 -0
  52. package/src/elements/description-list.js +0 -0
  53. package/src/elements/form.js +0 -0
  54. package/src/elements/html5-semantics.js +0 -0
  55. package/src/elements/img.js +0 -0
  56. package/src/elements/index.js +1 -0
  57. package/src/elements/interactive.js +0 -0
  58. package/src/elements/list.js +0 -0
  59. package/src/elements/medias.js +0 -0
  60. package/src/elements/meta-data.js +0 -0
  61. package/src/elements/table.js +0 -0
  62. package/src/errors/ArgTypesError.js +0 -0
  63. package/src/errors/NativeDocumentError.js +0 -0
  64. package/src/errors/RouterError.js +0 -0
  65. package/src/router/Route.js +0 -0
  66. package/src/router/RouteGroupHelper.js +0 -0
  67. package/src/router/Router.js +0 -0
  68. package/src/router/RouterComponent.js +0 -0
  69. package/src/router/link.js +0 -0
  70. package/src/router/modes/HashRouter.js +0 -0
  71. package/src/router/modes/HistoryRouter.js +0 -0
  72. package/src/router/modes/MemoryRouter.js +0 -0
  73. package/src/utils/args-types.js +0 -0
  74. package/src/utils/debug-manager.js +0 -0
  75. package/src/utils/events.js +0 -0
  76. package/src/utils/fetch/NativeFetch.js +0 -0
  77. package/src/utils/helpers.js +0 -0
  78. package/src/utils/memoize.js +53 -0
  79. package/src/utils/plugins-manager.js +0 -0
  80. package/src/utils/property-accumulator.js +0 -0
  81. package/src/utils/prototypes.js +4 -4
  82. package/src/utils/service.js +6 -0
  83. package/src/utils/validator.js +6 -0
  84. package/src/wrappers/AttributesWrapper.js +3 -3
  85. package/src/wrappers/DocumentObserver.js +0 -0
  86. package/src/wrappers/ElementCreator.js +0 -0
  87. package/src/wrappers/HtmlElementWrapper.js +0 -0
  88. package/src/wrappers/NDElement.js +0 -0
  89. package/src/wrappers/NdPrototype.js +0 -0
  90. package/src/wrappers/SingletonView.js +0 -0
  91. package/src/wrappers/TemplateCloner.js +0 -0
  92. package/src/wrappers/constants.js +0 -0
  93. package/types/args-types.d.ts +0 -0
  94. package/types/control-flow.d.ts +7 -3
  95. package/types/elements.d.ts +0 -0
  96. package/types/forms.d.ts +0 -0
  97. package/types/images.d.ts +0 -0
  98. package/types/memoize.d.ts +16 -0
  99. package/types/nd-element.d.ts +0 -0
  100. package/types/observable.d.ts +19 -3
  101. package/types/plugins-manager.d.ts +0 -0
  102. package/types/polyfill.d.ts +0 -0
  103. package/types/property-accumulator.d.ts +0 -0
  104. package/types/router.d.ts +0 -0
  105. package/types/singleton.d.ts +0 -0
  106. package/types/store.d.ts +0 -0
  107. package/types/template-cloner.ts +0 -0
  108. package/types/validator.ts +0 -0
  109. package/utils.d.ts +0 -0
  110. package/utils.js +0 -0
@@ -4,6 +4,7 @@ import NativeDocumentError from "../errors/NativeDocumentError";
4
4
  import ObservableChecker from "./ObservableChecker";
5
5
  import PluginsManager from "../utils/plugins-manager";
6
6
  import Validator from "../utils/validator";
7
+ import {ObservableWhen} from "./ObservableWhen";
7
8
 
8
9
  /**
9
10
  *
@@ -35,6 +36,7 @@ Object.defineProperty(ObservableItem.prototype, '$value', {
35
36
  ObservableItem.prototype.__$isObservable = true;
36
37
  const DEFAULT_OPERATIONS = {};
37
38
  const noneTrigger = function() {};
39
+
38
40
  ObservableItem.prototype.triggerFirstListener = function(operations) {
39
41
  this.$listeners[0](this.$currentValue, this.$previousValue, operations || {});
40
42
  }
@@ -235,7 +237,7 @@ ObservableItem.prototype.get = function(key) {
235
237
  };
236
238
 
237
239
  ObservableItem.prototype.when = function(value) {
238
- return {$target: value, $observer: this};
240
+ return new ObservableWhen(this, value);
239
241
  };
240
242
 
241
243
  ObservableItem.prototype.toString = function() {
@@ -0,0 +1,23 @@
1
+
2
+ export const ObservableWhen = function(observer, value) {
3
+ this.$target = value;
4
+ this.$observer = observer;
5
+ };
6
+
7
+ ObservableWhen.prototype.__$isObservableWhen = true;
8
+
9
+ ObservableWhen.prototype.subscribe = function(callback) {
10
+ return this.$observer.on(this.$target, callback);
11
+ };
12
+
13
+ ObservableWhen.prototype.val = function() {
14
+ return this.$observer.$currentValue === this.$target;
15
+ };
16
+
17
+ ObservableWhen.prototype.isMath = function() {
18
+ return this.$observer.$currentValue === this.$target;
19
+ };
20
+
21
+ ObservableWhen.prototype.isActive = function() {
22
+ return this.$observer.$currentValue === this.$target;
23
+ };
package/src/data/Store.js CHANGED
File without changes
@@ -1,108 +1,12 @@
1
- import NativeDocumentError from "../../errors/NativeDocumentError";
2
1
  import {Observable} from "../Observable";
3
- import PluginsManager from "../../utils/plugins-manager";
2
+ import ObservableArray from "../ObservableArray.js";
4
3
 
5
4
 
6
- const methods = ['push', 'pop', 'shift', 'unshift', 'reverse', 'sort', 'splice'];
7
-
8
5
  /**
9
6
  *
10
7
  * @param {Array} target
11
- * @returns {ObservableItem}
8
+ * @returns {ObservableArray}
12
9
  */
13
- Observable.array = function(target, { propagation = false, deep = false } = {}) {
14
- if(!Array.isArray(target)) {
15
- throw new NativeDocumentError('Observable.array : target must be an array');
16
- }
17
- const observer = Observable(target);
18
-
19
- PluginsManager.emit('CreateObservableArray', observer);
20
-
21
- methods.forEach((method) => {
22
- observer[method] = function(...values) {
23
- const result = observer.val()[method](...values);
24
- observer.trigger({ action: method, args: values, result });
25
- return result;
26
- };
27
- });
28
-
29
- observer.clear = function() {
30
- observer.val().length = 0;
31
- observer.trigger({ action: 'clear' });
32
- return true;
33
- };
34
-
35
- observer.merge = function(values) {
36
- observer.$value.push(...values);
37
- observer.trigger({ action: 'merge', args: values });
38
- };
39
-
40
- observer.populateAndRender = function(iteration, callback) {
41
- observer.trigger({ action: 'populate', args: [observer.val(), iteration, callback] });
42
- };
43
-
44
- observer.removeItem = function(item) {
45
- const indexOfItem = observer.val().indexOf(item);
46
- return observer.remove(indexOfItem);
47
- };
48
-
49
- observer.remove = function(index) {
50
- const deleted = observer.val().splice(index, 1);
51
- if(deleted.length === 0) {
52
- return [];
53
- }
54
- observer.trigger({ action: 'remove', args: [index], result: deleted[0] });
55
- return deleted;
56
- };
57
-
58
- observer.swap = function(indexA, indexB) {
59
- const value = observer.val();
60
- const length = value.length;
61
- if(length < indexA || length < indexB) {
62
- return false;
63
- }
64
- if(indexB < indexA) {
65
- const temp = indexA;
66
- indexA = indexB;
67
- indexB = temp;
68
- }
69
- const elementA = value[indexA];
70
- const elementB = value[indexB]
71
-
72
- value[indexA] = elementB;
73
- value[indexB] = elementA;
74
- observer.trigger({ action: 'swap', args: [indexA, indexB], result: [elementA, elementB] });
75
- return true;
76
- };
77
-
78
- observer.length = function() {
79
- return observer.val().length;
80
- };
81
-
82
- /**
83
- *
84
- * @param {Function} condition
85
- * @returns {number}
86
- */
87
- observer.count = (condition) => {
88
- let count = 0;
89
- observer.val().forEach((item, index) => {
90
- if(condition(item, index)) {
91
- count++;
92
- }
93
- });
94
- return count;
95
- };
96
- observer.isEmpty = function() {
97
- return observer.val().length === 0;
98
- };
99
-
100
- const overrideMethods = ['map', 'filter', 'reduce', 'some', 'every', 'find', 'findIndex', 'concat', 'includes', 'indexOf'];
101
- overrideMethods.forEach((method) => {
102
- observer[method] = (...args) => {
103
- return observer.val()[method](...args);
104
- };
105
- });
106
-
107
- return observer;
10
+ Observable.array = function(target) {
11
+ return new ObservableArray(target);
108
12
  };
File without changes
File without changes
@@ -174,12 +174,13 @@ Observable.update = function($target, newData) {
174
174
 
175
175
  if(Validator.isObservable(targetItem)) {
176
176
  if(Validator.isArray(newValue)) {
177
- if(Validator.isObservable(newValueOrigin[0]) || Validator.isProxy(newValueOrigin[0])) {
177
+ const firstElementFromOriginalValue = newValueOrigin.at(0);
178
+ if(Validator.isObservable(firstElementFromOriginalValue) || Validator.isProxy(firstElementFromOriginalValue)) {
178
179
  const newValues = newValue.map(item => {
179
- if(Validator.isObservable(newValueOrigin[0])) {
180
- return Observable(item);
180
+ if(Validator.isProxy(firstElementFromOriginalValue)) {
181
+ return Observable.init(item);
181
182
  }
182
- return Observable.init(newValueOrigin[0]);
183
+ return Observable(item);
183
184
  });
184
185
  targetItem.set(newValues);
185
186
  continue;
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -13,7 +13,7 @@ import {ElementCreator} from "../../wrappers/ElementCreator";
13
13
  * @returns {DocumentFragment}
14
14
  */
15
15
  export const ShowIf = function(condition, child, { comment = null, shouldKeepInCache = true} = {}) {
16
- if(!(Validator.isObservable(condition))) {
16
+ if(!(Validator.isObservable(condition)) && !Validator.isObservableWhenResult(condition)) {
17
17
  return DebugManager.warn('ShowIf', "ShowIf : condition must be an Observable / "+comment, condition);
18
18
  }
19
19
  const element = new Anchor('Show if : '+(comment || ''));
@@ -0,0 +1,31 @@
1
+ import Validator from "../../utils/validator.js";
2
+ import NativeDocumentError from "../../errors/NativeDocumentError.js";
3
+ import {ShowIf} from "./show-if.js";
4
+
5
+ export const ShowWhen = function() {
6
+ if(arguments.length === 2) {
7
+ const [observer, target] = arguments;
8
+ if(!Validator.isObservableWhenResult(observer)) {
9
+ throw new NativeDocumentError('showWhen observer must be an ObservableWhenResult', {
10
+ data: observer,
11
+ 'help': 'Use observer.when(target) to create an ObservableWhenResult'
12
+ });
13
+ }
14
+ return ShowIf(observer, target);
15
+ }
16
+ if(arguments.length === 3) {
17
+ const [observer, target, view] = arguments;
18
+ if(!Validator.isObservable(observer)) {
19
+ throw new NativeDocumentError('showWhen observer must be an Observable', {
20
+ data: observer,
21
+ });
22
+ }
23
+ return ShowIf(observer.when(target), view);
24
+ }
25
+ throw new NativeDocumentError('showWhen must have 2 or 3 arguments', {
26
+ data: [
27
+ 'showWhen(observer, target, view)',
28
+ 'showWhen(observerWhenResult, view)',
29
+ ]
30
+ });
31
+ };
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -3,6 +3,7 @@ import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
3
3
  export * from './control/for-each';
4
4
  export * from './control/for-each-array';
5
5
  export * from './control/show-if';
6
+ export * from './control/show-when';
6
7
  export * from './control/switch';
7
8
  export * from './content-formatter';
8
9
  export * from './description-list';
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,53 @@
1
+
2
+
3
+ export const once = (fn) => {
4
+ let result = null;
5
+ return (...args) => {
6
+ if(result === null) {
7
+ result = fn(...args);
8
+ }
9
+ return result;
10
+ };
11
+ };
12
+
13
+ export const autoOnce = (fn) => {
14
+ let target = null;
15
+ return new Proxy({}, {
16
+ get: (_, key) => {
17
+ if(target === null) {
18
+ target = fn();
19
+ }
20
+ return target[key];
21
+ }
22
+ });
23
+ };
24
+
25
+ export const memoize = (fn) => {
26
+ const cache = new Map();
27
+ return (...args) => {
28
+ const [key, ...rest] = args;
29
+ if(!cache.has(key)) {
30
+ cache.set(key, fn(...rest));
31
+ }
32
+ return cache.get(key);
33
+ };
34
+ };
35
+
36
+ export const autoMemoize = (fn) => {
37
+ const cache = new Map();
38
+ return new Proxy({}, {
39
+ get: (_, key) => {
40
+ if(!cache.has(key)) {
41
+ if(fn.length > 0) {
42
+ return (...args) => {
43
+ const result = fn(...args);
44
+ cache.set(key, result);
45
+ return result;
46
+ }
47
+ }
48
+ cache.set(key, fn());
49
+ }
50
+ return cache.get(key);
51
+ }
52
+ });
53
+ };
File without changes
File without changes
@@ -9,15 +9,15 @@ Function.prototype.args = function(...args) {
9
9
  };
10
10
 
11
11
  Function.prototype.cached = function(...args) {
12
- let $cache = null;
13
- let getCache = function(){ return $cache; };
12
+ let $cache;
13
+ let getCache = () => $cache;
14
14
  return () => {
15
15
  if(!$cache) {
16
16
  $cache = this.apply(this, args);
17
17
  if($cache.cloneNode) {
18
- getCache = function() { return $cache.cloneNode(true); };
18
+ getCache = () => $cache.cloneNode(true);
19
19
  } else if($cache.$element) {
20
- getCache = function() { return new NDElement($cache.$element.cloneNode(true)); };
20
+ getCache = () => new NDElement($cache.$element.cloneNode(true));
21
21
  }
22
22
  }
23
23
  return getCache();
@@ -0,0 +1,6 @@
1
+ import { autoMemoize, autoOnce } from "./memoize.js";
2
+
3
+ export const Service = {
4
+ once: fn => autoOnce(fn),
5
+ memoize: fn => autoMemoize(fn)
6
+ };
@@ -16,6 +16,12 @@ const Validator = {
16
16
  isObservable(value) {
17
17
  return value?.__$isObservable || value instanceof ObservableItem || value instanceof ObservableChecker;
18
18
  },
19
+ isObservableWhenResult(value) {
20
+ return value && (value.__$isObservableWhen || (typeof value === 'object' && '$target' in value && '$observer' in value));
21
+ },
22
+ isArrayObservable(value) {
23
+ return value?.__$isObservableArray;
24
+ },
19
25
  isProxy(value) {
20
26
  return value?.__isProxy__
21
27
  },
@@ -37,9 +37,9 @@ function bindClassAttribute(element, data) {
37
37
  value.subscribe(toggleElementClass.bind(null, element, className));
38
38
  continue;
39
39
  }
40
- if(value.$observer) {
41
- element.classes.toggle(className, value.$observer.val() === value.$target);
42
- value.$observer.on(value.$target, toggleElementClass.bind(null, element, className));
40
+ if(Validator.isObservableWhenResult(value)) {
41
+ element.classes.toggle(className, value.isMath());
42
+ value.subscribe(toggleElementClass.bind(null, element, className));
43
43
  continue;
44
44
  }
45
45
  if(value.$hydrate) {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,10 +1,10 @@
1
1
  // Control flow components type definitions
2
- import { ObservableItem, ObservableChecker, ObservableArray } from './observable';
2
+ import {ObservableItem, ObservableChecker, ObservableArray, ObservableWhen} from './observable';
3
3
  import { ValidChild } from './elements';
4
4
 
5
5
  // Control Flow Functions
6
6
  export interface ShowIfFunction {
7
- (condition: ObservableItem<boolean> | ObservableChecker<boolean>, child: ValidChild, options?: { comment?: string | null; shouldKeepInCache?: boolean }): DocumentFragment;
7
+ (condition: ObservableItem<boolean> | ObservableChecker<boolean> | ObservableWhen, child: ValidChild, options?: { comment?: string | null; shouldKeepInCache?: boolean }): DocumentFragment;
8
8
  }
9
9
 
10
10
  export interface HideIfFunction {
@@ -42,9 +42,13 @@ export interface ForEachArrayFunction {
42
42
  }
43
43
 
44
44
  export interface HideIfNotFunction {
45
- (condition: ObservableItem<boolean> | ObservableChecker<boolean>, child: ValidChild, options?: { comment?: string | null; shouldKeepInCache?: boolean }): DocumentFragment;
45
+ (condition: ObservableItem<boolean> | ObservableChecker<boolean> | ObservableWhen, child: ValidChild, options?: { comment?: string | null; shouldKeepInCache?: boolean }): DocumentFragment;
46
46
  }
47
47
 
48
+
49
+ export function ShowWhen(observer: ObservableWhen, target: any): ReturnType<typeof ShowIf>;
50
+ export function ShowWhen(observer: ObservableWhen, target: any, view: any): ReturnType<typeof ShowIf>;
51
+
48
52
  // Control Flow Components
49
53
  export declare const ShowIf: ShowIfFunction;
50
54
  export declare const HideIf: HideIfFunction;
File without changes
package/types/forms.d.ts CHANGED
File without changes
package/types/images.d.ts CHANGED
File without changes
@@ -0,0 +1,16 @@
1
+
2
+ export function once<T extends (...args: any[]) => any>(
3
+ fn: T
4
+ ): (...args: Parameters<T>) => ReturnType<T>;
5
+
6
+ export function autoOnce<T extends object>(
7
+ fn: () => T
8
+ ): T;
9
+
10
+ export function memoize<T extends (...args: any[]) => any>(
11
+ fn: T
12
+ ): (key: any, ...args: Parameters<T>) => ReturnType<T>;
13
+
14
+ export function autoMemoize<T extends (...args: any[]) => any>(
15
+ fn: T
16
+ ): Record<PropertyKey, Parameters<T>['length'] extends 0 ? ReturnType<T> : T>;
File without changes
@@ -1,3 +1,5 @@
1
+ export type Unsubscribe = () => void;
2
+
1
3
  // Observable system type definitions
2
4
  export interface ObservableItem<T = any> {
3
5
  readonly $currentValue: T;
@@ -12,7 +14,7 @@ export interface ObservableItem<T = any> {
12
14
  trigger(operations?: ObservableOperation): void;
13
15
  cleanup(): void;
14
16
 
15
- subscribe(callback: (current: T, previous: T, operations?: ObservableOperation) => void): () => void;
17
+ subscribe(callback: (current: T, previous: T, operations?: ObservableOperation) => void): Unsubscribe;
16
18
  unsubscribe(callback: Function): void;
17
19
  on(value: T, callback: ObservableItem<boolean> | ((isActive: boolean) => void)): () => void;
18
20
 
@@ -23,6 +25,19 @@ export interface ObservableItem<T = any> {
23
25
  toString(): string;
24
26
  }
25
27
 
28
+ export class ObservableWhen<T = any> {
29
+ readonly __$isObservableWhen: true;
30
+ private $target: T;
31
+ private $observer: ObservableItem<T>;
32
+
33
+ constructor(observer: ObservableItem<T>, value: T);
34
+
35
+ subscribe(callback: (value: boolean) => void): Unsubscribe;
36
+ val(): boolean;
37
+ isMath(): boolean;
38
+ isActive(): boolean;
39
+ }
40
+
26
41
  export interface ObservableOperation {
27
42
  action?: string;
28
43
  args?: any[];
@@ -32,7 +47,7 @@ export interface ObservableOperation {
32
47
  export interface ObservableChecker<T = any> {
33
48
  readonly __$isObservableChecker: true;
34
49
 
35
- subscribe(callback: (value: T) => void): () => void;
50
+ subscribe(callback: (value: T) => void): Unsubscribe;
36
51
  check<U>(callback: (value: T) => U): ObservableChecker<U>;
37
52
  val(): T;
38
53
 
@@ -74,6 +89,7 @@ export type ObservableProxy<T extends Record<string, any>> = {
74
89
  readonly __isProxy__: true;
75
90
  readonly $value: T;
76
91
  $val(): T;
92
+ $get(key: string): any;
77
93
  $clone(): ObservableProxy<T>;
78
94
  $updateWith(values: Partial<T>): void;
79
95
  $set(values: Partial<T>): void;
@@ -119,4 +135,4 @@ export interface ObservableStatic {
119
135
  cleanup(observable: ObservableItem): void;
120
136
  autoCleanup(enable?: boolean, options?: AutoCleanupOptions): void;
121
137
  arrayOfObject<T extends Record<string, any>>(data: T[]): ObservableProxy<T>[];
122
- }
138
+ }
File without changes
File without changes
File without changes
package/types/router.d.ts CHANGED
File without changes
File without changes
package/types/store.d.ts CHANGED
File without changes
File without changes
File without changes
package/utils.d.ts CHANGED
File without changes
package/utils.js CHANGED
File without changes