@ai-matrx/design-system 0.86.348 → 0.86.350

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.
Files changed (91) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/dist/carousel.cjs.map +1 -1
  3. package/dist/carousel.js +5 -5
  4. package/dist/chunk-4WSXAP24.js +51 -0
  5. package/dist/chunk-4WSXAP24.js.map +1 -0
  6. package/dist/{chunk-XTP6HOB6.js → chunk-6XNYYROM.js} +1 -1
  7. package/dist/chunk-6XNYYROM.js.map +1 -0
  8. package/dist/{chunk-54UK6P7E.js → chunk-BCGNEWZM.js} +3 -3
  9. package/dist/{chunk-CEA6X445.js → chunk-CFUXEGW2.js} +2 -2
  10. package/dist/{chunk-BC7LMEOD.js → chunk-GJ6UGQ4X.js} +7 -3
  11. package/dist/chunk-GJ6UGQ4X.js.map +1 -0
  12. package/dist/{chunk-6QKT52FR.js → chunk-MTE6N7XU.js} +2 -2
  13. package/dist/{chunk-S6F34AX5.js → chunk-QA7EHFRX.js} +2 -2
  14. package/dist/{chunk-KYH42WEX.js → chunk-SC3XPADZ.js} +3 -3
  15. package/dist/{chunk-CJBSBKG5.js → chunk-SOCNWQMX.js} +2 -2
  16. package/dist/{chunk-GLLPO66A.js → chunk-U46XUQI7.js} +2 -2
  17. package/dist/{chunk-6CDAHINE.js → chunk-UTADJKVR.js} +2 -2
  18. package/dist/{chunk-TWRC7NP4.js → chunk-WUD23YTG.js} +4 -4
  19. package/dist/{chunk-MIJMP4WI.js → chunk-YRF22M5S.js} +6 -1
  20. package/dist/{chunk-MIJMP4WI.js.map → chunk-YRF22M5S.js.map} +1 -1
  21. package/dist/clipboard-fallback-dialog.cjs.map +1 -1
  22. package/dist/clipboard-fallback-dialog.js +1 -1
  23. package/dist/controls.cjs.map +1 -1
  24. package/dist/controls.css +25 -0
  25. package/dist/controls.d.cts +2 -2
  26. package/dist/controls.d.ts +2 -2
  27. package/dist/controls.js +5 -5
  28. package/dist/data-table/data-row-inspector.cjs.map +1 -1
  29. package/dist/data-table/data-row-inspector.js +4 -4
  30. package/dist/data-table/data-row-window.cjs.map +1 -1
  31. package/dist/data-table/data-row-window.js +5 -5
  32. package/dist/data-table/index.cjs +8 -5
  33. package/dist/data-table/index.cjs.map +1 -1
  34. package/dist/data-table/index.js +9 -9
  35. package/dist/data-table/pagination.cjs.map +1 -1
  36. package/dist/data-table/pagination.js +2 -2
  37. package/dist/data-table/spreadsheet.cjs +6 -2
  38. package/dist/data-table/spreadsheet.cjs.map +1 -1
  39. package/dist/data-table/spreadsheet.d.cts +4 -1
  40. package/dist/data-table/spreadsheet.d.ts +4 -1
  41. package/dist/data-table/spreadsheet.js +3 -1
  42. package/dist/data-table/uuid-cell.cjs.map +1 -1
  43. package/dist/data-table/uuid-cell.js +2 -2
  44. package/dist/desktop.cjs +93 -12
  45. package/dist/desktop.cjs.map +1 -1
  46. package/dist/desktop.css +27 -0
  47. package/dist/desktop.d.cts +6 -5
  48. package/dist/desktop.d.ts +6 -5
  49. package/dist/desktop.js +64 -15
  50. package/dist/desktop.js.map +1 -1
  51. package/dist/index.cjs +17 -7
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +21 -12
  54. package/dist/index.d.ts +21 -12
  55. package/dist/index.js +21 -14
  56. package/dist/index.js.map +1 -1
  57. package/dist/item.cjs.map +1 -1
  58. package/dist/item.js +2 -2
  59. package/dist/lite-table.cjs.map +1 -1
  60. package/dist/lite-table.js +1 -1
  61. package/dist/notice-stack.cjs +70 -0
  62. package/dist/notice-stack.cjs.map +1 -0
  63. package/dist/notice-stack.d.cts +60 -0
  64. package/dist/notice-stack.d.ts +60 -0
  65. package/dist/notice-stack.js +16 -0
  66. package/dist/notice-stack.js.map +1 -0
  67. package/dist/record-list.cjs.map +1 -1
  68. package/dist/record-list.js +2 -2
  69. package/dist/settings.cjs.map +1 -1
  70. package/dist/settings.js +3 -3
  71. package/dist/swipe-deck.cjs +95 -25
  72. package/dist/swipe-deck.cjs.map +1 -1
  73. package/dist/swipe-deck.css +14 -0
  74. package/dist/swipe-deck.d.cts +20 -0
  75. package/dist/swipe-deck.d.ts +20 -0
  76. package/dist/swipe-deck.js +87 -25
  77. package/dist/swipe-deck.js.map +1 -1
  78. package/dist/writing-field.cjs.map +1 -1
  79. package/dist/writing-field.js +2 -2
  80. package/package.json +12 -18
  81. package/dist/chunk-BC7LMEOD.js.map +0 -1
  82. package/dist/chunk-XTP6HOB6.js.map +0 -1
  83. /package/dist/{chunk-54UK6P7E.js.map → chunk-BCGNEWZM.js.map} +0 -0
  84. /package/dist/{chunk-CEA6X445.js.map → chunk-CFUXEGW2.js.map} +0 -0
  85. /package/dist/{chunk-6QKT52FR.js.map → chunk-MTE6N7XU.js.map} +0 -0
  86. /package/dist/{chunk-S6F34AX5.js.map → chunk-QA7EHFRX.js.map} +0 -0
  87. /package/dist/{chunk-KYH42WEX.js.map → chunk-SC3XPADZ.js.map} +0 -0
  88. /package/dist/{chunk-CJBSBKG5.js.map → chunk-SOCNWQMX.js.map} +0 -0
  89. /package/dist/{chunk-GLLPO66A.js.map → chunk-U46XUQI7.js.map} +0 -0
  90. /package/dist/{chunk-6CDAHINE.js.map → chunk-UTADJKVR.js.map} +0 -0
  91. /package/dist/{chunk-TWRC7NP4.js.map → chunk-WUD23YTG.js.map} +0 -0
