@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
@@ -0,0 +1,15 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { c as ReadAloudProps } from '../strings-CtdSf2St.js';
3
+ export { R as ReadAloudAssessResult, d as RecordingBinding } from '../strings-CtdSf2St.js';
4
+ export { R as RecordedTake } from '../machine-CuwKqWXC.js';
5
+ import '@intellectif/lk-core';
6
+
7
+ /**
8
+ * Public Read Aloud activity: the core wrapped in `ActivityErrorBoundary` so a
9
+ * render failure (including the dev schema-validation throw and the
10
+ * missing-`upload` guard) degrades to an accessible fallback instead of
11
+ * crashing the host.
12
+ */
13
+ declare function ReadAloud(props: ReadAloudProps): react_jsx_runtime.JSX.Element;
14
+
15
+ export { ReadAloud, ReadAloudProps };
@@ -0,0 +1,12 @@
1
+ 'use client';
2
+ export { ReadAloud } from '../chunk-D57QZILZ.js';
3
+ import '../chunk-62AKSD5Y.js';
4
+ import '../chunk-MCO52PV5.js';
5
+ import '../chunk-YORQQXGO.js';
6
+ import '../chunk-RCMYEWBE.js';
7
+ import '../chunk-BO6P723E.js';
8
+ import '../chunk-XIBOFTOL.js';
9
+ import '../chunk-6N43WDVG.js';
10
+ import '../chunk-TDJEKXEP.js';
11
+ //# sourceMappingURL=ReadAloud.js.map
12
+ //# sourceMappingURL=ReadAloud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"ReadAloud.js"}
@@ -1,15 +1,15 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunk74QXBWCI_cjs = require('../chunk-74QXBWCI.cjs');
5
- require('../chunk-SBIJJ374.cjs');
6
- require('../chunk-MA7GXUWC.cjs');
4
+ var chunkRRH7ZPXC_cjs = require('../chunk-RRH7ZPXC.cjs');
5
+ require('../chunk-B2XQLU2E.cjs');
6
+ require('../chunk-LB3FEV7Z.cjs');
7
7
 
8
8
 
9
9
 
10
10
  Object.defineProperty(exports, "StimulusPanel", {
11
11
  enumerable: true,
12
- get: function () { return chunk74QXBWCI_cjs.StimulusPanel; }
12
+ get: function () { return chunkRRH7ZPXC_cjs.StimulusPanel; }
13
13
  });
14
14
  //# sourceMappingURL=StimulusPanel.cjs.map
15
15
  //# sourceMappingURL=StimulusPanel.cjs.map
@@ -1,5 +1,6 @@
1
1
  import { Stimulus, InteractionEvent } from '@intellectif/lk-core';
