@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.64 → 2.0.0-next.65
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.
- package/bundle/openbridge-webcomponents.bundle.js +66 -58
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +45 -187
- package/dist/components/navigation-item/navigation-item.d.ts +7 -7
- package/dist/components/navigation-item/navigation-item.d.ts.map +1 -1
- package/dist/components/navigation-item/navigation-item.js +3 -15
- package/dist/components/navigation-item/navigation-item.js.map +1 -1
- package/dist/components/navigation-item-group/navigation-item-group.d.ts +8 -7
- package/dist/components/navigation-item-group/navigation-item-group.d.ts.map +1 -1
- package/dist/components/navigation-item-group/navigation-item-group.js +3 -15
- package/dist/components/navigation-item-group/navigation-item-group.js.map +1 -1
- package/dist/components/navigation-menu/navigation-menu.d.ts +2 -2
- package/dist/components/navigation-menu/navigation-menu.js.map +1 -1
- package/dist/components/tree-navigation-group/tree-navigation-group.d.ts +10 -10
- package/dist/components/tree-navigation-group/tree-navigation-group.d.ts.map +1 -1
- package/dist/components/tree-navigation-group/tree-navigation-group.js +3 -15
- package/dist/components/tree-navigation-group/tree-navigation-group.js.map +1 -1
- package/dist/components/tree-navigation-item/tree-navigation-item.css.js +13 -0
- package/dist/components/tree-navigation-item/tree-navigation-item.css.js.map +1 -1
- package/dist/components/tree-navigation-item/tree-navigation-item.d.ts +59 -8
- package/dist/components/tree-navigation-item/tree-navigation-item.d.ts.map +1 -1
- package/dist/components/tree-navigation-item/tree-navigation-item.js +46 -17
- package/dist/components/tree-navigation-item/tree-navigation-item.js.map +1 -1
- package/package.json +1 -1
- package/src/components/navigation-item/navigation-item.ts +8 -12
- package/src/components/navigation-item-group/navigation-item-group.ts +9 -12
- package/src/components/navigation-menu/navigation-menu.stories.ts +34 -6
- package/src/components/navigation-menu/navigation-menu.ts +2 -2
- package/src/components/tree-navigation/tree-navigation.stories.ts +154 -9
- package/src/components/tree-navigation-group/tree-navigation-group.ts +11 -15
- package/src/components/tree-navigation-item/tree-navigation-item.css +12 -0
- package/src/components/tree-navigation-item/tree-navigation-item.stories.ts +38 -15
- package/src/components/tree-navigation-item/tree-navigation-item.ts +98 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-navigation-item.js","sources":["../../../src/components/tree-navigation-item/tree-navigation-item.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS} from 'lit';\nimport {property, query} from 'lit/decorators.js';\nimport componentStyle from './tree-navigation-item.css?inline';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {ifDefined} from 'lit/directives/if-defined.js';\nimport {customElement} from '../../decorator.js';\nimport '../../icons/icon-chevron-right-google.js';\nimport '../../icons/icon-alert-header-aggregated-iec.js';\nimport '../../icons/icon-alert-header-group-iec.js';\nimport '../badge/badge.js';\nimport {BadgeType} from '../badge/badge.js';\n\n/**\n * Guide line drawn for one indentation column. Normally computed by\n * `obc-tree-navigation`; rarely set by hand.\n *\n * - `straight`: vertical pass-through (`│`)\n * - `intersection`: vertical + stub for a non-last child (`├`)\n * - `corner`: half vertical + stub for the last child (`└`)\n * - `blank`: empty spacer\n */\nexport enum TreeBranchType {\n straight = 'straight',\n intersection = 'intersection',\n corner = 'corner',\n blank = 'blank',\n}\n\n/**\n * Terminal type for a tree item, controlling the alert-header marker shown in\n * the terminal (top-right, by the chevron).\n *\n * - `regular`: No marker — a plain expand/collapse terminal.\n * - `aggregatedHeader`: Shows the aggregated alert-header marker, indicating the\n * node aggregates alerts from its descendants.\n * - `groupHeader`: Shows the group alert-header marker, indicating a grouped set\n * of alerts beneath the node.\n */\nexport enum TreeTerminalType {\n regular = 'regular',\n aggregatedHeader = 'aggregated-header',\n groupHeader = 'group-header',\n}\n\n/**\n * `<obc-tree-navigation-item>` – A single row in a tree- or file-explorer-style\n * navigation list, with indentation guide lines, an optional expand/collapse\n * chevron, a leading icon, a label, and an optional alert badge.\n *\n * Each row represents one node in a hierarchy. Depth is expressed through the\n * `branches` array: one entry per ancestor level, each describing the guide line\n * to draw for that level. The expand chevron lets a node disclose its children,\n * emitting `expand-toggle` so a parent can manage the open/closed state.\n *\n * ## Features\n * - **Indentation guides:** Render one 32px guide column per `branches` entry —\n * pass-through vertical lines for ancestors that continue, and an elbow\n * (`intersection`) connecting the row to its parent.\n * - **Expand/collapse:** Set `expandable` to show a chevron that rotates when\n * `expanded`. The chevron is a visual indicator only — activating the row\n * fires `expand-toggle` with the next state; manage `expanded` in response.\n * When `expanded`, a vertical guide descends from the chevron to connect to\n * the revealed child rows below.\n * - **Terminal type:** `terminalType` adds an alert-header marker in the terminal\n * (`aggregatedHeader` or `groupHeader`), indicating the node heads a set of\n * aggregated or grouped alerts.\n * - **Leading icon:** Provide an icon via the `icon` slot (shown when\n * `hasLeadingIcon`).\n * - **Alert badge:** A trailing counter badge (e.g. an alarm count), toggled with\n * `hasAlertBadge` and configured via `alertCount` and `alertType`.\n * - **Checked state:** `checked` highlights the current selection using the\n * amplified elevation style. A checked row is the current item and is not\n * re-selectable — it shows no hover/pressed feedback and fires no `click` or\n * navigation. An expandable checked row still toggles (fires `expand-toggle`),\n * so a group that is the current selection can be opened and closed. It stays\n * keyboard-focusable.\n * - **Link or button:** Set `href` to render the row as a link; otherwise it acts\n * as a button.\n *\n * ## Usage Guidelines\n * - Use for hierarchical navigation such as file trees, layer panels, or nested\n * menus. For flat navigation lists, use `obc-navigation-item` instead.\n * - Build `branches` from the row's ancestry: `intersection` for the level that\n * owns this row, `straight` for ancestors with siblings still to come, and\n * `blank` for ancestors whose subtrees have ended. When placed inside\n * `obc-tree-navigation`, the container computes `branches` automatically.\n * - Keep one row `checked` at a time within a tree to mark the current location.\n * - Leaf nodes should leave `expandable` as `false` so no chevron is shown.\n *\n * ## Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |----------------|---------------------------------|-------------------------------------------------------------------------|\n * | icon | `hasLeadingIcon` is true | Leading icon for the row, e.g. `<obi-placeholder slot=\"icon\">`. |\n *\n * @slot icon - Leading icon slot (shown when `hasLeadingIcon` is true).\n * @fires expand-toggle {CustomEvent<boolean>} Fired when an expandable row is activated; detail is the next `expanded` value.\n * @fires click {CustomEvent<void>} Fired when the row is activated.\n */\n@customElement('obc-tree-navigation-item')\nexport class ObcTreeNavigationItem extends LitElement {\n /** The text label displayed for the row. */\n @property({type: String}) label = 'List item';\n\n /**\n * Guide line for each ancestor level, outermost first; one 32px column per\n * entry. Computed by `obc-tree-navigation` — rarely set by hand.\n */\n @property({type: Array}) branches: TreeBranchType[] = [];\n\n /** Whether the row shows an expand/collapse chevron. Leave false for leaf nodes. */\n @property({type: Boolean}) expandable = false;\n\n /** Whether the node is expanded. Rotates the chevron and sets `aria-expanded`. */\n @property({type: Boolean, reflect: true}) expanded = false;\n\n /**\n * Whether the row is the current selection. Applies the amplified style and\n * makes the row inert to re-selection (no hover/pressed feedback, no `click`\n * or navigation); it remains keyboard-focusable. An expandable checked row\n * still fires `expand-toggle` so a selected group can open and close.\n */\n @property({type: Boolean, reflect: true}) checked = false;\n\n /** Disables the row, removing it from the tab order and dimming its appearance. */\n @property({type: Boolean, reflect: true}) disabled = false;\n\n /**\n * Whether the row is in the tab order. A tree container manages this as a\n * roving tabindex (one row focusable at a time); standalone rows stay tabbable.\n */\n @property({type: Boolean, attribute: false}) focusable = true;\n\n /**\n * Whether the row shows a leading icon (provided via the `icon` slot).\n */\n @property({type: Boolean, attribute: false}) hasLeadingIcon = true;\n\n /**\n * Terminal type, controlling the alert-header marker shown in the terminal.\n * One of `regular` (default), `aggregated-header`, or `group-header`.\n */\n @property({type: String}) terminalType: string = TreeTerminalType.regular;\n\n /** Whether a trailing alert counter badge is shown. */\n @property({type: Boolean}) hasAlertBadge = false;\n\n /** The number shown in the alert badge when `hasAlertBadge` is true. */\n @property({type: Number}) alertCount = 0;\n\n /** The severity/type of the alert badge. One of the `obc-badge` types (default `alarm`). */\n @property({type: String}) alertType: string = BadgeType.alarm;\n\n /**\n * The URL to navigate to when the row is activated. If set, the row renders as\n * a link; otherwise it acts as a button.\n */\n @property({type: String}) href: string | undefined;\n\n @query('.wrapper') private wrapperElement?: HTMLElement;\n\n /** Focuses the row's interactive wrapper (the host itself is not focusable). */\n public override focus(options?: FocusOptions): void {\n this.wrapperElement?.focus(options);\n }\n\n /** A root-level row has no ancestor columns, so it draws no connector lines. */\n private get isRoot(): boolean {\n return this.branches.length === 0;\n }\n\n /**\n * All ancestor columns are blank spacers — the row is indented but draws no\n * guide lines, so the terminal connector and dropdown are suppressed too.\n */\n private get isBlankAncestry(): boolean {\n return (\n this.branches.length > 0 &&\n this.branches.every((b) => b === TreeBranchType.blank)\n );\n }\n\n private activate() {\n if (this.disabled) return;\n // An expandable row always toggles, even when checked — a group that is the\n // current selection must still open and close. A checked leaf, however, is\n // the current selection and is inert (no re-selection click or navigation).\n if (this.expandable) {\n this.dispatchEvent(\n new CustomEvent<boolean>('expand-toggle', {detail: !this.expanded})\n );\n }\n if (this.checked) return;\n this.dispatchEvent(new CustomEvent('click'));\n if (this.href !== undefined) {\n window.location.href = this.href;\n }\n }\n\n private handleKeydown(event: KeyboardEvent) {\n if (this.disabled) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n this.activate();\n }\n\n private renderBranch(type: TreeBranchType) {\n const hasVertical =\n type === TreeBranchType.straight ||\n type === TreeBranchType.intersection ||\n type === TreeBranchType.corner;\n const hasHorizontal =\n type === TreeBranchType.intersection || type === TreeBranchType.corner;\n return html`<div\n class=${classMap({branch: true, ['branch-' + type]: true})}\n >\n ${hasVertical ? html`<div class=\"branch-vertical\"></div>` : nothing}\n ${hasHorizontal ? html`<div class=\"branch-horizontal\"></div>` : nothing}\n ${type === TreeBranchType.corner\n ? html`<div class=\"branch-elbow\"></div>`\n : nothing}\n </div>`;\n }\n\n private renderTerminalHeader() {\n if (this.terminalType === TreeTerminalType.aggregatedHeader) {\n return html`<div class=\"terminal-header\" aria-hidden=\"true\">\n <obi-alert-header-aggregated-iec></obi-alert-header-aggregated-iec>\n </div>`;\n }\n if (this.terminalType === TreeTerminalType.groupHeader) {\n return html`<div class=\"terminal-header\" aria-hidden=\"true\">\n <obi-alert-header-group-iec></obi-alert-header-group-iec>\n </div>`;\n }\n return nothing;\n }\n\n override render() {\n return html`\n <div\n class=${classMap({\n wrapper: true,\n checked: this.checked,\n disabled: this.disabled,\n 'has-icon': this.hasLeadingIcon,\n })}\n role=\"treeitem\"\n aria-expanded=${ifDefined(this.expandable ? this.expanded : undefined)}\n aria-current=${ifDefined(this.checked ? 'page' : undefined)}\n aria-selected=${ifDefined(this.checked ? 'true' : undefined)}\n aria-disabled=${ifDefined(this.disabled ? 'true' : undefined)}\n tabindex=${this.disabled ? -1 : this.focusable ? 0 : -1}\n @click=${this.activate}\n @keydown=${this.handleKeydown}\n >\n <div class=\"visible-wrapper\">\n <div class=\"tree-node-row\">\n ${this.branches.map((branch) => this.renderBranch(branch))}\n <div class=\"terminal\">\n ${this.isRoot || this.isBlankAncestry\n ? nothing\n : html`<div class=\"terminal-connector\"></div>`}\n ${!this.isRoot &&\n !this.isBlankAncestry &&\n this.expandable &&\n this.expanded\n ? html`<div class=\"terminal-dropdown\"></div>`\n : nothing}\n ${this.expandable\n ? html`<div class=\"chevron\" aria-hidden=\"true\">\n <obi-chevron-right-google></obi-chevron-right-google>\n </div>`\n : nothing}\n ${this.renderTerminalHeader()}\n </div>\n </div>\n <div class=\"label-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"leading-icon\">\n <slot name=\"icon\"></slot>\n </div>`\n : nothing}\n <span part=\"label\" class=\"label\">${this.label}</span>\n </div>\n ${this.hasAlertBadge\n ? html`<obc-badge\n class=\"alert-badge\"\n .type=${this.alertType}\n .number=${this.alertCount}\n ></obc-badge>`\n : nothing}\n </div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\nexport type ObcTreeNavigationItemExpandToggleEvent = CustomEvent<boolean>;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-tree-navigation-item': ObcTreeNavigationItem;\n }\n}\n"],"names":["TreeBranchType","TreeTerminalType"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tree-navigation-item.js","sources":["../../../src/components/tree-navigation-item/tree-navigation-item.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS} from 'lit';\nimport {property, query} from 'lit/decorators.js';\nimport componentStyle from './tree-navigation-item.css?inline';\nimport {classMap} from 'lit/directives/class-map.js';\nimport {ifDefined} from 'lit/directives/if-defined.js';\nimport {customElement} from '../../decorator.js';\nimport '../../icons/icon-chevron-right-google.js';\nimport '../../icons/icon-alert-header-aggregated-iec.js';\nimport '../../icons/icon-alert-header-group-iec.js';\nimport '../badge/badge.js';\nimport {AlertType, ALERT_SEVERITY_PRIORITY} from '../../types.js';\n\n/**\n * Guide line drawn for one indentation column. Normally computed by\n * `obc-tree-navigation`; rarely set by hand.\n *\n * - `straight`: vertical pass-through (`│`)\n * - `intersection`: vertical + stub for a non-last child (`├`)\n * - `corner`: half vertical + stub for the last child (`└`)\n * - `blank`: empty spacer\n */\nexport enum TreeBranchType {\n straight = 'straight',\n intersection = 'intersection',\n corner = 'corner',\n blank = 'blank',\n}\n\n/**\n * Terminal type for a tree item, controlling the alert-header marker shown in\n * the terminal (top-right, by the chevron).\n *\n * - `regular`: No marker — a plain expand/collapse terminal.\n * - `aggregatedHeader`: Shows the aggregated alert-header marker, indicating the\n * node aggregates alerts from its descendants.\n * - `groupHeader`: Shows the group alert-header marker, indicating a grouped set\n * of alerts beneath the node.\n */\nexport enum TreeTerminalType {\n regular = 'regular',\n aggregatedHeader = 'aggregated-header',\n groupHeader = 'group-header',\n}\n\n/**\n * Per-severity alert counts for a tree row's trailing badge(s). Each `count*`\n * is the number of active alerts of that severity at or beneath the row — the\n * level severities `level-critical`, `level-high`, `level-medium`, `level-low`,\n * and `level-diagnostic`, plus the IEC severities `alarm`, `warning`, and\n * `caution`. Badges are ordered and aggregated by the shared\n * `ALERT_SEVERITY_PRIORITY` ranking, most to least severe.\n *\n * Set `aggregate` to collapse the counts into a single badge showing the total,\n * styled as the highest category present; otherwise one badge is rendered per\n * non-zero count.\n */\nexport interface TreeNavigationItemAlerts {\n /** Collapse all counts into one badge: total count, highest-severity style. */\n aggregate?: boolean;\n /** Number of level-critical alerts. */\n countLevelCritical?: number;\n /** Number of alarm alerts. */\n countAlarm?: number;\n /** Number of level-high alerts. */\n countLevelHigh?: number;\n /** Number of warning alerts. */\n countWarning?: number;\n /** Number of level-medium alerts. */\n countLevelMedium?: number;\n /** Number of caution alerts. */\n countCaution?: number;\n /** Number of level-low alerts. */\n countLevelLow?: number;\n /** Number of level-diagnostic alerts. */\n countLevelDiagnostic?: number;\n}\n\n/**\n * `<obc-tree-navigation-item>` – A single row in a tree- or file-explorer-style\n * navigation list, with indentation guide lines, an optional expand/collapse\n * chevron, a leading icon, a label, and an optional alert badge.\n *\n * Each row represents one node in a hierarchy. Depth is expressed through the\n * `branches` array: one entry per ancestor level, each describing the guide line\n * to draw for that level. The expand chevron lets a node disclose its children,\n * emitting `expand-toggle` so a parent can manage the open/closed state.\n *\n * ## Features\n * - **Indentation guides:** Render one 32px guide column per `branches` entry —\n * pass-through vertical lines for ancestors that continue, and an elbow\n * (`intersection`) connecting the row to its parent.\n * - **Expand/collapse:** Set `expandable` to show a chevron that rotates when\n * `expanded`. The chevron is a visual indicator only — activating the row\n * fires `expand-toggle` with the next state; manage `expanded` in response.\n * When `expanded`, a vertical guide descends from the chevron to connect to\n * the revealed child rows below.\n * - **Terminal type:** `terminalType` adds an alert-header marker in the terminal\n * (`aggregatedHeader` or `groupHeader`), indicating the node heads a set of\n * aggregated or grouped alerts.\n * - **Leading icon:** Provide an icon via the `icon` slot (shown when\n * `hasLeadingIcon`).\n * - **Alert badges:** Trailing counter badges driven by the `alerts` object — a\n * per-severity count map with one field per level severity (critical, high,\n * medium, low, diagnostic). By default each non-zero count renders its own\n * badge, ordered most to least severe by `ALERT_SEVERITY_PRIORITY`; set\n * `alerts.aggregate` to instead show a single badge with the combined total,\n * styled as the highest category present.\n * - **Checked state:** `checked` highlights the current selection using the\n * amplified elevation style. A checked row is the current item and is not\n * re-selectable — it shows no hover/pressed feedback and fires no `click` or\n * navigation. An expandable checked row still toggles (fires `expand-toggle`),\n * so a group that is the current selection can be opened and closed. It stays\n * keyboard-focusable.\n * - **Link or button:** Set `href` to render the row as a link; otherwise it acts\n * as a button.\n *\n * ## Usage Guidelines\n * - Use for hierarchical navigation such as file trees, layer panels, or nested\n * menus. For flat navigation lists, use `obc-navigation-item` instead.\n * - Build `branches` from the row's ancestry: `intersection` for the level that\n * owns this row, `straight` for ancestors with siblings still to come, and\n * `blank` for ancestors whose subtrees have ended. When placed inside\n * `obc-tree-navigation`, the container computes `branches` automatically.\n * - Keep one row `checked` at a time within a tree to mark the current location.\n * - Leaf nodes should leave `expandable` as `false` so no chevron is shown.\n *\n * ## Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |----------------|---------------------------------|-------------------------------------------------------------------------|\n * | icon | `hasLeadingIcon` is true | Leading icon for the row, e.g. `<obi-placeholder slot=\"icon\">`. |\n *\n * @slot icon - Leading icon slot (shown when `hasLeadingIcon` is true).\n * @fires expand-toggle {CustomEvent<boolean>} Fired when an expandable row is activated; detail is the next `expanded` value.\n * @fires click {CustomEvent<void>} Fired when the row is activated.\n */\n@customElement('obc-tree-navigation-item')\nexport class ObcTreeNavigationItem extends LitElement {\n /** The text label displayed for the row. */\n @property({type: String}) label = 'List item';\n\n /**\n * Guide line for each ancestor level, outermost first; one 32px column per\n * entry. Computed by `obc-tree-navigation` — rarely set by hand.\n */\n @property({type: Array}) branches: TreeBranchType[] = [];\n\n /** Whether the row shows an expand/collapse chevron. Leave false for leaf nodes. */\n @property({type: Boolean}) expandable = false;\n\n /** Whether the node is expanded. Rotates the chevron and sets `aria-expanded`. */\n @property({type: Boolean, reflect: true}) expanded = false;\n\n /**\n * Whether the row is the current selection. Applies the amplified style and\n * makes the row inert to re-selection (no hover/pressed feedback, no `click`\n * or navigation); it remains keyboard-focusable. An expandable checked row\n * still fires `expand-toggle` so a selected group can open and close.\n */\n @property({type: Boolean, reflect: true}) checked = false;\n\n /** Disables the row, removing it from the tab order and dimming its appearance. */\n @property({type: Boolean, reflect: true}) disabled = false;\n\n /**\n * Whether the row is in the tab order. A tree container manages this as a\n * roving tabindex (one row focusable at a time); standalone rows stay tabbable.\n */\n @property({type: Boolean, attribute: false}) focusable = true;\n\n /**\n * Whether the row shows a leading icon (provided via the `icon` slot).\n */\n @property({type: Boolean, attribute: false}) hasLeadingIcon = true;\n\n /**\n * Terminal type, controlling the alert-header marker shown in the terminal.\n * One of `regular` (default), `aggregated-header`, or `group-header`.\n */\n @property({type: String}) terminalType: string = TreeTerminalType.regular;\n\n /**\n * Per-severity alert counts for the row's trailing badge(s). Omit (or leave\n * every count at 0) for a row with no alerts. See {@link TreeNavigationItemAlerts}.\n *\n * - When `aggregate` is true, a single badge is shown: its number is the sum\n * of all counts and its severity is the highest category present\n * (critical → alarm → warning → caution).\n * - Otherwise one badge is shown per count greater than 0, ordered most to\n * least severe and spaced by the alert-counter spacing token.\n */\n @property({type: Object}) alerts?: TreeNavigationItemAlerts;\n\n /**\n * The URL to navigate to when the row is activated. If set, the row renders as\n * a link; otherwise it acts as a button.\n */\n @property({type: String}) href: string | undefined;\n\n @query('.wrapper') private wrapperElement?: HTMLElement;\n\n /** Focuses the row's interactive wrapper (the host itself is not focusable). */\n public override focus(options?: FocusOptions): void {\n this.wrapperElement?.focus(options);\n }\n\n /**\n * The badge(s) to render from `alerts`, as `{type, count}` pairs already in\n * severity order, ranked by `ALERT_SEVERITY_PRIORITY`.\n *\n * - No `alerts`, or every count 0 → no badges.\n * - `aggregate` → a single pair: the summed count typed as the highest\n * category that has any alerts.\n * - Otherwise → one pair per count greater than 0.\n */\n private get alertBadges(): {type: AlertType; count: number}[] {\n const alerts = this.alerts;\n if (!alerts) return [];\n const countByType: Partial<Record<AlertType, number>> = {\n [AlertType.LevelCritical]: alerts.countLevelCritical ?? 0,\n [AlertType.Alarm]: alerts.countAlarm ?? 0,\n [AlertType.LevelHigh]: alerts.countLevelHigh ?? 0,\n [AlertType.Warning]: alerts.countWarning ?? 0,\n [AlertType.LevelMedium]: alerts.countLevelMedium ?? 0,\n [AlertType.Caution]: alerts.countCaution ?? 0,\n [AlertType.LevelLow]: alerts.countLevelLow ?? 0,\n [AlertType.LevelDiagnostic]: alerts.countLevelDiagnostic ?? 0,\n };\n // Order (and, when aggregating, rank) by the shared severity priority,\n // keeping only the severities this component exposes.\n const ranked = ALERT_SEVERITY_PRIORITY.filter(\n (type) => type in countByType\n ).map((type) => ({type, count: countByType[type] ?? 0}));\n if (alerts.aggregate) {\n const total = ranked.reduce((sum, b) => sum + b.count, 0);\n const highest = ranked.find((b) => b.count > 0);\n if (!highest) return [];\n return [{type: highest.type, count: total}];\n }\n return ranked.filter((b) => b.count > 0);\n }\n\n /** A root-level row has no ancestor columns, so it draws no connector lines. */\n private get isRoot(): boolean {\n return this.branches.length === 0;\n }\n\n /**\n * All ancestor columns are blank spacers — the row is indented but draws no\n * guide lines, so the terminal connector and dropdown are suppressed too.\n */\n private get isBlankAncestry(): boolean {\n return (\n this.branches.length > 0 &&\n this.branches.every((b) => b === TreeBranchType.blank)\n );\n }\n\n private activate() {\n if (this.disabled) return;\n // An expandable row always toggles, even when checked — a group that is the\n // current selection must still open and close. A checked leaf, however, is\n // the current selection and is inert (no re-selection click or navigation).\n if (this.expandable) {\n this.dispatchEvent(\n new CustomEvent<boolean>('expand-toggle', {detail: !this.expanded})\n );\n }\n if (this.checked) return;\n this.dispatchEvent(new CustomEvent('click'));\n if (this.href !== undefined) {\n window.location.href = this.href;\n }\n }\n\n private handleKeydown(event: KeyboardEvent) {\n if (this.disabled) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n event.preventDefault();\n this.activate();\n }\n\n private renderBranch(type: TreeBranchType) {\n const hasVertical =\n type === TreeBranchType.straight ||\n type === TreeBranchType.intersection ||\n type === TreeBranchType.corner;\n const hasHorizontal =\n type === TreeBranchType.intersection || type === TreeBranchType.corner;\n return html`<div\n class=${classMap({branch: true, ['branch-' + type]: true})}\n >\n ${hasVertical ? html`<div class=\"branch-vertical\"></div>` : nothing}\n ${hasHorizontal ? html`<div class=\"branch-horizontal\"></div>` : nothing}\n ${type === TreeBranchType.corner\n ? html`<div class=\"branch-elbow\"></div>`\n : nothing}\n </div>`;\n }\n\n private renderTerminalHeader() {\n if (this.terminalType === TreeTerminalType.aggregatedHeader) {\n return html`<div class=\"terminal-header\" aria-hidden=\"true\">\n <obi-alert-header-aggregated-iec></obi-alert-header-aggregated-iec>\n </div>`;\n }\n if (this.terminalType === TreeTerminalType.groupHeader) {\n return html`<div class=\"terminal-header\" aria-hidden=\"true\">\n <obi-alert-header-group-iec></obi-alert-header-group-iec>\n </div>`;\n }\n return nothing;\n }\n\n override render() {\n return html`\n <div\n class=${classMap({\n wrapper: true,\n checked: this.checked,\n disabled: this.disabled,\n 'has-icon': this.hasLeadingIcon,\n })}\n role=\"treeitem\"\n aria-expanded=${ifDefined(this.expandable ? this.expanded : undefined)}\n aria-current=${ifDefined(this.checked ? 'page' : undefined)}\n aria-selected=${ifDefined(this.checked ? 'true' : undefined)}\n aria-disabled=${ifDefined(this.disabled ? 'true' : undefined)}\n tabindex=${this.disabled ? -1 : this.focusable ? 0 : -1}\n @click=${this.activate}\n @keydown=${this.handleKeydown}\n >\n <div class=\"visible-wrapper\">\n <div class=\"tree-node-row\">\n ${this.branches.map((branch) => this.renderBranch(branch))}\n <div class=\"terminal\">\n ${this.isRoot || this.isBlankAncestry\n ? nothing\n : html`<div class=\"terminal-connector\"></div>`}\n ${!this.isRoot &&\n !this.isBlankAncestry &&\n this.expandable &&\n this.expanded\n ? html`<div class=\"terminal-dropdown\"></div>`\n : nothing}\n ${this.expandable\n ? html`<div class=\"chevron\" aria-hidden=\"true\">\n <obi-chevron-right-google></obi-chevron-right-google>\n </div>`\n : nothing}\n ${this.renderTerminalHeader()}\n </div>\n </div>\n <div class=\"label-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"leading-icon\">\n <slot name=\"icon\"></slot>\n </div>`\n : nothing}\n <span part=\"label\" class=\"label\">${this.label}</span>\n </div>\n ${this.alertBadges.length > 0\n ? html`<div class=\"alert-badges\">\n ${this.alertBadges.map(\n (badge) =>\n html`<obc-badge\n class=\"alert-badge\"\n .type=${badge.type}\n .number=${badge.count}\n ></obc-badge>`\n )}\n </div>`\n : nothing}\n </div>\n </div>\n `;\n }\n\n static override styles = unsafeCSS(componentStyle);\n}\n\nexport type ObcTreeNavigationItemExpandToggleEvent = CustomEvent<boolean>;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-tree-navigation-item': ObcTreeNavigationItem;\n }\n}\n"],"names":["TreeBranchType","TreeTerminalType"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -10,8 +10,8 @@ import '../tree-navigation-item/tree-navigation-item.js';
|
|
|
10
10
|
import {
|
|
11
11
|
TreeBranchType,
|
|
12
12
|
TreeTerminalType,
|
|
13
|
+
type TreeNavigationItemAlerts,
|
|
13
14
|
} from '../tree-navigation-item/tree-navigation-item.js';
|
|
14
|
-
import {BadgeType} from '../badge/badge.js';
|
|
15
15
|
|
|
16
16
|
enum NavigationItemRole {
|
|
17
17
|
Button = 'button',
|
|
@@ -160,14 +160,12 @@ export class ObcNavigationItem extends LitElement {
|
|
|
160
160
|
*/
|
|
161
161
|
@property({type: String}) terminalType: string = TreeTerminalType.regular;
|
|
162
162
|
|
|
163
|
-
/**
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
/** The severity/type of the alert badge — one of the `obc-badge` types (Tree variant only). */
|
|
170
|
-
@property({type: String}) alertType: string = BadgeType.alarm;
|
|
163
|
+
/**
|
|
164
|
+
* Per-severity alert counts shown as trailing badge(s) (Tree variant only).
|
|
165
|
+
* Forwarded to the underlying `obc-tree-navigation-item`. See
|
|
166
|
+
* {@link TreeNavigationItemAlerts}.
|
|
167
|
+
*/
|
|
168
|
+
@property({type: Object}) alerts?: TreeNavigationItemAlerts;
|
|
171
169
|
|
|
172
170
|
@query('a') private anchorElement?: HTMLAnchorElement;
|
|
173
171
|
|
|
@@ -231,9 +229,7 @@ export class ObcNavigationItem extends LitElement {
|
|
|
231
229
|
.hasLeadingIcon=${this.hasIcon}
|
|
232
230
|
.href=${this.href}
|
|
233
231
|
.terminalType=${this.terminalType}
|
|
234
|
-
|
|
235
|
-
.alertCount=${this.alertCount}
|
|
236
|
-
.alertType=${this.alertType}
|
|
232
|
+
.alerts=${this.alerts}
|
|
237
233
|
@click=${this.onClick}
|
|
238
234
|
>
|
|
239
235
|
${this.hasIcon
|
|
@@ -8,8 +8,8 @@ import '../tree-navigation-item/tree-navigation-item.js';
|
|
|
8
8
|
import {
|
|
9
9
|
TreeBranchType,
|
|
10
10
|
TreeTerminalType,
|
|
11
|
+
type TreeNavigationItemAlerts,
|
|
11
12
|
} from '../tree-navigation-item/tree-navigation-item.js';
|
|
12
|
-
import {BadgeType} from '../badge/badge.js';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* `<obc-navigation-item-group>` – A collapsible navigation group component for organizing related navigation items under a single expandable label.
|
|
@@ -108,14 +108,13 @@ export class ObcNavigationItemGroup extends LitElement {
|
|
|
108
108
|
*/
|
|
109
109
|
@property({type: String}) terminalType: string = TreeTerminalType.regular;
|
|
110
110
|
|
|
111
|
-
/**
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
@property({type: String}) alertType: string = BadgeType.alarm;
|
|
111
|
+
/**
|
|
112
|
+
* Per-severity alert counts shown as trailing badge(s) on the group header
|
|
113
|
+
* (Tree variant only). Forwarded to the underlying `obc-tree-navigation-item`;
|
|
114
|
+
* typically `{aggregate: true, ...}` so the header totals the rows beneath it.
|
|
115
|
+
* See {@link TreeNavigationItemAlerts}.
|
|
116
|
+
*/
|
|
117
|
+
@property({type: Object}) alerts?: TreeNavigationItemAlerts;
|
|
119
118
|
|
|
120
119
|
/** Whether the group starts expanded. Useful for trees that open by default. */
|
|
121
120
|
@property({type: Boolean}) defaultOpen = false;
|
|
@@ -178,9 +177,7 @@ export class ObcNavigationItemGroup extends LitElement {
|
|
|
178
177
|
?checked=${this.checked}
|
|
179
178
|
.hasLeadingIcon=${this.hasIcon}
|
|
180
179
|
.terminalType=${this.terminalType}
|
|
181
|
-
|
|
182
|
-
.alertCount=${this.alertCount}
|
|
183
|
-
.alertType=${this.alertType}
|
|
180
|
+
.alerts=${this.expanded ? undefined : this.alerts}
|
|
184
181
|
@expand-toggle=${this.onClickGroup}
|
|
185
182
|
>
|
|
186
183
|
${this.hasIcon
|
|
@@ -268,6 +268,13 @@ export const Tree: Story = {
|
|
|
268
268
|
label="Vessel"
|
|
269
269
|
hasIcon
|
|
270
270
|
defaultOpen
|
|
271
|
+
.alerts=${{
|
|
272
|
+
aggregate: true,
|
|
273
|
+
countLevelCritical: 1,
|
|
274
|
+
countLevelHigh: 1,
|
|
275
|
+
countLevelMedium: 2,
|
|
276
|
+
countLevelLow: 1,
|
|
277
|
+
}}
|
|
271
278
|
>
|
|
272
279
|
<obi-placeholder slot="icon"></obi-placeholder>
|
|
273
280
|
<obc-navigation-item-group
|
|
@@ -275,26 +282,47 @@ export const Tree: Story = {
|
|
|
275
282
|
hasIcon
|
|
276
283
|
defaultOpen
|
|
277
284
|
terminalType="aggregated-header"
|
|
285
|
+
.alerts=${{
|
|
286
|
+
aggregate: true,
|
|
287
|
+
countLevelCritical: 1,
|
|
288
|
+
countLevelHigh: 1,
|
|
289
|
+
}}
|
|
278
290
|
>
|
|
279
291
|
<obi-placeholder slot="icon"></obi-placeholder>
|
|
280
|
-
<obc-navigation-item
|
|
292
|
+
<obc-navigation-item
|
|
293
|
+
label="Main engine"
|
|
294
|
+
hasIcon
|
|
295
|
+
checked
|
|
296
|
+
.alerts=${{countLevelHigh: 1}}
|
|
297
|
+
>
|
|
281
298
|
<obi-placeholder slot="icon"></obi-placeholder>
|
|
282
299
|
</obc-navigation-item>
|
|
283
300
|
<obc-navigation-item
|
|
284
301
|
label="Cooling system"
|
|
285
302
|
hasIcon
|
|
286
|
-
|
|
287
|
-
.alertCount=${3}
|
|
303
|
+
.alerts=${{countLevelCritical: 1}}
|
|
288
304
|
>
|
|
289
305
|
<obi-placeholder slot="icon"></obi-placeholder>
|
|
290
306
|
</obc-navigation-item>
|
|
291
307
|
</obc-navigation-item-group>
|
|
292
|
-
<obc-navigation-item-group
|
|
308
|
+
<obc-navigation-item-group
|
|
309
|
+
label="Bridge"
|
|
310
|
+
hasIcon
|
|
311
|
+
.alerts=${{aggregate: true, countLevelMedium: 2, countLevelLow: 1}}
|
|
312
|
+
>
|
|
293
313
|
<obi-placeholder slot="icon"></obi-placeholder>
|
|
294
|
-
<obc-navigation-item
|
|
314
|
+
<obc-navigation-item
|
|
315
|
+
label="Radar"
|
|
316
|
+
hasIcon
|
|
317
|
+
.alerts=${{countLevelMedium: 2}}
|
|
318
|
+
>
|
|
295
319
|
<obi-placeholder slot="icon"></obi-placeholder>
|
|
296
320
|
</obc-navigation-item>
|
|
297
|
-
<obc-navigation-item
|
|
321
|
+
<obc-navigation-item
|
|
322
|
+
label="Autopilot"
|
|
323
|
+
hasIcon
|
|
324
|
+
.alerts=${{countLevelLow: 1}}
|
|
325
|
+
>
|
|
298
326
|
<obi-placeholder slot="icon"></obi-placeholder>
|
|
299
327
|
</obc-navigation-item>
|
|
300
328
|
</obc-navigation-item-group>
|
|
@@ -77,8 +77,8 @@ export enum ObcNavigationMenuFlyoutVariant {
|
|
|
77
77
|
* - **Tree:** Renders the same `obc-navigation-item` / `obc-navigation-item-group`
|
|
78
78
|
* markup as a hierarchical tree. Groups expand inline (instead of as flyouts),
|
|
79
79
|
* rows are indented by depth, multiple branches can stay open at once, and the
|
|
80
|
-
* tree-row presentation (alert
|
|
81
|
-
* items' `
|
|
80
|
+
* tree-row presentation (alert badges, terminal marker) is available via the
|
|
81
|
+
* items' `alerts`/`terminalType` properties.
|
|
82
82
|
* - **Responsive Layout:**
|
|
83
83
|
* - `smallScreen` property adapts the footer and logo layout for smaller viewports.
|
|
84
84
|
* - **Slot-based Content:**
|
|
@@ -4,8 +4,9 @@ import './tree-navigation.js';
|
|
|
4
4
|
import '../tree-navigation-group/tree-navigation-group.js';
|
|
5
5
|
import '../tree-navigation-item/tree-navigation-item.js';
|
|
6
6
|
import {TreeTerminalType} from '../tree-navigation-item/tree-navigation-item.js';
|
|
7
|
+
import type {TreeNavigationItemAlerts} from '../tree-navigation-item/tree-navigation-item.js';
|
|
7
8
|
import {iconIdToIconHtml} from '../../storybook-util.js';
|
|
8
|
-
import {LitElement, html} from 'lit';
|
|
9
|
+
import {LitElement, html, type TemplateResult} from 'lit';
|
|
9
10
|
import {state} from 'lit/decorators.js';
|
|
10
11
|
import {customElement} from '../../decorator.js';
|
|
11
12
|
|
|
@@ -21,22 +22,30 @@ const meta: Meta<typeof ObcTreeNavigation> = {
|
|
|
21
22
|
component: 'obc-tree-navigation',
|
|
22
23
|
render: () => html`
|
|
23
24
|
<obc-tree-navigation>
|
|
24
|
-
<obc-tree-navigation-group
|
|
25
|
+
<obc-tree-navigation-group
|
|
26
|
+
label="Vessel"
|
|
27
|
+
.alerts=${{aggregate: true, countLevelHigh: 3}}
|
|
28
|
+
expanded
|
|
29
|
+
>
|
|
25
30
|
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
26
31
|
<obc-tree-navigation-group
|
|
27
32
|
label="Engine room"
|
|
28
33
|
expanded
|
|
34
|
+
.alerts=${{aggregate: true, countLevelHigh: 3}}
|
|
29
35
|
.terminalType=${TreeTerminalType.aggregatedHeader}
|
|
30
36
|
>
|
|
31
37
|
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
32
|
-
<obc-tree-navigation-item
|
|
38
|
+
<obc-tree-navigation-item
|
|
39
|
+
label="Main engine"
|
|
40
|
+
checked
|
|
41
|
+
.alerts=${{countLevelHigh: 1}}
|
|
42
|
+
>
|
|
33
43
|
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
34
44
|
</obc-tree-navigation-item>
|
|
35
45
|
<obc-tree-navigation-group
|
|
36
46
|
label="Auxiliary engine"
|
|
37
47
|
expanded
|
|
38
|
-
|
|
39
|
-
.alertCount=${3}
|
|
48
|
+
.alerts=${{aggregate: true, countLevelHigh: 1}}
|
|
40
49
|
>
|
|
41
50
|
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
42
51
|
<obc-tree-navigation-item label="Fuel pump">
|
|
@@ -44,8 +53,7 @@ const meta: Meta<typeof ObcTreeNavigation> = {
|
|
|
44
53
|
</obc-tree-navigation-item>
|
|
45
54
|
<obc-tree-navigation-item
|
|
46
55
|
label="Starter"
|
|
47
|
-
|
|
48
|
-
.alertCount=${1}
|
|
56
|
+
.alerts=${{countLevelHigh: 1}}
|
|
49
57
|
>
|
|
50
58
|
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
51
59
|
</obc-tree-navigation-item>
|
|
@@ -53,9 +61,16 @@ const meta: Meta<typeof ObcTreeNavigation> = {
|
|
|
53
61
|
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
54
62
|
</obc-tree-navigation-item>
|
|
55
63
|
</obc-tree-navigation-group>
|
|
56
|
-
<obc-tree-navigation-group
|
|
64
|
+
<obc-tree-navigation-group
|
|
65
|
+
label="Cooling system"
|
|
66
|
+
expanded
|
|
67
|
+
.alerts=${{aggregate: true, countLevelHigh: 1}}
|
|
68
|
+
>
|
|
57
69
|
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
58
|
-
<obc-tree-navigation-item
|
|
70
|
+
<obc-tree-navigation-item
|
|
71
|
+
label="Seawater pump"
|
|
72
|
+
.alerts=${{countLevelHigh: 1}}
|
|
73
|
+
>
|
|
59
74
|
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
60
75
|
</obc-tree-navigation-item>
|
|
61
76
|
</obc-tree-navigation-group>
|
|
@@ -160,3 +175,133 @@ export const Interactive: Story = {
|
|
|
160
175
|
render: () =>
|
|
161
176
|
html`<tree-navigation-selection-demo></tree-navigation-selection-demo>`,
|
|
162
177
|
};
|
|
178
|
+
|
|
179
|
+
/** The `alerts` count fields summed across a subtree, most to least severe. */
|
|
180
|
+
const COUNT_KEYS = [
|
|
181
|
+
'countLevelCritical',
|
|
182
|
+
'countLevelHigh',
|
|
183
|
+
'countLevelMedium',
|
|
184
|
+
'countLevelLow',
|
|
185
|
+
'countLevelDiagnostic',
|
|
186
|
+
] as const satisfies ReadonlyArray<keyof TreeNavigationItemAlerts>;
|
|
187
|
+
|
|
188
|
+
/** A node in the alert-demo tree: a leaf carries its own counts; a group has children. */
|
|
189
|
+
interface AlertNode {
|
|
190
|
+
label: string;
|
|
191
|
+
/** Per-severity counts for a leaf row. */
|
|
192
|
+
alerts?: TreeNavigationItemAlerts;
|
|
193
|
+
/** Child rows; presence makes this node a group. */
|
|
194
|
+
children?: AlertNode[];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Level severities spread across leaves at several depths. The whole tree totals
|
|
199
|
+
* 1 critical, 3 high, 10 medium, 5 low, and 0 diagnostic, so the rolled-up group
|
|
200
|
+
* totals are easy to verify by eye.
|
|
201
|
+
*/
|
|
202
|
+
const ALERT_TREE: AlertNode = {
|
|
203
|
+
label: 'Vessel',
|
|
204
|
+
children: [
|
|
205
|
+
{
|
|
206
|
+
label: 'Engine room',
|
|
207
|
+
children: [
|
|
208
|
+
{label: 'Main engine', alerts: {countLevelHigh: 1}},
|
|
209
|
+
{
|
|
210
|
+
label: 'Auxiliary engine',
|
|
211
|
+
children: [
|
|
212
|
+
{label: 'Fuel pump', alerts: {countLevelMedium: 4}},
|
|
213
|
+
{
|
|
214
|
+
label: 'Starter',
|
|
215
|
+
alerts: {countLevelCritical: 1, countLevelLow: 2},
|
|
216
|
+
},
|
|
217
|
+
{label: 'Oil filter', alerts: {countLevelMedium: 2}},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
label: 'Cooling system',
|
|
222
|
+
children: [
|
|
223
|
+
{
|
|
224
|
+
label: 'Seawater pump',
|
|
225
|
+
alerts: {countLevelHigh: 1, countLevelMedium: 3},
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
label: 'Bridge',
|
|
233
|
+
children: [
|
|
234
|
+
{label: 'Radar', alerts: {countLevelHigh: 1, countLevelLow: 3}},
|
|
235
|
+
{label: 'Autopilot'},
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
{label: 'Deck', alerts: {countLevelMedium: 1}},
|
|
239
|
+
],
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/** Sum every descendant leaf's counts, per severity, for a group header. */
|
|
243
|
+
function sumAlerts(node: AlertNode): TreeNavigationItemAlerts {
|
|
244
|
+
if (!node.children) return node.alerts ?? {};
|
|
245
|
+
const total: TreeNavigationItemAlerts = {};
|
|
246
|
+
for (const child of node.children) {
|
|
247
|
+
const childTotal = sumAlerts(child);
|
|
248
|
+
for (const key of COUNT_KEYS) {
|
|
249
|
+
const value = childTotal[key];
|
|
250
|
+
if (value) total[key] = (total[key] ?? 0) + value;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return total;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Render a node with every row using the given `aggregate` setting. Group rows
|
|
258
|
+
* carry the summed counts of their whole subtree; leaf rows carry their own
|
|
259
|
+
* counts. With `aggregate` true each row collapses to a single total badge;
|
|
260
|
+
* with it false each row shows one badge per non-zero severity.
|
|
261
|
+
*/
|
|
262
|
+
function renderAlertNode(node: AlertNode, aggregate: boolean): TemplateResult {
|
|
263
|
+
if (node.children) {
|
|
264
|
+
const alerts: TreeNavigationItemAlerts = {aggregate, ...sumAlerts(node)};
|
|
265
|
+
return html`<obc-tree-navigation-group
|
|
266
|
+
label=${node.label}
|
|
267
|
+
expanded
|
|
268
|
+
.alerts=${alerts}
|
|
269
|
+
>
|
|
270
|
+
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
271
|
+
${node.children.map((child) => renderAlertNode(child, aggregate))}
|
|
272
|
+
</obc-tree-navigation-group>`;
|
|
273
|
+
}
|
|
274
|
+
const alerts = node.alerts ? {aggregate, ...node.alerts} : undefined;
|
|
275
|
+
return html`<obc-tree-navigation-item label=${node.label} .alerts=${alerts}>
|
|
276
|
+
${iconIdToIconHtml('placeholder', {slot: 'icon'})}
|
|
277
|
+
</obc-tree-navigation-item>`;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Alerts spread across leaves at several depths, every row with
|
|
282
|
+
* `aggregate: true`. Each group header carries a single badge whose number is
|
|
283
|
+
* the sum of all alerts beneath it (child groups roll up into their parent in
|
|
284
|
+
* turn), styled as the most severe category present — e.g. "Auxiliary engine"
|
|
285
|
+
* totals 9 (1 critical + 6 medium + 2 low) and shows as critical, and "Vessel"
|
|
286
|
+
* totals 19 (1 critical + 3 high + 10 medium + 5 low) and also shows as critical.
|
|
287
|
+
*/
|
|
288
|
+
export const AggregatedAlertCounts: Story = {
|
|
289
|
+
render: () =>
|
|
290
|
+
html`<obc-tree-navigation>
|
|
291
|
+
${renderAlertNode(ALERT_TREE, true)}
|
|
292
|
+
</obc-tree-navigation>`,
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* The same tree and the same rolled-up totals, but every row with
|
|
297
|
+
* `aggregate: false`: each row renders one badge per non-zero severity instead
|
|
298
|
+
* of a single combined badge. Group headers still sum their whole subtree —
|
|
299
|
+
* e.g. "Auxiliary engine" shows separate critical (1), medium (6), and
|
|
300
|
+
* low (2) badges.
|
|
301
|
+
*/
|
|
302
|
+
export const PerSeverityAlertCounts: Story = {
|
|
303
|
+
render: () =>
|
|
304
|
+
html`<obc-tree-navigation>
|
|
305
|
+
${renderAlertNode(ALERT_TREE, false)}
|
|
306
|
+
</obc-tree-navigation>`,
|
|
307
|
+
};
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
TreeBranchType,
|
|
8
8
|
TreeTerminalType,
|
|
9
9
|
} from '../tree-navigation-item/tree-navigation-item.js';
|
|
10
|
+
import type {TreeNavigationItemAlerts} from '../tree-navigation-item/tree-navigation-item.js';
|
|
10
11
|
import '../tree-navigation-item/tree-navigation-item.js';
|
|
11
|
-
import {BadgeType} from '../badge/badge.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* `<obc-tree-navigation-group>` – An expandable parent row in a tree-navigation
|
|
@@ -16,7 +16,7 @@ import {BadgeType} from '../badge/badge.js';
|
|
|
16
16
|
* child rows it discloses.
|
|
17
17
|
*
|
|
18
18
|
* A group renders an `<obc-tree-navigation-item>` header (carrying its own label,
|
|
19
|
-
* icon, terminal type, and alert
|
|
19
|
+
* icon, terminal type, and alert badges) followed by its slotted children. When
|
|
20
20
|
* placed inside `<obc-tree-navigation>`, the container computes and assigns the
|
|
21
21
|
* `branches` guide lines for every row automatically from each row's position —
|
|
22
22
|
* a group does not need its depth configured by hand.
|
|
@@ -29,8 +29,7 @@ import {BadgeType} from '../badge/badge.js';
|
|
|
29
29
|
* - **Disclosure:** A chevron in the header toggles the slotted children. The open
|
|
30
30
|
* state is held in `expanded` and reflected so the container and CSS can react.
|
|
31
31
|
* - **Header presentation:** `label`, the `icon` slot, `terminalType`, and the
|
|
32
|
-
*
|
|
33
|
-
* header row.
|
|
32
|
+
* `alerts` count map are forwarded to the header row.
|
|
34
33
|
* - **Selection:** `checked` marks the group's header as the current item.
|
|
35
34
|
* - **Automatic guides:** Inside `<obc-tree-navigation>`, the header's `branches`
|
|
36
35
|
* are assigned by the container; nested groups continue the guide columns down.
|
|
@@ -83,14 +82,13 @@ export class ObcTreeNavigationGroup extends LitElement {
|
|
|
83
82
|
*/
|
|
84
83
|
@property({type: String}) terminalType: string = TreeTerminalType.regular;
|
|
85
84
|
|
|
86
|
-
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
@property({type: String}) alertType: string = BadgeType.alarm;
|
|
85
|
+
/**
|
|
86
|
+
* Per-severity alert counts shown as trailing badge(s) on the header row.
|
|
87
|
+
* Forwarded verbatim to the header `<obc-tree-navigation-item>` — typically a
|
|
88
|
+
* group sets `{aggregate: true, ...}` so its header shows one badge totalling
|
|
89
|
+
* the alerts of the rows beneath it. See {@link TreeNavigationItemAlerts}.
|
|
90
|
+
*/
|
|
91
|
+
@property({type: Object}) alerts?: TreeNavigationItemAlerts;
|
|
94
92
|
|
|
95
93
|
/**
|
|
96
94
|
* The URL to navigate to when the header is activated. If set, the header row
|
|
@@ -131,9 +129,7 @@ export class ObcTreeNavigationGroup extends LitElement {
|
|
|
131
129
|
?disabled=${this.disabled}
|
|
132
130
|
.hasLeadingIcon=${this.hasIcon}
|
|
133
131
|
.terminalType=${this.terminalType}
|
|
134
|
-
|
|
135
|
-
.alertCount=${this.alertCount}
|
|
136
|
-
.alertType=${this.alertType}
|
|
132
|
+
.alerts=${this.expanded ? undefined : this.alerts}
|
|
137
133
|
.href=${this.href}
|
|
138
134
|
@expand-toggle=${this.onHeaderToggle}
|
|
139
135
|
>
|
|
@@ -253,6 +253,18 @@
|
|
|
253
253
|
min-width: 0;
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
/*
|
|
257
|
+
* Trailing badge area. A row can carry more than one alert badge (e.g. a
|
|
258
|
+
* critical count beside a warning count); they sit in a flex row spaced by the
|
|
259
|
+
* shared alert-counter spacing token.
|
|
260
|
+
*/
|
|
261
|
+
.alert-badges {
|
|
262
|
+
flex-shrink: 0;
|
|
263
|
+
display: flex;
|
|
264
|
+
align-items: center;
|
|
265
|
+
gap: var(--app-components-alert-counter-item-badge-spacing);
|
|
266
|
+
}
|
|
267
|
+
|
|
256
268
|
.alert-badge {
|
|
257
269
|
flex-shrink: 0;
|
|
258
270
|
}
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
import './tree-navigation-item.js';
|
|
8
8
|
import {iconIds, iconIdToIconHtml} from '../../storybook-util.js';
|
|
9
9
|
import {html} from 'lit';
|
|
10
|
-
import {BadgeType} from '../badge/badge.js';
|
|
11
10
|
|
|
12
11
|
const meta: Meta<typeof ObcTreeNavigationItem> = {
|
|
13
12
|
title: 'UI Components/Menus and Navigation/Tree Navigation Item',
|
|
@@ -23,9 +22,7 @@ const meta: Meta<typeof ObcTreeNavigationItem> = {
|
|
|
23
22
|
disabled: false,
|
|
24
23
|
hasLeadingIcon: true,
|
|
25
24
|
terminalType: TreeTerminalType.regular,
|
|
26
|
-
|
|
27
|
-
alertCount: 9,
|
|
28
|
-
alertType: BadgeType.alarm,
|
|
25
|
+
alerts: undefined,
|
|
29
26
|
},
|
|
30
27
|
argTypes: {
|
|
31
28
|
icon: {
|
|
@@ -43,13 +40,7 @@ const meta: Meta<typeof ObcTreeNavigationItem> = {
|
|
|
43
40
|
control: {type: 'select'},
|
|
44
41
|
options: Object.values(TreeTerminalType),
|
|
45
42
|
},
|
|
46
|
-
|
|
47
|
-
alertCount: {control: {type: 'number'}},
|
|
48
|
-
alertType: {
|
|
49
|
-
control: {type: 'select'},
|
|
50
|
-
options: Object.values(BadgeType),
|
|
51
|
-
if: {arg: 'hasAlertBadge'},
|
|
52
|
-
},
|
|
43
|
+
alerts: {control: {type: 'object'}},
|
|
53
44
|
},
|
|
54
45
|
render: (args) => {
|
|
55
46
|
return html`<obc-tree-navigation-item
|
|
@@ -61,9 +52,7 @@ const meta: Meta<typeof ObcTreeNavigationItem> = {
|
|
|
61
52
|
?disabled=${args.disabled}
|
|
62
53
|
.hasLeadingIcon=${args.hasLeadingIcon}
|
|
63
54
|
.terminalType=${args.terminalType}
|
|
64
|
-
.
|
|
65
|
-
.alertCount=${args.alertCount}
|
|
66
|
-
.alertType=${args.alertType}
|
|
55
|
+
.alerts=${args.alerts}
|
|
67
56
|
@expand-toggle=${(e: CustomEvent<boolean>) => {
|
|
68
57
|
(e.currentTarget as ObcTreeNavigationItem).expanded = e.detail;
|
|
69
58
|
}}
|
|
@@ -106,8 +95,42 @@ export const IndentedNoConnectors: Story = {
|
|
|
106
95
|
args: {branches: [TreeBranchType.blank, TreeBranchType.blank]},
|
|
107
96
|
};
|
|
108
97
|
|
|
98
|
+
/** A single alert badge from one non-zero count in the `alerts` map. */
|
|
109
99
|
export const WithAlertBadge: Story = {
|
|
110
|
-
args: {
|
|
100
|
+
args: {alerts: {countLevelHigh: 9}},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Several severities at once. With `aggregate` unset, each non-zero count
|
|
105
|
+
* renders its own badge, ordered most to least severe and spaced by
|
|
106
|
+
* `var(--app-components-alert-counter-item-badge-spacing)`.
|
|
107
|
+
*/
|
|
108
|
+
export const MultipleAlertBadges: Story = {
|
|
109
|
+
args: {
|
|
110
|
+
alerts: {
|
|
111
|
+
countLevelCritical: 1,
|
|
112
|
+
countLevelHigh: 3,
|
|
113
|
+
countLevelMedium: 12,
|
|
114
|
+
countLevelLow: 2,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The same counts as `MultipleAlertBadges`, but `aggregate: true` collapses them
|
|
121
|
+
* into one badge: the number is the combined total (18) and the style is the
|
|
122
|
+
* highest category present (level-critical).
|
|
123
|
+
*/
|
|
124
|
+
export const AggregatedAlertBadge: Story = {
|
|
125
|
+
args: {
|
|
126
|
+
alerts: {
|
|
127
|
+
aggregate: true,
|
|
128
|
+
countLevelCritical: 1,
|
|
129
|
+
countLevelHigh: 3,
|
|
130
|
+
countLevelMedium: 12,
|
|
131
|
+
countLevelLow: 2,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
111
134
|
};
|
|
112
135
|
|
|
113
136
|
export const AggregatedHeader: Story = {
|