package/dist/settings.js CHANGED
@@ -13,10 +13,10 @@ import {
13
13
  CommandInput,
14
14
  CommandItem,
15
15
  CommandList
16
- } from "./chunk-MIJMP4WI.js";
16
+ } from "./chunk-YRF22M5S.js";
17
17
  import {
18
18
  Tile
19
- } from "./chunk-6CDAHINE.js";
19
+ } from "./chunk-UTADJKVR.js";
20
20
  import {
21
21
  Drawer,
22
22
  DrawerContent,
@@ -47,7 +47,7 @@ import {
47
47
  SearchField,
48
48
  Switch,
49
49
  Tabs
50
- } from "./chunk-XTP6HOB6.js";
50
+ } from "./chunk-6XNYYROM.js";
51
51
  import "./chunk-BD77DHUO.js";
52
52
  import "./chunk-BKCJUFD3.js";
53
53
  import "./chunk-PIQJULQB.js";
@@ -251,6 +251,15 @@ function CopyIcon(props) {
251
251
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
252
252
  ] });
253
253
  }
254
+ function ListChecksIcon(props) {
255
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...lucideProps("list-checks", props), children: [
256
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m3 17 2 2 4-4" }),
257
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m3 7 2 2 4-4" }),
258
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M13 6h8" }),
259
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M13 12h8" }),
260
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M13 18h8" })
261
+ ] });
262
+ }
254
263
 
255
264
  // src/swipe-deck/chrome.tsx
256
265
  var React2 = __toESM(require("react"), 1);
