ErdViewerElement
Починаючи з версії 5.0.0, пакет постачає ще й <erd-viewer> — перегляд документа лише для читання: читач панорамує, масштабує, шукає й підсвічує зв’язки, але нічого в ньому не редагується. Він малює лише полотно ERD зі смугами прокручування, мінікартою, панеллю керування і палітрою, яка шукає в документі, і не має ні панелі інструментів, ні вкладок, ні оглядача, ні контекстного меню.
import '@dineug/erd-editor/erd-viewer.js';
<erd-viewer src="/diagrams/shop.erd.json" style="display: block; height: 480px"></erd-viewer>
Фрейм вище — це цей елемент у вигляді, у якому його показує erd-editor.io/embed, тут із прикладом bookstore: клацніть його, щоб дати йому фокус, а потім масштабуйте й шукайте клавішами з розділу фокус і клавіші, а як вставити власний документ без коду, див. вбудовування.
Засіб перегляду — це звичайний HTMLElement.
Його визначення типу таке.
interface ErdViewerElement extends HTMLElement {
src: string;
nameView: 'physical' | 'logical' | 'both' | null;
minimap: boolean;
controls: boolean;
value: string;
setPresetTheme: (themeOptions: Partial<ThemeOptions>) => void;
setSystemAppearance: (appearance: 'dark' | 'light' | null) => void;
setTheme: (theme: Partial<Theme>) => void;
setLocale: (locale: LocaleOption) => Promise<void>;
setSystemLocale: (locale: string | null) => Promise<void>;
destroy: () => void;
}
Імпорт @dineug/erd-editor/erd-viewer.js визначає <erd-viewer> і залишає <erd-editor> невизначеним. Імпорт кореня пакета не визначає жодного з них: він експортує клас ErdViewerElement і defineErdViewer(), яка визначає тег там, де ви її викликаєте, тож сторінка може визначити клас і під власним тегом — див. реєстрація елементів.
Кожна точка входу, крім engine.js і peer.js, потребує DOM, і ця теж, тож сторінка, яку рендерять на сервері, імпортує її на клієнті — див. рендеринг на сервері.
Імпорт точки входу додає erd-viewer до HTMLElementTagNameMap, тож document.createElement('erd-viewer') і document.querySelector('erd-viewer') типізовано як ErdViewerElement без приведення типів.
Як і редактор, засіб перегляду рендерить у закритий тіньовий корінь (shadow root), тож viewer.shadowRoot дорівнює null, а стилі сторінки не потрапляють досередини й назовні; стилізуйте його через setTheme і власні властивості CSS --erd-editor-*. Кілька засобів перегляду на одній сторінці зберігають кожен власний документ, область перегляду, тему й мову.
<erd-viewer> не має власного розміру. Користувацький елемент є рядковим, тож задайте йому display: block і висоту, як вище. Вигляд заповнює рамку елемента й слідує за зміною її розміру, зберігаючи масштаб.
src, name-view, minimap і controls — його єдині атрибути, кожен із властивістю тієї самої назви, nameView для name-view. value — лише властивість.
Значення value, src, nameView, minimap або controls, задане на елементі до визначення його тега, наприклад фреймворком, який рендерить елемент до завантаження точки входу, підхоплюється, щойно тег визначено, поверх атрибутів, які дала розмітка. Вони підхоплюються в тому порядку, в якому сторінка вперше записала кожне з них, тож з value і src переважає пізніше. value, який не містить документа, тоді не має до кого викинути виняток: про нього повідомляється як про неперехоплену помилку, а засіб перегляду залишається порожнім.
Збірка для тегу script, dist/erd-viewer.umd.js, містить лише засіб перегляду з усіма залежностями. Вона визначає <erd-viewer> і кладе ErdViewerElement та defineErdViewer у window.ErdViewer. URL CDN без шляху віддає натомість збірку редактора, тож вкажіть файл — див. тег script.
<erd-viewer src="diagram.erd.json" style="display: block; height: 480px"></erd-viewer>
<script src="https://cdn.jsdelivr.net/npm/@dineug/erd-editor@5.0.0/dist/erd-viewer.umd.js"></script>
src
URL документа, який засіб перегляду має отримати й показати. За замовчуванням це '', тобто нічого.
Запит — це звичайний fetch(), GET без власних параметрів, тож його регулюють правила CORS браузера: документ в іншому джерелі потребує сервера, який дозволяє джерело сторінки, а cookies надсилаються лише до джерела самої сторінки. Відносний URL розв’язується відносно сторінки.
Відповідь має містити документ у тій формі, в якій його містить файл .erd.json, — у формі зберігання, яку записують value редактора й кожен офіційний хост. Інші формати не читаються: файл SQL, GraphQL, DBML чи AML завершується помилкою як текст, що не розбирається.
Документ, який розібрано, потрапляє вписаним у вигляд і генерує load. Запит, який мережа чи CORS відхилили, відповідь, що не є ok, або текст, що не розбирається, генерує error і залишає діаграму порожньою — див. завантаження.
Враховується лише останній запит. Новий src скасовує запит, що ще триває, тож повільна відповідь ніколи не потрапляє поверх пізнішого документа. Присвоєння value теж його скасовує, як і видалення src або присвоєння йому '', що припиняє стежити за ним і залишає показаний документ таким, яким він був.
Переважає те з value і src, що задано останнім, чи то через властивість, чи через атрибут. src, записаний після value, завантажується, навіть якщо називає URL, який завантажували раніше. Записаний знову поверх документа, який він уже показує, він нічого не завантажує.
Засіб перегляду завантажує лише тоді, коли він на сторінці. Видалення його зі сторінки скасовує запит, що ще триває, а повернення завантажує src, який він ще не показав, зокрема й той, що зазнав невдачі, але ніколи — той, що він уже показує.
src — єдиний fetch(), який робить пакет, тож сувора політика Content Security Policy вносить джерело документа в connect-src.
viewer.src = 'https://example.com/diagrams/shop.erd.json';
// or
viewer.setAttribute('src', 'https://example.com/diagrams/shop.erd.json');
<erd-viewer src="https://example.com/diagrams/shop.erd.json"></erd-viewer>
value
getter
Повертає показаний документ, чи то він прийшов із src, чи з value, як рядок JSON у формі зберігання, яку записує value редактора. Доки нічого не показано, це новий порожній документ, у якого doc дорівнює {}.
Поки блокування Viewport документа ввімкнено, як у новому документі, він записує масштаб і прокручування, на яких документ заблоковано, куди б читач не зсунув вигляд. Лише з вимкненим блокуванням він записує, де вигляд стоїть, зокрема й вписування, яке робить завантаження.
Він записує відображення назв, яке має документ, ніколи не те, що показує nameView або панель керування поверх нього, навіть у документі з вимкненим блокуванням Name View.
Він і далі повертає документ після destroy.
const data = viewer.value;
setter
Показує документ за його текстом, замінюючи показаний, і вписує його у вигляд — див. завантаження. Він приймає текст, який містить файл або value редактора.
Текст, що не розбирається, викидає виняток, поки нічого не змінилося, і показаний документ залишається: SyntaxError для тексту, що не є JSON, і TypeError для JSON, який не містить документа, як-от 7. Порожній рядок або будь-що, що не є рядком, показує порожню діаграму.
Присвоєння скасовує запит src, що ще триває, і не генерує ні load, ні error.
viewer.value = localStorage.getItem('my-diagram') ?? '';
nameView
Показує діаграму у відображенні назв поверх того, яке має документ: 'physical' для Physical Names, 'logical' для Logical Names або 'both' для Both Names. null, значення за замовчуванням, показує власне відображення документа, а значення атрибута, відмінне від цих трьох, зчитується як null.
Воно діє для кожного документа, завантаженого після нього, і value його ніколи не записує. Видалення атрибута повертає власне відображення документа.
Список Name View на панелі керування теж перемикає відображення, доки не з’явиться наступний документ або nameView знову не зміниться. Перемикання там теж не записується у value.
viewer.nameView = 'both';
// or
viewer.setAttribute('name-view', 'both');
<erd-viewer name-view="logical"></erd-viewer>
minimap
Показує мінікарту у верхньому правому куті, поки документ містить таблицю, показану нотатку чи показану групу таблиць. Увімкнено за замовчуванням.
Вона працює так, як у редакторі: клацніть її, щоб перейти туди, або перетягніть її прямокутник області перегляду, щоб панорамувати, — див. навігація полотном. Палець на ній належить сторінці, доки засіб перегляду не отримає фокус.
Лише minimap="false" її вимикає. Атрибут без значення, будь-яке інше значення й відсутність атрибута залишають її ввімкненою.
viewer.minimap = false;
// or
viewer.setAttribute('minimap', 'false');
<erd-viewer minimap="false"></erd-viewer>
controls
Показує панель керування над серединою нижнього краю полотна. Увімкнено за замовчуванням, і вона містить зліва направо:
- Масштаб:
Zoom out, поточний масштаб у відсотках іZoom in. Дві кнопки змінюють масштаб кроками, як клавіші масштабу, а клацання відсотка,Reset zoom, повертає100%. Кожна називає свою клавішу в підказці. Fit, який масштабує й прокручує так, щоб уся діаграма вмістилася у вигляд, по центру.Name View, кнопка, яка називає відображення, що діє, і відкриває над панеллю список ізPhysical Names,Logical NamesіBoth Names— див. nameView.- Компас
Go to content, який з’являється в кінці панелі лише тоді, коли жодної частини діаграми не видно на екрані, і переносить вигляд до найближчої її частини.
Панель стоїть зліва направо в кожній мові.
Лише controls="false" її вимикає, разом із її компасом і списком Name View. Атрибут без значення, будь-яке інше значення й відсутність атрибута залишають її ввімкненою. Без панелі коліщатко, щипок і клавіші й далі масштабують, щойно засіб перегляду отримує фокус.
viewer.controls = false;
// or
viewer.setAttribute('controls', 'false');
<erd-viewer controls="false"></erd-viewer>
Події
load і error — єдині дві події, і обидві повідомляють про src. Жодна не спливає, тож слухайте на самому елементі.
load
Генерується, коли документ, який називає src, отримано й показано. event.detail дорівнює null.
Присвоєння value не генерує жодної, як і запит, який скасували пізніший src, value, вилучення елемента зі сторінки чи destroy.
viewer.addEventListener('load', () => {
console.log('shown', viewer.src);
});
error
Генерується, коли отримання src зазнає невдачі: мережа чи CORS відхилили запит, відповідь не була ok або її текст не розібрався. Тоді засіб перегляду показує порожню діаграму й повідомлення Couldn't load the diagram — див. завантаження.
event.detail — це причина: TypeError, яким відхиляється fetch(), Error з назвою статусу, як-от GET /missing.erd.json answered 404 Not Found, або SyntaxError чи TypeError розбирача.
Запит, який щось скасувало, нічого не генерує.
viewer.addEventListener('error', event => {
console.warn('could not show', viewer.src, event.detail);
});
setPresetTheme
Задає готову тему, приймаючи ThemeOptions редактора — див. setPresetTheme.
Засіб перегляду починає з appearance: 'system', grayColor: 'slate' і accentColor: 'indigo', тож з першого кадру показує світлий чи темний вигляд, який повідомляє операційна система, і перемикається, коли він змінюється. Редактор натомість починає з темного.
Кожне поле застосовується окремо, тож частковий виклик залишає два інших такими, якими вони були. Значення, яке не є однією з назв, ігнорується, а виклик ніколи не викидає виняток.
Засіб перегляду не має конструктора теми й systemDarkMode і не генерує події для теми.
viewer.setPresetTheme({ appearance: 'light', accentColor: 'teal' });
setSystemAppearance
Називає світлий чи темний вигляд, який показує вигляд 'system', для сторінки з власним світлим і темним. Поки один названо, зміни операційної системи ігноруються.
null або будь-яке значення, крім 'dark' чи 'light', повертає стеження за операційною системою.
Поки вигляд — 'light' або 'dark', це нічого не змінює на екрані, але значення зберігається й застосовується, щойно вигляд стає 'system'. Воно нічого не генерує.
viewer.setSystemAppearance('dark'); // null follows the OS again
setTheme
Перевизначає токени теми поверх готової теми, приймаючи токени Theme редактора — див. setTheme.
Кожен виклик замінює весь шар, тож передайте {}, щоб повернутися до готової теми. Зберігаються лише назви токенів із рядковими значеннями, а пізніший setPresetTheme змінює готову тему під ними, і перевизначення залишаються.
Власні властивості CSS --erd-editor-* доходять і до засобу перегляду, задані на елементі або будь-де над ним — див. змінні CSS. Полотно, до якого не дістається жодна таблиця стилів, зчитує їх знову, коли змінюється таблиця стилів у head сторінки або коли змінюється атрибут class чи style елемента чи елемента над ним. Правило, додане через insertRule(), не змінює жодного з них, тож полотно підхоплює його під час наступної такої зміни.
erd-viewer {
--erd-editor-canvas-background: #ffffff;
}
setLocale
Задає мову інтерфейсу: 'system', значення за замовчуванням, або один із 25 кодів, які перелічує мова інтерфейсу редактора. Будь-що інше, як-от голе 'ko' чи значення, що не є рядком, ігнорується.
Мова змінює підказки панелі керування, список Name View, палітру, повідомлення про завантаження та слова, які діаграма малює сама, як-от unnamed. Назви, коментарі й решта документа ніколи не перекладаються.
Англійська входить до точки входу засобу перегляду і застосовується до повернення з виклику. Кожна інша мова — це окремий модуль, який ваш збирач генерує як чанк поруч із засобом перегляду, а засіб перегляду отримує з вашої збірки, коли сторінка вперше просить цю мову, один раз для всіх засобів перегляду сторінки. Доки він не надійде, засіб перегляду показує мову, яку показував, на першому кадрі — англійську. Якщо він не завантажується, засіб перегляду показує англійську, а повторне прохання про цю мову пробує знову.
Збірка для тегу script містить усі 25 мов, тож не отримує жодної. Збірка, що містить і редактор, завантажує всі мови разом із чанком редактора — див. реєстрація елементів.
Promise, який він повертає, вирішується, коли ця мова надійшла або не завантажилася, і ніколи не відхиляється. Тоді діє ця мова, або англійська після невдачі, якщо тільки пізніший виклик не попросив іншої: пізніший виклик переважає, в якому б порядку мови не надходили.
Іврит, арабська й перська розміщують палітру та повідомлення про завантаження справа наліво. Полотно, мінікарта, смуги прокручування й панель керування з її компасом залишаються зліва направо, як і полотно редактора — див. мови з письмом справа наліво.
Засіб перегляду задає lang і dir на власному корені всередині закритого тіньового кореня, ніколи не на елементі-хості чи сторінці.
Він нічого не генерує, а засіб перегляду не має панелі вибору мови й нічого не зберігає.
await viewer.setLocale('ko-KR');
setSystemLocale
Називає мову, яку означає 'system', як тег BCP 47, для сторінки з власним налаштуванням мови.
Тег обрізається. null, порожній рядок або значення, що не є рядком, повертає мови сторінки.
Це <html lang> сторінки, потім navigator.languages браузера, прочитані один раз, коли засіб перегляду вперше підключається. 'system' бере першу з них, для якої засіб перегляду має мову, за правилом редактора з setSystemLocale, і англійську, коли жодної з них він не має. Тож сторінка, чий <html lang> називає мову, яку має засіб перегляду, показує цю мову незалежно від уподобань браузера, а пізніша зміна lang чи мов браузера не рухає жодного засобу перегляду.
Це має значення лише тоді, коли діє 'system', а його Promise вирішується так, як у setLocale.
viewer.setSystemLocale('ja-JP'); // null goes back to the page's languages
destroy
Закінчує життя засобу перегляду назавжди. Він знімає вигляд до повернення з виклику, чи елемент ще на сторінці, чи його вже вилучено, скасовує запит src, що ще триває, і припиняє стежити за кольоровою схемою операційної системи та стилями сторінки.
Знищений засіб перегляду нічого більше не малює, нічого не завантажує й не просить жодної мови, навіть якщо його знову додати на сторінку. Читання value і далі повертає документ, який він тримав.
Вилучення елемента зі сторінки його не знищує: повернутий, він працює далі й завантажує src, який іще не показав, — див. завантаження.
viewer.destroy();
Фокус і клавіші
Засіб перегляду не бере фокуса під час монтування, під час надходження документа чи під час закриття палітри, тож ніколи не прокручує сторінку до себе й не забирає клавіші сторінки.
Клацання чи дотик на його полотні дає йому фокус без прокручування сторінки, і він є однією зупинкою клавіші Tab. На відміну від редактора, він не має власних членів focus() чи blur(). Натискання будь-де деінде на сторінці знову забирає фокус.
Доки засіб перегляду не має фокуса, сторінка зберігає коліщатко, яке її прокручує, і щипок на тачпаді. Палець на полотні прокручує сторінку й нічого не панорамує, а кожна клавіша доходить до сторінки без скасування.
Коли він має фокус:
- Коліщатко панорамує вигляд, а
Shift + Wheelпанорамує вбік. Над нотаткою, текст якої переповнюється, коліщатко прокручує нотатку. Ctrl + Wheel(Windows/Linux) або⌘ + Wheel(Mac), щипок на тачпаді або два пальці на сенсорному екрані масштабують.- Палець панорамує вигляд.
Ctrl + PlusіCtrl + Minus(Windows/Linux) або⌘ + Plusі⌘ + Minus(Mac) змінюють масштаб кроками, як кнопкиZoom inіZoom out, аCtrl + 0(Windows/Linux) або⌘ + 0(Mac) повертає одразу100%, залишаючи середину екрана на місці.Ctrl + K(Windows/Linux) або⌘ + K(Mac) відкриває палітру, аEscїї закриває.
Це його єдині клавіші, і їх не можна перепризначити. Кожна інша клавіша доходить до сторінки без скасування, з фокусом чи без: Delete, Backspace, Space, Enter, Tab, Ctrl + A, Ctrl + F і кожне сполучення, яке редагує в редакторі.
Палітра шукає лише в документі й не перелічує жодних команд. Її порожнє поле показує префікси: # шукає таблиці, @ — стовпці, : — коментарі й нотатки, а ? перелічує префікси, як у редакторі — див. пошук у діаграмі. Слово без префікса показує No commands match над рядками, які шукають його в діаграмі.
Вибір рядка зсуває вигляд за правилом редактора, куди веде перехід, залишаючи масштаб як є, і обводить те, до чого дійшов, виведеним наперед: таблицю, таблицю, що містить стовпець чи коментар, або нотатку.
Вибір рядка або натискання Esc закриває палітру й залишає фокус без елемента, тож наступне коліщатко прокручує сторінку; клацніть вигляд, щоб знову дати йому коліщатко й клавіші. Поки палітру відкрито, коліщатко прокручує її список, а клавіші масштабу нічого не роблять.
З фокусом чи без, перетягування головною кнопкою миші панорамує вигляд звідки завгодно на полотні, зокрема й над таблицею. Клацання чи дотик без руху підсвічує зв’язки: на таблиці — зв’язки цієї таблиці, на лінії зв’язку — цю лінію, будь-де інде, нотатку включно, воно гасить підсвічування. Таке клацання також знімає обведення, яке залишив перехід з палітри. Вказівник, що стоїть на таблиці, підсвічує її зв’язки, доки там перебуває.
Жодне натискання нічого не виділяє, не переміщує й не редагує. Виділення немає, окрім обведення переходу, немає рамки виділення, і ні подвійне клацання, ні Enter не відкривають клітинки.
Завантаження
Поки src завантажується, повідомлення над серединою полотна показує Loading diagram поруч з індикатором завантаження, що обертається. Коли завантаження зазнає невдачі, воно показує Couldn't load the diagram поруч зі знаком попередження, доки його місце не займе новий src чи value або доки src не буде видалено. Натискання проходять крізь повідомлення до полотна, а воно читається мовою інтерфейсу, справа наліво в мові з таким письмом.
Кожен документ, що надходить, із src чи з value, вписується в рамку засобу перегляду: масштабується й прокручується так, щоб уся діаграма вмістилася, по центру, як це робить Fit, а масштаб і прокручування, які зберіг файл, відкладаються. Документ, переданий до того, як засіб перегляду отримав розмір, заданий до того, як він на сторінці, або коли його рамка порожня, вписується, щойно розмір з’являється. Пізніша зміна розміру зберігає масштаб; Fit вписує знову.
Засіб перегляду завантажує src лише тоді, коли він на сторінці. Вилучення його зі сторінки скасовує запит, що ще триває, а повернення завантажує src, який він ще не показав, зокрема й той, що зазнав невдачі, але ніколи — той, що він уже показує. Засіб перегляду, який більше не потрібен, закінчують через destroy.
Що він додає на сторінку
- Жодного воркера. Він не запускає жодного, тож політиці Content Security Policy для нього не потрібен
worker-src. - Жодного сховища. Він не записує ні cookie, ні
localStorage,sessionStorageчи IndexedDB. - Два види запитів: fetch для src, джерело якого сувора політика вносить у
connect-src, і модуль мови інтерфейсу, відмінної від англійської, з вашої власної збірки — див. setLocale. - Стилі в сконструйованих таблицях стилів, які пропускає сувора політика
style-src. Браузер без сконструйованих таблиць стилів, як-от Firefox до 101, натомість отримує елементи<style>, яким потрібенstyle-src 'unsafe-inline'. - Слухачі на
window. Імпорт точки входу додає три на весь час життя сторінки, дляmousedown,touchstartі власної події пакета@dineug/erd-editor/internal-forward-move-start. Konva, яка малює полотно, задаєwindow.Konvaі з першою сценою додає слухачі миші й дотику наwindowта слухачvisibilitychangeнаdocument, яких ніколи не видаляє. Точка входу редактора додає те саме. - До destroy кожен засіб перегляду стежить за кольоровою схемою операційної системи та за стилями сторінки на предмет власних властивостей, які описує setTheme.