Перейти к основному содержимому

ErdEditorElement

Редактор — это обычный HTMLElement.
Его определение типа приведено ниже.

interface ErdEditorElement extends HTMLElement {
readonly: boolean;
systemDarkMode: boolean; // system dark/light auto
enableThemeBuilder: boolean;
enableLocalePicker: boolean;
enableWelcomeScreen: boolean;
value: string;
readonly runtimeValue: string;
focus: () => void;
blur: () => void;
clear: () => void;
destroy: () => void;
setInitialValue: (value: string) => void;
setPresetTheme: (themeOptions: Partial<ThemeOptions>) => void;
setSystemAppearance: (appearance: 'dark' | 'light' | null) => void;
setTheme: (theme: Partial<Theme>) => void;
setLocale: (locale: LocaleOption) => void;
setSystemLocale: (locale: string | null) => void;
setKeyBindingMap: (
keyBindingMap: Partial<
Omit<
KeyBindingMap,
| 'edit'
| 'stop'
| 'undo'
| 'redo'
| 'zoomIn'
| 'zoomOut'
| 'zoomReset'
>
>
) => void;
setSchemaSQL: SetSchema;
setSchemaGraphQL: SetSchema;
setSchemaDBML: SetSchema;
setSchemaAML: SetSchema;
setSchemaJSON: (
value: string,
options?: { mode?: 'replace' | 'append' }
) => void;
getSchemaSQL: (
databaseVendor?: DatabaseVendor,
options?: SchemaSQLOptions
) => string;
getSharedStore: (
config?: SharedStoreConfig & {
mouseTracker?: boolean;
focusTracker?: boolean;
}
) => SharedStore;
setDiffValue: (value: string) => void;
}

Редактор отрисовывается в закрытом теневом корне, поэтому editor.shadowRoot равен null, а стили страницы не проникают ни внутрь, ни наружу.
Ни до чего внутри нельзя добраться селектором — вместо этого задавайте стили через setTheme и пользовательские свойства --erd-editor-*.

Атрибутов всего пять: readonly, system-dark-mode, enable-theme-builder, enable-locale-picker и enable-welcome-screen, и у всех пяти значение по умолчанию — false. Последние два появились в версии 4.0.0. Каждый из них читает свое значение так, как описано в разделе readonly.

Начиная с версии 4.1.0 на вкладке ERD есть Обозреватель — дерево диаграммы, закрепленное слева от холста, с Поиском и заменой в верхней части. Ни один атрибут, свойство, метод или событие не открывает и не закрывает его и не сообщает о его состоянии: он открывается кнопкой Explorer на панели инструментов, пунктом Toggle Explorer в быстром поиске или в контекстном меню холста либо привязкой findReplace.
Каждый элемент начинает работу с закрытым Обозревателем. То, открыт ли он, а также его ширина, сворачивание и поиск сохраняются, пока существует элемент, — при переключении вкладок и при любой загрузке, включая setInitialValue, — и никогда не попадают в value, runtimeValue, историю изменений или общее хранилище.

readonly​

Задает возможность редактирования в редакторе.
Пока он установлен, присваивание value, clear(), setSchemaSQL(), setSchemaGraphQL(), setSchemaDBML(), setSchemaAML(), setSchemaJSON(), отмена и повтор игнорируются, а событие change никогда не генерируется. Вместо этого загружайте документ с помощью setInitialValue.
Просмотр по-прежнему работает: масштаб, перемещение, инструмент «Рука», режим дзен, вкладка холста, вкладка «Визуализация» в обоих режимах, включая фокус на таблицах, СУБД и настройки вывода SQL и генератора кода продолжают действовать, поэтому в редакторе только для чтения по-прежнему можно экспортировать SQL для другой СУБД или читать сгенерированный код.
Начиная с версии 4.1.0 открывается и Обозреватель, а выбор одной из его строк ведет к тому, что эта строка обозначает, как и в редакторе, доступном для редактирования. Поиск и замена в его верхней части только ищет, без стрелки Toggle Replace и без строки замены, а переход к совпадению по-прежнему показывает совпадение на экране и выделяет его. Панель называется Explorer, а всплывающая подсказка кнопки на панели инструментов в любом редакторе — Explorer (Ctrl + F) (Windows/Linux) или Explorer (⌘ + F) (Mac). В версиях с 3.10.0 по 4.0.0 Поиск и замена открывался как плавающая панель только для поиска с заголовком Find.
Окно «Свойства таблицы» по-прежнему открывается, и начиная с версии 3.10.0 в нем рядом с заголовком отображается метка Read only, а вкладка Indexes не позволяет ничего изменить — см. Свойства таблицы.
Начиная с версии 4.0.0 редактор только для чтения не предлагает Import and Add, New Table Group, Group selected tables, Remove from group (см. Группы таблиц) и Map Columns, а также не показывает экран приветствия. Кнопки блокировки на вкладке «Настройки» ничего не меняют, а скрипты Before tables и After tables на вкладке «Схема SQL» нельзя редактировать.
Начиная с версии 4.1.0 он также не показывает кнопки New Table, New Memo и New Table Group на панели инструментов холста, а привязки addTableGroup и groupSelectedTables ничего не делают.
Параметры This window only на вкладке «Схема SQL» — Statements, Header и Tables — никогда не сохраняются и по-прежнему действуют, как и окно Export image, конструктор темы и окно выбора языка интерфейса. Выбор в конструкторе темы или в окне выбора языка интерфейса по-прежнему генерирует changePresetTheme или changeLocale.
Атрибут без значения, ="" и ="true" читаются как true. ="false" читается как false, и так же читается любая другая строка — включая принятую в HTML запись readonly="readonly".

editor.readonly = true;
// or
editor.setAttribute('readonly', 'true');
<erd-editor readonly></erd-editor>

systemDarkMode​

Определяет, синхронизироваться ли автоматически с темным или светлым режимом системы.
Начиная с версии 4.0.0 его включение устанавливает appearance темы в 'system', как и setPresetTheme({ appearance: 'system' }). После этого редактор показывает светлое или темное оформление, о котором сообщает операционная система или которое задает setSystemAppearance, и переключается при его изменении.
Последующий вызов setPresetTheme со значением 'light' или 'dark' либо выбор Light или Dark в конструкторе темы или в быстром поиске заменяет 'system' и сохраняется: следующее изменение в ОС его больше не перезаписывает, хотя systemDarkMode по-прежнему равен true. До версии 4.0.0 следующее изменение в ОС его перезаписывало.
Если выключить его, пока оформление равно 'system', сохраняется светлое или темное оформление, показанное в этот момент. Если выключить его после того, как оформление было изменено с 'system' на другое, оформление остается как есть.
Его изменение не генерирует никаких событий.

editor.systemDarkMode = true;
// or
editor.setAttribute('system-dark-mode', 'true');
<erd-editor system-dark-mode></erd-editor>

enableThemeBuilder​

Определяет, доступен ли интерфейс для удобной настройки предустановленных тем.
Он показывает кнопку Theme на панели инструментов, которая открывает конструктор темы с параметрами Accent color, Gray color и Appearance. Начиная с версии 4.0.0 параметр Appearance предлагает System наряду с Light и Dark, а пока этот атрибут включен, быстрый поиск показывает Theme с вариантами System, Light и Dark. См. Язык и тема.

Открытие конструктора темы с панели инструментов, выбор цвета акцента и оттенка серого и переключение оформления на Light, а затем на System

editor.enableThemeBuilder = true;
// or
editor.setAttribute('enable-theme-builder', 'true');
<erd-editor enable-theme-builder></erd-editor>

Изменение предустановленной темы на этой панели или в быстром поиске генерирует событие changePresetTheme.

enableLocalePicker​

Начиная с версии 4.0.0 определяет, доступен ли в редакторе выбор языка интерфейса.
Он показывает кнопку Display Language на панели инструментов — после Theme, когда показаны обе. Кнопка открывает окно выбора языка интерфейса, а быстрый поиск показывает Display Language. И там, и там доступны System и 25 языков — см. Язык и тема.
Он также определяет, что показывает редактор, пока не вызван setLocale и не выбран язык: 'system', пока он включен, и английский, пока он выключен, поэтому элемент, в котором ничего не настроено, остается на английском, как и всегда. Включение или выключение сразу переключает между этими двумя вариантами. Если язык уже задан или выбран, этот выбор сохраняется независимо от того, включен атрибут или выключен.
Установите его до добавления элемента на страницу, чтобы уже первый кадр следовал 'system'.
Выбор языка генерирует changeLocale.

editor.enableLocalePicker = true;
// or
editor.setAttribute('enable-locale-picker', 'true');
<erd-editor enable-locale-picker></erd-editor>

enableWelcomeScreen​

