@stamprally/ui 0.16.0 → 0.18.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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # @stamprally/ui v0.16.0
1
+ # @stamprally/ui v0.18.0
2
2
 
3
3
  Participant-facing React components for `@stamprally/core`.
4
4
 
package/dist/index.cjs CHANGED
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
+ var jsxRuntime = require('react/jsx-runtime');
4
5
  var core = require('@stamprally/core');
5
6
  var react = require('react');
6
- var jsxRuntime = require('react/jsx-runtime');
7
7
 
8
8
  // src/locales/index.ts
9
9
  var DEFAULT_UI_DICTIONARY = {
@@ -37,7 +37,11 @@ var DEFAULT_UI_DICTIONARY = {
37
37
  "reward.lowStock": "Only a few left",
38
38
  "reward.remaining": "remaining",
39
39
  "reward.sharedRemaining": "Overall remaining",
40
- "reward.validUntil": "Valid until"
40
+ "reward.validUntil": "Valid until",
41
+ "sync.syncing": "Sending unsynced operations to the server...",
42
+ "sync.offline": "Recording offline",
43
+ "sync.unsynced": "unsynced",
44
+ "sync.rollback": "Some check-ins were rolled back by the server"
41
45
  },
42
46
  ja: {
43
47
  viewer: "\u30B9\u30BF\u30F3\u30D7\u30E9\u30EA\u30FC",
@@ -69,10 +73,53 @@ var DEFAULT_UI_DICTIONARY = {
69
73
  "reward.lowStock": "\u6B8B\u308A\u308F\u305A\u304B",
70
74
  "reward.remaining": "\u6B8B\u308A",
71
75
  "reward.sharedRemaining": "\u5168\u4F53\u3067\u6B8B\u308A",
72
- "reward.validUntil": "\u6709\u52B9\u671F\u9650"
76
+ "reward.validUntil": "\u6709\u52B9\u671F\u9650",
77
+ "sync.syncing": "\u672A\u540C\u671F\u306E\u64CD\u4F5C\u3092\u30B5\u30FC\u30D0\u30FC\u3078\u9001\u4FE1\u4E2D...",
78
+ "sync.offline": "\u30AA\u30D5\u30E9\u30A4\u30F3\u3067\u8A18\u9332\u4E2D",
79
+ "sync.unsynced": "\u672A\u540C\u671F",
80
+ "sync.rollback": "\u4E00\u90E8\u306E\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3\u304C\u30B5\u30FC\u30D0\u30FC\u306B\u3088\u308A\u53D6\u308A\u6D88\u3055\u308C\u307E\u3057\u305F"
73
81
  }
74
82
  };
75
83
  var UI_DICTIONARIES = DEFAULT_UI_DICTIONARY;
84
+ function text(dictionary, locale, key, fallback) {
85
+ return dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale]?.[key] ?? fallback;
86
+ }
87
+ function SyncStatusBanner({
88
+ status,
89
+ locale = "en",
90
+ dictionary,
91
+ className,
92
+ style
93
+ }) {
94
+ if (status.isSyncing)
95
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style, role: "status", "aria-live": "polite", children: [
96
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u27F3" }),
97
+ " ",
98
+ text(dictionary, locale, "sync.syncing", "\u672A\u540C\u671F\u306E\u64CD\u4F5C\u3092\u30B5\u30FC\u30D0\u30FC\u3078\u9001\u4FE1\u4E2D...")
99
+ ] });
100
+ if (status.rejectedHistory.length > 0) {
101
+ const detail = status.rejectedHistory[status.rejectedHistory.length - 1]?.reason.message;
102
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style, role: "alert", "aria-live": "assertive", children: [
103
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: text(
104
+ dictionary,
105
+ locale,
106
+ "sync.rollback",
107
+ "\u4E00\u90E8\u306E\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3\u304C\u30B5\u30FC\u30D0\u30FC\u306B\u3088\u308A\u53D6\u308A\u6D88\u3055\u308C\u307E\u3057\u305F"
108
+ ) }),
109
+ detail === void 0 ? null : /* @__PURE__ */ jsxRuntime.jsx("span", { children: detail })
110
+ ] });
111
+ }
112
+ if (status.pendingCount > 0)
113
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style, role: "status", "aria-live": "polite", children: [
114
+ text(dictionary, locale, "sync.offline", "\u30AA\u30D5\u30E9\u30A4\u30F3\u3067\u8A18\u9332\u4E2D"),
115
+ " (",
116
+ text(dictionary, locale, "sync.unsynced", "\u672A\u540C\u671F"),
117
+ ": ",
118
+ status.pendingCount,
119
+ "\u4EF6)"
120
+ ] });
121
+ return null;
122
+ }
76
123
  var label = (dictionary, locale, key, fallback) => dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale]?.[key] ?? fallback;
