@dineug/erd-editor 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +93 -280
  2. package/dist/components/erd/canvas/DiffOutline.template.d.ts +14 -0
  3. package/dist/components/erd/canvas/sceneTokens.d.ts +2 -0
  4. package/dist/components/erd/diff-viewer/diff-tree/DiffTree.d.ts +19 -0
  5. package/dist/components/erd/diff-viewer/diff-tree/DiffTree.styles.d.ts +12 -0
  6. package/dist/components/erd/diff-viewer/diff-tree/diffTreeModel.d.ts +49 -0
  7. package/dist/components/erd/diff-viewer/diff.d.ts +21 -19
  8. package/dist/components/erd/draw-target/placePill.d.ts +1 -3
  9. package/dist/components/erd/floating-toolbar/FloatingToolbar.d.ts +7 -4
  10. package/dist/components/erd/goToErdTarget.d.ts +40 -16
  11. package/dist/components/erd/relationshipHighlight.d.ts +18 -0
  12. package/dist/components/erd/welcome-screen/welcome-hints/WelcomeHints.styles.d.ts +5 -0
  13. package/dist/components/erd/welcome-screen/welcomeLayout.d.ts +7 -3
  14. package/dist/components/erd-editor/ErdEditor.styles.d.ts +4 -0
  15. package/dist/components/erd-editor/viewportLayout.d.ts +52 -0
  16. package/dist/components/explorer/Explorer.d.ts +12 -0
  17. package/dist/components/explorer/explorer-controller/ExplorerController.d.ts +11 -0
  18. package/dist/components/explorer/explorer-panel/ExplorerPanel.d.ts +14 -0
  19. package/dist/components/explorer/explorer-panel/ExplorerPanel.styles.d.ts +13 -0
  20. package/dist/components/explorer/explorer-search/ExplorerSearch.d.ts +12 -0
  21. package/dist/components/explorer/explorer-search/ExplorerSearch.styles.d.ts +13 -0
  22. package/dist/components/explorer/explorerCommands.d.ts +28 -0
  23. package/dist/components/explorer/explorerNavigation.d.ts +14 -0
  24. package/dist/components/explorer/explorerSearch.d.ts +71 -0
  25. package/dist/components/explorer/explorerTree.d.ts +90 -0
  26. package/dist/components/explorer/explorerView.d.ts +54 -0
  27. package/dist/components/{find-replace → explorer}/matchTarget.d.ts +5 -7
  28. package/dist/components/primitives/icon/icons.d.ts +8 -4
  29. package/dist/components/primitives/sash/Sash.d.ts +1 -0
  30. package/dist/components/primitives/tree/Tree.d.ts +30 -0
  31. package/dist/components/primitives/tree/Tree.styles.d.ts +5 -0
  32. package/dist/components/primitives/tree/treeModel.d.ts +42 -0
  33. package/dist/components/quick-search/QuickSearch.styles.d.ts +1 -0
  34. package/dist/components/quick-search/actions.d.ts +0 -3
  35. package/dist/components/quick-search/paletteList.d.ts +7 -0
  36. package/dist/components/quick-search/scopedActions.d.ts +5 -11
  37. package/dist/components/theme-builder/ThemeBuilder.styles.d.ts +3 -3
  38. package/dist/components/toolbar/Toolbar.styles.d.ts +0 -1
  39. package/dist/constants/layout.d.ts +7 -1
  40. package/dist/constants/open.d.ts +0 -1
  41. package/dist/engine/index.js +7 -7
  42. package/dist/erd-editor.umd.js +1008 -786
  43. package/dist/i18n/messages/ar-SA.d.ts +41 -15
  44. package/dist/i18n/messages/de-DE.d.ts +41 -11
  45. package/dist/i18n/messages/en/code.d.ts +0 -1
  46. package/dist/i18n/messages/en/common.d.ts +0 -1
  47. package/dist/i18n/messages/en/explorer.d.ts +37 -0
  48. package/dist/i18n/messages/en/findReplace.d.ts +5 -1
  49. package/dist/i18n/messages/en/index.d.ts +42 -12
  50. package/dist/i18n/messages/en/palette.d.ts +1 -7
  51. package/dist/i18n/messages/en/shortcuts.d.ts +3 -1
  52. package/dist/i18n/messages/en/toolbar.d.ts +0 -1
  53. package/dist/i18n/messages/es-ES.d.ts +41 -12
  54. package/dist/i18n/messages/eu-ES.d.ts +41 -11
  55. package/dist/i18n/messages/fa-IR.d.ts +41 -11
  56. package/dist/i18n/messages/fr-FR.d.ts +41 -12
  57. package/dist/i18n/messages/he-IL.d.ts +41 -12
  58. package/dist/i18n/messages/id-ID.d.ts +41 -10
  59. package/dist/i18n/messages/it-IT.d.ts +41 -12
  60. package/dist/i18n/messages/ja-JP.d.ts +41 -10
  61. package/dist/i18n/messages/ko-KR.d.ts +41 -10
  62. package/dist/i18n/messages/nl-NL.d.ts +41 -11
  63. package/dist/i18n/messages/pl-PL.d.ts +41 -13
  64. package/dist/i18n/messages/pt-BR.d.ts +41 -12
  65. package/dist/i18n/messages/pt-PT.d.ts +41 -12
  66. package/dist/i18n/messages/ro-RO.d.ts +41 -12
  67. package/dist/i18n/messages/ru-RU.d.ts +41 -13
  68. package/dist/i18n/messages/sk-SK.d.ts +41 -13
  69. package/dist/i18n/messages/sl-SI.d.ts +41 -13
  70. package/dist/i18n/messages/sv-SE.d.ts +41 -11
  71. package/dist/i18n/messages/tr-TR.d.ts +41 -11
  72. package/dist/i18n/messages/uk-UA.d.ts +41 -13
  73. package/dist/i18n/messages/zh-CN.d.ts +41 -10
  74. package/dist/i18n/messages/zh-TW.d.ts +41 -10
  75. package/dist/index.js +21553 -18898
  76. package/dist/{loadValue-B3EFSe9k.js → loadValue-BKvXDYoC.js} +1651 -1651
  77. package/dist/peer/index.js +23 -23
  78. package/dist/shared-store-2IUOt99m.js +1341 -0
  79. package/dist/styles/scrollbar.styles.d.ts +1 -1
  80. package/dist/themes/tokens.d.ts +9 -4
  81. package/dist/utils/diff/compareEntities.d.ts +39 -0
  82. package/dist/utils/diff/diffDocuments.d.ts +12 -0
  83. package/dist/utils/diff/index.d.ts +5 -0
  84. package/dist/utils/diff/pairEntities.d.ts +41 -0
  85. package/dist/utils/diff/types.d.ts +77 -0
  86. package/dist/utils/emitter.d.ts +2 -8
  87. package/dist/utils/find-replace/findMatches.d.ts +25 -12
  88. package/dist/utils/find-replace/matcher.d.ts +2 -0
  89. package/dist/utils/find-replace/present.d.ts +3 -2
  90. package/dist/utils/find-replace/preserveCase.d.ts +10 -0
  91. package/dist/utils/keyboard-shortcut/index.d.ts +11 -3
  92. package/dist/utils/takeover.d.ts +6 -0
  93. package/dist/utils/virtualRange.d.ts +15 -0
  94. package/dist/workers/exportPng.shared-worker.js +29 -29
  95. package/package.json +4 -4
  96. package/dist/components/erd/diff-viewer/tree-viewer/TreeViewer.d.ts +0 -12
  97. package/dist/components/erd/diff-viewer/tree-viewer/TreeViewer.styles.d.ts +0 -6
  98. package/dist/components/find-replace/FindReplace.d.ts +0 -13
  99. package/dist/components/find-replace/FindReplace.styles.d.ts +0 -27
  100. package/dist/components/find-replace/panelLayout.d.ts +0 -20
  101. package/dist/shared-store-fUggY7sI.js +0 -1341
  102. /package/dist/components/{find-replace → explorer}/fieldIcon.d.ts +0 -0