Начиная с версии 4.0.0 определяет, встречает ли пустая диаграмма пользователя экраном приветствия.
Он отображается поверх вкладки ERD, пока в документе нет ни одной таблицы, ни одной показанной заметки и ни одной показанной группы таблиц. Он не показывается, пока установлен атрибут readonly, в режиме дзен, а также пока открыто окно «Свойства таблицы», просмотр различий, путешествие во времени или предварительный просмотр Автоматического размещения. Первая таблица, показанная заметка или показанная группа таблиц убирает его, а отмена, возвращающая к пустой диаграмме, показывает его снова.
Его строки New Table, New Memo и Command Palette показывают первое сочетание клавиш привязок addTable, addMemo и search в том виде, в каком их оставил setKeyBindingMap, а для привязки, оставленной пустой, не показывают ничего. Его стрелки указывают на кнопки Theme и Display Language только там, где их показывают enableThemeBuilder и enableLocalePicker.
В его меню ↑, ↓, Home и End перемещают между строками, и для них отменяется действие по умолчанию и останавливается распространение. Для Enter и Space распространение останавливается, но действие по умолчанию не отменяется, поэтому их получает строка в фокусе, а Escape в списке форматов Import возвращает назад, с отменой действия по умолчанию и остановкой распространения. Все остальные клавиши, как обычно, доходят до редактора и страницы.
Он ничего не меняет в документе, поэтому оставляет value без изменений и не генерирует change.
Включайте его после того, как setInitialValue загрузил документ, как это делают официальные хосты, чтобы экран никогда не мелькал поверх файла, который еще загружается.

editor.enableWelcomeScreen = true;
// or
editor.setAttribute('enable-welcome-screen', 'true');
<erd-editor enable-welcome-screen></erd-editor>

value​

getter​

Возвращает текущий документ в виде строки JSON по схеме, которую определяет редактор.
Начиная с версии 4.0.0 это форма хранения — документ в том виде, в каком его хранит файл; ее же записывает экспорт json и сохраняют официальные хосты. Она содержит только действующие сущности, без удаленных, без порядка наложения и без того, что редактор вычисляет сам, например измеренной ширины, меток ключей и точек привязки связей. Ключи сущностей идут в фиксированном порядке, отступ составляет два пробела, а в конце стоит перевод строки, поэтому один и тот же документ всегда дает одни и те же байты.
Каждая настройка с включенной блокировкой записывается с заблокированным значением, а не так, как ее показывает экран. Блокировка Viewport удерживает originX, originY и zoomLevel, а Canvas Type, Language, Table Name Case, Column Name Case и Bracket Type удерживают каждая свою настройку. Все остальные настройки записываются как есть, а lockSettings записывается всегда. О битах см. Settings.
В новом документе включены все блокировки — будь то документ, который элемент показывает до получения значения, или документ, загруженный из пустого значения. Его value сохраняет начало координат 0, 0, масштаб 1, вкладку ERD, а также язык Генератора кода, стили имен и тип кавычек по умолчанию, пока не выключена соответствующая блокировка.
До версии 4.0.0 он возвращал весь документ в том виде, в каком его хранил редактор, с учетом ignoreSaveSettings. Документ в том виде, в каком его хранит редактор, теперь возвращает runtimeValue, а ignoreSaveSettings больше не читается и не записывается.

const data = editor.value;

setter​

Загружает ранее сохраненное состояние редактора. Он заменяет весь документ — текущий сначала очищается.
Как и clear(), setInitialValue() и методы setSchema* в режиме по умолчанию mode: 'replace', он также сбрасывает вид Flow на вкладке «Визуализация»: его размещение, таблицы, до которых он сужен, отображение строк, масштаб и перемещение. Добавление (mode: 'append') его не сбрасывает.
Он записывается в историю изменений, что позволяет выполнить Undo, Redo, и генерирует change.
Он принимает форму хранения, runtimeValue или файл, сохраненный более ранней версией.
Пустая строка или любое значение, не являющееся строкой, загружает новый документ, а не вызывает ошибку, поэтому проверяйте значение перед присваиванием.
Это тот же новый документ, который создает setInitialValue(''): пустой, с настройками по умолчанию и начиная с версии 4.0.0 со всеми включенными блокировками. В версиях 3.10.x он не сохранял ни положение прокрутки, ни масштаб, а до них сохранял и то и другое.
Общее хранилище передает эту загрузку соавторам вместе с полным JSON нового документа, поэтому каждый участник, включая участников с более старой версией, загружает один и тот же документ.
Начиная с версии 4.0.0 блокировки загруженного документа и заблокированные значения, которые затем записывает value, берутся из текста, а вид оказывается там, где его располагает текст, либо на диаграмме, если в этом месте не отрисована ни одна ее часть. Для каждой из остальных настроек, которые блокирует текст, — вкладки, языка Генератора кода, стилей имен и типа кавычек — редактор продолжает показывать то же, что показывал до загрузки. Настройка, которую текст оставляет незаблокированной, принимает значение из текста. setInitialValue, напротив, принимает все значения из текста; о тексте, в котором не указаны блокировки, см. также там.
Текст, не являющийся JSON, например файл с оставшимися маркерами конфликта слияния, тоже не вызывает ошибку: документ очищается, его настройки остаются прежними, а ошибка разбора выводится в консоль.
Пока установлен атрибут readonly, присваивание игнорируется; чтобы загрузить документ в редактор только для чтения, используйте setInitialValue.

editor.value = 'json...';

runtimeValue​

Начиная с версии 4.0.0 возвращает документ в том виде, в каком его хранит этот редактор, в виде строки JSON. У него нет сеттера, поэтому присваивание в коде в строгом режиме выбрасывает исключение.
Оно содержит то, что опускает value: удаленные сущности и их порядок, порядок наложения, измеренную ширину, метки ключей, точки привязки связей и последовательности. Заблокированные настройки и здесь записываются с заблокированными значениями.
Используйте его, чтобы через setInitialValue инициализировать другой редактор, который подключается к уже идущему сеансу, например редактор соавтора или второй вид того же документа. В этом случае отмена удаления, которую сеанс отправит позже, восстановит там сущность целиком, тогда как редактор, инициализированный из value, не содержит удаленных сущностей и вместо этого восстановит пустую безымянную таблицу. См. Совместное редактирование.
Сборщик мусора больше не убирает удаленные сущности, поэтому они остаются в нем до следующего открытия документа из файла.
Никогда не записывайте его в файл: сохраняйте value, который принимает JSON Schema, в отличие от этого значения.

otherEditor.setInitialValue(editor.runtimeValue);

setInitialValue​

Загружает ранее сохраненное состояние редактора. Сама загрузка не записывается в историю изменений, поэтому ее нельзя отменить, и событие change не генерируется.
Он также очищает историю изменений, поэтому ничего из сделанного до загрузки нельзя отменить или повторить в загруженном документе.
Он принимает форму хранения, runtimeValue или файл, сохраненный более ранней версией, и, в отличие от присваивания value, принимает все настройки из текста, включая вкладку и настройки кода.
Пустая строка или любое значение, не являющееся строкой, загружает новый документ, а не вызывает ошибку, поэтому setInitialValue('') создает пустую диаграмму.
Начиная с версии 4.0.0 в этом новом документе, который элемент также показывает до получения какого-либо значения, включены все блокировки. Прокрутка, масштабирование, переключение вкладок и изменение языка Генератора кода, стилей имен или типа кавычек оставляют value без изменений и не генерируют change. В версиях 3.10.x он не сохранял ни положение прокрутки, ни масштаб, а до них сохранял и то и другое.
Документ, загруженный из текста, сохраняет указанные в нем блокировки. Документ, в котором блокировки не указаны, — любой файл, сохраненный до версии 4.0.0, независимо от значения его ignoreSaveSettings, и файл .vuerd v2 — открывается со всеми включенными блокировками, с Viewport, заблокированным в начале координат 0, 0 и с масштабом 1, на вкладке ERD, а язык, стили имен и тип кавычек остаются такими, какими он их сохранил.
В обоих случаях вид открывается в положении вида документа — сохраненном в тексте, если в нем указаны блокировки, или в начале координат 0, 0 с масштабом 1, если они не указаны, — либо на диаграмме, если в этом месте не отрисована ни одна ее часть. Заблокированный Viewport по-прежнему сохраняет свои заблокированные значения в value.
Начиная с версии 4.0.0 он также сбрасывает состояние совместной работы прежнего документа, а уже подписанное общее хранилище этого редактора снова запрашивает состояние у других редакторов, поэтому редактор, перезагруженный в идущем сеансе, догоняет остальных. Инициализируйте такой редактор значением runtimeValue другого редактора.
Текст, не являющийся JSON, тоже не вызывает ошибку: документ очищается, его настройки остаются прежними, а ошибка разбора выводится в консоль.
В отличие от присваивания value, его не блокирует атрибут readonly, поэтому именно так документ загружается в редактор только для чтения.

editor.setInitialValue('json...');

Загрузка при запуске, сохранение при изменении.

editor.setInitialValue(localStorage.getItem('my-diagram') ?? '');
editor.addEventListener('change', () => {
localStorage.setItem('my-diagram', editor.value);
});

События​

Публичных событий всего три: change, changePresetTheme и changeLocale; событие changeLocale появилось в версии 4.0.0.
Элемент также отправляет сам себе внутренние события @dineug/erd-editor/internal-* для собственной внутренней работы; они не входят в API.

change​