77
124
  var join = (...names) => {
78
125
  const value = names.filter((name) => name !== void 0 && name !== "").join(" ");
@@ -91,7 +138,7 @@ function DefaultCondition({
91
138
  const [status, setStatus] = react.useState("idle");
92
139
  const [error, setError] = react.useState(null);
93
140
  const videoRef = react.useRef(null);
94
- const text = (key, fallback) => label(dictionary, locale, key, fallback);
141
+ const text2 = (key, fallback) => label(dictionary, locale, key, fallback);
95
142
  const verify = async (proof) => {
96
143
  setStatus("loading");
97
144
  setError(null);
@@ -99,11 +146,11 @@ function DefaultCondition({
99
146
  const result = await onSubmit(proof);
100
147
  if (result !== void 0 && typeof result === "object" && result !== null && "ok" in result && result.ok === false) {
101
148
  setStatus("error");
102
- setError(text("verificationFailed", "Verification failed."));
149
+ setError(text2("verificationFailed", "Verification failed."));
103
150
  } else setStatus("success");
104
151
  } catch {
105
152
  setStatus("error");
106
- setError(text("verificationFailed", "Verification failed."));
153
+ setError(text2("verificationFailed", "Verification failed."));
107
154
  }
108
155
  };
109
156
  const readLocation = () => {
@@ -140,12 +187,12 @@ function DefaultCondition({
140
187
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
141
188
  condition.type === "qr" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
142
189
  /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
143
- text("qrValue", "QR value"),
190
+ text2("qrValue", "QR value"),
144
191
  /* @__PURE__ */ jsxRuntime.jsx(
145
192
  "input",
146
193
  {
147
- "aria-label": text("qrValue", "QR value"),
148
- placeholder: condition.qrEntryUrl ?? text("qrPlaceholder", "Paste a QR value"),
194
+ "aria-label": text2("qrValue", "QR value"),
195
+ placeholder: condition.qrEntryUrl ?? text2("qrPlaceholder", "Paste a QR value"),
149
196
  value,
150
197
  onChange: (event) => setValue(event.target.value)
151
198
  }
@@ -155,7 +202,7 @@ function DefaultCondition({
155
202
  "video",
156
203
  {
157
204
  ref: videoRef,
158
- "aria-label": text("qrCamera", "QR camera"),
205
+ "aria-label": text2("qrCamera", "QR camera"),
159
206
  hidden: !core.isQrSupported(),
160
207
  children: /* @__PURE__ */ jsxRuntime.jsx("track", { kind: "captions" })
161
208
  }
@@ -168,7 +215,7 @@ function DefaultCondition({
168
215
  style: styles?.button ?? styles?.action,
169
216
  disabled: disabled || !core.isQrSupported(),
170
217
  onClick: scanQr,
171
- children: text("scanQr", "Scan QR")
218
+ children: text2("scanQr", "Scan QR")
172
219
  }
173
220
  )
174
221
  ] }),
@@ -180,7 +227,7 @@ function DefaultCondition({
180
227
  style: styles?.button ?? styles?.action,
181
228
  disabled,
182
229
  onClick: readLocation,
183
- children: text("checkLocation", "Check location")
230
+ children: text2("checkLocation", "Check location")
184
231
  }
185
232
  ),
186
233
  condition.type === "nfc" && /* @__PURE__ */ jsxRuntime.jsx(
@@ -191,7 +238,7 @@ function DefaultCondition({
191
238
  style: styles?.button ?? styles?.action,
192
239
  disabled: disabled || !core.isNfcSupported(),
193
240
  onClick: readNfc,
194
- children: text("readNfc", "Read NFC")
241
+ children: text2("readNfc", "Read NFC")
195
242
  }
196
243
  ),
197
244
  (condition.type === "passcode" || condition.type === "custom" || condition.type === "qr") && /* @__PURE__ */ jsxRuntime.jsxs(
@@ -203,14 +250,14 @@ function DefaultCondition({
203
250
  },
204
251
  children: [
205
252
  /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
206
- text(
253
+ text2(
207
254
  condition.type === "passcode" ? "passcode" : "proof",
208
255
  condition.type === "passcode" ? "Passcode" : "Proof"
209
256
  ),
210
257
  /* @__PURE__ */ jsxRuntime.jsx(
211
258
  "input",
212
259
  {
213
- "aria-label": text("proof", "Proof"),
260
+ "aria-label": text2("proof", "Proof"),
214
261
  value,
215
262
  onChange: (event) => setValue(event.target.value)
216
263
  }
@@ -223,7 +270,7 @@ function DefaultCondition({
223
270
  className: join("sry-action", classNames?.action, classNames?.button),
224
271
  style: styles?.button ?? styles?.action,
225
272
  disabled: disabled || value.trim() === "",
226
- children: text("checkIn", "Check in")
273
+ children: text2("checkIn", "Check in")
227
274
  }
228
275
  )
229
276
  ]
@@ -237,9 +284,9 @@ function DefaultCondition({
237
284
  "aria-live": "polite",
238
285
  role: status === "error" ? "alert" : void 0,
239
286
  children: [
240
- status === "loading" && text("verifying", "Verifying\u2026"),
241
- status === "success" && text("verified", "Verified"),
242
- status === "error" && (error ?? text("verificationFailed", "Verification failed."))
287
+ status === "loading" && text2("verifying", "Verifying\u2026"),
288
+ status === "success" && text2("verified", "Verified"),
289
+ status === "error" && (error ?? text2("verificationFailed", "Verification failed."))
243
290
  ]
244
291
  }
245
292
  )
@@ -304,6 +351,7 @@ function RallyViewer({
304
351
  styles = {},
305
352
  style,
306
353
  customConditionRenderers = {},
354
+ onSyncEvent,
307
355
  headerSlot,
308
356
  footerSlot,
309
357
  renderSpotCard,
@@ -311,18 +359,45 @@ function RallyViewer({
311
359
  renderStatusBadge,
312
360
  renderVerifyingState,
313
361
  renderSuccessFeedback,
314
- renderErrorFeedback
362
+ renderErrorFeedback,
363
+ renderSyncStatus,
364
+ showSyncStatus = true
315
365
  }) {
316
366
  const config = providedConfig ?? client?.getConfig() ?? adapter?.config;
317
367
  const [state, setState] = react.useState(() => client?.getState() ?? null);
318
368
  const [busy, setBusy] = react.useState(null);
319
369
  const [feedback, setFeedback] = react.useState(null);
370
+ const [syncStatus, setSyncStatus] = react.useState(() => ({
371
+ syncState: client?.syncState ?? "idle",
372
+ isSyncing: client?.syncState === "syncing",
373
+ pendingCount: client?.pendingCount ?? 0,
374
+ rejectedHistory: client?.rejectedHistory ?? [],
375
+ storageCapability: client?.storageCapability ?? "custom",
376
+ isStoragePersistent: client?.isStoragePersistent ?? true
377
+ }));
320
378
  react.useEffect(() => {
321
379
  if (client === void 0) return;
322
380
  const unsubscribe = client.subscribe(setState);
323
381
  void client.init().then(setState);
324
382
  return unsubscribe;
325
383
  }, [client]);
384
+ react.useEffect(() => {
385
+ if (client === void 0 || onSyncEvent === void 0) return;
386
+ return client.subscribeSyncEvents(onSyncEvent);
387
+ }, [client, onSyncEvent]);
388
+ react.useEffect(() => {
389
+ if (client === void 0) return;
390
+ const update = () => setSyncStatus({
391
+ syncState: client.syncState,
392
+ isSyncing: client.syncState === "syncing",
393
+ pendingCount: client.pendingCount,
394
+ rejectedHistory: client.rejectedHistory,
395
+ storageCapability: client.storageCapability,
396
+ isStoragePersistent: client.isStoragePersistent
397
+ });
398
+ update();
399
+ return client.subscribeSyncState(update);
400
+ }, [client]);
326
401
  if (config === void 0) throw new Error("RallyViewer requires config, client, or adapter.");
327
402
  const currentState = state ?? {
328
403
  rallyId: config.id,
@@ -389,6 +464,16 @@ function RallyViewer({
389
464
  feedback?.ok === false && (renderErrorFeedback?.(
390
465
  "message" in feedback.error ? feedback.error.message : feedback.error.code
391
466
  ) ?? /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames.feedback, style: styles.feedback, role: "alert", children: "message" in feedback.error ? feedback.error.message : feedback.error.code })),
467
+ showSyncStatus && (renderSyncStatus?.(syncStatus) ?? /* @__PURE__ */ jsxRuntime.jsx(
468
+ SyncStatusBanner,
469
+ {
470
+ status: syncStatus,
471
+ locale,
472
+ ...dictionary === void 0 ? {} : { dictionary },
473
+ ...classNames.feedback === void 0 ? {} : { className: classNames.feedback },
474
+ ...styles.feedback === void 0 ? {} : { style: styles.feedback }
475
+ }
476
+ )),
392
477
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: config.spots.map((spot) => {
393
478
  const status = busy === spot.id ? "VERIFYING" : core.evaluateSpotStatus(spot, currentState);
394
479
  const claimed = status === "CLAIMED";
@@ -545,6 +630,7 @@ function StampSheet({
545
630
  exports.DEFAULT_UI_DICTIONARY = DEFAULT_UI_DICTIONARY;
546
631
  exports.RallyViewer = RallyViewer;
547
632
  exports.StampSheet = StampSheet;
633
+ exports.SyncStatusBanner = SyncStatusBanner;
548
634
  exports.UI_DICTIONARIES = UI_DICTIONARIES;
549
635
  //# sourceMappingURL=index.cjs.map
550
636
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/locales/index.ts","../src/index.tsx"],"names":["useState","useRef","getCurrentGeoContext","readNfcContext","readQrContext","jsxs","Fragment","jsx","isQrSupported","isNfcSupported","resolveLocalizedText","useEffect","useMemo","calculateProgress","useCallback","evaluateSpotStatus","result"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { LocaleDictionary } from \"@stamprally/core\";\n\n/** Complete built-in labels for the standard participant components. */\nexport const DEFAULT_UI_DICTIONARY: LocaleDictionary<\"ja\" | \"en\"> = {\n en: {\n viewer: \"Stamp rally\",\n stampSheet: \"Stamp sheet\",\n progress: \"Progress\",\n rewards: \"Rewards\",\n externalReferences: \"External references\",\n qrValue: \"QR value\",\n qrPlaceholder: \"Paste a QR value\",\n qrCamera: \"QR camera\",\n scanQr: \"Scan QR\",\n passcode: \"Passcode\",\n proof: \"Proof\",\n checkLocation: \"Check location\",\n readNfc: \"Read NFC\",\n checkIn: \"Check in\",\n verifying: \"Verifying…\",\n verified: \"Verified\",\n verificationFailed: \"Verification failed.\",\n prerequisitesNotMet: \"Complete the prerequisite spots before checking in.\",\n \"status.locked\": \"🔒 LOCKED\",\n \"status.unclaimed\": \"UNCLAIMED\",\n \"status.claimed\": \"CLAIMED\",\n \"status.verifying\": \"VERIFYING\",\n \"status.available\": \"AVAILABLE\",\n \"status.consumed\": \"CONSUMED\",\n \"status.expired\": \"EXPIRED\",\n \"status.onlyAFewLeft\": \"Only a few left\",\n \"reward.lowStock\": \"Only a few left\",\n \"reward.remaining\": \"remaining\",\n \"reward.sharedRemaining\": \"Overall remaining\",\n \"reward.validUntil\": \"Valid until\",\n },\n ja: {\n viewer: \"スタンプラリー\",\n stampSheet: \"スタンプシート\",\n progress: \"進捗\",\n rewards: \"景品\",\n externalReferences: \"関連リンク\",\n qrValue: \"QR値\",\n qrPlaceholder: \"QR値を入力\",\n qrCamera: \"QRカメラ\",\n scanQr: \"QRを読み取る\",\n passcode: \"パスコード\",\n proof: \"証明情報\",\n checkLocation: \"位置情報を確認\",\n readNfc: \"NFCを読み取る\",\n checkIn: \"チェックイン\",\n verifying: \"確認中…\",\n verified: \"確認済み\",\n verificationFailed: \"確認に失敗しました。\",\n prerequisitesNotMet: \"前提スポットをクリアしてください。\",\n \"status.locked\": \"🔒 ロック中\",\n \"status.unclaimed\": \"未取得\",\n \"status.claimed\": \"取得済み\",\n \"status.verifying\": \"確認中\",\n \"status.available\": \"利用可能\",\n \"status.consumed\": \"使用済み\",\n \"status.expired\": \"期限切れ\",\n \"status.onlyAFewLeft\": \"残りわずか\",\n \"reward.lowStock\": \"残りわずか\",\n \"reward.remaining\": \"残り\",\n \"reward.sharedRemaining\": \"全体で残り\",\n \"reward.validUntil\": \"有効期限\",\n },\n};\n\nexport const UI_DICTIONARIES = DEFAULT_UI_DICTIONARY;\n","\"use client\";\n\nimport type {\n CheckInOptions,\n CheckInResult,\n ClaimOptions,\n ClaimResult,\n SpotStatus as CoreSpotStatus,\n LocaleDictionary,\n PublicCheckInCondition,\n PublicRallyConfig,\n PublicReward,\n PublicSpotItem,\n RallyConfig,\n RallyInventoryState,\n RewardState,\n StampRallyClient,\n StampRallyProgress,\n StampRallyState,\n UserRallyState,\n} from \"@stamprally/core\";\nimport { DEFAULT_UI_DICTIONARY } from \"./locales/index.js\";\n\nexport { DEFAULT_UI_DICTIONARY, UI_DICTIONARIES } from \"./locales/index.js\";\n\nimport {\n calculateProgress,\n evaluateSpotStatus,\n getCurrentGeoContext,\n isNfcSupported,\n isQrSupported,\n readNfcContext,\n readQrContext,\n resolveLocalizedText,\n} from \"@stamprally/core\";\nimport {\n type ComponentType,\n type CSSProperties,\n type ReactElement,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type ViewerClassName =\n | \"root\"\n | \"header\"\n | \"card\"\n | \"condition\"\n | \"slot\"\n | \"badge\"\n | \"modal\"\n | \"button\"\n | \"action\"\n | \"feedback\"\n | \"reward\"\n | \"footer\";\nexport type ViewerStyle = CSSProperties & {\n readonly [key: `--${string}`]: string | number | undefined;\n};\nexport type ViewerStyles = Partial<Record<ViewerClassName, ViewerStyle>>;\nexport type ViewerClassNames = Partial<Record<ViewerClassName, string>>;\nexport type SpotStatus = CoreSpotStatus;\n\nexport interface ConditionRendererProps<TLocale extends string = string> {\n readonly spot: PublicSpotItem<TLocale>;\n readonly condition: PublicCheckInCondition;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly disabled: boolean;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n // biome-ignore lint/suspicious/noConfusingVoidType: custom renderers may fire-and-forget while built-ins await feedback.\n readonly onSubmit: (proof: unknown) => void | Promise<unknown>;\n}\nexport type ConditionRenderer<TLocale extends string = string> = ComponentType<\n ConditionRendererProps<TLocale>\n>;\n\nexport interface SpotCardProps<TLocale extends string = string> {\n readonly spot: PublicSpotItem<TLocale>;\n readonly state: UserRallyState;\n readonly status: SpotStatus;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly children: ReactNode;\n}\nexport interface RewardCardProps<TLocale extends string = string> {\n readonly reward: PublicReward<TLocale>;\n readonly state: RewardState | undefined;\n readonly inventory?: RallyInventoryState;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly onClaim:\n | ((rewardId: string, options?: ClaimOptions) => Promise<ClaimResult>)\n | undefined;\n}\nexport interface RallyViewerSlots<TLocale extends string = string> {\n readonly headerSlot?:\n | ReactNode\n | ((props: {\n readonly config: PublicRallyConfig<TLocale>;\n readonly state: UserRallyState;\n }) => ReactNode);\n readonly footerSlot?: ReactNode;\n readonly renderSpotCard?: (props: SpotCardProps<TLocale>) => ReactNode;\n readonly renderRewardCard?: (props: RewardCardProps<TLocale>) => ReactNode;\n readonly renderStatusBadge?: (props: { readonly status: SpotStatus }) => ReactNode;\n readonly renderVerifyingState?: () => ReactNode;\n readonly renderSuccessFeedback?: (result: CheckInResult) => ReactNode;\n readonly renderErrorFeedback?: (error: string) => ReactNode;\n}\n\nexport interface RallyViewerAdapter<TLocale extends string = string> {\n readonly config: PublicRallyConfig<TLocale>;\n readonly onCheckIn: (\n spotId: string,\n proof: unknown,\n options?: CheckInOptions,\n ) => Promise<CheckInResult>;\n readonly onClaimReward?: (rewardId: string, options?: ClaimOptions) => Promise<ClaimResult>;\n}\nexport interface RallyViewerProps<TLocale extends string = string>\n extends RallyViewerSlots<TLocale> {\n readonly config?: PublicRallyConfig<TLocale>;\n readonly client?: StampRallyClient;\n readonly adapter?: RallyViewerAdapter<TLocale>;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n readonly style?: ViewerStyle;\n readonly customConditionRenderers?: Partial<\n Record<PublicCheckInCondition[\"type\"], ConditionRenderer<TLocale>>\n >;\n}\n\nconst label = <TLocale extends string>(\n dictionary: LocaleDictionary<TLocale> | undefined,\n locale: TLocale,\n key: string,\n fallback: string,\n): string =>\n dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale as \"ja\" | \"en\"]?.[key] ?? fallback;\nconst join = (...names: ReadonlyArray<string | undefined>): string | undefined => {\n const value = names.filter((name): name is string => name !== undefined && name !== \"\").join(\" \");\n return value === \"\" ? undefined : value;\n};\ntype VerificationStatus = \"idle\" | \"loading\" | \"success\" | \"error\";\n\nfunction DefaultCondition<TLocale extends string>({\n condition,\n dictionary,\n locale,\n disabled,\n classNames,\n styles,\n onSubmit,\n}: ConditionRendererProps<TLocale>): ReactElement {\n const [value, setValue] = useState(\"\");\n const [status, setStatus] = useState<VerificationStatus>(\"idle\");\n const [error, setError] = useState<string | null>(null);\n const videoRef = useRef<HTMLVideoElement>(null);\n const text = (key: string, fallback: string): string => label(dictionary, locale, key, fallback);\n const verify = async (proof: unknown): Promise<void> => {\n setStatus(\"loading\");\n setError(null);\n try {\n const result = await onSubmit(proof);\n if (\n result !== undefined &&\n typeof result === \"object\" &&\n result !== null &&\n \"ok\" in result &&\n result.ok === false\n ) {\n setStatus(\"error\");\n setError(text(\"verificationFailed\", \"Verification failed.\"));\n } else setStatus(\"success\");\n } catch {\n setStatus(\"error\");\n setError(text(\"verificationFailed\", \"Verification failed.\"));\n }\n };\n const readLocation = (): void => {\n setStatus(\"loading\");\n void getCurrentGeoContext().then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n const readNfc = (): void => {\n setStatus(\"loading\");\n void readNfcContext().then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n const scanQr = (): void => {\n if (videoRef.current === null) return;\n setStatus(\"loading\");\n void readQrContext(videoRef.current).then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n return (\n <div>\n {condition.type === \"qr\" && (\n <>\n <label>\n {text(\"qrValue\", \"QR value\")}\n <input\n aria-label={text(\"qrValue\", \"QR value\")}\n placeholder={condition.qrEntryUrl ?? text(\"qrPlaceholder\", \"Paste a QR value\")}\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </label>\n <video\n ref={videoRef}\n aria-label={text(\"qrCamera\", \"QR camera\")}\n hidden={!isQrSupported()}\n >\n <track kind=\"captions\" />\n </video>\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || !isQrSupported()}\n onClick={scanQr}\n >\n {text(\"scanQr\", \"Scan QR\")}\n </button>\n </>\n )}\n {condition.type === \"gps\" && (\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled}\n onClick={readLocation}\n >\n {text(\"checkLocation\", \"Check location\")}\n </button>\n )}\n {condition.type === \"nfc\" && (\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || !isNfcSupported()}\n onClick={readNfc}\n >\n {text(\"readNfc\", \"Read NFC\")}\n </button>\n )}\n {(condition.type === \"passcode\" ||\n condition.type === \"custom\" ||\n condition.type === \"qr\") && (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void verify(value);\n }}\n >\n <label>\n {text(\n condition.type === \"passcode\" ? \"passcode\" : \"proof\",\n condition.type === \"passcode\" ? \"Passcode\" : \"Proof\",\n )}\n <input\n aria-label={text(\"proof\", \"Proof\")}\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </label>\n <button\n type=\"submit\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || value.trim() === \"\"}\n >\n {text(\"checkIn\", \"Check in\")}\n </button>\n </form>\n )}\n <div\n className={join(\"sry-feedback\", classNames?.feedback)}\n style={styles?.feedback}\n aria-live=\"polite\"\n role={status === \"error\" ? \"alert\" : undefined}\n >\n {status === \"loading\" && text(\"verifying\", \"Verifying…\")}\n {status === \"success\" && text(\"verified\", \"Verified\")}\n {status === \"error\" && (error ?? text(\"verificationFailed\", \"Verification failed.\"))}\n </div>\n </div>\n );\n}\n\nfunction DefaultRewardCard<TLocale extends string>({\n reward,\n state,\n inventory,\n locale,\n dictionary,\n onClaim,\n classNames,\n styles,\n}: RewardCardProps<TLocale> & {\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n}): ReactElement {\n const status = state?.status ?? \"LOCKED\";\n const configuredRemaining =\n inventory?.rewardRemaining?.[reward.id] ??\n (reward.stockLimit === undefined\n ? undefined\n : Math.max(0, reward.stockLimit - (state?.redeemedCount ?? 0)));\n const sharedRemaining = inventory?.sharedRemaining;\n const unavailable =\n status !== \"AVAILABLE\" ||\n onClaim === undefined ||\n sharedRemaining === 0 ||\n configuredRemaining === 0;\n const expiry = reward.validUntil === undefined ? undefined : new Date(reward.validUntil);\n return (\n <article className={classNames?.reward} style={styles?.reward}>\n <h3>{resolveLocalizedText(reward.title, locale)}</h3>\n {reward.description !== undefined && (\n <p>{resolveLocalizedText(reward.description, locale)}</p>\n )}\n {sharedRemaining !== undefined && (\n <span>\n {label(dictionary, locale, \"reward.sharedRemaining\", \"Overall remaining\")}:{\" \"}\n {sharedRemaining}\n </span>\n )}\n {configuredRemaining !== undefined && (\n <>\n {configuredRemaining <= 3 && (\n <span>{label(dictionary, locale, \"reward.lowStock\", \"Only a few left\")}</span>\n )}\n <span>\n {`${configuredRemaining} ${label(dictionary, locale, \"reward.remaining\", \"remaining\")}`}\n </span>\n </>\n )}\n {expiry !== undefined && !Number.isNaN(expiry.getTime()) && (\n <time dateTime={reward.validUntil}>\n {label(dictionary, locale, \"reward.validUntil\", \"Valid until\")}:{\" \"}\n {expiry.toLocaleString(locale)}\n </time>\n )}\n <button\n type=\"button\"\n className={join(classNames?.reward, classNames?.button)}\n style={styles?.button}\n disabled={unavailable}\n onClick={() => {\n if (onClaim !== undefined) void onClaim(reward.id);\n }}\n >\n {label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </button>\n </article>\n );\n}\n\nexport function RallyViewer<TLocale extends string = string>({\n config: providedConfig,\n client,\n adapter,\n locale,\n dictionary,\n classNames = {},\n styles = {},\n style,\n customConditionRenderers = {},\n headerSlot,\n footerSlot,\n renderSpotCard,\n renderRewardCard,\n renderStatusBadge,\n renderVerifyingState,\n renderSuccessFeedback,\n renderErrorFeedback,\n}: RallyViewerProps<TLocale>): ReactElement {\n const config = providedConfig ?? client?.getConfig() ?? adapter?.config;\n const [state, setState] = useState<UserRallyState | null>(() => client?.getState() ?? null);\n const [busy, setBusy] = useState<string | null>(null);\n const [feedback, setFeedback] = useState<CheckInResult | null>(null);\n useEffect(() => {\n if (client === undefined) return;\n const unsubscribe = client.subscribe(setState);\n void client.init().then(setState);\n return unsubscribe;\n }, [client]);\n if (config === undefined) throw new Error(\"RallyViewer requires config, client, or adapter.\");\n const currentState = state ?? {\n rallyId: config.id,\n userId: null,\n records: [],\n rewards: [],\n updatedAt: \"\",\n };\n const progress = useMemo<StampRallyProgress>(\n () => calculateProgress(currentState, config),\n [config, currentState],\n );\n const checkIn =\n adapter?.onCheckIn ??\n (client === undefined\n ? undefined\n : (spotId: string, proof: unknown, options?: CheckInOptions) =>\n client.checkIn(spotId, proof, options));\n const claim =\n adapter?.onClaimReward ??\n (client === undefined\n ? undefined\n : (rewardId: string, options?: ClaimOptions) => client.claimReward(rewardId, options));\n const submit = useCallback(\n async (spotId: string, proof: unknown): Promise<CheckInResult | undefined> => {\n if (checkIn === undefined) return undefined;\n const target = config.spots.find((spot) => spot.id === spotId);\n if (target !== undefined && evaluateSpotStatus(target, currentState) === \"LOCKED\") {\n const result: CheckInResult = {\n ok: false,\n error: {\n code: \"PREREQUISITES_NOT_MET\",\n spotId,\n message: \"Complete the prerequisite spots before checking in.\",\n },\n };\n setFeedback(result);\n return result;\n }\n setBusy(spotId);\n const result = await checkIn(spotId, proof).finally(() => setBusy(null));\n setFeedback(result);\n return result;\n },\n [checkIn, config.spots, currentState],\n );\n return (\n <section\n className={classNames.root}\n style={styles.root ?? style}\n aria-label={label(dictionary, locale, \"viewer\", \"Stamp rally\")}\n >\n <header className={classNames.header} style={styles.header}>\n {typeof headerSlot === \"function\"\n ? headerSlot({ config, state: currentState })\n : headerSlot}\n {headerSlot === undefined && (\n <h1>{resolveLocalizedText(config.title, locale) || config.id}</h1>\n )}\n <progress\n aria-label={label(dictionary, locale, \"progress\", \"Progress\")}\n max={100}\n value={progress.percentage}\n />\n <span>\n {progress.acquired}/{progress.total}\n </span>\n </header>\n {busy !== null &&\n (renderVerifyingState?.() ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"status\">\n {label(dictionary, locale, \"verifying\", \"Verifying…\")}\n </div>\n ))}\n {feedback?.ok === true &&\n (renderSuccessFeedback?.(feedback) ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"status\">\n {label(dictionary, locale, \"verified\", \"Verified\")}\n </div>\n ))}\n {feedback?.ok === false &&\n (renderErrorFeedback?.(\n \"message\" in feedback.error ? feedback.error.message : feedback.error.code,\n ) ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"alert\">\n {\"message\" in feedback.error ? feedback.error.message : feedback.error.code}\n </div>\n ))}\n <div>\n {config.spots.map((spot) => {\n const status: SpotStatus =\n busy === spot.id ? \"VERIFYING\" : evaluateSpotStatus(spot, currentState);\n const claimed = status === \"CLAIMED\";\n const locked = status === \"LOCKED\";\n const children = spot.conditions.map((condition) => {\n const Renderer = customConditionRenderers[condition.type] ?? DefaultCondition;\n return (\n <div\n className={classNames.condition}\n style={styles.condition}\n key={`${spot.id}-${condition.type}-${JSON.stringify(condition)}`}\n >\n <Renderer\n spot={spot}\n condition={condition}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n disabled={busy !== null || claimed || locked}\n {...(Object.keys(classNames).length === 0 ? {} : { classNames })}\n {...(Object.keys(styles).length === 0 ? {} : { styles })}\n onSubmit={(proof) => submit(spot.id, proof)}\n />\n </div>\n );\n });\n const props: SpotCardProps<TLocale> = {\n spot,\n state: currentState,\n status,\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n children,\n };\n return (\n <div\n key={spot.id}\n className={classNames.card}\n style={styles.card}\n data-status={status}\n aria-disabled={locked}\n >\n {renderSpotCard?.(props) ?? (\n <article>\n {spot.iconUrl !== undefined && (\n <img src={spot.iconUrl} alt=\"\" width={32} height={32} />\n )}\n <h2>{resolveLocalizedText(spot.name, locale)}</h2>\n {spot.imageUrl !== undefined && <img src={spot.imageUrl} alt=\"\" loading=\"lazy\" />}\n {spot.description !== undefined && (\n <p>{resolveLocalizedText(spot.description, locale)}</p>\n )}\n {spot.hint !== undefined && <p>{resolveLocalizedText(spot.hint, locale)}</p>}\n {spot.externalReferences !== undefined && spot.externalReferences.length > 0 && (\n <span className={classNames.badge} style={styles.badge}>\n {label(dictionary, locale, \"externalReferences\", \"External references\")} (\n {spot.externalReferences.length})\n </span>\n )}\n {renderStatusBadge?.({ status }) ?? (\n <span className={classNames.badge} style={styles.badge}>\n {label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </span>\n )}\n {locked && (\n <p role=\"status\">\n {label(\n dictionary,\n locale,\n \"prerequisitesNotMet\",\n \"Complete the prerequisite spots before checking in.\",\n )}\n </p>\n )}\n {children}\n </article>\n )}\n </div>\n );\n })}\n </div>\n <section aria-label={label(dictionary, locale, \"rewards\", \"Rewards\")}>\n {config.rewards.map((reward) => {\n const props: RewardCardProps<TLocale> = {\n reward,\n state: currentState.rewards.find((item) => item.rewardId === reward.id),\n ...(currentState.inventory === undefined ? {} : { inventory: currentState.inventory }),\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n onClaim: claim,\n };\n return (\n <div key={reward.id} className={classNames.reward} style={styles.reward}>\n {renderRewardCard?.(props) ?? (\n <DefaultRewardCard {...props} classNames={classNames} styles={styles} />\n )}\n </div>\n );\n })}\n </section>\n <footer className={classNames.footer} style={styles.footer}>\n {footerSlot}\n </footer>\n </section>\n );\n}\n\nexport interface StampSheetProps<TLocale extends string = string>\n extends RallyViewerSlots<TLocale> {\n readonly config: RallyConfig<TLocale>;\n readonly state?: StampRallyState | null;\n readonly title?: string;\n readonly progress?: StampRallyProgress;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n readonly style?: ViewerStyle;\n}\nexport function StampSheet<TLocale extends string = string>({\n config,\n state,\n title,\n progress,\n locale = \"en\" as TLocale,\n dictionary,\n classNames = {},\n styles = {},\n style,\n headerSlot,\n footerSlot,\n renderSpotCard,\n renderStatusBadge,\n}: StampSheetProps<TLocale>): ReactElement {\n const currentState = state ?? {\n rallyId: config.id,\n userId: null,\n records: [],\n rewards: [],\n updatedAt: \"\",\n };\n const current = progress ?? calculateProgress(currentState, config);\n return (\n <section\n className={classNames.root}\n style={styles.root ?? style}\n aria-label={title ?? label(dictionary, locale, \"stampSheet\", \"Stamp sheet\")}\n >\n <header className={classNames.header} style={styles.header}>\n {typeof headerSlot === \"function\"\n ? headerSlot({ config, state: currentState })\n : (headerSlot ?? <h2>{title ?? resolveLocalizedText(config.title, locale)}</h2>)}\n <progress max={100} value={current.percentage} />\n </header>\n <div>\n {config.spots.map((spot) => {\n const status: SpotStatus = evaluateSpotStatus(spot, currentState);\n const props: SpotCardProps<TLocale> = {\n spot,\n state: currentState,\n status,\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n children: (\n <span className={classNames.slot} style={styles.slot}>\n {status === \"LOCKED\"\n ? label(dictionary, locale, \"status.locked\", \"🔒 LOCKED\")\n : status === \"CLAIMED\"\n ? label(dictionary, locale, \"status.claimed\", \"CLAIMED\")\n : label(dictionary, locale, \"status.unclaimed\", \"UNCLAIMED\")}\n </span>\n ),\n };\n return (\n <div\n key={spot.id}\n className={classNames.card}\n style={styles.card}\n data-status={status}\n aria-disabled={status === \"LOCKED\"}\n >\n {renderSpotCard?.(props) ?? (\n <span className={classNames.slot} style={styles.slot}>\n {spot.iconUrl !== undefined && (\n <img src={spot.iconUrl} alt=\"\" width={24} height={24} />\n )}\n {resolveLocalizedText(spot.name, locale)}{\" \"}\n {spot.description !== undefined && (\n <small>{resolveLocalizedText(spot.description, locale)}</small>\n )}{\" \"}\n {renderStatusBadge?.({ status }) ??\n label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n <footer className={classNames.footer} style={styles.footer}>\n {footerSlot}\n </footer>\n </section>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/locales/index.ts","../src/components/SyncStatusBanner.tsx","../src/index.tsx"],"names":["jsx","useState","useRef","text","getCurrentGeoContext","readNfcContext","readQrContext","jsxs","Fragment","isQrSupported","isNfcSupported","resolveLocalizedText","useEffect","useMemo","calculateProgress","useCallback","evaluateSpotStatus","result"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { LocaleDictionary } from \"@stamprally/core\";\n\n/** Complete built-in labels for the standard participant components. */\nexport const DEFAULT_UI_DICTIONARY: LocaleDictionary<\"ja\" | \"en\"> = {\n en: {\n viewer: \"Stamp rally\",\n stampSheet: \"Stamp sheet\",\n progress: \"Progress\",\n rewards: \"Rewards\",\n externalReferences: \"External references\",\n qrValue: \"QR value\",\n qrPlaceholder: \"Paste a QR value\",\n qrCamera: \"QR camera\",\n scanQr: \"Scan QR\",\n passcode: \"Passcode\",\n proof: \"Proof\",\n checkLocation: \"Check location\",\n readNfc: \"Read NFC\",\n checkIn: \"Check in\",\n verifying: \"Verifying…\",\n verified: \"Verified\",\n verificationFailed: \"Verification failed.\",\n prerequisitesNotMet: \"Complete the prerequisite spots before checking in.\",\n \"status.locked\": \"🔒 LOCKED\",\n \"status.unclaimed\": \"UNCLAIMED\",\n \"status.claimed\": \"CLAIMED\",\n \"status.verifying\": \"VERIFYING\",\n \"status.available\": \"AVAILABLE\",\n \"status.consumed\": \"CONSUMED\",\n \"status.expired\": \"EXPIRED\",\n \"status.onlyAFewLeft\": \"Only a few left\",\n \"reward.lowStock\": \"Only a few left\",\n \"reward.remaining\": \"remaining\",\n \"reward.sharedRemaining\": \"Overall remaining\",\n \"reward.validUntil\": \"Valid until\",\n \"sync.syncing\": \"Sending unsynced operations to the server...\",\n \"sync.offline\": \"Recording offline\",\n \"sync.unsynced\": \"unsynced\",\n \"sync.rollback\": \"Some check-ins were rolled back by the server\",\n },\n ja: {\n viewer: \"スタンプラリー\",\n stampSheet: \"スタンプシート\",\n progress: \"進捗\",\n rewards: \"景品\",\n externalReferences: \"関連リンク\",\n qrValue: \"QR値\",\n qrPlaceholder: \"QR値を入力\",\n qrCamera: \"QRカメラ\",\n scanQr: \"QRを読み取る\",\n passcode: \"パスコード\",\n proof: \"証明情報\",\n checkLocation: \"位置情報を確認\",\n readNfc: \"NFCを読み取る\",\n checkIn: \"チェックイン\",\n verifying: \"確認中…\",\n verified: \"確認済み\",\n verificationFailed: \"確認に失敗しました。\",\n prerequisitesNotMet: \"前提スポットをクリアしてください。\",\n \"status.locked\": \"🔒 ロック中\",\n \"status.unclaimed\": \"未取得\",\n \"status.claimed\": \"取得済み\",\n \"status.verifying\": \"確認中\",\n \"status.available\": \"利用可能\",\n \"status.consumed\": \"使用済み\",\n \"status.expired\": \"期限切れ\",\n \"status.onlyAFewLeft\": \"残りわずか\",\n \"reward.lowStock\": \"残りわずか\",\n \"reward.remaining\": \"残り\",\n \"reward.sharedRemaining\": \"全体で残り\",\n \"reward.validUntil\": \"有効期限\",\n \"sync.syncing\": \"未同期の操作をサーバーへ送信中...\",\n \"sync.offline\": \"オフラインで記録中\",\n \"sync.unsynced\": \"未同期\",\n \"sync.rollback\": \"一部のチェックインがサーバーにより取り消されました\",\n },\n};\n\nexport const UI_DICTIONARIES = DEFAULT_UI_DICTIONARY;\n","import type {\n LocaleDictionary,\n OfflineStorageCapability,\n RejectedOperationHistoryEntry,\n SyncState,\n} from \"@stamprally/core\";\nimport type { CSSProperties, ReactElement } from \"react\";\nimport { DEFAULT_UI_DICTIONARY } from \"../locales/index.js\";\n\nexport interface SyncStateContext {\n readonly syncState: SyncState;\n readonly isSyncing: boolean;\n readonly pendingCount: number;\n readonly rejectedHistory: ReadonlyArray<RejectedOperationHistoryEntry>;\n readonly storageCapability: OfflineStorageCapability;\n readonly isStoragePersistent: boolean;\n}\n\nexport interface SyncStatusBannerProps<TLocale extends string = string> {\n readonly status: SyncStateContext;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly className?: string;\n readonly style?: CSSProperties;\n}\n\nfunction text<TLocale extends string>(\n dictionary: LocaleDictionary<TLocale> | undefined,\n locale: TLocale,\n key: string,\n fallback: string,\n): string {\n return (\n dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale as \"ja\" | \"en\"]?.[key] ?? fallback\n );\n}\n\nexport function SyncStatusBanner<TLocale extends string = \"en\">({\n status,\n locale = \"en\" as TLocale,\n dictionary,\n className,\n style,\n}: SyncStatusBannerProps<TLocale>): ReactElement | null {\n if (status.isSyncing)\n return (\n <div className={className} style={style} role=\"status\" aria-live=\"polite\">\n <span aria-hidden=\"true\">⟳</span>{\" \"}\n {text(dictionary, locale, \"sync.syncing\", \"未同期の操作をサーバーへ送信中...\")}\n </div>\n );\n if (status.rejectedHistory.length > 0) {\n const detail = status.rejectedHistory[status.rejectedHistory.length - 1]?.reason.message;\n return (\n <div className={className} style={style} role=\"alert\" aria-live=\"assertive\">\n <strong>\n {text(\n dictionary,\n locale,\n \"sync.rollback\",\n \"一部のチェックインがサーバーにより取り消されました\",\n )}\n </strong>\n {detail === undefined ? null : <span>{detail}</span>}\n </div>\n );\n }\n if (status.pendingCount > 0)\n return (\n <div className={className} style={style} role=\"status\" aria-live=\"polite\">\n {text(dictionary, locale, \"sync.offline\", \"オフラインで記録中\")} (\n {text(dictionary, locale, \"sync.unsynced\", \"未同期\")}: {status.pendingCount}件)\n </div>\n );\n return null;\n}\n","\"use client\";\n\nimport type {\n CheckInOptions,\n CheckInResult,\n ClaimOptions,\n ClaimResult,\n SpotStatus as CoreSpotStatus,\n LocaleDictionary,\n PublicCheckInCondition,\n PublicRallyConfig,\n PublicReward,\n PublicSpotItem,\n RallyConfig,\n RallyInventoryState,\n RewardState,\n StampRallyClient,\n StampRallyProgress,\n StampRallyState,\n SyncEventListener,\n UserRallyState,\n} from \"@stamprally/core\";\nimport { type SyncStateContext, SyncStatusBanner } from \"./components/SyncStatusBanner.js\";\nimport { DEFAULT_UI_DICTIONARY } from \"./locales/index.js\";\n\nexport type { SyncStateContext, SyncStatusBannerProps } from \"./components/SyncStatusBanner.js\";\nexport { SyncStatusBanner } from \"./components/SyncStatusBanner.js\";\n\nexport { DEFAULT_UI_DICTIONARY, UI_DICTIONARIES } from \"./locales/index.js\";\n\nimport {\n calculateProgress,\n evaluateSpotStatus,\n getCurrentGeoContext,\n isNfcSupported,\n isQrSupported,\n readNfcContext,\n readQrContext,\n resolveLocalizedText,\n} from \"@stamprally/core\";\nimport {\n type ComponentType,\n type CSSProperties,\n type ReactElement,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type ViewerClassName =\n | \"root\"\n | \"header\"\n | \"card\"\n | \"condition\"\n | \"slot\"\n | \"badge\"\n | \"modal\"\n | \"button\"\n | \"action\"\n | \"feedback\"\n | \"reward\"\n | \"footer\";\n\nexport type ViewerSyncStateContext = SyncStateContext;\nexport type ViewerStyle = CSSProperties & {\n readonly [key: `--${string}`]: string | number | undefined;\n};\nexport type ViewerStyles = Partial<Record<ViewerClassName, ViewerStyle>>;\nexport type ViewerClassNames = Partial<Record<ViewerClassName, string>>;\nexport type SpotStatus = CoreSpotStatus;\n\nexport interface ConditionRendererProps<TLocale extends string = string> {\n readonly spot: PublicSpotItem<TLocale>;\n readonly condition: PublicCheckInCondition;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly disabled: boolean;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n // biome-ignore lint/suspicious/noConfusingVoidType: custom renderers may fire-and-forget while built-ins await feedback.\n readonly onSubmit: (proof: unknown) => void | Promise<unknown>;\n}\nexport type ConditionRenderer<TLocale extends string = string> = ComponentType<\n ConditionRendererProps<TLocale>\n>;\n\nexport interface SpotCardProps<TLocale extends string = string> {\n readonly spot: PublicSpotItem<TLocale>;\n readonly state: UserRallyState;\n readonly status: SpotStatus;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly children: ReactNode;\n}\nexport interface RewardCardProps<TLocale extends string = string> {\n readonly reward: PublicReward<TLocale>;\n readonly state: RewardState | undefined;\n readonly inventory?: RallyInventoryState;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly onClaim:\n | ((rewardId: string, options?: ClaimOptions) => Promise<ClaimResult>)\n | undefined;\n}\nexport interface RallyViewerSlots<TLocale extends string = string> {\n readonly headerSlot?:\n | ReactNode\n | ((props: {\n readonly config: PublicRallyConfig<TLocale>;\n readonly state: UserRallyState;\n }) => ReactNode);\n readonly footerSlot?: ReactNode;\n readonly renderSyncStatus?: (status: SyncStateContext) => ReactNode;\n readonly renderSpotCard?: (props: SpotCardProps<TLocale>) => ReactNode;\n readonly renderRewardCard?: (props: RewardCardProps<TLocale>) => ReactNode;\n readonly renderStatusBadge?: (props: { readonly status: SpotStatus }) => ReactNode;\n readonly renderVerifyingState?: () => ReactNode;\n readonly renderSuccessFeedback?: (result: CheckInResult) => ReactNode;\n readonly renderErrorFeedback?: (error: string) => ReactNode;\n}\n\nexport interface RallyViewerAdapter<TLocale extends string = string> {\n readonly config: PublicRallyConfig<TLocale>;\n readonly onCheckIn: (\n spotId: string,\n proof: unknown,\n options?: CheckInOptions,\n ) => Promise<CheckInResult>;\n readonly onClaimReward?: (rewardId: string, options?: ClaimOptions) => Promise<ClaimResult>;\n}\nexport interface RallyViewerProps<TLocale extends string = string>\n extends RallyViewerSlots<TLocale> {\n readonly config?: PublicRallyConfig<TLocale>;\n readonly client?: StampRallyClient;\n readonly adapter?: RallyViewerAdapter<TLocale>;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n readonly style?: ViewerStyle;\n readonly customConditionRenderers?: Partial<\n Record<PublicCheckInCondition[\"type\"], ConditionRenderer<TLocale>>\n >;\n readonly onSyncEvent?: SyncEventListener;\n readonly showSyncStatus?: boolean;\n}\n\nconst label = <TLocale extends string>(\n dictionary: LocaleDictionary<TLocale> | undefined,\n locale: TLocale,\n key: string,\n fallback: string,\n): string =>\n dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale as \"ja\" | \"en\"]?.[key] ?? fallback;\nconst join = (...names: ReadonlyArray<string | undefined>): string | undefined => {\n const value = names.filter((name): name is string => name !== undefined && name !== \"\").join(\" \");\n return value === \"\" ? undefined : value;\n};\ntype VerificationStatus = \"idle\" | \"loading\" | \"success\" | \"error\";\n\nfunction DefaultCondition<TLocale extends string>({\n condition,\n dictionary,\n locale,\n disabled,\n classNames,\n styles,\n onSubmit,\n}: ConditionRendererProps<TLocale>): ReactElement {\n const [value, setValue] = useState(\"\");\n const [status, setStatus] = useState<VerificationStatus>(\"idle\");\n const [error, setError] = useState<string | null>(null);\n const videoRef = useRef<HTMLVideoElement>(null);\n const text = (key: string, fallback: string): string => label(dictionary, locale, key, fallback);\n const verify = async (proof: unknown): Promise<void> => {\n setStatus(\"loading\");\n setError(null);\n try {\n const result = await onSubmit(proof);\n if (\n result !== undefined &&\n typeof result === \"object\" &&\n result !== null &&\n \"ok\" in result &&\n result.ok === false\n ) {\n setStatus(\"error\");\n setError(text(\"verificationFailed\", \"Verification failed.\"));\n } else setStatus(\"success\");\n } catch {\n setStatus(\"error\");\n setError(text(\"verificationFailed\", \"Verification failed.\"));\n }\n };\n const readLocation = (): void => {\n setStatus(\"loading\");\n void getCurrentGeoContext().then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n const readNfc = (): void => {\n setStatus(\"loading\");\n void readNfcContext().then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n const scanQr = (): void => {\n if (videoRef.current === null) return;\n setStatus(\"loading\");\n void readQrContext(videoRef.current).then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n return (\n <div>\n {condition.type === \"qr\" && (\n <>\n <label>\n {text(\"qrValue\", \"QR value\")}\n <input\n aria-label={text(\"qrValue\", \"QR value\")}\n placeholder={condition.qrEntryUrl ?? text(\"qrPlaceholder\", \"Paste a QR value\")}\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </label>\n <video\n ref={videoRef}\n aria-label={text(\"qrCamera\", \"QR camera\")}\n hidden={!isQrSupported()}\n >\n <track kind=\"captions\" />\n </video>\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || !isQrSupported()}\n onClick={scanQr}\n >\n {text(\"scanQr\", \"Scan QR\")}\n </button>\n </>\n )}\n {condition.type === \"gps\" && (\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled}\n onClick={readLocation}\n >\n {text(\"checkLocation\", \"Check location\")}\n </button>\n )}\n {condition.type === \"nfc\" && (\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || !isNfcSupported()}\n onClick={readNfc}\n >\n {text(\"readNfc\", \"Read NFC\")}\n </button>\n )}\n {(condition.type === \"passcode\" ||\n condition.type === \"custom\" ||\n condition.type === \"qr\") && (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void verify(value);\n }}\n >\n <label>\n {text(\n condition.type === \"passcode\" ? \"passcode\" : \"proof\",\n condition.type === \"passcode\" ? \"Passcode\" : \"Proof\",\n )}\n <input\n aria-label={text(\"proof\", \"Proof\")}\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </label>\n <button\n type=\"submit\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || value.trim() === \"\"}\n >\n {text(\"checkIn\", \"Check in\")}\n </button>\n </form>\n )}\n <div\n className={join(\"sry-feedback\", classNames?.feedback)}\n style={styles?.feedback}\n aria-live=\"polite\"\n role={status === \"error\" ? \"alert\" : undefined}\n >\n {status === \"loading\" && text(\"verifying\", \"Verifying…\")}\n {status === \"success\" && text(\"verified\", \"Verified\")}\n {status === \"error\" && (error ?? text(\"verificationFailed\", \"Verification failed.\"))}\n </div>\n </div>\n );\n}\n\nfunction DefaultRewardCard<TLocale extends string>({\n reward,\n state,\n inventory,\n locale,\n dictionary,\n onClaim,\n classNames,\n styles,\n}: RewardCardProps<TLocale> & {\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n}): ReactElement {\n const status = state?.status ?? \"LOCKED\";\n const configuredRemaining =\n inventory?.rewardRemaining?.[reward.id] ??\n (reward.stockLimit === undefined\n ? undefined\n : Math.max(0, reward.stockLimit - (state?.redeemedCount ?? 0)));\n const sharedRemaining = inventory?.sharedRemaining;\n const unavailable =\n status !== \"AVAILABLE\" ||\n onClaim === undefined ||\n sharedRemaining === 0 ||\n configuredRemaining === 0;\n const expiry = reward.validUntil === undefined ? undefined : new Date(reward.validUntil);\n return (\n <article className={classNames?.reward} style={styles?.reward}>\n <h3>{resolveLocalizedText(reward.title, locale)}</h3>\n {reward.description !== undefined && (\n <p>{resolveLocalizedText(reward.description, locale)}</p>\n )}\n {sharedRemaining !== undefined && (\n <span>\n {label(dictionary, locale, \"reward.sharedRemaining\", \"Overall remaining\")}:{\" \"}\n {sharedRemaining}\n </span>\n )}\n {configuredRemaining !== undefined && (\n <>\n {configuredRemaining <= 3 && (\n <span>{label(dictionary, locale, \"reward.lowStock\", \"Only a few left\")}</span>\n )}\n <span>\n {`${configuredRemaining} ${label(dictionary, locale, \"reward.remaining\", \"remaining\")}`}\n </span>\n </>\n )}\n {expiry !== undefined && !Number.isNaN(expiry.getTime()) && (\n <time dateTime={reward.validUntil}>\n {label(dictionary, locale, \"reward.validUntil\", \"Valid until\")}:{\" \"}\n {expiry.toLocaleString(locale)}\n </time>\n )}\n <button\n type=\"button\"\n className={join(classNames?.reward, classNames?.button)}\n style={styles?.button}\n disabled={unavailable}\n onClick={() => {\n if (onClaim !== undefined) void onClaim(reward.id);\n }}\n >\n {label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </button>\n </article>\n );\n}\n\nexport function RallyViewer<TLocale extends string = string>({\n config: providedConfig,\n client,\n adapter,\n locale,\n dictionary,\n classNames = {},\n styles = {},\n style,\n customConditionRenderers = {},\n onSyncEvent,\n headerSlot,\n footerSlot,\n renderSpotCard,\n renderRewardCard,\n renderStatusBadge,\n renderVerifyingState,\n renderSuccessFeedback,\n renderErrorFeedback,\n renderSyncStatus,\n showSyncStatus = true,\n}: RallyViewerProps<TLocale>): ReactElement {\n const config = providedConfig ?? client?.getConfig() ?? adapter?.config;\n const [state, setState] = useState<UserRallyState | null>(() => client?.getState() ?? null);\n const [busy, setBusy] = useState<string | null>(null);\n const [feedback, setFeedback] = useState<CheckInResult | null>(null);\n const [syncStatus, setSyncStatus] = useState<SyncStateContext>(() => ({\n syncState: client?.syncState ?? \"idle\",\n isSyncing: client?.syncState === \"syncing\",\n pendingCount: client?.pendingCount ?? 0,\n rejectedHistory: client?.rejectedHistory ?? [],\n storageCapability: client?.storageCapability ?? \"custom\",\n isStoragePersistent: client?.isStoragePersistent ?? true,\n }));\n useEffect(() => {\n if (client === undefined) return;\n const unsubscribe = client.subscribe(setState);\n void client.init().then(setState);\n return unsubscribe;\n }, [client]);\n useEffect(() => {\n if (client === undefined || onSyncEvent === undefined) return;\n return client.subscribeSyncEvents(onSyncEvent);\n }, [client, onSyncEvent]);\n useEffect(() => {\n if (client === undefined) return;\n const update = (): void =>\n setSyncStatus({\n syncState: client.syncState,\n isSyncing: client.syncState === \"syncing\",\n pendingCount: client.pendingCount,\n rejectedHistory: client.rejectedHistory,\n storageCapability: client.storageCapability,\n isStoragePersistent: client.isStoragePersistent,\n });\n update();\n return client.subscribeSyncState(update);\n }, [client]);\n if (config === undefined) throw new Error(\"RallyViewer requires config, client, or adapter.\");\n const currentState = state ?? {\n rallyId: config.id,\n userId: null,\n records: [],\n rewards: [],\n updatedAt: \"\",\n };\n const progress = useMemo<StampRallyProgress>(\n () => calculateProgress(currentState, config),\n [config, currentState],\n );\n const checkIn =\n adapter?.onCheckIn ??\n (client === undefined\n ? undefined\n : (spotId: string, proof: unknown, options?: CheckInOptions) =>\n client.checkIn(spotId, proof, options));\n const claim =\n adapter?.onClaimReward ??\n (client === undefined\n ? undefined\n : (rewardId: string, options?: ClaimOptions) => client.claimReward(rewardId, options));\n const submit = useCallback(\n async (spotId: string, proof: unknown): Promise<CheckInResult | undefined> => {\n if (checkIn === undefined) return undefined;\n const target = config.spots.find((spot) => spot.id === spotId);\n if (target !== undefined && evaluateSpotStatus(target, currentState) === \"LOCKED\") {\n const result: CheckInResult = {\n ok: false,\n error: {\n code: \"PREREQUISITES_NOT_MET\",\n spotId,\n message: \"Complete the prerequisite spots before checking in.\",\n },\n };\n setFeedback(result);\n return result;\n }\n setBusy(spotId);\n const result = await checkIn(spotId, proof).finally(() => setBusy(null));\n setFeedback(result);\n return result;\n },\n [checkIn, config.spots, currentState],\n );\n return (\n <section\n className={classNames.root}\n style={styles.root ?? style}\n aria-label={label(dictionary, locale, \"viewer\", \"Stamp rally\")}\n >\n <header className={classNames.header} style={styles.header}>\n {typeof headerSlot === \"function\"\n ? headerSlot({ config, state: currentState })\n : headerSlot}\n {headerSlot === undefined && (\n <h1>{resolveLocalizedText(config.title, locale) || config.id}</h1>\n )}\n <progress\n aria-label={label(dictionary, locale, \"progress\", \"Progress\")}\n max={100}\n value={progress.percentage}\n />\n <span>\n {progress.acquired}/{progress.total}\n </span>\n </header>\n {busy !== null &&\n (renderVerifyingState?.() ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"status\">\n {label(dictionary, locale, \"verifying\", \"Verifying…\")}\n </div>\n ))}\n {feedback?.ok === true &&\n (renderSuccessFeedback?.(feedback) ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"status\">\n {label(dictionary, locale, \"verified\", \"Verified\")}\n </div>\n ))}\n {feedback?.ok === false &&\n (renderErrorFeedback?.(\n \"message\" in feedback.error ? feedback.error.message : feedback.error.code,\n ) ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"alert\">\n {\"message\" in feedback.error ? feedback.error.message : feedback.error.code}\n </div>\n ))}\n {showSyncStatus &&\n (renderSyncStatus?.(syncStatus) ?? (\n <SyncStatusBanner\n status={syncStatus}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n {...(classNames.feedback === undefined ? {} : { className: classNames.feedback })}\n {...(styles.feedback === undefined ? {} : { style: styles.feedback })}\n />\n ))}\n <div>\n {config.spots.map((spot) => {\n const status: SpotStatus =\n busy === spot.id ? \"VERIFYING\" : evaluateSpotStatus(spot, currentState);\n const claimed = status === \"CLAIMED\";\n const locked = status === \"LOCKED\";\n const children = spot.conditions.map((condition) => {\n const Renderer = customConditionRenderers[condition.type] ?? DefaultCondition;\n return (\n <div\n className={classNames.condition}\n style={styles.condition}\n key={`${spot.id}-${condition.type}-${JSON.stringify(condition)}`}\n >\n <Renderer\n spot={spot}\n condition={condition}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n disabled={busy !== null || claimed || locked}\n {...(Object.keys(classNames).length === 0 ? {} : { classNames })}\n {...(Object.keys(styles).length === 0 ? {} : { styles })}\n onSubmit={(proof) => submit(spot.id, proof)}\n />\n </div>\n );\n });\n const props: SpotCardProps<TLocale> = {\n spot,\n state: currentState,\n status,\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n children,\n };\n return (\n <div\n key={spot.id}\n className={classNames.card}\n style={styles.card}\n data-status={status}\n aria-disabled={locked}\n >\n {renderSpotCard?.(props) ?? (\n <article>\n {spot.iconUrl !== undefined && (\n <img src={spot.iconUrl} alt=\"\" width={32} height={32} />\n )}\n <h2>{resolveLocalizedText(spot.name, locale)}</h2>\n {spot.imageUrl !== undefined && <img src={spot.imageUrl} alt=\"\" loading=\"lazy\" />}\n {spot.description !== undefined && (\n <p>{resolveLocalizedText(spot.description, locale)}</p>\n )}\n {spot.hint !== undefined && <p>{resolveLocalizedText(spot.hint, locale)}</p>}\n {spot.externalReferences !== undefined && spot.externalReferences.length > 0 && (\n <span className={classNames.badge} style={styles.badge}>\n {label(dictionary, locale, \"externalReferences\", \"External references\")} (\n {spot.externalReferences.length})\n </span>\n )}\n {renderStatusBadge?.({ status }) ?? (\n <span className={classNames.badge} style={styles.badge}>\n {label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </span>\n )}\n {locked && (\n <p role=\"status\">\n {label(\n dictionary,\n locale,\n \"prerequisitesNotMet\",\n \"Complete the prerequisite spots before checking in.\",\n )}\n </p>\n )}\n {children}\n </article>\n )}\n </div>\n );\n })}\n </div>\n <section aria-label={label(dictionary, locale, \"rewards\", \"Rewards\")}>\n {config.rewards.map((reward) => {\n const props: RewardCardProps<TLocale> = {\n reward,\n state: currentState.rewards.find((item) => item.rewardId === reward.id),\n ...(currentState.inventory === undefined ? {} : { inventory: currentState.inventory }),\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n onClaim: claim,\n };\n return (\n <div key={reward.id} className={classNames.reward} style={styles.reward}>\n {renderRewardCard?.(props) ?? (\n <DefaultRewardCard {...props} classNames={classNames} styles={styles} />\n )}\n </div>\n );\n })}\n </section>\n <footer className={classNames.footer} style={styles.footer}>\n {footerSlot}\n </footer>\n </section>\n );\n}\n\nexport interface StampSheetProps<TLocale extends string = string>\n extends RallyViewerSlots<TLocale> {\n readonly config: RallyConfig<TLocale>;\n readonly state?: StampRallyState | null;\n readonly title?: string;\n readonly progress?: StampRallyProgress;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n readonly style?: ViewerStyle;\n}\nexport function StampSheet<TLocale extends string = string>({\n config,\n state,\n title,\n progress,\n locale = \"en\" as TLocale,\n dictionary,\n classNames = {},\n styles = {},\n style,\n headerSlot,\n footerSlot,\n renderSpotCard,\n renderStatusBadge,\n}: StampSheetProps<TLocale>): ReactElement {\n const currentState = state ?? {\n rallyId: config.id,\n userId: null,\n records: [],\n rewards: [],\n updatedAt: \"\",\n };\n const current = progress ?? calculateProgress(currentState, config);\n return (\n <section\n className={classNames.root}\n style={styles.root ?? style}\n aria-label={title ?? label(dictionary, locale, \"stampSheet\", \"Stamp sheet\")}\n >\n <header className={classNames.header} style={styles.header}>\n {typeof headerSlot === \"function\"\n ? headerSlot({ config, state: currentState })\n : (headerSlot ?? <h2>{title ?? resolveLocalizedText(config.title, locale)}</h2>)}\n <progress max={100} value={current.percentage} />\n </header>\n <div>\n {config.spots.map((spot) => {\n const status: SpotStatus = evaluateSpotStatus(spot, currentState);\n const props: SpotCardProps<TLocale> = {\n spot,\n state: currentState,\n status,\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n children: (\n <span className={classNames.slot} style={styles.slot}>\n {status === \"LOCKED\"\n ? label(dictionary, locale, \"status.locked\", \"🔒 LOCKED\")\n : status === \"CLAIMED\"\n ? label(dictionary, locale, \"status.claimed\", \"CLAIMED\")\n : label(dictionary, locale, \"status.unclaimed\", \"UNCLAIMED\")}\n </span>\n ),\n };\n return (\n <div\n key={spot.id}\n className={classNames.card}\n style={styles.card}\n data-status={status}\n aria-disabled={status === \"LOCKED\"}\n >\n {renderSpotCard?.(props) ?? (\n <span className={classNames.slot} style={styles.slot}>\n {spot.iconUrl !== undefined && (\n <img src={spot.iconUrl} alt=\"\" width={24} height={24} />\n )}\n {resolveLocalizedText(spot.name, locale)}{\" \"}\n {spot.description !== undefined && (\n <small>{resolveLocalizedText(spot.description, locale)}</small>\n )}{\" \"}\n {renderStatusBadge?.({ status }) ??\n label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n <footer className={classNames.footer} style={styles.footer}>\n {footerSlot}\n </footer>\n </section>\n );\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -1,11 +1,29 @@
1
- import { LocaleDictionary, PublicSpotItem, PublicCheckInCondition, PublicRallyConfig, UserRallyState, SpotStatus as SpotStatus$1, PublicReward, RewardState, RallyInventoryState, ClaimOptions, ClaimResult, CheckInResult, StampRallyClient, CheckInOptions, RallyConfig, StampRallyState, StampRallyProgress } from '@stamprally/core';
2
- import { ComponentType, CSSProperties, ReactNode, ReactElement } from 'react';
1
+ import { SyncState, RejectedOperationHistoryEntry, OfflineStorageCapability, LocaleDictionary, PublicSpotItem, PublicCheckInCondition, PublicRallyConfig, UserRallyState, SpotStatus as SpotStatus$1, PublicReward, RewardState, RallyInventoryState, ClaimOptions, ClaimResult, CheckInResult, StampRallyClient, CheckInOptions, SyncEventListener, RallyConfig, StampRallyState, StampRallyProgress } from '@stamprally/core';
2
+ import { CSSProperties, ReactElement, ComponentType, ReactNode } from 'react';
3
+
4
+ interface SyncStateContext {
5
+ readonly syncState: SyncState;
6
+ readonly isSyncing: boolean;
7
+ readonly pendingCount: number;
8
+ readonly rejectedHistory: ReadonlyArray<RejectedOperationHistoryEntry>;
9
+ readonly storageCapability: OfflineStorageCapability;
10
+ readonly isStoragePersistent: boolean;
11
+ }
12
+ interface SyncStatusBannerProps<TLocale extends string = string> {
13
+ readonly status: SyncStateContext;
14
+ readonly locale?: TLocale;
15
+ readonly dictionary?: LocaleDictionary<TLocale>;
16
+ readonly className?: string;
17
+ readonly style?: CSSProperties;
18
+ }
19
+ declare function SyncStatusBanner<TLocale extends string = "en">({ status, locale, dictionary, className, style, }: SyncStatusBannerProps<TLocale>): ReactElement | null;
3
20
 
4
21
  /** Complete built-in labels for the standard participant components. */
5
22
  declare const DEFAULT_UI_DICTIONARY: LocaleDictionary<"ja" | "en">;
6
23
  declare const UI_DICTIONARIES: Readonly<Record<"en" | "ja", Readonly<Record<string, string>>>>;
7
24
 
8
25
  type ViewerClassName = "root" | "header" | "card" | "condition" | "slot" | "badge" | "modal" | "button" | "action" | "feedback" | "reward" | "footer";
26
+ type ViewerSyncStateContext = SyncStateContext;
9
27
  type ViewerStyle = CSSProperties & {
10
28
  readonly [key: `--${string}`]: string | number | undefined;
11
29
  };
@@ -45,6 +63,7 @@ interface RallyViewerSlots<TLocale extends string = string> {
45
63
  readonly state: UserRallyState;
46
64
  }) => ReactNode);
47
65
  readonly footerSlot?: ReactNode;
66
+ readonly renderSyncStatus?: (status: SyncStateContext) => ReactNode;
48
67
  readonly renderSpotCard?: (props: SpotCardProps<TLocale>) => ReactNode;
49
68
  readonly renderRewardCard?: (props: RewardCardProps<TLocale>) => ReactNode;
50
69
  readonly renderStatusBadge?: (props: {
@@ -69,8 +88,10 @@ interface RallyViewerProps<TLocale extends string = string> extends RallyViewerS
69
88
  readonly styles?: ViewerStyles;
70
89
  readonly style?: ViewerStyle;
71
90
  readonly customConditionRenderers?: Partial<Record<PublicCheckInCondition["type"], ConditionRenderer<TLocale>>>;
91
+ readonly onSyncEvent?: SyncEventListener;
92
+ readonly showSyncStatus?: boolean;
72
93
  }
73
- declare function RallyViewer<TLocale extends string = string>({ config: providedConfig, client, adapter, locale, dictionary, classNames, styles, style, customConditionRenderers, headerSlot, footerSlot, renderSpotCard, renderRewardCard, renderStatusBadge, renderVerifyingState, renderSuccessFeedback, renderErrorFeedback, }: RallyViewerProps<TLocale>): ReactElement;
94
+ declare function RallyViewer<TLocale extends string = string>({ config: providedConfig, client, adapter, locale, dictionary, classNames, styles, style, customConditionRenderers, onSyncEvent, headerSlot, footerSlot, renderSpotCard, renderRewardCard, renderStatusBadge, renderVerifyingState, renderSuccessFeedback, renderErrorFeedback, renderSyncStatus, showSyncStatus, }: RallyViewerProps<TLocale>): ReactElement;
74
95
  interface StampSheetProps<TLocale extends string = string> extends RallyViewerSlots<TLocale> {
75
96
  readonly config: RallyConfig<TLocale>;
76
97
  readonly state?: StampRallyState | null;
@@ -84,4 +105,4 @@ interface StampSheetProps<TLocale extends string = string> extends RallyViewerSl
84
105
  }
85
106
  declare function StampSheet<TLocale extends string = string>({ config, state, title, progress, locale, dictionary, classNames, styles, style, headerSlot, footerSlot, renderSpotCard, renderStatusBadge, }: StampSheetProps<TLocale>): ReactElement;
86
107
 
87
- export { type ConditionRenderer, type ConditionRendererProps, DEFAULT_UI_DICTIONARY, RallyViewer, type RallyViewerAdapter, type RallyViewerProps, type RallyViewerSlots, type RewardCardProps, type SpotCardProps, type SpotStatus, StampSheet, type StampSheetProps, UI_DICTIONARIES, type ViewerClassName, type ViewerClassNames, type ViewerStyle, type ViewerStyles };
108
+ export { type ConditionRenderer, type ConditionRendererProps, DEFAULT_UI_DICTIONARY, RallyViewer, type RallyViewerAdapter, type RallyViewerProps, type RallyViewerSlots, type RewardCardProps, type SpotCardProps, type SpotStatus, StampSheet, type StampSheetProps, type SyncStateContext, SyncStatusBanner, type SyncStatusBannerProps, UI_DICTIONARIES, type ViewerClassName, type ViewerClassNames, type ViewerStyle, type ViewerStyles, type ViewerSyncStateContext };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,29 @@
1
- import { LocaleDictionary, PublicSpotItem, PublicCheckInCondition, PublicRallyConfig, UserRallyState, SpotStatus as SpotStatus$1, PublicReward, RewardState, RallyInventoryState, ClaimOptions, ClaimResult, CheckInResult, StampRallyClient, CheckInOptions, RallyConfig, StampRallyState, StampRallyProgress } from '@stamprally/core';
2
- import { ComponentType, CSSProperties, ReactNode, ReactElement } from 'react';
1
+ import { SyncState, RejectedOperationHistoryEntry, OfflineStorageCapability, LocaleDictionary, PublicSpotItem, PublicCheckInCondition, PublicRallyConfig, UserRallyState, SpotStatus as SpotStatus$1, PublicReward, RewardState, RallyInventoryState, ClaimOptions, ClaimResult, CheckInResult, StampRallyClient, CheckInOptions, SyncEventListener, RallyConfig, StampRallyState, StampRallyProgress } from '@stamprally/core';
2
+ import { CSSProperties, ReactElement, ComponentType, ReactNode } from 'react';
3
+
4
+ interface SyncStateContext {
5
+ readonly syncState: SyncState;
6
+ readonly isSyncing: boolean;
7
+ readonly pendingCount: number;
8
+ readonly rejectedHistory: ReadonlyArray<RejectedOperationHistoryEntry>;
9
+ readonly storageCapability: OfflineStorageCapability;
10
+ readonly isStoragePersistent: boolean;
11
+ }
12
+ interface SyncStatusBannerProps<TLocale extends string = string> {
13
+ readonly status: SyncStateContext;
14
+ readonly locale?: TLocale;
15
+ readonly dictionary?: LocaleDictionary<TLocale>;
16
+ readonly className?: string;
17
+ readonly style?: CSSProperties;
18
+ }
19
+ declare function SyncStatusBanner<TLocale extends string = "en">({ status, locale, dictionary, className, style, }: SyncStatusBannerProps<TLocale>): ReactElement | null;
3
20
 
4
21
  /** Complete built-in labels for the standard participant components. */
5
22
  declare const DEFAULT_UI_DICTIONARY: LocaleDictionary<"ja" | "en">;
6
23
  declare const UI_DICTIONARIES: Readonly<Record<"en" | "ja", Readonly<Record<string, string>>>>;
7
24
 
8
25
  type ViewerClassName = "root" | "header" | "card" | "condition" | "slot" | "badge" | "modal" | "button" | "action" | "feedback" | "reward" | "footer";
26
+ type ViewerSyncStateContext = SyncStateContext;
9
27
  type ViewerStyle = CSSProperties & {
10
28
  readonly [key: `--${string}`]: string | number | undefined;
11
29
  };
@@ -45,6 +63,7 @@ interface RallyViewerSlots<TLocale extends string = string> {
45
63
  readonly state: UserRallyState;
46
64
  }) => ReactNode);
47
65
  readonly footerSlot?: ReactNode;
66
+ readonly renderSyncStatus?: (status: SyncStateContext) => ReactNode;
48
67
  readonly renderSpotCard?: (props: SpotCardProps<TLocale>) => ReactNode;
49
68
  readonly renderRewardCard?: (props: RewardCardProps<TLocale>) => ReactNode;
50
69
  readonly renderStatusBadge?: (props: {
@@ -69,8 +88,10 @@ interface RallyViewerProps<TLocale extends string = string> extends RallyViewerS
69
88
  readonly styles?: ViewerStyles;
70
89
  readonly style?: ViewerStyle;
71
90
  readonly customConditionRenderers?: Partial<Record<PublicCheckInCondition["type"], ConditionRenderer<TLocale>>>;
91
+ readonly onSyncEvent?: SyncEventListener;
92
+ readonly showSyncStatus?: boolean;
72
93
  }
73
- declare function RallyViewer<TLocale extends string = string>({ config: providedConfig, client, adapter, locale, dictionary, classNames, styles, style, customConditionRenderers, headerSlot, footerSlot, renderSpotCard, renderRewardCard, renderStatusBadge, renderVerifyingState, renderSuccessFeedback, renderErrorFeedback, }: RallyViewerProps<TLocale>): ReactElement;
94
+ declare function RallyViewer<TLocale extends string = string>({ config: providedConfig, client, adapter, locale, dictionary, classNames, styles, style, customConditionRenderers, onSyncEvent, headerSlot, footerSlot, renderSpotCard, renderRewardCard, renderStatusBadge, renderVerifyingState, renderSuccessFeedback, renderErrorFeedback, renderSyncStatus, showSyncStatus, }: RallyViewerProps<TLocale>): ReactElement;
74
95
  interface StampSheetProps<TLocale extends string = string> extends RallyViewerSlots<TLocale> {
75
96
  readonly config: RallyConfig<TLocale>;
76
97
  readonly state?: StampRallyState | null;
@@ -84,4 +105,4 @@ interface StampSheetProps<TLocale extends string = string> extends RallyViewerSl
84
105
  }
85
106
  declare function StampSheet<TLocale extends string = string>({ config, state, title, progress, locale, dictionary, classNames, styles, style, headerSlot, footerSlot, renderSpotCard, renderStatusBadge, }: StampSheetProps<TLocale>): ReactElement;
86
107
 
87
- export { type ConditionRenderer, type ConditionRendererProps, DEFAULT_UI_DICTIONARY, RallyViewer, type RallyViewerAdapter, type RallyViewerProps, type RallyViewerSlots, type RewardCardProps, type SpotCardProps, type SpotStatus, StampSheet, type StampSheetProps, UI_DICTIONARIES, type ViewerClassName, type ViewerClassNames, type ViewerStyle, type ViewerStyles };
108
+ export { type ConditionRenderer, type ConditionRendererProps, DEFAULT_UI_DICTIONARY, RallyViewer, type RallyViewerAdapter, type RallyViewerProps, type RallyViewerSlots, type RewardCardProps, type SpotCardProps, type SpotStatus, StampSheet, type StampSheetProps, type SyncStateContext, SyncStatusBanner, type SyncStatusBannerProps, UI_DICTIONARIES, type ViewerClassName, type ViewerClassNames, type ViewerStyle, type ViewerStyles, type ViewerSyncStateContext };
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
3
  import { calculateProgress, evaluateSpotStatus, resolveLocalizedText, isQrSupported, isNfcSupported, readQrContext, getCurrentGeoContext, readNfcContext } from '@stamprally/core';
3
4
  import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
4
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  // src/locales/index.ts
7
7
  var DEFAULT_UI_DICTIONARY = {
@@ -35,7 +35,11 @@ var DEFAULT_UI_DICTIONARY = {
35
35
  "reward.lowStock": "Only a few left",
36
36
  "reward.remaining": "remaining",
37
37
  "reward.sharedRemaining": "Overall remaining",
38
- "reward.validUntil": "Valid until"
38
+ "reward.validUntil": "Valid until",
39
+ "sync.syncing": "Sending unsynced operations to the server...",
40
+ "sync.offline": "Recording offline",
41
+ "sync.unsynced": "unsynced",
42
+ "sync.rollback": "Some check-ins were rolled back by the server"
39
43
  },
40
44
  ja: {
41
45
  viewer: "\u30B9\u30BF\u30F3\u30D7\u30E9\u30EA\u30FC",
@@ -67,10 +71,53 @@ var DEFAULT_UI_DICTIONARY = {
67
71
  "reward.lowStock": "\u6B8B\u308A\u308F\u305A\u304B",
68
72
  "reward.remaining": "\u6B8B\u308A",
69
73
  "reward.sharedRemaining": "\u5168\u4F53\u3067\u6B8B\u308A",
70
- "reward.validUntil": "\u6709\u52B9\u671F\u9650"
74
+ "reward.validUntil": "\u6709\u52B9\u671F\u9650",
75
+ "sync.syncing": "\u672A\u540C\u671F\u306E\u64CD\u4F5C\u3092\u30B5\u30FC\u30D0\u30FC\u3078\u9001\u4FE1\u4E2D...",
76
+ "sync.offline": "\u30AA\u30D5\u30E9\u30A4\u30F3\u3067\u8A18\u9332\u4E2D",
77
+ "sync.unsynced": "\u672A\u540C\u671F",
78
+ "sync.rollback": "\u4E00\u90E8\u306E\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3\u304C\u30B5\u30FC\u30D0\u30FC\u306B\u3088\u308A\u53D6\u308A\u6D88\u3055\u308C\u307E\u3057\u305F"
71
79
  }
72
80
  };
73
81
  var UI_DICTIONARIES = DEFAULT_UI_DICTIONARY;
82
+ function text(dictionary, locale, key, fallback) {
83
+ return dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale]?.[key] ?? fallback;
84
+ }
85
+ function SyncStatusBanner({
86
+ status,
87
+ locale = "en",
88
+ dictionary,
89
+ className,
90
+ style
91
+ }) {
92
+ if (status.isSyncing)
93
+ return /* @__PURE__ */ jsxs("div", { className, style, role: "status", "aria-live": "polite", children: [
94
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u27F3" }),
95
+ " ",
96
+ text(dictionary, locale, "sync.syncing", "\u672A\u540C\u671F\u306E\u64CD\u4F5C\u3092\u30B5\u30FC\u30D0\u30FC\u3078\u9001\u4FE1\u4E2D...")
97
+ ] });
98
+ if (status.rejectedHistory.length > 0) {
99
+ const detail = status.rejectedHistory[status.rejectedHistory.length - 1]?.reason.message;
100
+ return /* @__PURE__ */ jsxs("div", { className, style, role: "alert", "aria-live": "assertive", children: [
101
+ /* @__PURE__ */ jsx("strong", { children: text(
102
+ dictionary,
103
+ locale,
104
+ "sync.rollback",
105
+ "\u4E00\u90E8\u306E\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3\u304C\u30B5\u30FC\u30D0\u30FC\u306B\u3088\u308A\u53D6\u308A\u6D88\u3055\u308C\u307E\u3057\u305F"
106
+ ) }),
107
+ detail === void 0 ? null : /* @__PURE__ */ jsx("span", { children: detail })
108
+ ] });
109
+ }
110
+ if (status.pendingCount > 0)
111
+ return /* @__PURE__ */ jsxs("div", { className, style, role: "status", "aria-live": "polite", children: [
112
+ text(dictionary, locale, "sync.offline", "\u30AA\u30D5\u30E9\u30A4\u30F3\u3067\u8A18\u9332\u4E2D"),
113
+ " (",
114
+ text(dictionary, locale, "sync.unsynced", "\u672A\u540C\u671F"),
115
+ ": ",
116
+ status.pendingCount,
117
+ "\u4EF6)"
118
+ ] });
119
+ return null;
120
+ }
74
121
  var label = (dictionary, locale, key, fallback) => dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale]?.[key] ?? fallback;
75
122
  var join = (...names) => {
76
123
  const value = names.filter((name) => name !== void 0 && name !== "").join(" ");
@@ -89,7 +136,7 @@ function DefaultCondition({
89
136
  const [status, setStatus] = useState("idle");
90
137
  const [error, setError] = useState(null);
91
138
  const videoRef = useRef(null);
92
- const text = (key, fallback) => label(dictionary, locale, key, fallback);
139
+ const text2 = (key, fallback) => label(dictionary, locale, key, fallback);
93
140
  const verify = async (proof) => {
94
141
  setStatus("loading");
95
142
  setError(null);
@@ -97,11 +144,11 @@ function DefaultCondition({
97
144
  const result = await onSubmit(proof);
98
145
  if (result !== void 0 && typeof result === "object" && result !== null && "ok" in result && result.ok === false) {
99
146
  setStatus("error");
100
- setError(text("verificationFailed", "Verification failed."));
147
+ setError(text2("verificationFailed", "Verification failed."));
101
148
  } else setStatus("success");
102
149
  } catch {
103
150
  setStatus("error");
104
- setError(text("verificationFailed", "Verification failed."));
151
+ setError(text2("verificationFailed", "Verification failed."));
105
152
  }
106
153
  };
107
154
  const readLocation = () => {
@@ -138,12 +185,12 @@ function DefaultCondition({
138
185
  return /* @__PURE__ */ jsxs("div", { children: [
139
186
  condition.type === "qr" && /* @__PURE__ */ jsxs(Fragment, { children: [
140
187
  /* @__PURE__ */ jsxs("label", { children: [
141
- text("qrValue", "QR value"),
188
+ text2("qrValue", "QR value"),
142
189
  /* @__PURE__ */ jsx(
143
190
  "input",
144
191
  {
145
- "aria-label": text("qrValue", "QR value"),
146
- placeholder: condition.qrEntryUrl ?? text("qrPlaceholder", "Paste a QR value"),
192
+ "aria-label": text2("qrValue", "QR value"),
193
+ placeholder: condition.qrEntryUrl ?? text2("qrPlaceholder", "Paste a QR value"),
147
194
  value,
148
195
  onChange: (event) => setValue(event.target.value)
149
196
  }
@@ -153,7 +200,7 @@ function DefaultCondition({
153
200
  "video",
154
201
  {
155
202
  ref: videoRef,
156
- "aria-label": text("qrCamera", "QR camera"),
203
+ "aria-label": text2("qrCamera", "QR camera"),
157
204
  hidden: !isQrSupported(),
158
205
  children: /* @__PURE__ */ jsx("track", { kind: "captions" })
159
206
  }
@@ -166,7 +213,7 @@ function DefaultCondition({
166
213
  style: styles?.button ?? styles?.action,
167
214
  disabled: disabled || !isQrSupported(),
168
215
  onClick: scanQr,
169
- children: text("scanQr", "Scan QR")
216
+ children: text2("scanQr", "Scan QR")
170
217
  }
171
218
  )
172
219
  ] }),
@@ -178,7 +225,7 @@ function DefaultCondition({
178
225
  style: styles?.button ?? styles?.action,
179
226
  disabled,
180
227
  onClick: readLocation,
181
- children: text("checkLocation", "Check location")
228
+ children: text2("checkLocation", "Check location")
182
229
  }
183
230
  ),
184
231
  condition.type === "nfc" && /* @__PURE__ */ jsx(
@@ -189,7 +236,7 @@ function DefaultCondition({
189
236
  style: styles?.button ?? styles?.action,
190
237
  disabled: disabled || !isNfcSupported(),
191
238
  onClick: readNfc,
192
- children: text("readNfc", "Read NFC")
239
+ children: text2("readNfc", "Read NFC")
193
240
  }
194
241
  ),
195
242
  (condition.type === "passcode" || condition.type === "custom" || condition.type === "qr") && /* @__PURE__ */ jsxs(
@@ -201,14 +248,14 @@ function DefaultCondition({
201
248
  },
202
249
  children: [
203
250
  /* @__PURE__ */ jsxs("label", { children: [
204
- text(
251
+ text2(
205
252
  condition.type === "passcode" ? "passcode" : "proof",
206
253
  condition.type === "passcode" ? "Passcode" : "Proof"
207
254
  ),
208
255
  /* @__PURE__ */ jsx(
209
256
  "input",
210
257
  {
211
- "aria-label": text("proof", "Proof"),
258
+ "aria-label": text2("proof", "Proof"),
212
259
  value,
213
260
  onChange: (event) => setValue(event.target.value)
214
261
  }
@@ -221,7 +268,7 @@ function DefaultCondition({
221
268
  className: join("sry-action", classNames?.action, classNames?.button),
222
269
  style: styles?.button ?? styles?.action,
223
270
  disabled: disabled || value.trim() === "",
224
- children: text("checkIn", "Check in")
271
+ children: text2("checkIn", "Check in")
225
272
  }
226
273
  )
227
274
  ]
@@ -235,9 +282,9 @@ function DefaultCondition({
235
282
  "aria-live": "polite",
236
283
  role: status === "error" ? "alert" : void 0,
237
284
  children: [
238
- status === "loading" && text("verifying", "Verifying\u2026"),
239
- status === "success" && text("verified", "Verified"),
240
- status === "error" && (error ?? text("verificationFailed", "Verification failed."))
285
+ status === "loading" && text2("verifying", "Verifying\u2026"),
286
+ status === "success" && text2("verified", "Verified"),
287
+ status === "error" && (error ?? text2("verificationFailed", "Verification failed."))
241
288
  ]
242
289
  }
243
290
  )
@@ -302,6 +349,7 @@ function RallyViewer({
302
349
  styles = {},
303
350
  style,
304
351
  customConditionRenderers = {},
352
+ onSyncEvent,
305
353
  headerSlot,
306
354
  footerSlot,
307
355
  renderSpotCard,
@@ -309,18 +357,45 @@ function RallyViewer({
309
357
  renderStatusBadge,
310
358
  renderVerifyingState,
311
359
  renderSuccessFeedback,
312
- renderErrorFeedback
360
+ renderErrorFeedback,
361
+ renderSyncStatus,
362
+ showSyncStatus = true
313
363
  }) {
314
364
  const config = providedConfig ?? client?.getConfig() ?? adapter?.config;
315
365
  const [state, setState] = useState(() => client?.getState() ?? null);
316
366
  const [busy, setBusy] = useState(null);
317
367
  const [feedback, setFeedback] = useState(null);
368
+ const [syncStatus, setSyncStatus] = useState(() => ({
369
+ syncState: client?.syncState ?? "idle",
370
+ isSyncing: client?.syncState === "syncing",
371
+ pendingCount: client?.pendingCount ?? 0,
372
+ rejectedHistory: client?.rejectedHistory ?? [],
373
+ storageCapability: client?.storageCapability ?? "custom",
374
+ isStoragePersistent: client?.isStoragePersistent ?? true
375
+ }));
318
376
  useEffect(() => {
319
377
  if (client === void 0) return;
320
378
  const unsubscribe = client.subscribe(setState);
321
379
  void client.init().then(setState);
322
380
  return unsubscribe;
323
381
  }, [client]);
382
+ useEffect(() => {
383
+ if (client === void 0 || onSyncEvent === void 0) return;
384
+ return client.subscribeSyncEvents(onSyncEvent);
385
+ }, [client, onSyncEvent]);
386
+ useEffect(() => {
387
+ if (client === void 0) return;
388
+ const update = () => setSyncStatus({
389
+ syncState: client.syncState,
390
+ isSyncing: client.syncState === "syncing",
391
+ pendingCount: client.pendingCount,
392
+ rejectedHistory: client.rejectedHistory,
393
+ storageCapability: client.storageCapability,
394
+ isStoragePersistent: client.isStoragePersistent
395
+ });
396
+ update();
397
+ return client.subscribeSyncState(update);
398
+ }, [client]);
324
399
  if (config === void 0) throw new Error("RallyViewer requires config, client, or adapter.");
325
400
  const currentState = state ?? {
326
401
  rallyId: config.id,
@@ -387,6 +462,16 @@ function RallyViewer({
387
462
  feedback?.ok === false && (renderErrorFeedback?.(
388
463
  "message" in feedback.error ? feedback.error.message : feedback.error.code
389
464
  ) ?? /* @__PURE__ */ jsx("div", { className: classNames.feedback, style: styles.feedback, role: "alert", children: "message" in feedback.error ? feedback.error.message : feedback.error.code })),
465
+ showSyncStatus && (renderSyncStatus?.(syncStatus) ?? /* @__PURE__ */ jsx(
466
+ SyncStatusBanner,
467
+ {
468
+ status: syncStatus,
469
+ locale,
470
+ ...dictionary === void 0 ? {} : { dictionary },
471
+ ...classNames.feedback === void 0 ? {} : { className: classNames.feedback },
472
+ ...styles.feedback === void 0 ? {} : { style: styles.feedback }
473
+ }
474
+ )),
390
475
  /* @__PURE__ */ jsx("div", { children: config.spots.map((spot) => {
391
476
  const status = busy === spot.id ? "VERIFYING" : evaluateSpotStatus(spot, currentState);
392
477
  const claimed = status === "CLAIMED";
@@ -540,6 +625,6 @@ function StampSheet({
540
625
  );
541
626
  }
542
627
 
543
- export { DEFAULT_UI_DICTIONARY, RallyViewer, StampSheet, UI_DICTIONARIES };
628
+ export { DEFAULT_UI_DICTIONARY, RallyViewer, StampSheet, SyncStatusBanner, UI_DICTIONARIES };
544
629
  //# sourceMappingURL=index.js.map
545
630
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/locales/index.ts","../src/index.tsx"],"names":["result"],"mappings":"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","file":"index.js","sourcesContent":["import type { LocaleDictionary } from \"@stamprally/core\";\n\n/** Complete built-in labels for the standard participant components. */\nexport const DEFAULT_UI_DICTIONARY: LocaleDictionary<\"ja\" | \"en\"> = {\n en: {\n viewer: \"Stamp rally\",\n stampSheet: \"Stamp sheet\",\n progress: \"Progress\",\n rewards: \"Rewards\",\n externalReferences: \"External references\",\n qrValue: \"QR value\",\n qrPlaceholder: \"Paste a QR value\",\n qrCamera: \"QR camera\",\n scanQr: \"Scan QR\",\n passcode: \"Passcode\",\n proof: \"Proof\",\n checkLocation: \"Check location\",\n readNfc: \"Read NFC\",\n checkIn: \"Check in\",\n verifying: \"Verifying…\",\n verified: \"Verified\",\n verificationFailed: \"Verification failed.\",\n prerequisitesNotMet: \"Complete the prerequisite spots before checking in.\",\n \"status.locked\": \"🔒 LOCKED\",\n \"status.unclaimed\": \"UNCLAIMED\",\n \"status.claimed\": \"CLAIMED\",\n \"status.verifying\": \"VERIFYING\",\n \"status.available\": \"AVAILABLE\",\n \"status.consumed\": \"CONSUMED\",\n \"status.expired\": \"EXPIRED\",\n \"status.onlyAFewLeft\": \"Only a few left\",\n \"reward.lowStock\": \"Only a few left\",\n \"reward.remaining\": \"remaining\",\n \"reward.sharedRemaining\": \"Overall remaining\",\n \"reward.validUntil\": \"Valid until\",\n },\n ja: {\n viewer: \"スタンプラリー\",\n stampSheet: \"スタンプシート\",\n progress: \"進捗\",\n rewards: \"景品\",\n externalReferences: \"関連リンク\",\n qrValue: \"QR値\",\n qrPlaceholder: \"QR値を入力\",\n qrCamera: \"QRカメラ\",\n scanQr: \"QRを読み取る\",\n passcode: \"パスコード\",\n proof: \"証明情報\",\n checkLocation: \"位置情報を確認\",\n readNfc: \"NFCを読み取る\",\n checkIn: \"チェックイン\",\n verifying: \"確認中…\",\n verified: \"確認済み\",\n verificationFailed: \"確認に失敗しました。\",\n prerequisitesNotMet: \"前提スポットをクリアしてください。\",\n \"status.locked\": \"🔒 ロック中\",\n \"status.unclaimed\": \"未取得\",\n \"status.claimed\": \"取得済み\",\n \"status.verifying\": \"確認中\",\n \"status.available\": \"利用可能\",\n \"status.consumed\": \"使用済み\",\n \"status.expired\": \"期限切れ\",\n \"status.onlyAFewLeft\": \"残りわずか\",\n \"reward.lowStock\": \"残りわずか\",\n \"reward.remaining\": \"残り\",\n \"reward.sharedRemaining\": \"全体で残り\",\n \"reward.validUntil\": \"有効期限\",\n },\n};\n\nexport const UI_DICTIONARIES = DEFAULT_UI_DICTIONARY;\n","\"use client\";\n\nimport type {\n CheckInOptions,\n CheckInResult,\n ClaimOptions,\n ClaimResult,\n SpotStatus as CoreSpotStatus,\n LocaleDictionary,\n PublicCheckInCondition,\n PublicRallyConfig,\n PublicReward,\n PublicSpotItem,\n RallyConfig,\n RallyInventoryState,\n RewardState,\n StampRallyClient,\n StampRallyProgress,\n StampRallyState,\n UserRallyState,\n} from \"@stamprally/core\";\nimport { DEFAULT_UI_DICTIONARY } from \"./locales/index.js\";\n\nexport { DEFAULT_UI_DICTIONARY, UI_DICTIONARIES } from \"./locales/index.js\";\n\nimport {\n calculateProgress,\n evaluateSpotStatus,\n getCurrentGeoContext,\n isNfcSupported,\n isQrSupported,\n readNfcContext,\n readQrContext,\n resolveLocalizedText,\n} from \"@stamprally/core\";\nimport {\n type ComponentType,\n type CSSProperties,\n type ReactElement,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type ViewerClassName =\n | \"root\"\n | \"header\"\n | \"card\"\n | \"condition\"\n | \"slot\"\n | \"badge\"\n | \"modal\"\n | \"button\"\n | \"action\"\n | \"feedback\"\n | \"reward\"\n | \"footer\";\nexport type ViewerStyle = CSSProperties & {\n readonly [key: `--${string}`]: string | number | undefined;\n};\nexport type ViewerStyles = Partial<Record<ViewerClassName, ViewerStyle>>;\nexport type ViewerClassNames = Partial<Record<ViewerClassName, string>>;\nexport type SpotStatus = CoreSpotStatus;\n\nexport interface ConditionRendererProps<TLocale extends string = string> {\n readonly spot: PublicSpotItem<TLocale>;\n readonly condition: PublicCheckInCondition;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly disabled: boolean;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n // biome-ignore lint/suspicious/noConfusingVoidType: custom renderers may fire-and-forget while built-ins await feedback.\n readonly onSubmit: (proof: unknown) => void | Promise<unknown>;\n}\nexport type ConditionRenderer<TLocale extends string = string> = ComponentType<\n ConditionRendererProps<TLocale>\n>;\n\nexport interface SpotCardProps<TLocale extends string = string> {\n readonly spot: PublicSpotItem<TLocale>;\n readonly state: UserRallyState;\n readonly status: SpotStatus;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly children: ReactNode;\n}\nexport interface RewardCardProps<TLocale extends string = string> {\n readonly reward: PublicReward<TLocale>;\n readonly state: RewardState | undefined;\n readonly inventory?: RallyInventoryState;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly onClaim:\n | ((rewardId: string, options?: ClaimOptions) => Promise<ClaimResult>)\n | undefined;\n}\nexport interface RallyViewerSlots<TLocale extends string = string> {\n readonly headerSlot?:\n | ReactNode\n | ((props: {\n readonly config: PublicRallyConfig<TLocale>;\n readonly state: UserRallyState;\n }) => ReactNode);\n readonly footerSlot?: ReactNode;\n readonly renderSpotCard?: (props: SpotCardProps<TLocale>) => ReactNode;\n readonly renderRewardCard?: (props: RewardCardProps<TLocale>) => ReactNode;\n readonly renderStatusBadge?: (props: { readonly status: SpotStatus }) => ReactNode;\n readonly renderVerifyingState?: () => ReactNode;\n readonly renderSuccessFeedback?: (result: CheckInResult) => ReactNode;\n readonly renderErrorFeedback?: (error: string) => ReactNode;\n}\n\nexport interface RallyViewerAdapter<TLocale extends string = string> {\n readonly config: PublicRallyConfig<TLocale>;\n readonly onCheckIn: (\n spotId: string,\n proof: unknown,\n options?: CheckInOptions,\n ) => Promise<CheckInResult>;\n readonly onClaimReward?: (rewardId: string, options?: ClaimOptions) => Promise<ClaimResult>;\n}\nexport interface RallyViewerProps<TLocale extends string = string>\n extends RallyViewerSlots<TLocale> {\n readonly config?: PublicRallyConfig<TLocale>;\n readonly client?: StampRallyClient;\n readonly adapter?: RallyViewerAdapter<TLocale>;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n readonly style?: ViewerStyle;\n readonly customConditionRenderers?: Partial<\n Record<PublicCheckInCondition[\"type\"], ConditionRenderer<TLocale>>\n >;\n}\n\nconst label = <TLocale extends string>(\n dictionary: LocaleDictionary<TLocale> | undefined,\n locale: TLocale,\n key: string,\n fallback: string,\n): string =>\n dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale as \"ja\" | \"en\"]?.[key] ?? fallback;\nconst join = (...names: ReadonlyArray<string | undefined>): string | undefined => {\n const value = names.filter((name): name is string => name !== undefined && name !== \"\").join(\" \");\n return value === \"\" ? undefined : value;\n};\ntype VerificationStatus = \"idle\" | \"loading\" | \"success\" | \"error\";\n\nfunction DefaultCondition<TLocale extends string>({\n condition,\n dictionary,\n locale,\n disabled,\n classNames,\n styles,\n onSubmit,\n}: ConditionRendererProps<TLocale>): ReactElement {\n const [value, setValue] = useState(\"\");\n const [status, setStatus] = useState<VerificationStatus>(\"idle\");\n const [error, setError] = useState<string | null>(null);\n const videoRef = useRef<HTMLVideoElement>(null);\n const text = (key: string, fallback: string): string => label(dictionary, locale, key, fallback);\n const verify = async (proof: unknown): Promise<void> => {\n setStatus(\"loading\");\n setError(null);\n try {\n const result = await onSubmit(proof);\n if (\n result !== undefined &&\n typeof result === \"object\" &&\n result !== null &&\n \"ok\" in result &&\n result.ok === false\n ) {\n setStatus(\"error\");\n setError(text(\"verificationFailed\", \"Verification failed.\"));\n } else setStatus(\"success\");\n } catch {\n setStatus(\"error\");\n setError(text(\"verificationFailed\", \"Verification failed.\"));\n }\n };\n const readLocation = (): void => {\n setStatus(\"loading\");\n void getCurrentGeoContext().then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n const readNfc = (): void => {\n setStatus(\"loading\");\n void readNfcContext().then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n const scanQr = (): void => {\n if (videoRef.current === null) return;\n setStatus(\"loading\");\n void readQrContext(videoRef.current).then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n return (\n <div>\n {condition.type === \"qr\" && (\n <>\n <label>\n {text(\"qrValue\", \"QR value\")}\n <input\n aria-label={text(\"qrValue\", \"QR value\")}\n placeholder={condition.qrEntryUrl ?? text(\"qrPlaceholder\", \"Paste a QR value\")}\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </label>\n <video\n ref={videoRef}\n aria-label={text(\"qrCamera\", \"QR camera\")}\n hidden={!isQrSupported()}\n >\n <track kind=\"captions\" />\n </video>\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || !isQrSupported()}\n onClick={scanQr}\n >\n {text(\"scanQr\", \"Scan QR\")}\n </button>\n </>\n )}\n {condition.type === \"gps\" && (\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled}\n onClick={readLocation}\n >\n {text(\"checkLocation\", \"Check location\")}\n </button>\n )}\n {condition.type === \"nfc\" && (\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || !isNfcSupported()}\n onClick={readNfc}\n >\n {text(\"readNfc\", \"Read NFC\")}\n </button>\n )}\n {(condition.type === \"passcode\" ||\n condition.type === \"custom\" ||\n condition.type === \"qr\") && (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void verify(value);\n }}\n >\n <label>\n {text(\n condition.type === \"passcode\" ? \"passcode\" : \"proof\",\n condition.type === \"passcode\" ? \"Passcode\" : \"Proof\",\n )}\n <input\n aria-label={text(\"proof\", \"Proof\")}\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </label>\n <button\n type=\"submit\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || value.trim() === \"\"}\n >\n {text(\"checkIn\", \"Check in\")}\n </button>\n </form>\n )}\n <div\n className={join(\"sry-feedback\", classNames?.feedback)}\n style={styles?.feedback}\n aria-live=\"polite\"\n role={status === \"error\" ? \"alert\" : undefined}\n >\n {status === \"loading\" && text(\"verifying\", \"Verifying…\")}\n {status === \"success\" && text(\"verified\", \"Verified\")}\n {status === \"error\" && (error ?? text(\"verificationFailed\", \"Verification failed.\"))}\n </div>\n </div>\n );\n}\n\nfunction DefaultRewardCard<TLocale extends string>({\n reward,\n state,\n inventory,\n locale,\n dictionary,\n onClaim,\n classNames,\n styles,\n}: RewardCardProps<TLocale> & {\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n}): ReactElement {\n const status = state?.status ?? \"LOCKED\";\n const configuredRemaining =\n inventory?.rewardRemaining?.[reward.id] ??\n (reward.stockLimit === undefined\n ? undefined\n : Math.max(0, reward.stockLimit - (state?.redeemedCount ?? 0)));\n const sharedRemaining = inventory?.sharedRemaining;\n const unavailable =\n status !== \"AVAILABLE\" ||\n onClaim === undefined ||\n sharedRemaining === 0 ||\n configuredRemaining === 0;\n const expiry = reward.validUntil === undefined ? undefined : new Date(reward.validUntil);\n return (\n <article className={classNames?.reward} style={styles?.reward}>\n <h3>{resolveLocalizedText(reward.title, locale)}</h3>\n {reward.description !== undefined && (\n <p>{resolveLocalizedText(reward.description, locale)}</p>\n )}\n {sharedRemaining !== undefined && (\n <span>\n {label(dictionary, locale, \"reward.sharedRemaining\", \"Overall remaining\")}:{\" \"}\n {sharedRemaining}\n </span>\n )}\n {configuredRemaining !== undefined && (\n <>\n {configuredRemaining <= 3 && (\n <span>{label(dictionary, locale, \"reward.lowStock\", \"Only a few left\")}</span>\n )}\n <span>\n {`${configuredRemaining} ${label(dictionary, locale, \"reward.remaining\", \"remaining\")}`}\n </span>\n </>\n )}\n {expiry !== undefined && !Number.isNaN(expiry.getTime()) && (\n <time dateTime={reward.validUntil}>\n {label(dictionary, locale, \"reward.validUntil\", \"Valid until\")}:{\" \"}\n {expiry.toLocaleString(locale)}\n </time>\n )}\n <button\n type=\"button\"\n className={join(classNames?.reward, classNames?.button)}\n style={styles?.button}\n disabled={unavailable}\n onClick={() => {\n if (onClaim !== undefined) void onClaim(reward.id);\n }}\n >\n {label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </button>\n </article>\n );\n}\n\nexport function RallyViewer<TLocale extends string = string>({\n config: providedConfig,\n client,\n adapter,\n locale,\n dictionary,\n classNames = {},\n styles = {},\n style,\n customConditionRenderers = {},\n headerSlot,\n footerSlot,\n renderSpotCard,\n renderRewardCard,\n renderStatusBadge,\n renderVerifyingState,\n renderSuccessFeedback,\n renderErrorFeedback,\n}: RallyViewerProps<TLocale>): ReactElement {\n const config = providedConfig ?? client?.getConfig() ?? adapter?.config;\n const [state, setState] = useState<UserRallyState | null>(() => client?.getState() ?? null);\n const [busy, setBusy] = useState<string | null>(null);\n const [feedback, setFeedback] = useState<CheckInResult | null>(null);\n useEffect(() => {\n if (client === undefined) return;\n const unsubscribe = client.subscribe(setState);\n void client.init().then(setState);\n return unsubscribe;\n }, [client]);\n if (config === undefined) throw new Error(\"RallyViewer requires config, client, or adapter.\");\n const currentState = state ?? {\n rallyId: config.id,\n userId: null,\n records: [],\n rewards: [],\n updatedAt: \"\",\n };\n const progress = useMemo<StampRallyProgress>(\n () => calculateProgress(currentState, config),\n [config, currentState],\n );\n const checkIn =\n adapter?.onCheckIn ??\n (client === undefined\n ? undefined\n : (spotId: string, proof: unknown, options?: CheckInOptions) =>\n client.checkIn(spotId, proof, options));\n const claim =\n adapter?.onClaimReward ??\n (client === undefined\n ? undefined\n : (rewardId: string, options?: ClaimOptions) => client.claimReward(rewardId, options));\n const submit = useCallback(\n async (spotId: string, proof: unknown): Promise<CheckInResult | undefined> => {\n if (checkIn === undefined) return undefined;\n const target = config.spots.find((spot) => spot.id === spotId);\n if (target !== undefined && evaluateSpotStatus(target, currentState) === \"LOCKED\") {\n const result: CheckInResult = {\n ok: false,\n error: {\n code: \"PREREQUISITES_NOT_MET\",\n spotId,\n message: \"Complete the prerequisite spots before checking in.\",\n },\n };\n setFeedback(result);\n return result;\n }\n setBusy(spotId);\n const result = await checkIn(spotId, proof).finally(() => setBusy(null));\n setFeedback(result);\n return result;\n },\n [checkIn, config.spots, currentState],\n );\n return (\n <section\n className={classNames.root}\n style={styles.root ?? style}\n aria-label={label(dictionary, locale, \"viewer\", \"Stamp rally\")}\n >\n <header className={classNames.header} style={styles.header}>\n {typeof headerSlot === \"function\"\n ? headerSlot({ config, state: currentState })\n : headerSlot}\n {headerSlot === undefined && (\n <h1>{resolveLocalizedText(config.title, locale) || config.id}</h1>\n )}\n <progress\n aria-label={label(dictionary, locale, \"progress\", \"Progress\")}\n max={100}\n value={progress.percentage}\n />\n <span>\n {progress.acquired}/{progress.total}\n </span>\n </header>\n {busy !== null &&\n (renderVerifyingState?.() ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"status\">\n {label(dictionary, locale, \"verifying\", \"Verifying…\")}\n </div>\n ))}\n {feedback?.ok === true &&\n (renderSuccessFeedback?.(feedback) ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"status\">\n {label(dictionary, locale, \"verified\", \"Verified\")}\n </div>\n ))}\n {feedback?.ok === false &&\n (renderErrorFeedback?.(\n \"message\" in feedback.error ? feedback.error.message : feedback.error.code,\n ) ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"alert\">\n {\"message\" in feedback.error ? feedback.error.message : feedback.error.code}\n </div>\n ))}\n <div>\n {config.spots.map((spot) => {\n const status: SpotStatus =\n busy === spot.id ? \"VERIFYING\" : evaluateSpotStatus(spot, currentState);\n const claimed = status === \"CLAIMED\";\n const locked = status === \"LOCKED\";\n const children = spot.conditions.map((condition) => {\n const Renderer = customConditionRenderers[condition.type] ?? DefaultCondition;\n return (\n <div\n className={classNames.condition}\n style={styles.condition}\n key={`${spot.id}-${condition.type}-${JSON.stringify(condition)}`}\n >\n <Renderer\n spot={spot}\n condition={condition}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n disabled={busy !== null || claimed || locked}\n {...(Object.keys(classNames).length === 0 ? {} : { classNames })}\n {...(Object.keys(styles).length === 0 ? {} : { styles })}\n onSubmit={(proof) => submit(spot.id, proof)}\n />\n </div>\n );\n });\n const props: SpotCardProps<TLocale> = {\n spot,\n state: currentState,\n status,\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n children,\n };\n return (\n <div\n key={spot.id}\n className={classNames.card}\n style={styles.card}\n data-status={status}\n aria-disabled={locked}\n >\n {renderSpotCard?.(props) ?? (\n <article>\n {spot.iconUrl !== undefined && (\n <img src={spot.iconUrl} alt=\"\" width={32} height={32} />\n )}\n <h2>{resolveLocalizedText(spot.name, locale)}</h2>\n {spot.imageUrl !== undefined && <img src={spot.imageUrl} alt=\"\" loading=\"lazy\" />}\n {spot.description !== undefined && (\n <p>{resolveLocalizedText(spot.description, locale)}</p>\n )}\n {spot.hint !== undefined && <p>{resolveLocalizedText(spot.hint, locale)}</p>}\n {spot.externalReferences !== undefined && spot.externalReferences.length > 0 && (\n <span className={classNames.badge} style={styles.badge}>\n {label(dictionary, locale, \"externalReferences\", \"External references\")} (\n {spot.externalReferences.length})\n </span>\n )}\n {renderStatusBadge?.({ status }) ?? (\n <span className={classNames.badge} style={styles.badge}>\n {label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </span>\n )}\n {locked && (\n <p role=\"status\">\n {label(\n dictionary,\n locale,\n \"prerequisitesNotMet\",\n \"Complete the prerequisite spots before checking in.\",\n )}\n </p>\n )}\n {children}\n </article>\n )}\n </div>\n );\n })}\n </div>\n <section aria-label={label(dictionary, locale, \"rewards\", \"Rewards\")}>\n {config.rewards.map((reward) => {\n const props: RewardCardProps<TLocale> = {\n reward,\n state: currentState.rewards.find((item) => item.rewardId === reward.id),\n ...(currentState.inventory === undefined ? {} : { inventory: currentState.inventory }),\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n onClaim: claim,\n };\n return (\n <div key={reward.id} className={classNames.reward} style={styles.reward}>\n {renderRewardCard?.(props) ?? (\n <DefaultRewardCard {...props} classNames={classNames} styles={styles} />\n )}\n </div>\n );\n })}\n </section>\n <footer className={classNames.footer} style={styles.footer}>\n {footerSlot}\n </footer>\n </section>\n );\n}\n\nexport interface StampSheetProps<TLocale extends string = string>\n extends RallyViewerSlots<TLocale> {\n readonly config: RallyConfig<TLocale>;\n readonly state?: StampRallyState | null;\n readonly title?: string;\n readonly progress?: StampRallyProgress;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n readonly style?: ViewerStyle;\n}\nexport function StampSheet<TLocale extends string = string>({\n config,\n state,\n title,\n progress,\n locale = \"en\" as TLocale,\n dictionary,\n classNames = {},\n styles = {},\n style,\n headerSlot,\n footerSlot,\n renderSpotCard,\n renderStatusBadge,\n}: StampSheetProps<TLocale>): ReactElement {\n const currentState = state ?? {\n rallyId: config.id,\n userId: null,\n records: [],\n rewards: [],\n updatedAt: \"\",\n };\n const current = progress ?? calculateProgress(currentState, config);\n return (\n <section\n className={classNames.root}\n style={styles.root ?? style}\n aria-label={title ?? label(dictionary, locale, \"stampSheet\", \"Stamp sheet\")}\n >\n <header className={classNames.header} style={styles.header}>\n {typeof headerSlot === \"function\"\n ? headerSlot({ config, state: currentState })\n : (headerSlot ?? <h2>{title ?? resolveLocalizedText(config.title, locale)}</h2>)}\n <progress max={100} value={current.percentage} />\n </header>\n <div>\n {config.spots.map((spot) => {\n const status: SpotStatus = evaluateSpotStatus(spot, currentState);\n const props: SpotCardProps<TLocale> = {\n spot,\n state: currentState,\n status,\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n children: (\n <span className={classNames.slot} style={styles.slot}>\n {status === \"LOCKED\"\n ? label(dictionary, locale, \"status.locked\", \"🔒 LOCKED\")\n : status === \"CLAIMED\"\n ? label(dictionary, locale, \"status.claimed\", \"CLAIMED\")\n : label(dictionary, locale, \"status.unclaimed\", \"UNCLAIMED\")}\n </span>\n ),\n };\n return (\n <div\n key={spot.id}\n className={classNames.card}\n style={styles.card}\n data-status={status}\n aria-disabled={status === \"LOCKED\"}\n >\n {renderSpotCard?.(props) ?? (\n <span className={classNames.slot} style={styles.slot}>\n {spot.iconUrl !== undefined && (\n <img src={spot.iconUrl} alt=\"\" width={24} height={24} />\n )}\n {resolveLocalizedText(spot.name, locale)}{\" \"}\n {spot.description !== undefined && (\n <small>{resolveLocalizedText(spot.description, locale)}</small>\n )}{\" \"}\n {renderStatusBadge?.({ status }) ??\n label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n <footer className={classNames.footer} style={styles.footer}>\n {footerSlot}\n </footer>\n </section>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/locales/index.ts","../src/components/SyncStatusBanner.tsx","../src/index.tsx"],"names":["text","jsxs","jsx","result"],"mappings":"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","file":"index.js","sourcesContent":["import type { LocaleDictionary } from \"@stamprally/core\";\n\n/** Complete built-in labels for the standard participant components. */\nexport const DEFAULT_UI_DICTIONARY: LocaleDictionary<\"ja\" | \"en\"> = {\n en: {\n viewer: \"Stamp rally\",\n stampSheet: \"Stamp sheet\",\n progress: \"Progress\",\n rewards: \"Rewards\",\n externalReferences: \"External references\",\n qrValue: \"QR value\",\n qrPlaceholder: \"Paste a QR value\",\n qrCamera: \"QR camera\",\n scanQr: \"Scan QR\",\n passcode: \"Passcode\",\n proof: \"Proof\",\n checkLocation: \"Check location\",\n readNfc: \"Read NFC\",\n checkIn: \"Check in\",\n verifying: \"Verifying…\",\n verified: \"Verified\",\n verificationFailed: \"Verification failed.\",\n prerequisitesNotMet: \"Complete the prerequisite spots before checking in.\",\n \"status.locked\": \"🔒 LOCKED\",\n \"status.unclaimed\": \"UNCLAIMED\",\n \"status.claimed\": \"CLAIMED\",\n \"status.verifying\": \"VERIFYING\",\n \"status.available\": \"AVAILABLE\",\n \"status.consumed\": \"CONSUMED\",\n \"status.expired\": \"EXPIRED\",\n \"status.onlyAFewLeft\": \"Only a few left\",\n \"reward.lowStock\": \"Only a few left\",\n \"reward.remaining\": \"remaining\",\n \"reward.sharedRemaining\": \"Overall remaining\",\n \"reward.validUntil\": \"Valid until\",\n \"sync.syncing\": \"Sending unsynced operations to the server...\",\n \"sync.offline\": \"Recording offline\",\n \"sync.unsynced\": \"unsynced\",\n \"sync.rollback\": \"Some check-ins were rolled back by the server\",\n },\n ja: {\n viewer: \"スタンプラリー\",\n stampSheet: \"スタンプシート\",\n progress: \"進捗\",\n rewards: \"景品\",\n externalReferences: \"関連リンク\",\n qrValue: \"QR値\",\n qrPlaceholder: \"QR値を入力\",\n qrCamera: \"QRカメラ\",\n scanQr: \"QRを読み取る\",\n passcode: \"パスコード\",\n proof: \"証明情報\",\n checkLocation: \"位置情報を確認\",\n readNfc: \"NFCを読み取る\",\n checkIn: \"チェックイン\",\n verifying: \"確認中…\",\n verified: \"確認済み\",\n verificationFailed: \"確認に失敗しました。\",\n prerequisitesNotMet: \"前提スポットをクリアしてください。\",\n \"status.locked\": \"🔒 ロック中\",\n \"status.unclaimed\": \"未取得\",\n \"status.claimed\": \"取得済み\",\n \"status.verifying\": \"確認中\",\n \"status.available\": \"利用可能\",\n \"status.consumed\": \"使用済み\",\n \"status.expired\": \"期限切れ\",\n \"status.onlyAFewLeft\": \"残りわずか\",\n \"reward.lowStock\": \"残りわずか\",\n \"reward.remaining\": \"残り\",\n \"reward.sharedRemaining\": \"全体で残り\",\n \"reward.validUntil\": \"有効期限\",\n \"sync.syncing\": \"未同期の操作をサーバーへ送信中...\",\n \"sync.offline\": \"オフラインで記録中\",\n \"sync.unsynced\": \"未同期\",\n \"sync.rollback\": \"一部のチェックインがサーバーにより取り消されました\",\n },\n};\n\nexport const UI_DICTIONARIES = DEFAULT_UI_DICTIONARY;\n","import type {\n LocaleDictionary,\n OfflineStorageCapability,\n RejectedOperationHistoryEntry,\n SyncState,\n} from \"@stamprally/core\";\nimport type { CSSProperties, ReactElement } from \"react\";\nimport { DEFAULT_UI_DICTIONARY } from \"../locales/index.js\";\n\nexport interface SyncStateContext {\n readonly syncState: SyncState;\n readonly isSyncing: boolean;\n readonly pendingCount: number;\n readonly rejectedHistory: ReadonlyArray<RejectedOperationHistoryEntry>;\n readonly storageCapability: OfflineStorageCapability;\n readonly isStoragePersistent: boolean;\n}\n\nexport interface SyncStatusBannerProps<TLocale extends string = string> {\n readonly status: SyncStateContext;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly className?: string;\n readonly style?: CSSProperties;\n}\n\nfunction text<TLocale extends string>(\n dictionary: LocaleDictionary<TLocale> | undefined,\n locale: TLocale,\n key: string,\n fallback: string,\n): string {\n return (\n dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale as \"ja\" | \"en\"]?.[key] ?? fallback\n );\n}\n\nexport function SyncStatusBanner<TLocale extends string = \"en\">({\n status,\n locale = \"en\" as TLocale,\n dictionary,\n className,\n style,\n}: SyncStatusBannerProps<TLocale>): ReactElement | null {\n if (status.isSyncing)\n return (\n <div className={className} style={style} role=\"status\" aria-live=\"polite\">\n <span aria-hidden=\"true\">⟳</span>{\" \"}\n {text(dictionary, locale, \"sync.syncing\", \"未同期の操作をサーバーへ送信中...\")}\n </div>\n );\n if (status.rejectedHistory.length > 0) {\n const detail = status.rejectedHistory[status.rejectedHistory.length - 1]?.reason.message;\n return (\n <div className={className} style={style} role=\"alert\" aria-live=\"assertive\">\n <strong>\n {text(\n dictionary,\n locale,\n \"sync.rollback\",\n \"一部のチェックインがサーバーにより取り消されました\",\n )}\n </strong>\n {detail === undefined ? null : <span>{detail}</span>}\n </div>\n );\n }\n if (status.pendingCount > 0)\n return (\n <div className={className} style={style} role=\"status\" aria-live=\"polite\">\n {text(dictionary, locale, \"sync.offline\", \"オフラインで記録中\")} (\n {text(dictionary, locale, \"sync.unsynced\", \"未同期\")}: {status.pendingCount}件)\n </div>\n );\n return null;\n}\n","\"use client\";\n\nimport type {\n CheckInOptions,\n CheckInResult,\n ClaimOptions,\n ClaimResult,\n SpotStatus as CoreSpotStatus,\n LocaleDictionary,\n PublicCheckInCondition,\n PublicRallyConfig,\n PublicReward,\n PublicSpotItem,\n RallyConfig,\n RallyInventoryState,\n RewardState,\n StampRallyClient,\n StampRallyProgress,\n StampRallyState,\n SyncEventListener,\n UserRallyState,\n} from \"@stamprally/core\";\nimport { type SyncStateContext, SyncStatusBanner } from \"./components/SyncStatusBanner.js\";\nimport { DEFAULT_UI_DICTIONARY } from \"./locales/index.js\";\n\nexport type { SyncStateContext, SyncStatusBannerProps } from \"./components/SyncStatusBanner.js\";\nexport { SyncStatusBanner } from \"./components/SyncStatusBanner.js\";\n\nexport { DEFAULT_UI_DICTIONARY, UI_DICTIONARIES } from \"./locales/index.js\";\n\nimport {\n calculateProgress,\n evaluateSpotStatus,\n getCurrentGeoContext,\n isNfcSupported,\n isQrSupported,\n readNfcContext,\n readQrContext,\n resolveLocalizedText,\n} from \"@stamprally/core\";\nimport {\n type ComponentType,\n type CSSProperties,\n type ReactElement,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nexport type ViewerClassName =\n | \"root\"\n | \"header\"\n | \"card\"\n | \"condition\"\n | \"slot\"\n | \"badge\"\n | \"modal\"\n | \"button\"\n | \"action\"\n | \"feedback\"\n | \"reward\"\n | \"footer\";\n\nexport type ViewerSyncStateContext = SyncStateContext;\nexport type ViewerStyle = CSSProperties & {\n readonly [key: `--${string}`]: string | number | undefined;\n};\nexport type ViewerStyles = Partial<Record<ViewerClassName, ViewerStyle>>;\nexport type ViewerClassNames = Partial<Record<ViewerClassName, string>>;\nexport type SpotStatus = CoreSpotStatus;\n\nexport interface ConditionRendererProps<TLocale extends string = string> {\n readonly spot: PublicSpotItem<TLocale>;\n readonly condition: PublicCheckInCondition;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly disabled: boolean;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n // biome-ignore lint/suspicious/noConfusingVoidType: custom renderers may fire-and-forget while built-ins await feedback.\n readonly onSubmit: (proof: unknown) => void | Promise<unknown>;\n}\nexport type ConditionRenderer<TLocale extends string = string> = ComponentType<\n ConditionRendererProps<TLocale>\n>;\n\nexport interface SpotCardProps<TLocale extends string = string> {\n readonly spot: PublicSpotItem<TLocale>;\n readonly state: UserRallyState;\n readonly status: SpotStatus;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly children: ReactNode;\n}\nexport interface RewardCardProps<TLocale extends string = string> {\n readonly reward: PublicReward<TLocale>;\n readonly state: RewardState | undefined;\n readonly inventory?: RallyInventoryState;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly onClaim:\n | ((rewardId: string, options?: ClaimOptions) => Promise<ClaimResult>)\n | undefined;\n}\nexport interface RallyViewerSlots<TLocale extends string = string> {\n readonly headerSlot?:\n | ReactNode\n | ((props: {\n readonly config: PublicRallyConfig<TLocale>;\n readonly state: UserRallyState;\n }) => ReactNode);\n readonly footerSlot?: ReactNode;\n readonly renderSyncStatus?: (status: SyncStateContext) => ReactNode;\n readonly renderSpotCard?: (props: SpotCardProps<TLocale>) => ReactNode;\n readonly renderRewardCard?: (props: RewardCardProps<TLocale>) => ReactNode;\n readonly renderStatusBadge?: (props: { readonly status: SpotStatus }) => ReactNode;\n readonly renderVerifyingState?: () => ReactNode;\n readonly renderSuccessFeedback?: (result: CheckInResult) => ReactNode;\n readonly renderErrorFeedback?: (error: string) => ReactNode;\n}\n\nexport interface RallyViewerAdapter<TLocale extends string = string> {\n readonly config: PublicRallyConfig<TLocale>;\n readonly onCheckIn: (\n spotId: string,\n proof: unknown,\n options?: CheckInOptions,\n ) => Promise<CheckInResult>;\n readonly onClaimReward?: (rewardId: string, options?: ClaimOptions) => Promise<ClaimResult>;\n}\nexport interface RallyViewerProps<TLocale extends string = string>\n extends RallyViewerSlots<TLocale> {\n readonly config?: PublicRallyConfig<TLocale>;\n readonly client?: StampRallyClient;\n readonly adapter?: RallyViewerAdapter<TLocale>;\n readonly locale: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n readonly style?: ViewerStyle;\n readonly customConditionRenderers?: Partial<\n Record<PublicCheckInCondition[\"type\"], ConditionRenderer<TLocale>>\n >;\n readonly onSyncEvent?: SyncEventListener;\n readonly showSyncStatus?: boolean;\n}\n\nconst label = <TLocale extends string>(\n dictionary: LocaleDictionary<TLocale> | undefined,\n locale: TLocale,\n key: string,\n fallback: string,\n): string =>\n dictionary?.[locale]?.[key] ?? DEFAULT_UI_DICTIONARY[locale as \"ja\" | \"en\"]?.[key] ?? fallback;\nconst join = (...names: ReadonlyArray<string | undefined>): string | undefined => {\n const value = names.filter((name): name is string => name !== undefined && name !== \"\").join(\" \");\n return value === \"\" ? undefined : value;\n};\ntype VerificationStatus = \"idle\" | \"loading\" | \"success\" | \"error\";\n\nfunction DefaultCondition<TLocale extends string>({\n condition,\n dictionary,\n locale,\n disabled,\n classNames,\n styles,\n onSubmit,\n}: ConditionRendererProps<TLocale>): ReactElement {\n const [value, setValue] = useState(\"\");\n const [status, setStatus] = useState<VerificationStatus>(\"idle\");\n const [error, setError] = useState<string | null>(null);\n const videoRef = useRef<HTMLVideoElement>(null);\n const text = (key: string, fallback: string): string => label(dictionary, locale, key, fallback);\n const verify = async (proof: unknown): Promise<void> => {\n setStatus(\"loading\");\n setError(null);\n try {\n const result = await onSubmit(proof);\n if (\n result !== undefined &&\n typeof result === \"object\" &&\n result !== null &&\n \"ok\" in result &&\n result.ok === false\n ) {\n setStatus(\"error\");\n setError(text(\"verificationFailed\", \"Verification failed.\"));\n } else setStatus(\"success\");\n } catch {\n setStatus(\"error\");\n setError(text(\"verificationFailed\", \"Verification failed.\"));\n }\n };\n const readLocation = (): void => {\n setStatus(\"loading\");\n void getCurrentGeoContext().then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n const readNfc = (): void => {\n setStatus(\"loading\");\n void readNfcContext().then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n const scanQr = (): void => {\n if (videoRef.current === null) return;\n setStatus(\"loading\");\n void readQrContext(videoRef.current).then((result) => {\n if (result.ok) void verify(result.value);\n else {\n setStatus(\"error\");\n setError(result.error.message);\n }\n });\n };\n return (\n <div>\n {condition.type === \"qr\" && (\n <>\n <label>\n {text(\"qrValue\", \"QR value\")}\n <input\n aria-label={text(\"qrValue\", \"QR value\")}\n placeholder={condition.qrEntryUrl ?? text(\"qrPlaceholder\", \"Paste a QR value\")}\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </label>\n <video\n ref={videoRef}\n aria-label={text(\"qrCamera\", \"QR camera\")}\n hidden={!isQrSupported()}\n >\n <track kind=\"captions\" />\n </video>\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || !isQrSupported()}\n onClick={scanQr}\n >\n {text(\"scanQr\", \"Scan QR\")}\n </button>\n </>\n )}\n {condition.type === \"gps\" && (\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled}\n onClick={readLocation}\n >\n {text(\"checkLocation\", \"Check location\")}\n </button>\n )}\n {condition.type === \"nfc\" && (\n <button\n type=\"button\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || !isNfcSupported()}\n onClick={readNfc}\n >\n {text(\"readNfc\", \"Read NFC\")}\n </button>\n )}\n {(condition.type === \"passcode\" ||\n condition.type === \"custom\" ||\n condition.type === \"qr\") && (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void verify(value);\n }}\n >\n <label>\n {text(\n condition.type === \"passcode\" ? \"passcode\" : \"proof\",\n condition.type === \"passcode\" ? \"Passcode\" : \"Proof\",\n )}\n <input\n aria-label={text(\"proof\", \"Proof\")}\n value={value}\n onChange={(event) => setValue(event.target.value)}\n />\n </label>\n <button\n type=\"submit\"\n className={join(\"sry-action\", classNames?.action, classNames?.button)}\n style={styles?.button ?? styles?.action}\n disabled={disabled || value.trim() === \"\"}\n >\n {text(\"checkIn\", \"Check in\")}\n </button>\n </form>\n )}\n <div\n className={join(\"sry-feedback\", classNames?.feedback)}\n style={styles?.feedback}\n aria-live=\"polite\"\n role={status === \"error\" ? \"alert\" : undefined}\n >\n {status === \"loading\" && text(\"verifying\", \"Verifying…\")}\n {status === \"success\" && text(\"verified\", \"Verified\")}\n {status === \"error\" && (error ?? text(\"verificationFailed\", \"Verification failed.\"))}\n </div>\n </div>\n );\n}\n\nfunction DefaultRewardCard<TLocale extends string>({\n reward,\n state,\n inventory,\n locale,\n dictionary,\n onClaim,\n classNames,\n styles,\n}: RewardCardProps<TLocale> & {\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n}): ReactElement {\n const status = state?.status ?? \"LOCKED\";\n const configuredRemaining =\n inventory?.rewardRemaining?.[reward.id] ??\n (reward.stockLimit === undefined\n ? undefined\n : Math.max(0, reward.stockLimit - (state?.redeemedCount ?? 0)));\n const sharedRemaining = inventory?.sharedRemaining;\n const unavailable =\n status !== \"AVAILABLE\" ||\n onClaim === undefined ||\n sharedRemaining === 0 ||\n configuredRemaining === 0;\n const expiry = reward.validUntil === undefined ? undefined : new Date(reward.validUntil);\n return (\n <article className={classNames?.reward} style={styles?.reward}>\n <h3>{resolveLocalizedText(reward.title, locale)}</h3>\n {reward.description !== undefined && (\n <p>{resolveLocalizedText(reward.description, locale)}</p>\n )}\n {sharedRemaining !== undefined && (\n <span>\n {label(dictionary, locale, \"reward.sharedRemaining\", \"Overall remaining\")}:{\" \"}\n {sharedRemaining}\n </span>\n )}\n {configuredRemaining !== undefined && (\n <>\n {configuredRemaining <= 3 && (\n <span>{label(dictionary, locale, \"reward.lowStock\", \"Only a few left\")}</span>\n )}\n <span>\n {`${configuredRemaining} ${label(dictionary, locale, \"reward.remaining\", \"remaining\")}`}\n </span>\n </>\n )}\n {expiry !== undefined && !Number.isNaN(expiry.getTime()) && (\n <time dateTime={reward.validUntil}>\n {label(dictionary, locale, \"reward.validUntil\", \"Valid until\")}:{\" \"}\n {expiry.toLocaleString(locale)}\n </time>\n )}\n <button\n type=\"button\"\n className={join(classNames?.reward, classNames?.button)}\n style={styles?.button}\n disabled={unavailable}\n onClick={() => {\n if (onClaim !== undefined) void onClaim(reward.id);\n }}\n >\n {label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </button>\n </article>\n );\n}\n\nexport function RallyViewer<TLocale extends string = string>({\n config: providedConfig,\n client,\n adapter,\n locale,\n dictionary,\n classNames = {},\n styles = {},\n style,\n customConditionRenderers = {},\n onSyncEvent,\n headerSlot,\n footerSlot,\n renderSpotCard,\n renderRewardCard,\n renderStatusBadge,\n renderVerifyingState,\n renderSuccessFeedback,\n renderErrorFeedback,\n renderSyncStatus,\n showSyncStatus = true,\n}: RallyViewerProps<TLocale>): ReactElement {\n const config = providedConfig ?? client?.getConfig() ?? adapter?.config;\n const [state, setState] = useState<UserRallyState | null>(() => client?.getState() ?? null);\n const [busy, setBusy] = useState<string | null>(null);\n const [feedback, setFeedback] = useState<CheckInResult | null>(null);\n const [syncStatus, setSyncStatus] = useState<SyncStateContext>(() => ({\n syncState: client?.syncState ?? \"idle\",\n isSyncing: client?.syncState === \"syncing\",\n pendingCount: client?.pendingCount ?? 0,\n rejectedHistory: client?.rejectedHistory ?? [],\n storageCapability: client?.storageCapability ?? \"custom\",\n isStoragePersistent: client?.isStoragePersistent ?? true,\n }));\n useEffect(() => {\n if (client === undefined) return;\n const unsubscribe = client.subscribe(setState);\n void client.init().then(setState);\n return unsubscribe;\n }, [client]);\n useEffect(() => {\n if (client === undefined || onSyncEvent === undefined) return;\n return client.subscribeSyncEvents(onSyncEvent);\n }, [client, onSyncEvent]);\n useEffect(() => {\n if (client === undefined) return;\n const update = (): void =>\n setSyncStatus({\n syncState: client.syncState,\n isSyncing: client.syncState === \"syncing\",\n pendingCount: client.pendingCount,\n rejectedHistory: client.rejectedHistory,\n storageCapability: client.storageCapability,\n isStoragePersistent: client.isStoragePersistent,\n });\n update();\n return client.subscribeSyncState(update);\n }, [client]);\n if (config === undefined) throw new Error(\"RallyViewer requires config, client, or adapter.\");\n const currentState = state ?? {\n rallyId: config.id,\n userId: null,\n records: [],\n rewards: [],\n updatedAt: \"\",\n };\n const progress = useMemo<StampRallyProgress>(\n () => calculateProgress(currentState, config),\n [config, currentState],\n );\n const checkIn =\n adapter?.onCheckIn ??\n (client === undefined\n ? undefined\n : (spotId: string, proof: unknown, options?: CheckInOptions) =>\n client.checkIn(spotId, proof, options));\n const claim =\n adapter?.onClaimReward ??\n (client === undefined\n ? undefined\n : (rewardId: string, options?: ClaimOptions) => client.claimReward(rewardId, options));\n const submit = useCallback(\n async (spotId: string, proof: unknown): Promise<CheckInResult | undefined> => {\n if (checkIn === undefined) return undefined;\n const target = config.spots.find((spot) => spot.id === spotId);\n if (target !== undefined && evaluateSpotStatus(target, currentState) === \"LOCKED\") {\n const result: CheckInResult = {\n ok: false,\n error: {\n code: \"PREREQUISITES_NOT_MET\",\n spotId,\n message: \"Complete the prerequisite spots before checking in.\",\n },\n };\n setFeedback(result);\n return result;\n }\n setBusy(spotId);\n const result = await checkIn(spotId, proof).finally(() => setBusy(null));\n setFeedback(result);\n return result;\n },\n [checkIn, config.spots, currentState],\n );\n return (\n <section\n className={classNames.root}\n style={styles.root ?? style}\n aria-label={label(dictionary, locale, \"viewer\", \"Stamp rally\")}\n >\n <header className={classNames.header} style={styles.header}>\n {typeof headerSlot === \"function\"\n ? headerSlot({ config, state: currentState })\n : headerSlot}\n {headerSlot === undefined && (\n <h1>{resolveLocalizedText(config.title, locale) || config.id}</h1>\n )}\n <progress\n aria-label={label(dictionary, locale, \"progress\", \"Progress\")}\n max={100}\n value={progress.percentage}\n />\n <span>\n {progress.acquired}/{progress.total}\n </span>\n </header>\n {busy !== null &&\n (renderVerifyingState?.() ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"status\">\n {label(dictionary, locale, \"verifying\", \"Verifying…\")}\n </div>\n ))}\n {feedback?.ok === true &&\n (renderSuccessFeedback?.(feedback) ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"status\">\n {label(dictionary, locale, \"verified\", \"Verified\")}\n </div>\n ))}\n {feedback?.ok === false &&\n (renderErrorFeedback?.(\n \"message\" in feedback.error ? feedback.error.message : feedback.error.code,\n ) ?? (\n <div className={classNames.feedback} style={styles.feedback} role=\"alert\">\n {\"message\" in feedback.error ? feedback.error.message : feedback.error.code}\n </div>\n ))}\n {showSyncStatus &&\n (renderSyncStatus?.(syncStatus) ?? (\n <SyncStatusBanner\n status={syncStatus}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n {...(classNames.feedback === undefined ? {} : { className: classNames.feedback })}\n {...(styles.feedback === undefined ? {} : { style: styles.feedback })}\n />\n ))}\n <div>\n {config.spots.map((spot) => {\n const status: SpotStatus =\n busy === spot.id ? \"VERIFYING\" : evaluateSpotStatus(spot, currentState);\n const claimed = status === \"CLAIMED\";\n const locked = status === \"LOCKED\";\n const children = spot.conditions.map((condition) => {\n const Renderer = customConditionRenderers[condition.type] ?? DefaultCondition;\n return (\n <div\n className={classNames.condition}\n style={styles.condition}\n key={`${spot.id}-${condition.type}-${JSON.stringify(condition)}`}\n >\n <Renderer\n spot={spot}\n condition={condition}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n disabled={busy !== null || claimed || locked}\n {...(Object.keys(classNames).length === 0 ? {} : { classNames })}\n {...(Object.keys(styles).length === 0 ? {} : { styles })}\n onSubmit={(proof) => submit(spot.id, proof)}\n />\n </div>\n );\n });\n const props: SpotCardProps<TLocale> = {\n spot,\n state: currentState,\n status,\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n children,\n };\n return (\n <div\n key={spot.id}\n className={classNames.card}\n style={styles.card}\n data-status={status}\n aria-disabled={locked}\n >\n {renderSpotCard?.(props) ?? (\n <article>\n {spot.iconUrl !== undefined && (\n <img src={spot.iconUrl} alt=\"\" width={32} height={32} />\n )}\n <h2>{resolveLocalizedText(spot.name, locale)}</h2>\n {spot.imageUrl !== undefined && <img src={spot.imageUrl} alt=\"\" loading=\"lazy\" />}\n {spot.description !== undefined && (\n <p>{resolveLocalizedText(spot.description, locale)}</p>\n )}\n {spot.hint !== undefined && <p>{resolveLocalizedText(spot.hint, locale)}</p>}\n {spot.externalReferences !== undefined && spot.externalReferences.length > 0 && (\n <span className={classNames.badge} style={styles.badge}>\n {label(dictionary, locale, \"externalReferences\", \"External references\")} (\n {spot.externalReferences.length})\n </span>\n )}\n {renderStatusBadge?.({ status }) ?? (\n <span className={classNames.badge} style={styles.badge}>\n {label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </span>\n )}\n {locked && (\n <p role=\"status\">\n {label(\n dictionary,\n locale,\n \"prerequisitesNotMet\",\n \"Complete the prerequisite spots before checking in.\",\n )}\n </p>\n )}\n {children}\n </article>\n )}\n </div>\n );\n })}\n </div>\n <section aria-label={label(dictionary, locale, \"rewards\", \"Rewards\")}>\n {config.rewards.map((reward) => {\n const props: RewardCardProps<TLocale> = {\n reward,\n state: currentState.rewards.find((item) => item.rewardId === reward.id),\n ...(currentState.inventory === undefined ? {} : { inventory: currentState.inventory }),\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n onClaim: claim,\n };\n return (\n <div key={reward.id} className={classNames.reward} style={styles.reward}>\n {renderRewardCard?.(props) ?? (\n <DefaultRewardCard {...props} classNames={classNames} styles={styles} />\n )}\n </div>\n );\n })}\n </section>\n <footer className={classNames.footer} style={styles.footer}>\n {footerSlot}\n </footer>\n </section>\n );\n}\n\nexport interface StampSheetProps<TLocale extends string = string>\n extends RallyViewerSlots<TLocale> {\n readonly config: RallyConfig<TLocale>;\n readonly state?: StampRallyState | null;\n readonly title?: string;\n readonly progress?: StampRallyProgress;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly classNames?: ViewerClassNames;\n readonly styles?: ViewerStyles;\n readonly style?: ViewerStyle;\n}\nexport function StampSheet<TLocale extends string = string>({\n config,\n state,\n title,\n progress,\n locale = \"en\" as TLocale,\n dictionary,\n classNames = {},\n styles = {},\n style,\n headerSlot,\n footerSlot,\n renderSpotCard,\n renderStatusBadge,\n}: StampSheetProps<TLocale>): ReactElement {\n const currentState = state ?? {\n rallyId: config.id,\n userId: null,\n records: [],\n rewards: [],\n updatedAt: \"\",\n };\n const current = progress ?? calculateProgress(currentState, config);\n return (\n <section\n className={classNames.root}\n style={styles.root ?? style}\n aria-label={title ?? label(dictionary, locale, \"stampSheet\", \"Stamp sheet\")}\n >\n <header className={classNames.header} style={styles.header}>\n {typeof headerSlot === \"function\"\n ? headerSlot({ config, state: currentState })\n : (headerSlot ?? <h2>{title ?? resolveLocalizedText(config.title, locale)}</h2>)}\n <progress max={100} value={current.percentage} />\n </header>\n <div>\n {config.spots.map((spot) => {\n const status: SpotStatus = evaluateSpotStatus(spot, currentState);\n const props: SpotCardProps<TLocale> = {\n spot,\n state: currentState,\n status,\n locale,\n ...(dictionary === undefined ? {} : { dictionary }),\n children: (\n <span className={classNames.slot} style={styles.slot}>\n {status === \"LOCKED\"\n ? label(dictionary, locale, \"status.locked\", \"🔒 LOCKED\")\n : status === \"CLAIMED\"\n ? label(dictionary, locale, \"status.claimed\", \"CLAIMED\")\n : label(dictionary, locale, \"status.unclaimed\", \"UNCLAIMED\")}\n </span>\n ),\n };\n return (\n <div\n key={spot.id}\n className={classNames.card}\n style={styles.card}\n data-status={status}\n aria-disabled={status === \"LOCKED\"}\n >\n {renderSpotCard?.(props) ?? (\n <span className={classNames.slot} style={styles.slot}>\n {spot.iconUrl !== undefined && (\n <img src={spot.iconUrl} alt=\"\" width={24} height={24} />\n )}\n {resolveLocalizedText(spot.name, locale)}{\" \"}\n {spot.description !== undefined && (\n <small>{resolveLocalizedText(spot.description, locale)}</small>\n )}{\" \"}\n {renderStatusBadge?.({ status }) ??\n label(dictionary, locale, `status.${status.toLowerCase()}`, status)}\n </span>\n )}\n </div>\n );\n })}\n </div>\n <footer className={classNames.footer} style={styles.footer}>\n {footerSlot}\n </footer>\n </section>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stamprally/ui",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Accessible participant UI components for stamp rallies.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -32,8 +32,8 @@
32
32
  "./styles.css": "./dist/index.css"
33
33
  },
34
34
  "dependencies": {
35
- "@stamprally/core": "0.16.0",
36
- "@stamprally/react": "0.16.0"
35
+ "@stamprally/core": "0.18.0",
36
+ "@stamprally/react": "0.18.0"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "react": "^18.0.0 || ^19.0.0",