package/README.md CHANGED
@@ -4,155 +4,32 @@
4
4
 
5
5
  ![ERD Editor](https://github.com/dineug/erd-editor/blob/main/img/erd-editor-vscode.png?raw=true)
6
6
 
7
- `<erd-editor>` is a database-schema editor in a single custom element: design tables and
8
- relationships visually, import SQL DDL, GraphQL SDL, DBML or AML, and export DDL or generated code.
9
- It has no framework dependency and renders into a closed shadow root, so it drops into any page —
10
- React, Vue, Svelte, or plain HTML — without leaking styles either way.
11
-
12
- It is the same editor as [erd-editor.io](https://erd-editor.io), the
13
- [Google Drive app](https://workspace.google.com/marketplace/app/erd_editor/428467403360), the
7
+ `<erd-editor>` is a database-schema editor in one custom element. It has no framework dependency
8
+ and renders into a closed shadow root, so it drops into React, Vue, Svelte or plain HTML without
9
+ leaking styles either way. It is the same editor as [erd-editor.io](https://erd-editor.io), the
14
10
  [VS Code extension](https://marketplace.visualstudio.com/items?itemName=dineug.vuerd-vscode), the
15
- [IntelliJ plugin](https://plugins.jetbrains.com/plugin/23594-erd-editor) and the
11
+ [JetBrains plugin](https://plugins.jetbrains.com/plugin/23594-erd-editor) and the
16
12
  [Obsidian plugin](https://community.obsidian.md/plugins/erd-editor).
17
13
 
18
14
  ## Features
19
15
 
20
- ### Design
21
-
22
- - **Visual schema design** — tables, columns, memos, and four relationship cardinalities (Zero One,
23
- Zero N, One Only, One N)
24
- - **Quick edits** — `Alt`+`N` adds a table and `Alt`+`Enter` a column, `Alt`+`K` toggles the primary
25
- key on the focused column, or on every selected column when it is one of them, and `Delete` or
26
- `Backspace` removes the selection, each in one undo step; the Shortcuts page of the editor's
27
- Settings tab lists every key, and `setKeyBindingMap` remaps them
28
- - **Link existing columns** — while you draw a relationship with a mouse or a pen, the buttons
29
- beside the table it ends on either map the parent's key onto columns that table already has or add
30
- new ones, named after the parent table when the key is one word (`user_id` for `user`'s `id`), and
31
- **Map Columns** in a relationship's right-click menu changes its columns later
32
- - **Referential actions** — set **On Delete** and **On Update** (NO ACTION, CASCADE, SET NULL, SET
33
- DEFAULT, RESTRICT) from a relationship's right-click menu, which marks one the current database
34
- leaves out; the line shows them at its child end as `D:C U:R`, and View Option's Referential
35
- Actions hides the labels. SQL, DBML and AML import read them, and the DDL export and the code
36
- generators that have a place for them write the ones the target supports
37
- - **Alternate keys** — View Option's Alternate Key marks the columns of each unique index over two
38
- or more columns as `AK1.1`, `AK1.2`, and SQL import reads a UNIQUE over several columns as one
39
- such index
40
- - **Table groups** — draw a box behind related tables, which you name and can color, with
41
- **New Table Group** in the canvas menu or the command palette, or group the selected tables from
42
- their right-click menu. A table joins a group when you drop it inside and leaves when you drop it
43
- outside, dragging a group by its title moves its tables with it, each member's header takes the
44
- group's color, View Option hides the groups, and DBML import and the Code Generator's DBML carry
45
- them as `TableGroup`s
46
- - **Auto Layout** — place every table again by Force, Flow or a vertical or horizontal tree from the
47
- canvas menu or the command palette, table groups kept together, in one undo step; Force shows a
48
- preview you apply or cancel, and the others land at once
49
- - **Copy, paste and colors** — copy tables and memos and paste them as new ones, into another
50
- diagram too or into a spreadsheet as a grid, hold `Alt` while dragging to duplicate them, and
51
- color a table, memo or table group from its right-click menu
52
- - **Clean diffs** — the scroll position and zoom, the open tab, the code generator's language and
53
- name cases and the bracket type are locked in a new document
54
- ([Loading and saving](#loading-and-saving)), so the file keeps the values they had when locked
55
- and looking around never changes it; the file, written in a fixed order, also leaves out
56
- measured widths, connector anchors and removed items
57
-
58
- ### Import
59
-
60
- - **SQL DDL import** — bring in a `.sql` dump from any of the eight vendors below. The parser reads
61
- `CREATE TABLE`, `CREATE INDEX`, `ALTER TABLE` constraints and table and column comments
62
- (`COMMENT ON`, SQL Server's `sp_addextendedproperty`), and skips what it does not recognize, so an
63
- awkward dump imports partially rather than failing outright
64
- - **GraphQL SDL import** — bring in a schema from any tool that emits SDL. Object types become
65
- tables, scalars map to the diagram's own dialect, and the fields that point at another type become
66
- the relationships; the root types and the wrapper types Relay, Federation and Hasura generate are
67
- left out rather than drawn as tables
68
- - **DBML import** — bring in a `.dbml` file written for dbdiagram.io or dbdocs.io, or emitted by
69
- `sql2dbml` or `prisma-dbml-generator`. Tables, columns, indexes, enums, header colors, every `Ref`
70
- spelling and each `TableGroup` arrive; a `Project` or a sticky `Note` is skipped rather than
71
- refused
72
- - **AML import** — bring in an `.aml` file written for [Azimutt](https://azimutt.app), in either the
73
- v2 or the legacy v1 spelling. Entities, attributes, indexes, enums, colors and every relation
74
- arrow arrive; a check and a struct type are skipped rather than refused, and a view arrives as a
75
- table
76
- - **Imports land laid out** — a schema picked from the Import menu, the command palette or a host's
77
- file dialog arrives with its tables placed by their relationships (in rows when it has none), and
78
- one undo puts the previous diagram back; a `setSchema*` call, as from your own file dialog, is
79
- laid out the same way when given `{ placement: 'auto' }`
80
- - **Import and Add** — the menu beside Import, and its five formats in the command palette, add a
81
- `.sql`, GraphQL, DBML, AML or `.erd.json` file to the diagram instead of replacing it: its tables
82
- arrive below everything already there, laid out the same way (an `.erd.json` file keeps its own
83
- placement), selected, and one undo takes them away. A table whose name is already taken arrives as
84
- a second table rather than merging, and a foreign key to a table outside the file is dropped;
85
- `{ mode: 'append' }` does the same from `setSchemaJSON` and the four `setSchema*` methods, which
86
- lay the tables out only with `placement: 'auto'` and stand them in rows otherwise
87
-
88
- ### Export and code
89
-
90
- - **SQL DDL export** — Databricks, MariaDB, MSSQL, MySQL, Oracle, PostgreSQL, Snowflake and SQLite,
91
- from the Schema SQL tab, which saves the DDL as a `.sql` file or copies it, and from
92
- `getSchemaSQL(vendor?, options?)`
93
- - **Schema SQL options** — a panel beside the DDL picks the database and the bracket type, CREATE
94
- TABLE IF NOT EXISTS or drop and re-create and a `USE` or `CREATE + USE` header, each where the
95
- database has it, and the tables by table group, and keeps SQL of your own to write before and
96
- after the tables. The statements, header and tables stay with this editor until the element goes
97
- and never reach the file; the scripts are saved in the document
98
- - **Code generation** — TypeScript, GraphQL, C#, Java, JPA, Kotlin, Scala, Go, SQLAlchemy, TypeORM,
99
- Sequelize, Drizzle, DBML, AML, Mermaid, PHP, Doctrine, Rust, SeaORM, Swift, Zod and JSON Schema,
100
- from the Code Generator tab. Its options panel picks the language, the database, the table and
101
- column name cases and, for Doctrine, JPA and SeaORM, the bracket type, and saves the code as a
102
- file with the language's extension
103
- - **Export** — `.erd.json`, `.sql`, and a `.png` or `.svg` from a dialog with a preview: transparent
104
- background, light or dark, the PNG at 1x to 3x or copied to the clipboard instead
105
-
106
- ### Find and navigate
107
-
108
- - **Quick search** — `Ctrl`/`Cmd`+`K` opens the command palette to run editor commands (new table,
109
- import, export, Auto Layout, tabs, theme, language and more), or to jump to a table after `#`, a
110
- column after `@`, and a comment or memo after `:`; Korean also matches by its initial consonants
111
- (`ㅅㅇㅈ` finds 사용자)
112
- - **Find and replace** — `Ctrl`/`Cmd`+`F` searches table and column names, comments and memos, with
113
- match case, whole word and regular expressions, and one undo takes back a Replace All
114
- - **Visualization** — Graph mode draws a force-directed view of how the tables relate. Flow mode
115
- lays them out by their relationships, lights a table you hover and the tables it relates to, and
116
- shows names only, keys only or all fields; **Focus on this table** in a table's right-click menu
117
- opens Flow on that table and its neighbours, or, when it is one of several selected tables, as
118
- **Focus on selected tables** on all of them and their neighbours, as `Alt`+`F` does for the
119
- selection, and neither view writes its layout into the file
120
- - **Zoom and pan** — pinch a trackpad or two fingers to zoom, drag with the middle button to pan
121
- from anywhere, and click the zoom level on the floating toolbar to go back to 100%
122
- - **Time travel** — replay this editing session's history on the canvas and jump to any point in it,
123
- from the toolbar
124
- - **Diff viewer** — compare the diagram with another `.json` file from the canvas menu, or from
125
- `setDiffValue`
126
- - **Undo / redo** — every edit, from the toolbar or `Ctrl`/`Cmd`+`Z` and `Ctrl`/`Cmd`+`Shift`+`Z`,
127
- in the editor's own history
128
-
129
- ### Language and theme
130
-
131
- - **Display language** — the editor's menus, panels, dialogs, command palette and messages in 25
132
- languages, Arabic, Hebrew and Persian laid out right to left while the diagram stays left to
133
- right. The element shows English until the host turns on `enable-locale-picker`, which adds the
134
- toolbar's language button and **Display Language** and follows System, or calls `setLocale`
135
- ([Display language](#display-language)); table and column names, SQL keywords, data types and
136
- generated code stay as they are
137
- - **Theme** — once the host sets `enable-theme-builder`, the toolbar's theme builder picks the
138
- appearance, a gray color and an accent color, and **Theme** in the command palette picks the
139
- appearance; System follows the OS color scheme or what `setSystemAppearance` names, and the
140
- element stores nothing (`changePresetTheme` tells the host)
141
- - **Welcome screen** — opt-in with `enable-welcome-screen`: an empty diagram you can edit opens on a
142
- menu of New Table, New Memo, Import, Command Palette and Shortcuts, with arrows at the toolbar's
143
- search, theme and language buttons where the element shows them and at the floating toolbar where
144
- the canvas has room, until its first table, shown memo or shown table group
145
-
146
- ### Collaboration hooks
147
-
148
- - **Collaboration hooks** — the editor emits the actions it makes and applies a peer's through
149
- `getSharedStore()`; you supply the transport, and seed a joining editor with its `runtimeValue`
150
- ([Collaboration](#collaboration))
151
- - **Headless entries** — `engine.js` runs a replica with no DOM, so a worker can apply the same
152
- actions and serialize the document off the main thread, and `peer.js` runs a peer that edits by
153
- dispatching actions, which the
154
- [ERD Editor MCP server](https://github.com/dineug/erd-editor/tree/main/packages/mcp-server#readme)
155
- is built on
16
+ - **Design** — tables, columns, memos and table groups, four relationship cardinalities, ON DELETE
17
+ and ON UPDATE, alternate keys, Auto Layout
18
+ - **Import** — SQL DDL, GraphQL SDL, DBML and AML from the menu or [`setSchema*`](#importing-a-schema),
19
+ replacing the diagram or adding to it
20
+ - **Export** — DDL for eight databases, also from `getSchemaSQL()`, code in 22 languages and ORMs,
21
+ PNG and SVG
22
+ - **Navigate** — command palette (`Ctrl`/`Cmd`+`K`), an Explorer tree with find and replace, Graph
23
+ and Flow views
24
+ - **History** — undo and redo, time travel through the session, a diff viewer (`setDiffValue()`)
25
+ - **25 languages** and a System, Light or Dark theme, their pickers opt-in with an attribute
26
+ - **Collaboration** — [`getSharedStore()`](#collaboration) relays edits over your own transport,
27
+ and the [headless entries](#headless-replica) run the same document with no DOM
28
+
29
+ **Databases:** Databricks, MariaDB, MSSQL, MySQL, Oracle, PostgreSQL, Snowflake, SQLite
30
+
31
+ **Code:** TypeScript, GraphQL, C#, Java, JPA, Kotlin, Scala, Go, SQLAlchemy, TypeORM, Sequelize,
32
+ Drizzle, DBML, AML, Mermaid, PHP, Doctrine, Rust, SeaORM, Swift, Zod, JSON Schema
156
33
 
157
34
  ## Install
158
35
 
@@ -160,11 +37,9 @@ It is the same editor as [erd-editor.io](https://erd-editor.io), the
160
37
  npm install @dineug/erd-editor
161
38
  ```
162
39
 
163
- Your bundler resolves, dedupes and tree-shakes the package's ES modules and dependencies. The PNG
164
- and SVG export, the Flow and tree layouts and the syntax highlighting run in shared workers spawned
165
- as `new SharedWorker(new URL('./workers/…', import.meta.url), { type: 'module', name })`, which
166
- Vite, webpack and Rspack emit beside your chunks and esbuild does not. A strict CSP needs
167
- `worker-src 'self'`. Without a bundler, use the [Script tag](#script-tag) build.
40
+ The PNG and SVG export, the Flow and tree layouts and the syntax highlighting run in shared
41
+ workers, which Vite, webpack and Rspack emit beside your chunks and esbuild does not. A strict CSP
42
+ needs `worker-src 'self'`. Without a bundler, use the [script tag](#script-tag) build.
168
43
 
169
44
  ## Usage
170
45
 
@@ -184,8 +59,8 @@ editor.addEventListener('change', () => {
184
59
 
185
60
  ### Server-side rendering
186
61
 
187
- Importing the package registers the element, which throws without a DOM, so in Next.js, Nuxt,
188
- SvelteKit or Astro import it on the client:
62
+ Importing the package registers the element, which needs a DOM, so in Next.js, Nuxt, SvelteKit or
63
+ Astro import it on the client:
189
64
 
190
65
  ```js
191
66
  useEffect(() => {
@@ -195,9 +70,8 @@ useEffect(() => {
195
70
 
196
71
  ### Vite
197
72
 
198
- In development Vite would look the worker files up in its pre-bundle cache, so exclude the editor
199
- and include the CommonJS ELK bundle its layout worker imports, or the Flow and tree layouts fail. A
200
- production build needs nothing.
73
+ In development, keep the editor out of Vite's pre-bundling and include the ELK bundle its layout
74
+ worker imports, or the Flow and tree layouts fail. A production build needs nothing.
201
75
 
202
76
  ```js
203
77
  // vite.config.js
@@ -211,43 +85,32 @@ export default {
211
85
 
212
86
  ### Script tag
213
87
 
214
- `dist/erd-editor.umd.js`, served by `unpkg` and `jsdelivr`, bundles every dependency and worker,
215
- registers `<erd-editor>` and puts `setExportFileCallback`, `setImportFileCallback` and
216
- `createKeyBindingMap` on `window.ErdEditor`. Its workers are `data:` URLs, so a strict CSP needs
217
- `worker-src data:`. Pin a version in the URL beyond a demo.
88
+ `dist/erd-editor.umd.js` bundles every dependency and worker, registers `<erd-editor>` and puts
89
+ `setExportFileCallback`, `setImportFileCallback` and `createKeyBindingMap` on `window.ErdEditor`.
90
+ Its workers are `data:` URLs, so a strict CSP needs `worker-src data:`. Pin a version beyond a demo.
218
91
 
219
92
  ```html
220
93
  <erd-editor style="display: block; width: 100%; height: 100vh"></erd-editor>
221
94
  <script src="https://cdn.jsdelivr.net/npm/@dineug/erd-editor/dist/erd-editor.umd.js"></script>
222
95
  ```
223
96
 
224
- ### HTML
225
-
226
- In a page a bundler serves:
227
-
228
- ```html
229
- <erd-editor system-dark-mode style="display: block; height: 100vh"></erd-editor>
230
- <script type="module">
231
- import '@dineug/erd-editor';
232
- </script>
233
- ```
234
-
235
97
  ## API
236
98
 
237
- The package exports the element's type as `ErdEditorElement`.
99
+ The element's type is exported as `ErdEditorElement`. The
100
+ [Element API docs](https://docs.erd-editor.io/docs/api/erd-editor-element) cover each member in
101
+ full.
238
102
 
239
103
  ### Attributes
240
104
 
241
105
  | Attribute | Property | Description |
242
106
  | --- | --- | --- |
243
- | `readonly` | `readonly` | Blocks editing and `change`; `clear()` and every load you start but `setInitialValue()` are ignored. |
244
- | `system-dark-mode` | `systemDarkMode` | On, sets the appearance to `system`; off, keeps the light or dark it shows. |
245
- | `enable-theme-builder` | `enableThemeBuilder` | Shows the theme builder's toolbar button and the palette's Theme. |
246
- | `enable-locale-picker` | `enableLocalePicker` | Shows the toolbar's language button and the palette's Display Language, and makes System the default. |
247
- | `enable-welcome-screen` | `enableWelcomeScreen` | Shows the welcome screen over an empty, editable diagram, again after an undo back to empty. |
107
+ | `readonly` | `readonly` | Blocks editing and `change`; only `setInitialValue()` still loads. |
108
+ | `system-dark-mode` | `systemDarkMode` | Sets the appearance to `system`. |
109
+ | `enable-theme-builder` | `enableThemeBuilder` | Shows the theme builder and the palette's Theme. |
110
+ | `enable-locale-picker` | `enableLocalePicker` | Shows the language button and the palette's Display Language, System by default. |
111
+ | `enable-welcome-screen` | `enableWelcomeScreen` | Shows the welcome screen over an empty, editable diagram. |
248
112
 
249
- An attribute is on when present with no value or `"true"`, off for any other value (`"false"`,
250
- `"readonly"`).
113
+ An attribute is on when present with no value or `"true"`.
251
114
 
252
115
  ### Properties
253
116
 
@@ -260,78 +123,55 @@ An attribute is on when present with no value or `"true"`, off for any other val
260
123
 
261
124
  | Method | Description |
262
125
  | --- | --- |
263
- | `setInitialValue(value)` | Load a document with no undo entry, clearing the history; `''` starts a new one. |
264
- | `getSchemaSQL(vendor?, options?)` | DDL for one of the [eight vendors](#export-and-code), by default the document's, scripts included. `options` (`SchemaSQLOptions`): `statements` `create` (default), `ifNotExists` or `recreate`; `header` `none` (default), `use` or `createAndUse`, written only for a plain-identifier database name. |
126
+ | `setInitialValue(value)` | Load a document with no undo entry; `''` starts a new one. |
127
+ | `getSchemaSQL(vendor?, options?)` | DDL for one of the eight databases, by default the document's. `options`: `statements` (`create`, `ifNotExists`, `recreate`), `header` (`none`, `use`, `createAndUse`). |
265
128
  | `setSchemaSQL(value, options?)`, `setSchemaGraphQL`, `setSchemaDBML`, `setSchemaAML` | Replace the document with parsed DDL, GraphQL SDL, DBML or AML, or append it ([Importing a schema](#importing-a-schema)). |
266
129
  | `setSchemaJSON(value, options?)` | Load an `.erd.json` document as `value` does, or append it. |
267
- | `setDiffValue(value)` | Diff another document over the ERD tab without switching to it; it opens nothing before that tab first shows. |
130
+ | `setDiffValue(value)` | Diff another document over the ERD tab. |
268
131
  | `setPresetTheme(options)` | Set `appearance` (`light`, `dark`, `system`), `grayColor` and `accentColor`. |
269
132
  | `setSystemAppearance(appearance)` | Name the light or dark `system` shows; `null` follows the OS. |
270
- | `setLocale(locale)` | Set the display language, `'system'` or a [code](#display-language); emits nothing. |
271
- | `setSystemLocale(tag)` | Name, as a BCP 47 tag, the language `system` shows, for a host with its own UI language; `null` reads `navigator.languages`. |
272
- | `setTheme(theme)` | Override theme tokens with string values. Each call replaces the earlier overrides, which outlast `setPresetTheme`. |
133
+ | `setLocale(locale)` | Set the display language, `'system'` or a [code](#display-language). |
134
+ | `setSystemLocale(tag)` | Name the BCP 47 language `system` shows; `null` reads `navigator.languages`. |
135
+ | `setTheme(theme)` | Override theme tokens; each call replaces the earlier overrides. |
273
136
  | `setKeyBindingMap(map)` | Remap [shortcuts](#key-bindings) but `edit`, `stop`, `undo`, `redo` and the zoom keys. |
274
- | `getSharedStore(config?)` | A [shared store](#collaboration): `subscribe`, `dispatch`, `dispatchSync`, `connection`, `disconnect`, `flushStreamBuffers`, `destroy`. |
137
+ | `getSharedStore(config?)` | A [shared store](#collaboration) for collaboration. |
275
138
  | `focus()` / `blur()` | Move focus in or out. |
276
- | `clear()` | Empty the document and keep its settings; one undo brings it back. |
139
+ | `clear()` | Empty the document and keep its settings, in one undo step. |
277
140
  | `destroy()` | Release the editor's listeners, subscriptions and shared stores. |
278
141
 
279
142
  ### Events
280
143
 
281
144
  | Event | Description |
282
145
  | --- | --- |
283
- | `change` | The document changed; read `editor.value` ([Loading and saving](#loading-and-saving)). |
284
- | `changePresetTheme` | The theme changed in the editor; `event.detail` holds the options (`appearance: 'system'` for System). |
146
+ | `change` | The document changed; read `editor.value`. |
147
+ | `changePresetTheme` | The theme changed in the editor; `event.detail` holds the options. |
285
148
  | `changeLocale` | A language was picked in the editor; `event.detail.locale` holds it. |
286
149
 
287
150
  ### Loading and saving
288
151
 
289
- Save `value`; `runtimeValue`, which also keeps removed entities, only seeds a
290
- [collaborator](#collaboration).
291
-
292
- A new document locks each setting the Settings tab lists under **Lock**, which then saves its value
293
- at locking. A loaded document keeps its locks, or has all on if it predates them. A replacing load
294
- (`value`, an import, a peer's load, or the undo of a load or of `clear()`) keeps on screen what the
295
- incoming document locks (for an import, the current locks), scroll and zoom aside, and takes its
296
- values for the rest.
297
-
298
- `change` fires 200 ms after the last change, never under `readonly` or for a scroll, zoom, tab, code
299
- setting or bracket type under its lock. A file another release wrote, or one edited by hand, can
300
- differ from `value` once loaded: detect edits by a [replica](#headless-replica)'s `changed`, not by
301
- bytes.
302
-
303
- Under `readonly`, only the scroll, zoom, tab, database, code language, name cases and bracket type
304
- change; a peer's actions relayed into `getSharedStore().dispatch` still apply.
152
+ - Save `value`. `runtimeValue` also keeps removed entities and only seeds a
153
+ [collaborator](#collaboration).
154
+ - `change` fires 200 ms after the last change, never under `readonly`, and never for scroll, zoom,
155
+ the open tab or the code settings while the document locks them, which a new document does.
156
+ - A file written by hand or by another release can differ from `value` once loaded, so detect edits
157
+ with a [replica](#headless-replica)'s `changed`, not by comparing bytes.
305
158
 
306
159
  ### Importing a schema
307
160
 
308
- The four text `setSchema*` methods take
309
- `{ placement?: 'auto' | 'grid', mode?: 'replace' | 'append' }`, `setSchemaJSON` only `mode`; each
310
- lands in one undo step and ignores `''`; a replace with unreadable text loads an empty document.
311
-
312
- `'grid'`, the default, lands at once in rows. `'auto'` lays the tables out first, as the Import menu
313
- does, and returns a `Promise` that resolves on landing, keeping settings changed meanwhile. A load
314
- before then (a replacing import, `value`, `setInitialValue`, `clear()`, a peer's load or the undo of
315
- a load or `clear()`) supersedes it, and it resolves with nothing loaded; a readonly editor resolves
316
- at once.
317
-
318
- `mode: 'append'` is [Import and Add](#import), table groups included: it lands below hidden groups
319
- too, keeps every setting but the tab and scroll, and selects new groups while groups show. An
320
- `'auto'` append supersedes nothing: it lands after earlier `'auto'` imports, below the diagram as it
321
- stands then, and only a later load or replace drops it. From another tab it brings up the ERD tab
322
- first; a readonly editor adds nothing.
161
+ - The four text `setSchema*` methods take `{ placement?: 'auto' | 'grid', mode?: 'replace' | 'append' }`,
162
+ and `setSchemaJSON` only `mode`. Each lands in one undo step and ignores `''`.
163
+ - `'grid'`, the default, lands at once in rows. `'auto'` lays the tables out as the Import menu does
164
+ and returns a `Promise` that resolves when they land; a later load supersedes it.
165
+ - `mode: 'append'` adds the tables below the diagram, as Import and Add does.
323
166
 
324
167
  ### Theme and language
325
168
 
326
- The element starts dark; `setPresetTheme({ appearance: 'system' })` follows the OS, or the light or
327
- dark `setSystemAppearance` names. `setLocale` applies at once, so one set before appending paints
328
- the first frame. `setSystemLocale` matters only under System and shows English for a tag the
329
- editor lacks. Neither choice is stored; keep what `changePresetTheme` and `changeLocale` report.
169
+ The element starts dark and English and stores neither choice: `setPresetTheme` and `setLocale`
170
+ set them, and your host keeps what `changePresetTheme` and `changeLocale` report.
330
171
 
331
172
  ## Collaboration
332
173
 
333
- A joiner starts from the first editor's runtime value, so an undo there restores removed entities
334
- whole in both; then each relays its actions:
174
+ A joiner starts from the first editor's `runtimeValue`, then each relays its actions:
335
175
 
336
176
  ```js
337
177
  joiner.setInitialValue(editor.runtimeValue);
@@ -343,52 +183,36 @@ remote.subscribe(actions => local.dispatch(actions));
343
183
  ```
344
184
 
345
185
  An editor never forwards what it received, so with three or more, send each one's batches to every
346
- other.
347
-
348
- `getSharedStore` takes `{ getNickname?, mouseTracker?, focusTracker? }`; `mouseTracker` broadcasts
349
- the cursor and `focusTracker` the focused cell, selection and drag box, both on by default.
350
- `disconnect()` holds outgoing actions while your transport is down; `connection()` releases them.
351
- Call `flushStreamBuffers()` before destroying the store or editor, or drags, color changes and memo
352
- resizes in their quiet period never reach the peers.
186
+ other. Call `flushStreamBuffers()` before destroying a store, or the last drags and resizes never
187
+ reach the peers. `getSharedStore({ getNickname, mouseTracker, focusTracker })` also shares cursors
188
+ and focus.
353
189
 
354
190
  ## Key bindings
355
191
 
356
- `createKeyBindingMap()` returns a new map of the default shortcuts. A chord is its modifiers
357
- (`Shift`, `Alt`, `Control`, `Meta`, or `$mod`: Cmd on macOS and iOS, Ctrl elsewhere) joined by `+`,
358
- then a `KeyboardEvent.code` or a `key` in any case, matching only those exact modifiers.
359
-
360
- Entries are `ShortcutOption`s, `{ shortcut, preventDefault?, stopPropagation? }`; a remapped one
361
- without flags lets the browser default run and the keydown bubble. `setKeyBindingMap` replaces each
362
- list it names. The defaults stop `search`, `findReplace`, `undo`, `redo`, `focusView`, zoom and
363
- `zenMode`, so bubble-phase listeners miss them while the editor is focused, and a host that takes
364
- keys first (global hotkeys, a capture listener) must let them through, or leave `$mod+KeyF` to the
365
- page with `setKeyBindingMap({ findReplace: [] })`. The `KeyBindingMap`, `KeyBindingName` and
366
- `ShortcutOption` types are exported.
192
+ `createKeyBindingMap()` returns the default shortcuts, and `setKeyBindingMap` replaces each list it
193
+ names. A chord is modifiers (`Shift`, `Alt`, `Control`, `Meta`, or `$mod` for Cmd on macOS and Ctrl
194
+ elsewhere) joined by `+` with a `KeyboardEvent.code` or `key`; a space separates the chords of a
195
+ sequence, such as `KeyT KeyG`. Several defaults, search and find and replace among them, stop the
196
+ keydown, so to leave `$mod+KeyF` to the page, call `setKeyBindingMap({ findReplace: [] })`.
367
197
 
368
198
  ## Display language
369
199
 
370
- The codes are `en`, `ar-SA`, `de-DE`, `es-ES`, `eu-ES`, `fa-IR`, `fr-FR`, `he-IL`, `id-ID`, `it-IT`,
371
- `ja-JP`, `ko-KR`, `nl-NL`, `pl-PL`, `pt-BR`, `pt-PT`, `ro-RO`, `ru-RU`, `sk-SK`, `sl-SI`, `sv-SE`,
372
- `tr-TR`, `uk-UA`, `zh-CN` and `zh-TW`. `setLocale('system')` follows System even without
373
- `enable-locale-picker`. The `LocaleCode` and `LocaleOption` types are exported; cast a stored
374
- string `as LocaleOption`, since an unknown value is ignored.
200
+ `en`, `ar-SA`, `de-DE`, `es-ES`, `eu-ES`, `fa-IR`, `fr-FR`, `he-IL`, `id-ID`, `it-IT`, `ja-JP`,
201
+ `ko-KR`, `nl-NL`, `pl-PL`, `pt-BR`, `pt-PT`, `ro-RO`, `ru-RU`, `sk-SK`, `sl-SI`, `sv-SE`, `tr-TR`,
202
+ `uk-UA`, `zh-CN` and `zh-TW`. Arabic, Hebrew and Persian lay the editor out right to left. The
203
+ `LocaleCode` and `LocaleOption` types are exported.
375
204
 
376
- ## Syntax highlighting
205
+ ## Workers
377
206
 
378
- [Shiki](https://shiki.style) highlights the panels' code, DBML and AML as SQL, with a JavaScript
379
- regex engine, so a CSP needs no `wasm-unsafe-eval`, from a shared worker built when a code panel
380
- first renders; with a bundler, a page that opens none never fetches the grammars (the UMD file
381
- carries them).
382
-
383
- Without `SharedWorker`, as in Chrome on Android before Chrome 148, the panels log the error and show
384
- plain text, the Flow view places nothing, Auto Layout's Flow and tree placements say "Could not
385
- place tables" (Force works), an `'auto'` import lands in rows, and PNG and SVG exports draw on the
386
- main thread.
207
+ [Shiki](https://shiki.style) highlights the code panels with a JavaScript regex engine, so a CSP
208
+ needs no `wasm-unsafe-eval`. Without `SharedWorker`, as in Chrome on Android before Chrome 148, the
209
+ code panels show plain text, the Flow view and the Flow and tree layouts place nothing, an `'auto'`
210
+ import lands in rows, and PNG and SVG exports draw on the main thread.
387
211
 
388
212
  ## File dialogs
389
213
 
390
- Import and export go through page-wide callbacks, so a host without a browser file dialog (an IDE
391
- webview) supplies its own:
214
+ Import and export go through page-wide callbacks, so a host without a browser file dialog, such as
215
+ an IDE webview, supplies its own:
392
216
 
393
217
  ```js
394
218
  import { setExportFileCallback, setImportFileCallback } from '@dineug/erd-editor';
@@ -404,16 +228,12 @@ setImportFileCallback(async ({ type, op, accept, mode }) => {
404
228
  });
405
229
  ```
406
230
 
407
- Export gets `.erd.json`, `.sql`, PNG, SVG and the Code Generator's file. An import's `op` is
408
- `'diff'` for the Diff Viewer, whose file goes to `setDiffValue()`, so test it first; otherwise it is
409
- `'set'`. Skip a `type` you do not handle: a replacing `setSchemaJSON()` empties the document on any
410
- other payload. `accept` lists the type's extensions (`.json`, `.sql`,
411
- `.graphql,.gql,.graphqls`, `.dbml`, `.aml`), and `mode` is `'append'` from Import and Add. Unset or
412
- `null`, the browser's download and file picker work.
231
+ Skip a `type` you do not handle: a replacing `setSchemaJSON()` empties the document on any other
232
+ payload. Unset or `null`, the browser's download and file picker work.
413
233
 
414
234
  ## Headless replica
415
235
 
416
- The `engine.js` replica takes the same actions with no DOM:
236
+ `engine.js` applies the same actions with no DOM, so a worker can keep and serialize the document:
417
237
 
418
238
  ```js
419
239
  import { createReplicationStore } from '@dineug/erd-editor/engine.js';
@@ -424,18 +244,12 @@ store.on({ change: ({ value, changed }) => changed && persist(value) });
424
244
  store.dispatch(actions);
425
245
  ```
426
246
 
427
- `value` and `runtimeValue` mirror the element's; `dispatch` applies on the next microtask,
428
- `dispatchSync` at once, and `destroy` releases the store. `change` comes 200 ms after the last
429
- document action, locked settings included, with `changed` false when `value` matches what the store
430
- last reported or loaded, never your file. `ReplicationStore` and `ReplicationChange` are exported
431
- types.
432
-
433
- ### Headless peer
247
+ `changed` is false when `value` matches what the store last reported or loaded.
434
248
 
435
- `peer.js` runs a collaboration peer with no DOM, the base of the ERD Editor MCP server. Its
436
- `createPeerStore({ nickname })` store dispatches actions, receives a peer's batches and undoes its
437
- own dispatches; `PeerStoreError`, per-module action barrels (`tableActions`, `tableActions$`, …) and
438
- `createSchemaSQL` come with it.
249
+ `peer.js` runs a collaboration peer with no DOM: `createPeerStore({ nickname })` dispatches actions,
250
+ receives a peer's batches and undoes its own. The
251
+ [ERD Editor MCP server](https://github.com/dineug/erd-editor/tree/main/packages/mcp-server#readme)
252
+ is built on it.
439
253
 
440
254
  ## Development
441
255
 
@@ -451,10 +265,9 @@ What a change runs and carries is in
451
265
 
452
266
  ## Documentation
453
267
 
454
- - [Editing Guide](https://docs.erd-editor.io/docs/category/guides) — editing, import and export,
455
- relationships, quick search, visualization, code generation, settings
268
+ - [Editing Guide](https://docs.erd-editor.io/docs/category/guides) — every editor feature
456
269
  - [Element API](https://docs.erd-editor.io/docs/api/erd-editor-element) — the `<erd-editor>`
457
- element's API
270
+ element in full
458
271
  - [Documentation](https://docs.erd-editor.io)
459
272
 
460
273
  ## Issues
@@ -0,0 +1,14 @@
1
+ /** @jsxHost konva */
2
+ export type DiffOutlineOptions = {
3
+ name: string;
4
+ stroke: string | null;
5
+ width: number;
6
+ height: number;
7
+ cornerRadius: number;
8
+ };
9
+ /**
10
+ * The outline a diff pane draws round a box standing at its group's origin,
11
+ * centred on the box's edge and taking no press; none while stroke is null.
12
+ */
13
+ export declare const diffOutlineRect: ({ name, stroke, width, height, cornerRadius, }: DiffOutlineOptions) => import("@dineug/r-html/jsx-runtime").JSX.Element | null;
14
+ //# sourceMappingURL=DiffOutline.template.d.ts.map
@@ -59,6 +59,8 @@ export declare const TABLE_CORNER_RADIUS = 6;
59
59
  export declare const FOCUS_BORDER_HEIGHT = 1.5;
60
60
  /** What the ring outside a table box costs, as outline and box-shadow both do. */
61
61
  export declare const RING_WIDTH = 1;
62
+ /** The outline a diff pane draws round an entity added, removed or only moved. */
63
+ export declare const DIFF_OUTLINE_WIDTH = 2;
62
64
  /**
63
65
  * The drop shadow a view card sits on, deeper than any a document box casts.
64
66
  * The alpha is the shadow's own, since the minimap shadow token it borrows is
@@ -0,0 +1,19 @@
1
+ import { FC } from '@dineug/r-html';
2
+ import { AppContext } from '../../../appContext';
3
+ import { DiffEntries } from '../../../../utils/diff';
4
+ export type DiffTreeProps = {
5
+ prevApp: AppContext;
6
+ app: AppContext;
7
+ entries: DiffEntries;
8
+ /** The width the diff gives the tree, which a drag on its edge asks to change. */
9
+ width: number;
10
+ onResize: (width: number) => void;
11
+ };
12
+ /**
13
+ * What a diff found, on the tree the Explorer draws: the changed entities and
14
+ * the tables they are in, each named in the colour of what happened to it and
15
+ * ending on its status letter. A row takes either pane to its entity.
16
+ */
17
+ declare const DiffTree: FC<DiffTreeProps>;
18
+ export default DiffTree;
19
+ //# sourceMappingURL=DiffTree.d.ts.map
@@ -0,0 +1,12 @@
1
+ export declare const root: import('@dineug/r-html').CSSTemplateLiterals;
2
+ export declare const header: import('@dineug/r-html').CSSTemplateLiterals;
3
+ export declare const filter: import('@dineug/r-html').CSSTemplateLiterals;
4
+ export declare const body: import('@dineug/r-html').CSSTemplateLiterals;
5
+ export declare const empty: import('@dineug/r-html').CSSTemplateLiterals;
6
+ export declare const sash: import('@dineug/r-html').CSSTemplateLiterals;
7
+ export declare const rowIcon: import('@dineug/r-html').CSSTemplateLiterals;
8
+ export declare const name: import('@dineug/r-html').CSSTemplateLiterals;
9
+ export declare const count: import('@dineug/r-html').CSSTemplateLiterals;
10
+ export declare const status: import('@dineug/r-html').CSSTemplateLiterals;
11
+ export declare const visuallyHidden: import('@dineug/r-html').CSSTemplateLiterals;
12
+ //# sourceMappingURL=DiffTree.styles.d.ts.map
@@ -0,0 +1,49 @@
1
+ import { ErdTarget } from '../../goToErdTarget';
2
+ import { TreeNode } from '../../../primitives/tree/treeModel';
3
+ import { I18n } from '../../../../i18n/translate';
4
+ import { DiffEntries, DiffEntry, DiffStatus } from '../../../../utils/diff';
5
+ export type DiffFolder = 'tables' | 'tableGroups' | 'memos' | 'columns' | 'indexes' | 'foreignKeys';
6
+ /** What one row of the diff tree stands for: a folder, or an entry with the table it is in. */
7
+ export type DiffTreeItem = {
8
+ kind: 'folder';
9
+ folder: DiffFolder;
10
+ count: number;
11
+ } | {
12
+ kind: 'entry';
13
+ entry: DiffEntry;
14
+ table: DiffEntry | null;
15
+ };
16
+ export type DiffTreeNode = TreeNode<DiffTreeItem>;
17
+ export type DiffTree = {
18
+ roots: DiffTreeNode[];
19
+ /** Every row with children, which the tree shows open unless folded. */
20
+ branchIds: string[];
21
+ };
22
+ /** A row's id: the current entity's, or the saved one's where it is gone. */
23
+ export declare const entryNodeId: (entry: DiffEntry) => string;
24
+ /** Whether a name filter keeps an entry: its current name or the saved one holds what is typed, in any case. */
25
+ export declare function matchesFilter(entry: DiffEntry, filter: string): boolean;
26
+ /**
27
+ * The tree a diff lists: Tables, Table Groups and Memos as the Explorer has
28
+ * them, holding what changed and the tables what changed is in, and only what
29
+ * the name filter keeps. Every row with children shows open to begin with.
30
+ */
31
+ export declare function buildDiffTree(entries: DiffEntries, filter?: string): DiffTree;
32
+ /** The letter a row ends on: its status, or a tilde for a row listed only for what it holds. */
33
+ export declare function statusLetter(item: DiffTreeItem): string;
34
+ export declare const statusLabel: (status: DiffStatus | null, { t }: Pick<I18n, "t">) => string;
35
+ /** How long a text a tooltip line quotes may run before it is cut. */
36
+ export declare const QUOTE_LIMIT = 40;
37
+ /** The tooltip of a row: what it is, then each change as before → after, one a line. */
38
+ export declare function describeEntry(entry: DiffEntry, i18n: Pick<I18n, 't'>): string;
39
+ export type DiffTargets = {
40
+ prev: ErdTarget | null;
41
+ next: ErdTarget | null;
42
+ };
43
+ /**
44
+ * Where a row takes each pane: an added entity the current pane alone, a
45
+ * removed one the saved pane alone, and anything both hold both; a column or
46
+ * an index its table, and a folder neither.
47
+ */
48
+ export declare function diffTargets(item: DiffTreeItem): DiffTargets;
49
+ //# sourceMappingURL=diffTreeModel.d.ts.map