@fluffjs/fluff 0.2.4 → 0.3.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/bundle.min.js +1 -0
- package/decorators/Component.d.ts +0 -8
- package/decorators/Component.js +0 -11
- package/decorators/Input.d.ts +1 -1
- package/decorators/InputOutputHelper.d.ts +2 -1
- package/decorators/InputOutputHelper.js +3 -1
- package/decorators/Output.d.ts +1 -1
- package/decorators/Pipe.d.ts +1 -0
- package/decorators/Pipe.js +1 -1
- package/decorators/Reactive.d.ts +2 -1
- package/decorators/Reactive.js +1 -1
- package/index.d.ts +2 -1
- package/index.js +1 -1
- package/interfaces/FluffHostElement.d.ts +13 -3
- package/interfaces/ReactiveOptions.d.ts +6 -0
- package/interfaces/ReactiveOptions.js +1 -0
- package/package.json +1 -1
- package/runtime/FluffBase.d.ts +11 -1
- package/runtime/FluffBase.js +50 -17
- package/runtime/FluffElementImpl.d.ts +9 -21
- package/runtime/FluffElementImpl.js +48 -149
- package/runtime/ForController.js +1 -2
- package/runtime/IfController.js +1 -2
- package/runtime/MarkerConfigGuards.d.ts +0 -2
- package/runtime/MarkerConfigGuards.js +0 -3
- package/runtime/MarkerController.d.ts +1 -9
- package/runtime/MarkerController.js +28 -144
- package/runtime/MarkerManager.d.ts +2 -1
- package/runtime/MarkerManager.js +1 -2
- package/runtime/MarkerManagerInterface.d.ts +3 -1
- package/runtime/SwitchController.js +1 -2
- package/runtime/TextController.d.ts +0 -1
- package/runtime/TextController.js +5 -19
- package/runtime/tests/TestChildTasksListComponent.js +2 -2
- package/runtime/tests/TestForComponent.js +2 -2
- package/runtime/tests/TestForReinsertBindsInputParentComponent.js +2 -2
- package/runtime/tests/TestForTextMarkerCollisionNoTrackParentComponent.js +2 -2
- package/runtime/tests/TestForTextMarkerCollisionParentComponent.js +2 -2
- package/runtime/tests/TestForUnsubscribeNestedParentComponent.js +2 -2
- package/runtime/tests/TestGetterReactivityComponent.js +2 -2
- package/runtime/tests/TestHarness.d.ts +9 -0
- package/runtime/tests/TestHarness.js +29 -0
- package/runtime/tests/TestIfReinsertBindsInputChildComponent.js +2 -2
- package/runtime/tests/TestIfReinsertBindsInputParentComponent.js +2 -2
- package/runtime/tests/TestIfUnsubscribeNestedParentComponent.js +2 -2
- package/runtime/tests/TestInterpolationNestedPropertyComponentBase.js +2 -2
- package/runtime/tests/TestLateDefineForComponent.js +2 -2
- package/runtime/tests/TestNullInputTextComponent.js +2 -2
- package/runtime/tests/TestOutputBindingParentComponent.js +2 -2
- package/runtime/tests/TestParentBindsTasksComponent.js +2 -2
- package/runtime/tests/TestSwitchReinsertBindsInputChildComponent.js +2 -2
- package/runtime/tests/TestSwitchReinsertBindsInputParentComponent.js +2 -2
- package/runtime/tests/TestSwitchUnsubscribeNestedParentComponent.js +2 -2
- package/runtime/tests/TestTemplateNestedMarkersComponent.js +2 -2
- package/runtime/tests/TestUnsubscribeNestedGrandchildComponent.js +2 -2
- package/runtime/tests/createPipeUnwrapTestComponent.js +2 -2
- package/runtime/tests/createTestInterpolationPipeComponent.js +2 -2
- package/runtime/tests/createTestInterpolationPipeWithArgsComponent.js +2 -2
- package/utils/Property.d.ts +8 -2
- package/utils/Property.js +48 -8
- package/utils/DomUtils.d.ts +0 -3
- package/utils/DomUtils.js +0 -6
|
@@ -11,9 +11,9 @@ export class TestParentBindsTasksComponent extends FluffElement {
|
|
|
11
11
|
<test-child-tasks-list x-fluff-component="" data-lid="l0"></test-child-tasks-list>
|
|
12
12
|
</template>
|
|
13
13
|
`;
|
|
14
|
-
this.__setMarkerConfigs(
|
|
14
|
+
this.__setMarkerConfigs([
|
|
15
15
|
[0, { type: 'for', iterator: 'child', iterableExprId: 0, deps: ['childList'], hasEmpty: false }]
|
|
16
|
-
])
|
|
16
|
+
]);
|
|
17
17
|
}
|
|
18
18
|
__setupBindings() {
|
|
19
19
|
this.__initializeMarkers(MarkerManager);
|
|
@@ -28,9 +28,9 @@ export class TestSwitchReinsertBindsInputChildComponent extends FluffElement {
|
|
|
28
28
|
this.__getShadowRoot().innerHTML = `
|
|
29
29
|
<div class="total"><!--fluff:text:0--><!--/fluff:text:0--></div>
|
|
30
30
|
`;
|
|
31
|
-
this.__setMarkerConfigs(
|
|
31
|
+
this.__setMarkerConfigs([
|
|
32
32
|
[0, { type: 'text', exprId: 4, deps: ['stats'], pipes: [] }]
|
|
33
|
-
])
|
|
33
|
+
]);
|
|
34
34
|
}
|
|
35
35
|
__setupBindings() {
|
|
36
36
|
this.__initializeMarkers(MarkerManager);
|
|
@@ -42,7 +42,7 @@ export class TestSwitchReinsertBindsInputParentComponent extends FluffElement {
|
|
|
42
42
|
<test-switch-reinsert-binds-input-child x-fluff-component data-lid="l1"></test-switch-reinsert-binds-input-child>
|
|
43
43
|
</template>
|
|
44
44
|
`;
|
|
45
|
-
this.__setMarkerConfigs(
|
|
45
|
+
this.__setMarkerConfigs([
|
|
46
46
|
[
|
|
47
47
|
0, {
|
|
48
48
|
type: 'switch', expressionExprId: 0, deps: ['mode'], cases: [
|
|
@@ -51,7 +51,7 @@ export class TestSwitchReinsertBindsInputParentComponent extends FluffElement {
|
|
|
51
51
|
]
|
|
52
52
|
}
|
|
53
53
|
]
|
|
54
|
-
])
|
|
54
|
+
]);
|
|
55
55
|
const bindings = {
|
|
56
56
|
l0: [{ n: 'stats', b: 'property', e: 3, d: ['stats'] }],
|
|
57
57
|
l1: [{ n: 'stats', b: 'property', e: 3, d: ['stats'] }]
|
|
@@ -20,7 +20,7 @@ export class TestSwitchUnsubscribeNestedParentComponent extends TestUnsubscribeN
|
|
|
20
20
|
<div class="placeholder">placeholder</div>
|
|
21
21
|
</template>
|
|
22
22
|
`;
|
|
23
|
-
this.__setMarkerConfigs(
|
|
23
|
+
this.__setMarkerConfigs([
|
|
24
24
|
[
|
|
25
25
|
0, {
|
|
26
26
|
type: 'switch', expressionExprId: 0, deps: ['mode'], cases: [
|
|
@@ -29,7 +29,7 @@ export class TestSwitchUnsubscribeNestedParentComponent extends TestUnsubscribeN
|
|
|
29
29
|
]
|
|
30
30
|
}
|
|
31
31
|
]
|
|
32
|
-
])
|
|
32
|
+
]);
|
|
33
33
|
const bindings = {
|
|
34
34
|
l0: [{ n: 'stats', b: 'property', e: 3, d: ['stats'] }]
|
|
35
35
|
};
|
|
@@ -27,10 +27,10 @@ export class TestTemplateNestedMarkersComponent extends FluffElement {
|
|
|
27
27
|
<div class="fallback">Fallback</div>
|
|
28
28
|
</template>
|
|
29
29
|
`;
|
|
30
|
-
this.__setMarkerConfigs(
|
|
30
|
+
this.__setMarkerConfigs([
|
|
31
31
|
[0, { type: 'if', branches: [{ exprId: 0, deps: ['show'] }, { exprId: undefined, deps: [] }] }],
|
|
32
32
|
[1, { type: 'text', exprId: 1, deps: ['text'], pipes: [] }]
|
|
33
|
-
])
|
|
33
|
+
]);
|
|
34
34
|
}
|
|
35
35
|
__setupBindings() {
|
|
36
36
|
this.__initializeMarkers(MarkerManager);
|
|
@@ -28,9 +28,9 @@ export class TestUnsubscribeNestedGrandchildComponent extends FluffElement {
|
|
|
28
28
|
this.__getShadowRoot().innerHTML = `
|
|
29
29
|
<div class="total"><!--fluff:text:0--><!--/fluff:text:0--></div>
|
|
30
30
|
`;
|
|
31
|
-
this.__setMarkerConfigs(
|
|
31
|
+
this.__setMarkerConfigs([
|
|
32
32
|
[0, { type: 'text', exprId: 5, deps: ['stats'], pipes: [] }]
|
|
33
|
-
])
|
|
33
|
+
]);
|
|
34
34
|
}
|
|
35
35
|
__setupBindings() {
|
|
36
36
|
this.__initializeMarkers(MarkerManager);
|
|
@@ -19,9 +19,9 @@ export function createPipeUnwrapTestComponent(state) {
|
|
|
19
19
|
};
|
|
20
20
|
__render() {
|
|
21
21
|
this.__getShadowRoot().innerHTML = '<span><!--fluff:text:0--><!--/fluff:text:0--></span>';
|
|
22
|
-
this.__setMarkerConfigs(
|
|
22
|
+
this.__setMarkerConfigs([
|
|
23
23
|
[0, { type: 'text', exprId: 0, deps: ['testProp'], pipes: [{ name: 'capture', argExprIds: [] }] }]
|
|
24
|
-
])
|
|
24
|
+
]);
|
|
25
25
|
}
|
|
26
26
|
__setupBindings() {
|
|
27
27
|
this.__initializeMarkers(MarkerManager);
|
|
@@ -22,9 +22,9 @@ export function createTestInterpolationPipeComponent() {
|
|
|
22
22
|
};
|
|
23
23
|
__render() {
|
|
24
24
|
this.__getShadowRoot().innerHTML = '<span><!--fluff:text:0--><!--/fluff:text:0--></span>';
|
|
25
|
-
this.__setMarkerConfigs(
|
|
25
|
+
this.__setMarkerConfigs([
|
|
26
26
|
[0, { type: 'text', exprId: 0, deps: ['message'], pipes: [{ name: 'uppercase', argExprIds: [] }] }]
|
|
27
|
-
])
|
|
27
|
+
]);
|
|
28
28
|
}
|
|
29
29
|
__setupBindings() {
|
|
30
30
|
this.__initializeMarkers(MarkerManager);
|
|
@@ -22,9 +22,9 @@ export function createTestInterpolationPipeWithArgsComponent() {
|
|
|
22
22
|
};
|
|
23
23
|
__render() {
|
|
24
24
|
this.__getShadowRoot().innerHTML = '<span><!--fluff:text:0--><!--/fluff:text:0--></span>';
|
|
25
|
-
this.__setMarkerConfigs(
|
|
25
|
+
this.__setMarkerConfigs([
|
|
26
26
|
[0, { type: 'text', exprId: 0, deps: ['message'], pipes: [{ name: 'truncate', argExprIds: [1] }] }]
|
|
27
|
-
])
|
|
27
|
+
]);
|
|
28
28
|
}
|
|
29
29
|
__setupBindings() {
|
|
30
30
|
this.__initializeMarkers(MarkerManager);
|
package/utils/Property.d.ts
CHANGED
|
@@ -9,12 +9,17 @@ export declare class Property<T> {
|
|
|
9
9
|
private value?;
|
|
10
10
|
private committed;
|
|
11
11
|
private _isChanging;
|
|
12
|
-
private readonly _propName?;
|
|
13
12
|
private _parentProperty?;
|
|
14
13
|
private _parentSubscription?;
|
|
14
|
+
private _commitTriggerSub?;
|
|
15
|
+
private _pendingCommitValue?;
|
|
16
|
+
private _options?;
|
|
15
17
|
constructor(options: {
|
|
16
|
-
initialValue
|
|
18
|
+
initialValue?: T;
|
|
17
19
|
propertyName?: string;
|
|
20
|
+
direction?: Direction;
|
|
21
|
+
commitTrigger?: Property<unknown>;
|
|
22
|
+
linkHandler?: (prop: Property<T>) => void;
|
|
18
23
|
} | T);
|
|
19
24
|
prop(): Property<T> | undefined;
|
|
20
25
|
setValue(val: T | Property<T>, inbound?: boolean, commit?: boolean): void;
|
|
@@ -22,6 +27,7 @@ export declare class Property<T> {
|
|
|
22
27
|
private setValueInternal;
|
|
23
28
|
private pushToParent;
|
|
24
29
|
private clearParentLink;
|
|
30
|
+
setCommitTrigger(trigger: Property<unknown>): void;
|
|
25
31
|
reset(): void;
|
|
26
32
|
triggerChange(direction?: Direction): void;
|
|
27
33
|
subscribe(direction: Direction, cb: (val: T) => void): Subscription;
|
package/utils/Property.js
CHANGED
|
@@ -20,16 +20,19 @@ export class Property {
|
|
|
20
20
|
value;
|
|
21
21
|
committed = true;
|
|
22
22
|
_isChanging = false;
|
|
23
|
-
_propName;
|
|
24
23
|
_parentProperty;
|
|
25
24
|
_parentSubscription;
|
|
25
|
+
_commitTriggerSub;
|
|
26
|
+
_pendingCommitValue;
|
|
27
|
+
_options;
|
|
26
28
|
constructor(options) {
|
|
27
29
|
if (this.isOptionsObject(options)) {
|
|
30
|
+
this._options = options;
|
|
28
31
|
if (options.initialValue !== undefined) {
|
|
29
32
|
this.value = options.initialValue;
|
|
30
33
|
}
|
|
31
|
-
if (options.
|
|
32
|
-
this.
|
|
34
|
+
if (options.commitTrigger !== undefined) {
|
|
35
|
+
this.setCommitTrigger(options.commitTrigger);
|
|
33
36
|
}
|
|
34
37
|
}
|
|
35
38
|
else {
|
|
@@ -41,16 +44,22 @@ export class Property {
|
|
|
41
44
|
}
|
|
42
45
|
setValue(val, inbound = false, commit = true) {
|
|
43
46
|
if (val instanceof Property) {
|
|
47
|
+
const linkHandler = this._options?.linkHandler;
|
|
48
|
+
if (linkHandler) {
|
|
49
|
+
linkHandler(val);
|
|
50
|
+
}
|
|
44
51
|
this.linkToParent(val);
|
|
45
52
|
return;
|
|
46
53
|
}
|
|
47
54
|
if (this._isChanging) {
|
|
48
|
-
|
|
55
|
+
const propName = this._options?.propertyName;
|
|
56
|
+
console.error((propName ? propName + ': ' : '') + 'Binding loop detected: setValue called while change is in progress');
|
|
49
57
|
return;
|
|
50
58
|
}
|
|
51
59
|
const changed = val !== this.value && safeStringify(val) !== safeStringify(this.value);
|
|
52
|
-
if (!changed)
|
|
60
|
+
if (!changed && !(commit && !this.committed)) {
|
|
53
61
|
return;
|
|
62
|
+
}
|
|
54
63
|
this._isChanging = true;
|
|
55
64
|
try {
|
|
56
65
|
this.value = val;
|
|
@@ -62,7 +71,7 @@ export class Property {
|
|
|
62
71
|
this.committed = true;
|
|
63
72
|
this.onInboundChange.emit(val);
|
|
64
73
|
}
|
|
65
|
-
else if (commit
|
|
74
|
+
else if (commit) {
|
|
66
75
|
this.committed = true;
|
|
67
76
|
if (this.value !== undefined) {
|
|
68
77
|
this.onOutboundChange.emit(this.value);
|
|
@@ -83,7 +92,8 @@ export class Property {
|
|
|
83
92
|
root = root._parentProperty;
|
|
84
93
|
}
|
|
85
94
|
this._parentProperty = root;
|
|
86
|
-
this.
|
|
95
|
+
const direction = this._options?.direction ?? Direction.Any;
|
|
96
|
+
this._parentSubscription = root.subscribe(direction, (val) => {
|
|
87
97
|
this.setValueInternal(val, true);
|
|
88
98
|
});
|
|
89
99
|
const currentValue = root.getValue();
|
|
@@ -112,11 +122,22 @@ export class Property {
|
|
|
112
122
|
pushToParent(val) {
|
|
113
123
|
if (!this._parentProperty)
|
|
114
124
|
return;
|
|
125
|
+
const commitTrigger = this._options?.commitTrigger;
|
|
126
|
+
if (commitTrigger) {
|
|
127
|
+
const shouldCommit = Boolean(commitTrigger.getValue());
|
|
128
|
+
if (!shouldCommit) {
|
|
129
|
+
this._pendingCommitValue = { value: val };
|
|
130
|
+
this._parentProperty.setValue(val, false, false);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
this._pendingCommitValue = undefined;
|
|
134
|
+
}
|
|
115
135
|
const sub = this._parentSubscription;
|
|
116
136
|
this._parentSubscription = undefined;
|
|
117
137
|
sub?.unsubscribe();
|
|
118
138
|
this._parentProperty.setValue(val);
|
|
119
|
-
|
|
139
|
+
const direction = this._options?.direction ?? Direction.Any;
|
|
140
|
+
this._parentSubscription = this._parentProperty.subscribe(direction, (v) => {
|
|
120
141
|
this.setValueInternal(v, true);
|
|
121
142
|
});
|
|
122
143
|
}
|
|
@@ -127,6 +148,25 @@ export class Property {
|
|
|
127
148
|
}
|
|
128
149
|
this._parentProperty = undefined;
|
|
129
150
|
}
|
|
151
|
+
setCommitTrigger(trigger) {
|
|
152
|
+
if (this._commitTriggerSub) {
|
|
153
|
+
this._commitTriggerSub.unsubscribe();
|
|
154
|
+
this._commitTriggerSub = undefined;
|
|
155
|
+
}
|
|
156
|
+
this._options ??= {};
|
|
157
|
+
this._options.commitTrigger = trigger;
|
|
158
|
+
this._commitTriggerSub = trigger.onChange.subscribe((val) => {
|
|
159
|
+
if (!val)
|
|
160
|
+
return;
|
|
161
|
+
if (!this._parentProperty)
|
|
162
|
+
return;
|
|
163
|
+
if (!this._pendingCommitValue)
|
|
164
|
+
return;
|
|
165
|
+
const pending = this._pendingCommitValue.value;
|
|
166
|
+
this._pendingCommitValue = undefined;
|
|
167
|
+
this._parentProperty.setValue(pending, false, true);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
130
170
|
reset() {
|
|
131
171
|
this.clearParentLink();
|
|
132
172
|
}
|
package/utils/DomUtils.d.ts
DELETED