@omicronenergy/oscd-shell 0.0.14 → 0.0.16

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 (34) hide show
  1. package/README.md +11 -6
  2. package/dist/landing-page/landing-page.d.ts +3 -3
  3. package/dist/landing-page/landing-page.js.map +1 -1
  4. package/dist/landing-page/landing-page.spec.js +1 -1
  5. package/dist/landing-page/landing-page.spec.js.map +1 -1
  6. package/dist/localization.js +1 -1
  7. package/dist/localization.js.map +1 -1
  8. package/dist/menus/files-menu.d.ts +1 -1
  9. package/dist/menus/plugins-menu.d.ts +5 -5
  10. package/dist/menus/plugins-menu.js +2 -2
  11. package/dist/menus/plugins-menu.js.map +1 -1
  12. package/dist/oscd-shell-design-tokens.d.ts +1 -1
  13. package/dist/oscd-shell-design-tokens.js +12 -1
  14. package/dist/oscd-shell-design-tokens.js.map +1 -1
  15. package/dist/oscd-shell.d.ts +45 -17
  16. package/dist/oscd-shell.js +36 -12
  17. package/dist/oscd-shell.js.map +1 -1
  18. package/dist/side-panel/build-tree-nodes.spec.js.map +1 -1
  19. package/dist/side-panel/editor-plugins-panel.d.ts +6 -6
  20. package/dist/side-panel/editor-plugins-panel.js +6 -0
  21. package/dist/side-panel/editor-plugins-panel.js.map +1 -1
  22. package/dist/side-panel/editor-plugins-panel.spec.js +10 -7
  23. package/dist/side-panel/editor-plugins-panel.spec.js.map +1 -1
  24. package/dist/utils/plugin-utils.d.ts +28 -21
  25. package/dist/utils/plugin-utils.js +12 -19
  26. package/dist/utils/plugin-utils.js.map +1 -1
  27. package/dist/utils/plugin-utils.spec.js +30 -5
  28. package/dist/utils/plugin-utils.spec.js.map +1 -1
  29. package/dist/utils/testing/plugin-helpers.d.ts +6 -15
  30. package/dist/utils/testing/plugin-helpers.js +3 -3
  31. package/dist/utils/testing/plugin-helpers.js.map +1 -1
  32. package/dist/utils/testing/test-plugins.js +1 -1
  33. package/dist/utils/testing/test-plugins.js.map +1 -1
  34. package/package.json +18 -58
