@snowcone-app/ui 0.4.8 → 0.4.9
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/CHANGELOG.md +9 -0
- package/dist/index.cjs +25 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +25 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/patterns/RealtimeProvider.tsx +73 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snowcone-app/ui",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"description": "React components for merchandise visualization and customization",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"react-instantsearch": "^7.15.5",
|
|
104
104
|
"react-zoom-pan-pinch": "^3.6.4",
|
|
105
105
|
"tailwind-merge": "^3.0.0",
|
|
106
|
-
"@snowcone-app/sdk": "0.20.
|
|
106
|
+
"@snowcone-app/sdk": "0.20.2"
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
109
|
"@chromatic-com/storybook": "^4.1.2",
|
|
@@ -127,6 +127,26 @@ export interface RealtimeContextValue {
|
|
|
127
127
|
*/
|
|
128
128
|
updatePlacementSettings: (settings: Record<string, { scaleMode?: 'fill' | 'fit'; tiles?: number; alignment?: string }>) => boolean;
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Declare spread-mode crop geometry (ADR-0060) for canvases that run
|
|
132
|
+
* combined spread/group artboards: artboard name → artboard dims + piece
|
|
133
|
+
* rects keyed by the product's placement labels. Sent on the realtime
|
|
134
|
+
* config (re-sent when it changes) so the server can slice each rendered
|
|
135
|
+
* spread canvas_state into per-placement images. Pass undefined to clear.
|
|
136
|
+
*/
|
|
137
|
+
setSpreadCrops: (
|
|
138
|
+
crops:
|
|
139
|
+
| Record<
|
|
140
|
+
string,
|
|
141
|
+
{
|
|
142
|
+
width: number;
|
|
143
|
+
height: number;
|
|
144
|
+
pieces: Array<{ placement: string; x: number; y: number; width: number; height: number }>;
|
|
145
|
+
}
|
|
146
|
+
>
|
|
147
|
+
| undefined
|
|
148
|
+
) => void;
|
|
149
|
+
|
|
130
150
|
// PERFORMANCE: Direct access without state updates
|
|
131
151
|
getMockupResultsImmediate: () => MockupResult[];
|
|
132
152
|
|
|
@@ -310,6 +330,21 @@ export function RealtimeProvider({
|
|
|
310
330
|
// Track last sent variantId to detect when we need to re-send config
|
|
311
331
|
const lastSentVariantIdRef = useRef<string | null>(null);
|
|
312
332
|
const lastSentBgRef = useRef<string | undefined>(undefined);
|
|
333
|
+
// Spread crop geometry (ADR-0060) declared via setSpreadCrops. Ref holds
|
|
334
|
+
// the payload; the version state re-runs the config effect on change.
|
|
335
|
+
const spreadCropsRef = useRef<
|
|
336
|
+
| Record<
|
|
337
|
+
string,
|
|
338
|
+
{
|
|
339
|
+
width: number;
|
|
340
|
+
height: number;
|
|
341
|
+
pieces: Array<{ placement: string; x: number; y: number; width: number; height: number }>;
|
|
342
|
+
}
|
|
343
|
+
>
|
|
344
|
+
| undefined
|
|
345
|
+
>(undefined);
|
|
346
|
+
const [spreadCropsVersion, setSpreadCropsVersion] = useState(0);
|
|
347
|
+
const lastSentSpreadCropsRef = useRef<string>("null");
|
|
313
348
|
|
|
314
349
|
// Track last sent colors to prevent duplicates
|
|
315
350
|
const lastSentColorsRef = useRef<Record<string, string>>({});
|
|
@@ -583,6 +618,7 @@ export function RealtimeProvider({
|
|
|
583
618
|
configSentRef.current = false;
|
|
584
619
|
lastSentVariantIdRef.current = null;
|
|
585
620
|
lastSentBgRef.current = undefined;
|
|
621
|
+
lastSentSpreadCropsRef.current = "null";
|
|
586
622
|
lastSentColorsRef.current = {};
|
|
587
623
|
};
|
|
588
624
|
}
|
|
@@ -619,8 +655,12 @@ export function RealtimeProvider({
|
|
|
619
655
|
lastSentVariantIdRef.current !== variantId;
|
|
620
656
|
// 3. Background changed (theme flip swaps the MockupBackground hex)
|
|
621
657
|
const bgChanged = configSentRef.current && lastSentBgRef.current !== mockupBg;
|
|
658
|
+
// 4. Spread crop geometry changed (spread-mode editor mounted/unmounted)
|
|
659
|
+
const spreadCropsJson = JSON.stringify(spreadCropsRef.current ?? null);
|
|
660
|
+
const spreadCropsChanged =
|
|
661
|
+
configSentRef.current && lastSentSpreadCropsRef.current !== spreadCropsJson;
|
|
622
662
|
|
|
623
|
-
if (!isFirstSend && !variantChanged && !bgChanged) {
|
|
663
|
+
if (!isFirstSend && !variantChanged && !bgChanged && !spreadCropsChanged) {
|
|
624
664
|
return; // Nothing changed, skip
|
|
625
665
|
}
|
|
626
666
|
|
|
@@ -646,6 +686,7 @@ export function RealtimeProvider({
|
|
|
646
686
|
shop: shop as string,
|
|
647
687
|
width: mockupWidth,
|
|
648
688
|
...(mockupBg ? { bg: mockupBg } : {}),
|
|
689
|
+
...(spreadCropsRef.current ? { spreadCrops: spreadCropsRef.current } : {}),
|
|
649
690
|
placementSettings: { ...placementSettingsOverridesRef.current },
|
|
650
691
|
}
|
|
651
692
|
: {
|
|
@@ -656,6 +697,7 @@ export function RealtimeProvider({
|
|
|
656
697
|
seal: "bypass-sig-for-k6-load-test",
|
|
657
698
|
width: mockupWidth,
|
|
658
699
|
...(mockupBg ? { bg: mockupBg } : {}),
|
|
700
|
+
...(spreadCropsRef.current ? { spreadCrops: spreadCropsRef.current } : {}),
|
|
659
701
|
placementSettings: { ...placementSettingsOverridesRef.current },
|
|
660
702
|
};
|
|
661
703
|
|
|
@@ -673,6 +715,7 @@ export function RealtimeProvider({
|
|
|
673
715
|
configSentRef.current = true;
|
|
674
716
|
lastSentVariantIdRef.current = variantId;
|
|
675
717
|
lastSentBgRef.current = mockupBg;
|
|
718
|
+
lastSentSpreadCropsRef.current = spreadCropsJson;
|
|
676
719
|
|
|
677
720
|
// Send default colors for color placements
|
|
678
721
|
setTimeout(() => {
|
|
@@ -694,6 +737,7 @@ export function RealtimeProvider({
|
|
|
694
737
|
sendColorBlobTracked,
|
|
695
738
|
mockupWidth,
|
|
696
739
|
mockupBg,
|
|
740
|
+
spreadCropsVersion,
|
|
697
741
|
]);
|
|
698
742
|
|
|
699
743
|
// Watch for color placement changes
|
|
@@ -737,6 +781,32 @@ export function RealtimeProvider({
|
|
|
737
781
|
[updatePlacementSettingsRaw]
|
|
738
782
|
);
|
|
739
783
|
|
|
784
|
+
// Declare spread crop geometry (ADR-0060). Stored in a ref; bumping the
|
|
785
|
+
// version state re-runs the config effect, which re-sends the config when
|
|
786
|
+
// the serialized geometry actually changed.
|
|
787
|
+
const setSpreadCrops = useCallback(
|
|
788
|
+
(
|
|
789
|
+
crops:
|
|
790
|
+
| Record<
|
|
791
|
+
string,
|
|
792
|
+
{
|
|
793
|
+
width: number;
|
|
794
|
+
height: number;
|
|
795
|
+
pieces: Array<{ placement: string; x: number; y: number; width: number; height: number }>;
|
|
796
|
+
}
|
|
797
|
+
>
|
|
798
|
+
| undefined
|
|
799
|
+
) => {
|
|
800
|
+
const next = crops && Object.keys(crops).length > 0 ? crops : undefined;
|
|
801
|
+
if (JSON.stringify(next ?? null) === JSON.stringify(spreadCropsRef.current ?? null)) {
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
spreadCropsRef.current = next;
|
|
805
|
+
setSpreadCropsVersion((v) => v + 1);
|
|
806
|
+
},
|
|
807
|
+
[]
|
|
808
|
+
);
|
|
809
|
+
|
|
740
810
|
const enableRealtime = useCallback(() => {
|
|
741
811
|
setIsEnabled(true);
|
|
742
812
|
}, []);
|
|
@@ -1111,6 +1181,7 @@ export function RealtimeProvider({
|
|
|
1111
1181
|
sendCanvasState,
|
|
1112
1182
|
updateMockupIds: updateMockupIdsRaw,
|
|
1113
1183
|
updatePlacementSettings: updatePlacementSettingsWrapped,
|
|
1184
|
+
setSpreadCrops,
|
|
1114
1185
|
getMockupResultsImmediate: () => mockupResultsRef.current,
|
|
1115
1186
|
subscribeMockupResults: stableSubscribeMockupResults,
|
|
1116
1187
|
subscribeMockupResultById: stableSubscribeMockupResultById,
|
|
@@ -1147,6 +1218,7 @@ export function RealtimeProvider({
|
|
|
1147
1218
|
sendCanvasState,
|
|
1148
1219
|
updateMockupIdsRaw,
|
|
1149
1220
|
updatePlacementSettingsWrapped,
|
|
1221
|
+
setSpreadCrops,
|
|
1150
1222
|
stableSubscribeMockupResults,
|
|
1151
1223
|
stableSubscribeMockupResultById,
|
|
1152
1224
|
notifyPendingExport,
|