При изменениях в редакторе генерируется событие.
Событие генерируется с задержкой (debounce) 200 мс и не генерируется, пока readonly равен true.
Оно возникает при любом изменении документа — правке в интерфейсе, присваивании value, clear(), вызове каждого из методов setSchema*, а начиная с версии 4.0.0 и при setSchemaJSON() и Import and Add. setInitialValue его не генерирует.
Ничто из сделанного в режиме Flow на вкладке «Визуализация» его не генерирует — ни масштабирование, ни перемещение вида, ни перемещение карточек, ни Tidy Up, ни отображение строк, ни сужение вида с карточки, — поскольку ничто из этого не является изменением документа.
Начиная с версии 4.0.0 его не генерирует и изменение настройки с включенной блокировкой, потому что оно затрагивает только экран и никогда не затрагивает value: прокрутка или масштабирование холста ERD, пока заблокирован Viewport, переключение вкладки, пока заблокирован Canvas Type, и изменение языка Генератора кода, стиля имен таблиц, стиля имен столбцов или типа кавычек, пока включена собственная блокировка этой настройки. Не учитываются только эти изменения, поэтому пакет изменений, который также правит документ, все равно его генерирует. Блокировка или разблокировка настройки его генерирует.
В новом документе и в любом файле, сохраненном до версии 4.0.0, включены все блокировки, поэтому по умолчанию прокрутка, масштабирование и переключение вкладок ничего не генерируют. Это относится к фокусу на таблицах с вкладки ERD, к кнопке карточки со значком внешней ссылки, которая возвращает из режима Flow на вкладку ERD, к переходу к строке Обозревателя или к совпадению поиска, а также к открытию Обозревателя или переходу к результату быстрого поиска с другой вкладки. Каждое из этих действий генерирует одно событие change, только пока выключена охватывающая его блокировка: Canvas Type — для переключения вкладки и Viewport — для прокрутки, которую также выполняют кнопка карточки, результат быстрого поиска, строка Обозревателя или совпадение поиска. Начиная с версии 4.1.0 каждая из этих прокруток подчиняется одному правилу — Куда ведет переход, — поэтому результат быстрого поиска для таблицы больше не вызывает прокрутку каждый раз, а переход, при котором правило оставляет вид на месте, не создает прокрутки, которая могла бы сгенерировать событие. Открытие, закрытие или изменение ширины Обозревателя сужает или расширяет холст, не сдвигая его начало координат, и тоже ничего не генерирует. До версии 4.0.0 прокрутка, масштабирование и переключение вкладок всегда его генерировали, даже если editor.value оставался прежним.
Чтобы пропускать записи, которые ничего не меняют, сравнивайте editor.value со значением, которое вы сохранили последним, а не с загруженным файлом: файл, записанный более ранней версией, файл v2 или файл, отредактированный вручную, может дать в value другой результат сразу после загрузки, потому что value записывает его в форме хранения. То же может произойти с файлом, у которого блокировка Viewport выключена, а начало координат на этом экране не показывает ни одной части диаграммы: загрузка перемещает вид на диаграмму, и value записывает то место, где он оказался. Начиная с версии 4.0.0 измеренная ширина больше к этому не приводит, потому что value ее не содержит. Хост, который записывает файлы, может вместо этого отличать правку от изменения вида с помощью changed хранилища репликации — см. on@change.
Событие не содержит detail, не всплывает и не пересекает границу теневого корня, поэтому подписывайтесь на сам элемент и читайте editor.value в обработчике.

editor.addEventListener('change', event => {
const data = event.target.value;
});

changePresetTheme​

Возникает, когда предустановленная тема изменяется во встроенном конструкторе темы или начиная с версии 4.0.0 через Theme в быстром поиске. Его генерирует каждый выбор, в том числе выбор уже действующего варианта.
Программный вызов setPresetTheme или setSystemAppearance, а также включение или выключение systemDarkMode его не генерируют.
event.detail содержит полный объект ThemeOptions после выбора — { appearance, grayColor, accentColor }, — а не запрошенный частичный объект. Начиная с версии 4.0.0 его appearance равен 'system', пока выбран System, а не показываемому светлому или темному оформлению, поэтому сохраняйте его как есть и передавайте обратно в setPresetTheme.

editor.addEventListener('changePresetTheme', event => {
const themeOptions = event.detail;
});

changeLocale​

Начиная с версии 4.0.0 возникает, когда язык выбирается в редакторе — в окне выбора языка интерфейса или через Display Language в быстром поиске; оба способа включает enableLocalePicker.
Оно возникает после применения языка, при каждом выборе, в том числе при выборе уже действующего варианта. setLocale и setSystemLocale никогда его не генерируют, как и изменение языков браузера. Смена языка не генерирует change.
event.detail — это { locale }, значение типа LocaleOption: 'system', если выбран System, иначе код языка. Элемент не запоминает выбор, поэтому сохраните его и передайте в setLocale при следующей загрузке.
Как и change, оно не всплывает, поэтому подписывайтесь на сам элемент.

editor.addEventListener('changeLocale', event => {
const { locale } = event.detail; // 'system' | 'ko-KR' | ...
});

focus​

Устанавливает фокус на редактор.

editor.focus();

blur​

Снимает фокус с редактора.

editor.blur();

clear​

Очищает документ, удаляя все таблицы, столбцы, связи, индексы и заметки, а начиная с версии 4.0.0 и все группы таблиц.
Все настройки сохраняются, включая базу данных, положение вида, масштаб, параметры вида таблиц, каждую блокировку с ее значением и скрипты Before tables и After tables на вкладке «Схема SQL», поэтому очищенный файл продолжает сохранять то же, что и раньше. Чтобы вместо этого начать новый документ, присвойте '' свойству value или вызовите setInitialValue('').
Он записывается в историю изменений, поэтому его можно отменить, и генерирует change. Отмена возвращает документ в том виде, в каком его хранил редактор, причем каждая заблокированная настройка получает свое заблокированное значение. Пока установлен атрибут readonly, он игнорируется.

editor.clear();

destroy​

Полностью уничтожает экземпляр редактора, после чего его нельзя использовать повторно.
Он освобождает обработчики и подписки редактора и уничтожает все общие хранилища, возвращенные getSharedStore.
Пакет потока, который общее хранилище еще удерживает, отбрасывается вместе с ним; чтобы отправить его, сначала вызовите flushStreamBuffers этого хранилища.

editor.destroy();

setKeyBindingMap​

Переопределяет сочетания клавиш.
edit, stop, undo, redo, zoomIn, zoomOut и zoomReset фиксированы, и их нельзя переопределить.
Учитывается только двадцать одно имя из списка ниже; все остальное в объекте игнорируется, в том числе фиксированные имена.
Начиная с версии 3.10.0 привязку search можно переопределить, и появилась привязка findReplace. Раньше привязка search была фиксированной. В версии 4.0.0 появилась привязка removeSelection. В версии 4.1.0 появились addTableGroup и groupSelectedTables.
Значение привязки должно быть массивом ShortcutOption[]. Строка сама по себе игнорируется, поэтому пишите { addTable: [{ shortcut: 'Alt+KeyN' }] }, а не { addTable: 'Alt+KeyN' }.
Пустой массив допускается и ничего не привязывает: setKeyBindingMap({ findReplace: [] }) оставляет Ctrl + F (Windows/Linux) или ⌘ + F (Mac) странице, а { search: [] } делает то же для Ctrl + K (Windows/Linux) или ⌘ + K (Mac). Кнопка Search на панели инструментов по-прежнему открывает быстрый поиск, кнопка Explorer на панели инструментов по-прежнему открывает и закрывает Обозреватель, а пункт Toggle Explorer в быстром поиске и в контекстном меню холста по-прежнему открывает Обозреватель с поиском или закрывает его; ни один из них не показывает сочетание клавиш для имени, оставленного пустым. { removeSelection: [] } оставляет Delete и Backspace странице, и тогда пункты удаления в меню таблицы, заметки и группы таблиц (Delete, Delete selected, Delete column, Delete columns) не показывают сочетание клавиш.
Начиная с версии 4.1.0 значение { addTableGroup: [] } оставляет странице Alt + G (Windows/Linux) или ⌥ + G (Mac), а { groupSelectedTables: [] } — T, затем G. New Table Group на панели инструментов холста, в контекстном меню холста и в быстром поиске, Group selected tables в меню таблицы и Group Selected Tables в быстром поиске по-прежнему работают, но сочетание клавиш не показывается. Всплывающие подсказки кнопок New Table, New Memo и New Table Group на панели инструментов холста называют первое сочетание клавиш привязок addTable, addMemo и addTableGroup, а для привязки, оставленной пустой, — только саму кнопку.
Вызов выполняет частичное слияние: имена, которые вы не указали, сохраняют значения по умолчанию, а повторный вызов сохраняет предыдущие изменения. Геттера для текущих привязок нет: createKeyBindingMap возвращает значения по умолчанию, а не то, что изменил setKeyBindingMap.

type ShortcutOption = {
shortcut: string;
preventDefault?: boolean;
stopPropagation?: boolean;
};

