@stamprally/ui 0.4.0 → 0.5.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 +24 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -18
- package/dist/index.d.ts +23 -18
- package/dist/index.js +24 -21
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -127,6 +127,7 @@ function StampSheet({
|
|
|
127
127
|
animatedStampId = null,
|
|
128
128
|
disabled = false,
|
|
129
129
|
locale = "ja",
|
|
130
|
+
dictionary,
|
|
130
131
|
theme = config.theme ?? core.DEFAULT_SHEET_THEME,
|
|
131
132
|
onStampSelect
|
|
132
133
|
}) {
|
|
@@ -151,18 +152,12 @@ function StampSheet({
|
|
|
151
152
|
"--stamprally-text": `var(--stamprally-text-override, ${theme.textColor})`,
|
|
152
153
|
"--stamprally-columns": String(theme.gridColumns)
|
|
153
154
|
};
|
|
154
|
-
const messages =
|
|
155
|
-
available: "available",
|
|
156
|
-
locked: "locked",
|
|
157
|
-
stamped: "stamped",
|
|
158
|
-
remaining: (value) => `${value} spots remaining
|
|
159
|
-
completed: "RALLY COMPLETED"
|
|
160
|
-
} : {
|
|
161
|
-
available: "\u53D6\u5F97\u53EF\u80FD",
|
|
162
|
-
locked: "\u9806\u5E8F\u5F85\u3061",
|
|
163
|
-
stamped: "\u53D6\u5F97\u6E08\u307F",
|
|
164
|
-
remaining: (value) => `\u3042\u3068${value}\u7B87\u6240`,
|
|
165
|
-
completed: "\u30E9\u30EA\u30FC\u9054\u6210"
|
|
155
|
+
const messages = {
|
|
156
|
+
available: dictionary?.[locale]?.available ?? (locale === "en" ? "available" : "\u53D6\u5F97\u53EF\u80FD"),
|
|
157
|
+
locked: dictionary?.[locale]?.locked ?? (locale === "en" ? "locked" : "\u9806\u5E8F\u5F85\u3061"),
|
|
158
|
+
stamped: dictionary?.[locale]?.stamped ?? (locale === "en" ? "stamped" : "\u53D6\u5F97\u6E08\u307F"),
|
|
159
|
+
remaining: (value) => dictionary?.[locale]?.remaining?.replace("{count}", String(value)) ?? (locale === "en" ? `${value} spots remaining` : `\u3042\u3068${value}\u7B87\u6240`),
|
|
160
|
+
completed: dictionary?.[locale]?.completed ?? (locale === "en" ? "RALLY COMPLETED" : "\u30E9\u30EA\u30FC\u9054\u6210")
|
|
166
161
|
};
|
|
167
162
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
168
163
|
"section",
|
|
@@ -218,6 +213,7 @@ function StampSheet({
|
|
|
218
213
|
disabled,
|
|
219
214
|
slotShape: theme.slotShape,
|
|
220
215
|
locale,
|
|
216
|
+
...dictionary === void 0 ? {} : { dictionary },
|
|
221
217
|
statusText: recordForStamp === void 0 ? next.has(stamp.id) ? messages.available : messages.locked : messages.stamped,
|
|
222
218
|
onSelect: () => onStampSelect?.(stamp.id)
|
|
223
219
|
},
|
|
@@ -237,6 +233,7 @@ function StampModal({
|
|
|
237
233
|
isAvailable = true,
|
|
238
234
|
isPending = false,
|
|
239
235
|
locale = "ja",
|
|
236
|
+
dictionary,
|
|
240
237
|
onClose,
|
|
241
238
|
onAcquire,
|
|
242
239
|
onCheckIn,
|
|
@@ -257,6 +254,7 @@ function StampModal({
|
|
|
257
254
|
if (feedback.ok) onClose();
|
|
258
255
|
};
|
|
259
256
|
const name = core.resolveLocalizedText(stamp.name, locale);
|
|
257
|
+
const messages = dictionary?.[locale] ?? {};
|
|
260
258
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
261
259
|
"div",
|
|
262
260
|
{
|
|
@@ -277,7 +275,7 @@ function StampModal({
|
|
|
277
275
|
}
|
|
278
276
|
),
|
|
279
277
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: "stamprally-modal-title", children: name }),
|
|
280
|
-
record !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Already claimed." }) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: core.resolveLocalizedText(stamp.description, locale) }),
|
|
278
|
+
record !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { children: messages.alreadyClaimed ?? "Already claimed." }) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: core.resolveLocalizedText(stamp.description, locale) }),
|
|
281
279
|
stamp.condition.type === "token" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
282
280
|
"form",
|
|
283
281
|
{
|
|
@@ -287,7 +285,8 @@ function StampModal({
|
|
|
287
285
|
},
|
|
288
286
|
children: [
|
|
289
287
|
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
290
|
-
"Passcode
|
|
288
|
+
messages.passcode ?? "Passcode",
|
|
289
|
+
" ",
|
|
291
290
|
/* @__PURE__ */ jsxRuntime.jsx("input", { value: token, onChange: (event) => setToken(event.target.value) })
|
|
292
291
|
] }),
|
|
293
292
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -297,7 +296,7 @@ function StampModal({
|
|
|
297
296
|
"aria-label": "Claim stamp",
|
|
298
297
|
"aria-disabled": !isAvailable || isPending,
|
|
299
298
|
disabled: !isAvailable || isPending,
|
|
300
|
-
children: "Claim stamp"
|
|
299
|
+
children: messages.claimStamp ?? "Claim stamp"
|
|
301
300
|
}
|
|
302
301
|
)
|
|
303
302
|
]
|
|
@@ -310,7 +309,7 @@ function StampModal({
|
|
|
310
309
|
"aria-disabled": !isAvailable || isPending,
|
|
311
310
|
onClick: () => void submit({ type: "instant" }),
|
|
312
311
|
disabled: !isAvailable || isPending,
|
|
313
|
-
children: "Claim stamp"
|
|
312
|
+
children: messages.claimStamp ?? "Claim stamp"
|
|
314
313
|
}
|
|
315
314
|
)
|
|
316
315
|
] })
|
|
@@ -321,6 +320,7 @@ function RewardPanel({
|
|
|
321
320
|
rewards,
|
|
322
321
|
states,
|
|
323
322
|
locale = "ja",
|
|
323
|
+
dictionary,
|
|
324
324
|
isPending = false,
|
|
325
325
|
open = true,
|
|
326
326
|
onClose,
|
|
@@ -341,7 +341,7 @@ function RewardPanel({
|
|
|
341
341
|
tabIndex: -1,
|
|
342
342
|
children: [
|
|
343
343
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "stamprally-rewards__header", children: [
|
|
344
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: "stamprally-rewards-title", children: "Rewards" }),
|
|
344
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: "stamprally-rewards-title", children: dictionary?.[locale]?.rewards ?? "Rewards" }),
|
|
345
345
|
onClose !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
346
346
|
"button",
|
|
347
347
|
{
|
|
@@ -359,7 +359,10 @@ function RewardPanel({
|
|
|
359
359
|
const available = state?.status === "AVAILABLE";
|
|
360
360
|
const redeem = async (options) => {
|
|
361
361
|
const result = await onRedeem(reward.id, options);
|
|
362
|
-
onNotify?.(
|
|
362
|
+
onNotify?.(
|
|
363
|
+
result.ok,
|
|
364
|
+
result.ok ? dictionary?.[locale]?.rewardClaimed ?? "Reward claimed." : result.error.code
|
|
365
|
+
);
|
|
363
366
|
};
|
|
364
367
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
365
368
|
"article",
|
|
@@ -378,7 +381,7 @@ function RewardPanel({
|
|
|
378
381
|
},
|
|
379
382
|
children: [
|
|
380
383
|
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
381
|
-
"Staff passcode",
|
|
384
|
+
dictionary?.[locale]?.staffPasscode ?? "Staff passcode",
|
|
382
385
|
" ",
|
|
383
386
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
384
387
|
"input",
|
|
@@ -396,7 +399,7 @@ function RewardPanel({
|
|
|
396
399
|
"aria-label": `Redeem ${core.resolveLocalizedText(reward.title, locale)}`,
|
|
397
400
|
"aria-disabled": !available || isPending,
|
|
398
401
|
disabled: !available || isPending,
|
|
399
|
-
children: "Redeem"
|
|
402
|
+
children: dictionary?.[locale]?.redeem ?? "Redeem"
|
|
400
403
|
}
|
|
401
404
|
)
|
|
402
405
|
]
|
|
@@ -410,7 +413,7 @@ function RewardPanel({
|
|
|
410
413
|
"aria-disabled": !available || isPending,
|
|
411
414
|
disabled: !available || isPending,
|
|
412
415
|
onClick: () => void redeem(),
|
|
413
|
-
children: "Redeem"
|
|
416
|
+
children: dictionary?.[locale]?.redeem ?? "Redeem"
|
|
414
417
|
}
|
|
415
418
|
)
|
|
416
419
|
]
|
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":";;;;;;;AAmBA,SAAS,YAAA,CACP,MAAA,EACA,OAAA,EACA,aAAA,GAAgB,KAAA,EACkB;AAClC,EAAA,MAAM,YAAA,GAAeA,aAA8B,IAAI,CAAA;AAEvD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,MAAM,YAAY,YAAA,CAAa,OAAA;AAC/B,IAAA,IAAI,cAAc,IAAA,EAAM;AAExB,IAAA,MAAM,iBAAA,GACJ,0IAAA;AACF,IAAA,MAAM,YAAY,MAChB,KAAA,CAAM,KAAK,SAAA,CAAU,gBAAA,CAA8B,iBAAiB,CAAC,CAAA;AACvE,IAAA,MAAM,KAAA,GAAQ,SAAA,EAAU,CAAE,CAAC,CAAA;AAC3B,IAAA,KAAA,EAAO,KAAA,EAAM;AAEb,IAAA,MAAM,aAAA,GAAgB,CAAC,KAAA,KAA+B;AACpD,MAAA,IAAI,KAAA,CAAM,QAAQ,QAAA,EAAU;AAC1B,QAAA,IAAI,CAAC,aAAA,EAAe;AAClB,UAAA,KAAA,CAAM,cAAA,EAAe;AACrB,UAAA,OAAA,IAAU;AAAA,QACZ;AACA,QAAA;AAAA,MACF;AACA,MAAA,IAAI,KAAA,CAAM,QAAQ,KAAA,EAAO;AAEzB,MAAA,MAAM,WAAW,SAAA,EAAU;AAC3B,MAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,QAAA,KAAA,CAAM,cAAA,EAAe;AACrB,QAAA,SAAA,CAAU,KAAA,EAAM;AAChB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,YAAA,GAAe,SAAS,CAAC,CAAA;AAC/B,MAAA,MAAM,WAAA,GAAc,QAAA,CAAS,QAAA,CAAS,MAAA,GAAS,CAAC,CAAA;AAChD,MAAA,IAAI,KAAA,CAAM,QAAA,IAAY,QAAA,CAAS,aAAA,KAAkB,YAAA,EAAc;AAC7D,QAAA,KAAA,CAAM,cAAA,EAAe;AACrB,QAAA,WAAA,EAAa,KAAA,EAAM;AAAA,MACrB,WAAW,CAAC,KAAA,CAAM,QAAA,IAAY,QAAA,CAAS,kBAAkB,WAAA,EAAa;AACpE,QAAA,KAAA,CAAM,cAAA,EAAe;AACrB,QAAA,YAAA,EAAc,KAAA,EAAM;AAAA,MACtB;AAAA,IACF,CAAA;AAEA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,aAAa,CAAA;AAClD,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,aAAa,CAAA;AAAA,EACpE,CAAA,EAAG,CAAC,MAAA,EAAQ,aAAA,EAAe,OAAO,CAAC,CAAA;AAEnC,EAAA,OAAO,YAAA;AACT;AAuBA,IAAM,WAAA,GAA+E;AAAA,EACnF,WAAA,EAAa,sEAAA;AAAA,EACb,KAAA,EAAO,gDAAA;AAAA,EACP,cAAA,EAAgB,+EAAA;AAAA,EAChB,SAAA,EAAW,sEAAA;AAAA,EACX,WAAA,EAAa;AACf,CAAA;AAEA,SAAS,gBAAgB,KAAA,EAAuB;AAC9C,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,KAAK,CAAA;AAC3B,EAAA,IAAI,OAAO,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,GAAG,OAAO,KAAA;AACzC,EAAA,MAAM,GAAA,GAAM,CAAC,IAAA,KAAiB,MAAA,CAAO,IAAI,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAC1D,EAAA,OAAO,CAAA,EAAG,IAAA,CAAK,WAAA,EAAa,CAAA,CAAA,EAAI,GAAA,CAAI,IAAA,CAAK,QAAA,EAAS,GAAI,CAAC,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,IAAA,CAAK,OAAA,EAAS,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,IAAA,CAAK,QAAA,EAAU,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,IAAA,CAAK,UAAA,EAAY,CAAC,CAAA,CAAA;AACnI;AAEO,SAAS,SAAA,CAAU;AAAA,EACxB,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA,EACT,UAAA,GAAa,CAAA;AAAA,EACb,eAAe,EAAC;AAAA,EAChB,WAAA,GAAc,KAAA;AAAA,EACd,QAAA,GAAW,KAAA;AAAA,EACX,SAAA,GAAY,SAAA;AAAA,EACZ,MAAA,GAAS,IAAA;AAAA,EACT,UAAA;AAAA,EACA;AACF,CAAA,EAAmB;AACjB,EAAA,MAAM,MAAA,GAAS,MAAA,KAAW,MAAA,GAAa,MAAA,GAAS,cAAc,QAAA,GAAY,SAAA;AAC1E,EAAA,MAAM,iBAAiB,UAAA,IAAc,MAAA;AACrC,EAAA,MAAM,eAAA,GAAkB,UAAA,KAAe,MAAA,IAAa,MAAA,KAAW,OAAO,QAAA,GAAM,IAAA;AAC5E,EAAA,MAAM,IAAA,GAAOC,yBAAA,CAAqB,KAAA,CAAM,IAAA,EAAM,MAAM,CAAA;AACpD,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,IAAS,KAAA,CAAM,SAAA,CAAU,IAAA;AACpD,EAAA,uBACEC,eAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,QAAA;AAAA,MACA,OAAA,EAAS,QAAA;AAAA,MACT,YAAA,EAAY,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA,EAAI,IAAI,CAAA,EAAG,eAAe,GAAG,cAAc,CAAA,CAAA;AAAA,MAC9F,eAAA,EAAe,QAAA;AAAA,MACf,aAAA,EAAa,MAAA;AAAA,MACb,YAAA,EAAY,SAAA;AAAA,MACZ,SAAA,EAAW,CAAA,uBAAA,EAA0B,MAAM,CAAA,aAAA,EAAgB,YAAA,CAAa,GAAA,IAAO,WAAW,CAAA,mBAAA,EAAsB,SAAS,CAAA,EAAG,WAAA,GAAc,wBAAA,GAA2B,EAAE,CAAA,CAAA;AAAA,MACvK,KAAA,EAAO,EAAE,iBAAA,EAAmB,oCAAA,EAAqC;AAAA,MAEjE,QAAA,EAAA;AAAA,wBAAAA,eAAA,CAAC,MAAA,EAAA,EAAK,WAAU,qBAAA,EACd,QAAA,EAAA;AAAA,0BAAAA,eAAA,CAAC,MAAA,EAAA,EAAK,WAAU,oBAAA,EAAqB,QAAA,EAAA;AAAA,YAAA,GAAA;AAAA,YAAE,MAAA,CAAO,UAAU,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG;AAAA,WAAA,EAAE,CAAA;AAAA,yCAC1E,MAAA,EAAA,EAAK,SAAA,EAAW,CAAA,qCAAA,EAAwC,MAAM,IAAK,QAAA,EAAA,cAAA,EAAe;AAAA,SAAA,EACrF,CAAA;AAAA,wBACAC,cAAA,CAAC,UAAK,SAAA,EAAU,uBAAA,EAAwB,eAAY,MAAA,EACjD,QAAA,EAAA,YAAA,CAAa,QAAQ,QAAA,EACxB,CAAA;AAAA,wBACAA,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kBAAA,EAAoB,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,wBACzCD,eAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EACd,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAQ,QAAA,EAAA,YAAA,CAAa,QAAQ,QAAA,EAAI,CAAA;AAAA,UAClD;AAAA,SAAA,EACH,CAAA;AAAA,QACC,WAAW,MAAA,oBACVA,cAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,CAAA,cAAA,EAAiB,WAAA,GAAc,aAAA,GAAgB,EAAE,CAAA,CAAA;AAAA,YAC5D,IAAA,EAAK,KAAA;AAAA,YACL,YAAA,EAAY,CAAA,YAAA,EAAe,eAAA,CAAgB,MAAA,CAAO,UAAU,CAAC,CAAA,CAAA;AAAA,YAE7D,QAAA,kBAAAD,eAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,sBAAA,EACd,QAAA,EAAA;AAAA,8BAAAC,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAA,EAAsB,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,6CAC1C,MAAA,EAAA,EAAK,SAAA,EAAU,uBAAuB,QAAA,EAAA,eAAA,CAAgB,MAAA,CAAO,UAAU,CAAA,EAAE;AAAA,aAAA,EAC5E;AAAA;AAAA;AACF;AAAA;AAAA,GAEJ;AAEJ;AAeO,SAAS,UAAA,CAAW;AAAA,EACzB,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA,GAAQ,IAAA;AAAA,EACR,QAAA;AAAA,EACA,gBAAgB,EAAC;AAAA,EACjB,eAAA,GAAkB,IAAA;AAAA,EAClB,QAAA,GAAW,KAAA;AAAA,EACX,MAAA,GAAS,IAAA;AAAA,EACT,KAAA,GAAQ,OAAO,KAAA,IAASC,wBAAA;AAAA,EACxB;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW,MAAA,CAAO,OAAO,CAAA,IAAK,EAAE,CAAA;AAC7E,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,QAAA,EAAU,mBAAA,CAAoB,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,EAAE,CAAA,IAAK,EAAE,CAAA;AACjF,EAAA,MAAM,KAAA,GAAQ,QAAA,EAAU,QAAA,IAAY,QAAA,CAAS,IAAA;AAC7C,EAAA,MAAM,KAAA,GAAQ,QAAA,EAAU,KAAA,IAAS,MAAA,CAAO,MAAA,CAAO,MAAA;AAC/C,EAAA,MAAM,aAAa,QAAA,EAAU,UAAA,KAAe,UAAU,CAAA,GAAI,CAAA,GAAK,QAAQ,KAAA,GAAS,GAAA,CAAA;AAChF,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,iBAAA,EAAmB,CAAA,mCAAA,EAAsC,KAAA,CAAM,YAAY,CAAA,CAAA,CAAA;AAAA,IAC3E,cAAc,CAAA,sCAAA,EAAyC,KAAA,CAAM,eAAA,IAAmBA,wBAAA,CAAoB,mBAAmB,SAAS,CAAA,CAAA,CAAA;AAAA,IAChI,iBAAA,EAAmB,CAAA,gCAAA,EAAmC,KAAA,CAAM,mBAAmB,CAAA,CAAA,CAAA;AAAA,IAC/E,cAAA,EAAgB,CAAA,gCAAA,EAAmC,KAAA,CAAM,SAAS,CAAA,CAAA,CAAA;AAAA,IAClE,mBAAA,EAAqB,MAAA,CAAO,KAAA,CAAM,WAAW,CAAA;AAAA,IAC7C,4BAA4B,MAAA,CAAO,IAAA,CAAK,IAAI,KAAA,CAAM,WAAA,EAAa,CAAC,CAAC,CAAA;AAAA,IACjE,2BAAA,EAA6B,MAAA,CAAO,KAAA,CAAM,gBAAA,IAAoB,CAAC,CAAA;AAAA,IAC/D,qBAAA,EAAuB,WAAA,CAAY,KAAA,CAAM,UAAA,IAAc,OAAO,CAAA;AAAA,IAC9D,GAAI,MAAM,mBAAA,KAAwB,MAAA,GAC9B,EAAC,GACD,EAAE,yBAAA,EAA2B,KAAA,CAAM,mBAAA,EAAoB;AAAA,IAC3D,sBAAA,EAAwB,CAAA,mCAAA,EAAsC,KAAA,CAAM,YAAY,CAAA,CAAA,CAAA;AAAA,IAChF,yBAAA,EAA2B,CAAA,sCAAA,EAAyC,KAAA,CAAM,eAAA,IAAmB,aAAa,CAAA,CAAA,CAAA;AAAA,IAC1G,mBAAA,EAAqB,CAAA,gCAAA,EAAmC,KAAA,CAAM,mBAAmB,CAAA,CAAA,CAAA;AAAA,IACjF,mBAAA,EAAqB,CAAA,gCAAA,EAAmC,KAAA,CAAM,SAAS,CAAA,CAAA,CAAA;AAAA,IACvE,sBAAA,EAAwB,MAAA,CAAO,KAAA,CAAM,WAAW;AAAA,GAClD;AACA,EAAA,MAAM,QAAA,GACJ,WAAW,IAAA,GACP;AAAA,IACE,SAAA,EAAW,WAAA;AAAA,IACX,MAAA,EAAQ,QAAA;AAAA,IACR,OAAA,EAAS,SAAA;AAAA,IACT,SAAA,EAAW,CAAC,KAAA,KAAkB,CAAA,EAAG,KAAK,CAAA,gBAAA,CAAA;AAAA,IACtC,SAAA,EAAW;AAAA,GACb,GACA;AAAA,IACE,SAAA,EAAW,0BAAA;AAAA,IACX,MAAA,EAAQ,0BAAA;AAAA,IACR,OAAA,EAAS,0BAAA;AAAA,IACT,SAAA,EAAW,CAAC,KAAA,KAAkB,CAAA,YAAA,EAAK,KAAK,CAAA,YAAA,CAAA;AAAA,IACxC,SAAA,EAAW;AAAA,GACb;AACN,EAAA,uBACEF,eAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,CAAA,YAAA,EAAe,UAAA,IAAc,GAAA,GAAM,2BAA2B,EAAE,CAAA,CAAA;AAAA,MAC3E,KAAA;AAAA,MACA,YAAA,EAAYD,yBAAA,CAAqB,KAAA,EAAO,MAAM,KAAK,MAAA,CAAO,EAAA;AAAA,MAE1D,QAAA,EAAA;AAAA,wBAAAC,eAAA,CAAC,QAAA,EAAA,EAAO,WAAU,qBAAA,EAChB,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,QAAI,QAAA,EAAAF,yBAAA,CAAqB,KAAA,EAAO,MAAM,CAAA,IAAK,OAAO,EAAA,EAAG,CAAA;AAAA,0CACrD,MAAA,EAAA,EAAK,SAAA,EAAU,sBAAqB,IAAA,EAAK,QAAA,EAAS,aAAU,QAAA,EAC1D,QAAA,EAAA;AAAA,YAAA,KAAA;AAAA,YAAM,KAAA;AAAA,YAAI;AAAA,WAAA,EACb;AAAA,SAAA,EACF,CAAA;AAAA,wBACAC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EACb,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,MAAA,EAAA,EAAM,mBAAS,SAAA,CAAU,IAAA,CAAK,IAAI,CAAA,EAAG,KAAA,GAAQ,KAAK,CAAC,CAAA,EAAE,CAAA;AAAA,0CACrD,QAAA,EAAA,EAAQ,QAAA,EAAA;AAAA,YAAA,IAAA,CAAK,MAAM,UAAU,CAAA;AAAA,YAAE;AAAA,WAAA,EAAC;AAAA,SAAA,EACnC,CAAA;AAAA,wBACAA,cAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,6BAAA;AAAA,YACV,IAAA,EAAK,aAAA;AAAA,YACL,eAAA,EAAe,CAAA;AAAA,YACf,eAAA,EAAe,GAAA;AAAA,YACf,eAAA,EAAe,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AAAA,YACpC,YAAA,EAAY,MAAA,KAAW,IAAA,GAAO,gBAAA,GAAmB,kDAAA;AAAA,YAEjD,QAAA,kBAAAA,cAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAU,4BAAA;AAAA,gBACV,OAAO,EAAE,OAAA,EAAS,SAAS,KAAA,EAAO,CAAA,EAAG,UAAU,CAAA,CAAA,CAAA;AAAI;AAAA;AACrD;AAAA,SACF;AAAA,wBACAA,cAAA,CAAC,SAAI,SAAA,EAAU,mBAAA,EACZ,iBAAO,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAO,KAAA,KAAU;AACnC,UAAA,MAAM,cAAA,GAAiB,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,OAAA,KAAY,KAAA,CAAM,EAAE,CAAA;AAClF,UAAA,uBACEA,cAAA;AAAA,YAAC,SAAA;AAAA,YAAA;AAAA,cAEC,KAAA;AAAA,cACC,GAAI,cAAA,KAAmB,MAAA,GAAY,EAAC,GAAI,EAAE,QAAQ,cAAA,EAAe;AAAA,cAClE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA;AAAA,cACzB,YAAY,KAAA,GAAQ,CAAA;AAAA,cACnB,GAAI,aAAA,CAAc,KAAA,CAAM,EAAE,CAAA,KAAM,MAAA,GAC7B,EAAC,GACD,EAAE,YAAA,EAAc,aAAA,CAAc,KAAA,CAAM,EAAE,CAAA,EAAE;AAAA,cAC5C,WAAA,EAAa,oBAAoB,KAAA,CAAM,EAAA;AAAA,cACvC,QAAA;AAAA,cACA,WAAW,KAAA,CAAM,SAAA;AAAA,cACjB,MAAA;AAAA,cACA,UAAA,EACE,cAAA,KAAmB,MAAA,GACf,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,GACf,QAAA,CAAS,SAAA,GACT,QAAA,CAAS,MAAA,GACX,QAAA,CAAS,OAAA;AAAA,cAEf,QAAA,EAAU,MAAM,aAAA,GAAgB,KAAA,CAAM,EAAE;AAAA,aAAA;AAAA,YAnBnC,KAAA,CAAM;AAAA,WAoBb;AAAA,QAEJ,CAAC,CAAA,EACH,CAAA;AAAA,QACC,UAAA,IAAc,GAAA,oBACbA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8BAA6B,IAAA,EAAK,QAAA,EAAS,WAAA,EAAU,QAAA,EAAS,QAAA,EAAA,YAAA,EAE7E,CAAA;AAAA,QAED,cAAc,GAAA,oBACbA,cAAA,CAAC,SAAI,SAAA,EAAU,+BAAA,EAAiC,mBAAS,SAAA,EAAU;AAAA;AAAA;AAAA,GAEvE;AAEJ;AA4BO,SAAS,UAAA,CAAW;AAAA,EACzB,IAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA,GAAc,IAAA;AAAA,EACd,SAAA,GAAY,KAAA;AAAA,EACZ,MAAA,GAAS,IAAA;AAAA,EACT,OAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIE,eAAS,EAAE,CAAA;AACrC,EAAA,MAAM,WAAW,YAAA,CAAa,IAAA,IAAQ,KAAA,KAAU,IAAA,EAAM,SAAS,SAAS,CAAA;AACxE,EAAAL,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM,QAAA,CAAS,EAAE,CAAA;AAAA,EACxB,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AACT,EAAA,IAAI,CAAC,IAAA,IAAQ,KAAA,KAAU,IAAA,EAAM,OAAO,IAAA;AACpC,EAAA,MAAM,MAAA,GAAS,OAAO,OAAA,KAAgD;AACpE,IAAA,IAAI,CAAC,WAAA,IAAe,MAAA,KAAW,MAAA,EAAW;AAC1C,IAAA,MAAM,UAAU,SAAA,IAAa,SAAA;AAC7B,IAAA,IAAI,YAAY,MAAA,EAAW;AAC3B,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,KAAA,CAAM,IAAI,OAAO,CAAA;AAChD,IAAA,QAAA,GAAW,QAAQ,CAAA;AACnB,IAAA,IAAI,QAAA,CAAS,IAAI,OAAA,EAAQ;AAAA,EAC3B,CAAA;AACA,EAAA,MAAM,IAAA,GAAOC,yBAAA,CAAqB,KAAA,CAAM,IAAA,EAAM,MAAM,CAAA;AACpD,EAAA,uBACEE,cAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAW,MAAA;AAAA,MACX,iBAAA,EAAgB,wBAAA;AAAA,MAChB,SAAA,EAAU,kBAAA;AAAA,MAEV,0CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2BAA0B,GAAA,EAAK,QAAA,EAAU,UAAU,EAAA,EAChE,QAAA,EAAA;AAAA,wBAAAA,cAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,YAAA,EAAW,qBAAA;AAAA,YACX,eAAA,EAAe,SAAA;AAAA,YACf,OAAA,EAAS,OAAA;AAAA,YACT,QAAA,EAAU,SAAA;AAAA,YACX,QAAA,EAAA;AAAA;AAAA,SAED;AAAA,wBACAA,cAAA,CAAC,IAAA,EAAA,EAAG,EAAA,EAAG,wBAAA,EAA0B,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,QACrC,MAAA,KAAW,MAAA,mBACVA,cAAA,CAAC,GAAA,EAAA,EAAE,QAAA,EAAA,kBAAA,EAAgB,CAAA,mBAEnBA,cAAA,CAAC,GAAA,EAAA,EAAG,QAAA,EAAAF,yBAAA,CAAqB,KAAA,CAAM,WAAA,EAAa,MAAM,CAAA,EAAE,CAAA;AAAA,QAErD,KAAA,CAAM,SAAA,CAAU,IAAA,KAAS,OAAA,mBACxBC,eAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,QAAA,EAAU,CAAC,KAAA,KAAsC;AAC/C,cAAA,KAAA,CAAM,cAAA,EAAe;AACrB,cAAA,KAAK,MAAA,CAAO,EAAE,IAAA,EAAM,OAAA,EAAS,OAAO,CAAA;AAAA,YACtC,CAAA;AAAA,YAEA,QAAA,EAAA;AAAA,8BAAAA,eAAA,CAAC,OAAA,EAAA,EAAM,QAAA,EAAA;AAAA,gBAAA,WAAA;AAAA,gCACIC,cAAA,CAAC,OAAA,EAAA,EAAM,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU,CAAC,KAAA,KAAU,QAAA,CAAS,KAAA,CAAM,MAAA,CAAO,KAAK,CAAA,EAAG;AAAA,eAAA,EACnF,CAAA;AAAA,8BACAA,cAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,IAAA,EAAK,QAAA;AAAA,kBACL,YAAA,EAAW,aAAA;AAAA,kBACX,eAAA,EAAe,CAAC,WAAA,IAAe,SAAA;AAAA,kBAC/B,QAAA,EAAU,CAAC,WAAA,IAAe,SAAA;AAAA,kBAC3B,QAAA,EAAA;AAAA;AAAA;AAED;AAAA;AAAA,SACF,mBAEAA,cAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,YAAA,EAAW,aAAA;AAAA,YACX,eAAA,EAAe,CAAC,WAAA,IAAe,SAAA;AAAA,YAC/B,SAAS,MAAM,KAAK,OAAO,EAAE,IAAA,EAAM,WAAW,CAAA;AAAA,YAC9C,QAAA,EAAU,CAAC,WAAA,IAAe,SAAA;AAAA,YAC3B,QAAA,EAAA;AAAA;AAAA;AAED,OAAA,EAEJ;AAAA;AAAA,GACF;AAEJ;AAgBO,SAAS,WAAA,CAAY;AAAA,EAC1B,OAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA,GAAS,IAAA;AAAA,EACT,SAAA,GAAY,KAAA;AAAA,EACZ,IAAA,GAAO,IAAA;AAAA,EACP,OAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIE,cAAA,CAA2C,EAAE,CAAA;AAC/E,EAAA,MAAM,WAAW,YAAA,CAAa,IAAA,IAAQ,OAAA,KAAY,MAAA,EAAW,SAAS,SAAS,CAAA;AAC/E,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,uBACEH,eAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,QAAA;AAAA,MACL,IAAA,EAAK,QAAA;AAAA,MACL,iBAAA,EAAgB,0BAAA;AAAA,MAChB,YAAA,EAAW,MAAA;AAAA,MACX,SAAA,EAAU,oBAAA;AAAA,MACV,QAAA,EAAU,EAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAAA,eAAA,CAAC,QAAA,EAAA,EAAO,WAAU,4BAAA,EAChB,QAAA,EAAA;AAAA,0BAAAC,cAAA,CAAC,IAAA,EAAA,EAAG,EAAA,EAAG,0BAAA,EAA2B,QAAA,EAAA,SAAA,EAAO,CAAA;AAAA,UACxC,YAAY,MAAA,oBACXA,cAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,QAAA;AAAA,cACL,YAAA,EAAW,eAAA;AAAA,cACX,eAAA,EAAe,SAAA;AAAA,cACf,QAAA,EAAU,SAAA;AAAA,cACV,OAAA,EAAS,OAAA;AAAA,cACV,QAAA,EAAA;AAAA;AAAA;AAED,SAAA,EAEJ,CAAA;AAAA,QACC,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AACvB,UAAA,MAAM,KAAA,GAAQ,OAAO,IAAA,CAAK,CAAC,SAAS,IAAA,CAAK,QAAA,KAAa,OAAO,EAAE,CAAA;AAC/D,UAAA,MAAM,SAAA,GAAY,OAAO,MAAA,KAAW,WAAA;AACpC,UAAA,MAAM,MAAA,GAAS,OAAO,OAAA,KAA4D;AAChF,YAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,MAAA,CAAO,IAAI,OAAO,CAAA;AAChD,YAAA,QAAA,GAAW,OAAO,EAAA,EAAI,MAAA,CAAO,KAAK,iBAAA,GAAoB,MAAA,CAAO,MAAM,IAAI,CAAA;AAAA,UACzE,CAAA;AACA,UAAA,uBACED,eAAA;AAAA,YAAC,SAAA;AAAA,YAAA;AAAA,cAEC,SAAA,EAAW,CAAA,qCAAA,EAAwC,KAAA,EAAO,MAAA,IAAU,QAAQ,CAAA,CAAA;AAAA,cAE5E,QAAA,EAAA;AAAA,gCAAAC,cAAA,CAAC,IAAA,EAAA,EAAI,QAAA,EAAAF,yBAAA,CAAqB,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA,EAAE,CAAA;AAAA,+CAC/C,GAAA,EAAA,EAAG,QAAA,EAAAA,yBAAA,CAAqB,MAAA,CAAO,WAAA,EAAa,MAAM,CAAA,EAAE,CAAA;AAAA,gCACrDE,cAAA,CAAC,UAAK,IAAA,EAAK,QAAA,EAAS,aAAU,QAAA,EAC3B,QAAA,EAAA,KAAA,EAAO,UAAU,QAAA,EACpB,CAAA;AAAA,gBACC,MAAA,CAAO,qBAAqB,gBAAA,oBAC3BD,eAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,QAAA,EAAU,CAAC,KAAA,KAAU;AACnB,sBAAA,KAAA,CAAM,cAAA,EAAe;AACrB,sBAAA,KAAK,MAAA,CAAO,EAAE,QAAA,EAAU,SAAA,CAAU,OAAO,EAAE,CAAA,IAAK,IAAI,CAAA;AAAA,oBACtD,CAAA;AAAA,oBAEA,QAAA,EAAA;AAAA,sCAAAA,eAAA,CAAC,OAAA,EAAA,EAAM,QAAA,EAAA;AAAA,wBAAA,gBAAA;AAAA,wBACU,GAAA;AAAA,wCACfC,cAAA;AAAA,0BAAC,OAAA;AAAA,0BAAA;AAAA,4BACC,IAAA,EAAK,UAAA;AAAA,4BACL,KAAA,EAAO,SAAA,CAAU,MAAA,CAAO,EAAE,CAAA,IAAK,EAAA;AAAA,4BAC/B,UAAU,CAAC,KAAA,KACT,YAAA,CAAa,CAAC,aAAa,EAAE,GAAG,OAAA,EAAS,CAAC,OAAO,EAAE,GAAG,KAAA,CAAM,MAAA,CAAO,OAAM,CAAE;AAAA;AAAA;AAE/E,uBAAA,EACF,CAAA;AAAA,sCACAA,cAAA;AAAA,wBAAC,QAAA;AAAA,wBAAA;AAAA,0BACC,IAAA,EAAK,QAAA;AAAA,0BACL,cAAY,CAAA,OAAA,EAAUF,yBAAA,CAAqB,MAAA,CAAO,KAAA,EAAO,MAAM,CAAC,CAAA,CAAA;AAAA,0BAChE,eAAA,EAAe,CAAC,SAAA,IAAa,SAAA;AAAA,0BAC7B,QAAA,EAAU,CAAC,SAAA,IAAa,SAAA;AAAA,0BACzB,QAAA,EAAA;AAAA;AAAA;AAED;AAAA;AAAA,iBACF;AAAA,gBAED,MAAA,CAAO,qBAAqB,gBAAA,oBAC3BE,cAAA;AAAA,kBAAC,QAAA;AAAA,kBAAA;AAAA,oBACC,IAAA,EAAK,QAAA;AAAA,oBACL,cAAY,CAAA,OAAA,EAAUF,yBAAA,CAAqB,MAAA,CAAO,KAAA,EAAO,MAAM,CAAC,CAAA,CAAA;AAAA,oBAChE,eAAA,EAAe,CAAC,SAAA,IAAa,SAAA;AAAA,oBAC7B,QAAA,EAAU,CAAC,SAAA,IAAa,SAAA;AAAA,oBACxB,OAAA,EAAS,MAAM,KAAK,MAAA,EAAO;AAAA,oBAC5B,QAAA,EAAA;AAAA;AAAA;AAED;AAAA,aAAA;AAAA,YA5CG,MAAA,CAAO;AAAA,WA8Cd;AAAA,QAEJ,CAAC;AAAA;AAAA;AAAA,GACH;AAEJ","file":"index.cjs","sourcesContent":["import {\n type ConsumeResult,\n DEFAULT_SHEET_THEME,\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\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 {\n readonly stamp: SpotItem;\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?: SupportedLocale;\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({\n stamp,\n record,\n isNext = false,\n slotNumber = 1,\n presentation = {},\n isAnimating = false,\n disabled = false,\n slotShape = \"rounded\",\n locale = \"ja\",\n statusText,\n onSelect,\n}: StampSlotProps) {\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 {\n readonly title?: LocalizedText;\n readonly config: RallyConfig;\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?: SupportedLocale;\n readonly theme?: SheetTheme;\n readonly onStampSelect?: (stampId: string) => void;\n}\n\nexport function StampSheet({\n title,\n config,\n state = null,\n progress,\n presentations = {},\n animatedStampId = null,\n disabled = false,\n locale = \"ja\",\n theme = config.theme ?? DEFAULT_SHEET_THEME,\n onStampSelect,\n}: StampSheetProps) {\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 locale === \"en\"\n ? {\n available: \"available\",\n locked: \"locked\",\n stamped: \"stamped\",\n remaining: (value: number) => `${value} spots remaining`,\n completed: \"RALLY COMPLETED\",\n }\n : {\n available: \"取得可能\",\n locked: \"順序待ち\",\n stamped: \"取得済み\",\n remaining: (value: number) => `あと${value}箇所`,\n 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 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 {\n readonly open: boolean;\n readonly stamp: SpotItem | 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?: SupportedLocale;\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({\n open,\n stamp,\n record,\n isAvailable = true,\n isPending = false,\n locale = \"ja\",\n onClose,\n onAcquire,\n onCheckIn,\n onNotify,\n}: StampModalProps) {\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 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>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 Passcode <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 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 Claim stamp\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport interface RewardPanelProps {\n readonly rewards: ReadonlyArray<RewardItem>;\n readonly states: ReadonlyArray<RewardState>;\n readonly locale?: SupportedLocale;\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({\n rewards,\n states,\n locale = \"ja\",\n isPending = false,\n open = true,\n onClose,\n onRedeem,\n onNotify,\n}: RewardPanelProps) {\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\">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?.(result.ok, result.ok ? \"Reward claimed.\" : result.error.code);\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 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 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 Redeem\n </button>\n )}\n </article>\n );\n })}\n </section>\n );\n}\n"]}
|
|
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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { RewardItem, RewardState,
|
|
2
|
+
import { SupportedLocale, RewardItem, RewardState, LocaleDictionary, ConsumeResult, SpotItem, StampRallyState, VerificationContext, LocalizedText, RallyConfig, StampRallyProgress, SheetTheme, SlotShape } from '@stamprally/core';
|
|
3
|
+
export { LocaleDictionary } from '@stamprally/core';
|
|
3
4
|
|
|
4
5
|
interface StampPresentation {
|
|
5
6
|
readonly label?: string;
|
|
@@ -7,8 +8,8 @@ interface StampPresentation {
|
|
|
7
8
|
readonly ink?: "vermilion" | "indigo";
|
|
8
9
|
readonly channel?: "instant" | "qr" | "nfc" | "geo";
|
|
9
10
|
}
|
|
10
|
-
interface StampSlotProps {
|
|
11
|
-
readonly stamp: SpotItem
|
|
11
|
+
interface StampSlotProps<TLocale extends string = SupportedLocale> {
|
|
12
|
+
readonly stamp: SpotItem<TLocale>;
|
|
12
13
|
readonly record?: StampRallyState["records"][number] | undefined;
|
|
13
14
|
readonly isNext?: boolean;
|
|
14
15
|
readonly slotNumber?: number;
|
|
@@ -16,48 +17,52 @@ interface StampSlotProps {
|
|
|
16
17
|
readonly isAnimating?: boolean;
|
|
17
18
|
readonly disabled?: boolean;
|
|
18
19
|
readonly slotShape?: SlotShape;
|
|
19
|
-
readonly locale?:
|
|
20
|
+
readonly locale?: TLocale;
|
|
21
|
+
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
20
22
|
readonly statusText?: string;
|
|
21
23
|
readonly onSelect?: () => void;
|
|
22
24
|
}
|
|
23
|
-
declare function StampSlot({ stamp, record, isNext, slotNumber, presentation, isAnimating, disabled, slotShape, locale, statusText, onSelect, }: StampSlotProps): react.JSX.Element;
|
|
24
|
-
interface StampSheetProps {
|
|
25
|
-
readonly title?: LocalizedText
|
|
26
|
-
readonly config: RallyConfig
|
|
25
|
+
declare function StampSlot<TLocale extends string = SupportedLocale>({ stamp, record, isNext, slotNumber, presentation, isAnimating, disabled, slotShape, locale, statusText, onSelect, }: StampSlotProps<TLocale>): react.JSX.Element;
|
|
26
|
+
interface StampSheetProps<TLocale extends string = SupportedLocale> {
|
|
27
|
+
readonly title?: LocalizedText<TLocale>;
|
|
28
|
+
readonly config: RallyConfig<TLocale>;
|
|
27
29
|
readonly state?: StampRallyState | null;
|
|
28
30
|
readonly progress?: StampRallyProgress;
|
|
29
31
|
readonly presentations?: Readonly<Record<string, StampPresentation>>;
|
|
30
32
|
readonly animatedStampId?: string | null;
|
|
31
33
|
readonly disabled?: boolean;
|
|
32
|
-
readonly locale?:
|
|
34
|
+
readonly locale?: TLocale;
|
|
35
|
+
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
33
36
|
readonly theme?: SheetTheme;
|
|
34
37
|
readonly onStampSelect?: (stampId: string) => void;
|
|
35
38
|
}
|
|
36
|
-
declare function StampSheet({ title, config, state, progress, presentations, animatedStampId, disabled, locale, theme, onStampSelect, }: StampSheetProps): react.JSX.Element;
|
|
39
|
+
declare function StampSheet<TLocale extends string = SupportedLocale>({ title, config, state, progress, presentations, animatedStampId, disabled, locale, dictionary, theme, onStampSelect, }: StampSheetProps<TLocale>): react.JSX.Element;
|
|
37
40
|
interface AcquisitionFeedback {
|
|
38
41
|
readonly ok: boolean;
|
|
39
42
|
readonly message: string;
|
|
40
43
|
}
|
|
41
|
-
interface StampModalProps {
|
|
44
|
+
interface StampModalProps<TLocale extends string = SupportedLocale> {
|
|
42
45
|
readonly open: boolean;
|
|
43
|
-
readonly stamp: SpotItem | null;
|
|
46
|
+
readonly stamp: SpotItem<TLocale> | null;
|
|
44
47
|
readonly record?: StampRallyState["records"][number] | undefined;
|
|
45
48
|
readonly presentation?: StampPresentation | null;
|
|
46
49
|
readonly requiredStampName?: string | null;
|
|
47
50
|
readonly isAvailable?: boolean;
|
|
48
51
|
readonly isPending?: boolean;
|
|
49
52
|
readonly isCompleted?: boolean;
|
|
50
|
-
readonly locale?:
|
|
53
|
+
readonly locale?: TLocale;
|
|
54
|
+
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
51
55
|
readonly onClose: () => void;
|
|
52
56
|
readonly onAcquire?: (stampId: string, context: VerificationContext) => Promise<AcquisitionFeedback>;
|
|
53
57
|
readonly onCheckIn?: (stampId: string, context: VerificationContext) => Promise<AcquisitionFeedback>;
|
|
54
58
|
readonly onNotify?: (feedback: AcquisitionFeedback) => void;
|
|
55
59
|
}
|
|
56
|
-
declare function StampModal({ open, stamp, record, isAvailable, isPending, locale, onClose, onAcquire, onCheckIn, onNotify, }: StampModalProps): react.JSX.Element | null;
|
|
57
|
-
interface RewardPanelProps {
|
|
58
|
-
readonly rewards: ReadonlyArray<RewardItem
|
|
60
|
+
declare function StampModal<TLocale extends string = SupportedLocale>({ open, stamp, record, isAvailable, isPending, locale, dictionary, onClose, onAcquire, onCheckIn, onNotify, }: StampModalProps<TLocale>): react.JSX.Element | null;
|
|
61
|
+
interface RewardPanelProps<TLocale extends string = SupportedLocale> {
|
|
62
|
+
readonly rewards: ReadonlyArray<RewardItem<TLocale>>;
|
|
59
63
|
readonly states: ReadonlyArray<RewardState>;
|
|
60
|
-
readonly locale?:
|
|
64
|
+
readonly locale?: TLocale;
|
|
65
|
+
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
61
66
|
readonly isPending?: boolean;
|
|
62
67
|
readonly open?: boolean;
|
|
63
68
|
readonly onClose?: () => void;
|
|
@@ -67,6 +72,6 @@ interface RewardPanelProps {
|
|
|
67
72
|
}) => Promise<ConsumeResult>;
|
|
68
73
|
readonly onNotify?: (ok: boolean, message: string) => void;
|
|
69
74
|
}
|
|
70
|
-
declare function RewardPanel({ rewards, states, locale, isPending, open, onClose, onRedeem, onNotify, }: RewardPanelProps): react.JSX.Element | null;
|
|
75
|
+
declare function RewardPanel<TLocale extends string = SupportedLocale>({ rewards, states, locale, dictionary, isPending, open, onClose, onRedeem, onNotify, }: RewardPanelProps<TLocale>): react.JSX.Element | null;
|
|
71
76
|
|
|
72
77
|
export { type AcquisitionFeedback, RewardPanel, type RewardPanelProps, StampModal, type StampModalProps, type StampPresentation, StampSheet, type StampSheetProps, StampSlot, type StampSlotProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { RewardItem, RewardState,
|
|
2
|
+
import { SupportedLocale, RewardItem, RewardState, LocaleDictionary, ConsumeResult, SpotItem, StampRallyState, VerificationContext, LocalizedText, RallyConfig, StampRallyProgress, SheetTheme, SlotShape } from '@stamprally/core';
|
|
3
|
+
export { LocaleDictionary } from '@stamprally/core';
|
|
3
4
|
|
|
4
5
|
interface StampPresentation {
|
|
5
6
|
readonly label?: string;
|
|
@@ -7,8 +8,8 @@ interface StampPresentation {
|
|
|
7
8
|
readonly ink?: "vermilion" | "indigo";
|
|
8
9
|
readonly channel?: "instant" | "qr" | "nfc" | "geo";
|
|
9
10
|
}
|
|
10
|
-
interface StampSlotProps {
|
|
11
|
-
readonly stamp: SpotItem
|
|
11
|
+
interface StampSlotProps<TLocale extends string = SupportedLocale> {
|
|
12
|
+
readonly stamp: SpotItem<TLocale>;
|
|
12
13
|
readonly record?: StampRallyState["records"][number] | undefined;
|
|
13
14
|
readonly isNext?: boolean;
|
|
14
15
|
readonly slotNumber?: number;
|
|
@@ -16,48 +17,52 @@ interface StampSlotProps {
|
|
|
16
17
|
readonly isAnimating?: boolean;
|
|
17
18
|
readonly disabled?: boolean;
|
|
18
19
|
readonly slotShape?: SlotShape;
|
|
19
|
-
readonly locale?:
|
|
20
|
+
readonly locale?: TLocale;
|
|
21
|
+
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
20
22
|
readonly statusText?: string;
|
|
21
23
|
readonly onSelect?: () => void;
|
|
22
24
|
}
|
|
23
|
-
declare function StampSlot({ stamp, record, isNext, slotNumber, presentation, isAnimating, disabled, slotShape, locale, statusText, onSelect, }: StampSlotProps): react.JSX.Element;
|
|
24
|
-
interface StampSheetProps {
|
|
25
|
-
readonly title?: LocalizedText
|
|
26
|
-
readonly config: RallyConfig
|
|
25
|
+
declare function StampSlot<TLocale extends string = SupportedLocale>({ stamp, record, isNext, slotNumber, presentation, isAnimating, disabled, slotShape, locale, statusText, onSelect, }: StampSlotProps<TLocale>): react.JSX.Element;
|
|
26
|
+
interface StampSheetProps<TLocale extends string = SupportedLocale> {
|
|
27
|
+
readonly title?: LocalizedText<TLocale>;
|
|
28
|
+
readonly config: RallyConfig<TLocale>;
|
|
27
29
|
readonly state?: StampRallyState | null;
|
|
28
30
|
readonly progress?: StampRallyProgress;
|
|
29
31
|
readonly presentations?: Readonly<Record<string, StampPresentation>>;
|
|
30
32
|
readonly animatedStampId?: string | null;
|
|
31
33
|
readonly disabled?: boolean;
|
|
32
|
-
readonly locale?:
|
|
34
|
+
readonly locale?: TLocale;
|
|
35
|
+
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
33
36
|
readonly theme?: SheetTheme;
|
|
34
37
|
readonly onStampSelect?: (stampId: string) => void;
|
|
35
38
|
}
|
|
36
|
-
declare function StampSheet({ title, config, state, progress, presentations, animatedStampId, disabled, locale, theme, onStampSelect, }: StampSheetProps): react.JSX.Element;
|
|
39
|
+
declare function StampSheet<TLocale extends string = SupportedLocale>({ title, config, state, progress, presentations, animatedStampId, disabled, locale, dictionary, theme, onStampSelect, }: StampSheetProps<TLocale>): react.JSX.Element;
|
|
37
40
|
interface AcquisitionFeedback {
|
|
38
41
|
readonly ok: boolean;
|
|
39
42
|
readonly message: string;
|
|
40
43
|
}
|
|
41
|
-
interface StampModalProps {
|
|
44
|
+
interface StampModalProps<TLocale extends string = SupportedLocale> {
|
|
42
45
|
readonly open: boolean;
|
|
43
|
-
readonly stamp: SpotItem | null;
|
|
46
|
+
readonly stamp: SpotItem<TLocale> | null;
|
|
44
47
|
readonly record?: StampRallyState["records"][number] | undefined;
|
|
45
48
|
readonly presentation?: StampPresentation | null;
|
|
46
49
|
readonly requiredStampName?: string | null;
|
|
47
50
|
readonly isAvailable?: boolean;
|
|
48
51
|
readonly isPending?: boolean;
|
|
49
52
|
readonly isCompleted?: boolean;
|
|
50
|
-
readonly locale?:
|
|
53
|
+
readonly locale?: TLocale;
|
|
54
|
+
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
51
55
|
readonly onClose: () => void;
|
|
52
56
|
readonly onAcquire?: (stampId: string, context: VerificationContext) => Promise<AcquisitionFeedback>;
|
|
53
57
|
readonly onCheckIn?: (stampId: string, context: VerificationContext) => Promise<AcquisitionFeedback>;
|
|
54
58
|
readonly onNotify?: (feedback: AcquisitionFeedback) => void;
|
|
55
59
|
}
|
|
56
|
-
declare function StampModal({ open, stamp, record, isAvailable, isPending, locale, onClose, onAcquire, onCheckIn, onNotify, }: StampModalProps): react.JSX.Element | null;
|
|
57
|
-
interface RewardPanelProps {
|
|
58
|
-
readonly rewards: ReadonlyArray<RewardItem
|
|
60
|
+
declare function StampModal<TLocale extends string = SupportedLocale>({ open, stamp, record, isAvailable, isPending, locale, dictionary, onClose, onAcquire, onCheckIn, onNotify, }: StampModalProps<TLocale>): react.JSX.Element | null;
|
|
61
|
+
interface RewardPanelProps<TLocale extends string = SupportedLocale> {
|
|
62
|
+
readonly rewards: ReadonlyArray<RewardItem<TLocale>>;
|
|
59
63
|
readonly states: ReadonlyArray<RewardState>;
|
|
60
|
-
readonly locale?:
|
|
64
|
+
readonly locale?: TLocale;
|
|
65
|
+
readonly dictionary?: LocaleDictionary<TLocale>;
|
|
61
66
|
readonly isPending?: boolean;
|
|
62
67
|
readonly open?: boolean;
|
|
63
68
|
readonly onClose?: () => void;
|
|
@@ -67,6 +72,6 @@ interface RewardPanelProps {
|
|
|
67
72
|
}) => Promise<ConsumeResult>;
|
|
68
73
|
readonly onNotify?: (ok: boolean, message: string) => void;
|
|
69
74
|
}
|
|
70
|
-
declare function RewardPanel({ rewards, states, locale, isPending, open, onClose, onRedeem, onNotify, }: RewardPanelProps): react.JSX.Element | null;
|
|
75
|
+
declare function RewardPanel<TLocale extends string = SupportedLocale>({ rewards, states, locale, dictionary, isPending, open, onClose, onRedeem, onNotify, }: RewardPanelProps<TLocale>): react.JSX.Element | null;
|
|
71
76
|
|
|
72
77
|
export { type AcquisitionFeedback, RewardPanel, type RewardPanelProps, StampModal, type StampModalProps, type StampPresentation, StampSheet, type StampSheetProps, StampSlot, type StampSlotProps };
|
package/dist/index.js
CHANGED
|
@@ -125,6 +125,7 @@ function StampSheet({
|
|
|
125
125
|
animatedStampId = null,
|
|
126
126
|
disabled = false,
|
|
127
127
|
locale = "ja",
|
|
128
|
+
dictionary,
|
|
128
129
|
theme = config.theme ?? DEFAULT_SHEET_THEME,
|
|
129
130
|
onStampSelect
|
|
130
131
|
}) {
|
|
@@ -149,18 +150,12 @@ function StampSheet({
|
|
|
149
150
|
"--stamprally-text": `var(--stamprally-text-override, ${theme.textColor})`,
|
|
150
151
|
"--stamprally-columns": String(theme.gridColumns)
|
|
151
152
|
};
|
|
152
|
-
const messages =
|
|
153
|
-
available: "available",
|
|
154
|
-
locked: "locked",
|
|
155
|
-
stamped: "stamped",
|
|
156
|
-
remaining: (value) => `${value} spots remaining
|
|
157
|
-
completed: "RALLY COMPLETED"
|
|
158
|
-
} : {
|
|
159
|
-
available: "\u53D6\u5F97\u53EF\u80FD",
|
|
160
|
-
locked: "\u9806\u5E8F\u5F85\u3061",
|
|
161
|
-
stamped: "\u53D6\u5F97\u6E08\u307F",
|
|
162
|
-
remaining: (value) => `\u3042\u3068${value}\u7B87\u6240`,
|
|
163
|
-
completed: "\u30E9\u30EA\u30FC\u9054\u6210"
|
|
153
|
+
const messages = {
|
|
154
|
+
available: dictionary?.[locale]?.available ?? (locale === "en" ? "available" : "\u53D6\u5F97\u53EF\u80FD"),
|
|
155
|
+
locked: dictionary?.[locale]?.locked ?? (locale === "en" ? "locked" : "\u9806\u5E8F\u5F85\u3061"),
|
|
156
|
+
stamped: dictionary?.[locale]?.stamped ?? (locale === "en" ? "stamped" : "\u53D6\u5F97\u6E08\u307F"),
|
|
157
|
+
remaining: (value) => dictionary?.[locale]?.remaining?.replace("{count}", String(value)) ?? (locale === "en" ? `${value} spots remaining` : `\u3042\u3068${value}\u7B87\u6240`),
|
|
158
|
+
completed: dictionary?.[locale]?.completed ?? (locale === "en" ? "RALLY COMPLETED" : "\u30E9\u30EA\u30FC\u9054\u6210")
|
|
164
159
|
};
|
|
165
160
|
return /* @__PURE__ */ jsxs(
|
|
166
161
|
"section",
|
|
@@ -216,6 +211,7 @@ function StampSheet({
|
|
|
216
211
|
disabled,
|
|
217
212
|
slotShape: theme.slotShape,
|
|
218
213
|
locale,
|
|
214
|
+
...dictionary === void 0 ? {} : { dictionary },
|
|
219
215
|
statusText: recordForStamp === void 0 ? next.has(stamp.id) ? messages.available : messages.locked : messages.stamped,
|
|
220
216
|
onSelect: () => onStampSelect?.(stamp.id)
|
|
221
217
|
},
|
|
@@ -235,6 +231,7 @@ function StampModal({
|
|
|
235
231
|
isAvailable = true,
|
|
236
232
|
isPending = false,
|
|
237
233
|
locale = "ja",
|
|
234
|
+
dictionary,
|
|
238
235
|
onClose,
|
|
239
236
|
onAcquire,
|
|
240
237
|
onCheckIn,
|
|
@@ -255,6 +252,7 @@ function StampModal({
|
|
|
255
252
|
if (feedback.ok) onClose();
|
|
256
253
|
};
|
|
257
254
|
const name = resolveLocalizedText(stamp.name, locale);
|
|
255
|
+
const messages = dictionary?.[locale] ?? {};
|
|
258
256
|
return /* @__PURE__ */ jsx(
|
|
259
257
|
"div",
|
|
260
258
|
{
|
|
@@ -275,7 +273,7 @@ function StampModal({
|
|
|
275
273
|
}
|
|
276
274
|
),
|
|
277
275
|
/* @__PURE__ */ jsx("h2", { id: "stamprally-modal-title", children: name }),
|
|
278
|
-
record !== void 0 ? /* @__PURE__ */ jsx("p", { children: "Already claimed." }) : /* @__PURE__ */ jsx("p", { children: resolveLocalizedText(stamp.description, locale) }),
|
|
276
|
+
record !== void 0 ? /* @__PURE__ */ jsx("p", { children: messages.alreadyClaimed ?? "Already claimed." }) : /* @__PURE__ */ jsx("p", { children: resolveLocalizedText(stamp.description, locale) }),
|
|
279
277
|
stamp.condition.type === "token" ? /* @__PURE__ */ jsxs(
|
|
280
278
|
"form",
|
|
281
279
|
{
|
|
@@ -285,7 +283,8 @@ function StampModal({
|
|
|
285
283
|
},
|
|
286
284
|
children: [
|
|
287
285
|
/* @__PURE__ */ jsxs("label", { children: [
|
|
288
|
-
"Passcode
|
|
286
|
+
messages.passcode ?? "Passcode",
|
|
287
|
+
" ",
|
|
289
288
|
/* @__PURE__ */ jsx("input", { value: token, onChange: (event) => setToken(event.target.value) })
|
|
290
289
|
] }),
|
|
291
290
|
/* @__PURE__ */ jsx(
|
|
@@ -295,7 +294,7 @@ function StampModal({
|
|
|
295
294
|
"aria-label": "Claim stamp",
|
|
296
295
|
"aria-disabled": !isAvailable || isPending,
|
|
297
296
|
disabled: !isAvailable || isPending,
|
|
298
|
-
children: "Claim stamp"
|
|
297
|
+
children: messages.claimStamp ?? "Claim stamp"
|
|
299
298
|
}
|
|
300
299
|
)
|
|
301
300
|
]
|
|
@@ -308,7 +307,7 @@ function StampModal({
|
|
|
308
307
|
"aria-disabled": !isAvailable || isPending,
|
|
309
308
|
onClick: () => void submit({ type: "instant" }),
|
|
310
309
|
disabled: !isAvailable || isPending,
|
|
311
|
-
children: "Claim stamp"
|
|
310
|
+
children: messages.claimStamp ?? "Claim stamp"
|
|
312
311
|
}
|
|
313
312
|
)
|
|
314
313
|
] })
|
|
@@ -319,6 +318,7 @@ function RewardPanel({
|
|
|
319
318
|
rewards,
|
|
320
319
|
states,
|
|
321
320
|
locale = "ja",
|
|
321
|
+
dictionary,
|
|
322
322
|
isPending = false,
|
|
323
323
|
open = true,
|
|
324
324
|
onClose,
|
|
@@ -339,7 +339,7 @@ function RewardPanel({
|
|
|
339
339
|
tabIndex: -1,
|
|
340
340
|
children: [
|
|
341
341
|
/* @__PURE__ */ jsxs("header", { className: "stamprally-rewards__header", children: [
|
|
342
|
-
/* @__PURE__ */ jsx("h2", { id: "stamprally-rewards-title", children: "Rewards" }),
|
|
342
|
+
/* @__PURE__ */ jsx("h2", { id: "stamprally-rewards-title", children: dictionary?.[locale]?.rewards ?? "Rewards" }),
|
|
343
343
|
onClose !== void 0 && /* @__PURE__ */ jsx(
|
|
344
344
|
"button",
|
|
345
345
|
{
|
|
@@ -357,7 +357,10 @@ function RewardPanel({
|
|
|
357
357
|
const available = state?.status === "AVAILABLE";
|
|
358
358
|
const redeem = async (options) => {
|
|
359
359
|
const result = await onRedeem(reward.id, options);
|
|
360
|
-
onNotify?.(
|
|
360
|
+
onNotify?.(
|
|
361
|
+
result.ok,
|
|
362
|
+
result.ok ? dictionary?.[locale]?.rewardClaimed ?? "Reward claimed." : result.error.code
|
|
363
|
+
);
|
|
361
364
|
};
|
|
362
365
|
return /* @__PURE__ */ jsxs(
|
|
363
366
|
"article",
|
|
@@ -376,7 +379,7 @@ function RewardPanel({
|
|
|
376
379
|
},
|
|
377
380
|
children: [
|
|
378
381
|
/* @__PURE__ */ jsxs("label", { children: [
|
|
379
|
-
"Staff passcode",
|
|
382
|
+
dictionary?.[locale]?.staffPasscode ?? "Staff passcode",
|
|
380
383
|
" ",
|
|
381
384
|
/* @__PURE__ */ jsx(
|
|
382
385
|
"input",
|
|
@@ -394,7 +397,7 @@ function RewardPanel({
|
|
|
394
397
|
"aria-label": `Redeem ${resolveLocalizedText(reward.title, locale)}`,
|
|
395
398
|
"aria-disabled": !available || isPending,
|
|
396
399
|
disabled: !available || isPending,
|
|
397
|
-
children: "Redeem"
|
|
400
|
+
children: dictionary?.[locale]?.redeem ?? "Redeem"
|
|
398
401
|
}
|
|
399
402
|
)
|
|
400
403
|
]
|
|
@@ -408,7 +411,7 @@ function RewardPanel({
|
|
|
408
411
|
"aria-disabled": !available || isPending,
|
|
409
412
|
disabled: !available || isPending,
|
|
410
413
|
onClick: () => void redeem(),
|
|
411
|
-
children: "Redeem"
|
|
414
|
+
children: dictionary?.[locale]?.redeem ?? "Redeem"
|
|
412
415
|
}
|
|
413
416
|
)
|
|
414
417
|
]
|
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 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\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 {\n readonly stamp: SpotItem;\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?: SupportedLocale;\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({\n stamp,\n record,\n isNext = false,\n slotNumber = 1,\n presentation = {},\n isAnimating = false,\n disabled = false,\n slotShape = \"rounded\",\n locale = \"ja\",\n statusText,\n onSelect,\n}: StampSlotProps) {\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 {\n readonly title?: LocalizedText;\n readonly config: RallyConfig;\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?: SupportedLocale;\n readonly theme?: SheetTheme;\n readonly onStampSelect?: (stampId: string) => void;\n}\n\nexport function StampSheet({\n title,\n config,\n state = null,\n progress,\n presentations = {},\n animatedStampId = null,\n disabled = false,\n locale = \"ja\",\n theme = config.theme ?? DEFAULT_SHEET_THEME,\n onStampSelect,\n}: StampSheetProps) {\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 locale === \"en\"\n ? {\n available: \"available\",\n locked: \"locked\",\n stamped: \"stamped\",\n remaining: (value: number) => `${value} spots remaining`,\n completed: \"RALLY COMPLETED\",\n }\n : {\n available: \"取得可能\",\n locked: \"順序待ち\",\n stamped: \"取得済み\",\n remaining: (value: number) => `あと${value}箇所`,\n 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 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 {\n readonly open: boolean;\n readonly stamp: SpotItem | 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?: SupportedLocale;\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({\n open,\n stamp,\n record,\n isAvailable = true,\n isPending = false,\n locale = \"ja\",\n onClose,\n onAcquire,\n onCheckIn,\n onNotify,\n}: StampModalProps) {\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 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>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 Passcode <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 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 Claim stamp\n </button>\n )}\n </div>\n </div>\n );\n}\n\nexport interface RewardPanelProps {\n readonly rewards: ReadonlyArray<RewardItem>;\n readonly states: ReadonlyArray<RewardState>;\n readonly locale?: SupportedLocale;\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({\n rewards,\n states,\n locale = \"ja\",\n isPending = false,\n open = true,\n onClose,\n onRedeem,\n onNotify,\n}: RewardPanelProps) {\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\">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?.(result.ok, result.ok ? \"Reward claimed.\" : result.error.code);\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 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 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 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 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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stamprally/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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.5.0",
|
|
33
|
+
"@stamprally/react": "0.5.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": "^18.0.0 || ^19.0.0",
|