native-document 1.0.158 → 1.0.160

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.
@@ -0,0 +1,182 @@
1
+ import ObservableItem from "./ObservableItem";
2
+ import {debounce} from "../utils/helpers";
3
+
4
+ const STATE = {
5
+ UNRESOLVED: 'unresolved',
6
+ PENDING: 'pending',
7
+ READY: 'ready',
8
+ REFRESHING: 'refreshing',
9
+ ERRORED: 'errored',
10
+ };
11
+
12
+ export default function ObservableResource(fn, deps, config) {
13
+ this.$fn = (config.debounce > 0) ? debounce(fn, config.debounce) : fn;
14
+ this.$dependencies = deps;
15
+ this.$config = config;
16
+ this.$controller = null;
17
+ this.$subscriptions = [];
18
+
19
+ this.data = config.initial ?? new ObservableItem(null);
20
+ this.error = new ObservableItem(null);
21
+ this.state = new ObservableItem(STATE.UNRESOLVED);
22
+
23
+ this.loading = ObservableItem.computed(
24
+ (state) => state === STATE.PENDING || state === STATE.REFRESHING,
25
+ [this.state]
26
+ );
27
+
28
+ if (config.auto) {
29
+ if (deps.length > 0) {
30
+ this.$watchDependencies();
31
+ return;
32
+ }
33
+ this.fetch();
34
+ }
35
+ }
36
+
37
+ ObservableResource.prototype.$abort = function() {
38
+ if (this.$controller) {
39
+ this.$controller.abort();
40
+ this.$controller = null;
41
+ }
42
+ };
43
+
44
+ ObservableResource.prototype.$runWithAbortController = function(isRefetch = false) {
45
+ this.$abort();
46
+
47
+ this.$controller = new AbortController();
48
+ const signal = this.$controller.signal;
49
+
50
+ const hasData = this.data.val() !== null;
51
+ const nextState = isRefetch && hasData ? STATE.REFRESHING : STATE.PENDING;
52
+
53
+ this.error.set(null);
54
+ this.state.set(nextState);
55
+
56
+ const depValues = this.$dependencies.map(dep => dep.val());
57
+ const args = [...depValues, signal];
58
+
59
+ Promise.resolve(this.$fn(...args))
60
+ .then(result => {
61
+ if (signal.aborted) {
62
+ return;
63
+ }
64
+ this.data.set(result);
65
+ this.error.set(null);
66
+ this.state.set(STATE.READY);
67
+ this.$controller = null;
68
+ })
69
+ .catch(err => {
70
+ if (signal.aborted) {
71
+ return;
72
+ }
73
+ this.error.set(err);
74
+ this.state.set(STATE.ERRORED);
75
+ this.$controller = null;
76
+ });
77
+ };
78
+ ObservableResource.prototype.$runWithoutAbortController = function(isRefetch = false) {
79
+ const hasData = this.data.val() !== null;
80
+ const nextState = isRefetch && hasData ? STATE.REFRESHING : STATE.PENDING;
81
+
82
+ this.error.set(null);
83
+ this.state.set(nextState);
84
+
85
+ const args = this.$dependencies.map(dep => dep.val());
86
+
87
+ Promise.resolve(this.$fn(...args))
88
+ .then(result => {
89
+ this.data.set(result);
90
+ this.error.set(null);
91
+ this.state.set(STATE.READY);
92
+ })
93
+ .catch(err => {
94
+ this.error.set(err);
95
+ this.state.set(STATE.ERRORED);
96
+ });
97
+ };
98
+
99
+ ObservableResource.prototype.$run = function(isRefetch = false) {
100
+ const needsSignal = this.$fn.length > this.$dependencies.length;
101
+ if(needsSignal) {
102
+ this.$run = this.$runWithAbortController;
103
+ return this.$runWithAbortController(isRefetch);
104
+ }
105
+ this.$run = this.$runWithoutAbortController;
106
+
107
+ return this.$run(isRefetch);
108
+ };
109
+
110
+ ObservableResource.prototype.$watchDependencies = function() {
111
+ this.$subscriptions.forEach(unsub => unsub());
112
+ this.$subscriptions = [];
113
+
114
+ this.$dependencies.forEach(dep => {
115
+ const callback = () => this.$run(true);
116
+ dep.subscribe(callback);
117
+ this.$subscriptions.push(() => dep.unsubscribe(callback));
118
+ });
119
+ if (!this.$config.lazy) {
120
+ this.$run(false);
121
+ }
122
+ };
123
+
124
+ ObservableResource.prototype.fetch = function() {
125
+ this.$run(false);
126
+ return this;
127
+ };
128
+
129
+ ObservableResource.prototype.refetch = function() {
130
+ this.$run(true);
131
+ return this;
132
+ };
133
+
134
+ ObservableResource.prototype.mutate = function(value) {
135
+ this.data.set(value);
136
+ this.state.set(STATE.READY);
137
+ return this;
138
+ };
139
+
140
+ ObservableResource.prototype.destroy = function() {
141
+ this.$abort();
142
+ this.$subscriptions.forEach(unsub => unsub());
143
+ this.$subscriptions = [];
144
+ };
145
+
146
+ ObservableResource.prototype.isReady = function() {
147
+ return this.state.isEqualTo(STATE.READY);
148
+ };
149
+
150
+ ObservableResource.prototype.isPending = function() {
151
+ return this.state.isEqualTo(STATE.PENDING);
152
+ };
153
+
154
+ ObservableResource.prototype.isRefreshing = function() {
155
+ return this.state.isEqualTo(STATE.REFRESHING);
156
+ };
157
+
158
+ ObservableResource.prototype.isErrored = function() {
159
+ return this.state.isEqualTo(STATE.ERRORED);
160
+ };
161
+
162
+ ObservableResource.prototype.isUnresolved = function() {
163
+ return this.state.isEqualTo(STATE.UNRESOLVED);
164
+ };
165
+
166
+ ObservableResource.prototype.onSuccess = function(callback) {
167
+ this.data.subscribe((value) => {
168
+ if (this.state.val() === STATE.READY) {
169
+ callback(value);
170
+ }
171
+ });
172
+ return this;
173
+ };
174
+
175
+ ObservableResource.prototype.onError = function(callback) {
176
+ this.error.subscribe((err) => {
177
+ if (err !== null) {
178
+ callback(err);
179
+ }
180
+ });
181
+ return this;
182
+ };
@@ -100,7 +100,7 @@ ObservableItem.prototype.isEmpty = function () {
100
100
  };
