@omicronenergy/oscd-shell 0.0.5 → 0.0.7

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 (121) hide show
  1. package/dist/foundation/cyrb64.d.ts +6 -0
  2. package/dist/foundation/cyrb64.js +26 -0
  3. package/dist/foundation/cyrb64.js.map +1 -0
  4. package/dist/foundation.d.ts +1 -0
  5. package/dist/foundation.js +2 -0
  6. package/dist/foundation.js.map +1 -0
  7. package/dist/locales/de.d.ts +10 -0
  8. package/dist/locales/de.js +15 -0
  9. package/dist/locales/de.js.map +1 -0
  10. package/dist/locales.d.ts +13 -0
  11. package/dist/locales.js +21 -0
  12. package/dist/locales.js.map +1 -0
  13. package/dist/oscd-shell.d.ts +115 -0
  14. package/dist/oscd-shell.js +732 -0
  15. package/dist/oscd-shell.js.map +1 -0
  16. package/package.json +32 -29
  17. package/.editorconfig +0 -22
  18. package/.github/actions/setup-node-env/action.yml +0 -49
  19. package/.github/workflows/release-please.yml +0 -84
  20. package/.github/workflows/test.yml +0 -18
  21. package/.github/workflows/update-screenshots.yml +0 -29
  22. package/.husky/commit-msg +0 -1
  23. package/.husky/pre-commit +0 -1
  24. package/.release-please-manifest.json +0 -1
  25. package/CHANGELOG.md +0 -73
  26. package/CONTRIBUTING.md +0 -393
  27. package/commitlint.config.js +0 -1
  28. package/demo/AddPlugins.js +0 -42
  29. package/demo/DemoPluginSrc.js +0 -9
  30. package/demo/embedded.html +0 -17
  31. package/demo/index.html +0 -95
  32. package/foundation/cyrb64.ts +0 -27
  33. package/foundation/edit-event.ts +0 -273
  34. package/foundation/open-event.ts +0 -21
  35. package/foundation.ts +0 -28
  36. package/lit-localize.json +0 -15
  37. package/localization/de.xlf +0 -75
  38. package/oscd-shell.editing.spec.ts +0 -813
  39. package/oscd-shell.plugging.spec.ts +0 -78
  40. package/oscd-shell.spec.ts +0 -431
  41. package/oscd-shell.test.ts +0 -382
  42. package/oscd-shell.ts +0 -906
  43. package/release-please-config.json +0 -21
  44. package/rollup.config.js +0 -51
  45. package/screenshots/Chromium/baseline/app-bar-de.png +0 -0
  46. package/screenshots/Chromium/baseline/app-bar-en.png +0 -0
  47. package/screenshots/Chromium/baseline/document-name-de.png +0 -0
  48. package/screenshots/Chromium/baseline/document-name-en.png +0 -0
  49. package/screenshots/Chromium/baseline/editor-plugins-de.png +0 -0
  50. package/screenshots/Chromium/baseline/editor-plugins-en.png +0 -0
  51. package/screenshots/Chromium/baseline/editor-plugins-selected-de.png +0 -0
  52. package/screenshots/Chromium/baseline/editor-plugins-selected-en.png +0 -0
  53. package/screenshots/Chromium/baseline/editor-plugins-with-doc-de.png +0 -0
  54. package/screenshots/Chromium/baseline/editor-plugins-with-doc-en.png +0 -0
  55. package/screenshots/Chromium/baseline/log-entries-de.png +0 -0
  56. package/screenshots/Chromium/baseline/log-entries-en.png +0 -0
  57. package/screenshots/Chromium/baseline/log-entries-redone-de.png +0 -0
  58. package/screenshots/Chromium/baseline/log-entries-redone-en.png +0 -0
  59. package/screenshots/Chromium/baseline/log-entries-undone-de.png +0 -0
  60. package/screenshots/Chromium/baseline/log-entries-undone-en.png +0 -0
  61. package/screenshots/Chromium/baseline/log-screen-de.png +0 -0
  62. package/screenshots/Chromium/baseline/log-screen-en.png +0 -0
  63. package/screenshots/Chromium/baseline/menu-drawer-de.png +0 -0
  64. package/screenshots/Chromium/baseline/menu-drawer-en.png +0 -0
  65. package/screenshots/Chromium/baseline/menu-plugins-de.png +0 -0
  66. package/screenshots/Chromium/baseline/menu-plugins-en.png +0 -0
  67. package/screenshots/Chromium/baseline/menu-plugins-triggered-de.png +0 -0
  68. package/screenshots/Chromium/baseline/menu-plugins-triggered-en.png +0 -0
  69. package/screenshots/Firefox/baseline/app-bar-de.png +0 -0
  70. package/screenshots/Firefox/baseline/app-bar-en.png +0 -0
  71. package/screenshots/Firefox/baseline/document-name-de.png +0 -0
  72. package/screenshots/Firefox/baseline/document-name-en.png +0 -0
  73. package/screenshots/Firefox/baseline/editor-plugins-de.png +0 -0
  74. package/screenshots/Firefox/baseline/editor-plugins-en.png +0 -0
  75. package/screenshots/Firefox/baseline/editor-plugins-selected-de.png +0 -0
  76. package/screenshots/Firefox/baseline/editor-plugins-selected-en.png +0 -0
  77. package/screenshots/Firefox/baseline/editor-plugins-with-doc-de.png +0 -0
  78. package/screenshots/Firefox/baseline/editor-plugins-with-doc-en.png +0 -0
  79. package/screenshots/Firefox/baseline/log-entries-de.png +0 -0
  80. package/screenshots/Firefox/baseline/log-entries-en.png +0 -0
  81. package/screenshots/Firefox/baseline/log-entries-redone-de.png +0 -0
  82. package/screenshots/Firefox/baseline/log-entries-redone-en.png +0 -0
  83. package/screenshots/Firefox/baseline/log-entries-undone-de.png +0 -0
  84. package/screenshots/Firefox/baseline/log-entries-undone-en.png +0 -0
  85. package/screenshots/Firefox/baseline/log-screen-de.png +0 -0
  86. package/screenshots/Firefox/baseline/log-screen-en.png +0 -0
  87. package/screenshots/Firefox/baseline/menu-drawer-de.png +0 -0
  88. package/screenshots/Firefox/baseline/menu-drawer-en.png +0 -0
  89. package/screenshots/Firefox/baseline/menu-plugins-de.png +0 -0
  90. package/screenshots/Firefox/baseline/menu-plugins-en.png +0 -0
  91. package/screenshots/Firefox/baseline/menu-plugins-triggered-de.png +0 -0
  92. package/screenshots/Firefox/baseline/menu-plugins-triggered-en.png +0 -0
  93. package/screenshots/Webkit/baseline/app-bar-de.png +0 -0
  94. package/screenshots/Webkit/baseline/app-bar-en.png +0 -0
  95. package/screenshots/Webkit/baseline/document-name-de.png +0 -0
  96. package/screenshots/Webkit/baseline/document-name-en.png +0 -0
  97. package/screenshots/Webkit/baseline/editor-plugins-de.png +0 -0
  98. package/screenshots/Webkit/baseline/editor-plugins-en.png +0 -0
  99. package/screenshots/Webkit/baseline/editor-plugins-selected-de.png +0 -0
  100. package/screenshots/Webkit/baseline/editor-plugins-selected-en.png +0 -0
  101. package/screenshots/Webkit/baseline/editor-plugins-with-doc-de.png +0 -0
  102. package/screenshots/Webkit/baseline/editor-plugins-with-doc-en.png +0 -0
  103. package/screenshots/Webkit/baseline/log-entries-de.png +0 -0
  104. package/screenshots/Webkit/baseline/log-entries-en.png +0 -0
  105. package/screenshots/Webkit/baseline/log-entries-redone-de.png +0 -0
  106. package/screenshots/Webkit/baseline/log-entries-redone-en.png +0 -0
  107. package/screenshots/Webkit/baseline/log-entries-undone-de.png +0 -0
  108. package/screenshots/Webkit/baseline/log-entries-undone-en.png +0 -0
  109. package/screenshots/Webkit/baseline/log-screen-de.png +0 -0
  110. package/screenshots/Webkit/baseline/log-screen-en.png +0 -0
  111. package/screenshots/Webkit/baseline/menu-drawer-de.png +0 -0
  112. package/screenshots/Webkit/baseline/menu-drawer-en.png +0 -0
  113. package/screenshots/Webkit/baseline/menu-plugins-de.png +0 -0
  114. package/screenshots/Webkit/baseline/menu-plugins-en.png +0 -0
  115. package/screenshots/Webkit/baseline/menu-plugins-triggered-de.png +0 -0
  116. package/screenshots/Webkit/baseline/menu-plugins-triggered-en.png +0 -0
  117. package/tsconfig.json +0 -23
  118. package/utils/testing.spec.ts +0 -210
  119. package/utils/testing.ts +0 -65
  120. package/web-dev-server.config.js +0 -24
  121. package/web-test-runner.config.js +0 -180