const defaultKeyBindingMap: Omit<
KeyBindingMap,
| 'edit'
| 'stop'
| 'undo'
| 'redo'
| 'zoomIn'
| 'zoomOut'
| 'zoomReset'
> = {
search: [
{ shortcut: '$mod+KeyK', preventDefault: true, stopPropagation: true },
],
findReplace: [
{ shortcut: '$mod+KeyF', preventDefault: true, stopPropagation: true },
],
addTable: [{ shortcut: 'Alt+KeyN', preventDefault: true }],
addColumn: [{ shortcut: 'Alt+Enter', preventDefault: true }],
addMemo: [{ shortcut: 'Alt+KeyM', preventDefault: true }],
addTableGroup: [
{ shortcut: 'Alt+KeyG', preventDefault: true, stopPropagation: true },
],
groupSelectedTables: [{ shortcut: 'KeyT KeyG', preventDefault: true }],
removeTable: [
{ shortcut: '$mod+Backspace', preventDefault: true },
{ shortcut: '$mod+Delete', preventDefault: true },
],
removeColumn: [
{ shortcut: 'Alt+Backspace', preventDefault: true },
{ shortcut: 'Alt+Delete', preventDefault: true },
],
removeSelection: [
{ shortcut: 'Delete', preventDefault: true },
{ shortcut: 'Backspace', preventDefault: true },
],
primaryKey: [{ shortcut: 'Alt+KeyK', preventDefault: true }],
selectAllTable: [
{ shortcut: '$mod+KeyA', preventDefault: true },
{ shortcut: '$mod+Alt+KeyA', preventDefault: true },
],
selectAllColumn: [{ shortcut: 'Alt+KeyA', preventDefault: true }],
relationshipZeroOne: [{ shortcut: '$mod+Alt+Digit1', preventDefault: true }],
relationshipZeroN: [{ shortcut: '$mod+Alt+Digit2', preventDefault: true }],
relationshipOneOnly: [{ shortcut: '$mod+Alt+Digit3', preventDefault: true }],
relationshipOneN: [{ shortcut: '$mod+Alt+Digit4', preventDefault: true }],
tableProperties: [{ shortcut: 'Alt+Space', preventDefault: true }],
focusView: [
{ shortcut: 'Alt+KeyF', preventDefault: true, stopPropagation: true },
],
handTool: [{ shortcut: 'Space', preventDefault: true }],
zenMode: [
{ shortcut: 'Alt+KeyZ', preventDefault: true, stopPropagation: true },
],
};

// example
editor.setKeyBindingMap({
addTable: [{ shortcut: '$mod+KeyN', preventDefault: true }],
});

selectAllTable, handTool, removeSelection и начиная с версии 4.1.0 groupSelectedTables уступают курсору ввода: пока фокус находится в поле ввода, многострочном поле или элементе contenteditable, $mod + A выделяет текст, Space вводит пробел, Delete и Backspace стирают текст, а T, затем G вводит эти две буквы, вместо того чтобы действовать на холсте. Ни для одного из этих нажатий действие по умолчанию не отменяется. Любые сочетания, на которые вы их переназначите, ведут себя так же.

Начиная с версии 4.0.0 привязка removeSelection (Delete или Backspace) удаляет выделение на вкладке ERD одним шагом отмены, без подтверждения. Если выделена только таблица в фокусе, выделен один или несколько ее столбцов и при текущем масштабе ее строки отрисовываются, привязка удаляет эти столбцы; в противном случае она удаляет все выделенные таблицы, заметки и группы таблиц, сохраняя таблицы групп. См. Удаление таблиц и заметок.
Удерживаемая клавиша удаляет один раз, и ничего не удаляется, пока открыто поле редактирования ячейки, заметки или имени группы таблиц. Вне текстового поля и панелей, которые удерживают привязки (см. createKeyBindingMap), действие по умолчанию для нажатия отменяется на любой вкладке, пока редактор в фокусе, в том числе на кнопке панели инструментов в фокусе, а также в редакторе только для чтения, где ничего не удаляется.

Начиная с версии 4.1.0 привязка addTableGroup (Alt+KeyG) активирует на вкладке ERD рисование группы New Table Group: следующее нажатие основной кнопки мыши на холсте рисует группу, а повторное нажатие сочетания отменяет рисование, как и кнопка New Table Group на панели инструментов холста. Привязка groupSelectedTables (KeyT KeyG, T, затем G) помещает выделенные таблицы в новую группу и открывает поле редактирования ее имени, как и пункт Group selected tables в контекстном меню таблицы. Если ни одна таблица не выделена, она ничего не добавляет; выделенная заметка или группа таблиц не учитывается. См. Рисование группы и Группировка выделенных таблиц.
Обе действуют только там, где меню предлагают группу: они не действуют, пока установлен атрибут readonly, пока параметр вида Table Groups скрывает группы или пока открыто поле редактирования ячейки, заметки или имени группы таблиц. Как и другие привязки холста, они действуют только на вкладке ERD и не действуют, пока открыт быстрый поиск, окно «Свойства таблицы», просмотр различий, путешествие во времени, предварительный просмотр Автоматического размещения, Export image или Map Columns. Там, где они ничего не делают, действие по умолчанию для нажатия все равно отменяется, если только groupSelectedTables не уступает курсору ввода. Для addTableGroup также останавливается распространение, как и для focusView и zenMode, поэтому обработчик keydown на странице в фазе всплытия его никогда не получает.

Начиная с версии 3.10.0 привязка findReplace ($mod+KeyF) открывает Поиск и замену. Начиная с версии 4.1.0 она открывает и закрывает Обозреватель, в котором находится Поиск и замена, а вкладка «Сочетания клавиш» показывает ее как Toggle Explorer.
Пока кнопка Explorer на панели инструментов отображается нажатой (Обозреватель открыт на вкладке ERD и не скрыт режимом дзен), привязка закрывает Обозреватель, если только не открыт быстрый поиск, окно «Свойства таблицы», конструктор темы, окно выбора языка интерфейса, окно Export image или Map Columns. В противном случае она закрывает то из них, что открыто, переключает на вкладку ERD с любой другой вкладки и открывает Обозреватель с курсором ввода в поле Find и выделенным запросом. Редактор, слишком узкий, чтобы показать Обозреватель рядом с холстом, оставляет его открытым, но скрытым, и показывает уведомление Widen the window to show the Explorer. До версии 4.1.0 она открывала плавающую панель Поиска и замены или возвращала фокус клавиатуры в ее поле и никогда ее не закрывала.
Она не уступает курсору ввода: пока редактор в фокусе, она срабатывает на любой вкладке — с холста или из поля ввода внутри редактора. Действие по умолчанию для нажатия отменяется, поэтому браузер не открывает панель поиска, а распространение останавливается, поэтому ни один обработчик keydown на странице в фазе всплытия его не получает. Если открыто поле редактирования ячейки или заметки либо начиная с версии 4.0.0 поле редактирования имени группы таблиц, действие по умолчанию по-прежнему отменяется и распространение останавливается, но привязка ничего не делает.
Пока открыт просмотр различий, путешествие во времени или предварительный просмотр Автоматического размещения, на какой бы вкладке это ни было, или пока метод ввода (IME) еще выполняет набор, для нажатия не отменяется действие по умолчанию и не останавливается распространение, поэтому его получает собственный поиск браузера или хоста. Внутри Обозревателя распространение нажатия, сделанного во время набора, останавливается, хотя действие по умолчанию не отменяется. Любое сочетание, на которое вы переназначите findReplace, ведет себя так же.

Привязка focusView действует только на вкладке ERD. Если выделена хотя бы одна таблица, она открывает вкладку «Визуализация» в режиме Flow с видом, суженным до этих таблиц и всех таблиц на расстоянии одной связи от них; выделенная заметка или группа таблиц не учитывается, а если не выделено ни одной таблицы, привязка ничего не делает. См. Фокус на таблицах.

Привязка stop (Escape) на вкладке ERD закрывает открытое поле редактирования ячейки или заметки либо завершает рисование связи и оставляет выделение как есть. Начиная с версии 4.0.0 она также закрывает поле редактирования имени группы таблиц, не записывая имя, и завершает рисование группы New Table Group. Для этого нажатия редактор вызывает preventDefault().
Если ничего из этого не открыто, Escape снимает выделение и сбрасывает ячейку в фокусе, а действие по умолчанию не отменяется. Поэтому, чтобы выйти из редактирования и снять выделение, нужно нажать клавишу дважды.
Кроме Обозревателя, форматов Import на экране приветствия и описанных ниже окон выбора и диалоговых окон, редактор никогда не останавливает распространение Escape, поэтому страница, которая сама отслеживает эту клавишу, например чтобы закрыть собственное окно, получает оба нажатия и может пропустить то, у которого defaultPrevented равен true.
Пока открыт быстрый поиск, окно свойств таблицы, просмотр различий, предварительный просмотр Автоматического размещения или путешествие во времени, Escape вместо этого закрывает его и оставляет выделение как есть. Для этого нажатия действие по умолчанию тоже не отменяется.
Начиная с версии 4.0.0 открытое окно Export image или Map Columns тоже обрабатывает Escape: оно закрывается и оставляет выделение как есть. Каждое из них при открытии получает фокус клавиатуры, и для такого нажатия Escape отменяется действие по умолчанию и останавливается распространение.
Начиная с версии 4.1.0 нажатие Escape, когда фокус находится внутри Обозревателя — в его дереве, полях или кнопках, — возвращает фокус клавиатуры холсту, оставляя Обозреватель открытым, а выделение — без изменений. Редактор вызывает для него и preventDefault(), и stopPropagation(), поэтому оно никогда не доходит до обработчика keydown на странице в фазе всплытия.
Нажатие Escape на холсте никогда не закрывает Обозреватель. До версии 4.1.0 нажатие Escape внутри панели Поиска и замены закрывало ее, а нажатие на холсте закрывало ее одновременно со снятием выделения.
Начиная с версии 4.0.0 окно выбора языка интерфейса и окно выбора цвета закрываются по Escape: внутри них для нажатия отменяется действие по умолчанию и останавливается распространение, а на холсте нажатие закрывает их одновременно со снятием выделения, без отмены действия по умолчанию и без остановки распространения.
Нажатие Escape, пока метод ввода (IME) еще выполняет набор, относится к набору. Оно оставляет открытое поле редактирования как есть, и действие по умолчанию не отменяется, поэтому страница также может пропустить нажатие, у которого isComposing равен true или keyCode равен 229. Внутри Обозревателя распространение такого нажатия, как и любой клавиши, нажатой там во время набора, также останавливается, и фокус клавиатуры остается в поле.
До версии 3.9.2 одно нажатие Escape и завершало редактирование или рисование, и снимало выделение, а редактор никогда не отменял для него действие по умолчанию.