@@ -436,7 +445,7 @@ function EdgeButtons({ keyMap, suggested, refs, onAnswer, suggestionLabel, disab
436
445
  );
437
446
  }) });
438
447
  }
439
- function CornerButton({ corner, label, shortcut, onClick, disabled, children }) {
448
+ function CornerButton({ corner, label, shortcut, onClick, disabled, pressed, children }) {
440
449
  return (
441
450
  // ui-exception: the deck's four corner targets sit in its own frame geometry
442
451
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -449,6 +458,7 @@ function CornerButton({ corner, label, shortcut, onClick, disabled, children })
449
458
  title: shortcut ? `${label} (${shortcut})` : label,
450
459
  "aria-keyshortcuts": shortcut,
451
460
  disabled,
461
+ "aria-pressed": pressed,
452
462
  onClick,
453
463
  children
454
464
  }
@@ -965,17 +975,17 @@ function useDeckController({ items, binding, initialState, onChange }) {
965
975
  const stateRef = React3.useRef(state);
966
976
  stateRef.current = state;
967
977
  const send = React3.useCallback(
968
- (ops, onRefused) => {
978
+ (ops, onRefused, transient = false) => {
969
979
  if (!binding) {
970
980
  setLocal((s) => applyOps(s, ops));
971
981
  return;
972
982
  }
973
983
  const id = ++seq.current;
974
- setPending((list2) => [...list2, { id, ops, settledAt: null }]);
984
+ setPending((list2) => [...list2, { id, ops, settledAt: null, ...transient ? { transient } : {} }]);
975
985
  binding.apply(ops).then(
976
986
  () => {
977
987
  setWriteError(null);
978
- setPending((list2) => list2.map((p) => p.id === id ? { ...p, settledAt: Date.now() } : p));
988
+ setPending((list2) => transient ? list2.filter((p) => p.id !== id) : list2.map((p) => p.id === id ? { ...p, settledAt: Date.now() } : p));
979
989
  },
980
990
  (err) => {
981
991
  setPending((list2) => list2.filter((p) => p.id !== id));
@@ -990,7 +1000,7 @@ function useDeckController({ items, binding, initialState, onChange }) {
990
1000
  (change) => {
991
1001
  touched.current = true;
992
1002
  setHistory((h) => [...h, change]);
993
- send(change.ops, () => setHistory((h) => h.filter((c) => c !== change)));
1003
+ send(change.ops, () => setHistory((h) => h.filter((c) => c !== change)), change.transient);
994
1004
  onChangeRef.current?.(applyOps(stateRef.current, change.ops), change, false);
995
1005
  },
996
1006
  [send]
@@ -1002,7 +1012,7 @@ function useDeckController({ items, binding, initialState, onChange }) {
1002
1012
  if (!last) return null;
1003
1013
  touched.current = true;
1004
1014
  setHistory((h) => h.slice(0, -1));
1005
- send(last.inverse, () => setHistory((h) => [...h, last]));
1015
+ send(last.inverse, () => setHistory((h) => [...h, last]), last.transient);
1006
1016
  onChangeRef.current?.(applyOps(stateRef.current, last.inverse), last, true);
1007
1017
  return last;
1008
1018
  }, [send]);
@@ -1193,6 +1203,8 @@ var DEFAULT_SWIPE_DECK_LABELS = {
1193
1203
  allDone: "All done",
1194
1204
  answeredOf: "{answered} of {total} answered",
1195
1205
  yourAnswers: "Your answers",
1206
+ answered: "Answered",
1207
+ backToCards: "Back to cards",
1196
1208
  change: "Change",
1197
1209
  rightAnswer: "Right answer",
1198
1210
  right: "Right",
@@ -1773,9 +1785,13 @@ function SwipeDeck(props) {
1773
1785
  const [bubble, setBubble] = React6.useState(null);
1774
1786
  const [toast, setToast] = React6.useState(null);
1775
1787
  const [said, setSaid] = React6.useState("");
1776
- const cardItem = step.kind === "card" ? step.item : null;
1788
+ const [reviewing, setReviewing] = React6.useState(false);
1789
+ const reviewingRef = React6.useRef(false);
1790
+ reviewingRef.current = reviewing;
1791
+ const cardItem = step.kind === "card" && !reviewing ? step.item : null;
1777
1792
  const cardKey = cardItem ? keyFor(rules, cardItem) : deckKey;
1778
1793
  const cardMore = React6.useMemo(() => cardItem ? moreFor(rules, cardItem) : [], [cardItem, rules]);
1794
+ const cardMoreShown = React6.useMemo(() => cardMore.filter((a) => !a.hidden), [cardMore]);
1779
1795
  const suggestedDir = cardItem ? directionOf(cardKey, cardItem.suggested) : null;
1780
1796
  const [cardDetail, setCardDetail] = React6.useState(null);
1781
1797
  const detailNow = cardItem ? cardDetail?.id === cardItem.id ? cardDetail.detail : state.details?.[cardItem.id] ?? null : null;
@@ -1818,7 +1834,8 @@ function SwipeDeck(props) {
1818
1834
  await flyOut(layerRef.current, dir ?? "down", speed);
1819
1835
  const now = stateRef.current;
1820
1836
  const rides = answerDetail(cardItem, detail === void 0 ? detailRef.current : detail);
1821
- const change = answerChange(now, cardItem, answer.id, rules, items, dir, rides);
1837
+ const made = answerChange(now, cardItem, answer.id, rules, items, dir, rides);
1838
+ const change = answer.requeue && props.binding ? { ...made, transient: true } : made;
1822
1839
  enterFrom.current = null;
1823
1840
  setCardDetail(null);
1824
1841
  setLocked(null);
@@ -1963,6 +1980,13 @@ function SwipeDeck(props) {
1963
1980
  const afterTour = React6.useRef(null);
1964
1981
  const runKeyRef = React6.useRef(() => false);
1965
1982
  runKeyRef.current = (key, target) => {
1983
+ if (reviewingRef.current) {
1984
+ if (key === "Escape") {
1985
+ setReviewing(false);
1986
+ return true;
1987
+ }
1988
+ if (key !== "z" && key !== "Z" && key !== "Backspace") return false;
1989
+ }
1966
1990
  const dir = KEYS[key];
1967
1991
  const shortcut = !dir && key.length === 1 ? shortcutRef.current(key) : null;
1968
1992
  if ((dir || shortcut) && lockedRef.current) return false;
@@ -2004,7 +2028,7 @@ function SwipeDeck(props) {
2004
2028
  const a2 = cardKey[d];
2005
2029
  if (a2?.shortcut?.toLowerCase() === k) return { answer: a2, dir: d };
2006
2030
  }
2007
- const a = cardMore.find((x) => x.shortcut?.toLowerCase() === k);
2031
+ const a = cardMoreShown.find((x) => x.shortcut?.toLowerCase() === k);
2008
2032
  return a ? { answer: a, dir: null } : null;
2009
2033
  };
2010
2034
  const exitRef = React6.useRef({ kind: props.exitKind, onExit: props.onExit });
@@ -2020,6 +2044,11 @@ function SwipeDeck(props) {
2020
2044
  if (layout === "inline" && !(root && (root.contains(active ?? null) || root.matches(":hover")))) return;
2021
2045
  const t = e.target instanceof Element ? e.target : null;
2022
2046
  if (t?.closest("input, textarea, select, [contenteditable='true']")) return;
2047
+ if ((e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey && (e.key === "z" || e.key === "Z") && !e.repeat) {
2048
+ e.preventDefault();
2049
+ undoRef.current();
2050
+ return;
2051
+ }
2023
2052
  if (e.altKey || e.ctrlKey || e.metaKey) return;
2024
2053
  if (e.repeat) {
2025
2054
  if (KEYS[e.key] || e.key === "z" || e.key === "Z" || e.key === "Backspace") e.preventDefault();
@@ -2176,7 +2205,7 @@ function SwipeDeck(props) {
2176
2205
  wasAtEnd.current = atEnd;
2177
2206
  }, [atEnd, result, onComplete, labels]);
2178
2207
  const copy = async () => {
2179
- const text2 = props.copyText ? props.copyText({ item: cardItem, state, result }) : cardItem ? itemCopyText(cardItem, state, cardKey, labels, conflict, cardMore) : deckCopyText(result, rules);
2208
+ const text2 = props.copyText ? props.copyText({ item: cardItem, state, result }) : cardItem ? itemCopyText(cardItem, state, cardKey, labels, conflict, cardMoreShown) : deckCopyText(result, rules);
2180
2209
  const ok = await (0, import_clipboard.copyText)(text2);
2181
2210
  flash(ok ? labels.copied : labels.copyFailed);
2182
2211
  };
@@ -2230,11 +2259,41 @@ function SwipeDeck(props) {
2230
2259
  },
2231
2260
  children: [
2232
2261
  props.onExpand ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CornerButton, { corner: "tl", label: labels.expand, onClick: props.onExpand, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Maximize2Icon, {}) }) : props.onExit ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CornerButton, { corner: "tl", label: props.exitKind === "collapse" ? labels.collapse : labels.exit, ...props.exitKind === "collapse" ? { shortcut: "Escape" } : {}, onClick: props.onExit, children: props.exitKind === "collapse" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Minimize2Icon, {}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(XIcon, {}) }) : null,
2233
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CornerButton, { corner: "tr", label: labels.help, shortcut: "?", onClick: () => void tour(), disabled: !cardItem, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CircleHelpIcon, {}) }),
2262
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(CornerButton, { corner: "tr", label: labels.answered, onClick: () => setReviewing((v) => !v), disabled: !ready || !items.length || step.kind === "end", pressed: reviewing, children: [
2263
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ListChecksIcon, {}),
2264
+ result.answered ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "matrx-sd-corner-count", children: result.answered }) : null
2265
+ ] }),
2234
2266
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CornerButton, { corner: "bl", label: labels.undo, shortcut: "Z", onClick: undo, disabled: !controller.canUndo, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Undo2Icon, {}) }),
2235
2267
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CornerButton, { corner: "br", label: labels.copy, onClick: () => void copy(), disabled: !ready || !items.length, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CopyIcon, {}) }),
2236
2268
  cardItem ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EdgeButtons, { keyMap: cardKey, suggested: suggestedDir, refs: edgeRefs, onAnswer: (d) => act(d), suggestionLabel: labels.suggestion }) : null,
2237
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-stage", children: !ready ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-layer", "data-state": controller.status, children: controller.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ErrorBox, { className: "matrx-sd-message", message: controller.readError ?? "", operation: "Read the deck", origin: "design-system/SwipeDeck" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Loader2Icon, { className: "matrx-spin matrx-sd-spinner" }) }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EmptyView, { title: props.empty?.title ?? labels.emptyTitle, line: props.empty?.line, action: props.empty?.action, layerRef }, "empty") : step.kind === "card" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2269
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-stage", children: !ready ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-layer", "data-state": controller.status, children: controller.status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ErrorBox, { className: "matrx-sd-message", message: controller.readError ?? "", operation: "Read the deck", origin: "design-system/SwipeDeck" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Loader2Icon, { className: "matrx-spin matrx-sd-spinner" }) }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EmptyView, { title: props.empty?.title ?? labels.emptyTitle, line: props.empty?.line, action: props.empty?.action, layerRef }, "empty") : reviewing && step.kind !== "end" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2270
+ EndView,
2271
+ {
2272
+ result,
2273
+ rules,
2274
+ labels,
2275
+ groupLabels: props.groupLabels,
2276
+ layerRef,
2277
+ enterFrom,
2278
+ review: {
2279
+ onBack: () => setReviewing(false),
2280
+ onHelp: () => {
2281
+ setReviewing(false);
2282
+ void tour();
2283
+ }
2284
+ },
2285
+ onChange: (item) => {
2286
+ enterFrom.current = null;
2287
+ const now = stateRef.current;
2288
+ const ops = [{ kind: "answer", itemId: item.id, answer: null }];
2289
+ if (item.group && now.picks[item.group] === item.id) ops.push({ kind: "pick", group: item.group, itemId: null });
2290
+ controller.commit(makeChange(now, ops, items));
2291
+ setReviewing(false);
2292
+ setSaid(`${labels.change}: ${item.text}`);
2293
+ }
2294
+ },
2295
+ "review"
2296
+ ) : step.kind === "card" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2238
2297
  CardView,
