@remit/ui 0.0.101 → 0.0.102

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.
@@ -0,0 +1,42 @@
1
+ import { franc } from "franc-min";
2
+ import { detectionCodeFor } from "./compose-language.js";
3
+
4
+ /**
5
+ * Below this, detection is a coin toss — `franc-min` scores 90.7% at 20 to 45
6
+ * characters and drops off a cliff under that. A greeting line holds the
7
+ * account default instead.
8
+ */
9
+ export const DETECTION_MIN_LENGTH = 20;
10
+
11
+ /**
12
+ * The language of a body, chosen inside the account's own candidate set.
13
+ *
14
+ * The restriction is what makes a 53 kB trigram table good enough: `franc`
15
+ * scores 87.1% on one sentence over all 414 languages and 97.3% over six.
16
+ * Returns null when the text is too short, when there is nothing to choose
17
+ * between, or when the detector declines to answer.
18
+ *
19
+ * Kept apart from the hook that calls it so `franc-min` stays out of every
20
+ * chunk that only wants a language tag, and so this is testable as the pure
21
+ * function it is.
22
+ */
23
+ export const detectComposeLanguage = (
24
+ text: string,
25
+ candidates: readonly string[],
26
+ ): string | null => {
27
+ const trimmed = text.trim();
28
+ if (trimmed.length < DETECTION_MIN_LENGTH) return null;
29
+
30
+ const tagByCode = new Map<string, string>();
31
+ for (const tag of candidates) {
32
+ const code = detectionCodeFor(tag);
33
+ if (code && !tagByCode.has(code)) tagByCode.set(code, tag);
34
+ }
35
+ if (tagByCode.size < 2) return null;
36
+
37
+ const detected = franc(trimmed, {
38
+ only: [...tagByCode.keys()],
39
+ minLength: DETECTION_MIN_LENGTH,
40
+ });
41
+ return tagByCode.get(detected) ?? null;
42
+ };
package/src/rich-text.ts CHANGED
@@ -3,6 +3,11 @@
3
3
  * app can load them on demand: reached through the package barrel they would
4
4
  * land in whichever chunk already imports `@remit/ui`, which is every screen.
5
5
  */
6
+
7
+ export {
8
+ ComposeLanguageChip,
9
+ type ComposeLanguageChipProps,
10
+ } from "./components/compose-language-chip.js";
6
11
  export {
7
12
  type ComposeBodyMode,
8
13
  ComposeModeToggle,
@@ -25,3 +30,13 @@ export {
25
30
  EMPTY_RICH_TEXT,
26
31
  type RichTextValue,
27
32
  } from "./components/rich-text-value.js";
33
+ export {
34
+ type ComposeLanguageControl,
35
+ type ComposeLanguageSource,
36
+ type ComposeLanguageState,
37
+ useComposeLanguage,
38
+ } from "./components/use-compose-language.js";
39
+ export {
40
+ DETECTION_MIN_LENGTH,
41
+ detectComposeLanguage,
42
+ } from "./lib/detect-compose-language.js";