createKeyBindingMap​

Начиная с версии 3.9.2 пакет экспортирует функцию createKeyBindingMap(), а вместе с ней типы KeyBindingMap, KeyBindingName и ShortcutOption.
Она возвращает привязки клавиш по умолчанию — все 28 имен, включая фиксированные, — при каждом вызове в виде новой карты, поэтому изменение возвращенной карты больше ничего не меняет.
С этой карты начинает каждый редактор, а вызов setKeyBindingMap в ней не отражается.
Только createKeyBindingMap экспортируется как значение времени выполнения; остальные три — типы.

type KeyBindingName =
| 'edit'
| 'stop'
| 'search'
| 'findReplace'
| 'undo'
| 'redo'
| 'addTable'
| 'addColumn'
| 'addMemo'
| 'addTableGroup'
| 'groupSelectedTables'
| 'removeTable'
| 'removeColumn'
| 'removeSelection'
| 'primaryKey'
| 'selectAllTable'
| 'selectAllColumn'
| 'relationshipZeroOne'
| 'relationshipZeroN'
| 'relationshipOneOnly'
| 'relationshipOneN'
| 'tableProperties'
| 'focusView'
| 'zoomIn'
| 'zoomOut'
| 'zoomReset'
| 'handTool'
| 'zenMode';

type KeyBindingMap = Record<KeyBindingName, ShortcutOption[]>;

declare function createKeyBindingMap(): KeyBindingMap;

// example
import { createKeyBindingMap } from '@dineug/erd-editor';

const shortcuts = Object.values(createKeyBindingMap())
.flat()
.map(({ shortcut }) => shortcut); // 'Enter', 'Escape', '$mod+KeyK', ...

Каждое значение shortcut — это сочетание клавиш в синтаксисе tinykeys, где клавиша указывается по KeyboardEvent.code, а $mod означает ⌘ в macOS и Control в остальных системах.
Начиная с версии 4.0.0 редактор разбирает эти сочетания сам, а не через tinykeys, в том же синтаксисе. Клавиша совпадает по своему code или по key в любом регистре, а нажатие совпадает, только если зажаты ровно те клавиши-модификаторы, которые указаны в сочетании. AltGraph считается нажатием Control и Alt в Windows и нажатием Alt в macOS. Нажатия, разделенные пробелом, образуют последовательность, которая начинается заново после секунды без события keydown.
Начиная с версии 4.1.0 одна из привязок по умолчанию — последовательность: groupSelectedTables равна KeyT KeyG, т. е. T, затем G. Последовательность срабатывает на нажатии, которое ее завершает, и только к этому нажатию применяются ее preventDefault и stopPropagation, поэтому при значениях по умолчанию T доходит до страницы, а действие по умолчанию отменяется только для G. Меню, быстрый поиск и вкладка «Сочетания клавиш» показывают последовательность по одной клавише на каждое нажатие.
Фиксированные имена привязаны к Enter (edit), Escape (stop), $mod+KeyZ (undo), $mod+Shift+KeyZ (redo), $mod+Equal (zoomIn), $mod+Minus (zoomOut) и $mod+Digit0 (zoomReset). У edit и stop нет флагов; у остальных пяти есть preventDefault и stopPropagation. Остальные привязки — это значения по умолчанию, приведенные выше, в том числе search и findReplace.

Редактор отслеживает эти сочетания на собственном элементе, поэтому хост, который перехватывает клавиши раньше редактора — глобальными горячими клавишами или обработчиком keydown в фазе перехвата, — должен пропускать их, пока редактор в фокусе.
Составляйте список пропускаемых сочетаний на основе createKeyBindingMap(), заменяя значения по умолчанию привязками, которые вы передали в setKeyBindingMap.
Начиная с версии 3.10.0 в этот список входит $mod+KeyF — собственное сочетание поиска браузера. Хост, который хочет оставить на этом сочетании свой собственный поиск, вызывает setKeyBindingMap({ findReplace: [] }).
Начиная с версии 4.0.0 в него также входят Delete и Backspace без модификаторов. Хост, который хочет оставить эти клавиши себе, вызывает setKeyBindingMap({ removeSelection: [] }).
Начиная с версии 4.1.0 в него также входят Alt+KeyG и последовательность KeyT KeyG, которая приходит одной строкой: разделите ее по пробелу и пропускайте каждое нажатие, включая T и G без модификаторов, поскольку последовательность, в которой не хватает нажатия, никогда не завершается. Хост, который хочет оставить эти клавиши себе, вызывает setKeyBindingMap({ addTableGroup: [] }) или setKeyBindingMap({ groupSelectedTables: [] }).

Пока фокус находится внутри Обозревателя — в его дереве, полях Find и Replace или кнопках, — findReplace, search, undo, redo, zoomIn, zoomOut и zoomReset проходят к редактору, поэтому findReplace действует там так же, как на холсте. Все остальные привязки в их текущем виде останавливаются в Обозревателе (последовательность — на последнем нажатии, при значениях по умолчанию это G без модификаторов), как и клавиши со стрелками, Tab, Enter, Space, Home, End и любая клавиша, нажатая, пока метод ввода (IME) еще выполняет набор. Кроме клавиши Escape, которая возвращает фокус клавиатуры холсту, для них останавливается распространение без отмены действия по умолчанию, поэтому в полях, кнопках и дереве Обозревателя они работают как обычные клавиши и не доходят ни до холста, ни до обработчика keydown на странице в фазе всплытия: Alt + N там не добавляет таблицу, а Delete ничего не удаляет. Для клавиш, которые перемещают по строкам дерева, сворачивают их или переходят к ним, и для клавиши Enter в поле Find или Replace, которая перемещает по совпадениям или выполняет замену, также отменяется действие по умолчанию.
Любая другая клавиша, например сочетание сохранения или палитры команд хоста, как обычно, проходит к странице. См. Клавиши в Обозревателе. До версии 4.1.0 плавающая панель Поиска и замены удерживала клавиши так же, за исключением Home, End, последнего нажатия последовательности и Space, пока handTool был привязан к другой клавише.
Начиная с версии 4.0.0 окно выбора языка интерфейса удерживает клавиши так же: те же семь привязок проходят дальше, а для всех остальных привязок (начиная с версии 4.1.0 для последовательности — по последнему нажатию), клавиш со стрелками и Tab там останавливается распространение без отмены действия по умолчанию, как и для любой клавиши, нажатой, пока метод ввода (IME) еще выполняет набор. ↑, ↓, Home, End, Enter и Space на одной из его строк перемещают по строкам или выбирают строку, и для них также отменяется действие по умолчанию.

$mod​

Меняет клавишу Control в зависимости от среды.

  • Mac: $mod = Meta (⌘)
  • Windows/Linux: $mod = Control

Таблица сочетаний клавиш​

Использует свойства события клавиатуры key, code.
Используйте code для абсолютного положения клавиш, а key — для вводимых значений.

WindowsmacOSkeycode
НетCommand / ⌘MetaMetaLeft / MetaRight
AltOption / ⌥AltAltLeft / AltRight
ControlControl / ^ControlControlLeft / ControlRight
ShiftShiftShiftShiftLeft / ShiftRight
SpaceSpaceНетSpace
EnterReturnEnterEnter
EscEscEscapeEscape
BackspaceDelete / ⌫BackspaceBackspace
Deletefn + DeleteDeleteDelete
1, 2 и т. д.1, 2 и т. д.1, 2 и т. д.Digit1, Digit2 и т. д.
a, b и т. д.a, b и т. д.a, b и т. д.KeyA, KeyB и т. д.
---Minus
===Equal
+++Equal

Тема​

setPresetTheme​

Задает предустановленную тему.
Значения по умолчанию: appearance: 'dark', grayColor: 'slate' и accentColor: 'indigo'.
Каждое поле применяется отдельно, поэтому частичный вызов оставляет два других поля как есть. Значение, которое не входит в перечисленные ниже имена, игнорируется, и вызов никогда не выбрасывает исключение.
Начиная с версии 4.0.0 поле appearance также принимает 'system' — вариант System конструктора темы. Он показывает светлое или темное оформление, о котором сообщает операционная система или которое задает setSystemAppearance, и переключается при его изменении.

type ThemeOptions = {
appearance: 'dark' | 'light' | 'system';
grayColor: 'gray' | 'mauve' | 'slate' | 'sage' | 'olive' | 'sand';
accentColor:
| 'gray'
| 'gold'
| 'bronze'
| 'brown'
| 'yellow'
| 'amber'
| 'orange'
| 'tomato'
| 'red'
| 'ruby'
| 'crimson'
| 'pink'
| 'plum'
| 'purple'
| 'violet'
| 'iris'
| 'indigo'
| 'blue'
| 'cyan'
| 'teal'
| 'jade'
| 'green'
| 'grass'
| 'lime'
| 'mint'
| 'sky';
};

