@intellectif/lk-react 13.0.0 → 14.0.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.
Files changed (162) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +11 -3
  3. package/dist/{WrittenResponse-B5p_-RnJ.d.ts → WrittenResponse-C0P34En1.d.ts} +1 -1
  4. package/dist/{WrittenResponse-DWtS4tOL.d.cts → WrittenResponse-pB1ik8hg.d.cts} +1 -1
  5. package/dist/chunk-36FTYJWJ.cjs +869 -0
  6. package/dist/chunk-36FTYJWJ.cjs.map +1 -0
  7. package/dist/{chunk-PSHNTDKG.js → chunk-47HHC4GD.js} +13 -161
  8. package/dist/chunk-47HHC4GD.js.map +1 -0
  9. package/dist/chunk-62AKSD5Y.js +509 -0
  10. package/dist/chunk-62AKSD5Y.js.map +1 -0
  11. package/dist/{chunk-XAGWBVK3.js → chunk-72UGRIMM.js} +6 -5
  12. package/dist/chunk-72UGRIMM.js.map +1 -0
  13. package/dist/{chunk-SBIJJ374.cjs → chunk-B2XQLU2E.cjs} +5 -5
  14. package/dist/{chunk-SBIJJ374.cjs.map → chunk-B2XQLU2E.cjs.map} +1 -1
  15. package/dist/{chunk-DQERNAWI.js → chunk-BO6P723E.js} +26 -31
  16. package/dist/chunk-BO6P723E.js.map +1 -0
  17. package/dist/chunk-BRPEB43C.cjs +13 -0
  18. package/dist/chunk-BRPEB43C.cjs.map +1 -0
  19. package/dist/{chunk-NVUFEMPZ.cjs → chunk-BVRUUYYR.cjs} +30 -16
  20. package/dist/chunk-BVRUUYYR.cjs.map +1 -0
  21. package/dist/{chunk-AMGK7DDM.cjs → chunk-D4DQFTA7.cjs} +2 -2
  22. package/dist/chunk-D4DQFTA7.cjs.map +1 -0
  23. package/dist/chunk-D57QZILZ.js +863 -0
  24. package/dist/chunk-D57QZILZ.js.map +1 -0
  25. package/dist/chunk-F4TBCRGI.cjs +518 -0
  26. package/dist/chunk-F4TBCRGI.cjs.map +1 -0
  27. package/dist/{chunk-YILH4ETT.js → chunk-I33FOKZ7.js} +224 -31
  28. package/dist/chunk-I33FOKZ7.js.map +1 -0
  29. package/dist/{chunk-HT4FFZZQ.cjs → chunk-J2CDPIRC.cjs} +231 -38
  30. package/dist/chunk-J2CDPIRC.cjs.map +1 -0
  31. package/dist/{chunk-MA7GXUWC.cjs → chunk-LB3FEV7Z.cjs} +77 -2
  32. package/dist/chunk-LB3FEV7Z.cjs.map +1 -0
  33. package/dist/{chunk-5N7OLFHB.js → chunk-LGCUOLP6.js} +6 -5
  34. package/dist/chunk-LGCUOLP6.js.map +1 -0
  35. package/dist/{chunk-YZWXVZB3.js → chunk-LLXCX5KK.js} +6 -5
  36. package/dist/chunk-LLXCX5KK.js.map +1 -0
  37. package/dist/chunk-MCO52PV5.js +520 -0
  38. package/dist/chunk-MCO52PV5.js.map +1 -0
  39. package/dist/{chunk-K7NMNOPI.cjs → chunk-NDQD3ZRY.cjs} +15 -14
  40. package/dist/chunk-NDQD3ZRY.cjs.map +1 -0
  41. package/dist/chunk-OD65OZIW.cjs +159 -0
  42. package/dist/chunk-OD65OZIW.cjs.map +1 -0
  43. package/dist/chunk-RCMYEWBE.js +11 -0
  44. package/dist/chunk-RCMYEWBE.js.map +1 -0
  45. package/dist/{chunk-74QXBWCI.cjs → chunk-RRH7ZPXC.cjs} +6 -6
  46. package/dist/{chunk-74QXBWCI.cjs.map → chunk-RRH7ZPXC.cjs.map} +1 -1
  47. package/dist/{chunk-DQNVAXG6.js → chunk-RXS455MR.js} +2 -2
  48. package/dist/chunk-RXS455MR.js.map +1 -0
  49. package/dist/{chunk-Z63JRG4M.cjs → chunk-SE6WWDVW.cjs} +15 -14
  50. package/dist/chunk-SE6WWDVW.cjs.map +1 -0
  51. package/dist/{chunk-NVP6UEQQ.js → chunk-SWY6PWXK.js} +4 -4
  52. package/dist/{chunk-NVP6UEQQ.js.map → chunk-SWY6PWXK.js.map} +1 -1
  53. package/dist/{chunk-3Q4I4KT6.js → chunk-TDJEKXEP.js} +77 -2
  54. package/dist/chunk-TDJEKXEP.js.map +1 -0
  55. package/dist/{chunk-2GXSA322.cjs → chunk-U3APKQ7P.cjs} +15 -14
  56. package/dist/chunk-U3APKQ7P.cjs.map +1 -0
  57. package/dist/chunk-UDCQTOVU.cjs +523 -0
  58. package/dist/chunk-UDCQTOVU.cjs.map +1 -0
  59. package/dist/{chunk-K3EA547J.cjs → chunk-USBANZ7K.cjs} +27 -33
  60. package/dist/chunk-USBANZ7K.cjs.map +1 -0
  61. package/dist/{chunk-J73TDY7J.cjs → chunk-WTS34S5E.cjs} +25 -173
  62. package/dist/chunk-WTS34S5E.cjs.map +1 -0
  63. package/dist/{chunk-R7DI5UMU.js → chunk-XIBOFTOL.js} +3 -3
  64. package/dist/{chunk-R7DI5UMU.js.map → chunk-XIBOFTOL.js.map} +1 -1
  65. package/dist/{chunk-W4MXRZAB.js → chunk-XUEIUEPI.js} +6 -5
  66. package/dist/chunk-XUEIUEPI.js.map +1 -0
  67. package/dist/{chunk-UU2NV6SU.cjs → chunk-YEYKJFEC.cjs} +14 -13
  68. package/dist/chunk-YEYKJFEC.cjs.map +1 -0
  69. package/dist/{chunk-PY53ABWC.js → chunk-YMBBM5K7.js} +23 -9
  70. package/dist/chunk-YMBBM5K7.js.map +1 -0
  71. package/dist/chunk-YORQQXGO.js +155 -0
  72. package/dist/chunk-YORQQXGO.js.map +1 -0
  73. package/dist/components/ActivityPreview.cjs +15 -10
  74. package/dist/components/ActivityPreview.d.cts +9 -3
  75. package/dist/components/ActivityPreview.d.ts +9 -3
  76. package/dist/components/ActivityPreview.js +14 -9
  77. package/dist/components/ActivitySequence.cjs +16 -11
  78. package/dist/components/ActivitySequence.d.cts +108 -4
  79. package/dist/components/ActivitySequence.d.ts +108 -4
  80. package/dist/components/ActivitySequence.js +15 -10
  81. package/dist/components/Dictation.cjs +7 -5
  82. package/dist/components/Dictation.d.cts +2 -1
  83. package/dist/components/Dictation.d.ts +2 -1
  84. package/dist/components/Dictation.js +6 -4
  85. package/dist/components/FillInTheBlanks.cjs +6 -5
  86. package/dist/components/FillInTheBlanks.d.cts +2 -1
  87. package/dist/components/FillInTheBlanks.d.ts +2 -1
  88. package/dist/components/FillInTheBlanks.js +5 -4
  89. package/dist/components/GapSelect.cjs +6 -5
  90. package/dist/components/GapSelect.d.cts +2 -1
  91. package/dist/components/GapSelect.d.ts +2 -1
  92. package/dist/components/GapSelect.js +5 -4
  93. package/dist/components/MultipleChoice.cjs +6 -5
  94. package/dist/components/MultipleChoice.d.cts +2 -1
  95. package/dist/components/MultipleChoice.d.ts +2 -1
  96. package/dist/components/MultipleChoice.js +5 -4
  97. package/dist/components/PronunciationFeedback.cjs +16 -0
  98. package/dist/components/PronunciationFeedback.cjs.map +1 -0
  99. package/dist/components/PronunciationFeedback.d.cts +64 -0
  100. package/dist/components/PronunciationFeedback.d.ts +64 -0
  101. package/dist/components/PronunciationFeedback.js +7 -0
  102. package/dist/components/PronunciationFeedback.js.map +1 -0
  103. package/dist/components/ReadAloud.cjs +21 -0
  104. package/dist/components/ReadAloud.cjs.map +1 -0
  105. package/dist/components/ReadAloud.d.cts +15 -0
  106. package/dist/components/ReadAloud.d.ts +15 -0
  107. package/dist/components/ReadAloud.js +12 -0
  108. package/dist/components/ReadAloud.js.map +1 -0
  109. package/dist/components/StimulusPanel.cjs +4 -4
  110. package/dist/components/StimulusPanel.d.cts +2 -1
  111. package/dist/components/StimulusPanel.d.ts +2 -1
  112. package/dist/components/StimulusPanel.js +3 -3
  113. package/dist/components/WrittenResponse.cjs +6 -5
  114. package/dist/components/WrittenResponse.d.cts +4 -3
  115. package/dist/components/WrittenResponse.d.ts +4 -3
  116. package/dist/components/WrittenResponse.js +5 -4
  117. package/dist/hooks/useSpeechRecorder.cjs +17 -0
  118. package/dist/hooks/useSpeechRecorder.cjs.map +1 -0
  119. package/dist/hooks/useSpeechRecorder.d.cts +127 -0
  120. package/dist/hooks/useSpeechRecorder.d.ts +127 -0
  121. package/dist/hooks/useSpeechRecorder.js +4 -0
  122. package/dist/hooks/useSpeechRecorder.js.map +1 -0
  123. package/dist/i18n/LkIntlProvider.cjs +7 -7
  124. package/dist/i18n/LkIntlProvider.d.cts +3 -2
  125. package/dist/i18n/LkIntlProvider.d.ts +3 -2
  126. package/dist/i18n/LkIntlProvider.js +1 -1
  127. package/dist/index.cjs +53 -32
  128. package/dist/index.cjs.map +1 -1
  129. package/dist/index.d.cts +6 -2
  130. package/dist/index.d.ts +6 -2
  131. package/dist/index.js +17 -12
  132. package/dist/index.js.map +1 -1
  133. package/dist/machine-CuwKqWXC.d.cts +26 -0
  134. package/dist/machine-CuwKqWXC.d.ts +26 -0
  135. package/dist/{strings-DPTyLpHt.d.ts → strings--ADnHcaA.d.cts} +214 -4
  136. package/dist/{strings-DPTyLpHt.d.cts → strings-CtdSf2St.d.ts} +214 -4
  137. package/dist/theme/ThemeProvider.cjs +6 -6
  138. package/dist/theme/ThemeProvider.d.cts +4 -4
  139. package/dist/theme/ThemeProvider.d.ts +4 -4
  140. package/dist/theme/ThemeProvider.js +1 -1
  141. package/dist/theme/skin.css +596 -3
  142. package/package.json +33 -3
  143. package/dist/chunk-2GXSA322.cjs.map +0 -1
  144. package/dist/chunk-3Q4I4KT6.js.map +0 -1
  145. package/dist/chunk-5N7OLFHB.js.map +0 -1
  146. package/dist/chunk-AMGK7DDM.cjs.map +0 -1
  147. package/dist/chunk-DQERNAWI.js.map +0 -1
  148. package/dist/chunk-DQNVAXG6.js.map +0 -1
  149. package/dist/chunk-HT4FFZZQ.cjs.map +0 -1
  150. package/dist/chunk-J73TDY7J.cjs.map +0 -1
  151. package/dist/chunk-K3EA547J.cjs.map +0 -1
  152. package/dist/chunk-K7NMNOPI.cjs.map +0 -1
  153. package/dist/chunk-MA7GXUWC.cjs.map +0 -1
  154. package/dist/chunk-NVUFEMPZ.cjs.map +0 -1
  155. package/dist/chunk-PSHNTDKG.js.map +0 -1
  156. package/dist/chunk-PY53ABWC.js.map +0 -1
  157. package/dist/chunk-UU2NV6SU.cjs.map +0 -1
  158. package/dist/chunk-W4MXRZAB.js.map +0 -1
  159. package/dist/chunk-XAGWBVK3.js.map +0 -1
  160. package/dist/chunk-YILH4ETT.js.map +0 -1
  161. package/dist/chunk-YZWXVZB3.js.map +0 -1
  162. package/dist/chunk-Z63JRG4M.cjs.map +0 -1
