native-document 1.0.95 → 1.0.99
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/{src/devtools/hrm → devtools/transformers/templates}/hrm.orbservable.hook.template.js +8 -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 +1953 -1245
- package/dist/native-document.dev.js +2022 -1375
- 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 +333 -315
- package/docs/state-management.md +198 -193
- package/package.json +1 -1
- package/readme.md +1 -1
- package/rollup.config.js +1 -1
- package/src/core/data/ObservableArray.js +67 -0
- package/src/core/data/ObservableChecker.js +2 -0
- package/src/core/data/ObservableItem.js +97 -0
- package/src/core/data/ObservableObject.js +183 -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/fetch/NativeFetch.js +5 -2
- package/types/observable.d.ts +73 -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
|
@@ -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/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;
|
|
@@ -101,37 +150,46 @@ export interface ObservableArray<T> extends ObservableItem<T[]> {
|
|
|
101
150
|
where(predicates: PredicateMap<T>): ObservableArray<T>;
|
|
102
151
|
whereSome<K extends keyof T>(fields: K[], filter: FilterResult<T[K]>): ObservableArray<T>;
|
|
103
152
|
whereEvery<K extends keyof T>(fields: K[], filter: FilterResult<T[K]>): ObservableArray<T>;
|
|
153
|
+
|
|
154
|
+
deepSubscribe(callback: (value: T[]) => void): () => void;
|
|
104
155
|
}
|
|
105
156
|
|
|
106
|
-
export type
|
|
157
|
+
export type ObservableObject<T extends Record<string, any>> = ObservableItem<T> & {
|
|
158
|
+
readonly __$isObservableObject: true;
|
|
107
159
|
readonly __isProxy__: true;
|
|
108
|
-
readonly $
|
|
160
|
+
readonly $observables: { [K in keyof T]: ObservableItem<T[K]> };
|
|
109
161
|
readonly configs: ObservableConfig | null;
|
|
162
|
+
|
|
163
|
+
$load(initialValue: Partial<T>): void;
|
|
110
164
|
$val(): T;
|
|
111
165
|
val(): T;
|
|
112
|
-
$get(key: string): any;
|
|
113
166
|
get(key: string): any;
|
|
114
|
-
$
|
|
115
|
-
clone(): ObservableProxy<T>;
|
|
116
|
-
$updateWith(values: Partial<T>): void;
|
|
117
|
-
$set(values: Partial<T>): void;
|
|
167
|
+
$get(key: string): any;
|
|
118
168
|
set(values: Partial<T>): void;
|
|
169
|
+
$set(values: Partial<T>): void;
|
|
170
|
+
$updateWith(values: Partial<T>): void;
|
|
171
|
+
update(values: Partial<T>): void;
|
|
119
172
|
reset(): void;
|
|
173
|
+
clone(): ObservableObject<T>;
|
|
174
|
+
$clone(): ObservableObject<T>;
|
|
120
175
|
keys(): string[];
|
|
176
|
+
$keys(): string[];
|
|
177
|
+
observables(): ObservableItem<any>[];
|
|
121
178
|
} & {
|
|
122
179
|
[K in keyof T]: T[K] extends (infer U)[]
|
|
123
180
|
? ObservableArray<U>
|
|
124
181
|
: T[K] extends Record<string, any>
|
|
125
|
-
?
|
|
182
|
+
? ObservableObject<T[K]>
|
|
126
183
|
: ObservableItem<T[K]>;
|
|
127
184
|
};
|
|
128
185
|
|
|
186
|
+
|
|
129
187
|
export interface BatchFunction<TArgs extends any[] = any[], TReturn = any> {
|
|
130
188
|
(...args: TArgs): TReturn;
|
|
131
189
|
readonly $observer: ObservableItem<number>;
|
|
132
190
|
}
|
|
133
191
|
|
|
134
|
-
export type ValidComputedDependencies = Array<ObservableItem | ObservableArray<any> | ObservableChecker |
|
|
192
|
+
export type ValidComputedDependencies = Array<ObservableItem | ObservableArray<any> | ObservableChecker | ObservableObject<any>>;
|
|
135
193
|
|
|
136
194
|
export interface AutoCleanupOptions {
|
|
137
195
|
interval?: number;
|
|
@@ -148,9 +206,9 @@ export interface ObservableStatic {
|
|
|
148
206
|
<T>(value: T, configs?: ObservableConfig | null): ObservableItem<T>;
|
|
149
207
|
array<T>(target: T[] | null, configs?: ObservableConfig | null): ObservableArray<T>;
|
|
150
208
|
|
|
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):
|
|
209
|
+
init<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null): ObservableObject<T>;
|
|
210
|
+
object<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null): ObservableObject<T>;
|
|
211
|
+
json<T extends Record<string, any>>(value: T, configs?: ObservableConfig | null): ObservableObject<T>;
|
|
154
212
|
|
|
155
213
|
computed<T>(callback: () => T, dependencies?: ValidComputedDependencies | BatchFunction): ObservableItem<T>;
|
|
156
214
|
computed<T>(callback: () => T, batchFunction?: BatchFunction): ObservableItem<T>;
|
|
@@ -165,5 +223,5 @@ export interface ObservableStatic {
|
|
|
165
223
|
getById(id: number): ObservableItem | null;
|
|
166
224
|
cleanup(observable: ObservableItem): void;
|
|
167
225
|
autoCleanup(enable?: boolean, options?: AutoCleanupOptions): void;
|
|
168
|
-
arrayOfObject<T extends Record<string, any>>(data: T[]):
|
|
226
|
+
arrayOfObject<T extends Record<string, any>>(data: T[]): ObservableObject<T>[];
|
|
169
227
|
}
|
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
|