@snowcone-app/ui 0.3.0 → 0.4.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/CHANGELOG.md +20 -0
- package/dist/index.cjs +14 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/composed/HeroProductImage.tsx +14 -0
- package/src/patterns/RealtimeProvider.tsx +17 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snowcone-app/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
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.
|
|
106
|
+
"@snowcone-app/sdk": "0.17.0"
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
109
|
"@chromatic-com/storybook": "^4.1.2",
|
|
@@ -1044,6 +1044,20 @@ export const HeroProductImage = memo(function HeroProductImage({
|
|
|
1044
1044
|
/>
|
|
1045
1045
|
)}
|
|
1046
1046
|
|
|
1047
|
+
{/* Server render error badge — the realtime renderer rejected the last
|
|
1048
|
+
render (e.g. asset_not_allowed). The stale image above stays visible
|
|
1049
|
+
on purpose (stale + clearly marked beats blank); the typed code is
|
|
1050
|
+
exposed via data-render-error so agents/tests can assert on it. */}
|
|
1051
|
+
{realtimeContext?.renderError && (
|
|
1052
|
+
<div
|
|
1053
|
+
role="alert"
|
|
1054
|
+
data-render-error={realtimeContext.renderError.code}
|
|
1055
|
+
className="absolute inset-x-0 bottom-0 z-20 bg-red-600/90 text-white text-xs font-medium px-3 py-2 pointer-events-none"
|
|
1056
|
+
>
|
|
1057
|
+
{`Render blocked: ${realtimeContext.renderError.code} — ${realtimeContext.renderError.message}`}
|
|
1058
|
+
</div>
|
|
1059
|
+
)}
|
|
1060
|
+
|
|
1047
1061
|
{/* Previous image — fades out during crossfade */}
|
|
1048
1062
|
{prevUrl && (
|
|
1049
1063
|
<img
|
|
@@ -38,6 +38,7 @@ import React, {
|
|
|
38
38
|
} from "react";
|
|
39
39
|
import { useRealtimeMockup } from "@snowcone-app/sdk/react";
|
|
40
40
|
import { resolveVariantId as resolveVariantIdUtil } from "@snowcone-app/sdk";
|
|
41
|
+
import type { RealtimeRenderError } from "@snowcone-app/sdk";
|
|
41
42
|
import { readEnv } from "../lib/env";
|
|
42
43
|
import { useProductOptional } from "./Product";
|
|
43
44
|
import type { ReactProductContext } from "./Product";
|
|
@@ -69,6 +70,15 @@ export interface RealtimeContextValue {
|
|
|
69
70
|
// Mockup results (use subscriptions for performance-critical components)
|
|
70
71
|
mockupResults: MockupResult[];
|
|
71
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Most recent server render error (stable machine-readable `code` +
|
|
75
|
+
* human message, e.g. `{code: 'asset_not_allowed', ...}`). Cleared when a
|
|
76
|
+
* later render succeeds. While set, `mockupResults` still holds the LAST
|
|
77
|
+
* GOOD renders — surface the error visibly (badge the stale mockup) rather
|
|
78
|
+
* than blanking it or logging console-only.
|
|
79
|
+
*/
|
|
80
|
+
renderError: RealtimeRenderError | null;
|
|
81
|
+
|
|
72
82
|
// Debug/tracking state (now refs, won't trigger re-renders)
|
|
73
83
|
isPendingMockups: boolean;
|
|
74
84
|
canvasBlobsSent: number;
|
|
@@ -328,8 +338,10 @@ export function RealtimeProvider({
|
|
|
328
338
|
},
|
|
329
339
|
onAllMockupsRendered: (results) => {
|
|
330
340
|
},
|
|
331
|
-
onError: (error) => {
|
|
332
|
-
|
|
341
|
+
onError: (error, detail) => {
|
|
342
|
+
// Logged for traces; the actionable surface is `renderError` on the
|
|
343
|
+
// context (and the hook state), which consumers must render visibly.
|
|
344
|
+
console.error(`[RealtimeProvider] Render error [${detail.code}]:`, error);
|
|
333
345
|
},
|
|
334
346
|
});
|
|
335
347
|
|
|
@@ -341,6 +353,7 @@ export function RealtimeProvider({
|
|
|
341
353
|
const {
|
|
342
354
|
isConnected,
|
|
343
355
|
isConfigured,
|
|
356
|
+
renderError,
|
|
344
357
|
mockupResults: rawMockupResults,
|
|
345
358
|
sendCanvasBlob: sendCanvasBlobRaw,
|
|
346
359
|
sendCanvasState: sendCanvasStateRaw,
|
|
@@ -1067,6 +1080,7 @@ export function RealtimeProvider({
|
|
|
1067
1080
|
isEnabled,
|
|
1068
1081
|
isConnected,
|
|
1069
1082
|
isConfigured,
|
|
1083
|
+
renderError,
|
|
1070
1084
|
// Read from ref - this is a snapshot at render time, NOT reactive
|
|
1071
1085
|
// For reactive updates, use getMockupResultsImmediate() or subscribe functions
|
|
1072
1086
|
get mockupResults() {
|
|
@@ -1110,6 +1124,7 @@ export function RealtimeProvider({
|
|
|
1110
1124
|
isEnabled,
|
|
1111
1125
|
isConnected,
|
|
1112
1126
|
isConfigured,
|
|
1127
|
+
renderError,
|
|
1113
1128
|
// mockupResults removed from deps - it's a getter that reads from ref
|
|
1114
1129
|
canvasExportSize,
|
|
1115
1130
|
mockupWidth,
|