native-document 1.0.95 → 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 +1922 -1277
- package/dist/native-document.dev.js +1985 -1401
- 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/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/utils/formatters.js +91 -0
- package/src/core/utils/localstorage.js +57 -0
- package/src/core/utils/validator.js +0 -2
- package/src/devtools.js +9 -0
- package/src/fetch/NativeFetch.js +5 -2
- 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
|
@@ -1,137 +1,10 @@
|
|
|
1
1
|
import Validator from "../../utils/validator";
|
|
2
2
|
import {Observable} from "../Observable";
|
|
3
|
+
import {ObservableObject} from "../ObservableObject";
|
|
3
4
|
|
|
4
|
-
const ObservableObjectValue = function(data) {
|
|
5
|
-
const result = {};
|
|
6
|
-
for(const key in data) {
|
|
7
|
-
const dataItem = data[key];
|
|
8
|
-
if(Validator.isObservable(dataItem)) {
|
|
9
|
-
let value = dataItem.val();
|
|
10
|
-
if(Array.isArray(value)) {
|
|
11
|
-
value = value.map(item => {
|
|
12
|
-
if(Validator.isObservable(item)) {
|
|
13
|
-
return item.val();
|
|
14
|
-
}
|
|
15
|
-
if(Validator.isProxy(item)) {
|
|
16
|
-
return item.$value;
|
|
17
|
-
}
|
|
18
|
-
return item;
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
result[key] = value;
|
|
22
|
-
} else if(Validator.isProxy(dataItem)) {
|
|
23
|
-
result[key] = dataItem.$value;
|
|
24
|
-
} else {
|
|
25
|
-
result[key] = dataItem;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return result;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const ObservableGet = function(target, property) {
|
|
32
|
-
const item = target[property];
|
|
33
|
-
if(Validator.isObservable(item)) {
|
|
34
|
-
return item.val();
|
|
35
|
-
}
|
|
36
|
-
if(Validator.isProxy(item)) {
|
|
37
|
-
return item.$value;
|
|
38
|
-
}
|
|
39
|
-
return item;
|
|
40
|
-
};
|
|
41
5
|
|
|
42
|
-
/**
|
|
43
|
-
* Creates an observable proxy for an object where each property becomes an observable.
|
|
44
|
-
* Properties can be accessed directly or via getter methods.
|
|
45
|
-
*
|
|
46
|
-
* @param {Object} initialValue - Initial object value
|
|
47
|
-
* @param {Object|null} [configs=null] - Configuration options
|
|
48
|
-
* // @param {boolean} [configs.propagation=true] - Whether changes propagate to parent
|
|
49
|
-
* @param {boolean} [configs.deep=false] - Whether to make nested objects observable
|
|
50
|
-
* @param {boolean} [configs.reset=false] - Whether to enable reset() method
|
|
51
|
-
* @returns {ObservableProxy} A proxy where each property is an observable
|
|
52
|
-
* @example
|
|
53
|
-
* const user = Observable.init({
|
|
54
|
-
* name: 'John',
|
|
55
|
-
* age: 25,
|
|
56
|
-
* address: { city: 'NYC' }
|
|
57
|
-
* }, { deep: true });
|
|
58
|
-
*
|
|
59
|
-
* user.name.val(); // 'John'
|
|
60
|
-
* user.name.set('Jane');
|
|
61
|
-
* user.name = 'Jane X'
|
|
62
|
-
* user.age.subscribe(val => console.log('Age:', val));
|
|
63
|
-
*/
|
|
64
6
|
Observable.init = function(initialValue, configs = null) {
|
|
65
|
-
|
|
66
|
-
for(const key in initialValue) {
|
|
67
|
-
const itemValue = initialValue[key];
|
|
68
|
-
if(Array.isArray(itemValue)) {
|
|
69
|
-
if(configs?.deep !== false) {
|
|
70
|
-
const mappedItemValue = itemValue.map(item => {
|
|
71
|
-
if(Validator.isJson(item)) {
|
|
72
|
-
return Observable.json(item, configs);
|
|
73
|
-
}
|
|
74
|
-
if(Validator.isArray(item)) {
|
|
75
|
-
return Observable.array(item, configs);
|
|
76
|
-
}
|
|
77
|
-
return Observable(item, configs);
|
|
78
|
-
});
|
|
79
|
-
data[key] = Observable.array(mappedItemValue, configs);
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
data[key] = Observable.array(itemValue, configs);
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if(Validator.isObservable(itemValue) || Validator.isProxy(itemValue)) {
|
|
86
|
-
data[key] = itemValue;
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
data[key] = Observable(itemValue, configs);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const $reset = () => {
|
|
93
|
-
for(const key in data) {
|
|
94
|
-
const item = data[key];
|
|
95
|
-
item.reset();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const $val = () => ObservableObjectValue(data);
|
|
100
|
-
|
|
101
|
-
const $clone = () => Observable.init($val(), configs);
|
|
102
|
-
|
|
103
|
-
const $updateWith = (values) => {
|
|
104
|
-
Observable.update(proxy, values);
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
const $get = (key) => ObservableGet(data, key);
|
|
108
|
-
|
|
109
|
-
const proxy = new Proxy(data, {
|
|
110
|
-
get(target, property) {
|
|
111
|
-
if(property === '__isProxy__') { return true; }
|
|
112
|
-
if(property === '$value') { return $val() }
|
|
113
|
-
if(property === 'get' || property === '$get') { return $get; }
|
|
114
|
-
if(property === 'val' || property === '$val') { return $val; }
|
|
115
|
-
if(property === 'set' || property === '$set' || property === '$updateWith') { return $updateWith; }
|
|
116
|
-
if(property === 'observables' || property === '$observables') { return Object.values(target); }
|
|
117
|
-
if(property === 'keys'|| property === '$keys') { return Object.keys(initialValue); }
|
|
118
|
-
if(property === 'clone' || property === '$clone') { return $clone; }
|
|
119
|
-
if(property === 'reset') { return $reset; }
|
|
120
|
-
if(property === 'configs') { return configs; }
|
|
121
|
-
return target[property];
|
|
122
|
-
},
|
|
123
|
-
set(target, prop, newValue) {
|
|
124
|
-
if(target[prop] !== undefined) {
|
|
125
|
-
Validator.isObservable(newValue)
|
|
126
|
-
? target[prop].set(newValue.val())
|
|
127
|
-
: target[prop].set(newValue);
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
return proxy;
|
|
7
|
+
return new ObservableObject(initialValue, configs)
|
|
135
8
|
};
|
|
136
9
|
|
|
137
10
|
/**
|
|
@@ -166,42 +39,5 @@ Observable.value = function(data) {
|
|
|
166
39
|
return data;
|
|
167
40
|
};
|
|
168
41
|
|
|
169
|
-
|
|
170
|
-
Observable.update = function($target, newData) {
|
|
171
|
-
const data = Validator.isProxy(newData) ? newData.$value : newData;
|
|
172
|
-
const configs = $target.configs;
|
|
173
|
-
|
|
174
|
-
for(const key in data) {
|
|
175
|
-
const targetItem = $target[key];
|
|
176
|
-
const newValueOrigin = newData[key];
|
|
177
|
-
const newValue = data[key];
|
|
178
|
-
|
|
179
|
-
if(Validator.isObservable(targetItem)) {
|
|
180
|
-
if(Validator.isArray(newValue)) {
|
|
181
|
-
const firstElementFromOriginalValue = newValueOrigin.at(0);
|
|
182
|
-
if(Validator.isObservable(firstElementFromOriginalValue) || Validator.isProxy(firstElementFromOriginalValue)) {
|
|
183
|
-
const newValues = newValue.map(item => {
|
|
184
|
-
if(Validator.isProxy(firstElementFromOriginalValue)) {
|
|
185
|
-
return Observable.init(item, configs);
|
|
186
|
-
}
|
|
187
|
-
return Observable(item, configs);
|
|
188
|
-
});
|
|
189
|
-
targetItem.set(newValues);
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
targetItem.set([...newValue]);
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
targetItem.set(newValue);
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
if(Validator.isProxy(targetItem)) {
|
|
199
|
-
Observable.update(targetItem, newValue);
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
$target[key] = newValue;
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
42
|
Observable.object = Observable.init;
|
|
207
43
|
Observable.json = Observable.init;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const $parseDateParts = (value, locale) => {
|
|
2
|
+
const d = new Date(value);
|
|
3
|
+
return {
|
|
4
|
+
d,
|
|
5
|
+
parts: new Intl.DateTimeFormat(locale, {
|
|
6
|
+
year: 'numeric',
|
|
7
|
+
month: 'long',
|
|
8
|
+
day: '2-digit',
|
|
9
|
+
hour: '2-digit',
|
|
10
|
+
minute: '2-digit',
|
|
11
|
+
second: '2-digit',
|
|
12
|
+
}).formatToParts(d).reduce((acc, { type, value }) => {
|
|
13
|
+
acc[type] = value;
|
|
14
|
+
return acc;
|
|
15
|
+
}, {})
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const $applyDatePattern = (pattern, d, parts) => {
|
|
20
|
+
const pad = n => String(n).padStart(2, '0');
|
|
21
|
+
return pattern
|
|
22
|
+
.replace('YYYY', parts.year)
|
|
23
|
+
.replace('YY', parts.year.slice(-2))
|
|
24
|
+
.replace('MMMM', parts.month)
|
|
25
|
+
.replace('MMM', parts.month.slice(0, 3))
|
|
26
|
+
.replace('MM', pad(d.getMonth() + 1))
|
|
27
|
+
.replace('DD', pad(d.getDate()))
|
|
28
|
+
.replace('D', d.getDate())
|
|
29
|
+
.replace('HH', parts.hour)
|
|
30
|
+
.replace('mm', parts.minute)
|
|
31
|
+
.replace('ss', parts.second);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const Formatters = {
|
|
35
|
+
|
|
36
|
+
currency: (value, locale, { currency = 'XOF', notation, minimumFractionDigits, maximumFractionDigits } = {}) =>
|
|
37
|
+
new Intl.NumberFormat(locale, {
|
|
38
|
+
style: 'currency',
|
|
39
|
+
currency,
|
|
40
|
+
notation,
|
|
41
|
+
minimumFractionDigits,
|
|
42
|
+
maximumFractionDigits
|
|
43
|
+
}).format(value),
|
|
44
|
+
|
|
45
|
+
number: (value, locale, { notation, minimumFractionDigits, maximumFractionDigits } = {}) =>
|
|
46
|
+
new Intl.NumberFormat(locale, {
|
|
47
|
+
notation,
|
|
48
|
+
minimumFractionDigits,
|
|
49
|
+
maximumFractionDigits
|
|
50
|
+
}).format(value),
|
|
51
|
+
|
|
52
|
+
percent: (value, locale, { decimals = 1 } = {}) =>
|
|
53
|
+
new Intl.NumberFormat(locale, {
|
|
54
|
+
style: 'percent',
|
|
55
|
+
maximumFractionDigits: decimals
|
|
56
|
+
}).format(value),
|
|
57
|
+
|
|
58
|
+
date: (value, locale, { format, dateStyle = 'long' } = {}) => {
|
|
59
|
+
if (format) {
|
|
60
|
+
const { d, parts } = $parseDateParts(value, locale);
|
|
61
|
+
return $applyDatePattern(format, d, parts);
|
|
62
|
+
}
|
|
63
|
+
return new Intl.DateTimeFormat(locale, { dateStyle }).format(new Date(value));
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
time: (value, locale, { format, hour = '2-digit', minute = '2-digit', second } = {}) => {
|
|
67
|
+
if (format) {
|
|
68
|
+
const { d, parts } = $parseDateParts(value, locale);
|
|
69
|
+
return $applyDatePattern(format, d, parts);
|
|
70
|
+
}
|
|
71
|
+
return new Intl.DateTimeFormat(locale, { hour, minute, second }).format(new Date(value));
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
datetime: (value, locale, { format, dateStyle = 'long', hour = '2-digit', minute = '2-digit', second } = {}) => {
|
|
75
|
+
if (format) {
|
|
76
|
+
const { d, parts } = $parseDateParts(value, locale);
|
|
77
|
+
return $applyDatePattern(format, d, parts);
|
|
78
|
+
}
|
|
79
|
+
return new Intl.DateTimeFormat(locale, { dateStyle, hour, minute, second }).format(new Date(value));
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
relative: (value, locale, { unit = 'day', numeric = 'auto' } = {}) => {
|
|
83
|
+
const diff = Math.round((value - Date.now()) / (1000 * 60 * 60 * 24));
|
|
84
|
+
return new Intl.RelativeTimeFormat(locale, { numeric }).format(diff, unit);
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
plural: (value, locale, { singular, plural } = {}) => {
|
|
88
|
+
const rule = new Intl.PluralRules(locale).select(value);
|
|
89
|
+
return `${value} ${rule === 'one' ? singular : plural}`;
|
|
90
|
+
},
|
|
91
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import NativeDocumentError from "../errors/NativeDocumentError";
|
|
2
|
+
|
|
3
|
+
export const LocalStorage = {
|
|
4
|
+
getJson(key) {
|
|
5
|
+
let value = localStorage.getItem(key);
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(value);
|
|
8
|
+
} catch (e) {
|
|
9
|
+
throw new NativeDocumentError('invalid_json:'+key);
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
getNumber(key) {
|
|
13
|
+
return Number(this.get(key));
|
|
14
|
+
},
|
|
15
|
+
getBool(key) {
|
|
16
|
+
const value = this.get(key);
|
|
17
|
+
return value === 'true' || value === '1';
|
|
18
|
+
},
|
|
19
|
+
setJson(key, value) {
|
|
20
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
21
|
+
},
|
|
22
|
+
setBool(key, value) {
|
|
23
|
+
localStorage.setItem(key, value ? 'true' : 'false');
|
|
24
|
+
},
|
|
25
|
+
get(key, defaultValue = null) {
|
|
26
|
+
return localStorage.getItem(key) || defaultValue;
|
|
27
|
+
},
|
|
28
|
+
set(key, value) {
|
|
29
|
+
return localStorage.setItem(key, value);
|
|
30
|
+
},
|
|
31
|
+
remove(key) {
|
|
32
|
+
localStorage.removeItem(key);
|
|
33
|
+
},
|
|
34
|
+
has(key) {
|
|
35
|
+
return localStorage.getItem(key) != null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const $getFromStorage = (key, value) => {
|
|
40
|
+
if(!LocalStorage.has(key)) {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
switch (typeof value) {
|
|
44
|
+
case 'object': return LocalStorage.getJson(key) ?? value;
|
|
45
|
+
case 'boolean': return LocalStorage.getBool(key) ?? value;
|
|
46
|
+
case 'number': return LocalStorage.getNumber(key) ?? value;
|
|
47
|
+
default: return LocalStorage.get(key, value) ?? value;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const $saveToStorage = (value) => {
|
|
52
|
+
switch (typeof value) {
|
|
53
|
+
case 'object': return LocalStorage.setJson;
|
|
54
|
+
case 'boolean': return LocalStorage.setBool;
|
|
55
|
+
default: return LocalStorage.set;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import ObservableItem from "../data/ObservableItem";
|
|
2
1
|
import DebugManager from "./debug-manager";
|
|
3
2
|
import NativeDocumentError from "../errors/NativeDocumentError";
|
|
4
3
|
import ObservableChecker from "../data/ObservableChecker";
|
|
5
4
|
import {NDElement} from "../wrappers/NDElement";
|
|
6
|
-
import TemplateBinding from "../wrappers/TemplateBinding";
|
|
7
5
|
|
|
8
6
|
const COMMON_NODE_TYPES = {
|
|
9
7
|
ELEMENT: 1,
|
package/src/devtools.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import Devtools from './devtools';
|
|
2
|
+
import NdViteDevtools from "../devtools/transformers/nd-vite-devtools.js";
|
|
3
|
+
import transformComponentForHrm from "../devtools/transformers/src/transformComponentForHrm.js";
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
transformComponentForHrm,
|
|
7
|
+
NdViteDevtools,
|
|
8
|
+
Devtools,
|
|
9
|
+
};
|
package/src/fetch/NativeFetch.js
CHANGED
|
@@ -36,11 +36,14 @@ export default function NativeFetch($baseUrl) {
|
|
|
36
36
|
configs.body = params;
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
|
-
configs.headers['Content-Type'] = 'application/json';
|
|
40
39
|
if(method !== 'GET') {
|
|
40
|
+
configs.headers['Content-Type'] = 'application/json';
|
|
41
41
|
configs.body = JSON.stringify(params);
|
|
42
42
|
} else {
|
|
43
|
-
|
|
43
|
+
const queryString = new URLSearchParams(params).toString();
|
|
44
|
+
if (queryString) {
|
|
45
|
+
endpoint = endpoint + (endpoint.includes('?') ? '&' : '?') + queryString;
|
|
46
|
+
}
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
}
|
package/types/observable.d.ts
CHANGED
|
@@ -1,7 +1,47 @@
|
|
|
1
|
-
import {FilterResult, PredicateMap} from "./filters
|
|
1
|
+
import {FilterResult, PredicateMap} from "./filters";
|
|
2
2
|
|
|
3
3
|
export type Unsubscribe = () => void;
|
|
4
4
|
|
|
5
|
+
export type FormatType = 'currency' | 'number' | 'percent' | 'date' | 'time' | 'datetime' | 'relative' | 'plural';
|
|
6
|
+
|
|
7
|
+
export interface FormatOptions {
|
|
8
|
+
// currency
|
|
9
|
+
currency?: string;
|
|
10
|
+
notation?: 'standard' | 'scientific' | 'engineering' | 'compact';
|
|
11
|
+
minimumFractionDigits?: number;
|
|
12
|
+
maximumFractionDigits?: number;
|
|
13
|
+
// percent
|
|
14
|
+
decimals?: number;
|
|
15
|
+
// date / datetime
|
|
16
|
+
dateStyle?: 'full' | 'long' | 'medium' | 'short';
|
|
17
|
+
format?: string;
|
|
18
|
+
// time / datetime
|
|
19
|
+
hour?: '2-digit' | 'numeric';
|
|
20
|
+
minute?: '2-digit' | 'numeric';
|
|
21
|
+
second?: '2-digit' | 'numeric';
|
|
22
|
+
// relative
|
|
23
|
+
unit?: 'day' | 'week' | 'month' | 'year' | 'hour' | 'minute' | 'second';
|
|
24
|
+
numeric?: 'always' | 'auto';
|
|
25
|
+
// plural
|
|
26
|
+
singular?: string;
|
|
27
|
+
plural?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface FormattersStatic {
|
|
31
|
+
currency(value: number, locale: string, options?: FormatOptions): string;
|
|
32
|
+
number(value: number, locale: string, options?: FormatOptions): string;
|
|
33
|
+
percent(value: number, locale: string, options?: FormatOptions): string;
|
|
34
|
+
date(value: Date | number, locale: string, options?: FormatOptions): string;
|
|
35
|
+
time(value: Date | number, locale: string, options?: FormatOptions): string;
|
|
36
|
+
datetime(value: Date | number, locale: string, options?: FormatOptions): string;
|
|
37
|
+
relative(value: Date | number, locale: string, options?: FormatOptions): string;
|
|
38
|
+
plural(value: number, locale: string, options?: FormatOptions): string;
|
|
39
|
+
[key: string]: (value: any, locale: string, options?: FormatOptions) => string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export declare const Formatters: FormattersStatic;
|
|
43
|
+
|
|
44
|
+
|
|
5
45
|
// Observable system type definitions
|
|
6
46
|
export interface ObservableItem<T = any> {
|
|
7
47
|
readonly $currentValue: T;
|
|
@@ -22,12 +62,21 @@ export interface ObservableItem<T = any> {
|
|
|
22
62
|
on(value: T, callback: ObservableItem<boolean> | ((isActive: boolean) => void)): () => void;
|
|
23
63
|
|
|
24
64
|
check<U>(callback: (value: T) => U): ObservableChecker<U>;
|
|
25
|
-
|
|
65
|
+
transform<U>(callback: (value: T) => U): ObservableChecker<U>;
|
|
66
|
+
is<U>(callback: (value: T) => U): ObservableChecker<U>;
|
|
67
|
+
select<U>(callback: (value: T) => U): ObservableChecker<U>;
|
|
68
|
+
pluck<U>(callback: (value: T) => U): ObservableChecker<U>;
|
|
69
|
+
format(type: FormatType | ((value: T) => string), options?: FormatOptions): ObservableItem<string>;
|
|
70
|
+
get(key: string | number): any;
|
|
26
71
|
when(value: T): ObservableWhen<T>;
|
|
27
72
|
off(value: T, callback?: Function): void;
|
|
28
73
|
once(predicate: T | ((value: T) => boolean), callback: (value: T) => void): void;
|
|
29
74
|
onCleanup(callback: () => void): void;
|
|
30
75
|
intercept(callback: (newValue: T, currentValue: T) => T | undefined): this;
|
|
76
|
+
persist(key: string, options?: {
|
|
77
|
+
get?: (value: any) => T;
|
|
78
|
+
set?: (value: T) => any;
|
|
79
|
+
}): this;
|
|
31
80
|
disconnectAll(): void;
|
|
32
81
|
|
|
33
82
|
toString(): string;
|
|
@@ -103,35 +152,42 @@ export interface ObservableArray<T> extends ObservableItem<T[]> {
|
|
|
103
152
|
whereEvery<K extends keyof T>(fields: K[], filter: FilterResult<T[K]>): ObservableArray<T>;
|
|
104
153
|
}
|
|
105
154
|
|
|
106
|
-
export type
|
|
155
|
+
export type ObservableObject<T extends Record<string, any>> = ObservableItem<T> & {
|
|
156
|
+
readonly __$isObservableObject: true;
|
|
107
157
|
readonly __isProxy__: true;
|
|
108
|
-
readonly $
|
|
158
|
+
readonly $observables: { [K in keyof T]: ObservableItem<T[K]> };
|
|
109
159
|
readonly configs: ObservableConfig | null;
|
|
160
|
+
|
|
161
|
+
$load(initialValue: Partial<T>): void;
|
|
110
162
|
$val(): T;
|
|
111
163
|
val(): T;
|
|
112
|
-
$get(key: string): any;
|
|
113
164
|
get(key: string): any;
|
|
114
|
-
$
|
|
115
|
-
clone(): ObservableProxy<T>;
|
|
116
|
-
$updateWith(values: Partial<T>): void;
|
|
117
|
-
$set(values: Partial<T>): void;
|
|
165
|
+
$get(key: string): any;
|
|
118
166
|
set(values: Partial<T>): void;
|
|
167
|
+
$set(values: Partial<T>): void;
|
|
168
|
+
$updateWith(values: Partial<T>): void;
|
|
169
|
+
update(values: Partial<T>): void;
|
|
119
170
|
reset(): void;
|
|
171
|
+
clone(): ObservableObject<T>;
|
|
172
|
+
$clone(): ObservableObject<T>;
|
|
120
173
|
keys(): string[];
|
|
174
|
+
$keys(): string[];
|
|
175
|
+
observables(): ObservableItem<any>[];
|
|
121
176
|
} & {
|
|
122
177
|
[K in keyof T]: T[K] extends (infer U)[]
|
|
123
178
|
? ObservableArray<U>
|
|
124
179
|
: T[K] extends Record<string, any>
|
|
125
|
-
?
|
|
180
|
+
? ObservableObject<T[K]>
|
|
126
181
|
: ObservableItem<T[K]>;
|
|
127
182
|
};
|
|
128
183
|
|
|
184
|
+
|
|
129
185
|
export interface BatchFunction<TArgs extends any[] = any[], TReturn = any> {
|
|
130
186
|
(...args: TArgs): TReturn;
|
|
131
187
|
readonly $observer: ObservableItem<number>;
|
|
132
188
|
}
|
|
133
189
|
|
|
134
|
-
export type ValidComputedDependencies = Array<ObservableItem | ObservableArray<any> | ObservableChecker |
|
|
190
|
+
export type ValidComputedDependencies = Array<ObservableItem | ObservableArray<any> | ObservableChecker | ObservableObject<any>>;
|
|
135
191
|
|
|
136
192
|
export interface AutoCleanupOptions {
|
|
137
193
|
interval?: number;
|
|
@@ -148,9 +204,9 @@ export interface ObservableStatic {
|
|
|
148
204
|
<T>(value: T, configs?: ObservableConfig | null): ObservableItem<T>;
|
|
149
205
|
array<T>(target: T[] | null, configs?: ObservableConfig | null): ObservableArray<T>;
|
|
150
206
|
|
|
151
|
-
init<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null):
|
|
152
|
-
object<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null):
|
|
153
|
-
json<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null):
|
|
207
|
+
init<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null): ObservableObject<T>;
|
|
208
|
+
object<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null): ObservableObject<T>;
|
|
209
|
+
json<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null): ObservableObject<T>;
|
|
154
210
|
|
|
155
211
|
computed<T>(callback: () => T, dependencies?: ValidComputedDependencies | BatchFunction): ObservableItem<T>;
|
|
156
212
|
computed<T>(callback: () => T, batchFunction?: BatchFunction): ObservableItem<T>;
|
|
@@ -165,5 +221,5 @@ export interface ObservableStatic {
|
|
|
165
221
|
getById(id: number): ObservableItem | null;
|
|
166
222
|
cleanup(observable: ObservableItem): void;
|
|
167
223
|
autoCleanup(enable?: boolean, options?: AutoCleanupOptions): void;
|
|
168
|
-
arrayOfObject<T extends Record<string, any>>(data: T[]):
|
|
224
|
+
arrayOfObject<T extends Record<string, any>>(data: T[]): ObservableObject<T>[];
|
|
169
225
|
}
|
package/types/store.d.ts
CHANGED
|
@@ -1,12 +1,39 @@
|
|
|
1
|
-
// Store system type definitions
|
|
2
1
|
import { ObservableItem } from './observable';
|
|
3
|
-
import {Set} from "./polyfill";
|
|
2
|
+
import { Set } from "./polyfill";
|
|
3
|
+
|
|
4
|
+
export type StoreGroupInstance = StoreStatic & {
|
|
5
|
+
readonly $name: string;
|
|
6
|
+
};
|
|
4
7
|
|
|
5
8
|
export interface StoreStatic {
|
|
6
9
|
create<T>(name: string, value: T): ObservableItem<T>;
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
createResettable<T>(name: string, value: T): ObservableItem<T>;
|
|
11
|
+
createComposed<T>(
|
|
12
|
+
name: string,
|
|
13
|
+
computation: () => T,
|
|
14
|
+
dependencies: (string | ObservableItem<any>)[]
|
|
15
|
+
): ObservableItem<T>;
|
|
16
|
+
createPersistent<T>(name: string, value: T, localStorageKey?: string): ObservableItem<T>;
|
|
17
|
+
createPersistentResettable<T>(name: string, value: T, localStorageKey?: string): ObservableItem<T>;
|
|
18
|
+
|
|
19
|
+
has(name: string): boolean;
|
|
9
20
|
get<T>(name: string): ObservableItem<T> | null;
|
|
10
|
-
getWithSubscribers<T>(name: string): {
|
|
21
|
+
getWithSubscribers<T>(name: string): {
|
|
22
|
+
observer: ObservableItem<T>;
|
|
23
|
+
subscribers: Set<ObservableItem<T>>;
|
|
24
|
+
} | null;
|
|
25
|
+
|
|
26
|
+
use<T>(name: string): ObservableItem<T>;
|
|
27
|
+
follow<T>(name: string): Readonly<ObservableItem<T>>;
|
|
28
|
+
|
|
29
|
+
reset(name: string): void;
|
|
11
30
|
delete(name: string): void;
|
|
12
|
-
|
|
31
|
+
|
|
32
|
+
group(callback: (group: StoreGroupInstance) => void): StoreGroupInstance;
|
|
33
|
+
group(name: string, callback: (group: StoreGroupInstance) => void): StoreGroupInstance;
|
|
34
|
+
|
|
35
|
+
readonly [key: string]: ObservableItem<any> | unknown;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export declare const StoreFactory: () => StoreStatic;
|
|
39
|
+
export declare const Store: StoreStatic;
|
package/hrm.js
DELETED
package/src/devtools/app/App.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import {Div} from "../../../elements";
|
|
2
|
-
import DevToolsWidget from "../../devtools/widget/DevToolsWidget";
|
|
3
|
-
|
|
4
|
-
export default function App() {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return Div(
|
|
8
|
-
Div({ class: 'devtools-app-panel-wrapper pin-to-right' }, [
|
|
9
|
-
DevToolsWidget,
|
|
10
|
-
Div({ class: 'devtools-app-panel' }),
|
|
11
|
-
Div('Gogo Panel')
|
|
12
|
-
]),
|
|
13
|
-
).nd.closedShadow(`
|
|
14
|
-
.devtools-app-panel-wrapper {
|
|
15
|
-
position: fixed;
|
|
16
|
-
width: 0px;
|
|
17
|
-
background: red;
|
|
18
|
-
animate: .25s linear;
|
|
19
|
-
}
|
|
20
|
-
.devtools-app-panel-wrapper.pin-to-right {
|
|
21
|
-
right: 0;
|
|
22
|
-
top: 0;
|
|
23
|
-
bottom: 0;
|
|
24
|
-
}
|
|
25
|
-
.devtools-app-panel-widget {
|
|
26
|
-
position: fixed;
|
|
27
|
-
background: rgba(0, 0, 0, 0.8);
|
|
28
|
-
backdrop-filter: blur(5px);
|
|
29
|
-
padding: 2px;
|
|
30
|
-
width: 150px;
|
|
31
|
-
height: 30px;
|
|
32
|
-
border-radius: 5px;
|
|
33
|
-
border: 1px solid black;
|
|
34
|
-
z-index: 10000009;
|
|
35
|
-
color: white;
|
|
36
|
-
cursor: pointer;
|
|
37
|
-
transform: translate(-50%, -50%);
|
|
38
|
-
display: flex;
|
|
39
|
-
justify-content: space-between;
|
|
40
|
-
align-items: stretch;
|
|
41
|
-
align-content: center;
|
|
42
|
-
}
|
|
43
|
-
.widget-button {
|
|
44
|
-
width: 30px;
|
|
45
|
-
padding: 2px;
|
|
46
|
-
background: rgba(0, 0, 0, 0.8);
|
|
47
|
-
border: 1px solid black;
|
|
48
|
-
display: flex;
|
|
49
|
-
justify-content: center;
|
|
50
|
-
align-items: center;
|
|
51
|
-
align-content: center;
|
|
52
|
-
color: white;
|
|
53
|
-
border-radius: 5px;
|
|
54
|
-
cursor: pointer;
|
|
55
|
-
font-size: .9rem;
|
|
56
|
-
}
|
|
57
|
-
.widget-label {
|
|
58
|
-
font-weight: bold;
|
|
59
|
-
font-size: 1.5rem;
|
|
60
|
-
flex: 1;
|
|
61
|
-
display: flex;
|
|
62
|
-
justify-content: center;
|
|
63
|
-
align-items: center;
|
|
64
|
-
}
|
|
65
|
-
`);
|
|
66
|
-
}
|
package/src/devtools/app/app.css
DELETED
|
File without changes
|