// example
editor.setPresetTheme({ appearance: 'light' });

setSystemAppearance​

Начиная с версии 4.0.0 задает светлый или темный вариант, который показывает оформление 'system', — для хоста с собственными светлым и темным вариантами, например темой IDE. Пока вариант задан, изменения в операционной системе игнорируются.
null или любое значение, кроме 'dark' и 'light', возвращает к следованию за операционной системой.
Пока оформление равно 'light' или 'dark', метод ничего не меняет на экране, но значение сохраняется и применяется, как только оформление становится 'system'. В противном случае оно применяется сразу. Метод ничего не генерирует, а changePresetTheme по-прежнему сообщает 'system'.
Хосты VS Code, JetBrains и Obsidian вызывают его со своим светлым или темным оформлением и повторно при каждом его изменении.

editor.setPresetTheme({ appearance: 'system' });
editor.setSystemAppearance('light'); // null follows the OS again

setTheme​

Позволяет настроить тему.
Каждый вызов заменяет весь пользовательский слой целиком, поэтому, чтобы изменить один токен поверх уже заданного переопределения, снова передайте полный объект, а чтобы вернуться к предустановленной теме, передайте {}.
Сохраняются только перечисленные ниже имена токенов со строковыми значениями; все остальное отбрасывается без ошибки.
Слой лежит поверх предустановленной темы, поэтому последующий setPresetTheme меняет предустановленную тему под ним, а ваши переопределения сохраняются.

JavaScript​

type Theme = {
grayColor1: string;
grayColor2: string;
grayColor3: string;
grayColor4: string;
grayColor5: string;
grayColor6: string;
grayColor7: string;
grayColor8: string;
grayColor9: string;
grayColor10: string;
grayColor11: string;
grayColor12: string;

accentColor1: string;
accentColor2: string;
accentColor3: string;
accentColor4: string;
accentColor5: string;
accentColor6: string;
accentColor7: string;
accentColor8: string;
accentColor9: string;
accentColor10: string;
accentColor11: string;
accentColor12: string;

canvasBackground: string;
canvasBoundaryBackground: string;

tableBackground: string;
tableHeaderBackground: string;
tableSelect: string;
tableBorder: string;
tableShadow: string;

tableGroupHeaderBackground: string;
tableGroupBackground: string;
tableGroupBorder: string;

memoBackground: string;
memoSelect: string;
memoBorder: string;
memoShadow: string;

columnSelect: string;
columnSelectHover: string;
columnHover: string;

relationshipHover: string;

visualizationLink: string;
visualizationColumn: string;
visualizationRelationship: string;

toolbarBackground: string;

contextMenuBackground: string;
contextMenuSelect: string;
contextMenuHover: string;
contextMenuBorder: string;

minimapBorder: string;
minimapShadow: string;
minimapViewportBorder: string;
minimapViewportBorderHover: string;

toastBackground: string;
toastBorder: string;
toastSuccess: string;
toastError: string;

findReplaceError: string;

mapColumnsError: string;

schemaSqlWarningBackground: string;
schemaSqlWarningForeground: string;

dragSelectBackground: string;
dragSelectBorder: string;

scrollbarTrack: string;
scrollbarThumb: string;
scrollbarThumbHover: string;

foreground: string;
active: string;
placeholder: string;

focus: string;
inputActive: string;

keyPK: string;
keyFK: string;
keyPFK: string;

treeBackground: string;
treeRowHover: string;
treeRowCurrent: string;
treeMuted: string;
treeMatch: string;

explorerBackground: string;
explorerBorder: string;

diffInsertForeground: string;
diffDeleteForeground: string;
diffModifyForeground: string;
diffRenameForeground: string;
};

// example
editor.setTheme({
canvasBackground: '#1b1b1f',
tableBackground: '#242429',
keyPK: '#ffc53d',
});

tableShadow и memoShadow задают цвет тени, которую таблицы и заметки отбрасывают на холст ERD. Темная предустановленная тема оставляет их transparent, и тень не отбрасывается, как и при передаче none или пустой строки в setTheme; светлая предустановленная тема использует rgba(0, 0, 0, 0.18).

Начиная с версии 4.0.0 есть еще девять токенов:

  • tableGroupHeaderBackground, tableGroupBackground и tableGroupBorder задают цвет строки заголовка, тела и контура группы таблиц, у которой нет собственного цвета.
  • toastSuccess и toastError задают цвет значка уведомления, которое сообщает, чем что-то закончилось.
  • findReplaceError и mapColumnsError задают цвет ошибок, которые показывают Поиск и замена и окно «Сопоставить столбцы». Раньше Поиск и замена использовал diffDeleteForeground, поэтому переопределение этого токена его больше не перекрашивает.
  • schemaSqlWarningBackground и schemaSqlWarningForeground задают цвет предупреждений в параметрах вкладки «Схема SQL».

Начиная с версии 4.1.0 есть еще девять токенов:

  • treeBackground, treeRowHover, treeRowCurrent, treeMuted и treeMatch задают цвета дерева, общего для Обозревателя и Просмотра различий: его фона, которым также заливаются поля Find и Replace Обозревателя; строки под указателем, строки, выбранной с клавиатуры, пока дерево в фокусе, и кнопки под указателем в заголовке и поиске Обозревателя; строки текущего совпадения поиска; приглушенного текста, например счетчиков, типов данных и стрелок сворачивания; и подсветки под текстом, найденным поиском.
  • explorerBackground и explorerBorder задают цвета панели Обозревателя и ее линий: края рядом с холстом, линии под поиском и границ полей и кнопок, которые раскрывает Search In. explorerBorder также рисует край дерева Просмотра различий, линию под его полем Filter by name и границу этого поля. Значки ключей в Обозревателе используют keyPK, keyFK и keyPFK.
  • diffModifyForeground и diffRenameForeground задают цвет того, что Просмотр различий помечает как измененное и переименованное, в его дереве и на обоих документах. diffModifyForeground также обводит таблицу, заметку или группу таблиц, которую переместили, у которой изменили размер, цвет или группу, что бы еще в ней ни изменилось, и рисует линию связи измененного внешнего ключа.

diffInsertForeground и diffDeleteForeground теперь задают цвет того, что Просмотр различий помечает как добавленное и удаленное, в его дереве и на документе, который это содержит, — одинаково в тексте, контурах и линиях связи. diffInsertBackground, diffDeleteBackground, diffCrossBackground и diffCrossForeground удалены в версии 4.1.0, так как Просмотр различий больше не заливает ячейки. setTheme отбрасывает их, как и любое другое имя, которого нет в Theme, а их переменные CSS --erd-editor-diff-insert-background, --erd-editor-diff-delete-background, --erd-editor-diff-cross-background и --erd-editor-diff-cross-foreground больше не читаются.

Переменные CSS​

Каждому токену в Theme соответствует переменная CSS, имя которой состоит из --erd-editor- и ключа в стиле kebab-case: grayColor10 — это --erd-editor-gray-color-10, keyPK — --erd-editor-key-pk, а keyPFK — --erd-editor-key-pfk.
Эти переменные наследуются внутрь редактора, поэтому задавайте их там, где они должны действовать. На :root они задают тему всем редакторам на странице, а на самом элементе — только этому редактору.

erd-editor {
--erd-editor-canvas-background: #1b1b1f;
}

Начиная с версии 3.4.0 токены с опечаткой dargSelect пишутся как dragSelect, а их переменные CSS изменились с --erd-editor-darg-select-background и --erd-editor-darg-select-border на --erd-editor-drag-select-background и --erd-editor-drag-select-border. Таблица стилей, которая все еще использует старые имена, игнорируется.