2239
2298
  {
2240
2299
  item: step.item,
@@ -2243,7 +2302,7 @@ function SwipeDeck(props) {
2243
2302
  conflict,
2244
2303
  labels,
2245
2304
  suggestedDir,
2246
- more: cardMore,
2305
+ more: cardMoreShown,
2247
2306
  detail: detailNow,
2248
2307
  onDetail: (d) => setCardDetail({ id: step.item.id, detail: d }),
2249
2308
  body: cardContext && props.renderCardBody ? props.renderCardBody(cardContext) : null,
@@ -2587,7 +2646,7 @@ function groupOf(entry, graded) {
2587
2646
  if (graded && entry.right !== null) return entry.right ? "right" : "wrong";
2588
2647
  return entry.answer.label;
2589
2648
  }
2590
- function EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, actions, onChange, children }) {
2649
+ function EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, actions, onChange, children, review }) {
2591
2650
  const layer = React6.useRef(null);
2592
2651
  React6.useLayoutEffect(() => {
2593
2652
  layerRef.current = layer.current;
@@ -2607,11 +2666,11 @@ function EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, acti
2607
2666
  const answered = result.entries.filter((e) => e.answer);
2608
2667
  const shown = filter ? answered.filter((e) => groupOf(e, graded) === filter) : answered;
2609
2668
  const pct = score && score.graded ? score.right / score.graded : 1;
2610
- const kicker = first ? groupLabels?.[first[0]] ?? first[0] : score ? labels.score : null;
2611
- const headline = first ? first[1].text : score ? `${score.right} / ${score.graded}` : labels.allDone;
2669
+ const kicker = review ? null : first ? groupLabels?.[first[0]] ?? first[0] : score ? labels.score : null;
2670
+ const headline = review ? labels.answered : first ? first[1].text : score ? `${score.right} / ${score.graded}` : labels.allDone;
2612
2671
  const sub = labels.answeredOf.replace("{answered}", String(result.answered)).replace("{total}", String(result.total));
2613
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: layer, className: "matrx-sd-layer matrx-sd-endlayer", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "matrx-sd-end", "data-graded": graded ? "" : void 0, children: [
2614
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { className: "matrx-sd-mark", viewBox: "0 0 72 72", "aria-hidden": "true", "data-tone": score ? pct >= 0.5 ? "success" : "warning" : "success", children: [
2672
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: layer, className: "matrx-sd-layer matrx-sd-endlayer", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "matrx-sd-end", "data-graded": graded ? "" : void 0, "data-review": review ? "" : void 0, children: [
2673
+ review ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { className: "matrx-sd-mark", viewBox: "0 0 72 72", "aria-hidden": "true", "data-tone": score ? pct >= 0.5 ? "success" : "warning" : "success", children: [
2615
2674
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { className: "matrx-sd-mark-track", cx: "36", cy: "36", r: "32" }),
2616
2675
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { className: "matrx-sd-mark-ring", cx: "36", cy: "36", r: "32", pathLength: 100, style: { strokeDasharray: `${Math.round(pct * 100)} 100` } }),
2617
2676
  !score || pct === 1 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { className: "matrx-sd-mark-check", d: "M23 37.5l9 9 17-19", pathLength: 100 }) : null
@@ -2619,11 +2678,11 @@ function EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, acti
2619
2678
  kicker ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-kicker", children: kicker }) : null,
2620
2679
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "matrx-sd-end-hero", children: headline }),
2621
2680
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-end-sub", children: sub }),
2622
- score && first ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "matrx-sd-endline", children: [
2681
+ score && first && !review ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "matrx-sd-endline", children: [
2623
2682
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-label", children: labels.score }),
2624
2683
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-value", children: `${score.right} / ${score.graded}` })
2625
2684
  ] }) : null,
2626
- rest.map(([group, item]) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "matrx-sd-endline", children: [
2685
+ (review ? [] : rest).map(([group, item]) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "matrx-sd-endline", children: [
2627
2686
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-label", children: groupLabels?.[group] ?? group }),
2628
2687
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-value", children: item.text })
2629
2688
  ] }, group)),
@@ -2660,6 +2719,8 @@ function EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, acti
2660
2719
  ] }) : null,
