@zajno/common 1.2.5 → 1.3.0-beta
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/coverage/clover.xml +453 -173
- package/coverage/coverage-final.json +38 -30
- package/coverage/lcov-report/index.html +34 -19
- package/coverage/lcov-report/src/__tests__/helpers/index.html +1 -1
- package/coverage/lcov-report/src/__tests__/helpers/main.ts.html +1 -1
- package/coverage/lcov-report/src/async/arrays.ts.html +5 -5
- package/coverage/lcov-report/src/async/index.html +1 -1
- package/coverage/lcov-report/src/dates/calc.ts.html +1 -1
- package/coverage/lcov-report/src/dates/convert.ts.html +1 -1
- package/coverage/lcov-report/src/dates/datex.ts.html +1 -1
- package/coverage/lcov-report/src/dates/format.ts.html +1 -1
- package/coverage/lcov-report/src/dates/index.html +1 -1
- package/coverage/lcov-report/src/dates/index.ts.html +1 -1
- package/coverage/lcov-report/src/dates/parse.ts.html +1 -1
- package/coverage/lcov-report/src/dates/period.ts.html +1 -1
- package/coverage/lcov-report/src/dates/shift.ts.html +1 -1
- package/coverage/lcov-report/src/dates/types.ts.html +1 -1
- package/coverage/lcov-report/src/dates/yearDate.ts.html +1 -1
- package/coverage/lcov-report/src/enumHelper.ts.html +11 -11
- package/coverage/lcov-report/src/event.ts.html +6 -6
- package/coverage/lcov-report/src/index.html +49 -19
- package/coverage/lcov-report/src/lazy.light.ts.html +155 -0
- package/coverage/lcov-report/src/logger/console.ts.html +2 -2
- package/coverage/lcov-report/src/logger/index.html +1 -1
- package/coverage/lcov-report/src/logger/index.ts.html +8 -8
- package/coverage/lcov-report/src/logger/named.ts.html +16 -16
- package/coverage/lcov-report/src/logger/proxy.ts.html +4 -4
- package/coverage/lcov-report/src/math/arrays.ts.html +1 -1
- package/coverage/lcov-report/src/math/calc.ts.html +1 -1
- package/coverage/lcov-report/src/math/distribution.ts.html +1 -1
- package/coverage/lcov-report/src/math/index.html +1 -1
- package/coverage/lcov-report/src/math/index.ts.html +1 -1
- package/coverage/lcov-report/src/transitionObserver.ts.html +192 -45
- package/coverage/lcov-report/src/types.ts.html +143 -0
- package/coverage/lcov-report/src/validation/ValidationErrors.ts.html +22 -22
- package/coverage/lcov-report/src/validation/creditCard.ts.html +4 -4
- package/coverage/lcov-report/src/validation/helpers.ts.html +6 -6
- package/coverage/lcov-report/src/validation/index.html +1 -1
- package/coverage/lcov-report/src/validation/index.ts.html +6 -6
- package/coverage/lcov-report/src/validation/types.ts.html +2 -2
- package/coverage/lcov-report/src/validation/validators.ts.html +5 -5
- package/coverage/lcov-report/src/validation/wrappers.ts.html +5 -5
- package/coverage/lcov-report/src/viewModels/FlagModel.ts.html +209 -0
- package/coverage/lcov-report/src/viewModels/LabeledFlagModel.ts.html +146 -0
- package/coverage/lcov-report/src/viewModels/MultiSelectModel.ts.html +530 -0
- package/coverage/lcov-report/src/viewModels/NumberModel.ts.html +188 -0
- package/coverage/lcov-report/{enumHelper.ts.html → src/viewModels/SelectModel.ts.html} +158 -152
- package/coverage/lcov-report/src/viewModels/SelectViewModel.ts.html +434 -0
- package/coverage/lcov-report/src/viewModels/Validatable.ts.html +329 -0
- package/coverage/lcov-report/src/viewModels/index.html +186 -0
- package/coverage/lcov-report/src/viewModels/wrappers.ts.html +239 -0
- package/coverage/lcov-report/transitionObserver.ts.html +155 -44
- package/coverage/lcov.info +838 -229
- package/lib/timeHelper.d.ts +3 -0
- package/lib/timeHelper.d.ts.map +1 -1
- package/lib/timeHelper.js +3 -0
- package/lib/timeHelper.js.map +1 -1
- package/lib/transitionObserver.d.ts +6 -0
- package/lib/transitionObserver.d.ts.map +1 -1
- package/lib/transitionObserver.js +42 -0
- package/lib/transitionObserver.js.map +1 -1
- package/lib/types.d.ts +5 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +14 -0
- package/lib/types.js.map +1 -1
- package/lib/viewModels/FlagModel.d.ts +19 -0
- package/lib/viewModels/FlagModel.d.ts.map +1 -0
- package/lib/viewModels/FlagModel.js +38 -0
- package/lib/viewModels/FlagModel.js.map +1 -0
- package/lib/viewModels/MultiSelectModel.d.ts +41 -0
- package/lib/viewModels/MultiSelectModel.d.ts.map +1 -0
- package/lib/viewModels/MultiSelectModel.js +150 -0
- package/lib/viewModels/MultiSelectModel.js.map +1 -0
- package/lib/viewModels/NumberModel.d.ts +16 -0
- package/lib/viewModels/NumberModel.d.ts.map +1 -0
- package/lib/viewModels/NumberModel.js +40 -0
- package/lib/viewModels/NumberModel.js.map +1 -0
- package/lib/viewModels/PromptModalViewModel.d.ts +20 -16
- package/lib/viewModels/PromptModalViewModel.d.ts.map +1 -1
- package/lib/viewModels/PromptModalViewModel.js +37 -36
- package/lib/viewModels/PromptModalViewModel.js.map +1 -1
- package/lib/viewModels/{SelectViewModel.d.ts → SelectModel.d.ts} +14 -8
- package/lib/viewModels/SelectModel.d.ts.map +1 -0
- package/lib/viewModels/SelectModel.js +109 -0
- package/lib/viewModels/SelectModel.js.map +1 -0
- package/lib/viewModels/{TextInputViewModel.d.ts → TextModel.d.ts} +10 -9
- package/lib/viewModels/TextModel.d.ts.map +1 -0
- package/lib/viewModels/{TextInputViewModel.js → TextModel.js} +8 -17
- package/lib/viewModels/TextModel.js.map +1 -0
- package/lib/viewModels/Validatable.d.ts +9 -7
- package/lib/viewModels/Validatable.d.ts.map +1 -1
- package/lib/viewModels/Validatable.js +22 -8
- package/lib/viewModels/Validatable.js.map +1 -1
- package/lib/viewModels/ValuesCollector.d.ts +28 -0
- package/lib/viewModels/ValuesCollector.d.ts.map +1 -0
- package/lib/viewModels/ValuesCollector.js +51 -0
- package/lib/viewModels/ValuesCollector.js.map +1 -0
- package/lib/viewModels/index.d.ts +7 -5
- package/lib/viewModels/index.d.ts.map +1 -1
- package/lib/viewModels/index.js +7 -5
- package/lib/viewModels/index.js.map +1 -1
- package/lib/viewModels/wrappers.d.ts +15 -0
- package/lib/viewModels/wrappers.d.ts.map +1 -0
- package/lib/viewModels/wrappers.js +43 -0
- package/lib/viewModels/wrappers.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/transitionObserver.test.ts +39 -0
- package/src/timeHelper.ts +3 -0
- package/src/transitionObserver.ts +49 -0
- package/src/types.ts +16 -0
- package/src/viewModels/FlagModel.ts +43 -0
- package/src/viewModels/MultiSelectModel.ts +150 -0
- package/src/viewModels/NumberModel.ts +36 -0
- package/src/viewModels/PromptModalViewModel.ts +43 -49
- package/src/viewModels/SelectModel.ts +125 -0
- package/src/viewModels/{TextInputViewModel.ts → TextModel.ts} +22 -25
- package/src/viewModels/Validatable.ts +26 -11
- package/src/viewModels/ValuesCollector.ts +84 -0
- package/src/viewModels/__tests__/multiSelect.test.ts +23 -0
- package/src/viewModels/__tests__/select.test.ts +71 -0
- package/src/viewModels/__tests__/wrappers.test.ts +79 -0
- package/src/viewModels/index.ts +9 -5
- package/src/viewModels/wrappers.ts +53 -0
- package/yarn-error.log +3709 -0
- package/lib/viewModels/RadioButtonGroupViewModel.d.ts +0 -11
- package/lib/viewModels/RadioButtonGroupViewModel.d.ts.map +0 -1
- package/lib/viewModels/RadioButtonGroupViewModel.js +0 -51
- package/lib/viewModels/RadioButtonGroupViewModel.js.map +0 -1
- package/lib/viewModels/RadioButtonViewModel.d.ts +0 -9
- package/lib/viewModels/RadioButtonViewModel.d.ts.map +0 -1
- package/lib/viewModels/RadioButtonViewModel.js +0 -32
- package/lib/viewModels/RadioButtonViewModel.js.map +0 -1
- package/lib/viewModels/SelectViewModel.d.ts.map +0 -1
- package/lib/viewModels/SelectViewModel.js +0 -88
- package/lib/viewModels/SelectViewModel.js.map +0 -1
- package/lib/viewModels/TextInputViewModel.d.ts.map +0 -1
- package/lib/viewModels/TextInputViewModel.js.map +0 -1
- package/src/viewModels/RadioButtonGroupViewModel.ts +0 -47
- package/src/viewModels/RadioButtonViewModel.ts +0 -26
- package/src/viewModels/SelectViewModel.ts +0 -88
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Getter } from '../types';
|
|
2
|
+
import { IValueModel } from './ValuesCollector';
|
|
3
|
+
export interface ILabel<T> {
|
|
4
|
+
readonly label: T;
|
|
5
|
+
}
|
|
6
|
+
export declare function withLabel<T, TModel extends IValueModel<T>, TLabel = string>(model: TModel, label: Getter<TLabel>): TModel & ILabel<TLabel>;
|
|
7
|
+
export declare function inject<T, TModel extends IValueModel<T>>(model: TModel, source: IValueModel<T>): TModel;
|
|
8
|
+
export declare function wrap<T, TModel extends IValueModel<T>, TRes>(model: TModel, getter: (m: TModel) => TRes, setter: (v: TRes, model: TModel) => void): IValueModel<TRes>;
|
|
9
|
+
declare type LabeledModel<T, TModel extends IValueModel<T>, TLabel = string> = TModel & ILabel<TLabel>;
|
|
10
|
+
interface LabeledModelCtor<T, TModel extends IValueModel<T>, TLabel = string> {
|
|
11
|
+
new (label?: Getter<TLabel>, initial?: T): LabeledModel<T, TModel, TLabel>;
|
|
12
|
+
}
|
|
13
|
+
export declare function mixinLabel<T, TModel extends IValueModel<T>, TLabel = string>(Superclass: new (initial?: T) => TModel): LabeledModelCtor<T, TModel, TLabel>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=wrappers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrappers.d.ts","sourceRoot":"","sources":["../../src/viewModels/wrappers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,MAAM,CAAC,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;CACrB;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,2BAShH;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,UAS7F;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAKpK;AAED,aAAK,YAAY,CAAC,CAAC,EAAE,MAAM,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAE/F,UAAU,gBAAgB,CAAC,CAAC,EAAE,MAAM,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IACxE,KAAK,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9E;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAU1J"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mixinLabel = exports.wrap = exports.inject = exports.withLabel = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
function withLabel(model, label) {
|
|
6
|
+
const _label = label;
|
|
7
|
+
Object.defineProperty(model, 'label', {
|
|
8
|
+
configurable: true,
|
|
9
|
+
enumerable: false,
|
|
10
|
+
get() { return types_1.Getter.getValue(_label); },
|
|
11
|
+
});
|
|
12
|
+
return model;
|
|
13
|
+
}
|
|
14
|
+
exports.withLabel = withLabel;
|
|
15
|
+
function inject(model, source) {
|
|
16
|
+
Object.defineProperty(model, 'value', {
|
|
17
|
+
configurable: true,
|
|
18
|
+
enumerable: false,
|
|
19
|
+
get() { return source.value; },
|
|
20
|
+
set(v) { source.value = v; },
|
|
21
|
+
});
|
|
22
|
+
return model;
|
|
23
|
+
}
|
|
24
|
+
exports.inject = inject;
|
|
25
|
+
function wrap(model, getter, setter) {
|
|
26
|
+
return {
|
|
27
|
+
get value() { return getter(model); },
|
|
28
|
+
set value(v) { setter(v, model); },
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
exports.wrap = wrap;
|
|
32
|
+
function mixinLabel(Superclass) {
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
class Sub extends Superclass {
|
|
35
|
+
constructor(label, initial) {
|
|
36
|
+
super(initial);
|
|
37
|
+
withLabel(this, label);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return Sub;
|
|
41
|
+
}
|
|
42
|
+
exports.mixinLabel = mixinLabel;
|
|
43
|
+
//# sourceMappingURL=wrappers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrappers.js","sourceRoot":"","sources":["../../src/viewModels/wrappers.ts"],"names":[],"mappings":";;;AAAA,oCAAkC;AAOlC,SAAgB,SAAS,CAAoD,KAAa,EAAE,KAAqB;IAC7G,MAAM,MAAM,GAAG,KAAK,CAAC;IACrB,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE;QAClC,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;QACjB,GAAG,KAAK,OAAO,cAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;KAC5C,CAAC,CAAC;IAEH,OAAO,KAAgC,CAAC;AAC5C,CAAC;AATD,8BASC;AAED,SAAgB,MAAM,CAAmC,KAAa,EAAE,MAAsB;IAC1F,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE;QAClC,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,KAAK;QACjB,GAAG,KAAK,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9B,GAAG,CAAC,CAAI,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;KAClC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACjB,CAAC;AATD,wBASC;AAED,SAAgB,IAAI,CAAyC,KAAa,EAAE,MAA2B,EAAE,MAAwC;IAC7I,OAAO;QACH,IAAI,KAAK,KAAK,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,KAAK,CAAC,CAAO,IAAI,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;KAC3C,CAAC;AACN,CAAC;AALD,oBAKC;AAQD,SAAgB,UAAU,CAAoD,UAAuC;IACjH,aAAa;IACb,MAAM,GAAI,SAAQ,UAAU;QACxB,YAAY,KAAqB,EAAE,OAAW;YAC1C,KAAK,CAAC,OAAO,CAAC,CAAC;YACf,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3B,CAAC;KACJ;IAED,OAAO,GAAU,CAAC;AACtB,CAAC;AAVD,gCAUC"}
|
package/package.json
CHANGED
|
@@ -177,4 +177,43 @@ describe('TransitionObserver', () => {
|
|
|
177
177
|
expect(cbE).not.toHaveBeenCalled();
|
|
178
178
|
expect(cb).not.toHaveBeenCalled();
|
|
179
179
|
});
|
|
180
|
+
|
|
181
|
+
it('promises 2 times', async () => {
|
|
182
|
+
|
|
183
|
+
const store = createStore<boolean>(true);
|
|
184
|
+
const cb = jest.fn();
|
|
185
|
+
|
|
186
|
+
const to = new TransitionObserver(() => store.value)
|
|
187
|
+
.to(false)
|
|
188
|
+
.cb(cb);
|
|
189
|
+
|
|
190
|
+
for (let i = 1; i <= 2; ++i) {
|
|
191
|
+
store.setValue(true);
|
|
192
|
+
|
|
193
|
+
const p = to.getPromise();
|
|
194
|
+
|
|
195
|
+
store.setValue(false);
|
|
196
|
+
|
|
197
|
+
await expect(p).resolves.toBe(false);
|
|
198
|
+
expect(cb).not.toHaveBeenCalled();
|
|
199
|
+
cb.mockReset();
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('promising – aborting', async () => {
|
|
204
|
+
|
|
205
|
+
const store = createStore<boolean>(true);
|
|
206
|
+
const cb = jest.fn();
|
|
207
|
+
|
|
208
|
+
const to = new TransitionObserver(() => store.value)
|
|
209
|
+
.to(false)
|
|
210
|
+
.cb(cb);
|
|
211
|
+
|
|
212
|
+
const p = to.getPromise();
|
|
213
|
+
|
|
214
|
+
to.dispose();
|
|
215
|
+
|
|
216
|
+
await expect(p).rejects.toThrow(/Aborted/);
|
|
217
|
+
expect(cb).not.toHaveBeenCalled();
|
|
218
|
+
});
|
|
180
219
|
});
|
package/src/timeHelper.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { observable, makeObservable } from 'mobx';
|
|
2
2
|
|
|
3
|
+
/** @deprecated */
|
|
3
4
|
export function formatMS(ms: number): string {
|
|
4
5
|
if (!ms && ms !== 0) {
|
|
5
6
|
return '';
|
|
@@ -12,6 +13,7 @@ export function formatMS(ms: number): string {
|
|
|
12
13
|
return `${hours ? hours + ':' : ''}${min < 10 ? '0' + min : min}:${sec < 10 ? '0' + sec : sec}`;
|
|
13
14
|
}
|
|
14
15
|
|
|
16
|
+
/** @deprecated */
|
|
15
17
|
export function formatTime(n: number): string {
|
|
16
18
|
if (n < 10) {
|
|
17
19
|
return '0' + n;
|
|
@@ -20,6 +22,7 @@ export function formatTime(n: number): string {
|
|
|
20
22
|
return n.toString();
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
/** @deprecated */
|
|
23
26
|
export function secToFormattedMin(totalSec: number): string {
|
|
24
27
|
const sec = Math.round(totalSec) % 60;
|
|
25
28
|
const min = Math.floor((totalSec + 1) / 60);
|
|
@@ -17,6 +17,9 @@ export class TransitionObserver<T> implements IDisposable {
|
|
|
17
17
|
private _cb: (v: T) => any;
|
|
18
18
|
private _fireOnce = false;
|
|
19
19
|
|
|
20
|
+
private _promise: Promise<T> = null;
|
|
21
|
+
private _promiseReject: (err?: any) => any = null;
|
|
22
|
+
|
|
20
23
|
private logger: ILogger = createLogger('', true);
|
|
21
24
|
|
|
22
25
|
constructor(getter?: () => T) {
|
|
@@ -28,6 +31,9 @@ export class TransitionObserver<T> implements IDisposable {
|
|
|
28
31
|
public get event(): IEvent<T> { return this._event; }
|
|
29
32
|
public get currentValue() { return this._prev; }
|
|
30
33
|
|
|
34
|
+
public get isObserving() { return this._disposer != null; }
|
|
35
|
+
private get isPromising() { return this._promiseReject != null; }
|
|
36
|
+
|
|
31
37
|
observe(getter: () => T) {
|
|
32
38
|
this.dispose();
|
|
33
39
|
this._getter = getter;
|
|
@@ -47,6 +53,9 @@ export class TransitionObserver<T> implements IDisposable {
|
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
cb(cb: (v: T) => any) {
|
|
56
|
+
if (this.isPromising) {
|
|
57
|
+
throw new Error('Cannot set callback when promise is running');
|
|
58
|
+
}
|
|
50
59
|
this._cb = cb;
|
|
51
60
|
return this;
|
|
52
61
|
}
|
|
@@ -72,6 +81,33 @@ export class TransitionObserver<T> implements IDisposable {
|
|
|
72
81
|
return this;
|
|
73
82
|
}
|
|
74
83
|
|
|
84
|
+
getPromise(timeout: number = null) {
|
|
85
|
+
if (!this._promise) {
|
|
86
|
+
if (!this.isObserving) {
|
|
87
|
+
return Promise.reject(new Error('Cannot get promise for disposed TransitionObserver'));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
this._promise = new Promise<T>((resolve, reject) => {
|
|
91
|
+
this._promiseReject = reject;
|
|
92
|
+
|
|
93
|
+
let timeoutHandle: any = null;
|
|
94
|
+
if (timeout) {
|
|
95
|
+
timeoutHandle = setTimeout(() => {
|
|
96
|
+
this._finishPromise(this._promiseReject, new Error(`TransitionObserver Aborted – timed out after ${timeout}ms`));
|
|
97
|
+
}, timeout);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this._cb = (v => {
|
|
101
|
+
clearTimeout(timeoutHandle);
|
|
102
|
+
this._finishPromise(resolve, v);
|
|
103
|
+
});
|
|
104
|
+
this.forceCheck();
|
|
105
|
+
});
|
|
106
|
+
this.logger.log('started a new promise...');
|
|
107
|
+
}
|
|
108
|
+
return this._promise;
|
|
109
|
+
}
|
|
110
|
+
|
|
75
111
|
reverse() {
|
|
76
112
|
return new TransitionObserver<T>(this._getter)
|
|
77
113
|
.from(this._to)
|
|
@@ -87,6 +123,10 @@ export class TransitionObserver<T> implements IDisposable {
|
|
|
87
123
|
this.logger.log(' disposing... ');
|
|
88
124
|
if (this._disposer) {
|
|
89
125
|
this._disposer();
|
|
126
|
+
this._disposer = null;
|
|
127
|
+
}
|
|
128
|
+
if (this.isPromising) {
|
|
129
|
+
this._finishPromise(this._promiseReject, new Error('TransitionObserver Aborted'));
|
|
90
130
|
}
|
|
91
131
|
};
|
|
92
132
|
|
|
@@ -124,4 +164,13 @@ export class TransitionObserver<T> implements IDisposable {
|
|
|
124
164
|
|
|
125
165
|
return trigger;
|
|
126
166
|
};
|
|
167
|
+
|
|
168
|
+
private _finishPromise<T>(cb: (a?: T) => any, arg?: T) {
|
|
169
|
+
this._promise = null;
|
|
170
|
+
this._promiseReject = null;
|
|
171
|
+
this._cb = null;
|
|
172
|
+
if (cb) {
|
|
173
|
+
cb(arg);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
127
176
|
}
|
package/src/types.ts
CHANGED
|
@@ -3,3 +3,19 @@ export { DeepPartial } from './deepPartial';
|
|
|
3
3
|
export type DeepReadonly<T> = {
|
|
4
4
|
readonly [P in keyof T]: DeepReadonly<T[P]>;
|
|
5
5
|
};
|
|
6
|
+
|
|
7
|
+
export type Getter<T> = (() => T) | T | null;
|
|
8
|
+
|
|
9
|
+
export namespace Getter {
|
|
10
|
+
export function getValue<T>(getter: Getter<T>): T {
|
|
11
|
+
if (getter == null) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
if (typeof getter === 'function') {
|
|
15
|
+
return (getter as () => T)();
|
|
16
|
+
}
|
|
17
|
+
return getter;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type Predicate<T> = (value: T) => boolean;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { action, makeObservable, observable } from 'mobx';
|
|
2
|
+
import { ILabel } from './wrappers';
|
|
3
|
+
import { IValueModel } from './ValuesCollector';
|
|
4
|
+
|
|
5
|
+
export interface IFlagModel extends IValueModel<boolean> {
|
|
6
|
+
toggle(): void;
|
|
7
|
+
reset(): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type IFlagModelReadonly = {
|
|
11
|
+
readonly value: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type ILabeledFlagModel = IFlagModel & ILabel<string>;
|
|
15
|
+
|
|
16
|
+
export class FlagModel implements IFlagModel, IFlagModelReadonly {
|
|
17
|
+
|
|
18
|
+
@observable
|
|
19
|
+
private _value: boolean = false;
|
|
20
|
+
|
|
21
|
+
constructor(initial = false) {
|
|
22
|
+
makeObservable(this);
|
|
23
|
+
this._value = initial;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get value() {
|
|
27
|
+
return this._value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
set value(value: boolean) {
|
|
31
|
+
this._value = value;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@action
|
|
35
|
+
toggle = () => {
|
|
36
|
+
this._value = !this._value;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
@action
|
|
40
|
+
reset = () => {
|
|
41
|
+
this._value = false;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { createLazy } from '../lazy.light';
|
|
2
|
+
import { action, computed, makeObservable, observable, reaction } from 'mobx';
|
|
3
|
+
import { FlagModel, ILabeledFlagModel } from './FlagModel';
|
|
4
|
+
import { ValidatableModel } from './Validatable';
|
|
5
|
+
import { IValueModel } from './ValuesCollector';
|
|
6
|
+
import { withLabel } from './wrappers';
|
|
7
|
+
|
|
8
|
+
export class MultiSelect<T = any> extends ValidatableModel<ReadonlyArray<T>> implements IValueModel<readonly string[]> {
|
|
9
|
+
|
|
10
|
+
@observable
|
|
11
|
+
private _indexes = new Set<number>();
|
|
12
|
+
|
|
13
|
+
public readonly opened = new FlagModel();
|
|
14
|
+
private readonly _initial: number[] = null;
|
|
15
|
+
|
|
16
|
+
private readonly _flags = createLazy(() => this.createFlags());
|
|
17
|
+
private _indexesLocked = false;
|
|
18
|
+
|
|
19
|
+
constructor(
|
|
20
|
+
private readonly _items: readonly T[],
|
|
21
|
+
private readonly _accessor: (item: T) => string,
|
|
22
|
+
...selected: number[]
|
|
23
|
+
) {
|
|
24
|
+
super();
|
|
25
|
+
makeObservable(this);
|
|
26
|
+
this._initial = selected;
|
|
27
|
+
this.setInitialIndexes();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@computed
|
|
31
|
+
get selectedIndexes(): ReadonlyArray<number> { return Array.from(this._indexes); }
|
|
32
|
+
|
|
33
|
+
get items(): ReadonlyArray<T> { return this._items; }
|
|
34
|
+
|
|
35
|
+
get flags() { return this._flags.value; }
|
|
36
|
+
|
|
37
|
+
@computed
|
|
38
|
+
get values(): ReadonlyArray<string> {
|
|
39
|
+
return this._items.map(i => this._accessor(i));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@computed
|
|
43
|
+
get selectedItems(): ReadonlyArray<T> {
|
|
44
|
+
return this.selectedIndexes.map(i => this._items[i]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@computed
|
|
48
|
+
get selectedValues(): ReadonlyArray<string> {
|
|
49
|
+
const values = this.values;
|
|
50
|
+
return this.selectedIndexes.map(i => values[i]);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get value() { return this.selectedValues; }
|
|
54
|
+
set value(v: readonly string[]) { this.selectValues(v); }
|
|
55
|
+
|
|
56
|
+
isIndexSelected(index: number) { return this._indexes.has(index); }
|
|
57
|
+
isValueSelected(value: string) { return this.values.includes(value); }
|
|
58
|
+
|
|
59
|
+
get isEmpty() { return this._indexes.size === 0; }
|
|
60
|
+
|
|
61
|
+
protected get valueToValidate() { return this.selectedItems; }
|
|
62
|
+
|
|
63
|
+
setItemSelected = (item: T, selected: boolean) => {
|
|
64
|
+
const i = this.items.indexOf(item);
|
|
65
|
+
if (i >= 0) {
|
|
66
|
+
this.setIndexSelected(i, selected);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
selectItem = (item: T) => this.setItemSelected(item, true);
|
|
71
|
+
deSelectItem = (item: T) => this.setItemSelected(item, false);
|
|
72
|
+
|
|
73
|
+
@action
|
|
74
|
+
selectItems = (items: readonly T[]) => {
|
|
75
|
+
items.forEach(this.selectItem);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
setValueSelected = (value: string, selected: boolean) => {
|
|
79
|
+
const i = this.values.indexOf(value);
|
|
80
|
+
if (i >= 0) {
|
|
81
|
+
this.setIndexSelected(i, selected);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
selectValue = (value: string) => this.setValueSelected(value, true);
|
|
86
|
+
deSelectValue = (value: string) => this.setValueSelected(value, false);
|
|
87
|
+
|
|
88
|
+
@action
|
|
89
|
+
selectValues = (values: readonly string[]) => {
|
|
90
|
+
values.forEach(this.selectValue);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
@action
|
|
94
|
+
setIndexSelected = (index: number, selected: boolean) => {
|
|
95
|
+
if (this._indexesLocked) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (selected) {
|
|
100
|
+
this._indexes.add(index);
|
|
101
|
+
} else {
|
|
102
|
+
this._indexes.delete(index);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!this._flags.hasValue) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
this._indexesLocked = true;
|
|
111
|
+
this._flags.value[index].value = selected;
|
|
112
|
+
} finally {
|
|
113
|
+
this._indexesLocked = false;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
reset = () => {
|
|
118
|
+
super.reset();
|
|
119
|
+
this.setInitialIndexes();
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
private setInitialIndexes() {
|
|
123
|
+
this._indexes.clear();
|
|
124
|
+
this._initial.forEach(i => this._indexes.add(i));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private createFlags() {
|
|
128
|
+
const flags: ReadonlyArray<ILabeledFlagModel> = this._items
|
|
129
|
+
.map((item, index) => {
|
|
130
|
+
const flag = withLabel(
|
|
131
|
+
new FlagModel(this._indexes.has(index)),
|
|
132
|
+
() => this._accessor(item),
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// react on every flag is changed directly
|
|
136
|
+
reaction(() => flag.value, isSelected => {
|
|
137
|
+
this.setIndexSelected(index, isSelected);
|
|
138
|
+
});
|
|
139
|
+
return flag;
|
|
140
|
+
});
|
|
141
|
+
return flags;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export class MultiSelectString<T extends string = string> extends MultiSelect<T> {
|
|
146
|
+
|
|
147
|
+
constructor(items: ReadonlyArray<T>, ...selected: number[]) {
|
|
148
|
+
super(items, v => v, ...selected);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { action, makeObservable, observable } from 'mobx';
|
|
2
|
+
import { IValueModel } from './ValuesCollector';
|
|
3
|
+
|
|
4
|
+
export interface INumberModel {
|
|
5
|
+
value: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class NumberModel implements INumberModel, IValueModel<number> {
|
|
9
|
+
|
|
10
|
+
@observable
|
|
11
|
+
private _value: number = 0;
|
|
12
|
+
|
|
13
|
+
private _initial: number = 0;
|
|
14
|
+
|
|
15
|
+
constructor(initial: number = 0) {
|
|
16
|
+
makeObservable(this);
|
|
17
|
+
this._initial = initial;
|
|
18
|
+
this._value = this._initial;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get value() { return this._value; }
|
|
22
|
+
set value(v: number) { this._value = v; }
|
|
23
|
+
|
|
24
|
+
@action
|
|
25
|
+
reset = () => {
|
|
26
|
+
this._value = this._initial;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
@action
|
|
30
|
+
increment = (d = 1) => this.value += d;
|
|
31
|
+
|
|
32
|
+
@action
|
|
33
|
+
decrement = (d = 1) => this.value -= d;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default NumberModel;
|
|
@@ -1,71 +1,65 @@
|
|
|
1
|
-
import { observable, makeObservable } from 'mobx';
|
|
1
|
+
import { observable, makeObservable, action } from 'mobx';
|
|
2
|
+
import { FlagModel } from './FlagModel';
|
|
2
3
|
|
|
3
|
-
export type
|
|
4
|
-
title
|
|
5
|
-
message
|
|
6
|
-
confirmText: string;
|
|
7
|
-
rejectText?: string;
|
|
8
|
-
onConfirm: () => Promise<void> | void;
|
|
9
|
-
onReject?: () => Promise<void> | void;
|
|
10
|
-
modalImage?: number;
|
|
11
|
-
confirmColor?: string;
|
|
12
|
-
rejectColor?: string;
|
|
13
|
-
awaitActions?: boolean;
|
|
4
|
+
export type BaseModalAction = {
|
|
5
|
+
title?: string;
|
|
6
|
+
message?: string;
|
|
14
7
|
};
|
|
15
8
|
|
|
16
|
-
export class
|
|
17
|
-
|
|
18
|
-
private _isActive: boolean = false;
|
|
9
|
+
export class ModalActionModel<T extends BaseModalAction = BaseModalAction> {
|
|
10
|
+
public readonly isActive = new FlagModel();
|
|
19
11
|
|
|
20
|
-
@observable
|
|
21
|
-
private _currentAction:
|
|
12
|
+
@observable.ref
|
|
13
|
+
private _currentAction: T = null;
|
|
22
14
|
|
|
23
15
|
constructor() {
|
|
24
16
|
makeObservable(this);
|
|
25
17
|
}
|
|
26
18
|
|
|
27
|
-
get isActive() {
|
|
28
|
-
return this._isActive;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
set isActive(val: boolean) {
|
|
32
|
-
this._isActive = val;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
19
|
get currentAction() { return this._currentAction; }
|
|
36
20
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
get rejectColor() { return this._currentAction.rejectColor; }
|
|
40
|
-
|
|
41
|
-
openModal(action: PromptModalAction) {
|
|
21
|
+
@action
|
|
22
|
+
public openModal = (action: T) => {
|
|
42
23
|
this._currentAction = action;
|
|
43
|
-
this.
|
|
44
|
-
}
|
|
24
|
+
this.isActive.value = true;
|
|
25
|
+
};
|
|
45
26
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
27
|
+
@action
|
|
28
|
+
public closeModal = () => {
|
|
29
|
+
this.isActive.value = false;
|
|
30
|
+
this._currentAction = null;
|
|
31
|
+
};
|
|
49
32
|
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
const promise =
|
|
53
|
-
if (
|
|
33
|
+
protected runAction = async (cb: () => Promise<void> | void, close = true, awaitAction = false) => {
|
|
34
|
+
if (cb) {
|
|
35
|
+
const promise = cb();
|
|
36
|
+
if (awaitAction) {
|
|
54
37
|
await promise;
|
|
55
38
|
}
|
|
56
39
|
}
|
|
57
40
|
|
|
58
|
-
|
|
41
|
+
if (close) {
|
|
42
|
+
this.closeModal();
|
|
43
|
+
}
|
|
59
44
|
};
|
|
45
|
+
}
|
|
60
46
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
47
|
+
export type PromptModalAction = BaseModalAction & {
|
|
48
|
+
confirmText?: string;
|
|
49
|
+
rejectText?: string;
|
|
50
|
+
onConfirm?: () => Promise<void> | void;
|
|
51
|
+
onReject?: () => Promise<void> | void;
|
|
52
|
+
awaitActions?: boolean;
|
|
53
|
+
modalImage?: any;
|
|
54
|
+
confirmColor?: string;
|
|
55
|
+
rejectColor?: string;
|
|
56
|
+
};
|
|
68
57
|
|
|
69
|
-
|
|
70
|
-
}
|
|
58
|
+
export class PromptModalViewModel extends ModalActionModel<PromptModalAction> {
|
|
59
|
+
get confirmColor() { return this.currentAction.confirmColor; }
|
|
60
|
+
|
|
61
|
+
get rejectColor() { return this.currentAction.rejectColor; }
|
|
62
|
+
|
|
63
|
+
onConfirm = () => this.runAction(this.currentAction.onConfirm, true, this.currentAction.awaitActions);
|
|
64
|
+
onReject = () => this.runAction(this.currentAction.onConfirm, true, this.currentAction.awaitActions);
|
|
71
65
|
}
|