cogsbox-state 0.5.475-canary.4 → 0.5.475-canary.6
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/package.json +1 -1
- package/src/CogsState.tsx +34 -22
- package/src/Components.tsx +26 -14
package/package.json
CHANGED
package/src/CogsState.tsx
CHANGED
|
@@ -230,9 +230,18 @@ export type EndType<
|
|
|
230
230
|
$update: UpdateType<T>;
|
|
231
231
|
$_path: string[];
|
|
232
232
|
$_stateKey: string;
|
|
233
|
-
$isolate:
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
$isolate: {
|
|
234
|
+
// Overload 1: Just the render function (Default behavior)
|
|
235
|
+
(
|
|
236
|
+
renderFn: (state: StateObject<T, TPlugins>) => React.ReactNode
|
|
237
|
+
): JSX.Element;
|
|
238
|
+
|
|
239
|
+
// Overload 2: Dependencies array + render function (Optimized behavior)
|
|
240
|
+
(
|
|
241
|
+
dependencies: any[],
|
|
242
|
+
renderFn: (state: StateObject<T, TPlugins>) => React.ReactNode
|
|
243
|
+
): JSX.Element;
|
|
244
|
+
};
|
|
236
245
|
$formElement: (
|
|
237
246
|
control: FormControl<T>,
|
|
238
247
|
opts?: PerPathFormOptsType<T, TPlugins>
|
|
@@ -314,6 +323,7 @@ export type StateObject<
|
|
|
314
323
|
};
|
|
315
324
|
|
|
316
325
|
export type CogsUpdate<T extends unknown> = UpdateType<T>;
|
|
326
|
+
|
|
317
327
|
type EffectiveSetStateArg<
|
|
318
328
|
T,
|
|
319
329
|
UpdateType extends 'update' | 'insert' | 'cut',
|
|
@@ -349,7 +359,6 @@ export type UpdateTypeDetail = {
|
|
|
349
359
|
oldValue: any;
|
|
350
360
|
newValue: any;
|
|
351
361
|
userId?: number;
|
|
352
|
-
|
|
353
362
|
itemId?: string;
|
|
354
363
|
insertAfterId?: string;
|
|
355
364
|
metaData?: Record<string, any>;
|
|
@@ -511,14 +520,12 @@ const {
|
|
|
511
520
|
addPathComponent,
|
|
512
521
|
clearSelectedIndexesForState,
|
|
513
522
|
addStateLog,
|
|
514
|
-
setSyncInfo,
|
|
515
523
|
clearSelectedIndex,
|
|
516
524
|
getSyncInfo,
|
|
517
525
|
notifyPathSubscribers,
|
|
518
526
|
getPluginMetaDataMap,
|
|
519
527
|
setPluginMetaData,
|
|
520
528
|
removePluginMetaData,
|
|
521
|
-
// Note: The old functions are no longer imported under their original names
|
|
522
529
|
} = getGlobalStore.getState();
|
|
523
530
|
|
|
524
531
|
const { notifyUpdate } = pluginStore.getState();
|
|
@@ -1069,9 +1076,7 @@ let isFlushScheduled = false;
|
|
|
1069
1076
|
function scheduleFlush() {
|
|
1070
1077
|
if (!isFlushScheduled) {
|
|
1071
1078
|
isFlushScheduled = true;
|
|
1072
|
-
console.log('Scheduling flush');
|
|
1073
1079
|
queueMicrotask(() => {
|
|
1074
|
-
console.log('Actually flushing');
|
|
1075
1080
|
flushQueue();
|
|
1076
1081
|
});
|
|
1077
1082
|
}
|
|
@@ -2764,7 +2769,7 @@ function createProxyHandler<
|
|
|
2764
2769
|
if (prop === '$cut') {
|
|
2765
2770
|
return (index?: number, options?: { waitForSync?: boolean }) => {
|
|
2766
2771
|
const shadowMeta = getShadowMetadata(stateKey, path);
|
|
2767
|
-
|
|
2772
|
+
|
|
2768
2773
|
if (!shadowMeta?.arrayKeys || shadowMeta.arrayKeys.length === 0)
|
|
2769
2774
|
return;
|
|
2770
2775
|
|
|
@@ -2775,12 +2780,8 @@ function createProxyHandler<
|
|
|
2775
2780
|
? index
|
|
2776
2781
|
: shadowMeta.arrayKeys.length - 1;
|
|
2777
2782
|
|
|
2778
|
-
console.log('indexToCut ->>>>>>>>>>>>>>>>', indexToCut);
|
|
2779
|
-
|
|
2780
2783
|
const idToCut = shadowMeta.arrayKeys[indexToCut];
|
|
2781
2784
|
if (!idToCut) return;
|
|
2782
|
-
console.log('idToCut ->>>>>>>>>>>>>>>>', idToCut);
|
|
2783
|
-
|
|
2784
2785
|
effectiveSetState(null, [...path, idToCut], {
|
|
2785
2786
|
updateType: 'cut',
|
|
2786
2787
|
});
|
|
@@ -3011,7 +3012,6 @@ function createProxyHandler<
|
|
|
3011
3012
|
getPluginMetaDataMap(stateKey, path)?.get(pluginName);
|
|
3012
3013
|
}
|
|
3013
3014
|
if (prop === '$addPluginMetaData') {
|
|
3014
|
-
console.log('$addPluginMetaDat');
|
|
3015
3015
|
return (pluginName: string, data: Record<string, any>) =>
|
|
3016
3016
|
setPluginMetaData(stateKey, path, pluginName, data);
|
|
3017
3017
|
}
|
|
@@ -3078,12 +3078,6 @@ function createProxyHandler<
|
|
|
3078
3078
|
},
|
|
3079
3079
|
metaData?: Record<string, any>
|
|
3080
3080
|
) => {
|
|
3081
|
-
console.log(
|
|
3082
|
-
'getGlobalStore',
|
|
3083
|
-
getGlobalStore
|
|
3084
|
-
.getState()
|
|
3085
|
-
.getShadowMetadata(stateKey, operation.path)
|
|
3086
|
-
);
|
|
3087
3081
|
let index: number | undefined;
|
|
3088
3082
|
if (
|
|
3089
3083
|
operation.insertAfterId &&
|
|
@@ -3269,11 +3263,29 @@ function createProxyHandler<
|
|
|
3269
3263
|
};
|
|
3270
3264
|
}
|
|
3271
3265
|
if (prop === '$isolate') {
|
|
3272
|
-
|
|
3266
|
+
// We accept (renderFn) OR (deps, renderFn)
|
|
3267
|
+
return (
|
|
3268
|
+
arg1: any[] | ((state: any) => React.ReactNode),
|
|
3269
|
+
arg2?: (state: any) => React.ReactNode
|
|
3270
|
+
) => {
|
|
3271
|
+
// Check if the first argument is the dependency array
|
|
3272
|
+
const hasDependencies = Array.isArray(arg1);
|
|
3273
|
+
|
|
3274
|
+
// Normalize arguments
|
|
3275
|
+
const dependencies = hasDependencies ? arg1 : undefined;
|
|
3276
|
+
const renderFn = hasDependencies ? arg2 : arg1;
|
|
3277
|
+
|
|
3278
|
+
if (!renderFn || typeof renderFn !== 'function') {
|
|
3279
|
+
throw new Error(
|
|
3280
|
+
'CogsState: $isolate requires a render function.'
|
|
3281
|
+
);
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3273
3284
|
return (
|
|
3274
3285
|
<IsolatedComponentWrapper
|
|
3275
3286
|
stateKey={stateKey}
|
|
3276
|
-
path={path}
|
|
3287
|
+
path={path} // The path of the node calling $isolate (e.g. "form")
|
|
3288
|
+
dependencies={dependencies} // Pass the specific parts to watch
|
|
3277
3289
|
rebuildStateShape={rebuildStateShape}
|
|
3278
3290
|
renderFn={renderFn}
|
|
3279
3291
|
/>
|
package/src/Components.tsx
CHANGED
|
@@ -633,36 +633,49 @@ const useImageLoaded = (ref: RefObject<HTMLElement>): boolean => {
|
|
|
633
633
|
};
|
|
634
634
|
// Components.tsx
|
|
635
635
|
|
|
636
|
-
// Generic isolated component wrapper
|
|
637
636
|
export function IsolatedComponentWrapper({
|
|
638
637
|
stateKey,
|
|
639
|
-
path,
|
|
638
|
+
path, // The path of the parent node (e.g. ['form'])
|
|
639
|
+
dependencies, // NEW: Optional array of Proxy objects or path arrays
|
|
640
640
|
rebuildStateShape,
|
|
641
641
|
renderFn,
|
|
642
642
|
}: {
|
|
643
643
|
stateKey: string;
|
|
644
644
|
path: string[];
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
componentId: string;
|
|
648
|
-
meta?: any;
|
|
649
|
-
}) => any;
|
|
645
|
+
dependencies?: any[]; // The explicit list of dependencies
|
|
646
|
+
rebuildStateShape: (options: any) => any;
|
|
650
647
|
renderFn: (state: any) => React.ReactNode;
|
|
651
648
|
}) {
|
|
652
649
|
const [componentId] = useState(() => uuidv4());
|
|
653
650
|
const [, forceUpdate] = useState({});
|
|
654
651
|
|
|
655
|
-
const stateKeyPathKey = [stateKey, ...path].join('.');
|
|
656
652
|
useRegisterComponent(stateKey, componentId, forceUpdate);
|
|
657
653
|
|
|
654
|
+
const pathsToSubscribe = useMemo(() => {
|
|
655
|
+
if (dependencies && dependencies.length > 0) {
|
|
656
|
+
return dependencies.map((dep) => {
|
|
657
|
+
return [stateKey, ...dep.$_path].join('.');
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
return [[stateKey, ...path].join('.')];
|
|
662
|
+
}, [stateKey, path, dependencies]);
|
|
663
|
+
|
|
664
|
+
// 2. Subscribe to ALL calculated paths
|
|
658
665
|
useEffect(() => {
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
666
|
+
const store = getGlobalStore.getState();
|
|
667
|
+
|
|
668
|
+
// Create an array of unsubscribe functions
|
|
669
|
+
const unsubs = pathsToSubscribe.map((fullPathKey) => {
|
|
670
|
+
return store.subscribeToPath(fullPathKey, () => {
|
|
662
671
|
forceUpdate({});
|
|
663
672
|
});
|
|
664
|
-
|
|
665
|
-
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
return () => {
|
|
676
|
+
unsubs.forEach((unsub) => unsub());
|
|
677
|
+
};
|
|
678
|
+
}, [pathsToSubscribe]);
|
|
666
679
|
|
|
667
680
|
const baseState = rebuildStateShape({
|
|
668
681
|
path: path,
|
|
@@ -672,7 +685,6 @@ export function IsolatedComponentWrapper({
|
|
|
672
685
|
|
|
673
686
|
return <>{renderFn(baseState)}</>;
|
|
674
687
|
}
|
|
675
|
-
|
|
676
688
|
// 1. Define the MINIMAL props needed.
|
|
677
689
|
type PluginWrapperProps = {
|
|
678
690
|
children: React.ReactNode;
|