@@ -0,0 +1,732 @@
1
+ var _OpenSCD_plugins, _OpenSCD_loadedPlugins, _OpenSCD_loadedPluginTagNames, _OpenSCD_actions;
2
+ import { __classPrivateFieldGet, __classPrivateFieldSet, __decorate } from "tslib";
3
+ import '@webcomponents/scoped-custom-element-registry';
4
+ import { configureLocalization, localized, msg } from '@lit/localize';
5
+ import { css, html, LitElement, nothing } from 'lit';
6
+ import { customElement, property, query, state } from 'lit/decorators.js';
7
+ import { html as staticHtml, unsafeStatic } from 'lit/static-html.js';
8
+ import { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';
9
+ import { OscdAppBar } from '@omicronenergy/oscd-ui/app-bar/OscdAppBar.js';
10
+ import { OscdDialog } from '@omicronenergy/oscd-ui/dialog/OscdDialog.js';
11
+ import { OscdDivider } from '@omicronenergy/oscd-ui/divider/OscdDivider.js';
12
+ import { OscdFilledIconButton } from '@omicronenergy/oscd-ui/iconbutton/OscdFilledIconButton.js';
13
+ import { OscdFilledSelect } from '@omicronenergy/oscd-ui/select/OscdFilledSelect.js';
14
+ import { OscdFilledTextField } from '@omicronenergy/oscd-ui/textfield/OscdFilledTextField.js';
15
+ import { OscdIcon } from '@omicronenergy/oscd-ui/icon/OscdIcon.js';
16
+ import { OscdList } from '@omicronenergy/oscd-ui/list/OscdList.js';
17
+ import { OscdListItem } from '@omicronenergy/oscd-ui/list/OscdListItem.js';
18
+ import { OscdMenu } from '@omicronenergy/oscd-ui/menu/OscdMenu.js';
19
+ import { OscdMenuItem } from '@omicronenergy/oscd-ui/menu/OscdMenuItem.js';
20
+ import { OscdNavigationDrawer } from '@omicronenergy/oscd-ui/navigation-drawer/OscdNavigationDrawer.js';
21
+ import { OscdNavigationDrawerHeader } from '@omicronenergy/oscd-ui/navigation-drawer/OscdNavigationDrawerHeader.js';
22
+ import { OscdSecondaryTab } from '@omicronenergy/oscd-ui/tabs/OscdSecondaryTab.js';
23
+ import { OscdSelectOption } from '@omicronenergy/oscd-ui/select/OscdSelectOption.js';
24
+ import { OscdTabs } from '@omicronenergy/oscd-ui/tabs/OscdTabs.js';
25
+ import { OscdTextButton } from '@omicronenergy/oscd-ui/button/OscdTextButton.js';
26
+ import { XMLEditor } from '@omicronenergy/oscd-editor';
27
+ import { sourceLocale, targetLocales } from './locales.js';
28
+ import { cyrb64 } from './foundation/cyrb64.js';
29
+ const _customElementsDefine = window.customElements.define;
30
+ window.customElements.define = (name, cl, conf) => {
31
+ if (!customElements.get(name)) {
32
+ _customElementsDefine.call(window.customElements, name, cl, conf);
33
+ }
34
+ };
35
+ const pluginTags = new Map();
36
+ /** @returns a valid customElement tagName containing the URI hash. */
37
+ function pluginTag(uri) {
38
+ if (!pluginTags.has(uri)) {
39
+ pluginTags.set(uri, `oscd-p${cyrb64(uri)}`);
40
+ }
41
+ return pluginTags.get(uri);
42
+ }
43
+ const { getLocale, setLocale } = configureLocalization({
44
+ sourceLocale,
45
+ targetLocales,
46
+ loadLocale: locale => import(new URL(`./locales/${locale}.js`, import.meta.url).href),
47
+ });
48
+ function renderActionItem(control, slot = 'actionItems') {
49
+ return html `<oscd-filled-icon-button
50
+ slot="${slot}"
51
+ aria-label="${control.getName()}"
52
+ ?disabled=${control.isDisabled()}
53
+ @click=${control.action}
54
+ ><oscd-icon>${control.icon}</oscd-icon></oscd-filled-icon-button
55
+ >`;
56
+ }
57
+ function renderMenuItem(control) {
58
+ return html `
59
+ <oscd-list-item
60
+ type="button"
61
+ .disabled=${control.isDisabled()}
62
+ @click=${control.action}
63
+ >
64
+ <oscd-icon slot="start">${control.icon}</oscd-icon>
65
+ <span>${control.getName()}</span>
66
+ </oscd-list-item>
67
+ `;
68
+ }
69
+ let OpenSCD = class OpenSCD extends ScopedElementsMixin(LitElement) {
70
+ static get scopedElements() {
71
+ return {
72
+ 'oscd-app-bar': OscdAppBar,
73
+ 'oscd-dialog': OscdDialog,
74
+ 'oscd-icon': OscdIcon,
75
+ 'oscd-filled-text-field': OscdFilledTextField,
76
+ 'oscd-filled-select': OscdFilledSelect,
77
+ 'oscd-select-option': OscdSelectOption,
78
+ 'oscd-filled-icon-button': OscdFilledIconButton,
79
+ 'oscd-list': OscdList,
80
+ 'oscd-list-item': OscdListItem,
81
+ 'oscd-divider': OscdDivider,
82
+ 'oscd-menu-item': OscdMenuItem,
83
+ 'oscd-navigation-drawer': OscdNavigationDrawer,
84
+ 'oscd-navigation-drawer-header': OscdNavigationDrawerHeader,
85
+ 'oscd-secondary-tab': OscdSecondaryTab,
86
+ 'oscd-tabs': OscdTabs,
87
+ 'oscd-text-button': OscdTextButton,
88
+ 'oscd-menu': OscdMenu,
89
+ };
90
+ }
91
+ get doc() {
92
+ return this.docs[this.docName];
93
+ }
94
+ get last() {
95
+ return this.xmlEditor.past.length - 1;
96
+ }
97
+ get canUndo() {
98
+ return this.xmlEditor.past.length >= 0;
99
+ }
100
+ get canRedo() {
101
+ return this.xmlEditor.future.length >= 0;
102
+ }
103
+ isEditable(docName) {
104
+ return !!this.editable.find(ext => docName.toLowerCase().endsWith(`.${ext}`));
105
+ }
106
+ get editableDocs() {
107
+ return Object.keys(this.docs).filter(name => this.isEditable(name));
108
+ }
109
+ get plugins() {
110
+ return __classPrivateFieldGet(this, _OpenSCD_plugins, "f");
111
+ }
112
+ set plugins(plugins) {
113
+ Object.entries(plugins).forEach(([pluginType, kind]) => kind.forEach((plugin, index) => {
114
+ const tagName = pluginTag(plugin.src);
115
+ if (__classPrivateFieldGet(this, _OpenSCD_loadedPluginTagNames, "f").includes(tagName)) {
116
+ return;
117
+ }
118
+ if (this.registry.get(tagName)) {
119
+ this.addLoadedPlugin(tagName, pluginType, plugin, index);
120
+ this.requestUpdate('loadedPlugins');
121
+ return;
122
+ }
123
+ const url = new URL(plugin.src, window.location.href).toString();
124
+ import(url).then(mod => {
125
+ this.addLoadedPlugin(tagName, pluginType, plugin, index);
126
+ // Because this is async, we need to check (again) if the element is already defined.
127
+ if (!this.registry.get(tagName)) {
128
+ this.registry.define(tagName, mod.default);
129
+ }
130
+ this.requestUpdate('loadedPlugins');
131
+ });
132
+ }));
133
+ __classPrivateFieldSet(this, _OpenSCD_plugins, { menu: [], editor: [], background: [], ...plugins }, "f");
134
+ }
135
+ get loadedPlugins() {
136
+ return __classPrivateFieldGet(this, _OpenSCD_loadedPlugins, "f");
137
+ }
138
+ addLoadedPlugin(tagName, kind, plugin, index) {
139
+ __classPrivateFieldGet(this, _OpenSCD_loadedPlugins, "f")[kind][index] = plugin;
140
+ __classPrivateFieldGet(this, _OpenSCD_loadedPluginTagNames, "f").push(tagName);
141
+ }
142
+ handleOpenDoc({ detail: { docName, doc } }) {
143
+ this.docs[docName] = doc;
144
+ if (this.isEditable(docName)) {
145
+ this.docName = docName;
146
+ }
147
+ this.requestUpdate();
148
+ }
149
+ /** Undo the last `n` [[Edit]]s committed */
150
+ undo(n = 1) {
151
+ if (!this.canUndo || n < 1) {
152
+ return;
153
+ }
154
+ this.xmlEditor.undo();
155
+ if (n > 1) {
156
+ this.undo(n - 1);
157
+ }
158
+ this.requestUpdate();
159
+ }
160
+ /** Redo the last `n` [[Edit]]s that have been undone */
161
+ redo(n = 1) {
162
+ if (!this.canRedo || n < 1) {
163
+ return;
164
+ }
165
+ this.xmlEditor.redo();
166
+ if (n > 1) {
167
+ this.redo(n - 1);
168
+ }
169
+ this.requestUpdate();
170
+ }
171
+ get locale() {
172
+ return getLocale();
173
+ }
174
+ set locale(tag) {
175
+ try {
176
+ setLocale(tag);
177
+ }
178
+ catch {
179
+ // don't change locale if tag is invalid
180
+ }
181
+ }
182
+ get editor() {
183
+ return this.editors[this.editorIndex]?.tagName ?? '';
184
+ }
185
+ get menu() {
186
+ return (this.loadedPlugins.menu
187
+ ?.map((plugin) => ({
188
+ icon: plugin.icon,
189
+ getName: () => plugin.translations?.[this.locale] || plugin.name,
190
+ isDisabled: () => (plugin.requireDoc && !this.docName) ?? false,
191
+ tagName: pluginTag(plugin.src),
192
+ action: () => {
193
+ this.shadowRoot.querySelector(pluginTag(plugin.src)).run?.();
194
+ this.menuUI.opened = false;
195
+ },
196
+ }))
197
+ .filter(p => p !== undefined)).concat(__classPrivateFieldGet(this, _OpenSCD_actions, "f"));
198
+ }
199
+ get editors() {
200
+ return this.loadedPlugins.editor?.map((plugin) => ({
201
+ icon: plugin.icon,
202
+ getName: () => plugin.translations?.[this.locale] || plugin.name,
203
+ isDisabled: () => (plugin.requireDoc && !this.docName) ?? false,
204
+ tagName: pluginTag(plugin.src),
205
+ }));
206
+ }
207
+ handleKeyPress(e) {
208
+ if (!e.ctrlKey) {
209
+ return;
210
+ }
211
+ if (!Object.prototype.hasOwnProperty.call(this.hotkeys, e.key)) {
212
+ return;
213
+ }
214
+ this.hotkeys[e.key]();
215
+ e.preventDefault();
216
+ }
217
+ constructor() {
218
+ super();
219
+ this.xmlEditor = new XMLEditor();
220
+ /** The set of `XMLDocument`s currently loaded */
221
+ this.docs = {};
222
+ /** The name of the [[`doc`]] currently being edited */
223
+ this.docName = '';
224
+ /** The file endings of editable files */
225
+ this.editable = [
226
+ 'cid',
227
+ 'icd',
228
+ 'iid',
229
+ 'scd',
230
+ 'sed',
231
+ 'ssd',
232
+ ];
233
+ _OpenSCD_plugins.set(this, { menu: [], editor: [], background: [] });
234
+ _OpenSCD_loadedPlugins.set(this, {
235
+ menu: new Array(this.plugins.menu.length).fill(null),
236
+ editor: new Array(this.plugins.editor.length).fill(null),
237
+ background: new Array(this.plugins.editor.length).fill(null),
238
+ });
239
+ _OpenSCD_loadedPluginTagNames.set(this, []);
240
+ this.editorIndex = 0;
241
+ this.controls = {
242
+ undo: {
243
+ icon: 'undo',
244
+ getName: () => msg('Undo'),
245
+ action: () => {
246
+ this.undo();
247
+ this.menuUI.opened = false;
248
+ },
249
+ isDisabled: () => !this.canUndo,
250
+ },
251
+ redo: {
252
+ icon: 'redo',
253
+ getName: () => msg('Redo'),
254
+ action: () => {
255
+ this.redo();
256
+ this.menuUI.opened = false;
257
+ },
258
+ isDisabled: () => !this.canRedo,
259
+ },
260
+ menu: {
261
+ icon: 'menu',
262
+ getName: () => msg('Menu'),
263
+ action: async () => {
264
+ this.menuUI.opened = !this.menuUI.opened;
265
+ await this.menuUI.updateComplete;
266
+ if (this.menuUI.opened) {
267
+ this.menuUI.querySelector('oscd-list').focus();
268
+ }
269
+ },
270
+ isDisabled: () => false,
271
+ },
272
+ };
273
+ _OpenSCD_actions.set(this, [this.controls.undo, this.controls.redo]);
274
+ this.hotkeys = {
275
+ m: this.controls.menu.action,
276
+ z: this.controls.undo.action,
277
+ y: this.controls.redo.action,
278
+ Z: this.controls.redo.action,
279
+ };
280
+ document.addEventListener('keydown', event => this.handleKeyPress(event));
281
+ this.addEventListener('oscd-open', event => this.handleOpenDoc(event));
282
+ this.addEventListener('oscd-edit-v2', (event) => {
283
+ this.xmlEditor.commit(event.detail.edit);
284
+ });
285
+ // Catch all edits (from commits AND events) and trigger an update
286
+ this.xmlEditor.subscribe(() => {
287
+ this.requestUpdate();
288
+ });
289
+ }
290
+ updated(changedProps) {
291
+ super.updated(changedProps);
292
+ this.updateComplete.then(() => {
293
+ // Ensure the active tab is set after tabs are rendered
294
+ const oscdTabs = this.shadowRoot.querySelector('oscd-tabs');
295
+ if (oscdTabs && oscdTabs.activeTabIndex !== this.editorIndex) {
296
+ oscdTabs.activeTabIndex = this.editorIndex;
297
+ }
298
+ });
299
+ }
300
+ render() {
301
+ return html `<oscd-app-bar slot="appContent">
302
+ ${renderActionItem(this.controls.menu, 'actionStart')}
303
+ <div slot="title" id="title">
304
+ ${this.editableDocs.length > 1
305
+ ? html `<oscd-filled-icon-button
306
+ id="fileMenuButton"
307
+ @click=${() => this.fileMenuUI.show()}
308
+ ><oscd-icon>arrow_drop_down</oscd-icon></oscd-filled-icon-button
309
+ >`
310
+ : nothing}
311
+ ${this.docName}
312
+ ${this.docName
313
+ ? html `<oscd-filled-icon-button
314
+ @click=${() => this.editFileUI.show()}
315
+ ><oscd-icon>edit</oscd-icon></oscd-filled-icon-button
316
+ >`
317
+ : nothing}
318
+ <oscd-menu
319
+ fixed
320
+ id="fileMenu"
321
+ anchor="fileMenuButton"
322
+ corner="BOTTOM_END"
323
+ >
324
+ ${this.editableDocs.map((name, index) => html `<oscd-menu-item
325
+ @click=${() => {
326
+ this.docName = name;
327
+ }}
328
+ ?disabled=${!this.isEditable(name)}
329
+ ?selected=${this.docName === name}
330
+ id=${index}
331
+ >${name}</oscd-menu-item
332
+ >`)}
333
+ </oscd-menu>
334
+ </div>
335
+
336
+ <div slot="actionEnd">
337
+ ${__classPrivateFieldGet(this, _OpenSCD_actions, "f").map(op => renderActionItem(op))}
338
+ </div>
339
+
340
+ <oscd-tabs
341
+ .activeTabIndex=${this.editorIndex}
342
+ @change=${(event) => {
343
+ const tabs = event.currentTarget;
344
+ this.editorIndex = tabs.activeTabIndex;
345
+ }}
346
+ >
347
+ ${this.editors.map(editor => editor.isDisabled()
348
+ ? nothing
349
+ : html `<oscd-secondary-tab>
350
+ <oscd-icon slot="icon">${editor.icon}</oscd-icon>
351
+ ${editor.getName()}
352
+ </oscd-secondary-tab>`)}
353
+ </oscd-tabs>
354
+ </oscd-app-bar>
355
+
356
+ <oscd-navigation-drawer hasheader type="modal" id="menu">
357
+ <oscd-navigation-drawer-header>
358
+ <span slot="headline">${msg('Menu')}</span>
359
+ ${this.docName
360
+ ? html `<span slot="supporting-text">${this.docName}</span>`
361
+ : ''}
362
+ </oscd-navigation-drawer-header>
363
+ <oscd-list>
364
+ <oscd-divider></oscd-divider>
365
+ ${this.menu.map(renderMenuItem)}
366
+ </oscd-list>
367
+ </oscd-navigation-drawer>
368
+
369
+ ${this.editor
370
+ ? staticHtml `<${unsafeStatic(this.editor)} locale="${this.locale}"
371
+ docName="${this.docName}"
372
+ .doc=${this.doc}
373
+ .docs=${this.docs}
374
+ .editCount=${this.xmlEditor.past.length}
375
+ .editor=${this.xmlEditor}>
376
+ </${unsafeStatic(this.editor)}>`
377
+ : nothing}
378
+
379
+ <oscd-dialog
380
+ id="editFile"
381
+ @closed=${(event) => {
382
+ const dialog = event.target;
383
+ if (dialog.returnValue === 'remove') {
384
+ delete this.docs[this.docName];
385
+ this.docName = this.editableDocs[0] || '';
386
+ }
387
+ }}
388
+ >
389
+ <div slot="headline">
390
+ <oscd-icon>description</oscd-icon>${this.docName}
391
+ </div>
392
+ <form slot="content" id="edit-file-form" method="dialog">
393
+ <oscd-filled-text-field
394
+ id="fileName"
395
+ label="${msg('Filename')}"
396
+ value="${this.docName.replace(/\.[^.]+$/, '')}"
397
+ @input=${(event) => {
398
+ const input = event.target;
399
+ const { value } = input;
400
+ const name = `${value}.${this.fileExtensionUI.value}`;
401
+ if (name in this.docs && name !== this.docName) {
402
+ input.setCustomValidity('File already exists!');
403
+ }
404
+ else {
405
+ input.setCustomValidity('');
406
+ }
407
+ input.reportValidity();
408
+ }}
409
+ ></oscd-filled-text-field>
410
+ <oscd-filled-select
411
+ label="${msg('Extension')}"
412
+ fixedMenuPosition
413
+ id="fileExtension"
414
+ @selected=${() => this.fileNameUI.reportValidity()}
415
+ >
416
+ ${this.editable.map(ext => html `<oscd-select-option
417
+ ?selected=${this.docName.endsWith(`.${ext}`)}
418
+ value="${ext}"
419
+ >${ext}</oscd-select-option
420
+ >`)}
421
+ </oscd-filled-select>
422
+ </form>
423
+ <div slot="actions">
424
+ <oscd-text-button
425
+ form="edit-file-form"
426
+ class="edit-dialog-remove-button"
427
+ value="remove"
428
+ >
429
+ <oscd-icon slot="icon">delete</oscd-icon>
430
+ ${msg('Close file')}
431
+ </oscd-text-button>
432
+ <oscd-text-button form="edit-file-form" value="close">
433
+ ${msg('Cancel')}
434
+ </oscd-text-button>
435
+ <oscd-text-button
436
+ @click=${() => {
437
+ const valid = this.fileNameUI.checkValidity();
438
+ if (!valid) {
439
+ this.fileNameUI.reportValidity();
440
+ return;
441
+ }
442
+ const newDocName = `${this.fileNameUI.value}.${this.fileExtensionUI.value}`;
443
+ this.docs[newDocName] = this.doc;
444
+ delete this.docs[this.docName];
445
+ this.docName = newDocName;
446
+ this.editFileUI.close();
447
+ }}
448
+ trailing-icon
449
+ >
450
+ <oscd-icon slot="icon">edit</oscd-icon>
451
+ ${msg('Rename')}
452
+ </oscd-text-button>
453
+ </div>
454
+ </oscd-dialog>
455
+
456
+ <aside>
457
+ <div class="menu-plugins">
458
+ ${this.loadedPlugins.menu.map(plugin => staticHtml `<${unsafeStatic(pluginTag(plugin.src))}
459
+ locale="${this.locale}"
460
+ docName="${this.docName}"
461
+ .doc=${this.doc}
462
+ .docs=${this.docs}
463
+ .editCount=${this.xmlEditor.past.length}
464
+ .editor=${this.xmlEditor}>
465
+ </${unsafeStatic(pluginTag(plugin.src))}>`)}
466
+ </div>
467
+ <div class="background-plugins">
468
+ ${this.loadedPlugins.background.map(plugin => staticHtml `<${unsafeStatic(pluginTag(plugin.src))}
469
+ locale="${this.locale}"
470
+ docName="${this.docName}"
471
+ .doc=${this.doc}
472
+ .docs=${this.docs}
473
+ .editCount=${this.xmlEditor.past.length}
474
+ .editor=${this.xmlEditor}>
475
+ </${unsafeStatic(pluginTag(plugin.src))}>`)}
476
+ </div>
477
+ </aside> `;
478
+ }
479
+ firstUpdated() {
480
+ const background = getComputedStyle(this.menuUI).getPropertyValue('--oscd-base2');
481
+ document.body.style.background = background;
482
+ }
483
+ };
484
+ _OpenSCD_plugins = new WeakMap();
485
+ _OpenSCD_loadedPlugins = new WeakMap();
486
+ _OpenSCD_loadedPluginTagNames = new WeakMap();
487
+ _OpenSCD_actions = new WeakMap();
488
+ OpenSCD.styles = css `
489
+ .fileext {
490
+ opacity: 0.81;
491
+ }
492
+
493
+ .filename {
494
+ caret-color: var(--oscd-secondary);
495
+ }
496
+
497
+ .filename:focus {
498
+ outline: none;
499
+ }
500
+
501
+ aside {
502
+ position: absolute;
503
+ top: 0;
504
+ left: 0;
505
+ width: 0;
506
+ height: 0;
507
+ overflow: hidden;
508
+ margin: 0;
509
+ padding: 0;
510
+ }
511
+
512
+ abbr {
513
+ text-decoration: none;
514
+ }
515
+
516
+ @media (prefers-color-scheme: light) {
517
+ * {
518
+ --oscd-primary: var(--oscd-theme-primary, #2aa198);
519
+ --oscd-secondary: var(--oscd-theme-secondary, #6c71c4);
520
+ --oscd-base03: var(--oscd-theme-base03, #002b36);
521
+ --oscd-base02: var(--oscd-theme-base02, #073642);
522
+ --oscd-base01: var(--oscd-theme-base01, #586e75);
523
+ --oscd-base00: var(--oscd-theme-base00, #657b83);
524
+ --oscd-base0: var(--oscd-theme-base0, #839496);
525
+ --oscd-base1: var(--oscd-theme-base1, #93a1a1);
526
+ --oscd-base2: var(--oscd-theme-base2, #eee8d5);
527
+ --oscd-base3: var(--oscd-theme-base3, #fdf6e3);
528
+
529
+ --mdc-theme-text-disabled-on-light: rgba(255, 255, 255, 0.38);
530
+ }
531
+ }
532
+
533
+ @media (prefers-color-scheme: dark) {
534
+ * {
535
+ --oscd-primary: var(--oscd-theme-secondary, #6c71c4);
536
+ --oscd-secondary: var(--oscd-theme-primary, #2aa198);
537
+ --oscd-base03: var(--oscd-theme-base3, #fdf6e3);
538
+ --oscd-base02: var(--oscd-theme-base2, #eee8d5);
539
+ --oscd-base01: var(--oscd-theme-base1, #93a1a1);
540
+ --oscd-base00: var(--oscd-theme-base0, #839496);
541
+ --oscd-base0: var(--oscd-theme-base00, #657b83);
542
+ --oscd-base1: var(--oscd-theme-base01, #586e75);
543
+ --oscd-base2: var(--oscd-theme-base02, #073642);
544
+ --oscd-base3: var(--oscd-theme-base03, #002b36);
545
+ }
546
+ }
547
+
548
+ * {
549
+ --oscd-error: var(--oscd-theme-error, #dc322f);
550
+
551
+ --oscd-text-font: var(--oscd-theme-text-font, 'Roboto');
552
+ --oscd-icon-font: var(--oscd-theme-icon-font, 'Material Icons');
553
+ --oscd-text-font-mono: var(--oscd-theme-text-font-mono, 'Roboto Mono');
554
+
555
+ --oscd-warning: var(--oscd-theme-warning, #b58900);
556
+ --md-sys-color-primary: var(--oscd-primary);
557
+ --md-sys-color-on-primary: var(--oscd-base3);
558
+
559
+ --md-sys-color-secondary: var(--oscd-secondary);
560
+ --md-sys-color-on-secondary: var(--oscd-base3);
561
+ --md-sys-color-secondary-container: var(--oscd-base2);
562
+
563
+ --md-sys-color-surface: var(--oscd-base3);
564
+ --md-sys-color-on-surface: var(--oscd-base00);
565
+ --md-sys-color-surface-variant: var(--oscd-base3);
566
+ --md-sys-color-on-surface-variant: var(--oscd-base00);
567
+ --md-sys-color-surface-bright: var(--oscd-base2);
568
+ --md-sys-color-surface-container: var(--oscd-base3);
569
+ --md-sys-color-surface-container-high: var(--oscd-base3);
570
+ --md-sys-color-surface-container-highest: var(--oscd-base3);
571
+
572
+ --md-sys-color-outline-variant: var(--oscd-primary);
573
+ --md-sys-color-scrim: #000000;
574
+ --md-sys-color-error: var(--oscd-error);
575
+ --md-sys-color-on-error: var(--oscd-base3);
576
+
577
+ /* --md-menu-item-selected-label-text-color: var(--oscd-base01); */
578
+ --md-icon-button-disabled-icon-color: var(--oscd-base3);
579
+
580
+ /* MDC Theme Colors
581
+ * Needed for supporting any pluggins still using the depricated MWC Components
582
+ */
583
+ --mdc-theme-primary: var(--oscd-primary);
584
+ --mdc-theme-secondary: var(--oscd-secondary);
585
+ --mdc-theme-background: var(--oscd-base3);
586
+ --mdc-theme-surface: var(--oscd-base3);
587
+ --mdc-theme-on-primary: var(--oscd-base2);
588
+ --mdc-theme-on-secondary: var(--oscd-base02);
589
+ --mdc-theme-on-background: var(--oscd-base00);
590
+ --mdc-theme-on-surface: var(--oscd-base00);
591
+ --mdc-theme-text-primary-on-background: var(--oscd-base01);
592
+ --mdc-theme-text-secondary-on-background: var(--oscd-base00);
593
+ --mdc-theme-text-icon-on-background: var(--oscd-base00);
594
+ --mdc-theme-error: var(--oscd-error);
595
+
596
+ --mdc-button-disabled-ink-color: var(--oscd-base1);
597
+
598
+ --mdc-drawer-heading-ink-color: var(--oscd-base00);
599
+
600
+ --mdc-dialog-heading-ink-color: var(--oscd-base00);
601
+
602
+ --mdc-text-field-fill-color: var(--oscd-base2);
603
+ --mdc-text-field-ink-color: var(--oscd-base02);
604
+ --mdc-text-field-label-ink-color: var(--oscd-base01);
605
+ --mdc-text-field-idle-line-color: var(--oscd-base00);
606
+ --mdc-text-field-hover-line-color: var(--oscd-base02);
607
+
608
+ --mdc-select-fill-color: var(--oscd-base2);
609
+ --mdc-select-ink-color: var(--oscd-base02);
610
+ --mdc-select-label-ink-color: var(--oscd-base01);
611
+ --mdc-select-idle-line-color: var(--oscd-base00);
612
+ --mdc-select-hover-line-color: var(--oscd-base02);
613
+ --mdc-select-dropdown-icon-color: var(--oscd-base01);
614
+
615
+ --mdc-typography-font-family: var(--oscd-text-font);
616
+ --mdc-icon-font: var(--oscd-icon-font);
617
+ }
618
+
619
+ oscd-navigation-drawer-header {
620
+ --md-list-item-supporting-text-color: var(--md-sys-color-on-surface);
621
+ }
622
+ oscd-app-bar * {
623
+ --md-filled-icon-button-disabled-container-opacity: 0;
624
+ --md-filled-icon-button-disabled-icon-color: var(
625
+ --md-sys-color-on-primary
626
+ );
627
+ }
628
+
629
+ oscd-tabs {
630
+ display: flex;
631
+ flex-grow: 1;
632
+ --md-secondary-tab-container-color: var(--oscd-primary);
633
+ }
634
+ oscd-secondary-tab {
635
+ --md-sys-color-on-surface: var(--md-sys-color-on-primary);
636
+ --md-sys-color-on-surface-variant: var(--md-sys-color-on-primary);
637
+ --md-secondary-tab-active-indicator-color: var(--oscd-base2);
638
+ }
639
+
640
+ .edit-dialog-remove-button {
641
+ --md-text-button-icon-color: var(--oscd-error);
642
+ --md-text-button-label-text-color: var(--oscd-error);
643
+
644
+ --md-text-button-focus-label-text-color: var(--oscd-error);
645
+ --md-text-button-focus-icon-color: var(--oscd-error);
646
+
647
+ --md-text-button-hover-label-text-color: var(--oscd-error);
648
+ --md-text-button-hover-state-layer-color: var(--oscd-error);
649
+ --md-text-button-hover-icon-color: var(--oscd-error);
650
+
651
+ --md-text-button-pressed-label-text-color: var(--oscd-error);
652
+ --md-text-button-pressed-state-layer-color: var(--oscd-error);
653
+ --md-text-button-pressed-icon-color: var(--oscd-error);
654
+ }
655
+
656
+ #title {
657
+ position: relative;
658
+ }
659
+ `;
660
+ __decorate([
661
+ state()
662
+ /** The `XMLDocument` currently being edited */
663
+ ], OpenSCD.prototype, "doc", null);
664
+ __decorate([
665
+ state()
666
+ ], OpenSCD.prototype, "xmlEditor", void 0);
667
+ __decorate([
668
+ state()
669
+ ], OpenSCD.prototype, "last", null);
670
+ __decorate([
671
+ state()
672
+ ], OpenSCD.prototype, "canUndo", null);
673
+ __decorate([
674
+ state()
675
+ ], OpenSCD.prototype, "canRedo", null);
676
+ __decorate([
677
+ state()
678
+ ], OpenSCD.prototype, "docs", void 0);
679
+ __decorate([
680
+ property({ type: String, reflect: true })
681
+ ], OpenSCD.prototype, "docName", void 0);
682
+ __decorate([
683
+ property({ type: Array, reflect: true })
684
+ ], OpenSCD.prototype, "editable", void 0);
685
+ __decorate([
686
+ state()
687
+ ], OpenSCD.prototype, "editableDocs", null);
688
+ __decorate([
689
+ property({ type: Object })
690
+ ], OpenSCD.prototype, "plugins", null);
691
+ __decorate([
692
+ state()
693
+ ], OpenSCD.prototype, "loadedPlugins", null);
694
+ __decorate([
695
+ query('#editFile')
696
+ ], OpenSCD.prototype, "editFileUI", void 0);
697
+ __decorate([
698
+ query('#menu')
699
+ ], OpenSCD.prototype, "menuUI", void 0);
700
+ __decorate([
701
+ query('#fileName')
702
+ ], OpenSCD.prototype, "fileNameUI", void 0);
703
+ __decorate([
704
+ query('#fileExtension')
705
+ ], OpenSCD.prototype, "fileExtensionUI", void 0);
706
+ __decorate([
707
+ query('#fileMenu')
708
+ ], OpenSCD.prototype, "fileMenuUI", void 0);
709
+ __decorate([
710
+ query('#fileMenuButton')
711
+ ], OpenSCD.prototype, "fileMenuButtonUI", void 0);
712
+ __decorate([
713
+ property({ type: String, reflect: true })
714
+ ], OpenSCD.prototype, "locale", null);
715
+ __decorate([
716
+ state()
717
+ ], OpenSCD.prototype, "editorIndex", void 0);
718
+ __decorate([
719
+ state()
720
+ ], OpenSCD.prototype, "editor", null);
721
+ __decorate([
722
+ state()
723
+ ], OpenSCD.prototype, "menu", null);
724
+ __decorate([
725
+ state()
726
+ ], OpenSCD.prototype, "editors", null);
727
+ OpenSCD = __decorate([
728
+ customElement('oscd-shell'),
729
+ localized()
730
+ ], OpenSCD);
731
+ export { OpenSCD };
732
+ //# sourceMappingURL=oscd-shell.js.map