2661
2720
  shown.length ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "matrx-sd-review", "aria-label": labels.yourAnswers, children: shown.map((e) => {
2662
2721
  const rightIds = e.item.correct === void 0 ? [] : typeof e.item.correct === "string" ? [e.item.correct] : e.item.correct;
2722
+ const said = typeof e.detail?.value === "string" && e.detail.value.trim() ? e.detail.value : e.item.text;
2723
+ const answerWords = typeof e.detail?.label === "string" && e.detail.label ? e.detail.label : e.answer?.label;
2663
2724
  const rightWords = rightIds.map((id) => findAnswer(rules, e.item, id)?.label).filter(Boolean).join(", ");
2664
2725
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2665
2726
  "button",
@@ -2668,14 +2729,14 @@ function EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, acti
2668
2729
  className: "matrx-sd-review-row",
2669
2730
  onClick: () => onChange(e.item),
2670
2731
  "aria-label": [
2671
- `${labels.change}: ${e.item.text}`,
2672
- [e.answer?.label, e.right === true ? labels.right : e.right === false ? labels.wrong : null].filter(Boolean).join(", "),
2732
+ `${labels.change}: ${said}`,
2733
+ [answerWords, e.right === true ? labels.right : e.right === false ? labels.wrong : null].filter(Boolean).join(", "),
2673
2734
  e.right === false && rightWords ? `${labels.rightAnswer}: ${rightWords}` : null
2674
2735
  ].filter(Boolean).join(". "),
2675
2736
  children: [
2676
2737
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "matrx-sd-review-text", children: [
2677
2738
  e.item.kicker ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "matrx-sd-label", children: e.item.kicker }) : null,
2678
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "matrx-sd-review-item", children: e.item.text }),
2739
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "matrx-sd-review-item", children: said }),
2679
2740
  e.right === false && rightWords ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "matrx-sd-review-right", children: [
2680
2741
  labels.rightAnswer,
2681
2742
  ": ",
@@ -2684,14 +2745,23 @@ function EndView({ result, rules, labels, groupLabels, layerRef, enterFrom, acti
2684
2745
  ] }),
