@stamprally/ui 0.6.0 → 0.8.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/dist/index.cjs +138 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -4
- package/dist/index.d.ts +21 -4
- package/dist/index.js +138 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,121 @@ var react = require('react');
|
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
|
|
7
7
|
// src/index.tsx
|
|
8
|
+
function RallyViewer({
|
|
9
|
+
config,
|
|
10
|
+
adapter,
|
|
11
|
+
client,
|
|
12
|
+
locale,
|
|
13
|
+
onSpotSelect
|
|
14
|
+
}) {
|
|
15
|
+
const activeLocale = locale ?? "en";
|
|
16
|
+
const resolvedConfig = adapter?.config ?? config ?? client?.getConfig();
|
|
17
|
+
const renderConfig = resolvedConfig ?? {
|
|
18
|
+
id: "empty",
|
|
19
|
+
title: "",
|
|
20
|
+
spots: [],
|
|
21
|
+
rewards: []
|
|
22
|
+
};
|
|
23
|
+
const emptyState = {
|
|
24
|
+
rallyId: renderConfig.id,
|
|
25
|
+
records: [],
|
|
26
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString()
|
|
27
|
+
};
|
|
28
|
+
const resolvedState = adapter?.state ?? client?.getState() ?? emptyState;
|
|
29
|
+
const [selectedSpotId, setSelectedSpotId] = react.useState(null);
|
|
30
|
+
const [proof, setProof] = react.useState("");
|
|
31
|
+
const [feedback, setFeedback] = react.useState(null);
|
|
32
|
+
const [, setClientRevision] = react.useState(0);
|
|
33
|
+
react.useEffect(() => {
|
|
34
|
+
if (client === void 0) return;
|
|
35
|
+
return client.subscribe(() => setClientRevision((revision) => revision + 1));
|
|
36
|
+
}, [client]);
|
|
37
|
+
const selectedSpot = renderConfig.spots.find((spot) => spot.id === selectedSpotId);
|
|
38
|
+
const checkIn = adapter?.onCheckIn ?? (client === void 0 ? void 0 : (spotId, value) => client.checkIn(spotId, value));
|
|
39
|
+
const claimReward = adapter?.onClaimReward ?? (client === void 0 ? void 0 : (rewardId, options) => client.claimReward(rewardId, options));
|
|
40
|
+
const claimed = new Set(resolvedState.records.map((record) => record.stampId));
|
|
41
|
+
const submit = async () => {
|
|
42
|
+
if (selectedSpot === void 0 || checkIn === void 0) return;
|
|
43
|
+
const result = await checkIn(selectedSpot.id, proof);
|
|
44
|
+
setFeedback(result.ok ? "Check-in completed." : result.error.code);
|
|
45
|
+
if (result.ok) {
|
|
46
|
+
setProof("");
|
|
47
|
+
setSelectedSpotId(null);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
if (resolvedConfig === void 0) return null;
|
|
51
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-label": "Stamp rally viewer", className: "stamprally-viewer", children: [
|
|
52
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { children: [
|
|
53
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { children: core.resolveLocalizedText(renderConfig.title, activeLocale) }),
|
|
54
|
+
renderConfig.description !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { children: core.resolveLocalizedText(renderConfig.description, activeLocale) }),
|
|
55
|
+
adapter?.onSync !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void adapter.onSync?.(), children: "Sync" })
|
|
56
|
+
] }),
|
|
57
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { role: "grid", "aria-label": "Stamp rally spots", children: renderConfig.spots.map((spot, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
58
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
59
|
+
"button",
|
|
60
|
+
{
|
|
61
|
+
type: "button",
|
|
62
|
+
"aria-label": `${core.resolveLocalizedText(spot.name, activeLocale)}${claimed.has(spot.id) ? ", claimed" : ", available"}`,
|
|
63
|
+
onClick: () => {
|
|
64
|
+
onSpotSelect?.(spot.id);
|
|
65
|
+
setSelectedSpotId(spot.id);
|
|
66
|
+
setFeedback(null);
|
|
67
|
+
},
|
|
68
|
+
children: [
|
|
69
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { "aria-hidden": "true", children: [
|
|
70
|
+
"#",
|
|
71
|
+
String(index + 1).padStart(2, "0")
|
|
72
|
+
] }),
|
|
73
|
+
" ",
|
|
74
|
+
core.resolveLocalizedText(spot.name, activeLocale)
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
),
|
|
78
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: spot.conditions[0]?.type ?? "custom" })
|
|
79
|
+
] }, spot.id)) }),
|
|
80
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", "aria-live": "polite", children: feedback ?? `${claimed.size} / ${renderConfig.spots.length} claimed` }),
|
|
81
|
+
/* @__PURE__ */ jsxRuntime.jsxs("section", { "aria-label": "Rewards", children: [
|
|
82
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: "Rewards" }),
|
|
83
|
+
renderConfig.rewards.map((reward) => {
|
|
84
|
+
const rewardState = resolvedState.rewards?.find((item) => item.rewardId === reward.id);
|
|
85
|
+
const available = rewardState?.status === "AVAILABLE";
|
|
86
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("article", { children: [
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { children: core.resolveLocalizedText(reward.title, activeLocale) }),
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: rewardState?.status ?? "LOCKED" }),
|
|
89
|
+
claimReward !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
90
|
+
"button",
|
|
91
|
+
{
|
|
92
|
+
type: "button",
|
|
93
|
+
disabled: !available,
|
|
94
|
+
onClick: () => void claimReward(reward.id).then((result) => {
|
|
95
|
+
setFeedback(result.ok ? "Reward claimed." : result.error.code);
|
|
96
|
+
}),
|
|
97
|
+
children: "Claim reward"
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
] }, reward.id);
|
|
101
|
+
})
|
|
102
|
+
] }),
|
|
103
|
+
selectedSpot !== void 0 && checkIn !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "dialog", "aria-modal": "true", "aria-labelledby": "rally-viewer-spot-title", children: [
|
|
104
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: "rally-viewer-spot-title", children: core.resolveLocalizedText(selectedSpot.name, activeLocale) }),
|
|
105
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: core.resolveLocalizedText(selectedSpot.description, activeLocale) }),
|
|
106
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
107
|
+
"Proof",
|
|
108
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { value: proof, onChange: (event) => setProof(event.target.value) })
|
|
109
|
+
] }),
|
|
110
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
111
|
+
"button",
|
|
112
|
+
{
|
|
113
|
+
type: "button",
|
|
114
|
+
onClick: () => void submit(),
|
|
115
|
+
disabled: claimed.has(selectedSpot.id),
|
|
116
|
+
children: "Check in"
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => setSelectedSpotId(null), children: "Close" })
|
|
120
|
+
] })
|
|
121
|
+
] });
|
|
122
|
+
}
|
|
8
123
|
function useFocusTrap(active, onClose, closeDisabled = false) {
|
|
9
124
|
const containerRef = react.useRef(null);
|
|
10
125
|
react.useEffect(() => {
|
|
@@ -129,8 +244,29 @@ function StampSheet({
|
|
|
129
244
|
locale = "ja",
|
|
130
245
|
dictionary,
|
|
131
246
|
theme = config.theme ?? core.DEFAULT_SHEET_THEME,
|
|
132
|
-
onStampSelect
|
|
247
|
+
onStampSelect,
|
|
248
|
+
adapter
|
|
133
249
|
}) {
|
|
250
|
+
if ("spots" in config) {
|
|
251
|
+
if (adapter === void 0)
|
|
252
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
253
|
+
RallyViewer,
|
|
254
|
+
{
|
|
255
|
+
config,
|
|
256
|
+
locale,
|
|
257
|
+
...onStampSelect === void 0 ? {} : { onSpotSelect: onStampSelect }
|
|
258
|
+
}
|
|
259
|
+
);
|
|
260
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
261
|
+
RallyViewer,
|
|
262
|
+
{
|
|
263
|
+
config,
|
|
264
|
+
adapter,
|
|
265
|
+
locale,
|
|
266
|
+
...onStampSelect === void 0 ? {} : { onSpotSelect: onStampSelect }
|
|
267
|
+
}
|
|
268
|
+
);
|
|
269
|
+
}
|
|
134
270
|
const acquired = new Set(state?.records.map((record) => record.stampId) ?? []);
|
|
135
271
|
const next = new Set(progress?.nextAvailableStamps.map((stamp) => stamp.id) ?? []);
|
|
136
272
|
const count = progress?.acquired ?? acquired.size;
|
|
@@ -426,6 +562,7 @@ function RewardPanel({
|
|
|
426
562
|
);
|
|
427
563
|
}
|
|
428
564
|
|
|
565
|
+
exports.RallyViewer = RallyViewer;
|
|
429
566
|
exports.RewardPanel = RewardPanel;
|
|
430
567
|
exports.StampModal = StampModal;
|
|
431
568
|
exports.StampSheet = StampSheet;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"names":["useRef","useEffect","resolveLocalizedText","jsxs","jsx","DEFAULT_SHEET_THEME","useState"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n type ConsumeResult,\n DEFAULT_SHEET_THEME,\n type LocaleDictionary,\n type LocalizedText,\n type RallyConfig,\n type RewardItem,\n type RewardState,\n resolveLocalizedText,\n type SheetTheme,\n type SlotShape,\n type SpotItem,\n type StampRallyProgress,\n type StampRallyState,\n type SupportedLocale,\n type VerificationContext,\n} from \"@stamprally/core\";\nimport type { CSSProperties, FormEvent, RefObject } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport type { LocaleDictionary } from \"@stamprally/core\";\n\nfunction useFocusTrap(\n active: boolean,\n onClose: (() => void) | undefined,\n closeDisabled = false,\n): RefObject<HTMLDivElement | null> {\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!active) return;\n const container = containerRef.current;\n if (container === null) return;\n\n const focusableSelector =\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n const focusable = (): ReadonlyArray<HTMLElement> =>\n Array.from(container.querySelectorAll<HTMLElement>(focusableSelector));\n const first = focusable()[0];\n first?.focus();\n\n const handleKeyDown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n if (!closeDisabled) {\n event.preventDefault();\n onClose?.();\n }\n return;\n }\n if (event.key !== \"Tab\") return;\n\n const elements = focusable();\n if (elements.length === 0) {\n event.preventDefault();\n container.focus();\n return;\n }\n const firstElement = elements[0];\n const lastElement = elements[elements.length - 1];\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement?.focus();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement?.focus();\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [active, closeDisabled, onClose]);\n\n return containerRef;\n}\n\nexport interface StampPresentation {\n readonly label?: string;\n readonly icon?: string;\n readonly ink?: \"vermilion\" | \"indigo\";\n readonly channel?: \"instant\" | \"qr\" | \"nfc\" | \"geo\";\n}\n\nexport interface StampSlotProps<TLocale extends string = SupportedLocale> {\n readonly stamp: SpotItem<TLocale>;\n readonly record?: StampRallyState[\"records\"][number] | undefined;\n readonly isNext?: boolean;\n readonly slotNumber?: number;\n readonly presentation?: StampPresentation | undefined;\n readonly isAnimating?: boolean;\n readonly disabled?: boolean;\n readonly slotShape?: SlotShape;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly statusText?: string;\n readonly onSelect?: () => void;\n}\n\nconst FONT_STACKS: Readonly<Record<NonNullable<SheetTheme[\"fontFamily\"]>, string>> = {\n \"system-ui\": 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n serif: 'Georgia, \"Times New Roman\", \"Yu Mincho\", serif',\n \"rounded-sans\": '\"Arial Rounded MT Bold\", \"Hiragino Maru Gothic ProN\", \"Yu Gothic\", sans-serif',\n monospace: 'ui-monospace, SFMono-Regular, Consolas, \"Liberation Mono\", monospace',\n handwritten: '\"Segoe Print\", \"Bradley Hand\", \"Comic Sans MS\", cursive',\n};\n\nfunction formatStampDate(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n const pad = (part: number) => String(part).padStart(2, \"0\");\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;\n}\n\nexport function StampSlot<TLocale extends string = SupportedLocale>({\n stamp,\n record,\n isNext = false,\n slotNumber = 1,\n presentation = {},\n isAnimating = false,\n disabled = false,\n slotShape = \"rounded\",\n locale = \"ja\" as TLocale,\n statusText,\n onSelect,\n}: StampSlotProps<TLocale>) {\n const status = record === undefined ? (isNext ? \"available\" : \"locked\") : \"stamped\";\n const resolvedStatus = statusText ?? status;\n const statusSeparator = statusText !== undefined && locale === \"ja\" ? \"、\" : \", \";\n const name = resolveLocalizedText(stamp.name, locale);\n const label = presentation.label ?? stamp.condition.type;\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={onSelect}\n aria-label={`#${String(slotNumber).padStart(2, \"0\")} ${name}${statusSeparator}${resolvedStatus}`}\n aria-disabled={disabled}\n data-status={status}\n data-shape={slotShape}\n className={`stamp-slot stamp-slot--${status} stamp-slot--${presentation.ink ?? \"vermilion\"} stamp-slot--shape-${slotShape}${isAnimating ? \" stamp-slot--animating\" : \"\"}`}\n style={{ \"--stamp-primary\": \"var(--stamprally-primary, #9e551e)\" } as CSSProperties}\n >\n <span className=\"stamp-slot__topline\">\n <span className=\"stamp-slot__number\">#{String(slotNumber).padStart(2, \"0\")}</span>\n <span className={`stamp-slot__state stamp-slot__state--${status}`}>{resolvedStatus}</span>\n </span>\n <span className=\"stamp-slot__watermark\" aria-hidden=\"true\">\n {presentation.icon ?? \"✦\"}\n </span>\n <span className=\"stamp-slot__name\">{name}</span>\n <span className=\"stamp-slot__condition\">\n <span aria-hidden=\"true\">{presentation.icon ?? \"✦\"}</span>\n {label}\n </span>\n {record !== undefined && (\n <span\n className={`stamp-imprint ${isAnimating ? \"stamp-press\" : \"\"}`}\n role=\"img\"\n aria-label={`Acquired at ${formatStampDate(record.acquiredAt)}`}\n >\n <span className=\"stamp-imprint__inner\">\n <span className=\"stamp-imprint__word\">STAMP</span>\n <span className=\"stamp-imprint__date\">{formatStampDate(record.acquiredAt)}</span>\n </span>\n </span>\n )}\n </button>\n );\n}\n\nexport interface StampSheetProps<TLocale extends string = SupportedLocale> {\n readonly title?: LocalizedText<TLocale>;\n readonly config: RallyConfig<TLocale>;\n readonly state?: StampRallyState | null;\n readonly progress?: StampRallyProgress;\n readonly presentations?: Readonly<Record<string, StampPresentation>>;\n readonly animatedStampId?: string | null;\n readonly disabled?: boolean;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly theme?: SheetTheme;\n readonly onStampSelect?: (stampId: string) => void;\n}\n\nexport function StampSheet<TLocale extends string = SupportedLocale>({\n title,\n config,\n state = null,\n progress,\n presentations = {},\n animatedStampId = null,\n disabled = false,\n locale = \"ja\" as TLocale,\n dictionary,\n theme = config.theme ?? DEFAULT_SHEET_THEME,\n onStampSelect,\n}: StampSheetProps<TLocale>) {\n const acquired = new Set(state?.records.map((record) => record.stampId) ?? []);\n const next = new Set(progress?.nextAvailableStamps.map((stamp) => stamp.id) ?? []);\n const count = progress?.acquired ?? acquired.size;\n const total = progress?.total ?? config.stamps.length;\n const percentage = progress?.percentage ?? (total === 0 ? 0 : (count / total) * 100);\n const style = {\n \"--stamp-primary\": `var(--stamprally-primary-override, ${theme.primaryColor})`,\n \"--stamp-bg\": `var(--stamprally-background-override, ${theme.backgroundColor ?? DEFAULT_SHEET_THEME.backgroundColor ?? \"#ffffff\"})`,\n \"--stamp-card-bg\": `var(--stamprally-card-override, ${theme.cardBackgroundColor})`,\n \"--stamp-text\": `var(--stamprally-text-override, ${theme.textColor})`,\n \"--stamp-grid-cols\": String(theme.gridColumns),\n \"--stamp-grid-cols-mobile\": String(Math.min(theme.gridColumns, 2)),\n \"--stamp-unclaimed-opacity\": String(theme.unclaimedOpacity ?? 1),\n \"--stamp-font-family\": FONT_STACKS[theme.fontFamily ?? \"serif\"],\n ...(theme.completedStampColor === undefined\n ? {}\n : { \"--stamp-completed-color\": theme.completedStampColor }),\n \"--stamprally-primary\": `var(--stamprally-primary-override, ${theme.primaryColor})`,\n \"--stamprally-background\": `var(--stamprally-background-override, ${theme.backgroundColor ?? \"transparent\"})`,\n \"--stamprally-card\": `var(--stamprally-card-override, ${theme.cardBackgroundColor})`,\n \"--stamprally-text\": `var(--stamprally-text-override, ${theme.textColor})`,\n \"--stamprally-columns\": String(theme.gridColumns),\n } as CSSProperties;\n const messages = {\n available: dictionary?.[locale]?.available ?? (locale === \"en\" ? \"available\" : \"取得可能\"),\n locked: dictionary?.[locale]?.locked ?? (locale === \"en\" ? \"locked\" : \"順序待ち\"),\n stamped: dictionary?.[locale]?.stamped ?? (locale === \"en\" ? \"stamped\" : \"取得済み\"),\n remaining: (value: number) =>\n dictionary?.[locale]?.remaining?.replace(\"{count}\", String(value)) ??\n (locale === \"en\" ? `${value} spots remaining` : `あと${value}箇所`),\n completed:\n dictionary?.[locale]?.completed ?? (locale === \"en\" ? \"RALLY COMPLETED\" : \"ラリー達成\"),\n };\n return (\n <section\n className={`stamp-sheet ${percentage >= 100 ? \"stamp-sheet--completed\" : \"\"}`}\n style={style}\n aria-label={resolveLocalizedText(title, locale) || config.id}\n >\n <header className=\"stamp-sheet__header\">\n <h2>{resolveLocalizedText(title, locale) || config.id}</h2>\n <span className=\"stamp-sheet__score\" role=\"status\" aria-live=\"polite\">\n {count} / {total}\n </span>\n </header>\n <div className=\"stamp-sheet__progress-label\">\n <span>{messages.remaining(Math.max(0, total - count))}</span>\n <strong>{Math.round(percentage)}%</strong>\n </div>\n <div\n className=\"stamp-sheet__progress-track\"\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(percentage)}\n aria-label={locale === \"en\" ? \"Rally progress\" : \"スタンプ取得進捗\"}\n >\n <span\n className=\"stamp-sheet__progress-fill\"\n style={{ display: \"block\", width: `${percentage}%` }}\n />\n </div>\n <div className=\"stamp-sheet__grid\">\n {config.stamps.map((stamp, index) => {\n const recordForStamp = state?.records.find((record) => record.stampId === stamp.id);\n return (\n <StampSlot\n key={stamp.id}\n stamp={stamp}\n {...(recordForStamp === undefined ? {} : { record: recordForStamp })}\n isNext={next.has(stamp.id)}\n slotNumber={index + 1}\n {...(presentations[stamp.id] === undefined\n ? {}\n : { presentation: presentations[stamp.id] })}\n isAnimating={animatedStampId === stamp.id}\n disabled={disabled}\n slotShape={theme.slotShape}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n statusText={\n recordForStamp === undefined\n ? next.has(stamp.id)\n ? messages.available\n : messages.locked\n : messages.stamped\n }\n onSelect={() => onStampSelect?.(stamp.id)}\n />\n );\n })}\n </div>\n {percentage >= 100 && (\n <div className=\"stamp-sheet__complete-mark\" role=\"status\" aria-live=\"polite\">\n COMPLETE!!\n </div>\n )}\n {percentage >= 100 && (\n <div className=\"stamp-sheet__complete-message\">{messages.completed}</div>\n )}\n </section>\n );\n}\n\nexport interface AcquisitionFeedback {\n readonly ok: boolean;\n readonly message: string;\n}\nexport interface StampModalProps<TLocale extends string = SupportedLocale> {\n readonly open: boolean;\n readonly stamp: SpotItem<TLocale> | null;\n readonly record?: StampRallyState[\"records\"][number] | undefined;\n readonly presentation?: StampPresentation | null;\n readonly requiredStampName?: string | null;\n readonly isAvailable?: boolean;\n readonly isPending?: boolean;\n readonly isCompleted?: boolean;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly onClose: () => void;\n readonly onAcquire?: (\n stampId: string,\n context: VerificationContext,\n ) => Promise<AcquisitionFeedback>;\n readonly onCheckIn?: (\n stampId: string,\n context: VerificationContext,\n ) => Promise<AcquisitionFeedback>;\n readonly onNotify?: (feedback: AcquisitionFeedback) => void;\n}\n\nexport function StampModal<TLocale extends string = SupportedLocale>({\n open,\n stamp,\n record,\n isAvailable = true,\n isPending = false,\n locale = \"ja\" as TLocale,\n dictionary,\n onClose,\n onAcquire,\n onCheckIn,\n onNotify,\n}: StampModalProps<TLocale>) {\n const [token, setToken] = useState(\"\");\n const modalRef = useFocusTrap(open && stamp !== null, onClose, isPending);\n useEffect(() => {\n if (!open) setToken(\"\");\n }, [open]);\n if (!open || stamp === null) return null;\n const submit = async (context: VerificationContext): Promise<void> => {\n if (!isAvailable || record !== undefined) return;\n const handler = onAcquire ?? onCheckIn;\n if (handler === undefined) return;\n const feedback = await handler(stamp.id, context);\n onNotify?.(feedback);\n if (feedback.ok) onClose();\n };\n const name = resolveLocalizedText(stamp.name, locale);\n const messages = dictionary?.[locale] ?? {};\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"stamprally-modal-title\"\n className=\"stamprally-modal\"\n >\n <div className=\"stamprally-modal__panel\" ref={modalRef} tabIndex={-1}>\n <button\n type=\"button\"\n aria-label=\"Close stamp details\"\n aria-disabled={isPending}\n onClick={onClose}\n disabled={isPending}\n >\n ×\n </button>\n <h2 id=\"stamprally-modal-title\">{name}</h2>\n {record !== undefined ? (\n <p>{messages.alreadyClaimed ?? \"Already claimed.\"}</p>\n ) : (\n <p>{resolveLocalizedText(stamp.description, locale)}</p>\n )}\n {stamp.condition.type === \"token\" ? (\n <form\n onSubmit={(event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n void submit({ type: \"token\", token });\n }}\n >\n <label>\n {messages.passcode ?? \"Passcode\"}{\" \"}\n <input value={token} onChange={(event) => setToken(event.target.value)} />\n </label>\n <button\n type=\"submit\"\n aria-label=\"Claim stamp\"\n aria-disabled={!isAvailable || isPending}\n disabled={!isAvailable || isPending}\n >\n {messages.claimStamp ?? \"Claim stamp\"}\n </button>\n </form>\n ) : (\n <button\n type=\"button\"\n aria-label=\"Claim stamp\"\n aria-disabled={!isAvailable || isPending}\n onClick={() => void submit({ type: \"instant\" })}\n disabled={!isAvailable || isPending}\n >\n {messages.claimStamp ?? \"Claim stamp\"}\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport interface RewardPanelProps<TLocale extends string = SupportedLocale> {\n readonly rewards: ReadonlyArray<RewardItem<TLocale>>;\n readonly states: ReadonlyArray<RewardState>;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly isPending?: boolean;\n readonly open?: boolean;\n readonly onClose?: () => void;\n readonly onRedeem: (\n rewardId: string,\n options?: { readonly passcode?: string; readonly staffId?: string },\n ) => Promise<ConsumeResult>;\n readonly onNotify?: (ok: boolean, message: string) => void;\n}\n\nexport function RewardPanel<TLocale extends string = SupportedLocale>({\n rewards,\n states,\n locale = \"ja\" as TLocale,\n dictionary,\n isPending = false,\n open = true,\n onClose,\n onRedeem,\n onNotify,\n}: RewardPanelProps<TLocale>) {\n const [passcodes, setPasscodes] = useState<Readonly<Record<string, string>>>({});\n const panelRef = useFocusTrap(open && onClose !== undefined, onClose, isPending);\n if (!open) return null;\n return (\n <section\n ref={panelRef}\n role=\"dialog\"\n aria-labelledby=\"stamprally-rewards-title\"\n aria-modal=\"true\"\n className=\"stamprally-rewards\"\n tabIndex={-1}\n >\n <header className=\"stamprally-rewards__header\">\n <h2 id=\"stamprally-rewards-title\">{dictionary?.[locale]?.rewards ?? \"Rewards\"}</h2>\n {onClose !== undefined && (\n <button\n type=\"button\"\n aria-label=\"Close rewards\"\n aria-disabled={isPending}\n disabled={isPending}\n onClick={onClose}\n >\n ×\n </button>\n )}\n </header>\n {rewards.map((reward) => {\n const state = states.find((item) => item.rewardId === reward.id);\n const available = state?.status === \"AVAILABLE\";\n const redeem = async (options?: { readonly passcode?: string }): Promise<void> => {\n const result = await onRedeem(reward.id, options);\n onNotify?.(\n result.ok,\n result.ok\n ? (dictionary?.[locale]?.rewardClaimed ?? \"Reward claimed.\")\n : result.error.code,\n );\n };\n return (\n <article\n key={reward.id}\n className={`stamprally-reward stamprally-reward--${state?.status ?? \"LOCKED\"}`}\n >\n <h3>{resolveLocalizedText(reward.title, locale)}</h3>\n <p>{resolveLocalizedText(reward.description, locale)}</p>\n <span role=\"status\" aria-live=\"polite\">\n {state?.status ?? \"LOCKED\"}\n </span>\n {reward.redemptionMethod === \"staff_passcode\" && (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void redeem({ passcode: passcodes[reward.id] ?? \"\" });\n }}\n >\n <label>\n {dictionary?.[locale]?.staffPasscode ?? \"Staff passcode\"}{\" \"}\n <input\n type=\"password\"\n value={passcodes[reward.id] ?? \"\"}\n onChange={(event) =>\n setPasscodes((current) => ({ ...current, [reward.id]: event.target.value }))\n }\n />\n </label>\n <button\n type=\"submit\"\n aria-label={`Redeem ${resolveLocalizedText(reward.title, locale)}`}\n aria-disabled={!available || isPending}\n disabled={!available || isPending}\n >\n {dictionary?.[locale]?.redeem ?? \"Redeem\"}\n </button>\n </form>\n )}\n {reward.redemptionMethod !== \"staff_passcode\" && (\n <button\n type=\"button\"\n aria-label={`Redeem ${resolveLocalizedText(reward.title, locale)}`}\n aria-disabled={!available || isPending}\n disabled={!available || isPending}\n onClick={() => void redeem()}\n >\n {dictionary?.[locale]?.redeem ?? \"Redeem\"}\n </button>\n )}\n </article>\n );\n })}\n </section>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"names":["useState","useEffect","jsxs","jsx","resolveLocalizedText","useRef","DEFAULT_SHEET_THEME"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n type ClaimOptions,\n type ConsumeResult,\n DEFAULT_SHEET_THEME,\n type LocaleDictionary,\n type LocalizedText,\n type PublicRallyConfig,\n type RallyConfig,\n type RewardItem,\n type RewardState,\n resolveLocalizedText,\n type SheetTheme,\n type SlotShape,\n type SpotItem,\n type StampRallyProgress,\n type StampRallyState,\n type SupportedLocale,\n type UniversalCheckInResult,\n type UniversalClaimResult,\n type UniversalStampRallyClient,\n type UserRallyState,\n type VerificationContext,\n} from \"@stamprally/core\";\nimport type { CSSProperties, FormEvent, RefObject } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport type { LocaleDictionary } from \"@stamprally/core\";\n\nexport interface RallyViewerAdapter<TLocale extends string = string> {\n readonly state: UserRallyState;\n readonly config: PublicRallyConfig<TLocale>;\n readonly onCheckIn: (spotId: string, proof: unknown) => Promise<UniversalCheckInResult>;\n readonly onClaimReward: (\n rewardId: string,\n options?: ClaimOptions,\n ) => Promise<UniversalClaimResult>;\n readonly onSync?: () => Promise<void>;\n}\n\nexport interface RallyViewerProps<TLocale extends string = string> {\n readonly config?: PublicRallyConfig<TLocale>;\n readonly adapter?: RallyViewerAdapter<TLocale>;\n readonly client?: UniversalStampRallyClient;\n readonly locale?: TLocale;\n readonly onSpotSelect?: (spotId: string) => void;\n}\n\n/** Lightweight public-config viewer for applications that do not need the legacy StampSheet state model. */\nexport function RallyViewer<TLocale extends string = string>({\n config,\n adapter,\n client,\n locale,\n onSpotSelect,\n}: RallyViewerProps<TLocale>) {\n const activeLocale = locale ?? (\"en\" as TLocale);\n const resolvedConfig = adapter?.config ?? config ?? client?.getConfig();\n const renderConfig: PublicRallyConfig<TLocale> = resolvedConfig ?? {\n id: \"empty\",\n version: \"0.7.0\",\n title: \"\",\n spots: [],\n rewards: [],\n };\n const emptyState: UserRallyState = {\n rallyId: renderConfig.id,\n records: [],\n updatedAt: new Date(0).toISOString(),\n };\n const resolvedState = adapter?.state ?? client?.getState() ?? emptyState;\n const [selectedSpotId, setSelectedSpotId] = useState<string | null>(null);\n const [proof, setProof] = useState(\"\");\n const [feedback, setFeedback] = useState<string | null>(null);\n const [, setClientRevision] = useState(0);\n useEffect(() => {\n if (client === undefined) return;\n return client.subscribe(() => setClientRevision((revision) => revision + 1));\n }, [client]);\n const selectedSpot = renderConfig.spots.find((spot) => spot.id === selectedSpotId);\n const checkIn =\n adapter?.onCheckIn ??\n (client === undefined\n ? undefined\n : (spotId: string, value: unknown) => client.checkIn(spotId, value));\n const claimReward =\n adapter?.onClaimReward ??\n (client === undefined\n ? undefined\n : (rewardId: string, options?: ClaimOptions) => client.claimReward(rewardId, options));\n const claimed = new Set(resolvedState.records.map((record) => record.stampId));\n const submit = async (): Promise<void> => {\n if (selectedSpot === undefined || checkIn === undefined) return;\n const result = await checkIn(selectedSpot.id, proof);\n setFeedback(result.ok ? \"Check-in completed.\" : result.error.code);\n if (result.ok) {\n setProof(\"\");\n setSelectedSpotId(null);\n }\n };\n if (resolvedConfig === undefined) return null;\n return (\n <section aria-label=\"Stamp rally viewer\" className=\"stamprally-viewer\">\n <header>\n <h1>{resolveLocalizedText(renderConfig.title, activeLocale)}</h1>\n {renderConfig.description !== undefined && (\n <p>{resolveLocalizedText(renderConfig.description, activeLocale)}</p>\n )}\n {adapter?.onSync !== undefined && (\n <button type=\"button\" onClick={() => void adapter.onSync?.()}>\n Sync\n </button>\n )}\n </header>\n {/* biome-ignore lint/a11y/useSemanticElements: The viewer exposes the requested ARIA grid contract. */}\n <div role=\"grid\" aria-label=\"Stamp rally spots\">\n {renderConfig.spots.map((spot, index) => (\n <div key={spot.id}>\n <button\n type=\"button\"\n aria-label={`${resolveLocalizedText(spot.name, activeLocale)}${claimed.has(spot.id) ? \", claimed\" : \", available\"}`}\n onClick={() => {\n onSpotSelect?.(spot.id);\n setSelectedSpotId(spot.id);\n setFeedback(null);\n }}\n >\n <span aria-hidden=\"true\">#{String(index + 1).padStart(2, \"0\")}</span>{\" \"}\n {resolveLocalizedText(spot.name, activeLocale)}\n </button>\n <span>{spot.conditions[0]?.type ?? \"custom\"}</span>\n </div>\n ))}\n </div>\n <p role=\"status\" aria-live=\"polite\">\n {feedback ?? `${claimed.size} / ${renderConfig.spots.length} claimed`}\n </p>\n <section aria-label=\"Rewards\">\n <h2>Rewards</h2>\n {renderConfig.rewards.map((reward) => {\n const rewardState = resolvedState.rewards?.find((item) => item.rewardId === reward.id);\n const available = rewardState?.status === \"AVAILABLE\";\n return (\n <article key={reward.id}>\n <h3>{resolveLocalizedText(reward.title, activeLocale)}</h3>\n <span>{rewardState?.status ?? \"LOCKED\"}</span>\n {claimReward !== undefined && (\n <button\n type=\"button\"\n disabled={!available}\n onClick={() =>\n void claimReward(reward.id).then((result) => {\n setFeedback(result.ok ? \"Reward claimed.\" : result.error.code);\n })\n }\n >\n Claim reward\n </button>\n )}\n </article>\n );\n })}\n </section>\n {selectedSpot !== undefined && checkIn !== undefined && (\n <div role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"rally-viewer-spot-title\">\n <h2 id=\"rally-viewer-spot-title\">\n {resolveLocalizedText(selectedSpot.name, activeLocale)}\n </h2>\n <p>{resolveLocalizedText(selectedSpot.description, activeLocale)}</p>\n <label>\n Proof\n <input value={proof} onChange={(event) => setProof(event.target.value)} />\n </label>\n <button\n type=\"button\"\n onClick={() => void submit()}\n disabled={claimed.has(selectedSpot.id)}\n >\n Check in\n </button>\n <button type=\"button\" onClick={() => setSelectedSpotId(null)}>\n Close\n </button>\n </div>\n )}\n </section>\n );\n}\n\nfunction useFocusTrap(\n active: boolean,\n onClose: (() => void) | undefined,\n closeDisabled = false,\n): RefObject<HTMLDivElement | null> {\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!active) return;\n const container = containerRef.current;\n if (container === null) return;\n\n const focusableSelector =\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n const focusable = (): ReadonlyArray<HTMLElement> =>\n Array.from(container.querySelectorAll<HTMLElement>(focusableSelector));\n const first = focusable()[0];\n first?.focus();\n\n const handleKeyDown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n if (!closeDisabled) {\n event.preventDefault();\n onClose?.();\n }\n return;\n }\n if (event.key !== \"Tab\") return;\n\n const elements = focusable();\n if (elements.length === 0) {\n event.preventDefault();\n container.focus();\n return;\n }\n const firstElement = elements[0];\n const lastElement = elements[elements.length - 1];\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement?.focus();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement?.focus();\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [active, closeDisabled, onClose]);\n\n return containerRef;\n}\n\nexport interface StampPresentation {\n readonly label?: string;\n readonly icon?: string;\n readonly ink?: \"vermilion\" | \"indigo\";\n readonly channel?: \"instant\" | \"qr\" | \"nfc\" | \"geo\";\n}\n\nexport interface StampSlotProps<TLocale extends string = SupportedLocale> {\n readonly stamp: SpotItem<TLocale>;\n readonly record?: StampRallyState[\"records\"][number] | undefined;\n readonly isNext?: boolean;\n readonly slotNumber?: number;\n readonly presentation?: StampPresentation | undefined;\n readonly isAnimating?: boolean;\n readonly disabled?: boolean;\n readonly slotShape?: SlotShape;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly statusText?: string;\n readonly onSelect?: () => void;\n}\n\nconst FONT_STACKS: Readonly<Record<NonNullable<SheetTheme[\"fontFamily\"]>, string>> = {\n \"system-ui\": 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n serif: 'Georgia, \"Times New Roman\", \"Yu Mincho\", serif',\n \"rounded-sans\": '\"Arial Rounded MT Bold\", \"Hiragino Maru Gothic ProN\", \"Yu Gothic\", sans-serif',\n monospace: 'ui-monospace, SFMono-Regular, Consolas, \"Liberation Mono\", monospace',\n handwritten: '\"Segoe Print\", \"Bradley Hand\", \"Comic Sans MS\", cursive',\n};\n\nfunction formatStampDate(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n const pad = (part: number) => String(part).padStart(2, \"0\");\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;\n}\n\nexport function StampSlot<TLocale extends string = SupportedLocale>({\n stamp,\n record,\n isNext = false,\n slotNumber = 1,\n presentation = {},\n isAnimating = false,\n disabled = false,\n slotShape = \"rounded\",\n locale = \"ja\" as TLocale,\n statusText,\n onSelect,\n}: StampSlotProps<TLocale>) {\n const status = record === undefined ? (isNext ? \"available\" : \"locked\") : \"stamped\";\n const resolvedStatus = statusText ?? status;\n const statusSeparator = statusText !== undefined && locale === \"ja\" ? \"、\" : \", \";\n const name = resolveLocalizedText(stamp.name, locale);\n const label = presentation.label ?? stamp.condition.type;\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={onSelect}\n aria-label={`#${String(slotNumber).padStart(2, \"0\")} ${name}${statusSeparator}${resolvedStatus}`}\n aria-disabled={disabled}\n data-status={status}\n data-shape={slotShape}\n className={`stamp-slot stamp-slot--${status} stamp-slot--${presentation.ink ?? \"vermilion\"} stamp-slot--shape-${slotShape}${isAnimating ? \" stamp-slot--animating\" : \"\"}`}\n style={{ \"--stamp-primary\": \"var(--stamprally-primary, #9e551e)\" } as CSSProperties}\n >\n <span className=\"stamp-slot__topline\">\n <span className=\"stamp-slot__number\">#{String(slotNumber).padStart(2, \"0\")}</span>\n <span className={`stamp-slot__state stamp-slot__state--${status}`}>{resolvedStatus}</span>\n </span>\n <span className=\"stamp-slot__watermark\" aria-hidden=\"true\">\n {presentation.icon ?? \"✦\"}\n </span>\n <span className=\"stamp-slot__name\">{name}</span>\n <span className=\"stamp-slot__condition\">\n <span aria-hidden=\"true\">{presentation.icon ?? \"✦\"}</span>\n {label}\n </span>\n {record !== undefined && (\n <span\n className={`stamp-imprint ${isAnimating ? \"stamp-press\" : \"\"}`}\n role=\"img\"\n aria-label={`Acquired at ${formatStampDate(record.acquiredAt)}`}\n >\n <span className=\"stamp-imprint__inner\">\n <span className=\"stamp-imprint__word\">STAMP</span>\n <span className=\"stamp-imprint__date\">{formatStampDate(record.acquiredAt)}</span>\n </span>\n </span>\n )}\n </button>\n );\n}\n\nexport interface StampSheetProps<TLocale extends string = SupportedLocale> {\n readonly title?: LocalizedText<TLocale>;\n readonly config: RallyConfig<TLocale> | PublicRallyConfig<TLocale>;\n readonly state?: StampRallyState | null;\n readonly progress?: StampRallyProgress;\n readonly presentations?: Readonly<Record<string, StampPresentation>>;\n readonly animatedStampId?: string | null;\n readonly disabled?: boolean;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly theme?: SheetTheme;\n readonly onStampSelect?: (stampId: string) => void;\n readonly adapter?: RallyViewerAdapter<TLocale>;\n}\n\nexport function StampSheet<TLocale extends string = SupportedLocale>({\n title,\n config,\n state = null,\n progress,\n presentations = {},\n animatedStampId = null,\n disabled = false,\n locale = \"ja\" as TLocale,\n dictionary,\n theme = config.theme ?? DEFAULT_SHEET_THEME,\n onStampSelect,\n adapter,\n}: StampSheetProps<TLocale>) {\n if (\"spots\" in config) {\n if (adapter === undefined)\n return (\n <RallyViewer\n config={config}\n locale={locale}\n {...(onStampSelect === undefined ? {} : { onSpotSelect: onStampSelect })}\n />\n );\n return (\n <RallyViewer\n config={config}\n adapter={adapter}\n locale={locale}\n {...(onStampSelect === undefined ? {} : { onSpotSelect: onStampSelect })}\n />\n );\n }\n const acquired = new Set(state?.records.map((record) => record.stampId) ?? []);\n const next = new Set(progress?.nextAvailableStamps.map((stamp) => stamp.id) ?? []);\n const count = progress?.acquired ?? acquired.size;\n const total = progress?.total ?? config.stamps.length;\n const percentage = progress?.percentage ?? (total === 0 ? 0 : (count / total) * 100);\n const style = {\n \"--stamp-primary\": `var(--stamprally-primary-override, ${theme.primaryColor})`,\n \"--stamp-bg\": `var(--stamprally-background-override, ${theme.backgroundColor ?? DEFAULT_SHEET_THEME.backgroundColor ?? \"#ffffff\"})`,\n \"--stamp-card-bg\": `var(--stamprally-card-override, ${theme.cardBackgroundColor})`,\n \"--stamp-text\": `var(--stamprally-text-override, ${theme.textColor})`,\n \"--stamp-grid-cols\": String(theme.gridColumns),\n \"--stamp-grid-cols-mobile\": String(Math.min(theme.gridColumns, 2)),\n \"--stamp-unclaimed-opacity\": String(theme.unclaimedOpacity ?? 1),\n \"--stamp-font-family\": FONT_STACKS[theme.fontFamily ?? \"serif\"],\n ...(theme.completedStampColor === undefined\n ? {}\n : { \"--stamp-completed-color\": theme.completedStampColor }),\n \"--stamprally-primary\": `var(--stamprally-primary-override, ${theme.primaryColor})`,\n \"--stamprally-background\": `var(--stamprally-background-override, ${theme.backgroundColor ?? \"transparent\"})`,\n \"--stamprally-card\": `var(--stamprally-card-override, ${theme.cardBackgroundColor})`,\n \"--stamprally-text\": `var(--stamprally-text-override, ${theme.textColor})`,\n \"--stamprally-columns\": String(theme.gridColumns),\n } as CSSProperties;\n const messages = {\n available: dictionary?.[locale]?.available ?? (locale === \"en\" ? \"available\" : \"取得可能\"),\n locked: dictionary?.[locale]?.locked ?? (locale === \"en\" ? \"locked\" : \"順序待ち\"),\n stamped: dictionary?.[locale]?.stamped ?? (locale === \"en\" ? \"stamped\" : \"取得済み\"),\n remaining: (value: number) =>\n dictionary?.[locale]?.remaining?.replace(\"{count}\", String(value)) ??\n (locale === \"en\" ? `${value} spots remaining` : `あと${value}箇所`),\n completed:\n dictionary?.[locale]?.completed ?? (locale === \"en\" ? \"RALLY COMPLETED\" : \"ラリー達成\"),\n };\n return (\n <section\n className={`stamp-sheet ${percentage >= 100 ? \"stamp-sheet--completed\" : \"\"}`}\n style={style}\n aria-label={resolveLocalizedText(title, locale) || config.id}\n >\n <header className=\"stamp-sheet__header\">\n <h2>{resolveLocalizedText(title, locale) || config.id}</h2>\n <span className=\"stamp-sheet__score\" role=\"status\" aria-live=\"polite\">\n {count} / {total}\n </span>\n </header>\n <div className=\"stamp-sheet__progress-label\">\n <span>{messages.remaining(Math.max(0, total - count))}</span>\n <strong>{Math.round(percentage)}%</strong>\n </div>\n <div\n className=\"stamp-sheet__progress-track\"\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(percentage)}\n aria-label={locale === \"en\" ? \"Rally progress\" : \"スタンプ取得進捗\"}\n >\n <span\n className=\"stamp-sheet__progress-fill\"\n style={{ display: \"block\", width: `${percentage}%` }}\n />\n </div>\n <div className=\"stamp-sheet__grid\">\n {config.stamps.map((stamp, index) => {\n const recordForStamp = state?.records.find((record) => record.stampId === stamp.id);\n return (\n <StampSlot\n key={stamp.id}\n stamp={stamp}\n {...(recordForStamp === undefined ? {} : { record: recordForStamp })}\n isNext={next.has(stamp.id)}\n slotNumber={index + 1}\n {...(presentations[stamp.id] === undefined\n ? {}\n : { presentation: presentations[stamp.id] })}\n isAnimating={animatedStampId === stamp.id}\n disabled={disabled}\n slotShape={theme.slotShape}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n statusText={\n recordForStamp === undefined\n ? next.has(stamp.id)\n ? messages.available\n : messages.locked\n : messages.stamped\n }\n onSelect={() => onStampSelect?.(stamp.id)}\n />\n );\n })}\n </div>\n {percentage >= 100 && (\n <div className=\"stamp-sheet__complete-mark\" role=\"status\" aria-live=\"polite\">\n COMPLETE!!\n </div>\n )}\n {percentage >= 100 && (\n <div className=\"stamp-sheet__complete-message\">{messages.completed}</div>\n )}\n </section>\n );\n}\n\nexport interface AcquisitionFeedback {\n readonly ok: boolean;\n readonly message: string;\n}\nexport interface StampModalProps<TLocale extends string = SupportedLocale> {\n readonly open: boolean;\n readonly stamp: SpotItem<TLocale> | null;\n readonly record?: StampRallyState[\"records\"][number] | undefined;\n readonly presentation?: StampPresentation | null;\n readonly requiredStampName?: string | null;\n readonly isAvailable?: boolean;\n readonly isPending?: boolean;\n readonly isCompleted?: boolean;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly onClose: () => void;\n readonly onAcquire?: (\n stampId: string,\n context: VerificationContext,\n ) => Promise<AcquisitionFeedback>;\n readonly onCheckIn?: (\n stampId: string,\n context: VerificationContext,\n ) => Promise<AcquisitionFeedback>;\n readonly onNotify?: (feedback: AcquisitionFeedback) => void;\n}\n\nexport function StampModal<TLocale extends string = SupportedLocale>({\n open,\n stamp,\n record,\n isAvailable = true,\n isPending = false,\n locale = \"ja\" as TLocale,\n dictionary,\n onClose,\n onAcquire,\n onCheckIn,\n onNotify,\n}: StampModalProps<TLocale>) {\n const [token, setToken] = useState(\"\");\n const modalRef = useFocusTrap(open && stamp !== null, onClose, isPending);\n useEffect(() => {\n if (!open) setToken(\"\");\n }, [open]);\n if (!open || stamp === null) return null;\n const submit = async (context: VerificationContext): Promise<void> => {\n if (!isAvailable || record !== undefined) return;\n const handler = onAcquire ?? onCheckIn;\n if (handler === undefined) return;\n const feedback = await handler(stamp.id, context);\n onNotify?.(feedback);\n if (feedback.ok) onClose();\n };\n const name = resolveLocalizedText(stamp.name, locale);\n const messages = dictionary?.[locale] ?? {};\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"stamprally-modal-title\"\n className=\"stamprally-modal\"\n >\n <div className=\"stamprally-modal__panel\" ref={modalRef} tabIndex={-1}>\n <button\n type=\"button\"\n aria-label=\"Close stamp details\"\n aria-disabled={isPending}\n onClick={onClose}\n disabled={isPending}\n >\n ×\n </button>\n <h2 id=\"stamprally-modal-title\">{name}</h2>\n {record !== undefined ? (\n <p>{messages.alreadyClaimed ?? \"Already claimed.\"}</p>\n ) : (\n <p>{resolveLocalizedText(stamp.description, locale)}</p>\n )}\n {stamp.condition.type === \"token\" ? (\n <form\n onSubmit={(event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n void submit({ type: \"token\", token });\n }}\n >\n <label>\n {messages.passcode ?? \"Passcode\"}{\" \"}\n <input value={token} onChange={(event) => setToken(event.target.value)} />\n </label>\n <button\n type=\"submit\"\n aria-label=\"Claim stamp\"\n aria-disabled={!isAvailable || isPending}\n disabled={!isAvailable || isPending}\n >\n {messages.claimStamp ?? \"Claim stamp\"}\n </button>\n </form>\n ) : (\n <button\n type=\"button\"\n aria-label=\"Claim stamp\"\n aria-disabled={!isAvailable || isPending}\n onClick={() => void submit({ type: \"instant\" })}\n disabled={!isAvailable || isPending}\n >\n {messages.claimStamp ?? \"Claim stamp\"}\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport interface RewardPanelProps<TLocale extends string = SupportedLocale> {\n readonly rewards: ReadonlyArray<RewardItem<TLocale>>;\n readonly states: ReadonlyArray<RewardState>;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly isPending?: boolean;\n readonly open?: boolean;\n readonly onClose?: () => void;\n readonly onRedeem: (\n rewardId: string,\n options?: { readonly passcode?: string; readonly staffId?: string },\n ) => Promise<ConsumeResult>;\n readonly onNotify?: (ok: boolean, message: string) => void;\n}\n\nexport function RewardPanel<TLocale extends string = SupportedLocale>({\n rewards,\n states,\n locale = \"ja\" as TLocale,\n dictionary,\n isPending = false,\n open = true,\n onClose,\n onRedeem,\n onNotify,\n}: RewardPanelProps<TLocale>) {\n const [passcodes, setPasscodes] = useState<Readonly<Record<string, string>>>({});\n const panelRef = useFocusTrap(open && onClose !== undefined, onClose, isPending);\n if (!open) return null;\n return (\n <section\n ref={panelRef}\n role=\"dialog\"\n aria-labelledby=\"stamprally-rewards-title\"\n aria-modal=\"true\"\n className=\"stamprally-rewards\"\n tabIndex={-1}\n >\n <header className=\"stamprally-rewards__header\">\n <h2 id=\"stamprally-rewards-title\">{dictionary?.[locale]?.rewards ?? \"Rewards\"}</h2>\n {onClose !== undefined && (\n <button\n type=\"button\"\n aria-label=\"Close rewards\"\n aria-disabled={isPending}\n disabled={isPending}\n onClick={onClose}\n >\n ×\n </button>\n )}\n </header>\n {rewards.map((reward) => {\n const state = states.find((item) => item.rewardId === reward.id);\n const available = state?.status === \"AVAILABLE\";\n const redeem = async (options?: { readonly passcode?: string }): Promise<void> => {\n const result = await onRedeem(reward.id, options);\n onNotify?.(\n result.ok,\n result.ok\n ? (dictionary?.[locale]?.rewardClaimed ?? \"Reward claimed.\")\n : result.error.code,\n );\n };\n return (\n <article\n key={reward.id}\n className={`stamprally-reward stamprally-reward--${state?.status ?? \"LOCKED\"}`}\n >\n <h3>{resolveLocalizedText(reward.title, locale)}</h3>\n <p>{resolveLocalizedText(reward.description, locale)}</p>\n <span role=\"status\" aria-live=\"polite\">\n {state?.status ?? \"LOCKED\"}\n </span>\n {reward.redemptionMethod === \"staff_passcode\" && (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void redeem({ passcode: passcodes[reward.id] ?? \"\" });\n }}\n >\n <label>\n {dictionary?.[locale]?.staffPasscode ?? \"Staff passcode\"}{\" \"}\n <input\n type=\"password\"\n value={passcodes[reward.id] ?? \"\"}\n onChange={(event) =>\n setPasscodes((current) => ({ ...current, [reward.id]: event.target.value }))\n }\n />\n </label>\n <button\n type=\"submit\"\n aria-label={`Redeem ${resolveLocalizedText(reward.title, locale)}`}\n aria-disabled={!available || isPending}\n disabled={!available || isPending}\n >\n {dictionary?.[locale]?.redeem ?? \"Redeem\"}\n </button>\n </form>\n )}\n {reward.redemptionMethod !== \"staff_passcode\" && (\n <button\n type=\"button\"\n aria-label={`Redeem ${resolveLocalizedText(reward.title, locale)}`}\n aria-disabled={!available || isPending}\n disabled={!available || isPending}\n onClick={() => void redeem()}\n >\n {dictionary?.[locale]?.redeem ?? \"Redeem\"}\n </button>\n )}\n </article>\n );\n })}\n </section>\n );\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { SupportedLocale, RewardItem, RewardState, LocaleDictionary, ConsumeResult, SpotItem, StampRallyState, VerificationContext, LocalizedText, RallyConfig, StampRallyProgress, SheetTheme, SlotShape } from '@stamprally/core';
|
|
2
|
+
import { PublicRallyConfig, UserRallyState, UniversalCheckInResult, ClaimOptions, UniversalClaimResult, UniversalStampRallyClient, SupportedLocale, RewardItem, RewardState, LocaleDictionary, ConsumeResult, SpotItem, StampRallyState, VerificationContext, LocalizedText, RallyConfig, StampRallyProgress, SheetTheme, SlotShape } from '@stamprally/core';
|
|
3
3
|
export { LocaleDictionary } from '@stamprally/core';
|
|
4
4
|
|
|
5
|
+
interface RallyViewerAdapter<TLocale extends string = string> {
|
|
6
|
+
readonly state: UserRallyState;
|
|
7
|
+
readonly config: PublicRallyConfig<TLocale>;
|
|
8
|
+
readonly onCheckIn: (spotId: string, proof: unknown) => Promise<UniversalCheckInResult>;
|
|
9
|
+
readonly onClaimReward: (rewardId: string, options?: ClaimOptions) => Promise<UniversalClaimResult>;
|
|
10
|
+
readonly onSync?: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
interface RallyViewerProps<TLocale extends string = string> {
|
|
13
|
+
readonly config?: PublicRallyConfig<TLocale>;
|
|
14
|
+
readonly adapter?: RallyViewerAdapter<TLocale>;
|
|
15
|
+
readonly client?: UniversalStampRallyClient;
|
|
16
|
+
readonly locale?: TLocale;
|
|
17
|
+
readonly onSpotSelect?: (spotId: string) => void;
|
|
18
|
+
}
|
|
19
|
+
/** Lightweight public-config viewer for applications that do not need the legacy StampSheet state model. */
|
|
20
|
+
declare function RallyViewer<TLocale extends string = string>({ config, adapter, client, locale, onSpotSelect, }: RallyViewerProps<TLocale>): react.JSX.Element | null;
|
|
5
21
|
interface StampPresentation {
|
|
6
22
|
readonly label?: string;
|
|
7
23
|
readonly icon?: string;
|
|
@@ -25,7 +41,7 @@ interface StampSlotProps<TLocale extends string = SupportedLocale> {
|
|
|
25
41
|
declare function StampSlot<TLocale extends string = SupportedLocale>({ stamp, record, isNext, slotNumber, presentation, isAnimating, disabled, slotShape, locale, statusText, onSelect, }: StampSlotProps<TLocale>): react.JSX.Element;
|
|
26
42
|
interface StampSheetProps<TLocale extends string = SupportedLocale> {
|
|
27
43
|
readonly title?: LocalizedText<TLocale>;
|
|
28
|
-
readonly config: RallyConfig<TLocale>;
|
|
44
|
+
readonly config: RallyConfig<TLocale> | PublicRallyConfig<TLocale>;
|
|
29
45
|
readonly state?: StampRallyState | null;
|
|
30
46
|
readonly progress?: StampRallyProgress;
|
|
31
47
|
readonly presentations?: Readonly<Record<string, StampPresentation>>;
|
|
@@ -35,8 +51,9 @@ interface StampSheetProps<TLocale extends string = SupportedLocale> {
|
|
|
35
51
|
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
36
52
|
readonly theme?: SheetTheme;
|
|
37
53
|
readonly onStampSelect?: (stampId: string) => void;
|
|
54
|
+
readonly adapter?: RallyViewerAdapter<TLocale>;
|
|
38
55
|
}
|
|
39
|
-
declare function StampSheet<TLocale extends string = SupportedLocale>({ title, config, state, progress, presentations, animatedStampId, disabled, locale, dictionary, theme, onStampSelect, }: StampSheetProps<TLocale>): react.JSX.Element;
|
|
56
|
+
declare function StampSheet<TLocale extends string = SupportedLocale>({ title, config, state, progress, presentations, animatedStampId, disabled, locale, dictionary, theme, onStampSelect, adapter, }: StampSheetProps<TLocale>): react.JSX.Element;
|
|
40
57
|
interface AcquisitionFeedback {
|
|
41
58
|
readonly ok: boolean;
|
|
42
59
|
readonly message: string;
|
|
@@ -74,4 +91,4 @@ interface RewardPanelProps<TLocale extends string = SupportedLocale> {
|
|
|
74
91
|
}
|
|
75
92
|
declare function RewardPanel<TLocale extends string = SupportedLocale>({ rewards, states, locale, dictionary, isPending, open, onClose, onRedeem, onNotify, }: RewardPanelProps<TLocale>): react.JSX.Element | null;
|
|
76
93
|
|
|
77
|
-
export { type AcquisitionFeedback, RewardPanel, type RewardPanelProps, StampModal, type StampModalProps, type StampPresentation, StampSheet, type StampSheetProps, StampSlot, type StampSlotProps };
|
|
94
|
+
export { type AcquisitionFeedback, RallyViewer, type RallyViewerAdapter, type RallyViewerProps, RewardPanel, type RewardPanelProps, StampModal, type StampModalProps, type StampPresentation, StampSheet, type StampSheetProps, StampSlot, type StampSlotProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { SupportedLocale, RewardItem, RewardState, LocaleDictionary, ConsumeResult, SpotItem, StampRallyState, VerificationContext, LocalizedText, RallyConfig, StampRallyProgress, SheetTheme, SlotShape } from '@stamprally/core';
|
|
2
|
+
import { PublicRallyConfig, UserRallyState, UniversalCheckInResult, ClaimOptions, UniversalClaimResult, UniversalStampRallyClient, SupportedLocale, RewardItem, RewardState, LocaleDictionary, ConsumeResult, SpotItem, StampRallyState, VerificationContext, LocalizedText, RallyConfig, StampRallyProgress, SheetTheme, SlotShape } from '@stamprally/core';
|
|
3
3
|
export { LocaleDictionary } from '@stamprally/core';
|
|
4
4
|
|
|
5
|
+
interface RallyViewerAdapter<TLocale extends string = string> {
|
|
6
|
+
readonly state: UserRallyState;
|
|
7
|
+
readonly config: PublicRallyConfig<TLocale>;
|
|
8
|
+
readonly onCheckIn: (spotId: string, proof: unknown) => Promise<UniversalCheckInResult>;
|
|
9
|
+
readonly onClaimReward: (rewardId: string, options?: ClaimOptions) => Promise<UniversalClaimResult>;
|
|
10
|
+
readonly onSync?: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
interface RallyViewerProps<TLocale extends string = string> {
|
|
13
|
+
readonly config?: PublicRallyConfig<TLocale>;
|
|
14
|
+
readonly adapter?: RallyViewerAdapter<TLocale>;
|
|
15
|
+
readonly client?: UniversalStampRallyClient;
|
|
16
|
+
readonly locale?: TLocale;
|
|
17
|
+
readonly onSpotSelect?: (spotId: string) => void;
|
|
18
|
+
}
|
|
19
|
+
/** Lightweight public-config viewer for applications that do not need the legacy StampSheet state model. */
|
|
20
|
+
declare function RallyViewer<TLocale extends string = string>({ config, adapter, client, locale, onSpotSelect, }: RallyViewerProps<TLocale>): react.JSX.Element | null;
|
|
5
21
|
interface StampPresentation {
|
|
6
22
|
readonly label?: string;
|
|
7
23
|
readonly icon?: string;
|
|
@@ -25,7 +41,7 @@ interface StampSlotProps<TLocale extends string = SupportedLocale> {
|
|
|
25
41
|
declare function StampSlot<TLocale extends string = SupportedLocale>({ stamp, record, isNext, slotNumber, presentation, isAnimating, disabled, slotShape, locale, statusText, onSelect, }: StampSlotProps<TLocale>): react.JSX.Element;
|
|
26
42
|
interface StampSheetProps<TLocale extends string = SupportedLocale> {
|
|
27
43
|
readonly title?: LocalizedText<TLocale>;
|
|
28
|
-
readonly config: RallyConfig<TLocale>;
|
|
44
|
+
readonly config: RallyConfig<TLocale> | PublicRallyConfig<TLocale>;
|
|
29
45
|
readonly state?: StampRallyState | null;
|
|
30
46
|
readonly progress?: StampRallyProgress;
|
|
31
47
|
readonly presentations?: Readonly<Record<string, StampPresentation>>;
|
|
@@ -35,8 +51,9 @@ interface StampSheetProps<TLocale extends string = SupportedLocale> {
|
|
|
35
51
|
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
36
52
|
readonly theme?: SheetTheme;
|
|
37
53
|
readonly onStampSelect?: (stampId: string) => void;
|
|
54
|
+
readonly adapter?: RallyViewerAdapter<TLocale>;
|
|
38
55
|
}
|
|
39
|
-
declare function StampSheet<TLocale extends string = SupportedLocale>({ title, config, state, progress, presentations, animatedStampId, disabled, locale, dictionary, theme, onStampSelect, }: StampSheetProps<TLocale>): react.JSX.Element;
|
|
56
|
+
declare function StampSheet<TLocale extends string = SupportedLocale>({ title, config, state, progress, presentations, animatedStampId, disabled, locale, dictionary, theme, onStampSelect, adapter, }: StampSheetProps<TLocale>): react.JSX.Element;
|
|
40
57
|
interface AcquisitionFeedback {
|
|
41
58
|
readonly ok: boolean;
|
|
42
59
|
readonly message: string;
|
|
@@ -74,4 +91,4 @@ interface RewardPanelProps<TLocale extends string = SupportedLocale> {
|
|
|
74
91
|
}
|
|
75
92
|
declare function RewardPanel<TLocale extends string = SupportedLocale>({ rewards, states, locale, dictionary, isPending, open, onClose, onRedeem, onNotify, }: RewardPanelProps<TLocale>): react.JSX.Element | null;
|
|
76
93
|
|
|
77
|
-
export { type AcquisitionFeedback, RewardPanel, type RewardPanelProps, StampModal, type StampModalProps, type StampPresentation, StampSheet, type StampSheetProps, StampSlot, type StampSlotProps };
|
|
94
|
+
export { type AcquisitionFeedback, RallyViewer, type RallyViewerAdapter, type RallyViewerProps, RewardPanel, type RewardPanelProps, StampModal, type StampModalProps, type StampPresentation, StampSheet, type StampSheetProps, StampSlot, type StampSlotProps };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,121 @@ import { useState, useEffect, useRef } from 'react';
|
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
5
|
// src/index.tsx
|
|
6
|
+
function RallyViewer({
|
|
7
|
+
config,
|
|
8
|
+
adapter,
|
|
9
|
+
client,
|
|
10
|
+
locale,
|
|
11
|
+
onSpotSelect
|
|
12
|
+
}) {
|
|
13
|
+
const activeLocale = locale ?? "en";
|
|
14
|
+
const resolvedConfig = adapter?.config ?? config ?? client?.getConfig();
|
|
15
|
+
const renderConfig = resolvedConfig ?? {
|
|
16
|
+
id: "empty",
|
|
17
|
+
title: "",
|
|
18
|
+
spots: [],
|
|
19
|
+
rewards: []
|
|
20
|
+
};
|
|
21
|
+
const emptyState = {
|
|
22
|
+
rallyId: renderConfig.id,
|
|
23
|
+
records: [],
|
|
24
|
+
updatedAt: (/* @__PURE__ */ new Date(0)).toISOString()
|
|
25
|
+
};
|
|
26
|
+
const resolvedState = adapter?.state ?? client?.getState() ?? emptyState;
|
|
27
|
+
const [selectedSpotId, setSelectedSpotId] = useState(null);
|
|
28
|
+
const [proof, setProof] = useState("");
|
|
29
|
+
const [feedback, setFeedback] = useState(null);
|
|
30
|
+
const [, setClientRevision] = useState(0);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (client === void 0) return;
|
|
33
|
+
return client.subscribe(() => setClientRevision((revision) => revision + 1));
|
|
34
|
+
}, [client]);
|
|
35
|
+
const selectedSpot = renderConfig.spots.find((spot) => spot.id === selectedSpotId);
|
|
36
|
+
const checkIn = adapter?.onCheckIn ?? (client === void 0 ? void 0 : (spotId, value) => client.checkIn(spotId, value));
|
|
37
|
+
const claimReward = adapter?.onClaimReward ?? (client === void 0 ? void 0 : (rewardId, options) => client.claimReward(rewardId, options));
|
|
38
|
+
const claimed = new Set(resolvedState.records.map((record) => record.stampId));
|
|
39
|
+
const submit = async () => {
|
|
40
|
+
if (selectedSpot === void 0 || checkIn === void 0) return;
|
|
41
|
+
const result = await checkIn(selectedSpot.id, proof);
|
|
42
|
+
setFeedback(result.ok ? "Check-in completed." : result.error.code);
|
|
43
|
+
if (result.ok) {
|
|
44
|
+
setProof("");
|
|
45
|
+
setSelectedSpotId(null);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
if (resolvedConfig === void 0) return null;
|
|
49
|
+
return /* @__PURE__ */ jsxs("section", { "aria-label": "Stamp rally viewer", className: "stamprally-viewer", children: [
|
|
50
|
+
/* @__PURE__ */ jsxs("header", { children: [
|
|
51
|
+
/* @__PURE__ */ jsx("h1", { children: resolveLocalizedText(renderConfig.title, activeLocale) }),
|
|
52
|
+
renderConfig.description !== void 0 && /* @__PURE__ */ jsx("p", { children: resolveLocalizedText(renderConfig.description, activeLocale) }),
|
|
53
|
+
adapter?.onSync !== void 0 && /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void adapter.onSync?.(), children: "Sync" })
|
|
54
|
+
] }),
|
|
55
|
+
/* @__PURE__ */ jsx("div", { role: "grid", "aria-label": "Stamp rally spots", children: renderConfig.spots.map((spot, index) => /* @__PURE__ */ jsxs("div", { children: [
|
|
56
|
+
/* @__PURE__ */ jsxs(
|
|
57
|
+
"button",
|
|
58
|
+
{
|
|
59
|
+
type: "button",
|
|
60
|
+
"aria-label": `${resolveLocalizedText(spot.name, activeLocale)}${claimed.has(spot.id) ? ", claimed" : ", available"}`,
|
|
61
|
+
onClick: () => {
|
|
62
|
+
onSpotSelect?.(spot.id);
|
|
63
|
+
setSelectedSpotId(spot.id);
|
|
64
|
+
setFeedback(null);
|
|
65
|
+
},
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ jsxs("span", { "aria-hidden": "true", children: [
|
|
68
|
+
"#",
|
|
69
|
+
String(index + 1).padStart(2, "0")
|
|
70
|
+
] }),
|
|
71
|
+
" ",
|
|
72
|
+
resolveLocalizedText(spot.name, activeLocale)
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
/* @__PURE__ */ jsx("span", { children: spot.conditions[0]?.type ?? "custom" })
|
|
77
|
+
] }, spot.id)) }),
|
|
78
|
+
/* @__PURE__ */ jsx("p", { role: "status", "aria-live": "polite", children: feedback ?? `${claimed.size} / ${renderConfig.spots.length} claimed` }),
|
|
79
|
+
/* @__PURE__ */ jsxs("section", { "aria-label": "Rewards", children: [
|
|
80
|
+
/* @__PURE__ */ jsx("h2", { children: "Rewards" }),
|
|
81
|
+
renderConfig.rewards.map((reward) => {
|
|
82
|
+
const rewardState = resolvedState.rewards?.find((item) => item.rewardId === reward.id);
|
|
83
|
+
const available = rewardState?.status === "AVAILABLE";
|
|
84
|
+
return /* @__PURE__ */ jsxs("article", { children: [
|
|
85
|
+
/* @__PURE__ */ jsx("h3", { children: resolveLocalizedText(reward.title, activeLocale) }),
|
|
86
|
+
/* @__PURE__ */ jsx("span", { children: rewardState?.status ?? "LOCKED" }),
|
|
87
|
+
claimReward !== void 0 && /* @__PURE__ */ jsx(
|
|
88
|
+
"button",
|
|
89
|
+
{
|
|
90
|
+
type: "button",
|
|
91
|
+
disabled: !available,
|
|
92
|
+
onClick: () => void claimReward(reward.id).then((result) => {
|
|
93
|
+
setFeedback(result.ok ? "Reward claimed." : result.error.code);
|
|
94
|
+
}),
|
|
95
|
+
children: "Claim reward"
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
] }, reward.id);
|
|
99
|
+
})
|
|
100
|
+
] }),
|
|
101
|
+
selectedSpot !== void 0 && checkIn !== void 0 && /* @__PURE__ */ jsxs("div", { role: "dialog", "aria-modal": "true", "aria-labelledby": "rally-viewer-spot-title", children: [
|
|
102
|
+
/* @__PURE__ */ jsx("h2", { id: "rally-viewer-spot-title", children: resolveLocalizedText(selectedSpot.name, activeLocale) }),
|
|
103
|
+
/* @__PURE__ */ jsx("p", { children: resolveLocalizedText(selectedSpot.description, activeLocale) }),
|
|
104
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
105
|
+
"Proof",
|
|
106
|
+
/* @__PURE__ */ jsx("input", { value: proof, onChange: (event) => setProof(event.target.value) })
|
|
107
|
+
] }),
|
|
108
|
+
/* @__PURE__ */ jsx(
|
|
109
|
+
"button",
|
|
110
|
+
{
|
|
111
|
+
type: "button",
|
|
112
|
+
onClick: () => void submit(),
|
|
113
|
+
disabled: claimed.has(selectedSpot.id),
|
|
114
|
+
children: "Check in"
|
|
115
|
+
}
|
|
116
|
+
),
|
|
117
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setSelectedSpotId(null), children: "Close" })
|
|
118
|
+
] })
|
|
119
|
+
] });
|
|
120
|
+
}
|
|
6
121
|
function useFocusTrap(active, onClose, closeDisabled = false) {
|
|
7
122
|
const containerRef = useRef(null);
|
|
8
123
|
useEffect(() => {
|
|
@@ -127,8 +242,29 @@ function StampSheet({
|
|
|
127
242
|
locale = "ja",
|
|
128
243
|
dictionary,
|
|
129
244
|
theme = config.theme ?? DEFAULT_SHEET_THEME,
|
|
130
|
-
onStampSelect
|
|
245
|
+
onStampSelect,
|
|
246
|
+
adapter
|
|
131
247
|
}) {
|
|
248
|
+
if ("spots" in config) {
|
|
249
|
+
if (adapter === void 0)
|
|
250
|
+
return /* @__PURE__ */ jsx(
|
|
251
|
+
RallyViewer,
|
|
252
|
+
{
|
|
253
|
+
config,
|
|
254
|
+
locale,
|
|
255
|
+
...onStampSelect === void 0 ? {} : { onSpotSelect: onStampSelect }
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
return /* @__PURE__ */ jsx(
|
|
259
|
+
RallyViewer,
|
|
260
|
+
{
|
|
261
|
+
config,
|
|
262
|
+
adapter,
|
|
263
|
+
locale,
|
|
264
|
+
...onStampSelect === void 0 ? {} : { onSpotSelect: onStampSelect }
|
|
265
|
+
}
|
|
266
|
+
);
|
|
267
|
+
}
|
|
132
268
|
const acquired = new Set(state?.records.map((record) => record.stampId) ?? []);
|
|
133
269
|
const next = new Set(progress?.nextAvailableStamps.map((stamp) => stamp.id) ?? []);
|
|
134
270
|
const count = progress?.acquired ?? acquired.size;
|
|
@@ -424,6 +560,6 @@ function RewardPanel({
|
|
|
424
560
|
);
|
|
425
561
|
}
|
|
426
562
|
|
|
427
|
-
export { RewardPanel, StampModal, StampSheet, StampSlot };
|
|
563
|
+
export { RallyViewer, RewardPanel, StampModal, StampSheet, StampSlot };
|
|
428
564
|
//# sourceMappingURL=index.js.map
|
|
429
565
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n type ConsumeResult,\n DEFAULT_SHEET_THEME,\n type LocaleDictionary,\n type LocalizedText,\n type RallyConfig,\n type RewardItem,\n type RewardState,\n resolveLocalizedText,\n type SheetTheme,\n type SlotShape,\n type SpotItem,\n type StampRallyProgress,\n type StampRallyState,\n type SupportedLocale,\n type VerificationContext,\n} from \"@stamprally/core\";\nimport type { CSSProperties, FormEvent, RefObject } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport type { LocaleDictionary } from \"@stamprally/core\";\n\nfunction useFocusTrap(\n active: boolean,\n onClose: (() => void) | undefined,\n closeDisabled = false,\n): RefObject<HTMLDivElement | null> {\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!active) return;\n const container = containerRef.current;\n if (container === null) return;\n\n const focusableSelector =\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n const focusable = (): ReadonlyArray<HTMLElement> =>\n Array.from(container.querySelectorAll<HTMLElement>(focusableSelector));\n const first = focusable()[0];\n first?.focus();\n\n const handleKeyDown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n if (!closeDisabled) {\n event.preventDefault();\n onClose?.();\n }\n return;\n }\n if (event.key !== \"Tab\") return;\n\n const elements = focusable();\n if (elements.length === 0) {\n event.preventDefault();\n container.focus();\n return;\n }\n const firstElement = elements[0];\n const lastElement = elements[elements.length - 1];\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement?.focus();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement?.focus();\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [active, closeDisabled, onClose]);\n\n return containerRef;\n}\n\nexport interface StampPresentation {\n readonly label?: string;\n readonly icon?: string;\n readonly ink?: \"vermilion\" | \"indigo\";\n readonly channel?: \"instant\" | \"qr\" | \"nfc\" | \"geo\";\n}\n\nexport interface StampSlotProps<TLocale extends string = SupportedLocale> {\n readonly stamp: SpotItem<TLocale>;\n readonly record?: StampRallyState[\"records\"][number] | undefined;\n readonly isNext?: boolean;\n readonly slotNumber?: number;\n readonly presentation?: StampPresentation | undefined;\n readonly isAnimating?: boolean;\n readonly disabled?: boolean;\n readonly slotShape?: SlotShape;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly statusText?: string;\n readonly onSelect?: () => void;\n}\n\nconst FONT_STACKS: Readonly<Record<NonNullable<SheetTheme[\"fontFamily\"]>, string>> = {\n \"system-ui\": 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n serif: 'Georgia, \"Times New Roman\", \"Yu Mincho\", serif',\n \"rounded-sans\": '\"Arial Rounded MT Bold\", \"Hiragino Maru Gothic ProN\", \"Yu Gothic\", sans-serif',\n monospace: 'ui-monospace, SFMono-Regular, Consolas, \"Liberation Mono\", monospace',\n handwritten: '\"Segoe Print\", \"Bradley Hand\", \"Comic Sans MS\", cursive',\n};\n\nfunction formatStampDate(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n const pad = (part: number) => String(part).padStart(2, \"0\");\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;\n}\n\nexport function StampSlot<TLocale extends string = SupportedLocale>({\n stamp,\n record,\n isNext = false,\n slotNumber = 1,\n presentation = {},\n isAnimating = false,\n disabled = false,\n slotShape = \"rounded\",\n locale = \"ja\" as TLocale,\n statusText,\n onSelect,\n}: StampSlotProps<TLocale>) {\n const status = record === undefined ? (isNext ? \"available\" : \"locked\") : \"stamped\";\n const resolvedStatus = statusText ?? status;\n const statusSeparator = statusText !== undefined && locale === \"ja\" ? \"、\" : \", \";\n const name = resolveLocalizedText(stamp.name, locale);\n const label = presentation.label ?? stamp.condition.type;\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={onSelect}\n aria-label={`#${String(slotNumber).padStart(2, \"0\")} ${name}${statusSeparator}${resolvedStatus}`}\n aria-disabled={disabled}\n data-status={status}\n data-shape={slotShape}\n className={`stamp-slot stamp-slot--${status} stamp-slot--${presentation.ink ?? \"vermilion\"} stamp-slot--shape-${slotShape}${isAnimating ? \" stamp-slot--animating\" : \"\"}`}\n style={{ \"--stamp-primary\": \"var(--stamprally-primary, #9e551e)\" } as CSSProperties}\n >\n <span className=\"stamp-slot__topline\">\n <span className=\"stamp-slot__number\">#{String(slotNumber).padStart(2, \"0\")}</span>\n <span className={`stamp-slot__state stamp-slot__state--${status}`}>{resolvedStatus}</span>\n </span>\n <span className=\"stamp-slot__watermark\" aria-hidden=\"true\">\n {presentation.icon ?? \"✦\"}\n </span>\n <span className=\"stamp-slot__name\">{name}</span>\n <span className=\"stamp-slot__condition\">\n <span aria-hidden=\"true\">{presentation.icon ?? \"✦\"}</span>\n {label}\n </span>\n {record !== undefined && (\n <span\n className={`stamp-imprint ${isAnimating ? \"stamp-press\" : \"\"}`}\n role=\"img\"\n aria-label={`Acquired at ${formatStampDate(record.acquiredAt)}`}\n >\n <span className=\"stamp-imprint__inner\">\n <span className=\"stamp-imprint__word\">STAMP</span>\n <span className=\"stamp-imprint__date\">{formatStampDate(record.acquiredAt)}</span>\n </span>\n </span>\n )}\n </button>\n );\n}\n\nexport interface StampSheetProps<TLocale extends string = SupportedLocale> {\n readonly title?: LocalizedText<TLocale>;\n readonly config: RallyConfig<TLocale>;\n readonly state?: StampRallyState | null;\n readonly progress?: StampRallyProgress;\n readonly presentations?: Readonly<Record<string, StampPresentation>>;\n readonly animatedStampId?: string | null;\n readonly disabled?: boolean;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly theme?: SheetTheme;\n readonly onStampSelect?: (stampId: string) => void;\n}\n\nexport function StampSheet<TLocale extends string = SupportedLocale>({\n title,\n config,\n state = null,\n progress,\n presentations = {},\n animatedStampId = null,\n disabled = false,\n locale = \"ja\" as TLocale,\n dictionary,\n theme = config.theme ?? DEFAULT_SHEET_THEME,\n onStampSelect,\n}: StampSheetProps<TLocale>) {\n const acquired = new Set(state?.records.map((record) => record.stampId) ?? []);\n const next = new Set(progress?.nextAvailableStamps.map((stamp) => stamp.id) ?? []);\n const count = progress?.acquired ?? acquired.size;\n const total = progress?.total ?? config.stamps.length;\n const percentage = progress?.percentage ?? (total === 0 ? 0 : (count / total) * 100);\n const style = {\n \"--stamp-primary\": `var(--stamprally-primary-override, ${theme.primaryColor})`,\n \"--stamp-bg\": `var(--stamprally-background-override, ${theme.backgroundColor ?? DEFAULT_SHEET_THEME.backgroundColor ?? \"#ffffff\"})`,\n \"--stamp-card-bg\": `var(--stamprally-card-override, ${theme.cardBackgroundColor})`,\n \"--stamp-text\": `var(--stamprally-text-override, ${theme.textColor})`,\n \"--stamp-grid-cols\": String(theme.gridColumns),\n \"--stamp-grid-cols-mobile\": String(Math.min(theme.gridColumns, 2)),\n \"--stamp-unclaimed-opacity\": String(theme.unclaimedOpacity ?? 1),\n \"--stamp-font-family\": FONT_STACKS[theme.fontFamily ?? \"serif\"],\n ...(theme.completedStampColor === undefined\n ? {}\n : { \"--stamp-completed-color\": theme.completedStampColor }),\n \"--stamprally-primary\": `var(--stamprally-primary-override, ${theme.primaryColor})`,\n \"--stamprally-background\": `var(--stamprally-background-override, ${theme.backgroundColor ?? \"transparent\"})`,\n \"--stamprally-card\": `var(--stamprally-card-override, ${theme.cardBackgroundColor})`,\n \"--stamprally-text\": `var(--stamprally-text-override, ${theme.textColor})`,\n \"--stamprally-columns\": String(theme.gridColumns),\n } as CSSProperties;\n const messages = {\n available: dictionary?.[locale]?.available ?? (locale === \"en\" ? \"available\" : \"取得可能\"),\n locked: dictionary?.[locale]?.locked ?? (locale === \"en\" ? \"locked\" : \"順序待ち\"),\n stamped: dictionary?.[locale]?.stamped ?? (locale === \"en\" ? \"stamped\" : \"取得済み\"),\n remaining: (value: number) =>\n dictionary?.[locale]?.remaining?.replace(\"{count}\", String(value)) ??\n (locale === \"en\" ? `${value} spots remaining` : `あと${value}箇所`),\n completed:\n dictionary?.[locale]?.completed ?? (locale === \"en\" ? \"RALLY COMPLETED\" : \"ラリー達成\"),\n };\n return (\n <section\n className={`stamp-sheet ${percentage >= 100 ? \"stamp-sheet--completed\" : \"\"}`}\n style={style}\n aria-label={resolveLocalizedText(title, locale) || config.id}\n >\n <header className=\"stamp-sheet__header\">\n <h2>{resolveLocalizedText(title, locale) || config.id}</h2>\n <span className=\"stamp-sheet__score\" role=\"status\" aria-live=\"polite\">\n {count} / {total}\n </span>\n </header>\n <div className=\"stamp-sheet__progress-label\">\n <span>{messages.remaining(Math.max(0, total - count))}</span>\n <strong>{Math.round(percentage)}%</strong>\n </div>\n <div\n className=\"stamp-sheet__progress-track\"\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(percentage)}\n aria-label={locale === \"en\" ? \"Rally progress\" : \"スタンプ取得進捗\"}\n >\n <span\n className=\"stamp-sheet__progress-fill\"\n style={{ display: \"block\", width: `${percentage}%` }}\n />\n </div>\n <div className=\"stamp-sheet__grid\">\n {config.stamps.map((stamp, index) => {\n const recordForStamp = state?.records.find((record) => record.stampId === stamp.id);\n return (\n <StampSlot\n key={stamp.id}\n stamp={stamp}\n {...(recordForStamp === undefined ? {} : { record: recordForStamp })}\n isNext={next.has(stamp.id)}\n slotNumber={index + 1}\n {...(presentations[stamp.id] === undefined\n ? {}\n : { presentation: presentations[stamp.id] })}\n isAnimating={animatedStampId === stamp.id}\n disabled={disabled}\n slotShape={theme.slotShape}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n statusText={\n recordForStamp === undefined\n ? next.has(stamp.id)\n ? messages.available\n : messages.locked\n : messages.stamped\n }\n onSelect={() => onStampSelect?.(stamp.id)}\n />\n );\n })}\n </div>\n {percentage >= 100 && (\n <div className=\"stamp-sheet__complete-mark\" role=\"status\" aria-live=\"polite\">\n COMPLETE!!\n </div>\n )}\n {percentage >= 100 && (\n <div className=\"stamp-sheet__complete-message\">{messages.completed}</div>\n )}\n </section>\n );\n}\n\nexport interface AcquisitionFeedback {\n readonly ok: boolean;\n readonly message: string;\n}\nexport interface StampModalProps<TLocale extends string = SupportedLocale> {\n readonly open: boolean;\n readonly stamp: SpotItem<TLocale> | null;\n readonly record?: StampRallyState[\"records\"][number] | undefined;\n readonly presentation?: StampPresentation | null;\n readonly requiredStampName?: string | null;\n readonly isAvailable?: boolean;\n readonly isPending?: boolean;\n readonly isCompleted?: boolean;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly onClose: () => void;\n readonly onAcquire?: (\n stampId: string,\n context: VerificationContext,\n ) => Promise<AcquisitionFeedback>;\n readonly onCheckIn?: (\n stampId: string,\n context: VerificationContext,\n ) => Promise<AcquisitionFeedback>;\n readonly onNotify?: (feedback: AcquisitionFeedback) => void;\n}\n\nexport function StampModal<TLocale extends string = SupportedLocale>({\n open,\n stamp,\n record,\n isAvailable = true,\n isPending = false,\n locale = \"ja\" as TLocale,\n dictionary,\n onClose,\n onAcquire,\n onCheckIn,\n onNotify,\n}: StampModalProps<TLocale>) {\n const [token, setToken] = useState(\"\");\n const modalRef = useFocusTrap(open && stamp !== null, onClose, isPending);\n useEffect(() => {\n if (!open) setToken(\"\");\n }, [open]);\n if (!open || stamp === null) return null;\n const submit = async (context: VerificationContext): Promise<void> => {\n if (!isAvailable || record !== undefined) return;\n const handler = onAcquire ?? onCheckIn;\n if (handler === undefined) return;\n const feedback = await handler(stamp.id, context);\n onNotify?.(feedback);\n if (feedback.ok) onClose();\n };\n const name = resolveLocalizedText(stamp.name, locale);\n const messages = dictionary?.[locale] ?? {};\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"stamprally-modal-title\"\n className=\"stamprally-modal\"\n >\n <div className=\"stamprally-modal__panel\" ref={modalRef} tabIndex={-1}>\n <button\n type=\"button\"\n aria-label=\"Close stamp details\"\n aria-disabled={isPending}\n onClick={onClose}\n disabled={isPending}\n >\n ×\n </button>\n <h2 id=\"stamprally-modal-title\">{name}</h2>\n {record !== undefined ? (\n <p>{messages.alreadyClaimed ?? \"Already claimed.\"}</p>\n ) : (\n <p>{resolveLocalizedText(stamp.description, locale)}</p>\n )}\n {stamp.condition.type === \"token\" ? (\n <form\n onSubmit={(event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n void submit({ type: \"token\", token });\n }}\n >\n <label>\n {messages.passcode ?? \"Passcode\"}{\" \"}\n <input value={token} onChange={(event) => setToken(event.target.value)} />\n </label>\n <button\n type=\"submit\"\n aria-label=\"Claim stamp\"\n aria-disabled={!isAvailable || isPending}\n disabled={!isAvailable || isPending}\n >\n {messages.claimStamp ?? \"Claim stamp\"}\n </button>\n </form>\n ) : (\n <button\n type=\"button\"\n aria-label=\"Claim stamp\"\n aria-disabled={!isAvailable || isPending}\n onClick={() => void submit({ type: \"instant\" })}\n disabled={!isAvailable || isPending}\n >\n {messages.claimStamp ?? \"Claim stamp\"}\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport interface RewardPanelProps<TLocale extends string = SupportedLocale> {\n readonly rewards: ReadonlyArray<RewardItem<TLocale>>;\n readonly states: ReadonlyArray<RewardState>;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly isPending?: boolean;\n readonly open?: boolean;\n readonly onClose?: () => void;\n readonly onRedeem: (\n rewardId: string,\n options?: { readonly passcode?: string; readonly staffId?: string },\n ) => Promise<ConsumeResult>;\n readonly onNotify?: (ok: boolean, message: string) => void;\n}\n\nexport function RewardPanel<TLocale extends string = SupportedLocale>({\n rewards,\n states,\n locale = \"ja\" as TLocale,\n dictionary,\n isPending = false,\n open = true,\n onClose,\n onRedeem,\n onNotify,\n}: RewardPanelProps<TLocale>) {\n const [passcodes, setPasscodes] = useState<Readonly<Record<string, string>>>({});\n const panelRef = useFocusTrap(open && onClose !== undefined, onClose, isPending);\n if (!open) return null;\n return (\n <section\n ref={panelRef}\n role=\"dialog\"\n aria-labelledby=\"stamprally-rewards-title\"\n aria-modal=\"true\"\n className=\"stamprally-rewards\"\n tabIndex={-1}\n >\n <header className=\"stamprally-rewards__header\">\n <h2 id=\"stamprally-rewards-title\">{dictionary?.[locale]?.rewards ?? \"Rewards\"}</h2>\n {onClose !== undefined && (\n <button\n type=\"button\"\n aria-label=\"Close rewards\"\n aria-disabled={isPending}\n disabled={isPending}\n onClick={onClose}\n >\n ×\n </button>\n )}\n </header>\n {rewards.map((reward) => {\n const state = states.find((item) => item.rewardId === reward.id);\n const available = state?.status === \"AVAILABLE\";\n const redeem = async (options?: { readonly passcode?: string }): Promise<void> => {\n const result = await onRedeem(reward.id, options);\n onNotify?.(\n result.ok,\n result.ok\n ? (dictionary?.[locale]?.rewardClaimed ?? \"Reward claimed.\")\n : result.error.code,\n );\n };\n return (\n <article\n key={reward.id}\n className={`stamprally-reward stamprally-reward--${state?.status ?? \"LOCKED\"}`}\n >\n <h3>{resolveLocalizedText(reward.title, locale)}</h3>\n <p>{resolveLocalizedText(reward.description, locale)}</p>\n <span role=\"status\" aria-live=\"polite\">\n {state?.status ?? \"LOCKED\"}\n </span>\n {reward.redemptionMethod === \"staff_passcode\" && (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void redeem({ passcode: passcodes[reward.id] ?? \"\" });\n }}\n >\n <label>\n {dictionary?.[locale]?.staffPasscode ?? \"Staff passcode\"}{\" \"}\n <input\n type=\"password\"\n value={passcodes[reward.id] ?? \"\"}\n onChange={(event) =>\n setPasscodes((current) => ({ ...current, [reward.id]: event.target.value }))\n }\n />\n </label>\n <button\n type=\"submit\"\n aria-label={`Redeem ${resolveLocalizedText(reward.title, locale)}`}\n aria-disabled={!available || isPending}\n disabled={!available || isPending}\n >\n {dictionary?.[locale]?.redeem ?? \"Redeem\"}\n </button>\n </form>\n )}\n {reward.redemptionMethod !== \"staff_passcode\" && (\n <button\n type=\"button\"\n aria-label={`Redeem ${resolveLocalizedText(reward.title, locale)}`}\n aria-disabled={!available || isPending}\n disabled={!available || isPending}\n onClick={() => void redeem()}\n >\n {dictionary?.[locale]?.redeem ?? \"Redeem\"}\n </button>\n )}\n </article>\n );\n })}\n </section>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n type ClaimOptions,\n type ConsumeResult,\n DEFAULT_SHEET_THEME,\n type LocaleDictionary,\n type LocalizedText,\n type PublicRallyConfig,\n type RallyConfig,\n type RewardItem,\n type RewardState,\n resolveLocalizedText,\n type SheetTheme,\n type SlotShape,\n type SpotItem,\n type StampRallyProgress,\n type StampRallyState,\n type SupportedLocale,\n type UniversalCheckInResult,\n type UniversalClaimResult,\n type UniversalStampRallyClient,\n type UserRallyState,\n type VerificationContext,\n} from \"@stamprally/core\";\nimport type { CSSProperties, FormEvent, RefObject } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport type { LocaleDictionary } from \"@stamprally/core\";\n\nexport interface RallyViewerAdapter<TLocale extends string = string> {\n readonly state: UserRallyState;\n readonly config: PublicRallyConfig<TLocale>;\n readonly onCheckIn: (spotId: string, proof: unknown) => Promise<UniversalCheckInResult>;\n readonly onClaimReward: (\n rewardId: string,\n options?: ClaimOptions,\n ) => Promise<UniversalClaimResult>;\n readonly onSync?: () => Promise<void>;\n}\n\nexport interface RallyViewerProps<TLocale extends string = string> {\n readonly config?: PublicRallyConfig<TLocale>;\n readonly adapter?: RallyViewerAdapter<TLocale>;\n readonly client?: UniversalStampRallyClient;\n readonly locale?: TLocale;\n readonly onSpotSelect?: (spotId: string) => void;\n}\n\n/** Lightweight public-config viewer for applications that do not need the legacy StampSheet state model. */\nexport function RallyViewer<TLocale extends string = string>({\n config,\n adapter,\n client,\n locale,\n onSpotSelect,\n}: RallyViewerProps<TLocale>) {\n const activeLocale = locale ?? (\"en\" as TLocale);\n const resolvedConfig = adapter?.config ?? config ?? client?.getConfig();\n const renderConfig: PublicRallyConfig<TLocale> = resolvedConfig ?? {\n id: \"empty\",\n version: \"0.7.0\",\n title: \"\",\n spots: [],\n rewards: [],\n };\n const emptyState: UserRallyState = {\n rallyId: renderConfig.id,\n records: [],\n updatedAt: new Date(0).toISOString(),\n };\n const resolvedState = adapter?.state ?? client?.getState() ?? emptyState;\n const [selectedSpotId, setSelectedSpotId] = useState<string | null>(null);\n const [proof, setProof] = useState(\"\");\n const [feedback, setFeedback] = useState<string | null>(null);\n const [, setClientRevision] = useState(0);\n useEffect(() => {\n if (client === undefined) return;\n return client.subscribe(() => setClientRevision((revision) => revision + 1));\n }, [client]);\n const selectedSpot = renderConfig.spots.find((spot) => spot.id === selectedSpotId);\n const checkIn =\n adapter?.onCheckIn ??\n (client === undefined\n ? undefined\n : (spotId: string, value: unknown) => client.checkIn(spotId, value));\n const claimReward =\n adapter?.onClaimReward ??\n (client === undefined\n ? undefined\n : (rewardId: string, options?: ClaimOptions) => client.claimReward(rewardId, options));\n const claimed = new Set(resolvedState.records.map((record) => record.stampId));\n const submit = async (): Promise<void> => {\n if (selectedSpot === undefined || checkIn === undefined) return;\n const result = await checkIn(selectedSpot.id, proof);\n setFeedback(result.ok ? \"Check-in completed.\" : result.error.code);\n if (result.ok) {\n setProof(\"\");\n setSelectedSpotId(null);\n }\n };\n if (resolvedConfig === undefined) return null;\n return (\n <section aria-label=\"Stamp rally viewer\" className=\"stamprally-viewer\">\n <header>\n <h1>{resolveLocalizedText(renderConfig.title, activeLocale)}</h1>\n {renderConfig.description !== undefined && (\n <p>{resolveLocalizedText(renderConfig.description, activeLocale)}</p>\n )}\n {adapter?.onSync !== undefined && (\n <button type=\"button\" onClick={() => void adapter.onSync?.()}>\n Sync\n </button>\n )}\n </header>\n {/* biome-ignore lint/a11y/useSemanticElements: The viewer exposes the requested ARIA grid contract. */}\n <div role=\"grid\" aria-label=\"Stamp rally spots\">\n {renderConfig.spots.map((spot, index) => (\n <div key={spot.id}>\n <button\n type=\"button\"\n aria-label={`${resolveLocalizedText(spot.name, activeLocale)}${claimed.has(spot.id) ? \", claimed\" : \", available\"}`}\n onClick={() => {\n onSpotSelect?.(spot.id);\n setSelectedSpotId(spot.id);\n setFeedback(null);\n }}\n >\n <span aria-hidden=\"true\">#{String(index + 1).padStart(2, \"0\")}</span>{\" \"}\n {resolveLocalizedText(spot.name, activeLocale)}\n </button>\n <span>{spot.conditions[0]?.type ?? \"custom\"}</span>\n </div>\n ))}\n </div>\n <p role=\"status\" aria-live=\"polite\">\n {feedback ?? `${claimed.size} / ${renderConfig.spots.length} claimed`}\n </p>\n <section aria-label=\"Rewards\">\n <h2>Rewards</h2>\n {renderConfig.rewards.map((reward) => {\n const rewardState = resolvedState.rewards?.find((item) => item.rewardId === reward.id);\n const available = rewardState?.status === \"AVAILABLE\";\n return (\n <article key={reward.id}>\n <h3>{resolveLocalizedText(reward.title, activeLocale)}</h3>\n <span>{rewardState?.status ?? \"LOCKED\"}</span>\n {claimReward !== undefined && (\n <button\n type=\"button\"\n disabled={!available}\n onClick={() =>\n void claimReward(reward.id).then((result) => {\n setFeedback(result.ok ? \"Reward claimed.\" : result.error.code);\n })\n }\n >\n Claim reward\n </button>\n )}\n </article>\n );\n })}\n </section>\n {selectedSpot !== undefined && checkIn !== undefined && (\n <div role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"rally-viewer-spot-title\">\n <h2 id=\"rally-viewer-spot-title\">\n {resolveLocalizedText(selectedSpot.name, activeLocale)}\n </h2>\n <p>{resolveLocalizedText(selectedSpot.description, activeLocale)}</p>\n <label>\n Proof\n <input value={proof} onChange={(event) => setProof(event.target.value)} />\n </label>\n <button\n type=\"button\"\n onClick={() => void submit()}\n disabled={claimed.has(selectedSpot.id)}\n >\n Check in\n </button>\n <button type=\"button\" onClick={() => setSelectedSpotId(null)}>\n Close\n </button>\n </div>\n )}\n </section>\n );\n}\n\nfunction useFocusTrap(\n active: boolean,\n onClose: (() => void) | undefined,\n closeDisabled = false,\n): RefObject<HTMLDivElement | null> {\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!active) return;\n const container = containerRef.current;\n if (container === null) return;\n\n const focusableSelector =\n 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n const focusable = (): ReadonlyArray<HTMLElement> =>\n Array.from(container.querySelectorAll<HTMLElement>(focusableSelector));\n const first = focusable()[0];\n first?.focus();\n\n const handleKeyDown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n if (!closeDisabled) {\n event.preventDefault();\n onClose?.();\n }\n return;\n }\n if (event.key !== \"Tab\") return;\n\n const elements = focusable();\n if (elements.length === 0) {\n event.preventDefault();\n container.focus();\n return;\n }\n const firstElement = elements[0];\n const lastElement = elements[elements.length - 1];\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement?.focus();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement?.focus();\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [active, closeDisabled, onClose]);\n\n return containerRef;\n}\n\nexport interface StampPresentation {\n readonly label?: string;\n readonly icon?: string;\n readonly ink?: \"vermilion\" | \"indigo\";\n readonly channel?: \"instant\" | \"qr\" | \"nfc\" | \"geo\";\n}\n\nexport interface StampSlotProps<TLocale extends string = SupportedLocale> {\n readonly stamp: SpotItem<TLocale>;\n readonly record?: StampRallyState[\"records\"][number] | undefined;\n readonly isNext?: boolean;\n readonly slotNumber?: number;\n readonly presentation?: StampPresentation | undefined;\n readonly isAnimating?: boolean;\n readonly disabled?: boolean;\n readonly slotShape?: SlotShape;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly statusText?: string;\n readonly onSelect?: () => void;\n}\n\nconst FONT_STACKS: Readonly<Record<NonNullable<SheetTheme[\"fontFamily\"]>, string>> = {\n \"system-ui\": 'system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n serif: 'Georgia, \"Times New Roman\", \"Yu Mincho\", serif',\n \"rounded-sans\": '\"Arial Rounded MT Bold\", \"Hiragino Maru Gothic ProN\", \"Yu Gothic\", sans-serif',\n monospace: 'ui-monospace, SFMono-Regular, Consolas, \"Liberation Mono\", monospace',\n handwritten: '\"Segoe Print\", \"Bradley Hand\", \"Comic Sans MS\", cursive',\n};\n\nfunction formatStampDate(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n const pad = (part: number) => String(part).padStart(2, \"0\");\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;\n}\n\nexport function StampSlot<TLocale extends string = SupportedLocale>({\n stamp,\n record,\n isNext = false,\n slotNumber = 1,\n presentation = {},\n isAnimating = false,\n disabled = false,\n slotShape = \"rounded\",\n locale = \"ja\" as TLocale,\n statusText,\n onSelect,\n}: StampSlotProps<TLocale>) {\n const status = record === undefined ? (isNext ? \"available\" : \"locked\") : \"stamped\";\n const resolvedStatus = statusText ?? status;\n const statusSeparator = statusText !== undefined && locale === \"ja\" ? \"、\" : \", \";\n const name = resolveLocalizedText(stamp.name, locale);\n const label = presentation.label ?? stamp.condition.type;\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={onSelect}\n aria-label={`#${String(slotNumber).padStart(2, \"0\")} ${name}${statusSeparator}${resolvedStatus}`}\n aria-disabled={disabled}\n data-status={status}\n data-shape={slotShape}\n className={`stamp-slot stamp-slot--${status} stamp-slot--${presentation.ink ?? \"vermilion\"} stamp-slot--shape-${slotShape}${isAnimating ? \" stamp-slot--animating\" : \"\"}`}\n style={{ \"--stamp-primary\": \"var(--stamprally-primary, #9e551e)\" } as CSSProperties}\n >\n <span className=\"stamp-slot__topline\">\n <span className=\"stamp-slot__number\">#{String(slotNumber).padStart(2, \"0\")}</span>\n <span className={`stamp-slot__state stamp-slot__state--${status}`}>{resolvedStatus}</span>\n </span>\n <span className=\"stamp-slot__watermark\" aria-hidden=\"true\">\n {presentation.icon ?? \"✦\"}\n </span>\n <span className=\"stamp-slot__name\">{name}</span>\n <span className=\"stamp-slot__condition\">\n <span aria-hidden=\"true\">{presentation.icon ?? \"✦\"}</span>\n {label}\n </span>\n {record !== undefined && (\n <span\n className={`stamp-imprint ${isAnimating ? \"stamp-press\" : \"\"}`}\n role=\"img\"\n aria-label={`Acquired at ${formatStampDate(record.acquiredAt)}`}\n >\n <span className=\"stamp-imprint__inner\">\n <span className=\"stamp-imprint__word\">STAMP</span>\n <span className=\"stamp-imprint__date\">{formatStampDate(record.acquiredAt)}</span>\n </span>\n </span>\n )}\n </button>\n );\n}\n\nexport interface StampSheetProps<TLocale extends string = SupportedLocale> {\n readonly title?: LocalizedText<TLocale>;\n readonly config: RallyConfig<TLocale> | PublicRallyConfig<TLocale>;\n readonly state?: StampRallyState | null;\n readonly progress?: StampRallyProgress;\n readonly presentations?: Readonly<Record<string, StampPresentation>>;\n readonly animatedStampId?: string | null;\n readonly disabled?: boolean;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly theme?: SheetTheme;\n readonly onStampSelect?: (stampId: string) => void;\n readonly adapter?: RallyViewerAdapter<TLocale>;\n}\n\nexport function StampSheet<TLocale extends string = SupportedLocale>({\n title,\n config,\n state = null,\n progress,\n presentations = {},\n animatedStampId = null,\n disabled = false,\n locale = \"ja\" as TLocale,\n dictionary,\n theme = config.theme ?? DEFAULT_SHEET_THEME,\n onStampSelect,\n adapter,\n}: StampSheetProps<TLocale>) {\n if (\"spots\" in config) {\n if (adapter === undefined)\n return (\n <RallyViewer\n config={config}\n locale={locale}\n {...(onStampSelect === undefined ? {} : { onSpotSelect: onStampSelect })}\n />\n );\n return (\n <RallyViewer\n config={config}\n adapter={adapter}\n locale={locale}\n {...(onStampSelect === undefined ? {} : { onSpotSelect: onStampSelect })}\n />\n );\n }\n const acquired = new Set(state?.records.map((record) => record.stampId) ?? []);\n const next = new Set(progress?.nextAvailableStamps.map((stamp) => stamp.id) ?? []);\n const count = progress?.acquired ?? acquired.size;\n const total = progress?.total ?? config.stamps.length;\n const percentage = progress?.percentage ?? (total === 0 ? 0 : (count / total) * 100);\n const style = {\n \"--stamp-primary\": `var(--stamprally-primary-override, ${theme.primaryColor})`,\n \"--stamp-bg\": `var(--stamprally-background-override, ${theme.backgroundColor ?? DEFAULT_SHEET_THEME.backgroundColor ?? \"#ffffff\"})`,\n \"--stamp-card-bg\": `var(--stamprally-card-override, ${theme.cardBackgroundColor})`,\n \"--stamp-text\": `var(--stamprally-text-override, ${theme.textColor})`,\n \"--stamp-grid-cols\": String(theme.gridColumns),\n \"--stamp-grid-cols-mobile\": String(Math.min(theme.gridColumns, 2)),\n \"--stamp-unclaimed-opacity\": String(theme.unclaimedOpacity ?? 1),\n \"--stamp-font-family\": FONT_STACKS[theme.fontFamily ?? \"serif\"],\n ...(theme.completedStampColor === undefined\n ? {}\n : { \"--stamp-completed-color\": theme.completedStampColor }),\n \"--stamprally-primary\": `var(--stamprally-primary-override, ${theme.primaryColor})`,\n \"--stamprally-background\": `var(--stamprally-background-override, ${theme.backgroundColor ?? \"transparent\"})`,\n \"--stamprally-card\": `var(--stamprally-card-override, ${theme.cardBackgroundColor})`,\n \"--stamprally-text\": `var(--stamprally-text-override, ${theme.textColor})`,\n \"--stamprally-columns\": String(theme.gridColumns),\n } as CSSProperties;\n const messages = {\n available: dictionary?.[locale]?.available ?? (locale === \"en\" ? \"available\" : \"取得可能\"),\n locked: dictionary?.[locale]?.locked ?? (locale === \"en\" ? \"locked\" : \"順序待ち\"),\n stamped: dictionary?.[locale]?.stamped ?? (locale === \"en\" ? \"stamped\" : \"取得済み\"),\n remaining: (value: number) =>\n dictionary?.[locale]?.remaining?.replace(\"{count}\", String(value)) ??\n (locale === \"en\" ? `${value} spots remaining` : `あと${value}箇所`),\n completed:\n dictionary?.[locale]?.completed ?? (locale === \"en\" ? \"RALLY COMPLETED\" : \"ラリー達成\"),\n };\n return (\n <section\n className={`stamp-sheet ${percentage >= 100 ? \"stamp-sheet--completed\" : \"\"}`}\n style={style}\n aria-label={resolveLocalizedText(title, locale) || config.id}\n >\n <header className=\"stamp-sheet__header\">\n <h2>{resolveLocalizedText(title, locale) || config.id}</h2>\n <span className=\"stamp-sheet__score\" role=\"status\" aria-live=\"polite\">\n {count} / {total}\n </span>\n </header>\n <div className=\"stamp-sheet__progress-label\">\n <span>{messages.remaining(Math.max(0, total - count))}</span>\n <strong>{Math.round(percentage)}%</strong>\n </div>\n <div\n className=\"stamp-sheet__progress-track\"\n role=\"progressbar\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={Math.round(percentage)}\n aria-label={locale === \"en\" ? \"Rally progress\" : \"スタンプ取得進捗\"}\n >\n <span\n className=\"stamp-sheet__progress-fill\"\n style={{ display: \"block\", width: `${percentage}%` }}\n />\n </div>\n <div className=\"stamp-sheet__grid\">\n {config.stamps.map((stamp, index) => {\n const recordForStamp = state?.records.find((record) => record.stampId === stamp.id);\n return (\n <StampSlot\n key={stamp.id}\n stamp={stamp}\n {...(recordForStamp === undefined ? {} : { record: recordForStamp })}\n isNext={next.has(stamp.id)}\n slotNumber={index + 1}\n {...(presentations[stamp.id] === undefined\n ? {}\n : { presentation: presentations[stamp.id] })}\n isAnimating={animatedStampId === stamp.id}\n disabled={disabled}\n slotShape={theme.slotShape}\n locale={locale}\n {...(dictionary === undefined ? {} : { dictionary })}\n statusText={\n recordForStamp === undefined\n ? next.has(stamp.id)\n ? messages.available\n : messages.locked\n : messages.stamped\n }\n onSelect={() => onStampSelect?.(stamp.id)}\n />\n );\n })}\n </div>\n {percentage >= 100 && (\n <div className=\"stamp-sheet__complete-mark\" role=\"status\" aria-live=\"polite\">\n COMPLETE!!\n </div>\n )}\n {percentage >= 100 && (\n <div className=\"stamp-sheet__complete-message\">{messages.completed}</div>\n )}\n </section>\n );\n}\n\nexport interface AcquisitionFeedback {\n readonly ok: boolean;\n readonly message: string;\n}\nexport interface StampModalProps<TLocale extends string = SupportedLocale> {\n readonly open: boolean;\n readonly stamp: SpotItem<TLocale> | null;\n readonly record?: StampRallyState[\"records\"][number] | undefined;\n readonly presentation?: StampPresentation | null;\n readonly requiredStampName?: string | null;\n readonly isAvailable?: boolean;\n readonly isPending?: boolean;\n readonly isCompleted?: boolean;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly onClose: () => void;\n readonly onAcquire?: (\n stampId: string,\n context: VerificationContext,\n ) => Promise<AcquisitionFeedback>;\n readonly onCheckIn?: (\n stampId: string,\n context: VerificationContext,\n ) => Promise<AcquisitionFeedback>;\n readonly onNotify?: (feedback: AcquisitionFeedback) => void;\n}\n\nexport function StampModal<TLocale extends string = SupportedLocale>({\n open,\n stamp,\n record,\n isAvailable = true,\n isPending = false,\n locale = \"ja\" as TLocale,\n dictionary,\n onClose,\n onAcquire,\n onCheckIn,\n onNotify,\n}: StampModalProps<TLocale>) {\n const [token, setToken] = useState(\"\");\n const modalRef = useFocusTrap(open && stamp !== null, onClose, isPending);\n useEffect(() => {\n if (!open) setToken(\"\");\n }, [open]);\n if (!open || stamp === null) return null;\n const submit = async (context: VerificationContext): Promise<void> => {\n if (!isAvailable || record !== undefined) return;\n const handler = onAcquire ?? onCheckIn;\n if (handler === undefined) return;\n const feedback = await handler(stamp.id, context);\n onNotify?.(feedback);\n if (feedback.ok) onClose();\n };\n const name = resolveLocalizedText(stamp.name, locale);\n const messages = dictionary?.[locale] ?? {};\n return (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"stamprally-modal-title\"\n className=\"stamprally-modal\"\n >\n <div className=\"stamprally-modal__panel\" ref={modalRef} tabIndex={-1}>\n <button\n type=\"button\"\n aria-label=\"Close stamp details\"\n aria-disabled={isPending}\n onClick={onClose}\n disabled={isPending}\n >\n ×\n </button>\n <h2 id=\"stamprally-modal-title\">{name}</h2>\n {record !== undefined ? (\n <p>{messages.alreadyClaimed ?? \"Already claimed.\"}</p>\n ) : (\n <p>{resolveLocalizedText(stamp.description, locale)}</p>\n )}\n {stamp.condition.type === \"token\" ? (\n <form\n onSubmit={(event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n void submit({ type: \"token\", token });\n }}\n >\n <label>\n {messages.passcode ?? \"Passcode\"}{\" \"}\n <input value={token} onChange={(event) => setToken(event.target.value)} />\n </label>\n <button\n type=\"submit\"\n aria-label=\"Claim stamp\"\n aria-disabled={!isAvailable || isPending}\n disabled={!isAvailable || isPending}\n >\n {messages.claimStamp ?? \"Claim stamp\"}\n </button>\n </form>\n ) : (\n <button\n type=\"button\"\n aria-label=\"Claim stamp\"\n aria-disabled={!isAvailable || isPending}\n onClick={() => void submit({ type: \"instant\" })}\n disabled={!isAvailable || isPending}\n >\n {messages.claimStamp ?? \"Claim stamp\"}\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport interface RewardPanelProps<TLocale extends string = SupportedLocale> {\n readonly rewards: ReadonlyArray<RewardItem<TLocale>>;\n readonly states: ReadonlyArray<RewardState>;\n readonly locale?: TLocale;\n readonly dictionary?: LocaleDictionary<TLocale>;\n readonly isPending?: boolean;\n readonly open?: boolean;\n readonly onClose?: () => void;\n readonly onRedeem: (\n rewardId: string,\n options?: { readonly passcode?: string; readonly staffId?: string },\n ) => Promise<ConsumeResult>;\n readonly onNotify?: (ok: boolean, message: string) => void;\n}\n\nexport function RewardPanel<TLocale extends string = SupportedLocale>({\n rewards,\n states,\n locale = \"ja\" as TLocale,\n dictionary,\n isPending = false,\n open = true,\n onClose,\n onRedeem,\n onNotify,\n}: RewardPanelProps<TLocale>) {\n const [passcodes, setPasscodes] = useState<Readonly<Record<string, string>>>({});\n const panelRef = useFocusTrap(open && onClose !== undefined, onClose, isPending);\n if (!open) return null;\n return (\n <section\n ref={panelRef}\n role=\"dialog\"\n aria-labelledby=\"stamprally-rewards-title\"\n aria-modal=\"true\"\n className=\"stamprally-rewards\"\n tabIndex={-1}\n >\n <header className=\"stamprally-rewards__header\">\n <h2 id=\"stamprally-rewards-title\">{dictionary?.[locale]?.rewards ?? \"Rewards\"}</h2>\n {onClose !== undefined && (\n <button\n type=\"button\"\n aria-label=\"Close rewards\"\n aria-disabled={isPending}\n disabled={isPending}\n onClick={onClose}\n >\n ×\n </button>\n )}\n </header>\n {rewards.map((reward) => {\n const state = states.find((item) => item.rewardId === reward.id);\n const available = state?.status === \"AVAILABLE\";\n const redeem = async (options?: { readonly passcode?: string }): Promise<void> => {\n const result = await onRedeem(reward.id, options);\n onNotify?.(\n result.ok,\n result.ok\n ? (dictionary?.[locale]?.rewardClaimed ?? \"Reward claimed.\")\n : result.error.code,\n );\n };\n return (\n <article\n key={reward.id}\n className={`stamprally-reward stamprally-reward--${state?.status ?? \"LOCKED\"}`}\n >\n <h3>{resolveLocalizedText(reward.title, locale)}</h3>\n <p>{resolveLocalizedText(reward.description, locale)}</p>\n <span role=\"status\" aria-live=\"polite\">\n {state?.status ?? \"LOCKED\"}\n </span>\n {reward.redemptionMethod === \"staff_passcode\" && (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n void redeem({ passcode: passcodes[reward.id] ?? \"\" });\n }}\n >\n <label>\n {dictionary?.[locale]?.staffPasscode ?? \"Staff passcode\"}{\" \"}\n <input\n type=\"password\"\n value={passcodes[reward.id] ?? \"\"}\n onChange={(event) =>\n setPasscodes((current) => ({ ...current, [reward.id]: event.target.value }))\n }\n />\n </label>\n <button\n type=\"submit\"\n aria-label={`Redeem ${resolveLocalizedText(reward.title, locale)}`}\n aria-disabled={!available || isPending}\n disabled={!available || isPending}\n >\n {dictionary?.[locale]?.redeem ?? \"Redeem\"}\n </button>\n </form>\n )}\n {reward.redemptionMethod !== \"staff_passcode\" && (\n <button\n type=\"button\"\n aria-label={`Redeem ${resolveLocalizedText(reward.title, locale)}`}\n aria-disabled={!available || isPending}\n disabled={!available || isPending}\n onClick={() => void redeem()}\n >\n {dictionary?.[locale]?.redeem ?? \"Redeem\"}\n </button>\n )}\n </article>\n );\n })}\n </section>\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stamprally/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Accessible participant UI components for stamp rallies.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"./styles.css": "./dist/index.css"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@stamprally/core": "0.
|
|
33
|
-
"@stamprally/react": "0.
|
|
32
|
+
"@stamprally/core": "0.8.0",
|
|
33
|
+
"@stamprally/react": "0.8.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": "^18.0.0 || ^19.0.0",
|