cx 26.7.0 → 26.7.2
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/build/ui/Cx.d.ts +2 -0
- package/build/ui/Cx.d.ts.map +1 -1
- package/build/ui/Cx.js +36 -7
- package/build/widgets/DocumentTitle.d.ts.map +1 -1
- package/build/widgets/DocumentTitle.js +2 -0
- package/build/widgets/grid/TreeNode.d.ts +2 -0
- package/build/widgets/grid/TreeNode.d.ts.map +1 -1
- package/dist/manifest.js +822 -822
- package/dist/ui.js +50 -14
- package/dist/widgets.js +1 -0
- package/package.json +1 -1
- package/src/ui/Cx.tsx +416 -386
- package/src/ui/DataProxy.ts +55 -55
- package/src/ui/Rescope.ts +50 -50
- package/src/ui/Restate.tsx +217 -217
- package/src/ui/exprHelpers.ts +96 -96
- package/src/widgets/DocumentTitle.ts +2 -0
- package/src/widgets/Sandbox.ts +104 -104
- package/src/widgets/form/ColorField.scss +112 -112
- package/src/widgets/form/DateTimeField.scss +111 -111
- package/src/widgets/form/LookupField.maps.scss +26 -26
- package/src/widgets/form/MonthField.scss +113 -113
- package/src/widgets/form/Select.scss +104 -104
- package/src/widgets/form/TextField.scss +66 -66
- package/src/widgets/grid/TreeNode.tsx +3 -0
- package/src/widgets/nav/MenuItem.tsx +525 -525
package/dist/ui.js
CHANGED
|
@@ -2107,6 +2107,8 @@ class Cx extends VDOM.Component {
|
|
|
2107
2107
|
deferCounter;
|
|
2108
2108
|
pendingUpdateTimer;
|
|
2109
2109
|
unsubscribeIdleRequest;
|
|
2110
|
+
// 0 when no synchronous setState is in flight; >0 while one is pending (re-entrancy guard for update())
|
|
2111
|
+
stateUpdateDepth = 0;
|
|
2110
2112
|
constructor(props) {
|
|
2111
2113
|
super(props);
|
|
2112
2114
|
if (props.instance) {
|
|
@@ -2132,6 +2134,7 @@ class Cx extends VDOM.Component {
|
|
|
2132
2134
|
this.unsubscribe = this.store.subscribe(this.update.bind(this));
|
|
2133
2135
|
this.state.data = this.store.getData();
|
|
2134
2136
|
}
|
|
2137
|
+
this.onStateUpdateCompleted = this.onStateUpdateCompleted.bind(this);
|
|
2135
2138
|
this.flags = {};
|
|
2136
2139
|
this.renderCount = 0;
|
|
2137
2140
|
if (props.onError) this.componentDidCatch = this.componentDidCatchHandler.bind(this);
|
|
@@ -2163,7 +2166,7 @@ class Cx extends VDOM.Component {
|
|
|
2163
2166
|
return this.instance;
|
|
2164
2167
|
}
|
|
2165
2168
|
if (this.widget && this.parentInstance)
|
|
2166
|
-
return (this.instance = this.parentInstance.getDetachedChild(this.widget, 0, this.store));
|
|
2169
|
+
return (this.instance = this.parentInstance.getDetachedChild(this.widget, "0", this.store));
|
|
2167
2170
|
throw new Error("Could not resolve a widget instance in the Cx component.");
|
|
2168
2171
|
}
|
|
2169
2172
|
render() {
|
|
@@ -2192,23 +2195,33 @@ class Cx extends VDOM.Component {
|
|
|
2192
2195
|
let data = this.store.getData();
|
|
2193
2196
|
debug(appDataFlag, data);
|
|
2194
2197
|
if (this.flags.preparing) this.flags.dirty = true;
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
)
|
|
2198
|
+
// Synchronous path (while batching, or for `immediate` instances). At most one setState may be in flight
|
|
2199
|
+
// per Cx: if one is already pending (stateUpdateDepth != 0) skip issuing another. Re-entrant setStates
|
|
2200
|
+
// nested deep -- e.g. a large initial render that writes to the store while it renders -- are what trip
|
|
2201
|
+
// React's "Maximum update depth exceeded"; coalescing them into a single in-flight update avoids that.
|
|
2202
|
+
// The pending update's completion callback re-reads the store and renders again if it changed
|
|
2203
|
+
// (see onStateUpdateCompleted), so no change is dropped.
|
|
2204
|
+
else if (this.props.immediate || isBatchingUpdates()) {
|
|
2205
|
+
if (this.stateUpdateDepth == 0) {
|
|
2206
|
+
this.stateUpdateDepth = 1;
|
|
2207
|
+
notifyBatchedUpdateStarting();
|
|
2208
|
+
this.setState(
|
|
2209
|
+
{
|
|
2210
|
+
data: data,
|
|
2211
|
+
},
|
|
2212
|
+
this.onStateUpdateCompleted,
|
|
2213
|
+
);
|
|
2214
|
+
}
|
|
2203
2215
|
} else {
|
|
2204
|
-
//
|
|
2216
|
+
// standard mode: coalesce sequential store commands into a single deferred update
|
|
2205
2217
|
if (!this.pendingUpdateTimer) {
|
|
2206
2218
|
notifyBatchedUpdateStarting();
|
|
2207
2219
|
this.pendingUpdateTimer = setTimeout(() => {
|
|
2208
2220
|
delete this.pendingUpdateTimer;
|
|
2221
|
+
// read fresh data at fire time so the coalesced update renders the latest store state
|
|
2209
2222
|
this.setState(
|
|
2210
2223
|
{
|
|
2211
|
-
data:
|
|
2224
|
+
data: this.store.getData(),
|
|
2212
2225
|
},
|
|
2213
2226
|
notifyBatchedUpdateCompleted,
|
|
2214
2227
|
);
|
|
@@ -2216,15 +2229,38 @@ class Cx extends VDOM.Component {
|
|
|
2216
2229
|
}
|
|
2217
2230
|
}
|
|
2218
2231
|
}
|
|
2232
|
+
// Completion callback for the synchronous setState above. If the store changed while that update was
|
|
2233
|
+
// rendering -- i.e. the render itself wrote to the store, as happens throughout a large initial render --
|
|
2234
|
+
// render once more with the latest data, keeping this callback armed; otherwise the burst has settled, so
|
|
2235
|
+
// clear the in-flight flag and report completion. Re-arming coalesces until the store reaches a fixpoint;
|
|
2236
|
+
// a genuinely non-converging update loop is still caught by React's own max-update-depth guard.
|
|
2237
|
+
onStateUpdateCompleted() {
|
|
2238
|
+
let latestData = this.store.getData();
|
|
2239
|
+
if (this.state.data === latestData) {
|
|
2240
|
+
this.stateUpdateDepth = 0;
|
|
2241
|
+
notifyBatchedUpdateCompleted();
|
|
2242
|
+
} else {
|
|
2243
|
+
this.stateUpdateDepth++;
|
|
2244
|
+
this.setState(
|
|
2245
|
+
{
|
|
2246
|
+
data: latestData,
|
|
2247
|
+
},
|
|
2248
|
+
this.onStateUpdateCompleted,
|
|
2249
|
+
);
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2219
2252
|
waitForIdle() {
|
|
2220
2253
|
if (!this.props.deferredUntilIdle) return;
|
|
2221
2254
|
if (this.unsubscribeIdleRequest) this.unsubscribeIdleRequest();
|
|
2222
2255
|
let token = ++this.deferCounter;
|
|
2223
2256
|
this.unsubscribeIdleRequest = onIdleCallback(
|
|
2224
2257
|
() => {
|
|
2225
|
-
this.setState(
|
|
2226
|
-
|
|
2227
|
-
|
|
2258
|
+
this.setState(
|
|
2259
|
+
{
|
|
2260
|
+
deferToken: token,
|
|
2261
|
+
},
|
|
2262
|
+
this.onStateUpdateCompleted,
|
|
2263
|
+
);
|
|
2228
2264
|
},
|
|
2229
2265
|
{
|
|
2230
2266
|
timeout: this.props.idleTimeout || 30000,
|
package/dist/widgets.js
CHANGED
|
@@ -1124,6 +1124,7 @@ class DocumentTitle extends Widget {
|
|
|
1124
1124
|
super.explore(context, instance);
|
|
1125
1125
|
}
|
|
1126
1126
|
prepare(context, instance) {
|
|
1127
|
+
if (typeof document == "undefined") return;
|
|
1127
1128
|
if (context.documentTitle.activeInstance == instance) document.title = context.documentTitle.title;
|
|
1128
1129
|
}
|
|
1129
1130
|
render() {
|