2
- import { H as HtmlSanitizer, R as RenderMode, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from '../strings-DPTyLpHt.cjs';
2
+ import { H as HtmlSanitizer, e as RenderMode, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from '../strings--ADnHcaA.cjs';
3
+ import '../machine-CuwKqWXC.cjs';
3
4
 
4
5
  interface StimulusPanelProps {
5
6
  stimulus: Stimulus;
@@ -1,5 +1,6 @@
1
1
  import { Stimulus, InteractionEvent } from '@intellectif/lk-core';
2
- import { H as HtmlSanitizer, R as RenderMode, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from '../strings-DPTyLpHt.js';
2
+ import { H as HtmlSanitizer, e as RenderMode, M as MediaBudgetBinding, b as MediaTransportStrings, a as LkStringsOverride } from '../strings-CtdSf2St.js';
3
+ import '../machine-CuwKqWXC.js';
3
4
 
4
5
  interface StimulusPanelProps {
5
6
  stimulus: Stimulus;
@@ -1,6 +1,6 @@
1
1
  'use client';
2
- export { StimulusPanel } from '../chunk-NVP6UEQQ.js';
3
- import '../chunk-R7DI5UMU.js';
4
- import '../chunk-3Q4I4KT6.js';
2
+ export { StimulusPanel } from '../chunk-SWY6PWXK.js';
3
+ import '../chunk-XIBOFTOL.js';
4
+ import '../chunk-TDJEKXEP.js';
5
5
  //# sourceMappingURL=StimulusPanel.js.map
6
6
  //# sourceMappingURL=StimulusPanel.js.map
@@ -1,17 +1,18 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkUU2NV6SU_cjs = require('../chunk-UU2NV6SU.cjs');
5
- require('../chunk-K3EA547J.cjs');
6
- require('../chunk-SBIJJ374.cjs');
4
+ var chunkYEYKJFEC_cjs = require('../chunk-YEYKJFEC.cjs');
5
+ require('../chunk-BRPEB43C.cjs');
6
+ require('../chunk-USBANZ7K.cjs');
7
+ require('../chunk-B2XQLU2E.cjs');
7
8
  require('../chunk-XOR4MPEN.cjs');
8
- require('../chunk-MA7GXUWC.cjs');
9
+ require('../chunk-LB3FEV7Z.cjs');
9
10
 
10
11
 
11
12
 
12
13
  Object.defineProperty(exports, "WrittenResponse", {
13
14
  enumerable: true,
14
- get: function () { return chunkUU2NV6SU_cjs.WrittenResponse; }
15
+ get: function () { return chunkYEYKJFEC_cjs.WrittenResponse; }
15
16
  });
16
17
  //# sourceMappingURL=WrittenResponse.cjs.map
17
18
  //# sourceMappingURL=WrittenResponse.cjs.map
@@ -1,8 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { W as WrittenResponseProps } from '../WrittenResponse-DWtS4tOL.cjs';
3
- export { a as WrittenResponseSubmission } from '../WrittenResponse-DWtS4tOL.cjs';
4
- export { H as HtmlSanitizer, R as RenderMode, c as Renderable } from '../strings-DPTyLpHt.cjs';
2
+ import { W as WrittenResponseProps } from '../WrittenResponse-pB1ik8hg.cjs';
3
+ export { a as WrittenResponseSubmission } from '../WrittenResponse-pB1ik8hg.cjs';
4
+ export { H as HtmlSanitizer, e as RenderMode, f as Renderable } from '../strings--ADnHcaA.cjs';
5
5
  import '@intellectif/lk-core';
6
+ import '../machine-CuwKqWXC.cjs';
6
7
 
7
8
  /**
8
9
  * Public Written Response activity: a labelled textarea with a live word
@@ -1,8 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { W as WrittenResponseProps } from '../WrittenResponse-B5p_-RnJ.js';
3
- export { a as WrittenResponseSubmission } from '../WrittenResponse-B5p_-RnJ.js';
4
- export { H as HtmlSanitizer, R as RenderMode, c as Renderable } from '../strings-DPTyLpHt.js';
2
+ import { W as WrittenResponseProps } from '../WrittenResponse-C0P34En1.js';
3
+ export { a as WrittenResponseSubmission } from '../WrittenResponse-C0P34En1.js';
4
+ export { H as HtmlSanitizer, e as RenderMode, f as Renderable } from '../strings-CtdSf2St.js';
5
5
  import '@intellectif/lk-core';
6
+ import '../machine-CuwKqWXC.js';
6
7
 
7
8
  /**
8
9
  * Public Written Response activity: a labelled textarea with a live word
@@ -1,8 +1,9 @@
1
1
  'use client';
2
- export { WrittenResponse } from '../chunk-YZWXVZB3.js';
3
- import '../chunk-DQERNAWI.js';
4
- import '../chunk-R7DI5UMU.js';
2
+ export { WrittenResponse } from '../chunk-LLXCX5KK.js';
3
+ import '../chunk-RCMYEWBE.js';
4
+ import '../chunk-BO6P723E.js';
5
+ import '../chunk-XIBOFTOL.js';
5
6
  import '../chunk-6N43WDVG.js';
6
- import '../chunk-3Q4I4KT6.js';
7
+ import '../chunk-TDJEKXEP.js';
7
8
  //# sourceMappingURL=WrittenResponse.js.map
8
9
  //# sourceMappingURL=WrittenResponse.js.map
@@ -0,0 +1,17 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var chunkUDCQTOVU_cjs = require('../chunk-UDCQTOVU.cjs');
5
+
6
+
7
+
8
+ Object.defineProperty(exports, "CAPTURE_PROCESSOR_SOURCE", {
9
+ enumerable: true,
10
+ get: function () { return chunkUDCQTOVU_cjs.CAPTURE_PROCESSOR_SOURCE; }
11
+ });
12
+ Object.defineProperty(exports, "useSpeechRecorder", {
13
+ enumerable: true,
14
+ get: function () { return chunkUDCQTOVU_cjs.useSpeechRecorder; }
15
+ });
16
+ //# sourceMappingURL=useSpeechRecorder.cjs.map
17
+ //# sourceMappingURL=useSpeechRecorder.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"useSpeechRecorder.cjs"}
@@ -0,0 +1,127 @@
1
+ import { a as SpeechRecorderStatus, S as SpeechRecorderError, R as RecordedTake } from '../machine-CuwKqWXC.cjs';
2
+
3
+ /**
4
+ * The audio worklet module `useSpeechRecorder` captures through, as source
5
+ * text — exported so an application with a strict Content-Security-Policy can
6
+ * serve it itself.
7
+ *
8
+ * By default the hook loads this text from a `blob:` URL. A worklet module is
9
+ * loaded as a script, so it is `script-src` that must allow `blob:` —
10
+ * `worker-src` does not govern it. Where that is refused, write this string to
11
+ * a file your policy's `script-src` does allow, at build time and from the
12
+ * installed package so it moves with the version you run, and pass that file's
13
+ * URL as `workletUrl`:
14
+ *
15
+ * ```ts
16
+ * import { writeFileSync } from 'node:fs';
17
+ * import { CAPTURE_PROCESSOR_SOURCE } from '@intellectif/lk-react/hooks/useSpeechRecorder';
18
+ *
19
+ * writeFileSync('public/lk-speech-capture.js', CAPTURE_PROCESSOR_SOURCE);
20
+ * ```
21
+ *
22
+ * **The contract** a module at `workletUrl` must meet, which this source does:
23
+ * register an `AudioWorkletProcessor` under the name `lk-speech-capture`, and
24
+ * from its `process(inputs)` post the first input's channels to its `port` as
25
+ * an array with one `Float32Array` per channel, **copied** — the render
26
+ * quantum's buffers belong to the audio thread and are overwritten on the next
27
+ * quantum, so a block posted without copying arrives as whatever the
28
+ * microphone heard some milliseconds later. Return `true`, which keeps the
29
+ * processor alive while its source is silent. Anything else changes what is
30
+ * recorded, so serve this text unchanged rather than a copy of your own.
31
+ */
32
+ declare const CAPTURE_PROCESSOR_SOURCE: string;
33
+
34
+ interface SpeechRecorderOptions {
35
+ /** The longest a take may be. Reached, the recording stops itself. */
36
+ maxDurationMs: number;
37
+ /** Shorter than this and the take is refused as `too-short`. */
38
+ minDurationMs?: number;
39
+ /** How many takes the learner may make. Unbounded when absent. */
40
+ maxTakes?: number;
41
+ /**
42
+ * The URL of a self-hosted copy of {@link CAPTURE_PROCESSOR_SOURCE}, for an
43
+ * application whose Content-Security-Policy does not allow `blob:` in
44
+ * `script-src`. Serve that string unchanged; the contract a module here must
45
+ * meet is written on it.
46
+ *
47
+ * **A URL that does not work is not reported.** If the module fails to load,
48
+ * or loads without registering `lk-speech-capture`, the hook records through
49
+ * the deprecated `ScriptProcessorNode` on the main thread instead — the
50
+ * fallback it keeps for engines without audio worklets — and a recorder with
51
+ * a broken `workletUrl` looks like a working one. Only an engine with neither
52
+ * path reports `error: 'unsupported'`. Check that the module is actually
53
+ * fetched.
54
+ */
55
+ workletUrl?: string;
56
+ }
57
+ interface SpeechRecorder {
58
+ status: SpeechRecorderStatus;
59
+ error: SpeechRecorderError | null;
60
+ /** The loudest block since the last update, 0..1. */
61
+ level: number;
62
+ /** How much audio has been captured, from the sample count. */
63
+ elapsedMs: number;
64
+ take: RecordedTake | null;
65
+ takesUsed: number;
66
+ /** Whether a take remains. Not whether a `start()` would be accepted now. */
67
+ canRecord: boolean;
68
+ /** Opens the microphone and begins capturing. **Never rejects.** */
69
+ start(): Promise<void>;
70
+ /** Ends the capture and encodes the take. */
71
+ stop(): void;
72
+ /** Throws the take away and releases the microphone. */
73
+ discard(): void;
74
+ /**
75
+ * Starts over: releases the microphone, throws the take away **and gives the
76
+ * budget back**.
77
+ *
78
+ * That last part is the whole difference from {@link SpeechRecorder.discard},
79
+ * which deliberately refunds nothing — a budget a re-record gave back would
80
+ * bound nothing. A reset is for a recorder that has been handed a different
81
+ * reading while it stayed mounted: the takes belong to the activity, so the
82
+ * next activity's are its own. Calling it for the same reading hands a
83
+ * learner takes they have already spent.
84
+ */
85
+ reset(): void;
86
+ }
87
+ /**
88
+ * Records a take of speech as mono 16-bit PCM WAV at 16 kHz.
89
+ *
90
+ * That is the one format the SDK measures directly: `inspectWav` reads it
91
+ * without a decoding library, and it is what every mainstream pronunciation
92
+ * assessor accepts. A take is captured at whatever rate the device runs at,
93
+ * downmixed to mono, low-pass filtered and resampled, then encoded — so what a
94
+ * server measures is what this hook produced, not a claim about it.
95
+ *
96
+ * **Server rendering.** `status`, `error` and `canRecord` are derived from the
97
+ * take count alone and never from a browser global, so the markup a server
98
+ * produces is the markup the browser's first render produces. Support is
99
+ * discovered inside {@link SpeechRecorder.start} and reported as
100
+ * `error: 'unsupported'`; the obvious `!!navigator.mediaDevices` guard at
101
+ * render time would make a server render and its hydration disagree.
102
+ *
103
+ * **Identity.** `start`, `stop`, `discard` and `reset` keep one identity for the
104
+ * life of the hook, so they are safe in a dependency array. The returned object keeps
105
+ * one identity for as long as none of its values changes, so a render caused
106
+ * by something else does not invalidate an effect that depends on it.
107
+ *
108
+ * `start()` does nothing when no take remains, so `canRecord` is presentation:
109
+ * mark the control `aria-disabled` rather than `disabled`, which would take it
110
+ * out of the tab order and leave a learner nothing to read.
111
+ *
112
+ * ```tsx
113
+ * const recorder = useSpeechRecorder({ maxDurationMs: 20_000, maxTakes: 3 });
114
+ * <button
115
+ * type="button"
116
+ * aria-disabled={!recorder.canRecord}
117
+ * onClick={() => {
118
+ * void recorder.start();
119
+ * }}
120
+ * >
121
+ * Record
122
+ * </button>
123
+ * ```
124
+ */
125
+ declare function useSpeechRecorder(options: SpeechRecorderOptions): SpeechRecorder;
126
+
127
+ export { CAPTURE_PROCESSOR_SOURCE, RecordedTake, type SpeechRecorder, SpeechRecorderError, type SpeechRecorderOptions, SpeechRecorderStatus, useSpeechRecorder };
@@ -0,0 +1,127 @@
1
+ import { a as SpeechRecorderStatus, S as SpeechRecorderError, R as RecordedTake } from '../machine-CuwKqWXC.js';
2
+
3
+ /**
4
+ * The audio worklet module `useSpeechRecorder` captures through, as source
5
+ * text — exported so an application with a strict Content-Security-Policy can
6
+ * serve it itself.
7
+ *
8
+ * By default the hook loads this text from a `blob:` URL. A worklet module is
9
+ * loaded as a script, so it is `script-src` that must allow `blob:` —
10
+ * `worker-src` does not govern it. Where that is refused, write this string to
11
+ * a file your policy's `script-src` does allow, at build time and from the
12
+ * installed package so it moves with the version you run, and pass that file's
13
+ * URL as `workletUrl`:
14
+ *
15
+ * ```ts
16
+ * import { writeFileSync } from 'node:fs';
17
+ * import { CAPTURE_PROCESSOR_SOURCE } from '@intellectif/lk-react/hooks/useSpeechRecorder';
18
+ *
19
+ * writeFileSync('public/lk-speech-capture.js', CAPTURE_PROCESSOR_SOURCE);
20
+ * ```
21
+ *
22
+ * **The contract** a module at `workletUrl` must meet, which this source does:
23
+ * register an `AudioWorkletProcessor` under the name `lk-speech-capture`, and
24
+ * from its `process(inputs)` post the first input's channels to its `port` as
25
+ * an array with one `Float32Array` per channel, **copied** — the render
26
+ * quantum's buffers belong to the audio thread and are overwritten on the next
27
+ * quantum, so a block posted without copying arrives as whatever the
28
+ * microphone heard some milliseconds later. Return `true`, which keeps the
29
+ * processor alive while its source is silent. Anything else changes what is
30
+ * recorded, so serve this text unchanged rather than a copy of your own.
31
+ */
32
+ declare const CAPTURE_PROCESSOR_SOURCE: string;
33
+
34
+ interface SpeechRecorderOptions {
35
+ /** The longest a take may be. Reached, the recording stops itself. */
36
+ maxDurationMs: number;
37
+ /** Shorter than this and the take is refused as `too-short`. */
38
+ minDurationMs?: number;
39
+ /** How many takes the learner may make. Unbounded when absent. */
40
+ maxTakes?: number;
41
+ /**
42
+ * The URL of a self-hosted copy of {@link CAPTURE_PROCESSOR_SOURCE}, for an
43
+ * application whose Content-Security-Policy does not allow `blob:` in
44
+ * `script-src`. Serve that string unchanged; the contract a module here must
45
+ * meet is written on it.
46
+ *
47
+ * **A URL that does not work is not reported.** If the module fails to load,
48
+ * or loads without registering `lk-speech-capture`, the hook records through
49
+ * the deprecated `ScriptProcessorNode` on the main thread instead — the
50
+ * fallback it keeps for engines without audio worklets — and a recorder with
51
+ * a broken `workletUrl` looks like a working one. Only an engine with neither
52
+ * path reports `error: 'unsupported'`. Check that the module is actually
53
+ * fetched.
54
+ */
55
+ workletUrl?: string;
56
+ }
57
+ interface SpeechRecorder {
58
+ status: SpeechRecorderStatus;
59
+ error: SpeechRecorderError | null;
60
+ /** The loudest block since the last update, 0..1. */
61
+ level: number;
62
+ /** How much audio has been captured, from the sample count. */
63
+ elapsedMs: number;
64
+ take: RecordedTake | null;
65
+ takesUsed: number;
66
+ /** Whether a take remains. Not whether a `start()` would be accepted now. */
67
+ canRecord: boolean;
68
+ /** Opens the microphone and begins capturing. **Never rejects.** */
69
+ start(): Promise<void>;
70
+ /** Ends the capture and encodes the take. */
71
+ stop(): void;
72
+ /** Throws the take away and releases the microphone. */
73
+ discard(): void;
74
+ /**
75
+ * Starts over: releases the microphone, throws the take away **and gives the
76
+ * budget back**.
77
+ *
78
+ * That last part is the whole difference from {@link SpeechRecorder.discard},
79
+ * which deliberately refunds nothing — a budget a re-record gave back would
80
+ * bound nothing. A reset is for a recorder that has been handed a different
81
+ * reading while it stayed mounted: the takes belong to the activity, so the
82
+ * next activity's are its own. Calling it for the same reading hands a
83
+ * learner takes they have already spent.
84
+ */
85
+ reset(): void;
86
+ }
87
+ /**
88
+ * Records a take of speech as mono 16-bit PCM WAV at 16 kHz.
89
+ *
90
+ * That is the one format the SDK measures directly: `inspectWav` reads it
91
+ * without a decoding library, and it is what every mainstream pronunciation
92
+ * assessor accepts. A take is captured at whatever rate the device runs at,
93
+ * downmixed to mono, low-pass filtered and resampled, then encoded — so what a
94
+ * server measures is what this hook produced, not a claim about it.
95
+ *
96
+ * **Server rendering.** `status`, `error` and `canRecord` are derived from the
97
+ * take count alone and never from a browser global, so the markup a server
98
+ * produces is the markup the browser's first render produces. Support is
99
+ * discovered inside {@link SpeechRecorder.start} and reported as
100
+ * `error: 'unsupported'`; the obvious `!!navigator.mediaDevices` guard at
101
+ * render time would make a server render and its hydration disagree.
102
+ *
103
+ * **Identity.** `start`, `stop`, `discard` and `reset` keep one identity for the
104
+ * life of the hook, so they are safe in a dependency array. The returned object keeps
105
+ * one identity for as long as none of its values changes, so a render caused
106
+ * by something else does not invalidate an effect that depends on it.
107
+ *
108
+ * `start()` does nothing when no take remains, so `canRecord` is presentation:
109
+ * mark the control `aria-disabled` rather than `disabled`, which would take it
110
+ * out of the tab order and leave a learner nothing to read.
111
+ *
112
+ * ```tsx
113
+ * const recorder = useSpeechRecorder({ maxDurationMs: 20_000, maxTakes: 3 });
114
+ * <button
115
+ * type="button"
116
+ * aria-disabled={!recorder.canRecord}
117
+ * onClick={() => {
118
+ * void recorder.start();
119
+ * }}
120
+ * >
121
+ * Record
122
+ * </button>
123
+ * ```
124
+ */
125
+ declare function useSpeechRecorder(options: SpeechRecorderOptions): SpeechRecorder;
126
+
127
+ export { CAPTURE_PROCESSOR_SOURCE, RecordedTake, type SpeechRecorder, SpeechRecorderError, type SpeechRecorderOptions, SpeechRecorderStatus, useSpeechRecorder };
@@ -0,0 +1,4 @@
1
+ 'use client';
2
+ export { CAPTURE_PROCESSOR_SOURCE, useSpeechRecorder } from '../chunk-MCO52PV5.js';
3
+ //# sourceMappingURL=useSpeechRecorder.js.map
4
+ //# sourceMappingURL=useSpeechRecorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"useSpeechRecorder.js"}
@@ -1,33 +1,33 @@
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
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "DEFAULT_STRINGS", {
9
9
  enumerable: true,
10
- get: function () { return chunkMA7GXUWC_cjs.DEFAULT_STRINGS; }
10
+ get: function () { return chunkLB3FEV7Z_cjs.DEFAULT_STRINGS; }
11
11
  });
12
12
  Object.defineProperty(exports, "LkIntlProvider", {
13
13
  enumerable: true,
14
- get: function () { return chunkMA7GXUWC_cjs.LkIntlProvider; }
14
+ get: function () { return chunkLB3FEV7Z_cjs.LkIntlProvider; }
15
15
  });
16
16
  Object.defineProperty(exports, "directionForLocale", {
17
17
  enumerable: true,
18
- get: function () { return chunkMA7GXUWC_cjs.directionForLocale; }
18
+ get: function () { return chunkLB3FEV7Z_cjs.directionForLocale; }
19
19
  });
20
20
  Object.defineProperty(exports, "mergeStrings", {
21
21
  enumerable: true,
22
- get: function () { return chunkMA7GXUWC_cjs.mergeStrings; }
22
+ get: function () { return chunkLB3FEV7Z_cjs.mergeStrings; }
23
23
  });
24
24
  Object.defineProperty(exports, "useLkDirection", {
25
25
  enumerable: true,
26
- get: function () { return chunkMA7GXUWC_cjs.useLkDirection; }
26
+ get: function () { return chunkLB3FEV7Z_cjs.useLkDirection; }
27
27
  });
28
28
  Object.defineProperty(exports, "useLkStrings", {
29
29
  enumerable: true,
30
- get: function () { return chunkMA7GXUWC_cjs.useLkStrings; }
30
+ get: function () { return chunkLB3FEV7Z_cjs.useLkStrings; }
31
31
  });
32
32
  //# sourceMappingURL=LkIntlProvider.cjs.map
33
33
  //# sourceMappingURL=LkIntlProvider.cjs.map
@@ -1,6 +1,7 @@
1
- import { a as LkStringsOverride, L as LkStrings } from '../strings-DPTyLpHt.cjs';
2
- export { D as DEFAULT_STRINGS, m as mergeStrings } from '../strings-DPTyLpHt.cjs';
1
+ import { a as LkStringsOverride, L as LkStrings } from '../strings--ADnHcaA.cjs';
2
+ export { D as DEFAULT_STRINGS, m as mergeStrings } from '../strings--ADnHcaA.cjs';
3
3
  import '@intellectif/lk-core';
4
+ import '../machine-CuwKqWXC.cjs';
4
5
 
5
6
  /** Writing direction of the surrounding UI. `auto` defers to the locale. */
6
7
  type LkDirection = 'ltr' | 'rtl' | 'auto';
@@ -1,6 +1,7 @@
1
- import { a as LkStringsOverride, L as LkStrings } from '../strings-DPTyLpHt.js';
2
- export { D as DEFAULT_STRINGS, m as mergeStrings } from '../strings-DPTyLpHt.js';
1
+ import { a as LkStringsOverride, L as LkStrings } from '../strings-CtdSf2St.js';
2
+ export { D as DEFAULT_STRINGS, m as mergeStrings } from '../strings-CtdSf2St.js';
3
3
  import '@intellectif/lk-core';
4
+ import '../machine-CuwKqWXC.js';
4
5
 
5
6
  /** Writing direction of the surrounding UI. `auto` defers to the locale. */
6
7
  type LkDirection = 'ltr' | 'rtl' | 'auto';
@@ -1,4 +1,4 @@
1
1
  'use client';
2
- export { DEFAULT_STRINGS, LkIntlProvider, directionForLocale, mergeStrings, useLkDirection, useLkStrings } from '../chunk-3Q4I4KT6.js';
2
+ export { DEFAULT_STRINGS, LkIntlProvider, directionForLocale, mergeStrings, useLkDirection, useLkStrings } from '../chunk-TDJEKXEP.js';
3
3
  //# sourceMappingURL=LkIntlProvider.js.map
4
4
  //# sourceMappingURL=LkIntlProvider.js.map