2685
2746
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "matrx-sd-review-answer", "data-tone": e.right === null ? e.answer?.tone : e.right ? "success" : "destructive", children: [
2686
2747
  e.right === true ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CheckIcon, {}) : e.right === false ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(XIcon, {}) : null,
2687
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: e.answer?.label })
2748
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: answerWords })
2688
2749
  ] }),
2689
2750
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PencilIcon, { className: "matrx-sd-review-change", "aria-hidden": "true" })
2690
2751
  ]
2691
2752
  }
2692
2753
  ) }, e.item.id);
2693
2754
  }) }) : null,
2694
- actions ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-end-actions", children: actions }) : null
2755
+ review ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "matrx-sd-end-actions", children: [
2756
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "matrx-sd-review-back", onClick: review.onBack, autoFocus: true, children: labels.backToCards }),
2757
+ review.onHelp ? (
2758
+ // ui-exception: the walkthrough, from the answered list (the corner it had now opens this list)
2759
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { type: "button", className: "matrx-sd-legend-chip", onClick: review.onHelp, children: [
2760
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CircleHelpIcon, { "aria-hidden": "true" }),
2761
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: labels.help })
2762
+ ] })
2763
+ ) : null
2764
+ ] }) : actions ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "matrx-sd-end-actions", children: actions }) : null
2695
2765
  ] }) });
2696
2766
  }
2697
2767
  function EmptyView({ title, line, action, layerRef }) {