arrmatura 5.0.4 → 5.2.0
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/commons/auth/AuthService.ts +111 -0
- package/commons/auth/UserService.ts +28 -78
- package/commons/auth/index.ts +4 -3
- package/commons/auth/user.xml +18 -20
- package/commons/components/buttons.xml +6 -4
- package/commons/components/layouts.xml +8 -8
- package/commons/components/modal.xml +4 -4
- package/commons/components/navigation.xml +21 -7
- package/commons/components/searchbar.xml +36 -22
- package/commons/components/table.xml +25 -5
- package/commons/components/toasts.xml +10 -5
- package/commons/forms/FormController.ts +48 -34
- package/commons/forms/Item.ts +93 -29
- package/commons/forms/ItemCollectionController.ts +113 -0
- package/commons/forms/ItemController.ts +50 -21
- package/commons/forms/NewItemController.ts +46 -0
- package/commons/forms/SmartareaField.xml +3 -3
- package/commons/forms/SuggestionField.xml +3 -3
- package/commons/forms/fields.xml +28 -15
- package/commons/forms/form.xml +3 -3
- package/commons/forms/index.ts +4 -4
- package/commons/index.ts +2 -2
- package/commons/services/ApiClientService.ts +32 -0
- package/commons/services/GSheetsService.ts +92 -64
- package/commons/services/Invoke.ts +24 -8
- package/commons/services/JsonpService.ts +1 -1
- package/commons/services/MetadataService.ts +50 -0
- package/commons/services/NavigationService.ts +20 -1
- package/commons/services/Service.ts +22 -28
- package/commons/services/Storage.ts +55 -0
- package/commons/services/ToastService.ts +16 -4
- package/commons/services/index.ts +3 -4
- package/core/Arrmatura.ts +4 -9
- package/core/CNode.ts +1 -2
- package/core/Component.ts +29 -31
- package/core/cnodes/conditionals.ts +3 -2
- package/core/expression.ts +1 -1
- package/core/register.ts +1 -1
- package/core/utils.ts +1 -3
- package/core-web/attributes.ts +38 -10
- package/core-web/elements.ts +22 -4
- package/core-web/index.ts +14 -2
- package/core-web/reflow.ts +3 -1
- package/core-web/support.ts +27 -0
- package/docs/index.js +350 -66
- package/lib/{arrayGroupBy.ts → array/arrayGroupBy.ts} +1 -1
- package/lib/{arraySortBy.ts → array/arraySortBy.ts} +5 -5
- package/lib/{arrayToObject.ts → array/arrayToObject.ts} +0 -0
- package/lib/array/arrayish.ts +7 -0
- package/lib/array/index.ts +4 -0
- package/lib/crypto/index.ts +25 -0
- package/lib/{dateFormat.ts → date/index.ts} +61 -3
- package/lib/func/curry.ts +11 -0
- package/lib/{fx.ts → func/fx.ts} +32 -38
- package/lib/{noop.ts → func/identity.ts} +1 -3
- package/lib/{nextId.ts → func/nextId.ts} +0 -0
- package/lib/func/noop.ts +6 -0
- package/lib/geo/index.js +22 -0
- package/lib/index.ts +17 -19
- package/lib/{obj.ts → object/index.ts} +8 -3
- package/lib/{codus.ts → parsing/codus.ts} +1 -1
- package/lib/{predicat.ts → parsing/compiler.ts} +0 -0
- package/lib/{scalar.ts → parsing/scalarParse.ts} +0 -0
- package/lib/{urls.ts → parsing/urls.ts} +0 -0
- package/lib/{xml.ts → parsing/xml.ts} +3 -3
- package/lib/{l10n.ts → resources/l10n.ts} +2 -2
- package/lib/{resources.ru.ts → resources/resources.ru.ts} +0 -0
- package/lib/{resources.ts → resources/resources.ts} +0 -0
- package/lib/{str.ts → string/index.ts} +2 -20
- package/lib/{createListeners.ts → support/createListeners.ts} +0 -0
- package/package.json +7 -6
- package/commons/forms/ItemCollection.ts +0 -152
- package/commons/forms/MetadataService.ts +0 -45
- package/commons/pipes/index.ts +0 -21
- package/commons/pipes/showCounts.ts +0 -16
- package/commons/services/LocalStorage.ts +0 -46
- package/lib/consts.ts +0 -3
- package/lib/curry.ts +0 -8
- package/lib/dateOf.ts +0 -31
- package/lib/dateParseISO8601.ts +0 -27
- package/lib/guid.ts +0 -7
|
@@ -3,15 +3,24 @@ import { Service } from './Service';
|
|
|
3
3
|
|
|
4
4
|
export type Toast = {
|
|
5
5
|
message: string;
|
|
6
|
+
link?: string;
|
|
6
7
|
mode: 'error' | 'warning' | 'info' | '';
|
|
7
8
|
id: string;
|
|
8
9
|
ttl: number;
|
|
10
|
+
timeout?: number;
|
|
11
|
+
counter?: number;
|
|
9
12
|
};
|
|
10
13
|
|
|
14
|
+
export class ToastSender extends Service {
|
|
15
|
+
onData(data: Delta) {
|
|
16
|
+
this.emit('toaster.send', data);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
11
20
|
export class ToastService extends Service {
|
|
12
21
|
items: Toast[] = [];
|
|
13
22
|
|
|
14
|
-
heartbeat = new HeartbeatService(() => this.emit('this.tick'));
|
|
23
|
+
heartbeat = new HeartbeatService(() => this.emit('this.tick', {}));
|
|
15
24
|
|
|
16
25
|
setItems(items: Toast[]) {
|
|
17
26
|
this.heartbeat.setActive(!!items.length);
|
|
@@ -27,11 +36,14 @@ export class ToastService extends Service {
|
|
|
27
36
|
mode: data?.message?.startsWith('error') ? 'error' : data.mode,
|
|
28
37
|
id,
|
|
29
38
|
close,
|
|
30
|
-
ttl: now +
|
|
39
|
+
ttl: now + (data.timeout || 6000),
|
|
31
40
|
};
|
|
32
|
-
|
|
41
|
+
const prev = items.find((e) => e.id === id);
|
|
42
|
+
if (prev) {
|
|
43
|
+
toast.counter = 1 + (prev.counter || 1);
|
|
44
|
+
}
|
|
33
45
|
return {
|
|
34
|
-
items: [toast, ...items.filter((e) => e
|
|
46
|
+
items: [toast, ...items.filter((e) => e !== prev)],
|
|
35
47
|
};
|
|
36
48
|
}
|
|
37
49
|
|
|
@@ -6,9 +6,8 @@ export { Loader } from './Loader';
|
|
|
6
6
|
export { Invoke } from './Invoke';
|
|
7
7
|
export { ErrorHandlingService } from './ErrorHandlingService';
|
|
8
8
|
export { FormController } from '../forms/FormController';
|
|
9
|
+
export * from './MetadataService';
|
|
9
10
|
export * from './GSheetsService';
|
|
10
|
-
export * from '
|
|
11
|
-
export * from '../forms/ItemController';
|
|
11
|
+
export * from './ApiClientService';
|
|
12
12
|
export * from './FirebaseService';
|
|
13
|
-
export * from '
|
|
14
|
-
export * from '../forms/MultivalueController';
|
|
13
|
+
export * from './MetadataService';
|
package/core/Arrmatura.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CNode } from './CNode';
|
|
2
2
|
import { compileNodes } from './compileNode';
|
|
3
3
|
import { Component } from './Component';
|
|
4
|
-
import { xmlParse } from '../lib/xml';
|
|
4
|
+
import { xmlParse } from '../lib/parsing/xml';
|
|
5
5
|
import { registerTypes } from './register';
|
|
6
6
|
|
|
7
7
|
export class Arrmatura extends Component<CArrmaturaNode> implements IArrmatura {
|
|
@@ -11,9 +11,6 @@ export class Arrmatura extends Component<CArrmaturaNode> implements IArrmatura {
|
|
|
11
11
|
get displayName(): string {
|
|
12
12
|
return 'Arrmatura';
|
|
13
13
|
}
|
|
14
|
-
get arrmatura(): IArrmatura {
|
|
15
|
-
return this;
|
|
16
|
-
}
|
|
17
14
|
|
|
18
15
|
get platform(): IPlatform {
|
|
19
16
|
return this.node.platform;
|
|
@@ -74,11 +71,9 @@ export class CArrmaturaNode extends CNode<Arrmatura> {
|
|
|
74
71
|
return Arrmatura;
|
|
75
72
|
}
|
|
76
73
|
|
|
77
|
-
launch() {
|
|
78
|
-
const arrmatura = this.createComponent()
|
|
79
|
-
|
|
80
|
-
arrmatura.up({}, true);
|
|
74
|
+
launch(config = {}) {
|
|
75
|
+
const arrmatura = this.createComponent();
|
|
81
76
|
|
|
82
|
-
|
|
77
|
+
arrmatura.up(config, true);
|
|
83
78
|
}
|
|
84
79
|
}
|
package/core/CNode.ts
CHANGED
package/core/Component.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import { applyValue, methodName, stringifyState } from './utils';
|
|
3
|
-
import { scalarParse } from '
|
|
4
|
-
import { createListeners } from 'createListeners';
|
|
3
|
+
import { scalarParse } from '../lib';
|
|
4
|
+
import { createListeners } from 'support/createListeners';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Runtime Component class.
|
|
@@ -13,6 +13,7 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
13
13
|
|
|
14
14
|
readonly $scope: IScope;
|
|
15
15
|
readonly #parent?: IComponent;
|
|
16
|
+
readonly arrmatura: IArrmatura;
|
|
16
17
|
#isInited: boolean = false;
|
|
17
18
|
#isDone: boolean = false;
|
|
18
19
|
#listeners?: Listeners<void>;
|
|
@@ -24,6 +25,7 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
24
25
|
constructor(readonly _node: INode, _parent?: IComponent, scope?: IScope) {
|
|
25
26
|
this.$scope = scope || this;
|
|
26
27
|
this.#parent = _parent;
|
|
28
|
+
this.arrmatura = _parent?.arrmatura || (this as unknown as IArrmatura);
|
|
27
29
|
this.$impl = this.createImplementation(this.getInitialState());
|
|
28
30
|
|
|
29
31
|
if (this.refId) {
|
|
@@ -31,10 +33,6 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
get parent(): IComponent {
|
|
35
|
-
return this.#parent || this;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
36
|
get node(): T {
|
|
39
37
|
return this._node as T;
|
|
40
38
|
}
|
|
@@ -43,10 +41,6 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
43
41
|
return '🔹';
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
get arrmatura(): IArrmatura {
|
|
47
|
-
return this.parent.arrmatura;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
44
|
get uid() {
|
|
51
45
|
return this.node.uid;
|
|
52
46
|
}
|
|
@@ -61,20 +55,19 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
61
55
|
return this.node.resolveInitialProps(this);
|
|
62
56
|
}
|
|
63
57
|
|
|
64
|
-
up(Δ: Delta | Promise<any
|
|
65
|
-
if (this.#isDone) {
|
|
66
|
-
return;
|
|
58
|
+
up(Δ: Delta | Promise<any>, force: boolean = false): null | Promise<any> {
|
|
59
|
+
if (!Δ || this.#isDone) {
|
|
60
|
+
return null;
|
|
67
61
|
}
|
|
68
62
|
if (Δ.then && Δ.catch) {
|
|
69
|
-
this.upAsync(Δ as Promise<any>);
|
|
70
|
-
return;
|
|
63
|
+
return this.upAsync(Δ as Promise<any>);
|
|
71
64
|
}
|
|
72
|
-
|
|
65
|
+
let prom: Promise<any>[] | null = null;
|
|
73
66
|
const changes = new Map<string, unknown>();
|
|
74
67
|
Object.entries(Δ).forEach(([k, v]) => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.upAsync(pv, k);
|
|
68
|
+
if (v && v.then && v.catch) {
|
|
69
|
+
const pv = v as Promise<any>;
|
|
70
|
+
(prom || (prom = [])).push(this.upAsync(pv, k));
|
|
78
71
|
} else if (k && typeof v !== 'undefined' && v !== this.$impl[k]) {
|
|
79
72
|
changes.set(k, v);
|
|
80
73
|
}
|
|
@@ -87,16 +80,19 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
87
80
|
this.notify();
|
|
88
81
|
}
|
|
89
82
|
}
|
|
83
|
+
if (prom) {
|
|
84
|
+
return Promise.all(prom).then((arr: object[]) => arr.reduce((a, b) => ({ ...a, ...b }), {}));
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
90
87
|
}
|
|
91
88
|
|
|
92
|
-
upAsync(promise: Promise<any>, key?: string) {
|
|
89
|
+
upAsync(promise: Promise<any>, key?: string): Promise<any> {
|
|
93
90
|
const racer = this.raceCondition('set:' + key);
|
|
94
|
-
|
|
95
|
-
if (key && key !== '*') {
|
|
91
|
+
if (key && key[0] !== '*') {
|
|
96
92
|
const akey = key.replace('Promise', '');
|
|
97
|
-
promise.then((val) => up({ [akey]: val }));
|
|
93
|
+
promise.then((val) => racer(() => this.up({ [akey]: val })));
|
|
98
94
|
} else {
|
|
99
|
-
promise.then(up);
|
|
95
|
+
promise.then((r: Delta) => racer(() => this.up(r)));
|
|
100
96
|
}
|
|
101
97
|
return promise;
|
|
102
98
|
}
|
|
@@ -180,11 +176,10 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
180
176
|
|
|
181
177
|
// --- Right Arrow.
|
|
182
178
|
|
|
183
|
-
emit(key: string, data: Delta):
|
|
179
|
+
emit(key: string, data: Delta): null | Promise<any> {
|
|
184
180
|
if (!key || !key.includes('.')) {
|
|
185
|
-
this.up(key ? { [key]: data } : data);
|
|
186
181
|
this.log('update:' + key, data, this.$impl);
|
|
187
|
-
return;
|
|
182
|
+
return this.up(key ? { [key]: data } : data);
|
|
188
183
|
}
|
|
189
184
|
|
|
190
185
|
const [refId, target] = key.split('.');
|
|
@@ -206,11 +201,13 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
206
201
|
|
|
207
202
|
this.log(refId + ':' + propId, result, data, impl);
|
|
208
203
|
if (result) {
|
|
209
|
-
ref.up(result);
|
|
204
|
+
const ret = ref.up(result);
|
|
205
|
+
return ret;
|
|
210
206
|
}
|
|
211
207
|
} catch (ex) {
|
|
212
208
|
this.logError('emit ' + key + ':', ex);
|
|
213
209
|
}
|
|
210
|
+
return null;
|
|
214
211
|
}
|
|
215
212
|
|
|
216
213
|
// --- Life-cycle hooks.
|
|
@@ -386,7 +383,7 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
386
383
|
return (fn: Procedure) => {
|
|
387
384
|
if (counter === COUNTERS.get(key)) {
|
|
388
385
|
counter = 0;
|
|
389
|
-
fn();
|
|
386
|
+
return fn();
|
|
390
387
|
}
|
|
391
388
|
};
|
|
392
389
|
}
|
|
@@ -397,8 +394,9 @@ export class Component<T extends INode = INode> implements IComponent, IScope {
|
|
|
397
394
|
}
|
|
398
395
|
}
|
|
399
396
|
|
|
400
|
-
log(...args: unknown[]) {
|
|
401
|
-
console.log('' + this.displayName + ':' + this.uid, ...args);
|
|
397
|
+
log(val: any, ...args: unknown[]) {
|
|
398
|
+
console.log('' + this.displayName + ':' + this.uid, val, ...args);
|
|
399
|
+
return val;
|
|
402
400
|
}
|
|
403
401
|
|
|
404
402
|
logError(...args: unknown[]) {
|
|
@@ -6,7 +6,7 @@ import { Component } from '../Component';
|
|
|
6
6
|
|
|
7
7
|
class IfComponent extends Component<CIfNode> {
|
|
8
8
|
get content() {
|
|
9
|
-
return this.$impl.condition ? this.node.then : this.node.else;
|
|
9
|
+
return !!this.$impl.condition ? this.node.then : this.node.else;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -45,7 +45,8 @@ export class CIfNode extends CNode<IfComponent> {
|
|
|
45
45
|
// DO NOT place inside iterations.
|
|
46
46
|
this.addPropertyResolver((c: IComponent) => (c.$scope as CompositeComponent).slotContent?.(slotId), 'condition');
|
|
47
47
|
} else {
|
|
48
|
-
|
|
48
|
+
const resolver = compileExpression(expr[0] === '{' ? expr : `{${expr}}`);
|
|
49
|
+
this.addPropertyResolver((c) => !!resolver(c), 'condition');
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
}
|
package/core/expression.ts
CHANGED
package/core/register.ts
CHANGED
package/core/utils.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { nextId } from '
|
|
2
|
-
import { identity } from 'noop';
|
|
3
|
-
import { attributesToString } from 'xml';
|
|
1
|
+
import { nextId, identity, attributesToString } from '../lib';
|
|
4
2
|
|
|
5
3
|
export const applyValue = (value: any, fn = identity) => (value?.then ? value.then(fn) : fn(value));
|
|
6
4
|
|
package/core-web/attributes.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DomNode, IElement } from './type';
|
|
1
|
+
import type { DomNode, IElement } from './type';
|
|
2
2
|
|
|
3
3
|
const camelize = (key: string, sep = '_', jn = ' ') =>
|
|
4
4
|
('' + key)
|
|
@@ -6,13 +6,14 @@ const camelize = (key: string, sep = '_', jn = ' ') =>
|
|
|
6
6
|
.map((s, i) => (i ? s[0].toUpperCase() + s.slice(1) : s))
|
|
7
7
|
.join(jn);
|
|
8
8
|
|
|
9
|
-
const setListener = ($: IElement, key: string, e: DomNode,
|
|
9
|
+
const setListener = ($: IElement, key: string, e: DomNode, fn: unknown) => {
|
|
10
10
|
const fnKey = key.split(':')[0];
|
|
11
|
-
if (!
|
|
11
|
+
if (!fn) {
|
|
12
12
|
setAttribute($, key, null);
|
|
13
13
|
} else {
|
|
14
|
-
setAttribute($, key, (
|
|
15
|
-
|
|
14
|
+
setAttribute($, key, (domEvent: Event) => {
|
|
15
|
+
// indirect reference. could be changed along the time.
|
|
16
|
+
$[fnKey]({ ...e.$dataset }, domEvent);
|
|
16
17
|
return false;
|
|
17
18
|
});
|
|
18
19
|
}
|
|
@@ -74,11 +75,38 @@ export const ATTR_SETTERS: Hash<($: IElement, e: DomNode, v: unknown) => void> =
|
|
|
74
75
|
}
|
|
75
76
|
},
|
|
76
77
|
|
|
77
|
-
click: ($, e, v) => setListener($, 'click
|
|
78
|
+
click: ($, e, v) => setListener($, 'click', e, v),
|
|
79
|
+
click2: ($, e, v) => setListener($, 'click2:click', e, v),
|
|
78
80
|
['bubble-click']: ($, e, v) => setListener($, 'bubble-click:click', e, v),
|
|
79
|
-
blur: ($, e, v) => setListener($, 'blur
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
blur: ($, e, v) => setListener($, 'blur', e, v),
|
|
82
|
+
focus: ($, e, v) => setListener($, 'focus', e, v),
|
|
83
|
+
dblclick: ($, e, v) => setListener($, 'dblclick', e, v),
|
|
84
|
+
scroll: ($, e, v) =>
|
|
85
|
+
setAttribute(
|
|
86
|
+
$,
|
|
87
|
+
'scroll',
|
|
88
|
+
!v
|
|
89
|
+
? null
|
|
90
|
+
: (ev) => {
|
|
91
|
+
$.scroll({ value: e.scrollTop }, ev);
|
|
92
|
+
}
|
|
93
|
+
),
|
|
94
|
+
scrolledDown: ($, element, v) =>
|
|
95
|
+
setAttribute(
|
|
96
|
+
$,
|
|
97
|
+
'scrolledDown:scroll',
|
|
98
|
+
!v
|
|
99
|
+
? null
|
|
100
|
+
: (ev) => {
|
|
101
|
+
const gap = $.scrolledDownGap || 10;
|
|
102
|
+
const offset = element.clientHeight + element.scrollTop;
|
|
103
|
+
const isDown = Math.abs(element.scrollHeight - offset) < gap;
|
|
104
|
+
if (isDown && offset > ($._maxScrolledDownOffset || 0)) {
|
|
105
|
+
$._maxScrolledDownOffset = offset;
|
|
106
|
+
$.scrolledDown({ offset }, ev);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
),
|
|
82
110
|
|
|
83
111
|
touchstart: function ($, e, v) {
|
|
84
112
|
const h = !v
|
|
@@ -166,7 +194,7 @@ export const ATTR_SETTERS: Hash<($: IElement, e: DomNode, v: unknown) => void> =
|
|
|
166
194
|
change: function ($, e, v) {
|
|
167
195
|
setAttribute(
|
|
168
196
|
$,
|
|
169
|
-
'change
|
|
197
|
+
'change',
|
|
170
198
|
!v
|
|
171
199
|
? null
|
|
172
200
|
: (ev: Event) => {
|
package/core-web/elements.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { decodeXmlEntities } from '../lib';
|
|
1
2
|
import { ATTR_SETTERS, setAttribute } from './attributes';
|
|
2
|
-
import { DomNode, IElement } from './type';
|
|
3
|
+
import type { DomNode, IElement } from './type';
|
|
3
4
|
|
|
4
5
|
export class DomElement implements IComponentImplementation, IElement {
|
|
5
6
|
$: IComponent;
|
|
6
7
|
$element: DomNode;
|
|
7
8
|
$listeners: any;
|
|
8
|
-
|
|
9
|
+
$changes: Map<string, any> = new Map();
|
|
9
10
|
init?: () => any;
|
|
10
11
|
[key: string]: unknown;
|
|
11
12
|
|
|
@@ -20,10 +21,21 @@ export class DomElement implements IComponentImplementation, IElement {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
stateChanged(changes: Map<string, any>) {
|
|
24
|
+
const attrs = this;
|
|
25
|
+
changes.forEach((value, key) => {
|
|
26
|
+
if (key[0] === '$') return;
|
|
27
|
+
if (value !== attrs[key]) {
|
|
28
|
+
this.$changes?.set(key, value);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
applyStateChanges() {
|
|
23
34
|
const attrs = this;
|
|
24
35
|
const e = this.$element;
|
|
36
|
+
if (!this.$changes.size) return;
|
|
25
37
|
// this.$.log('changes', changes)
|
|
26
|
-
changes.forEach((value, key) => {
|
|
38
|
+
this.$changes.forEach((value, key) => {
|
|
27
39
|
if (key[0] === '$') return;
|
|
28
40
|
if (value !== attrs[key]) {
|
|
29
41
|
const setter = ATTR_SETTERS[key];
|
|
@@ -40,11 +52,13 @@ export class DomElement implements IComponentImplementation, IElement {
|
|
|
40
52
|
}
|
|
41
53
|
attrs[key] = value;
|
|
42
54
|
});
|
|
55
|
+
this.$changes.clear();
|
|
43
56
|
}
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
export class DomTextElement implements IComponentImplementation {
|
|
47
60
|
$element: Text;
|
|
61
|
+
$string: string | null = null;
|
|
48
62
|
[key: string]: unknown;
|
|
49
63
|
|
|
50
64
|
constructor(attrs: Hash) {
|
|
@@ -57,7 +71,11 @@ export class DomTextElement implements IComponentImplementation {
|
|
|
57
71
|
|
|
58
72
|
stateChanged(changes: Map<string, any>) {
|
|
59
73
|
if (changes.has('text')) {
|
|
60
|
-
this.$
|
|
74
|
+
this.$string = decodeXmlEntities(changes.get('text'));
|
|
61
75
|
}
|
|
62
76
|
}
|
|
77
|
+
|
|
78
|
+
applyStateChanges() {
|
|
79
|
+
this.$element.textContent = this.$string;
|
|
80
|
+
}
|
|
63
81
|
}
|
package/core-web/index.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { CArrmaturaNode } from '../core';
|
|
2
2
|
import { WebPlatform } from './WebPlatform';
|
|
3
|
+
import * as lib from '../lib';
|
|
4
|
+
|
|
5
|
+
import commons from '../commons';
|
|
6
|
+
|
|
7
|
+
import support from './support';
|
|
3
8
|
|
|
4
9
|
export type ArrmaturaOptionsForWeb = ArrmaturaOptions & {
|
|
5
10
|
rootElement?: HTMLElement;
|
|
@@ -7,10 +12,17 @@ export type ArrmaturaOptionsForWeb = ArrmaturaOptions & {
|
|
|
7
12
|
|
|
8
13
|
export function arrmatura(
|
|
9
14
|
template: string,
|
|
10
|
-
{ rootElement, pipes, functions = pipes, types, resources }: ArrmaturaOptionsForWeb & { pipes: Hash<Pipe> }
|
|
15
|
+
{ rootElement, pipes, functions = pipes, types = [], resources }: ArrmaturaOptionsForWeb & { pipes: Hash<Pipe> }
|
|
11
16
|
) {
|
|
12
|
-
const
|
|
17
|
+
const options: ArrmaturaOptions = {
|
|
18
|
+
functions: { ...lib, ...support(arrmatura), ...functions },
|
|
19
|
+
types: [...commons, ...types],
|
|
20
|
+
resources,
|
|
21
|
+
};
|
|
22
|
+
const node = new CArrmaturaNode(template, options, new WebPlatform(rootElement));
|
|
13
23
|
node.launch();
|
|
14
24
|
}
|
|
15
25
|
|
|
26
|
+
arrmatura.lib = lib;
|
|
27
|
+
|
|
16
28
|
Object.defineProperty(window, 'arrmatura', { value: arrmatura });
|
package/core-web/reflow.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DomElement } from './elements';
|
|
2
|
+
import type { DomNode } from './type';
|
|
2
3
|
|
|
3
4
|
function appendElt(e: DomNode, p: DomNode | HTMLElement, cursor?: DomNode): DomNode {
|
|
4
5
|
const before = cursor ? cursor.nextSibling : p.firstChild;
|
|
@@ -18,6 +19,7 @@ export function reflow($: IComponent, parent: DomNode | HTMLElement, cursor?: Do
|
|
|
18
19
|
const e = p.$impl.$element as DomNode;
|
|
19
20
|
if (e) {
|
|
20
21
|
reflow(p, e);
|
|
22
|
+
(p.$impl as DomElement).applyStateChanges();
|
|
21
23
|
cursor = appendElt(e, parent, cursor);
|
|
22
24
|
} else {
|
|
23
25
|
cursor = reflow(p, parent, cursor);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const showCounts = (counts: Obj, nicNema = '⭕', neZnojdzeno = '⭕', loading = '…') => {
|
|
2
|
+
if (!counts) {
|
|
3
|
+
return loading;
|
|
4
|
+
}
|
|
5
|
+
const { total, actual } = counts;
|
|
6
|
+
if (!total) {
|
|
7
|
+
return nicNema;
|
|
8
|
+
}
|
|
9
|
+
if (!actual) {
|
|
10
|
+
return neZnojdzeno;
|
|
11
|
+
}
|
|
12
|
+
if (actual === total) {
|
|
13
|
+
return total;
|
|
14
|
+
}
|
|
15
|
+
return actual + ' / ' + total;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default (arrmatura: (m: string, opts: unknown) => void) => ({
|
|
19
|
+
showCounts,
|
|
20
|
+
|
|
21
|
+
sandbox: (markup: string) =>
|
|
22
|
+
function () {
|
|
23
|
+
try {
|
|
24
|
+
arrmatura(`<div>${markup}</div>`, { rootElement: this.$element });
|
|
25
|
+
} catch (err) {}
|
|
26
|
+
},
|
|
27
|
+
});
|