@@ -1,38 +1,17 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkMA7GXUWC_cjs = require('./chunk-MA7GXUWC.cjs');
4
+ var chunkLB3FEV7Z_cjs = require('./chunk-LB3FEV7Z.cjs');
5
5
  var react = require('react');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
8
- function isProduction() {
9
- const g = globalThis;
10
- return g.process?.env?.NODE_ENV === "production";
11
- }
12
- var ActivityErrorBoundary = class extends react.Component {
13
- state = { error: null };
14
- static getDerivedStateFromError(error) {
15
- return { error };
16
- }
17
- render() {
18
- const { error } = this.state;
19
- if (!error) {
20
- return this.props.children;
21
- }
22
- if (!isProduction()) {
23
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", children: [
24
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: (this.props.strings ?? chunkMA7GXUWC_cjs.DEFAULT_STRINGS).activityFailed }),
25
- /* @__PURE__ */ jsxRuntime.jsx("pre", { children: error.stack ?? error.message })
26
- ] });
27
- }
28
- return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", children: this.props.activityTitle ? (this.props.strings ?? chunkMA7GXUWC_cjs.DEFAULT_STRINGS).activityFailedNamed(this.props.activityTitle) : (this.props.strings ?? chunkMA7GXUWC_cjs.DEFAULT_STRINGS).activityFailedUnnamed });
29
- }
30
- };
31
-
32
8
  // src/components/_internal.ts
33
9
  function isDevelopment() {
34
- const g = globalThis;
35
- return g.process?.env?.NODE_ENV !== "production";
10
+ try {
11
+ return process.env.NODE_ENV !== "production";
12
+ } catch {
13
+ return true;
14
+ }
36
15
  }
