@olddevs/ui 4.3.0 → 4.4.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.
- package/CHANGELOG.md +23 -0
- package/dist/editor/RichTextEditor.d.ts.map +1 -1
- package/dist/editor/RichTextEditor.js +38 -4
- package/dist/editor/RichTextEditor.js.map +1 -1
- package/dist/editor/core/handle.d.ts +1 -5
- package/dist/editor/core/handle.d.ts.map +1 -1
- package/dist/editor/core/handle.js +1 -13
- package/dist/editor/core/handle.js.map +1 -1
- package/dist/editor/core/handleWatchers.d.ts +6 -0
- package/dist/editor/core/handleWatchers.d.ts.map +1 -0
- package/dist/editor/core/handleWatchers.js +14 -0
- package/dist/editor/core/handleWatchers.js.map +1 -0
- package/dist/editor/core/tools.d.ts +7 -2
- package/dist/editor/core/tools.d.ts.map +1 -1
- package/dist/editor/core/tools.js +2 -1
- package/dist/editor/core/tools.js.map +1 -1
- package/dist/editor/features/toc/RichTextToc.d.ts +63 -0
- package/dist/editor/features/toc/RichTextToc.d.ts.map +1 -0
- package/dist/editor/features/toc/RichTextToc.js +372 -0
- package/dist/editor/features/toc/RichTextToc.js.map +1 -0
- package/dist/editor/features/toc/headings.d.ts +31 -0
- package/dist/editor/features/toc/headings.d.ts.map +1 -0
- package/dist/editor/features/toc/headings.js +25 -0
- package/dist/editor/features/toc/headings.js.map +1 -0
- package/dist/editor/features/toc/stickyOffset.d.ts +3 -0
- package/dist/editor/features/toc/stickyOffset.d.ts.map +1 -0
- package/dist/editor/features/toc/stickyOffset.js +14 -0
- package/dist/editor/features/toc/stickyOffset.js.map +1 -0
- package/dist/editor/index.d.ts +2 -0
- package/dist/editor/index.d.ts.map +1 -1
- package/dist/editor/index.js +1 -0
- package/dist/editor/index.js.map +1 -1
- package/dist/i18n/defaults.d.ts.map +1 -1
- package/dist/i18n/defaults.js +1 -0
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/messages.d.ts +5 -0
- package/dist/i18n/messages.d.ts.map +1 -1
- package/dist/locales/ru.d.ts.map +1 -1
- package/dist/locales/ru.js +1 -0
- package/dist/locales/ru.js.map +1 -1
- package/docs/api/messages.en.md +743 -0
- package/docs/api/messages.md +1 -0
- package/docs/api/utilities.en.md +233 -0
- package/docs/components/content/rich-text-toc.en.md +130 -0
- package/docs/components/content/rich-text-toc.md +129 -0
- package/docs/components/index.en.md +2 -1
- package/docs/components/index.md +1 -0
- package/docs/components/inputs/rich-text-editor.en.md +52 -34
- package/docs/components/inputs/rich-text-editor.md +20 -2
- package/docs/conventions.en.md +318 -0
- package/docs/getting-started.en.md +4 -4
- package/docs/getting-started.md +3 -3
- package/docs/glossary.en.md +2 -1
- package/docs/glossary.md +1 -0
- package/docs/index.en.md +53 -0
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/src/editor/RichTextEditor.tsx +107 -3
- package/src/editor/core/handle.ts +2 -23
- package/src/editor/core/handleWatchers.ts +27 -0
- package/src/editor/core/tools.ts +9 -2
- package/src/editor/features/toc/RichTextToc.tsx +712 -0
- package/src/editor/features/toc/headings.ts +70 -0
- package/src/editor/features/toc/stickyOffset.ts +21 -0
- package/src/editor/index.ts +2 -0
- package/src/i18n/defaults.ts +1 -0
- package/src/i18n/messages.ts +5 -0
- package/src/locales/ru.ts +1 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Заголовки Документа для Оглавления (`RichTextToc`, ADR-0066).
|
|
3
|
+
*
|
|
4
|
+
* Читаются из DOM цели, а не из строки `html`: один путь для Просмотра,
|
|
5
|
+
* Редактора и JSON-конверта, и переходу всё равно нужен живой узел.
|
|
6
|
+
*
|
|
7
|
+
* Модуль без React и без движка: только обход DOM.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Заголовок в Оглавлении. */
|
|
11
|
+
export interface TocHeading {
|
|
12
|
+
/** Узел заголовка в Документе: к нему ведёт переход. */
|
|
13
|
+
element: HTMLElement;
|
|
14
|
+
/** Текст пункта — текст заголовка без разметки. */
|
|
15
|
+
text: string;
|
|
16
|
+
/** Уровень по тегу: 1 для `h1` … 4 для `h4`. */
|
|
17
|
+
level: number;
|
|
18
|
+
/**
|
|
19
|
+
* Глубина относительно самого крупного заголовка Документа: у него 0. Отступ
|
|
20
|
+
* пункта и длина штриха считаются от неё, а не от уровня, — иначе Документ,
|
|
21
|
+
* где старший заголовок H2, начинался бы с пустой ступени.
|
|
22
|
+
*/
|
|
23
|
+
depth: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const HEADING = "h1, h2, h3, h4";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Обёртка — единственный контейнер, чьи заголовки идут в Оглавление.
|
|
30
|
+
*
|
|
31
|
+
* Колонки Раскладки — нет: два заголовка на одной высоте в соседних колонках
|
|
32
|
+
* путают подсветку текущего раздела, и порядок «левая колонка, затем правая»
|
|
33
|
+
* читателю ничего не говорит. Острова и свои Блоки — тоже нет: их содержимое —
|
|
34
|
+
* часть Блока, а не структура Документа.
|
|
35
|
+
*/
|
|
36
|
+
const WRAPPER = 'div[data-block="wrapper"]';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Корень Документа внутри цели. У Просмотра это сам контейнер; у Редактора
|
|
40
|
+
* Документ лежит глубже, в узле движка — Панель и строка статуса снаружи него.
|
|
41
|
+
*/
|
|
42
|
+
export function documentRoot(target: HTMLElement): HTMLElement {
|
|
43
|
+
return target.querySelector<HTMLElement>(".ProseMirror") ?? target;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Заголовок лежит на верхнем уровне Документа или только в Обёртках. */
|
|
47
|
+
function isStructural(heading: Element, root: HTMLElement): boolean {
|
|
48
|
+
for (let node = heading.parentElement; node && node !== root; node = node.parentElement) {
|
|
49
|
+
if (!node.matches(WRAPPER)) return false;
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Заголовки Документа в порядке чтения. */
|
|
55
|
+
export function collectHeadings(target: HTMLElement): TocHeading[] {
|
|
56
|
+
const root = documentRoot(target);
|
|
57
|
+
// Пустой заголовок (автор только начал его в Редакторе) — не пункт: у
|
|
58
|
+
// кнопки без текста не было бы имени, а у полосы — лишний штрих.
|
|
59
|
+
const found = [...root.querySelectorAll<HTMLElement>(HEADING)].filter(
|
|
60
|
+
(heading) => isStructural(heading, root) && heading.textContent?.trim()
|
|
61
|
+
);
|
|
62
|
+
const levels = found.map((heading) => Number(heading.tagName[1]));
|
|
63
|
+
const top = Math.min(...levels);
|
|
64
|
+
return found.map((element, index) => ({
|
|
65
|
+
element,
|
|
66
|
+
text: element.textContent?.trim() ?? "",
|
|
67
|
+
level: levels[index]!,
|
|
68
|
+
depth: levels[index]! - top,
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { toPixels } from "../../../hooks/useStickyOffset.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Последний замер шапки. Подсветка читает отступ на каждом кадре прокрутки, а
|
|
7
|
+
* `toPixels` для значения не в пикселях (`4rem`) меряет зонд — две раскладки.
|
|
8
|
+
* Замер повторяется только при смене сырого значения, как в `useStickyOffset`.
|
|
9
|
+
*/
|
|
10
|
+
let measured: { raw: string; px: number | null } = { raw: "", px: null };
|
|
11
|
+
|
|
12
|
+
/** Высота липкой шапки в пикселях; переменной нет — `null`. */
|
|
13
|
+
export function stickyOffset(offsetVar: string): number | null {
|
|
14
|
+
const raw = getComputedStyle(document.documentElement).getPropertyValue(offsetVar).trim();
|
|
15
|
+
if (!raw) return null;
|
|
16
|
+
if (raw !== measured.raw) {
|
|
17
|
+
const px = parseFloat(toPixels(raw, "0px"));
|
|
18
|
+
measured = { raw, px: Number.isFinite(px) && px > 0 ? px : null };
|
|
19
|
+
}
|
|
20
|
+
return measured.px;
|
|
21
|
+
}
|
package/src/editor/index.ts
CHANGED
|
@@ -21,6 +21,8 @@ export type { RichTextDocument } from "./core/jsonDocument.js";
|
|
|
21
21
|
export { useRichTextEditorState } from "./hooks/useRichTextEditorState.js";
|
|
22
22
|
export { RichTextView } from "./RichTextView.js";
|
|
23
23
|
export type { RichTextViewProps } from "./RichTextView.js";
|
|
24
|
+
export { RichTextToc } from "./features/toc/RichTextToc.js";
|
|
25
|
+
export type { RichTextTocProps } from "./features/toc/RichTextToc.js";
|
|
24
26
|
export type { FieldNotice, FieldNoticeTone } from "./core/fieldNotice.js";
|
|
25
27
|
export type { RichTextSurface } from "./styles/surface.js";
|
|
26
28
|
export { richTextSanitizeConfig, richTextSchema, sanitizeRichText } from "./core/schema.js";
|
package/src/i18n/defaults.ts
CHANGED
package/src/i18n/messages.ts
CHANGED
|
@@ -1080,6 +1080,11 @@ export interface UiMessages {
|
|
|
1080
1080
|
blockMoveDown: string;
|
|
1081
1081
|
blockDuplicate: string;
|
|
1082
1082
|
blockDelete: string;
|
|
1083
|
+
/**
|
|
1084
|
+
* Оглавление Документа (`RichTextToc`): имя кнопки-полосы и подпись
|
|
1085
|
+
* `nav` со списком заголовков — одно слово на оба, это одна вещь.
|
|
1086
|
+
*/
|
|
1087
|
+
toc: string;
|
|
1083
1088
|
};
|
|
1084
1089
|
}
|
|
1085
1090
|
|