Значения темы по умолчанию
:root {
--erd-editor-gray-color-1: #111113;
--erd-editor-gray-color-2: #18191b;
--erd-editor-gray-color-3: #212225;
--erd-editor-gray-color-4: #272a2d;
--erd-editor-gray-color-5: #2e3135;
--erd-editor-gray-color-6: #363a3f;
--erd-editor-gray-color-7: #43484e;
--erd-editor-gray-color-8: #5a6169;
--erd-editor-gray-color-9: #696e77;
--erd-editor-gray-color-10: #777b84;
--erd-editor-gray-color-11: #b0b4ba;
--erd-editor-gray-color-12: #edeef0;
--erd-editor-accent-color-1: #11131f;
--erd-editor-accent-color-2: #141726;
--erd-editor-accent-color-3: #182449;
--erd-editor-accent-color-4: #1d2e62;
--erd-editor-accent-color-5: #253974;
--erd-editor-accent-color-6: #304384;
--erd-editor-accent-color-7: #3a4f97;
--erd-editor-accent-color-8: #435db1;
--erd-editor-accent-color-9: #3e63dd;
--erd-editor-accent-color-10: #5472e4;
--erd-editor-accent-color-11: #9eb1ff;
--erd-editor-accent-color-12: #d6e1ff;
--erd-editor-canvas-background: #212225;
--erd-editor-canvas-boundary-background: #111113;
--erd-editor-table-background: #18191b;
--erd-editor-table-header-background: #2e3135;
--erd-editor-table-select: #435db1;
--erd-editor-table-border: #363a3f;
--erd-editor-table-shadow: transparent;
--erd-editor-table-group-header-background: #43484e;
--erd-editor-table-group-background: #d3edf81d;
--erd-editor-table-group-border: #43484e;
--erd-editor-memo-background: #18191b;
--erd-editor-memo-select: #435db1;
--erd-editor-memo-border: #363a3f;
--erd-editor-memo-shadow: transparent;
--erd-editor-column-select: #182449;
--erd-editor-column-select-hover: #1d2e62;
--erd-editor-column-hover: #272a2d;
--erd-editor-relationship-hover: #435db1;
--erd-editor-visualization-link: #43484e;
--erd-editor-visualization-column: #5a6169;
--erd-editor-visualization-relationship: #5a6169;
--erd-editor-toolbar-background: #111113;
--erd-editor-context-menu-background: #18191b;
--erd-editor-context-menu-select: #272a2d;
--erd-editor-context-menu-hover: #3a4f97;
--erd-editor-context-menu-border: #363a3f;
--erd-editor-minimap-border: black;
--erd-editor-minimap-shadow: black;
--erd-editor-minimap-viewport-border: #3a4f97;
--erd-editor-minimap-viewport-border-hover: #435db1;
--erd-editor-toast-background: #18191b;
--erd-editor-toast-border: #363a3f;
--erd-editor-toast-success: #3dd68c;
--erd-editor-toast-error: #ff9592;
--erd-editor-find-replace-error: #ff9592;
--erd-editor-map-columns-error: #ff9592;
--erd-editor-schema-sql-warning-background: #500f1c;
--erd-editor-schema-sql-warning-foreground: #ff9592;
--erd-editor-drag-select-background: #253974;
--erd-editor-drag-select-border: #435db1;
--erd-editor-scrollbar-track: #ddeaf814;
--erd-editor-scrollbar-thumb: #696e77;
--erd-editor-scrollbar-thumb-hover: #777b84;
--erd-editor-foreground: #b0b4ba;
--erd-editor-active: #edeef0;
--erd-editor-placeholder: #e5edfd7b;
--erd-editor-focus: #435db1;
--erd-editor-input-active: #5472e4;
--erd-editor-key-pk: #ffc53d;
--erd-editor-key-fk: #e54666;
--erd-editor-key-pfk: #00a2c7;
--erd-editor-tree-background: #111113;
--erd-editor-tree-row-hover: #212225;
--erd-editor-tree-row-current: #1d2e62;
--erd-editor-tree-muted: #b0b4ba;
--erd-editor-tree-match: #253974;
--erd-editor-explorer-background: #111113;
--erd-editor-explorer-border: #363a3f;
--erd-editor-diff-insert-foreground: #3dd68c;
--erd-editor-diff-delete-foreground: #ff9592;
--erd-editor-diff-modify-foreground: #ffca16;
--erd-editor-diff-rename-foreground: #70b8ff;
}

Язык интерфейса​

Начиная с версии 4.0.0 собственный текст редактора — меню, панели, окна, быстрый поиск, уведомления и слова, которые он рисует на диаграмме, например unnamed, в том числе при экспорте изображений, — доступен на 25 языках. Имена таблиц и столбцов, SQL, типы данных и сгенерированный код никогда не переводятся. См. Язык и тема.
Пока не вызван setLocale и не выбран язык, редактор показывает английский или, если включен enableLocalePicker, следует 'system'.
Редактор задает lang и dir на собственном корневом элементе внутри закрытого теневого корня и никогда на элементе-хосте или странице, поэтому страница с письмом справа налево не переворачивает редактор, а язык с письмом справа налево не переворачивает страницу. На иврите, арабском и персидском интерфейс редактора располагается справа налево; сама диаграмма никогда не отражается зеркально. Начиная с версии 4.1.0 Обозреватель на любом языке остается слева от холста, а его собственные строки на этих трех языках читаются справа налево.
Пакет экспортирует типы LocaleCode (один из кодов ниже) и LocaleOption.

type LocaleOption = LocaleCode | 'system';
КодОтображается какЯзык
id-IDBahasa IndonesiaИндонезийский
de-DEDeutschНемецкий
enEnglishАнглийский
es-ESEspañolИспанский
eu-ESEuskaraБаскский
fr-FRFrançaisФранцузский
it-ITItalianoИтальянский
nl-NLNederlandsНидерландский
pl-PLPolskiПольский
pt-PTPortuguêsПортугальский
pt-BRPortuguês BrasileiroБразильский португальский
ro-RORomânăРумынский
sk-SKSlovenčinaСловацкий
sl-SISlovenščinaСловенский
sv-SESvenskaШведский
tr-TRTürkçeТурецкий
ru-RUРусскийРусский
uk-UAУкраїнськаУкраинский
he-ILעבריתИврит
ar-SAالعربيةАрабский
fa-IRفارسیПерсидский
ja-JP日本語Японский
zh-CN简体中文Упрощенный китайский
zh-TW繁體中文Традиционный китайский
ko-KR한국어Корейский

setLocale​

Задает язык интерфейса: 'system' или один из кодов выше. Все остальное, например просто 'ko', неизвестный код или значение, не являющееся строкой, игнорируется без ошибки.
Он применяется до возврата из вызова, поэтому язык, заданный до добавления элемента на страницу, виден уже в первом кадре.
Он ничего не генерирует — ни changeLocale, ни change — и не затрагивает ни value, ни историю изменений, ни общее хранилище.
Выбор сохраняется независимо от того, включен enableLocalePicker или выключен, а setLocale('system') следует за системой и при выключенном выборе языка.
Редактор ничего не сохраняет. Чтобы запомнить выбор пользователя, отслеживайте changeLocale и передавайте выбор обратно при следующей загрузке.

editor.enableLocalePicker = true;
editor.setLocale(localStorage.getItem('locale') ?? 'system');
editor.addEventListener('changeLocale', event => {
localStorage.setItem('locale', event.detail.locale);
});

setSystemLocale​

Задает язык, который обозначает 'system', в виде тега BCP 47 — для хоста с собственным языком интерфейса. Хосты VS Code, JetBrains и Obsidian вызывают его со своим языком интерфейса.
Пробелы по краям тега обрезаются. null, пустая строка или значение, не являющееся строкой, возвращает к navigator.languages браузера, за изменениями которого редактор следит.
Он имеет значение, только пока действует вариант 'system', и применяется сразу. Строка System в окне выбора называет язык, в который он разрешается.
Тег или каждый из языков браузера по порядку разрешается в первый язык, который есть в редакторе, по подтегу языка, без учета регистра и символов подчеркивания: de-AT дает de-DE, а en-GB — en. Китайский определяется по письменности (Hant дает zh-TW, а Hans — zh-CN), а без нее — по региону: TW, HK и MO дают zh-TW, а любой другой — zh-CN. pt дает pt-BR, если не указан регион, отличный от BR. Если ничего не подходит, редактор показывает английский.

editor.setLocale('system');
editor.setSystemLocale('pt-PT'); // null follows the browser again

setSchemaSQL​

Загружает файл Схемы SQL.
По умолчанию он заменяет текущий документ, а не объединяется с ним; см. mode ниже. Уже заданные настройки сохраняются, включая каждую блокировку и ее заблокированное значение, кроме положения вида и масштаба, а таблицы размещаются после чтения файла — рядами, если placement ниже не требует иного. Если Viewport заблокирован, value затем записывает вид, с которого начинается импорт: начало координат 0, 0 при масштабе 1. Поэтому в документе, импортированном в элемент, которому никогда не задавалось значение, включены все блокировки, как и в новом документе.
Он записывается в историю изменений, что позволяет выполнить Undo, Redo, и генерирует change. Пустая строка игнорируется, а пока установлен атрибут readonly, вызов ничего не делает.
setSchemaGraphQL, setSchemaDBML и setSchemaAML ведут себя так же, а их парсеры никогда не завершаются с ошибкой: текст, который они не могут прочитать, загружает пустой документ, а не вызывает ошибку.
Начиная с версии 4.0.0 все четыре метода принимают необязательный второй аргумент { placement, mode }:

  • placement: 'grid', значение по умолчанию, сразу размещает таблицы рядами, как и раньше, и вызов ничего не возвращает.
  • placement: 'auto' сначала размещает таблицы с учетом их связей, как это делает Import в редакторе, и возвращает Promise, который разрешается, когда импорт применен как один шаг отмены. Если таблиц меньше двух, связей нет, размещение не удалось, на странице нет SharedWorker или в уведомлении Placing tables нажата кнопка Cancel, таблицы вместо этого размещаются рядами. Загрузка, произошедшая за это время, — другой заменяющий импорт, присваивание value, setInitialValue(), clear(), загрузка соавтора либо отмена или повтор загрузки или clear() — вытесняет его, и Promise разрешается, ничего не загрузив. Импорты, размещаемые таким способом, применяются в том порядке, в котором они начались.
  • mode: 'replace', значение по умолчанию, заменяет документ. mode: 'append' добавляет файл под диаграммой, как Импорт с добавлением, оставляя как есть все уже имеющиеся таблицы и все настройки, кроме вкладки и положения вида. Если открыта другая вкладка, сначала открывается вкладка ERD. Новые таблицы, а также группы таблиц, которые приносит файл DBML, пока группы таблиц показаны, становятся выделением, и вид прокручивается к ним, если они еще не видны как следует, по правилу, которому начиная с версии 4.1.0 следует каждый переход, — см. Куда ведет переход. Одна отмена удаляет все добавленное. Текст, который не удается прочитать, ничего не добавляет и оставляет документ как есть.