@@ -1 +1 @@
1
- {"version":3,"file":"oscd-shell.js","sourceRoot":"","sources":["../src/oscd-shell.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing } from 'lit';\nimport {\n customElement,\n property,\n query,\n queryAssignedNodes,\n state,\n} from 'lit/decorators.js';\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';\nimport { localized, msg } from '@lit/localize';\nimport { html as staticHtml, unsafeStatic } from 'lit/static-html.js';\n\nimport { OscdFilledIconButton } from '@omicronenergy/oscd-ui/iconbutton/OscdFilledIconButton.js';\nimport { XMLEditor } from '@openscd/oscd-editor';\nimport { EditEventV2, OpenEvent } from '@openscd/oscd-api';\n\nimport {\n flattenPluginEntries,\n loadSourcedPlugins,\n} from './utils/plugin-utils.js';\nimport { getLocale, LocaleTag, setLocale } from './localization.js';\nimport { EditorPluginsPanel } from './side-panel/editor-plugins-panel.js';\nimport { PluginsMenu } from './menus/plugins-menu.js';\nimport { LandingPage } from './landing-page/landing-page.js';\nimport { RenameEvent, CloseEvent } from './foundation/events.js';\nimport { FilesMenu } from './menus/files-menu.js';\nimport { oscdShellDesignTokens } from './oscd-shell-design-tokens.js';\nimport { OscdAppBar } from '@omicronenergy/oscd-ui/app-bar/OscdAppBar.js';\nimport { OscdDivider } from '@omicronenergy/oscd-ui/divider/OscdDivider.js';\nimport { OscdIcon } from '@omicronenergy/oscd-ui/icon/OscdIcon.js';\n\nexport interface PluginBase {\n name: string;\n translations?: Record<string, string>;\n icon: string;\n}\n\nexport interface SourcedPluginEntry extends PluginBase {\n src: string;\n requireDoc?: boolean;\n}\n\nexport interface PluginEntry extends PluginBase {\n tagName: string;\n requireDoc?: boolean;\n}\n\n/**\n * The unvalidated plugin shape accepted at the `plugins` setter boundary.\n * Fields are optional and either `tagName` or `src` may be present; the\n * concrete kind is resolved and validated later by `loadSourcedPlugins`.\n */\nexport type InputPluginEntry = Partial<PluginEntry & SourcedPluginEntry>;\n\nexport interface PluginGroup<\n P extends Partial<PluginBase> = PluginEntry,\n> extends PluginBase {\n plugins: P[];\n}\n\nexport interface PluginSet<P extends Partial<PluginBase> = PluginEntry> {\n menu: (P | PluginGroup<P>)[];\n editor: (P | PluginGroup<P>)[];\n background: P[];\n}\n\n@localized()\n@customElement('oscd-shell')\nexport class OscdShell extends ScopedElementsMixin(LitElement) {\n static scopedElements = {\n 'oscd-app-bar': OscdAppBar,\n 'oscd-filled-icon-button': OscdFilledIconButton,\n 'oscd-divider': OscdDivider,\n 'oscd-icon': OscdIcon,\n 'files-menu': FilesMenu,\n 'plugins-menu': PluginsMenu,\n 'editor-plugins-panel': EditorPluginsPanel,\n 'landing-page': LandingPage,\n };\n\n /*\n * Properties\n */\n\n /**\n * Url to the app icon displayed in the app bar\n */\n @property({ type: String })\n appIcon: string = '';\n\n @property({ type: String })\n appTitle: string = 'OpenSCD';\n\n @property({ type: String })\n landingPageHeading: string = 'Welcome to OpenSCD';\n\n @property({ type: String })\n landingPageSubHeading: string =\n 'Open Source IEC-61850-6 SCL Editing Platform';\n\n /** The file endings of editable files */\n @property({ type: Array, reflect: true }) editable = [\n 'cid',\n 'icd',\n 'iid',\n 'scd',\n 'sed',\n 'ssd',\n ];\n\n @property({ type: String, reflect: true })\n get locale() {\n return getLocale() as LocaleTag;\n }\n\n set locale(tag: LocaleTag) {\n try {\n if (tag) {\n setLocale(tag);\n }\n } catch {\n // don't change locale if tag is invalid\n }\n }\n\n _plugins: PluginSet = { menu: [], editor: [], background: [] };\n\n @property({ type: Object })\n get plugins(): PluginSet {\n return this._plugins;\n }\n\n set plugins(plugins: Partial<PluginSet<InputPluginEntry>>) {\n this._plugins = Object.entries(plugins).reduce(\n (acc, [pluginType, kind]) => {\n const convertedPlugins = loadSourcedPlugins(kind, this.registry!);\n acc[pluginType as keyof PluginSet] = convertedPlugins;\n return acc;\n },\n { menu: [], editor: [], background: [] } as PluginSet,\n );\n }\n\n /*\n * States\n */\n @state()\n get canRedo(): boolean {\n return this.xmlEditor.future.length >= 1;\n }\n\n @state()\n get canUndo(): boolean {\n return this.xmlEditor.past.length >= 1;\n }\n\n @state()\n selectedEditor?: PluginEntry;\n\n @state()\n /** The `XMLDocument` currently being edited */\n get doc(): XMLDocument {\n return this.docs[this.docName];\n }\n\n /** The name of the [[`doc`]] currently being edited */\n @property({ type: String, reflect: true })\n docName = '';\n\n /** The set of `XMLDocument`s currently loaded */\n private _docs: Record<string, XMLDocument> = {};\n\n @state()\n get docs(): Record<string, XMLDocument> {\n return this._docs;\n }\n\n set docs(newDocs: Record<string, XMLDocument>) {\n this._docs = newDocs;\n this.docVersion += 1;\n }\n\n @state()\n docVersion: number = -1;\n\n @state()\n get editableDocs(): string[] {\n return Object.keys(this.docs).filter(name => this.isEditable(name));\n }\n\n @state()\n get last(): number {\n return this.xmlEditor.past.length - 1;\n }\n\n @state()\n xmlEditor: XMLEditor = new XMLEditor();\n\n /*\n * All Queries\n */\n\n @query('plugins-menu')\n pluginsMenu!: PluginsMenu;\n\n @query('editor-plugins-panel')\n editorPluginsPanel!: EditorPluginsPanel;\n\n @queryAssignedNodes({ slot: 'landing-page' })\n private _landingPageNodes?: NodeListOf<HTMLElement>;\n\n /*\n * Constructor & life cycle methods\n */\n constructor() {\n super();\n // Catch all edits (from commits AND events) and trigger an update\n this.xmlEditor.subscribe(() => {\n this.docVersion += 1;\n });\n }\n\n willUpdate(changedProperties: Map<PropertyKey, unknown>) {\n if (changedProperties.has('docName') || changedProperties.has('plugins')) {\n const firstEditor = flattenPluginEntries(this.plugins.editor)[0];\n if (this.docName && firstEditor && !this.selectedEditor) {\n this.selectedEditor = firstEditor;\n }\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n\n document.addEventListener('keydown', this.handleKeyPress, true);\n this.addEventListener('oscd-open', this.handleOpenDoc);\n this.addEventListener('oscd-rename', this.handleRenameDoc);\n this.addEventListener('oscd-close', this.handleCloseDoc);\n this.addEventListener('oscd-edit-v2', this.handleEditV2);\n this.addEventListener('oscd-undo', this.handleUndo);\n this.addEventListener('oscd-redo', this.handleRedo);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n // Remove event listeners\n document.removeEventListener('keydown', this.handleKeyPress, true);\n this.removeEventListener('oscd-open', this.handleOpenDoc);\n this.removeEventListener('oscd-rename', this.handleRenameDoc);\n this.removeEventListener('oscd-edit-v2', this.handleEditV2);\n this.removeEventListener('oscd-undo', this.handleUndo);\n this.removeEventListener('oscd-redo', this.handleRedo);\n this.removeEventListener('oscd-close', this.handleCloseDoc);\n }\n\n /*\n * Event Handlers\n */\n\n handleOpenDoc = ({ detail: { docName, doc } }: OpenEvent) => {\n this.docs = {\n ...this.docs,\n [docName]: doc,\n };\n if (this.isEditable(docName)) {\n this.docName = docName;\n }\n this.requestUpdate();\n };\n\n handleRenameDoc = (customEvent: RenameEvent) => {\n const { oldName, newName } = customEvent.detail;\n if (!this.docs[oldName] || newName === oldName || this.docs[newName]) {\n return;\n }\n const doc = this.docs[oldName];\n delete this.docs[oldName];\n this.docs = {\n ...this.docs,\n [newName]: doc,\n };\n this.docName = newName;\n };\n\n handleEditV2 = (event: EditEventV2) => {\n const { edit, title, squash } = event.detail;\n this.xmlEditor.commit(edit, { title, squash });\n };\n\n handleCloseDoc = (event: CloseEvent) => {\n const docName = event.detail.docName as string;\n delete this.docs[docName];\n if (this.docName === docName) {\n this.docName = this.editableDocs[0] || '';\n }\n };\n\n handleUndo = () => {\n this.undo();\n };\n\n handleRedo = () => {\n this.redo();\n };\n\n private handleKeyPress = (e: KeyboardEvent) => {\n if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key.toLowerCase() === 'f') {\n const panel = this.shadowRoot?.querySelector<EditorPluginsPanel>(\n 'editor-plugins-panel',\n );\n if (panel) {\n if (!panel.expanded) {\n panel.searchMode = true;\n }\n panel.focusSearch(true);\n e.preventDefault();\n e.stopPropagation();\n }\n return;\n }\n if (!e.ctrlKey) {\n return;\n }\n if (!Object.prototype.hasOwnProperty.call(this.hotkeys, e.key)) {\n return;\n }\n this.hotkeys[e.key]!.call(this);\n e.preventDefault();\n };\n\n handleOpenPluginMenu = () => {\n this.pluginsMenu.open();\n };\n\n handlePluginMenuSelect(customEvent: CustomEvent) {\n const plugin = customEvent.detail.plugin as PluginEntry;\n if (plugin.tagName) {\n this.shadowRoot!.querySelector<\n HTMLElement & { run: () => Promise<void> }\n >(plugin.tagName)!.run?.();\n }\n }\n /** Undo the last `n` [[Edit]]s committed */\n undo = (n = 1) => {\n if (!this.canUndo || n < 1) {\n return;\n }\n this.xmlEditor.undo();\n if (n > 1) {\n this.undo(n - 1);\n }\n this.requestUpdate();\n };\n\n /** Redo the last `n` [[Edit]]s that have been undone */\n redo = (n = 1) => {\n if (!this.canRedo || n < 1) {\n return;\n }\n this.xmlEditor.redo();\n if (n > 1) {\n this.redo(n - 1);\n }\n this.requestUpdate();\n };\n\n private hotkeys: Partial<Record<string, () => void>> = {\n m: this.handleOpenPluginMenu,\n z: this.undo,\n y: this.redo,\n Z: this.redo,\n };\n\n isEditable(docName: string): boolean {\n return !!this.editable.find(ext =>\n docName.toLowerCase().endsWith(`.${ext}`),\n );\n }\n\n renderPlugin(plugin: PluginEntry) {\n const tag = unsafeStatic(plugin.tagName);\n return staticHtml`<${tag}\n .locale=\"${this.locale}\"\n .docName=\"${this.docName}\"\n .doc=${this.doc}\n .docs=${this.docs}\n .editCount=${this.docVersion}\n .docVersion=${this.docVersion}\n .editor=${this.xmlEditor}>\n </${tag}>`;\n }\n\n renderOffScreenPlugins() {\n return html`\n <section class=\"off-screen-plugin-container\" aria-hidden=\"true\">\n <div class=\"menu-plugins\">\n ${flattenPluginEntries(this.plugins.menu)\n .filter(plugin => !plugin.requireDoc || !!this.docName)\n .map(plugin => this.renderPlugin(plugin))}\n </div>\n <div class=\"background-plugins\">\n ${this.plugins.background\n .filter(plugin => !plugin.requireDoc || !!this.docName)\n .map(plugin => this.renderPlugin(plugin))}\n </div>\n </section>\n `;\n }\n\n renderDefaultLandingPage() {\n return html`\n <landing-page\n heading=${this.landingPageHeading}\n subHeading=${this.landingPageSubHeading}\n .menuPlugins=${flattenPluginEntries(this.plugins.menu).filter(\n plugin => !plugin.requireDoc || !!this.docName,\n )}\n .locale=${this.locale}\n @menu-plugin-select=${(event: CustomEvent) =>\n this.handlePluginMenuSelect(event)}\n >\n </landing-page>\n `;\n }\n\n render() {\n const hasCustomLandingPage = !!this._landingPageNodes?.length;\n if (this.editableDocs.length === 0) {\n return html` <div class=\"landing-page-container\">\n <slot\n name=\"landing-page\"\n @slotchange=${() => this.requestUpdate()}\n ></slot>\n ${!hasCustomLandingPage ? this.renderDefaultLandingPage() : nothing}\n </div>\n ${this.renderOffScreenPlugins()}`;\n }\n\n return html` <oscd-app-bar>\n <plugins-menu\n slot=\"alignStart\"\n appTitle=${this.appTitle}\n appIcon=${this.appIcon}\n .editableDocs=${this.editableDocs}\n .menuPlugins=${this.plugins.menu}\n .locale=${this.locale}\n @menu-plugin-select=${(event: CustomEvent) =>\n this.handlePluginMenuSelect(event)}\n ></plugins-menu>\n\n ${this.selectedEditor\n ? html`<div class=\"current-editor\" slot=\"alignStart\">\n <oscd-divider class=\"vertical\" aria-hidden=\"true\"></oscd-divider>\n <span>${this.selectedEditor.name}</span>\n </div>`\n : nothing}\n\n <div slot=\"alignEnd\">\n ${this.docName\n ? html`<files-menu\n .selectedDocName=${this.docName}\n .editableDocs=${this.editableDocs}\n .locale=${this.locale}\n @change=${(event: CustomEvent) => {\n const name = event.detail.name as string;\n this.docName = name;\n }}\n ></files-menu>\n <oscd-divider\n class=\"vertical\"\n aria-hidden=\"true\"\n ></oscd-divider>`\n : nothing}\n <oscd-filled-icon-button\n aria-label=\"${msg('Undo')}\"\n ?disabled=${!this.canUndo}\n @click=${async () => {\n this.dispatchEvent(\n new CustomEvent('oscd-undo', {\n bubbles: true,\n composed: true,\n }),\n );\n }}\n ><oscd-icon>undo</oscd-icon></oscd-filled-icon-button\n >\n <oscd-filled-icon-button\n aria-label=\"${msg('Redo')}\"\n ?disabled=${!this.canRedo}\n @click=${async () => {\n this.dispatchEvent(\n new CustomEvent('oscd-redo', {\n bubbles: true,\n composed: true,\n }),\n );\n }}\n ><oscd-icon>redo</oscd-icon></oscd-filled-icon-button\n >\n </div>\n </oscd-app-bar>\n\n <main>\n <section class=\"editors-side-panel-section\">\n <editor-plugins-panel\n .editors=${this.plugins.editor}\n .selectedEditor=${this.selectedEditor}\n .locale=${this.locale}\n @editor-select=${(e: CustomEvent) => {\n this.selectedEditor = e.detail.editor;\n }}\n ></editor-plugins-panel>\n </section>\n\n <section class=\"editor-container\">\n ${this.selectedEditor\n ? this.renderPlugin(this.selectedEditor)\n : nothing}\n </section>\n\n ${this.renderOffScreenPlugins()}\n </main>`;\n }\n\n static styles = [\n oscdShellDesignTokens,\n css`\n :host {\n height: 100%;\n display: grid;\n grid-template-rows: min-content 1fr;\n grid-template-columns: 1fr;\n grid-template-areas:\n 'header'\n 'main';\n background-color: var(--shell-background-color);\n }\n\n .landing-page-container {\n grid-column: 1 / -1;\n grid-row: 1 / -1;\n height: 100%;\n overflow: auto;\n }\n\n .landing-page-container ::slotted(*) {\n height: 100%;\n }\n\n oscd-app-bar {\n grid-area: header;\n box-shadow: var(--md-sys-elevation-level-2);\n z-index: 10;\n }\n\n .current-editor {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-right: 12px;\n color: var(--app-bar-current-editor-color);\n font-family: var(--app-bar-current-editor-font-family);\n font-size: var(--app-bar-current-editor-font-size);\n font-style: var(--app-bar-current-editor-font-style);\n line-height: var(--app-bar-current-editor-line-height);\n font-weight: var(--app-bar-current-editor-font-weight);\n white-space: nowrap;\n }\n\n oscd-divider.vertical {\n width: 1px;\n height: 32px;\n --md-divider-color: var(--app-bar-separator-color);\n opacity: var(--app-bar-separator-opacity);\n }\n\n [slot='alignEnd'] {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n [slot='alignEnd'] oscd-divider.vertical {\n margin: 0 8px;\n }\n\n [slot='alignEnd'] oscd-filled-icon-button {\n /* Local colour scheme: setting the system colour once lets the icon\n colour and every derived state layer follow from one declaration.\n Safe because the token mapping block is declared only on :host, so\n --app-bar-action-icon-color is inherited here, not re-declared. */\n --md-sys-color-on-primary: var(--app-bar-action-icon-color);\n --md-filled-icon-button-icon-size: var(--app-bar-action-icon-size);\n --md-filled-icon-button-disabled-icon-color: var(\n --app-bar-action-icon-disabled-color\n );\n --md-filled-icon-button-disabled-container-opacity: var(\n --app-bar-action-icon-disabled-container-opacity\n );\n }\n\n main {\n grid-area: main;\n display: grid;\n /* The side-panel column follows the panel's own intrinsic width, which\n the panel switches between its expanded (308px) and collapsed rail\n (76px) states. */\n grid-template-columns: auto 1fr;\n grid-template-areas: 'sidebar editor';\n overflow: hidden;\n }\n\n section.editors-side-panel-section {\n grid-area: sidebar;\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n section.editor-container {\n grid-area: editor;\n background-color: var(--editor-background-color);\n padding: var(--editor-padding);\n overflow: auto;\n position: relative;\n }\n\n .off-screen-plugin-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n overflow: hidden;\n margin: 0;\n padding: 0;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'oscd-shell': OscdShell;\n }\n}\n"]}
1
+ {"version":3,"file":"oscd-shell.js","sourceRoot":"","sources":["../src/oscd-shell.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing } from 'lit';\nimport {\n customElement,\n property,\n query,\n queryAssignedNodes,\n state,\n} from 'lit/decorators.js';\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';\nimport { localized, msg } from '@lit/localize';\nimport { html as staticHtml, unsafeStatic } from 'lit/static-html.js';\n\nimport { OscdFilledIconButton } from '@omicronenergy/oscd-ui/iconbutton/OscdFilledIconButton.js';\nimport { XMLEditor } from '@openscd/oscd-editor';\nimport { EditEventV2, OpenEvent } from '@openscd/oscd-api';\n\nimport {\n flattenPluginEntries,\n loadSourcedPlugins,\n} from './utils/plugin-utils.js';\nimport { getLocale, LocaleTag, setLocale } from './localization.js';\nimport { EditorPluginsPanel } from './side-panel/editor-plugins-panel.js';\nimport { PluginsMenu } from './menus/plugins-menu.js';\nimport { LandingPage } from './landing-page/landing-page.js';\nimport { RenameEvent, CloseEvent } from './foundation/events.js';\nimport { FilesMenu } from './menus/files-menu.js';\nimport { oscdShellDesignTokens } from './oscd-shell-design-tokens.js';\nimport { OscdAppBar } from '@omicronenergy/oscd-ui/app-bar/OscdAppBar.js';\nimport { OscdDivider } from '@omicronenergy/oscd-ui/divider/OscdDivider.js';\nimport { OscdIcon } from '@omicronenergy/oscd-ui/icon/OscdIcon.js';\n\n/** Fields shared by plugin entries and the groups that contain them. */\nexport interface PluginMetadata {\n name: string;\n translations?: Record<string, string>;\n icon: string;\n}\n\n/** Fields common to actual plugins (not groups)\n * require a document. */\nexport interface OscdPluginBase extends PluginMetadata {\n requireDoc?: boolean;\n}\n\n/** A plugin dynamically imported at runtime from a URL, defined by the `src` field.\n * The shell will load the plugin and assign it a unique tagName generated from hashing the `src` url. */\nexport interface SourcedPlugin extends OscdPluginBase {\n src: string;\n}\n\n/** A plugin already defined in the registry under `tagName`. */\nexport interface TaggedPlugin extends OscdPluginBase {\n tagName: string;\n}\n\n/** A declared plugin, either sourced or already registered. */\nexport type OscdPlugin = SourcedPlugin | TaggedPlugin;\n\n/**\n * The shell's internal object for all plugins. Here `tagName` is guaranteed because\n * resolution has already happened, and `src` is deliberately absent - it has\n * served its purpose and nothing downstream reads it.\n * Currently its the same shape as TaggedPlugin, their purposes are\n * different and clarity is favored over brevity.\n */\nexport interface ResolvedPlugin extends OscdPluginBase {\n tagName: string;\n}\n\n/** A group of plugins. */\nexport interface PluginGroup<\n P extends PluginMetadata = OscdPlugin,\n> extends PluginMetadata {\n plugins: P[];\n}\n\n/**\n * The root object representing the plugins property (and the resolved plugins).\n */\nexport interface PluginSet<P extends PluginMetadata = OscdPlugin> {\n menu: (P | PluginGroup<P>)[];\n editor: (P | PluginGroup<P>)[];\n background: P[];\n}\n\n@localized()\n@customElement('oscd-shell')\nexport class OscdShell extends ScopedElementsMixin(LitElement) {\n static scopedElements = {\n 'oscd-app-bar': OscdAppBar,\n 'oscd-filled-icon-button': OscdFilledIconButton,\n 'oscd-divider': OscdDivider,\n 'oscd-icon': OscdIcon,\n 'files-menu': FilesMenu,\n 'plugins-menu': PluginsMenu,\n 'editor-plugins-panel': EditorPluginsPanel,\n 'landing-page': LandingPage,\n };\n\n /*\n * Properties\n */\n\n /**\n * Url to the app icon displayed in the app bar\n */\n @property({ type: String })\n appIcon: string = '';\n\n @property({ type: String })\n appTitle: string = 'OpenSCD';\n\n @property({ type: String })\n landingPageHeading: string = 'Welcome to OpenSCD';\n\n @property({ type: String })\n landingPageSubHeading: string =\n 'Open Source IEC-61850-6 SCL Editing Platform';\n\n /** The file endings of editable files */\n @property({ type: Array, reflect: true }) editable = [\n 'cid',\n 'icd',\n 'iid',\n 'scd',\n 'sed',\n 'ssd',\n ];\n\n @property({ type: String, reflect: true })\n get locale() {\n return getLocale() as LocaleTag;\n }\n\n set locale(tag: LocaleTag) {\n try {\n if (tag) {\n setLocale(tag);\n }\n } catch {\n // don't change locale if tag is invalid\n }\n }\n\n _plugins: PluginSet<OscdPlugin> = {\n menu: [],\n editor: [],\n background: [],\n };\n\n /** Internal representation of processed `_plugins`. These plugins have been validated and the\n * `tagName` here is guaranteed, sourced entries imported into the registry & tagged. This copy of the\n * plugins is kept separate from the _plugins, which remain an unmodified single source of truth.\n */\n _resolvedPlugins: PluginSet<ResolvedPlugin> = {\n menu: [],\n editor: [],\n background: [],\n };\n\n /**\n * The plugin set as declared. Deliberately symmetric: what you assign is\n * what you read back, untouched. Resolution (deriving `tagName` from `src`,\n * validating, importing) happens into `_resolvedPlugins`, so the hashed\n * tag names it invents stay an implementation detail.\n */\n @property({ type: Object })\n get plugins(): PluginSet<OscdPlugin> {\n return this._plugins;\n }\n\n set plugins(plugins: Partial<PluginSet<OscdPlugin>>) {\n this._plugins = {\n menu: plugins.menu ?? [],\n editor: plugins.editor ?? [],\n background: plugins.background ?? [],\n };\n this._resolvedPlugins = {\n menu: loadSourcedPlugins(this._plugins.menu, this.registry!),\n editor: loadSourcedPlugins(this._plugins.editor, this.registry!),\n background: loadSourcedPlugins(this._plugins.background, this.registry!),\n };\n }\n\n /*\n * States\n */\n @state()\n get canRedo(): boolean {\n return this.xmlEditor.future.length >= 1;\n }\n\n @state()\n get canUndo(): boolean {\n return this.xmlEditor.past.length >= 1;\n }\n\n @state()\n selectedEditor?: ResolvedPlugin;\n\n @state()\n /** The `XMLDocument` currently being edited */\n get doc(): XMLDocument {\n return this.docs[this.docName];\n }\n\n /** The name of the [[`doc`]] currently being edited */\n @property({ type: String, reflect: true })\n docName = '';\n\n /** The set of `XMLDocument`s currently loaded */\n private _docs: Record<string, XMLDocument> = {};\n\n @state()\n get docs(): Record<string, XMLDocument> {\n return this._docs;\n }\n\n set docs(newDocs: Record<string, XMLDocument>) {\n this._docs = newDocs;\n this.docVersion += 1;\n }\n\n @state()\n docVersion: number = -1;\n\n @state()\n get editableDocs(): string[] {\n return Object.keys(this.docs).filter(name => this.isEditable(name));\n }\n\n @state()\n get last(): number {\n return this.xmlEditor.past.length - 1;\n }\n\n @state()\n xmlEditor: XMLEditor = new XMLEditor();\n\n /*\n * All Queries\n */\n\n @query('plugins-menu')\n pluginsMenu!: PluginsMenu;\n\n @query('editor-plugins-panel')\n editorPluginsPanel!: EditorPluginsPanel;\n\n @queryAssignedNodes({ slot: 'landing-page' })\n private _landingPageNodes?: NodeListOf<HTMLElement>;\n\n /*\n * Constructor & life cycle methods\n */\n constructor() {\n super();\n // Catch all edits (from commits AND events) and trigger an update\n this.xmlEditor.subscribe(() => {\n this.docVersion += 1;\n });\n }\n\n willUpdate(changedProperties: Map<PropertyKey, unknown>) {\n if (changedProperties.has('docName') || changedProperties.has('plugins')) {\n const firstEditor = flattenPluginEntries(this._resolvedPlugins.editor)[0];\n if (this.docName && firstEditor && !this.selectedEditor) {\n this.selectedEditor = firstEditor;\n }\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n\n document.addEventListener('keydown', this.handleKeyPress, true);\n this.addEventListener('oscd-open', this.handleOpenDoc);\n this.addEventListener('oscd-rename', this.handleRenameDoc);\n this.addEventListener('oscd-close', this.handleCloseDoc);\n this.addEventListener('oscd-edit-v2', this.handleEditV2);\n this.addEventListener('oscd-undo', this.handleUndo);\n this.addEventListener('oscd-redo', this.handleRedo);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n // Remove event listeners\n document.removeEventListener('keydown', this.handleKeyPress, true);\n this.removeEventListener('oscd-open', this.handleOpenDoc);\n this.removeEventListener('oscd-rename', this.handleRenameDoc);\n this.removeEventListener('oscd-edit-v2', this.handleEditV2);\n this.removeEventListener('oscd-undo', this.handleUndo);\n this.removeEventListener('oscd-redo', this.handleRedo);\n this.removeEventListener('oscd-close', this.handleCloseDoc);\n }\n\n /*\n * Event Handlers\n */\n\n handleOpenDoc = ({ detail: { docName, doc } }: OpenEvent) => {\n this.docs = {\n ...this.docs,\n [docName]: doc,\n };\n if (this.isEditable(docName)) {\n this.docName = docName;\n }\n this.requestUpdate();\n };\n\n handleRenameDoc = (customEvent: RenameEvent) => {\n const { oldName, newName } = customEvent.detail;\n if (!this.docs[oldName] || newName === oldName || this.docs[newName]) {\n return;\n }\n const doc = this.docs[oldName];\n delete this.docs[oldName];\n this.docs = {\n ...this.docs,\n [newName]: doc,\n };\n this.docName = newName;\n };\n\n handleEditV2 = (event: EditEventV2) => {\n const { edit, title, squash } = event.detail;\n this.xmlEditor.commit(edit, { title, squash });\n };\n\n handleCloseDoc = (event: CloseEvent) => {\n const docName = event.detail.docName as string;\n delete this.docs[docName];\n if (this.docName === docName) {\n this.docName = this.editableDocs[0] || '';\n }\n };\n\n handleUndo = () => {\n this.undo();\n };\n\n handleRedo = () => {\n this.redo();\n };\n\n private handleKeyPress = (e: KeyboardEvent) => {\n if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key.toLowerCase() === 'f') {\n const panel = this.shadowRoot?.querySelector<EditorPluginsPanel>(\n 'editor-plugins-panel',\n );\n if (panel) {\n if (!panel.expanded) {\n panel.searchMode = true;\n }\n panel.focusSearch(true);\n e.preventDefault();\n e.stopPropagation();\n }\n return;\n }\n if (!e.ctrlKey) {\n return;\n }\n if (!Object.prototype.hasOwnProperty.call(this.hotkeys, e.key)) {\n return;\n }\n this.hotkeys[e.key]!.call(this);\n e.preventDefault();\n };\n\n handleOpenPluginMenu = () => {\n this.pluginsMenu.open();\n };\n\n handlePluginMenuSelect(customEvent: CustomEvent) {\n const plugin = customEvent.detail.plugin as ResolvedPlugin;\n if (plugin.tagName) {\n this.shadowRoot!.querySelector<\n HTMLElement & { run: () => Promise<void> }\n >(plugin.tagName)!.run?.();\n }\n }\n /** Undo the last `n` [[Edit]]s committed */\n undo = (n = 1) => {\n if (!this.canUndo || n < 1) {\n return;\n }\n this.xmlEditor.undo();\n if (n > 1) {\n this.undo(n - 1);\n }\n this.requestUpdate();\n };\n\n /** Redo the last `n` [[Edit]]s that have been undone */\n redo = (n = 1) => {\n if (!this.canRedo || n < 1) {\n return;\n }\n this.xmlEditor.redo();\n if (n > 1) {\n this.redo(n - 1);\n }\n this.requestUpdate();\n };\n\n private hotkeys: Partial<Record<string, () => void>> = {\n m: this.handleOpenPluginMenu,\n z: this.undo,\n y: this.redo,\n Z: this.redo,\n };\n\n isEditable(docName: string): boolean {\n return !!this.editable.find(ext =>\n docName.toLowerCase().endsWith(`.${ext}`),\n );\n }\n\n renderPlugin(plugin: ResolvedPlugin) {\n const tag = unsafeStatic(plugin.tagName);\n return staticHtml`<${tag}\n .locale=\"${this.locale}\"\n .docName=\"${this.docName}\"\n .doc=${this.doc}\n .docs=${this.docs}\n .editCount=${this.docVersion}\n .docVersion=${this.docVersion}\n .editor=${this.xmlEditor}>\n </${tag}>`;\n }\n\n renderOffScreenPlugins() {\n return html`\n <section class=\"off-screen-plugin-container\" aria-hidden=\"true\">\n <div class=\"menu-plugins\">\n ${flattenPluginEntries(this._resolvedPlugins.menu)\n .filter(plugin => !plugin.requireDoc || !!this.docName)\n .map(plugin => this.renderPlugin(plugin))}\n </div>\n <div class=\"background-plugins\">\n ${this._resolvedPlugins.background\n .filter(plugin => !plugin.requireDoc || !!this.docName)\n .map(plugin => this.renderPlugin(plugin))}\n </div>\n </section>\n `;\n }\n\n renderDefaultLandingPage() {\n return html`\n <landing-page\n heading=${this.landingPageHeading}\n subHeading=${this.landingPageSubHeading}\n .menuPlugins=${flattenPluginEntries(this._resolvedPlugins.menu).filter(\n plugin => !plugin.requireDoc || !!this.docName,\n )}\n .locale=${this.locale}\n @menu-plugin-select=${(event: CustomEvent) =>\n this.handlePluginMenuSelect(event)}\n >\n </landing-page>\n `;\n }\n\n render() {\n const hasCustomLandingPage = !!this._landingPageNodes?.length;\n if (this.editableDocs.length === 0) {\n return html` <div class=\"landing-page-container\">\n <slot\n name=\"landing-page\"\n @slotchange=${() => this.requestUpdate()}\n ></slot>\n ${!hasCustomLandingPage ? this.renderDefaultLandingPage() : nothing}\n </div>\n ${this.renderOffScreenPlugins()}`;\n }\n\n return html` <oscd-app-bar>\n <plugins-menu\n slot=\"alignStart\"\n appTitle=${this.appTitle}\n appIcon=${this.appIcon}\n .editableDocs=${this.editableDocs}\n .menuPlugins=${this._resolvedPlugins.menu}\n .locale=${this.locale}\n @menu-plugin-select=${(event: CustomEvent) =>\n this.handlePluginMenuSelect(event)}\n ></plugins-menu>\n\n ${this.selectedEditor\n ? html`<div class=\"current-editor\" slot=\"alignStart\">\n <oscd-divider class=\"vertical\" aria-hidden=\"true\"></oscd-divider>\n <span>${this.selectedEditor.name}</span>\n </div>`\n : nothing}\n\n <div slot=\"alignEnd\">\n ${this.docName\n ? html`<files-menu\n .selectedDocName=${this.docName}\n .editableDocs=${this.editableDocs}\n .locale=${this.locale}\n @change=${(event: CustomEvent) => {\n const name = event.detail.name as string;\n this.docName = name;\n }}\n ></files-menu>\n <oscd-divider\n class=\"vertical\"\n aria-hidden=\"true\"\n ></oscd-divider>`\n : nothing}\n <oscd-filled-icon-button\n aria-label=\"${msg('Undo')}\"\n ?disabled=${!this.canUndo}\n @click=${async () => {\n this.dispatchEvent(\n new CustomEvent('oscd-undo', {\n bubbles: true,\n composed: true,\n }),\n );\n }}\n ><oscd-icon>undo</oscd-icon></oscd-filled-icon-button\n >\n <oscd-filled-icon-button\n aria-label=\"${msg('Redo')}\"\n ?disabled=${!this.canRedo}\n @click=${async () => {\n this.dispatchEvent(\n new CustomEvent('oscd-redo', {\n bubbles: true,\n composed: true,\n }),\n );\n }}\n ><oscd-icon>redo</oscd-icon></oscd-filled-icon-button\n >\n </div>\n </oscd-app-bar>\n\n <main>\n <section class=\"editors-side-panel-section\">\n <editor-plugins-panel\n .editors=${this._resolvedPlugins.editor}\n .selectedEditor=${this.selectedEditor}\n .locale=${this.locale}\n @editor-select=${(e: CustomEvent) => {\n this.selectedEditor = e.detail.editor;\n }}\n ></editor-plugins-panel>\n </section>\n\n <section class=\"editor-container\">\n ${this.selectedEditor\n ? this.renderPlugin(this.selectedEditor)\n : nothing}\n </section>\n\n ${this.renderOffScreenPlugins()}\n </main>`;\n }\n\n static styles = [\n oscdShellDesignTokens,\n css`\n :host {\n height: 100%;\n display: grid;\n grid-template-rows: min-content 1fr;\n grid-template-columns: 1fr;\n grid-template-areas:\n 'header'\n 'main';\n background-color: var(--shell-background-color);\n }\n\n .landing-page-container {\n grid-column: 1 / -1;\n grid-row: 1 / -1;\n height: 100%;\n overflow: auto;\n }\n\n .landing-page-container ::slotted(*) {\n height: 100%;\n }\n\n oscd-app-bar {\n grid-area: header;\n box-shadow: var(--md-sys-elevation-level-2);\n z-index: 10;\n }\n\n .current-editor {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-right: 12px;\n color: var(--app-bar-current-editor-color);\n font-family: var(--app-bar-current-editor-font-family);\n font-size: var(--app-bar-current-editor-font-size);\n font-style: var(--app-bar-current-editor-font-style);\n line-height: var(--app-bar-current-editor-line-height);\n font-weight: var(--app-bar-current-editor-font-weight);\n white-space: nowrap;\n }\n\n oscd-divider.vertical {\n width: 1px;\n height: 32px;\n --md-divider-color: var(--app-bar-separator-color);\n opacity: var(--app-bar-separator-opacity);\n }\n\n [slot='alignEnd'] {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n [slot='alignEnd'] oscd-divider.vertical {\n margin: 0 8px;\n }\n\n [slot='alignEnd'] oscd-filled-icon-button {\n /* Local colour scheme: setting the system colour once lets the icon\n colour and every derived state layer follow from one declaration.\n Safe because the token mapping block is declared only on :host, so\n --app-bar-action-icon-color is inherited here, not re-declared. */\n --md-sys-color-on-primary: var(--app-bar-action-icon-color);\n --md-filled-icon-button-icon-size: var(--app-bar-action-icon-size);\n --md-filled-icon-button-disabled-icon-color: var(\n --app-bar-action-icon-disabled-color\n );\n --md-filled-icon-button-disabled-container-opacity: var(\n --app-bar-action-icon-disabled-container-opacity\n );\n }\n\n main {\n grid-area: main;\n display: grid;\n /* The side-panel column follows the panel's own intrinsic width, which\n the panel switches between its expanded (308px) and collapsed rail\n (76px) states. */\n grid-template-columns: auto 1fr;\n grid-template-areas: 'sidebar editor';\n overflow: hidden;\n }\n\n section.editors-side-panel-section {\n grid-area: sidebar;\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n section.editor-container {\n grid-area: editor;\n background-color: var(--editor-background-color);\n padding: var(--editor-padding);\n overflow: auto;\n position: relative;\n }\n\n .off-screen-plugin-container {\n position: absolute;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n overflow: hidden;\n margin: 0;\n padding: 0;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'oscd-shell': OscdShell;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"build-tree-nodes.spec.js","sourceRoot":"","sources":["../../src/side-panel/build-tree-nodes.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,OAAe,EAAe,EAAE,CAAC,CAAC;IAC5D,IAAI;IACJ,OAAO;IACP,IAAI,EAAE,QAAQ;CACf,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC;YAC5B,IAAI,CAAC,mBAAmB,EAAE,iBAAiB,CAAC;SAC7C,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,KAAK,GAAgB;YACzB,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;SAC9C,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,KAAK,GAAG,CAAC,IAAY,EAAe,EAAE,CAAC,CAAC;YAC5C,IAAI;YACJ,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/D,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzC,eAAe;YACf,eAAe;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,4EAA4E;QAC5E,6CAA6C;QAC7C,MAAM,KAAK,GAAG,cAAc,CAAC;YAC3B,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC;YAClC,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC;SACnC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { buildTreeNodes } from './editor-plugins-panel.js';\nimport { PluginEntry, PluginGroup } from '../oscd-shell.js';\n\nconst leaf = (name: string, tagName: string): PluginEntry => ({\n name,\n tagName,\n icon: 'margin',\n});\n\ndescribe('buildTreeNodes', () => {\n it('converts a leaf plugin into a node with id set to its tagName', () => {\n const [node] = buildTreeNodes([\n leaf('Substation Editor', 'oscd-substation'),\n ]);\n expect(node.id).to.equal('oscd-substation');\n expect(node.name).to.equal('Substation Editor');\n expect(node.children).to.deep.equal([]);\n });\n\n it('converts a group into a node with a unique positional id and built children', () => {\n const group: PluginGroup = {\n name: 'Communication',\n icon: 'folder',\n plugins: [leaf('GOOSE Editor', 'oscd-goose')],\n };\n const [node] = buildTreeNodes([group]);\n expect(node.id).to.equal('group:0:Communication');\n expect(node.children).to.have.lengthOf(1);\n expect(node.children?.[0].id).to.equal('oscd-goose');\n });\n\n it('gives same-named groups distinct ids by position', () => {\n const group = (name: string): PluginGroup => ({\n name,\n icon: 'folder',\n plugins: [],\n });\n const nodes = buildTreeNodes([group('Files'), group('Files')]);\n expect(nodes.map(n => n.id)).to.deep.equal([\n 'group:0:Files',\n 'group:1:Files',\n ]);\n });\n\n it('builds leaf nodes from a flat list (as used for pinned plugins)', () => {\n // Regression: pinned plugins are flattened entries; each must gain an id so\n // the pinned tree can render and match them.\n const nodes = buildTreeNodes([\n leaf('GOOSE Editor', 'oscd-goose'),\n leaf('Sampled Values', 'oscd-smv'),\n ]);\n expect(nodes.map(n => n.id)).to.deep.equal(['oscd-goose', 'oscd-smv']);\n });\n});\n"]}
1
+ {"version":3,"file":"build-tree-nodes.spec.js","sourceRoot":"","sources":["../../src/side-panel/build-tree-nodes.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAG3D,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,OAAe,EAAkB,EAAE,CAAC,CAAC;IAC/D,IAAI;IACJ,OAAO;IACP,IAAI,EAAE,QAAQ;CACf,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC;YAC5B,IAAI,CAAC,mBAAmB,EAAE,iBAAiB,CAAC;SAC7C,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,KAAK,GAAgC;YACzC,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;SAC9C,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,KAAK,GAAG,CAAC,IAAY,EAA+B,EAAE,CAAC,CAAC;YAC5D,IAAI;YACJ,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/D,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACzC,eAAe;YACf,eAAe;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,4EAA4E;QAC5E,6CAA6C;QAC7C,MAAM,KAAK,GAAG,cAAc,CAAC;YAC3B,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC;YAClC,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC;SACnC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { buildTreeNodes } from './editor-plugins-panel.js';\nimport { ResolvedPlugin, PluginGroup } from '../oscd-shell.js';\n\nconst leaf = (name: string, tagName: string): ResolvedPlugin => ({\n name,\n tagName,\n icon: 'margin',\n});\n\ndescribe('buildTreeNodes', () => {\n it('converts a leaf plugin into a node with id set to its tagName', () => {\n const [node] = buildTreeNodes([\n leaf('Substation Editor', 'oscd-substation'),\n ]);\n expect(node.id).to.equal('oscd-substation');\n expect(node.name).to.equal('Substation Editor');\n expect(node.children).to.deep.equal([]);\n });\n\n it('converts a group into a node with a unique positional id and built children', () => {\n const group: PluginGroup<ResolvedPlugin> = {\n name: 'Communication',\n icon: 'folder',\n plugins: [leaf('GOOSE Editor', 'oscd-goose')],\n };\n const [node] = buildTreeNodes([group]);\n expect(node.id).to.equal('group:0:Communication');\n expect(node.children).to.have.lengthOf(1);\n expect(node.children?.[0].id).to.equal('oscd-goose');\n });\n\n it('gives same-named groups distinct ids by position', () => {\n const group = (name: string): PluginGroup<ResolvedPlugin> => ({\n name,\n icon: 'folder',\n plugins: [],\n });\n const nodes = buildTreeNodes([group('Files'), group('Files')]);\n expect(nodes.map(n => n.id)).to.deep.equal([\n 'group:0:Files',\n 'group:1:Files',\n ]);\n });\n\n it('builds leaf nodes from a flat list (as used for pinned plugins)', () => {\n // Regression: pinned plugins are flattened entries; each must gain an id so\n // the pinned tree can render and match them.\n const nodes = buildTreeNodes([\n leaf('GOOSE Editor', 'oscd-goose'),\n leaf('Sampled Values', 'oscd-smv'),\n ]);\n expect(nodes.map(n => n.id)).to.deep.equal(['oscd-goose', 'oscd-smv']);\n });\n});\n"]}
@@ -5,7 +5,7 @@ import { OscdListItem } from '@omicronenergy/oscd-ui/list/OscdListItem.js';
5
5
  import { OscdMenu } from '@omicronenergy/oscd-ui/menu/OscdMenu.js';
6
6
  import { OscdMenuItem } from '@omicronenergy/oscd-ui/menu/OscdMenuItem.js';
7
7
  import { LocaleTag } from '../localization.js';
8
- import { PluginEntry, PluginGroup } from '../oscd-shell.js';
8
+ import { PluginGroup, ResolvedPlugin } from '../oscd-shell.js';
9
9
  import { OscdTree, TreeNode, TreeRenderContext } from '@omicronenergy/oscd-ui/tree/OscdTree.js';
10
10
  import { OscdTreeItem } from '@omicronenergy/oscd-ui/tree/OscdTreeItem.js';
11
11
  import { OscdDivider } from '@omicronenergy/oscd-ui/divider/OscdDivider.js';
@@ -15,7 +15,7 @@ type PlaceholderTreeNode = {
15
15
  name: string;
16
16
  translations?: Record<string, string>;
17
17
  };
18
- type EditorPluginTreeNode = (PluginGroup | PluginEntry | PlaceholderTreeNode) & TreeNode & {
18
+ type EditorPluginTreeNode = (PluginGroup<ResolvedPlugin> | ResolvedPlugin | PlaceholderTreeNode) & TreeNode & {
19
19
  children?: EditorPluginTreeNode[];
20
20
  plugins?: EditorPluginTreeNode[];
21
21
  };
@@ -24,8 +24,8 @@ declare global {
24
24
  'editor-plugins-panel': EditorPluginsPanel;
25
25
  }
26
26
  }
27
- export declare function buildTreeNodes(plugins: (PluginEntry | PluginGroup)[]): EditorPluginTreeNode[];
28
- declare const EditorPluginsPanel_base: typeof LitElement & import("@open-wc/scoped-elements/lit-element.js").ScopedElementsHostConstructor;
27
+ export declare function buildTreeNodes(plugins: (ResolvedPlugin | PluginGroup<ResolvedPlugin>)[]): EditorPluginTreeNode[];
28
+ declare const EditorPluginsPanel_base: typeof LitElement & import("@open-wc/dedupe-mixin").Constructor<import("@open-wc/scoped-elements/types.js").ScopedElementsHost> & import("@open-wc/scoped-elements/types.js").ScopedElementsHostConstructor;
29
29
  export declare class EditorPluginsPanel extends EditorPluginsPanel_base {
30
30
  static scopedElements: {
31
31
  'oscd-icon-button': typeof OscdIconButton;
@@ -39,8 +39,8 @@ export declare class EditorPluginsPanel extends EditorPluginsPanel_base {
39
39
  'oscd-menu-item': typeof OscdMenuItem;
40
40
  };
41
41
  id: string;
42
- editors: (PluginEntry | PluginGroup)[];
43
- selectedEditor?: PluginEntry;
42
+ editors: (ResolvedPlugin | PluginGroup<ResolvedPlugin>)[];
43
+ selectedEditor?: ResolvedPlugin;
44
44
  locale: LocaleTag;
45
45
  expanded: boolean;
46
46
  /**
@@ -680,6 +680,12 @@ EditorPluginsPanel.styles = css `
680
680
  oscd-tree {
681
681
  margin-inline: 0;
682
682
  min-height: 0;
683
+ /* .tree-scroll is the sole flex item allowed to shrink/scroll; without
684
+ this, a too-short container shrinks each tree's box below its
685
+ rendered content instead of letting the scroll container overflow,
686
+ and the (unclipped) shadow-DOM rows bleed past the shrunk box into
687
+ whichever tree follows. */
688
+ flex-shrink: 0;
683
689
  --oscd-tree-row-height: 36px;
684
690
  --oscd-tree-item-min-height: 36px;
685
691
  --oscd-tree-row-gap: 4px;
@@ -1 +1 @@
1
- {"version":3,"file":"editor-plugins-panel.js","sourceRoot":"","sources":["../../src/side-panel/editor-plugins-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';\nimport { localized, msg, str } from '@lit/localize';\n\nimport { OscdIconButton } from '@omicronenergy/oscd-ui/iconbutton/OscdIconButton.js';\nimport { OscdIcon } from '@omicronenergy/oscd-ui/icon/OscdIcon.js';\nimport { OscdListItem } from '@omicronenergy/oscd-ui/list/OscdListItem.js';\nimport { OscdMenu } from '@omicronenergy/oscd-ui/menu/OscdMenu.js';\nimport { OscdMenuItem } from '@omicronenergy/oscd-ui/menu/OscdMenuItem.js';\n\nimport { LocaleTag } from '../localization.js';\nimport { PluginEntry, PluginGroup } from '../oscd-shell.js';\nimport {\n OscdTree,\n TreeNode,\n TreeRenderContext,\n} from '@omicronenergy/oscd-ui/tree/OscdTree.js';\nimport {\n filterBySearchTerm,\n filterByPinned,\n isPluginGroup,\n flattenPluginEntries,\n} from '../utils/plugin-utils.js';\nimport { OscdTreeItem } from '@omicronenergy/oscd-ui/tree/OscdTreeItem.js';\nimport { OscdDivider } from '@omicronenergy/oscd-ui/divider/OscdDivider.js';\nimport { localstorage } from '@omicronenergy/oscd-ui/decorators/localstorage.js';\nimport { OscdOutlinedSearchField } from '@omicronenergy/oscd-ui/search-field/OscdOutlinedSearchField.js';\n\ntype PlaceholderTreeNode = {\n kind: 'placeholder';\n name: string;\n translations?: Record<string, string>;\n};\n\ntype EditorPluginTreeNode = (PluginGroup | PluginEntry | PlaceholderTreeNode) &\n TreeNode & {\n children?: EditorPluginTreeNode[];\n plugins?: EditorPluginTreeNode[];\n };\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'editor-plugins-panel': EditorPluginsPanel;\n }\n}\n\nconst unpinnedIcon = html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n fill=\"none\"\n>\n <path\n d=\"M16.391 14.4188L16.8773 16.2406L16.2096 17.3947L13.3244 15.7253L11.3211 19.1876L10.4102 19.4307L10.1671 18.5198L12.1703 15.0576L9.28512 13.3882L9.95287 12.2341L11.7747 11.7478L14.1118 7.70854L13.5348 7.37467L14.2025 6.22059L19.9729 9.55934L19.3052 10.7134L18.7281 10.3795L16.391 14.4188ZM11.5974 13.1857L15.2328 15.2891L14.9531 14.2415L17.574 9.71179L15.2659 8.37629L12.645 12.906L11.5974 13.1857Z\"\n fill=\"currentColor\"\n />\n</svg>`;\n\nconst pinnedIcon = html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n fill=\"none\"\n>\n <path\n d=\"M16.4379 14.5274L16.9273 16.3484L16.2615 17.5036L13.3735 15.8391L11.3761 19.3047L10.4656 19.5494L10.2209 18.6389L12.2183 15.1733L9.33034 13.5088L9.99614 12.3536L11.8171 11.8642L14.1475 7.821L13.5699 7.4881L14.2357 6.3329L20.0117 9.66194L19.3459 10.8171L18.7683 10.4842L16.4379 14.5274Z\"\n fill=\"currentColor\"\n />\n</svg>`;\n\nexport function buildTreeNodes(\n plugins: (PluginEntry | PluginGroup)[],\n): EditorPluginTreeNode[] {\n function pluginEntryToTreeNode(\n pluginEntry: PluginEntry,\n ): EditorPluginTreeNode {\n return {\n ...pluginEntry,\n id: pluginEntry.tagName,\n children: [], //explicitly set children to an empty array for leaf nodes\n };\n }\n\n return plugins.map((editor, index) => {\n const isGroup = isPluginGroup(editor);\n if (isGroup) {\n const children = (editor as PluginGroup).plugins.map(\n pluginEntryToTreeNode,\n );\n return {\n ...editor,\n id: `group:${index}:${editor.name}`,\n children,\n };\n }\n return pluginEntryToTreeNode(editor as PluginEntry);\n });\n}\n\nfunction renderFlyoutPlaceholder() {\n return html`<oscd-menu-item disabled>\n <div slot=\"headline\">${msg('Items you pin will appear here')}</div>\n </oscd-menu-item>`;\n}\n\n@localized()\nexport class EditorPluginsPanel extends ScopedElementsMixin(LitElement) {\n static scopedElements = {\n 'oscd-icon-button': OscdIconButton,\n 'oscd-icon': OscdIcon,\n 'oscd-list-item': OscdListItem,\n 'oscd-tree': OscdTree,\n 'oscd-tree-item': OscdTreeItem,\n 'oscd-outlined-search-field': OscdOutlinedSearchField,\n 'oscd-divider': OscdDivider,\n 'oscd-menu': OscdMenu,\n 'oscd-menu-item': OscdMenuItem,\n };\n\n id = 'editor-plugins-panel';\n\n @property({ type: Array })\n editors: (PluginEntry | PluginGroup)[] = [];\n\n @property({ type: Number })\n selectedEditor?: PluginEntry;\n\n @property({ type: String })\n locale!: LocaleTag;\n\n @localstorage({ default: true })\n @property({ type: Boolean, reflect: true })\n expanded!: boolean;\n\n /**\n * Transient \"search mode\": the collapsed rail's search icon opens the full\n * panel to let the user search, WITHOUT persisting the panel as expanded.\n * It is reflected purely so `:host([search-mode])` can drive the open width.\n * Exited on editor selection or Escape (see `exitSearchMode`).\n */\n @property({ type: Boolean, reflect: true, attribute: 'search-mode' })\n searchMode = false;\n\n /** True when the panel is visually open (persisted expanded OR transient search). */\n get isOpen(): boolean {\n return this.expanded || this.searchMode;\n }\n\n editorTreeNodes: EditorPluginTreeNode[] = [];\n\n pinnedTreeNodes: EditorPluginTreeNode[] = [\n {\n id: 'pinned',\n name: 'Pinned',\n icon: 'keep',\n plugins: [],\n children: [],\n },\n ];\n\n @state()\n searchValue = '';\n\n @state()\n focusedTree: 'pinned' | 'editors' | null = null;\n\n @localstorage({ default: [] })\n @state()\n expandedIds!: string[];\n\n @localstorage({ default: [] })\n @state()\n pinnedPluginIds!: string[];\n\n @localstorage({ default: [] })\n @state()\n pinnedExpanded!: string[];\n\n willUpdate(changedProperties: Map<string, unknown>) {\n if (\n changedProperties.has('editors') ||\n changedProperties.has('searchValue') ||\n changedProperties.has('locale')\n ) {\n const searchResults = filterBySearchTerm(\n this.editors,\n this.searchValue,\n this.locale,\n );\n this.editorTreeNodes = buildTreeNodes(searchResults);\n }\n\n if (\n changedProperties.has('editors') ||\n changedProperties.has('pinnedPluginIds') ||\n changedProperties.has('locale')\n ) {\n const pinnedPlugins = filterByPinned(this.editors, this.pinnedPluginIds);\n const pinnedChildren: EditorPluginTreeNode[] = pinnedPlugins.length\n ? buildTreeNodes(pinnedPlugins)\n : [\n {\n kind: 'placeholder',\n name: msg('Items you pin will appear here'),\n id: 'pinned-placeholder',\n children: [],\n },\n ];\n this.pinnedTreeNodes = [\n {\n id: 'pinned',\n name: msg('Pinned'),\n icon: 'keep',\n plugins: [],\n children: pinnedChildren,\n },\n ];\n }\n }\n\n togglePin(id: string) {\n if (this.pinnedPluginIds.includes(id)) {\n this.pinnedPluginIds = this.pinnedPluginIds.filter(\n pinnedId => pinnedId !== id,\n );\n } else {\n this.pinnedPluginIds = [...this.pinnedPluginIds, id];\n this.pinnedExpanded = ['pinned']; // Expand the pinned section when a new plugin is pinned\n }\n }\n\n selectEditor(selectedIds: string[]) {\n const [selectedId] = selectedIds;\n if (!selectedId) {\n return;\n }\n const editor = flattenPluginEntries(this.editors).find(\n editor => editor.tagName === selectedId,\n );\n if (!editor) {\n return;\n }\n this.dispatchEditorSelect(editor);\n }\n\n /**\n * Dispatches the `editor-select` event and leaves transient search mode, if\n * active. Used by both the expanded trees and the collapsed rail flyouts.\n */\n private dispatchEditorSelect(editor?: PluginEntry) {\n this.dispatchEvent(\n new CustomEvent('editor-select', {\n detail: { editor },\n bubbles: true,\n composed: true,\n }),\n );\n if (this.searchMode) {\n this.exitSearchMode();\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener('keydown', this.handleKeydown);\n }\n\n disconnectedCallback() {\n this.removeEventListener('keydown', this.handleKeydown);\n super.disconnectedCallback();\n }\n\n private handleKeydown = (event: KeyboardEvent) => {\n const fromSearchField =\n (event.currentTarget as Element | null)?.localName ===\n 'oscd-outlined-search-field' ||\n event\n .composedPath()\n .some(\n target =>\n (target as Element).localName === 'oscd-outlined-search-field',\n );\n if (event.key === 'Escape' && this.searchMode) {\n event.stopPropagation();\n this.exitSearchMode();\n return;\n }\n\n if (\n fromSearchField &&\n (event.key === 'ArrowDown' || event.key === 'ArrowUp')\n ) {\n event.preventDefault();\n event.stopPropagation();\n this.startTreeNavigation(event.key === 'ArrowDown' ? 'down' : 'up');\n return;\n }\n\n if (fromSearchField && event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n this.activateKeyboardTarget();\n }\n };\n\n /** Opens the panel transiently for searching (does not persist `expanded`). */\n private enterSearchMode() {\n this.searchMode = true;\n this.focusSearch(true);\n }\n\n /** Focuses the search field, optionally selecting its current query. */\n focusSearch(selectQuery = false) {\n const focusField = () => {\n const searchField =\n this.shadowRoot?.querySelector<OscdOutlinedSearchField>(\n 'oscd-outlined-search-field',\n );\n searchField?.focus();\n if (selectQuery) {\n searchField?.select();\n }\n };\n\n this.updateComplete.then(() => {\n focusField();\n requestAnimationFrame(() => requestAnimationFrame(focusField));\n });\n }\n\n /** Returns the panel to the collapsed rail and clears the search query. */\n private exitSearchMode() {\n this.searchMode = false;\n this.searchValue = '';\n this.focusedTree = null;\n }\n\n private getTree(kind: 'pinned' | 'editors'): OscdTree | null {\n return (\n this.shadowRoot?.querySelector<OscdTree>(`oscd-tree.${kind}-tree`) ?? null\n );\n }\n\n private focusTree(\n kind: 'pinned' | 'editors',\n activeId: string | null,\n ): boolean {\n const tree = this.getTree(kind);\n if (!tree || !activeId) {\n return false;\n }\n tree.activeId = activeId;\n this.focusedTree = kind;\n tree.focus();\n return true;\n }\n\n private startTreeNavigation(direction: 'up' | 'down') {\n const first = direction === 'down';\n const pinnedTree = this.getTree('pinned');\n if (this.searchValue.trim().length === 0 && pinnedTree) {\n const activeId = this.focusTree(\n 'pinned',\n first ? pinnedTree.getFirstNodeId() : pinnedTree.getLastNodeId(),\n );\n if (activeId) {\n return;\n }\n }\n const editorsTree = this.getTree('editors');\n this.focusTree(\n 'editors',\n editorsTree\n ? first\n ? editorsTree.getFirstNodeId()\n : editorsTree.getLastNodeId()\n : null,\n );\n }\n\n private handleTreeActiveChanged(kind: 'pinned' | 'editors') {\n this.focusedTree = kind;\n }\n\n private handleTreeFocus(kind: 'pinned' | 'editors') {\n this.focusedTree = kind;\n }\n\n private handleTreeSelection(\n kind: 'pinned' | 'editors',\n selectedIds: string[],\n ) {\n const tree = this.getTree(kind);\n const selectedId = selectedIds[0];\n const selectedNode = tree?.data.find(node => node.id === selectedId);\n if (tree && selectedNode?.children?.length && selectedId) {\n tree.toggle(selectedId);\n return;\n }\n this.selectEditor(selectedIds);\n }\n\n private handleTreeBoundary(\n kind: 'pinned' | 'editors',\n direction: 'first' | 'last',\n ) {\n if (kind === 'pinned' && direction === 'last') {\n this.focusTree(\n 'editors',\n this.getTree('editors')?.getFirstNodeId() ?? null,\n );\n } else if (\n kind === 'editors' &&\n direction === 'first' &&\n this.searchValue.trim().length === 0\n ) {\n this.focusTree('pinned', this.getTree('pinned')?.getLastNodeId() ?? null);\n }\n }\n\n private activateKeyboardTarget() {\n if (!this.focusedTree) {\n if (\n this.shadowRoot?.activeElement?.localName ===\n 'oscd-outlined-search-field' &&\n flattenPluginEntries(\n filterBySearchTerm(this.editors, this.searchValue, this.locale),\n ).length === 1\n ) {\n this.dispatchEditorSelect(\n flattenPluginEntries(\n filterBySearchTerm(this.editors, this.searchValue, this.locale),\n )[0],\n );\n }\n return;\n }\n }\n\n /** Toggles the persisted expanded/collapsed state via the footer control. */\n private toggleExpanded() {\n if (this.isOpen) {\n this.expanded = false;\n this.exitSearchMode();\n } else {\n this.expanded = true;\n }\n }\n\n private toggleFlyout(anchorId: string) {\n const menu = this.shadowRoot?.querySelector<OscdMenu>(\n `oscd-menu[data-flyout=\"${anchorId}\"]`,\n );\n if (!menu) {\n return;\n }\n if (menu.open) {\n menu.close();\n } else {\n menu.show();\n }\n }\n\n renderPluginItem({\n node,\n level,\n disabled,\n active,\n }: TreeRenderContext<EditorPluginTreeNode>) {\n const label = node.translations?.[this.locale] ?? node.name;\n return html`<oscd-tree-item ?disabled=${disabled} ?active=${active}>\n ${level === 1 && !('kind' in node)\n ? html`<oscd-icon slot=\"start\">${node.icon}</oscd-icon>`\n : nothing}\n <span slot=\"headline\" title=${label}>${label}</span>\n </oscd-tree-item>`;\n }\n\n renderLeafAccessory({ node, id }: TreeRenderContext<EditorPluginTreeNode>) {\n const pinned = this.pinnedPluginIds.includes(id);\n return html`<button\n aria-label=${pinned\n ? msg(str`Unpin ${node.name}`)\n : msg(str`Pin ${node.name}`)}\n aria-pressed=${pinned}\n @click=${() => this.togglePin(id)}\n >\n <oscd-icon>${pinned ? pinnedIcon : unpinnedIcon}</oscd-icon>\n </button>`;\n }\n\n private renderExpanded() {\n return html`\n <div class=\"tree-container\">\n <oscd-outlined-search-field\n placeholder=${msg('Search')}\n clearLabel=${msg('Clear search')}\n .value=${this.searchValue}\n @input=${(event: InputEvent) => {\n this.searchValue = (event.target as OscdOutlinedSearchField).value;\n }}\n ></oscd-outlined-search-field>\n <div class=\"tree-scroll\">\n ${this.searchValue.trim().length === 0\n ? html`<oscd-tree\n .data=${this.pinnedTreeNodes}\n .expandedIds=${this.pinnedExpanded}\n .selectionMode=${'single'}\n .selectedIds=${this.selectedEditor\n ? [this.selectedEditor.tagName]\n : []}\n .isDisabled=${(node: EditorPluginTreeNode) =>\n 'kind' in node && node.kind === 'placeholder'}\n .isSelectable=${(node: EditorPluginTreeNode) =>\n !('kind' in node && node.kind === 'placeholder')}\n class=\"pinned-tree\"\n ?keyboard-active=${this.focusedTree === 'pinned'}\n @focusin=${() => this.handleTreeFocus('pinned')}\n .renderItem=${(\n context: TreeRenderContext<EditorPluginTreeNode>,\n ) => this.renderPluginItem(context)}\n .renderLeafAccessory=${(\n context: TreeRenderContext<EditorPluginTreeNode>,\n ) => this.renderLeafAccessory(context)}\n toggle-position=\"trailing\"\n collapse-icon=\"arrow_drop_up\"\n expand-icon=\"arrow_drop_down\"\n @selected-ids-changed=${(\n event: CustomEvent<{ selectedIds: string[] }>,\n ) =>\n this.handleTreeSelection(\n 'pinned',\n event.detail.selectedIds,\n )}\n @expanded-ids-changed=${(\n event: CustomEvent<{ expandedIds: string[] }>,\n ) => {\n this.pinnedExpanded = event.detail.expandedIds;\n }}\n @active-changed=${() =>\n this.handleTreeActiveChanged('pinned')}\n @navigation-boundary=${(\n event: CustomEvent<{ direction: 'first' | 'last' }>,\n ) =>\n this.handleTreeBoundary('pinned', event.detail.direction)}\n ></oscd-tree>\n <oscd-divider></oscd-divider>`\n : nothing}\n <oscd-tree\n class=\"editors-tree\"\n ?keyboard-active=${this.focusedTree === 'editors'}\n @focusin=${() => this.handleTreeFocus('editors')}\n .data=${this.editorTreeNodes}\n .expandedIds=${this.searchValue.length === 0\n ? this.expandedIds\n : this.editorTreeNodes.map(node => node.id)}\n .selectionMode=${'single'}\n .selectedIds=${this.selectedEditor\n ? [this.selectedEditor.tagName]\n : []}\n .isDisabled=${(node: EditorPluginTreeNode) =>\n 'kind' in node && node.kind === 'placeholder'}\n .isSelectable=${(node: EditorPluginTreeNode) =>\n !('kind' in node && node.kind === 'placeholder')}\n .renderItem=${(context: TreeRenderContext<EditorPluginTreeNode>) =>\n this.renderPluginItem(context)}\n .renderLeafAccessory=${(\n context: TreeRenderContext<EditorPluginTreeNode>,\n ) => this.renderLeafAccessory(context)}\n toggle-position=\"trailing\"\n collapse-icon=\"arrow_drop_down\"\n expand-icon=\"arrow_drop_up\"\n @selected-ids-changed=${(\n event: CustomEvent<{ selectedIds: string[] }>,\n ) => this.handleTreeSelection('editors', event.detail.selectedIds)}\n @expanded-ids-changed=${(\n event: CustomEvent<{ expandedIds: string[] }>,\n ) => {\n this.expandedIds = event.detail.expandedIds;\n }}\n @active-changed=${() => this.handleTreeActiveChanged('editors')}\n @navigation-boundary=${(\n event: CustomEvent<{ direction: 'first' | 'last' }>,\n ) => this.handleTreeBoundary('editors', event.detail.direction)}\n ></oscd-tree>\n </div>\n </div>\n `;\n }\n\n private renderRail() {\n const pinnedPlugins = flattenPluginEntries(\n filterByPinned(this.editors, this.pinnedPluginIds),\n );\n return html`\n <div class=\"rail\">\n <oscd-icon-button\n class=\"rail-item\"\n aria-label=${msg('Search')}\n @click=${() => this.enterSearchMode()}\n >\n <oscd-icon>search</oscd-icon>\n </oscd-icon-button>\n ${this.renderRailGroup(\n { name: msg('Pinned'), icon: 'keep', plugins: pinnedPlugins },\n 'pinned',\n true,\n )}\n <oscd-divider></oscd-divider>\n ${this.editors.map((entry, index) =>\n isPluginGroup(entry)\n ? this.renderRailGroup(entry, `group-${index}`)\n : this.renderRailLeaf(entry as PluginEntry),\n )}\n </div>\n `;\n }\n\n private renderRailGroup(\n group: PluginGroup,\n anchorId: string,\n showEmptyPlaceholder = false,\n ) {\n const label = group.translations?.[this.locale] ?? group.name;\n const active = group.plugins.some(\n plugin => plugin.tagName === this.selectedEditor?.tagName,\n );\n const anchor = `rail-${anchorId}`;\n return html`\n <oscd-icon-button\n id=${anchor}\n class=${classMap({ 'rail-item': true, active })}\n aria-haspopup=\"menu\"\n aria-label=${label}\n @click=${() => this.toggleFlyout(anchorId)}\n >\n <oscd-icon>${group.icon}</oscd-icon>\n </oscd-icon-button>\n <oscd-menu\n class=\"rail-flyout\"\n data-flyout=${anchorId}\n anchor=${anchor}\n anchor-corner=\"start-end\"\n menu-corner=\"start-start\"\n positioning=\"popover\"\n quick\n >\n <div class=\"flyout-header\" role=\"presentation\">${label}</div>\n <oscd-divider class=\"flyout-divider\"></oscd-divider>\n ${group.plugins.length > 0\n ? group.plugins.map(plugin => this.renderFlyoutItem(plugin))\n : showEmptyPlaceholder\n ? renderFlyoutPlaceholder()\n : nothing}\n </oscd-menu>\n `;\n }\n\n private renderRailLeaf(plugin: PluginEntry) {\n const label = plugin.translations?.[this.locale] ?? plugin.name;\n const active = plugin.tagName === this.selectedEditor?.tagName;\n return html`\n <oscd-icon-button\n class=${classMap({ 'rail-item': true, active })}\n aria-label=${label}\n @click=${() => this.dispatchEditorSelect(plugin)}\n >\n <oscd-icon>${plugin.icon}</oscd-icon>\n </oscd-icon-button>\n `;\n }\n\n private renderFlyoutItem(plugin: PluginEntry) {\n const label = plugin.translations?.[this.locale] ?? plugin.name;\n const selected = plugin.tagName === this.selectedEditor?.tagName;\n return html`\n <oscd-menu-item\n .selected=${selected}\n @click=${() => this.dispatchEditorSelect(plugin)}\n >\n <div slot=\"headline\">${label}</div>\n </oscd-menu-item>\n `;\n }\n\n private renderFooter() {\n const open = this.isOpen;\n const label = open ? msg('Collapse sidebar') : msg('Expand sidebar');\n const icon = open ? 'left_panel_close' : 'left_panel_open';\n return html`\n <div class=\"footer\">\n ${open\n ? html`<oscd-list-item\n class=\"toggle-button\"\n type=\"button\"\n aria-label=${label}\n @click=${() => this.toggleExpanded()}\n >\n <oscd-icon slot=\"start\">${icon}</oscd-icon>\n <span slot=\"headline\">${label}</span>\n </oscd-list-item>`\n : html`<oscd-icon-button\n class=\"toggle-button\"\n aria-label=${label}\n @click=${() => this.toggleExpanded()}\n >\n <oscd-icon>${icon}</oscd-icon>\n </oscd-icon-button>`}\n </div>\n `;\n }\n\n render() {\n return html`\n ${this.isOpen ? this.renderExpanded() : this.renderRail()}\n <oscd-divider class=\"footer-divider\"></oscd-divider>\n ${this.renderFooter()}\n `;\n }\n\n static styles = css`\n :host {\n /* Collapsed rail is the default width; the panel widens to its full width\n when persistently expanded OR while in transient search mode. The shell\n grid column follows this intrinsic width (grid-template-columns: auto). */\n width: var(--editor-plugins-panel-collapsed-width);\n height: calc(100% - var(--editor-plugins-panel-padding-top));\n display: grid;\n /* Row 1 (tree-container/rail) is the only scrollable region; the divider\n and footer rows are sized to content so they stay pinned and always\n visible below it, however tall the tree content grows. */\n grid-template-rows: 1fr auto auto;\n min-height: 0;\n padding-top: var(--editor-plugins-panel-padding-top);\n transition: width 0.1s ease-in-out;\n /* Clip transient horizontal overflow while the width animates on\n expand/collapse: the content swaps to its full width before the host\n finishes resizing, and this stops that from forcing horizontal reflow /\n scrollbar churn every animation frame. Steady-state label overrun is\n handled by the tree row ellipsis, not by this. */\n overflow-x: hidden;\n /* The panel paints its own surface color; it must never depend on\n page/body background showing through, or hosts that don't set a\n background image get a blank panel. */\n background-color: var(--editor-plugins-panel-background-color);\n }\n\n /* Material colour scheme for the panel's content. By default the panel's\n background-color (above) is the dark --oscd-primary surface, so its\n content is light (\"white\"/--oscd-base3) on a dark surface. We set the\n *system* colours once here — not each component's final colour — so\n resting text/icons AND every derived hover/pressed state layer resolve\n to the light content colour from one place. (The flyout menus are a\n light surface and reset these back to the shell defaults; see\n .rail-flyout.)\n\n NB: these are set on the content containers rather than :host on\n purpose. A :host declaration would sit on the same element that\n inherits --editor-plugins-panel-item-text-color, which is itself\n derived from --md-sys-color-on-surface; declaring on the containers\n keeps the source token a plain inherited value and so cannot form a\n reference cycle. See \"Layers are read upward\" in THEMING.md. */\n .rail,\n .tree-container,\n .footer {\n --md-sys-color-on-surface: var(--editor-plugins-panel-item-text-color);\n --md-sys-color-on-surface-variant: var(\n --editor-plugins-panel-item-icon-color\n );\n\n --md-sys-color-surface: var(--editor-plugins-panel-background-color);\n }\n\n :host([expanded]),\n :host([search-mode]) {\n width: var(--editor-plugins-panel-width);\n }\n\n /* Base divider styling, overridden by the more specific rail/flyout/footer\n dividers below where the Figma spec calls for different sizing. */\n oscd-divider {\n --md-divider-color: var(--editor-plugins-panel-divider-color);\n /* No margin: .tree-container's 12px gap owns the spacing on both sides. */\n margin-block: 0;\n }\n\n /* --- Expanded panel: search field + scrollable tree --- */\n\n .tree-container {\n margin-inline: 16px;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n oscd-outlined-search-field * {\n --md-icon-button-state-layer-width: 32px;\n --md-icon-button-state-layer-height: 32px;\n --md-icon-button-state-layer-shape: 50%;\n }\n\n oscd-outlined-search-field {\n background-color: color-mix(\n in srgb,\n var(\n --md-outlined-text-field-input-text-color,\n var(--md-sys-color-on-surface, #1d1b20)\n )\n 20%,\n transparent\n );\n border-radius: 5px;\n --md-outlined-text-field-top-space: 6px;\n --md-outlined-text-field-bottom-space: 6px;\n --md-outlined-text-field-leading-space: 8px;\n --md-outlined-text-field-trailing-space: 8px;\n --md-outlined-text-field-with-leading-icon-leading-space: 10px;\n --md-outlined-field-with-trailing-content-trailing-space: 8px;\n --md-outlined-text-field-icon-input-space: 10px;\n --md-icon-button-state-layer-width: 32px;\n --md-icon-button-state-layer-height: 32px;\n --md-icon-button-state-layer-shape: 50%;\n\n --md-outlined-text-field-trailing-icon-size: 32px;\n\n --md-icon-button-icon-size: 24px;\n\n /* keep the outline light in every state */\n --md-outlined-text-field-focus-outline-color: var(\n --editor-plugins-panel-item-text-color\n );\n --md-outlined-text-field-hover-outline-color: var(\n --editor-plugins-panel-item-text-color\n );\n --md-outlined-text-field-outline-color: var(\n --editor-plugins-panel-item-text-color\n );\n /* hide the outline border entirely, in every state */\n --md-outlined-text-field-outline-width: 0px;\n --md-outlined-text-field-hover-outline-width: 0px;\n --md-outlined-text-field-focus-outline-width: 0px;\n\n /* caret follows the light text instead of the primary accent */\n --md-outlined-text-field-caret-color: var(\n --editor-plugins-panel-item-text-color\n );\n --md-outlined-text-field-focus-caret-color: var(\n --editor-plugins-panel-item-text-color\n );\n }\n\n .tree-scroll {\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-height: 0;\n overflow-y: auto;\n\n /* Recolour the scrollbar to sit on the panel's dark-blue surface instead\n of the browser's default light-themed bar. Firefox reads\n scrollbar-color; Chromium/Safari (and Firefox with the layout flag\n off) read the ::-webkit-scrollbar-* pseudo-elements below. */\n scrollbar-color: var(--editor-plugins-panel-divider-color) transparent;\n scrollbar-width: thin;\n }\n\n .tree-scroll::-webkit-scrollbar {\n width: 8px;\n }\n\n .tree-scroll::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .tree-scroll::-webkit-scrollbar-thumb {\n background-color: var(--editor-plugins-panel-divider-color);\n border-radius: 4px;\n }\n\n oscd-tree {\n margin-inline: 0;\n min-height: 0;\n --oscd-tree-row-height: 36px;\n --oscd-tree-item-min-height: 36px;\n --oscd-tree-row-gap: 4px;\n --oscd-tree-row-padding-start: 8px;\n --oscd-tree-row-padding-end: 8px;\n --oscd-tree-indent-step: 36px;\n --oscd-tree-row-shape: 5px;\n --oscd-tree-toggle-icon-size: 28px;\n --oscd-tree-trailing-toggle-gap: 8px;\n /* Pin accessory hidden at rest, revealed on row hover / keyboard focus\n (see Figma side-panel spec); its icon size inherits the 28px toggle. */\n --oscd-tree-accessory-rest-opacity: 0;\n --md-icon-size: var(--editor-plugins-panel-item-icon-size);\n /* oscd-tree-item colours its leading/trailing icon slots explicitly\n (not via inherited 'color'), so — unlike the label — they don't\n automatically pick up the selected-row text colour above. Tying them\n to currentColor makes the icon track whatever colour the row itself\n resolves to (resting on-surface ink, or the active/selected colour),\n matching the label in both states. */\n --oscd-tree-item-leading-icon-color: currentColor;\n --oscd-tree-item-trailing-icon-color: currentColor;\n --oscd-tree-row-selected-color: var(\n --editor-plugins-panel-item-active-bg\n );\n --oscd-tree-row-selected-text-color: var(\n --editor-plugins-panel-item-active-color\n );\n --oscd-tree-row-active-border-width: 0px;\n /* The keyboard-active row highlight (outline + optional text override)\n must stay visible whether that row is merely keyboard-highlighted at\n rest (panel surface bg, on-surface ink text) or also selected\n (--editor-plugins-panel-item-active-bg, active-color text). Using\n currentColor/inherit ties the outline and text to whichever of those\n two colours the row already resolves to, instead of hardcoding the\n selected-row colour (which vanishes against the resting surface). */\n --oscd-tree-row-active-border-color: currentColor;\n --oscd-tree-row-active-text-color: inherit;\n --oscd-tree-row-focus-ring-color: currentColor;\n }\n\n oscd-tree.keyboard-active {\n --oscd-tree-row-active-border-width: 1px;\n }\n\n oscd-tree.pinned-tree {\n --oscd-tree-leaf-toggle-size: 0px;\n --oscd-tree-leaf-toggle-gap: 0px;\n }\n\n /* --- Collapsed icon rail --- */\n\n /* Collapsed icon rail: a flat column of 44px icon buttons (28px glyph + 8px\n padding), inset 16px so the glyphs land at the same x (24px) as both the\n search icon and the tree-item icons in the expanded panel. */\n .rail {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n padding-inline: 16px;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n }\n\n .rail-item {\n --md-icon-button-icon-size: 28px;\n --md-icon-button-state-layer-height: 44px;\n --md-icon-button-state-layer-width: 44px;\n border-radius: 5px;\n }\n\n /* Active group/editor: dark rounded square behind the glyph. */\n .rail-item.active {\n background: var(--editor-plugins-panel-item-active-bg);\n }\n\n .rail oscd-divider {\n /* 44px wide (aligned with the icon column), 12px clearance above and\n below, per the Figma collapsed spec. */\n width: 44px;\n margin-block: 12px;\n --md-divider-color: var(--editor-plugins-panel-divider-color);\n }\n\n /* Flyout menu opened from a collapsed group icon. Figma \"Links container\":\n padding 8px, gap 4px, 1px border, 5px radius, light surface + shadow.\n Unlike the rest of the panel this is a LIGHT surface, so it resets the\n system colours back to the shell defaults (dark content on a light\n surface); everything inside then derives correctly. */\n .rail-flyout {\n --md-sys-color-surface: var(--plugins-menu-container-color);\n --md-sys-color-surface-container: var(--plugins-menu-container-color);\n --md-sys-color-on-surface: var(--plugins-menu-item-label-color);\n --md-sys-color-on-surface-variant: var(\n --plugins-menu-item-leading-icon-color\n );\n --md-menu-container-color: var(--plugins-menu-container-color);\n min-width: 200px;\n }\n\n .flyout-header {\n /* Group name heading: Material label-large, in the secondary blue, per the\n Figma \"Links container\" header. */\n padding: 8px 12px;\n font-family: var(--oscd-text-font, Roboto), sans-serif;\n font-size: 14px;\n font-weight: 500;\n line-height: 20px;\n letter-spacing: 0.1px;\n color: var(--editor-plugins-panel-flyout-header-text-color);\n }\n\n .rail-flyout .flyout-divider {\n /* Separates the group heading from its editor items. */\n --md-divider-color: var(--editor-plugins-panel-divider-color);\n margin-block: 4px;\n width: 80%;\n margin: auto;\n }\n\n .rail-flyout oscd-menu-item {\n width: 100%;\n --md-menu-item-selected-container-color: var(\n --plugins-menu-item-selected-container-color\n );\n --md-menu-item-selected-label-text-color: var(\n --plugins-menu-item-selected-label-color\n );\n }\n\n /* --- Footer: collapse/expand toggle --- */\n\n .footer-divider {\n padding-inline: 16px;\n margin-block: 12px 0;\n }\n\n .footer {\n /* Persistent collapse/expand control, bottom-left in both modes. The 16px\n inline inset matches the tree-container (so the expanded list-item spans\n the same width as the rows) and the rail items; 16px below is the Figma\n bottom margin. */\n display: flex;\n align-items: center;\n justify-content: flex-start;\n padding-inline: 16px;\n padding-block: 0 16px;\n }\n\n /* Expanded: an interactive list item so it reads as \"one more row\" — full\n width with a full-width hover/ripple state layer, left-aligned, no\n container fill at rest. 8px leading space lands the 28px glyph at x24,\n exactly like the search field and tree rows above it. */\n oscd-list-item.toggle-button {\n width: 100%;\n border-radius: 5px;\n --md-list-item-leading-space: 8px;\n --md-list-item-trailing-space: 8px;\n --md-list-item-one-line-container-height: 40px;\n --md-list-item-top-space: 8px;\n --md-list-item-bottom-space: 8px;\n --md-list-item-label-text-size: 16px;\n }\n\n oscd-list-item.toggle-button oscd-icon[slot='start'] {\n /* Every icon in the side panel is 28px (matches the tree icons). */\n --md-icon-size: 28px;\n }\n\n /* Collapsed rail: icon-only toggle, matching the rail items (44px target,\n 28px glyph, glyph lands at x24 like the other rail icons). */\n oscd-icon-button.toggle-button {\n --md-icon-button-icon-size: 28px;\n --md-icon-button-state-layer-height: 44px;\n --md-icon-button-state-layer-width: 44px;\n }\n `;\n}\n"]}
1
+ {"version":3,"file":"editor-plugins-panel.js","sourceRoot":"","sources":["../../src/side-panel/editor-plugins-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements/lit-element.js';\nimport { localized, msg, str } from '@lit/localize';\n\nimport { OscdIconButton } from '@omicronenergy/oscd-ui/iconbutton/OscdIconButton.js';\nimport { OscdIcon } from '@omicronenergy/oscd-ui/icon/OscdIcon.js';\nimport { OscdListItem } from '@omicronenergy/oscd-ui/list/OscdListItem.js';\nimport { OscdMenu } from '@omicronenergy/oscd-ui/menu/OscdMenu.js';\nimport { OscdMenuItem } from '@omicronenergy/oscd-ui/menu/OscdMenuItem.js';\n\nimport { LocaleTag } from '../localization.js';\nimport { PluginGroup, ResolvedPlugin } from '../oscd-shell.js';\nimport {\n OscdTree,\n TreeNode,\n TreeRenderContext,\n} from '@omicronenergy/oscd-ui/tree/OscdTree.js';\nimport {\n filterBySearchTerm,\n filterByPinned,\n isPluginGroup,\n flattenPluginEntries,\n} from '../utils/plugin-utils.js';\nimport { OscdTreeItem } from '@omicronenergy/oscd-ui/tree/OscdTreeItem.js';\nimport { OscdDivider } from '@omicronenergy/oscd-ui/divider/OscdDivider.js';\nimport { localstorage } from '@omicronenergy/oscd-ui/decorators/localstorage.js';\nimport { OscdOutlinedSearchField } from '@omicronenergy/oscd-ui/search-field/OscdOutlinedSearchField.js';\n\ntype PlaceholderTreeNode = {\n kind: 'placeholder';\n name: string;\n translations?: Record<string, string>;\n};\n\ntype EditorPluginTreeNode = (\n | PluginGroup<ResolvedPlugin>\n | ResolvedPlugin\n | PlaceholderTreeNode\n) &\n TreeNode & {\n children?: EditorPluginTreeNode[];\n plugins?: EditorPluginTreeNode[];\n };\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'editor-plugins-panel': EditorPluginsPanel;\n }\n}\n\nconst unpinnedIcon = html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n fill=\"none\"\n>\n <path\n d=\"M16.391 14.4188L16.8773 16.2406L16.2096 17.3947L13.3244 15.7253L11.3211 19.1876L10.4102 19.4307L10.1671 18.5198L12.1703 15.0576L9.28512 13.3882L9.95287 12.2341L11.7747 11.7478L14.1118 7.70854L13.5348 7.37467L14.2025 6.22059L19.9729 9.55934L19.3052 10.7134L18.7281 10.3795L16.391 14.4188ZM11.5974 13.1857L15.2328 15.2891L14.9531 14.2415L17.574 9.71179L15.2659 8.37629L12.645 12.906L11.5974 13.1857Z\"\n fill=\"currentColor\"\n />\n</svg>`;\n\nconst pinnedIcon = html`<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n fill=\"none\"\n>\n <path\n d=\"M16.4379 14.5274L16.9273 16.3484L16.2615 17.5036L13.3735 15.8391L11.3761 19.3047L10.4656 19.5494L10.2209 18.6389L12.2183 15.1733L9.33034 13.5088L9.99614 12.3536L11.8171 11.8642L14.1475 7.821L13.5699 7.4881L14.2357 6.3329L20.0117 9.66194L19.3459 10.8171L18.7683 10.4842L16.4379 14.5274Z\"\n fill=\"currentColor\"\n />\n</svg>`;\n\nexport function buildTreeNodes(\n plugins: (ResolvedPlugin | PluginGroup<ResolvedPlugin>)[],\n): EditorPluginTreeNode[] {\n function pluginEntryToTreeNode(\n pluginEntry: ResolvedPlugin,\n ): EditorPluginTreeNode {\n return {\n ...pluginEntry,\n id: pluginEntry.tagName,\n children: [], //explicitly set children to an empty array for leaf nodes\n };\n }\n\n return plugins.map((editor, index) => {\n const isGroup = isPluginGroup(editor);\n if (isGroup) {\n const children = (editor as PluginGroup<ResolvedPlugin>).plugins.map(\n pluginEntryToTreeNode,\n );\n return {\n ...editor,\n id: `group:${index}:${editor.name}`,\n children,\n };\n }\n return pluginEntryToTreeNode(editor as ResolvedPlugin);\n });\n}\n\nfunction renderFlyoutPlaceholder() {\n return html`<oscd-menu-item disabled>\n <div slot=\"headline\">${msg('Items you pin will appear here')}</div>\n </oscd-menu-item>`;\n}\n\n@localized()\nexport class EditorPluginsPanel extends ScopedElementsMixin(LitElement) {\n static scopedElements = {\n 'oscd-icon-button': OscdIconButton,\n 'oscd-icon': OscdIcon,\n 'oscd-list-item': OscdListItem,\n 'oscd-tree': OscdTree,\n 'oscd-tree-item': OscdTreeItem,\n 'oscd-outlined-search-field': OscdOutlinedSearchField,\n 'oscd-divider': OscdDivider,\n 'oscd-menu': OscdMenu,\n 'oscd-menu-item': OscdMenuItem,\n };\n\n id = 'editor-plugins-panel';\n\n @property({ type: Array })\n editors: (ResolvedPlugin | PluginGroup<ResolvedPlugin>)[] = [];\n\n @property({ type: Number })\n selectedEditor?: ResolvedPlugin;\n\n @property({ type: String })\n locale!: LocaleTag;\n\n @localstorage({ default: true })\n @property({ type: Boolean, reflect: true })\n expanded!: boolean;\n\n /**\n * Transient \"search mode\": the collapsed rail's search icon opens the full\n * panel to let the user search, WITHOUT persisting the panel as expanded.\n * It is reflected purely so `:host([search-mode])` can drive the open width.\n * Exited on editor selection or Escape (see `exitSearchMode`).\n */\n @property({ type: Boolean, reflect: true, attribute: 'search-mode' })\n searchMode = false;\n\n /** True when the panel is visually open (persisted expanded OR transient search). */\n get isOpen(): boolean {\n return this.expanded || this.searchMode;\n }\n\n editorTreeNodes: EditorPluginTreeNode[] = [];\n\n pinnedTreeNodes: EditorPluginTreeNode[] = [\n {\n id: 'pinned',\n name: 'Pinned',\n icon: 'keep',\n plugins: [],\n children: [],\n },\n ];\n\n @state()\n searchValue = '';\n\n @state()\n focusedTree: 'pinned' | 'editors' | null = null;\n\n @localstorage({ default: [] })\n @state()\n expandedIds!: string[];\n\n @localstorage({ default: [] })\n @state()\n pinnedPluginIds!: string[];\n\n @localstorage({ default: [] })\n @state()\n pinnedExpanded!: string[];\n\n willUpdate(changedProperties: Map<string, unknown>) {\n if (\n changedProperties.has('editors') ||\n changedProperties.has('searchValue') ||\n changedProperties.has('locale')\n ) {\n const searchResults = filterBySearchTerm(\n this.editors,\n this.searchValue,\n this.locale,\n );\n this.editorTreeNodes = buildTreeNodes(searchResults);\n }\n\n if (\n changedProperties.has('editors') ||\n changedProperties.has('pinnedPluginIds') ||\n changedProperties.has('locale')\n ) {\n const pinnedPlugins = filterByPinned(this.editors, this.pinnedPluginIds);\n const pinnedChildren: EditorPluginTreeNode[] = pinnedPlugins.length\n ? buildTreeNodes(pinnedPlugins)\n : [\n {\n kind: 'placeholder',\n name: msg('Items you pin will appear here'),\n id: 'pinned-placeholder',\n children: [],\n },\n ];\n this.pinnedTreeNodes = [\n {\n id: 'pinned',\n name: msg('Pinned'),\n icon: 'keep',\n plugins: [],\n children: pinnedChildren,\n },\n ];\n }\n }\n\n togglePin(id: string) {\n if (this.pinnedPluginIds.includes(id)) {\n this.pinnedPluginIds = this.pinnedPluginIds.filter(\n pinnedId => pinnedId !== id,\n );\n } else {\n this.pinnedPluginIds = [...this.pinnedPluginIds, id];\n this.pinnedExpanded = ['pinned']; // Expand the pinned section when a new plugin is pinned\n }\n }\n\n selectEditor(selectedIds: string[]) {\n const [selectedId] = selectedIds;\n if (!selectedId) {\n return;\n }\n const editor = flattenPluginEntries(this.editors).find(\n editor => editor.tagName === selectedId,\n );\n if (!editor) {\n return;\n }\n this.dispatchEditorSelect(editor);\n }\n\n /**\n * Dispatches the `editor-select` event and leaves transient search mode, if\n * active. Used by both the expanded trees and the collapsed rail flyouts.\n */\n private dispatchEditorSelect(editor?: ResolvedPlugin) {\n this.dispatchEvent(\n new CustomEvent('editor-select', {\n detail: { editor },\n bubbles: true,\n composed: true,\n }),\n );\n if (this.searchMode) {\n this.exitSearchMode();\n }\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener('keydown', this.handleKeydown);\n }\n\n disconnectedCallback() {\n this.removeEventListener('keydown', this.handleKeydown);\n super.disconnectedCallback();\n }\n\n private handleKeydown = (event: KeyboardEvent) => {\n const fromSearchField =\n (event.currentTarget as Element | null)?.localName ===\n 'oscd-outlined-search-field' ||\n event\n .composedPath()\n .some(\n target =>\n (target as Element).localName === 'oscd-outlined-search-field',\n );\n if (event.key === 'Escape' && this.searchMode) {\n event.stopPropagation();\n this.exitSearchMode();\n return;\n }\n\n if (\n fromSearchField &&\n (event.key === 'ArrowDown' || event.key === 'ArrowUp')\n ) {\n event.preventDefault();\n event.stopPropagation();\n this.startTreeNavigation(event.key === 'ArrowDown' ? 'down' : 'up');\n return;\n }\n\n if (fromSearchField && event.key === 'Enter') {\n event.preventDefault();\n event.stopPropagation();\n this.activateKeyboardTarget();\n }\n };\n\n /** Opens the panel transiently for searching (does not persist `expanded`). */\n private enterSearchMode() {\n this.searchMode = true;\n this.focusSearch(true);\n }\n\n /** Focuses the search field, optionally selecting its current query. */\n focusSearch(selectQuery = false) {\n const focusField = () => {\n const searchField =\n this.shadowRoot?.querySelector<OscdOutlinedSearchField>(\n 'oscd-outlined-search-field',\n );\n searchField?.focus();\n if (selectQuery) {\n searchField?.select();\n }\n };\n\n this.updateComplete.then(() => {\n focusField();\n requestAnimationFrame(() => requestAnimationFrame(focusField));\n });\n }\n\n /** Returns the panel to the collapsed rail and clears the search query. */\n private exitSearchMode() {\n this.searchMode = false;\n this.searchValue = '';\n this.focusedTree = null;\n }\n\n private getTree(kind: 'pinned' | 'editors'): OscdTree | null {\n return (\n this.shadowRoot?.querySelector<OscdTree>(`oscd-tree.${kind}-tree`) ?? null\n );\n }\n\n private focusTree(\n kind: 'pinned' | 'editors',\n activeId: string | null,\n ): boolean {\n const tree = this.getTree(kind);\n if (!tree || !activeId) {\n return false;\n }\n tree.activeId = activeId;\n this.focusedTree = kind;\n tree.focus();\n return true;\n }\n\n private startTreeNavigation(direction: 'up' | 'down') {\n const first = direction === 'down';\n const pinnedTree = this.getTree('pinned');\n if (this.searchValue.trim().length === 0 && pinnedTree) {\n const activeId = this.focusTree(\n 'pinned',\n first ? pinnedTree.getFirstNodeId() : pinnedTree.getLastNodeId(),\n );\n if (activeId) {\n return;\n }\n }\n const editorsTree = this.getTree('editors');\n this.focusTree(\n 'editors',\n editorsTree\n ? first\n ? editorsTree.getFirstNodeId()\n : editorsTree.getLastNodeId()\n : null,\n );\n }\n\n private handleTreeActiveChanged(kind: 'pinned' | 'editors') {\n this.focusedTree = kind;\n }\n\n private handleTreeFocus(kind: 'pinned' | 'editors') {\n this.focusedTree = kind;\n }\n\n private handleTreeSelection(\n kind: 'pinned' | 'editors',\n selectedIds: string[],\n ) {\n const tree = this.getTree(kind);\n const selectedId = selectedIds[0];\n const selectedNode = tree?.data.find(node => node.id === selectedId);\n if (tree && selectedNode?.children?.length && selectedId) {\n tree.toggle(selectedId);\n return;\n }\n this.selectEditor(selectedIds);\n }\n\n private handleTreeBoundary(\n kind: 'pinned' | 'editors',\n direction: 'first' | 'last',\n ) {\n if (kind === 'pinned' && direction === 'last') {\n this.focusTree(\n 'editors',\n this.getTree('editors')?.getFirstNodeId() ?? null,\n );\n } else if (\n kind === 'editors' &&\n direction === 'first' &&\n this.searchValue.trim().length === 0\n ) {\n this.focusTree('pinned', this.getTree('pinned')?.getLastNodeId() ?? null);\n }\n }\n\n private activateKeyboardTarget() {\n if (!this.focusedTree) {\n if (\n this.shadowRoot?.activeElement?.localName ===\n 'oscd-outlined-search-field' &&\n flattenPluginEntries(\n filterBySearchTerm(this.editors, this.searchValue, this.locale),\n ).length === 1\n ) {\n this.dispatchEditorSelect(\n flattenPluginEntries(\n filterBySearchTerm(this.editors, this.searchValue, this.locale),\n )[0],\n );\n }\n return;\n }\n }\n\n /** Toggles the persisted expanded/collapsed state via the footer control. */\n private toggleExpanded() {\n if (this.isOpen) {\n this.expanded = false;\n this.exitSearchMode();\n } else {\n this.expanded = true;\n }\n }\n\n private toggleFlyout(anchorId: string) {\n const menu = this.shadowRoot?.querySelector<OscdMenu>(\n `oscd-menu[data-flyout=\"${anchorId}\"]`,\n );\n if (!menu) {\n return;\n }\n if (menu.open) {\n menu.close();\n } else {\n menu.show();\n }\n }\n\n renderPluginItem({\n node,\n level,\n disabled,\n active,\n }: TreeRenderContext<EditorPluginTreeNode>) {\n const label = node.translations?.[this.locale] ?? node.name;\n return html`<oscd-tree-item ?disabled=${disabled} ?active=${active}>\n ${level === 1 && !('kind' in node)\n ? html`<oscd-icon slot=\"start\">${node.icon}</oscd-icon>`\n : nothing}\n <span slot=\"headline\" title=${label}>${label}</span>\n </oscd-tree-item>`;\n }\n\n renderLeafAccessory({ node, id }: TreeRenderContext<EditorPluginTreeNode>) {\n const pinned = this.pinnedPluginIds.includes(id);\n return html`<button\n aria-label=${pinned\n ? msg(str`Unpin ${node.name}`)\n : msg(str`Pin ${node.name}`)}\n aria-pressed=${pinned}\n @click=${() => this.togglePin(id)}\n >\n <oscd-icon>${pinned ? pinnedIcon : unpinnedIcon}</oscd-icon>\n </button>`;\n }\n\n private renderExpanded() {\n return html`\n <div class=\"tree-container\">\n <oscd-outlined-search-field\n placeholder=${msg('Search')}\n clearLabel=${msg('Clear search')}\n .value=${this.searchValue}\n @input=${(event: InputEvent) => {\n this.searchValue = (event.target as OscdOutlinedSearchField).value;\n }}\n ></oscd-outlined-search-field>\n <div class=\"tree-scroll\">\n ${this.searchValue.trim().length === 0\n ? html`<oscd-tree\n .data=${this.pinnedTreeNodes}\n .expandedIds=${this.pinnedExpanded}\n .selectionMode=${'single'}\n .selectedIds=${this.selectedEditor\n ? [this.selectedEditor.tagName]\n : []}\n .isDisabled=${(node: EditorPluginTreeNode) =>\n 'kind' in node && node.kind === 'placeholder'}\n .isSelectable=${(node: EditorPluginTreeNode) =>\n !('kind' in node && node.kind === 'placeholder')}\n class=\"pinned-tree\"\n ?keyboard-active=${this.focusedTree === 'pinned'}\n @focusin=${() => this.handleTreeFocus('pinned')}\n .renderItem=${(\n context: TreeRenderContext<EditorPluginTreeNode>,\n ) => this.renderPluginItem(context)}\n .renderLeafAccessory=${(\n context: TreeRenderContext<EditorPluginTreeNode>,\n ) => this.renderLeafAccessory(context)}\n toggle-position=\"trailing\"\n collapse-icon=\"arrow_drop_up\"\n expand-icon=\"arrow_drop_down\"\n @selected-ids-changed=${(\n event: CustomEvent<{ selectedIds: string[] }>,\n ) =>\n this.handleTreeSelection(\n 'pinned',\n event.detail.selectedIds,\n )}\n @expanded-ids-changed=${(\n event: CustomEvent<{ expandedIds: string[] }>,\n ) => {\n this.pinnedExpanded = event.detail.expandedIds;\n }}\n @active-changed=${() =>\n this.handleTreeActiveChanged('pinned')}\n @navigation-boundary=${(\n event: CustomEvent<{ direction: 'first' | 'last' }>,\n ) =>\n this.handleTreeBoundary('pinned', event.detail.direction)}\n ></oscd-tree>\n <oscd-divider></oscd-divider>`\n : nothing}\n <oscd-tree\n class=\"editors-tree\"\n ?keyboard-active=${this.focusedTree === 'editors'}\n @focusin=${() => this.handleTreeFocus('editors')}\n .data=${this.editorTreeNodes}\n .expandedIds=${this.searchValue.length === 0\n ? this.expandedIds\n : this.editorTreeNodes.map(node => node.id)}\n .selectionMode=${'single'}\n .selectedIds=${this.selectedEditor\n ? [this.selectedEditor.tagName]\n : []}\n .isDisabled=${(node: EditorPluginTreeNode) =>\n 'kind' in node && node.kind === 'placeholder'}\n .isSelectable=${(node: EditorPluginTreeNode) =>\n !('kind' in node && node.kind === 'placeholder')}\n .renderItem=${(context: TreeRenderContext<EditorPluginTreeNode>) =>\n this.renderPluginItem(context)}\n .renderLeafAccessory=${(\n context: TreeRenderContext<EditorPluginTreeNode>,\n ) => this.renderLeafAccessory(context)}\n toggle-position=\"trailing\"\n collapse-icon=\"arrow_drop_down\"\n expand-icon=\"arrow_drop_up\"\n @selected-ids-changed=${(\n event: CustomEvent<{ selectedIds: string[] }>,\n ) => this.handleTreeSelection('editors', event.detail.selectedIds)}\n @expanded-ids-changed=${(\n event: CustomEvent<{ expandedIds: string[] }>,\n ) => {\n this.expandedIds = event.detail.expandedIds;\n }}\n @active-changed=${() => this.handleTreeActiveChanged('editors')}\n @navigation-boundary=${(\n event: CustomEvent<{ direction: 'first' | 'last' }>,\n ) => this.handleTreeBoundary('editors', event.detail.direction)}\n ></oscd-tree>\n </div>\n </div>\n `;\n }\n\n private renderRail() {\n const pinnedPlugins = flattenPluginEntries(\n filterByPinned(this.editors, this.pinnedPluginIds),\n );\n return html`\n <div class=\"rail\">\n <oscd-icon-button\n class=\"rail-item\"\n aria-label=${msg('Search')}\n @click=${() => this.enterSearchMode()}\n >\n <oscd-icon>search</oscd-icon>\n </oscd-icon-button>\n ${this.renderRailGroup(\n { name: msg('Pinned'), icon: 'keep', plugins: pinnedPlugins },\n 'pinned',\n true,\n )}\n <oscd-divider></oscd-divider>\n ${this.editors.map((entry, index) =>\n isPluginGroup(entry)\n ? this.renderRailGroup(entry, `group-${index}`)\n : this.renderRailLeaf(entry as ResolvedPlugin),\n )}\n </div>\n `;\n }\n\n private renderRailGroup(\n group: PluginGroup<ResolvedPlugin>,\n anchorId: string,\n showEmptyPlaceholder = false,\n ) {\n const label = group.translations?.[this.locale] ?? group.name;\n const active = group.plugins.some(\n plugin => plugin.tagName === this.selectedEditor?.tagName,\n );\n const anchor = `rail-${anchorId}`;\n return html`\n <oscd-icon-button\n id=${anchor}\n class=${classMap({ 'rail-item': true, active })}\n aria-haspopup=\"menu\"\n aria-label=${label}\n @click=${() => this.toggleFlyout(anchorId)}\n >\n <oscd-icon>${group.icon}</oscd-icon>\n </oscd-icon-button>\n <oscd-menu\n class=\"rail-flyout\"\n data-flyout=${anchorId}\n anchor=${anchor}\n anchor-corner=\"start-end\"\n menu-corner=\"start-start\"\n positioning=\"popover\"\n quick\n >\n <div class=\"flyout-header\" role=\"presentation\">${label}</div>\n <oscd-divider class=\"flyout-divider\"></oscd-divider>\n ${group.plugins.length > 0\n ? group.plugins.map(plugin => this.renderFlyoutItem(plugin))\n : showEmptyPlaceholder\n ? renderFlyoutPlaceholder()\n : nothing}\n </oscd-menu>\n `;\n }\n\n private renderRailLeaf(plugin: ResolvedPlugin) {\n const label = plugin.translations?.[this.locale] ?? plugin.name;\n const active = plugin.tagName === this.selectedEditor?.tagName;\n return html`\n <oscd-icon-button\n class=${classMap({ 'rail-item': true, active })}\n aria-label=${label}\n @click=${() => this.dispatchEditorSelect(plugin)}\n >\n <oscd-icon>${plugin.icon}</oscd-icon>\n </oscd-icon-button>\n `;\n }\n\n private renderFlyoutItem(plugin: ResolvedPlugin) {\n const label = plugin.translations?.[this.locale] ?? plugin.name;\n const selected = plugin.tagName === this.selectedEditor?.tagName;\n return html`\n <oscd-menu-item\n .selected=${selected}\n @click=${() => this.dispatchEditorSelect(plugin)}\n >\n <div slot=\"headline\">${label}</div>\n </oscd-menu-item>\n `;\n }\n\n private renderFooter() {\n const open = this.isOpen;\n const label = open ? msg('Collapse sidebar') : msg('Expand sidebar');\n const icon = open ? 'left_panel_close' : 'left_panel_open';\n return html`\n <div class=\"footer\">\n ${open\n ? html`<oscd-list-item\n class=\"toggle-button\"\n type=\"button\"\n aria-label=${label}\n @click=${() => this.toggleExpanded()}\n >\n <oscd-icon slot=\"start\">${icon}</oscd-icon>\n <span slot=\"headline\">${label}</span>\n </oscd-list-item>`\n : html`<oscd-icon-button\n class=\"toggle-button\"\n aria-label=${label}\n @click=${() => this.toggleExpanded()}\n >\n <oscd-icon>${icon}</oscd-icon>\n </oscd-icon-button>`}\n </div>\n `;\n }\n\n render() {\n return html`\n ${this.isOpen ? this.renderExpanded() : this.renderRail()}\n <oscd-divider class=\"footer-divider\"></oscd-divider>\n ${this.renderFooter()}\n `;\n }\n\n static styles = css`\n :host {\n /* Collapsed rail is the default width; the panel widens to its full width\n when persistently expanded OR while in transient search mode. The shell\n grid column follows this intrinsic width (grid-template-columns: auto). */\n width: var(--editor-plugins-panel-collapsed-width);\n height: calc(100% - var(--editor-plugins-panel-padding-top));\n display: grid;\n /* Row 1 (tree-container/rail) is the only scrollable region; the divider\n and footer rows are sized to content so they stay pinned and always\n visible below it, however tall the tree content grows. */\n grid-template-rows: 1fr auto auto;\n min-height: 0;\n padding-top: var(--editor-plugins-panel-padding-top);\n transition: width 0.1s ease-in-out;\n /* Clip transient horizontal overflow while the width animates on\n expand/collapse: the content swaps to its full width before the host\n finishes resizing, and this stops that from forcing horizontal reflow /\n scrollbar churn every animation frame. Steady-state label overrun is\n handled by the tree row ellipsis, not by this. */\n overflow-x: hidden;\n /* The panel paints its own surface color; it must never depend on\n page/body background showing through, or hosts that don't set a\n background image get a blank panel. */\n background-color: var(--editor-plugins-panel-background-color);\n }\n\n /* Material colour scheme for the panel's content. By default the panel's\n background-color (above) is the dark --oscd-primary surface, so its\n content is light (\"white\"/--oscd-base3) on a dark surface. We set the\n *system* colours once here — not each component's final colour — so\n resting text/icons AND every derived hover/pressed state layer resolve\n to the light content colour from one place. (The flyout menus are a\n light surface and reset these back to the shell defaults; see\n .rail-flyout.)\n\n NB: these are set on the content containers rather than :host on\n purpose. A :host declaration would sit on the same element that\n inherits --editor-plugins-panel-item-text-color, which is itself\n derived from --md-sys-color-on-surface; declaring on the containers\n keeps the source token a plain inherited value and so cannot form a\n reference cycle. See \"Layers are read upward\" in THEMING.md. */\n .rail,\n .tree-container,\n .footer {\n --md-sys-color-on-surface: var(--editor-plugins-panel-item-text-color);\n --md-sys-color-on-surface-variant: var(\n --editor-plugins-panel-item-icon-color\n );\n\n --md-sys-color-surface: var(--editor-plugins-panel-background-color);\n }\n\n :host([expanded]),\n :host([search-mode]) {\n width: var(--editor-plugins-panel-width);\n }\n\n /* Base divider styling, overridden by the more specific rail/flyout/footer\n dividers below where the Figma spec calls for different sizing. */\n oscd-divider {\n --md-divider-color: var(--editor-plugins-panel-divider-color);\n /* No margin: .tree-container's 12px gap owns the spacing on both sides. */\n margin-block: 0;\n }\n\n /* --- Expanded panel: search field + scrollable tree --- */\n\n .tree-container {\n margin-inline: 16px;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n oscd-outlined-search-field * {\n --md-icon-button-state-layer-width: 32px;\n --md-icon-button-state-layer-height: 32px;\n --md-icon-button-state-layer-shape: 50%;\n }\n\n oscd-outlined-search-field {\n background-color: color-mix(\n in srgb,\n var(\n --md-outlined-text-field-input-text-color,\n var(--md-sys-color-on-surface, #1d1b20)\n )\n 20%,\n transparent\n );\n border-radius: 5px;\n --md-outlined-text-field-top-space: 6px;\n --md-outlined-text-field-bottom-space: 6px;\n --md-outlined-text-field-leading-space: 8px;\n --md-outlined-text-field-trailing-space: 8px;\n --md-outlined-text-field-with-leading-icon-leading-space: 10px;\n --md-outlined-field-with-trailing-content-trailing-space: 8px;\n --md-outlined-text-field-icon-input-space: 10px;\n --md-icon-button-state-layer-width: 32px;\n --md-icon-button-state-layer-height: 32px;\n --md-icon-button-state-layer-shape: 50%;\n\n --md-outlined-text-field-trailing-icon-size: 32px;\n\n --md-icon-button-icon-size: 24px;\n\n /* keep the outline light in every state */\n --md-outlined-text-field-focus-outline-color: var(\n --editor-plugins-panel-item-text-color\n );\n --md-outlined-text-field-hover-outline-color: var(\n --editor-plugins-panel-item-text-color\n );\n --md-outlined-text-field-outline-color: var(\n --editor-plugins-panel-item-text-color\n );\n /* hide the outline border entirely, in every state */\n --md-outlined-text-field-outline-width: 0px;\n --md-outlined-text-field-hover-outline-width: 0px;\n --md-outlined-text-field-focus-outline-width: 0px;\n\n /* caret follows the light text instead of the primary accent */\n --md-outlined-text-field-caret-color: var(\n --editor-plugins-panel-item-text-color\n );\n --md-outlined-text-field-focus-caret-color: var(\n --editor-plugins-panel-item-text-color\n );\n }\n\n .tree-scroll {\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-height: 0;\n overflow-y: auto;\n\n /* Recolour the scrollbar to sit on the panel's dark-blue surface instead\n of the browser's default light-themed bar. Firefox reads\n scrollbar-color; Chromium/Safari (and Firefox with the layout flag\n off) read the ::-webkit-scrollbar-* pseudo-elements below. */\n scrollbar-color: var(--editor-plugins-panel-divider-color) transparent;\n scrollbar-width: thin;\n }\n\n .tree-scroll::-webkit-scrollbar {\n width: 8px;\n }\n\n .tree-scroll::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .tree-scroll::-webkit-scrollbar-thumb {\n background-color: var(--editor-plugins-panel-divider-color);\n border-radius: 4px;\n }\n\n oscd-tree {\n margin-inline: 0;\n min-height: 0;\n /* .tree-scroll is the sole flex item allowed to shrink/scroll; without\n this, a too-short container shrinks each tree's box below its\n rendered content instead of letting the scroll container overflow,\n and the (unclipped) shadow-DOM rows bleed past the shrunk box into\n whichever tree follows. */\n flex-shrink: 0;\n --oscd-tree-row-height: 36px;\n --oscd-tree-item-min-height: 36px;\n --oscd-tree-row-gap: 4px;\n --oscd-tree-row-padding-start: 8px;\n --oscd-tree-row-padding-end: 8px;\n --oscd-tree-indent-step: 36px;\n --oscd-tree-row-shape: 5px;\n --oscd-tree-toggle-icon-size: 28px;\n --oscd-tree-trailing-toggle-gap: 8px;\n /* Pin accessory hidden at rest, revealed on row hover / keyboard focus\n (see Figma side-panel spec); its icon size inherits the 28px toggle. */\n --oscd-tree-accessory-rest-opacity: 0;\n --md-icon-size: var(--editor-plugins-panel-item-icon-size);\n /* oscd-tree-item colours its leading/trailing icon slots explicitly\n (not via inherited 'color'), so — unlike the label — they don't\n automatically pick up the selected-row text colour above. Tying them\n to currentColor makes the icon track whatever colour the row itself\n resolves to (resting on-surface ink, or the active/selected colour),\n matching the label in both states. */\n --oscd-tree-item-leading-icon-color: currentColor;\n --oscd-tree-item-trailing-icon-color: currentColor;\n --oscd-tree-row-selected-color: var(\n --editor-plugins-panel-item-active-bg\n );\n --oscd-tree-row-selected-text-color: var(\n --editor-plugins-panel-item-active-color\n );\n --oscd-tree-row-active-border-width: 0px;\n /* The keyboard-active row highlight (outline + optional text override)\n must stay visible whether that row is merely keyboard-highlighted at\n rest (panel surface bg, on-surface ink text) or also selected\n (--editor-plugins-panel-item-active-bg, active-color text). Using\n currentColor/inherit ties the outline and text to whichever of those\n two colours the row already resolves to, instead of hardcoding the\n selected-row colour (which vanishes against the resting surface). */\n --oscd-tree-row-active-border-color: currentColor;\n --oscd-tree-row-active-text-color: inherit;\n --oscd-tree-row-focus-ring-color: currentColor;\n }\n\n oscd-tree.keyboard-active {\n --oscd-tree-row-active-border-width: 1px;\n }\n\n oscd-tree.pinned-tree {\n --oscd-tree-leaf-toggle-size: 0px;\n --oscd-tree-leaf-toggle-gap: 0px;\n }\n\n /* --- Collapsed icon rail --- */\n\n /* Collapsed icon rail: a flat column of 44px icon buttons (28px glyph + 8px\n padding), inset 16px so the glyphs land at the same x (24px) as both the\n search icon and the tree-item icons in the expanded panel. */\n .rail {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n padding-inline: 16px;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n }\n\n .rail-item {\n --md-icon-button-icon-size: 28px;\n --md-icon-button-state-layer-height: 44px;\n --md-icon-button-state-layer-width: 44px;\n border-radius: 5px;\n }\n\n /* Active group/editor: dark rounded square behind the glyph. */\n .rail-item.active {\n background: var(--editor-plugins-panel-item-active-bg);\n }\n\n .rail oscd-divider {\n /* 44px wide (aligned with the icon column), 12px clearance above and\n below, per the Figma collapsed spec. */\n width: 44px;\n margin-block: 12px;\n --md-divider-color: var(--editor-plugins-panel-divider-color);\n }\n\n /* Flyout menu opened from a collapsed group icon. Figma \"Links container\":\n padding 8px, gap 4px, 1px border, 5px radius, light surface + shadow.\n Unlike the rest of the panel this is a LIGHT surface, so it resets the\n system colours back to the shell defaults (dark content on a light\n surface); everything inside then derives correctly. */\n .rail-flyout {\n --md-sys-color-surface: var(--plugins-menu-container-color);\n --md-sys-color-surface-container: var(--plugins-menu-container-color);\n --md-sys-color-on-surface: var(--plugins-menu-item-label-color);\n --md-sys-color-on-surface-variant: var(\n --plugins-menu-item-leading-icon-color\n );\n --md-menu-container-color: var(--plugins-menu-container-color);\n min-width: 200px;\n }\n\n .flyout-header {\n /* Group name heading: Material label-large, in the secondary blue, per the\n Figma \"Links container\" header. */\n padding: 8px 12px;\n font-family: var(--oscd-text-font, Roboto), sans-serif;\n font-size: 14px;\n font-weight: 500;\n line-height: 20px;\n letter-spacing: 0.1px;\n color: var(--editor-plugins-panel-flyout-header-text-color);\n }\n\n .rail-flyout .flyout-divider {\n /* Separates the group heading from its editor items. */\n --md-divider-color: var(--editor-plugins-panel-divider-color);\n margin-block: 4px;\n width: 80%;\n margin: auto;\n }\n\n .rail-flyout oscd-menu-item {\n width: 100%;\n --md-menu-item-selected-container-color: var(\n --plugins-menu-item-selected-container-color\n );\n --md-menu-item-selected-label-text-color: var(\n --plugins-menu-item-selected-label-color\n );\n }\n\n /* --- Footer: collapse/expand toggle --- */\n\n .footer-divider {\n padding-inline: 16px;\n margin-block: 12px 0;\n }\n\n .footer {\n /* Persistent collapse/expand control, bottom-left in both modes. The 16px\n inline inset matches the tree-container (so the expanded list-item spans\n the same width as the rows) and the rail items; 16px below is the Figma\n bottom margin. */\n display: flex;\n align-items: center;\n justify-content: flex-start;\n padding-inline: 16px;\n padding-block: 0 16px;\n }\n\n /* Expanded: an interactive list item so it reads as \"one more row\" — full\n width with a full-width hover/ripple state layer, left-aligned, no\n container fill at rest. 8px leading space lands the 28px glyph at x24,\n exactly like the search field and tree rows above it. */\n oscd-list-item.toggle-button {\n width: 100%;\n border-radius: 5px;\n --md-list-item-leading-space: 8px;\n --md-list-item-trailing-space: 8px;\n --md-list-item-one-line-container-height: 40px;\n --md-list-item-top-space: 8px;\n --md-list-item-bottom-space: 8px;\n --md-list-item-label-text-size: 16px;\n }\n\n oscd-list-item.toggle-button oscd-icon[slot='start'] {\n /* Every icon in the side panel is 28px (matches the tree icons). */\n --md-icon-size: 28px;\n }\n\n /* Collapsed rail: icon-only toggle, matching the rail items (44px target,\n 28px glyph, glyph lands at x24 like the other rail icons). */\n oscd-icon-button.toggle-button {\n --md-icon-button-icon-size: 28px;\n --md-icon-button-state-layer-height: 44px;\n --md-icon-button-state-layer-width: 44px;\n }\n `;\n}\n"]}
@@ -6,7 +6,7 @@ import { TestMenuPlugin1 } from '../utils/testing/test-plugins.js';
6
6
  import { OscdOutlinedSearchField } from '@omicronenergy/oscd-ui/search-field/OscdOutlinedSearchField.js';
7
7
  import sinon from 'sinon';
8
8
  // A grouped editor fixture, used to exercise the collapsed rail's group
9
- // flyout (rendered only when `editors` contains a `PluginGroup`).
9
+ // flyout (rendered only when `editors` contains a `PluginGroup<ResolvedPlugin>`).
10
10
  const groupedEditorPlugins = [
11
11
  {
12
12
  name: 'Grouped Editors',
@@ -301,7 +301,8 @@ describe('editor-plugins-panel', () => {
301
301
  expect(editorPluginsPanel.focusedTree).to.equal('editors');
302
302
  });
303
303
  it('pins and unpins an editor, persisting the ids to localStorage', async () => {
304
- const tagName = oscdShell.plugins.editor[0].tagName;
304
+ const tagName = oscdShell._resolvedPlugins.editor[0]
305
+ .tagName;
305
306
  editorPluginsPanel.togglePin(tagName);
306
307
  await editorPluginsPanel.updateComplete;
307
308
  expect(editorPluginsPanel.pinnedPluginIds).to.include(tagName);
@@ -311,7 +312,7 @@ describe('editor-plugins-panel', () => {
311
312
  expect(editorPluginsPanel.pinnedPluginIds).to.not.include(tagName);
312
313
  });
313
314
  it('reflects the selected editor into the pinned tree selectedIds', async () => {
314
- const editor = oscdShell.plugins.editor[0];
315
+ const editor = oscdShell._resolvedPlugins.editor[0];
315
316
  editorPluginsPanel.togglePin(editor.tagName);
316
317
  editorPluginsPanel.selectedEditor = editor;
317
318
  await editorPluginsPanel.updateComplete;
@@ -319,7 +320,7 @@ describe('editor-plugins-panel', () => {
319
320
  expect(pinnedTree.selectedIds).to.deep.equal([editor.tagName]);
320
321
  });
321
322
  it('selects an editor chosen from the pinned tree', async () => {
322
- const editor = oscdShell.plugins.editor[0];
323
+ const editor = oscdShell._resolvedPlugins.editor[0];
323
324
  editorPluginsPanel.togglePin(editor.tagName);
324
325
  await editorPluginsPanel.updateComplete;
325
326
  let selected;
@@ -404,7 +405,8 @@ describe('editor-plugins-panel', () => {
404
405
  editorPluginsPanel.addEventListener('editor-select', (event) => {
405
406
  selected = event.detail.editor;
406
407
  });
407
- const tagName = oscdShell.plugins.editor[0].tagName;
408
+ const tagName = oscdShell._resolvedPlugins.editor[0]
409
+ .tagName;
408
410
  editorPluginsPanel.selectEditor([tagName]);
409
411
  await editorPluginsPanel.updateComplete;
410
412
  expect(selected?.tagName).to.equal(tagName);
@@ -413,7 +415,7 @@ describe('editor-plugins-panel', () => {
413
415
  });
414
416
  it('selects a root editor from the collapsed rail', async () => {
415
417
  await collapse(editorPluginsPanel);
416
- const editor = oscdShell.plugins.editor[0];
418
+ const editor = oscdShell._resolvedPlugins.editor[0];
417
419
  const railEditors = editorPluginsPanel.shadowRoot.querySelectorAll('.rail > oscd-icon-button.rail-item');
418
420
  const railEditor = railEditors[2];
419
421
  expect(!!railEditor).to.be.true;
@@ -428,7 +430,8 @@ describe('editor-plugins-panel', () => {
428
430
  });
429
431
  describe('pinned/editors tree expand-state persistence', () => {
430
432
  it('persists the pinned tree expanded ids on `expanded-ids-changed`', async () => {
431
- const tagName = oscdShell.plugins.editor[0].tagName;
433
+ const tagName = oscdShell._resolvedPlugins.editor[0]
434
+ .tagName;
432
435
  editorPluginsPanel.togglePin(tagName);
433
436
  await editorPluginsPanel.updateComplete;
434
437
  const pinnedTree = editorPluginsPanel.shadowRoot.querySelector('.tree-container oscd-tree:not(.editors-tree)');