Набор для встраивания: структура, события, меню
Модель доступа без DOM, структурные проекции книги, события щелчка и выбора, вклад в контекстное меню и команды вместо прямой записи.
| Статус | Объект | Что это означает |
|---|---|---|
| Есть сейчас | Контракт операций в ядре | Чтение структуры, ячеек и объектов, типизированные операции изменения. |
| Есть сейчас | Обработка действий в поверхности | Определение попадания, щелчки и вызов меню, выделение и внутренние смысловые события. |
| Требует оформления | Публичный набор для встраивания | Устойчивые методы и события, добавление своих пунктов меню, права и версионирование. |
Какой API нужен для встраивания
Заголовок раздела «Какой API нужен для встраивания»- Чтение — узнать состав книги, выделение, ячейку, объект.
- События — реагировать на действия пользователя.
- Команды — безопасно изменять книгу.
- Расширение интерфейса — добавлять свои команды и пункты меню.
Не DOM документа, а структурные проекции и команды
Заголовок раздела «Не DOM документа, а структурные проекции и команды»Таблица в F1 не выложена в разметку страницы как дерево элементов. Она рисуется на полотне, а в памяти держится только видимая часть книги — поэтому нужной ячейки или объекта в разметке может не быть вовсе, даже когда пользователь их видит. Обращаться нужно к логической структуре через набор вызовов.
| Объект | Что даёт | Откуда берутся данные |
|---|---|---|
| WorkbookSession | Идентификаторы книги и сеанса, ревизия, признак несохранённых изменений, активный лист, доступные форматы. | Сеанс ядра. |
| WorkbookInfo | Листы с устойчивыми идентификаторами, их имена, видимость и какой лист активен. | Проекция из ядра. |
| Selection | Лист, выделенный диапазон, активная ячейка и идентификаторы выбранных объектов. | Определение попадания в поверхности плюс идентификаторы из ядра. |
| CellDetails | Хранимое значение, отображаемое значение, формула, тип, формат, проверка ввода, примечание и ссылка. | Операция read_cell_details. |
| RangeSnapshot | Ограниченный участок: значения, формулы, стили и сопутствующие данные. | Запрос к ядру с явными границами участка. |
| ObjectInventory | Фигуры, диаграммы, изображения, элементы управления, их привязки, порядок наложения и доступные действия. | Опись объектов из файла. |
| ContextTarget | Что находится под указателем: ячейка, таблица, диаграмма, фигура, заголовок. | Смысловое определение попадания. |
Главное правило
Заголовок раздела «Главное правило»Так предлагается назвать публичные вызовы — в текущем контракте таких имён нет.
const session = await F1.open({ mount, documentId, bytes, mode: "edit"});
const workbook = await session.getWorkbookInfo();const selection = await session.getSelection();const cell = await session.getCellDetails(selection.activeCell);Как получить листы, диапазон, таблицу и графический объект
Заголовок раздела «Как получить листы, диапазон, таблицу и графический объект»| Задача | Предлагаемый вызов | Что вернётся |
|---|---|---|
| Получить листы | session.getWorkbookInfo() |
Список листов с идентификаторами, именами, видимостью и порядком. |
| Прочитать ячейку | session.getCellDetails(...) |
Хранимое и отображаемое значение, формула, тип, стиль и сопутствующие данные. |
| Прочитать диапазон | session.getRangeSnapshot(...) |
Значения, формулы и стили запрошенного участка — без всей книги. |
| Узнать таблицу | session.getTableAt(...) |
Идентификатор таблицы, её диапазон, столбцы, фильтры, итоги и доступные действия. |
| Получить объекты | session.getObjects(...) |
Опись объектов с идентификаторами, типами, привязками, порядком наложения и признаком изменяемости. |
| Узнать объект под точкой | session.hitTest(...) |
Что находится под указателем: вид объекта и его устойчивый идентификатор. |
Пример: найти диаграмму и переименовать через команду
const objects = await session.getObjects({ sheetId });const chart = objects.find(x => x.type === "chart");
if (chart?.capabilities.rename) { await session.execute({ operation: "renameObject", objectId: chart.stableId, name: "План перевозок", expectedRevision: session.revision });}Что проекция ядра отдаёт уже сейчас
Заголовок раздела «Что проекция ядра отдаёт уже сейчас»Открытие книги уже возвращает активный лист, список листов, видимую область, предпросмотр ячеек, сведения о таблицах и опись объектов. Для каждого объекта доступны устойчивый идентификатор, лист, тип, имя, привязка, связи с другими частями, порядок наложения, видимость, блокировка и перечень допустимых изменений. Для отдельной ячейки есть операция read_cell_details.
Щелчки, выделение и действия с объектами
Заголовок раздела «Щелчки, выделение и действия с объектами»| Событие | Когда приходит | Основные поля |
|---|---|---|
selectionChanged |
Выделение изменилось и это подтверждено. | новое и прежнее выделение, источник изменения, ревизия. |
cellActivated |
Одиночный щелчок или касание сделали ячейку активной. | ссылка на ячейку, диапазон, нажатые клавиши-модификаторы, источник. |
cellDoubleClicked |
Двойной щелчок по ячейке — после того, как определено, во что именно попали. | ссылка на ячейку, намерение правки, клавиши-модификаторы. |
objectSelected |
Выбрана фигура, диаграмма, картинка или элемент управления. | устойчивый идентификатор, тип объекта, привязка, доступные действия. |
objectDoubleClicked |
Двойной щелчок по графическому объекту. | сам объект, действие по умолчанию, клавиши-модификаторы. |
contextMenuOpening |
Щелчок правой кнопкой или долгое нажатие на телефоне. | объект под указателем, выделение, встроенные пункты меню, доступные действия. |
workbookChanged |
Ядро применило изменение. | новая ревизия, какая операция, что изменилось, признак несохранённых изменений. |
operationRefused |
Ядро отказало — до того, как что-либо изменилось. | код и текст отказа, объект, текущая ревизия. |
Подписка на смысловые события
const unsubscribe = session.on("cellDoubleClicked", async event => { const details = await session.getCellDetails(event.cellRef); hostPanel.open({ documentId, cell: details });});
session.on("objectSelected", event => { propertiesPanel.show(event.target);});
// При закрытии интеграции:unsubscribe();Порядок обработки жеста
Заголовок раздела «Порядок обработки жеста»указатель или касание → определение попадания → подтверждение выделения → смысловое событие → действие по умолчанию
Как менять меню в зависимости от выбранного элемента
Заголовок раздела «Как менять меню в зависимости от выбранного элемента»Искать внутренний элемент меню в разметке и вставлять туда кнопку не нужно. Вместо этого вы регистрируете поставщика пунктов меню: перед показом F1 определяет, что находится под указателем, и запрашивает у вас дополнительные пункты.
| ContextTarget.kind | Примеры данных контекста |
|---|---|
| cell / range | sheetId, address, valueType, formula, validation, comment, hyperlink, protected. |
| table | tableId, name, range, columnId, totals/filter state, mutation capabilities. |
| chart | objectId, chartType, source range, anchor, editable capabilities. |
| shape / image | objectId, anchor, zOrder, groupId, metadata, supported mutations. |
| rowHeader / columnHeader | track index, hidden state, size, protection. |
sheetTab |
sheetId, name, visibility, active/grouped state. |
| canvas | sheetId, pointer coordinates, no semantic object. |
Пример menu contribution для строки таблицы
session.contextMenu.registerProvider(async context => { if (context.target.kind !== "table") return [];
return [{ id: "partner.open-shipment-card", label: "Открыть карточку перевозки", icon: "external-link", enabled: Boolean(context.target.rowKey), group: "partner", order: 20, run: () => host.openCard(context.target.rowKey) }];});Правила расширения меню
Заголовок раздела «Правила расширения меню»-
У пункта есть собственное имя с вашей приставкой, переводимая подпись, необязательный значок, группа, порядок в ней и правило, по которому он включён или виден.
-
Поставщик пунктов получает безопасный снимок обстановки, а не внутреннюю разметку и не всю книгу.
-
Встроенные команды остаются за F1; вы добавляете свои пункты и в оговорённых местах заменяете разрешённые.
-
Если ваш поставщик пунктов думает слишком долго, ожидание обрывается: меню не должно зависнуть из-за вашей серверной части.
Команды вместо прямой записи в структуру
Заголовок раздела «Команды вместо прямой записи в структуру»Любая операция, меняющая документ, проходит через контракт операций в ядре. Так поведение остаётся одинаковым в браузере, в настольном приложении и на сервере, а история изменений — целостной.
| Шаг | Что происходит |
|---|---|
| 1. Собрать намерение | Имя операции, устойчивая ссылка на объект или диапазон, параметры и ожидаемая ревизия. |
| 2. Проверить доступ | Режим только для чтения, защита листа, объявленные возможности, формат исходного файла и правила сеанса. |
| 3. Передать ядру | Тот же контракт — через сборку для браузера, настольный процессор или серверную службу. |
| 4. Применить целиком | При успехе меняются ревизия и история; при отказе книга остаётся нетронутой — половины правки не бывает. |
| 5. Отдать результат | Новая проекция и событие об изменении книги — либо событие об отказе. |
Пример правки с проверкой ревизии
const result = await session.execute({ operation: "setCellValue", target: { sheetId, row: 12, col: 4 }, value: { kind: "string", value: "Доставлено" }, expectedRevision: session.revision});
if (!result.ok && result.code.endsWith("-stale-revision")) { await session.refreshProjection();}Запрещённая модель
Заголовок раздела «Запрещённая модель»// НЕЛЬЗЯ: это обходит Rust, историю и сохранение.document.querySelector("[data-cell='E13']").textContent = "Доставлено";session.workbook.sheets[0].cells[12][4].value = "Доставлено";