Пока установлен атрибут readonly, замена игнорируется, добавление ничего не добавляет, а вызов с placement: 'auto' сразу разрешается.
Начиная с версии 3.10.0 метод setSchemaSQL читает файл с учетом текущей базы данных документа: если выбрана СУБД Databricks, строки в одинарных кавычках следуют правилам экранирования обратной косой чертой, принятым в Spark. См. Комментарии.
Начиная с версии 3.10.0 метод setSchemaSQL читает UNIQUE по двум и более столбцам как один уникальный индекс, а не как флаг «Уникальный» у каждого столбца. См. Уникальные ключи и индексы.
Начиная с версии 3.10.0 импорт SQL, DBML и AML сохраняет действия ON DELETE и ON UPDATE прочитанных внешних ключей.
Начиная с версии 4.0.0 метод setSchemaSQL сохраняет выражение DEFAULT столбца целиком, читает ADD DEFAULT … FOR из SQL Server и его комментарии MS_Description, превращает столбцы serial и identity из PostgreSQL в Автоинкремент, сохраняет UNSIGNED и ZEROFILL в типе данных и читает первичный ключ, который ALTER TABLE … ADD PRIMARY KEY помечает как CLUSTERED, NONCLUSTERED или USING BTREE. См. Схема SQL.
О синтаксисе, который принимает каждый парсер, см. Импорт и экспорт файлов.

type SetSchema = {
(
value: string,
options: { placement: 'auto'; mode?: 'replace' | 'append' }
): Promise<void>;
(
value: string,
options?: { placement?: 'grid'; mode?: 'replace' | 'append' }
): void;
};

// example
editor.setSchemaSQL('Schema SQL...');
// or
await editor.setSchemaSQL('Schema SQL...', { placement: 'auto' });
// or
editor.setSchemaSQL('Schema SQL...', { mode: 'append' });

setSchemaGraphQL​

Загружает документ GraphQL SDL.
Определения объектных типов становятся таблицами, а поле, тип которого — другая таблица, становится связью.

editor.setSchemaGraphQL('GraphQL SDL...');

setSchemaDBML​

Загружает файл DBML — формата, который используют dbdiagram.io и dbdocs.
Начиная с версии 4.0.0 каждый TableGroup становится группой таблиц, а headercolor таблицы становится ее цветом. См. DBML.

editor.setSchemaDBML('DBML...');

setSchemaAML​

Загружает файл AML (Azimutt Markup Language). Принимается как текущий синтаксис, так и устаревший синтаксис v1.
Начиная с версии 4.0.0 цвет сущности — одно из имен цветов Azimutt или шестнадцатеричное значение в кавычках — становится цветом ее таблицы. См. AML.

editor.setSchemaAML('AML...');

setSchemaJSON​

Начиная с версии 4.0.0 загружает документ .erd.json, например текст, который возвращает value.
В режиме по умолчанию mode: 'replace' он загружает документ так же, как присваивание value: загрузка записывается в историю изменений, генерирует change и так же принимает блокировки документа. В отличие от value, пустая строка или значение, не являющееся строкой, игнорируется, а не начинает новый документ. Текст, не являющийся JSON, очищает документ, как и в случае с value.
mode: 'append' добавляет таблицы, связи, индексы, заметки и группы таблиц документа под диаграммой с новыми идентификаторами, сохраняя их взаимное расположение и не учитывая настройки документа, как Импорт с добавлением с файлом json. Текст, который не удается прочитать, или документ без таблиц и заметок ничего не добавляет. В остальных случаях добавление применяется так же, как добавление в setSchemaSQL, причем новые заметки и группы таблиц выделяются вместе с таблицами — каждый вид, пока он показан.
Он возвращает управление, когда документ применен, и игнорируется, пока установлен атрибут readonly.

editor.setSchemaJSON('json...');
// or
editor.setSchemaJSON('json...', { mode: 'append' });

getSchemaSQL​

Экспортирует текущее состояние редактора в виде Схемы SQL.
Если databaseVendor не указан, используется выбранная сейчас СУБД. Имя, которого нет в списке ниже, обрабатывается так же, без ошибки.
Имена заключаются в кавычки того типа, который показывает редактор. Пока Bracket Type заблокирован, этот тип может отличаться от того, который сохраняет value, — именно с ним заключает имена в кавычки erd_read агента для программирования.
Начиная с версии 4.0.0 необязательный аргумент options выбирает операторы и заголовок, как это делают параметры вкладки «Схема SQL». SchemaSQLOptions экспортируется как тип.

  • statements: 'create' — значение по умолчанию; 'ifNotExists', который пишет IF NOT EXISTS в MySQL, MariaDB, PostgreSQL, SQLite и Databricks, а в остальных СУБД переходит на 'create'; или 'recreate', который удаляет таблицы перед их созданием, а для Snowflake вместо этого пишет CREATE OR REPLACE TABLE.
  • header: 'none' — значение по умолчанию; 'use', который переключается на базу данных или схему документа; или 'createAndUse', который сначала создает ее, если она не существует, а затем переключается на нее. СУБД, в которой нет запрошенного варианта, переходит на запасной так же, как вкладка: Oracle пишет 'use' вместо 'createAndUse', PostgreSQL не пишет заголовок для 'use', а SQLite не пишет его вовсе. Заголовок пишется, только если имя базы данных документа — простой идентификатор: буквы ASCII, цифры и _, без цифры в начале.

Пропущенный параметр или параметр с неизвестным значением считается равным значению по умолчанию, поэтому вызов без параметров пишет обычные операторы CREATE без заголовка, как и раньше.
Начиная с версии 4.0.0 вывод всегда включает скрипты документа Before tables и After tables в таком порядке: заголовок, скрипт перед таблицами, операторы удаления, таблицы, скрипт после таблиц. Собственные параметры Statements, Header и Tables вкладки «Схема SQL» никогда не влияют на этот вызов, который всегда пишет весь документ.
Начиная с версии 3.10.0 каждый внешний ключ содержит предложения ON DELETE и ON UPDATE связи. Предложение пишется, только если его действие задано и СУБД его поддерживает, поэтому действие, которое эта СУБД не принимает, опускается и применяется ее значение по умолчанию. Начиная с версии 4.0.0 Snowflake принимает только NO ACTION. О том, что пишет каждая СУБД, см. ON DELETE и ON UPDATE.
Начиная с версии 3.10.0 одинарная кавычка внутри комментария таблицы или столбца экранируется, поэтому комментарий вроде it's больше не ломает оператор. Каждая СУБД, которая пишет комментарии как строковые литералы, удваивает ее, кроме Databricks, которая ставит обратную косую черту перед каждой кавычкой и каждой обратной косой чертой. SQLite по-прежнему пишет комментарии строками --.
Начиная с версии 4.0.0 несколько СУБД также по-другому пишут имена ключей, значения по умолчанию и автоинкремент. См. Что содержит DDL.

type DatabaseVendor =
| 'Databricks'
| 'MariaDB'
| 'MSSQL'
| 'MySQL'
| 'Oracle'
| 'PostgreSQL'
| 'Snowflake'
| 'SQLite';

type SchemaSQLOptions = {
statements?: 'create' | 'ifNotExists' | 'recreate';
header?: 'none' | 'use' | 'createAndUse';
};

const schemaSQL = editor.getSchemaSQL();
// or
const postgresSQL = editor.getSchemaSQL('PostgreSQL');
// or
const mysqlSQL = editor.getSchemaSQL('MySQL', {
statements: 'ifNotExists',
header: 'createAndUse',
});

getSharedStore​

Возвращает хранилище для совместного редактирования в реальном времени.
config имеет вид { getNickname?, mouseTracker?, focusTracker? }. Оба трекера по умолчанию равны true: mouseTracker транслирует курсор этого редактора остальным, а focusTracker — его ячейку в фокусе, выделение и рамку выделения.
См. Совместное редактирование.

const sharedStore = editor.getSharedStore({
mouseTracker: false,
focusTracker: false,
});

setDiffValue​

Открывает Просмотр различий, сравнивая открытый сейчас документ с переданным.
Он ничего не возвращает и не изменяет документ, поэтому после закрытия окна просмотра редактор остается точно таким же, каким был.
Пустое значение или любое значение, не являющееся строкой, сравнивается с пустым документом.
Это то же окно, которое открывает пункт Просмотр различий в контекстном меню холста.
Начиная с версии 4.1.0 он сопоставляет содержимое двух документов сначала по идентификатору и только затем по тому, что хранит каждый элемент, например по имени таблицы или тексту заметки, — см. Что сравнивается. Поэтому при сравнении с более ранней версией того же документа, например с ревизией его файла в Git, переименование отображается как один переименованный элемент, а при сравнении с документом с другими идентификаторами — как удаление и добавление. Окно просмотра показывает изменения в дереве рядом с двумя документами и выделяет их цветом, а не заливкой ячеек.

editor.setDiffValue('prev json...');