@cntrl-site/sdk-nextjs 1.9.139 → 1.10.1
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.
|
@@ -22,6 +22,7 @@ const useItemGeometry_1 = require("../../../ItemGeometry/useItemGeometry");
|
|
|
22
22
|
const RichTextGeometryController_1 = require("../../../ItemGeometry/RichTextGeometryController");
|
|
23
23
|
const RichTextConverter_1 = require("../../../utils/RichTextConverter/RichTextConverter");
|
|
24
24
|
const getHeadingTag_1 = require("../../../utils/getHeadingTag");
|
|
25
|
+
const detectLang_1 = require("../../../utils/detectLang");
|
|
25
26
|
const RichTextItem = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
|
|
26
27
|
var _a, _b, _c, _d, _e;
|
|
27
28
|
const reactId = (0, react_1.useId)();
|
|
@@ -59,10 +60,11 @@ const RichTextItem = ({ item, sectionId, onResize, interactionCtrl, onVisibility
|
|
|
59
60
|
const isInteractive = colorAlpha !== 0 || hasVisibleRangeColors;
|
|
60
61
|
const [content, styles] = (0, useRichTextItem_1.useRichTextItem)(item);
|
|
61
62
|
const Wrapper = ((_e = (0, getHeadingTag_1.getHeadingTag)(item)) !== null && _e !== void 0 ? _e : 'div');
|
|
63
|
+
const lang = (0, react_1.useMemo)(() => (0, detectLang_1.detectLang)(item.commonParams.text), [item.commonParams.text]);
|
|
62
64
|
(0, react_1.useEffect)(() => {
|
|
63
65
|
onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
|
|
64
66
|
}, [isInteractive, onVisibilityChange]);
|
|
65
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Wrapper, { ref: setRef, className: `rich-text-wrapper-${item.id}${layoutId ? '' : ` ${RichTextConverter_1.RICH_TEXT_LAYOUT_PENDING_CLASS}`}`, style: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), (textColor ? { color: `${textColor.fmt('rgba')}` } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (letterSpacing !== undefined ? { letterSpacing: `${letterSpacing * exemplary}px` } : {})), (wordSpacing !== undefined ? { wordSpacing: `${wordSpacing * exemplary}px` } : {})), (fontSize !== undefined ? { fontSize: `${Math.round(fontSize * exemplary)}px` } : {})), (lineHeight !== undefined ? { lineHeight: `${lineHeight * exemplary}px` } : {})), (columnsEnabled ? { columnCount: columns, columnFill: 'balance' } : {})), (columnsEnabled && columnGutter !== undefined ? { columnGap: `${Math.round(columnGutter * exemplary)}px` } : {})), (hyphens !== undefined ? { hyphens, WebkitHyphens: hyphens } : {})), { willChange: blur !== 0 && blur !== undefined ? 'transform' : 'unset', transition }), children: content }), (0, jsx_runtime_1.jsxs)(style_1.default, { id: id, children: [styles, `${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams]) => {
|
|
67
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Wrapper, { lang: lang, ref: setRef, className: `rich-text-wrapper-${item.id}${layoutId ? '' : ` ${RichTextConverter_1.RICH_TEXT_LAYOUT_PENDING_CLASS}`}`, style: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), (textColor ? { color: `${textColor.fmt('rgba')}` } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (letterSpacing !== undefined ? { letterSpacing: `${letterSpacing * exemplary}px` } : {})), (wordSpacing !== undefined ? { wordSpacing: `${wordSpacing * exemplary}px` } : {})), (fontSize !== undefined ? { fontSize: `${Math.round(fontSize * exemplary)}px` } : {})), (lineHeight !== undefined ? { lineHeight: `${lineHeight * exemplary}px` } : {})), (columnsEnabled ? { columnCount: columns, columnFill: 'balance' } : {})), (columnsEnabled && columnGutter !== undefined ? { columnGap: `${Math.round(columnGutter * exemplary)}px` } : {})), (hyphens !== undefined ? { hyphens, WebkitHyphens: hyphens } : {})), { willChange: blur !== 0 && blur !== undefined ? 'transform' : 'unset', transition }), children: content }), (0, jsx_runtime_1.jsxs)(style_1.default, { id: id, children: [styles, `${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams]) => {
|
|
66
68
|
var _a, _b, _c;
|
|
67
69
|
const color = color_1.CntrlColor.parse(layoutParams.color);
|
|
68
70
|
const columns = (_a = layoutParams.columns) !== null && _a !== void 0 ? _a : 1;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.detectLang = void 0;
|
|
7
|
+
// franc-min ships no types, and this package publishes raw .ts as its
|
|
8
|
+
// "types" entry, so downstream projects type-check this file directly
|
|
9
|
+
// out of node_modules rather than a compiled .d.ts. No local `declare
|
|
10
|
+
// module` here on purpose — that would only cover this package's own
|
|
11
|
+
// build and leave @ts-expect-error unused (and thus itself an error).
|
|
12
|
+
// @ts-expect-error franc-min has no type declarations
|
|
13
|
+
const franc_min_1 = __importDefault(require("franc-min"));
|
|
14
|
+
// Maps the ISO 639-3 codes franc-min can detect to their ISO 639-1
|
|
15
|
+
// equivalent, since `lang` in the browser is conventionally two letters.
|
|
16
|
+
// Codes with no ISO 639-1 equivalent are passed through as-is — a bare
|
|
17
|
+
// ISO 639-3 code is still a valid BCP 47 language tag.
|
|
18
|
+
const ISO_639_3_TO_1 = {
|
|
19
|
+
arb: 'ar',
|
|
20
|
+
azj: 'az',
|
|
21
|
+
bel: 'be',
|
|
22
|
+
bos: 'bs',
|
|
23
|
+
bul: 'bg',
|
|
24
|
+
ces: 'cs',
|
|
25
|
+
deu: 'de',
|
|
26
|
+
eng: 'en',
|
|
27
|
+
fas: 'fa',
|
|
28
|
+
fra: 'fr',
|
|
29
|
+
hau: 'ha',
|
|
30
|
+
hin: 'hi',
|
|
31
|
+
hrv: 'hr',
|
|
32
|
+
hun: 'hu',
|
|
33
|
+
ibo: 'ig',
|
|
34
|
+
ind: 'id',
|
|
35
|
+
ita: 'it',
|
|
36
|
+
jav: 'jv',
|
|
37
|
+
kaz: 'kk',
|
|
38
|
+
kin: 'rw',
|
|
39
|
+
lin: 'ln',
|
|
40
|
+
mar: 'mr',
|
|
41
|
+
nep: 'ne',
|
|
42
|
+
nld: 'nl',
|
|
43
|
+
nya: 'ny',
|
|
44
|
+
pol: 'pl',
|
|
45
|
+
por: 'pt',
|
|
46
|
+
ron: 'ro',
|
|
47
|
+
run: 'rn',
|
|
48
|
+
rus: 'ru',
|
|
49
|
+
som: 'so',
|
|
50
|
+
spa: 'es',
|
|
51
|
+
srp: 'sr',
|
|
52
|
+
sun: 'su',
|
|
53
|
+
swe: 'sv',
|
|
54
|
+
swh: 'sw',
|
|
55
|
+
tgl: 'tl',
|
|
56
|
+
tur: 'tr',
|
|
57
|
+
ukr: 'uk',
|
|
58
|
+
urd: 'ur',
|
|
59
|
+
uzn: 'uz',
|
|
60
|
+
vie: 'vi',
|
|
61
|
+
yor: 'yo',
|
|
62
|
+
zlm: 'ms',
|
|
63
|
+
zul: 'zu'
|
|
64
|
+
};
|
|
65
|
+
// Below this many characters franc-min's own trigram model is unreliable
|
|
66
|
+
// (headings, labels, short captions) — leave `lang` unset so it inherits
|
|
67
|
+
// from the document instead of guessing wrong.
|
|
68
|
+
const MIN_DETECTABLE_LENGTH = 20;
|
|
69
|
+
function detectLang(text) {
|
|
70
|
+
var _a;
|
|
71
|
+
if (!text)
|
|
72
|
+
return undefined;
|
|
73
|
+
const trimmed = text.trim();
|
|
74
|
+
if (trimmed.length < MIN_DETECTABLE_LENGTH)
|
|
75
|
+
return undefined;
|
|
76
|
+
const code3 = (0, franc_min_1.default)(trimmed, { minLength: MIN_DETECTABLE_LENGTH });
|
|
77
|
+
if (code3 === 'und')
|
|
78
|
+
return undefined;
|
|
79
|
+
return (_a = ISO_639_3_TO_1[code3]) !== null && _a !== void 0 ? _a : code3;
|
|
80
|
+
}
|
|
81
|
+
exports.detectLang = detectLang;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cntrl-site/sdk-nextjs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "SDK for Next.js",
|
|
5
5
|
"author": "arsen@momdesign.nyc",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"@cntrl-site/sdk": "^1.28.10",
|
|
37
37
|
"@types/vimeo__player": "^2.18.0",
|
|
38
38
|
"@vimeo/player": "^2.25.0",
|
|
39
|
+
"franc-min": "^5.0.0",
|
|
39
40
|
"html-react-parser": "^3.0.1",
|
|
40
41
|
"resize-observer-polyfill": "^1.5.1",
|
|
41
42
|
"styled-jsx": "^5.0.2"
|
|
@@ -16,6 +16,7 @@ import { useItemGeometry } from '../../../ItemGeometry/useItemGeometry';
|
|
|
16
16
|
import { RichTextGeometryController } from '../../../ItemGeometry/RichTextGeometryController';
|
|
17
17
|
import { RICH_TEXT_LAYOUT_PENDING_CLASS } from '../../../utils/RichTextConverter/RichTextConverter';
|
|
18
18
|
import { getHeadingTag } from '../../../utils/getHeadingTag';
|
|
19
|
+
import { detectLang } from '../../../utils/detectLang';
|
|
19
20
|
|
|
20
21
|
export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
|
|
21
22
|
const reactId = useId();
|
|
@@ -63,6 +64,7 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
|
|
|
63
64
|
const isInteractive = colorAlpha !== 0 || hasVisibleRangeColors;
|
|
64
65
|
const [content, styles] = useRichTextItem(item);
|
|
65
66
|
const Wrapper = (getHeadingTag(item) ?? 'div') as 'div';
|
|
67
|
+
const lang = useMemo(() => detectLang(item.commonParams.text), [item.commonParams.text]);
|
|
66
68
|
useEffect(() => {
|
|
67
69
|
onVisibilityChange?.(isInteractive);
|
|
68
70
|
}, [isInteractive, onVisibilityChange]);
|
|
@@ -70,6 +72,7 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
|
|
|
70
72
|
return (
|
|
71
73
|
<>
|
|
72
74
|
<Wrapper
|
|
75
|
+
lang={lang}
|
|
73
76
|
ref={setRef}
|
|
74
77
|
className={`rich-text-wrapper-${item.id}${layoutId ? '' : ` ${RICH_TEXT_LAYOUT_PENDING_CLASS}`}`}
|
|
75
78
|
style={{
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// franc-min ships no types, and this package publishes raw .ts as its
|
|
2
|
+
// "types" entry, so downstream projects type-check this file directly
|
|
3
|
+
// out of node_modules rather than a compiled .d.ts. No local `declare
|
|
4
|
+
// module` here on purpose — that would only cover this package's own
|
|
5
|
+
// build and leave @ts-expect-error unused (and thus itself an error).
|
|
6
|
+
// @ts-expect-error franc-min has no type declarations
|
|
7
|
+
import franc from 'franc-min';
|
|
8
|
+
|
|
9
|
+
// Maps the ISO 639-3 codes franc-min can detect to their ISO 639-1
|
|
10
|
+
// equivalent, since `lang` in the browser is conventionally two letters.
|
|
11
|
+
// Codes with no ISO 639-1 equivalent are passed through as-is — a bare
|
|
12
|
+
// ISO 639-3 code is still a valid BCP 47 language tag.
|
|
13
|
+
const ISO_639_3_TO_1: Record<string, string> = {
|
|
14
|
+
arb: 'ar',
|
|
15
|
+
azj: 'az',
|
|
16
|
+
bel: 'be',
|
|
17
|
+
bos: 'bs',
|
|
18
|
+
bul: 'bg',
|
|
19
|
+
ces: 'cs',
|
|
20
|
+
deu: 'de',
|
|
21
|
+
eng: 'en',
|
|
22
|
+
fas: 'fa',
|
|
23
|
+
fra: 'fr',
|
|
24
|
+
hau: 'ha',
|
|
25
|
+
hin: 'hi',
|
|
26
|
+
hrv: 'hr',
|
|
27
|
+
hun: 'hu',
|
|
28
|
+
ibo: 'ig',
|
|
29
|
+
ind: 'id',
|
|
30
|
+
ita: 'it',
|
|
31
|
+
jav: 'jv',
|
|
32
|
+
kaz: 'kk',
|
|
33
|
+
kin: 'rw',
|
|
34
|
+
lin: 'ln',
|
|
35
|
+
mar: 'mr',
|
|
36
|
+
nep: 'ne',
|
|
37
|
+
nld: 'nl',
|
|
38
|
+
nya: 'ny',
|
|
39
|
+
pol: 'pl',
|
|
40
|
+
por: 'pt',
|
|
41
|
+
ron: 'ro',
|
|
42
|
+
run: 'rn',
|
|
43
|
+
rus: 'ru',
|
|
44
|
+
som: 'so',
|
|
45
|
+
spa: 'es',
|
|
46
|
+
srp: 'sr',
|
|
47
|
+
sun: 'su',
|
|
48
|
+
swe: 'sv',
|
|
49
|
+
swh: 'sw',
|
|
50
|
+
tgl: 'tl',
|
|
51
|
+
tur: 'tr',
|
|
52
|
+
ukr: 'uk',
|
|
53
|
+
urd: 'ur',
|
|
54
|
+
uzn: 'uz',
|
|
55
|
+
vie: 'vi',
|
|
56
|
+
yor: 'yo',
|
|
57
|
+
zlm: 'ms',
|
|
58
|
+
zul: 'zu'
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Below this many characters franc-min's own trigram model is unreliable
|
|
62
|
+
// (headings, labels, short captions) — leave `lang` unset so it inherits
|
|
63
|
+
// from the document instead of guessing wrong.
|
|
64
|
+
const MIN_DETECTABLE_LENGTH = 20;
|
|
65
|
+
|
|
66
|
+
export function detectLang(text: string | undefined): string | undefined {
|
|
67
|
+
if (!text) return undefined;
|
|
68
|
+
const trimmed = text.trim();
|
|
69
|
+
if (trimmed.length < MIN_DETECTABLE_LENGTH) return undefined;
|
|
70
|
+
const code3 = franc(trimmed, { minLength: MIN_DETECTABLE_LENGTH });
|
|
71
|
+
if (code3 === 'und') return undefined;
|
|
72
|
+
return ISO_639_3_TO_1[code3] ?? code3;
|
|
73
|
+
}
|