101
101
 
102
102
  ObservableItem.prototype.isNotEmpty = function () {
103
- return $checker(this, x => x == null || x === '' || (Array.isArray(x) && x.length !== 0));
103
+ return $checker(this, x => x != null && x !== '' && !(Array.isArray(x) && x.length === 0));
104
104
  };
105
105
 
106
106
  ObservableItem.prototype.isIncludes = function (value) {
@@ -188,7 +188,7 @@ export function ForEachArray(data, callback, configs = {}) {
188
188
  }
189
189
  }
190
190
  child = null;
191
- element.appendElementRaw(fragment);
191
+ element.appendChildRaw(fragment);
192
192
  },
193
193
  removeOne: (element, index) => {
194
194
  removeCacheItem(element, true);
@@ -11,7 +11,7 @@ import HtmlElementWrapper from "../wrappers/HtmlElementWrapper";
11
11
  * multipartFormData: () => HTMLFormElement,
12
12
  * }}
13
13
  */
14
- export const Form = HtmlElementWrapper('form', function(el) {
14
+ export const Form = HtmlElementWrapper('form', (el) => {
15
15
 
16
16
  el.submit = function(action) {
17
17
  if(typeof action === 'function') {
@@ -37,7 +37,7 @@ export const createHtmlElement = (element, _attributes, _children = null) => {
37
37
  * @param {?Function=} customWrapper
38
38
  * @returns {Function}
39
39
  */
40
- export default function HtmlElementWrapper(name, customWrapper = null) {
40
+ export default function HtmlElementWrapper(name, customWrapper = null) {
41
41
  if(name) {
42
42
  if(customWrapper) {
43
43
  let node = null;
@@ -2,6 +2,11 @@ import DocumentObserver from "./DocumentObserver";
2
2
  import PluginsManager from "../utils/plugins-manager";
3
3
  import NativeDocumentError from "../errors/NativeDocumentError.js";
4
4
  import DebugManager from "../utils/debug-manager.js";
5
+ import attributesWrapper, {
6
+ bindAttributeWithObservable,
7
+ bindClassAttribute,
8
+ bindStyleAttribute
9
+ } from "./AttributesWrapper";
5
10
 
6
11
  export function NDElement(element) {
7
12
  this.$element = element;
@@ -195,6 +200,31 @@ NDElement.prototype.with = function(methods) {
195
200
  return this;
196
201
  };
197
202
 
203
+
204
+ NDElement.prototype.attr = function(name, value) {
205
+ if(value?.__$Observable) {
206
+ bindAttributeWithObservable(this.$element, name, value);
207
+ return this;
208
+ }
209
+ this.$element.setAttribute(name, value);
210
+ };
211
+
212
+ NDElement.prototype.attrs = function(attrs) {
213
+ attributesWrapper(this.$element, attrs);
214
+ return this;
215
+ };
216
+
217
+ NDElement.prototype.class = function(classes) {
218
+ bindClassAttribute(this.$element, classes);
219
+ return this;
220
+ };
221
+
222
+ NDElement.prototype.style = function(style) {
223
+ bindStyleAttribute(this.$element, style);
224
+ return this;
225
+ };
226
+
227
+
198
228
  /**
199
229
  * Extends the NDElement prototype with new methods available to all NDElement instances.
200
230
  * Use this to add global methods to all NDElements.
@@ -32,9 +32,7 @@ export function RouterComponent(router, container) {
32
32
  };
33
33
 
34
34
  const removeLastNodeInserted = () => {
35
- if(Validator.isAnchor($lastNodeInserted)) {
36
- $lastNodeInserted.remove();
37
- }
35
+ $lastNodeInserted.remove();
38
36
  };
39
37
 
40
38
  const cleanContainer = () => {
@@ -13,6 +13,7 @@ import {
13
13
  TRow
14
14
  } from "../../../../../elements";
15
15
  import { $ } from "../../../../core/data/Observable";
16
+ import {classPropertyAccumulator} from "../../../../core/utils/property-accumulator";
16
17
 
17
18
  export const buildTable = ($desc, instance, visibleColumns) => {
18
19
  const thead = $desc.noHeader ? null : buildTHead($desc, instance, visibleColumns);
@@ -297,23 +298,23 @@ export const buildRow = ($desc, instance, visibleColumns, row) => {
297
298
  ? $descCol.render(value, row)
298
299
  : value ?? '';
299
300
 
300
- const classes = {};
301
+ const classProperty = classPropertyAccumulator($descCol.props?.class || {});
301
302
  if($descCol.align) {
302
303
  if($descCol.align.__$Observable) {
303
- classes['_'] = $descCol.align.transform((v) => `is-align-${v}`);
304
+ classProperty.add($descCol.align.transform((v) => `is-align-${v}`))
304
305
  } else {
305
- classes[`is-align-${$descCol.align}`] = true;
306
+ classProperty.add(`is-align-${$descCol.align}`, true)
306
307
  }
307
308
  }
308
309
  if($descCol.pinned) {
309
310
  if($descCol.pinned.__$Observable) {
310
- classes['__'] = $descCol.pinned.transform((v) => `is-pinned-${v}`);
311
+ classProperty.add($descCol.pinned.transform((v) => `is-pinned-${v}`))
311
312
  } else {
312
- classes[`is-pinned-${$descCol.pinned}`] = true;
313
+ classProperty.add(`is-pinned-${$descCol.pinned}`, true)
313
314
  }
314
315
  }
315
316
 
316
- const cell = TBodyCell({ class: classes, }, content);
317
+ const cell = TBodyCell({ ...$descCol.props, class: classProperty.value() }, content);
317
318
  if($descCol.onClick) {
318
319
  cell.nd.onClick((event) => {$descCol.onClick(row, event);});
319
320
  }