@foxeltech/angular-ui 0.7.83 → 0.7.101
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/components.css +40 -1
- package/fesm2022/foxeltech-angular-ui-chart.mjs +33 -3
- package/fesm2022/foxeltech-angular-ui-chart.mjs.map +1 -1
- package/fesm2022/foxeltech-angular-ui-flow.mjs +42 -5
- package/fesm2022/foxeltech-angular-ui-flow.mjs.map +1 -1
- package/fesm2022/foxeltech-angular-ui.mjs +559 -42
- package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
- package/package.json +3 -2
- package/src/lib/styles/components.css +40 -1
- package/src/lib/styles/utilities.css +2 -1
- package/src/lib/ui/components/breadcrumb/breadcrumb.component.css +262 -0
- package/src/lib/ui/components/breadcrumb/breadcrumb.component.html +91 -0
- package/src/lib/ui/components/button/button.component.html +1 -0
- package/src/lib/ui/components/filter-pills/filter-pills.component.html +1 -1
- package/src/lib/ui/components/load-status/load-status.component.css +96 -0
- package/src/lib/ui/components/load-status/load-status.component.html +20 -0
- package/src/lib/ui/components/master-detail/master-detail.component.css +63 -11
- package/src/lib/ui/components/master-detail/master-detail.component.html +71 -42
- package/src/lib/ui/components/route-skeleton/route-skeleton.component.css +1 -1
- package/src/lib/ui/components/segmented/segmented.component.html +3 -1
- package/src/lib/ui/components/severity-badges/severity-badges.component.html +1 -1
- package/src/lib/ui/components/stat-cards/stat-cards.component.css +18 -0
- package/src/lib/ui/components/stat-cards/stat-cards.component.html +3 -3
- package/types/foxeltech-angular-ui-chart.d.ts +18 -1
- package/types/foxeltech-angular-ui-flow.d.ts +7 -0
- package/types/foxeltech-angular-ui.d.ts +309 -8
- package/utilities.css +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foxeltech-angular-ui-flow.mjs","sources":["../../../projects/ui/flow/src/flow-canvas/flow-canvas.component.ts","../../../projects/ui/flow/src/flow-canvas/flow-canvas.component.html","../../../projects/ui/flow/src/flow-connection/flow-connection.component.ts","../../../projects/ui/flow/src/flow-connection/flow-connection.component.html","../../../projects/ui/flow/src/foxeltech-angular-ui-flow.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n input,\n output,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\nimport {\n Edge,\n EdgeTemplateDirective,\n HandleComponent,\n Node,\n NodeHtmlTemplateDirective,\n VflowComponent,\n} from 'ngx-vflow';\n\n/**\n * What a chain node represents. Structural kinds (`entry`, `convergence`,\n * `impact`, `stage`) can be derived from the graph itself; the validation kinds\n * (`mitigation`, `review`, `not-reproduced`) come from an analyst verdict.\n */\nexport type FxChainNodeKind =\n | 'entry'\n | 'convergence'\n | 'mitigation'\n | 'review'\n | 'not-reproduced'\n | 'impact'\n | 'stage';\n\nexport interface FxChainNode {\n id: string;\n /** Node title — rendered in the figure/mono face. */\n label: string;\n kind: FxChainNodeKind;\n /** Caller-translated kind eyebrow; falls back to the raw kind key. */\n kindLabel?: string;\n /** Caller-translated muted subtitle. */\n caption?: string;\n /** true = verified badge, false = unverified badge, null/undefined = no badge. */\n verified?: boolean | null;\n /** Explicit column (0 = leftmost); omit to derive depth from the edges. */\n column?: number;\n /** Explicit row inside the column; omit to stack in declaration order. */\n row?: number;\n}\n\nexport interface FxChainEdge {\n source: string;\n target: string;\n}\n\n/** Kind → severity token. Exported so callers can tint matching chips (the\n stage list beside the canvas) from the same source of truth. */\nexport const FX_CHAIN_KIND_TONE: Record<FxChainNodeKind, string> = {\n entry: 'warning',\n convergence: 'information',\n mitigation: 'success',\n review: 'warning',\n 'not-reproduced': 'danger',\n impact: 'critical',\n stage: 'information',\n};\n\nconst COLUMN_GAP = 216;\nconst ROW_GAP = 104;\nconst NODE_WIDTH = 176;\nconst NODE_HEIGHT = 66;\n\n/**\n * V2 exploit-chain canvas — the attack-path graph of design refs 04..07:\n * kind-tinted node cards laid out left→right, curved edges, draggable nodes on\n * a pannable/zoomable surface.\n *\n * Presentational: it takes a graph plus the currently selected node and emits\n * clicks. Layout is derived from the edges (longest path from a source) unless\n * a node pins its own column/row, so callers can hand over a plain chain.\n *\n * <fx-ui-flow-canvas [nodes]=\"chainNodes\" [edges]=\"chainEdges\"\n * [activeId]=\"stageId()\" (nodeClick)=\"selectStage($event)\" />\n */\n@Component({\n selector: 'fx-ui-flow-canvas',\n templateUrl: './flow-canvas.component.html',\n styleUrl: './flow-canvas.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgClass,\n VflowComponent,\n NodeHtmlTemplateDirective,\n EdgeTemplateDirective,\n HandleComponent,\n ],\n})\nexport class FlowCanvasComponent {\n readonly nodes = input<FxChainNode[]>([]);\n readonly edges = input<FxChainEdge[]>([]);\n /** Selected/current node: full opacity + accent border; the rest dim. */\n readonly activeId = input<string | null>(null);\n /** Explicit canvas height; omit to size it from the number of stacked rows. */\n readonly height = input('');\n /** Caller-translated hint shown when the graph is empty. */\n readonly emptyText = input('No chain data available');\n\n readonly nodeClick = output<string>();\n\n /** Column index per node: pinned value, else longest path from a source. */\n private readonly columns = computed<Record<string, number>>(() => {\n const nodes = this.nodes();\n const edges = this.edges();\n const incoming = new Map<string, string[]>();\n nodes.forEach((n) => incoming.set(n.id, []));\n edges.forEach((e) => incoming.get(e.target)?.push(e.source));\n\n const depth: Record<string, number> = {};\n const resolve = (id: string, seen: Set<string>): number => {\n if (depth[id] !== undefined) return depth[id];\n // Cycle guard: a malformed graph must not blow the stack.\n if (seen.has(id)) return 0;\n seen.add(id);\n const parents = incoming.get(id) ?? [];\n const value = parents.length\n ? Math.max(...parents.map((p) => resolve(p, seen))) + 1\n : 0;\n depth[id] = value;\n return value;\n };\n nodes.forEach((n) => {\n depth[n.id] = n.column ?? resolve(n.id, new Set());\n });\n return depth;\n });\n\n /** ngx-vflow nodes: html-template cards positioned by the derived layout. */\n readonly flowNodes = computed<Node[]>(() => {\n const columns = this.columns();\n const perColumn: Record<number, number> = {};\n // Tallest column decides the vertical centre every column is balanced on.\n const counts: Record<number, number> = {};\n this.nodes().forEach((n) => {\n const c = columns[n.id] ?? 0;\n counts[c] = (counts[c] ?? 0) + 1;\n });\n const tallest = Math.max(1, ...Object.values(counts));\n\n return this.nodes().map((node) => {\n const column = columns[node.id] ?? 0;\n const row = node.row ?? perColumn[column] ?? 0;\n perColumn[column] = row + 1;\n const rows = counts[column] ?? 1;\n const offset = ((tallest - rows) * ROW_GAP) / 2;\n return {\n id: node.id,\n type: 'html-template' as const,\n point: { x: 24 + column * COLUMN_GAP, y: 24 + offset + row * ROW_GAP },\n width: NODE_WIDTH,\n height: NODE_HEIGHT,\n data: node,\n };\n });\n });\n\n /**\n * Edges stay identity-stable across selections: state lives in the template\n * (read off `activeId`), so selecting a stage never re-creates them.\n */\n readonly flowEdges = computed<Edge[]>(() =>\n this.edges().map((e) => ({\n id: `${e.source}->${e.target}`,\n source: e.source,\n target: e.target,\n type: 'template' as const,\n curve: 'bezier' as const,\n markers: { end: { type: 'arrow-closed' as const, width: 11, height: 11 } },\n })),\n );\n\n /** Nodes one hop from the selection — they stay lit alongside it. */\n private readonly relatedIds = computed<Set<string>>(() => {\n const active = this.activeId();\n const related = new Set<string>();\n if (!active) return related;\n this.edges().forEach((e) => {\n if (e.source === active) related.add(e.target);\n if (e.target === active) related.add(e.source);\n });\n return related;\n });\n\n readonly isEmpty = computed(() => this.nodes().length === 0);\n\n /**\n * A linear chain needs one row, the design's converging entries need three —\n * sizing from the layout keeps the card from leaving a tall empty band.\n */\n readonly resolvedHeight = computed(() => {\n const explicit = this.height();\n if (explicit) return explicit;\n const counts: Record<number, number> = {};\n const columns = this.columns();\n this.nodes().forEach((n) => {\n const c = columns[n.id] ?? 0;\n counts[c] = (counts[c] ?? 0) + 1;\n });\n const rows = Math.max(1, ...Object.values(counts));\n return `${48 + rows * ROW_GAP}px`;\n });\n\n kindTone(kind: FxChainNodeKind): string {\n return FX_CHAIN_KIND_TONE[kind] ?? 'information';\n }\n\n isActive(node: FxChainNode): boolean {\n const active = this.activeId();\n return active != null && active === node.id;\n }\n\n /** One hop from the selection: lit, but without the selected accent frame. */\n isRelated(node: FxChainNode): boolean {\n return !this.isActive(node) && this.relatedIds().has(node.id);\n }\n\n /** Nothing selected → every node reads at full strength. */\n isDimmed(node: FxChainNode): boolean {\n return this.activeId() != null && !this.isActive(node) && !this.isRelated(node);\n }\n\n /** An edge touching the selection is part of the step being read. */\n isEdgeActive(edge: Edge): boolean {\n const active = this.activeId();\n return active != null && (edge.source === active || edge.target === active);\n }\n\n isEdgeDimmed(edge: Edge): boolean {\n return this.activeId() != null && !this.isEdgeActive(edge);\n }\n}\n","<ng-template #blankHandle></ng-template>\n\n@if (isEmpty()) {\n <div\n class=\"flex items-center justify-center rounded-card border border-border bg-surface-sunken txt-body-01 text-text-placeholder\"\n [style.height]=\"resolvedHeight()\"\n >\n {{ emptyText() }}\n </div>\n} @else {\n <!-- view=\"auto\" sizes the flow from this wrapper, so the height input is the\n single source of truth for the canvas box. -->\n <div class=\"fx-chain-canvas rounded-card border border-border overflow-hidden\" [style.height]=\"resolvedHeight()\">\n <vflow\n view=\"auto\"\n [nodes]=\"flowNodes()\"\n [edges]=\"flowEdges()\"\n [minZoom]=\"0.4\"\n [maxZoom]=\"1.6\"\n [entitiesSelectable]=\"false\"\n background=\"rgba(var(--og-surface-sunken) / 1)\"\n >\n <ng-template let-ctx nodeHtml>\n <!-- Handles are what edges anchor to: without them vflow renders the\n cards but draws no connections. The graph is read-only here, so an\n empty template replaces vflow's default handle dot (it only draws\n one when the template is null) while keeping the anchor point. -->\n <handle type=\"target\" position=\"left\" [template]=\"blankHandle\" />\n <handle type=\"source\" position=\"right\" [template]=\"blankHandle\" />\n <button\n type=\"button\"\n class=\"fx-chain-node\"\n [ngClass]=\"{\n 'fx-chain-node--active': isActive(ctx.node.data),\n 'fx-chain-node--related': isRelated(ctx.node.data),\n 'fx-chain-node--dim': isDimmed(ctx.node.data),\n }\"\n (click)=\"nodeClick.emit(ctx.node.data.id)\"\n >\n <span class=\"fx-chain-node__eyebrow\">\n <span class=\"fx-chain-node__dot\" [ngClass]=\"'bg-' + kindTone(ctx.node.data.kind)\"></span>\n <span [ngClass]=\"'text-' + kindTone(ctx.node.data.kind)\">{{ ctx.node.data.kindLabel || ctx.node.data.kind }}</span>\n @if (ctx.node.data.verified !== null && ctx.node.data.verified !== undefined) {\n <span\n class=\"fx-chain-node__check\"\n [ngClass]=\"ctx.node.data.verified ? 'bg-success/20 text-success' : 'bg-bg-hover text-text-placeholder'\"\n >\n {{ ctx.node.data.verified ? '✓' : '○' }}\n </span>\n }\n </span>\n <span class=\"fx-chain-node__label\">{{ ctx.node.data.label }}</span>\n @if (ctx.node.data.caption) {\n <span class=\"fx-chain-node__caption\">{{ ctx.node.data.caption }}</span>\n }\n </button>\n </ng-template>\n\n <!-- Edge state is read from activeId here rather than baked into the edge\n objects, so selecting a stage restyles without re-creating them.\n The arrowhead only shows on the selected step (design 04). -->\n <ng-template let-ctx edge>\n <svg:path\n class=\"fx-chain-edge\"\n [class.fx-chain-edge--active]=\"isEdgeActive(ctx.edge)\"\n [class.fx-chain-edge--dim]=\"isEdgeDimmed(ctx.edge)\"\n [attr.d]=\"ctx.path()\"\n [attr.marker-end]=\"isEdgeActive(ctx.edge) ? ctx.markerEnd() : null\"\n />\n </ng-template>\n </vflow>\n </div>\n}\n","import { Component, Input, ChangeDetectionStrategy, input } from '@angular/core';\nimport { Node, Edge, Vflow, Connection, ChangesControllerDirective, VflowComponent, ConnectionControllerDirective } from 'ngx-vflow';\n\n@Component({\n selector: 'fx-ui-flow-connection',\n templateUrl: './flow-connection.component.html',\n styleUrl: './flow-connection.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ChangesControllerDirective,\n VflowComponent,\n ConnectionControllerDirective,\n ],\n})\nexport class FlowConnection {\n readonly nodes = input<Node[]>([]);\n @Input() edges: Edge[] = [];\n readonly backgroundColor = input<any>('--bg-hover-primary');\n readonly view = input<any>(['100%', '400px']);\n\n handleConnection(connection: Connection) {\n this.edges = [\n ...this.edges,\n {\n id: `${connection.source} -> ${connection.target}`,\n ...connection,\n },\n ];\n }\n}\n","<vflow\n [background]=\"{\n type: 'solid',\n color: `rgba(var(${backgroundColor()})`\n}\"\n [nodes]=\"nodes()\"\n [edges]=\"edges\"\n (onConnect)=\"handleConnection($event)\"\n [view]=\"view()\"\n/>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"foxeltech-angular-ui-flow.mjs","sources":["../../../projects/ui/flow/src/flow-canvas/flow-canvas.component.ts","../../../projects/ui/flow/src/flow-canvas/flow-canvas.component.html","../../../projects/ui/flow/src/flow-connection/flow-connection.component.ts","../../../projects/ui/flow/src/flow-connection/flow-connection.component.html","../../../projects/ui/flow/src/foxeltech-angular-ui-flow.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n afterRenderEffect,\n computed,\n inject,\n input,\n output,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\nimport {\n Edge,\n EdgeTemplateDirective,\n HandleComponent,\n Node,\n NodeHtmlTemplateDirective,\n VflowComponent,\n} from 'ngx-vflow';\n\n/**\n * What a chain node represents. Structural kinds (`entry`, `convergence`,\n * `impact`, `stage`) can be derived from the graph itself; the validation kinds\n * (`mitigation`, `review`, `not-reproduced`) come from an analyst verdict.\n */\nexport type FxChainNodeKind =\n | 'entry'\n | 'convergence'\n | 'mitigation'\n | 'review'\n | 'not-reproduced'\n | 'impact'\n | 'stage';\n\nexport interface FxChainNode {\n id: string;\n /** Node title — rendered in the figure/mono face. */\n label: string;\n kind: FxChainNodeKind;\n /** Caller-translated kind eyebrow; falls back to the raw kind key. */\n kindLabel?: string;\n /** Caller-translated muted subtitle. */\n caption?: string;\n /** true = verified badge, false = unverified badge, null/undefined = no badge. */\n verified?: boolean | null;\n /** Explicit column (0 = leftmost); omit to derive depth from the edges. */\n column?: number;\n /** Explicit row inside the column; omit to stack in declaration order. */\n row?: number;\n}\n\nexport interface FxChainEdge {\n source: string;\n target: string;\n}\n\n/** Kind → severity token. Exported so callers can tint matching chips (the\n stage list beside the canvas) from the same source of truth. */\nexport const FX_CHAIN_KIND_TONE: Record<FxChainNodeKind, string> = {\n entry: 'warning',\n convergence: 'information',\n mitigation: 'success',\n review: 'warning',\n 'not-reproduced': 'danger',\n impact: 'critical',\n stage: 'information',\n};\n\nconst COLUMN_GAP = 216;\nconst ROW_GAP = 104;\nconst NODE_WIDTH = 176;\nconst NODE_HEIGHT = 66;\n\n/**\n * V2 exploit-chain canvas — the attack-path graph of design refs 04..07:\n * kind-tinted node cards laid out left→right, curved edges, draggable nodes on\n * a pannable/zoomable surface.\n *\n * Presentational: it takes a graph plus the currently selected node and emits\n * clicks. Layout is derived from the edges (longest path from a source) unless\n * a node pins its own column/row, so callers can hand over a plain chain.\n *\n * <fx-ui-flow-canvas [nodes]=\"chainNodes\" [edges]=\"chainEdges\"\n * [activeId]=\"stageId()\" (nodeClick)=\"selectStage($event)\" />\n */\n@Component({\n selector: 'fx-ui-flow-canvas',\n templateUrl: './flow-canvas.component.html',\n styleUrl: './flow-canvas.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgClass,\n VflowComponent,\n NodeHtmlTemplateDirective,\n EdgeTemplateDirective,\n HandleComponent,\n ],\n})\nexport class FlowCanvasComponent {\n readonly nodes = input<FxChainNode[]>([]);\n readonly edges = input<FxChainEdge[]>([]);\n /** Selected/current node: full opacity + accent border; the rest dim. */\n readonly activeId = input<string | null>(null);\n /** Explicit canvas height; omit to size it from the number of stacked rows. */\n readonly height = input('');\n /** Caller-translated hint shown when the graph is empty. */\n readonly emptyText = input('No chain data available');\n\n readonly nodeClick = output<string>();\n\n private readonly flow = viewChild(VflowComponent);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n\n constructor() {\n // `view=\"auto\"` only sizes vflow's viewport to the wrapper — it does not\n // frame the graph, so a taller canvas left the chain pinned top-left and\n // clipped (anh Tú 04/09). Fit whenever the graph or the box changes.\n afterRenderEffect(() => {\n const flow = this.flow();\n this.flowNodes();\n this.resolvedHeight();\n if (!flow) return;\n untracked(() => this.scheduleFit());\n });\n if (typeof ResizeObserver !== 'undefined') {\n const ro = new ResizeObserver(() => this.scheduleFit());\n ro.observe(this.host.nativeElement);\n this.destroyRef.onDestroy(() => ro.disconnect());\n }\n }\n\n private fitHandle: number | null = null;\n /** Coalesces fit requests into one frame after vflow has measured its nodes. */\n private scheduleFit(): void {\n if (this.fitHandle !== null) return;\n this.fitHandle = requestAnimationFrame(() => {\n this.fitHandle = null;\n const flow = this.flow();\n if (!flow || this.isEmpty()) return;\n // Design 04: cards fill the width with a little air (0.18 left them at\n // ~0.74×, visibly smaller than the mock — measured 04/09).\n flow.fitView({ padding: 0.1, duration: 0 });\n });\n }\n\n /** Column index per node: pinned value, else longest path from a source. */\n private readonly columns = computed<Record<string, number>>(() => {\n const nodes = this.nodes();\n const edges = this.edges();\n const incoming = new Map<string, string[]>();\n nodes.forEach((n) => incoming.set(n.id, []));\n edges.forEach((e) => incoming.get(e.target)?.push(e.source));\n\n const depth: Record<string, number> = {};\n const resolve = (id: string, seen: Set<string>): number => {\n if (depth[id] !== undefined) return depth[id];\n // Cycle guard: a malformed graph must not blow the stack.\n if (seen.has(id)) return 0;\n seen.add(id);\n const parents = incoming.get(id) ?? [];\n const value = parents.length\n ? Math.max(...parents.map((p) => resolve(p, seen))) + 1\n : 0;\n depth[id] = value;\n return value;\n };\n nodes.forEach((n) => {\n depth[n.id] = n.column ?? resolve(n.id, new Set());\n });\n return depth;\n });\n\n /** ngx-vflow nodes: html-template cards positioned by the derived layout. */\n readonly flowNodes = computed<Node[]>(() => {\n const columns = this.columns();\n const perColumn: Record<number, number> = {};\n // Tallest column decides the vertical centre every column is balanced on.\n const counts: Record<number, number> = {};\n this.nodes().forEach((n) => {\n const c = columns[n.id] ?? 0;\n counts[c] = (counts[c] ?? 0) + 1;\n });\n const tallest = Math.max(1, ...Object.values(counts));\n\n return this.nodes().map((node) => {\n const column = columns[node.id] ?? 0;\n const row = node.row ?? perColumn[column] ?? 0;\n perColumn[column] = row + 1;\n const rows = counts[column] ?? 1;\n const offset = ((tallest - rows) * ROW_GAP) / 2;\n return {\n id: node.id,\n type: 'html-template' as const,\n point: { x: 24 + column * COLUMN_GAP, y: 24 + offset + row * ROW_GAP },\n width: NODE_WIDTH,\n height: NODE_HEIGHT,\n data: node,\n };\n });\n });\n\n /**\n * Edges stay identity-stable across selections: state lives in the template\n * (read off `activeId`), so selecting a stage never re-creates them.\n */\n readonly flowEdges = computed<Edge[]>(() =>\n this.edges().map((e) => ({\n id: `${e.source}->${e.target}`,\n source: e.source,\n target: e.target,\n type: 'template' as const,\n curve: 'bezier' as const,\n markers: { end: { type: 'arrow-closed' as const, width: 11, height: 11 } },\n })),\n );\n\n /** Nodes one hop from the selection — they stay lit alongside it. */\n private readonly relatedIds = computed<Set<string>>(() => {\n const active = this.activeId();\n const related = new Set<string>();\n if (!active) return related;\n this.edges().forEach((e) => {\n if (e.source === active) related.add(e.target);\n if (e.target === active) related.add(e.source);\n });\n return related;\n });\n\n readonly isEmpty = computed(() => this.nodes().length === 0);\n\n /**\n * A linear chain needs one row, the design's converging entries need three —\n * sizing from the layout keeps the card from leaving a tall empty band.\n */\n readonly resolvedHeight = computed(() => {\n const explicit = this.height();\n if (explicit) return explicit;\n const counts: Record<number, number> = {};\n const columns = this.columns();\n this.nodes().forEach((n) => {\n const c = columns[n.id] ?? 0;\n counts[c] = (counts[c] ?? 0) + 1;\n });\n const rows = Math.max(1, ...Object.values(counts));\n // Floor at 300px: a one-row chain in a 152px band read too small (04/09).\n return `${Math.max(300, 48 + rows * ROW_GAP)}px`;\n });\n\n kindTone(kind: FxChainNodeKind): string {\n return FX_CHAIN_KIND_TONE[kind] ?? 'information';\n }\n\n isActive(node: FxChainNode): boolean {\n const active = this.activeId();\n return active != null && active === node.id;\n }\n\n /** One hop from the selection: lit, but without the selected accent frame. */\n isRelated(node: FxChainNode): boolean {\n return !this.isActive(node) && this.relatedIds().has(node.id);\n }\n\n /** Nothing selected → every node reads at full strength. */\n isDimmed(node: FxChainNode): boolean {\n return this.activeId() != null && !this.isActive(node) && !this.isRelated(node);\n }\n\n /** An edge touching the selection is part of the step being read. */\n isEdgeActive(edge: Edge): boolean {\n const active = this.activeId();\n return active != null && (edge.source === active || edge.target === active);\n }\n\n isEdgeDimmed(edge: Edge): boolean {\n return this.activeId() != null && !this.isEdgeActive(edge);\n }\n}\n","<ng-template #blankHandle></ng-template>\n\n@if (isEmpty()) {\n <div\n class=\"flex items-center justify-center rounded-card border border-border bg-surface-sunken txt-body-01 text-text-placeholder\"\n [style.height]=\"resolvedHeight()\"\n >\n {{ emptyText() }}\n </div>\n} @else {\n <!-- view=\"auto\" sizes the flow from this wrapper, so the height input is the\n single source of truth for the canvas box. -->\n <div class=\"fx-chain-canvas rounded-card border border-border overflow-hidden\" [style.height]=\"resolvedHeight()\">\n <vflow\n view=\"auto\"\n [nodes]=\"flowNodes()\"\n [edges]=\"flowEdges()\"\n [minZoom]=\"0.4\"\n [maxZoom]=\"1.35\"\n [entitiesSelectable]=\"false\"\n background=\"rgba(var(--og-surface-sunken) / 1)\"\n >\n <ng-template let-ctx nodeHtml>\n <!-- Handles are what edges anchor to: without them vflow renders the\n cards but draws no connections. The graph is read-only here, so an\n empty template replaces vflow's default handle dot (it only draws\n one when the template is null) while keeping the anchor point. -->\n <handle type=\"target\" position=\"left\" [template]=\"blankHandle\" />\n <handle type=\"source\" position=\"right\" [template]=\"blankHandle\" />\n <button\n type=\"button\"\n class=\"fx-chain-node\"\n [ngClass]=\"{\n 'fx-chain-node--active': isActive(ctx.node.data),\n 'fx-chain-node--related': isRelated(ctx.node.data),\n 'fx-chain-node--dim': isDimmed(ctx.node.data),\n }\"\n (click)=\"nodeClick.emit(ctx.node.data.id)\"\n >\n <span class=\"fx-chain-node__eyebrow\">\n <span class=\"fx-chain-node__dot\" [ngClass]=\"'bg-' + kindTone(ctx.node.data.kind)\"></span>\n <span [ngClass]=\"'text-' + kindTone(ctx.node.data.kind)\">{{ ctx.node.data.kindLabel || ctx.node.data.kind }}</span>\n @if (ctx.node.data.verified !== null && ctx.node.data.verified !== undefined) {\n <span\n class=\"fx-chain-node__check\"\n [ngClass]=\"ctx.node.data.verified ? 'bg-success/20 text-success' : 'bg-bg-hover text-text-placeholder'\"\n >\n {{ ctx.node.data.verified ? '✓' : '○' }}\n </span>\n }\n </span>\n <span class=\"fx-chain-node__label\">{{ ctx.node.data.label }}</span>\n @if (ctx.node.data.caption) {\n <span class=\"fx-chain-node__caption\">{{ ctx.node.data.caption }}</span>\n }\n </button>\n </ng-template>\n\n <!-- Edge state is read from activeId here rather than baked into the edge\n objects, so selecting a stage restyles without re-creating them.\n The arrowhead only shows on the selected step (design 04). -->\n <ng-template let-ctx edge>\n <svg:path\n class=\"fx-chain-edge\"\n [class.fx-chain-edge--active]=\"isEdgeActive(ctx.edge)\"\n [class.fx-chain-edge--dim]=\"isEdgeDimmed(ctx.edge)\"\n [attr.d]=\"ctx.path()\"\n [attr.marker-end]=\"isEdgeActive(ctx.edge) ? ctx.markerEnd() : null\"\n />\n </ng-template>\n </vflow>\n </div>\n}\n","import { Component, Input, ChangeDetectionStrategy, input } from '@angular/core';\nimport { Node, Edge, Vflow, Connection, ChangesControllerDirective, VflowComponent, ConnectionControllerDirective } from 'ngx-vflow';\n\n@Component({\n selector: 'fx-ui-flow-connection',\n templateUrl: './flow-connection.component.html',\n styleUrl: './flow-connection.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n ChangesControllerDirective,\n VflowComponent,\n ConnectionControllerDirective,\n ],\n})\nexport class FlowConnection {\n readonly nodes = input<Node[]>([]);\n @Input() edges: Edge[] = [];\n readonly backgroundColor = input<any>('--bg-hover-primary');\n readonly view = input<any>(['100%', '400px']);\n\n handleConnection(connection: Connection) {\n this.edges = [\n ...this.edges,\n {\n id: `${connection.source} -> ${connection.target}`,\n ...connection,\n },\n ];\n }\n}\n","<vflow\n [background]=\"{\n type: 'solid',\n color: `rgba(var(${backgroundColor()})`\n}\"\n [nodes]=\"nodes()\"\n [edges]=\"edges\"\n (onConnect)=\"handleConnection($event)\"\n [view]=\"view()\"\n/>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|