37
16
  var ANONYMOUS_ACTOR = {
38
17
  objectType: "Agent",
@@ -48,15 +27,30 @@ function randomSessionId() {
48
27
  }
49
28
  return `s-${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
50
29
  }
51
- function FeedbackRegion({ id, className, children }) {
52
- return /* @__PURE__ */ jsxRuntime.jsx("div", { id, className, "aria-live": "polite", "aria-atomic": "true", children });
53
- }
30
+ var ActivityErrorBoundary = class extends react.Component {
31
+ state = { error: null };
32
+ static getDerivedStateFromError(error) {
33
+ return { error };
34
+ }
35
+ render() {
36
+ const { error } = this.state;
37
+ if (!error) {
38
+ return this.props.children;
39
+ }
40
+ if (isDevelopment()) {
41
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", children: [
42
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: (this.props.strings ?? chunkLB3FEV7Z_cjs.DEFAULT_STRINGS).activityFailed }),
43
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { children: error.stack ?? error.message })
44
+ ] });
45
+ }
46
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", children: this.props.activityTitle ? (this.props.strings ?? chunkLB3FEV7Z_cjs.DEFAULT_STRINGS).activityFailedNamed(this.props.activityTitle) : (this.props.strings ?? chunkLB3FEV7Z_cjs.DEFAULT_STRINGS).activityFailedUnnamed });
47
+ }
48
+ };
54
49
 
55
50
  exports.ANONYMOUS_ACTOR = ANONYMOUS_ACTOR;
56
51
  exports.ActivityErrorBoundary = ActivityErrorBoundary;
57
- exports.FeedbackRegion = FeedbackRegion;
58
52
  exports.isDevelopment = isDevelopment;
59
53
  exports.objectIdFor = objectIdFor;
60
54
  exports.randomSessionId = randomSessionId;
61
- //# sourceMappingURL=chunk-K3EA547J.cjs.map
62
- //# sourceMappingURL=chunk-K3EA547J.cjs.map
55
+ //# sourceMappingURL=chunk-USBANZ7K.cjs.map
56
+ //# sourceMappingURL=chunk-USBANZ7K.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/_internal.ts","../src/components/ActivityErrorBoundary.tsx"],"names":["Component","jsxs","jsx","DEFAULT_STRINGS"],"mappings":";;;;;;;AA8BO,SAAS,aAAA,GAAyB;AACvC,EAAA,IAAI;AACF,IAAA,OAAO,OAAA,CAAQ,IAAI,QAAA,KAAa,YAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAOO,IAAM,eAAA,GAA6B;AAAA,EACxC,UAAA,EAAY,OAAA;AAAA,EACZ,OAAA,EAAS,EAAE,QAAA,EAAU,6CAAA,EAA+C,MAAM,WAAA;AAC5E;AAGO,SAAS,YAAY,EAAA,EAAoB;AAC9C,EAAA,OAAO,CAAA,0BAAA,EAA6B,kBAAA,CAAmB,EAAE,CAAC,CAAA,CAAA;AAC5D;AAQO,SAAS,eAAA,GAA0B;AACxC,EAAA,MAAM,IAAK,UAAA,CAA0D,MAAA;AACrE,EAAA,IAAI,GAAG,UAAA,EAAY;AACjB,IAAA,OAAO,EAAE,UAAA,EAAW;AAAA,EACtB;AACA,EAAA,OAAO,KAAK,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,EAAE,EAAE,KAAA,CAAM,CAAC,CAAC,CAAA,EAAG,IAAA,CAAK,QAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACvF;ACrCO,IAAM,qBAAA,GAAN,cAAoCA,eAAA,CAGzC;AAAA,EACA,KAAA,GAAoC,EAAE,KAAA,EAAO,IAAA,EAAK;AAAA,EAElD,OAAO,yBAAyB,KAAA,EAA0C;AACxE,IAAA,OAAO,EAAE,KAAA,EAAM;AAAA,EACjB;AAAA,EAEA,MAAA,GAAoB;AAClB,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,IAAA,CAAK,KAAA;AACvB,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,KAAK,KAAA,CAAM,QAAA;AAAA,IACpB;AAKA,IAAA,IAAI,eAAc,EAAG;AACnB,MAAA,uBACEC,eAAA,CAAC,KAAA,EAAA,EAAI,IAAA,EAAK,OAAA,EACR,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAAC,QAAA,EAAA,EAAS,QAAA,EAAA,CAAA,IAAA,CAAK,KAAA,CAAM,OAAA,IAAWC,mCAAiB,cAAA,EAAe,CAAA;AAAA,wBAChED,cAAA,CAAC,KAAA,EAAA,EAAK,QAAA,EAAA,KAAA,CAAM,KAAA,IAAS,MAAM,OAAA,EAAQ;AAAA,OAAA,EACrC,CAAA;AAAA,IAEJ;AAEA,IAAA,uBACEA,cAAA,CAAC,SAAI,IAAA,EAAK,OAAA,EACP,eAAK,KAAA,CAAM,aAAA,GAAA,CACP,KAAK,KAAA,CAAM,OAAA,IAAWC,mCAAiB,mBAAA,CAAoB,IAAA,CAAK,MAAM,aAAa,CAAA,GAAA,CACnF,KAAK,KAAA,CAAM,OAAA,IAAWA,mCAAiB,qBAAA,EAC9C,CAAA;AAAA,EAEJ;AACF","file":"chunk-USBANZ7K.cjs","sourcesContent":["import type { XAPIActor } from '@intellectif/lk-core';\n\n/**\n * The one global this module reads by name. Declared here, not globally: this\n * package compiles without Node's types on purpose, and nothing else in it may\n * come to rely on `process`.\n */\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Whether this is anything other than a production build — the one answer\n * every development check and the error boundary's stack trace read.\n *\n * **The literal `process.env.NODE_ENV`, spelled exactly so.** It is the one\n * expression bundlers replace at build time — Vite, webpack, esbuild, Next.js\n * and Rollup's replace plugin all substitute it — and a browser has no\n * `process` to read at run time. The reading this replaces,\n * `globalThis.process?.env?.NODE_ENV`, is not that expression, so no bundler\n * touched it, and in a browser it found no `process` and answered\n * \"development\" in every production app: learners were shown a stack trace\n * where each component's production fallback belonged. Tests running in Node\n * never saw it, because Node has a `process`.\n *\n * This package's own build must leave the literal in its output, for the\n * consumer's bundler to replace. A library build that substituted it would\n * freeze every consumer into whichever mode the library was built in.\n *\n * The `try` covers code that reaches a runtime unbundled, with no `process`\n * at all: that is development, as it always was.\n */\nexport function isDevelopment(): boolean {\n try {\n return process.env.NODE_ENV !== 'production';\n } catch {\n return true;\n }\n}\n\n/**\n * Activity components cannot know the learner's identity (Req 3.1 fixes the\n * prop set). They emit a structurally-valid statement with this anonymous\n * actor; real identity is applied by the useXAPI/LRS layer (XAPIConfig.actor).\n */\nexport const ANONYMOUS_ACTOR: XAPIActor = {\n objectType: 'Agent',\n account: { homePage: 'https://github.com/intellectif/learning-kit', name: 'anonymous' },\n};\n\n/** `data.id` is not an IRI; xAPI object ids must be. Wrap it as a URN. */\nexport function objectIdFor(id: string): string {\n return `urn:learning-kit:activity:${encodeURIComponent(id)}`;\n}\n\n/**\n * Random per-mount session id for the shuffle seed. `crypto.randomUUID` is\n * unavailable outside secure contexts (plain-http LAN/staging hosts), so a\n * Math.random fallback keeps the component from crashing there — the seed\n * only randomises presentation order, so cryptographic strength is not needed.\n */\nexport function randomSessionId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `s-${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;\n}\n","'use client';\n\nimport { Component, type ReactNode } from 'react';\nimport type { LkStrings } from '../i18n/strings.js';\nimport { DEFAULT_STRINGS } from '../i18n/strings.js';\nimport { isDevelopment } from './_internal.js';\n\nexport interface ActivityErrorBoundaryProps {\n /** Shown in the production fallback when a render error occurs. */\n activityTitle?: string;\n /**\n * Chrome text. A class component cannot call `useLkStrings`, so the public\n * wrapper reads the hook and hands the resolved dictionary down.\n */\n strings?: LkStrings;\n children: ReactNode;\n}\n\ninterface ActivityErrorBoundaryState {\n error: Error | null;\n}\n\n/**\n * Catches render errors in an activity subtree. In development it renders the\n * full error stack to aid debugging; in production it renders an accessible,\n * generic fallback (optionally naming the activity) so a single broken\n * activity never crashes the host application.\n */\nexport class ActivityErrorBoundary extends Component<\n ActivityErrorBoundaryProps,\n ActivityErrorBoundaryState\n> {\n state: ActivityErrorBoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): ActivityErrorBoundaryState {\n return { error };\n }\n\n render(): ReactNode {\n const { error } = this.state;\n if (!error) {\n return this.props.children;\n }\n\n // The same answer every development check reads, from the one function\n // that gives it: a boundary with a reading of its own showed a learner a\n // stack trace in every browser production build.\n if (isDevelopment()) {\n return (\n <div role=\"alert\">\n <strong>{(this.props.strings ?? DEFAULT_STRINGS).activityFailed}</strong>\n <pre>{error.stack ?? error.message}</pre>\n </div>\n );\n }\n\n return (\n <div role=\"alert\">\n {this.props.activityTitle\n ? (this.props.strings ?? DEFAULT_STRINGS).activityFailedNamed(this.props.activityTitle)\n : (this.props.strings ?? DEFAULT_STRINGS).activityFailedUnnamed}\n </div>\n );\n }\n}\n"]}
@@ -1,164 +1,16 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkK3EA547J_cjs = require('./chunk-K3EA547J.cjs');
5
- var chunkSBIJJ374_cjs = require('./chunk-SBIJJ374.cjs');
4
+ var chunkOD65OZIW_cjs = require('./chunk-OD65OZIW.cjs');
5
+ var chunkBRPEB43C_cjs = require('./chunk-BRPEB43C.cjs');
6
+ var chunkUSBANZ7K_cjs = require('./chunk-USBANZ7K.cjs');
7
+ var chunkB2XQLU2E_cjs = require('./chunk-B2XQLU2E.cjs');
6
8
  var chunkXOR4MPEN_cjs = require('./chunk-XOR4MPEN.cjs');
7
- var chunkMA7GXUWC_cjs = require('./chunk-MA7GXUWC.cjs');
9
+ var chunkLB3FEV7Z_cjs = require('./chunk-LB3FEV7Z.cjs');
8
10
  var lkCore = require('@intellectif/lk-core');
9
11
  var react = require('react');
10
12
  var jsxRuntime = require('react/jsx-runtime');
11
13
 
12
- // src/i18n/direction.ts
13
- var RTL_SCRIPT_CODES = /* @__PURE__ */ new Set([
14
- "phlv",
15
- "adlm",
16
- "arab",
17
- "aran",
18
- "armi",
19
- "avst",
20
- "chrs",
21
- "cprt",
22
- "elym",
23
- "gara",
24
- "hatr",
25
- "hebr",
26
- "hung",
27
- "khar",
28
- "lydi",
29
- "mand",
30
- "mani",
31
- "mend",
32
- "merc",
33
- "mero",
34
- "narb",
35
- "nbat",
36
- "nkoo",
37
- "orkh",
38
- "ougr",
39
- "palm",
40
- "phli",
41
- "phlp",
42
- "phnx",
43
- "prti",
44
- "rohg",
45
- "samr",
46
- "sarb",
47
- "sidt",
48
- "sogd",
49
- "sogo",
50
- "syrc",
51
- "syre",
52
- "syrj",
53
- "syrn",
54
- "thaa",
55
- "yezi"
56
- ]);
57
- var RTL_LANGUAGES = /* @__PURE__ */ new Set([
58
- "acm",
59
- "aeb",
60
- "aii",
61
- "ajp",
62
- "apc",
63
- "ar",
64
- "arc",
65
- "ars",
66
- "ary",
67
- "arz",
68
- "azb",
69
- "bqi",
70
- "ckb",
71
- "dv",
72
- "fa",
73
- "glk",
74
- "hbo",
75
- "he",
76
- "iw",
77
- "ji",
78
- "jrb",
79
- "khw",
80
- "lrc",
81
- "mzn",
82
- "nqo",
83
- "ota",
84
- "pnb",
85
- "prs",
86
- "ps",
87
- "sdh",
88
- "skr",
89
- "syc",
90
- "syr",
91
- "ur",
92
- "yi"
93
- ]);
94
- var RTL_BLOCKS = [
95
- [1424, 2303],
96
- [64285, 65023],
97
- [65136, 65279],
98
- [67584, 69631],
99
- [124928, 126975]
100
- ];
101
- var RTL_DIGITS = [
102
- [1984, 1993],
103
- [125127, 125135],
104
- [125264, 125273]
105
- ];
106
- var LETTER_RE = /^\p{L}$/u;
107
- var NUMBER_RE = /^\p{N}$/u;
108
- function within(point, ranges) {
109
- return ranges.some(([first, last]) => point >= first && point <= last);
110
- }
111
- function scriptSubtagOf(subtags) {
112
- if (subtags[0].length === 1) {
113
- return void 0;
114
- }
115
- let index = 1;
116
- while (index < subtags.length && index <= 3 && /^[a-z]{3}$/.test(subtags[index])) {
117
- index += 1;
118
- }
119
- const candidate = subtags[index];
120
- if (candidate === void 0 || !/^[a-z]{4}$/.test(candidate)) {
121
- return void 0;
122
- }
123
- return /^z/.test(candidate) || candidate >= "qaaa" && candidate <= "qabx" ? void 0 : candidate;
124
- }
125
- function localeDirectionOf(locale) {
126
- if (typeof locale !== "string") {
127
- return void 0;
128
- }
129
- const subtags = locale.toLowerCase().split(/[-_]/);
130
- const script = scriptSubtagOf(subtags);
131
- if (script !== void 0) {
132
- return RTL_SCRIPT_CODES.has(script) ? "rtl" : "ltr";
133
- }
134
- return RTL_LANGUAGES.has(subtags[0]) ? "rtl" : void 0;
135
- }
136
- var LEFT_TO_RIGHT_MARK = String.fromCodePoint(8206);
137
- var RIGHT_TO_LEFT_MARKS = /* @__PURE__ */ new Set([String.fromCodePoint(8207), String.fromCodePoint(1564)]);
138
- function textDirectionOf(text) {
139
- for (const character of text) {
140
- if (character === LEFT_TO_RIGHT_MARK) {
141
- return "ltr";
142
- }
143
- if (RIGHT_TO_LEFT_MARKS.has(character)) {
144
- return "rtl";
145
- }
146
- if (LETTER_RE.test(character)) {
147
- return within(character.codePointAt(0), RTL_BLOCKS) ? "rtl" : "ltr";
148
- }
149
- }
150
- return void 0;
151
- }
152
- function characterDirectionOf(character) {
153
- const point = character.codePointAt(0);
154
- if (NUMBER_RE.test(character)) {
155
- return within(point, RTL_DIGITS) ? "rtl" : "ltr";
156
- }
157
- if (LETTER_RE.test(character)) {
158
- return within(point, RTL_BLOCKS) ? "rtl" : "ltr";
159
- }
160
- return void 0;
161
- }
162
14
  var TEXT_CHANGED_DEBOUNCE_MS = 500;
163
15
  var VISUALLY_HIDDEN = {
164
16
  position: "absolute",
@@ -183,7 +35,7 @@ var HINT_SPACE_RE = new RegExp(
183
35
  );
184
36
  var VISIBLE_TEXT_RE = /[^\p{White_Space}\p{Cc}\p{Cf}\p{Default_Ignorable_Code_Point}]/u;
185
37
  var BULLET = "\u2022";
186
- var LEFT_TO_RIGHT_MARK2 = String.fromCodePoint(8206);
38
+ var LEFT_TO_RIGHT_MARK = String.fromCodePoint(8206);
187
39
  var RIGHT_TO_LEFT_MARK = String.fromCodePoint(8207);
188
40
  var EXTENDING_RE = new RegExp(
189
41
  `^[\\p{M}${String.fromCodePoint(8204, 8205, 3635, 3763)}${String.fromCodePoint(127995)}-${String.fromCodePoint(127999)}${String.fromCodePoint(917536)}-${String.fromCodePoint(917631)}${String.fromCodePoint(4448)}-${String.fromCodePoint(4607)}${String.fromCodePoint(55216)}-${String.fromCodePoint(55295)}]$`,
@@ -233,7 +85,7 @@ var LIGATING_ALEFS = new Set(
233
85
  )
234
86
  );
235
87
  var REGIONAL_INDICATOR_RE = /^[\u{1f1e6}-\u{1f1ff}]$/u;
236
- var LETTER_RE2 = /^\p{L}$/u;
88
+ var LETTER_RE = /^\p{L}$/u;
237
89
  var LETTER_WITH_REQUIRED_LIGATURES_RE = /(?![\p{Script=Latin}\p{Script=Greek}\p{Script=Cyrillic}])\p{L}/u;
238
90
  var DIGIT_RE = /^\p{Nd}$/u;
239
91
  var NUMBER_SIGN_RE = new RegExp(
@@ -316,7 +168,7 @@ function extendsCluster(before, shown) {
316
168
  if (EXTENDING_RE.test(shown)) {
317
169
  return true;
318
170
  }
319
- if (LETTER_RE2.test(shown)) {
171
+ if (LETTER_RE.test(shown)) {
320
172
  if (STACKING_VIRAMAS.has(previous) || PREPENDED.has(previous) || SUBJOINED_AFTER.get(shown)?.(before) === true) {
321
173
  return true;
322
174
  }
@@ -334,10 +186,10 @@ function characterOf(op) {
334
186
  }
335
187
  function isArabicLetter(character) {
336
188
  const point = character?.codePointAt(0);
337
- return point !== void 0 && LETTER_RE2.test(character) && ARABIC_LETTER_BLOCKS.some(([first, last]) => point >= first && point <= last);
189
+ return point !== void 0 && LETTER_RE.test(character) && ARABIC_LETTER_BLOCKS.some(([first, last]) => point >= first && point <= last);
338
190
  }
339
191
  function bulletDirections(ops, contentDir) {
340
- const own = ops.map((op) => characterDirectionOf(characterOf(op)));
192
+ const own = ops.map((op) => chunkOD65OZIW_cjs.characterDirectionOf(characterOf(op)));
341
193
  const before = [];
342
194
  const arabicBefore = [];
343
195
  let lastDirection;
@@ -346,7 +198,7 @@ function bulletDirections(ops, contentDir) {
346
198
  before[index] = lastDirection;
347
199
  arabicBefore[index] = lastLetterArabic;
348
200
  lastDirection = own[index] ?? lastDirection;
349
- if (LETTER_RE2.test(characterOf(op))) {
201
+ if (LETTER_RE.test(characterOf(op))) {
350
202
  lastLetterArabic = isArabicLetter(characterOf(op));
351
203
  }
352
204
  });
@@ -401,7 +253,7 @@ function clustersOf(ops, contentDir) {
401
253
  });
402
254
  const clusters = [];
403
255
  for (const group of groups) {
404
- const mark = group.bullet === void 0 ? "" : group.bullet === "rtl" ? RIGHT_TO_LEFT_MARK : LEFT_TO_RIGHT_MARK2;
256
+ const mark = group.bullet === void 0 ? "" : group.bullet === "rtl" ? RIGHT_TO_LEFT_MARK : LEFT_TO_RIGHT_MARK;
405
257
  const cluster = { op: clusterOpOf(group.ops), text: `${mark}${group.shown.join("")}${mark}` };
406
258
  const previous = clusters.at(-1);
407
259
  if (previous !== void 0 && previous.op === "equal" && cluster.op === "equal") {
@@ -460,10 +312,10 @@ function Dictation({
460
312
  }) {
461
313
  const isExam = renderMode === "exam";
462
314
  const isReview = renderMode === "review";
463
- const s = chunkMA7GXUWC_cjs.useLkStrings(strings);
315
+ const s = chunkLB3FEV7Z_cjs.useLkStrings(strings);
464
316
  const hasKey = typeof data.transcript === "string";
465
317
  const devError = react.useMemo(() => {
466
- if (!chunkK3EA547J_cjs.isDevelopment()) {
318
+ if (!chunkUSBANZ7K_cjs.isDevelopment()) {
467
319
  return null;
468
320
  }
469
321
  if (data.redacted === true) {
@@ -642,9 +494,9 @@ function Dictation({
642
494
  complete();
643
495
  const timeSpent = getTimeSpent();
644
496
  const xapiStatement = lkCore.xAPIBuilder.buildAnsweredStatement({
645
- actor: chunkK3EA547J_cjs.ANONYMOUS_ACTOR,
497
+ actor: chunkUSBANZ7K_cjs.ANONYMOUS_ACTOR,
646
498
  object: {
647
- id: chunkK3EA547J_cjs.objectIdFor(data.id),
499
+ id: chunkUSBANZ7K_cjs.objectIdFor(data.id),
648
500
  name: { [data.locale ?? "en-US"]: data.title },
649
501
  ...lkCore.xapiDefinitionFor(data)
650
502
  },
@@ -679,7 +531,7 @@ function Dictation({
679
531
  const given = isControlled ? value : defaultValue;
680
532
  const hasResponse = given !== void 0 && given.type === "dictation";
681
533
  const contentLang = typeof data.locale === "string" ? data.locale.replaceAll("_", "-") : void 0;
682
- const localeDir = localeDirectionOf(data.locale);
534
+ const localeDir = chunkOD65OZIW_cjs.localeDirectionOf(data.locale);
683
535
  const alignment = react.useMemo(
684
536
  () => revealing && transcript !== void 0 && (!isReview || hasResponse) ? lkCore.alignDictation(data, text) : null,
685
537
  [revealing, transcript, isReview, hasResponse, data, text]
@@ -694,7 +546,7 @@ function Dictation({
694
546
  );
695
547
  const words = alignment?.words ?? detailWords;
696
548
  const marksShown = revealing && words !== null;
697
- const contentDir = localeDir ?? textDirectionOf(transcript ?? words?.map((word) => word.reference).join(" ") ?? "");
549
+ const contentDir = localeDir ?? chunkOD65OZIW_cjs.textDirectionOf(transcript ?? words?.map((word) => word.reference).join(" ") ?? "");
698
550
  const nothingTyped = alignment !== null ? alignment.attempt === "" : words?.every((word) => word.attempt === "") ?? false;
699
551
  const passed = isReview ? outcome?.status === "scored" || outcome?.status === "graded" ? outcome.passed : void 0 : result?.passed;
700
552
  const reviewSummary = react.useMemo(() => {
@@ -747,7 +599,7 @@ function Dictation({
747
599
  data.media !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className: "lk-dc-recording", children: [
748
600
  /* @__PURE__ */ jsxRuntime.jsx("legend", { className: "lk-dc-recording-label", children: s.dictationRecording }),
749
601
  /* @__PURE__ */ jsxRuntime.jsx(
750
- chunkSBIJJ374_cjs.ActivityMedia,
602
+ chunkB2XQLU2E_cjs.ActivityMedia,
751
603
  {
752
604
  media: data.media,
753
605
  renderMode,
@@ -764,7 +616,7 @@ function Dictation({
764
616
  slowMedia !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className: "lk-dc-recording", "data-slow": "true", children: [
765
617
  /* @__PURE__ */ jsxRuntime.jsx("legend", { className: "lk-dc-recording-label", children: s.dictationSlowRecording }),
766
618
  /* @__PURE__ */ jsxRuntime.jsx(
767
- chunkSBIJJ374_cjs.ActivityMedia,
619
+ chunkB2XQLU2E_cjs.ActivityMedia,
768
620
  {
769
621
  media: slowMedia,
770
622
  renderMode,
@@ -898,16 +750,16 @@ function Dictation({
898
750
  ) : null
899
751
  ] }) : null
900
752
  ] }) : null,
901
- /* @__PURE__ */ jsxRuntime.jsx(chunkK3EA547J_cjs.FeedbackRegion, { id: `${data.id}-feedback`, children: /* @__PURE__ */ jsxRuntime.jsx(AnnouncementText, { announcement: isReview ? reviewSummary : summary }) })
753
+ /* @__PURE__ */ jsxRuntime.jsx(chunkBRPEB43C_cjs.FeedbackRegion, { id: `${data.id}-feedback`, children: /* @__PURE__ */ jsxRuntime.jsx(AnnouncementText, { announcement: isReview ? reviewSummary : summary }) })
902
754
  ]
903
755
  }
904
756
  );
905
757
  }
906
758
  function Dictation2(props) {
907
- const strings = chunkMA7GXUWC_cjs.useLkStrings(props.strings);
908
- return /* @__PURE__ */ jsxRuntime.jsx(chunkK3EA547J_cjs.ActivityErrorBoundary, { activityTitle: props.data?.title, strings, children: /* @__PURE__ */ jsxRuntime.jsx(Dictation, { ...props }) });
759
+ const strings = chunkLB3FEV7Z_cjs.useLkStrings(props.strings);
760
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkUSBANZ7K_cjs.ActivityErrorBoundary, { activityTitle: props.data?.title, strings, children: /* @__PURE__ */ jsxRuntime.jsx(Dictation, { ...props }) });
909
761
  }
910
762
 
911
763
  exports.Dictation = Dictation2;
912
- //# sourceMappingURL=chunk-J73TDY7J.cjs.map
913
- //# sourceMappingURL=chunk-J73TDY7J.cjs.map
764
+ //# sourceMappingURL=chunk-WTS34S5E.cjs.map
765
+ //# sourceMappingURL=chunk-WTS34S5E.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Dictation/Dictation.tsx","../src/components/Dictation/index.tsx"],"names":["characterDirectionOf","jsx","jsxs","Fragment","useLkStrings","useMemo","isDevelopment","assertRedacted","result","validateActivity","ActivitySchemaError","useActivityState","useState","useRef","useEffect","useId","score","xAPIBuilder","ANONYMOUS_ACTOR","objectIdFor","xapiDefinitionFor","localeDirectionOf","alignDictation","diffDictationChars","textDirectionOf","ActivityMedia","DICTATION_MAX_TEXT_LENGTH","FeedbackRegion","Dictation","ActivityErrorBoundary"],"mappings":"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","file":"chunk-WTS34S5E.cjs","sourcesContent":["'use client';\n\nimport {\n type ActivityMedia as ActivityMediaData,\n ActivitySchemaError,\n alignDictation,\n assertRedacted,\n DICTATION_MAX_TEXT_LENGTH,\n type DictationAlignment,\n type DictationCharOp,\n type DictationData,\n type DictationLearnerResponse,\n type DictationWordAlignment,\n diffDictationChars,\n type LearnerResponse,\n type MediaPlaybackPolicy,\n type ScoringDetail,\n type ScoringResult,\n score,\n validateActivity,\n xAPIBuilder,\n xapiDefinitionFor,\n} from '@intellectif/lk-core';\nimport { type CSSProperties, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { useActivityState } from '../../hooks/useActivityState.js';\nimport { characterDirectionOf, localeDirectionOf, textDirectionOf } from '../../i18n/direction.js';\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport { ANONYMOUS_ACTOR, isDevelopment, objectIdFor } from '../_internal.js';\nimport { ActivityMedia } from '../shared/ActivityMedia.js';\nimport { FeedbackRegion } from '../shared/FeedbackRegion.js';\nimport type { ActivityProps, Renderable } from '../types.js';\n\n// Nothing shuffles and nothing is seeded, so the shared contract is the whole\n// contract. Kept as an interface so a later prop lands here, not in a union.\nexport interface DictationProps extends ActivityProps<DictationData> {}\n\n/** How long the learner has to stop typing before one `text-changed` is emitted. */\nconst TEXT_CHANGED_DEBOUNCE_MS = 500;\n\n/**\n * Present for assistive technology, invisible on screen. Inline rather than\n * left to the optional skin: the per-word sentences are the marks' only\n * channel for a screen reader, and without this a page that does not load the\n * skin would show every one of them beside its word.\n */\nconst VISUALLY_HIDDEN: CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n whiteSpace: 'nowrap',\n border: 0,\n};\n\n/**\n * Names playback groups. Per mount and never derived from `useId`: two\n * separately hydrated roots derive the same id for the same tree position, and\n * their recordings would pause each other. The name never reaches the DOM.\n */\nlet recordingsGroupCount = 0;\n\n/**\n * A token with nothing spelled in it, as the scorer reads it once composed:\n * only punctuation, control, format and default-ignorable characters, the acute\n * accent, grave accent (and its fullwidth form) and modifier apostrophe the\n * scorer folds into an apostrophe, and the Arabic tatweel and N'Ko lajanyalan\n * it removes.\n */\nconst UNSPELLED_RE = new RegExp(\n `^[\\\\p{P}\\\\p{Cc}\\\\p{Cf}\\\\p{Default_Ignorable_Code_Point}${String.fromCodePoint(0xb4, 0x60, 0xff40, 0x2bc, 0x640, 0x7fa)}]*$`,\n 'u',\n);\n/**\n * Spacing as the scorer reads it: whitespace and NEXT LINE — but not the\n * byte-order mark, which JavaScript counts as whitespace and the scorer\n * removes as a format character, joining the letters on either side.\n */\nconst HINT_SPACE_RE = new RegExp(\n `(?:(?!${String.fromCodePoint(0xfeff)})\\\\s|${String.fromCodePoint(0x85)})+`,\n 'u',\n);\n/** A title with something in it a screen reader can say. */\nconst VISIBLE_TEXT_RE = /[^\\p{White_Space}\\p{Cc}\\p{Cf}\\p{Default_Ignorable_Code_Point}]/u;\n\nconst BULLET = '•';\nconst LEFT_TO_RIGHT_MARK = String.fromCodePoint(0x200e);\nconst RIGHT_TO_LEFT_MARK = String.fromCodePoint(0x200f);\n/**\n * Code points a font draws onto the character before them rather than beside\n * it — combining marks (variation selectors among them), the joiners, emoji\n * skin tones, tag characters, the vowel and final jamo of an old Hangul\n * syllable, and the Thai and Lao SARA AM, whose ring the font sets on the\n * consonant before — so their own span can have no width to decorate.\n */\nconst EXTENDING_RE = new RegExp(\n `^[\\\\p{M}${String.fromCodePoint(0x200c, 0x200d, 0xe33, 0xeb3)}${String.fromCodePoint(0x1f3fb)}-${String.fromCodePoint(0x1f3ff)}${String.fromCodePoint(0xe0020)}-${String.fromCodePoint(0xe007f)}${String.fromCodePoint(0x1160)}-${String.fromCodePoint(0x11ff)}${String.fromCodePoint(0xd7b0)}-${String.fromCodePoint(0xd7ff)}]$`,\n 'u',\n);\n/**\n * Viramas that stack the letter after them into one glyph without asking —\n * Devanagari, Bengali, Gujarati, Oriya, Telugu, Kannada and Malayalam, the\n * Burmese stacker, the Khmer coeng, and the Tai Tham, Balinese, Javanese,\n * Chakma and Brahmi signs. Not the Tamil, Gurmukhi or Sinhala virama, which is\n * drawn visibly and leaves most letters after it on their own.\n */\nconst STACKING_VIRAMAS = new Set(\n [\n 0x94d, 0x9cd, 0xacd, 0xb4d, 0xc4d, 0xccd, 0xd4d, 0x1039, 0x17d2, 0x1a60, 0x1b44, 0xa9c0,\n 0x11046, 0x11133,\n ].map((point) => String.fromCodePoint(point)),\n);\n/**\n * The letters a visible virama still draws into the letter before it: the\n * Gurmukhi RA, YA and VA, which fonts set under the consonant, and the Tamil\n * conjuncts KSSA (க்ஷ) and SHRII (ஸ்ரீ), which fonts draw as one glyph —\n * each keyed by its letter, virama and the letter before the virama.\n */\nconst SUBJOINED_AFTER = new Map<string, (before: readonly string[]) => boolean>([\n ...[0xa30, 0xa2f, 0xa35].map(\n (point) =>\n [\n String.fromCodePoint(point),\n (before: readonly string[]) => before.at(-1) === String.fromCodePoint(0xa4d),\n ] as const,\n ),\n [\n String.fromCodePoint(0xbb7),\n (before: readonly string[]) =>\n before.at(-1) === String.fromCodePoint(0xbcd) &&\n before.at(-2) === String.fromCodePoint(0xb95),\n ],\n [\n String.fromCodePoint(0xbb0),\n (before: readonly string[]) =>\n before.at(-1) === String.fromCodePoint(0xbcd) &&\n before.at(-2) === String.fromCodePoint(0xbb8),\n ],\n]);\n/** Viramas after which a zero-width joiner asks for a conjunct: every stacking one, and the Sinhala. */\nconst JOINABLE_VIRAMAS = new Set([...STACKING_VIRAMAS, String.fromCodePoint(0xdca)]);\nconst ZERO_WIDTH_JOINER = String.fromCodePoint(0x200d);\n/**\n * Characters the font draws into the letter after them: MALAYALAM LETTER DOT\n * REPH, set on the consonant after it, and the MONGOLIAN VOWEL SEPARATOR, which\n * has no width of its own and changes the shape of the vowel after it.\n */\nconst PREPENDED = new Set([String.fromCodePoint(0xd4e), String.fromCodePoint(0x180e)]);\nconst ARABIC_LAM = String.fromCodePoint(0x644);\n/** The alefs a lam before them fuses with into one glyph, in every Arabic font. */\nconst LIGATING_ALEFS = new Set(\n [0x622, 0x623, 0x625, 0x627, 0x671, 0x672, 0x673, 0x675].map((point) =>\n String.fromCodePoint(point),\n ),\n);\nconst REGIONAL_INDICATOR_RE = /^[\\u{1f1e6}-\\u{1f1ff}]$/u;\nconst LETTER_RE = /^\\p{L}$/u;\n/** A letter of any script but Latin, Greek or Cyrillic, whose common ligatures are only decorative. */\nconst LETTER_WITH_REQUIRED_LIGATURES_RE =\n /(?![\\p{Script=Latin}\\p{Script=Greek}\\p{Script=Cyrillic}])\\p{L}/u;\nconst DIGIT_RE = /^\\p{Nd}$/u;\n/**\n * Signs laid out with the European number beside them (bidirectional class\n * ET): the currency signs, the degree, plus-minus and per-mille signs.\n */\nconst NUMBER_SIGN_RE = new RegExp(\n `^[\\\\p{Sc}${String.fromCodePoint(0xb0, 0xb1, 0x2030, 0x2031, 0x212e, 0x2213)}]$`,\n 'u',\n);\n/** Letters of the Arabic, Syriac and Thaana blocks and their presentation forms: before them, a European number is not one. */\nconst ARABIC_LETTER_BLOCKS: readonly (readonly [number, number])[] = [\n [0x0600, 0x07bf],\n [0x0860, 0x08ff],\n [0xfb50, 0xfdff],\n [0xfe70, 0xfeff],\n];\n\n/**\n * The text out of a `LearnerResponse`. A response of another activity type\n * reads as nothing typed rather than throwing — a controlled host that has not\n * yet swapped its state on an activity change would otherwise crash the attempt.\n */\nfunction textOf(response: LearnerResponse | undefined): string {\n return response !== undefined && response.type === 'dictation' ? response.text : '';\n}\n\n/** The hint count out of a `LearnerResponse`; absent or another type reads as none. */\nfunction hintsOf(response: LearnerResponse | undefined): number {\n if (response === undefined || response.type !== 'dictation') {\n return 0;\n }\n const revealed = response.hintsRevealed;\n return typeof revealed === 'number' && Number.isInteger(revealed) && revealed > 0 ? revealed : 0;\n}\n\n/** The response this component emits; `hintsRevealed` is written only when there is one. */\nfunction responseOf(text: string, hintsRevealed: number): DictationLearnerResponse {\n return { type: 'dictation', text, ...(hintsRevealed > 0 ? { hintsRevealed } : {}) };\n}\n\n/**\n * The slower recording as an `ActivityMedia`: it follows the recording's\n * playback policy minus `maxPlays` (`controls`, `seek`, `rate`, the native\n * hints), so a locked scrubber or a fixed speed binds both files — and it never\n * carries a budget of its own, so `<ActivityMedia>` never demands a binding\n * for it. `undefined` when there is no slow recording.\n */\nfunction slowMediaFor(\n data: Renderable<DictationData>,\n label: string,\n): ActivityMediaData | undefined {\n const slow = data.slowMedia;\n if (slow === undefined) {\n return undefined;\n }\n const policy: MediaPlaybackPolicy = data.media?.playback ?? {};\n const { maxPlays: _budget, ...inherited } = policy;\n const hasPolicy = Object.values(inherited).some((value) => value !== undefined);\n return {\n type: 'audio',\n url: slow.url,\n alt: slow.alt ?? label,\n ...(hasPolicy ? { playback: inherited } : {}),\n };\n}\n\n/**\n * The transcript's words as a learner would read them: raw, in order, split at\n * whitespace. A token with nothing in it that is spelled — a dash, an ellipsis\n * — is joined to the word before it (or to the first word, when it leads), so\n * every reveal shows a word. A script written without spaces is one token, so\n * one reveal shows the whole sentence.\n */\nfunction hintWordsOf(transcript: string): string[] {\n const words: string[] = [];\n let leading = '';\n for (const token of transcript.split(HINT_SPACE_RE)) {\n if (token === '') {\n continue;\n }\n const last = words.length - 1;\n // Composed first: the Greek varia and oxia decompose to the grave and acute\n // accents, which the scorer folds into an apostrophe and removes.\n if (!UNSPELLED_RE.test(token.normalize('NFC'))) {\n words.push(leading === '' ? token : `${leading} ${token}`);\n leading = '';\n } else if (last >= 0) {\n words[last] = `${words[last]} ${token}`;\n } else {\n leading = leading === '' ? token : `${leading} ${token}`;\n }\n }\n return words;\n}\n\n/**\n * Word marks rebuilt from stored scoring details — a server-recorded mark\n * shown after an exam, with no transcript on the client. Extras are not in the\n * details (the scorer writes one per transcript word), so none appear.\n */\nfunction wordsFromDetails(details: readonly ScoringDetail[]): DictationWordAlignment[] | null {\n if (details.length === 0 || !details.every((detail) => /^w\\d+$/.test(detail.itemId))) {\n return null;\n }\n return details.map((detail) => {\n const attempt = Array.isArray(detail.learnerResponse)\n ? detail.learnerResponse.join(' ')\n : detail.learnerResponse;\n const reference = Array.isArray(detail.correctResponse)\n ? detail.correctResponse.join(' ')\n : detail.correctResponse;\n const correct = detail.outcome !== undefined ? detail.outcome === 'correct' : detail.correct;\n const missing = detail.outcome === 'incorrect-omission' || (!correct && attempt === '');\n return {\n itemId: detail.itemId,\n reference,\n attempt,\n similarity: detail.score ?? (correct ? 1 : 0),\n status: correct ? 'correct' : missing ? 'missing' : 'incorrect',\n };\n });\n}\n\n/** A run of character operations drawn as one glyph cluster, and how it is marked. */\ninterface MarkedCluster {\n op: DictationCharOp['op'];\n text: string;\n}\n\n/**\n * Whether `shown`, the character an operation displays, is drawn into the\n * cluster whose characters so far are `before`: a mark, a joiner or a skin tone\n * onto its base, a letter stacked under a virama, an alef fused with the lam\n * before it, the second half of a flag.\n */\nfunction extendsCluster(before: readonly string[], shown: string): boolean {\n const previous = before.at(-1) as string;\n if (EXTENDING_RE.test(shown)) {\n return true;\n }\n if (LETTER_RE.test(shown)) {\n if (\n STACKING_VIRAMAS.has(previous) ||\n PREPENDED.has(previous) ||\n SUBJOINED_AFTER.get(shown)?.(before) === true\n ) {\n return true;\n }\n if (previous === ZERO_WIDTH_JOINER && JOINABLE_VIRAMAS.has(before.at(-2) as string)) {\n return true;\n }\n }\n if (previous === ARABIC_LAM && LIGATING_ALEFS.has(shown)) {\n return true;\n }\n return (\n REGIONAL_INDICATOR_RE.test(shown) &&\n before.length % 2 === 1 &&\n before.every((character) => REGIONAL_INDICATOR_RE.test(character))\n );\n}\n\n/** The character an operation stands for: what should have been typed, or what was typed in excess. */\nfunction characterOf(op: DictationCharOp): string {\n return op.reference === '' ? op.attempt : op.reference;\n}\n\nfunction isArabicLetter(character: string | undefined): boolean {\n const point = character?.codePointAt(0);\n return (\n point !== undefined &&\n LETTER_RE.test(character as string) &&\n ARABIC_LETTER_BLOCKS.some(([first, last]) => point >= first && point <= last)\n );\n}\n\n/**\n * The directions missing characters' bullets are laid out in, by operation\n * index, worked out in two passes over the operations rather than a search\n * per bullet: a word of 2,000 emoji missing its letters took seconds to draw.\n *\n * A bullet takes the character's own direction when it has one — a digit runs\n * left to right, unless it is a digit of a right-to-left script. A currency,\n * degree or per-mille sign beside a digit is laid out with that number, left to\n * right, unless an Arabic letter comes before it, after which the number is not\n * a European one. Otherwise, for a space or a punctuation mark, it takes the\n * direction of the characters on both sides when they agree, and the content's\n * when they do not. A bare bullet is a neutral, which the bidirectional\n * algorithm would otherwise attach to the wrong side of a number or a word of\n * the other direction.\n */\nexport function bulletDirections(\n ops: readonly DictationCharOp[],\n contentDir: 'ltr' | 'rtl' | undefined,\n): Map<number, 'ltr' | 'rtl' | undefined> {\n const own = ops.map((op) => characterDirectionOf(characterOf(op)));\n const before: ('ltr' | 'rtl' | undefined)[] = [];\n const arabicBefore: boolean[] = [];\n let lastDirection: 'ltr' | 'rtl' | undefined;\n let lastLetterArabic = false;\n ops.forEach((op, index) => {\n before[index] = lastDirection;\n arabicBefore[index] = lastLetterArabic;\n lastDirection = own[index] ?? lastDirection;\n if (LETTER_RE.test(characterOf(op))) {\n lastLetterArabic = isArabicLetter(characterOf(op));\n }\n });\n const after: ('ltr' | 'rtl' | undefined)[] = [];\n let nextDirection: 'ltr' | 'rtl' | undefined;\n for (let index = ops.length - 1; index >= 0; index -= 1) {\n after[index] = nextDirection;\n nextDirection = own[index] ?? nextDirection;\n }\n const directions = new Map<number, 'ltr' | 'rtl' | undefined>();\n ops.forEach((op, index) => {\n if (op.op !== 'missing') {\n return;\n }\n const neighbourIsDigit = [ops[index - 1], ops[index + 1]].some(\n (neighbour) => neighbour !== undefined && DIGIT_RE.test(characterOf(neighbour)),\n );\n directions.set(\n index,\n own[index] ??\n (NUMBER_SIGN_RE.test(characterOf(op)) && neighbourIsDigit && !arabicBefore[index]\n ? 'ltr'\n : before[index] !== undefined && before[index] === after[index]\n ? before[index]\n : (contentDir ?? before[index] ?? after[index])),\n );\n });\n return directions;\n}\n\n/**\n * How a cluster is marked. One led by a missing character's bullet is missing,\n * whatever marks sit on the bullet: the character they belong to is not there.\n * Otherwise a cluster is marked as its wrong operations are when they agree —\n * a correct letter with an extra mark is `extra` — and as a substitution when\n * they do not.\n */\nfunction clusterOpOf(ops: readonly DictationCharOp[]): DictationCharOp['op'] {\n if ((ops[0] as DictationCharOp).op === 'missing') {\n return 'missing';\n }\n const wrong = new Set(ops.map((op) => op.op).filter((kind) => kind !== 'equal'));\n if (wrong.size === 0) {\n return 'equal';\n }\n return wrong.size === 1 ? ([...wrong][0] as DictationCharOp['op']) : 'substitute';\n}\n\n/**\n * Character operations grouped into what is drawn as one cluster, so a wrong\n * combining mark, joiner or stacked letter marks the glyph it is drawn into —\n * alone, its span has no width, and its underline or strike would not be\n * painted at all. A missing character's bullet carries only the marks drawn\n * onto it, never a letter that is drawn apart. A missing character's bullet is\n * wrapped in the direction mark of the character it stands for. Consecutive\n * correct clusters are one run: an engine that shapes each element on its own\n * would otherwise draw a correctly typed conjunct or a joined Mongolian word\n * broken apart.\n */\nfunction clustersOf(\n ops: readonly DictationCharOp[],\n contentDir: 'ltr' | 'rtl' | undefined,\n): MarkedCluster[] {\n const bullets = bulletDirections(ops, contentDir);\n const groups: { ops: DictationCharOp[]; shown: string[]; bullet?: 'ltr' | 'rtl' }[] = [];\n ops.forEach((op, index) => {\n const shown = op.op === 'missing' ? BULLET : op.attempt;\n const current = groups.at(-1);\n if (\n current !== undefined &&\n op.op !== 'missing' &&\n ((current.ops[0] as DictationCharOp).op === 'missing'\n ? EXTENDING_RE.test(shown)\n : extendsCluster(current.shown, shown))\n ) {\n current.ops.push(op);\n current.shown.push(shown);\n return;\n }\n const direction = bullets.get(index);\n groups.push({\n ops: [op],\n shown: [shown],\n ...(direction !== undefined ? { bullet: direction } : {}),\n });\n });\n const clusters: MarkedCluster[] = [];\n for (const group of groups) {\n const mark =\n group.bullet === undefined\n ? ''\n : group.bullet === 'rtl'\n ? RIGHT_TO_LEFT_MARK\n : LEFT_TO_RIGHT_MARK;\n const cluster = { op: clusterOpOf(group.ops), text: `${mark}${group.shown.join('')}${mark}` };\n const previous = clusters.at(-1);\n if (previous !== undefined && previous.op === 'equal' && cluster.op === 'equal') {\n previous.text += cluster.text;\n } else {\n clusters.push(cluster);\n }\n }\n return clusters;\n}\n\n/**\n * Character-level edit operations as decoration. Hidden from assistive\n * technology as a whole: a screen reader must never verbalise surrogate or\n * combining fragments one by one, and the word list already carries the\n * meaning. Sighted colour-blind and forced-colors users still get one\n * decoration per state, which the skin draws and the legend explains.\n */\nfunction CharOps({\n ops,\n contentDir,\n}: {\n ops: readonly DictationCharOp[];\n contentDir: 'ltr' | 'rtl' | undefined;\n}) {\n return clustersOf(ops, contentDir).map((cluster, index) => (\n <span\n // biome-ignore lint/suspicious/noArrayIndexKey: clusters are positional and recomputed whole\n key={index}\n className=\"lk-dc-op\"\n data-op={cluster.op}\n // A run with no letter whose script needs its common ligatures: the skin\n // turns them off there, so a font's \"fi\" cannot draw a wrong \"i\" into one glyph.\n {...(LETTER_WITH_REQUIRED_LIGATURES_RE.test(cluster.text)\n ? {}\n : { 'data-ligatures': 'decorative' })}\n aria-hidden=\"true\"\n >\n {cluster.text}\n </span>\n ));\n}\n\n/** What the live region says: the SDK's own sentences, then any authored feedback. */\ninterface Announcement {\n text: string;\n feedback: string | null;\n}\n\n/**\n * The announcement, with authored feedback in its own isolated span: its\n * direction is its own, so an English \"Well heard.\" in an Arabic interface\n * keeps its full stop at its end. Its language is not guessed — feedback may be\n * written in the interface's language or the dictation's.\n */\nfunction AnnouncementText({ announcement }: { announcement: Announcement | null }) {\n if (announcement === null) {\n return null;\n }\n return (\n <>\n {announcement.text}\n {announcement.feedback ? (\n <>\n {' '}\n <span dir=\"auto\">{announcement.feedback}</span>\n </>\n ) : null}\n </>\n );\n}\n\nexport function Dictation({\n data,\n onComplete,\n onSubmit,\n onChange,\n onInteraction,\n value,\n defaultValue,\n defaultSubmitted,\n renderMode = 'practice',\n outcome,\n mediaBudget,\n mediaStrings,\n strings,\n theme,\n locale,\n disabled,\n}: DictationProps) {\n const isExam = renderMode === 'exam';\n const isReview = renderMode === 'review';\n const s = useLkStrings(strings);\n\n // Whether the payload carries the transcript at all — the KEY, not the\n // `redacted` marker. `redact(data, { reveal: 'after-submit' })` stamps\n // `redacted: true` on a projection that still has its transcript, and that\n // projection is exactly what a review screen hands this component. A type\n // test only: no content is read here, and none is read in `exam` below.\n const hasKey = typeof (data as { transcript?: unknown }).transcript === 'string';\n\n const devError = useMemo(() => {\n if (!isDevelopment()) {\n return null;\n }\n if (data.redacted === true) {\n if (hasKey) {\n // An after-submit projection: the strict redacted schema has no\n // `transcript`, so `assertRedacted` would throw on the one payload\n // this component exists to render in review. Check the public subset.\n const shape = data as { type?: unknown; id?: unknown; title?: unknown };\n return shape.type === 'dictation' &&\n typeof shape.id === 'string' &&\n typeof shape.title === 'string'\n ? null\n : new Error(\n 'Dictation received a revealed projection (redacted: true with a transcript) that ' +\n 'is not a dictation: `type`, `id` and `title` are required.',\n );\n }\n try {\n assertRedacted(data);\n return null;\n } catch (error) {\n return error instanceof Error ? error : new Error(String(error));\n }\n }\n const result = validateActivity('dictation', data);\n return result.success ? null : new ActivitySchemaError('dictation', result.errors);\n }, [data, hasKey]);\n\n const { state, start, complete, getTimeSpent, reset } = useActivityState(\n defaultSubmitted === true ? 'completed' : 'idle',\n );\n const isControlled = value !== undefined;\n const [internalText, setInternalText] = useState<string>(() => textOf(defaultValue));\n const [internalRevealed, setInternalRevealed] = useState<number>(() => hintsOf(defaultValue));\n const [result, setResult] = useState<ScoringResult | null>(null);\n const [summary, setSummary] = useState<Announcement | null>(null);\n const [solutionShown, setSolutionShown] = useState(false);\n\n const text = isControlled ? textOf(value) : internalText;\n const revealed = isControlled ? hintsOf(value) : internalRevealed;\n\n const defaultValueRef = useRef(defaultValue);\n useEffect(() => {\n defaultValueRef.current = defaultValue;\n }, [defaultValue]);\n\n const defaultSubmittedRef = useRef(defaultSubmitted);\n useEffect(() => {\n defaultSubmittedRef.current = defaultSubmitted;\n }, [defaultSubmitted]);\n\n // Identity-guarded so the mount run is a no-op: without it this fires after\n // the first paint and undoes every seed it was just given (Req 3.7).\n const lastDataRef = useRef(data);\n useEffect(() => {\n if (lastDataRef.current === data) {\n return;\n }\n lastDataRef.current = data;\n setInternalText(textOf(defaultValueRef.current));\n setInternalRevealed(hintsOf(defaultValueRef.current));\n setResult(null);\n setSummary(null);\n setSolutionShown(false);\n reset(defaultSubmittedRef.current === true ? 'completed' : 'idle');\n }, [data, reset]);\n\n // `text-changed` is debounced so an autosaving host is not told about every\n // keystroke; only the length travels, never the text.\n const textChangedRef = useRef<{ timer: ReturnType<typeof setTimeout>; length: number } | null>(\n null,\n );\n useEffect(\n () => () => {\n if (textChangedRef.current !== null) {\n clearTimeout(textChangedRef.current.timer);\n }\n },\n [],\n );\n\n const revealButtonRef = useRef<HTMLButtonElement>(null);\n const ids = useId();\n const hintId = `${ids}-hint`;\n const titleId = `${ids}-title`;\n const solutionId = `${ids}-solution`;\n // Per mount, not per activity id: two renderings of one item on a page (a\n // review list of several attempts, a preview beside a sequence) are\n // separate players, and neither should pause the other's recordings.\n const [recordingsGroup] = useState(() => {\n recordingsGroupCount += 1;\n return `lk-dc-recordings-${recordingsGroupCount}`;\n });\n\n const slowMedia = useMemo(\n () => slowMediaFor(data, s.dictationSlowRecording),\n [data, s.dictationSlowRecording],\n );\n\n // All hooks are called before these throws, so hook order stays stable.\n if (devError) {\n throw devError;\n }\n // Practice grades locally, and a redacted projection has no answer key to\n // grade against — `score()` would throw RedactedScoringError from the submit\n // handler, where no error boundary can reach it and after the learner has\n // typed. Fail at render instead, in production too, as every built-in does.\n if (data.redacted === true && renderMode === 'practice') {\n throw new Error(\n `Dictation \"${data.id}\" received redacted activity data in renderMode \"practice\", ` +\n 'which grades locally and has no answer key to grade against. ' +\n 'Render redacted data with renderMode=\"exam\" (server grades) or \"review\" (pass `outcome`).',\n );\n }\n\n const submitted = state === 'completed';\n const inactive = disabled === true || submitted || isReview;\n\n /**\n * Whether answer-key-derived information may be shown. Never in `exam`; in\n * `practice` only once this component has scored; in `review` only once the\n * caller supplies a SCORED outcome.\n */\n const revealing = isReview ? outcome?.status === 'scored' : !isExam && submitted;\n\n // The transcript, read only outside `exam`. `Renderable` says it is a\n // string; a plain redacted projection has none, so it is read defensively\n // and every consumer of it goes through `alignDictation`'s own guards.\n const transcript: string | undefined =\n isExam || !hasKey ? undefined : (data as { transcript: string }).transcript;\n\n // Hints exist only where the transcript does and nothing has been graded:\n // practice, before submit. A plain redacted projection has no words to give.\n const hintWords = useMemo(\n () => (transcript === undefined ? [] : hintWordsOf(transcript)),\n [transcript],\n );\n const hintsOffered =\n data.hints?.mode === 'progressive-words' && !isExam && !isReview && transcript !== undefined;\n const hintsEnabled = hintsOffered && !submitted;\n const hintTotal = hintWords.length;\n const hintsShown = Math.min(revealed, hintTotal);\n // What a response reports: the words actually shown, and none where no hint\n // can be — whatever count a seeded or controlled value carries.\n const reportedHints = hintsOffered ? hintsShown : 0;\n\n const fireInteraction = (\n type: 'text-changed' | 'hint-requested' | 'submitted',\n payload: Record<string, unknown>,\n ): void => {\n onInteraction?.({ type, activityId: data.id, timestamp: Date.now(), payload });\n };\n\n const flushTextChanged = (): void => {\n const pending = textChangedRef.current;\n if (pending === null) {\n return;\n }\n clearTimeout(pending.timer);\n textChangedRef.current = null;\n fireInteraction('text-changed', { length: pending.length });\n };\n\n const handleTextChange = (next: string): void => {\n if (inactive) {\n return;\n }\n if (state === 'idle') {\n start();\n }\n if (!isControlled) {\n setInternalText(next);\n }\n onChange?.(responseOf(next, reportedHints));\n if (onInteraction === undefined) {\n return;\n }\n if (textChangedRef.current !== null) {\n clearTimeout(textChangedRef.current.timer);\n }\n textChangedRef.current = {\n length: next.length,\n timer: setTimeout(() => {\n const pending = textChangedRef.current;\n textChangedRef.current = null;\n if (pending !== null) {\n fireInteraction('text-changed', { length: pending.length });\n }\n }, TEXT_CHANGED_DEBOUNCE_MS),\n };\n };\n\n const setRevealed = (next: number): void => {\n if (!isControlled) {\n setInternalRevealed(next);\n }\n onChange?.(responseOf(text, next));\n };\n\n const revealNextHint = (): void => {\n if (inactive || hintsShown >= hintTotal) {\n return;\n }\n if (state === 'idle') {\n start();\n }\n const next = hintsShown + 1;\n setRevealed(next);\n fireInteraction('hint-requested', { revealed: next, total: hintTotal });\n };\n\n const resetHints = (): void => {\n if (inactive || hintsShown === 0) {\n return;\n }\n // The reset button leaves the page once nothing is revealed; hand focus to\n // the reveal button first, or the keyboard user lands on the page body.\n revealButtonRef.current?.focus();\n setRevealed(0);\n };\n\n const handleSubmit = (event: React.FormEvent): void => {\n event.preventDefault();\n if (inactive) {\n return;\n }\n const response = responseOf(text, reportedHints);\n onSubmit?.(response);\n flushTextChanged();\n\n if (isExam) {\n // The client neither grades nor reveals: no score(), no read of the\n // transcript, no onComplete, and no xAPI statement — its\n // correctResponsesPattern IS the answer key.\n complete();\n setSummary({ text: s.answerSubmitted, feedback: null });\n fireInteraction('submitted', { length: text.length, hintsRevealed: reportedHints });\n return;\n }\n\n const scoringResult = score('dictation', data as DictationData, response);\n complete();\n const timeSpent = getTimeSpent();\n const xapiStatement = xAPIBuilder.buildAnsweredStatement({\n actor: ANONYMOUS_ACTOR,\n object: {\n id: objectIdFor(data.id),\n name: { [data.locale ?? 'en-US']: data.title },\n ...xapiDefinitionFor(data),\n },\n scoringResult,\n timeSpentMs: timeSpent,\n response: response.text,\n });\n setResult(scoringResult);\n onComplete?.({\n score: scoringResult.score,\n maxScore: scoringResult.maxScore,\n passed: scoringResult.passed,\n timeSpent,\n xapiStatement,\n });\n const correctWords = scoringResult.details.filter(\n (detail) => (detail.outcome ?? (detail.correct ? 'correct' : 'incorrect')) === 'correct',\n ).length;\n setSummary({\n text: `${s.answerSubmitted} ${s.scoreAnnouncement(\n Math.round(scoringResult.score * 100),\n scoringResult.passed,\n )} ${s.dictationWordsSummary(correctWords, scoringResult.details.length)}`,\n feedback: scoringResult.feedback,\n });\n fireInteraction('submitted', {\n length: text.length,\n hintsRevealed: reportedHints,\n score: scoringResult.score,\n });\n };\n\n // A review may hold the key but not the learner's text — an outcome recorded\n // without its response. Recomputing from an empty box would contradict the\n // stored score, so the stored details are the record then.\n const given = isControlled ? value : defaultValue;\n const hasResponse = given !== undefined && given.type === 'dictation';\n // The dictation's language, and the direction its tag names when it names\n // one. Read defensively: stale data may carry a locale that is not a string.\n // A tag written with underscores reads as its hyphenated form, the only one `lang` accepts.\n const contentLang =\n typeof data.locale === 'string' ? data.locale.replaceAll('_', '-') : undefined;\n const localeDir = localeDirectionOf(data.locale);\n\n // The same comparison the scorer made — computed only when it may be shown.\n // The character diff is UI-only and needs memory proportional to the product\n // of the two lengths, so it lives here and nowhere near `score()`.\n const alignment = useMemo<DictationAlignment | null>(\n () =>\n revealing && transcript !== undefined && (!isReview || hasResponse)\n ? alignDictation(data, text)\n : null,\n [revealing, transcript, isReview, hasResponse, data, text],\n );\n const sentenceDiff = useMemo<DictationCharOp[] | null>(\n () =>\n alignment !== null && alignment.attempt !== ''\n ? diffDictationChars(alignment.reference, alignment.attempt)\n : null,\n [alignment],\n );\n\n // Review with no transcript on the client, or no response to recompute from:\n // a server-recorded mark still renders its word list from the stored details.\n const detailWords = useMemo<DictationWordAlignment[] | null>(\n () =>\n isReview && alignment === null && outcome?.status === 'scored'\n ? wordsFromDetails(outcome.details)\n : null,\n [isReview, alignment, outcome],\n );\n\n const words: DictationWordAlignment[] | null = alignment?.words ?? detailWords;\n const marksShown = revealing && words !== null;\n // The authored content's direction: from its language, or else from the first\n // letter of the transcript (or of the stored words, when only they are here).\n // Never `auto` on a container: its first strong character could be a hidden\n // interface sentence, or whatever the learner typed. `undefined` — no letter\n // anywhere — inherits the interface's.\n const contentDir =\n localeDir ??\n textDirectionOf(transcript ?? words?.map((word) => word.reference).join(' ') ?? '');\n // Nothing survived normalisation: from the alignment when there is one, and\n // from the stored details otherwise (every transcript word unanswered).\n const nothingTyped =\n alignment !== null\n ? alignment.attempt === ''\n : (words?.every((word) => word.attempt === '') ?? false);\n\n const passed = isReview\n ? outcome?.status === 'scored' || outcome?.status === 'graded'\n ? outcome.passed\n : undefined\n : result?.passed;\n\n const reviewSummary = useMemo<Announcement | null>(() => {\n if (!isReview || outcome === undefined) {\n return null;\n }\n if (outcome.status === 'scored') {\n return {\n text: s.scoreAnnouncement(Math.round(outcome.score * 100), outcome.passed),\n feedback: outcome.feedback,\n };\n }\n if (outcome.status === 'deferred') {\n return { text: s.notGradedYet, feedback: null };\n }\n if (outcome.status === 'graded') {\n const percent =\n outcome.maxScore > 0\n ? Math.round((outcome.score / outcome.maxScore) * 100)\n : Math.round(outcome.score * 100);\n return {\n text: s.scoreAnnouncement(percent, outcome.passed),\n feedback: outcome.feedback ?? null,\n };\n }\n return { text: s.noGradeAvailable, feedback: null };\n }, [isReview, outcome, s]);\n\n const sentenceFor = (word: DictationWordAlignment): string => {\n switch (word.status) {\n case 'correct':\n return s.dictationWordCorrect(word.attempt);\n case 'incorrect':\n return s.dictationWordWrong(word.attempt, word.reference);\n case 'missing':\n return s.dictationWordMissing(word.reference);\n default:\n return s.dictationWordExtra(word.attempt);\n }\n };\n\n const acceptedTranscripts: readonly string[] | undefined =\n transcript === undefined || !Array.isArray(data.acceptedTranscripts)\n ? undefined\n : data.acceptedTranscripts.filter((entry): entry is string => typeof entry === 'string');\n\n return (\n <form\n className=\"lk-dc\"\n // A title with nothing to say would name the form with silence.\n aria-labelledby={VISIBLE_TEXT_RE.test(data.title) ? titleId : undefined}\n lang={locale}\n data-render-mode={renderMode}\n style={theme as CSSProperties | undefined}\n onSubmit={handleSubmit}\n >\n {/*\n The form's name: read from here, it keeps the content's language. A\n paragraph of its own, so without a language to go by its own first\n letter decides its direction.\n */}\n <p id={titleId} className=\"lk-dc-title\" dir={localeDir ?? 'auto'} lang={contentLang}>\n {data.title}\n </p>\n\n {data.media !== undefined || slowMedia !== undefined ? (\n <div className=\"lk-dc-recordings\">\n {/*\n Each recording is a named group (a fieldset with a legend, which is\n what `role=\"group\"` plus a label spells natively), so the two\n transports are told apart by name and not only by position.\n */}\n {data.media !== undefined ? (\n <fieldset className=\"lk-dc-recording\">\n <legend className=\"lk-dc-recording-label\">{s.dictationRecording}</legend>\n {/* The ONLY budgeted recording: the binding is whatever the pager or the caller passes. */}\n <ActivityMedia\n media={data.media}\n renderMode={renderMode}\n playbackGroup={recordingsGroup}\n {...(mediaBudget !== undefined ? { mediaBudget } : {})}\n {...(mediaStrings !== undefined ? { mediaStrings } : {})}\n {...(strings !== undefined ? { strings } : {})}\n {...(onInteraction !== undefined ? { onInteraction } : {})}\n {...(locale !== undefined ? { locale } : {})}\n {...(disabled !== undefined ? { disabled } : {})}\n />\n </fieldset>\n ) : null}\n {slowMedia !== undefined ? (\n <fieldset className=\"lk-dc-recording\" data-slow=\"true\">\n <legend className=\"lk-dc-recording-label\">{s.dictationSlowRecording}</legend>\n {/* No budget of its own, by contract — so no binding is passed and none is demanded. */}\n <ActivityMedia\n media={slowMedia}\n renderMode={renderMode}\n playbackGroup={recordingsGroup}\n {...(mediaStrings !== undefined ? { mediaStrings } : {})}\n {...(strings !== undefined ? { strings } : {})}\n {...(locale !== undefined ? { locale } : {})}\n {...(disabled !== undefined ? { disabled } : {})}\n />\n </fieldset>\n ) : null}\n </div>\n ) : null}\n\n {hintsEnabled ? (\n <div className=\"lk-dc-hints\">\n {/*\n aria-disabled, never disabled, once every word is shown: a natively\n disabled button drops keyboard focus to the page body.\n */}\n <button\n ref={revealButtonRef}\n type=\"button\"\n className=\"lk-dc-hint-btn\"\n disabled={inactive}\n aria-disabled={hintsShown >= hintTotal || undefined}\n onClick={revealNextHint}\n >\n {s.dictationRevealNextWord(hintsShown, hintTotal)}\n </button>\n {hintsShown > 0 ? (\n <button\n type=\"button\"\n className=\"lk-dc-hint-reset\"\n disabled={inactive}\n onClick={resetHints}\n >\n {s.dictationResetHints}\n </button>\n ) : null}\n {/* Rendered before it has content, so the live region exists when the first word lands. */}\n <p id={hintId} className=\"lk-dc-hint\" role=\"status\" dir={contentDir} lang={contentLang}>\n {hintsShown > 0\n ? `${hintWords.slice(0, hintsShown).join(' ')}${hintsShown < hintTotal ? ' …' : ''}`\n : ''}\n </p>\n </div>\n ) : null}\n\n <fieldset disabled={inactive}>\n <textarea\n className=\"lk-dc-input\"\n aria-label={s.dictationInputLabel}\n aria-describedby={hintsEnabled && hintsShown > 0 ? hintId : undefined}\n // No content lang here: the element's accessible name is interface\n // text, and a screen reader voices a name in its element's language.\n dir=\"auto\"\n rows={3}\n maxLength={DICTATION_MAX_TEXT_LENGTH}\n // Assessment integrity, not style: a corrected or completed word is\n // not the learner's spelling.\n autoComplete=\"off\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={text}\n disabled={inactive}\n aria-disabled={inactive || undefined}\n data-correct={\n revealing && passed !== undefined && (!isReview || hasResponse)\n ? String(passed)\n : undefined\n }\n onChange={(event) => handleTextChange(event.target.value)}\n />\n {isReview ? null : (\n // Enabled on empty text: an omission is a recorded answer.\n <button type=\"submit\" disabled={inactive}>\n {isExam ? s.submitAnswers : s.checkAnswers}\n </button>\n )}\n </fieldset>\n\n {marksShown ? (\n <div className=\"lk-dc-result\">\n {nothingTyped ? (\n <p className=\"lk-dc-nothing\" role=\"note\">\n {s.dictationNothingTyped}\n </p>\n ) : (\n <>\n {/*\n The word list is the assistive-technology channel: one hidden\n sentence per word says what happened to it. The visible token,\n its glyph and its character marks are decoration.\n */}\n {/*\n The list's name and the hidden sentences are interface text, so\n they keep the interface language; only the typed tokens carry\n the dictation's. Its direction is the dictation's, never\n resolved from the list's own text: the first strong character\n there would be a hidden interface sentence, or whatever the\n learner typed. Each word's own text may resolve from itself.\n */}\n <ol className=\"lk-dc-words\" aria-label={s.dictationMarksLabel} dir={contentDir}>\n {words?.map((word, index) => {\n const sentence = sentenceFor(word);\n return (\n <li\n // biome-ignore lint/suspicious/noArrayIndexKey: alignment order is the identity; words repeat\n key={index}\n className=\"lk-dc-word\"\n data-state={word.status}\n title={sentence}\n >\n <span className=\"lk-visually-hidden\" style={VISUALLY_HIDDEN}>\n {sentence}\n </span>\n <span\n className=\"lk-dc-word-text\"\n aria-hidden=\"true\"\n dir={contentDir ?? 'auto'}\n lang={contentLang}\n // A wrong word drawn as its character marks: the marks\n // carry the decoration, so the wrong characters stand\n // out from the right ones by shape, not colour alone.\n {...(word.status === 'incorrect' && alignment !== null\n ? { 'data-marks': 'characters' }\n : {})}\n >\n {word.status === 'incorrect' && alignment !== null ? (\n <CharOps\n ops={diffDictationChars(word.reference, word.attempt)}\n contentDir={contentDir}\n />\n ) : word.status === 'missing' ? (\n word.reference\n ) : (\n word.attempt\n )}\n </span>\n </li>\n );\n })}\n </ol>\n {sentenceDiff !== null ? (\n <p className=\"lk-dc-diff\" aria-hidden=\"true\" dir={contentDir} lang={contentLang}>\n <CharOps ops={sentenceDiff} contentDir={contentDir} />\n </p>\n ) : null}\n <ul className=\"lk-dc-legend\">\n <li data-state=\"correct\">{s.dictationLegendCorrect}</li>\n <li data-state=\"incorrect\">{s.dictationLegendWrong}</li>\n <li data-state=\"missing\">{s.dictationLegendMissing}</li>\n {alignment !== null ? <li data-state=\"extra\">{s.dictationLegendExtra}</li> : null}\n </ul>\n <p className=\"lk-dc-diff-note\">{s.dictationDiffNote}</p>\n </>\n )}\n {/*\n Offered after an empty answer too: a learner who could make out\n nothing is the one who most needs to read the sentence, and a\n single typed letter would reveal it anyway.\n */}\n {transcript !== undefined ? (\n <>\n <button\n type=\"button\"\n className=\"lk-dc-solution-toggle\"\n aria-expanded={solutionShown}\n aria-controls={solutionId}\n onClick={() => setSolutionShown((shown) => !shown)}\n >\n {solutionShown ? s.hideSolution : s.showSolution}\n </button>\n {solutionShown ? (\n <blockquote\n id={solutionId}\n className=\"lk-dc-solution\"\n aria-label={s.dictationSolutionLabel}\n dir={contentDir}\n >\n <p lang={contentLang}>{transcript}</p>\n {acceptedTranscripts !== undefined && acceptedTranscripts.length > 0 ? (\n <ul className=\"lk-dc-solution-alternatives\" lang={contentLang}>\n {acceptedTranscripts.map((alternative) => (\n <li key={alternative}>{alternative}</li>\n ))}\n </ul>\n ) : null}\n </blockquote>\n ) : null}\n </>\n ) : null}\n </div>\n ) : null}\n\n <FeedbackRegion id={`${data.id}-feedback`}>\n <AnnouncementText announcement={isReview ? reviewSummary : summary} />\n </FeedbackRegion>\n </form>\n );\n}\n","'use client';\n\nimport { useLkStrings } from '../../i18n/LkIntlProvider.js';\nimport { ActivityErrorBoundary } from '../ActivityErrorBoundary.js';\nimport { Dictation as DictationCore, type DictationProps } from './Dictation.js';\n\nexport type { DictationProps } from './Dictation.js';\n\n/**\n * Public Dictation activity: the core wrapped in `ActivityErrorBoundary` so a\n * render failure (including the dev schema-validation throw and the\n * redacted-in-`practice` guard) degrades to an accessible fallback instead of\n * crashing the host.\n */\nexport function Dictation(props: DictationProps) {\n const strings = useLkStrings(props.strings);\n return (\n <ActivityErrorBoundary activityTitle={props.data?.title} strings={strings}>\n <DictationCore {...props} />\n </ActivityErrorBoundary>\n );\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { useLkStrings } from './chunk-3Q4I4KT6.js';
2
+ import { useLkStrings } from './chunk-TDJEKXEP.js';
3
3
  import { resolvePlaybackPolicy } from '@intellectif/lk-core';
4
4
  import { useRef, useEffect, useId, useState, useCallback } from 'react';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -575,5 +575,5 @@ function ActivityMedia(props) {
575
575
  }
576
576
 
577
577
  export { ActivityMedia };
578
- //# sourceMappingURL=chunk-R7DI5UMU.js.map
579
- //# sourceMappingURL=chunk-R7DI5UMU.js.map
578
+ //# sourceMappingURL=chunk-XIBOFTOL.js.map
579
+ //# sourceMappingURL=chunk-XIBOFTOL.js.map