@praxisui/page-builder 9.0.65 → 9.0.67
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/README.md +162 -2
- package/ai/component-registry.json +13 -7
- package/fesm2022/praxisui-page-builder.mjs +1570 -187
- package/package.json +4 -4
- package/types/praxisui-page-builder.d.ts +108 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Inject, ChangeDetectionStrategy, Component, EventEmitter, Output, Input, inject, ElementRef, signal, computed, effect, Optional, input, output, InjectionToken, ENVIRONMENT_INITIALIZER, Injectable, Injector, ViewChild } from '@angular/core';
|
|
2
|
+
import { Inject, ChangeDetectionStrategy, Component, EventEmitter, Output, Input, inject, ElementRef, signal, computed, effect, Optional, input, output, afterEveryRender, InjectionToken, ENVIRONMENT_INITIALIZER, Injectable, Injector, ViewChild } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/material/button';
|
|
4
4
|
import { MatButtonModule } from '@angular/material/button';
|
|
5
5
|
import * as i1 from '@angular/material/dialog';
|
|
@@ -7,10 +7,10 @@ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
|
7
7
|
import * as i2$1 from '@angular/material/icon';
|
|
8
8
|
import { MatIconModule } from '@angular/material/icon';
|
|
9
9
|
import * as i2$2 from '@praxisui/core';
|
|
10
|
-
import { PraxisIconDirective, providePraxisI18n, BUILTIN_SHELL_PRESETS,
|
|
10
|
+
import { PraxisIconDirective, providePraxisI18n, BUILTIN_SHELL_PRESETS, PraxisI18nService, PraxisIconButtonComponent, GLOBAL_ACTION_CATALOG, ComponentMetadataRegistry, CompositionValidatorService, getGlobalActionCatalog, PRAXIS_GLOBAL_ACTION_CATALOG, SurfaceOpenActionEditorComponent, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, PraxisJsonLogicService, NestedWidgetConfigAccessor, canonicalJsonSha256, ResourceDiscoveryService, ComponentRuntimeProfileService, buildApiUrl, deepMerge, generateId, ObservabilityDashboardService, PraxisRuntimeComponentObservationRegistryService, domainKnowledgeTimelineToRichContentDocument, DomainRuleService, DomainKnowledgeService, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
|
|
11
11
|
import * as i3 from '@angular/material/tooltip';
|
|
12
12
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
13
|
-
import * as
|
|
13
|
+
import * as i4 from '@angular/material/form-field';
|
|
14
14
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
15
15
|
import * as i5 from '@angular/material/input';
|
|
16
16
|
import { MatInputModule } from '@angular/material/input';
|
|
@@ -22,13 +22,15 @@ import * as i5$1 from '@angular/material/checkbox';
|
|
|
22
22
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
23
23
|
import * as i6 from '@angular/material/divider';
|
|
24
24
|
import { MatDividerModule } from '@angular/material/divider';
|
|
25
|
-
import * as
|
|
25
|
+
import * as i10 from '@angular/material/select';
|
|
26
26
|
import { MatSelectModule } from '@angular/material/select';
|
|
27
27
|
import { BehaviorSubject, merge, timeout, map, catchError, throwError, firstValueFrom, from, share, concatMap, of, timer, takeUntil, Subject, tap, filter, take } from 'rxjs';
|
|
28
28
|
import { SETTINGS_PANEL_DATA } from '@praxisui/settings-panel';
|
|
29
29
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
30
30
|
import { CdkTrapFocus } from '@angular/cdk/a11y';
|
|
31
|
-
import * as
|
|
31
|
+
import * as i3$1 from '@angular/material/button-toggle';
|
|
32
|
+
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
33
|
+
import * as i8 from '@angular/material/tabs';
|
|
32
34
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
33
35
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
|
34
36
|
import { AgenticAuthoringTurnClientService, withAuthoringScopePolicyContextHints, toPraxisAssistantConversationMessages, PraxisAssistantTurnOrchestratorService, PraxisAssistantSessionRegistryService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
|
|
@@ -361,6 +363,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
361
363
|
}] } });
|
|
362
364
|
|
|
363
365
|
const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
366
|
+
"praxis.pageBuilder.editor.devices.target": "Device to configure",
|
|
367
|
+
"praxis.pageBuilder.editor.devices.advanced": "Advanced overrides",
|
|
368
|
+
"praxis.pageBuilder.editor.grouping.canvasNotice": "Canvas positions control this page. Groups below are preserved for flow layouts and do not arrange widgets in the canvas. Use the widget move and resize controls to place them side by side.",
|
|
369
|
+
"praxis.pageBuilder.editor.devices.stack": "Stack widgets",
|
|
370
|
+
"praxis.pageBuilder.editor.devices.stackHelp": "Use full width and natural height, in reading order. This replaces positions and width limits only for this device; other layouts stay unchanged.",
|
|
371
|
+
"praxis.pageBuilder.editor.devices.stacked": "Single-column layout prepared. Save to apply; Reset undoes the changes.",
|
|
372
|
+
'praxis.pageBuilder.shell.menuPlacement': 'More actions menu',
|
|
373
|
+
'praxis.pageBuilder.editor.limits.tab': "Widget limits",
|
|
374
|
+
'praxis.pageBuilder.editor.limits.help': 'Grid limits use columns and rows. Content-row layouts also offer pixel height below. Leave limits blank for defaults or to inherit the base layout.',
|
|
375
|
+
'praxis.pageBuilder.editor.limits.target': "Widget and layout",
|
|
376
|
+
'praxis.pageBuilder.editor.limits.base': "Base layout",
|
|
377
|
+
'praxis.pageBuilder.editor.limits.minColSpan': "Minimum width (columns)",
|
|
378
|
+
'praxis.pageBuilder.editor.limits.maxColSpan': "Maximum width (columns)",
|
|
379
|
+
'praxis.pageBuilder.editor.limits.minRowSpan': "Minimum height (rows)",
|
|
380
|
+
'praxis.pageBuilder.editor.limits.maxRowSpan': "Maximum height (rows)",
|
|
381
|
+
'praxis.pageBuilder.editor.limits.autoHeight': 'Outer height, with internal scrolling. The editor opened by the page also checks usable space in the current geometry. Review other variants on their device. Default inherits the base; Automatic clears height and inset.',
|
|
382
|
+
'praxis.pageBuilder.editor.height.mode': 'Widget height',
|
|
383
|
+
'praxis.pageBuilder.editor.height.inherit': 'Default',
|
|
384
|
+
'praxis.pageBuilder.editor.height.auto': 'Automatic',
|
|
385
|
+
'praxis.pageBuilder.editor.height.fixed': 'Adjustable',
|
|
386
|
+
'praxis.pageBuilder.editor.height.value': 'Height (px)',
|
|
387
|
+
'praxis.pageBuilder.editor.height.top': 'Top inset (px)',
|
|
388
|
+
'praxis.pageBuilder.editor.height.min': 'Minimum height (px)',
|
|
389
|
+
'praxis.pageBuilder.editor.height.max': 'Maximum height (px)',
|
|
390
|
+
'praxis.pageBuilder.editor.height.error': 'Use a whole height of at least 160px, within the effective limits, and a non-negative top inset.',
|
|
391
|
+
'praxis.pageBuilder.editor.limits.empty': "Add widgets to the canvas to configure their limits.",
|
|
392
|
+
'praxis.pageBuilder.editor.limits.geometry': "Current size: {{width}} columns × {{height}} rows. Grid: {{columns}} columns.",
|
|
393
|
+
'praxis.pageBuilder.editor.limits.errors.integer': "Use positive whole numbers or leave blank.",
|
|
394
|
+
'praxis.pageBuilder.editor.limits.errors.range': "The minimum cannot exceed the maximum, including inherited limits.",
|
|
395
|
+
'praxis.pageBuilder.editor.limits.errors.columns': "The minimum width exceeds the grid columns.",
|
|
396
|
+
'praxis.pageBuilder.editor.limits.errors.size': "The current size is outside these limits. Resize the widget first, or review the limits.",
|
|
397
|
+
'praxis.pageBuilder.shell.invalidCss': 'Invalid CSS value. Use a valid color, dimension or expression for this field.',
|
|
398
|
+
'praxis.pageBuilder.shell.stickyHeader': 'Keep header visible while scrolling the page',
|
|
364
399
|
'praxis.pageBuilder.authoringSource.alert.title': 'Semantic lineage requires attention',
|
|
365
400
|
'praxis.pageBuilder.authoringSource.alert.description': 'The page remains available, but this source will not be reused until new governed authoring restores its provenance.',
|
|
366
401
|
'praxis.pageBuilder.authoringSource.diagnostics.authoring-source-schema-invalid': 'The authoring envelope does not match the schema supported by Page Builder.',
|
|
@@ -685,9 +720,9 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
685
720
|
'praxis.pageBuilder.connections.validation.statePathNotDeclared': 'State path is not declared in page state values.',
|
|
686
721
|
'praxis.pageBuilder.connections.validation.feedbackCycleUnguarded': 'Connection participates in an unguarded feedback cycle.',
|
|
687
722
|
'praxis.pageBuilder.connections.validation.feedbackCycleGuarded': 'Connection participates in an intentional guarded feedback cycle.',
|
|
688
|
-
'praxis.pageBuilder.connections.suggestions.title': '
|
|
689
|
-
'praxis.pageBuilder.connections.suggestions.recommendedTitle': '
|
|
690
|
-
'praxis.pageBuilder.connections.suggestions.quickConnect': '
|
|
723
|
+
'praxis.pageBuilder.connections.suggestions.title': 'Wiring possibilities',
|
|
724
|
+
'praxis.pageBuilder.connections.suggestions.recommendedTitle': 'Shortcut · table and detail',
|
|
725
|
+
'praxis.pageBuilder.connections.suggestions.quickConnect': 'Review connection',
|
|
691
726
|
'praxis.pageBuilder.connections.suggestions.connectSelectionToForm': 'Connect selection to form',
|
|
692
727
|
'praxis.pageBuilder.connections.suggestions.outcome.masterDetail': 'Selecting a row in {{source}} updates {{target}}.',
|
|
693
728
|
'praxis.pageBuilder.connections.suggestions.outcome.default': '{{source}} updates {{target}}.',
|
|
@@ -701,9 +736,9 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
701
736
|
'praxis.pageBuilder.connections.suggestions.preview.rowIdToDetail': 'Will deliver the selected row id (payload.row.id) to the form.',
|
|
702
737
|
'praxis.pageBuilder.connections.suggestions.preview.stateToInput': 'Will deliver the current page state value.',
|
|
703
738
|
'praxis.pageBuilder.connections.suggestions.preview.sourcePayload': 'Will deliver the source payload unless you add a transform.',
|
|
704
|
-
'praxis.pageBuilder.connections.trace.simulate': '
|
|
705
|
-
'praxis.pageBuilder.connections.trace.title': '
|
|
706
|
-
'praxis.pageBuilder.connections.trace.summary': '
|
|
739
|
+
'praxis.pageBuilder.connections.trace.simulate': 'Explore route',
|
|
740
|
+
'praxis.pageBuilder.connections.trace.title': 'Structural route',
|
|
741
|
+
'praxis.pageBuilder.connections.trace.summary': 'Configuration walkthrough. Does not execute real events, conditions or requests.',
|
|
707
742
|
'praxis.pageBuilder.connections.trace.livePath': 'Live path',
|
|
708
743
|
'praxis.pageBuilder.connections.trace.sourceNode': 'Source',
|
|
709
744
|
'praxis.pageBuilder.connections.trace.reactingNode': 'Reacting',
|
|
@@ -718,7 +753,7 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
718
753
|
'praxis.pageBuilder.connections.tooltip.stateData': 'State - Data',
|
|
719
754
|
'praxis.pageBuilder.connections.tooltip.capability': 'Capability',
|
|
720
755
|
'praxis.pageBuilder.connections.tooltip.dataFlow': 'Data Flow',
|
|
721
|
-
'praxis.pageBuilder.connections.trace.empty': 'No connections to
|
|
756
|
+
'praxis.pageBuilder.connections.trace.empty': 'No connections to explore.',
|
|
722
757
|
'praxis.pageBuilder.connections.trace.phase.emit': 'Emit',
|
|
723
758
|
'praxis.pageBuilder.connections.trace.phase.condition': 'Condition',
|
|
724
759
|
'praxis.pageBuilder.connections.trace.phase.transform': 'Transform',
|
|
@@ -1023,9 +1058,82 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
1023
1058
|
'praxis.pageBuilder.agentic.errors.componentManifestUnavailable': 'This component does not provide an AI authoring manifest compatible with the requested change.',
|
|
1024
1059
|
'praxis.pageBuilder.agentic.errors.componentPlanInvalid': 'The proposed change did not pass the component validations. Review the request and try again.',
|
|
1025
1060
|
'praxis.pageBuilder.agentic.errors.generic': 'AI authoring failed.',
|
|
1061
|
+
'praxis.pageBuilder.connections.draft.new': 'New connection',
|
|
1062
|
+
'praxis.pageBuilder.connections.draft.backToEdit': 'Back to editing',
|
|
1063
|
+
'praxis.pageBuilder.connections.draft.present': 'Present diagram',
|
|
1064
|
+
'praxis.pageBuilder.connections.draft.title': 'Connection draft',
|
|
1065
|
+
'praxis.pageBuilder.connections.draft.prerequisites': 'Enable the source event in its component settings. For row selection, enable single selection; configure the detail as read-only when needed.',
|
|
1066
|
+
'praxis.pageBuilder.connections.draft.help': 'Choose the source and destination. Review the route and delivered value before applying.',
|
|
1067
|
+
'praxis.pageBuilder.connections.draft.source': '1 · Source / event',
|
|
1068
|
+
'praxis.pageBuilder.connections.draft.target': '2 · Destination / input',
|
|
1069
|
+
'praxis.pageBuilder.connections.draft.chooseSource': 'Choose a source',
|
|
1070
|
+
'praxis.pageBuilder.connections.draft.chooseTarget': 'Choose a destination',
|
|
1071
|
+
'praxis.pageBuilder.connections.draft.review': 'Review the route',
|
|
1072
|
+
'praxis.pageBuilder.connections.draft.valuePath': 'Delivered value · payload path',
|
|
1073
|
+
'praxis.pageBuilder.connections.draft.nullFallback': 'When the value is absent, deliver null to clear the destination.',
|
|
1074
|
+
'praxis.pageBuilder.connections.draft.existingFallback': 'Missing values follow the transformation and delivery policy configured below.',
|
|
1075
|
+
'praxis.pageBuilder.connections.draft.wholePayload': 'The whole source value will be delivered. Use the transformation settings to extract a field.',
|
|
1076
|
+
'praxis.pageBuilder.connections.draft.conflict': 'The page changed during editing. Cancel this draft and reopen the connection to use the latest version.',
|
|
1077
|
+
'praxis.pageBuilder.connections.draft.pending': 'Draft · not yet applied to the page',
|
|
1078
|
+
'praxis.pageBuilder.connections.draft.apply': 'Apply connection',
|
|
1079
|
+
'praxis.pageBuilder.connections.draft.cancel': 'Cancel',
|
|
1080
|
+
'praxis.pageBuilder.connections.draft.pageSave': 'Connections apply to the page in the builder. Save the page to persist changes.',
|
|
1081
|
+
'praxis.pageBuilder.connections.draft.edit': 'Edit connection',
|
|
1082
|
+
'praxis.pageBuilder.connections.draft.advanced': 'Transformation, conditions and delivery',
|
|
1083
|
+
'praxis.pageBuilder.connections.mode.simulation': 'Route',
|
|
1084
|
+
'praxis.pageBuilder.connections.mode.all': 'All',
|
|
1085
|
+
'praxis.pageBuilder.connections.mode.data': 'Data',
|
|
1086
|
+
'praxis.pageBuilder.connections.mode.event': 'Events',
|
|
1087
|
+
'praxis.pageBuilder.connections.mode.capability': 'Actions',
|
|
1088
|
+
'praxis.pageBuilder.connections.draft.extract': 'Extract a field',
|
|
1089
|
+
'praxis.pageBuilder.connections.draft.clearMissing': 'Clear when absent',
|
|
1090
|
+
'praxis.pageBuilder.connections.draft.keepMissing': 'Keep destination when absent',
|
|
1091
|
+
'praxis.pageBuilder.connections.editor.segmentKindLegend': 'Port types',
|
|
1092
|
+
'praxis.pageBuilder.connections.closeAria': 'Close connection editor',
|
|
1093
|
+
'praxis.pageBuilder.connections.mode.showFullSchemaAria': 'Show ports and technical details',
|
|
1094
|
+
'praxis.pageBuilder.connections.mode.showGuidedViewAria': 'Show guided view',
|
|
1095
|
+
'praxis.pageBuilder.connections.mode.statusGuided': 'Guided view',
|
|
1096
|
+
'praxis.pageBuilder.connections.mode.statusAll': 'Ports and details',
|
|
1097
|
+
'praxis.pageBuilder.connections.mode.statusSimulation': 'Configuration walkthrough',
|
|
1098
|
+
'praxis.pageBuilder.connections.mode.aria': 'Filter connections by type',
|
|
1099
|
+
'praxis.pageBuilder.connections.editor.segmentKinds': 'Port types',
|
|
1100
|
+
'praxis.pageBuilder.connections.draft.duplicate': 'An identical connection already exists. Edit the existing connection or change this draft.',
|
|
1026
1101
|
};
|
|
1027
1102
|
|
|
1028
1103
|
const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
1104
|
+
"praxis.pageBuilder.editor.devices.target": "Dispositivo para configurar",
|
|
1105
|
+
"praxis.pageBuilder.editor.devices.advanced": "Ajustes avançados",
|
|
1106
|
+
"praxis.pageBuilder.editor.grouping.canvasNotice": "As posições no canvas controlam esta página. Os agrupamentos abaixo são preservados para layouts de fluxo e não organizam os widgets no canvas. Para colocá-los lado a lado, use os controles de mover e redimensionar de cada widget.",
|
|
1107
|
+
"praxis.pageBuilder.editor.devices.stack": "Empilhar widgets",
|
|
1108
|
+
"praxis.pageBuilder.editor.devices.stackHelp": "Usa a largura total e altura natural, na ordem de leitura. Substitui as posições e os limites de largura apenas neste dispositivo; os outros layouts são preservados.",
|
|
1109
|
+
"praxis.pageBuilder.editor.devices.stacked": "Layout de uma coluna preparado. Salve para aplicar; Redefinir desfaz os ajustes.",
|
|
1110
|
+
'praxis.pageBuilder.shell.menuPlacement': 'Menu Mais ações',
|
|
1111
|
+
'praxis.pageBuilder.editor.limits.tab': "Limites dos widgets",
|
|
1112
|
+
'praxis.pageBuilder.editor.limits.help': 'Os limites da grade usam colunas e linhas. Em linhas de conteúdo, a seção de altura também permite pixels. Deixe os limites em branco para usar os padrões ou herdar o layout base.',
|
|
1113
|
+
'praxis.pageBuilder.editor.limits.target': "Widget e layout",
|
|
1114
|
+
'praxis.pageBuilder.editor.limits.base': "Layout base",
|
|
1115
|
+
'praxis.pageBuilder.editor.limits.minColSpan': "Largura mínima (colunas)",
|
|
1116
|
+
'praxis.pageBuilder.editor.limits.maxColSpan': "Largura máxima (colunas)",
|
|
1117
|
+
'praxis.pageBuilder.editor.limits.minRowSpan': "Altura mínima (linhas)",
|
|
1118
|
+
'praxis.pageBuilder.editor.limits.maxRowSpan': "Altura máxima (linhas)",
|
|
1119
|
+
'praxis.pageBuilder.editor.limits.autoHeight': 'Altura externa, com rolagem interna. O editor aberto pela página também verifica a área útil na geometria atual. Confira outras variantes no dispositivo correspondente. Padrão herda a base; Automática remove altura e recuo.',
|
|
1120
|
+
'praxis.pageBuilder.editor.height.mode': 'Altura do widget',
|
|
1121
|
+
'praxis.pageBuilder.editor.height.inherit': 'Padrão',
|
|
1122
|
+
'praxis.pageBuilder.editor.height.auto': 'Automática',
|
|
1123
|
+
'praxis.pageBuilder.editor.height.fixed': 'Ajustável',
|
|
1124
|
+
'praxis.pageBuilder.editor.height.value': 'Altura (px)',
|
|
1125
|
+
'praxis.pageBuilder.editor.height.top': 'Recuo superior (px)',
|
|
1126
|
+
'praxis.pageBuilder.editor.height.min': 'Altura mínima (px)',
|
|
1127
|
+
'praxis.pageBuilder.editor.height.max': 'Altura máxima (px)',
|
|
1128
|
+
'praxis.pageBuilder.editor.height.error': 'Use altura inteira de pelo menos 160px, dentro dos limites efetivos, e recuo superior não negativo.',
|
|
1129
|
+
'praxis.pageBuilder.editor.limits.empty': "Adicione widgets ao canvas para configurar seus limites.",
|
|
1130
|
+
'praxis.pageBuilder.editor.limits.geometry': "Tamanho atual: {{width}} colunas × {{height}} linhas. Grade: {{columns}} colunas.",
|
|
1131
|
+
'praxis.pageBuilder.editor.limits.errors.integer': "Use números inteiros positivos ou deixe em branco.",
|
|
1132
|
+
'praxis.pageBuilder.editor.limits.errors.range': "O mínimo não pode ultrapassar o máximo, incluindo os limites herdados.",
|
|
1133
|
+
'praxis.pageBuilder.editor.limits.errors.columns': "A largura mínima ultrapassa as colunas da grade.",
|
|
1134
|
+
'praxis.pageBuilder.editor.limits.errors.size': "O tamanho atual está fora destes limites. Redimensione o widget antes ou revise os limites.",
|
|
1135
|
+
'praxis.pageBuilder.shell.invalidCss': 'Valor CSS inválido. Use uma cor, medida ou expressão válida para este campo.',
|
|
1136
|
+
'praxis.pageBuilder.shell.stickyHeader': 'Manter cabeçalho visível ao rolar a página',
|
|
1029
1137
|
'praxis.pageBuilder.authoringSource.alert.title': 'Linhagem semântica requer atenção',
|
|
1030
1138
|
'praxis.pageBuilder.authoringSource.alert.description': 'A página continua disponível, mas esta fonte não será reutilizada até que uma nova autoria governada restabeleça sua proveniência.',
|
|
1031
1139
|
'praxis.pageBuilder.authoringSource.diagnostics.authoring-source-schema-invalid': 'O envelope de autoria não atende ao schema suportado pelo Page Builder.',
|
|
@@ -1350,9 +1458,9 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
1350
1458
|
'praxis.pageBuilder.connections.validation.statePathNotDeclared': 'O caminho de estado não está declarado nos valores de estado da página.',
|
|
1351
1459
|
'praxis.pageBuilder.connections.validation.feedbackCycleUnguarded': 'A conexão participa de um ciclo de feedback sem guarda.',
|
|
1352
1460
|
'praxis.pageBuilder.connections.validation.feedbackCycleGuarded': 'A conexão participa de um ciclo de feedback intencional e guardado.',
|
|
1353
|
-
'praxis.pageBuilder.connections.suggestions.title': '
|
|
1354
|
-
'praxis.pageBuilder.connections.suggestions.recommendedTitle': '
|
|
1355
|
-
'praxis.pageBuilder.connections.suggestions.quickConnect': '
|
|
1461
|
+
'praxis.pageBuilder.connections.suggestions.title': 'Possibilidades de ligação',
|
|
1462
|
+
'praxis.pageBuilder.connections.suggestions.recommendedTitle': 'Atalho · tabela e detalhe',
|
|
1463
|
+
'praxis.pageBuilder.connections.suggestions.quickConnect': 'Revisar conexão',
|
|
1356
1464
|
'praxis.pageBuilder.connections.suggestions.connectSelectionToForm': 'Conectar seleção ao formulário',
|
|
1357
1465
|
'praxis.pageBuilder.connections.suggestions.outcome.masterDetail': 'Selecionar uma linha em {{source}} atualiza {{target}}.',
|
|
1358
1466
|
'praxis.pageBuilder.connections.suggestions.outcome.default': '{{source}} atualiza {{target}}.',
|
|
@@ -1366,9 +1474,9 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
1366
1474
|
'praxis.pageBuilder.connections.suggestions.preview.rowIdToDetail': 'Entregará o ID da linha selecionada (payload.row.id) ao formulário.',
|
|
1367
1475
|
'praxis.pageBuilder.connections.suggestions.preview.stateToInput': 'Entregará o valor atual do estado da página.',
|
|
1368
1476
|
'praxis.pageBuilder.connections.suggestions.preview.sourcePayload': 'Entregará o payload da origem, a menos que você adicione uma transformação.',
|
|
1369
|
-
'praxis.pageBuilder.connections.trace.simulate': '
|
|
1370
|
-
'praxis.pageBuilder.connections.trace.title': '
|
|
1371
|
-
'praxis.pageBuilder.connections.trace.summary': '
|
|
1477
|
+
'praxis.pageBuilder.connections.trace.simulate': 'Explorar percurso',
|
|
1478
|
+
'praxis.pageBuilder.connections.trace.title': 'Percurso estrutural',
|
|
1479
|
+
'praxis.pageBuilder.connections.trace.summary': 'Leitura da configuração. Não executa eventos, condições ou chamadas reais.',
|
|
1372
1480
|
'praxis.pageBuilder.connections.trace.livePath': 'Caminho ativo',
|
|
1373
1481
|
'praxis.pageBuilder.connections.trace.sourceNode': 'Origem',
|
|
1374
1482
|
'praxis.pageBuilder.connections.trace.reactingNode': 'Reagindo',
|
|
@@ -1383,7 +1491,7 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
1383
1491
|
'praxis.pageBuilder.connections.tooltip.stateData': 'Estado - Dados',
|
|
1384
1492
|
'praxis.pageBuilder.connections.tooltip.capability': 'Capacidade',
|
|
1385
1493
|
'praxis.pageBuilder.connections.tooltip.dataFlow': 'Fluxo de dados',
|
|
1386
|
-
'praxis.pageBuilder.connections.trace.empty': 'Nenhuma conexão para
|
|
1494
|
+
'praxis.pageBuilder.connections.trace.empty': 'Nenhuma conexão para explorar.',
|
|
1387
1495
|
'praxis.pageBuilder.connections.trace.phase.emit': 'Emitir',
|
|
1388
1496
|
'praxis.pageBuilder.connections.trace.phase.condition': 'Condição',
|
|
1389
1497
|
'praxis.pageBuilder.connections.trace.phase.transform': 'Transformar',
|
|
@@ -1688,6 +1796,46 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
1688
1796
|
'praxis.pageBuilder.agentic.errors.componentManifestUnavailable': 'Este componente não disponibiliza um manifesto de autoria por IA compatível com a alteração solicitada.',
|
|
1689
1797
|
'praxis.pageBuilder.agentic.errors.componentPlanInvalid': 'A alteração proposta não passou pelas validações do componente. Revise o pedido e tente novamente.',
|
|
1690
1798
|
'praxis.pageBuilder.agentic.errors.generic': 'Falha na autoria com IA.',
|
|
1799
|
+
'praxis.pageBuilder.connections.draft.new': 'Nova conexão',
|
|
1800
|
+
'praxis.pageBuilder.connections.draft.backToEdit': 'Voltar à edição',
|
|
1801
|
+
'praxis.pageBuilder.connections.draft.present': 'Apresentar diagrama',
|
|
1802
|
+
'praxis.pageBuilder.connections.draft.title': 'Rascunho da conexão',
|
|
1803
|
+
'praxis.pageBuilder.connections.draft.prerequisites': 'Habilite o evento nas configurações do componente de origem. Para seleção de linhas, habilite a seleção única; configure o detalhe como somente leitura quando necessário.',
|
|
1804
|
+
'praxis.pageBuilder.connections.draft.help': 'Escolha a origem e o destino. Revise o percurso e o valor entregue antes de aplicar.',
|
|
1805
|
+
'praxis.pageBuilder.connections.draft.source': '1 · Origem / evento',
|
|
1806
|
+
'praxis.pageBuilder.connections.draft.target': '2 · Destino / entrada',
|
|
1807
|
+
'praxis.pageBuilder.connections.draft.chooseSource': 'Selecione a origem',
|
|
1808
|
+
'praxis.pageBuilder.connections.draft.chooseTarget': 'Selecione o destino',
|
|
1809
|
+
'praxis.pageBuilder.connections.draft.review': 'Revise o percurso',
|
|
1810
|
+
'praxis.pageBuilder.connections.draft.valuePath': 'Valor entregue · caminho no payload',
|
|
1811
|
+
'praxis.pageBuilder.connections.draft.nullFallback': 'Quando o valor estiver ausente, entregar null para limpar o destino.',
|
|
1812
|
+
'praxis.pageBuilder.connections.draft.existingFallback': 'Valores ausentes seguem a transformação e a política de entrega configuradas abaixo.',
|
|
1813
|
+
'praxis.pageBuilder.connections.draft.wholePayload': 'O valor de origem será entregue inteiro. Use as opções de transformação para extrair um campo.',
|
|
1814
|
+
'praxis.pageBuilder.connections.draft.conflict': 'A página mudou durante a edição. Cancele este rascunho e reabra a conexão para usar a versão atual.',
|
|
1815
|
+
'praxis.pageBuilder.connections.draft.pending': 'Rascunho · ainda não aplicado à página',
|
|
1816
|
+
'praxis.pageBuilder.connections.draft.apply': 'Aplicar conexão',
|
|
1817
|
+
'praxis.pageBuilder.connections.draft.cancel': 'Cancelar',
|
|
1818
|
+
'praxis.pageBuilder.connections.draft.pageSave': 'As conexões são aplicadas à página no builder. Salve a página para persistir as alterações.',
|
|
1819
|
+
'praxis.pageBuilder.connections.draft.edit': 'Editar conexão',
|
|
1820
|
+
'praxis.pageBuilder.connections.draft.advanced': 'Transformação, condições e entrega',
|
|
1821
|
+
'praxis.pageBuilder.connections.mode.simulation': 'Percurso',
|
|
1822
|
+
'praxis.pageBuilder.connections.mode.all': 'Todas',
|
|
1823
|
+
'praxis.pageBuilder.connections.mode.data': 'Dados',
|
|
1824
|
+
'praxis.pageBuilder.connections.mode.event': 'Eventos',
|
|
1825
|
+
'praxis.pageBuilder.connections.mode.capability': 'Ações',
|
|
1826
|
+
'praxis.pageBuilder.connections.draft.extract': 'Extrair um campo',
|
|
1827
|
+
'praxis.pageBuilder.connections.draft.clearMissing': 'Limpar quando ausente',
|
|
1828
|
+
'praxis.pageBuilder.connections.draft.keepMissing': 'Manter destino quando ausente',
|
|
1829
|
+
'praxis.pageBuilder.connections.editor.segmentKindLegend': 'Tipos de porta',
|
|
1830
|
+
'praxis.pageBuilder.connections.closeAria': 'Fechar editor de conexões',
|
|
1831
|
+
'praxis.pageBuilder.connections.mode.showFullSchemaAria': 'Mostrar portas e detalhes técnicos',
|
|
1832
|
+
'praxis.pageBuilder.connections.mode.showGuidedViewAria': 'Mostrar visão guiada',
|
|
1833
|
+
'praxis.pageBuilder.connections.mode.statusGuided': 'Visão guiada',
|
|
1834
|
+
'praxis.pageBuilder.connections.mode.statusAll': 'Portas e detalhes',
|
|
1835
|
+
'praxis.pageBuilder.connections.mode.statusSimulation': 'Percurso da configuração',
|
|
1836
|
+
'praxis.pageBuilder.connections.mode.aria': 'Filtrar conexões por tipo',
|
|
1837
|
+
'praxis.pageBuilder.connections.editor.segmentKinds': 'Tipos de porta',
|
|
1838
|
+
'praxis.pageBuilder.connections.draft.duplicate': 'Já existe uma conexão idêntica. Edite a conexão existente ou altere este rascunho.',
|
|
1691
1839
|
};
|
|
1692
1840
|
|
|
1693
1841
|
function createPraxisPageBuilderI18nConfig(options = {}) {
|
|
@@ -2011,7 +2159,7 @@ class ComponentPaletteDialogComponent {
|
|
|
2011
2159
|
<div mat-dialog-actions align="end">
|
|
2012
2160
|
<button mat-stroked-button color="primary" mat-dialog-close>{{ tx('palette.cancel', 'Cancelar') }}</button>
|
|
2013
2161
|
</div>
|
|
2014
|
-
`, isInline: true, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-palette-search{width:100%;margin-bottom:12px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{appearance:none;position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;color:inherit;font:inherit;min-height:92px;text-align:left;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-card-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.pdx-card-badge{display:inline-flex;align-items:center;gap:4px;min-height:22px;padding:2px 8px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-highest);font-size:11px;line-height:1.2;font-weight:600;letter-spacing:.01em}.pdx-card-badge mat-icon{width:14px;height:14px;font-size:14px}.pdx-card-badge.ready{color:var(--md-sys-color-primary);border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent)}.pdx-card-badge.info{color:var(--md-sys-color-tertiary);border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 38%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 68%,transparent)}.pdx-card-badge.warning{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 62%,transparent)}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type:
|
|
2162
|
+
`, isInline: true, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-palette-search{width:100%;margin-bottom:12px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{appearance:none;position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;color:inherit;font:inherit;min-height:92px;text-align:left;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-card-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.pdx-card-badge{display:inline-flex;align-items:center;gap:4px;min-height:22px;padding:2px 8px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-highest);font-size:11px;line-height:1.2;font-weight:600;letter-spacing:.01em}.pdx-card-badge mat-icon{width:14px;height:14px;font-size:14px}.pdx-card-badge.ready{color:var(--md-sys-color-primary);border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent)}.pdx-card-badge.info{color:var(--md-sys-color-tertiary);border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 38%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 68%,transparent)}.pdx-card-badge.warning{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 62%,transparent)}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2015
2163
|
}
|
|
2016
2164
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ComponentPaletteDialogComponent, decorators: [{
|
|
2017
2165
|
type: Component,
|
|
@@ -2091,6 +2239,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
2091
2239
|
args: [MAT_DIALOG_DATA]
|
|
2092
2240
|
}] }] });
|
|
2093
2241
|
|
|
2242
|
+
/** Browser syntax validation only; token resolution and URL policy belong to the host. */
|
|
2243
|
+
function cssDeclarationValidator(property) {
|
|
2244
|
+
return (control) => {
|
|
2245
|
+
const value = control.value;
|
|
2246
|
+
if (value == null || value === '')
|
|
2247
|
+
return null;
|
|
2248
|
+
if (typeof value !== 'string')
|
|
2249
|
+
return { cssDeclaration: true };
|
|
2250
|
+
if (!value.trim())
|
|
2251
|
+
return null;
|
|
2252
|
+
// SSR has no CSS parser or interactive authoring. Validate on browser hydration.
|
|
2253
|
+
if (typeof CSS === 'undefined' || typeof CSS.supports !== 'function')
|
|
2254
|
+
return null;
|
|
2255
|
+
return CSS.supports(property, value.trim()) ? null : { cssDeclaration: true };
|
|
2256
|
+
};
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2094
2259
|
const BUILTIN_PRESET_LABELS = {
|
|
2095
2260
|
'dark-glass': 'Dark Glass',
|
|
2096
2261
|
'light-neutral': 'Light Neutral',
|
|
@@ -2316,6 +2481,14 @@ const SET_INPUT_PRESETS = {
|
|
|
2316
2481
|
};
|
|
2317
2482
|
class WidgetShellEditorComponent {
|
|
2318
2483
|
registry;
|
|
2484
|
+
i18n = inject(PraxisI18nService);
|
|
2485
|
+
menuPlacementLabel() { return this.i18n.t('praxis.pageBuilder.shell.menuPlacement'); }
|
|
2486
|
+
appearanceError() {
|
|
2487
|
+
return this.i18n.t('praxis.pageBuilder.shell.invalidCss');
|
|
2488
|
+
}
|
|
2489
|
+
stickyHeaderLabel() {
|
|
2490
|
+
return this.i18n.t('praxis.pageBuilder.shell.stickyHeader');
|
|
2491
|
+
}
|
|
2319
2492
|
form = new FormGroup({
|
|
2320
2493
|
kind: new FormControl('dashboard-card', {
|
|
2321
2494
|
nonNullable: true,
|
|
@@ -2328,6 +2501,7 @@ class WidgetShellEditorComponent {
|
|
|
2328
2501
|
showHeader: new FormControl('auto', {
|
|
2329
2502
|
nonNullable: true,
|
|
2330
2503
|
}),
|
|
2504
|
+
stickyHeader: new FormControl(false, { nonNullable: true }),
|
|
2331
2505
|
collapsible: new FormControl(true, { nonNullable: true }),
|
|
2332
2506
|
cardBg: new FormControl('', { nonNullable: true }),
|
|
2333
2507
|
cardBorder: new FormControl('', { nonNullable: true }),
|
|
@@ -2379,6 +2553,18 @@ class WidgetShellEditorComponent {
|
|
|
2379
2553
|
constructor(data, registry) {
|
|
2380
2554
|
this.registry = registry;
|
|
2381
2555
|
this.authoringCapabilities = data?.authoringCapabilities ?? null;
|
|
2556
|
+
if (this.canEditShellAppearance()) {
|
|
2557
|
+
const properties = {
|
|
2558
|
+
cardBg: 'background', cardBorder: 'border-color', cardRadius: 'border-radius',
|
|
2559
|
+
cardShadow: 'box-shadow', headerBg: 'background', headerBorder: 'border-color',
|
|
2560
|
+
titleColor: 'color', subtitleColor: 'color', iconColor: 'color',
|
|
2561
|
+
bodyBg: 'background', bodyColor: 'color', bodyPadding: 'padding',
|
|
2562
|
+
titleSize: 'font-size', titleWeight: 'font-weight', subtitleSize: 'font-size',
|
|
2563
|
+
};
|
|
2564
|
+
for (const name of Object.keys(properties)) {
|
|
2565
|
+
this.form.controls[name].addValidators(cssDeclarationValidator(properties[name]));
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2382
2568
|
const customPresets = data?.presets || {};
|
|
2383
2569
|
const customOptions = Object.keys(customPresets).map((id) => ({
|
|
2384
2570
|
id,
|
|
@@ -2441,10 +2627,14 @@ class WidgetShellEditorComponent {
|
|
|
2441
2627
|
this.actions.removeAt(index);
|
|
2442
2628
|
}
|
|
2443
2629
|
getSettingsValue() {
|
|
2630
|
+
if (this.form.invalid) {
|
|
2631
|
+
this.form.markAllAsTouched();
|
|
2632
|
+
throw new Error(this.i18n.t('praxis.pageBuilder.editor.status.review'));
|
|
2633
|
+
}
|
|
2444
2634
|
return this.buildResult();
|
|
2445
2635
|
}
|
|
2446
2636
|
onSave() {
|
|
2447
|
-
return this.
|
|
2637
|
+
return this.getSettingsValue();
|
|
2448
2638
|
}
|
|
2449
2639
|
reset() {
|
|
2450
2640
|
const shell = this.initialShell.value;
|
|
@@ -2469,6 +2659,7 @@ class WidgetShellEditorComponent {
|
|
|
2469
2659
|
subtitle: this.editableText(shell?.subtitle),
|
|
2470
2660
|
icon: shell?.icon || '',
|
|
2471
2661
|
showHeader,
|
|
2662
|
+
stickyHeader: shell?.stickyHeader === true,
|
|
2472
2663
|
collapsible: window.collapsible !== false,
|
|
2473
2664
|
cardBg: card.background || '',
|
|
2474
2665
|
cardBorder: card.borderColor || '',
|
|
@@ -2570,6 +2761,7 @@ class WidgetShellEditorComponent {
|
|
|
2570
2761
|
delete shell.subtitle;
|
|
2571
2762
|
delete shell.icon;
|
|
2572
2763
|
delete shell.showHeader;
|
|
2764
|
+
delete shell.stickyHeader;
|
|
2573
2765
|
if (raw.preset)
|
|
2574
2766
|
shell.preset = raw.preset;
|
|
2575
2767
|
const title = this.preserveTextDescriptor(this.initialTitle, raw.title);
|
|
@@ -2582,6 +2774,8 @@ class WidgetShellEditorComponent {
|
|
|
2582
2774
|
shell.icon = raw.icon.trim();
|
|
2583
2775
|
if (raw.showHeader !== 'auto')
|
|
2584
2776
|
shell.showHeader = raw.showHeader === 'true';
|
|
2777
|
+
if (raw.stickyHeader)
|
|
2778
|
+
shell.stickyHeader = true;
|
|
2585
2779
|
const windowActions = {
|
|
2586
2780
|
...(initial?.windowActions || {}),
|
|
2587
2781
|
};
|
|
@@ -2766,7 +2960,7 @@ class WidgetShellEditorComponent {
|
|
|
2766
2960
|
}
|
|
2767
2961
|
previewOverflowCount() {
|
|
2768
2962
|
const actions = this.previewActions().filter((a) => (a.placement || 'header') === 'header');
|
|
2769
|
-
return Math.max(0, actions.length - 3);
|
|
2963
|
+
return Math.max(0, actions.length - 3) + this.previewActions().filter(a => a.placement === 'menu').length;
|
|
2770
2964
|
}
|
|
2771
2965
|
previewWindowActions() {
|
|
2772
2966
|
return this.previewActions().filter((a) => (a.placement || 'header') === 'window');
|
|
@@ -2985,7 +3179,7 @@ class WidgetShellEditorComponent {
|
|
|
2985
3179
|
}
|
|
2986
3180
|
}
|
|
2987
3181
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellEditorComponent, deps: [{ token: SETTINGS_PANEL_DATA, optional: true }, { token: i2$2.ComponentMetadataRegistry, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
2988
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: WidgetShellEditorComponent, isStandalone: true, selector: "praxis-widget-shell-editor", ngImport: i0, template: `
|
|
3182
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: WidgetShellEditorComponent, isStandalone: true, selector: "praxis-widget-shell-editor", providers: [providePraxisPageBuilderI18n()], ngImport: i0, template: `
|
|
2989
3183
|
<div class="shell-editor">
|
|
2990
3184
|
@if (
|
|
2991
3185
|
canEditShellIdentity() &&
|
|
@@ -3054,6 +3248,9 @@ class WidgetShellEditorComponent {
|
|
|
3054
3248
|
<mat-option value="false">Nunca</mat-option>
|
|
3055
3249
|
</mat-select>
|
|
3056
3250
|
</mat-form-field>
|
|
3251
|
+
<mat-checkbox [formControl]="form.controls.stickyHeader">
|
|
3252
|
+
{{ stickyHeaderLabel() }}
|
|
3253
|
+
</mat-checkbox>
|
|
3057
3254
|
</div>
|
|
3058
3255
|
|
|
3059
3256
|
<div class="shell-section">Controles de janela</div>
|
|
@@ -3069,125 +3266,170 @@ class WidgetShellEditorComponent {
|
|
|
3069
3266
|
|
|
3070
3267
|
<div class="shell-section">Aparência</div>
|
|
3071
3268
|
<div class="shell-grid">
|
|
3072
|
-
<mat-form-field appearance="outline">
|
|
3269
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3073
3270
|
<mat-label>Fundo do card</mat-label>
|
|
3074
3271
|
<input
|
|
3075
3272
|
matInput
|
|
3076
3273
|
[formControl]="form.controls.cardBg"
|
|
3077
3274
|
placeholder="ex: #0b1220"
|
|
3078
3275
|
/>
|
|
3276
|
+
@if (form.controls.cardBg.hasError('cssDeclaration')) {
|
|
3277
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3278
|
+
}
|
|
3079
3279
|
</mat-form-field>
|
|
3080
|
-
<mat-form-field appearance="outline">
|
|
3280
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3081
3281
|
<mat-label>Cor da borda</mat-label>
|
|
3082
3282
|
<input
|
|
3083
3283
|
matInput
|
|
3084
3284
|
[formControl]="form.controls.cardBorder"
|
|
3085
3285
|
placeholder="ex: rgba(255,255,255,0.12)"
|
|
3086
3286
|
/>
|
|
3287
|
+
@if (form.controls.cardBorder.hasError('cssDeclaration')) {
|
|
3288
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3289
|
+
}
|
|
3087
3290
|
</mat-form-field>
|
|
3088
|
-
<mat-form-field appearance="outline">
|
|
3291
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3089
3292
|
<mat-label>Raio da borda</mat-label>
|
|
3090
3293
|
<input
|
|
3091
3294
|
matInput
|
|
3092
3295
|
[formControl]="form.controls.cardRadius"
|
|
3093
3296
|
placeholder="ex: 14px"
|
|
3094
3297
|
/>
|
|
3298
|
+
@if (form.controls.cardRadius.hasError('cssDeclaration')) {
|
|
3299
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3300
|
+
}
|
|
3095
3301
|
</mat-form-field>
|
|
3096
|
-
<mat-form-field appearance="outline">
|
|
3302
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3097
3303
|
<mat-label>Sombra</mat-label>
|
|
3098
3304
|
<input
|
|
3099
3305
|
matInput
|
|
3100
3306
|
[formControl]="form.controls.cardShadow"
|
|
3101
3307
|
placeholder="ex: 0 10px 30px rgba(0,0,0,0.2)"
|
|
3102
3308
|
/>
|
|
3309
|
+
@if (form.controls.cardShadow.hasError('cssDeclaration')) {
|
|
3310
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3311
|
+
}
|
|
3103
3312
|
</mat-form-field>
|
|
3104
|
-
<mat-form-field appearance="outline">
|
|
3313
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3105
3314
|
<mat-label>Fundo do cabeçalho</mat-label>
|
|
3106
3315
|
<input
|
|
3107
3316
|
matInput
|
|
3108
3317
|
[formControl]="form.controls.headerBg"
|
|
3109
3318
|
placeholder="ex: linear-gradient(...)"
|
|
3110
3319
|
/>
|
|
3320
|
+
@if (form.controls.headerBg.hasError('cssDeclaration')) {
|
|
3321
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3322
|
+
}
|
|
3111
3323
|
</mat-form-field>
|
|
3112
|
-
<mat-form-field appearance="outline">
|
|
3324
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3113
3325
|
<mat-label>Borda do cabeçalho</mat-label>
|
|
3114
3326
|
<input
|
|
3115
3327
|
matInput
|
|
3116
3328
|
[formControl]="form.controls.headerBorder"
|
|
3117
3329
|
placeholder="ex: rgba(255,255,255,0.08)"
|
|
3118
3330
|
/>
|
|
3331
|
+
@if (form.controls.headerBorder.hasError('cssDeclaration')) {
|
|
3332
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3333
|
+
}
|
|
3119
3334
|
</mat-form-field>
|
|
3120
|
-
<mat-form-field appearance="outline">
|
|
3335
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3121
3336
|
<mat-label>Cor do título</mat-label>
|
|
3122
3337
|
<input
|
|
3123
3338
|
matInput
|
|
3124
3339
|
[formControl]="form.controls.titleColor"
|
|
3125
3340
|
placeholder="ex: #e6edf3"
|
|
3126
3341
|
/>
|
|
3342
|
+
@if (form.controls.titleColor.hasError('cssDeclaration')) {
|
|
3343
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3344
|
+
}
|
|
3127
3345
|
</mat-form-field>
|
|
3128
|
-
<mat-form-field appearance="outline">
|
|
3346
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3129
3347
|
<mat-label>Cor do subtítulo</mat-label>
|
|
3130
3348
|
<input
|
|
3131
3349
|
matInput
|
|
3132
3350
|
[formControl]="form.controls.subtitleColor"
|
|
3133
3351
|
placeholder="ex: #9fb0c4"
|
|
3134
3352
|
/>
|
|
3353
|
+
@if (form.controls.subtitleColor.hasError('cssDeclaration')) {
|
|
3354
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3355
|
+
}
|
|
3135
3356
|
</mat-form-field>
|
|
3136
|
-
<mat-form-field appearance="outline">
|
|
3357
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3137
3358
|
<mat-label>Cor do ícone</mat-label>
|
|
3138
3359
|
<input
|
|
3139
3360
|
matInput
|
|
3140
3361
|
[formControl]="form.controls.iconColor"
|
|
3141
3362
|
placeholder="ex: #8ab4ff"
|
|
3142
3363
|
/>
|
|
3364
|
+
@if (form.controls.iconColor.hasError('cssDeclaration')) {
|
|
3365
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3366
|
+
}
|
|
3143
3367
|
</mat-form-field>
|
|
3144
|
-
<mat-form-field appearance="outline">
|
|
3368
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3145
3369
|
<mat-label>Fundo do corpo</mat-label>
|
|
3146
3370
|
<input
|
|
3147
3371
|
matInput
|
|
3148
3372
|
[formControl]="form.controls.bodyBg"
|
|
3149
3373
|
placeholder="ex: transparent"
|
|
3150
3374
|
/>
|
|
3375
|
+
@if (form.controls.bodyBg.hasError('cssDeclaration')) {
|
|
3376
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3377
|
+
}
|
|
3151
3378
|
</mat-form-field>
|
|
3152
|
-
<mat-form-field appearance="outline">
|
|
3379
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3153
3380
|
<mat-label>Cor do texto do corpo</mat-label>
|
|
3154
3381
|
<input
|
|
3155
3382
|
matInput
|
|
3156
3383
|
[formControl]="form.controls.bodyColor"
|
|
3157
3384
|
placeholder="ex: #e6edf3"
|
|
3158
3385
|
/>
|
|
3386
|
+
@if (form.controls.bodyColor.hasError('cssDeclaration')) {
|
|
3387
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3388
|
+
}
|
|
3159
3389
|
</mat-form-field>
|
|
3160
|
-
<mat-form-field appearance="outline">
|
|
3390
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3161
3391
|
<mat-label>Padding do corpo</mat-label>
|
|
3162
3392
|
<input
|
|
3163
3393
|
matInput
|
|
3164
3394
|
[formControl]="form.controls.bodyPadding"
|
|
3165
3395
|
placeholder="ex: 10px 12px 12px"
|
|
3166
3396
|
/>
|
|
3397
|
+
@if (form.controls.bodyPadding.hasError('cssDeclaration')) {
|
|
3398
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3399
|
+
}
|
|
3167
3400
|
</mat-form-field>
|
|
3168
|
-
<mat-form-field appearance="outline">
|
|
3401
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3169
3402
|
<mat-label>Tamanho do título</mat-label>
|
|
3170
3403
|
<input
|
|
3171
3404
|
matInput
|
|
3172
3405
|
[formControl]="form.controls.titleSize"
|
|
3173
3406
|
placeholder="ex: 14px"
|
|
3174
3407
|
/>
|
|
3408
|
+
@if (form.controls.titleSize.hasError('cssDeclaration')) {
|
|
3409
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3410
|
+
}
|
|
3175
3411
|
</mat-form-field>
|
|
3176
|
-
<mat-form-field appearance="outline">
|
|
3412
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3177
3413
|
<mat-label>Peso do título</mat-label>
|
|
3178
3414
|
<input
|
|
3179
3415
|
matInput
|
|
3180
3416
|
[formControl]="form.controls.titleWeight"
|
|
3181
3417
|
placeholder="ex: 600"
|
|
3182
3418
|
/>
|
|
3419
|
+
@if (form.controls.titleWeight.hasError('cssDeclaration')) {
|
|
3420
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3421
|
+
}
|
|
3183
3422
|
</mat-form-field>
|
|
3184
|
-
<mat-form-field appearance="outline">
|
|
3423
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3185
3424
|
<mat-label>Tamanho do subtítulo</mat-label>
|
|
3186
3425
|
<input
|
|
3187
3426
|
matInput
|
|
3188
3427
|
[formControl]="form.controls.subtitleSize"
|
|
3189
3428
|
placeholder="ex: 12px"
|
|
3190
3429
|
/>
|
|
3430
|
+
@if (form.controls.subtitleSize.hasError('cssDeclaration')) {
|
|
3431
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3432
|
+
}
|
|
3191
3433
|
</mat-form-field>
|
|
3192
3434
|
</div>
|
|
3193
3435
|
}
|
|
@@ -3472,6 +3714,7 @@ class WidgetShellEditorComponent {
|
|
|
3472
3714
|
<mat-select formControlName="placement">
|
|
3473
3715
|
<mat-option value="header">Cabeçalho</mat-option>
|
|
3474
3716
|
<mat-option value="window">Janela</mat-option>
|
|
3717
|
+
<mat-option value="menu">{{ menuPlacementLabel() }}</mat-option>
|
|
3475
3718
|
</mat-select>
|
|
3476
3719
|
</mat-form-field>
|
|
3477
3720
|
<mat-form-field appearance="outline">
|
|
@@ -3533,11 +3776,11 @@ class WidgetShellEditorComponent {
|
|
|
3533
3776
|
<div class="shell-empty">Nenhuma ação configurada.</div>
|
|
3534
3777
|
}
|
|
3535
3778
|
</div>
|
|
3536
|
-
`, isInline: true, styles: [".shell-editor{display:grid;gap:20px;padding:12px 4px 20px}.shell-intro{margin:0;max-width:68ch;color:var(--md-sys-color-on-surface-variant);font-size:14px;line-height:1.5}.shell-section{margin:4px 0 -8px;color:var(--md-sys-color-on-surface);font-size:14px;font-weight:650;line-height:1.4}.shell-grid{display:grid;gap:12px 16px;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}.shell-field--wide{grid-column:1 / -1}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100
|
|
3779
|
+
`, isInline: true, styles: [".shell-editor{display:grid;grid-template-columns:minmax(0,1fr);min-width:0;gap:20px;padding:12px 4px 20px}.shell-intro{margin:0;max-width:68ch;color:var(--md-sys-color-on-surface-variant);font-size:14px;line-height:1.5}.shell-section{margin:4px 0 -8px;color:var(--md-sys-color-on-surface);font-size:14px;font-weight:650;line-height:1.4}.shell-grid{display:grid;gap:12px 16px;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}.shell-field--wide{grid-column:1 / -1}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:minmax(0,1fr) auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%;min-width:0}:host{display:block;min-width:0}.shell-editor>*,.shell-action>*{min-width:0}.shell-available-text,.shell-input-path{min-width:0;overflow-wrap:anywhere}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var( --pdx-shell-card-shadow, 0 16px 34px rgba(0, 0, 0, .32) );transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var( --pdx-shell-header-bg, var(--md-sys-color-surface-container) )}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}@media(max-width:640px){.shell-editor{padding-inline:0}.shell-grid,.shell-action-row,.shell-quick-inputs,.shell-available-toolbar{grid-template-columns:minmax(0,1fr)}.shell-actions-head,.shell-flags{flex-wrap:wrap}.shell-field--wide{grid-column:auto}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i10.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i10.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3537
3780
|
}
|
|
3538
3781
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellEditorComponent, decorators: [{
|
|
3539
3782
|
type: Component,
|
|
3540
|
-
args: [{ selector: 'praxis-widget-shell-editor', standalone: true, imports: [
|
|
3783
|
+
args: [{ selector: 'praxis-widget-shell-editor', providers: [providePraxisPageBuilderI18n()], standalone: true, imports: [
|
|
3541
3784
|
CommonModule,
|
|
3542
3785
|
FormsModule,
|
|
3543
3786
|
ReactiveFormsModule,
|
|
@@ -3619,6 +3862,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
3619
3862
|
<mat-option value="false">Nunca</mat-option>
|
|
3620
3863
|
</mat-select>
|
|
3621
3864
|
</mat-form-field>
|
|
3865
|
+
<mat-checkbox [formControl]="form.controls.stickyHeader">
|
|
3866
|
+
{{ stickyHeaderLabel() }}
|
|
3867
|
+
</mat-checkbox>
|
|
3622
3868
|
</div>
|
|
3623
3869
|
|
|
3624
3870
|
<div class="shell-section">Controles de janela</div>
|
|
@@ -3634,125 +3880,170 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
3634
3880
|
|
|
3635
3881
|
<div class="shell-section">Aparência</div>
|
|
3636
3882
|
<div class="shell-grid">
|
|
3637
|
-
<mat-form-field appearance="outline">
|
|
3883
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3638
3884
|
<mat-label>Fundo do card</mat-label>
|
|
3639
3885
|
<input
|
|
3640
3886
|
matInput
|
|
3641
3887
|
[formControl]="form.controls.cardBg"
|
|
3642
3888
|
placeholder="ex: #0b1220"
|
|
3643
3889
|
/>
|
|
3890
|
+
@if (form.controls.cardBg.hasError('cssDeclaration')) {
|
|
3891
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3892
|
+
}
|
|
3644
3893
|
</mat-form-field>
|
|
3645
|
-
<mat-form-field appearance="outline">
|
|
3894
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3646
3895
|
<mat-label>Cor da borda</mat-label>
|
|
3647
3896
|
<input
|
|
3648
3897
|
matInput
|
|
3649
3898
|
[formControl]="form.controls.cardBorder"
|
|
3650
3899
|
placeholder="ex: rgba(255,255,255,0.12)"
|
|
3651
3900
|
/>
|
|
3901
|
+
@if (form.controls.cardBorder.hasError('cssDeclaration')) {
|
|
3902
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3903
|
+
}
|
|
3652
3904
|
</mat-form-field>
|
|
3653
|
-
<mat-form-field appearance="outline">
|
|
3905
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3654
3906
|
<mat-label>Raio da borda</mat-label>
|
|
3655
3907
|
<input
|
|
3656
3908
|
matInput
|
|
3657
3909
|
[formControl]="form.controls.cardRadius"
|
|
3658
3910
|
placeholder="ex: 14px"
|
|
3659
3911
|
/>
|
|
3912
|
+
@if (form.controls.cardRadius.hasError('cssDeclaration')) {
|
|
3913
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3914
|
+
}
|
|
3660
3915
|
</mat-form-field>
|
|
3661
|
-
<mat-form-field appearance="outline">
|
|
3916
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3662
3917
|
<mat-label>Sombra</mat-label>
|
|
3663
3918
|
<input
|
|
3664
3919
|
matInput
|
|
3665
3920
|
[formControl]="form.controls.cardShadow"
|
|
3666
3921
|
placeholder="ex: 0 10px 30px rgba(0,0,0,0.2)"
|
|
3667
3922
|
/>
|
|
3923
|
+
@if (form.controls.cardShadow.hasError('cssDeclaration')) {
|
|
3924
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3925
|
+
}
|
|
3668
3926
|
</mat-form-field>
|
|
3669
|
-
<mat-form-field appearance="outline">
|
|
3927
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3670
3928
|
<mat-label>Fundo do cabeçalho</mat-label>
|
|
3671
3929
|
<input
|
|
3672
3930
|
matInput
|
|
3673
3931
|
[formControl]="form.controls.headerBg"
|
|
3674
3932
|
placeholder="ex: linear-gradient(...)"
|
|
3675
3933
|
/>
|
|
3934
|
+
@if (form.controls.headerBg.hasError('cssDeclaration')) {
|
|
3935
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3936
|
+
}
|
|
3676
3937
|
</mat-form-field>
|
|
3677
|
-
<mat-form-field appearance="outline">
|
|
3938
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3678
3939
|
<mat-label>Borda do cabeçalho</mat-label>
|
|
3679
3940
|
<input
|
|
3680
3941
|
matInput
|
|
3681
3942
|
[formControl]="form.controls.headerBorder"
|
|
3682
3943
|
placeholder="ex: rgba(255,255,255,0.08)"
|
|
3683
3944
|
/>
|
|
3945
|
+
@if (form.controls.headerBorder.hasError('cssDeclaration')) {
|
|
3946
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3947
|
+
}
|
|
3684
3948
|
</mat-form-field>
|
|
3685
|
-
<mat-form-field appearance="outline">
|
|
3949
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3686
3950
|
<mat-label>Cor do título</mat-label>
|
|
3687
3951
|
<input
|
|
3688
3952
|
matInput
|
|
3689
3953
|
[formControl]="form.controls.titleColor"
|
|
3690
3954
|
placeholder="ex: #e6edf3"
|
|
3691
3955
|
/>
|
|
3956
|
+
@if (form.controls.titleColor.hasError('cssDeclaration')) {
|
|
3957
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3958
|
+
}
|
|
3692
3959
|
</mat-form-field>
|
|
3693
|
-
<mat-form-field appearance="outline">
|
|
3960
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3694
3961
|
<mat-label>Cor do subtítulo</mat-label>
|
|
3695
3962
|
<input
|
|
3696
3963
|
matInput
|
|
3697
3964
|
[formControl]="form.controls.subtitleColor"
|
|
3698
3965
|
placeholder="ex: #9fb0c4"
|
|
3699
3966
|
/>
|
|
3967
|
+
@if (form.controls.subtitleColor.hasError('cssDeclaration')) {
|
|
3968
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3969
|
+
}
|
|
3700
3970
|
</mat-form-field>
|
|
3701
|
-
<mat-form-field appearance="outline">
|
|
3971
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3702
3972
|
<mat-label>Cor do ícone</mat-label>
|
|
3703
3973
|
<input
|
|
3704
3974
|
matInput
|
|
3705
3975
|
[formControl]="form.controls.iconColor"
|
|
3706
3976
|
placeholder="ex: #8ab4ff"
|
|
3707
3977
|
/>
|
|
3978
|
+
@if (form.controls.iconColor.hasError('cssDeclaration')) {
|
|
3979
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3980
|
+
}
|
|
3708
3981
|
</mat-form-field>
|
|
3709
|
-
<mat-form-field appearance="outline">
|
|
3982
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3710
3983
|
<mat-label>Fundo do corpo</mat-label>
|
|
3711
3984
|
<input
|
|
3712
3985
|
matInput
|
|
3713
3986
|
[formControl]="form.controls.bodyBg"
|
|
3714
3987
|
placeholder="ex: transparent"
|
|
3715
3988
|
/>
|
|
3989
|
+
@if (form.controls.bodyBg.hasError('cssDeclaration')) {
|
|
3990
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
3991
|
+
}
|
|
3716
3992
|
</mat-form-field>
|
|
3717
|
-
<mat-form-field appearance="outline">
|
|
3993
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3718
3994
|
<mat-label>Cor do texto do corpo</mat-label>
|
|
3719
3995
|
<input
|
|
3720
3996
|
matInput
|
|
3721
3997
|
[formControl]="form.controls.bodyColor"
|
|
3722
3998
|
placeholder="ex: #e6edf3"
|
|
3723
3999
|
/>
|
|
4000
|
+
@if (form.controls.bodyColor.hasError('cssDeclaration')) {
|
|
4001
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
4002
|
+
}
|
|
3724
4003
|
</mat-form-field>
|
|
3725
|
-
<mat-form-field appearance="outline">
|
|
4004
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3726
4005
|
<mat-label>Padding do corpo</mat-label>
|
|
3727
4006
|
<input
|
|
3728
4007
|
matInput
|
|
3729
4008
|
[formControl]="form.controls.bodyPadding"
|
|
3730
4009
|
placeholder="ex: 10px 12px 12px"
|
|
3731
4010
|
/>
|
|
4011
|
+
@if (form.controls.bodyPadding.hasError('cssDeclaration')) {
|
|
4012
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
4013
|
+
}
|
|
3732
4014
|
</mat-form-field>
|
|
3733
|
-
<mat-form-field appearance="outline">
|
|
4015
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3734
4016
|
<mat-label>Tamanho do título</mat-label>
|
|
3735
4017
|
<input
|
|
3736
4018
|
matInput
|
|
3737
4019
|
[formControl]="form.controls.titleSize"
|
|
3738
4020
|
placeholder="ex: 14px"
|
|
3739
4021
|
/>
|
|
4022
|
+
@if (form.controls.titleSize.hasError('cssDeclaration')) {
|
|
4023
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
4024
|
+
}
|
|
3740
4025
|
</mat-form-field>
|
|
3741
|
-
<mat-form-field appearance="outline">
|
|
4026
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3742
4027
|
<mat-label>Peso do título</mat-label>
|
|
3743
4028
|
<input
|
|
3744
4029
|
matInput
|
|
3745
4030
|
[formControl]="form.controls.titleWeight"
|
|
3746
4031
|
placeholder="ex: 600"
|
|
3747
4032
|
/>
|
|
4033
|
+
@if (form.controls.titleWeight.hasError('cssDeclaration')) {
|
|
4034
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
4035
|
+
}
|
|
3748
4036
|
</mat-form-field>
|
|
3749
|
-
<mat-form-field appearance="outline">
|
|
4037
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
3750
4038
|
<mat-label>Tamanho do subtítulo</mat-label>
|
|
3751
4039
|
<input
|
|
3752
4040
|
matInput
|
|
3753
4041
|
[formControl]="form.controls.subtitleSize"
|
|
3754
4042
|
placeholder="ex: 12px"
|
|
3755
4043
|
/>
|
|
4044
|
+
@if (form.controls.subtitleSize.hasError('cssDeclaration')) {
|
|
4045
|
+
<mat-error>{{ appearanceError() }}</mat-error>
|
|
4046
|
+
}
|
|
3756
4047
|
</mat-form-field>
|
|
3757
4048
|
</div>
|
|
3758
4049
|
}
|
|
@@ -4037,6 +4328,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
4037
4328
|
<mat-select formControlName="placement">
|
|
4038
4329
|
<mat-option value="header">Cabeçalho</mat-option>
|
|
4039
4330
|
<mat-option value="window">Janela</mat-option>
|
|
4331
|
+
<mat-option value="menu">{{ menuPlacementLabel() }}</mat-option>
|
|
4040
4332
|
</mat-select>
|
|
4041
4333
|
</mat-form-field>
|
|
4042
4334
|
<mat-form-field appearance="outline">
|
|
@@ -4098,7 +4390,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
4098
4390
|
<div class="shell-empty">Nenhuma ação configurada.</div>
|
|
4099
4391
|
}
|
|
4100
4392
|
</div>
|
|
4101
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".shell-editor{display:grid;gap:20px;padding:12px 4px 20px}.shell-intro{margin:0;max-width:68ch;color:var(--md-sys-color-on-surface-variant);font-size:14px;line-height:1.5}.shell-section{margin:4px 0 -8px;color:var(--md-sys-color-on-surface);font-size:14px;font-weight:650;line-height:1.4}.shell-grid{display:grid;gap:12px 16px;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}.shell-field--wide{grid-column:1 / -1}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100
|
|
4393
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".shell-editor{display:grid;grid-template-columns:minmax(0,1fr);min-width:0;gap:20px;padding:12px 4px 20px}.shell-intro{margin:0;max-width:68ch;color:var(--md-sys-color-on-surface-variant);font-size:14px;line-height:1.5}.shell-section{margin:4px 0 -8px;color:var(--md-sys-color-on-surface);font-size:14px;font-weight:650;line-height:1.4}.shell-grid{display:grid;gap:12px 16px;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}.shell-field--wide{grid-column:1 / -1}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:minmax(0,1fr) auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%;min-width:0}:host{display:block;min-width:0}.shell-editor>*,.shell-action>*{min-width:0}.shell-available-text,.shell-input-path{min-width:0;overflow-wrap:anywhere}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var( --pdx-shell-card-shadow, 0 16px 34px rgba(0, 0, 0, .32) );transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var( --pdx-shell-header-bg, var(--md-sys-color-surface-container) )}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}@media(max-width:640px){.shell-editor{padding-inline:0}.shell-grid,.shell-action-row,.shell-quick-inputs,.shell-available-toolbar{grid-template-columns:minmax(0,1fr)}.shell-actions-head,.shell-flags{flex-wrap:wrap}.shell-field--wide{grid-column:auto}}\n"] }]
|
|
4102
4394
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
4103
4395
|
type: Optional
|
|
4104
4396
|
}, {
|
|
@@ -4230,13 +4522,24 @@ function deriveConnectionEditorGraph(page, options = {}) {
|
|
|
4230
4522
|
const angle = (index / count) * Math.PI * 2 - Math.PI / 2;
|
|
4231
4523
|
const widgetId = widget.key;
|
|
4232
4524
|
const componentType = widget.definition?.id ?? 'unknown';
|
|
4233
|
-
const
|
|
4525
|
+
const metadata = options.componentMetadata?.(componentType);
|
|
4526
|
+
const contracts = (metadata?.ports ?? []).filter(port => port.exposure?.public !== false && !port.exposure?.deprecated);
|
|
4527
|
+
const inputs = uniqueStrings([
|
|
4528
|
+
...contracts.filter(port => port.direction === 'input').map(port => port.id),
|
|
4529
|
+
...(contracts.length ? [] : metadata?.inputs ?? []).map(input => input.name),
|
|
4530
|
+
...Object.keys(widget.definition?.inputs ?? {}),
|
|
4531
|
+
]);
|
|
4234
4532
|
const outputs = uniqueStrings([
|
|
4533
|
+
...contracts.filter(port => port.direction === 'output').map(port => port.id),
|
|
4534
|
+
...(contracts.length ? [] : metadata?.outputs ?? []).map(output => output.name),
|
|
4235
4535
|
...Object.keys(widget.definition?.outputs ?? {}),
|
|
4236
4536
|
...configuredWidgetEventOutputs(widget),
|
|
4237
4537
|
]);
|
|
4238
|
-
const outputPorts = (outputs.length ? outputs : ['change']).map((port) => componentPort(widgetId, port, 'output', componentType));
|
|
4239
|
-
const inputPorts = prioritizedInputPorts(inputs).map((port) => componentPort(widgetId, port, 'input', componentType));
|
|
4538
|
+
const outputPorts = (outputs.length || metadata ? outputs : ['change']).map((port) => componentPort(widgetId, port, 'output', componentType));
|
|
4539
|
+
const inputPorts = (metadata ? inputs : prioritizedInputPorts(inputs)).map((port) => componentPort(widgetId, port, 'input', componentType));
|
|
4540
|
+
for (const port of [...inputPorts, ...outputPorts]) {
|
|
4541
|
+
port.contract = contracts.find(contract => contract.id === port.label && contract.direction === port.kind);
|
|
4542
|
+
}
|
|
4240
4543
|
for (const nested of collectNestedWidgets(widget)) {
|
|
4241
4544
|
const nestedComponentType = nested.definition.id ?? nested.path.find((segment) => segment.kind === 'widget')?.componentType;
|
|
4242
4545
|
const nestedPrefix = nested.definition.childWidgetKey
|
|
@@ -4251,7 +4554,7 @@ function deriveConnectionEditorGraph(page, options = {}) {
|
|
|
4251
4554
|
}
|
|
4252
4555
|
return {
|
|
4253
4556
|
id: widgetId,
|
|
4254
|
-
title: editableText(widget.shell?.title) || widgetId,
|
|
4557
|
+
title: options.widgetTitle?.(widget) || editableText(widget.shell?.title) || widgetId,
|
|
4255
4558
|
subtitle: componentType,
|
|
4256
4559
|
icon: widget.shell?.icon ?? iconForComponentType(componentType),
|
|
4257
4560
|
x: center.x + Math.cos(angle) * radiusX,
|
|
@@ -4350,7 +4653,7 @@ function deriveConnectionEditorGraph(page, options = {}) {
|
|
|
4350
4653
|
}
|
|
4351
4654
|
function editableText(value) {
|
|
4352
4655
|
if (typeof value === 'string')
|
|
4353
|
-
return value;
|
|
4656
|
+
return value.includes('${') ? '' : value;
|
|
4354
4657
|
return value?.text ?? value?.key ?? '';
|
|
4355
4658
|
}
|
|
4356
4659
|
function feedbackDiagnosticsForLinks(links) {
|
|
@@ -4530,11 +4833,23 @@ function buildCompositionLinkFromPorts(source, target, links) {
|
|
|
4530
4833
|
};
|
|
4531
4834
|
}
|
|
4532
4835
|
function inferCanonicalTransform(source, target) {
|
|
4836
|
+
if (source.kind === 'output' && target.kind === 'input'
|
|
4837
|
+
&& source.contract?.resourceQueryFieldSource && target.contract?.semanticKind === 'query-context') {
|
|
4838
|
+
return {
|
|
4839
|
+
id: `${source.nodeId}-${target.nodeId}-filter-query-projection`,
|
|
4840
|
+
version: '2.0', phase: 'link-propagation', mode: 'object-fragment',
|
|
4841
|
+
sourceBindings: [{ source: 'event' }],
|
|
4842
|
+
steps: [{ id: 'shape-filter-query', kind: 'object-template', phase: 'link-propagation',
|
|
4843
|
+
input: { source: 'event' }, config: { template: { filters: '${payload}' } } }],
|
|
4844
|
+
output: { semanticKind: 'query-context', cardinality: 'one', stableShape: true, materializationHint: 'replace' },
|
|
4845
|
+
};
|
|
4846
|
+
}
|
|
4533
4847
|
if (!isTableRowSelectionToFormResourceId(source, target)) {
|
|
4534
4848
|
return undefined;
|
|
4535
4849
|
}
|
|
4536
4850
|
return {
|
|
4537
4851
|
id: `${source.nodeId}-${target.nodeId}-row-id-projection`,
|
|
4852
|
+
fallbackValue: null,
|
|
4538
4853
|
version: '2.0',
|
|
4539
4854
|
phase: 'link-propagation',
|
|
4540
4855
|
mode: 'single-value',
|
|
@@ -4543,7 +4858,8 @@ function inferCanonicalTransform(source, target) {
|
|
|
4543
4858
|
id: 'pick-selected-row-id',
|
|
4544
4859
|
kind: 'pick-path',
|
|
4545
4860
|
phase: 'link-propagation',
|
|
4546
|
-
config: { path: '
|
|
4861
|
+
config: { path: source.endpoint.kind === 'component-port' && source.endpoint.ref.port === 'selectionChange'
|
|
4862
|
+
? 'payload.selectedRows.0.id' : 'payload.row.id' },
|
|
4547
4863
|
output: {
|
|
4548
4864
|
semanticKind: 'selection',
|
|
4549
4865
|
cardinality: 'one',
|
|
@@ -4571,9 +4887,9 @@ function isTableRowSelectionToFormResourceId(source, target) {
|
|
|
4571
4887
|
const targetComponent = String(target.endpoint.ref.componentType ?? '').toLowerCase();
|
|
4572
4888
|
const sourcePort = source.endpoint.ref.port.toLowerCase();
|
|
4573
4889
|
const targetPort = target.endpoint.ref.port.toLowerCase();
|
|
4574
|
-
return sourceComponent
|
|
4575
|
-
&& targetComponent
|
|
4576
|
-
&&
|
|
4890
|
+
return sourceComponent === 'praxis-table'
|
|
4891
|
+
&& targetComponent === 'praxis-dynamic-form'
|
|
4892
|
+
&& ['rowclick', 'selectionchange'].includes(sourcePort)
|
|
4577
4893
|
&& targetPort === 'resourceid';
|
|
4578
4894
|
}
|
|
4579
4895
|
function deriveConnectionEditorSuggestions(graph, limit = 5) {
|
|
@@ -4593,6 +4909,7 @@ function buildConnectionEditorSuggestions(graph) {
|
|
|
4593
4909
|
const targets = uniquePorts$1(graph.nodes.flatMap((node) => [...node.inputs, ...node.states]));
|
|
4594
4910
|
return sources.flatMap((source) => targets
|
|
4595
4911
|
.filter((target) => canConnectPorts(source, target))
|
|
4912
|
+
.filter((target) => !graph.connections.some(connection => connection.toPort && endpointKey(connection.toPort.endpoint) === endpointKey(target.endpoint)))
|
|
4596
4913
|
.filter((target) => !connectedPairs.has(`${endpointKey(source.endpoint)}->${endpointKey(target.endpoint)}`))
|
|
4597
4914
|
.map((target) => {
|
|
4598
4915
|
const score = suggestionScore(source, target);
|
|
@@ -4607,6 +4924,7 @@ function buildConnectionEditorSuggestions(graph) {
|
|
|
4607
4924
|
score,
|
|
4608
4925
|
};
|
|
4609
4926
|
}))
|
|
4927
|
+
.filter(suggestion => suggestion.score > 0)
|
|
4610
4928
|
.sort((a, b) => b.score - a.score || a.id.localeCompare(b.id));
|
|
4611
4929
|
}
|
|
4612
4930
|
function uniqueConnectionLinkId(source, target, links) {
|
|
@@ -4622,35 +4940,16 @@ function uniqueConnectionLinkId(source, target, links) {
|
|
|
4622
4940
|
}
|
|
4623
4941
|
return candidate;
|
|
4624
4942
|
}
|
|
4943
|
+
// Rank only explicit endpoint structure and the existing table/detail projection recipe.
|
|
4944
|
+
// This is a deterministic wiring shortcut, never primary user-intent resolution or AI advice.
|
|
4625
4945
|
function suggestionScore(source, target) {
|
|
4626
|
-
|
|
4627
|
-
const sourceLabel = source.label.toLowerCase();
|
|
4628
|
-
const targetLabel = target.label.toLowerCase();
|
|
4629
|
-
if (source.kind === 'state' && target.kind === 'input')
|
|
4630
|
-
score += 6;
|
|
4631
|
-
if (source.kind === 'output' && target.kind === 'state')
|
|
4632
|
-
score += 2;
|
|
4633
|
-
if (source.kind === 'output' && target.kind === 'input')
|
|
4634
|
-
score += 10;
|
|
4635
|
-
if (/(row|select|selection|click|change)/.test(sourceLabel))
|
|
4636
|
-
score += 8;
|
|
4637
|
-
if (/(id|resourceid|formid|query|context|filter)/.test(targetLabel))
|
|
4638
|
-
score += 8;
|
|
4639
|
-
if (source.kind === 'output' && /(row|select|selection|click)/.test(sourceLabel) && /(id|resourceid|formid)/.test(targetLabel))
|
|
4640
|
-
score += 30;
|
|
4641
|
-
if (target.endpoint.kind === 'global-action' && target.endpoint.ref.actionId === 'surface.open' && /(pointclick|selectionchange|crossfilter)/.test(sourceLabel)) {
|
|
4642
|
-
score += 70;
|
|
4643
|
-
}
|
|
4644
|
-
return score;
|
|
4946
|
+
return isTableRowSelectionToFormResourceId(source, target) ? 40 : 0;
|
|
4645
4947
|
}
|
|
4646
|
-
function suggestionReason(source, target,
|
|
4948
|
+
function suggestionReason(source, target, _score) {
|
|
4949
|
+
if (isTableRowSelectionToFormResourceId(source, target))
|
|
4950
|
+
return 'row-selection-to-id';
|
|
4647
4951
|
if (source.kind === 'state' && target.kind === 'input')
|
|
4648
4952
|
return 'state-to-input';
|
|
4649
|
-
const sourceLabel = source.label.toLowerCase();
|
|
4650
|
-
const targetLabel = target.label.toLowerCase();
|
|
4651
|
-
if (score >= 40 && /(row|select|selection|click)/.test(sourceLabel) && /(id|resourceid|formid)/.test(targetLabel)) {
|
|
4652
|
-
return 'row-selection-to-id';
|
|
4653
|
-
}
|
|
4654
4953
|
return 'compatible-port';
|
|
4655
4954
|
}
|
|
4656
4955
|
function componentPort(widgetId, port, direction, componentType, nestedPath, label = port) {
|
|
@@ -5149,7 +5448,7 @@ const CONNECTION_EDITOR_CANVAS_WIDTH = 900;
|
|
|
5149
5448
|
const CONNECTION_EDITOR_CANVAS_HEIGHT = 540;
|
|
5150
5449
|
const CENTER = { x: CONNECTION_EDITOR_CANVAS_WIDTH / 2, y: CONNECTION_EDITOR_CANVAS_HEIGHT / 2 };
|
|
5151
5450
|
const RADIUS_X = 310;
|
|
5152
|
-
const RADIUS_Y =
|
|
5451
|
+
const RADIUS_Y = 250;
|
|
5153
5452
|
function autoArrangeConnectionEditorGraph(graph) {
|
|
5154
5453
|
const stateNode = graph.nodes.find((node) => node.id === CONNECTION_EDITOR_STATE_NODE_ID) ?? null;
|
|
5155
5454
|
const widgetNodes = graph.nodes.filter((node) => node.id !== CONNECTION_EDITOR_STATE_NODE_ID);
|
|
@@ -5539,6 +5838,71 @@ class ConnectionEditorComponent {
|
|
|
5539
5838
|
focusWidget = output();
|
|
5540
5839
|
openPageSettings = output();
|
|
5541
5840
|
close = output();
|
|
5841
|
+
componentRegistry = inject(ComponentMetadataRegistry);
|
|
5842
|
+
compositionValidator = new CompositionValidatorService();
|
|
5843
|
+
draftBase = signal(null, ...(ngDevMode ? [{ debugName: "draftBase" }] : /* istanbul ignore next */ []));
|
|
5844
|
+
draftPage = signal(null, ...(ngDevMode ? [{ debugName: "draftPage" }] : /* istanbul ignore next */ []));
|
|
5845
|
+
workingPage = computed(() => this.draftPage() ?? this.page(), ...(ngDevMode ? [{ debugName: "workingPage" }] : /* istanbul ignore next */ []));
|
|
5846
|
+
draftSourceId = signal('', ...(ngDevMode ? [{ debugName: "draftSourceId" }] : /* istanbul ignore next */ []));
|
|
5847
|
+
draftTargetId = signal('', ...(ngDevMode ? [{ debugName: "draftTargetId" }] : /* istanbul ignore next */ []));
|
|
5848
|
+
draftLinkId = signal(null, ...(ngDevMode ? [{ debugName: "draftLinkId" }] : /* istanbul ignore next */ []));
|
|
5849
|
+
draftIsNew = signal(false, ...(ngDevMode ? [{ debugName: "draftIsNew" }] : /* istanbul ignore next */ []));
|
|
5850
|
+
draftSelectionBefore = null;
|
|
5851
|
+
presentationMode = signal(false, ...(ngDevMode ? [{ debugName: "presentationMode" }] : /* istanbul ignore next */ []));
|
|
5852
|
+
draftConflict = computed(() => !!this.draftBase() && !this.pagesEqual(this.draftBase(), this.page()), ...(ngDevMode ? [{ debugName: "draftConflict" }] : /* istanbul ignore next */ []));
|
|
5853
|
+
draftPorts = computed(() => {
|
|
5854
|
+
const ports = new Map(this.editorGraph().portById);
|
|
5855
|
+
for (const widget of this.workingPage()?.widgets ?? []) {
|
|
5856
|
+
for (const contract of this.componentRegistry.get(widget.definition.id)?.ports ?? []) {
|
|
5857
|
+
if (contract.exposure?.public === false || contract.exposure?.deprecated)
|
|
5858
|
+
continue;
|
|
5859
|
+
const existing = [...ports.values()].find(port => port.endpoint.kind === 'component-port'
|
|
5860
|
+
&& port.endpoint.ref.widget === widget.key && !port.endpoint.ref.nestedPath?.length
|
|
5861
|
+
&& port.endpoint.ref.port === contract.id && port.kind === contract.direction);
|
|
5862
|
+
if (existing)
|
|
5863
|
+
continue;
|
|
5864
|
+
const id = `${widget.key}-${contract.direction}-${contract.id.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'port'}`;
|
|
5865
|
+
ports.set(id, { id, nodeId: widget.key, label: contract.id, kind: contract.direction,
|
|
5866
|
+
endpoint: { kind: 'component-port', ref: { widget: widget.key, port: contract.id,
|
|
5867
|
+
direction: contract.direction, componentType: widget.definition.id } } });
|
|
5868
|
+
}
|
|
5869
|
+
}
|
|
5870
|
+
return [...ports.values()].filter(port => {
|
|
5871
|
+
if (port.endpoint.kind !== 'component-port')
|
|
5872
|
+
return true;
|
|
5873
|
+
const ref = port.endpoint.ref;
|
|
5874
|
+
const metadata = this.componentRegistry.get(ref.componentType ?? '');
|
|
5875
|
+
if (!metadata || port.id === this.draftSourceId() || port.id === this.draftTargetId())
|
|
5876
|
+
return true;
|
|
5877
|
+
return metadata.ports?.some(contract => contract.id === ref.port && contract.direction === ref.direction
|
|
5878
|
+
&& contract.exposure?.public !== false && !contract.exposure?.deprecated) ?? false;
|
|
5879
|
+
});
|
|
5880
|
+
}, ...(ngDevMode ? [{ debugName: "draftPorts" }] : /* istanbul ignore next */ []));
|
|
5881
|
+
draftSources = computed(() => this.draftPorts().filter(port => port.kind === 'output' || port.kind === 'state'), ...(ngDevMode ? [{ debugName: "draftSources" }] : /* istanbul ignore next */ []));
|
|
5882
|
+
draftTargets = computed(() => {
|
|
5883
|
+
const source = this.draftPorts().find(port => port.id === this.draftSourceId());
|
|
5884
|
+
return source ? this.draftPorts().filter(port => canConnectPorts(source, port)) : [];
|
|
5885
|
+
}, ...(ngDevMode ? [{ debugName: "draftTargets" }] : /* istanbul ignore next */ []));
|
|
5886
|
+
draftDiagnostics = computed(() => {
|
|
5887
|
+
const page = this.draftPage();
|
|
5888
|
+
if (!page)
|
|
5889
|
+
return [];
|
|
5890
|
+
const links = page.composition?.links ?? [];
|
|
5891
|
+
const baseline = new Set(this.compositionValidator.validateLinks(this.draftBase()?.composition?.links ?? [], { page: this.draftBase(), registry: this.componentRegistry }).map(diagnostic => diagnostic.id));
|
|
5892
|
+
return this.compositionValidator.validateLinks(links, { page, registry: this.componentRegistry })
|
|
5893
|
+
.filter(diagnostic => diagnostic.subject.linkId === this.draftLinkId() || !baseline.has(diagnostic.id));
|
|
5894
|
+
}, ...(ngDevMode ? [{ debugName: "draftDiagnostics" }] : /* istanbul ignore next */ []));
|
|
5895
|
+
draftDuplicate = computed(() => {
|
|
5896
|
+
const links = this.draftPage()?.composition?.links ?? [];
|
|
5897
|
+
const draft = links.find(link => link.id === this.draftLinkId());
|
|
5898
|
+
if (!draft)
|
|
5899
|
+
return false;
|
|
5900
|
+
const signature = (link) => JSON.stringify([link.from, link.to, link.condition, link.transform, link.policy]);
|
|
5901
|
+
return links.some(link => link.id !== draft.id && signature(link) === signature(draft));
|
|
5902
|
+
}, ...(ngDevMode ? [{ debugName: "draftDuplicate" }] : /* istanbul ignore next */ []));
|
|
5903
|
+
canApplyDraft = computed(() => !!this.draftSourceId() && !!this.draftTargetId() && !!this.draftLinkId()
|
|
5904
|
+
&& !this.draftConflict() && !this.draftDuplicate() && !this.globalActionPayloadError()
|
|
5905
|
+
&& !this.draftDiagnostics().some(diagnostic => diagnostic.severity === 'error' || diagnostic.severity === 'fatal'), ...(ngDevMode ? [{ debugName: "canApplyDraft" }] : /* istanbul ignore next */ []));
|
|
5542
5906
|
activeMode = signal('all', ...(ngDevMode ? [{ debugName: "activeMode" }] : /* istanbul ignore next */ []));
|
|
5543
5907
|
activeFilter = signal('all', ...(ngDevMode ? [{ debugName: "activeFilter" }] : /* istanbul ignore next */ []));
|
|
5544
5908
|
selectedWidgetId = signal(null, ...(ngDevMode ? [{ debugName: "selectedWidgetId" }] : /* istanbul ignore next */ []));
|
|
@@ -5574,17 +5938,24 @@ class ConnectionEditorComponent {
|
|
|
5574
5938
|
recentLinkFeedbackTimer = null;
|
|
5575
5939
|
minimapPointerCaptureTarget = null;
|
|
5576
5940
|
suppressedNodeClickId = null;
|
|
5577
|
-
fitViewportOnOpen = effect(() => {
|
|
5941
|
+
fitViewportOnOpen = effect((onCleanup) => {
|
|
5578
5942
|
if (!this.open())
|
|
5579
5943
|
return;
|
|
5580
|
-
|
|
5944
|
+
let observer;
|
|
5945
|
+
const timer = window.setTimeout(() => {
|
|
5581
5946
|
this.resetViewport();
|
|
5582
5947
|
this.focusEditorSurface();
|
|
5948
|
+
const stage = this.hostElement.nativeElement.querySelector('.connection-editor__stage');
|
|
5949
|
+
if (stage) {
|
|
5950
|
+
observer = new ResizeObserver(() => this.resetViewport());
|
|
5951
|
+
observer.observe(stage);
|
|
5952
|
+
}
|
|
5583
5953
|
if (this.open() && this.visualDensity() === 'guided') {
|
|
5584
5954
|
this.expandedNodeId.set(null);
|
|
5585
5955
|
this.selectedPort.set(null);
|
|
5586
5956
|
}
|
|
5587
5957
|
}, 0);
|
|
5958
|
+
onCleanup(() => { window.clearTimeout(timer); observer?.disconnect(); });
|
|
5588
5959
|
}, ...(ngDevMode ? [{ debugName: "fitViewportOnOpen" }] : /* istanbul ignore next */ []));
|
|
5589
5960
|
filters = [
|
|
5590
5961
|
{ id: 'all', label: this.tx('connections.filters.all', 'All') },
|
|
@@ -5606,7 +5977,7 @@ class ConnectionEditorComponent {
|
|
|
5606
5977
|
{ id: 'derived', label: this.tx('connections.dock.derived', 'Derived'), glyph: '⌘' },
|
|
5607
5978
|
{ id: 'export', label: this.tx('connections.dock.export', 'Export'), glyph: '⇩' },
|
|
5608
5979
|
];
|
|
5609
|
-
model = computed(() => buildConnectionsViewerModel(this.
|
|
5980
|
+
model = computed(() => buildConnectionsViewerModel(this.workingPage()), ...(ngDevMode ? [{ debugName: "model" }] : /* istanbul ignore next */ []));
|
|
5610
5981
|
selectedNode = computed(() => this.model().nodes.find((node) => node.widgetId === this.selectedWidgetId()) ?? null, ...(ngDevMode ? [{ debugName: "selectedNode" }] : /* istanbul ignore next */ []));
|
|
5611
5982
|
visibleEdges = computed(() => {
|
|
5612
5983
|
const widgetId = this.selectedWidgetId();
|
|
@@ -5631,9 +6002,20 @@ class ConnectionEditorComponent {
|
|
|
5631
6002
|
return edges;
|
|
5632
6003
|
}, ...(ngDevMode ? [{ debugName: "visibleEdges" }] : /* istanbul ignore next */ []));
|
|
5633
6004
|
selectedEdge = computed(() => this.model().edges.find((edge) => edge.id === this.selectedLinkId()) ?? null, ...(ngDevMode ? [{ debugName: "selectedEdge" }] : /* istanbul ignore next */ []));
|
|
5634
|
-
editorGraph = computed(() => deriveConnectionEditorGraph(this.
|
|
6005
|
+
editorGraph = computed(() => deriveConnectionEditorGraph(this.workingPage(), {
|
|
6006
|
+
componentMetadata: componentType => this.componentRegistry.get(componentType),
|
|
5635
6007
|
stateNodeTitle: this.tx('connections.editor.stateNode', 'Page state'),
|
|
5636
6008
|
globalActionIds: this.availableGlobalActionIds(),
|
|
6009
|
+
widgetTitle: widget => {
|
|
6010
|
+
const title = this.i18n.resolve(widget.shell?.title, '').trim();
|
|
6011
|
+
if (title && !title.includes('${'))
|
|
6012
|
+
return title;
|
|
6013
|
+
const metadata = this.componentRegistry.get(widget.definition.id);
|
|
6014
|
+
if (!metadata)
|
|
6015
|
+
return widget.key;
|
|
6016
|
+
const peers = (this.workingPage()?.widgets ?? []).filter(peer => peer.definition.id === widget.definition.id);
|
|
6017
|
+
return peers.length > 1 ? `${metadata.friendlyName} ${peers.findIndex(peer => peer.key === widget.key) + 1}` : metadata.friendlyName;
|
|
6018
|
+
},
|
|
5637
6019
|
}), ...(ngDevMode ? [{ debugName: "editorGraph" }] : /* istanbul ignore next */ []));
|
|
5638
6020
|
connectedNodeIds = computed(() => {
|
|
5639
6021
|
const ids = new Set();
|
|
@@ -5656,14 +6038,10 @@ class ConnectionEditorComponent {
|
|
|
5656
6038
|
return ids;
|
|
5657
6039
|
}, ...(ngDevMode ? [{ debugName: "connectedPortIds" }] : /* istanbul ignore next */ []));
|
|
5658
6040
|
editorNodes = computed(() => {
|
|
5659
|
-
const
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
return arranged.filter((node) => node.id !== CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID
|
|
5664
|
-
|| connectedNodeIds.has(node.id)
|
|
5665
|
-
|| this.selectedWidgetId() === node.id
|
|
5666
|
-
|| this.hoveredNodeId() === node.id);
|
|
6041
|
+
const graph = this.editorGraph();
|
|
6042
|
+
const nodes = this.visualDensity() === 'full' ? graph.nodes : graph.nodes.filter(node => node.id !== CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID || this.connectedNodeIds().has(node.id)
|
|
6043
|
+
|| this.selectedWidgetId() === node.id || this.hoveredNodeId() === node.id);
|
|
6044
|
+
return autoArrangeConnectionEditorGraph({ ...graph, nodes }).nodes.map(node => this.applyNodeOffset(this.applyNodeRotation(applyConnectionEditorPortOrder(node, this.portOrder()))));
|
|
5667
6045
|
}, ...(ngDevMode ? [{ debugName: "editorNodes" }] : /* istanbul ignore next */ []));
|
|
5668
6046
|
navigationBounds = computed(() => this.connectionEditorNavigationBounds(), ...(ngDevMode ? [{ debugName: "navigationBounds" }] : /* istanbul ignore next */ []));
|
|
5669
6047
|
minimapViewBox = computed(() => {
|
|
@@ -5710,8 +6088,8 @@ class ConnectionEditorComponent {
|
|
|
5710
6088
|
const nodes = this.editorNodes();
|
|
5711
6089
|
const hasSelectionOutput = nodes.some((node) => node.outputs.some((port) => this.isTableSelectionOutput(port)));
|
|
5712
6090
|
const hasResourceIdInput = nodes.some((node) => node.inputs.some((port) => this.isFormResourceIdInput(port)));
|
|
5713
|
-
const hasTable = nodes.some((node) => [...node.outputs, ...node.inputs, ...node.states].some((port) => this.portComponentType(port)
|
|
5714
|
-
const hasForm = nodes.some((node) => [...node.outputs, ...node.inputs, ...node.states].some((port) => this.portComponentType(port)
|
|
6091
|
+
const hasTable = nodes.some((node) => [...node.outputs, ...node.inputs, ...node.states].some((port) => this.portComponentType(port) === 'praxis-table'));
|
|
6092
|
+
const hasForm = nodes.some((node) => [...node.outputs, ...node.inputs, ...node.states].some((port) => this.portComponentType(port) === 'praxis-dynamic-form'));
|
|
5715
6093
|
if (hasTable && hasForm && !hasSelectionOutput && !hasResourceIdInput) {
|
|
5716
6094
|
return this.tx('connections.suggestions.diagnostics.masterDetailMissingBoth', 'To create master-detail, the table needs a row selection output and the form needs a resourceId input.');
|
|
5717
6095
|
}
|
|
@@ -5799,8 +6177,8 @@ class ConnectionEditorComponent {
|
|
|
5799
6177
|
|| this.rotationState()), ...(ngDevMode ? [{ debugName: "canvasInteractionActive" }] : /* istanbul ignore next */ []));
|
|
5800
6178
|
visibleConnectionTooltip = computed(() => (this.canvasInteractionActive() ? null : this.connectionTooltip()), ...(ngDevMode ? [{ debugName: "visibleConnectionTooltip" }] : /* istanbul ignore next */ []));
|
|
5801
6179
|
visibleExpandedNodeId = computed(() => (this.canvasInteractionActive() ? null : this.expandedNodeId()), ...(ngDevMode ? [{ debugName: "visibleExpandedNodeId" }] : /* istanbul ignore next */ []));
|
|
5802
|
-
canUndo = computed(() => this.undoStack().length > 0, ...(ngDevMode ? [{ debugName: "canUndo" }] : /* istanbul ignore next */ []));
|
|
5803
|
-
canRedo = computed(() => this.redoStack().length > 0, ...(ngDevMode ? [{ debugName: "canRedo" }] : /* istanbul ignore next */ []));
|
|
6180
|
+
canUndo = computed(() => !this.draftBase() && !this.presentationMode() && this.undoStack().length > 0, ...(ngDevMode ? [{ debugName: "canUndo" }] : /* istanbul ignore next */ []));
|
|
6181
|
+
canRedo = computed(() => !this.draftBase() && !this.presentationMode() && this.redoStack().length > 0, ...(ngDevMode ? [{ debugName: "canRedo" }] : /* istanbul ignore next */ []));
|
|
5804
6182
|
hasVisualPortOrder = computed(() => Object.keys(this.portOrder()).length > 0, ...(ngDevMode ? [{ debugName: "hasVisualPortOrder" }] : /* istanbul ignore next */ []));
|
|
5805
6183
|
dragPreviewPath = computed(() => {
|
|
5806
6184
|
const drag = this.dragState();
|
|
@@ -5894,6 +6272,8 @@ class ConnectionEditorComponent {
|
|
|
5894
6272
|
};
|
|
5895
6273
|
}, ...(ngDevMode ? [{ debugName: "minimapViewport" }] : /* istanbul ignore next */ []));
|
|
5896
6274
|
selectNode(nodeId) {
|
|
6275
|
+
if (this.draftBase())
|
|
6276
|
+
return;
|
|
5897
6277
|
if (this.suppressedNodeClickId === nodeId) {
|
|
5898
6278
|
this.suppressedNodeClickId = null;
|
|
5899
6279
|
return;
|
|
@@ -5909,6 +6289,8 @@ class ConnectionEditorComponent {
|
|
|
5909
6289
|
this.selectedLinkId.set(null);
|
|
5910
6290
|
}
|
|
5911
6291
|
selectSegment(port, event) {
|
|
6292
|
+
if (this.draftBase())
|
|
6293
|
+
return;
|
|
5912
6294
|
event.preventDefault();
|
|
5913
6295
|
event.stopPropagation();
|
|
5914
6296
|
this.selectedWidgetId.set(port.nodeId === this.stateNodeId ? null : port.nodeId);
|
|
@@ -5918,16 +6300,22 @@ class ConnectionEditorComponent {
|
|
|
5918
6300
|
this.traceSourceNodeId.set(null);
|
|
5919
6301
|
}
|
|
5920
6302
|
selectWidget(node) {
|
|
6303
|
+
if (this.draftBase())
|
|
6304
|
+
return;
|
|
5921
6305
|
this.selectedPort.set(null);
|
|
5922
6306
|
this.selectedWidgetId.update((current) => (current === node.widgetId ? null : node.widgetId));
|
|
5923
6307
|
this.selectedLinkId.set(null);
|
|
5924
6308
|
}
|
|
5925
6309
|
selectLink(edge) {
|
|
6310
|
+
if (this.draftBase())
|
|
6311
|
+
return;
|
|
5926
6312
|
this.selectedPort.set(null);
|
|
5927
6313
|
this.selectedLinkId.update((current) => (current === edge.id ? null : edge.id));
|
|
5928
6314
|
this.selectedWidgetId.set(null);
|
|
5929
6315
|
}
|
|
5930
6316
|
selectConnection(connection) {
|
|
6317
|
+
if (this.draftBase())
|
|
6318
|
+
return;
|
|
5931
6319
|
this.selectedLinkId.set(connection.id);
|
|
5932
6320
|
this.selectedWidgetId.set(null);
|
|
5933
6321
|
}
|
|
@@ -5956,12 +6344,27 @@ class ConnectionEditorComponent {
|
|
|
5956
6344
|
}
|
|
5957
6345
|
}
|
|
5958
6346
|
handleEditorKeydown(event) {
|
|
5959
|
-
if (!this.open()
|
|
6347
|
+
if (!this.open())
|
|
6348
|
+
return;
|
|
6349
|
+
if (event.key === 'Escape' && this.draftBase()) {
|
|
6350
|
+
event.preventDefault();
|
|
6351
|
+
this.cancelDraft();
|
|
6352
|
+
return;
|
|
6353
|
+
}
|
|
6354
|
+
if (this.shouldIgnoreEditorShortcut(event))
|
|
5960
6355
|
return;
|
|
5961
6356
|
const key = event.key.toLowerCase();
|
|
5962
6357
|
const hasCommandModifier = event.ctrlKey || event.metaKey;
|
|
5963
6358
|
if (key === 'escape') {
|
|
5964
6359
|
event.preventDefault();
|
|
6360
|
+
if (this.draftBase()) {
|
|
6361
|
+
this.cancelDraft();
|
|
6362
|
+
return;
|
|
6363
|
+
}
|
|
6364
|
+
if (this.presentationMode()) {
|
|
6365
|
+
this.togglePresentation();
|
|
6366
|
+
return;
|
|
6367
|
+
}
|
|
5965
6368
|
const hasTransientEditorState = !!(this.pendingSegmentState()
|
|
5966
6369
|
|| this.dragState()
|
|
5967
6370
|
|| this.nodeDragState()
|
|
@@ -6003,10 +6406,14 @@ class ConnectionEditorComponent {
|
|
|
6003
6406
|
}
|
|
6004
6407
|
}
|
|
6005
6408
|
setFilter(filter) {
|
|
6409
|
+
if (this.draftBase())
|
|
6410
|
+
return;
|
|
6006
6411
|
this.activeFilter.set(filter);
|
|
6007
6412
|
this.selectedLinkId.set(null);
|
|
6008
6413
|
}
|
|
6009
6414
|
setMode(mode) {
|
|
6415
|
+
if (this.draftBase())
|
|
6416
|
+
return;
|
|
6010
6417
|
this.activeMode.set(mode);
|
|
6011
6418
|
this.selectedLinkId.set(null);
|
|
6012
6419
|
this.traceEnabled.set(mode === 'simulation');
|
|
@@ -6079,6 +6486,8 @@ class ConnectionEditorComponent {
|
|
|
6079
6486
|
this.dockCollapsed.update((collapsed) => !collapsed);
|
|
6080
6487
|
}
|
|
6081
6488
|
toggleTrace(event) {
|
|
6489
|
+
if (this.draftBase())
|
|
6490
|
+
return;
|
|
6082
6491
|
event.preventDefault();
|
|
6083
6492
|
event.stopPropagation();
|
|
6084
6493
|
this.traceEnabled.update((enabled) => {
|
|
@@ -6092,6 +6501,8 @@ class ConnectionEditorComponent {
|
|
|
6092
6501
|
});
|
|
6093
6502
|
}
|
|
6094
6503
|
selectTraceSource(nodeId, event) {
|
|
6504
|
+
if (this.draftBase())
|
|
6505
|
+
return;
|
|
6095
6506
|
event.preventDefault();
|
|
6096
6507
|
event.stopPropagation();
|
|
6097
6508
|
this.traceSourceNodeId.set(nodeId);
|
|
@@ -6123,6 +6534,8 @@ class ConnectionEditorComponent {
|
|
|
6123
6534
|
this.addLink(suggestion.source, suggestion.target);
|
|
6124
6535
|
}
|
|
6125
6536
|
startDrag(port, event) {
|
|
6537
|
+
if (this.presentationMode() || this.draftBase())
|
|
6538
|
+
return;
|
|
6126
6539
|
event.preventDefault();
|
|
6127
6540
|
event.stopPropagation();
|
|
6128
6541
|
this.clearInvalidDropFeedback();
|
|
@@ -6137,6 +6550,8 @@ class ConnectionEditorComponent {
|
|
|
6137
6550
|
});
|
|
6138
6551
|
}
|
|
6139
6552
|
startSegmentDrag(port, event) {
|
|
6553
|
+
if (this.presentationMode() || this.draftBase())
|
|
6554
|
+
return;
|
|
6140
6555
|
if (event.shiftKey) {
|
|
6141
6556
|
this.startNodeRotation(port.nodeId, event);
|
|
6142
6557
|
return;
|
|
@@ -6313,6 +6728,9 @@ class ConnectionEditorComponent {
|
|
|
6313
6728
|
event.stopPropagation();
|
|
6314
6729
|
const source = this.dragState()?.port;
|
|
6315
6730
|
this.dragState.set(null);
|
|
6731
|
+
// Segment pointerup stops propagation, so finish gestures normally closed by the document.
|
|
6732
|
+
this.cancelPendingSegment();
|
|
6733
|
+
this.stopRotation();
|
|
6316
6734
|
if (!source)
|
|
6317
6735
|
return;
|
|
6318
6736
|
if (!canConnectPorts(source, target)) {
|
|
@@ -6501,7 +6919,11 @@ class ConnectionEditorComponent {
|
|
|
6501
6919
|
return this.invalidDropFeedback()?.target?.id === target.id;
|
|
6502
6920
|
}
|
|
6503
6921
|
removeLink(linkId) {
|
|
6504
|
-
|
|
6922
|
+
if (this.presentationMode())
|
|
6923
|
+
return;
|
|
6924
|
+
if (this.draftBase())
|
|
6925
|
+
return;
|
|
6926
|
+
const source = this.workingPage();
|
|
6505
6927
|
if (!source)
|
|
6506
6928
|
return;
|
|
6507
6929
|
const next = this.clonePage(source);
|
|
@@ -6516,6 +6938,10 @@ class ConnectionEditorComponent {
|
|
|
6516
6938
|
}
|
|
6517
6939
|
}
|
|
6518
6940
|
undoHistory(event) {
|
|
6941
|
+
if (this.presentationMode())
|
|
6942
|
+
return;
|
|
6943
|
+
if (this.draftBase())
|
|
6944
|
+
return;
|
|
6519
6945
|
event.preventDefault();
|
|
6520
6946
|
event.stopPropagation();
|
|
6521
6947
|
const undoStack = this.undoStack();
|
|
@@ -6529,6 +6955,10 @@ class ConnectionEditorComponent {
|
|
|
6529
6955
|
this.pageChange.emit(this.clonePage(entry.before));
|
|
6530
6956
|
}
|
|
6531
6957
|
redoHistory(event) {
|
|
6958
|
+
if (this.presentationMode())
|
|
6959
|
+
return;
|
|
6960
|
+
if (this.draftBase())
|
|
6961
|
+
return;
|
|
6532
6962
|
event.preventDefault();
|
|
6533
6963
|
event.stopPropagation();
|
|
6534
6964
|
const redoStack = this.redoStack();
|
|
@@ -6727,8 +7157,7 @@ class ConnectionEditorComponent {
|
|
|
6727
7157
|
if (this.dragState() || this.pendingSegmentState() || this.nodeHasCompatiblePreviewPort(node)) {
|
|
6728
7158
|
return true;
|
|
6729
7159
|
}
|
|
6730
|
-
|
|
6731
|
-
return [...node.inputs, ...node.outputs, ...node.states].some((port) => connectedPortIds.has(port.id));
|
|
7160
|
+
return node.id === this.selectedWidgetId() || this.isNodeFocusedByConnection(node);
|
|
6732
7161
|
}
|
|
6733
7162
|
isGuidedPortVisible(port) {
|
|
6734
7163
|
if (this.visualDensity() === 'full')
|
|
@@ -6739,7 +7168,7 @@ class ConnectionEditorComponent {
|
|
|
6739
7168
|
if (this.isDragSource(port) || this.isCompatibleDrop(port) || this.isDropCandidate(port) || this.isPortFocusedByConnection(port)) {
|
|
6740
7169
|
return true;
|
|
6741
7170
|
}
|
|
6742
|
-
return
|
|
7171
|
+
return false;
|
|
6743
7172
|
}
|
|
6744
7173
|
isGuidedSegmentLabelVisible(port) {
|
|
6745
7174
|
if (this.visualDensity() === 'full')
|
|
@@ -6906,7 +7335,8 @@ class ConnectionEditorComponent {
|
|
|
6906
7335
|
}
|
|
6907
7336
|
suggestionPreviewText(suggestion) {
|
|
6908
7337
|
if (this.isSuggestedMasterDetail(suggestion)) {
|
|
6909
|
-
|
|
7338
|
+
const link = buildCompositionLinkFromPorts(suggestion.source, suggestion.target, []);
|
|
7339
|
+
return `${this.tx('connections.preview.deliversPath', 'Delivered value')}: ${link.transform?.steps[0]?.config?.['path']}.`;
|
|
6910
7340
|
}
|
|
6911
7341
|
if (suggestion.source.kind === 'state') {
|
|
6912
7342
|
return this.tx('connections.suggestions.preview.stateToInput', 'Will deliver the current page state value.');
|
|
@@ -7010,7 +7440,7 @@ class ConnectionEditorComponent {
|
|
|
7010
7440
|
return false;
|
|
7011
7441
|
if (target.label !== 'resourceId')
|
|
7012
7442
|
return false;
|
|
7013
|
-
if (
|
|
7443
|
+
if (!['rowClick', 'selectionChange'].includes(source.label))
|
|
7014
7444
|
return false;
|
|
7015
7445
|
const sourceComponent = source.endpoint.kind === 'component-port'
|
|
7016
7446
|
? String(source.endpoint.ref.componentType ?? '').toLowerCase()
|
|
@@ -7018,17 +7448,17 @@ class ConnectionEditorComponent {
|
|
|
7018
7448
|
const targetComponent = target.endpoint.kind === 'component-port'
|
|
7019
7449
|
? String(target.endpoint.ref.componentType ?? '').toLowerCase()
|
|
7020
7450
|
: '';
|
|
7021
|
-
return sourceComponent
|
|
7451
|
+
return sourceComponent === 'praxis-table' && targetComponent === 'praxis-dynamic-form';
|
|
7022
7452
|
}
|
|
7023
7453
|
isTableSelectionOutput(port) {
|
|
7024
7454
|
return port.kind === 'output'
|
|
7025
|
-
&&
|
|
7026
|
-
&& this.portComponentType(port)
|
|
7455
|
+
&& ['rowClick', 'selectionChange'].includes(port.label)
|
|
7456
|
+
&& this.portComponentType(port) === 'praxis-table';
|
|
7027
7457
|
}
|
|
7028
7458
|
isFormResourceIdInput(port) {
|
|
7029
7459
|
return port.kind === 'input'
|
|
7030
7460
|
&& port.label === 'resourceId'
|
|
7031
|
-
&& this.portComponentType(port)
|
|
7461
|
+
&& this.portComponentType(port) === 'praxis-dynamic-form';
|
|
7032
7462
|
}
|
|
7033
7463
|
portComponentType(port) {
|
|
7034
7464
|
return port.endpoint.kind === 'component-port'
|
|
@@ -7118,7 +7548,7 @@ class ConnectionEditorComponent {
|
|
|
7118
7548
|
return this.tx('connections.tooltip.dataFlow', 'Data Flow');
|
|
7119
7549
|
}
|
|
7120
7550
|
dockJson() {
|
|
7121
|
-
return this.
|
|
7551
|
+
return this.workingPage();
|
|
7122
7552
|
}
|
|
7123
7553
|
dockLinks() {
|
|
7124
7554
|
return this.editorConnections().map((connection) => ({
|
|
@@ -7163,7 +7593,7 @@ class ConnectionEditorComponent {
|
|
|
7163
7593
|
return {
|
|
7164
7594
|
exportedAt: 'runtime',
|
|
7165
7595
|
source: '@praxisui/page-builder/connection-editor',
|
|
7166
|
-
composition: this.
|
|
7596
|
+
composition: this.workingPage()?.composition ?? { version: '1.0.0', links: [] },
|
|
7167
7597
|
derived: this.dockDerived(),
|
|
7168
7598
|
};
|
|
7169
7599
|
}
|
|
@@ -7182,17 +7612,21 @@ class ConnectionEditorComponent {
|
|
|
7182
7612
|
...graphDiagnostics,
|
|
7183
7613
|
];
|
|
7184
7614
|
}
|
|
7615
|
+
edgeRouteTitle(edge) {
|
|
7616
|
+
const connection = this.editorConnections().find(item => item.id === edge.id);
|
|
7617
|
+
return connection ? `${this.readableEndpointLabel(connection, 'from')} → ${this.readableEndpointLabel(connection, 'to')}` : this.describeEdge(edge);
|
|
7618
|
+
}
|
|
7185
7619
|
describeSource(edge) {
|
|
7186
7620
|
if (edge.fromKind === 'component-port') {
|
|
7187
7621
|
return `${edge.fromWidgetId}.${edge.fromPort}`;
|
|
7188
7622
|
}
|
|
7189
|
-
return edge.fromKind;
|
|
7623
|
+
return edge.link.from.kind === 'state' ? `state.${edge.link.from.ref.path}` : edge.fromKind;
|
|
7190
7624
|
}
|
|
7191
7625
|
describeTarget(edge) {
|
|
7192
7626
|
if (edge.toKind === 'component-port') {
|
|
7193
7627
|
return `${edge.toWidgetId}.${edge.toPort}`;
|
|
7194
7628
|
}
|
|
7195
|
-
return `state.${edge.toStatePath}`;
|
|
7629
|
+
return edge.link.to.kind === 'global-action' ? edge.link.to.ref.actionId : `state.${edge.toStatePath}`;
|
|
7196
7630
|
}
|
|
7197
7631
|
globalActionPayloadText(connection) {
|
|
7198
7632
|
const payload = connection.link.to.kind === 'global-action'
|
|
@@ -7282,6 +7716,161 @@ class ConnectionEditorComponent {
|
|
|
7282
7716
|
};
|
|
7283
7717
|
});
|
|
7284
7718
|
}
|
|
7719
|
+
beginNewConnection() {
|
|
7720
|
+
if (this.presentationMode())
|
|
7721
|
+
return;
|
|
7722
|
+
if (this.draftBase() || !this.page())
|
|
7723
|
+
return;
|
|
7724
|
+
this.draftSelectionBefore = this.selectedLinkId();
|
|
7725
|
+
this.draftBase.set(this.clonePage(this.page()));
|
|
7726
|
+
this.draftPage.set(this.clonePage(this.page()));
|
|
7727
|
+
this.draftIsNew.set(true);
|
|
7728
|
+
this.draftSourceId.set('');
|
|
7729
|
+
this.draftTargetId.set('');
|
|
7730
|
+
this.draftLinkId.set(null);
|
|
7731
|
+
this.selectedLinkId.set(null);
|
|
7732
|
+
this.selectedWidgetId.set(null);
|
|
7733
|
+
this.scrollConnectionSidePanelToTop();
|
|
7734
|
+
window.setTimeout(() => this.hostElement.nativeElement.querySelector('[data-testid="page-builder-connections-draft-source"]')?.focus(), 0);
|
|
7735
|
+
}
|
|
7736
|
+
beginEditConnection(linkId) {
|
|
7737
|
+
if (this.presentationMode())
|
|
7738
|
+
return;
|
|
7739
|
+
if (this.draftBase())
|
|
7740
|
+
return;
|
|
7741
|
+
const connection = this.editorConnections().find(item => item.id === linkId);
|
|
7742
|
+
if (!connection || !this.page())
|
|
7743
|
+
return;
|
|
7744
|
+
this.beginNewConnection();
|
|
7745
|
+
this.draftIsNew.set(false);
|
|
7746
|
+
this.draftLinkId.set(linkId);
|
|
7747
|
+
this.selectedLinkId.set(linkId);
|
|
7748
|
+
this.draftSourceId.set(connection.fromPort?.id ?? '');
|
|
7749
|
+
this.draftTargetId.set(connection.toPort?.id ?? '');
|
|
7750
|
+
}
|
|
7751
|
+
changeDraftEndpoint(side, id) {
|
|
7752
|
+
if (!this.draftBase())
|
|
7753
|
+
return;
|
|
7754
|
+
if (side === 'source')
|
|
7755
|
+
this.draftSourceId.set(id);
|
|
7756
|
+
else
|
|
7757
|
+
this.draftTargetId.set(id);
|
|
7758
|
+
const source = this.draftPorts().find(port => port.id === this.draftSourceId());
|
|
7759
|
+
const target = this.draftPorts().find(port => port.id === this.draftTargetId());
|
|
7760
|
+
if (!source || !target || !canConnectPorts(source, target)) {
|
|
7761
|
+
if (side === 'source')
|
|
7762
|
+
this.draftTargetId.set('');
|
|
7763
|
+
return;
|
|
7764
|
+
}
|
|
7765
|
+
const next = this.clonePage(this.draftPage());
|
|
7766
|
+
next.widgets = this.clonePage(this.draftBase()).widgets;
|
|
7767
|
+
const links = next.composition?.links ?? [];
|
|
7768
|
+
const previous = links.find(link => link.id === this.draftLinkId());
|
|
7769
|
+
const created = buildCompositionLinkFromPorts(source, target, links);
|
|
7770
|
+
// Editing one endpoint must not replace payload, bindingPath or nested metadata on the other.
|
|
7771
|
+
const previousConnection = this.editorConnections().find(item => item.id === previous?.id);
|
|
7772
|
+
const previousDefaultTransform = previousConnection?.fromPort && previousConnection.toPort
|
|
7773
|
+
? buildCompositionLinkFromPorts(previousConnection.fromPort, previousConnection.toPort, []).transform : undefined;
|
|
7774
|
+
const replaceDefaultTransform = this.draftIsNew() && previous
|
|
7775
|
+
&& JSON.stringify(previous.transform) === JSON.stringify(previousDefaultTransform);
|
|
7776
|
+
const link = previous
|
|
7777
|
+
? { ...previous,
|
|
7778
|
+
from: source.id === previousConnection?.fromPort?.id ? previous.from : created.from,
|
|
7779
|
+
to: target.id === previousConnection?.toPort?.id ? previous.to : created.to,
|
|
7780
|
+
intent: created.intent,
|
|
7781
|
+
...(replaceDefaultTransform ? { transform: created.transform } : {}),
|
|
7782
|
+
}
|
|
7783
|
+
: created;
|
|
7784
|
+
this.ensureSourceOutputDeclared(next, source);
|
|
7785
|
+
next.composition = { ...(next.composition ?? { version: '1.0.0' }),
|
|
7786
|
+
links: [...links.filter(item => item.id !== this.draftLinkId()), link] };
|
|
7787
|
+
this.draftLinkId.set(link.id);
|
|
7788
|
+
this.selectedLinkId.set(link.id);
|
|
7789
|
+
this.draftPage.set(next);
|
|
7790
|
+
}
|
|
7791
|
+
projectDraftValue() {
|
|
7792
|
+
const connection = this.selectedConnection();
|
|
7793
|
+
if (!connection || !this.draftBase())
|
|
7794
|
+
return;
|
|
7795
|
+
this.setConnectionTransform(connection.id, { ...this.defaultTransformPipeline(connection),
|
|
7796
|
+
steps: [this.createTransformStep('pick-path', 0, connection)],
|
|
7797
|
+
output: { semanticKind: 'value', cardinality: 'one', stableShape: false },
|
|
7798
|
+
});
|
|
7799
|
+
}
|
|
7800
|
+
setDraftMissingValue(missingValuePolicy) {
|
|
7801
|
+
const id = this.draftLinkId();
|
|
7802
|
+
if (!id)
|
|
7803
|
+
return;
|
|
7804
|
+
this.updateConnectionLink(id, link => ({ ...link,
|
|
7805
|
+
policy: { ...link.policy, missingValuePolicy },
|
|
7806
|
+
transform: link.transform ? { ...link.transform, fallbackValue: null } : undefined,
|
|
7807
|
+
}));
|
|
7808
|
+
}
|
|
7809
|
+
changeDraftPickPath(index, path) {
|
|
7810
|
+
const id = this.draftLinkId();
|
|
7811
|
+
if (!id)
|
|
7812
|
+
return;
|
|
7813
|
+
this.updateConnectionLink(id, link => ({ ...link, transform: link.transform ? { ...link.transform,
|
|
7814
|
+
steps: link.transform.steps.map((step, stepIndex) => stepIndex === index
|
|
7815
|
+
? { ...step, config: { ...step.config, path: path.trim() } } : step) } : undefined }));
|
|
7816
|
+
}
|
|
7817
|
+
draftPortLabel(port) {
|
|
7818
|
+
const title = this.editorGraph().nodes.find(node => node.id === port.nodeId)?.title ?? port.nodeId;
|
|
7819
|
+
if (port.endpoint.kind !== 'component-port')
|
|
7820
|
+
return `${title} · ${port.label}`;
|
|
7821
|
+
const ref = port.endpoint.ref;
|
|
7822
|
+
const contract = this.componentRegistry.get(ref.componentType ?? '')?.ports?.find(item => item.id === ref.port && item.direction === ref.direction);
|
|
7823
|
+
return `${title} · ${contract?.label ?? port.label}${contract?.label && contract.label !== port.label ? ` (${port.label})` : ''}`;
|
|
7824
|
+
}
|
|
7825
|
+
draftEndpointLabel(id) {
|
|
7826
|
+
const port = this.draftPorts().find(item => item.id === id);
|
|
7827
|
+
return port ? this.draftPortLabel(port) : id;
|
|
7828
|
+
}
|
|
7829
|
+
applyDraft() {
|
|
7830
|
+
if (!this.canApplyDraft())
|
|
7831
|
+
return;
|
|
7832
|
+
const next = this.draftPage();
|
|
7833
|
+
const id = this.draftLinkId();
|
|
7834
|
+
const created = this.draftIsNew();
|
|
7835
|
+
this.clearDraft();
|
|
7836
|
+
this.selectedLinkId.set(this.draftSelectionBefore);
|
|
7837
|
+
this.commitPageChange(next, id);
|
|
7838
|
+
if (created && id) {
|
|
7839
|
+
this.lastCreatedLinkId.set(id);
|
|
7840
|
+
this.markRecentLink(id);
|
|
7841
|
+
}
|
|
7842
|
+
this.focusEditorSurface();
|
|
7843
|
+
}
|
|
7844
|
+
cancelDraft() {
|
|
7845
|
+
const id = this.draftIsNew() ? null : this.draftLinkId();
|
|
7846
|
+
this.clearDraft();
|
|
7847
|
+
this.selectedLinkId.set(id);
|
|
7848
|
+
this.focusEditorSurface();
|
|
7849
|
+
}
|
|
7850
|
+
clearDraft() {
|
|
7851
|
+
this.draftBase.set(null);
|
|
7852
|
+
this.draftPage.set(null);
|
|
7853
|
+
this.draftLinkId.set(null);
|
|
7854
|
+
this.draftSourceId.set('');
|
|
7855
|
+
this.draftTargetId.set('');
|
|
7856
|
+
this.globalActionPayloadError.set(null);
|
|
7857
|
+
}
|
|
7858
|
+
closeEditor() {
|
|
7859
|
+
if (this.draftBase()) {
|
|
7860
|
+
this.cancelDraft();
|
|
7861
|
+
return;
|
|
7862
|
+
}
|
|
7863
|
+
this.close.emit();
|
|
7864
|
+
}
|
|
7865
|
+
nodeCaptionWidth() {
|
|
7866
|
+
return Math.min(180, this.stageClientSize().width / 3) / this.viewport().scale;
|
|
7867
|
+
}
|
|
7868
|
+
togglePresentation() {
|
|
7869
|
+
if (this.draftBase())
|
|
7870
|
+
return;
|
|
7871
|
+
this.presentationMode.update(value => !value);
|
|
7872
|
+
window.setTimeout(() => this.resetViewport(), 0);
|
|
7873
|
+
}
|
|
7285
7874
|
tx(key, fallback) {
|
|
7286
7875
|
return resolvePraxisPageBuilderText(this.i18n, key, fallback);
|
|
7287
7876
|
}
|
|
@@ -7293,7 +7882,12 @@ class ConnectionEditorComponent {
|
|
|
7293
7882
|
return this.availableGlobalActions().map((entry) => entry.id);
|
|
7294
7883
|
}
|
|
7295
7884
|
addLink(source, target) {
|
|
7296
|
-
|
|
7885
|
+
if (this.presentationMode())
|
|
7886
|
+
return;
|
|
7887
|
+
if (this.draftBase())
|
|
7888
|
+
return;
|
|
7889
|
+
this.beginNewConnection();
|
|
7890
|
+
const page = this.workingPage();
|
|
7297
7891
|
if (!page)
|
|
7298
7892
|
return;
|
|
7299
7893
|
const next = this.clonePage(page);
|
|
@@ -7304,9 +7898,11 @@ class ConnectionEditorComponent {
|
|
|
7304
7898
|
...(next.composition ?? { version: '1.0.0' }),
|
|
7305
7899
|
links: [...links, link],
|
|
7306
7900
|
};
|
|
7307
|
-
this.
|
|
7308
|
-
this.
|
|
7309
|
-
this.
|
|
7901
|
+
this.draftSourceId.set(source.id);
|
|
7902
|
+
this.draftTargetId.set(target.id);
|
|
7903
|
+
this.draftLinkId.set(link.id);
|
|
7904
|
+
this.selectedLinkId.set(link.id);
|
|
7905
|
+
this.draftPage.set(next);
|
|
7310
7906
|
this.scrollConnectionSidePanelToTop();
|
|
7311
7907
|
}
|
|
7312
7908
|
ensureSourceOutputDeclared(page, source) {
|
|
@@ -7366,7 +7962,9 @@ class ConnectionEditorComponent {
|
|
|
7366
7962
|
});
|
|
7367
7963
|
}
|
|
7368
7964
|
updateConnectionLink(linkId, update) {
|
|
7369
|
-
|
|
7965
|
+
if (!this.draftBase())
|
|
7966
|
+
this.beginEditConnection(linkId);
|
|
7967
|
+
const source = this.workingPage();
|
|
7370
7968
|
if (!source)
|
|
7371
7969
|
return;
|
|
7372
7970
|
const next = this.clonePage(source);
|
|
@@ -7378,6 +7976,11 @@ class ConnectionEditorComponent {
|
|
|
7378
7976
|
this.commitPageChange(next, linkId);
|
|
7379
7977
|
}
|
|
7380
7978
|
commitPageChange(next, selectedAfter) {
|
|
7979
|
+
if (this.draftBase()) {
|
|
7980
|
+
this.draftPage.set(next);
|
|
7981
|
+
this.selectedLinkId.set(selectedAfter);
|
|
7982
|
+
return;
|
|
7983
|
+
}
|
|
7381
7984
|
const current = this.page();
|
|
7382
7985
|
if (!current)
|
|
7383
7986
|
return;
|
|
@@ -7411,7 +8014,7 @@ class ConnectionEditorComponent {
|
|
|
7411
8014
|
kind,
|
|
7412
8015
|
phase: 'link-propagation',
|
|
7413
8016
|
...(kind === 'pick-path'
|
|
7414
|
-
? { config: { path: connection.
|
|
8017
|
+
? { config: { path: connection.link.from.kind === 'state' ? 'current' : 'payload' } }
|
|
7415
8018
|
: {}),
|
|
7416
8019
|
};
|
|
7417
8020
|
}
|
|
@@ -7683,7 +8286,7 @@ class ConnectionEditorComponent {
|
|
|
7683
8286
|
fitViewportState() {
|
|
7684
8287
|
const stage = this.stageClientSize();
|
|
7685
8288
|
const bounds = this.navigationBounds();
|
|
7686
|
-
const scale = this.clamp(Math.min(stage.width / bounds.width, stage.height / bounds.height) * 0.94, 0.
|
|
8289
|
+
const scale = this.clamp(Math.min(stage.width / bounds.width, stage.height / bounds.height) * 0.94, 0.2, 1);
|
|
7687
8290
|
return this.clampViewport({
|
|
7688
8291
|
x: ((stage.width - bounds.width * scale) / 2) - bounds.x * scale,
|
|
7689
8292
|
y: ((stage.height - bounds.height * scale) / 2) - bounds.y * scale,
|
|
@@ -7760,6 +8363,8 @@ class ConnectionEditorComponent {
|
|
|
7760
8363
|
@if (open()) {
|
|
7761
8364
|
<aside
|
|
7762
8365
|
class="connection-editor"
|
|
8366
|
+
[class.connection-editor--presentation]="presentationMode()"
|
|
8367
|
+
[class.connection-editor--draft]="!!draftBase()"
|
|
7763
8368
|
[class.connection-editor--guided]="visualDensity() === 'guided'"
|
|
7764
8369
|
[class.connection-editor--full]="visualDensity() === 'full'"
|
|
7765
8370
|
[class.connection-editor--dock-collapsed]="dockCollapsed()"
|
|
@@ -7780,7 +8385,7 @@ class ConnectionEditorComponent {
|
|
|
7780
8385
|
@for (mode of flowModes; track mode.id) {
|
|
7781
8386
|
<button
|
|
7782
8387
|
type="button"
|
|
7783
|
-
class="connection-editor__mode"
|
|
8388
|
+
class="connection-editor__mode" [disabled]="!!draftBase()"
|
|
7784
8389
|
role="tab"
|
|
7785
8390
|
[class.connection-editor__mode--active]="activeMode() === mode.id"
|
|
7786
8391
|
[attr.aria-selected]="activeMode() === mode.id"
|
|
@@ -7796,6 +8401,16 @@ class ConnectionEditorComponent {
|
|
|
7796
8401
|
}
|
|
7797
8402
|
</div>
|
|
7798
8403
|
</div>
|
|
8404
|
+
<div class="connection-editor__header-actions">
|
|
8405
|
+
<button type="button" class="connection-editor__action connection-editor__action--primary"
|
|
8406
|
+
data-testid="page-builder-connections-new" [disabled]="!!draftBase() || presentationMode()"
|
|
8407
|
+
(click)="beginNewConnection()">+ {{ tx('connections.draft.new', 'New connection') }}</button>
|
|
8408
|
+
<button type="button" class="connection-editor__action"
|
|
8409
|
+
data-testid="page-builder-connections-presentation" [attr.aria-pressed]="presentationMode()"
|
|
8410
|
+
[disabled]="!!draftBase()" (click)="togglePresentation()">
|
|
8411
|
+
{{ presentationMode() ? tx('connections.draft.backToEdit', 'Back to editing') : tx('connections.draft.present', 'Present diagram') }}
|
|
8412
|
+
</button>
|
|
8413
|
+
</div>
|
|
7799
8414
|
<div class="connection-editor__subtitle">
|
|
7800
8415
|
<button
|
|
7801
8416
|
type="button"
|
|
@@ -7814,7 +8429,7 @@ class ConnectionEditorComponent {
|
|
|
7814
8429
|
class="connection-editor__close"
|
|
7815
8430
|
data-testid="page-builder-connections-close"
|
|
7816
8431
|
[attr.aria-label]="tx('connections.closeAria', 'Close connection editor')"
|
|
7817
|
-
(click)="
|
|
8432
|
+
(click)="closeEditor()"
|
|
7818
8433
|
>
|
|
7819
8434
|
×
|
|
7820
8435
|
</button>
|
|
@@ -7832,6 +8447,9 @@ class ConnectionEditorComponent {
|
|
|
7832
8447
|
<div class="connection-editor__viewport" [style.transform]="viewportTransform()">
|
|
7833
8448
|
<svg class="connection-editor__wires" [attr.viewBox]="canvasViewBox" aria-hidden="true">
|
|
7834
8449
|
<defs>
|
|
8450
|
+
<marker id="connection-direction" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse" markerUnits="userSpaceOnUse">
|
|
8451
|
+
<path d="M 1 1 L 9 5 L 1 9" fill="none" stroke="context-stroke" stroke-width="2" />
|
|
8452
|
+
</marker>
|
|
7835
8453
|
<filter id="connection-glow" x="-20%" y="-20%" width="140%" height="140%">
|
|
7836
8454
|
<feGaussianBlur stdDeviation="3" result="blur" />
|
|
7837
8455
|
<feMerge>
|
|
@@ -7862,11 +8480,11 @@ class ConnectionEditorComponent {
|
|
|
7862
8480
|
[class.connection-editor__wire--trace]="isTracedConnection(connection)"
|
|
7863
8481
|
[class.connection-editor__wire--active]="selectedLinkId() === connection.id"
|
|
7864
8482
|
[class.connection-editor__wire--new]="recentLinkId() === connection.id"
|
|
7865
|
-
[class.connection-editor__wire--mode-dimmed]="isModeDimmedConnection(connection)"
|
|
8483
|
+
[class.connection-editor__wire--mode-dimmed]="isModeDimmedConnection(connection) || (!!selectedLinkId() && selectedLinkId() !== connection.id)"
|
|
7866
8484
|
[attr.d]="wirePath(connection)"
|
|
7867
8485
|
/>
|
|
7868
8486
|
<path
|
|
7869
|
-
class="connection-editor__wire"
|
|
8487
|
+
class="connection-editor__wire" marker-end="url(#connection-direction)"
|
|
7870
8488
|
[class.connection-editor__wire--active]="selectedLinkId() === connection.id"
|
|
7871
8489
|
[class.connection-editor__wire--state]="connection.intent === 'state-write'"
|
|
7872
8490
|
[class.connection-editor__wire--state-read]="connection.intent === 'state-read'"
|
|
@@ -7877,7 +8495,7 @@ class ConnectionEditorComponent {
|
|
|
7877
8495
|
[class.connection-editor__wire--error]="connectionHasErrors(connection)"
|
|
7878
8496
|
[class.connection-editor__wire--trace]="isTracedConnection(connection)"
|
|
7879
8497
|
[class.connection-editor__wire--new]="recentLinkId() === connection.id"
|
|
7880
|
-
[class.connection-editor__wire--mode-dimmed]="isModeDimmedConnection(connection)"
|
|
8498
|
+
[class.connection-editor__wire--mode-dimmed]="isModeDimmedConnection(connection) || (!!selectedLinkId() && selectedLinkId() !== connection.id)"
|
|
7881
8499
|
[attr.d]="wirePath(connection)"
|
|
7882
8500
|
(pointerenter)="previewConnection(connection)"
|
|
7883
8501
|
(pointerleave)="clearPreviewConnection(connection)"
|
|
@@ -8159,9 +8777,11 @@ class ConnectionEditorComponent {
|
|
|
8159
8777
|
</svg>
|
|
8160
8778
|
<span class="connection-editor__node-core">
|
|
8161
8779
|
<span class="connection-editor__node-icon" aria-hidden="true">{{ nodeIcon(node) }}</span>
|
|
8162
|
-
|
|
8780
|
+
|
|
8163
8781
|
<span class="connection-editor__node-subtitle">{{ node.subtitle }}</span>
|
|
8164
8782
|
</span>
|
|
8783
|
+
<span class="connection-editor__node-caption" [style.font-size.px]="13 / viewport().scale"
|
|
8784
|
+
[style.width.px]="nodeCaptionWidth()">{{ node.title }}</span>
|
|
8165
8785
|
</button>
|
|
8166
8786
|
|
|
8167
8787
|
@if (visibleExpandedNodeId() === node.id) {
|
|
@@ -8239,6 +8859,8 @@ class ConnectionEditorComponent {
|
|
|
8239
8859
|
<div
|
|
8240
8860
|
class="connection-editor__ports connection-editor__ports--outputs"
|
|
8241
8861
|
[class.connection-editor__ports--visible]="areNodePortsVisible(node)"
|
|
8862
|
+
[style.font-size.px]="11 / viewport().scale"
|
|
8863
|
+
[style.max-width.px]="230 / viewport().scale"
|
|
8242
8864
|
[style.left.px]="node.x + 132"
|
|
8243
8865
|
[style.top.px]="node.y + 24"
|
|
8244
8866
|
(pointerenter)="hoveredNodeId.set(node.id)"
|
|
@@ -8263,6 +8885,8 @@ class ConnectionEditorComponent {
|
|
|
8263
8885
|
<div
|
|
8264
8886
|
class="connection-editor__ports connection-editor__ports--inputs"
|
|
8265
8887
|
[class.connection-editor__ports--visible]="areNodePortsVisible(node)"
|
|
8888
|
+
[style.font-size.px]="11 / viewport().scale"
|
|
8889
|
+
[style.max-width.px]="230 / viewport().scale"
|
|
8266
8890
|
[style.left.px]="node.x - 104"
|
|
8267
8891
|
[style.top.px]="node.y + 24"
|
|
8268
8892
|
(pointerenter)="hoveredNodeId.set(node.id)"
|
|
@@ -8520,6 +9144,76 @@ class ConnectionEditorComponent {
|
|
|
8520
9144
|
[class.connection-editor__side-panel--contextual]="!!selectedConnection() || !!selectedEditorNode()"
|
|
8521
9145
|
data-testid="page-builder-connections-side-panel"
|
|
8522
9146
|
>
|
|
9147
|
+
@if (draftBase()) {
|
|
9148
|
+
<section class="connection-editor__draft" data-testid="page-builder-connections-draft">
|
|
9149
|
+
<div class="connection-editor__section-title">{{ tx('connections.draft.title', 'Connection draft') }}</div>
|
|
9150
|
+
<p>{{ tx('connections.draft.help', 'Choose the source and destination, then review the connection before applying it.') }}</p>
|
|
9151
|
+
<label>
|
|
9152
|
+
<span>{{ tx('connections.draft.source', '1 · Source / event') }}</span>
|
|
9153
|
+
<select #sourceSelect [value]="draftSourceId()" (change)="changeDraftEndpoint('source', sourceSelect.value)"
|
|
9154
|
+
data-testid="page-builder-connections-draft-source">
|
|
9155
|
+
<option value="">{{ tx('connections.draft.chooseSource', 'Choose a source') }}</option>
|
|
9156
|
+
@for (port of draftSources(); track port.id) { <option [value]="port.id">{{ draftPortLabel(port) }}</option> }
|
|
9157
|
+
</select>
|
|
9158
|
+
</label>
|
|
9159
|
+
<label>
|
|
9160
|
+
<span>{{ tx('connections.draft.target', '2 · Destination / input') }}</span>
|
|
9161
|
+
<select #targetSelect [value]="draftTargetId()" [disabled]="!draftSourceId()"
|
|
9162
|
+
(change)="changeDraftEndpoint('target', targetSelect.value)" data-testid="page-builder-connections-draft-target">
|
|
9163
|
+
<option value="">{{ tx('connections.draft.chooseTarget', 'Choose a destination') }}</option>
|
|
9164
|
+
@for (port of draftTargets(); track port.id) { <option [value]="port.id">{{ draftPortLabel(port) }}</option> }
|
|
9165
|
+
</select>
|
|
9166
|
+
</label>
|
|
9167
|
+
<p>{{ tx('connections.draft.prerequisites', 'Enable the source event in its component settings. For row selection, enable single selection; configure the detail as read-only when needed.') }}</p>
|
|
9168
|
+
@if (selectedConnection(); as connection) {
|
|
9169
|
+
<div class="connection-editor__draft-review">
|
|
9170
|
+
<span>{{ tx('connections.draft.review', 'Review the route') }}</span>
|
|
9171
|
+
<strong>{{ draftEndpointLabel(draftSourceId()) }}</strong>
|
|
9172
|
+
<span aria-hidden="true">↓</span>
|
|
9173
|
+
<strong>{{ draftEndpointLabel(draftTargetId()) }}</strong>
|
|
9174
|
+
</div>
|
|
9175
|
+
@for (step of connection.link.transform?.steps; track step.id ?? $index) {
|
|
9176
|
+
@if (step.kind === 'pick-path') {
|
|
9177
|
+
<label>
|
|
9178
|
+
<span>{{ tx('connections.draft.valuePath', 'Value to deliver · payload path') }}</span>
|
|
9179
|
+
<input #valuePath [value]="step.config?.['path'] ?? ''" (change)="changeDraftPickPath($index, valuePath.value)"
|
|
9180
|
+
data-testid="page-builder-connections-draft-path" />
|
|
9181
|
+
</label>
|
|
9182
|
+
<p>{{ connection.link.transform?.fallbackValue === null && connection.link.policy?.missingValuePolicy !== 'skip' ? tx('connections.draft.nullFallback', 'When the value is absent, deliver null (clear the destination).') : tx('connections.draft.existingFallback', 'Missing values follow the configured transform and delivery policy below.') }}</p>
|
|
9183
|
+
<div class="connection-editor__actions">
|
|
9184
|
+
<button type="button" class="connection-editor__action"
|
|
9185
|
+
[attr.aria-pressed]="connection.link.transform?.fallbackValue === null && connection.link.policy?.missingValuePolicy !== 'skip'"
|
|
9186
|
+
(click)="setDraftMissingValue('use-default')">{{ tx('connections.draft.clearMissing', 'Clear when absent') }}</button>
|
|
9187
|
+
<button type="button" class="connection-editor__action" [attr.aria-pressed]="connection.link.policy?.missingValuePolicy === 'skip'"
|
|
9188
|
+
(click)="setDraftMissingValue('skip')">{{ tx('connections.draft.keepMissing', 'Keep destination when absent') }}</button>
|
|
9189
|
+
</div>
|
|
9190
|
+
}
|
|
9191
|
+
}
|
|
9192
|
+
@if (!connection.link.transform?.steps?.length) {
|
|
9193
|
+
<p>{{ tx('connections.draft.wholePayload', 'The source value is delivered without a transformation. Use the advanced settings to project a field.') }}</p>
|
|
9194
|
+
<button type="button" class="connection-editor__action" (click)="projectDraftValue()">{{ tx('connections.draft.extract', 'Extract a field') }}</button>
|
|
9195
|
+
}
|
|
9196
|
+
}
|
|
9197
|
+
@for (diagnostic of draftDiagnostics(); track diagnostic.id) {
|
|
9198
|
+
<p class="connection-editor__diagnostic" [class.connection-editor__diagnostic--error]="diagnostic.severity === 'error' || diagnostic.severity === 'fatal'"
|
|
9199
|
+
role="status">{{ diagnostic.message }}</p>
|
|
9200
|
+
}
|
|
9201
|
+
@if (draftDuplicate()) { <p role="alert">{{ tx('connections.draft.duplicate', 'An identical connection already exists. Edit the existing connection or change this draft.') }}</p> }
|
|
9202
|
+
@if (draftConflict()) { <p role="alert">{{ tx('connections.draft.conflict', 'The page changed during editing. Cancel this draft and reopen the connection to use the latest version.') }}</p> }
|
|
9203
|
+
<p class="connection-editor__draft-status" role="status">{{ tx('connections.draft.pending', 'Draft · not yet applied to the page') }}</p>
|
|
9204
|
+
<div class="connection-editor__actions connection-editor__draft-actions">
|
|
9205
|
+
<button type="button" class="connection-editor__action connection-editor__action--primary"
|
|
9206
|
+
data-testid="page-builder-connections-draft-apply" [disabled]="!canApplyDraft()" (click)="applyDraft()">
|
|
9207
|
+
{{ tx('connections.draft.apply', 'Apply connection') }}
|
|
9208
|
+
</button>
|
|
9209
|
+
<button type="button" class="connection-editor__action" data-testid="page-builder-connections-draft-cancel"
|
|
9210
|
+
(click)="cancelDraft()">{{ tx('connections.draft.cancel', 'Cancel') }}</button>
|
|
9211
|
+
</div>
|
|
9212
|
+
</section>
|
|
9213
|
+
} @else {
|
|
9214
|
+
<p class="connection-editor__working-note" role="status">{{ tx('connections.draft.pageSave', 'Connections apply to the page in the builder. Save the page to persist your changes.') }}</p>
|
|
9215
|
+
}
|
|
9216
|
+
@if (visualDensity() === 'full' && !draftBase()) {
|
|
8523
9217
|
@if (recommendedMasterDetailSuggestion(); as suggestion) {
|
|
8524
9218
|
<section
|
|
8525
9219
|
class="connection-editor__section connection-editor__recommended"
|
|
@@ -8540,6 +9234,7 @@ class ConnectionEditorComponent {
|
|
|
8540
9234
|
</button>
|
|
8541
9235
|
</section>
|
|
8542
9236
|
}
|
|
9237
|
+
}
|
|
8543
9238
|
<section class="connection-editor__section connection-editor__filters-section">
|
|
8544
9239
|
<div class="connection-editor__section-title">{{ tx('connections.filters.title', 'Filters') }}</div>
|
|
8545
9240
|
<div class="connection-editor__filters">
|
|
@@ -8622,6 +9317,14 @@ class ConnectionEditorComponent {
|
|
|
8622
9317
|
<pre>{{ connection.link.to | json }}</pre>
|
|
8623
9318
|
</div>
|
|
8624
9319
|
</details>
|
|
9320
|
+
@if (!draftBase()) {
|
|
9321
|
+
<button type="button" class="connection-editor__action connection-editor__action--primary"
|
|
9322
|
+
data-testid="page-builder-connections-edit" (click)="beginEditConnection(connection.id)">
|
|
9323
|
+
{{ tx('connections.draft.edit', 'Edit connection') }}
|
|
9324
|
+
</button>
|
|
9325
|
+
}
|
|
9326
|
+
<details class="connection-editor__advanced" [open]="!!draftBase()">
|
|
9327
|
+
<summary>{{ tx('connections.draft.advanced', 'Transformation, conditions and delivery') }}</summary>
|
|
8625
9328
|
@if (connection.link.to.kind === 'global-action') {
|
|
8626
9329
|
<div class="connection-editor__details-block" data-testid="page-builder-connections-global-action-payload-editor">
|
|
8627
9330
|
<div class="connection-editor__details-label">{{ tx('connections.globalAction.payloadTitle', 'Action payload') }}</div>
|
|
@@ -8808,6 +9511,7 @@ class ConnectionEditorComponent {
|
|
|
8808
9511
|
}
|
|
8809
9512
|
</div>
|
|
8810
9513
|
</div>
|
|
9514
|
+
</details>
|
|
8811
9515
|
@if (connection.diagnostics.length) {
|
|
8812
9516
|
<div class="connection-editor__details-block" data-testid="page-builder-connections-inspector-diagnostics">
|
|
8813
9517
|
<div class="connection-editor__details-label">{{ tx('connections.validation.title', 'Validation') }}</div>
|
|
@@ -8849,7 +9553,7 @@ class ConnectionEditorComponent {
|
|
|
8849
9553
|
<button
|
|
8850
9554
|
type="button"
|
|
8851
9555
|
class="connection-editor__action connection-editor__action--danger"
|
|
8852
|
-
data-testid="page-builder-connections-inspector-remove-link"
|
|
9556
|
+
data-testid="page-builder-connections-inspector-remove-link" [disabled]="!!draftBase()"
|
|
8853
9557
|
(click)="removeLink(connection.id)"
|
|
8854
9558
|
>
|
|
8855
9559
|
{{ tx('connections.editor.removeLink', 'Remove connection') }}
|
|
@@ -8924,6 +9628,7 @@ class ConnectionEditorComponent {
|
|
|
8924
9628
|
</div>
|
|
8925
9629
|
</div>
|
|
8926
9630
|
}
|
|
9631
|
+
@if (visualDensity() === 'full' && !draftBase()) {
|
|
8927
9632
|
@if (smartSuggestions().length) {
|
|
8928
9633
|
<div class="connection-editor__suggestions" data-testid="page-builder-connections-suggestions">
|
|
8929
9634
|
<div class="connection-editor__section-title">{{ tx('connections.suggestions.title', 'Smart suggestions') }}</div>
|
|
@@ -8971,6 +9676,7 @@ class ConnectionEditorComponent {
|
|
|
8971
9676
|
</div>
|
|
8972
9677
|
</div>
|
|
8973
9678
|
}
|
|
9679
|
+
}
|
|
8974
9680
|
@if (traceEnabled()) {
|
|
8975
9681
|
<div class="connection-editor__trace" data-testid="page-builder-connections-trace">
|
|
8976
9682
|
<div class="connection-editor__section-title">{{ tx('connections.trace.title', 'Simulation trace') }}</div>
|
|
@@ -8993,7 +9699,7 @@ class ConnectionEditorComponent {
|
|
|
8993
9699
|
}
|
|
8994
9700
|
</section>
|
|
8995
9701
|
|
|
8996
|
-
<section class="connection-editor__section">
|
|
9702
|
+
<section class="connection-editor__section connection-editor__widget-list">
|
|
8997
9703
|
<div class="connection-editor__section-title">{{ tx('connections.widgets.title', 'Widgets') }}</div>
|
|
8998
9704
|
@for (node of model().nodes; track node.widgetId) {
|
|
8999
9705
|
<button
|
|
@@ -9028,7 +9734,7 @@ class ConnectionEditorComponent {
|
|
|
9028
9734
|
</section>
|
|
9029
9735
|
}
|
|
9030
9736
|
|
|
9031
|
-
<section class="connection-editor__section">
|
|
9737
|
+
<section class="connection-editor__section connection-editor__link-list">
|
|
9032
9738
|
<div class="connection-editor__section-title">{{ tx('connections.links.title', 'Links') }}</div>
|
|
9033
9739
|
@for (edge of visibleEdges(); track edge.id) {
|
|
9034
9740
|
<button
|
|
@@ -9038,8 +9744,8 @@ class ConnectionEditorComponent {
|
|
|
9038
9744
|
[class.connection-editor__item--active]="selectedLinkId() === edge.id"
|
|
9039
9745
|
(click)="selectLink(edge)"
|
|
9040
9746
|
>
|
|
9041
|
-
<div class="connection-editor__item-title">{{ edge
|
|
9042
|
-
<div class="connection-editor__item-copy">{{
|
|
9747
|
+
<div class="connection-editor__item-title">{{ edgeRouteTitle(edge) }}</div>
|
|
9748
|
+
<div class="connection-editor__item-copy">{{ edge.id }}</div>
|
|
9043
9749
|
<div class="connection-editor__badges">
|
|
9044
9750
|
@if (edge.hasCondition) {
|
|
9045
9751
|
<span class="connection-editor__badge">{{ tx('connections.badges.condition', 'Condition') }}</span>
|
|
@@ -9279,7 +9985,7 @@ class ConnectionEditorComponent {
|
|
|
9279
9985
|
</section>
|
|
9280
9986
|
</aside>
|
|
9281
9987
|
}
|
|
9282
|
-
`, isInline: true, styles: [":host{position:fixed;inset:0;z-index:1000;pointer-events:none}.connection-editor{--pce-fg: var(--md-sys-color-on-surface, #dce6f4);--pce-strong: var(--md-sys-color-on-surface, #f8fafc);--pce-muted: var(--md-sys-color-on-surface-variant, #94a3b8);--pce-primary: var(--md-sys-color-primary, #19c8e8);--pce-secondary: var(--md-sys-color-secondary, #b46cff);--pce-tertiary: var(--md-sys-color-tertiary, #ff9f2f);--pce-success: var(--md-sys-color-tertiary, #10b981);--pce-warning: var(--md-sys-color-error, #ff9f2f);--pce-error: var(--md-sys-color-error, #ef4444);--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #07111f) 80%, #020617);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #08101d) 78%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #0f172a) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #080d18) 64%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #899ab7) 46%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #94a3b8) 58%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #7d8fa9) 24%, transparent);--pce-glass-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, #ffffff) 8%, transparent);--pce-shadow: color-mix(in srgb, #000 56%, transparent);--pce-shadow-soft: color-mix(in srgb, #000 30%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #040a13) 42%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high, #050912) 94%, transparent);position:absolute;inset:12px;height:calc(100vh - 24px);box-sizing:border-box;overflow:hidden;padding:16px;border-radius:18px;color:var(--pce-fg);background:radial-gradient(circle at 72% 20%,color-mix(in srgb,var(--pce-secondary) 16%,transparent),transparent 28%),radial-gradient(circle at 26% 74%,color-mix(in srgb,var(--pce-primary) 10%,transparent),transparent 34%),radial-gradient(circle at 48% 52%,color-mix(in srgb,var(--pce-tertiary) 5%,transparent),transparent 35%),linear-gradient(var(--pce-grid) 1px,transparent 1px),linear-gradient(90deg,var(--pce-grid) 1px,transparent 1px),var(--pce-surface-base);background-size:auto,auto,auto,38px 38px,38px 38px,auto;border:1px solid var(--pce-outline);box-shadow:0 28px 90px var(--pce-shadow);pointer-events:auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);grid-template-rows:auto minmax(0,1fr) minmax(44px,118px);gap:14px}:host-context(.theme-light) .connection-editor{--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 94%, var(--md-sys-color-primary, #2563eb) 6%);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 82%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #eef2ff) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #f8fafc) 70%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 68%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #64748b) 62%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 34%, transparent);--pce-glass-highlight: color-mix(in srgb, #fff 64%, transparent);--pce-shadow: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 22%, transparent);--pce-shadow-soft: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 14%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #ffffff) 58%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 92%, transparent)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(0,1fr) 48px}.connection-editor__header{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:42px;padding:8px 14px;border-radius:999px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__mode-frame{position:relative;min-width:0;flex:1 1 auto;display:flex;justify-content:center}.connection-editor__close{width:32px;height:32px;flex:0 0 auto;display:inline-grid;place-items:center;border:1px solid var(--pce-outline);border-radius:999px;color:var(--pce-text);background:var(--pce-surface-strong);box-shadow:inset 0 1px var(--pce-glass-highlight);cursor:pointer;font:inherit;font-size:1.2rem;line-height:1}.connection-editor__close:hover,.connection-editor__close:focus-visible{border-color:var(--pce-outline-strong);background:color-mix(in srgb,var(--pce-accent) 16%,var(--pce-surface-strong));outline:none}.connection-editor__mode-shell{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:4px;border-radius:999px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:inset 0 1px var(--pce-glass-highlight),0 10px 26px var(--pce-shadow-soft);scrollbar-width:none}.connection-editor__mode-shell::-webkit-scrollbar{display:none}.connection-editor__mode{min-height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 12px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.76rem;font-weight:800;white-space:nowrap;transition:background .16s ease,border-color .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__mode:hover,.connection-editor__mode--active{color:var(--pce-strong);border-color:color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-strong) 82%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 12%,transparent)}.connection-editor__mode-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__mode--active .connection-editor__mode-glyph{color:var(--pce-primary)}.connection-editor__mode-dot{width:6px;height:6px;border-radius:999px;background:var(--pce-success);box-shadow:0 0 12px color-mix(in srgb,var(--pce-success) 70%,transparent)}.connection-editor__status-pill{display:inline-flex;align-items:center;gap:8px;min-height:24px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 36%,transparent);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.72rem;font-weight:800;white-space:nowrap}.connection-editor__status-pill--button{cursor:pointer;transition:border-color .16s ease,background .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__status-pill--button:hover,.connection-editor__status-pill--button:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 62%,transparent);background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 14%,transparent);outline:none}.connection-editor__status-pill span{width:6px;height:6px;border-radius:999px;background:var(--pce-primary);box-shadow:0 0 12px color-mix(in srgb,var(--pce-primary) 70%,transparent)}.connection-editor__section{display:grid;gap:10px}.connection-editor__dock{grid-column:1 / -1;grid-row:3;position:relative;z-index:4;min-height:0;display:grid;border-radius:14px;border:1px solid var(--pce-outline);background:radial-gradient(circle at 16% 0%,color-mix(in srgb,var(--pce-primary) 22%,transparent),transparent 34%),radial-gradient(circle at 78% 0%,color-mix(in srgb,var(--pce-secondary) 25%,transparent),transparent 38%),linear-gradient(90deg,var(--pce-dock-bg),var(--pce-surface-strong) 46%,color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-dock-bg))),var(--pce-dock-bg);box-shadow:0 18px 58px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__dock--collapsed .connection-editor__dock-tabs{border-block-end:0}.connection-editor__dock-tabs{display:flex;align-items:center;gap:10px;min-height:52px;padding:9px 14px;border-block-end:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-glass-highlight),transparent),color-mix(in srgb,var(--pce-surface-soft) 34%,transparent)}.connection-editor__dock-tablist{display:flex;align-items:center;gap:10px;min-width:0}.connection-editor__dock-tab,.connection-editor__dock-toggle{min-height:30px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.72rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-tab{display:inline-flex;align-items:center;gap:8px;padding:0 13px;white-space:nowrap}.connection-editor__dock-tab-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.8rem;letter-spacing:0;text-transform:none}.connection-editor__dock-tab--active{color:var(--pce-strong);border-color:var(--pce-outline-strong);background:linear-gradient(180deg,color-mix(in srgb,var(--pce-strong) 14%,transparent),color-mix(in srgb,var(--pce-strong) 6%,transparent));box-shadow:0 0 0 1px color-mix(in srgb,var(--pce-shadow) 72%,transparent),0 0 22px color-mix(in srgb,var(--pce-strong) 8%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__dock-tab--active .connection-editor__dock-tab-glyph{color:var(--pce-strong)}.connection-editor__dock-count{margin-inline-start:auto;color:color-mix(in srgb,var(--pce-muted) 62%,transparent);font-size:.7rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-toggle{width:32px;padding:0;border-color:var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.88rem;letter-spacing:0}.connection-editor__dock-body{max-height:154px;overflow:auto;padding:12px 12px 14px;border-block-start:1px solid var(--pce-outline);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 9%,transparent),color-mix(in srgb,var(--pce-secondary) 10%,transparent) 62%,color-mix(in srgb,var(--pce-surface-strong) 18%,transparent)),color-mix(in srgb,var(--pce-surface-soft) 30%,transparent)}.connection-editor__dock-body pre{max-height:60px}.connection-editor__dock-links{display:grid;gap:8px}.connection-editor__dock-link-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;padding:7px 10px;border-radius:10px;border:1px solid var(--pce-outline);background:linear-gradient(90deg,var(--pce-surface-soft),color-mix(in srgb,var(--pce-secondary) 10%,var(--pce-surface-soft)) 72%,var(--pce-surface-soft)),var(--pce-surface-soft);color:var(--pce-fg);transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-link{display:grid;grid-template-columns:minmax(116px,.52fr) minmax(300px,1.72fr) minmax(160px,.9fr) auto;align-items:center;gap:12px;width:100%;min-height:42px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;text-align:start}.connection-editor__dock-link-row:hover,.connection-editor__dock-link--active{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 13%,transparent),color-mix(in srgb,var(--pce-secondary) 16%,transparent),var(--pce-surface-strong)),var(--pce-surface-strong);box-shadow:0 12px 32px var(--pce-shadow-soft),inset 0 0 18px color-mix(in srgb,var(--pce-primary) 6%,transparent)}.connection-editor__dock-link--active{border-color:#facc1575;box-shadow:0 12px 32px var(--pce-shadow-soft),0 0 24px #facc151f}.connection-editor__dock-link--new{border-color:#fb923ca3;background:linear-gradient(90deg,#fb923c2e,#a855f729,#0ea5e91f),#0f172ac2;box-shadow:0 12px 34px #02061752,0 0 30px #fb923c2e;animation:new-dock-link-flash 1.35s ease-out forwards}.connection-editor__dock-link--error{border-color:#ef444461}.connection-editor__dock-jump{min-width:62px;min-height:30px;padding:0 10px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 54%,transparent);color:var(--pce-primary);cursor:pointer;font-size:.66rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__dock-jump:hover,.connection-editor__dock-jump:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 56%,transparent);background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 18%,transparent);outline:none}.connection-editor__dock-link-kind{display:inline-flex;align-items:center;gap:7px;min-width:0;color:var(--pce-muted);font-size:.66rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-link-kind span{width:8px;height:8px;border-radius:999px;background:#b46cff;box-shadow:0 0 14px #b46cff7a}.connection-editor__dock-link--state .connection-editor__dock-link-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2f94}.connection-editor__dock-link--state-read .connection-editor__dock-link-kind span{background:#8b7dff;box-shadow:0 0 13px #8b7dff75}.connection-editor__dock-link--projection .connection-editor__dock-link-kind span{background:#19c8e8;box-shadow:0 0 10px #19c8e857}.connection-editor__dock-link--event-propagation .connection-editor__dock-link-kind span{background:#ffb454;box-shadow:0 0 15px #ffb45485}.connection-editor__dock-link--policy .connection-editor__dock-link-kind span{outline:1px solid rgba(34,197,94,.76);outline-offset:2px;box-shadow:0 0 16px #22c55e61}.connection-editor__dock-link--policy:not(.connection-editor__dock-link--state,.connection-editor__dock-link--state-read,.connection-editor__dock-link--projection,.connection-editor__dock-link--event-propagation) .connection-editor__dock-link-kind span{background:#22c55e}.connection-editor__dock-link-route{display:inline-flex;align-items:center;gap:8px;min-width:0}.connection-editor__dock-link-chip{min-width:0;overflow:hidden;padding:4px 8px;border-radius:999px;border:1px solid var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-soft) 72%,transparent);color:var(--pce-fg);font-size:.72rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-chip--from{border-color:#ff9f2f66;color:#ffbd62}.connection-editor__dock-link-chip--to{border-color:#19c8e83d;color:#7dddeb}:host-context(.theme-light) .connection-editor__dock-link-chip--from{border-color:color-mix(in srgb,var(--pce-tertiary) 46%,transparent);color:#8a4600}:host-context(.theme-light) .connection-editor__dock-link-chip--to{border-color:color-mix(in srgb,var(--pce-primary) 34%,transparent);color:#075f73}.connection-editor__dock-link-arrow{flex:0 0 auto;color:var(--pce-muted);font-weight:900}.connection-editor__dock-link-id{min-width:0;overflow:hidden;color:var(--pce-muted);font-size:.66rem;font-weight:800;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-badges{display:inline-flex;justify-content:flex-end;gap:5px;min-width:70px}.connection-editor__dock-link-badges span{padding:3px 7px;border-radius:999px;background:#a855f724;color:#d8b4fe;font-size:.62rem;font-weight:900;text-transform:uppercase;white-space:nowrap}:host-context(.theme-light) .connection-editor__dock-link-badges span{background:color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-surface-soft));color:#6d2a9f}.connection-editor__dock-empty{padding:12px;border-radius:12px;border:1px dashed var(--pce-outline);color:var(--pce-muted);font-size:.76rem;font-weight:700}.connection-editor__inspector{border-color:color-mix(in srgb,var(--pce-primary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 10%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface)}.connection-editor__eyebrow,.connection-editor__section-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--pce-muted);font-weight:700}.connection-editor__title{font-size:1.02rem;font-weight:800}.connection-editor__subtitle,.connection-editor__item-copy,.connection-editor__item-meta,.connection-editor__details-row span,.connection-editor__details-label,.connection-editor__empty{color:var(--pce-muted);font-size:.84rem}.connection-editor__inspector-heading{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--pce-surface-soft);border:1px solid var(--pce-outline)}.connection-editor__inspector-heading strong{color:var(--pce-strong);font-size:.96rem;overflow-wrap:anywhere}.connection-editor__inspector-heading span{color:var(--pce-primary);font-size:.76rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}.connection-editor__human-summary{display:grid;gap:6px;padding:12px;border-radius:14px;border:1px solid color-mix(in srgb,var(--pce-primary) 24%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface-soft);color:var(--pce-fg);line-height:1.35}.connection-editor__nested-summary{display:grid;gap:6px;padding:10px;border-radius:12px;border:1px solid color-mix(in srgb,var(--pce-primary) 22%,transparent);background:color-mix(in srgb,var(--pce-primary) 8%,var(--pce-surface-soft))}.connection-editor__nested-summary strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__nested-summary span:last-child{color:var(--pce-primary);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.72rem;overflow-wrap:anywhere}.connection-editor__recommended{border-color:color-mix(in srgb,var(--pce-secondary) 32%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 14%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface)}.connection-editor__recommended-card{display:grid;gap:8px;width:100%;padding:13px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 36%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 16%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__recommended-card:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 52%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 22%,transparent),color-mix(in srgb,var(--pce-primary) 14%,transparent)),var(--pce-surface-strong)}.connection-editor__recommended-card strong{color:var(--pce-strong);font-size:.92rem;line-height:1.28}.connection-editor__recommended-card span:not(.connection-editor__human-summary-label):not(.connection-editor__suggestion-action),.connection-editor__recommended-card small{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__success{display:grid;gap:4px;padding:10px 12px;border-radius:14px;border:1px solid rgba(34,197,94,.34);background:#22c55e1f;color:var(--pce-fg);line-height:1.35}.connection-editor__success strong{color:#bbf7d0;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__success span{color:var(--pce-strong);font-size:.82rem}.connection-editor__human-summary-label,.connection-editor__suggestion-intent{justify-self:start;padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:#bae6fd;font-size:.66rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__human-summary strong{color:var(--pce-strong);font-size:.88rem}.connection-editor__human-summary span:last-child,.connection-editor__suggestion-preview{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__technical-details{display:grid;gap:10px;padding:10px 12px;border-radius:14px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__technical-details summary{cursor:pointer;color:var(--pce-muted);font-size:.78rem;font-weight:800}.connection-editor__technical-details[open] summary{margin-bottom:10px;color:var(--pce-strong)}.connection-editor__inspector-ports{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__inspector-port{max-width:100%;padding:4px 8px;border-radius:999px;border:1px solid rgba(148,163,184,.16);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-editor__inspector-port--input{border-color:#22d3ee57;color:#67e8f9}.connection-editor__inspector-port--output{border-color:#f59e0b57;color:#fbbf24}.connection-editor__inspector-port--state{border-color:#a855f761;color:#d8b4fe}.connection-editor__segment-kind-legend{display:grid;gap:10px;padding:12px;border-radius:16px;border:1px solid rgba(148,163,184,.14);background:linear-gradient(135deg,#0f172aa8,#080d1885),#02061757}.connection-editor__segment-kind-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.connection-editor__segment-kind-pill{min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:900;overflow:hidden;white-space:nowrap}.connection-editor__segment-kind-pill span{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:currentColor;box-shadow:0 0 12px currentColor}.connection-editor__segment-kind-pill--input{border-color:#19c8e83d;color:#7dddeb}.connection-editor__segment-kind-pill--output{border-color:#ff9f2f61;color:#ffbd62}.connection-editor__segment-kind-pill--state{border-color:#b46cff61;color:#d9b8ff}:host-context(.theme-light) .connection-editor__segment-kind-pill{border-color:var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-strong) 88%,transparent)}:host-context(.theme-light) .connection-editor__segment-kind-pill--input{color:#075f73}:host-context(.theme-light) .connection-editor__segment-kind-pill--output{color:#8a4600}:host-context(.theme-light) .connection-editor__segment-kind-pill--state{color:#6d2a9f}.connection-editor__stage{grid-column:1;grid-row:2;position:relative;min-height:0;height:100%;overflow:visible;border-radius:16px;border:1px solid var(--pce-outline);background:radial-gradient(circle at center,color-mix(in srgb,var(--pce-secondary) 7%,transparent),transparent 38%),radial-gradient(circle,var(--pce-grid) 1px,transparent 1.5px),var(--pce-stage-bg);background-size:auto,31px 31px,auto;box-shadow:inset 0 0 0 1px var(--pce-glass-highlight);cursor:grab;touch-action:none}.connection-editor__stage--panning,.connection-editor__stage:active{cursor:grabbing}.connection-editor__stage--dragging{cursor:crosshair}.connection-editor__stage--rotating{cursor:grabbing}.connection-editor__viewport{position:absolute;inset-block-start:0;inset-inline-start:0;width:900px;height:540px;overflow:visible;transform-origin:0 0;transition:transform .14s ease}.connection-editor__wires{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.connection-editor__wire,.connection-editor__wire-hit{fill:none;stroke-linecap:round}.connection-editor__wire{stroke:#b46cff;stroke-width:1.45;stroke-opacity:.48;pointer-events:none;filter:url(#connection-glow);stroke-dasharray:10 8;animation:connection-flow 1.65s linear infinite}.connection-editor__wire-hit{stroke:transparent;stroke-width:18;cursor:pointer;pointer-events:stroke}.connection-editor__wire-hit--active{stroke-width:28}.connection-editor__wire--halo{stroke:#b46cff1f;stroke-width:7;stroke-dasharray:none;animation:none}.connection-editor__wire--state{stroke:#ff9f2f;stroke-width:2.25;stroke-dasharray:8 7;animation:connection-flow .92s linear infinite}.connection-editor__wire--state.connection-editor__wire--halo{stroke:#ff9f2f29;stroke-width:11}.connection-editor__wire--projection{stroke:#15b8d8;stroke-width:1.75;stroke-dasharray:20 8;animation:connection-flow 1.9s linear infinite}.connection-editor__wire--projection.connection-editor__wire--halo{stroke:#15b8d81a;stroke-width:7}.connection-editor__wire--state-read{stroke:#8b7dff;stroke-width:1.65;stroke-dasharray:3 11;animation:connection-flow 2.25s linear infinite reverse}.connection-editor__wire--state-read.connection-editor__wire--halo{stroke:#8b7dff21;stroke-width:8}.connection-editor__wire--event-propagation{stroke:#ffb454;stroke-width:2.05;stroke-dasharray:5 7;animation:connection-flow .78s linear infinite}.connection-editor__wire--event-propagation.connection-editor__wire--halo{stroke:#ffb4542e;stroke-width:10}.connection-editor__wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.2)) url(#connection-glow)}.connection-editor__wire--policy.connection-editor__wire--halo{stroke:#22c55e1f;stroke-width:13}.connection-editor__wire--warning{stroke:#ff9f2f}.connection-editor__wire--warning.connection-editor__wire--halo{stroke:#ff9f2f2e}.connection-editor__wire--error{stroke:#ef4444}.connection-editor__wire--error.connection-editor__wire--halo{stroke:#ef44442e}.connection-editor__wire--active{stroke:#d9b8ff;stroke-width:3;stroke-opacity:1;stroke-dasharray:5 7;animation-duration:.58s}.connection-editor__wire--halo.connection-editor__wire--active{stroke-width:16;stroke-opacity:.8;animation:selected-wire-aura 1.35s ease-in-out infinite}.connection-editor__wire--new{stroke-width:3.4;stroke-opacity:1;stroke-dasharray:640;stroke-dashoffset:640;animation:wire-draw-in .62s cubic-bezier(.16,1,.3,1) forwards,connection-flow 1.05s linear .62s infinite}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:22;stroke-opacity:0;animation:new-wire-halo 1.45s ease-out forwards}.connection-editor__wire--trace{stroke:#9b5cff;stroke-width:3.2;stroke-opacity:1;stroke-dasharray:7 6;animation:connection-flow .72s linear infinite,trace-wire-pulse 1.18s ease-in-out infinite}.connection-editor__wire--halo.connection-editor__wire--trace{stroke:#9b5cff57;stroke-width:18;stroke-opacity:.86;animation:trace-halo-pulse 1.18s ease-in-out infinite}.connection-editor__wire--mode-dimmed{stroke-opacity:.14;stroke-width:1.05;filter:none;animation-duration:2.6s}.connection-editor--guided .connection-editor__wire:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.34;filter:none;animation:none}.connection-editor--guided .connection-editor__wire--halo:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.08;animation:none}.connection-editor__wire--halo.connection-editor__wire--mode-dimmed{stroke-opacity:.05;stroke-width:5;animation:none}.connection-editor__wire-hit--mode-dimmed{stroke-width:12}.connection-editor__wire-endpoint{fill:#f8fafc;stroke:#0f172ae6;stroke-width:1.5;filter:drop-shadow(0 0 8px rgba(216,180,254,.8));pointer-events:none;animation:endpoint-pulse 1.2s ease-in-out infinite}.connection-editor__wire-endpoint--source{fill:#ff9f2f}.connection-editor__wire-endpoint--target{fill:#19c8e8}.connection-editor__connection-tooltip{position:absolute;z-index:6;width:min(312px,calc(100% - 24px));display:grid;gap:8px;padding:12px 14px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(135deg,var(--pce-surface-strong),var(--pce-surface)),var(--pce-surface-strong);box-shadow:0 18px 44px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);color:var(--pce-fg);pointer-events:none;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .14s ease-out}.connection-editor__connection-tooltip-callout{position:absolute;inset-block-start:100%;inset-inline-start:var(--connection-tooltip-callout-x, 42px);width:2px;height:28px;border-radius:999px;background:linear-gradient(180deg,#e2e8f0bd,#19c8e800);box-shadow:0 0 12px #19c8e852;transform:translate(-1px);pointer-events:none}.connection-editor__connection-tooltip-callout:before,.connection-editor__connection-tooltip-callout:after{content:\"\";position:absolute;border-radius:999px;pointer-events:none}.connection-editor__connection-tooltip-callout:before{inset-block-start:-5px;inset-inline-start:-5px;width:12px;height:12px;border:1px solid rgba(148,163,184,.24);background:#080d18f5;box-shadow:inset 0 1px #ffffff14}.connection-editor__connection-tooltip-callout:after{inset-block-end:-3px;inset-inline-start:-4px;width:10px;height:10px;background:#19c8e8;box-shadow:0 0 16px #19c8e88f}.connection-editor__connection-tooltip--projection{border-color:#19c8e833;background:linear-gradient(135deg,#15b8d81f,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state{border-color:#ff9f2f66;background:linear-gradient(135deg,#ff9f2f3d,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout{background:linear-gradient(180deg,#ffbd62d1,#ff9f2f00);box-shadow:0 0 14px #ff9f2f61}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout:after{background:#ff9f2f;box-shadow:0 0 18px #ff9f2fad}.connection-editor__connection-tooltip--error{border-color:#f871716b}.connection-editor__connection-tooltip--error .connection-editor__connection-tooltip-callout:after{background:#fb7185;box-shadow:0 0 18px #fb7185ad}.connection-editor__connection-tooltip-kind{display:inline-flex;align-items:center;gap:8px;color:#94a3b8;font-size:.62rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__connection-tooltip-kind span{width:8px;height:8px;border-radius:999px;background:#19c8e8;box-shadow:0 0 12px #19c8e880}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2fc7}.connection-editor__connection-tooltip-row{min-width:0;display:grid;grid-template-columns:54px minmax(0,1fr);align-items:center;gap:8px;min-height:28px;padding:0 10px;border-radius:999px;background:#0f172a94}.connection-editor__connection-tooltip-row span{color:#8d9bb0;font-size:.62rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.connection-editor__connection-tooltip-row strong{min-width:0;overflow:hidden;color:#e2e8f0;font-size:.75rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__connection-tooltip-badges{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__connection-tooltip-badges span{padding:3px 8px;border-radius:999px;background:#02061799;color:#fbbf24;font-size:.66rem;font-weight:900}.connection-editor__trace-overlay{position:absolute;z-index:6;inset-block-start:16px;inset-inline-start:50%;width:min(560px,calc(100% - 360px));min-width:320px;padding:12px 14px;border-radius:16px;border:1px solid rgba(34,197,94,.26);background:linear-gradient(135deg,#22c55e1f,#0ea5e91a),#080d18f0;box-shadow:0 22px 56px #02061775,0 0 42px #22c55e1f;transform:translate(-50%);pointer-events:auto;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .16s ease-out}.connection-editor__trace-overlay-head,.connection-editor__trace-overlay-route{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.connection-editor__trace-overlay-head span,.connection-editor__trace-overlay-route span{color:#86efac;font-size:.66rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap}.connection-editor__trace-overlay-head strong{color:#cbd5e1;font-size:.7rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace}.connection-editor__trace-overlay-route{margin-top:6px}.connection-editor__trace-overlay-controls{display:grid;grid-template-columns:28px minmax(0,1fr) 28px;align-items:center;gap:8px;margin-top:10px}.connection-editor__trace-overlay-button{width:28px;height:24px;display:inline-grid;place-items:center;border:1px solid rgba(148,163,184,.18);border-radius:999px;background:#0206176b;color:#e2e8f0;cursor:pointer;font-size:1rem;font-weight:900;line-height:1;transition:border-color .15s ease,background .15s ease,color .15s ease,opacity .15s ease}.connection-editor__trace-overlay-button:hover:not(:disabled){border-color:#22d3ee6b;background:#0ea5e929;color:#f8fafc}.connection-editor__trace-overlay-button:disabled{cursor:default;opacity:.36}.connection-editor__trace-overlay-steps{min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto;padding:2px;scrollbar-width:none}.connection-editor__trace-overlay-steps::-webkit-scrollbar{display:none}.connection-editor__trace-overlay-step{position:relative;flex:1 0 28px;min-width:28px;height:22px;border:1px solid rgba(148,163,184,.16);border-radius:999px;background:#0f172a9e;color:#94a3b8;cursor:pointer;font-size:.62rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__trace-overlay-step--active{border-color:#22d3eea3;background:linear-gradient(90deg,#22d3ee3d,#9b5cff33);color:#f8fafc;box-shadow:0 0 18px #22d3ee33}.connection-editor__trace-overlay-step--blocked{border-color:#fb71855c;color:#fecdd3}.connection-editor__trace-overlay-route strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.82rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__trace-overlay-bar{position:relative;height:5px;margin-top:10px;overflow:hidden;border-radius:999px;background:#94a3b829}.connection-editor__trace-overlay-bar span{position:absolute;inset-block:0;inset-inline-start:0;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#22d3ee);box-shadow:0 0 18px #22c55e61;min-width:8%}.connection-editor__drag-wire{fill:none;stroke:#94a3b8;stroke-width:2.4;stroke-linecap:round;stroke-dasharray:6 7;pointer-events:none;filter:url(#connection-glow);animation:connection-flow 1.05s linear infinite,drag-wire-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--halo{stroke:#94a3b829;stroke-width:14;stroke-dasharray:none;animation:drag-halo-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--valid{stroke:#22c55e}.connection-editor__drag-wire--halo.connection-editor__drag-wire--valid{stroke:#22c55e47}.connection-editor__drag-endpoint{fill:#94a3b8;stroke:#020617eb;stroke-width:2;pointer-events:none;filter:url(#connection-glow);transform-box:fill-box;transform-origin:center;animation:endpoint-pulse 1s ease-in-out infinite}.connection-editor__drag-endpoint--source{fill:#ff9f2f}.connection-editor__drag-endpoint--target{fill:#7dddeb}.connection-editor__drag-endpoint--valid{fill:#22c55e;stroke:#bbf7d0e0}.connection-editor__wire-handle-line{stroke-width:2;stroke-linecap:round;stroke-dasharray:4 5;pointer-events:none;opacity:.88;filter:url(#connection-glow)}.connection-editor__wire-handle-line--source{stroke:#ff9f2ff0}.connection-editor__wire-handle-line--target{stroke:#19c8e8c2}.connection-editor__wire-control{fill:#0f172af5;stroke:#cbd5e1c7;stroke-width:1.8;pointer-events:none;filter:url(#connection-glow)}.connection-editor__wire-label{pointer-events:none;filter:drop-shadow(0 0 10px rgba(2,6,23,.44));animation:tooltip-rise .14s ease-out}.connection-editor__wire-label rect{fill:#080d18eb;stroke-width:1}.connection-editor__wire-label text{fill:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__wire-label--source rect{stroke:#ff9f2fad}.connection-editor__wire-label--target rect{stroke:#19c8e86b}.connection-editor__zoom-controls{position:absolute;inset-inline-start:14px;inset-block-start:14px;z-index:4;display:grid;grid-template-columns:max-content;gap:6px;width:46px;pointer-events:auto}.connection-editor__tool-group,.connection-editor__trace-source{display:grid;gap:6px;padding:6px;border-radius:12px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:0 16px 36px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__tool-group{grid-template-columns:30px;width:max-content}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:30px}.connection-editor__arrange-button{width:34px;min-height:34px;display:inline-flex;align-items:center;justify-content:center;gap:0;padding:0;border-radius:999px;border:1px solid rgba(168,85,247,.34);background:linear-gradient(90deg,#a855f72e,#22d3ee1f);color:#e9d5ff;font-size:0;font-weight:800;letter-spacing:0;cursor:pointer;opacity:1;transform:scale(1);transition:opacity .14s ease,transform .14s ease,border-color .14s ease,background .14s ease}.connection-editor--guided .connection-editor__arrange-button{opacity:.34;transform:scale(.9);border-color:color-mix(in srgb,var(--pce-outline) 82%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 84%,transparent)}.connection-editor--guided .connection-editor__zoom-controls:hover .connection-editor__arrange-button,.connection-editor--guided .connection-editor__zoom-controls:focus-within .connection-editor__arrange-button,.connection-editor--guided .connection-editor__arrange-button:hover,.connection-editor--guided .connection-editor__arrange-button:focus-visible,.connection-editor--guided .connection-editor__arrange-button--active{opacity:1;transform:scale(1);border-color:#a855f757;background:linear-gradient(90deg,#a855f72e,#22d3ee1f)}.connection-editor__arrange-button span{color:#c084fc;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.78rem;font-weight:900}.connection-editor__tool-button{width:30px;height:30px;border-radius:999px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.9rem;font-weight:800;letter-spacing:.02em;cursor:pointer;line-height:1}.connection-editor__tool-button:hover:not(:disabled){border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);color:var(--pce-primary);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 16%,transparent)}.connection-editor__history-button:disabled{cursor:not-allowed;opacity:.42}.connection-editor__arrange-button--active{border-color:#22d3ee94;background:linear-gradient(90deg,#0ea5e93d,#22d3ee2e);color:#cffafe}.connection-editor__trace-source{gap:4px;max-height:230px;overflow:auto}.connection-editor__trace-source-title{padding:2px 4px 6px;color:var(--pce-muted);font-size:.64rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.connection-editor__trace-source-item{min-width:0;min-height:30px;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:8px;background:transparent;color:var(--pce-fg);cursor:pointer;font-size:.74rem;font-weight:800;text-align:start}.connection-editor__trace-source-item span{color:#f59e0b;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__trace-source-item:hover,.connection-editor__trace-source-item--active{background:var(--pce-surface-strong);color:var(--pce-strong);box-shadow:inset 3px 0 #f59e0bd1}.connection-editor__minimap{position:absolute;inset-inline-end:14px;inset-block-end:14px;z-index:4;width:184px;height:124px;padding:18px 10px 10px;overflow:hidden;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-primary) 30%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),var(--pce-surface-strong)),var(--pce-surface);box-shadow:0 20px 48px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);cursor:pointer;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);opacity:1;transform:scale(1);transform-origin:100% 100%;transition:opacity .16s ease,transform .16s ease,border-color .16s ease,box-shadow .16s ease}.connection-editor--guided .connection-editor__minimap{opacity:.54;transform:scale(.88);border-color:color-mix(in srgb,var(--pce-outline) 64%,transparent);box-shadow:0 14px 34px color-mix(in srgb,var(--pce-shadow-soft) 70%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor--guided .connection-editor__minimap:hover,.connection-editor--guided .connection-editor__minimap:focus-visible,.connection-editor--guided .connection-editor__minimap--panning{opacity:1;transform:scale(1)}.connection-editor__minimap:hover,.connection-editor__minimap--panning{border-color:#22d3ee75;box-shadow:0 20px 48px var(--pce-shadow-soft),0 0 24px color-mix(in srgb,var(--pce-primary) 14%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__minimap--panning{cursor:grabbing}.connection-editor__minimap:before{content:\"\";position:absolute;inset:22px 10px 10px;border-radius:10px;background-image:radial-gradient(circle,rgba(125,211,252,.18) 1px,transparent 1px);background-size:22px 22px;opacity:.58;pointer-events:none}.connection-editor__minimap-title{position:absolute;inset-block-start:7px;inset-inline-start:12px;color:var(--pce-muted);font-size:.6rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__minimap svg{position:relative;width:100%;height:100%;display:block;overflow:visible}.connection-editor__minimap-wire{fill:none;stroke:#b46cff8f;stroke-width:4;stroke-linecap:round;opacity:.86}.connection-editor__minimap-wire--state{stroke:#ff9f2fdb}.connection-editor__minimap-wire--state-read{stroke:#8b7dffb8;stroke-dasharray:4 9}.connection-editor__minimap-wire--projection{stroke:#19c8e88a;stroke-dasharray:18 8}.connection-editor__minimap-wire--event-propagation{stroke:#ffb454cc;stroke-dasharray:6 7}.connection-editor__minimap-wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.28))}.connection-editor__minimap-wire--trace{stroke:#9b5cffe0;stroke-width:5;stroke-dasharray:12 9;animation:connection-flow 1s linear infinite}.connection-editor__minimap-wire--active{stroke:#facc15eb;stroke-width:6;filter:drop-shadow(0 0 8px rgba(250,204,21,.38))}.connection-editor__minimap-wire--mode-dimmed{opacity:.2;stroke-width:2.6;filter:none}.connection-editor__minimap-node{fill:#f59e0be0;stroke:#020617db;stroke-width:4;filter:drop-shadow(0 0 7px rgba(245,158,11,.24))}.connection-editor__minimap-node--state{fill:#a855f7e6;filter:drop-shadow(0 0 8px rgba(168,85,247,.34))}.connection-editor__minimap-node--selected{fill:#facc15f5;stroke:#fef08aeb;filter:drop-shadow(0 0 10px rgba(250,204,21,.42))}.connection-editor__minimap-node--trace-source{fill:#facc15f5;filter:drop-shadow(0 0 10px rgba(250,204,21,.44))}.connection-editor__minimap-node--trace-reacting{fill:#22c55eeb;filter:drop-shadow(0 0 10px rgba(34,197,94,.42))}.connection-editor__minimap-node--mode-dimmed{opacity:.28;filter:none}.connection-editor__minimap-viewport{fill:#7dd3fc1f;stroke:#7dd3fce6;stroke-width:5;stroke-dasharray:18 10;filter:drop-shadow(0 0 10px rgba(125,211,252,.3));transition:x .12s ease,y .12s ease,width .12s ease,height .12s ease}.connection-editor__minimap--panning .connection-editor__minimap-viewport{fill:#22d3ee2e;stroke:#22d3eef5;stroke-dasharray:none}.connection-editor__node{position:absolute;z-index:10;width:168px;height:168px;transform:translate(-84px,-84px);border:0;padding:0;background:transparent;color:inherit;cursor:pointer;transition:filter .16s ease}.connection-editor__node--dragging{cursor:grabbing;filter:drop-shadow(0 0 22px rgba(34,211,238,.26));z-index:12}.connection-editor__node--connection-focus{filter:drop-shadow(0 0 16px rgba(34,211,238,.2))}.connection-editor__node--compat-target .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e66,0 0 0 18px #22c55e0b,0 0 32px #22c55e29}.connection-editor__node--mode-dimmed{opacity:.42;filter:grayscale(.22) saturate(.56)}.connection-editor__node--quiet{opacity:.58;filter:saturate(.68) brightness(.86)}.connection-editor__node--mode-dimmed .connection-editor__node-ring{animation:none;box-shadow:0 0 0 1px #2dd4bf14,0 0 14px #0ea5e90f}.connection-editor__node--mode-dimmed .connection-editor__node-halo{stroke-opacity:.28}.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-svg{position:absolute;inset:0}.connection-editor__node-ring,.connection-editor__node-core{display:grid;place-items:center;clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}.connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from -28deg,#06b6d4b3 0 28%,#f59e0b9e 28% 48%,#a855f780 48% 68%,#06b6d4a3 68% 100%);box-shadow:0 0 0 1px #2dd4bf2e,0 0 26px #0ea5e929;animation:node-breathe 2.8s ease-in-out infinite}.connection-editor__node-svg{overflow:visible;filter:drop-shadow(0 0 16px rgba(14,165,233,.16))}.connection-editor__node-halo{fill:transparent;stroke:#38bdf838;stroke-width:1;stroke-dasharray:0;pointer-events:none}.connection-editor__node-halo:nth-child(2){stroke:#38bdf824}.connection-editor__node-halo:nth-child(3){stroke:#94a3b81a}.connection-editor__node-segment{fill-opacity:.28;stroke-opacity:.72;stroke-width:1.15;transition:fill-opacity .16s ease,stroke-opacity .16s ease,stroke-width .16s ease;cursor:grab}.connection-editor__node:hover .connection-editor__node-segment,.connection-editor__node--selected .connection-editor__node-segment,.connection-editor__node--connection-focus .connection-editor__node-segment{fill-opacity:.54;stroke-opacity:.95;stroke-width:1.55}.connection-editor__node-segment--connection-focus{fill-opacity:.76;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 8px rgba(34,211,238,.76));animation:segment-focus-sweep 1.45s ease-in-out infinite}.connection-editor__node-segment--source{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 12px rgba(251,146,60,.82))}.connection-editor__node-segment--compatible{fill-opacity:.74;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 10px rgba(34,197,94,.72));animation:snap-pulse 1s ease-in-out infinite}.connection-editor__node-segment--compat-preview{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 13px rgba(245,158,11,.78))}.connection-editor__node-segment--candidate{fill-opacity:.92;stroke-opacity:1;stroke-width:2.8;filter:drop-shadow(0 0 16px rgba(34,197,94,.86))}.connection-editor__node-segment--incompatible{fill-opacity:.12;stroke-opacity:.28;cursor:not-allowed}.connection-editor__node-segment--invalid-drop{fill-opacity:.72;stroke:#fb7185;stroke-opacity:1;stroke-width:3;filter:drop-shadow(0 0 16px rgba(244,63,94,.84));animation:invalid-drop-jolt .36s ease-out}.connection-editor__node-segment--state{fill-opacity:.44;filter:drop-shadow(0 0 8px rgba(180,108,255,.2))}.connection-editor__node-segment--mode-dimmed{fill-opacity:.08;stroke-opacity:.2;stroke-width:.9;filter:none}.connection-editor__node-anchor{opacity:.95;filter:drop-shadow(0 0 6px currentColor)}.connection-editor__node-rotate-handle{cursor:grab;opacity:0;pointer-events:none;transition:opacity .16s ease,filter .16s ease;filter:drop-shadow(0 0 8px rgba(34,211,238,.28))}.connection-editor__node:hover .connection-editor__node-rotate-handle,.connection-editor__node--selected .connection-editor__node-rotate-handle,.connection-editor__node--rotating .connection-editor__node-rotate-handle{opacity:1;pointer-events:auto}.connection-editor__node--rotating .connection-editor__node-rotate-handle{cursor:grabbing;filter:drop-shadow(0 0 12px rgba(34,211,238,.54))}.connection-editor__node-rotate-hit{fill:transparent}.connection-editor__node-rotate-dot{fill:var(--pce-surface-strong);stroke:var(--pce-primary);stroke-opacity:.88;stroke-width:1.4}.connection-editor__node-rotate-arc,.connection-editor__node-rotate-arrow{fill:none;stroke:var(--pce-primary);stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.96;stroke-width:1.2;pointer-events:none}.connection-editor__segment-icon,.connection-editor__segment-label{pointer-events:none;fill:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:800;paint-order:stroke;stroke:#020617c2;stroke-width:3px;stroke-linejoin:round}.connection-editor__segment-icon{font-size:12px;fill:#19c8e8;opacity:1;transition:opacity .14s ease}.connection-editor__segment-icon--output{fill:#ff9f2f}.connection-editor--guided .connection-editor__segment-icon:not(.connection-editor__segment-icon--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-icon{opacity:0}.connection-editor__segment-label{font-size:9.5px;letter-spacing:0;fill:#e2e8f0e0;opacity:1;transition:opacity .14s ease}.connection-editor--guided .connection-editor__segment-label:not(.connection-editor__segment-label--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-label{opacity:0}.connection-editor__node-core{inset:43px;padding:12px;border-radius:999px;clip-path:none;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(circle at center,#111827 0 58%,#060b14);border:1px solid rgba(226,232,240,.1);box-shadow:0 12px 28px #00000073,inset 0 1px #ffffff0d;color:#f8fafc;text-shadow:0 1px 2px rgba(0,0,0,.62)}.connection-editor__node-icon{display:block;max-width:44px;overflow:hidden;color:#f8fafc;font-family:Material Symbols Outlined,Material Icons,sans-serif;font-size:1.22rem;font-weight:400;line-height:1;text-align:center;text-transform:none;letter-spacing:0;white-space:nowrap;filter:drop-shadow(0 0 10px rgba(226,232,240,.18))}.connection-editor__node--state .connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from 14deg,#a855f7c7 0 42%,#7e3af26b 42% 78%,#f59e0b47 78% 100%);box-shadow:0 0 0 1px #a855f738,0 0 30px #a855f733}.connection-editor__node--selected .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15bd,0 0 34px #facc153d}.connection-editor__node--connection-focus .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eead,0 0 38px #22d3ee42;animation:node-focus-breathe 1.7s ease-in-out infinite}.connection-editor__node--trace-source .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 0 18px #facc150f,0 0 54px #facc154d;animation:trace-source-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:before{content:\"\";position:absolute;z-index:0;inset:-44px;border-radius:999px;border:2px solid rgba(250,204,21,.36);background:radial-gradient(circle at center,transparent 0 64%,rgba(250,204,21,.05) 65% 66%,transparent 67%),conic-gradient(from -20deg,#facc1500,#facc1552,#facc1500);box-shadow:0 0 36px #facc151f;opacity:.92;pointer-events:none;animation:trace-source-orbit 2.8s linear infinite}.connection-editor__node--trace-reacting .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e94,0 0 46px #22c55e38;animation:trace-reacting-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:after,.connection-editor__node--trace-reacting:after{position:absolute;z-index:3;inset-inline-start:50%;inset-block-start:-42px;padding:0;border:0;background:transparent;color:#facc15;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.68rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase;transform:translate(-50%);text-shadow:0 0 12px rgba(250,204,21,.52);pointer-events:none}.connection-editor__node--trace-source:after{content:attr(data-trace-label)}.connection-editor__node--trace-reacting:after{content:attr(data-trace-label);color:#86efac;text-shadow:0 0 12px rgba(34,197,94,.44)}.connection-editor__node--trace-source .connection-editor__node-segment--output{fill-opacity:.66;stroke-width:2.2;filter:drop-shadow(0 0 14px rgba(255,159,47,.42))}.connection-editor__node--expanded .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eebd,0 0 34px #22d3ee3d}.connection-editor__node--rotating .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 42px #facc1547;animation:node-focus-breathe 1.1s ease-in-out infinite}.connection-editor__node--rotating .connection-editor__node-segment{fill-opacity:.68;stroke-opacity:1;stroke-width:1.9;cursor:grabbing}.connection-editor__node-title,.connection-editor__node-subtitle{display:block;max-width:92px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.connection-editor__node-title{color:#f8fafc;font-size:.82rem;font-weight:800}.connection-editor__node-subtitle{margin-top:4px;color:#a7b4c8;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__ports{position:absolute;z-index:30;display:grid;gap:6px;width:104px;opacity:0;pointer-events:none;transform:translateY(3px);transition:opacity .16s ease,transform .16s ease}.connection-editor__ports--visible{opacity:1;pointer-events:auto;transform:translateY(0)}.connection-editor__ports--outputs{z-index:42}.connection-editor__ports--inputs{z-index:36}.connection-editor__segment-popover{position:absolute;z-index:80;width:292px;max-height:320px;overflow:auto;display:grid;gap:10px;padding:14px;border-radius:16px;border:1px solid rgba(148,163,184,.18);background:linear-gradient(135deg,#0f172af5,#110c20f0),#090c16eb;box-shadow:0 28px 72px #0000007a,0 0 48px #a855f71a,inset 0 1px #ffffff0d;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__segment-popover-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:2px}.connection-editor__segment-popover-title{color:#94a3b8;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}.connection-editor__segment-popover-hint{margin-top:5px;color:#64748b;font-size:.66rem;font-weight:700}.connection-editor__segment-rotation{flex:0 0 auto;min-width:54px;padding:5px 8px;border-radius:999px;border:1px solid rgba(34,211,238,.28);background:#082f4957;color:#7dd3fc;font-size:.66rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-align:center;box-shadow:inset 0 0 16px #0ea5e914}.connection-editor__segment-row{display:grid;grid-template-columns:28px 72px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:40px;padding:7px;border-radius:12px;border:1px solid rgba(148,163,184,.12);background:linear-gradient(90deg,#0f172ac7,#0f172a75),#0f172a99;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__segment-row--input{border-color:#22d3ee42}.connection-editor__segment-row--output{border-color:#f59e0b47}.connection-editor__segment-row--state{border-color:#a855f74d}.connection-editor__segment-row--source,.connection-editor__segment-row--candidate{transform:translate(2px);box-shadow:0 0 22px #f59e0b24,inset 0 0 20px #f59e0b14}.connection-editor__segment-row--compatible{border-color:#22d3ee6b;box-shadow:inset 0 0 18px #22d3ee14}.connection-editor__segment-row--compat-preview{border-color:#f59e0b94;background:linear-gradient(90deg,#f59e0b1f,#0f172a8a),#0f172ab3;box-shadow:0 0 22px #f59e0b1f,inset 0 0 18px #f59e0b14}.connection-editor__segment-row--invalid-drop{border-color:#fb7185b3;background:linear-gradient(90deg,#f43f5e24,#0f172a94),#0f172ab3;box-shadow:0 0 24px #f43f5e2e,inset 0 0 18px #f43f5e1a;animation:invalid-drop-jolt .36s ease-out}.connection-editor__segment-index{color:#64748b;font-size:.64rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;letter-spacing:.08em}.connection-editor__segment-kind{display:inline-flex;align-items:center;gap:6px;color:#94a3b8;font-size:.62rem;font-weight:800;text-transform:uppercase;min-width:0;white-space:nowrap}.connection-editor__segment-kind-dot{width:7px;height:7px;border-radius:999px;background:#94a3b8;box-shadow:0 0 12px #94a3b847}.connection-editor__segment-row--input .connection-editor__segment-kind-dot{background:#22d3ee;box-shadow:0 0 12px #22d3ee61}.connection-editor__segment-row--output .connection-editor__segment-kind-dot{background:#fb923c;box-shadow:0 0 12px #fb923c66}.connection-editor__segment-row--state .connection-editor__segment-kind-dot{background:#a855f7;box-shadow:0 0 12px #a855f76b}.connection-editor__segment-label{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;color:#e2e8f0;font-size:.74rem;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-badge{flex:0 0 auto;padding:2px 5px;border-radius:999px;border:1px solid rgba(56,189,248,.28);background:#0ea5e91a;color:#bae6fd;font-size:.55rem;font-weight:900;text-transform:uppercase}.connection-editor__segment-path{grid-column:3 / 4;min-width:0;margin-top:-5px;overflow:hidden;color:#93c5fd;font-size:.62rem;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-row--nested{min-height:56px;border-color:#38bdf84d;background:linear-gradient(90deg,#0ea5e91a,#0f172a80),#0f172aa3}.connection-editor__segment-actions{display:inline-flex;gap:4px}.connection-editor__segment-action{width:24px;height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.18);background:#060c16b8;color:#dbeafe;cursor:pointer;font-weight:900;line-height:1}.connection-editor__segment-action:hover{border-color:#22d3ee75;box-shadow:0 0 14px #22d3ee29}.connection-editor__port{min-height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#080d18c2;color:#cbd5e1;font-size:.64rem;font-weight:700;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:crosshair;box-shadow:0 8px 20px #00000038}.connection-editor--guided .connection-editor__ports--visible .connection-editor__port:not(.connection-editor__port--guided-visible){display:none}.connection-editor__port--output{border-color:#f59e0b75;color:#fbbf24}.connection-editor__port--input{border-color:#06b6d475;color:#22d3ee}.connection-editor__port--state{border-color:#a855f785;color:#c084fc}.connection-editor__port--compatible{background:#22c55e29;box-shadow:0 0 0 1px #22c55e61,0 0 18px #22c55e2e;animation:snap-pulse 1s ease-in-out infinite}.connection-editor__port--source{border-color:#fb923cb8;background:#fb923c29;color:#fed7aa;box-shadow:0 0 0 1px #fb923c73,0 0 20px #fb923c2e}.connection-editor__port--candidate{background:#22c55e3d;box-shadow:0 0 0 2px #22c55e94,0 0 24px #22c55e3d}.connection-editor__port--incompatible{opacity:.42;cursor:not-allowed;filter:grayscale(.45)}.connection-editor__port--invalid-drop{opacity:1;border-color:#fb7185c7;color:#fecdd3;background:#f43f5e2e;box-shadow:0 0 0 2px #f43f5e75,0 0 24px #f43f5e38;filter:none;animation:invalid-drop-jolt .36s ease-out}.connection-editor__port--connection-focus{border-color:#facc15ad;color:#fde68a;background:#facc151f;box-shadow:0 0 0 1px #facc156b,0 0 20px #facc152e;animation:port-focus-pulse 1.25s ease-in-out infinite}.connection-editor__drag-tip{position:absolute;z-index:6;display:grid;gap:4px;width:min(330px,calc(100% - 28px));padding:10px 12px;border-radius:14px;border:1px solid rgba(125,211,252,.26);background:linear-gradient(135deg,#0ea5e91f,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 28px #0ea5e91a;font-size:.76rem;pointer-events:none;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);animation:tooltip-rise .14s ease-out}.connection-editor__drag-tip--valid{border-color:#22c55e66;background:linear-gradient(135deg,#22c55e29,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 30px #22c55e24}.connection-editor__drag-tip--invalid{z-index:7;border-color:#fb71858a;background:linear-gradient(135deg,#f43f5e2e,#0f172af0),#080d18f5;box-shadow:0 18px 44px #0206176b,0 0 34px #f43f5e29;animation:tooltip-rise .14s ease-out,invalid-drop-jolt .36s ease-out}.connection-editor__invalid-drop-pulse{position:absolute;z-index:6;width:16px;height:16px;border-radius:999px;border:2px solid rgba(251,113,133,.88);background:#f43f5e38;box-shadow:0 0 0 8px #f43f5e1a,0 0 28px #f43f5e3d;pointer-events:none;transform:translate(-50%,-50%);animation:invalid-drop-ping 1.2s ease-out both}.connection-editor__drag-tip span{color:#7dd3fc;text-transform:uppercase;letter-spacing:.12em;font-size:.62rem;font-weight:800}.connection-editor__drag-tip strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.78rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__drag-tip small{color:#94a3b8;font-size:.68rem;font-weight:700}.connection-editor__drag-tip--valid small{color:#86efac}.connection-editor__drag-tip--invalid span,.connection-editor__drag-tip--invalid small{color:#fda4af}.connection-editor__summary{grid-column:1;grid-row:2;align-self:end;justify-self:start;z-index:6;display:flex;flex-wrap:wrap;gap:6px;padding:0 0 12px 12px;pointer-events:none}.connection-editor__side-panel{grid-column:2;grid-row:2 / 3;position:relative;z-index:8;min-width:0;min-height:0;display:grid;align-content:start;gap:14px;overflow:auto;padding-inline-end:4px;scrollbar-color:var(--pce-outline-strong) var(--pce-surface-soft)}.connection-editor__side-panel--contextual .connection-editor__inspector{order:-3}.connection-editor__side-panel--contextual .connection-editor__recommended{order:2}.connection-editor__side-panel--contextual .connection-editor__filters-section{order:3}.connection-editor__side-panel--contextual .connection-editor__recommended,.connection-editor__side-panel--contextual .connection-editor__filters-section{opacity:.82}.connection-editor__metric,.connection-editor__item{border-radius:16px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__metric{min-width:auto;display:inline-flex;align-items:baseline;gap:7px;padding:6px 9px;border-radius:999px;background:color-mix(in srgb,var(--pce-surface-strong) 86%,transparent);box-shadow:0 10px 26px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight)}.connection-editor__metric span{color:var(--pce-muted);font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__metric strong,.connection-editor__details-row strong{color:var(--pce-strong);font-size:.78rem}.connection-editor__filters,.connection-editor__actions,.connection-editor__badges{display:flex;gap:8px;flex-wrap:wrap}.connection-editor__filter,.connection-editor__action{border:1px solid var(--pce-outline-strong);background:var(--pce-surface-soft);color:var(--pce-fg);border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connection-editor__filter--active,.connection-editor__action:hover{border-color:color-mix(in srgb,var(--pce-secondary) 62%,transparent);background:color-mix(in srgb,var(--pce-secondary) 16%,var(--pce-surface-soft));color:var(--pce-strong)}.connection-editor__action--danger{border-color:#f8717161;color:#fecaca}.connection-editor__item{width:100%;text-align:start;padding:12px;display:grid;gap:6px;cursor:pointer;color:inherit}.connection-editor__item--active{border-color:#a855f7b8;background:linear-gradient(90deg,#0ea5e91a,#a855f721)}.connection-editor__item-title{font-weight:800;color:#f8fafc;word-break:break-word}.connection-editor__badge{padding:3px 8px;border-radius:999px;background:#0ea5e92e;color:#bae6fd;font-size:.72rem;font-weight:800}.connection-editor__section{min-width:0;padding:14px;border-radius:18px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight),0 18px 50px var(--pce-shadow-soft);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__badge--warning{background:#facc1524;color:#fde68a}.connection-editor__badge--error{background:#ef444424;color:#fecaca}.connection-editor__diagnostics{display:grid;gap:8px}.connection-editor__diagnostic{display:grid;gap:4px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.78rem;line-height:1.35}.connection-editor__diagnostic--warning{border-color:#f59e0b47;background:#f59e0b1a}.connection-editor__diagnostic--error{border-color:#ef44445c;background:#ef44441f}.connection-editor__diagnostic-severity{font-size:.68rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#f8fafc}.connection-editor__suggestions{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__suggestion{display:grid;gap:8px;width:100%;padding:12px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 12%,transparent),color-mix(in srgb,var(--pce-primary) 8%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__suggestion:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 46%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 18%,transparent),color-mix(in srgb,var(--pce-primary) 12%,transparent)),var(--pce-surface-strong)}.connection-editor__suggestion-route{display:grid;gap:4px;font-size:.78rem}.connection-editor__suggestion-route strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__suggestion-reason{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__suggestion-diagnostic{padding:10px 12px;border-radius:14px;border:1px solid rgba(245,158,11,.28);background:#f59e0b1a;color:var(--pce-strong);font-size:.78rem;line-height:1.35}.connection-editor__suggestion-outcome{color:var(--pce-strong);font-size:.84rem;line-height:1.3}.connection-editor__suggestion-action{justify-self:start;padding:3px 8px;border-radius:999px;background:#22d3ee24;color:#67e8f9;font-size:.68rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase}:host-context(.theme-light) .connection-editor__suggestion-action{background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:#075f73}.connection-editor__trace{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__trace-summary{color:var(--pce-muted);font-size:.78rem;line-height:1.35}.connection-editor__trace-step{display:grid;grid-template-columns:24px minmax(76px,auto) 1fr;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(34,211,238,.18);background:var(--pce-surface-soft);font-size:.76rem}.connection-editor__trace-step--blocked{border-color:#ef444457;background:#ef44441a}.connection-editor__trace-order{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:999px;background:#22d3ee29;color:#67e8f9;font-weight:900}.connection-editor__trace-phase{color:var(--pce-strong);font-weight:900;text-transform:uppercase;letter-spacing:.06em;font-size:.66rem}.connection-editor__trace-copy{min-width:0;color:var(--pce-fg);word-break:break-word}.connection-editor__transform-steps{display:grid;gap:8px}.connection-editor__transform-step{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(168,85,247,.22);background:var(--pce-surface-soft)}.connection-editor__transform-kind{min-width:0;color:var(--pce-strong);font-weight:900;word-break:break-word}.connection-editor__transform-phase{color:var(--pce-muted);font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.connection-editor__details-row,.connection-editor__details-block{display:grid;gap:6px}.connection-editor__payload-input{width:100%;min-height:128px;box-sizing:border-box;resize:vertical;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 92%,black);color:var(--pce-fg);padding:10px;font:.76rem/1.45 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.connection-editor__surface-action-editor{display:block;max-height:min(58vh,620px);overflow:auto;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 96%,black);padding:10px;margin-bottom:10px}.connection-editor__rule-grid{display:grid;gap:10px}.connection-editor__rule-card{display:grid;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__rule-heading{color:var(--pce-fg);font-size:.72rem;font-weight:900;text-transform:uppercase;letter-spacing:.06em}pre{margin:0;padding:12px;border-radius:12px;background:color-mix(in srgb,var(--pce-surface-strong) 82%,#020617);color:var(--pce-fg);overflow:auto;font-size:.75rem}@keyframes connection-flow{to{stroke-dashoffset:-38}}@keyframes drag-wire-pulse{0%,to{stroke-opacity:.76}50%{stroke-opacity:1}}@keyframes drag-halo-pulse{0%,to{stroke-opacity:.48}50%{stroke-opacity:.82}}@keyframes endpoint-pulse{0%,to{opacity:.78;transform:scale(1)}50%{opacity:1;transform:scale(1.25)}}@keyframes selected-wire-aura{0%,to{stroke-opacity:.46}50%{stroke-opacity:.92}}@keyframes wire-draw-in{0%{stroke-dashoffset:640;opacity:.32}70%{opacity:1}to{stroke-dashoffset:0;opacity:1}}@keyframes new-wire-halo{0%{stroke-opacity:0;stroke-width:30}28%{stroke-opacity:.78}to{stroke-opacity:0;stroke-width:12}}@keyframes new-dock-link-flash{0%{transform:translateY(-2px);box-shadow:0 16px 40px #0206175c,0 0 42px #fb923c47}to{transform:translateY(0)}}@keyframes trace-wire-pulse{0%,to{stroke-opacity:.78}50%{stroke-opacity:1}}@keyframes trace-halo-pulse{0%,to{stroke-opacity:.34}50%{stroke-opacity:.86}}@keyframes tooltip-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes invalid-drop-jolt{0%,to{transform:translate(0)}28%{transform:translate(-3px)}56%{transform:translate(3px)}}@keyframes invalid-drop-ping{0%{opacity:1;transform:translate(-50%,-50%) scale(.72)}72%{opacity:.74;transform:translate(-50%,-50%) scale(1.35)}to{opacity:0;transform:translate(-50%,-50%) scale(1.8)}}@keyframes node-breathe{50%{transform:scale(1.035)}}@keyframes node-focus-breathe{0%,to{transform:scale(1)}50%{transform:scale(1.055)}}@keyframes trace-source-pulse{50%{transform:scale(1.04);box-shadow:0 0 0 3px #facc15db,0 0 0 22px #facc1514,0 0 64px #facc1557}}@keyframes trace-source-orbit{to{transform:rotate(360deg)}}@keyframes trace-reacting-pulse{50%{transform:scale(1.045);box-shadow:0 0 0 3px #22c55ead,0 0 62px #22c55e4d}}@keyframes segment-focus-sweep{0%,to{stroke-opacity:.82}50%{stroke-opacity:1}}@keyframes snap-pulse{50%{filter:brightness(1.16)}}@keyframes port-focus-pulse{50%{transform:translateY(-1px);box-shadow:0 0 0 2px #facc158f,0 0 26px #facc153d}}@media(prefers-reduced-motion:reduce){.connection-editor__viewport,.connection-editor__node,.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-segment,.connection-editor__dock-link,.connection-editor__port{transition-duration:1ms}.connection-editor__wire,.connection-editor__wire--state,.connection-editor__wire--projection,.connection-editor__wire--state-read,.connection-editor__wire--event-propagation,.connection-editor__wire--halo.connection-editor__wire--active,.connection-editor__wire--trace,.connection-editor__wire--halo.connection-editor__wire--trace,.connection-editor__wire-endpoint,.connection-editor__connection-tooltip,.connection-editor__dock-link--new,.connection-editor__trace-overlay,.connection-editor__trace-overlay-step,.connection-editor__drag-wire,.connection-editor__drag-wire--halo,.connection-editor__drag-endpoint,.connection-editor__drag-tip,.connection-editor__node-ring,.connection-editor__node--connection-focus .connection-editor__node-ring,.connection-editor__node--trace-source .connection-editor__node-ring,.connection-editor__node--trace-source:before,.connection-editor__node--trace-reacting .connection-editor__node-ring,.connection-editor__node--rotating .connection-editor__node-ring,.connection-editor__node-segment--connection-focus,.connection-editor__node-segment--compatible,.connection-editor__node-segment--invalid-drop,.connection-editor__segment-popover,.connection-editor__port--compatible,.connection-editor__port--invalid-drop,.connection-editor__port--connection-focus,.connection-editor__invalid-drop,.connection-editor__invalid-drop-pulse{animation:none}.connection-editor__wire{stroke-dashoffset:0}.connection-editor__wire--new{stroke-dasharray:10 8;stroke-dashoffset:0;opacity:1}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:12;stroke-opacity:.16}.connection-editor__wire-endpoint,.connection-editor__drag-endpoint,.connection-editor__node-ring,.connection-editor__node--trace-source:before{transform:none}.connection-editor__invalid-drop-pulse{opacity:0}}@media(max-width:900px){:host{inset:0}.connection-editor{inset:8px;height:calc(100vh - 16px);padding:12px;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) minmax(76px,112px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) 48px}.connection-editor__header,.connection-editor__stage,.connection-editor__summary,.connection-editor__side-panel,.connection-editor__dock{grid-column:1}.connection-editor__header{align-items:stretch;flex-wrap:wrap;border-radius:18px}.connection-editor__mode-frame{order:3;width:100%;max-width:100%}.connection-editor__close{margin-inline-start:auto}.connection-editor__mode-frame:before,.connection-editor__mode-frame:after{content:\"\";position:absolute;z-index:2;inset-block:4px;width:24px;border-radius:999px;pointer-events:none}.connection-editor__mode-frame:before{inset-inline-start:1px;background:linear-gradient(90deg,#080d18f0,#080d1800)}.connection-editor__mode-frame:after{inset-inline-end:1px;background:linear-gradient(270deg,#080d18f0,#080d1800)}.connection-editor__mode-shell{width:100%;max-width:100%;overflow-x:auto;scroll-padding-inline:28px;-webkit-overflow-scrolling:touch}.connection-editor__subtitle{margin-inline-start:auto}.connection-editor__stage{grid-row:2;min-height:260px}.connection-editor__summary{grid-row:2;max-width:calc(100% - 24px)}.connection-editor__side-panel{grid-row:3;max-height:30vh}.connection-editor__dock{grid-row:4;min-height:0}.connection-editor__connection-tooltip{width:min(620px,calc(100% - 24px));max-height:min(260px,calc(100% - 24px));overflow:auto}.connection-editor__dock-tabs{width:100%;min-width:0;min-height:0;flex-wrap:wrap;align-items:flex-start}.connection-editor__dock-tablist{width:100%;flex-wrap:wrap}.connection-editor__dock-count{flex:1 1 100%;margin-inline-start:0}.connection-editor__dock-body{width:100%;min-width:0;max-height:76px;box-sizing:border-box}.connection-editor__dock-body pre{white-space:pre-wrap;overflow-wrap:anywhere}.connection-editor__dock-link{grid-template-columns:1fr;align-items:start}.connection-editor__dock-link-route{flex-wrap:wrap}.connection-editor__dock-link-badges{justify-content:flex-start}.connection-editor__trace-overlay{inset-inline-start:14px;width:min(420px,calc(100% - 28px));min-width:0;transform:none}.connection-editor__drag-tip{width:min(300px,calc(100% - 28px))}.connection-editor__segment-popover{width:min(280px,calc(100% - 28px));max-height:min(280px,calc(100% - 28px))}.connection-editor__minimap{inset-inline-end:10px;inset-block-end:10px;width:132px;height:94px;padding:16px 8px 8px;border-radius:14px}.connection-editor__minimap:before{inset:20px 8px 8px;background-size:18px 18px}.connection-editor__minimap-title{inset-block-start:6px;inset-inline-start:10px;font-size:.54rem}}@media(max-width:640px){.connection-editor{inset:4px;height:calc(100vh - 8px);padding:8px;gap:8px;grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) minmax(72px,104px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) 46px}.connection-editor__header{gap:8px;padding:10px}.connection-editor__mode-shell{padding:4px;gap:2px}.connection-editor__mode{min-height:28px;gap:4px;padding:0 7px;font-size:.68rem}.connection-editor__mode-glyph{font-size:.64rem}.connection-editor__stage{min-height:240px}.connection-editor__zoom-controls{inset-inline-start:8px;inset-block-start:8px;gap:6px;width:42px}.connection-editor__tool-group,.connection-editor__trace-source{gap:6px;padding:8px;border-radius:12px}.connection-editor__tool-group{grid-template-columns:28px}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:28px}.connection-editor__tool-button{width:28px;height:28px}.connection-editor__arrange-button,.connection-editor__simulate-button{width:30px;min-height:30px}.connection-editor__summary{gap:6px;padding-inline-end:8px}.connection-editor__side-panel{max-height:28vh}.connection-editor__dock{border-radius:16px}.connection-editor__dock-tabs,.connection-editor__dock-tablist{gap:4px}.connection-editor__dock-tab{padding:0 9px}.connection-editor__dock-count{font-size:.62rem}.connection-editor__dock-body{max-height:66px;padding:8px}.connection-editor__minimap{width:116px;height:84px}.connection-editor__segment-row{grid-template-columns:24px minmax(54px,.55fr) minmax(0,1fr) auto}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: SurfaceOpenActionEditorComponent, selector: "praxis-surface-open-action-editor", inputs: ["value", "hostKind"], outputs: ["valueChange"] }, { kind: "pipe", type: i2$3.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9988
|
+
`, isInline: true, styles: [":host{position:fixed;inset:0;z-index:1000;pointer-events:none}.connection-editor{--pce-fg: var(--md-sys-color-on-surface, #dce6f4);--pce-strong: var(--md-sys-color-on-surface, #f8fafc);--pce-muted: var(--md-sys-color-on-surface-variant, #94a3b8);--pce-primary: var(--md-sys-color-primary, #19c8e8);--pce-secondary: var(--md-sys-color-secondary, #b46cff);--pce-tertiary: var(--md-sys-color-tertiary, #ff9f2f);--pce-success: var(--md-sys-color-tertiary, #10b981);--pce-warning: var(--md-sys-color-error, #ff9f2f);--pce-error: var(--md-sys-color-error, #ef4444);--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #07111f) 80%, #020617);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #08101d) 78%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #0f172a) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #080d18) 64%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #899ab7) 46%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #94a3b8) 58%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #7d8fa9) 24%, transparent);--pce-glass-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, #ffffff) 8%, transparent);--pce-shadow: color-mix(in srgb, #000 56%, transparent);--pce-shadow-soft: color-mix(in srgb, #000 30%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #040a13) 42%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high, #050912) 94%, transparent);position:absolute;inset:12px;height:calc(100vh - 24px);box-sizing:border-box;overflow:hidden;padding:16px;border-radius:18px;color:var(--pce-fg);background:radial-gradient(circle at 72% 20%,color-mix(in srgb,var(--pce-secondary) 16%,transparent),transparent 28%),radial-gradient(circle at 26% 74%,color-mix(in srgb,var(--pce-primary) 10%,transparent),transparent 34%),radial-gradient(circle at 48% 52%,color-mix(in srgb,var(--pce-tertiary) 5%,transparent),transparent 35%),linear-gradient(var(--pce-grid) 1px,transparent 1px),linear-gradient(90deg,var(--pce-grid) 1px,transparent 1px),var(--pce-surface-base);background-size:auto,auto,auto,38px 38px,38px 38px,auto;border:1px solid var(--pce-outline);box-shadow:0 28px 90px var(--pce-shadow);pointer-events:auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);grid-template-rows:auto minmax(0,1fr) minmax(44px,118px);gap:14px}:host-context(.theme-light) .connection-editor{--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 94%, var(--md-sys-color-primary, #2563eb) 6%);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 82%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #eef2ff) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #f8fafc) 70%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 68%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #64748b) 62%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 34%, transparent);--pce-glass-highlight: color-mix(in srgb, #fff 64%, transparent);--pce-shadow: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 22%, transparent);--pce-shadow-soft: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 14%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #ffffff) 58%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 92%, transparent)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(0,1fr) 48px}.connection-editor__header{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:42px;padding:8px 14px;border-radius:999px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__mode-frame{position:relative;min-width:0;flex:1 1 auto;display:flex;justify-content:center}.connection-editor__close{width:32px;height:32px;flex:0 0 auto;display:inline-grid;place-items:center;border:1px solid var(--pce-outline);border-radius:999px;color:var(--pce-text);background:var(--pce-surface-strong);box-shadow:inset 0 1px var(--pce-glass-highlight);cursor:pointer;font:inherit;font-size:1.2rem;line-height:1}.connection-editor__close:hover,.connection-editor__close:focus-visible{border-color:var(--pce-outline-strong);background:color-mix(in srgb,var(--pce-accent) 16%,var(--pce-surface-strong));outline:none}.connection-editor__mode-shell{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:4px;border-radius:999px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:inset 0 1px var(--pce-glass-highlight),0 10px 26px var(--pce-shadow-soft);scrollbar-width:none}.connection-editor__mode-shell::-webkit-scrollbar{display:none}.connection-editor__mode{min-height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 12px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.76rem;font-weight:800;white-space:nowrap;transition:background .16s ease,border-color .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__mode:hover,.connection-editor__mode--active{color:var(--pce-strong);border-color:color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-strong) 82%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 12%,transparent)}.connection-editor__mode-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__mode--active .connection-editor__mode-glyph{color:var(--pce-primary)}.connection-editor__mode-dot{width:6px;height:6px;border-radius:999px;background:var(--pce-success);box-shadow:0 0 12px color-mix(in srgb,var(--pce-success) 70%,transparent)}.connection-editor__status-pill{display:inline-flex;align-items:center;gap:8px;min-height:24px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 36%,transparent);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.72rem;font-weight:800;white-space:nowrap}.connection-editor__status-pill--button{cursor:pointer;transition:border-color .16s ease,background .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__status-pill--button:hover,.connection-editor__status-pill--button:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 62%,transparent);background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 14%,transparent);outline:none}.connection-editor__status-pill span{width:6px;height:6px;border-radius:999px;background:var(--pce-primary);box-shadow:0 0 12px color-mix(in srgb,var(--pce-primary) 70%,transparent)}.connection-editor__section{display:grid;gap:10px}.connection-editor__dock{grid-column:1 / -1;grid-row:3;position:relative;z-index:4;min-height:0;display:grid;border-radius:14px;border:1px solid var(--pce-outline);background:radial-gradient(circle at 16% 0%,color-mix(in srgb,var(--pce-primary) 22%,transparent),transparent 34%),radial-gradient(circle at 78% 0%,color-mix(in srgb,var(--pce-secondary) 25%,transparent),transparent 38%),linear-gradient(90deg,var(--pce-dock-bg),var(--pce-surface-strong) 46%,color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-dock-bg))),var(--pce-dock-bg);box-shadow:0 18px 58px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__dock--collapsed .connection-editor__dock-tabs{border-block-end:0}.connection-editor__dock-tabs{display:flex;align-items:center;gap:10px;min-height:52px;padding:9px 14px;border-block-end:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-glass-highlight),transparent),color-mix(in srgb,var(--pce-surface-soft) 34%,transparent)}.connection-editor__dock-tablist{display:flex;align-items:center;gap:10px;min-width:0}.connection-editor__dock-tab,.connection-editor__dock-toggle{min-height:30px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.72rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-tab{display:inline-flex;align-items:center;gap:8px;padding:0 13px;white-space:nowrap}.connection-editor__dock-tab-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.8rem;letter-spacing:0;text-transform:none}.connection-editor__dock-tab--active{color:var(--pce-strong);border-color:var(--pce-outline-strong);background:linear-gradient(180deg,color-mix(in srgb,var(--pce-strong) 14%,transparent),color-mix(in srgb,var(--pce-strong) 6%,transparent));box-shadow:0 0 0 1px color-mix(in srgb,var(--pce-shadow) 72%,transparent),0 0 22px color-mix(in srgb,var(--pce-strong) 8%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__dock-tab--active .connection-editor__dock-tab-glyph{color:var(--pce-strong)}.connection-editor__dock-count{margin-inline-start:auto;color:color-mix(in srgb,var(--pce-muted) 62%,transparent);font-size:.7rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-toggle{width:32px;padding:0;border-color:var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.88rem;letter-spacing:0}.connection-editor__dock-body{max-height:154px;overflow:auto;padding:12px 12px 14px;border-block-start:1px solid var(--pce-outline);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 9%,transparent),color-mix(in srgb,var(--pce-secondary) 10%,transparent) 62%,color-mix(in srgb,var(--pce-surface-strong) 18%,transparent)),color-mix(in srgb,var(--pce-surface-soft) 30%,transparent)}.connection-editor__dock-body pre{max-height:60px}.connection-editor__dock-links{display:grid;gap:8px}.connection-editor__dock-link-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;padding:7px 10px;border-radius:10px;border:1px solid var(--pce-outline);background:linear-gradient(90deg,var(--pce-surface-soft),color-mix(in srgb,var(--pce-secondary) 10%,var(--pce-surface-soft)) 72%,var(--pce-surface-soft)),var(--pce-surface-soft);color:var(--pce-fg);transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-link{display:grid;grid-template-columns:minmax(116px,.52fr) minmax(300px,1.72fr) minmax(160px,.9fr) auto;align-items:center;gap:12px;width:100%;min-height:42px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;text-align:start}.connection-editor__dock-link-row:hover,.connection-editor__dock-link--active{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 13%,transparent),color-mix(in srgb,var(--pce-secondary) 16%,transparent),var(--pce-surface-strong)),var(--pce-surface-strong);box-shadow:0 12px 32px var(--pce-shadow-soft),inset 0 0 18px color-mix(in srgb,var(--pce-primary) 6%,transparent)}.connection-editor__dock-link--active{border-color:#facc1575;box-shadow:0 12px 32px var(--pce-shadow-soft),0 0 24px #facc151f}.connection-editor__dock-link--new{border-color:#fb923ca3;background:linear-gradient(90deg,#fb923c2e,#a855f729,#0ea5e91f),#0f172ac2;box-shadow:0 12px 34px #02061752,0 0 30px #fb923c2e;animation:new-dock-link-flash 1.35s ease-out forwards}.connection-editor__dock-link--error{border-color:#ef444461}.connection-editor__dock-jump{min-width:62px;min-height:30px;padding:0 10px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 54%,transparent);color:var(--pce-primary);cursor:pointer;font-size:.66rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__dock-jump:hover,.connection-editor__dock-jump:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 56%,transparent);background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 18%,transparent);outline:none}.connection-editor__dock-link-kind{display:inline-flex;align-items:center;gap:7px;min-width:0;color:var(--pce-muted);font-size:.66rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-link-kind span{width:8px;height:8px;border-radius:999px;background:#b46cff;box-shadow:0 0 14px #b46cff7a}.connection-editor__dock-link--state .connection-editor__dock-link-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2f94}.connection-editor__dock-link--state-read .connection-editor__dock-link-kind span{background:#8b7dff;box-shadow:0 0 13px #8b7dff75}.connection-editor__dock-link--projection .connection-editor__dock-link-kind span{background:#19c8e8;box-shadow:0 0 10px #19c8e857}.connection-editor__dock-link--event-propagation .connection-editor__dock-link-kind span{background:#ffb454;box-shadow:0 0 15px #ffb45485}.connection-editor__dock-link--policy .connection-editor__dock-link-kind span{outline:1px solid rgba(34,197,94,.76);outline-offset:2px;box-shadow:0 0 16px #22c55e61}.connection-editor__dock-link--policy:not(.connection-editor__dock-link--state,.connection-editor__dock-link--state-read,.connection-editor__dock-link--projection,.connection-editor__dock-link--event-propagation) .connection-editor__dock-link-kind span{background:#22c55e}.connection-editor__dock-link-route{display:inline-flex;align-items:center;gap:8px;min-width:0}.connection-editor__dock-link-chip{min-width:0;overflow:hidden;padding:4px 8px;border-radius:999px;border:1px solid var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-soft) 72%,transparent);color:var(--pce-fg);font-size:.72rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-chip--from{border-color:#ff9f2f66;color:#ffbd62}.connection-editor__dock-link-chip--to{border-color:#19c8e83d;color:#7dddeb}:host-context(.theme-light) .connection-editor__dock-link-chip--from{border-color:color-mix(in srgb,var(--pce-tertiary) 46%,transparent);color:#8a4600}:host-context(.theme-light) .connection-editor__dock-link-chip--to{border-color:color-mix(in srgb,var(--pce-primary) 34%,transparent);color:#075f73}.connection-editor__dock-link-arrow{flex:0 0 auto;color:var(--pce-muted);font-weight:900}.connection-editor__dock-link-id{min-width:0;overflow:hidden;color:var(--pce-muted);font-size:.66rem;font-weight:800;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-badges{display:inline-flex;justify-content:flex-end;gap:5px;min-width:70px}.connection-editor__dock-link-badges span{padding:3px 7px;border-radius:999px;background:#a855f724;color:#d8b4fe;font-size:.62rem;font-weight:900;text-transform:uppercase;white-space:nowrap}:host-context(.theme-light) .connection-editor__dock-link-badges span{background:color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-surface-soft));color:#6d2a9f}.connection-editor__dock-empty{padding:12px;border-radius:12px;border:1px dashed var(--pce-outline);color:var(--pce-muted);font-size:.76rem;font-weight:700}.connection-editor__inspector{border-color:color-mix(in srgb,var(--pce-primary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 10%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface)}.connection-editor__eyebrow,.connection-editor__section-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--pce-muted);font-weight:700}.connection-editor__title{font-size:1.02rem;font-weight:800}.connection-editor__subtitle,.connection-editor__item-copy,.connection-editor__item-meta,.connection-editor__details-row span,.connection-editor__details-label,.connection-editor__empty{color:var(--pce-muted);font-size:.84rem}.connection-editor__inspector-heading{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--pce-surface-soft);border:1px solid var(--pce-outline)}.connection-editor__inspector-heading strong{color:var(--pce-strong);font-size:.96rem;overflow-wrap:anywhere}.connection-editor__inspector-heading span{color:var(--pce-primary);font-size:.76rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}.connection-editor__human-summary{display:grid;gap:6px;padding:12px;border-radius:14px;border:1px solid color-mix(in srgb,var(--pce-primary) 24%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface-soft);color:var(--pce-fg);line-height:1.35}.connection-editor__nested-summary{display:grid;gap:6px;padding:10px;border-radius:12px;border:1px solid color-mix(in srgb,var(--pce-primary) 22%,transparent);background:color-mix(in srgb,var(--pce-primary) 8%,var(--pce-surface-soft))}.connection-editor__nested-summary strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__nested-summary span:last-child{color:var(--pce-primary);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.72rem;overflow-wrap:anywhere}.connection-editor__recommended{border-color:color-mix(in srgb,var(--pce-secondary) 32%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 14%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface)}.connection-editor__recommended-card{display:grid;gap:8px;width:100%;padding:13px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 36%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 16%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__recommended-card:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 52%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 22%,transparent),color-mix(in srgb,var(--pce-primary) 14%,transparent)),var(--pce-surface-strong)}.connection-editor__recommended-card strong{color:var(--pce-strong);font-size:.92rem;line-height:1.28}.connection-editor__recommended-card span:not(.connection-editor__human-summary-label):not(.connection-editor__suggestion-action),.connection-editor__recommended-card small{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__success{display:grid;gap:4px;padding:10px 12px;border-radius:14px;border:1px solid rgba(34,197,94,.34);background:#22c55e1f;color:var(--pce-fg);line-height:1.35}.connection-editor__success strong{color:#bbf7d0;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__success span{color:var(--pce-strong);font-size:.82rem}.connection-editor__human-summary-label,.connection-editor__suggestion-intent{justify-self:start;padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:#bae6fd;font-size:.66rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__human-summary strong{color:var(--pce-strong);font-size:.88rem}.connection-editor__human-summary span:last-child,.connection-editor__suggestion-preview{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__technical-details{display:grid;gap:10px;padding:10px 12px;border-radius:14px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__technical-details summary{cursor:pointer;color:var(--pce-muted);font-size:.78rem;font-weight:800}.connection-editor__technical-details[open] summary{margin-bottom:10px;color:var(--pce-strong)}.connection-editor__inspector-ports{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__inspector-port{max-width:100%;padding:4px 8px;border-radius:999px;border:1px solid rgba(148,163,184,.16);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-editor__inspector-port--input{border-color:#22d3ee57;color:#67e8f9}.connection-editor__inspector-port--output{border-color:#f59e0b57;color:#fbbf24}.connection-editor__inspector-port--state{border-color:#a855f761;color:#d8b4fe}.connection-editor__segment-kind-legend{display:grid;gap:10px;padding:12px;border-radius:16px;border:1px solid rgba(148,163,184,.14);background:linear-gradient(135deg,#0f172aa8,#080d1885),#02061757}.connection-editor__segment-kind-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.connection-editor__segment-kind-pill{min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:900;overflow:hidden;white-space:nowrap}.connection-editor__segment-kind-pill span{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:currentColor;box-shadow:0 0 12px currentColor}.connection-editor__segment-kind-pill--input{border-color:#19c8e83d;color:#7dddeb}.connection-editor__segment-kind-pill--output{border-color:#ff9f2f61;color:#ffbd62}.connection-editor__segment-kind-pill--state{border-color:#b46cff61;color:#d9b8ff}:host-context(.theme-light) .connection-editor__segment-kind-pill{border-color:var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-strong) 88%,transparent)}:host-context(.theme-light) .connection-editor__segment-kind-pill--input{color:#075f73}:host-context(.theme-light) .connection-editor__segment-kind-pill--output{color:#8a4600}:host-context(.theme-light) .connection-editor__segment-kind-pill--state{color:#6d2a9f}.connection-editor__stage{grid-column:1;grid-row:2;position:relative;min-height:0;height:100%;overflow:visible;border-radius:16px;border:1px solid var(--pce-outline);background:radial-gradient(circle at center,color-mix(in srgb,var(--pce-secondary) 7%,transparent),transparent 38%),radial-gradient(circle,var(--pce-grid) 1px,transparent 1.5px),var(--pce-stage-bg);background-size:auto,31px 31px,auto;box-shadow:inset 0 0 0 1px var(--pce-glass-highlight);cursor:grab;touch-action:none}.connection-editor__stage--panning,.connection-editor__stage:active{cursor:grabbing}.connection-editor__stage--dragging{cursor:crosshair}.connection-editor__stage--rotating{cursor:grabbing}.connection-editor__viewport{position:absolute;inset-block-start:0;inset-inline-start:0;width:900px;height:540px;overflow:visible;transform-origin:0 0;transition:transform .14s ease}.connection-editor__wires{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.connection-editor__wire,.connection-editor__wire-hit{fill:none;stroke-linecap:round}.connection-editor__wire{stroke:#b46cff;stroke-width:1.45;stroke-opacity:.48;pointer-events:none;filter:url(#connection-glow);stroke-dasharray:10 8;animation:connection-flow 1.65s linear infinite}.connection-editor__wire-hit{stroke:transparent;stroke-width:18;cursor:pointer;pointer-events:stroke}.connection-editor__wire-hit--active{stroke-width:28}.connection-editor__wire--halo{stroke:#b46cff1f;stroke-width:7;stroke-dasharray:none;animation:none}.connection-editor__wire--state{stroke:#ff9f2f;stroke-width:2.25;stroke-dasharray:8 7;animation:connection-flow .92s linear infinite}.connection-editor__wire--state.connection-editor__wire--halo{stroke:#ff9f2f29;stroke-width:11}.connection-editor__wire--projection{stroke:#15b8d8;stroke-width:1.75;stroke-dasharray:20 8;animation:connection-flow 1.9s linear infinite}.connection-editor__wire--projection.connection-editor__wire--halo{stroke:#15b8d81a;stroke-width:7}.connection-editor__wire--state-read{stroke:#8b7dff;stroke-width:1.65;stroke-dasharray:3 11;animation:connection-flow 2.25s linear infinite reverse}.connection-editor__wire--state-read.connection-editor__wire--halo{stroke:#8b7dff21;stroke-width:8}.connection-editor__wire--event-propagation{stroke:#ffb454;stroke-width:2.05;stroke-dasharray:5 7;animation:connection-flow .78s linear infinite}.connection-editor__wire--event-propagation.connection-editor__wire--halo{stroke:#ffb4542e;stroke-width:10}.connection-editor__wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.2)) url(#connection-glow)}.connection-editor__wire--policy.connection-editor__wire--halo{stroke:#22c55e1f;stroke-width:13}.connection-editor__wire--warning{stroke:#ff9f2f}.connection-editor__wire--warning.connection-editor__wire--halo{stroke:#ff9f2f2e}.connection-editor__wire--error{stroke:#ef4444}.connection-editor__wire--error.connection-editor__wire--halo{stroke:#ef44442e}.connection-editor__wire--active{stroke:#d9b8ff;stroke-width:3;stroke-opacity:1;stroke-dasharray:5 7;animation-duration:.58s}.connection-editor__wire--halo.connection-editor__wire--active{stroke-width:16;stroke-opacity:.8;animation:selected-wire-aura 1.35s ease-in-out infinite}.connection-editor__wire--new{stroke-width:3.4;stroke-opacity:1;stroke-dasharray:640;stroke-dashoffset:640;animation:wire-draw-in .62s cubic-bezier(.16,1,.3,1) forwards,connection-flow 1.05s linear .62s infinite}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:22;stroke-opacity:0;animation:new-wire-halo 1.45s ease-out forwards}.connection-editor__wire--trace{stroke:#9b5cff;stroke-width:3.2;stroke-opacity:1;stroke-dasharray:7 6;animation:connection-flow .72s linear infinite,trace-wire-pulse 1.18s ease-in-out infinite}.connection-editor__wire--halo.connection-editor__wire--trace{stroke:#9b5cff57;stroke-width:18;stroke-opacity:.86;animation:trace-halo-pulse 1.18s ease-in-out infinite}.connection-editor__wire--mode-dimmed{stroke-opacity:.14;stroke-width:1.05;filter:none;animation-duration:2.6s}.connection-editor--guided .connection-editor__wire:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.85;filter:none;animation:none}.connection-editor--guided .connection-editor__wire--halo:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.08;animation:none}.connection-editor__wire--halo.connection-editor__wire--mode-dimmed{stroke-opacity:.05;stroke-width:5;animation:none}.connection-editor__wire-hit--mode-dimmed{stroke-width:12}.connection-editor__wire-endpoint{fill:#f8fafc;stroke:#0f172ae6;stroke-width:1.5;filter:drop-shadow(0 0 8px rgba(216,180,254,.8));pointer-events:none;animation:endpoint-pulse 1.2s ease-in-out infinite}.connection-editor__wire-endpoint--source{fill:#ff9f2f}.connection-editor__wire-endpoint--target{fill:#19c8e8}.connection-editor__connection-tooltip{position:absolute;z-index:6;width:min(312px,calc(100% - 24px));display:grid;gap:8px;padding:12px 14px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(135deg,var(--pce-surface-strong),var(--pce-surface)),var(--pce-surface-strong);box-shadow:0 18px 44px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);color:var(--pce-fg);pointer-events:none;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .14s ease-out}.connection-editor__connection-tooltip-callout{position:absolute;inset-block-start:100%;inset-inline-start:var(--connection-tooltip-callout-x, 42px);width:2px;height:28px;border-radius:999px;background:linear-gradient(180deg,#e2e8f0bd,#19c8e800);box-shadow:0 0 12px #19c8e852;transform:translate(-1px);pointer-events:none}.connection-editor__connection-tooltip-callout:before,.connection-editor__connection-tooltip-callout:after{content:\"\";position:absolute;border-radius:999px;pointer-events:none}.connection-editor__connection-tooltip-callout:before{inset-block-start:-5px;inset-inline-start:-5px;width:12px;height:12px;border:1px solid rgba(148,163,184,.24);background:#080d18f5;box-shadow:inset 0 1px #ffffff14}.connection-editor__connection-tooltip-callout:after{inset-block-end:-3px;inset-inline-start:-4px;width:10px;height:10px;background:#19c8e8;box-shadow:0 0 16px #19c8e88f}.connection-editor__connection-tooltip--projection{border-color:#19c8e833;background:linear-gradient(135deg,#15b8d81f,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state{border-color:#ff9f2f66;background:linear-gradient(135deg,#ff9f2f3d,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout{background:linear-gradient(180deg,#ffbd62d1,#ff9f2f00);box-shadow:0 0 14px #ff9f2f61}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout:after{background:#ff9f2f;box-shadow:0 0 18px #ff9f2fad}.connection-editor__connection-tooltip--error{border-color:#f871716b}.connection-editor__connection-tooltip--error .connection-editor__connection-tooltip-callout:after{background:#fb7185;box-shadow:0 0 18px #fb7185ad}.connection-editor__connection-tooltip-kind{display:inline-flex;align-items:center;gap:8px;color:#94a3b8;font-size:.62rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__connection-tooltip-kind span{width:8px;height:8px;border-radius:999px;background:#19c8e8;box-shadow:0 0 12px #19c8e880}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2fc7}.connection-editor__connection-tooltip-row{min-width:0;display:grid;grid-template-columns:54px minmax(0,1fr);align-items:center;gap:8px;min-height:28px;padding:0 10px;border-radius:999px;background:#0f172a94}.connection-editor__connection-tooltip-row span{color:#8d9bb0;font-size:.62rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.connection-editor__connection-tooltip-row strong{min-width:0;overflow:hidden;color:#e2e8f0;font-size:.75rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__connection-tooltip-badges{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__connection-tooltip-badges span{padding:3px 8px;border-radius:999px;background:#02061799;color:#fbbf24;font-size:.66rem;font-weight:900}.connection-editor__trace-overlay{position:absolute;z-index:6;inset-block-start:16px;inset-inline-start:50%;width:min(560px,calc(100% - 360px));min-width:320px;padding:12px 14px;border-radius:16px;border:1px solid rgba(34,197,94,.26);background:linear-gradient(135deg,#22c55e1f,#0ea5e91a),#080d18f0;box-shadow:0 22px 56px #02061775,0 0 42px #22c55e1f;transform:translate(-50%);pointer-events:auto;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .16s ease-out}.connection-editor__trace-overlay-head,.connection-editor__trace-overlay-route{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.connection-editor__trace-overlay-head span,.connection-editor__trace-overlay-route span{color:#86efac;font-size:.66rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap}.connection-editor__trace-overlay-head strong{color:#cbd5e1;font-size:.7rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace}.connection-editor__trace-overlay-route{margin-top:6px}.connection-editor__trace-overlay-controls{display:grid;grid-template-columns:28px minmax(0,1fr) 28px;align-items:center;gap:8px;margin-top:10px}.connection-editor__trace-overlay-button{width:28px;height:24px;display:inline-grid;place-items:center;border:1px solid rgba(148,163,184,.18);border-radius:999px;background:#0206176b;color:#e2e8f0;cursor:pointer;font-size:1rem;font-weight:900;line-height:1;transition:border-color .15s ease,background .15s ease,color .15s ease,opacity .15s ease}.connection-editor__trace-overlay-button:hover:not(:disabled){border-color:#22d3ee6b;background:#0ea5e929;color:#f8fafc}.connection-editor__trace-overlay-button:disabled{cursor:default;opacity:.36}.connection-editor__trace-overlay-steps{min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto;padding:2px;scrollbar-width:none}.connection-editor__trace-overlay-steps::-webkit-scrollbar{display:none}.connection-editor__trace-overlay-step{position:relative;flex:1 0 28px;min-width:28px;height:22px;border:1px solid rgba(148,163,184,.16);border-radius:999px;background:#0f172a9e;color:#94a3b8;cursor:pointer;font-size:.62rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__trace-overlay-step--active{border-color:#22d3eea3;background:linear-gradient(90deg,#22d3ee3d,#9b5cff33);color:#f8fafc;box-shadow:0 0 18px #22d3ee33}.connection-editor__trace-overlay-step--blocked{border-color:#fb71855c;color:#fecdd3}.connection-editor__trace-overlay-route strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.82rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__trace-overlay-bar{position:relative;height:5px;margin-top:10px;overflow:hidden;border-radius:999px;background:#94a3b829}.connection-editor__trace-overlay-bar span{position:absolute;inset-block:0;inset-inline-start:0;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#22d3ee);box-shadow:0 0 18px #22c55e61;min-width:8%}.connection-editor__drag-wire{fill:none;stroke:#94a3b8;stroke-width:2.4;stroke-linecap:round;stroke-dasharray:6 7;pointer-events:none;filter:url(#connection-glow);animation:connection-flow 1.05s linear infinite,drag-wire-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--halo{stroke:#94a3b829;stroke-width:14;stroke-dasharray:none;animation:drag-halo-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--valid{stroke:#22c55e}.connection-editor__drag-wire--halo.connection-editor__drag-wire--valid{stroke:#22c55e47}.connection-editor__drag-endpoint{fill:#94a3b8;stroke:#020617eb;stroke-width:2;pointer-events:none;filter:url(#connection-glow);transform-box:fill-box;transform-origin:center;animation:endpoint-pulse 1s ease-in-out infinite}.connection-editor__drag-endpoint--source{fill:#ff9f2f}.connection-editor__drag-endpoint--target{fill:#7dddeb}.connection-editor__drag-endpoint--valid{fill:#22c55e;stroke:#bbf7d0e0}.connection-editor__wire-handle-line{stroke-width:2;stroke-linecap:round;stroke-dasharray:4 5;pointer-events:none;opacity:.88;filter:url(#connection-glow)}.connection-editor__wire-handle-line--source{stroke:#ff9f2ff0}.connection-editor__wire-handle-line--target{stroke:#19c8e8c2}.connection-editor__wire-control{fill:#0f172af5;stroke:#cbd5e1c7;stroke-width:1.8;pointer-events:none;filter:url(#connection-glow)}.connection-editor__wire-label{pointer-events:none;filter:drop-shadow(0 0 10px rgba(2,6,23,.44));animation:tooltip-rise .14s ease-out}.connection-editor__wire-label rect{fill:#080d18eb;stroke-width:1}.connection-editor__wire-label text{fill:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__wire-label--source rect{stroke:#ff9f2fad}.connection-editor__wire-label--target rect{stroke:#19c8e86b}.connection-editor__zoom-controls{position:absolute;inset-inline-start:14px;inset-block-start:14px;z-index:4;display:grid;grid-template-columns:max-content;gap:6px;width:46px;pointer-events:auto}.connection-editor__tool-group,.connection-editor__trace-source{display:grid;gap:6px;padding:6px;border-radius:12px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:0 16px 36px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__tool-group{grid-template-columns:30px;width:max-content}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:30px}.connection-editor__arrange-button{width:34px;min-height:34px;display:inline-flex;align-items:center;justify-content:center;gap:0;padding:0;border-radius:999px;border:1px solid rgba(168,85,247,.34);background:linear-gradient(90deg,#a855f72e,#22d3ee1f);color:#e9d5ff;font-size:0;font-weight:800;letter-spacing:0;cursor:pointer;opacity:1;transform:scale(1);transition:opacity .14s ease,transform .14s ease,border-color .14s ease,background .14s ease}.connection-editor--guided .connection-editor__arrange-button{opacity:.34;transform:scale(.9);border-color:color-mix(in srgb,var(--pce-outline) 82%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 84%,transparent)}.connection-editor--guided .connection-editor__zoom-controls:hover .connection-editor__arrange-button,.connection-editor--guided .connection-editor__zoom-controls:focus-within .connection-editor__arrange-button,.connection-editor--guided .connection-editor__arrange-button:hover,.connection-editor--guided .connection-editor__arrange-button:focus-visible,.connection-editor--guided .connection-editor__arrange-button--active{opacity:1;transform:scale(1);border-color:#a855f757;background:linear-gradient(90deg,#a855f72e,#22d3ee1f)}.connection-editor__arrange-button span{color:#c084fc;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.78rem;font-weight:900}.connection-editor__tool-button{width:30px;height:30px;border-radius:999px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.9rem;font-weight:800;letter-spacing:.02em;cursor:pointer;line-height:1}.connection-editor__tool-button:hover:not(:disabled){border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);color:var(--pce-primary);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 16%,transparent)}.connection-editor__history-button:disabled{cursor:not-allowed;opacity:.42}.connection-editor__arrange-button--active{border-color:#22d3ee94;background:linear-gradient(90deg,#0ea5e93d,#22d3ee2e);color:#cffafe}.connection-editor__trace-source{gap:4px;max-height:230px;overflow:auto}.connection-editor__trace-source-title{padding:2px 4px 6px;color:var(--pce-muted);font-size:.64rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.connection-editor__trace-source-item{min-width:0;min-height:30px;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:8px;background:transparent;color:var(--pce-fg);cursor:pointer;font-size:.74rem;font-weight:800;text-align:start}.connection-editor__trace-source-item span{color:#f59e0b;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__trace-source-item:hover,.connection-editor__trace-source-item--active{background:var(--pce-surface-strong);color:var(--pce-strong);box-shadow:inset 3px 0 #f59e0bd1}.connection-editor__minimap{position:absolute;inset-inline-end:14px;inset-block-end:14px;z-index:4;width:184px;height:124px;padding:18px 10px 10px;overflow:hidden;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-primary) 30%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),var(--pce-surface-strong)),var(--pce-surface);box-shadow:0 20px 48px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);cursor:pointer;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);opacity:1;transform:scale(1);transform-origin:100% 100%;transition:opacity .16s ease,transform .16s ease,border-color .16s ease,box-shadow .16s ease}.connection-editor--guided .connection-editor__minimap{opacity:.54;transform:scale(.88);border-color:color-mix(in srgb,var(--pce-outline) 64%,transparent);box-shadow:0 14px 34px color-mix(in srgb,var(--pce-shadow-soft) 70%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor--guided .connection-editor__minimap:hover,.connection-editor--guided .connection-editor__minimap:focus-visible,.connection-editor--guided .connection-editor__minimap--panning{opacity:1;transform:scale(1)}.connection-editor__minimap:hover,.connection-editor__minimap--panning{border-color:#22d3ee75;box-shadow:0 20px 48px var(--pce-shadow-soft),0 0 24px color-mix(in srgb,var(--pce-primary) 14%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__minimap--panning{cursor:grabbing}.connection-editor__minimap:before{content:\"\";position:absolute;inset:22px 10px 10px;border-radius:10px;background-image:radial-gradient(circle,rgba(125,211,252,.18) 1px,transparent 1px);background-size:22px 22px;opacity:.58;pointer-events:none}.connection-editor__minimap-title{position:absolute;inset-block-start:7px;inset-inline-start:12px;color:var(--pce-muted);font-size:.6rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__minimap svg{position:relative;width:100%;height:100%;display:block;overflow:visible}.connection-editor__minimap-wire{fill:none;stroke:#b46cff8f;stroke-width:4;stroke-linecap:round;opacity:.86}.connection-editor__minimap-wire--state{stroke:#ff9f2fdb}.connection-editor__minimap-wire--state-read{stroke:#8b7dffb8;stroke-dasharray:4 9}.connection-editor__minimap-wire--projection{stroke:#19c8e88a;stroke-dasharray:18 8}.connection-editor__minimap-wire--event-propagation{stroke:#ffb454cc;stroke-dasharray:6 7}.connection-editor__minimap-wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.28))}.connection-editor__minimap-wire--trace{stroke:#9b5cffe0;stroke-width:5;stroke-dasharray:12 9;animation:connection-flow 1s linear infinite}.connection-editor__minimap-wire--active{stroke:#facc15eb;stroke-width:6;filter:drop-shadow(0 0 8px rgba(250,204,21,.38))}.connection-editor__minimap-wire--mode-dimmed{opacity:.2;stroke-width:2.6;filter:none}.connection-editor__minimap-node{fill:#f59e0be0;stroke:#020617db;stroke-width:4;filter:drop-shadow(0 0 7px rgba(245,158,11,.24))}.connection-editor__minimap-node--state{fill:#a855f7e6;filter:drop-shadow(0 0 8px rgba(168,85,247,.34))}.connection-editor__minimap-node--selected{fill:#facc15f5;stroke:#fef08aeb;filter:drop-shadow(0 0 10px rgba(250,204,21,.42))}.connection-editor__minimap-node--trace-source{fill:#facc15f5;filter:drop-shadow(0 0 10px rgba(250,204,21,.44))}.connection-editor__minimap-node--trace-reacting{fill:#22c55eeb;filter:drop-shadow(0 0 10px rgba(34,197,94,.42))}.connection-editor__minimap-node--mode-dimmed{opacity:.28;filter:none}.connection-editor__minimap-viewport{fill:#7dd3fc1f;stroke:#7dd3fce6;stroke-width:5;stroke-dasharray:18 10;filter:drop-shadow(0 0 10px rgba(125,211,252,.3));transition:x .12s ease,y .12s ease,width .12s ease,height .12s ease}.connection-editor__minimap--panning .connection-editor__minimap-viewport{fill:#22d3ee2e;stroke:#22d3eef5;stroke-dasharray:none}.connection-editor__node{position:absolute;z-index:10;width:168px;height:168px;transform:translate(-84px,-84px);border:0;padding:0;background:transparent;color:inherit;cursor:pointer;transition:filter .16s ease}.connection-editor__node--dragging{cursor:grabbing;filter:drop-shadow(0 0 22px rgba(34,211,238,.26));z-index:12}.connection-editor__node--connection-focus{filter:drop-shadow(0 0 16px rgba(34,211,238,.2))}.connection-editor__node--compat-target .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e66,0 0 0 18px #22c55e0b,0 0 32px #22c55e29}.connection-editor__node--mode-dimmed{opacity:.42;filter:grayscale(.22) saturate(.56)}.connection-editor__node--quiet{opacity:.58;filter:saturate(.68) brightness(.86)}.connection-editor__node--mode-dimmed .connection-editor__node-ring{animation:none;box-shadow:0 0 0 1px #2dd4bf14,0 0 14px #0ea5e90f}.connection-editor__node--mode-dimmed .connection-editor__node-halo{stroke-opacity:.28}.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-svg{position:absolute;inset:0}.connection-editor__node-ring,.connection-editor__node-core{display:grid;place-items:center;clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}.connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from -28deg,#06b6d4b3 0 28%,#f59e0b9e 28% 48%,#a855f780 48% 68%,#06b6d4a3 68% 100%);box-shadow:0 0 0 1px #2dd4bf2e,0 0 26px #0ea5e929;animation:node-breathe 2.8s ease-in-out infinite}.connection-editor__node-svg{overflow:visible;filter:drop-shadow(0 0 16px rgba(14,165,233,.16))}.connection-editor__node-halo{fill:transparent;stroke:#38bdf838;stroke-width:1;stroke-dasharray:0;pointer-events:none}.connection-editor__node-halo:nth-child(2){stroke:#38bdf824}.connection-editor__node-halo:nth-child(3){stroke:#94a3b81a}.connection-editor__node-segment{fill-opacity:.28;stroke-opacity:.72;stroke-width:1.15;transition:fill-opacity .16s ease,stroke-opacity .16s ease,stroke-width .16s ease;cursor:grab}.connection-editor__node:hover .connection-editor__node-segment,.connection-editor__node--selected .connection-editor__node-segment,.connection-editor__node--connection-focus .connection-editor__node-segment{fill-opacity:.54;stroke-opacity:.95;stroke-width:1.55}.connection-editor__node-segment--connection-focus{fill-opacity:.76;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 8px rgba(34,211,238,.76));animation:segment-focus-sweep 1.45s ease-in-out infinite}.connection-editor__node-segment--source{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 12px rgba(251,146,60,.82))}.connection-editor__node-segment--compatible{fill-opacity:.74;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 10px rgba(34,197,94,.72));animation:snap-pulse 1s ease-in-out infinite}.connection-editor__node-segment--compat-preview{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 13px rgba(245,158,11,.78))}.connection-editor__node-segment--candidate{fill-opacity:.92;stroke-opacity:1;stroke-width:2.8;filter:drop-shadow(0 0 16px rgba(34,197,94,.86))}.connection-editor__node-segment--incompatible{fill-opacity:.12;stroke-opacity:.28;cursor:not-allowed}.connection-editor__node-segment--invalid-drop{fill-opacity:.72;stroke:#fb7185;stroke-opacity:1;stroke-width:3;filter:drop-shadow(0 0 16px rgba(244,63,94,.84));animation:invalid-drop-jolt .36s ease-out}.connection-editor__node-segment--state{fill-opacity:.44;filter:drop-shadow(0 0 8px rgba(180,108,255,.2))}.connection-editor__node-segment--mode-dimmed{fill-opacity:.08;stroke-opacity:.2;stroke-width:.9;filter:none}.connection-editor__node-anchor{opacity:.95;filter:drop-shadow(0 0 6px currentColor)}.connection-editor__node-rotate-handle{cursor:grab;opacity:0;pointer-events:none;transition:opacity .16s ease,filter .16s ease;filter:drop-shadow(0 0 8px rgba(34,211,238,.28))}.connection-editor__node:hover .connection-editor__node-rotate-handle,.connection-editor__node--selected .connection-editor__node-rotate-handle,.connection-editor__node--rotating .connection-editor__node-rotate-handle{opacity:1;pointer-events:auto}.connection-editor__node--rotating .connection-editor__node-rotate-handle{cursor:grabbing;filter:drop-shadow(0 0 12px rgba(34,211,238,.54))}.connection-editor__node-rotate-hit{fill:transparent}.connection-editor__node-rotate-dot{fill:var(--pce-surface-strong);stroke:var(--pce-primary);stroke-opacity:.88;stroke-width:1.4}.connection-editor__node-rotate-arc,.connection-editor__node-rotate-arrow{fill:none;stroke:var(--pce-primary);stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.96;stroke-width:1.2;pointer-events:none}.connection-editor__segment-icon,.connection-editor__segment-label{pointer-events:none;fill:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:800;paint-order:stroke;stroke:#020617c2;stroke-width:3px;stroke-linejoin:round}.connection-editor__segment-icon{font-size:12px;fill:#19c8e8;opacity:1;transition:opacity .14s ease}.connection-editor__segment-icon--output{fill:#ff9f2f}.connection-editor--guided .connection-editor__segment-icon:not(.connection-editor__segment-icon--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-icon{opacity:0}.connection-editor__segment-label{font-size:9.5px;letter-spacing:0;fill:#e2e8f0e0;opacity:1;transition:opacity .14s ease}.connection-editor--guided .connection-editor__segment-label:not(.connection-editor__segment-label--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-label{opacity:0}.connection-editor__node-core{inset:43px;padding:12px;border-radius:999px;clip-path:none;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(circle at center,#111827 0 58%,#060b14);border:1px solid rgba(226,232,240,.1);box-shadow:0 12px 28px #00000073,inset 0 1px #ffffff0d;color:#f8fafc;text-shadow:0 1px 2px rgba(0,0,0,.62)}.connection-editor__node-icon{display:block;max-width:44px;overflow:hidden;color:#f8fafc;font-family:Material Symbols Outlined,Material Icons,sans-serif;font-size:1.22rem;font-weight:400;line-height:1;text-align:center;text-transform:none;letter-spacing:0;white-space:nowrap;filter:drop-shadow(0 0 10px rgba(226,232,240,.18))}.connection-editor__node--state .connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from 14deg,#a855f7c7 0 42%,#7e3af26b 42% 78%,#f59e0b47 78% 100%);box-shadow:0 0 0 1px #a855f738,0 0 30px #a855f733}.connection-editor__node--selected .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15bd,0 0 34px #facc153d}.connection-editor__node--connection-focus .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eead,0 0 38px #22d3ee42;animation:node-focus-breathe 1.7s ease-in-out infinite}.connection-editor__node--trace-source .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 0 18px #facc150f,0 0 54px #facc154d;animation:trace-source-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:before{content:\"\";position:absolute;z-index:0;inset:-44px;border-radius:999px;border:2px solid rgba(250,204,21,.36);background:radial-gradient(circle at center,transparent 0 64%,rgba(250,204,21,.05) 65% 66%,transparent 67%),conic-gradient(from -20deg,#facc1500,#facc1552,#facc1500);box-shadow:0 0 36px #facc151f;opacity:.92;pointer-events:none;animation:trace-source-orbit 2.8s linear infinite}.connection-editor__node--trace-reacting .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e94,0 0 46px #22c55e38;animation:trace-reacting-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:after,.connection-editor__node--trace-reacting:after{position:absolute;z-index:3;inset-inline-start:50%;inset-block-start:-42px;padding:0;border:0;background:transparent;color:#facc15;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.68rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase;transform:translate(-50%);text-shadow:0 0 12px rgba(250,204,21,.52);pointer-events:none}.connection-editor__node--trace-source:after{content:attr(data-trace-label)}.connection-editor__node--trace-reacting:after{content:attr(data-trace-label);color:#86efac;text-shadow:0 0 12px rgba(34,197,94,.44)}.connection-editor__node--trace-source .connection-editor__node-segment--output{fill-opacity:.66;stroke-width:2.2;filter:drop-shadow(0 0 14px rgba(255,159,47,.42))}.connection-editor__node--expanded .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eebd,0 0 34px #22d3ee3d}.connection-editor__node--rotating .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 42px #facc1547;animation:node-focus-breathe 1.1s ease-in-out infinite}.connection-editor__node--rotating .connection-editor__node-segment{fill-opacity:.68;stroke-opacity:1;stroke-width:1.9;cursor:grabbing}.connection-editor__node-title,.connection-editor__node-subtitle{display:block;max-width:92px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.connection-editor__node-title{color:#f8fafc;font-size:.82rem;font-weight:800}.connection-editor__node-subtitle{margin-top:4px;color:#a7b4c8;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__ports{position:absolute;z-index:30;display:grid;gap:6px;width:104px;opacity:0;pointer-events:none;transform:translateY(3px);transition:opacity .16s ease,transform .16s ease}.connection-editor__ports--visible{opacity:1;pointer-events:auto;transform:translateY(0)}.connection-editor__ports--outputs{z-index:42}.connection-editor__ports--inputs{z-index:36}.connection-editor__segment-popover{position:absolute;z-index:80;width:292px;max-height:320px;overflow:auto;display:grid;gap:10px;padding:14px;border-radius:16px;border:1px solid rgba(148,163,184,.18);background:linear-gradient(135deg,#0f172af5,#110c20f0),#090c16eb;box-shadow:0 28px 72px #0000007a,0 0 48px #a855f71a,inset 0 1px #ffffff0d;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__segment-popover-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:2px}.connection-editor__segment-popover-title{color:#94a3b8;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}.connection-editor__segment-popover-hint{margin-top:5px;color:#64748b;font-size:.66rem;font-weight:700}.connection-editor__segment-rotation{flex:0 0 auto;min-width:54px;padding:5px 8px;border-radius:999px;border:1px solid rgba(34,211,238,.28);background:#082f4957;color:#7dd3fc;font-size:.66rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-align:center;box-shadow:inset 0 0 16px #0ea5e914}.connection-editor__segment-row{display:grid;grid-template-columns:28px 72px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:40px;padding:7px;border-radius:12px;border:1px solid rgba(148,163,184,.12);background:linear-gradient(90deg,#0f172ac7,#0f172a75),#0f172a99;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__segment-row--input{border-color:#22d3ee42}.connection-editor__segment-row--output{border-color:#f59e0b47}.connection-editor__segment-row--state{border-color:#a855f74d}.connection-editor__segment-row--source,.connection-editor__segment-row--candidate{transform:translate(2px);box-shadow:0 0 22px #f59e0b24,inset 0 0 20px #f59e0b14}.connection-editor__segment-row--compatible{border-color:#22d3ee6b;box-shadow:inset 0 0 18px #22d3ee14}.connection-editor__segment-row--compat-preview{border-color:#f59e0b94;background:linear-gradient(90deg,#f59e0b1f,#0f172a8a),#0f172ab3;box-shadow:0 0 22px #f59e0b1f,inset 0 0 18px #f59e0b14}.connection-editor__segment-row--invalid-drop{border-color:#fb7185b3;background:linear-gradient(90deg,#f43f5e24,#0f172a94),#0f172ab3;box-shadow:0 0 24px #f43f5e2e,inset 0 0 18px #f43f5e1a;animation:invalid-drop-jolt .36s ease-out}.connection-editor__segment-index{color:#64748b;font-size:.64rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;letter-spacing:.08em}.connection-editor__segment-kind{display:inline-flex;align-items:center;gap:6px;color:#94a3b8;font-size:.62rem;font-weight:800;text-transform:uppercase;min-width:0;white-space:nowrap}.connection-editor__segment-kind-dot{width:7px;height:7px;border-radius:999px;background:#94a3b8;box-shadow:0 0 12px #94a3b847}.connection-editor__segment-row--input .connection-editor__segment-kind-dot{background:#22d3ee;box-shadow:0 0 12px #22d3ee61}.connection-editor__segment-row--output .connection-editor__segment-kind-dot{background:#fb923c;box-shadow:0 0 12px #fb923c66}.connection-editor__segment-row--state .connection-editor__segment-kind-dot{background:#a855f7;box-shadow:0 0 12px #a855f76b}.connection-editor__segment-label{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;color:#e2e8f0;font-size:.74rem;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-badge{flex:0 0 auto;padding:2px 5px;border-radius:999px;border:1px solid rgba(56,189,248,.28);background:#0ea5e91a;color:#bae6fd;font-size:.55rem;font-weight:900;text-transform:uppercase}.connection-editor__segment-path{grid-column:3 / 4;min-width:0;margin-top:-5px;overflow:hidden;color:#93c5fd;font-size:.62rem;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-row--nested{min-height:56px;border-color:#38bdf84d;background:linear-gradient(90deg,#0ea5e91a,#0f172a80),#0f172aa3}.connection-editor__segment-actions{display:inline-flex;gap:4px}.connection-editor__segment-action{width:24px;height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.18);background:#060c16b8;color:#dbeafe;cursor:pointer;font-weight:900;line-height:1}.connection-editor__segment-action:hover{border-color:#22d3ee75;box-shadow:0 0 14px #22d3ee29}.connection-editor__port{min-height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#080d18c2;color:#cbd5e1;font-size:.64rem;font-weight:700;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:crosshair;box-shadow:0 8px 20px #00000038}.connection-editor--guided .connection-editor__ports--visible .connection-editor__port:not(.connection-editor__port--guided-visible){display:none}.connection-editor__port--output{border-color:#f59e0b75;color:#fbbf24}.connection-editor__port--input{border-color:#06b6d475;color:#22d3ee}.connection-editor__port--state{border-color:#a855f785;color:#c084fc}.connection-editor__port--compatible{background:#22c55e29;box-shadow:0 0 0 1px #22c55e61,0 0 18px #22c55e2e;animation:snap-pulse 1s ease-in-out infinite}.connection-editor__port--source{border-color:#fb923cb8;background:#fb923c29;color:#fed7aa;box-shadow:0 0 0 1px #fb923c73,0 0 20px #fb923c2e}.connection-editor__port--candidate{background:#22c55e3d;box-shadow:0 0 0 2px #22c55e94,0 0 24px #22c55e3d}.connection-editor__port--incompatible{opacity:.42;cursor:not-allowed;filter:grayscale(.45)}.connection-editor__port--invalid-drop{opacity:1;border-color:#fb7185c7;color:#fecdd3;background:#f43f5e2e;box-shadow:0 0 0 2px #f43f5e75,0 0 24px #f43f5e38;filter:none;animation:invalid-drop-jolt .36s ease-out}.connection-editor__port--connection-focus{border-color:#facc15ad;color:#fde68a;background:#facc151f;box-shadow:0 0 0 1px #facc156b,0 0 20px #facc152e;animation:port-focus-pulse 1.25s ease-in-out infinite}:host-context(.theme-light) .connection-editor__port{color:var(--pce-fg)}.connection-editor__drag-tip{position:absolute;z-index:6;display:grid;gap:4px;width:min(330px,calc(100% - 28px));padding:10px 12px;border-radius:14px;border:1px solid rgba(125,211,252,.26);background:linear-gradient(135deg,#0ea5e91f,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 28px #0ea5e91a;font-size:.76rem;pointer-events:none;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);animation:tooltip-rise .14s ease-out}.connection-editor__drag-tip--valid{border-color:#22c55e66;background:linear-gradient(135deg,#22c55e29,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 30px #22c55e24}.connection-editor__drag-tip--invalid{z-index:7;border-color:#fb71858a;background:linear-gradient(135deg,#f43f5e2e,#0f172af0),#080d18f5;box-shadow:0 18px 44px #0206176b,0 0 34px #f43f5e29;animation:tooltip-rise .14s ease-out,invalid-drop-jolt .36s ease-out}.connection-editor__invalid-drop-pulse{position:absolute;z-index:6;width:16px;height:16px;border-radius:999px;border:2px solid rgba(251,113,133,.88);background:#f43f5e38;box-shadow:0 0 0 8px #f43f5e1a,0 0 28px #f43f5e3d;pointer-events:none;transform:translate(-50%,-50%);animation:invalid-drop-ping 1.2s ease-out both}.connection-editor__drag-tip span{color:#7dd3fc;text-transform:uppercase;letter-spacing:.12em;font-size:.62rem;font-weight:800}.connection-editor__drag-tip strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.78rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__drag-tip small{color:#94a3b8;font-size:.68rem;font-weight:700}.connection-editor__drag-tip--valid small{color:#86efac}.connection-editor__drag-tip--invalid span,.connection-editor__drag-tip--invalid small{color:#fda4af}.connection-editor__summary{grid-column:1;grid-row:2;align-self:end;justify-self:start;z-index:6;display:flex;flex-wrap:wrap;gap:6px;padding:0 0 12px 12px;pointer-events:none}.connection-editor__side-panel{grid-column:2;grid-row:2 / 3;position:relative;z-index:8;min-width:0;min-height:0;display:grid;align-content:start;gap:14px;overflow:auto;padding-inline-end:4px;scrollbar-color:var(--pce-outline-strong) var(--pce-surface-soft)}.connection-editor__side-panel--contextual .connection-editor__inspector{order:-3}.connection-editor__side-panel--contextual .connection-editor__recommended{order:2}.connection-editor__side-panel--contextual .connection-editor__filters-section{order:3}.connection-editor__side-panel--contextual .connection-editor__recommended,.connection-editor__side-panel--contextual .connection-editor__filters-section{opacity:.82}.connection-editor__metric,.connection-editor__item{border-radius:16px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__metric{min-width:auto;display:inline-flex;align-items:baseline;gap:7px;padding:6px 9px;border-radius:999px;background:color-mix(in srgb,var(--pce-surface-strong) 86%,transparent);box-shadow:0 10px 26px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight)}.connection-editor__metric span{color:var(--pce-muted);font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__metric strong,.connection-editor__details-row strong{color:var(--pce-strong);font-size:.78rem}.connection-editor__filters,.connection-editor__actions,.connection-editor__badges{display:flex;gap:8px;flex-wrap:wrap}.connection-editor__filter,.connection-editor__action{border:1px solid var(--pce-outline-strong);background:var(--pce-surface-soft);color:var(--pce-fg);border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connection-editor__filter--active,.connection-editor__action:hover{border-color:color-mix(in srgb,var(--pce-secondary) 62%,transparent);background:color-mix(in srgb,var(--pce-secondary) 16%,var(--pce-surface-soft));color:var(--pce-strong)}.connection-editor__action--danger{border-color:#f8717161;color:#fecaca}.connection-editor__item{width:100%;text-align:start;padding:12px;display:grid;gap:6px;cursor:pointer;color:inherit}.connection-editor__item--active{border-color:#a855f7b8;background:linear-gradient(90deg,#0ea5e91a,#a855f721)}.connection-editor__item-title{font-weight:800;color:#f8fafc;word-break:break-word}.connection-editor__badge{padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface));color:var(--pce-fg);font-size:.72rem;font-weight:800}.connection-editor__section{min-width:0;padding:14px;border-radius:18px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight),0 18px 50px var(--pce-shadow-soft);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__badge--warning{background:color-mix(in srgb,var(--pce-warning) 14%,var(--pce-surface));color:var(--pce-fg)}.connection-editor__badge--error{background:color-mix(in srgb,var(--pce-error) 14%,var(--pce-surface));color:var(--pce-fg)}.connection-editor__diagnostics{display:grid;gap:8px}.connection-editor__diagnostic{display:grid;gap:4px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.78rem;line-height:1.35}.connection-editor__diagnostic--warning{border-color:#f59e0b47;background:#f59e0b1a}.connection-editor__diagnostic--error{border-color:#ef44445c;background:#ef44441f}.connection-editor__diagnostic-severity{font-size:.68rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#f8fafc}.connection-editor__suggestions{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__suggestion{display:grid;gap:8px;width:100%;padding:12px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 12%,transparent),color-mix(in srgb,var(--pce-primary) 8%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__suggestion:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 46%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 18%,transparent),color-mix(in srgb,var(--pce-primary) 12%,transparent)),var(--pce-surface-strong)}.connection-editor__suggestion-route{display:grid;gap:4px;font-size:.78rem}.connection-editor__suggestion-route strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__suggestion-reason{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__suggestion-diagnostic{padding:10px 12px;border-radius:14px;border:1px solid rgba(245,158,11,.28);background:#f59e0b1a;color:var(--pce-strong);font-size:.78rem;line-height:1.35}.connection-editor__suggestion-outcome{color:var(--pce-strong);font-size:.84rem;line-height:1.3}.connection-editor__suggestion-action{justify-self:start;padding:3px 8px;border-radius:999px;background:#22d3ee24;color:#67e8f9;font-size:.68rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase}:host-context(.theme-light) .connection-editor__suggestion-action{background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:#075f73}.connection-editor__trace{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__trace-summary{color:var(--pce-muted);font-size:.78rem;line-height:1.35}.connection-editor__trace-step{display:grid;grid-template-columns:24px minmax(76px,auto) 1fr;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(34,211,238,.18);background:var(--pce-surface-soft);font-size:.76rem}.connection-editor__trace-step--blocked{border-color:#ef444457;background:#ef44441a}.connection-editor__trace-order{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:999px;background:#22d3ee29;color:#67e8f9;font-weight:900}.connection-editor__trace-phase{color:var(--pce-strong);font-weight:900;text-transform:uppercase;letter-spacing:.06em;font-size:.66rem}.connection-editor__trace-copy{min-width:0;color:var(--pce-fg);word-break:break-word}.connection-editor__transform-steps{display:grid;gap:8px}.connection-editor__transform-step{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(168,85,247,.22);background:var(--pce-surface-soft)}.connection-editor__transform-kind{min-width:0;color:var(--pce-strong);font-weight:900;word-break:break-word}.connection-editor__transform-phase{color:var(--pce-muted);font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.connection-editor__details-row,.connection-editor__details-block{display:grid;gap:6px}.connection-editor__payload-input{width:100%;min-height:128px;box-sizing:border-box;resize:vertical;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 92%,black);color:var(--pce-fg);padding:10px;font:.76rem/1.45 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.connection-editor__surface-action-editor{display:block;max-height:min(58vh,620px);overflow:auto;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 96%,black);padding:10px;margin-bottom:10px}.connection-editor__rule-grid{display:grid;gap:10px}.connection-editor__rule-card{display:grid;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__rule-heading{color:var(--pce-fg);font-size:.72rem;font-weight:900;text-transform:uppercase;letter-spacing:.06em}pre{margin:0;padding:12px;border-radius:12px;background:color-mix(in srgb,var(--pce-surface-strong) 82%,#020617);color:var(--pce-fg);overflow:auto;font-size:.75rem}@keyframes connection-flow{to{stroke-dashoffset:-38}}@keyframes drag-wire-pulse{0%,to{stroke-opacity:.76}50%{stroke-opacity:1}}@keyframes drag-halo-pulse{0%,to{stroke-opacity:.48}50%{stroke-opacity:.82}}@keyframes endpoint-pulse{0%,to{opacity:.78;transform:scale(1)}50%{opacity:1;transform:scale(1.25)}}@keyframes selected-wire-aura{0%,to{stroke-opacity:.46}50%{stroke-opacity:.92}}@keyframes wire-draw-in{0%{stroke-dashoffset:640;opacity:.32}70%{opacity:1}to{stroke-dashoffset:0;opacity:1}}@keyframes new-wire-halo{0%{stroke-opacity:0;stroke-width:30}28%{stroke-opacity:.78}to{stroke-opacity:0;stroke-width:12}}@keyframes new-dock-link-flash{0%{transform:translateY(-2px);box-shadow:0 16px 40px #0206175c,0 0 42px #fb923c47}to{transform:translateY(0)}}@keyframes trace-wire-pulse{0%,to{stroke-opacity:.78}50%{stroke-opacity:1}}@keyframes trace-halo-pulse{0%,to{stroke-opacity:.34}50%{stroke-opacity:.86}}@keyframes tooltip-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes invalid-drop-jolt{0%,to{transform:translate(0)}28%{transform:translate(-3px)}56%{transform:translate(3px)}}@keyframes invalid-drop-ping{0%{opacity:1;transform:translate(-50%,-50%) scale(.72)}72%{opacity:.74;transform:translate(-50%,-50%) scale(1.35)}to{opacity:0;transform:translate(-50%,-50%) scale(1.8)}}@keyframes node-breathe{50%{transform:scale(1.035)}}@keyframes node-focus-breathe{0%,to{transform:scale(1)}50%{transform:scale(1.055)}}@keyframes trace-source-pulse{50%{transform:scale(1.04);box-shadow:0 0 0 3px #facc15db,0 0 0 22px #facc1514,0 0 64px #facc1557}}@keyframes trace-source-orbit{to{transform:rotate(360deg)}}@keyframes trace-reacting-pulse{50%{transform:scale(1.045);box-shadow:0 0 0 3px #22c55ead,0 0 62px #22c55e4d}}@keyframes segment-focus-sweep{0%,to{stroke-opacity:.82}50%{stroke-opacity:1}}@keyframes snap-pulse{50%{filter:brightness(1.16)}}@keyframes port-focus-pulse{50%{transform:translateY(-1px);box-shadow:0 0 0 2px #facc158f,0 0 26px #facc153d}}.connection-editor__link-list{order:-2}.connection-editor__item-title{color:var(--pce-fg);font-weight:650;overflow-wrap:anywhere}.connection-editor__link-list .connection-editor__item{border:0;border-radius:6px;background:transparent;border-bottom:1px solid var(--pce-outline);box-shadow:none;padding:12px 4px;gap:4px}.connection-editor__link-list .connection-editor__item--active{background:var(--pce-surface-strong)}.connection-editor--guided .connection-editor__widget-list,.connection-editor--guided .connection-editor__link-list .connection-editor__item-copy{display:none}.connection-editor__filters-section,.connection-editor__side-panel--contextual .connection-editor__inspector{order:-3}.connection-editor__working-note{order:4}.connection-editor__draft{order:-5}.connection-editor--guided .connection-editor__segment-kind-legend{background:var(--pce-surface-strong);color:var(--pce-fg)}.connection-editor__node-caption{position:absolute;left:50%;top:-16px;transform:translate(-50%,-100%);color:var(--pce-fg);background:var(--pce-surface-base);border:1px solid var(--pce-outline);border-radius:8px;padding:6px 8px;line-height:1.3;font-weight:650;white-space:normal;overflow-wrap:anywhere}.connection-editor__node-core{padding:8px}.connection-editor__node-icon{font-size:30px}.connection-editor__node-subtitle{display:none}.connection-editor__wire:not(.connection-editor__wire--halo){stroke:var(--pce-primary);stroke-opacity:.85;stroke-width:2;vector-effect:non-scaling-stroke;stroke-dasharray:none;animation:none;filter:none}.connection-editor__wire--state:not(.connection-editor__wire--halo){stroke:var(--pce-tertiary)}.connection-editor__wire--state-read:not(.connection-editor__wire--halo){stroke:var(--pce-secondary)}.connection-editor__wire--error:not(.connection-editor__wire--halo){stroke:var(--pce-error)}.connection-editor__wire--active:not(.connection-editor__wire--halo),.connection-editor__wire--trace:not(.connection-editor__wire--halo){stroke-width:3;stroke-opacity:1;stroke-dasharray:12 6;animation:connection-flow 1.8s linear infinite}.connection-editor__wire--mode-dimmed:not(.connection-editor__wire--halo){stroke-opacity:.16}.connection-editor__header{gap:12px}.connection-editor__mode-frame{min-width:0;flex:1 1 300px}.connection-editor__header-actions{flex:0 1 auto}@media(max-width:1200px){.connection-editor__header{flex-wrap:wrap}}@media(prefers-reduced-motion:reduce){.connection-editor__viewport,.connection-editor__node,.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-segment,.connection-editor__dock-link,.connection-editor__port{transition-duration:1ms}.connection-editor__wire,.connection-editor__wire--state,.connection-editor__wire--projection,.connection-editor__wire--state-read,.connection-editor__wire--event-propagation,.connection-editor__wire--halo.connection-editor__wire--active,.connection-editor__wire--trace,.connection-editor__wire--halo.connection-editor__wire--trace,.connection-editor__wire-endpoint,.connection-editor__connection-tooltip,.connection-editor__dock-link--new,.connection-editor__trace-overlay,.connection-editor__trace-overlay-step,.connection-editor__drag-wire,.connection-editor__drag-wire--halo,.connection-editor__drag-endpoint,.connection-editor__drag-tip,.connection-editor__node-ring,.connection-editor__node--connection-focus .connection-editor__node-ring,.connection-editor__node--trace-source .connection-editor__node-ring,.connection-editor__node--trace-source:before,.connection-editor__node--trace-reacting .connection-editor__node-ring,.connection-editor__node--rotating .connection-editor__node-ring,.connection-editor__node-segment--connection-focus,.connection-editor__node-segment--compatible,.connection-editor__node-segment--invalid-drop,.connection-editor__segment-popover,.connection-editor__port--compatible,.connection-editor__port--invalid-drop,.connection-editor__port--connection-focus,.connection-editor__invalid-drop,.connection-editor__invalid-drop-pulse{animation:none}.connection-editor__wire{stroke-dashoffset:0}.connection-editor__wire--new{stroke-dasharray:10 8;stroke-dashoffset:0;opacity:1}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:12;stroke-opacity:.16}.connection-editor__wire-endpoint,.connection-editor__drag-endpoint,.connection-editor__node-ring,.connection-editor__node--trace-source:before{transform:none}.connection-editor__invalid-drop-pulse{opacity:0}}@media(max-width:900px){:host{inset:0}.connection-editor{inset:8px;height:calc(100vh - 16px);padding:12px;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) minmax(76px,112px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) 48px}.connection-editor__header,.connection-editor__stage,.connection-editor__summary,.connection-editor__side-panel,.connection-editor__dock{grid-column:1}.connection-editor__header{align-items:stretch;flex-wrap:wrap;border-radius:18px}.connection-editor__mode-frame{order:3;width:100%;max-width:100%}.connection-editor__close{margin-inline-start:auto}.connection-editor__mode-frame:before,.connection-editor__mode-frame:after{content:\"\";position:absolute;z-index:2;inset-block:4px;width:24px;border-radius:999px;pointer-events:none}.connection-editor__mode-frame:before{inset-inline-start:1px;background:linear-gradient(90deg,#080d18f0,#080d1800)}.connection-editor__mode-frame:after{inset-inline-end:1px;background:linear-gradient(270deg,#080d18f0,#080d1800)}.connection-editor__mode-shell{width:100%;max-width:100%;overflow-x:auto;scroll-padding-inline:28px;-webkit-overflow-scrolling:touch}.connection-editor__subtitle{margin-inline-start:auto}.connection-editor__stage{grid-row:2;min-height:260px}.connection-editor__summary{grid-row:2;max-width:calc(100% - 24px)}.connection-editor__side-panel{grid-row:3;max-height:30vh}.connection-editor__dock{grid-row:4;min-height:0}.connection-editor__connection-tooltip{width:min(620px,calc(100% - 24px));max-height:min(260px,calc(100% - 24px));overflow:auto}.connection-editor__dock-tabs{width:100%;min-width:0;min-height:0;flex-wrap:wrap;align-items:flex-start}.connection-editor__dock-tablist{width:100%;flex-wrap:wrap}.connection-editor__dock-count{flex:1 1 100%;margin-inline-start:0}.connection-editor__dock-body{width:100%;min-width:0;max-height:76px;box-sizing:border-box}.connection-editor__dock-body pre{white-space:pre-wrap;overflow-wrap:anywhere}.connection-editor__dock-link{grid-template-columns:1fr;align-items:start}.connection-editor__dock-link-route{flex-wrap:wrap}.connection-editor__dock-link-badges{justify-content:flex-start}.connection-editor__trace-overlay{inset-inline-start:14px;width:min(420px,calc(100% - 28px));min-width:0;transform:none}.connection-editor__drag-tip{width:min(300px,calc(100% - 28px))}.connection-editor__segment-popover{width:min(280px,calc(100% - 28px));max-height:min(280px,calc(100% - 28px))}.connection-editor__minimap{inset-inline-end:10px;inset-block-end:10px;width:132px;height:94px;padding:16px 8px 8px;border-radius:14px}.connection-editor__minimap:before{inset:20px 8px 8px;background-size:18px 18px}.connection-editor__minimap-title{inset-block-start:6px;inset-inline-start:10px;font-size:.54rem}}@media(max-width:640px){.connection-editor{inset:4px;height:calc(100vh - 8px);padding:8px;gap:8px;grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) minmax(72px,104px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) 46px}.connection-editor__header{gap:8px;padding:10px}.connection-editor__mode-shell{padding:4px;gap:2px}.connection-editor__mode{min-height:28px;gap:4px;padding:0 7px;font-size:.68rem}.connection-editor__mode-glyph{font-size:.64rem}.connection-editor__stage{min-height:240px}.connection-editor__zoom-controls{inset-inline-start:8px;inset-block-start:8px;gap:6px;width:42px}.connection-editor__tool-group,.connection-editor__trace-source{gap:6px;padding:8px;border-radius:12px}.connection-editor__tool-group{grid-template-columns:28px}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:28px}.connection-editor__tool-button{width:28px;height:28px}.connection-editor__arrange-button,.connection-editor__simulate-button{width:30px;min-height:30px}.connection-editor__summary{gap:6px;padding-inline-end:8px}.connection-editor__side-panel{max-height:28vh}.connection-editor__dock{border-radius:16px}.connection-editor__dock-tabs,.connection-editor__dock-tablist{gap:4px}.connection-editor__dock-tab{padding:0 9px}.connection-editor__dock-count{font-size:.62rem}.connection-editor__dock-body{max-height:66px;padding:8px}.connection-editor__minimap{width:116px;height:84px}.connection-editor__segment-row{grid-template-columns:24px minmax(54px,.55fr) minmax(0,1fr) auto}}.connection-editor__ports{width:max-content}.connection-editor__port{font-size:inherit;white-space:normal;overflow:visible;overflow-wrap:anywhere;padding:4px 8px}.connection-editor__header-actions{display:flex;flex-wrap:wrap;gap:8px}.connection-editor__action--primary{background:var(--pce-primary);color:var(--pce-surface-base);font-weight:700}.connection-editor__action:disabled{opacity:.5;cursor:default}.connection-editor__draft{order:-4;padding:16px;border-bottom:1px solid var(--pce-outline)}.connection-editor__draft p,.connection-editor__working-note{font-size:.8rem;line-height:1.55;color:var(--pce-muted)}.connection-editor__working-note{margin:12px 16px}.connection-editor__draft label{display:grid;gap:6px;margin:14px 0;font-size:.82rem}.connection-editor__draft select,.connection-editor__draft input{box-sizing:border-box;width:100%;min-width:0;min-height:40px;padding:8px;color:var(--pce-fg);background:var(--pce-surface-base);border:1px solid var(--pce-outline-strong);border-radius:8px}.connection-editor__draft-review{display:grid;gap:6px;padding:12px 0;font-size:.85rem;overflow-wrap:anywhere}.connection-editor__draft-actions{position:sticky;bottom:0;z-index:4;padding:12px 0;background:var(--pce-surface-base);border-top:1px solid var(--pce-outline)}.connection-editor--draft .connection-editor__filters-section,.connection-editor--draft .connection-editor__link-list{display:none}.connection-editor__draft-status{color:var(--pce-primary)}.connection-editor__advanced{margin:16px 0}.connection-editor__advanced summary{cursor:pointer;font-size:.82rem;padding:10px 0}.connection-editor__node-title{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere;line-height:1.25}.connection-editor--presentation{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr)}.connection-editor--presentation .connection-editor__side-panel,.connection-editor--presentation .connection-editor__summary,.connection-editor--presentation .connection-editor__dock,.connection-editor--presentation .connection-editor__subtitle,.connection-editor--presentation .connection-editor__mode-frame{display:none}.connection-editor--presentation .connection-editor__stage{grid-column:1;grid-row:2}@media(max-width:900px){.connection-editor__header{flex-wrap:wrap}.connection-editor__header-actions{order:2;width:100%}.connection-editor--draft{grid-template-rows:auto minmax(160px,.45fr) minmax(260px,1fr) 46px}.connection-editor--draft .connection-editor__stage{min-height:0}.connection-editor__side-panel{max-height:none}.connection-editor--draft .connection-editor__summary{display:none}}@media(max-width:640px){.connection-editor__eyebrow,.connection-editor__subtitle,.connection-editor__summary,.connection-editor__minimap{display:none}.connection-editor__header{position:relative;padding-right:42px}.connection-editor__close{position:absolute;top:8px;right:8px}.connection-editor__header-actions{flex-wrap:nowrap}.connection-editor__header-actions .connection-editor__action{min-height:36px}.connection-editor__mode-frame{flex-basis:auto}.connection-editor__side-panel{max-height:none}.connection-editor__draft{padding:10px}.connection-editor__stage{overflow:hidden}.connection-editor__connection-tooltip{display:none}.connection-editor__dock{min-width:0}.connection-editor__dock-tablist{min-width:0;overflow-x:auto;max-width:100%}.connection-editor__dock-meta{display:none}}@media(prefers-reduced-motion:reduce){.connection-editor *,.connection-editor *:before,.connection-editor *:after{animation:none!important;transition:none!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: SurfaceOpenActionEditorComponent, selector: "praxis-surface-open-action-editor", inputs: ["value", "hostKind"], outputs: ["valueChange"] }, { kind: "pipe", type: i2$3.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
9283
9989
|
}
|
|
9284
9990
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ConnectionEditorComponent, decorators: [{
|
|
9285
9991
|
type: Component,
|
|
@@ -9292,6 +9998,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9292
9998
|
@if (open()) {
|
|
9293
9999
|
<aside
|
|
9294
10000
|
class="connection-editor"
|
|
10001
|
+
[class.connection-editor--presentation]="presentationMode()"
|
|
10002
|
+
[class.connection-editor--draft]="!!draftBase()"
|
|
9295
10003
|
[class.connection-editor--guided]="visualDensity() === 'guided'"
|
|
9296
10004
|
[class.connection-editor--full]="visualDensity() === 'full'"
|
|
9297
10005
|
[class.connection-editor--dock-collapsed]="dockCollapsed()"
|
|
@@ -9312,7 +10020,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9312
10020
|
@for (mode of flowModes; track mode.id) {
|
|
9313
10021
|
<button
|
|
9314
10022
|
type="button"
|
|
9315
|
-
class="connection-editor__mode"
|
|
10023
|
+
class="connection-editor__mode" [disabled]="!!draftBase()"
|
|
9316
10024
|
role="tab"
|
|
9317
10025
|
[class.connection-editor__mode--active]="activeMode() === mode.id"
|
|
9318
10026
|
[attr.aria-selected]="activeMode() === mode.id"
|
|
@@ -9328,6 +10036,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9328
10036
|
}
|
|
9329
10037
|
</div>
|
|
9330
10038
|
</div>
|
|
10039
|
+
<div class="connection-editor__header-actions">
|
|
10040
|
+
<button type="button" class="connection-editor__action connection-editor__action--primary"
|
|
10041
|
+
data-testid="page-builder-connections-new" [disabled]="!!draftBase() || presentationMode()"
|
|
10042
|
+
(click)="beginNewConnection()">+ {{ tx('connections.draft.new', 'New connection') }}</button>
|
|
10043
|
+
<button type="button" class="connection-editor__action"
|
|
10044
|
+
data-testid="page-builder-connections-presentation" [attr.aria-pressed]="presentationMode()"
|
|
10045
|
+
[disabled]="!!draftBase()" (click)="togglePresentation()">
|
|
10046
|
+
{{ presentationMode() ? tx('connections.draft.backToEdit', 'Back to editing') : tx('connections.draft.present', 'Present diagram') }}
|
|
10047
|
+
</button>
|
|
10048
|
+
</div>
|
|
9331
10049
|
<div class="connection-editor__subtitle">
|
|
9332
10050
|
<button
|
|
9333
10051
|
type="button"
|
|
@@ -9346,7 +10064,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9346
10064
|
class="connection-editor__close"
|
|
9347
10065
|
data-testid="page-builder-connections-close"
|
|
9348
10066
|
[attr.aria-label]="tx('connections.closeAria', 'Close connection editor')"
|
|
9349
|
-
(click)="
|
|
10067
|
+
(click)="closeEditor()"
|
|
9350
10068
|
>
|
|
9351
10069
|
×
|
|
9352
10070
|
</button>
|
|
@@ -9364,6 +10082,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9364
10082
|
<div class="connection-editor__viewport" [style.transform]="viewportTransform()">
|
|
9365
10083
|
<svg class="connection-editor__wires" [attr.viewBox]="canvasViewBox" aria-hidden="true">
|
|
9366
10084
|
<defs>
|
|
10085
|
+
<marker id="connection-direction" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse" markerUnits="userSpaceOnUse">
|
|
10086
|
+
<path d="M 1 1 L 9 5 L 1 9" fill="none" stroke="context-stroke" stroke-width="2" />
|
|
10087
|
+
</marker>
|
|
9367
10088
|
<filter id="connection-glow" x="-20%" y="-20%" width="140%" height="140%">
|
|
9368
10089
|
<feGaussianBlur stdDeviation="3" result="blur" />
|
|
9369
10090
|
<feMerge>
|
|
@@ -9394,11 +10115,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9394
10115
|
[class.connection-editor__wire--trace]="isTracedConnection(connection)"
|
|
9395
10116
|
[class.connection-editor__wire--active]="selectedLinkId() === connection.id"
|
|
9396
10117
|
[class.connection-editor__wire--new]="recentLinkId() === connection.id"
|
|
9397
|
-
[class.connection-editor__wire--mode-dimmed]="isModeDimmedConnection(connection)"
|
|
10118
|
+
[class.connection-editor__wire--mode-dimmed]="isModeDimmedConnection(connection) || (!!selectedLinkId() && selectedLinkId() !== connection.id)"
|
|
9398
10119
|
[attr.d]="wirePath(connection)"
|
|
9399
10120
|
/>
|
|
9400
10121
|
<path
|
|
9401
|
-
class="connection-editor__wire"
|
|
10122
|
+
class="connection-editor__wire" marker-end="url(#connection-direction)"
|
|
9402
10123
|
[class.connection-editor__wire--active]="selectedLinkId() === connection.id"
|
|
9403
10124
|
[class.connection-editor__wire--state]="connection.intent === 'state-write'"
|
|
9404
10125
|
[class.connection-editor__wire--state-read]="connection.intent === 'state-read'"
|
|
@@ -9409,7 +10130,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9409
10130
|
[class.connection-editor__wire--error]="connectionHasErrors(connection)"
|
|
9410
10131
|
[class.connection-editor__wire--trace]="isTracedConnection(connection)"
|
|
9411
10132
|
[class.connection-editor__wire--new]="recentLinkId() === connection.id"
|
|
9412
|
-
[class.connection-editor__wire--mode-dimmed]="isModeDimmedConnection(connection)"
|
|
10133
|
+
[class.connection-editor__wire--mode-dimmed]="isModeDimmedConnection(connection) || (!!selectedLinkId() && selectedLinkId() !== connection.id)"
|
|
9413
10134
|
[attr.d]="wirePath(connection)"
|
|
9414
10135
|
(pointerenter)="previewConnection(connection)"
|
|
9415
10136
|
(pointerleave)="clearPreviewConnection(connection)"
|
|
@@ -9691,9 +10412,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9691
10412
|
</svg>
|
|
9692
10413
|
<span class="connection-editor__node-core">
|
|
9693
10414
|
<span class="connection-editor__node-icon" aria-hidden="true">{{ nodeIcon(node) }}</span>
|
|
9694
|
-
|
|
10415
|
+
|
|
9695
10416
|
<span class="connection-editor__node-subtitle">{{ node.subtitle }}</span>
|
|
9696
10417
|
</span>
|
|
10418
|
+
<span class="connection-editor__node-caption" [style.font-size.px]="13 / viewport().scale"
|
|
10419
|
+
[style.width.px]="nodeCaptionWidth()">{{ node.title }}</span>
|
|
9697
10420
|
</button>
|
|
9698
10421
|
|
|
9699
10422
|
@if (visibleExpandedNodeId() === node.id) {
|
|
@@ -9771,6 +10494,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9771
10494
|
<div
|
|
9772
10495
|
class="connection-editor__ports connection-editor__ports--outputs"
|
|
9773
10496
|
[class.connection-editor__ports--visible]="areNodePortsVisible(node)"
|
|
10497
|
+
[style.font-size.px]="11 / viewport().scale"
|
|
10498
|
+
[style.max-width.px]="230 / viewport().scale"
|
|
9774
10499
|
[style.left.px]="node.x + 132"
|
|
9775
10500
|
[style.top.px]="node.y + 24"
|
|
9776
10501
|
(pointerenter)="hoveredNodeId.set(node.id)"
|
|
@@ -9795,6 +10520,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
9795
10520
|
<div
|
|
9796
10521
|
class="connection-editor__ports connection-editor__ports--inputs"
|
|
9797
10522
|
[class.connection-editor__ports--visible]="areNodePortsVisible(node)"
|
|
10523
|
+
[style.font-size.px]="11 / viewport().scale"
|
|
10524
|
+
[style.max-width.px]="230 / viewport().scale"
|
|
9798
10525
|
[style.left.px]="node.x - 104"
|
|
9799
10526
|
[style.top.px]="node.y + 24"
|
|
9800
10527
|
(pointerenter)="hoveredNodeId.set(node.id)"
|
|
@@ -10052,6 +10779,76 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10052
10779
|
[class.connection-editor__side-panel--contextual]="!!selectedConnection() || !!selectedEditorNode()"
|
|
10053
10780
|
data-testid="page-builder-connections-side-panel"
|
|
10054
10781
|
>
|
|
10782
|
+
@if (draftBase()) {
|
|
10783
|
+
<section class="connection-editor__draft" data-testid="page-builder-connections-draft">
|
|
10784
|
+
<div class="connection-editor__section-title">{{ tx('connections.draft.title', 'Connection draft') }}</div>
|
|
10785
|
+
<p>{{ tx('connections.draft.help', 'Choose the source and destination, then review the connection before applying it.') }}</p>
|
|
10786
|
+
<label>
|
|
10787
|
+
<span>{{ tx('connections.draft.source', '1 · Source / event') }}</span>
|
|
10788
|
+
<select #sourceSelect [value]="draftSourceId()" (change)="changeDraftEndpoint('source', sourceSelect.value)"
|
|
10789
|
+
data-testid="page-builder-connections-draft-source">
|
|
10790
|
+
<option value="">{{ tx('connections.draft.chooseSource', 'Choose a source') }}</option>
|
|
10791
|
+
@for (port of draftSources(); track port.id) { <option [value]="port.id">{{ draftPortLabel(port) }}</option> }
|
|
10792
|
+
</select>
|
|
10793
|
+
</label>
|
|
10794
|
+
<label>
|
|
10795
|
+
<span>{{ tx('connections.draft.target', '2 · Destination / input') }}</span>
|
|
10796
|
+
<select #targetSelect [value]="draftTargetId()" [disabled]="!draftSourceId()"
|
|
10797
|
+
(change)="changeDraftEndpoint('target', targetSelect.value)" data-testid="page-builder-connections-draft-target">
|
|
10798
|
+
<option value="">{{ tx('connections.draft.chooseTarget', 'Choose a destination') }}</option>
|
|
10799
|
+
@for (port of draftTargets(); track port.id) { <option [value]="port.id">{{ draftPortLabel(port) }}</option> }
|
|
10800
|
+
</select>
|
|
10801
|
+
</label>
|
|
10802
|
+
<p>{{ tx('connections.draft.prerequisites', 'Enable the source event in its component settings. For row selection, enable single selection; configure the detail as read-only when needed.') }}</p>
|
|
10803
|
+
@if (selectedConnection(); as connection) {
|
|
10804
|
+
<div class="connection-editor__draft-review">
|
|
10805
|
+
<span>{{ tx('connections.draft.review', 'Review the route') }}</span>
|
|
10806
|
+
<strong>{{ draftEndpointLabel(draftSourceId()) }}</strong>
|
|
10807
|
+
<span aria-hidden="true">↓</span>
|
|
10808
|
+
<strong>{{ draftEndpointLabel(draftTargetId()) }}</strong>
|
|
10809
|
+
</div>
|
|
10810
|
+
@for (step of connection.link.transform?.steps; track step.id ?? $index) {
|
|
10811
|
+
@if (step.kind === 'pick-path') {
|
|
10812
|
+
<label>
|
|
10813
|
+
<span>{{ tx('connections.draft.valuePath', 'Value to deliver · payload path') }}</span>
|
|
10814
|
+
<input #valuePath [value]="step.config?.['path'] ?? ''" (change)="changeDraftPickPath($index, valuePath.value)"
|
|
10815
|
+
data-testid="page-builder-connections-draft-path" />
|
|
10816
|
+
</label>
|
|
10817
|
+
<p>{{ connection.link.transform?.fallbackValue === null && connection.link.policy?.missingValuePolicy !== 'skip' ? tx('connections.draft.nullFallback', 'When the value is absent, deliver null (clear the destination).') : tx('connections.draft.existingFallback', 'Missing values follow the configured transform and delivery policy below.') }}</p>
|
|
10818
|
+
<div class="connection-editor__actions">
|
|
10819
|
+
<button type="button" class="connection-editor__action"
|
|
10820
|
+
[attr.aria-pressed]="connection.link.transform?.fallbackValue === null && connection.link.policy?.missingValuePolicy !== 'skip'"
|
|
10821
|
+
(click)="setDraftMissingValue('use-default')">{{ tx('connections.draft.clearMissing', 'Clear when absent') }}</button>
|
|
10822
|
+
<button type="button" class="connection-editor__action" [attr.aria-pressed]="connection.link.policy?.missingValuePolicy === 'skip'"
|
|
10823
|
+
(click)="setDraftMissingValue('skip')">{{ tx('connections.draft.keepMissing', 'Keep destination when absent') }}</button>
|
|
10824
|
+
</div>
|
|
10825
|
+
}
|
|
10826
|
+
}
|
|
10827
|
+
@if (!connection.link.transform?.steps?.length) {
|
|
10828
|
+
<p>{{ tx('connections.draft.wholePayload', 'The source value is delivered without a transformation. Use the advanced settings to project a field.') }}</p>
|
|
10829
|
+
<button type="button" class="connection-editor__action" (click)="projectDraftValue()">{{ tx('connections.draft.extract', 'Extract a field') }}</button>
|
|
10830
|
+
}
|
|
10831
|
+
}
|
|
10832
|
+
@for (diagnostic of draftDiagnostics(); track diagnostic.id) {
|
|
10833
|
+
<p class="connection-editor__diagnostic" [class.connection-editor__diagnostic--error]="diagnostic.severity === 'error' || diagnostic.severity === 'fatal'"
|
|
10834
|
+
role="status">{{ diagnostic.message }}</p>
|
|
10835
|
+
}
|
|
10836
|
+
@if (draftDuplicate()) { <p role="alert">{{ tx('connections.draft.duplicate', 'An identical connection already exists. Edit the existing connection or change this draft.') }}</p> }
|
|
10837
|
+
@if (draftConflict()) { <p role="alert">{{ tx('connections.draft.conflict', 'The page changed during editing. Cancel this draft and reopen the connection to use the latest version.') }}</p> }
|
|
10838
|
+
<p class="connection-editor__draft-status" role="status">{{ tx('connections.draft.pending', 'Draft · not yet applied to the page') }}</p>
|
|
10839
|
+
<div class="connection-editor__actions connection-editor__draft-actions">
|
|
10840
|
+
<button type="button" class="connection-editor__action connection-editor__action--primary"
|
|
10841
|
+
data-testid="page-builder-connections-draft-apply" [disabled]="!canApplyDraft()" (click)="applyDraft()">
|
|
10842
|
+
{{ tx('connections.draft.apply', 'Apply connection') }}
|
|
10843
|
+
</button>
|
|
10844
|
+
<button type="button" class="connection-editor__action" data-testid="page-builder-connections-draft-cancel"
|
|
10845
|
+
(click)="cancelDraft()">{{ tx('connections.draft.cancel', 'Cancel') }}</button>
|
|
10846
|
+
</div>
|
|
10847
|
+
</section>
|
|
10848
|
+
} @else {
|
|
10849
|
+
<p class="connection-editor__working-note" role="status">{{ tx('connections.draft.pageSave', 'Connections apply to the page in the builder. Save the page to persist your changes.') }}</p>
|
|
10850
|
+
}
|
|
10851
|
+
@if (visualDensity() === 'full' && !draftBase()) {
|
|
10055
10852
|
@if (recommendedMasterDetailSuggestion(); as suggestion) {
|
|
10056
10853
|
<section
|
|
10057
10854
|
class="connection-editor__section connection-editor__recommended"
|
|
@@ -10072,6 +10869,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10072
10869
|
</button>
|
|
10073
10870
|
</section>
|
|
10074
10871
|
}
|
|
10872
|
+
}
|
|
10075
10873
|
<section class="connection-editor__section connection-editor__filters-section">
|
|
10076
10874
|
<div class="connection-editor__section-title">{{ tx('connections.filters.title', 'Filters') }}</div>
|
|
10077
10875
|
<div class="connection-editor__filters">
|
|
@@ -10154,6 +10952,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10154
10952
|
<pre>{{ connection.link.to | json }}</pre>
|
|
10155
10953
|
</div>
|
|
10156
10954
|
</details>
|
|
10955
|
+
@if (!draftBase()) {
|
|
10956
|
+
<button type="button" class="connection-editor__action connection-editor__action--primary"
|
|
10957
|
+
data-testid="page-builder-connections-edit" (click)="beginEditConnection(connection.id)">
|
|
10958
|
+
{{ tx('connections.draft.edit', 'Edit connection') }}
|
|
10959
|
+
</button>
|
|
10960
|
+
}
|
|
10961
|
+
<details class="connection-editor__advanced" [open]="!!draftBase()">
|
|
10962
|
+
<summary>{{ tx('connections.draft.advanced', 'Transformation, conditions and delivery') }}</summary>
|
|
10157
10963
|
@if (connection.link.to.kind === 'global-action') {
|
|
10158
10964
|
<div class="connection-editor__details-block" data-testid="page-builder-connections-global-action-payload-editor">
|
|
10159
10965
|
<div class="connection-editor__details-label">{{ tx('connections.globalAction.payloadTitle', 'Action payload') }}</div>
|
|
@@ -10340,6 +11146,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10340
11146
|
}
|
|
10341
11147
|
</div>
|
|
10342
11148
|
</div>
|
|
11149
|
+
</details>
|
|
10343
11150
|
@if (connection.diagnostics.length) {
|
|
10344
11151
|
<div class="connection-editor__details-block" data-testid="page-builder-connections-inspector-diagnostics">
|
|
10345
11152
|
<div class="connection-editor__details-label">{{ tx('connections.validation.title', 'Validation') }}</div>
|
|
@@ -10381,7 +11188,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10381
11188
|
<button
|
|
10382
11189
|
type="button"
|
|
10383
11190
|
class="connection-editor__action connection-editor__action--danger"
|
|
10384
|
-
data-testid="page-builder-connections-inspector-remove-link"
|
|
11191
|
+
data-testid="page-builder-connections-inspector-remove-link" [disabled]="!!draftBase()"
|
|
10385
11192
|
(click)="removeLink(connection.id)"
|
|
10386
11193
|
>
|
|
10387
11194
|
{{ tx('connections.editor.removeLink', 'Remove connection') }}
|
|
@@ -10456,6 +11263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10456
11263
|
</div>
|
|
10457
11264
|
</div>
|
|
10458
11265
|
}
|
|
11266
|
+
@if (visualDensity() === 'full' && !draftBase()) {
|
|
10459
11267
|
@if (smartSuggestions().length) {
|
|
10460
11268
|
<div class="connection-editor__suggestions" data-testid="page-builder-connections-suggestions">
|
|
10461
11269
|
<div class="connection-editor__section-title">{{ tx('connections.suggestions.title', 'Smart suggestions') }}</div>
|
|
@@ -10503,6 +11311,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10503
11311
|
</div>
|
|
10504
11312
|
</div>
|
|
10505
11313
|
}
|
|
11314
|
+
}
|
|
10506
11315
|
@if (traceEnabled()) {
|
|
10507
11316
|
<div class="connection-editor__trace" data-testid="page-builder-connections-trace">
|
|
10508
11317
|
<div class="connection-editor__section-title">{{ tx('connections.trace.title', 'Simulation trace') }}</div>
|
|
@@ -10525,7 +11334,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10525
11334
|
}
|
|
10526
11335
|
</section>
|
|
10527
11336
|
|
|
10528
|
-
<section class="connection-editor__section">
|
|
11337
|
+
<section class="connection-editor__section connection-editor__widget-list">
|
|
10529
11338
|
<div class="connection-editor__section-title">{{ tx('connections.widgets.title', 'Widgets') }}</div>
|
|
10530
11339
|
@for (node of model().nodes; track node.widgetId) {
|
|
10531
11340
|
<button
|
|
@@ -10560,7 +11369,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10560
11369
|
</section>
|
|
10561
11370
|
}
|
|
10562
11371
|
|
|
10563
|
-
<section class="connection-editor__section">
|
|
11372
|
+
<section class="connection-editor__section connection-editor__link-list">
|
|
10564
11373
|
<div class="connection-editor__section-title">{{ tx('connections.links.title', 'Links') }}</div>
|
|
10565
11374
|
@for (edge of visibleEdges(); track edge.id) {
|
|
10566
11375
|
<button
|
|
@@ -10570,8 +11379,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10570
11379
|
[class.connection-editor__item--active]="selectedLinkId() === edge.id"
|
|
10571
11380
|
(click)="selectLink(edge)"
|
|
10572
11381
|
>
|
|
10573
|
-
<div class="connection-editor__item-title">{{ edge
|
|
10574
|
-
<div class="connection-editor__item-copy">{{
|
|
11382
|
+
<div class="connection-editor__item-title">{{ edgeRouteTitle(edge) }}</div>
|
|
11383
|
+
<div class="connection-editor__item-copy">{{ edge.id }}</div>
|
|
10575
11384
|
<div class="connection-editor__badges">
|
|
10576
11385
|
@if (edge.hasCondition) {
|
|
10577
11386
|
<span class="connection-editor__badge">{{ tx('connections.badges.condition', 'Condition') }}</span>
|
|
@@ -10811,9 +11620,177 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
10811
11620
|
</section>
|
|
10812
11621
|
</aside>
|
|
10813
11622
|
}
|
|
10814
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{position:fixed;inset:0;z-index:1000;pointer-events:none}.connection-editor{--pce-fg: var(--md-sys-color-on-surface, #dce6f4);--pce-strong: var(--md-sys-color-on-surface, #f8fafc);--pce-muted: var(--md-sys-color-on-surface-variant, #94a3b8);--pce-primary: var(--md-sys-color-primary, #19c8e8);--pce-secondary: var(--md-sys-color-secondary, #b46cff);--pce-tertiary: var(--md-sys-color-tertiary, #ff9f2f);--pce-success: var(--md-sys-color-tertiary, #10b981);--pce-warning: var(--md-sys-color-error, #ff9f2f);--pce-error: var(--md-sys-color-error, #ef4444);--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #07111f) 80%, #020617);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #08101d) 78%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #0f172a) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #080d18) 64%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #899ab7) 46%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #94a3b8) 58%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #7d8fa9) 24%, transparent);--pce-glass-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, #ffffff) 8%, transparent);--pce-shadow: color-mix(in srgb, #000 56%, transparent);--pce-shadow-soft: color-mix(in srgb, #000 30%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #040a13) 42%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high, #050912) 94%, transparent);position:absolute;inset:12px;height:calc(100vh - 24px);box-sizing:border-box;overflow:hidden;padding:16px;border-radius:18px;color:var(--pce-fg);background:radial-gradient(circle at 72% 20%,color-mix(in srgb,var(--pce-secondary) 16%,transparent),transparent 28%),radial-gradient(circle at 26% 74%,color-mix(in srgb,var(--pce-primary) 10%,transparent),transparent 34%),radial-gradient(circle at 48% 52%,color-mix(in srgb,var(--pce-tertiary) 5%,transparent),transparent 35%),linear-gradient(var(--pce-grid) 1px,transparent 1px),linear-gradient(90deg,var(--pce-grid) 1px,transparent 1px),var(--pce-surface-base);background-size:auto,auto,auto,38px 38px,38px 38px,auto;border:1px solid var(--pce-outline);box-shadow:0 28px 90px var(--pce-shadow);pointer-events:auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);grid-template-rows:auto minmax(0,1fr) minmax(44px,118px);gap:14px}:host-context(.theme-light) .connection-editor{--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 94%, var(--md-sys-color-primary, #2563eb) 6%);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 82%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #eef2ff) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #f8fafc) 70%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 68%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #64748b) 62%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 34%, transparent);--pce-glass-highlight: color-mix(in srgb, #fff 64%, transparent);--pce-shadow: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 22%, transparent);--pce-shadow-soft: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 14%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #ffffff) 58%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 92%, transparent)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(0,1fr) 48px}.connection-editor__header{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:42px;padding:8px 14px;border-radius:999px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__mode-frame{position:relative;min-width:0;flex:1 1 auto;display:flex;justify-content:center}.connection-editor__close{width:32px;height:32px;flex:0 0 auto;display:inline-grid;place-items:center;border:1px solid var(--pce-outline);border-radius:999px;color:var(--pce-text);background:var(--pce-surface-strong);box-shadow:inset 0 1px var(--pce-glass-highlight);cursor:pointer;font:inherit;font-size:1.2rem;line-height:1}.connection-editor__close:hover,.connection-editor__close:focus-visible{border-color:var(--pce-outline-strong);background:color-mix(in srgb,var(--pce-accent) 16%,var(--pce-surface-strong));outline:none}.connection-editor__mode-shell{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:4px;border-radius:999px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:inset 0 1px var(--pce-glass-highlight),0 10px 26px var(--pce-shadow-soft);scrollbar-width:none}.connection-editor__mode-shell::-webkit-scrollbar{display:none}.connection-editor__mode{min-height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 12px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.76rem;font-weight:800;white-space:nowrap;transition:background .16s ease,border-color .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__mode:hover,.connection-editor__mode--active{color:var(--pce-strong);border-color:color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-strong) 82%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 12%,transparent)}.connection-editor__mode-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__mode--active .connection-editor__mode-glyph{color:var(--pce-primary)}.connection-editor__mode-dot{width:6px;height:6px;border-radius:999px;background:var(--pce-success);box-shadow:0 0 12px color-mix(in srgb,var(--pce-success) 70%,transparent)}.connection-editor__status-pill{display:inline-flex;align-items:center;gap:8px;min-height:24px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 36%,transparent);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.72rem;font-weight:800;white-space:nowrap}.connection-editor__status-pill--button{cursor:pointer;transition:border-color .16s ease,background .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__status-pill--button:hover,.connection-editor__status-pill--button:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 62%,transparent);background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 14%,transparent);outline:none}.connection-editor__status-pill span{width:6px;height:6px;border-radius:999px;background:var(--pce-primary);box-shadow:0 0 12px color-mix(in srgb,var(--pce-primary) 70%,transparent)}.connection-editor__section{display:grid;gap:10px}.connection-editor__dock{grid-column:1 / -1;grid-row:3;position:relative;z-index:4;min-height:0;display:grid;border-radius:14px;border:1px solid var(--pce-outline);background:radial-gradient(circle at 16% 0%,color-mix(in srgb,var(--pce-primary) 22%,transparent),transparent 34%),radial-gradient(circle at 78% 0%,color-mix(in srgb,var(--pce-secondary) 25%,transparent),transparent 38%),linear-gradient(90deg,var(--pce-dock-bg),var(--pce-surface-strong) 46%,color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-dock-bg))),var(--pce-dock-bg);box-shadow:0 18px 58px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__dock--collapsed .connection-editor__dock-tabs{border-block-end:0}.connection-editor__dock-tabs{display:flex;align-items:center;gap:10px;min-height:52px;padding:9px 14px;border-block-end:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-glass-highlight),transparent),color-mix(in srgb,var(--pce-surface-soft) 34%,transparent)}.connection-editor__dock-tablist{display:flex;align-items:center;gap:10px;min-width:0}.connection-editor__dock-tab,.connection-editor__dock-toggle{min-height:30px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.72rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-tab{display:inline-flex;align-items:center;gap:8px;padding:0 13px;white-space:nowrap}.connection-editor__dock-tab-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.8rem;letter-spacing:0;text-transform:none}.connection-editor__dock-tab--active{color:var(--pce-strong);border-color:var(--pce-outline-strong);background:linear-gradient(180deg,color-mix(in srgb,var(--pce-strong) 14%,transparent),color-mix(in srgb,var(--pce-strong) 6%,transparent));box-shadow:0 0 0 1px color-mix(in srgb,var(--pce-shadow) 72%,transparent),0 0 22px color-mix(in srgb,var(--pce-strong) 8%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__dock-tab--active .connection-editor__dock-tab-glyph{color:var(--pce-strong)}.connection-editor__dock-count{margin-inline-start:auto;color:color-mix(in srgb,var(--pce-muted) 62%,transparent);font-size:.7rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-toggle{width:32px;padding:0;border-color:var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.88rem;letter-spacing:0}.connection-editor__dock-body{max-height:154px;overflow:auto;padding:12px 12px 14px;border-block-start:1px solid var(--pce-outline);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 9%,transparent),color-mix(in srgb,var(--pce-secondary) 10%,transparent) 62%,color-mix(in srgb,var(--pce-surface-strong) 18%,transparent)),color-mix(in srgb,var(--pce-surface-soft) 30%,transparent)}.connection-editor__dock-body pre{max-height:60px}.connection-editor__dock-links{display:grid;gap:8px}.connection-editor__dock-link-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;padding:7px 10px;border-radius:10px;border:1px solid var(--pce-outline);background:linear-gradient(90deg,var(--pce-surface-soft),color-mix(in srgb,var(--pce-secondary) 10%,var(--pce-surface-soft)) 72%,var(--pce-surface-soft)),var(--pce-surface-soft);color:var(--pce-fg);transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-link{display:grid;grid-template-columns:minmax(116px,.52fr) minmax(300px,1.72fr) minmax(160px,.9fr) auto;align-items:center;gap:12px;width:100%;min-height:42px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;text-align:start}.connection-editor__dock-link-row:hover,.connection-editor__dock-link--active{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 13%,transparent),color-mix(in srgb,var(--pce-secondary) 16%,transparent),var(--pce-surface-strong)),var(--pce-surface-strong);box-shadow:0 12px 32px var(--pce-shadow-soft),inset 0 0 18px color-mix(in srgb,var(--pce-primary) 6%,transparent)}.connection-editor__dock-link--active{border-color:#facc1575;box-shadow:0 12px 32px var(--pce-shadow-soft),0 0 24px #facc151f}.connection-editor__dock-link--new{border-color:#fb923ca3;background:linear-gradient(90deg,#fb923c2e,#a855f729,#0ea5e91f),#0f172ac2;box-shadow:0 12px 34px #02061752,0 0 30px #fb923c2e;animation:new-dock-link-flash 1.35s ease-out forwards}.connection-editor__dock-link--error{border-color:#ef444461}.connection-editor__dock-jump{min-width:62px;min-height:30px;padding:0 10px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 54%,transparent);color:var(--pce-primary);cursor:pointer;font-size:.66rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__dock-jump:hover,.connection-editor__dock-jump:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 56%,transparent);background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 18%,transparent);outline:none}.connection-editor__dock-link-kind{display:inline-flex;align-items:center;gap:7px;min-width:0;color:var(--pce-muted);font-size:.66rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-link-kind span{width:8px;height:8px;border-radius:999px;background:#b46cff;box-shadow:0 0 14px #b46cff7a}.connection-editor__dock-link--state .connection-editor__dock-link-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2f94}.connection-editor__dock-link--state-read .connection-editor__dock-link-kind span{background:#8b7dff;box-shadow:0 0 13px #8b7dff75}.connection-editor__dock-link--projection .connection-editor__dock-link-kind span{background:#19c8e8;box-shadow:0 0 10px #19c8e857}.connection-editor__dock-link--event-propagation .connection-editor__dock-link-kind span{background:#ffb454;box-shadow:0 0 15px #ffb45485}.connection-editor__dock-link--policy .connection-editor__dock-link-kind span{outline:1px solid rgba(34,197,94,.76);outline-offset:2px;box-shadow:0 0 16px #22c55e61}.connection-editor__dock-link--policy:not(.connection-editor__dock-link--state,.connection-editor__dock-link--state-read,.connection-editor__dock-link--projection,.connection-editor__dock-link--event-propagation) .connection-editor__dock-link-kind span{background:#22c55e}.connection-editor__dock-link-route{display:inline-flex;align-items:center;gap:8px;min-width:0}.connection-editor__dock-link-chip{min-width:0;overflow:hidden;padding:4px 8px;border-radius:999px;border:1px solid var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-soft) 72%,transparent);color:var(--pce-fg);font-size:.72rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-chip--from{border-color:#ff9f2f66;color:#ffbd62}.connection-editor__dock-link-chip--to{border-color:#19c8e83d;color:#7dddeb}:host-context(.theme-light) .connection-editor__dock-link-chip--from{border-color:color-mix(in srgb,var(--pce-tertiary) 46%,transparent);color:#8a4600}:host-context(.theme-light) .connection-editor__dock-link-chip--to{border-color:color-mix(in srgb,var(--pce-primary) 34%,transparent);color:#075f73}.connection-editor__dock-link-arrow{flex:0 0 auto;color:var(--pce-muted);font-weight:900}.connection-editor__dock-link-id{min-width:0;overflow:hidden;color:var(--pce-muted);font-size:.66rem;font-weight:800;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-badges{display:inline-flex;justify-content:flex-end;gap:5px;min-width:70px}.connection-editor__dock-link-badges span{padding:3px 7px;border-radius:999px;background:#a855f724;color:#d8b4fe;font-size:.62rem;font-weight:900;text-transform:uppercase;white-space:nowrap}:host-context(.theme-light) .connection-editor__dock-link-badges span{background:color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-surface-soft));color:#6d2a9f}.connection-editor__dock-empty{padding:12px;border-radius:12px;border:1px dashed var(--pce-outline);color:var(--pce-muted);font-size:.76rem;font-weight:700}.connection-editor__inspector{border-color:color-mix(in srgb,var(--pce-primary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 10%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface)}.connection-editor__eyebrow,.connection-editor__section-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--pce-muted);font-weight:700}.connection-editor__title{font-size:1.02rem;font-weight:800}.connection-editor__subtitle,.connection-editor__item-copy,.connection-editor__item-meta,.connection-editor__details-row span,.connection-editor__details-label,.connection-editor__empty{color:var(--pce-muted);font-size:.84rem}.connection-editor__inspector-heading{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--pce-surface-soft);border:1px solid var(--pce-outline)}.connection-editor__inspector-heading strong{color:var(--pce-strong);font-size:.96rem;overflow-wrap:anywhere}.connection-editor__inspector-heading span{color:var(--pce-primary);font-size:.76rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}.connection-editor__human-summary{display:grid;gap:6px;padding:12px;border-radius:14px;border:1px solid color-mix(in srgb,var(--pce-primary) 24%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface-soft);color:var(--pce-fg);line-height:1.35}.connection-editor__nested-summary{display:grid;gap:6px;padding:10px;border-radius:12px;border:1px solid color-mix(in srgb,var(--pce-primary) 22%,transparent);background:color-mix(in srgb,var(--pce-primary) 8%,var(--pce-surface-soft))}.connection-editor__nested-summary strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__nested-summary span:last-child{color:var(--pce-primary);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.72rem;overflow-wrap:anywhere}.connection-editor__recommended{border-color:color-mix(in srgb,var(--pce-secondary) 32%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 14%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface)}.connection-editor__recommended-card{display:grid;gap:8px;width:100%;padding:13px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 36%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 16%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__recommended-card:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 52%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 22%,transparent),color-mix(in srgb,var(--pce-primary) 14%,transparent)),var(--pce-surface-strong)}.connection-editor__recommended-card strong{color:var(--pce-strong);font-size:.92rem;line-height:1.28}.connection-editor__recommended-card span:not(.connection-editor__human-summary-label):not(.connection-editor__suggestion-action),.connection-editor__recommended-card small{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__success{display:grid;gap:4px;padding:10px 12px;border-radius:14px;border:1px solid rgba(34,197,94,.34);background:#22c55e1f;color:var(--pce-fg);line-height:1.35}.connection-editor__success strong{color:#bbf7d0;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__success span{color:var(--pce-strong);font-size:.82rem}.connection-editor__human-summary-label,.connection-editor__suggestion-intent{justify-self:start;padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:#bae6fd;font-size:.66rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__human-summary strong{color:var(--pce-strong);font-size:.88rem}.connection-editor__human-summary span:last-child,.connection-editor__suggestion-preview{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__technical-details{display:grid;gap:10px;padding:10px 12px;border-radius:14px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__technical-details summary{cursor:pointer;color:var(--pce-muted);font-size:.78rem;font-weight:800}.connection-editor__technical-details[open] summary{margin-bottom:10px;color:var(--pce-strong)}.connection-editor__inspector-ports{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__inspector-port{max-width:100%;padding:4px 8px;border-radius:999px;border:1px solid rgba(148,163,184,.16);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-editor__inspector-port--input{border-color:#22d3ee57;color:#67e8f9}.connection-editor__inspector-port--output{border-color:#f59e0b57;color:#fbbf24}.connection-editor__inspector-port--state{border-color:#a855f761;color:#d8b4fe}.connection-editor__segment-kind-legend{display:grid;gap:10px;padding:12px;border-radius:16px;border:1px solid rgba(148,163,184,.14);background:linear-gradient(135deg,#0f172aa8,#080d1885),#02061757}.connection-editor__segment-kind-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.connection-editor__segment-kind-pill{min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:900;overflow:hidden;white-space:nowrap}.connection-editor__segment-kind-pill span{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:currentColor;box-shadow:0 0 12px currentColor}.connection-editor__segment-kind-pill--input{border-color:#19c8e83d;color:#7dddeb}.connection-editor__segment-kind-pill--output{border-color:#ff9f2f61;color:#ffbd62}.connection-editor__segment-kind-pill--state{border-color:#b46cff61;color:#d9b8ff}:host-context(.theme-light) .connection-editor__segment-kind-pill{border-color:var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-strong) 88%,transparent)}:host-context(.theme-light) .connection-editor__segment-kind-pill--input{color:#075f73}:host-context(.theme-light) .connection-editor__segment-kind-pill--output{color:#8a4600}:host-context(.theme-light) .connection-editor__segment-kind-pill--state{color:#6d2a9f}.connection-editor__stage{grid-column:1;grid-row:2;position:relative;min-height:0;height:100%;overflow:visible;border-radius:16px;border:1px solid var(--pce-outline);background:radial-gradient(circle at center,color-mix(in srgb,var(--pce-secondary) 7%,transparent),transparent 38%),radial-gradient(circle,var(--pce-grid) 1px,transparent 1.5px),var(--pce-stage-bg);background-size:auto,31px 31px,auto;box-shadow:inset 0 0 0 1px var(--pce-glass-highlight);cursor:grab;touch-action:none}.connection-editor__stage--panning,.connection-editor__stage:active{cursor:grabbing}.connection-editor__stage--dragging{cursor:crosshair}.connection-editor__stage--rotating{cursor:grabbing}.connection-editor__viewport{position:absolute;inset-block-start:0;inset-inline-start:0;width:900px;height:540px;overflow:visible;transform-origin:0 0;transition:transform .14s ease}.connection-editor__wires{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.connection-editor__wire,.connection-editor__wire-hit{fill:none;stroke-linecap:round}.connection-editor__wire{stroke:#b46cff;stroke-width:1.45;stroke-opacity:.48;pointer-events:none;filter:url(#connection-glow);stroke-dasharray:10 8;animation:connection-flow 1.65s linear infinite}.connection-editor__wire-hit{stroke:transparent;stroke-width:18;cursor:pointer;pointer-events:stroke}.connection-editor__wire-hit--active{stroke-width:28}.connection-editor__wire--halo{stroke:#b46cff1f;stroke-width:7;stroke-dasharray:none;animation:none}.connection-editor__wire--state{stroke:#ff9f2f;stroke-width:2.25;stroke-dasharray:8 7;animation:connection-flow .92s linear infinite}.connection-editor__wire--state.connection-editor__wire--halo{stroke:#ff9f2f29;stroke-width:11}.connection-editor__wire--projection{stroke:#15b8d8;stroke-width:1.75;stroke-dasharray:20 8;animation:connection-flow 1.9s linear infinite}.connection-editor__wire--projection.connection-editor__wire--halo{stroke:#15b8d81a;stroke-width:7}.connection-editor__wire--state-read{stroke:#8b7dff;stroke-width:1.65;stroke-dasharray:3 11;animation:connection-flow 2.25s linear infinite reverse}.connection-editor__wire--state-read.connection-editor__wire--halo{stroke:#8b7dff21;stroke-width:8}.connection-editor__wire--event-propagation{stroke:#ffb454;stroke-width:2.05;stroke-dasharray:5 7;animation:connection-flow .78s linear infinite}.connection-editor__wire--event-propagation.connection-editor__wire--halo{stroke:#ffb4542e;stroke-width:10}.connection-editor__wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.2)) url(#connection-glow)}.connection-editor__wire--policy.connection-editor__wire--halo{stroke:#22c55e1f;stroke-width:13}.connection-editor__wire--warning{stroke:#ff9f2f}.connection-editor__wire--warning.connection-editor__wire--halo{stroke:#ff9f2f2e}.connection-editor__wire--error{stroke:#ef4444}.connection-editor__wire--error.connection-editor__wire--halo{stroke:#ef44442e}.connection-editor__wire--active{stroke:#d9b8ff;stroke-width:3;stroke-opacity:1;stroke-dasharray:5 7;animation-duration:.58s}.connection-editor__wire--halo.connection-editor__wire--active{stroke-width:16;stroke-opacity:.8;animation:selected-wire-aura 1.35s ease-in-out infinite}.connection-editor__wire--new{stroke-width:3.4;stroke-opacity:1;stroke-dasharray:640;stroke-dashoffset:640;animation:wire-draw-in .62s cubic-bezier(.16,1,.3,1) forwards,connection-flow 1.05s linear .62s infinite}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:22;stroke-opacity:0;animation:new-wire-halo 1.45s ease-out forwards}.connection-editor__wire--trace{stroke:#9b5cff;stroke-width:3.2;stroke-opacity:1;stroke-dasharray:7 6;animation:connection-flow .72s linear infinite,trace-wire-pulse 1.18s ease-in-out infinite}.connection-editor__wire--halo.connection-editor__wire--trace{stroke:#9b5cff57;stroke-width:18;stroke-opacity:.86;animation:trace-halo-pulse 1.18s ease-in-out infinite}.connection-editor__wire--mode-dimmed{stroke-opacity:.14;stroke-width:1.05;filter:none;animation-duration:2.6s}.connection-editor--guided .connection-editor__wire:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.34;filter:none;animation:none}.connection-editor--guided .connection-editor__wire--halo:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.08;animation:none}.connection-editor__wire--halo.connection-editor__wire--mode-dimmed{stroke-opacity:.05;stroke-width:5;animation:none}.connection-editor__wire-hit--mode-dimmed{stroke-width:12}.connection-editor__wire-endpoint{fill:#f8fafc;stroke:#0f172ae6;stroke-width:1.5;filter:drop-shadow(0 0 8px rgba(216,180,254,.8));pointer-events:none;animation:endpoint-pulse 1.2s ease-in-out infinite}.connection-editor__wire-endpoint--source{fill:#ff9f2f}.connection-editor__wire-endpoint--target{fill:#19c8e8}.connection-editor__connection-tooltip{position:absolute;z-index:6;width:min(312px,calc(100% - 24px));display:grid;gap:8px;padding:12px 14px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(135deg,var(--pce-surface-strong),var(--pce-surface)),var(--pce-surface-strong);box-shadow:0 18px 44px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);color:var(--pce-fg);pointer-events:none;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .14s ease-out}.connection-editor__connection-tooltip-callout{position:absolute;inset-block-start:100%;inset-inline-start:var(--connection-tooltip-callout-x, 42px);width:2px;height:28px;border-radius:999px;background:linear-gradient(180deg,#e2e8f0bd,#19c8e800);box-shadow:0 0 12px #19c8e852;transform:translate(-1px);pointer-events:none}.connection-editor__connection-tooltip-callout:before,.connection-editor__connection-tooltip-callout:after{content:\"\";position:absolute;border-radius:999px;pointer-events:none}.connection-editor__connection-tooltip-callout:before{inset-block-start:-5px;inset-inline-start:-5px;width:12px;height:12px;border:1px solid rgba(148,163,184,.24);background:#080d18f5;box-shadow:inset 0 1px #ffffff14}.connection-editor__connection-tooltip-callout:after{inset-block-end:-3px;inset-inline-start:-4px;width:10px;height:10px;background:#19c8e8;box-shadow:0 0 16px #19c8e88f}.connection-editor__connection-tooltip--projection{border-color:#19c8e833;background:linear-gradient(135deg,#15b8d81f,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state{border-color:#ff9f2f66;background:linear-gradient(135deg,#ff9f2f3d,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout{background:linear-gradient(180deg,#ffbd62d1,#ff9f2f00);box-shadow:0 0 14px #ff9f2f61}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout:after{background:#ff9f2f;box-shadow:0 0 18px #ff9f2fad}.connection-editor__connection-tooltip--error{border-color:#f871716b}.connection-editor__connection-tooltip--error .connection-editor__connection-tooltip-callout:after{background:#fb7185;box-shadow:0 0 18px #fb7185ad}.connection-editor__connection-tooltip-kind{display:inline-flex;align-items:center;gap:8px;color:#94a3b8;font-size:.62rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__connection-tooltip-kind span{width:8px;height:8px;border-radius:999px;background:#19c8e8;box-shadow:0 0 12px #19c8e880}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2fc7}.connection-editor__connection-tooltip-row{min-width:0;display:grid;grid-template-columns:54px minmax(0,1fr);align-items:center;gap:8px;min-height:28px;padding:0 10px;border-radius:999px;background:#0f172a94}.connection-editor__connection-tooltip-row span{color:#8d9bb0;font-size:.62rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.connection-editor__connection-tooltip-row strong{min-width:0;overflow:hidden;color:#e2e8f0;font-size:.75rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__connection-tooltip-badges{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__connection-tooltip-badges span{padding:3px 8px;border-radius:999px;background:#02061799;color:#fbbf24;font-size:.66rem;font-weight:900}.connection-editor__trace-overlay{position:absolute;z-index:6;inset-block-start:16px;inset-inline-start:50%;width:min(560px,calc(100% - 360px));min-width:320px;padding:12px 14px;border-radius:16px;border:1px solid rgba(34,197,94,.26);background:linear-gradient(135deg,#22c55e1f,#0ea5e91a),#080d18f0;box-shadow:0 22px 56px #02061775,0 0 42px #22c55e1f;transform:translate(-50%);pointer-events:auto;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .16s ease-out}.connection-editor__trace-overlay-head,.connection-editor__trace-overlay-route{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.connection-editor__trace-overlay-head span,.connection-editor__trace-overlay-route span{color:#86efac;font-size:.66rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap}.connection-editor__trace-overlay-head strong{color:#cbd5e1;font-size:.7rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace}.connection-editor__trace-overlay-route{margin-top:6px}.connection-editor__trace-overlay-controls{display:grid;grid-template-columns:28px minmax(0,1fr) 28px;align-items:center;gap:8px;margin-top:10px}.connection-editor__trace-overlay-button{width:28px;height:24px;display:inline-grid;place-items:center;border:1px solid rgba(148,163,184,.18);border-radius:999px;background:#0206176b;color:#e2e8f0;cursor:pointer;font-size:1rem;font-weight:900;line-height:1;transition:border-color .15s ease,background .15s ease,color .15s ease,opacity .15s ease}.connection-editor__trace-overlay-button:hover:not(:disabled){border-color:#22d3ee6b;background:#0ea5e929;color:#f8fafc}.connection-editor__trace-overlay-button:disabled{cursor:default;opacity:.36}.connection-editor__trace-overlay-steps{min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto;padding:2px;scrollbar-width:none}.connection-editor__trace-overlay-steps::-webkit-scrollbar{display:none}.connection-editor__trace-overlay-step{position:relative;flex:1 0 28px;min-width:28px;height:22px;border:1px solid rgba(148,163,184,.16);border-radius:999px;background:#0f172a9e;color:#94a3b8;cursor:pointer;font-size:.62rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__trace-overlay-step--active{border-color:#22d3eea3;background:linear-gradient(90deg,#22d3ee3d,#9b5cff33);color:#f8fafc;box-shadow:0 0 18px #22d3ee33}.connection-editor__trace-overlay-step--blocked{border-color:#fb71855c;color:#fecdd3}.connection-editor__trace-overlay-route strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.82rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__trace-overlay-bar{position:relative;height:5px;margin-top:10px;overflow:hidden;border-radius:999px;background:#94a3b829}.connection-editor__trace-overlay-bar span{position:absolute;inset-block:0;inset-inline-start:0;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#22d3ee);box-shadow:0 0 18px #22c55e61;min-width:8%}.connection-editor__drag-wire{fill:none;stroke:#94a3b8;stroke-width:2.4;stroke-linecap:round;stroke-dasharray:6 7;pointer-events:none;filter:url(#connection-glow);animation:connection-flow 1.05s linear infinite,drag-wire-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--halo{stroke:#94a3b829;stroke-width:14;stroke-dasharray:none;animation:drag-halo-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--valid{stroke:#22c55e}.connection-editor__drag-wire--halo.connection-editor__drag-wire--valid{stroke:#22c55e47}.connection-editor__drag-endpoint{fill:#94a3b8;stroke:#020617eb;stroke-width:2;pointer-events:none;filter:url(#connection-glow);transform-box:fill-box;transform-origin:center;animation:endpoint-pulse 1s ease-in-out infinite}.connection-editor__drag-endpoint--source{fill:#ff9f2f}.connection-editor__drag-endpoint--target{fill:#7dddeb}.connection-editor__drag-endpoint--valid{fill:#22c55e;stroke:#bbf7d0e0}.connection-editor__wire-handle-line{stroke-width:2;stroke-linecap:round;stroke-dasharray:4 5;pointer-events:none;opacity:.88;filter:url(#connection-glow)}.connection-editor__wire-handle-line--source{stroke:#ff9f2ff0}.connection-editor__wire-handle-line--target{stroke:#19c8e8c2}.connection-editor__wire-control{fill:#0f172af5;stroke:#cbd5e1c7;stroke-width:1.8;pointer-events:none;filter:url(#connection-glow)}.connection-editor__wire-label{pointer-events:none;filter:drop-shadow(0 0 10px rgba(2,6,23,.44));animation:tooltip-rise .14s ease-out}.connection-editor__wire-label rect{fill:#080d18eb;stroke-width:1}.connection-editor__wire-label text{fill:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__wire-label--source rect{stroke:#ff9f2fad}.connection-editor__wire-label--target rect{stroke:#19c8e86b}.connection-editor__zoom-controls{position:absolute;inset-inline-start:14px;inset-block-start:14px;z-index:4;display:grid;grid-template-columns:max-content;gap:6px;width:46px;pointer-events:auto}.connection-editor__tool-group,.connection-editor__trace-source{display:grid;gap:6px;padding:6px;border-radius:12px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:0 16px 36px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__tool-group{grid-template-columns:30px;width:max-content}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:30px}.connection-editor__arrange-button{width:34px;min-height:34px;display:inline-flex;align-items:center;justify-content:center;gap:0;padding:0;border-radius:999px;border:1px solid rgba(168,85,247,.34);background:linear-gradient(90deg,#a855f72e,#22d3ee1f);color:#e9d5ff;font-size:0;font-weight:800;letter-spacing:0;cursor:pointer;opacity:1;transform:scale(1);transition:opacity .14s ease,transform .14s ease,border-color .14s ease,background .14s ease}.connection-editor--guided .connection-editor__arrange-button{opacity:.34;transform:scale(.9);border-color:color-mix(in srgb,var(--pce-outline) 82%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 84%,transparent)}.connection-editor--guided .connection-editor__zoom-controls:hover .connection-editor__arrange-button,.connection-editor--guided .connection-editor__zoom-controls:focus-within .connection-editor__arrange-button,.connection-editor--guided .connection-editor__arrange-button:hover,.connection-editor--guided .connection-editor__arrange-button:focus-visible,.connection-editor--guided .connection-editor__arrange-button--active{opacity:1;transform:scale(1);border-color:#a855f757;background:linear-gradient(90deg,#a855f72e,#22d3ee1f)}.connection-editor__arrange-button span{color:#c084fc;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.78rem;font-weight:900}.connection-editor__tool-button{width:30px;height:30px;border-radius:999px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.9rem;font-weight:800;letter-spacing:.02em;cursor:pointer;line-height:1}.connection-editor__tool-button:hover:not(:disabled){border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);color:var(--pce-primary);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 16%,transparent)}.connection-editor__history-button:disabled{cursor:not-allowed;opacity:.42}.connection-editor__arrange-button--active{border-color:#22d3ee94;background:linear-gradient(90deg,#0ea5e93d,#22d3ee2e);color:#cffafe}.connection-editor__trace-source{gap:4px;max-height:230px;overflow:auto}.connection-editor__trace-source-title{padding:2px 4px 6px;color:var(--pce-muted);font-size:.64rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.connection-editor__trace-source-item{min-width:0;min-height:30px;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:8px;background:transparent;color:var(--pce-fg);cursor:pointer;font-size:.74rem;font-weight:800;text-align:start}.connection-editor__trace-source-item span{color:#f59e0b;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__trace-source-item:hover,.connection-editor__trace-source-item--active{background:var(--pce-surface-strong);color:var(--pce-strong);box-shadow:inset 3px 0 #f59e0bd1}.connection-editor__minimap{position:absolute;inset-inline-end:14px;inset-block-end:14px;z-index:4;width:184px;height:124px;padding:18px 10px 10px;overflow:hidden;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-primary) 30%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),var(--pce-surface-strong)),var(--pce-surface);box-shadow:0 20px 48px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);cursor:pointer;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);opacity:1;transform:scale(1);transform-origin:100% 100%;transition:opacity .16s ease,transform .16s ease,border-color .16s ease,box-shadow .16s ease}.connection-editor--guided .connection-editor__minimap{opacity:.54;transform:scale(.88);border-color:color-mix(in srgb,var(--pce-outline) 64%,transparent);box-shadow:0 14px 34px color-mix(in srgb,var(--pce-shadow-soft) 70%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor--guided .connection-editor__minimap:hover,.connection-editor--guided .connection-editor__minimap:focus-visible,.connection-editor--guided .connection-editor__minimap--panning{opacity:1;transform:scale(1)}.connection-editor__minimap:hover,.connection-editor__minimap--panning{border-color:#22d3ee75;box-shadow:0 20px 48px var(--pce-shadow-soft),0 0 24px color-mix(in srgb,var(--pce-primary) 14%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__minimap--panning{cursor:grabbing}.connection-editor__minimap:before{content:\"\";position:absolute;inset:22px 10px 10px;border-radius:10px;background-image:radial-gradient(circle,rgba(125,211,252,.18) 1px,transparent 1px);background-size:22px 22px;opacity:.58;pointer-events:none}.connection-editor__minimap-title{position:absolute;inset-block-start:7px;inset-inline-start:12px;color:var(--pce-muted);font-size:.6rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__minimap svg{position:relative;width:100%;height:100%;display:block;overflow:visible}.connection-editor__minimap-wire{fill:none;stroke:#b46cff8f;stroke-width:4;stroke-linecap:round;opacity:.86}.connection-editor__minimap-wire--state{stroke:#ff9f2fdb}.connection-editor__minimap-wire--state-read{stroke:#8b7dffb8;stroke-dasharray:4 9}.connection-editor__minimap-wire--projection{stroke:#19c8e88a;stroke-dasharray:18 8}.connection-editor__minimap-wire--event-propagation{stroke:#ffb454cc;stroke-dasharray:6 7}.connection-editor__minimap-wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.28))}.connection-editor__minimap-wire--trace{stroke:#9b5cffe0;stroke-width:5;stroke-dasharray:12 9;animation:connection-flow 1s linear infinite}.connection-editor__minimap-wire--active{stroke:#facc15eb;stroke-width:6;filter:drop-shadow(0 0 8px rgba(250,204,21,.38))}.connection-editor__minimap-wire--mode-dimmed{opacity:.2;stroke-width:2.6;filter:none}.connection-editor__minimap-node{fill:#f59e0be0;stroke:#020617db;stroke-width:4;filter:drop-shadow(0 0 7px rgba(245,158,11,.24))}.connection-editor__minimap-node--state{fill:#a855f7e6;filter:drop-shadow(0 0 8px rgba(168,85,247,.34))}.connection-editor__minimap-node--selected{fill:#facc15f5;stroke:#fef08aeb;filter:drop-shadow(0 0 10px rgba(250,204,21,.42))}.connection-editor__minimap-node--trace-source{fill:#facc15f5;filter:drop-shadow(0 0 10px rgba(250,204,21,.44))}.connection-editor__minimap-node--trace-reacting{fill:#22c55eeb;filter:drop-shadow(0 0 10px rgba(34,197,94,.42))}.connection-editor__minimap-node--mode-dimmed{opacity:.28;filter:none}.connection-editor__minimap-viewport{fill:#7dd3fc1f;stroke:#7dd3fce6;stroke-width:5;stroke-dasharray:18 10;filter:drop-shadow(0 0 10px rgba(125,211,252,.3));transition:x .12s ease,y .12s ease,width .12s ease,height .12s ease}.connection-editor__minimap--panning .connection-editor__minimap-viewport{fill:#22d3ee2e;stroke:#22d3eef5;stroke-dasharray:none}.connection-editor__node{position:absolute;z-index:10;width:168px;height:168px;transform:translate(-84px,-84px);border:0;padding:0;background:transparent;color:inherit;cursor:pointer;transition:filter .16s ease}.connection-editor__node--dragging{cursor:grabbing;filter:drop-shadow(0 0 22px rgba(34,211,238,.26));z-index:12}.connection-editor__node--connection-focus{filter:drop-shadow(0 0 16px rgba(34,211,238,.2))}.connection-editor__node--compat-target .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e66,0 0 0 18px #22c55e0b,0 0 32px #22c55e29}.connection-editor__node--mode-dimmed{opacity:.42;filter:grayscale(.22) saturate(.56)}.connection-editor__node--quiet{opacity:.58;filter:saturate(.68) brightness(.86)}.connection-editor__node--mode-dimmed .connection-editor__node-ring{animation:none;box-shadow:0 0 0 1px #2dd4bf14,0 0 14px #0ea5e90f}.connection-editor__node--mode-dimmed .connection-editor__node-halo{stroke-opacity:.28}.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-svg{position:absolute;inset:0}.connection-editor__node-ring,.connection-editor__node-core{display:grid;place-items:center;clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}.connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from -28deg,#06b6d4b3 0 28%,#f59e0b9e 28% 48%,#a855f780 48% 68%,#06b6d4a3 68% 100%);box-shadow:0 0 0 1px #2dd4bf2e,0 0 26px #0ea5e929;animation:node-breathe 2.8s ease-in-out infinite}.connection-editor__node-svg{overflow:visible;filter:drop-shadow(0 0 16px rgba(14,165,233,.16))}.connection-editor__node-halo{fill:transparent;stroke:#38bdf838;stroke-width:1;stroke-dasharray:0;pointer-events:none}.connection-editor__node-halo:nth-child(2){stroke:#38bdf824}.connection-editor__node-halo:nth-child(3){stroke:#94a3b81a}.connection-editor__node-segment{fill-opacity:.28;stroke-opacity:.72;stroke-width:1.15;transition:fill-opacity .16s ease,stroke-opacity .16s ease,stroke-width .16s ease;cursor:grab}.connection-editor__node:hover .connection-editor__node-segment,.connection-editor__node--selected .connection-editor__node-segment,.connection-editor__node--connection-focus .connection-editor__node-segment{fill-opacity:.54;stroke-opacity:.95;stroke-width:1.55}.connection-editor__node-segment--connection-focus{fill-opacity:.76;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 8px rgba(34,211,238,.76));animation:segment-focus-sweep 1.45s ease-in-out infinite}.connection-editor__node-segment--source{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 12px rgba(251,146,60,.82))}.connection-editor__node-segment--compatible{fill-opacity:.74;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 10px rgba(34,197,94,.72));animation:snap-pulse 1s ease-in-out infinite}.connection-editor__node-segment--compat-preview{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 13px rgba(245,158,11,.78))}.connection-editor__node-segment--candidate{fill-opacity:.92;stroke-opacity:1;stroke-width:2.8;filter:drop-shadow(0 0 16px rgba(34,197,94,.86))}.connection-editor__node-segment--incompatible{fill-opacity:.12;stroke-opacity:.28;cursor:not-allowed}.connection-editor__node-segment--invalid-drop{fill-opacity:.72;stroke:#fb7185;stroke-opacity:1;stroke-width:3;filter:drop-shadow(0 0 16px rgba(244,63,94,.84));animation:invalid-drop-jolt .36s ease-out}.connection-editor__node-segment--state{fill-opacity:.44;filter:drop-shadow(0 0 8px rgba(180,108,255,.2))}.connection-editor__node-segment--mode-dimmed{fill-opacity:.08;stroke-opacity:.2;stroke-width:.9;filter:none}.connection-editor__node-anchor{opacity:.95;filter:drop-shadow(0 0 6px currentColor)}.connection-editor__node-rotate-handle{cursor:grab;opacity:0;pointer-events:none;transition:opacity .16s ease,filter .16s ease;filter:drop-shadow(0 0 8px rgba(34,211,238,.28))}.connection-editor__node:hover .connection-editor__node-rotate-handle,.connection-editor__node--selected .connection-editor__node-rotate-handle,.connection-editor__node--rotating .connection-editor__node-rotate-handle{opacity:1;pointer-events:auto}.connection-editor__node--rotating .connection-editor__node-rotate-handle{cursor:grabbing;filter:drop-shadow(0 0 12px rgba(34,211,238,.54))}.connection-editor__node-rotate-hit{fill:transparent}.connection-editor__node-rotate-dot{fill:var(--pce-surface-strong);stroke:var(--pce-primary);stroke-opacity:.88;stroke-width:1.4}.connection-editor__node-rotate-arc,.connection-editor__node-rotate-arrow{fill:none;stroke:var(--pce-primary);stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.96;stroke-width:1.2;pointer-events:none}.connection-editor__segment-icon,.connection-editor__segment-label{pointer-events:none;fill:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:800;paint-order:stroke;stroke:#020617c2;stroke-width:3px;stroke-linejoin:round}.connection-editor__segment-icon{font-size:12px;fill:#19c8e8;opacity:1;transition:opacity .14s ease}.connection-editor__segment-icon--output{fill:#ff9f2f}.connection-editor--guided .connection-editor__segment-icon:not(.connection-editor__segment-icon--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-icon{opacity:0}.connection-editor__segment-label{font-size:9.5px;letter-spacing:0;fill:#e2e8f0e0;opacity:1;transition:opacity .14s ease}.connection-editor--guided .connection-editor__segment-label:not(.connection-editor__segment-label--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-label{opacity:0}.connection-editor__node-core{inset:43px;padding:12px;border-radius:999px;clip-path:none;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(circle at center,#111827 0 58%,#060b14);border:1px solid rgba(226,232,240,.1);box-shadow:0 12px 28px #00000073,inset 0 1px #ffffff0d;color:#f8fafc;text-shadow:0 1px 2px rgba(0,0,0,.62)}.connection-editor__node-icon{display:block;max-width:44px;overflow:hidden;color:#f8fafc;font-family:Material Symbols Outlined,Material Icons,sans-serif;font-size:1.22rem;font-weight:400;line-height:1;text-align:center;text-transform:none;letter-spacing:0;white-space:nowrap;filter:drop-shadow(0 0 10px rgba(226,232,240,.18))}.connection-editor__node--state .connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from 14deg,#a855f7c7 0 42%,#7e3af26b 42% 78%,#f59e0b47 78% 100%);box-shadow:0 0 0 1px #a855f738,0 0 30px #a855f733}.connection-editor__node--selected .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15bd,0 0 34px #facc153d}.connection-editor__node--connection-focus .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eead,0 0 38px #22d3ee42;animation:node-focus-breathe 1.7s ease-in-out infinite}.connection-editor__node--trace-source .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 0 18px #facc150f,0 0 54px #facc154d;animation:trace-source-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:before{content:\"\";position:absolute;z-index:0;inset:-44px;border-radius:999px;border:2px solid rgba(250,204,21,.36);background:radial-gradient(circle at center,transparent 0 64%,rgba(250,204,21,.05) 65% 66%,transparent 67%),conic-gradient(from -20deg,#facc1500,#facc1552,#facc1500);box-shadow:0 0 36px #facc151f;opacity:.92;pointer-events:none;animation:trace-source-orbit 2.8s linear infinite}.connection-editor__node--trace-reacting .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e94,0 0 46px #22c55e38;animation:trace-reacting-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:after,.connection-editor__node--trace-reacting:after{position:absolute;z-index:3;inset-inline-start:50%;inset-block-start:-42px;padding:0;border:0;background:transparent;color:#facc15;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.68rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase;transform:translate(-50%);text-shadow:0 0 12px rgba(250,204,21,.52);pointer-events:none}.connection-editor__node--trace-source:after{content:attr(data-trace-label)}.connection-editor__node--trace-reacting:after{content:attr(data-trace-label);color:#86efac;text-shadow:0 0 12px rgba(34,197,94,.44)}.connection-editor__node--trace-source .connection-editor__node-segment--output{fill-opacity:.66;stroke-width:2.2;filter:drop-shadow(0 0 14px rgba(255,159,47,.42))}.connection-editor__node--expanded .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eebd,0 0 34px #22d3ee3d}.connection-editor__node--rotating .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 42px #facc1547;animation:node-focus-breathe 1.1s ease-in-out infinite}.connection-editor__node--rotating .connection-editor__node-segment{fill-opacity:.68;stroke-opacity:1;stroke-width:1.9;cursor:grabbing}.connection-editor__node-title,.connection-editor__node-subtitle{display:block;max-width:92px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.connection-editor__node-title{color:#f8fafc;font-size:.82rem;font-weight:800}.connection-editor__node-subtitle{margin-top:4px;color:#a7b4c8;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__ports{position:absolute;z-index:30;display:grid;gap:6px;width:104px;opacity:0;pointer-events:none;transform:translateY(3px);transition:opacity .16s ease,transform .16s ease}.connection-editor__ports--visible{opacity:1;pointer-events:auto;transform:translateY(0)}.connection-editor__ports--outputs{z-index:42}.connection-editor__ports--inputs{z-index:36}.connection-editor__segment-popover{position:absolute;z-index:80;width:292px;max-height:320px;overflow:auto;display:grid;gap:10px;padding:14px;border-radius:16px;border:1px solid rgba(148,163,184,.18);background:linear-gradient(135deg,#0f172af5,#110c20f0),#090c16eb;box-shadow:0 28px 72px #0000007a,0 0 48px #a855f71a,inset 0 1px #ffffff0d;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__segment-popover-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:2px}.connection-editor__segment-popover-title{color:#94a3b8;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}.connection-editor__segment-popover-hint{margin-top:5px;color:#64748b;font-size:.66rem;font-weight:700}.connection-editor__segment-rotation{flex:0 0 auto;min-width:54px;padding:5px 8px;border-radius:999px;border:1px solid rgba(34,211,238,.28);background:#082f4957;color:#7dd3fc;font-size:.66rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-align:center;box-shadow:inset 0 0 16px #0ea5e914}.connection-editor__segment-row{display:grid;grid-template-columns:28px 72px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:40px;padding:7px;border-radius:12px;border:1px solid rgba(148,163,184,.12);background:linear-gradient(90deg,#0f172ac7,#0f172a75),#0f172a99;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__segment-row--input{border-color:#22d3ee42}.connection-editor__segment-row--output{border-color:#f59e0b47}.connection-editor__segment-row--state{border-color:#a855f74d}.connection-editor__segment-row--source,.connection-editor__segment-row--candidate{transform:translate(2px);box-shadow:0 0 22px #f59e0b24,inset 0 0 20px #f59e0b14}.connection-editor__segment-row--compatible{border-color:#22d3ee6b;box-shadow:inset 0 0 18px #22d3ee14}.connection-editor__segment-row--compat-preview{border-color:#f59e0b94;background:linear-gradient(90deg,#f59e0b1f,#0f172a8a),#0f172ab3;box-shadow:0 0 22px #f59e0b1f,inset 0 0 18px #f59e0b14}.connection-editor__segment-row--invalid-drop{border-color:#fb7185b3;background:linear-gradient(90deg,#f43f5e24,#0f172a94),#0f172ab3;box-shadow:0 0 24px #f43f5e2e,inset 0 0 18px #f43f5e1a;animation:invalid-drop-jolt .36s ease-out}.connection-editor__segment-index{color:#64748b;font-size:.64rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;letter-spacing:.08em}.connection-editor__segment-kind{display:inline-flex;align-items:center;gap:6px;color:#94a3b8;font-size:.62rem;font-weight:800;text-transform:uppercase;min-width:0;white-space:nowrap}.connection-editor__segment-kind-dot{width:7px;height:7px;border-radius:999px;background:#94a3b8;box-shadow:0 0 12px #94a3b847}.connection-editor__segment-row--input .connection-editor__segment-kind-dot{background:#22d3ee;box-shadow:0 0 12px #22d3ee61}.connection-editor__segment-row--output .connection-editor__segment-kind-dot{background:#fb923c;box-shadow:0 0 12px #fb923c66}.connection-editor__segment-row--state .connection-editor__segment-kind-dot{background:#a855f7;box-shadow:0 0 12px #a855f76b}.connection-editor__segment-label{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;color:#e2e8f0;font-size:.74rem;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-badge{flex:0 0 auto;padding:2px 5px;border-radius:999px;border:1px solid rgba(56,189,248,.28);background:#0ea5e91a;color:#bae6fd;font-size:.55rem;font-weight:900;text-transform:uppercase}.connection-editor__segment-path{grid-column:3 / 4;min-width:0;margin-top:-5px;overflow:hidden;color:#93c5fd;font-size:.62rem;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-row--nested{min-height:56px;border-color:#38bdf84d;background:linear-gradient(90deg,#0ea5e91a,#0f172a80),#0f172aa3}.connection-editor__segment-actions{display:inline-flex;gap:4px}.connection-editor__segment-action{width:24px;height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.18);background:#060c16b8;color:#dbeafe;cursor:pointer;font-weight:900;line-height:1}.connection-editor__segment-action:hover{border-color:#22d3ee75;box-shadow:0 0 14px #22d3ee29}.connection-editor__port{min-height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#080d18c2;color:#cbd5e1;font-size:.64rem;font-weight:700;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:crosshair;box-shadow:0 8px 20px #00000038}.connection-editor--guided .connection-editor__ports--visible .connection-editor__port:not(.connection-editor__port--guided-visible){display:none}.connection-editor__port--output{border-color:#f59e0b75;color:#fbbf24}.connection-editor__port--input{border-color:#06b6d475;color:#22d3ee}.connection-editor__port--state{border-color:#a855f785;color:#c084fc}.connection-editor__port--compatible{background:#22c55e29;box-shadow:0 0 0 1px #22c55e61,0 0 18px #22c55e2e;animation:snap-pulse 1s ease-in-out infinite}.connection-editor__port--source{border-color:#fb923cb8;background:#fb923c29;color:#fed7aa;box-shadow:0 0 0 1px #fb923c73,0 0 20px #fb923c2e}.connection-editor__port--candidate{background:#22c55e3d;box-shadow:0 0 0 2px #22c55e94,0 0 24px #22c55e3d}.connection-editor__port--incompatible{opacity:.42;cursor:not-allowed;filter:grayscale(.45)}.connection-editor__port--invalid-drop{opacity:1;border-color:#fb7185c7;color:#fecdd3;background:#f43f5e2e;box-shadow:0 0 0 2px #f43f5e75,0 0 24px #f43f5e38;filter:none;animation:invalid-drop-jolt .36s ease-out}.connection-editor__port--connection-focus{border-color:#facc15ad;color:#fde68a;background:#facc151f;box-shadow:0 0 0 1px #facc156b,0 0 20px #facc152e;animation:port-focus-pulse 1.25s ease-in-out infinite}.connection-editor__drag-tip{position:absolute;z-index:6;display:grid;gap:4px;width:min(330px,calc(100% - 28px));padding:10px 12px;border-radius:14px;border:1px solid rgba(125,211,252,.26);background:linear-gradient(135deg,#0ea5e91f,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 28px #0ea5e91a;font-size:.76rem;pointer-events:none;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);animation:tooltip-rise .14s ease-out}.connection-editor__drag-tip--valid{border-color:#22c55e66;background:linear-gradient(135deg,#22c55e29,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 30px #22c55e24}.connection-editor__drag-tip--invalid{z-index:7;border-color:#fb71858a;background:linear-gradient(135deg,#f43f5e2e,#0f172af0),#080d18f5;box-shadow:0 18px 44px #0206176b,0 0 34px #f43f5e29;animation:tooltip-rise .14s ease-out,invalid-drop-jolt .36s ease-out}.connection-editor__invalid-drop-pulse{position:absolute;z-index:6;width:16px;height:16px;border-radius:999px;border:2px solid rgba(251,113,133,.88);background:#f43f5e38;box-shadow:0 0 0 8px #f43f5e1a,0 0 28px #f43f5e3d;pointer-events:none;transform:translate(-50%,-50%);animation:invalid-drop-ping 1.2s ease-out both}.connection-editor__drag-tip span{color:#7dd3fc;text-transform:uppercase;letter-spacing:.12em;font-size:.62rem;font-weight:800}.connection-editor__drag-tip strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.78rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__drag-tip small{color:#94a3b8;font-size:.68rem;font-weight:700}.connection-editor__drag-tip--valid small{color:#86efac}.connection-editor__drag-tip--invalid span,.connection-editor__drag-tip--invalid small{color:#fda4af}.connection-editor__summary{grid-column:1;grid-row:2;align-self:end;justify-self:start;z-index:6;display:flex;flex-wrap:wrap;gap:6px;padding:0 0 12px 12px;pointer-events:none}.connection-editor__side-panel{grid-column:2;grid-row:2 / 3;position:relative;z-index:8;min-width:0;min-height:0;display:grid;align-content:start;gap:14px;overflow:auto;padding-inline-end:4px;scrollbar-color:var(--pce-outline-strong) var(--pce-surface-soft)}.connection-editor__side-panel--contextual .connection-editor__inspector{order:-3}.connection-editor__side-panel--contextual .connection-editor__recommended{order:2}.connection-editor__side-panel--contextual .connection-editor__filters-section{order:3}.connection-editor__side-panel--contextual .connection-editor__recommended,.connection-editor__side-panel--contextual .connection-editor__filters-section{opacity:.82}.connection-editor__metric,.connection-editor__item{border-radius:16px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__metric{min-width:auto;display:inline-flex;align-items:baseline;gap:7px;padding:6px 9px;border-radius:999px;background:color-mix(in srgb,var(--pce-surface-strong) 86%,transparent);box-shadow:0 10px 26px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight)}.connection-editor__metric span{color:var(--pce-muted);font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__metric strong,.connection-editor__details-row strong{color:var(--pce-strong);font-size:.78rem}.connection-editor__filters,.connection-editor__actions,.connection-editor__badges{display:flex;gap:8px;flex-wrap:wrap}.connection-editor__filter,.connection-editor__action{border:1px solid var(--pce-outline-strong);background:var(--pce-surface-soft);color:var(--pce-fg);border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connection-editor__filter--active,.connection-editor__action:hover{border-color:color-mix(in srgb,var(--pce-secondary) 62%,transparent);background:color-mix(in srgb,var(--pce-secondary) 16%,var(--pce-surface-soft));color:var(--pce-strong)}.connection-editor__action--danger{border-color:#f8717161;color:#fecaca}.connection-editor__item{width:100%;text-align:start;padding:12px;display:grid;gap:6px;cursor:pointer;color:inherit}.connection-editor__item--active{border-color:#a855f7b8;background:linear-gradient(90deg,#0ea5e91a,#a855f721)}.connection-editor__item-title{font-weight:800;color:#f8fafc;word-break:break-word}.connection-editor__badge{padding:3px 8px;border-radius:999px;background:#0ea5e92e;color:#bae6fd;font-size:.72rem;font-weight:800}.connection-editor__section{min-width:0;padding:14px;border-radius:18px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight),0 18px 50px var(--pce-shadow-soft);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__badge--warning{background:#facc1524;color:#fde68a}.connection-editor__badge--error{background:#ef444424;color:#fecaca}.connection-editor__diagnostics{display:grid;gap:8px}.connection-editor__diagnostic{display:grid;gap:4px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.78rem;line-height:1.35}.connection-editor__diagnostic--warning{border-color:#f59e0b47;background:#f59e0b1a}.connection-editor__diagnostic--error{border-color:#ef44445c;background:#ef44441f}.connection-editor__diagnostic-severity{font-size:.68rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#f8fafc}.connection-editor__suggestions{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__suggestion{display:grid;gap:8px;width:100%;padding:12px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 12%,transparent),color-mix(in srgb,var(--pce-primary) 8%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__suggestion:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 46%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 18%,transparent),color-mix(in srgb,var(--pce-primary) 12%,transparent)),var(--pce-surface-strong)}.connection-editor__suggestion-route{display:grid;gap:4px;font-size:.78rem}.connection-editor__suggestion-route strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__suggestion-reason{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__suggestion-diagnostic{padding:10px 12px;border-radius:14px;border:1px solid rgba(245,158,11,.28);background:#f59e0b1a;color:var(--pce-strong);font-size:.78rem;line-height:1.35}.connection-editor__suggestion-outcome{color:var(--pce-strong);font-size:.84rem;line-height:1.3}.connection-editor__suggestion-action{justify-self:start;padding:3px 8px;border-radius:999px;background:#22d3ee24;color:#67e8f9;font-size:.68rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase}:host-context(.theme-light) .connection-editor__suggestion-action{background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:#075f73}.connection-editor__trace{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__trace-summary{color:var(--pce-muted);font-size:.78rem;line-height:1.35}.connection-editor__trace-step{display:grid;grid-template-columns:24px minmax(76px,auto) 1fr;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(34,211,238,.18);background:var(--pce-surface-soft);font-size:.76rem}.connection-editor__trace-step--blocked{border-color:#ef444457;background:#ef44441a}.connection-editor__trace-order{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:999px;background:#22d3ee29;color:#67e8f9;font-weight:900}.connection-editor__trace-phase{color:var(--pce-strong);font-weight:900;text-transform:uppercase;letter-spacing:.06em;font-size:.66rem}.connection-editor__trace-copy{min-width:0;color:var(--pce-fg);word-break:break-word}.connection-editor__transform-steps{display:grid;gap:8px}.connection-editor__transform-step{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(168,85,247,.22);background:var(--pce-surface-soft)}.connection-editor__transform-kind{min-width:0;color:var(--pce-strong);font-weight:900;word-break:break-word}.connection-editor__transform-phase{color:var(--pce-muted);font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.connection-editor__details-row,.connection-editor__details-block{display:grid;gap:6px}.connection-editor__payload-input{width:100%;min-height:128px;box-sizing:border-box;resize:vertical;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 92%,black);color:var(--pce-fg);padding:10px;font:.76rem/1.45 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.connection-editor__surface-action-editor{display:block;max-height:min(58vh,620px);overflow:auto;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 96%,black);padding:10px;margin-bottom:10px}.connection-editor__rule-grid{display:grid;gap:10px}.connection-editor__rule-card{display:grid;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__rule-heading{color:var(--pce-fg);font-size:.72rem;font-weight:900;text-transform:uppercase;letter-spacing:.06em}pre{margin:0;padding:12px;border-radius:12px;background:color-mix(in srgb,var(--pce-surface-strong) 82%,#020617);color:var(--pce-fg);overflow:auto;font-size:.75rem}@keyframes connection-flow{to{stroke-dashoffset:-38}}@keyframes drag-wire-pulse{0%,to{stroke-opacity:.76}50%{stroke-opacity:1}}@keyframes drag-halo-pulse{0%,to{stroke-opacity:.48}50%{stroke-opacity:.82}}@keyframes endpoint-pulse{0%,to{opacity:.78;transform:scale(1)}50%{opacity:1;transform:scale(1.25)}}@keyframes selected-wire-aura{0%,to{stroke-opacity:.46}50%{stroke-opacity:.92}}@keyframes wire-draw-in{0%{stroke-dashoffset:640;opacity:.32}70%{opacity:1}to{stroke-dashoffset:0;opacity:1}}@keyframes new-wire-halo{0%{stroke-opacity:0;stroke-width:30}28%{stroke-opacity:.78}to{stroke-opacity:0;stroke-width:12}}@keyframes new-dock-link-flash{0%{transform:translateY(-2px);box-shadow:0 16px 40px #0206175c,0 0 42px #fb923c47}to{transform:translateY(0)}}@keyframes trace-wire-pulse{0%,to{stroke-opacity:.78}50%{stroke-opacity:1}}@keyframes trace-halo-pulse{0%,to{stroke-opacity:.34}50%{stroke-opacity:.86}}@keyframes tooltip-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes invalid-drop-jolt{0%,to{transform:translate(0)}28%{transform:translate(-3px)}56%{transform:translate(3px)}}@keyframes invalid-drop-ping{0%{opacity:1;transform:translate(-50%,-50%) scale(.72)}72%{opacity:.74;transform:translate(-50%,-50%) scale(1.35)}to{opacity:0;transform:translate(-50%,-50%) scale(1.8)}}@keyframes node-breathe{50%{transform:scale(1.035)}}@keyframes node-focus-breathe{0%,to{transform:scale(1)}50%{transform:scale(1.055)}}@keyframes trace-source-pulse{50%{transform:scale(1.04);box-shadow:0 0 0 3px #facc15db,0 0 0 22px #facc1514,0 0 64px #facc1557}}@keyframes trace-source-orbit{to{transform:rotate(360deg)}}@keyframes trace-reacting-pulse{50%{transform:scale(1.045);box-shadow:0 0 0 3px #22c55ead,0 0 62px #22c55e4d}}@keyframes segment-focus-sweep{0%,to{stroke-opacity:.82}50%{stroke-opacity:1}}@keyframes snap-pulse{50%{filter:brightness(1.16)}}@keyframes port-focus-pulse{50%{transform:translateY(-1px);box-shadow:0 0 0 2px #facc158f,0 0 26px #facc153d}}@media(prefers-reduced-motion:reduce){.connection-editor__viewport,.connection-editor__node,.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-segment,.connection-editor__dock-link,.connection-editor__port{transition-duration:1ms}.connection-editor__wire,.connection-editor__wire--state,.connection-editor__wire--projection,.connection-editor__wire--state-read,.connection-editor__wire--event-propagation,.connection-editor__wire--halo.connection-editor__wire--active,.connection-editor__wire--trace,.connection-editor__wire--halo.connection-editor__wire--trace,.connection-editor__wire-endpoint,.connection-editor__connection-tooltip,.connection-editor__dock-link--new,.connection-editor__trace-overlay,.connection-editor__trace-overlay-step,.connection-editor__drag-wire,.connection-editor__drag-wire--halo,.connection-editor__drag-endpoint,.connection-editor__drag-tip,.connection-editor__node-ring,.connection-editor__node--connection-focus .connection-editor__node-ring,.connection-editor__node--trace-source .connection-editor__node-ring,.connection-editor__node--trace-source:before,.connection-editor__node--trace-reacting .connection-editor__node-ring,.connection-editor__node--rotating .connection-editor__node-ring,.connection-editor__node-segment--connection-focus,.connection-editor__node-segment--compatible,.connection-editor__node-segment--invalid-drop,.connection-editor__segment-popover,.connection-editor__port--compatible,.connection-editor__port--invalid-drop,.connection-editor__port--connection-focus,.connection-editor__invalid-drop,.connection-editor__invalid-drop-pulse{animation:none}.connection-editor__wire{stroke-dashoffset:0}.connection-editor__wire--new{stroke-dasharray:10 8;stroke-dashoffset:0;opacity:1}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:12;stroke-opacity:.16}.connection-editor__wire-endpoint,.connection-editor__drag-endpoint,.connection-editor__node-ring,.connection-editor__node--trace-source:before{transform:none}.connection-editor__invalid-drop-pulse{opacity:0}}@media(max-width:900px){:host{inset:0}.connection-editor{inset:8px;height:calc(100vh - 16px);padding:12px;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) minmax(76px,112px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) 48px}.connection-editor__header,.connection-editor__stage,.connection-editor__summary,.connection-editor__side-panel,.connection-editor__dock{grid-column:1}.connection-editor__header{align-items:stretch;flex-wrap:wrap;border-radius:18px}.connection-editor__mode-frame{order:3;width:100%;max-width:100%}.connection-editor__close{margin-inline-start:auto}.connection-editor__mode-frame:before,.connection-editor__mode-frame:after{content:\"\";position:absolute;z-index:2;inset-block:4px;width:24px;border-radius:999px;pointer-events:none}.connection-editor__mode-frame:before{inset-inline-start:1px;background:linear-gradient(90deg,#080d18f0,#080d1800)}.connection-editor__mode-frame:after{inset-inline-end:1px;background:linear-gradient(270deg,#080d18f0,#080d1800)}.connection-editor__mode-shell{width:100%;max-width:100%;overflow-x:auto;scroll-padding-inline:28px;-webkit-overflow-scrolling:touch}.connection-editor__subtitle{margin-inline-start:auto}.connection-editor__stage{grid-row:2;min-height:260px}.connection-editor__summary{grid-row:2;max-width:calc(100% - 24px)}.connection-editor__side-panel{grid-row:3;max-height:30vh}.connection-editor__dock{grid-row:4;min-height:0}.connection-editor__connection-tooltip{width:min(620px,calc(100% - 24px));max-height:min(260px,calc(100% - 24px));overflow:auto}.connection-editor__dock-tabs{width:100%;min-width:0;min-height:0;flex-wrap:wrap;align-items:flex-start}.connection-editor__dock-tablist{width:100%;flex-wrap:wrap}.connection-editor__dock-count{flex:1 1 100%;margin-inline-start:0}.connection-editor__dock-body{width:100%;min-width:0;max-height:76px;box-sizing:border-box}.connection-editor__dock-body pre{white-space:pre-wrap;overflow-wrap:anywhere}.connection-editor__dock-link{grid-template-columns:1fr;align-items:start}.connection-editor__dock-link-route{flex-wrap:wrap}.connection-editor__dock-link-badges{justify-content:flex-start}.connection-editor__trace-overlay{inset-inline-start:14px;width:min(420px,calc(100% - 28px));min-width:0;transform:none}.connection-editor__drag-tip{width:min(300px,calc(100% - 28px))}.connection-editor__segment-popover{width:min(280px,calc(100% - 28px));max-height:min(280px,calc(100% - 28px))}.connection-editor__minimap{inset-inline-end:10px;inset-block-end:10px;width:132px;height:94px;padding:16px 8px 8px;border-radius:14px}.connection-editor__minimap:before{inset:20px 8px 8px;background-size:18px 18px}.connection-editor__minimap-title{inset-block-start:6px;inset-inline-start:10px;font-size:.54rem}}@media(max-width:640px){.connection-editor{inset:4px;height:calc(100vh - 8px);padding:8px;gap:8px;grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) minmax(72px,104px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) 46px}.connection-editor__header{gap:8px;padding:10px}.connection-editor__mode-shell{padding:4px;gap:2px}.connection-editor__mode{min-height:28px;gap:4px;padding:0 7px;font-size:.68rem}.connection-editor__mode-glyph{font-size:.64rem}.connection-editor__stage{min-height:240px}.connection-editor__zoom-controls{inset-inline-start:8px;inset-block-start:8px;gap:6px;width:42px}.connection-editor__tool-group,.connection-editor__trace-source{gap:6px;padding:8px;border-radius:12px}.connection-editor__tool-group{grid-template-columns:28px}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:28px}.connection-editor__tool-button{width:28px;height:28px}.connection-editor__arrange-button,.connection-editor__simulate-button{width:30px;min-height:30px}.connection-editor__summary{gap:6px;padding-inline-end:8px}.connection-editor__side-panel{max-height:28vh}.connection-editor__dock{border-radius:16px}.connection-editor__dock-tabs,.connection-editor__dock-tablist{gap:4px}.connection-editor__dock-tab{padding:0 9px}.connection-editor__dock-count{font-size:.62rem}.connection-editor__dock-body{max-height:66px;padding:8px}.connection-editor__minimap{width:116px;height:84px}.connection-editor__segment-row{grid-template-columns:24px minmax(54px,.55fr) minmax(0,1fr) auto}}\n"] }]
|
|
11623
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{position:fixed;inset:0;z-index:1000;pointer-events:none}.connection-editor{--pce-fg: var(--md-sys-color-on-surface, #dce6f4);--pce-strong: var(--md-sys-color-on-surface, #f8fafc);--pce-muted: var(--md-sys-color-on-surface-variant, #94a3b8);--pce-primary: var(--md-sys-color-primary, #19c8e8);--pce-secondary: var(--md-sys-color-secondary, #b46cff);--pce-tertiary: var(--md-sys-color-tertiary, #ff9f2f);--pce-success: var(--md-sys-color-tertiary, #10b981);--pce-warning: var(--md-sys-color-error, #ff9f2f);--pce-error: var(--md-sys-color-error, #ef4444);--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #07111f) 80%, #020617);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #08101d) 78%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #0f172a) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #080d18) 64%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #899ab7) 46%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #94a3b8) 58%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #7d8fa9) 24%, transparent);--pce-glass-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, #ffffff) 8%, transparent);--pce-shadow: color-mix(in srgb, #000 56%, transparent);--pce-shadow-soft: color-mix(in srgb, #000 30%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #040a13) 42%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high, #050912) 94%, transparent);position:absolute;inset:12px;height:calc(100vh - 24px);box-sizing:border-box;overflow:hidden;padding:16px;border-radius:18px;color:var(--pce-fg);background:radial-gradient(circle at 72% 20%,color-mix(in srgb,var(--pce-secondary) 16%,transparent),transparent 28%),radial-gradient(circle at 26% 74%,color-mix(in srgb,var(--pce-primary) 10%,transparent),transparent 34%),radial-gradient(circle at 48% 52%,color-mix(in srgb,var(--pce-tertiary) 5%,transparent),transparent 35%),linear-gradient(var(--pce-grid) 1px,transparent 1px),linear-gradient(90deg,var(--pce-grid) 1px,transparent 1px),var(--pce-surface-base);background-size:auto,auto,auto,38px 38px,38px 38px,auto;border:1px solid var(--pce-outline);box-shadow:0 28px 90px var(--pce-shadow);pointer-events:auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);grid-template-rows:auto minmax(0,1fr) minmax(44px,118px);gap:14px}:host-context(.theme-light) .connection-editor{--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 94%, var(--md-sys-color-primary, #2563eb) 6%);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 82%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #eef2ff) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #f8fafc) 70%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 68%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #64748b) 62%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 34%, transparent);--pce-glass-highlight: color-mix(in srgb, #fff 64%, transparent);--pce-shadow: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 22%, transparent);--pce-shadow-soft: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 14%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #ffffff) 58%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 92%, transparent)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(0,1fr) 48px}.connection-editor__header{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:42px;padding:8px 14px;border-radius:999px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__mode-frame{position:relative;min-width:0;flex:1 1 auto;display:flex;justify-content:center}.connection-editor__close{width:32px;height:32px;flex:0 0 auto;display:inline-grid;place-items:center;border:1px solid var(--pce-outline);border-radius:999px;color:var(--pce-text);background:var(--pce-surface-strong);box-shadow:inset 0 1px var(--pce-glass-highlight);cursor:pointer;font:inherit;font-size:1.2rem;line-height:1}.connection-editor__close:hover,.connection-editor__close:focus-visible{border-color:var(--pce-outline-strong);background:color-mix(in srgb,var(--pce-accent) 16%,var(--pce-surface-strong));outline:none}.connection-editor__mode-shell{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:4px;border-radius:999px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:inset 0 1px var(--pce-glass-highlight),0 10px 26px var(--pce-shadow-soft);scrollbar-width:none}.connection-editor__mode-shell::-webkit-scrollbar{display:none}.connection-editor__mode{min-height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 12px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.76rem;font-weight:800;white-space:nowrap;transition:background .16s ease,border-color .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__mode:hover,.connection-editor__mode--active{color:var(--pce-strong);border-color:color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-strong) 82%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 12%,transparent)}.connection-editor__mode-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__mode--active .connection-editor__mode-glyph{color:var(--pce-primary)}.connection-editor__mode-dot{width:6px;height:6px;border-radius:999px;background:var(--pce-success);box-shadow:0 0 12px color-mix(in srgb,var(--pce-success) 70%,transparent)}.connection-editor__status-pill{display:inline-flex;align-items:center;gap:8px;min-height:24px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 36%,transparent);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.72rem;font-weight:800;white-space:nowrap}.connection-editor__status-pill--button{cursor:pointer;transition:border-color .16s ease,background .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__status-pill--button:hover,.connection-editor__status-pill--button:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 62%,transparent);background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 14%,transparent);outline:none}.connection-editor__status-pill span{width:6px;height:6px;border-radius:999px;background:var(--pce-primary);box-shadow:0 0 12px color-mix(in srgb,var(--pce-primary) 70%,transparent)}.connection-editor__section{display:grid;gap:10px}.connection-editor__dock{grid-column:1 / -1;grid-row:3;position:relative;z-index:4;min-height:0;display:grid;border-radius:14px;border:1px solid var(--pce-outline);background:radial-gradient(circle at 16% 0%,color-mix(in srgb,var(--pce-primary) 22%,transparent),transparent 34%),radial-gradient(circle at 78% 0%,color-mix(in srgb,var(--pce-secondary) 25%,transparent),transparent 38%),linear-gradient(90deg,var(--pce-dock-bg),var(--pce-surface-strong) 46%,color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-dock-bg))),var(--pce-dock-bg);box-shadow:0 18px 58px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__dock--collapsed .connection-editor__dock-tabs{border-block-end:0}.connection-editor__dock-tabs{display:flex;align-items:center;gap:10px;min-height:52px;padding:9px 14px;border-block-end:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-glass-highlight),transparent),color-mix(in srgb,var(--pce-surface-soft) 34%,transparent)}.connection-editor__dock-tablist{display:flex;align-items:center;gap:10px;min-width:0}.connection-editor__dock-tab,.connection-editor__dock-toggle{min-height:30px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.72rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-tab{display:inline-flex;align-items:center;gap:8px;padding:0 13px;white-space:nowrap}.connection-editor__dock-tab-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.8rem;letter-spacing:0;text-transform:none}.connection-editor__dock-tab--active{color:var(--pce-strong);border-color:var(--pce-outline-strong);background:linear-gradient(180deg,color-mix(in srgb,var(--pce-strong) 14%,transparent),color-mix(in srgb,var(--pce-strong) 6%,transparent));box-shadow:0 0 0 1px color-mix(in srgb,var(--pce-shadow) 72%,transparent),0 0 22px color-mix(in srgb,var(--pce-strong) 8%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__dock-tab--active .connection-editor__dock-tab-glyph{color:var(--pce-strong)}.connection-editor__dock-count{margin-inline-start:auto;color:color-mix(in srgb,var(--pce-muted) 62%,transparent);font-size:.7rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-toggle{width:32px;padding:0;border-color:var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.88rem;letter-spacing:0}.connection-editor__dock-body{max-height:154px;overflow:auto;padding:12px 12px 14px;border-block-start:1px solid var(--pce-outline);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 9%,transparent),color-mix(in srgb,var(--pce-secondary) 10%,transparent) 62%,color-mix(in srgb,var(--pce-surface-strong) 18%,transparent)),color-mix(in srgb,var(--pce-surface-soft) 30%,transparent)}.connection-editor__dock-body pre{max-height:60px}.connection-editor__dock-links{display:grid;gap:8px}.connection-editor__dock-link-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;padding:7px 10px;border-radius:10px;border:1px solid var(--pce-outline);background:linear-gradient(90deg,var(--pce-surface-soft),color-mix(in srgb,var(--pce-secondary) 10%,var(--pce-surface-soft)) 72%,var(--pce-surface-soft)),var(--pce-surface-soft);color:var(--pce-fg);transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-link{display:grid;grid-template-columns:minmax(116px,.52fr) minmax(300px,1.72fr) minmax(160px,.9fr) auto;align-items:center;gap:12px;width:100%;min-height:42px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;text-align:start}.connection-editor__dock-link-row:hover,.connection-editor__dock-link--active{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 13%,transparent),color-mix(in srgb,var(--pce-secondary) 16%,transparent),var(--pce-surface-strong)),var(--pce-surface-strong);box-shadow:0 12px 32px var(--pce-shadow-soft),inset 0 0 18px color-mix(in srgb,var(--pce-primary) 6%,transparent)}.connection-editor__dock-link--active{border-color:#facc1575;box-shadow:0 12px 32px var(--pce-shadow-soft),0 0 24px #facc151f}.connection-editor__dock-link--new{border-color:#fb923ca3;background:linear-gradient(90deg,#fb923c2e,#a855f729,#0ea5e91f),#0f172ac2;box-shadow:0 12px 34px #02061752,0 0 30px #fb923c2e;animation:new-dock-link-flash 1.35s ease-out forwards}.connection-editor__dock-link--error{border-color:#ef444461}.connection-editor__dock-jump{min-width:62px;min-height:30px;padding:0 10px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 54%,transparent);color:var(--pce-primary);cursor:pointer;font-size:.66rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__dock-jump:hover,.connection-editor__dock-jump:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 56%,transparent);background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 18%,transparent);outline:none}.connection-editor__dock-link-kind{display:inline-flex;align-items:center;gap:7px;min-width:0;color:var(--pce-muted);font-size:.66rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-link-kind span{width:8px;height:8px;border-radius:999px;background:#b46cff;box-shadow:0 0 14px #b46cff7a}.connection-editor__dock-link--state .connection-editor__dock-link-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2f94}.connection-editor__dock-link--state-read .connection-editor__dock-link-kind span{background:#8b7dff;box-shadow:0 0 13px #8b7dff75}.connection-editor__dock-link--projection .connection-editor__dock-link-kind span{background:#19c8e8;box-shadow:0 0 10px #19c8e857}.connection-editor__dock-link--event-propagation .connection-editor__dock-link-kind span{background:#ffb454;box-shadow:0 0 15px #ffb45485}.connection-editor__dock-link--policy .connection-editor__dock-link-kind span{outline:1px solid rgba(34,197,94,.76);outline-offset:2px;box-shadow:0 0 16px #22c55e61}.connection-editor__dock-link--policy:not(.connection-editor__dock-link--state,.connection-editor__dock-link--state-read,.connection-editor__dock-link--projection,.connection-editor__dock-link--event-propagation) .connection-editor__dock-link-kind span{background:#22c55e}.connection-editor__dock-link-route{display:inline-flex;align-items:center;gap:8px;min-width:0}.connection-editor__dock-link-chip{min-width:0;overflow:hidden;padding:4px 8px;border-radius:999px;border:1px solid var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-soft) 72%,transparent);color:var(--pce-fg);font-size:.72rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-chip--from{border-color:#ff9f2f66;color:#ffbd62}.connection-editor__dock-link-chip--to{border-color:#19c8e83d;color:#7dddeb}:host-context(.theme-light) .connection-editor__dock-link-chip--from{border-color:color-mix(in srgb,var(--pce-tertiary) 46%,transparent);color:#8a4600}:host-context(.theme-light) .connection-editor__dock-link-chip--to{border-color:color-mix(in srgb,var(--pce-primary) 34%,transparent);color:#075f73}.connection-editor__dock-link-arrow{flex:0 0 auto;color:var(--pce-muted);font-weight:900}.connection-editor__dock-link-id{min-width:0;overflow:hidden;color:var(--pce-muted);font-size:.66rem;font-weight:800;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-badges{display:inline-flex;justify-content:flex-end;gap:5px;min-width:70px}.connection-editor__dock-link-badges span{padding:3px 7px;border-radius:999px;background:#a855f724;color:#d8b4fe;font-size:.62rem;font-weight:900;text-transform:uppercase;white-space:nowrap}:host-context(.theme-light) .connection-editor__dock-link-badges span{background:color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-surface-soft));color:#6d2a9f}.connection-editor__dock-empty{padding:12px;border-radius:12px;border:1px dashed var(--pce-outline);color:var(--pce-muted);font-size:.76rem;font-weight:700}.connection-editor__inspector{border-color:color-mix(in srgb,var(--pce-primary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 10%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface)}.connection-editor__eyebrow,.connection-editor__section-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--pce-muted);font-weight:700}.connection-editor__title{font-size:1.02rem;font-weight:800}.connection-editor__subtitle,.connection-editor__item-copy,.connection-editor__item-meta,.connection-editor__details-row span,.connection-editor__details-label,.connection-editor__empty{color:var(--pce-muted);font-size:.84rem}.connection-editor__inspector-heading{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--pce-surface-soft);border:1px solid var(--pce-outline)}.connection-editor__inspector-heading strong{color:var(--pce-strong);font-size:.96rem;overflow-wrap:anywhere}.connection-editor__inspector-heading span{color:var(--pce-primary);font-size:.76rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}.connection-editor__human-summary{display:grid;gap:6px;padding:12px;border-radius:14px;border:1px solid color-mix(in srgb,var(--pce-primary) 24%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface-soft);color:var(--pce-fg);line-height:1.35}.connection-editor__nested-summary{display:grid;gap:6px;padding:10px;border-radius:12px;border:1px solid color-mix(in srgb,var(--pce-primary) 22%,transparent);background:color-mix(in srgb,var(--pce-primary) 8%,var(--pce-surface-soft))}.connection-editor__nested-summary strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__nested-summary span:last-child{color:var(--pce-primary);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.72rem;overflow-wrap:anywhere}.connection-editor__recommended{border-color:color-mix(in srgb,var(--pce-secondary) 32%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 14%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface)}.connection-editor__recommended-card{display:grid;gap:8px;width:100%;padding:13px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 36%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 16%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__recommended-card:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 52%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 22%,transparent),color-mix(in srgb,var(--pce-primary) 14%,transparent)),var(--pce-surface-strong)}.connection-editor__recommended-card strong{color:var(--pce-strong);font-size:.92rem;line-height:1.28}.connection-editor__recommended-card span:not(.connection-editor__human-summary-label):not(.connection-editor__suggestion-action),.connection-editor__recommended-card small{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__success{display:grid;gap:4px;padding:10px 12px;border-radius:14px;border:1px solid rgba(34,197,94,.34);background:#22c55e1f;color:var(--pce-fg);line-height:1.35}.connection-editor__success strong{color:#bbf7d0;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__success span{color:var(--pce-strong);font-size:.82rem}.connection-editor__human-summary-label,.connection-editor__suggestion-intent{justify-self:start;padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:#bae6fd;font-size:.66rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__human-summary strong{color:var(--pce-strong);font-size:.88rem}.connection-editor__human-summary span:last-child,.connection-editor__suggestion-preview{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__technical-details{display:grid;gap:10px;padding:10px 12px;border-radius:14px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__technical-details summary{cursor:pointer;color:var(--pce-muted);font-size:.78rem;font-weight:800}.connection-editor__technical-details[open] summary{margin-bottom:10px;color:var(--pce-strong)}.connection-editor__inspector-ports{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__inspector-port{max-width:100%;padding:4px 8px;border-radius:999px;border:1px solid rgba(148,163,184,.16);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-editor__inspector-port--input{border-color:#22d3ee57;color:#67e8f9}.connection-editor__inspector-port--output{border-color:#f59e0b57;color:#fbbf24}.connection-editor__inspector-port--state{border-color:#a855f761;color:#d8b4fe}.connection-editor__segment-kind-legend{display:grid;gap:10px;padding:12px;border-radius:16px;border:1px solid rgba(148,163,184,.14);background:linear-gradient(135deg,#0f172aa8,#080d1885),#02061757}.connection-editor__segment-kind-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.connection-editor__segment-kind-pill{min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:900;overflow:hidden;white-space:nowrap}.connection-editor__segment-kind-pill span{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:currentColor;box-shadow:0 0 12px currentColor}.connection-editor__segment-kind-pill--input{border-color:#19c8e83d;color:#7dddeb}.connection-editor__segment-kind-pill--output{border-color:#ff9f2f61;color:#ffbd62}.connection-editor__segment-kind-pill--state{border-color:#b46cff61;color:#d9b8ff}:host-context(.theme-light) .connection-editor__segment-kind-pill{border-color:var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-strong) 88%,transparent)}:host-context(.theme-light) .connection-editor__segment-kind-pill--input{color:#075f73}:host-context(.theme-light) .connection-editor__segment-kind-pill--output{color:#8a4600}:host-context(.theme-light) .connection-editor__segment-kind-pill--state{color:#6d2a9f}.connection-editor__stage{grid-column:1;grid-row:2;position:relative;min-height:0;height:100%;overflow:visible;border-radius:16px;border:1px solid var(--pce-outline);background:radial-gradient(circle at center,color-mix(in srgb,var(--pce-secondary) 7%,transparent),transparent 38%),radial-gradient(circle,var(--pce-grid) 1px,transparent 1.5px),var(--pce-stage-bg);background-size:auto,31px 31px,auto;box-shadow:inset 0 0 0 1px var(--pce-glass-highlight);cursor:grab;touch-action:none}.connection-editor__stage--panning,.connection-editor__stage:active{cursor:grabbing}.connection-editor__stage--dragging{cursor:crosshair}.connection-editor__stage--rotating{cursor:grabbing}.connection-editor__viewport{position:absolute;inset-block-start:0;inset-inline-start:0;width:900px;height:540px;overflow:visible;transform-origin:0 0;transition:transform .14s ease}.connection-editor__wires{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.connection-editor__wire,.connection-editor__wire-hit{fill:none;stroke-linecap:round}.connection-editor__wire{stroke:#b46cff;stroke-width:1.45;stroke-opacity:.48;pointer-events:none;filter:url(#connection-glow);stroke-dasharray:10 8;animation:connection-flow 1.65s linear infinite}.connection-editor__wire-hit{stroke:transparent;stroke-width:18;cursor:pointer;pointer-events:stroke}.connection-editor__wire-hit--active{stroke-width:28}.connection-editor__wire--halo{stroke:#b46cff1f;stroke-width:7;stroke-dasharray:none;animation:none}.connection-editor__wire--state{stroke:#ff9f2f;stroke-width:2.25;stroke-dasharray:8 7;animation:connection-flow .92s linear infinite}.connection-editor__wire--state.connection-editor__wire--halo{stroke:#ff9f2f29;stroke-width:11}.connection-editor__wire--projection{stroke:#15b8d8;stroke-width:1.75;stroke-dasharray:20 8;animation:connection-flow 1.9s linear infinite}.connection-editor__wire--projection.connection-editor__wire--halo{stroke:#15b8d81a;stroke-width:7}.connection-editor__wire--state-read{stroke:#8b7dff;stroke-width:1.65;stroke-dasharray:3 11;animation:connection-flow 2.25s linear infinite reverse}.connection-editor__wire--state-read.connection-editor__wire--halo{stroke:#8b7dff21;stroke-width:8}.connection-editor__wire--event-propagation{stroke:#ffb454;stroke-width:2.05;stroke-dasharray:5 7;animation:connection-flow .78s linear infinite}.connection-editor__wire--event-propagation.connection-editor__wire--halo{stroke:#ffb4542e;stroke-width:10}.connection-editor__wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.2)) url(#connection-glow)}.connection-editor__wire--policy.connection-editor__wire--halo{stroke:#22c55e1f;stroke-width:13}.connection-editor__wire--warning{stroke:#ff9f2f}.connection-editor__wire--warning.connection-editor__wire--halo{stroke:#ff9f2f2e}.connection-editor__wire--error{stroke:#ef4444}.connection-editor__wire--error.connection-editor__wire--halo{stroke:#ef44442e}.connection-editor__wire--active{stroke:#d9b8ff;stroke-width:3;stroke-opacity:1;stroke-dasharray:5 7;animation-duration:.58s}.connection-editor__wire--halo.connection-editor__wire--active{stroke-width:16;stroke-opacity:.8;animation:selected-wire-aura 1.35s ease-in-out infinite}.connection-editor__wire--new{stroke-width:3.4;stroke-opacity:1;stroke-dasharray:640;stroke-dashoffset:640;animation:wire-draw-in .62s cubic-bezier(.16,1,.3,1) forwards,connection-flow 1.05s linear .62s infinite}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:22;stroke-opacity:0;animation:new-wire-halo 1.45s ease-out forwards}.connection-editor__wire--trace{stroke:#9b5cff;stroke-width:3.2;stroke-opacity:1;stroke-dasharray:7 6;animation:connection-flow .72s linear infinite,trace-wire-pulse 1.18s ease-in-out infinite}.connection-editor__wire--halo.connection-editor__wire--trace{stroke:#9b5cff57;stroke-width:18;stroke-opacity:.86;animation:trace-halo-pulse 1.18s ease-in-out infinite}.connection-editor__wire--mode-dimmed{stroke-opacity:.14;stroke-width:1.05;filter:none;animation-duration:2.6s}.connection-editor--guided .connection-editor__wire:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.85;filter:none;animation:none}.connection-editor--guided .connection-editor__wire--halo:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.08;animation:none}.connection-editor__wire--halo.connection-editor__wire--mode-dimmed{stroke-opacity:.05;stroke-width:5;animation:none}.connection-editor__wire-hit--mode-dimmed{stroke-width:12}.connection-editor__wire-endpoint{fill:#f8fafc;stroke:#0f172ae6;stroke-width:1.5;filter:drop-shadow(0 0 8px rgba(216,180,254,.8));pointer-events:none;animation:endpoint-pulse 1.2s ease-in-out infinite}.connection-editor__wire-endpoint--source{fill:#ff9f2f}.connection-editor__wire-endpoint--target{fill:#19c8e8}.connection-editor__connection-tooltip{position:absolute;z-index:6;width:min(312px,calc(100% - 24px));display:grid;gap:8px;padding:12px 14px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(135deg,var(--pce-surface-strong),var(--pce-surface)),var(--pce-surface-strong);box-shadow:0 18px 44px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);color:var(--pce-fg);pointer-events:none;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .14s ease-out}.connection-editor__connection-tooltip-callout{position:absolute;inset-block-start:100%;inset-inline-start:var(--connection-tooltip-callout-x, 42px);width:2px;height:28px;border-radius:999px;background:linear-gradient(180deg,#e2e8f0bd,#19c8e800);box-shadow:0 0 12px #19c8e852;transform:translate(-1px);pointer-events:none}.connection-editor__connection-tooltip-callout:before,.connection-editor__connection-tooltip-callout:after{content:\"\";position:absolute;border-radius:999px;pointer-events:none}.connection-editor__connection-tooltip-callout:before{inset-block-start:-5px;inset-inline-start:-5px;width:12px;height:12px;border:1px solid rgba(148,163,184,.24);background:#080d18f5;box-shadow:inset 0 1px #ffffff14}.connection-editor__connection-tooltip-callout:after{inset-block-end:-3px;inset-inline-start:-4px;width:10px;height:10px;background:#19c8e8;box-shadow:0 0 16px #19c8e88f}.connection-editor__connection-tooltip--projection{border-color:#19c8e833;background:linear-gradient(135deg,#15b8d81f,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state{border-color:#ff9f2f66;background:linear-gradient(135deg,#ff9f2f3d,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout{background:linear-gradient(180deg,#ffbd62d1,#ff9f2f00);box-shadow:0 0 14px #ff9f2f61}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout:after{background:#ff9f2f;box-shadow:0 0 18px #ff9f2fad}.connection-editor__connection-tooltip--error{border-color:#f871716b}.connection-editor__connection-tooltip--error .connection-editor__connection-tooltip-callout:after{background:#fb7185;box-shadow:0 0 18px #fb7185ad}.connection-editor__connection-tooltip-kind{display:inline-flex;align-items:center;gap:8px;color:#94a3b8;font-size:.62rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__connection-tooltip-kind span{width:8px;height:8px;border-radius:999px;background:#19c8e8;box-shadow:0 0 12px #19c8e880}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2fc7}.connection-editor__connection-tooltip-row{min-width:0;display:grid;grid-template-columns:54px minmax(0,1fr);align-items:center;gap:8px;min-height:28px;padding:0 10px;border-radius:999px;background:#0f172a94}.connection-editor__connection-tooltip-row span{color:#8d9bb0;font-size:.62rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.connection-editor__connection-tooltip-row strong{min-width:0;overflow:hidden;color:#e2e8f0;font-size:.75rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__connection-tooltip-badges{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__connection-tooltip-badges span{padding:3px 8px;border-radius:999px;background:#02061799;color:#fbbf24;font-size:.66rem;font-weight:900}.connection-editor__trace-overlay{position:absolute;z-index:6;inset-block-start:16px;inset-inline-start:50%;width:min(560px,calc(100% - 360px));min-width:320px;padding:12px 14px;border-radius:16px;border:1px solid rgba(34,197,94,.26);background:linear-gradient(135deg,#22c55e1f,#0ea5e91a),#080d18f0;box-shadow:0 22px 56px #02061775,0 0 42px #22c55e1f;transform:translate(-50%);pointer-events:auto;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .16s ease-out}.connection-editor__trace-overlay-head,.connection-editor__trace-overlay-route{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.connection-editor__trace-overlay-head span,.connection-editor__trace-overlay-route span{color:#86efac;font-size:.66rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap}.connection-editor__trace-overlay-head strong{color:#cbd5e1;font-size:.7rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace}.connection-editor__trace-overlay-route{margin-top:6px}.connection-editor__trace-overlay-controls{display:grid;grid-template-columns:28px minmax(0,1fr) 28px;align-items:center;gap:8px;margin-top:10px}.connection-editor__trace-overlay-button{width:28px;height:24px;display:inline-grid;place-items:center;border:1px solid rgba(148,163,184,.18);border-radius:999px;background:#0206176b;color:#e2e8f0;cursor:pointer;font-size:1rem;font-weight:900;line-height:1;transition:border-color .15s ease,background .15s ease,color .15s ease,opacity .15s ease}.connection-editor__trace-overlay-button:hover:not(:disabled){border-color:#22d3ee6b;background:#0ea5e929;color:#f8fafc}.connection-editor__trace-overlay-button:disabled{cursor:default;opacity:.36}.connection-editor__trace-overlay-steps{min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto;padding:2px;scrollbar-width:none}.connection-editor__trace-overlay-steps::-webkit-scrollbar{display:none}.connection-editor__trace-overlay-step{position:relative;flex:1 0 28px;min-width:28px;height:22px;border:1px solid rgba(148,163,184,.16);border-radius:999px;background:#0f172a9e;color:#94a3b8;cursor:pointer;font-size:.62rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__trace-overlay-step--active{border-color:#22d3eea3;background:linear-gradient(90deg,#22d3ee3d,#9b5cff33);color:#f8fafc;box-shadow:0 0 18px #22d3ee33}.connection-editor__trace-overlay-step--blocked{border-color:#fb71855c;color:#fecdd3}.connection-editor__trace-overlay-route strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.82rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__trace-overlay-bar{position:relative;height:5px;margin-top:10px;overflow:hidden;border-radius:999px;background:#94a3b829}.connection-editor__trace-overlay-bar span{position:absolute;inset-block:0;inset-inline-start:0;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#22d3ee);box-shadow:0 0 18px #22c55e61;min-width:8%}.connection-editor__drag-wire{fill:none;stroke:#94a3b8;stroke-width:2.4;stroke-linecap:round;stroke-dasharray:6 7;pointer-events:none;filter:url(#connection-glow);animation:connection-flow 1.05s linear infinite,drag-wire-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--halo{stroke:#94a3b829;stroke-width:14;stroke-dasharray:none;animation:drag-halo-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--valid{stroke:#22c55e}.connection-editor__drag-wire--halo.connection-editor__drag-wire--valid{stroke:#22c55e47}.connection-editor__drag-endpoint{fill:#94a3b8;stroke:#020617eb;stroke-width:2;pointer-events:none;filter:url(#connection-glow);transform-box:fill-box;transform-origin:center;animation:endpoint-pulse 1s ease-in-out infinite}.connection-editor__drag-endpoint--source{fill:#ff9f2f}.connection-editor__drag-endpoint--target{fill:#7dddeb}.connection-editor__drag-endpoint--valid{fill:#22c55e;stroke:#bbf7d0e0}.connection-editor__wire-handle-line{stroke-width:2;stroke-linecap:round;stroke-dasharray:4 5;pointer-events:none;opacity:.88;filter:url(#connection-glow)}.connection-editor__wire-handle-line--source{stroke:#ff9f2ff0}.connection-editor__wire-handle-line--target{stroke:#19c8e8c2}.connection-editor__wire-control{fill:#0f172af5;stroke:#cbd5e1c7;stroke-width:1.8;pointer-events:none;filter:url(#connection-glow)}.connection-editor__wire-label{pointer-events:none;filter:drop-shadow(0 0 10px rgba(2,6,23,.44));animation:tooltip-rise .14s ease-out}.connection-editor__wire-label rect{fill:#080d18eb;stroke-width:1}.connection-editor__wire-label text{fill:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__wire-label--source rect{stroke:#ff9f2fad}.connection-editor__wire-label--target rect{stroke:#19c8e86b}.connection-editor__zoom-controls{position:absolute;inset-inline-start:14px;inset-block-start:14px;z-index:4;display:grid;grid-template-columns:max-content;gap:6px;width:46px;pointer-events:auto}.connection-editor__tool-group,.connection-editor__trace-source{display:grid;gap:6px;padding:6px;border-radius:12px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:0 16px 36px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__tool-group{grid-template-columns:30px;width:max-content}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:30px}.connection-editor__arrange-button{width:34px;min-height:34px;display:inline-flex;align-items:center;justify-content:center;gap:0;padding:0;border-radius:999px;border:1px solid rgba(168,85,247,.34);background:linear-gradient(90deg,#a855f72e,#22d3ee1f);color:#e9d5ff;font-size:0;font-weight:800;letter-spacing:0;cursor:pointer;opacity:1;transform:scale(1);transition:opacity .14s ease,transform .14s ease,border-color .14s ease,background .14s ease}.connection-editor--guided .connection-editor__arrange-button{opacity:.34;transform:scale(.9);border-color:color-mix(in srgb,var(--pce-outline) 82%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 84%,transparent)}.connection-editor--guided .connection-editor__zoom-controls:hover .connection-editor__arrange-button,.connection-editor--guided .connection-editor__zoom-controls:focus-within .connection-editor__arrange-button,.connection-editor--guided .connection-editor__arrange-button:hover,.connection-editor--guided .connection-editor__arrange-button:focus-visible,.connection-editor--guided .connection-editor__arrange-button--active{opacity:1;transform:scale(1);border-color:#a855f757;background:linear-gradient(90deg,#a855f72e,#22d3ee1f)}.connection-editor__arrange-button span{color:#c084fc;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.78rem;font-weight:900}.connection-editor__tool-button{width:30px;height:30px;border-radius:999px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.9rem;font-weight:800;letter-spacing:.02em;cursor:pointer;line-height:1}.connection-editor__tool-button:hover:not(:disabled){border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);color:var(--pce-primary);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 16%,transparent)}.connection-editor__history-button:disabled{cursor:not-allowed;opacity:.42}.connection-editor__arrange-button--active{border-color:#22d3ee94;background:linear-gradient(90deg,#0ea5e93d,#22d3ee2e);color:#cffafe}.connection-editor__trace-source{gap:4px;max-height:230px;overflow:auto}.connection-editor__trace-source-title{padding:2px 4px 6px;color:var(--pce-muted);font-size:.64rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.connection-editor__trace-source-item{min-width:0;min-height:30px;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:8px;background:transparent;color:var(--pce-fg);cursor:pointer;font-size:.74rem;font-weight:800;text-align:start}.connection-editor__trace-source-item span{color:#f59e0b;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__trace-source-item:hover,.connection-editor__trace-source-item--active{background:var(--pce-surface-strong);color:var(--pce-strong);box-shadow:inset 3px 0 #f59e0bd1}.connection-editor__minimap{position:absolute;inset-inline-end:14px;inset-block-end:14px;z-index:4;width:184px;height:124px;padding:18px 10px 10px;overflow:hidden;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-primary) 30%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),var(--pce-surface-strong)),var(--pce-surface);box-shadow:0 20px 48px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);cursor:pointer;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);opacity:1;transform:scale(1);transform-origin:100% 100%;transition:opacity .16s ease,transform .16s ease,border-color .16s ease,box-shadow .16s ease}.connection-editor--guided .connection-editor__minimap{opacity:.54;transform:scale(.88);border-color:color-mix(in srgb,var(--pce-outline) 64%,transparent);box-shadow:0 14px 34px color-mix(in srgb,var(--pce-shadow-soft) 70%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor--guided .connection-editor__minimap:hover,.connection-editor--guided .connection-editor__minimap:focus-visible,.connection-editor--guided .connection-editor__minimap--panning{opacity:1;transform:scale(1)}.connection-editor__minimap:hover,.connection-editor__minimap--panning{border-color:#22d3ee75;box-shadow:0 20px 48px var(--pce-shadow-soft),0 0 24px color-mix(in srgb,var(--pce-primary) 14%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__minimap--panning{cursor:grabbing}.connection-editor__minimap:before{content:\"\";position:absolute;inset:22px 10px 10px;border-radius:10px;background-image:radial-gradient(circle,rgba(125,211,252,.18) 1px,transparent 1px);background-size:22px 22px;opacity:.58;pointer-events:none}.connection-editor__minimap-title{position:absolute;inset-block-start:7px;inset-inline-start:12px;color:var(--pce-muted);font-size:.6rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__minimap svg{position:relative;width:100%;height:100%;display:block;overflow:visible}.connection-editor__minimap-wire{fill:none;stroke:#b46cff8f;stroke-width:4;stroke-linecap:round;opacity:.86}.connection-editor__minimap-wire--state{stroke:#ff9f2fdb}.connection-editor__minimap-wire--state-read{stroke:#8b7dffb8;stroke-dasharray:4 9}.connection-editor__minimap-wire--projection{stroke:#19c8e88a;stroke-dasharray:18 8}.connection-editor__minimap-wire--event-propagation{stroke:#ffb454cc;stroke-dasharray:6 7}.connection-editor__minimap-wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.28))}.connection-editor__minimap-wire--trace{stroke:#9b5cffe0;stroke-width:5;stroke-dasharray:12 9;animation:connection-flow 1s linear infinite}.connection-editor__minimap-wire--active{stroke:#facc15eb;stroke-width:6;filter:drop-shadow(0 0 8px rgba(250,204,21,.38))}.connection-editor__minimap-wire--mode-dimmed{opacity:.2;stroke-width:2.6;filter:none}.connection-editor__minimap-node{fill:#f59e0be0;stroke:#020617db;stroke-width:4;filter:drop-shadow(0 0 7px rgba(245,158,11,.24))}.connection-editor__minimap-node--state{fill:#a855f7e6;filter:drop-shadow(0 0 8px rgba(168,85,247,.34))}.connection-editor__minimap-node--selected{fill:#facc15f5;stroke:#fef08aeb;filter:drop-shadow(0 0 10px rgba(250,204,21,.42))}.connection-editor__minimap-node--trace-source{fill:#facc15f5;filter:drop-shadow(0 0 10px rgba(250,204,21,.44))}.connection-editor__minimap-node--trace-reacting{fill:#22c55eeb;filter:drop-shadow(0 0 10px rgba(34,197,94,.42))}.connection-editor__minimap-node--mode-dimmed{opacity:.28;filter:none}.connection-editor__minimap-viewport{fill:#7dd3fc1f;stroke:#7dd3fce6;stroke-width:5;stroke-dasharray:18 10;filter:drop-shadow(0 0 10px rgba(125,211,252,.3));transition:x .12s ease,y .12s ease,width .12s ease,height .12s ease}.connection-editor__minimap--panning .connection-editor__minimap-viewport{fill:#22d3ee2e;stroke:#22d3eef5;stroke-dasharray:none}.connection-editor__node{position:absolute;z-index:10;width:168px;height:168px;transform:translate(-84px,-84px);border:0;padding:0;background:transparent;color:inherit;cursor:pointer;transition:filter .16s ease}.connection-editor__node--dragging{cursor:grabbing;filter:drop-shadow(0 0 22px rgba(34,211,238,.26));z-index:12}.connection-editor__node--connection-focus{filter:drop-shadow(0 0 16px rgba(34,211,238,.2))}.connection-editor__node--compat-target .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e66,0 0 0 18px #22c55e0b,0 0 32px #22c55e29}.connection-editor__node--mode-dimmed{opacity:.42;filter:grayscale(.22) saturate(.56)}.connection-editor__node--quiet{opacity:.58;filter:saturate(.68) brightness(.86)}.connection-editor__node--mode-dimmed .connection-editor__node-ring{animation:none;box-shadow:0 0 0 1px #2dd4bf14,0 0 14px #0ea5e90f}.connection-editor__node--mode-dimmed .connection-editor__node-halo{stroke-opacity:.28}.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-svg{position:absolute;inset:0}.connection-editor__node-ring,.connection-editor__node-core{display:grid;place-items:center;clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}.connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from -28deg,#06b6d4b3 0 28%,#f59e0b9e 28% 48%,#a855f780 48% 68%,#06b6d4a3 68% 100%);box-shadow:0 0 0 1px #2dd4bf2e,0 0 26px #0ea5e929;animation:node-breathe 2.8s ease-in-out infinite}.connection-editor__node-svg{overflow:visible;filter:drop-shadow(0 0 16px rgba(14,165,233,.16))}.connection-editor__node-halo{fill:transparent;stroke:#38bdf838;stroke-width:1;stroke-dasharray:0;pointer-events:none}.connection-editor__node-halo:nth-child(2){stroke:#38bdf824}.connection-editor__node-halo:nth-child(3){stroke:#94a3b81a}.connection-editor__node-segment{fill-opacity:.28;stroke-opacity:.72;stroke-width:1.15;transition:fill-opacity .16s ease,stroke-opacity .16s ease,stroke-width .16s ease;cursor:grab}.connection-editor__node:hover .connection-editor__node-segment,.connection-editor__node--selected .connection-editor__node-segment,.connection-editor__node--connection-focus .connection-editor__node-segment{fill-opacity:.54;stroke-opacity:.95;stroke-width:1.55}.connection-editor__node-segment--connection-focus{fill-opacity:.76;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 8px rgba(34,211,238,.76));animation:segment-focus-sweep 1.45s ease-in-out infinite}.connection-editor__node-segment--source{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 12px rgba(251,146,60,.82))}.connection-editor__node-segment--compatible{fill-opacity:.74;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 10px rgba(34,197,94,.72));animation:snap-pulse 1s ease-in-out infinite}.connection-editor__node-segment--compat-preview{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 13px rgba(245,158,11,.78))}.connection-editor__node-segment--candidate{fill-opacity:.92;stroke-opacity:1;stroke-width:2.8;filter:drop-shadow(0 0 16px rgba(34,197,94,.86))}.connection-editor__node-segment--incompatible{fill-opacity:.12;stroke-opacity:.28;cursor:not-allowed}.connection-editor__node-segment--invalid-drop{fill-opacity:.72;stroke:#fb7185;stroke-opacity:1;stroke-width:3;filter:drop-shadow(0 0 16px rgba(244,63,94,.84));animation:invalid-drop-jolt .36s ease-out}.connection-editor__node-segment--state{fill-opacity:.44;filter:drop-shadow(0 0 8px rgba(180,108,255,.2))}.connection-editor__node-segment--mode-dimmed{fill-opacity:.08;stroke-opacity:.2;stroke-width:.9;filter:none}.connection-editor__node-anchor{opacity:.95;filter:drop-shadow(0 0 6px currentColor)}.connection-editor__node-rotate-handle{cursor:grab;opacity:0;pointer-events:none;transition:opacity .16s ease,filter .16s ease;filter:drop-shadow(0 0 8px rgba(34,211,238,.28))}.connection-editor__node:hover .connection-editor__node-rotate-handle,.connection-editor__node--selected .connection-editor__node-rotate-handle,.connection-editor__node--rotating .connection-editor__node-rotate-handle{opacity:1;pointer-events:auto}.connection-editor__node--rotating .connection-editor__node-rotate-handle{cursor:grabbing;filter:drop-shadow(0 0 12px rgba(34,211,238,.54))}.connection-editor__node-rotate-hit{fill:transparent}.connection-editor__node-rotate-dot{fill:var(--pce-surface-strong);stroke:var(--pce-primary);stroke-opacity:.88;stroke-width:1.4}.connection-editor__node-rotate-arc,.connection-editor__node-rotate-arrow{fill:none;stroke:var(--pce-primary);stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.96;stroke-width:1.2;pointer-events:none}.connection-editor__segment-icon,.connection-editor__segment-label{pointer-events:none;fill:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:800;paint-order:stroke;stroke:#020617c2;stroke-width:3px;stroke-linejoin:round}.connection-editor__segment-icon{font-size:12px;fill:#19c8e8;opacity:1;transition:opacity .14s ease}.connection-editor__segment-icon--output{fill:#ff9f2f}.connection-editor--guided .connection-editor__segment-icon:not(.connection-editor__segment-icon--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-icon{opacity:0}.connection-editor__segment-label{font-size:9.5px;letter-spacing:0;fill:#e2e8f0e0;opacity:1;transition:opacity .14s ease}.connection-editor--guided .connection-editor__segment-label:not(.connection-editor__segment-label--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-label{opacity:0}.connection-editor__node-core{inset:43px;padding:12px;border-radius:999px;clip-path:none;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(circle at center,#111827 0 58%,#060b14);border:1px solid rgba(226,232,240,.1);box-shadow:0 12px 28px #00000073,inset 0 1px #ffffff0d;color:#f8fafc;text-shadow:0 1px 2px rgba(0,0,0,.62)}.connection-editor__node-icon{display:block;max-width:44px;overflow:hidden;color:#f8fafc;font-family:Material Symbols Outlined,Material Icons,sans-serif;font-size:1.22rem;font-weight:400;line-height:1;text-align:center;text-transform:none;letter-spacing:0;white-space:nowrap;filter:drop-shadow(0 0 10px rgba(226,232,240,.18))}.connection-editor__node--state .connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from 14deg,#a855f7c7 0 42%,#7e3af26b 42% 78%,#f59e0b47 78% 100%);box-shadow:0 0 0 1px #a855f738,0 0 30px #a855f733}.connection-editor__node--selected .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15bd,0 0 34px #facc153d}.connection-editor__node--connection-focus .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eead,0 0 38px #22d3ee42;animation:node-focus-breathe 1.7s ease-in-out infinite}.connection-editor__node--trace-source .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 0 18px #facc150f,0 0 54px #facc154d;animation:trace-source-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:before{content:\"\";position:absolute;z-index:0;inset:-44px;border-radius:999px;border:2px solid rgba(250,204,21,.36);background:radial-gradient(circle at center,transparent 0 64%,rgba(250,204,21,.05) 65% 66%,transparent 67%),conic-gradient(from -20deg,#facc1500,#facc1552,#facc1500);box-shadow:0 0 36px #facc151f;opacity:.92;pointer-events:none;animation:trace-source-orbit 2.8s linear infinite}.connection-editor__node--trace-reacting .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e94,0 0 46px #22c55e38;animation:trace-reacting-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:after,.connection-editor__node--trace-reacting:after{position:absolute;z-index:3;inset-inline-start:50%;inset-block-start:-42px;padding:0;border:0;background:transparent;color:#facc15;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.68rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase;transform:translate(-50%);text-shadow:0 0 12px rgba(250,204,21,.52);pointer-events:none}.connection-editor__node--trace-source:after{content:attr(data-trace-label)}.connection-editor__node--trace-reacting:after{content:attr(data-trace-label);color:#86efac;text-shadow:0 0 12px rgba(34,197,94,.44)}.connection-editor__node--trace-source .connection-editor__node-segment--output{fill-opacity:.66;stroke-width:2.2;filter:drop-shadow(0 0 14px rgba(255,159,47,.42))}.connection-editor__node--expanded .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eebd,0 0 34px #22d3ee3d}.connection-editor__node--rotating .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 42px #facc1547;animation:node-focus-breathe 1.1s ease-in-out infinite}.connection-editor__node--rotating .connection-editor__node-segment{fill-opacity:.68;stroke-opacity:1;stroke-width:1.9;cursor:grabbing}.connection-editor__node-title,.connection-editor__node-subtitle{display:block;max-width:92px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.connection-editor__node-title{color:#f8fafc;font-size:.82rem;font-weight:800}.connection-editor__node-subtitle{margin-top:4px;color:#a7b4c8;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__ports{position:absolute;z-index:30;display:grid;gap:6px;width:104px;opacity:0;pointer-events:none;transform:translateY(3px);transition:opacity .16s ease,transform .16s ease}.connection-editor__ports--visible{opacity:1;pointer-events:auto;transform:translateY(0)}.connection-editor__ports--outputs{z-index:42}.connection-editor__ports--inputs{z-index:36}.connection-editor__segment-popover{position:absolute;z-index:80;width:292px;max-height:320px;overflow:auto;display:grid;gap:10px;padding:14px;border-radius:16px;border:1px solid rgba(148,163,184,.18);background:linear-gradient(135deg,#0f172af5,#110c20f0),#090c16eb;box-shadow:0 28px 72px #0000007a,0 0 48px #a855f71a,inset 0 1px #ffffff0d;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__segment-popover-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:2px}.connection-editor__segment-popover-title{color:#94a3b8;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}.connection-editor__segment-popover-hint{margin-top:5px;color:#64748b;font-size:.66rem;font-weight:700}.connection-editor__segment-rotation{flex:0 0 auto;min-width:54px;padding:5px 8px;border-radius:999px;border:1px solid rgba(34,211,238,.28);background:#082f4957;color:#7dd3fc;font-size:.66rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-align:center;box-shadow:inset 0 0 16px #0ea5e914}.connection-editor__segment-row{display:grid;grid-template-columns:28px 72px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:40px;padding:7px;border-radius:12px;border:1px solid rgba(148,163,184,.12);background:linear-gradient(90deg,#0f172ac7,#0f172a75),#0f172a99;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__segment-row--input{border-color:#22d3ee42}.connection-editor__segment-row--output{border-color:#f59e0b47}.connection-editor__segment-row--state{border-color:#a855f74d}.connection-editor__segment-row--source,.connection-editor__segment-row--candidate{transform:translate(2px);box-shadow:0 0 22px #f59e0b24,inset 0 0 20px #f59e0b14}.connection-editor__segment-row--compatible{border-color:#22d3ee6b;box-shadow:inset 0 0 18px #22d3ee14}.connection-editor__segment-row--compat-preview{border-color:#f59e0b94;background:linear-gradient(90deg,#f59e0b1f,#0f172a8a),#0f172ab3;box-shadow:0 0 22px #f59e0b1f,inset 0 0 18px #f59e0b14}.connection-editor__segment-row--invalid-drop{border-color:#fb7185b3;background:linear-gradient(90deg,#f43f5e24,#0f172a94),#0f172ab3;box-shadow:0 0 24px #f43f5e2e,inset 0 0 18px #f43f5e1a;animation:invalid-drop-jolt .36s ease-out}.connection-editor__segment-index{color:#64748b;font-size:.64rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;letter-spacing:.08em}.connection-editor__segment-kind{display:inline-flex;align-items:center;gap:6px;color:#94a3b8;font-size:.62rem;font-weight:800;text-transform:uppercase;min-width:0;white-space:nowrap}.connection-editor__segment-kind-dot{width:7px;height:7px;border-radius:999px;background:#94a3b8;box-shadow:0 0 12px #94a3b847}.connection-editor__segment-row--input .connection-editor__segment-kind-dot{background:#22d3ee;box-shadow:0 0 12px #22d3ee61}.connection-editor__segment-row--output .connection-editor__segment-kind-dot{background:#fb923c;box-shadow:0 0 12px #fb923c66}.connection-editor__segment-row--state .connection-editor__segment-kind-dot{background:#a855f7;box-shadow:0 0 12px #a855f76b}.connection-editor__segment-label{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;color:#e2e8f0;font-size:.74rem;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-badge{flex:0 0 auto;padding:2px 5px;border-radius:999px;border:1px solid rgba(56,189,248,.28);background:#0ea5e91a;color:#bae6fd;font-size:.55rem;font-weight:900;text-transform:uppercase}.connection-editor__segment-path{grid-column:3 / 4;min-width:0;margin-top:-5px;overflow:hidden;color:#93c5fd;font-size:.62rem;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-row--nested{min-height:56px;border-color:#38bdf84d;background:linear-gradient(90deg,#0ea5e91a,#0f172a80),#0f172aa3}.connection-editor__segment-actions{display:inline-flex;gap:4px}.connection-editor__segment-action{width:24px;height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.18);background:#060c16b8;color:#dbeafe;cursor:pointer;font-weight:900;line-height:1}.connection-editor__segment-action:hover{border-color:#22d3ee75;box-shadow:0 0 14px #22d3ee29}.connection-editor__port{min-height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#080d18c2;color:#cbd5e1;font-size:.64rem;font-weight:700;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:crosshair;box-shadow:0 8px 20px #00000038}.connection-editor--guided .connection-editor__ports--visible .connection-editor__port:not(.connection-editor__port--guided-visible){display:none}.connection-editor__port--output{border-color:#f59e0b75;color:#fbbf24}.connection-editor__port--input{border-color:#06b6d475;color:#22d3ee}.connection-editor__port--state{border-color:#a855f785;color:#c084fc}.connection-editor__port--compatible{background:#22c55e29;box-shadow:0 0 0 1px #22c55e61,0 0 18px #22c55e2e;animation:snap-pulse 1s ease-in-out infinite}.connection-editor__port--source{border-color:#fb923cb8;background:#fb923c29;color:#fed7aa;box-shadow:0 0 0 1px #fb923c73,0 0 20px #fb923c2e}.connection-editor__port--candidate{background:#22c55e3d;box-shadow:0 0 0 2px #22c55e94,0 0 24px #22c55e3d}.connection-editor__port--incompatible{opacity:.42;cursor:not-allowed;filter:grayscale(.45)}.connection-editor__port--invalid-drop{opacity:1;border-color:#fb7185c7;color:#fecdd3;background:#f43f5e2e;box-shadow:0 0 0 2px #f43f5e75,0 0 24px #f43f5e38;filter:none;animation:invalid-drop-jolt .36s ease-out}.connection-editor__port--connection-focus{border-color:#facc15ad;color:#fde68a;background:#facc151f;box-shadow:0 0 0 1px #facc156b,0 0 20px #facc152e;animation:port-focus-pulse 1.25s ease-in-out infinite}:host-context(.theme-light) .connection-editor__port{color:var(--pce-fg)}.connection-editor__drag-tip{position:absolute;z-index:6;display:grid;gap:4px;width:min(330px,calc(100% - 28px));padding:10px 12px;border-radius:14px;border:1px solid rgba(125,211,252,.26);background:linear-gradient(135deg,#0ea5e91f,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 28px #0ea5e91a;font-size:.76rem;pointer-events:none;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);animation:tooltip-rise .14s ease-out}.connection-editor__drag-tip--valid{border-color:#22c55e66;background:linear-gradient(135deg,#22c55e29,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 30px #22c55e24}.connection-editor__drag-tip--invalid{z-index:7;border-color:#fb71858a;background:linear-gradient(135deg,#f43f5e2e,#0f172af0),#080d18f5;box-shadow:0 18px 44px #0206176b,0 0 34px #f43f5e29;animation:tooltip-rise .14s ease-out,invalid-drop-jolt .36s ease-out}.connection-editor__invalid-drop-pulse{position:absolute;z-index:6;width:16px;height:16px;border-radius:999px;border:2px solid rgba(251,113,133,.88);background:#f43f5e38;box-shadow:0 0 0 8px #f43f5e1a,0 0 28px #f43f5e3d;pointer-events:none;transform:translate(-50%,-50%);animation:invalid-drop-ping 1.2s ease-out both}.connection-editor__drag-tip span{color:#7dd3fc;text-transform:uppercase;letter-spacing:.12em;font-size:.62rem;font-weight:800}.connection-editor__drag-tip strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.78rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__drag-tip small{color:#94a3b8;font-size:.68rem;font-weight:700}.connection-editor__drag-tip--valid small{color:#86efac}.connection-editor__drag-tip--invalid span,.connection-editor__drag-tip--invalid small{color:#fda4af}.connection-editor__summary{grid-column:1;grid-row:2;align-self:end;justify-self:start;z-index:6;display:flex;flex-wrap:wrap;gap:6px;padding:0 0 12px 12px;pointer-events:none}.connection-editor__side-panel{grid-column:2;grid-row:2 / 3;position:relative;z-index:8;min-width:0;min-height:0;display:grid;align-content:start;gap:14px;overflow:auto;padding-inline-end:4px;scrollbar-color:var(--pce-outline-strong) var(--pce-surface-soft)}.connection-editor__side-panel--contextual .connection-editor__inspector{order:-3}.connection-editor__side-panel--contextual .connection-editor__recommended{order:2}.connection-editor__side-panel--contextual .connection-editor__filters-section{order:3}.connection-editor__side-panel--contextual .connection-editor__recommended,.connection-editor__side-panel--contextual .connection-editor__filters-section{opacity:.82}.connection-editor__metric,.connection-editor__item{border-radius:16px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__metric{min-width:auto;display:inline-flex;align-items:baseline;gap:7px;padding:6px 9px;border-radius:999px;background:color-mix(in srgb,var(--pce-surface-strong) 86%,transparent);box-shadow:0 10px 26px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight)}.connection-editor__metric span{color:var(--pce-muted);font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__metric strong,.connection-editor__details-row strong{color:var(--pce-strong);font-size:.78rem}.connection-editor__filters,.connection-editor__actions,.connection-editor__badges{display:flex;gap:8px;flex-wrap:wrap}.connection-editor__filter,.connection-editor__action{border:1px solid var(--pce-outline-strong);background:var(--pce-surface-soft);color:var(--pce-fg);border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connection-editor__filter--active,.connection-editor__action:hover{border-color:color-mix(in srgb,var(--pce-secondary) 62%,transparent);background:color-mix(in srgb,var(--pce-secondary) 16%,var(--pce-surface-soft));color:var(--pce-strong)}.connection-editor__action--danger{border-color:#f8717161;color:#fecaca}.connection-editor__item{width:100%;text-align:start;padding:12px;display:grid;gap:6px;cursor:pointer;color:inherit}.connection-editor__item--active{border-color:#a855f7b8;background:linear-gradient(90deg,#0ea5e91a,#a855f721)}.connection-editor__item-title{font-weight:800;color:#f8fafc;word-break:break-word}.connection-editor__badge{padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface));color:var(--pce-fg);font-size:.72rem;font-weight:800}.connection-editor__section{min-width:0;padding:14px;border-radius:18px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight),0 18px 50px var(--pce-shadow-soft);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__badge--warning{background:color-mix(in srgb,var(--pce-warning) 14%,var(--pce-surface));color:var(--pce-fg)}.connection-editor__badge--error{background:color-mix(in srgb,var(--pce-error) 14%,var(--pce-surface));color:var(--pce-fg)}.connection-editor__diagnostics{display:grid;gap:8px}.connection-editor__diagnostic{display:grid;gap:4px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.78rem;line-height:1.35}.connection-editor__diagnostic--warning{border-color:#f59e0b47;background:#f59e0b1a}.connection-editor__diagnostic--error{border-color:#ef44445c;background:#ef44441f}.connection-editor__diagnostic-severity{font-size:.68rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#f8fafc}.connection-editor__suggestions{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__suggestion{display:grid;gap:8px;width:100%;padding:12px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 12%,transparent),color-mix(in srgb,var(--pce-primary) 8%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__suggestion:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 46%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 18%,transparent),color-mix(in srgb,var(--pce-primary) 12%,transparent)),var(--pce-surface-strong)}.connection-editor__suggestion-route{display:grid;gap:4px;font-size:.78rem}.connection-editor__suggestion-route strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__suggestion-reason{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__suggestion-diagnostic{padding:10px 12px;border-radius:14px;border:1px solid rgba(245,158,11,.28);background:#f59e0b1a;color:var(--pce-strong);font-size:.78rem;line-height:1.35}.connection-editor__suggestion-outcome{color:var(--pce-strong);font-size:.84rem;line-height:1.3}.connection-editor__suggestion-action{justify-self:start;padding:3px 8px;border-radius:999px;background:#22d3ee24;color:#67e8f9;font-size:.68rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase}:host-context(.theme-light) .connection-editor__suggestion-action{background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:#075f73}.connection-editor__trace{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__trace-summary{color:var(--pce-muted);font-size:.78rem;line-height:1.35}.connection-editor__trace-step{display:grid;grid-template-columns:24px minmax(76px,auto) 1fr;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(34,211,238,.18);background:var(--pce-surface-soft);font-size:.76rem}.connection-editor__trace-step--blocked{border-color:#ef444457;background:#ef44441a}.connection-editor__trace-order{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:999px;background:#22d3ee29;color:#67e8f9;font-weight:900}.connection-editor__trace-phase{color:var(--pce-strong);font-weight:900;text-transform:uppercase;letter-spacing:.06em;font-size:.66rem}.connection-editor__trace-copy{min-width:0;color:var(--pce-fg);word-break:break-word}.connection-editor__transform-steps{display:grid;gap:8px}.connection-editor__transform-step{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(168,85,247,.22);background:var(--pce-surface-soft)}.connection-editor__transform-kind{min-width:0;color:var(--pce-strong);font-weight:900;word-break:break-word}.connection-editor__transform-phase{color:var(--pce-muted);font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.connection-editor__details-row,.connection-editor__details-block{display:grid;gap:6px}.connection-editor__payload-input{width:100%;min-height:128px;box-sizing:border-box;resize:vertical;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 92%,black);color:var(--pce-fg);padding:10px;font:.76rem/1.45 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.connection-editor__surface-action-editor{display:block;max-height:min(58vh,620px);overflow:auto;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 96%,black);padding:10px;margin-bottom:10px}.connection-editor__rule-grid{display:grid;gap:10px}.connection-editor__rule-card{display:grid;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__rule-heading{color:var(--pce-fg);font-size:.72rem;font-weight:900;text-transform:uppercase;letter-spacing:.06em}pre{margin:0;padding:12px;border-radius:12px;background:color-mix(in srgb,var(--pce-surface-strong) 82%,#020617);color:var(--pce-fg);overflow:auto;font-size:.75rem}@keyframes connection-flow{to{stroke-dashoffset:-38}}@keyframes drag-wire-pulse{0%,to{stroke-opacity:.76}50%{stroke-opacity:1}}@keyframes drag-halo-pulse{0%,to{stroke-opacity:.48}50%{stroke-opacity:.82}}@keyframes endpoint-pulse{0%,to{opacity:.78;transform:scale(1)}50%{opacity:1;transform:scale(1.25)}}@keyframes selected-wire-aura{0%,to{stroke-opacity:.46}50%{stroke-opacity:.92}}@keyframes wire-draw-in{0%{stroke-dashoffset:640;opacity:.32}70%{opacity:1}to{stroke-dashoffset:0;opacity:1}}@keyframes new-wire-halo{0%{stroke-opacity:0;stroke-width:30}28%{stroke-opacity:.78}to{stroke-opacity:0;stroke-width:12}}@keyframes new-dock-link-flash{0%{transform:translateY(-2px);box-shadow:0 16px 40px #0206175c,0 0 42px #fb923c47}to{transform:translateY(0)}}@keyframes trace-wire-pulse{0%,to{stroke-opacity:.78}50%{stroke-opacity:1}}@keyframes trace-halo-pulse{0%,to{stroke-opacity:.34}50%{stroke-opacity:.86}}@keyframes tooltip-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes invalid-drop-jolt{0%,to{transform:translate(0)}28%{transform:translate(-3px)}56%{transform:translate(3px)}}@keyframes invalid-drop-ping{0%{opacity:1;transform:translate(-50%,-50%) scale(.72)}72%{opacity:.74;transform:translate(-50%,-50%) scale(1.35)}to{opacity:0;transform:translate(-50%,-50%) scale(1.8)}}@keyframes node-breathe{50%{transform:scale(1.035)}}@keyframes node-focus-breathe{0%,to{transform:scale(1)}50%{transform:scale(1.055)}}@keyframes trace-source-pulse{50%{transform:scale(1.04);box-shadow:0 0 0 3px #facc15db,0 0 0 22px #facc1514,0 0 64px #facc1557}}@keyframes trace-source-orbit{to{transform:rotate(360deg)}}@keyframes trace-reacting-pulse{50%{transform:scale(1.045);box-shadow:0 0 0 3px #22c55ead,0 0 62px #22c55e4d}}@keyframes segment-focus-sweep{0%,to{stroke-opacity:.82}50%{stroke-opacity:1}}@keyframes snap-pulse{50%{filter:brightness(1.16)}}@keyframes port-focus-pulse{50%{transform:translateY(-1px);box-shadow:0 0 0 2px #facc158f,0 0 26px #facc153d}}.connection-editor__link-list{order:-2}.connection-editor__item-title{color:var(--pce-fg);font-weight:650;overflow-wrap:anywhere}.connection-editor__link-list .connection-editor__item{border:0;border-radius:6px;background:transparent;border-bottom:1px solid var(--pce-outline);box-shadow:none;padding:12px 4px;gap:4px}.connection-editor__link-list .connection-editor__item--active{background:var(--pce-surface-strong)}.connection-editor--guided .connection-editor__widget-list,.connection-editor--guided .connection-editor__link-list .connection-editor__item-copy{display:none}.connection-editor__filters-section,.connection-editor__side-panel--contextual .connection-editor__inspector{order:-3}.connection-editor__working-note{order:4}.connection-editor__draft{order:-5}.connection-editor--guided .connection-editor__segment-kind-legend{background:var(--pce-surface-strong);color:var(--pce-fg)}.connection-editor__node-caption{position:absolute;left:50%;top:-16px;transform:translate(-50%,-100%);color:var(--pce-fg);background:var(--pce-surface-base);border:1px solid var(--pce-outline);border-radius:8px;padding:6px 8px;line-height:1.3;font-weight:650;white-space:normal;overflow-wrap:anywhere}.connection-editor__node-core{padding:8px}.connection-editor__node-icon{font-size:30px}.connection-editor__node-subtitle{display:none}.connection-editor__wire:not(.connection-editor__wire--halo){stroke:var(--pce-primary);stroke-opacity:.85;stroke-width:2;vector-effect:non-scaling-stroke;stroke-dasharray:none;animation:none;filter:none}.connection-editor__wire--state:not(.connection-editor__wire--halo){stroke:var(--pce-tertiary)}.connection-editor__wire--state-read:not(.connection-editor__wire--halo){stroke:var(--pce-secondary)}.connection-editor__wire--error:not(.connection-editor__wire--halo){stroke:var(--pce-error)}.connection-editor__wire--active:not(.connection-editor__wire--halo),.connection-editor__wire--trace:not(.connection-editor__wire--halo){stroke-width:3;stroke-opacity:1;stroke-dasharray:12 6;animation:connection-flow 1.8s linear infinite}.connection-editor__wire--mode-dimmed:not(.connection-editor__wire--halo){stroke-opacity:.16}.connection-editor__header{gap:12px}.connection-editor__mode-frame{min-width:0;flex:1 1 300px}.connection-editor__header-actions{flex:0 1 auto}@media(max-width:1200px){.connection-editor__header{flex-wrap:wrap}}@media(prefers-reduced-motion:reduce){.connection-editor__viewport,.connection-editor__node,.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-segment,.connection-editor__dock-link,.connection-editor__port{transition-duration:1ms}.connection-editor__wire,.connection-editor__wire--state,.connection-editor__wire--projection,.connection-editor__wire--state-read,.connection-editor__wire--event-propagation,.connection-editor__wire--halo.connection-editor__wire--active,.connection-editor__wire--trace,.connection-editor__wire--halo.connection-editor__wire--trace,.connection-editor__wire-endpoint,.connection-editor__connection-tooltip,.connection-editor__dock-link--new,.connection-editor__trace-overlay,.connection-editor__trace-overlay-step,.connection-editor__drag-wire,.connection-editor__drag-wire--halo,.connection-editor__drag-endpoint,.connection-editor__drag-tip,.connection-editor__node-ring,.connection-editor__node--connection-focus .connection-editor__node-ring,.connection-editor__node--trace-source .connection-editor__node-ring,.connection-editor__node--trace-source:before,.connection-editor__node--trace-reacting .connection-editor__node-ring,.connection-editor__node--rotating .connection-editor__node-ring,.connection-editor__node-segment--connection-focus,.connection-editor__node-segment--compatible,.connection-editor__node-segment--invalid-drop,.connection-editor__segment-popover,.connection-editor__port--compatible,.connection-editor__port--invalid-drop,.connection-editor__port--connection-focus,.connection-editor__invalid-drop,.connection-editor__invalid-drop-pulse{animation:none}.connection-editor__wire{stroke-dashoffset:0}.connection-editor__wire--new{stroke-dasharray:10 8;stroke-dashoffset:0;opacity:1}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:12;stroke-opacity:.16}.connection-editor__wire-endpoint,.connection-editor__drag-endpoint,.connection-editor__node-ring,.connection-editor__node--trace-source:before{transform:none}.connection-editor__invalid-drop-pulse{opacity:0}}@media(max-width:900px){:host{inset:0}.connection-editor{inset:8px;height:calc(100vh - 16px);padding:12px;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) minmax(76px,112px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) 48px}.connection-editor__header,.connection-editor__stage,.connection-editor__summary,.connection-editor__side-panel,.connection-editor__dock{grid-column:1}.connection-editor__header{align-items:stretch;flex-wrap:wrap;border-radius:18px}.connection-editor__mode-frame{order:3;width:100%;max-width:100%}.connection-editor__close{margin-inline-start:auto}.connection-editor__mode-frame:before,.connection-editor__mode-frame:after{content:\"\";position:absolute;z-index:2;inset-block:4px;width:24px;border-radius:999px;pointer-events:none}.connection-editor__mode-frame:before{inset-inline-start:1px;background:linear-gradient(90deg,#080d18f0,#080d1800)}.connection-editor__mode-frame:after{inset-inline-end:1px;background:linear-gradient(270deg,#080d18f0,#080d1800)}.connection-editor__mode-shell{width:100%;max-width:100%;overflow-x:auto;scroll-padding-inline:28px;-webkit-overflow-scrolling:touch}.connection-editor__subtitle{margin-inline-start:auto}.connection-editor__stage{grid-row:2;min-height:260px}.connection-editor__summary{grid-row:2;max-width:calc(100% - 24px)}.connection-editor__side-panel{grid-row:3;max-height:30vh}.connection-editor__dock{grid-row:4;min-height:0}.connection-editor__connection-tooltip{width:min(620px,calc(100% - 24px));max-height:min(260px,calc(100% - 24px));overflow:auto}.connection-editor__dock-tabs{width:100%;min-width:0;min-height:0;flex-wrap:wrap;align-items:flex-start}.connection-editor__dock-tablist{width:100%;flex-wrap:wrap}.connection-editor__dock-count{flex:1 1 100%;margin-inline-start:0}.connection-editor__dock-body{width:100%;min-width:0;max-height:76px;box-sizing:border-box}.connection-editor__dock-body pre{white-space:pre-wrap;overflow-wrap:anywhere}.connection-editor__dock-link{grid-template-columns:1fr;align-items:start}.connection-editor__dock-link-route{flex-wrap:wrap}.connection-editor__dock-link-badges{justify-content:flex-start}.connection-editor__trace-overlay{inset-inline-start:14px;width:min(420px,calc(100% - 28px));min-width:0;transform:none}.connection-editor__drag-tip{width:min(300px,calc(100% - 28px))}.connection-editor__segment-popover{width:min(280px,calc(100% - 28px));max-height:min(280px,calc(100% - 28px))}.connection-editor__minimap{inset-inline-end:10px;inset-block-end:10px;width:132px;height:94px;padding:16px 8px 8px;border-radius:14px}.connection-editor__minimap:before{inset:20px 8px 8px;background-size:18px 18px}.connection-editor__minimap-title{inset-block-start:6px;inset-inline-start:10px;font-size:.54rem}}@media(max-width:640px){.connection-editor{inset:4px;height:calc(100vh - 8px);padding:8px;gap:8px;grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) minmax(72px,104px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) 46px}.connection-editor__header{gap:8px;padding:10px}.connection-editor__mode-shell{padding:4px;gap:2px}.connection-editor__mode{min-height:28px;gap:4px;padding:0 7px;font-size:.68rem}.connection-editor__mode-glyph{font-size:.64rem}.connection-editor__stage{min-height:240px}.connection-editor__zoom-controls{inset-inline-start:8px;inset-block-start:8px;gap:6px;width:42px}.connection-editor__tool-group,.connection-editor__trace-source{gap:6px;padding:8px;border-radius:12px}.connection-editor__tool-group{grid-template-columns:28px}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:28px}.connection-editor__tool-button{width:28px;height:28px}.connection-editor__arrange-button,.connection-editor__simulate-button{width:30px;min-height:30px}.connection-editor__summary{gap:6px;padding-inline-end:8px}.connection-editor__side-panel{max-height:28vh}.connection-editor__dock{border-radius:16px}.connection-editor__dock-tabs,.connection-editor__dock-tablist{gap:4px}.connection-editor__dock-tab{padding:0 9px}.connection-editor__dock-count{font-size:.62rem}.connection-editor__dock-body{max-height:66px;padding:8px}.connection-editor__minimap{width:116px;height:84px}.connection-editor__segment-row{grid-template-columns:24px minmax(54px,.55fr) minmax(0,1fr) auto}}.connection-editor__ports{width:max-content}.connection-editor__port{font-size:inherit;white-space:normal;overflow:visible;overflow-wrap:anywhere;padding:4px 8px}.connection-editor__header-actions{display:flex;flex-wrap:wrap;gap:8px}.connection-editor__action--primary{background:var(--pce-primary);color:var(--pce-surface-base);font-weight:700}.connection-editor__action:disabled{opacity:.5;cursor:default}.connection-editor__draft{order:-4;padding:16px;border-bottom:1px solid var(--pce-outline)}.connection-editor__draft p,.connection-editor__working-note{font-size:.8rem;line-height:1.55;color:var(--pce-muted)}.connection-editor__working-note{margin:12px 16px}.connection-editor__draft label{display:grid;gap:6px;margin:14px 0;font-size:.82rem}.connection-editor__draft select,.connection-editor__draft input{box-sizing:border-box;width:100%;min-width:0;min-height:40px;padding:8px;color:var(--pce-fg);background:var(--pce-surface-base);border:1px solid var(--pce-outline-strong);border-radius:8px}.connection-editor__draft-review{display:grid;gap:6px;padding:12px 0;font-size:.85rem;overflow-wrap:anywhere}.connection-editor__draft-actions{position:sticky;bottom:0;z-index:4;padding:12px 0;background:var(--pce-surface-base);border-top:1px solid var(--pce-outline)}.connection-editor--draft .connection-editor__filters-section,.connection-editor--draft .connection-editor__link-list{display:none}.connection-editor__draft-status{color:var(--pce-primary)}.connection-editor__advanced{margin:16px 0}.connection-editor__advanced summary{cursor:pointer;font-size:.82rem;padding:10px 0}.connection-editor__node-title{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere;line-height:1.25}.connection-editor--presentation{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr)}.connection-editor--presentation .connection-editor__side-panel,.connection-editor--presentation .connection-editor__summary,.connection-editor--presentation .connection-editor__dock,.connection-editor--presentation .connection-editor__subtitle,.connection-editor--presentation .connection-editor__mode-frame{display:none}.connection-editor--presentation .connection-editor__stage{grid-column:1;grid-row:2}@media(max-width:900px){.connection-editor__header{flex-wrap:wrap}.connection-editor__header-actions{order:2;width:100%}.connection-editor--draft{grid-template-rows:auto minmax(160px,.45fr) minmax(260px,1fr) 46px}.connection-editor--draft .connection-editor__stage{min-height:0}.connection-editor__side-panel{max-height:none}.connection-editor--draft .connection-editor__summary{display:none}}@media(max-width:640px){.connection-editor__eyebrow,.connection-editor__subtitle,.connection-editor__summary,.connection-editor__minimap{display:none}.connection-editor__header{position:relative;padding-right:42px}.connection-editor__close{position:absolute;top:8px;right:8px}.connection-editor__header-actions{flex-wrap:nowrap}.connection-editor__header-actions .connection-editor__action{min-height:36px}.connection-editor__mode-frame{flex-basis:auto}.connection-editor__side-panel{max-height:none}.connection-editor__draft{padding:10px}.connection-editor__stage{overflow:hidden}.connection-editor__connection-tooltip{display:none}.connection-editor__dock{min-width:0}.connection-editor__dock-tablist{min-width:0;overflow-x:auto;max-width:100%}.connection-editor__dock-meta{display:none}}@media(prefers-reduced-motion:reduce){.connection-editor *,.connection-editor *:before,.connection-editor *:after{animation:none!important;transition:none!important}}\n"] }]
|
|
10815
11624
|
}], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], focusWidget: [{ type: i0.Output, args: ["focusWidget"] }], openPageSettings: [{ type: i0.Output, args: ["openPageSettings"] }], close: [{ type: i0.Output, args: ["close"] }] } });
|
|
10816
11625
|
|
|
11626
|
+
const LIMIT_KEYS = ['minColSpan', 'maxColSpan', 'minRowSpan', 'maxRowSpan', 'minHeightPx', 'maxHeightPx'];
|
|
11627
|
+
/** Editor projection of Core canvas constraints; never a second persisted document. */
|
|
11628
|
+
class CanvasConstraintEditorModel {
|
|
11629
|
+
form = new FormArray([]);
|
|
11630
|
+
targets = [];
|
|
11631
|
+
baseline = { widgets: [] };
|
|
11632
|
+
hydrate(page) {
|
|
11633
|
+
this.form.clear({ emitEvent: false });
|
|
11634
|
+
this.targets = [];
|
|
11635
|
+
this.baseline = structuredClone(page);
|
|
11636
|
+
// Missing variants inherit Core's base canvas. Expose their override controls
|
|
11637
|
+
// without creating persisted blocks until a value is actually edited.
|
|
11638
|
+
const scopes = ['base', 'desktop', 'tablet', 'mobile'];
|
|
11639
|
+
for (const scope of scopes) {
|
|
11640
|
+
for (const [key, item] of Object.entries(page.canvas?.items ?? {})) {
|
|
11641
|
+
const widget = page.widgets.find(candidate => candidate.key === key);
|
|
11642
|
+
const override = scope === 'base' ? undefined : page.deviceLayouts?.[scope]?.canvas?.items?.[key];
|
|
11643
|
+
if (!widget || override?.hidden)
|
|
11644
|
+
continue;
|
|
11645
|
+
const constraints = scope === 'base' ? item.constraints : override?.constraints;
|
|
11646
|
+
const size = scope === 'base' ? item.contentSize : override?.contentSize;
|
|
11647
|
+
const seed = {
|
|
11648
|
+
minColSpan: constraints?.minColSpan ?? null, maxColSpan: constraints?.maxColSpan ?? null,
|
|
11649
|
+
minRowSpan: constraints?.minRowSpan ?? null, maxRowSpan: constraints?.maxRowSpan ?? null,
|
|
11650
|
+
minHeightPx: constraints?.minHeightPx ?? null, maxHeightPx: constraints?.maxHeightPx ?? null,
|
|
11651
|
+
heightMode: size === 'auto' ? 'auto' : size ? 'fixed' : 'inherit',
|
|
11652
|
+
heightPx: size && size !== 'auto' ? size.heightPx : null,
|
|
11653
|
+
offsetTopPx: size && size !== 'auto' ? size.offsetTopPx ?? 0 : null,
|
|
11654
|
+
};
|
|
11655
|
+
const authoredTitle = typeof widget.shell?.title === 'string' ? widget.shell.title : '';
|
|
11656
|
+
// This editor has no runtime state projection: identify templates by stable widget key.
|
|
11657
|
+
// Template detection is presentation only, never intent routing or expression evaluation.
|
|
11658
|
+
const title = authoredTitle.includes('${') ? key : authoredTitle;
|
|
11659
|
+
this.targets.push({ key, title: title || key, scope, seed });
|
|
11660
|
+
this.form.push(new FormGroup({
|
|
11661
|
+
minColSpan: new FormControl(seed.minColSpan), maxColSpan: new FormControl(seed.maxColSpan),
|
|
11662
|
+
minRowSpan: new FormControl(seed.minRowSpan), maxRowSpan: new FormControl(seed.maxRowSpan),
|
|
11663
|
+
minHeightPx: new FormControl(seed.minHeightPx), maxHeightPx: new FormControl(seed.maxHeightPx),
|
|
11664
|
+
heightMode: new FormControl(seed.heightMode, { nonNullable: true }),
|
|
11665
|
+
heightPx: new FormControl(seed.heightPx), offsetTopPx: new FormControl(seed.offsetTopPx),
|
|
11666
|
+
}), { emitEvent: false });
|
|
11667
|
+
}
|
|
11668
|
+
}
|
|
11669
|
+
}
|
|
11670
|
+
/** Mutates only the caller's cloned draft, preserving unknown fields and untouched overrides. */
|
|
11671
|
+
apply(page) {
|
|
11672
|
+
for (const group of this.form.controls) {
|
|
11673
|
+
for (const control of Object.values(group.controls)) {
|
|
11674
|
+
const errors = { ...control.errors };
|
|
11675
|
+
delete errors['canvasLimit'];
|
|
11676
|
+
control.setErrors(Object.keys(errors).length ? errors : null, { emitEvent: false });
|
|
11677
|
+
}
|
|
11678
|
+
}
|
|
11679
|
+
for (const [index, target] of this.targets.entries()) {
|
|
11680
|
+
const values = this.form.at(index).getRawValue();
|
|
11681
|
+
const invalidKeys = LIMIT_KEYS.filter(key => values[key] !== null && (!Number.isSafeInteger(values[key]) || values[key] < 1));
|
|
11682
|
+
if (invalidKeys.length) {
|
|
11683
|
+
return this.fail(index, 'integer', invalidKeys);
|
|
11684
|
+
}
|
|
11685
|
+
const heightChanged = values.heightMode !== target.seed.heightMode || values.heightPx !== target.seed.heightPx || values.offsetTopPx !== target.seed.offsetTopPx;
|
|
11686
|
+
if (!heightChanged && !LIMIT_KEYS.some(key => values[key] !== target.seed[key]))
|
|
11687
|
+
continue;
|
|
11688
|
+
const baseItem = page.canvas?.items[target.key];
|
|
11689
|
+
if (!baseItem)
|
|
11690
|
+
continue;
|
|
11691
|
+
const canvas = target.scope === 'base' ? page.canvas :
|
|
11692
|
+
(((page.deviceLayouts ??= {})[target.scope] ??= {}).canvas ??= {});
|
|
11693
|
+
const item = target.scope === 'base' ? baseItem :
|
|
11694
|
+
((canvas.items ??= {})[target.key] ??= {});
|
|
11695
|
+
if (heightChanged) {
|
|
11696
|
+
if (values.heightMode === 'inherit')
|
|
11697
|
+
delete item.contentSize;
|
|
11698
|
+
else if (values.heightMode === 'auto')
|
|
11699
|
+
item.contentSize = 'auto';
|
|
11700
|
+
else {
|
|
11701
|
+
if (!Number.isSafeInteger(values.heightPx) || values.heightPx < 160 || !Number.isSafeInteger(values.offsetTopPx ?? 0) || (values.offsetTopPx ?? 0) < 0) {
|
|
11702
|
+
return this.fail(index, 'height', ['heightPx', 'offsetTopPx']);
|
|
11703
|
+
}
|
|
11704
|
+
item.contentSize = { heightPx: values.heightPx, offsetTopPx: values.offsetTopPx ?? 0 };
|
|
11705
|
+
}
|
|
11706
|
+
}
|
|
11707
|
+
const constraints = { ...item.constraints };
|
|
11708
|
+
for (const key of LIMIT_KEYS) {
|
|
11709
|
+
if (values[key] === target.seed[key])
|
|
11710
|
+
continue;
|
|
11711
|
+
if (values[key] === null)
|
|
11712
|
+
delete constraints[key];
|
|
11713
|
+
else
|
|
11714
|
+
constraints[key] = values[key];
|
|
11715
|
+
}
|
|
11716
|
+
if (Object.keys(constraints).length)
|
|
11717
|
+
item.constraints = constraints;
|
|
11718
|
+
else
|
|
11719
|
+
delete item.constraints;
|
|
11720
|
+
}
|
|
11721
|
+
for (const [index, target] of this.targets.entries()) {
|
|
11722
|
+
const base = page.canvas?.items[target.key];
|
|
11723
|
+
if (!base)
|
|
11724
|
+
continue;
|
|
11725
|
+
const canvas = target.scope === 'base' ? undefined : page.deviceLayouts?.[target.scope]?.canvas;
|
|
11726
|
+
const override = canvas?.items?.[target.key];
|
|
11727
|
+
const limits = { ...base.constraints, ...override?.constraints };
|
|
11728
|
+
const minHeight = limits.minHeightPx ?? 160;
|
|
11729
|
+
const maxHeight = limits.maxHeightPx ?? Number.MAX_SAFE_INTEGER;
|
|
11730
|
+
if (minHeight < 160 || maxHeight < minHeight)
|
|
11731
|
+
return this.fail(index, 'height', ['minHeightPx', 'maxHeightPx']);
|
|
11732
|
+
const size = override?.contentSize ?? base.contentSize;
|
|
11733
|
+
if (size && size !== 'auto' && (size.heightPx < minHeight || size.heightPx > maxHeight))
|
|
11734
|
+
return this.fail(index, 'height', ['heightPx', 'minHeightPx', 'maxHeightPx']);
|
|
11735
|
+
const columns = canvas?.columns ?? page.canvas.columns;
|
|
11736
|
+
const minCol = limits.minColSpan ?? 1;
|
|
11737
|
+
const maxCol = limits.maxColSpan ?? columns;
|
|
11738
|
+
const minRow = limits.minRowSpan ?? 1;
|
|
11739
|
+
const maxRow = limits.maxRowSpan ?? Number.MAX_SAFE_INTEGER;
|
|
11740
|
+
if (minCol > columns)
|
|
11741
|
+
return this.fail(index, 'columns', ['minColSpan']);
|
|
11742
|
+
if (minCol > maxCol)
|
|
11743
|
+
return this.fail(index, 'range', ['minColSpan', 'maxColSpan']);
|
|
11744
|
+
if (minRow > maxRow)
|
|
11745
|
+
return this.fail(index, 'range', ['minRowSpan', 'maxRowSpan']);
|
|
11746
|
+
const original = this.baseline.canvas?.items[target.key];
|
|
11747
|
+
const originalOverride = target.scope === 'base' ? undefined : this.baseline.deviceLayouts?.[target.scope]?.canvas?.items?.[target.key];
|
|
11748
|
+
const previous = { ...original?.constraints, ...originalOverride?.constraints };
|
|
11749
|
+
// Compare rendered spans under the original and proposed limits, using the
|
|
11750
|
+
// edited grid width in both. Preserve already-clamped source documents.
|
|
11751
|
+
const rawCol = override?.colSpan ?? base.colSpan;
|
|
11752
|
+
const rawRow = override?.rowSpan ?? base.rowSpan;
|
|
11753
|
+
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
11754
|
+
const oldMinCol = Math.max(1, previous.minColSpan || 1);
|
|
11755
|
+
const oldMinRow = Math.max(1, previous.minRowSpan || 1);
|
|
11756
|
+
const oldCol = clamp(rawCol, oldMinCol, Math.min(columns, Math.max(oldMinCol, previous.maxColSpan || columns)));
|
|
11757
|
+
const oldRow = clamp(rawRow, oldMinRow, Math.max(oldMinRow, previous.maxRowSpan || Number.MAX_SAFE_INTEGER));
|
|
11758
|
+
const widthChanged = LIMIT_KEYS.slice(0, 2).some(key => limits[key] !== previous[key]);
|
|
11759
|
+
const heightChanged = LIMIT_KEYS.slice(2, 4).some(key => limits[key] !== previous[key]);
|
|
11760
|
+
const oldWidthValid = oldMinCol <= columns && oldMinCol <= (previous.maxColSpan ?? columns);
|
|
11761
|
+
const oldHeightValid = oldMinRow <= (previous.maxRowSpan ?? Number.MAX_SAFE_INTEGER);
|
|
11762
|
+
if (widthChanged && oldWidthValid && oldCol !== clamp(rawCol, minCol, Math.min(maxCol, columns))) {
|
|
11763
|
+
return this.fail(index, 'size', ['minColSpan', 'maxColSpan']);
|
|
11764
|
+
}
|
|
11765
|
+
if (heightChanged && oldHeightValid && oldRow !== clamp(rawRow, minRow, maxRow)) {
|
|
11766
|
+
return this.fail(index, 'size', ['minRowSpan', 'maxRowSpan']);
|
|
11767
|
+
}
|
|
11768
|
+
}
|
|
11769
|
+
return null;
|
|
11770
|
+
}
|
|
11771
|
+
fail(index, code, keys) {
|
|
11772
|
+
for (const key of keys) {
|
|
11773
|
+
const control = this.form.at(index).controls[key];
|
|
11774
|
+
control.setErrors({ ...control.errors, canvasLimit: code }, { emitEvent: false });
|
|
11775
|
+
}
|
|
11776
|
+
return { index, code };
|
|
11777
|
+
}
|
|
11778
|
+
displayedSize(index, columns) {
|
|
11779
|
+
const target = this.targets[index];
|
|
11780
|
+
const base = target && this.baseline.canvas?.items[target.key];
|
|
11781
|
+
if (!base)
|
|
11782
|
+
return { width: 1, height: 1 };
|
|
11783
|
+
const override = target.scope === 'base' ? undefined : this.baseline.deviceLayouts?.[target.scope]?.canvas?.items?.[target.key];
|
|
11784
|
+
const limits = { ...base.constraints, ...override?.constraints };
|
|
11785
|
+
const minCol = Math.max(1, limits.minColSpan || 1);
|
|
11786
|
+
const minRow = Math.max(1, limits.minRowSpan || 1);
|
|
11787
|
+
return {
|
|
11788
|
+
width: Math.max(minCol, Math.min(override?.colSpan ?? base.colSpan, columns, Math.max(minCol, limits.maxColSpan || columns))),
|
|
11789
|
+
height: Math.max(minRow, Math.min(override?.rowSpan ?? base.rowSpan, Math.max(minRow, limits.maxRowSpan || Number.MAX_SAFE_INTEGER))),
|
|
11790
|
+
};
|
|
11791
|
+
}
|
|
11792
|
+
}
|
|
11793
|
+
|
|
10817
11794
|
const LAYOUT_PRESET_ENTRIES = Object.values(BUILTIN_PAGE_LAYOUT_PRESETS).map((preset) => ({
|
|
10818
11795
|
id: preset.id,
|
|
10819
11796
|
label: preset.label,
|
|
@@ -10870,23 +11847,46 @@ class DynamicPageConfigEditorComponent {
|
|
|
10870
11847
|
contextError = signal(null, ...(ngDevMode ? [{ debugName: "contextError" }] : /* istanbul ignore next */ []));
|
|
10871
11848
|
stateError = signal(null, ...(ngDevMode ? [{ debugName: "stateError" }] : /* istanbul ignore next */ []));
|
|
10872
11849
|
deviceError = signal(null, ...(ngDevMode ? [{ debugName: "deviceError" }] : /* istanbul ignore next */ []));
|
|
11850
|
+
canvasLimits = new CanvasConstraintEditorModel();
|
|
11851
|
+
limitsTargetControl = new FormControl(0, { nonNullable: true });
|
|
11852
|
+
limitsError = signal(null, ...(ngDevMode ? [{ debugName: "limitsError" }] : /* istanbul ignore next */ []));
|
|
11853
|
+
limitsErrorMatcher = { isErrorState: (control) => !!control?.invalid };
|
|
10873
11854
|
injectedData = inject(SETTINGS_PANEL_DATA$1, { optional: true });
|
|
11855
|
+
isHostedInSettingsPanel = this.injectedData != null;
|
|
10874
11856
|
i18n = inject(PraxisI18nService);
|
|
10875
11857
|
pageInput = null;
|
|
10876
11858
|
snapshot = '';
|
|
11859
|
+
stackedDevices = new Set();
|
|
11860
|
+
activeDevice = signal('mobile', ...(ngDevMode ? [{ debugName: "activeDevice" }] : /* istanbul ignore next */ []));
|
|
10877
11861
|
hydrating = false;
|
|
10878
|
-
|
|
11862
|
+
renderedCandidate = null;
|
|
11863
|
+
renderedValidationFingerprint = '';
|
|
11864
|
+
tabOrder = ['canvas', 'grouping', 'devices', 'context', 'state', 'limits'];
|
|
10879
11865
|
constructor() {
|
|
10880
|
-
|
|
11866
|
+
afterEveryRender({ read: () => this.refreshRenderedValidation() });
|
|
11867
|
+
merge(this.canvasLimits.form.valueChanges, this.canvasColumnsControl.valueChanges, this.canvasRowUnitControl.valueChanges, this.canvasGapControl.valueChanges, this.canvasAutoRowsControl.valueChanges, this.layoutPresetControl.valueChanges, this.themePresetControl.valueChanges, this.shellPresetControl.valueChanges, this.contextControl.valueChanges, this.stateControl.valueChanges, this.groupingNodes.valueChanges, this.deviceForms.desktop.valueChanges, this.deviceForms.tablet.valueChanges, this.deviceForms.mobile.valueChanges).pipe(takeUntilDestroyed()).subscribe(() => { if (!this.hydrating)
|
|
10881
11868
|
this.refreshPanelState(); });
|
|
10882
11869
|
}
|
|
10883
11870
|
ngOnInit() { this.hydrate(); }
|
|
10884
11871
|
get selectedTabIndex() { return this.tabOrder.indexOf(this.activeTab()); }
|
|
10885
11872
|
get isConfigurationValid() { return this.isValid$.value; }
|
|
10886
11873
|
get hasPendingChanges() { return this.isDirty$.value; }
|
|
10887
|
-
get validationStateLabel() { const issue = this.canvasError() || this.groupingError() || this.deviceError() || this.contextError() || this.stateError(); if (issue)
|
|
11874
|
+
get validationStateLabel() { const issue = this.limitsError() || this.canvasError() || this.groupingError() || this.deviceError() || this.contextError() || this.stateError(); if (issue)
|
|
10888
11875
|
return this.tx('editor.status.validationIssue', 'Review: {{issue}}').replace('{{issue}}', issue); return this.isValid$.value ? this.tx('editor.status.valid', 'Valid configuration') : this.tx('editor.status.review', 'Review errors before saving'); }
|
|
10889
11876
|
get dirtyStateLabel() { return this.hasPendingChanges ? this.tx('editor.status.pending', 'Pending changes') : this.tx('editor.status.clean', 'No changes'); }
|
|
11877
|
+
get nonLimitError() {
|
|
11878
|
+
return this.canvasError() || this.groupingError() || this.deviceError() || this.contextError() || this.stateError();
|
|
11879
|
+
}
|
|
11880
|
+
get limitsSummaryError() {
|
|
11881
|
+
const message = this.limitsError();
|
|
11882
|
+
const form = this.canvasLimits.form.at(this.limitsTargetControl.value);
|
|
11883
|
+
// A rendered-height diagnostic is already attached to the visible height field.
|
|
11884
|
+
// Keep the summary for a different target or a field hidden by the current mode.
|
|
11885
|
+
return form?.controls.heightMode.value === 'fixed'
|
|
11886
|
+
&& this.limitsUseContentHeight()
|
|
11887
|
+
&& form.controls.heightPx.getError('canvasLimit') === 'rendered-height'
|
|
11888
|
+
? null : message;
|
|
11889
|
+
}
|
|
10890
11890
|
get selectedLayoutPresetLabel() { return this.tx('editor.summary.layout', 'Layout: {{label}}').replace('{{label}}', this.lookupPresetLabel(this.layoutPresetEntries, this.layoutPresetControl.value, this.tx('editor.fallback.manual', 'manual'))); }
|
|
10891
11891
|
get selectedThemePresetLabel() { return this.tx('editor.summary.theme', 'Theme: {{label}}').replace('{{label}}', this.lookupPresetLabel(this.themePresetEntries, this.themePresetControl.value, this.tx('editor.layout.layoutDefault', 'Layout default'))); }
|
|
10892
11892
|
get selectedLayoutPresetEntry() { return this.layoutPresetEntries.find((entry) => entry.id === this.layoutPresetControl.value) || null; }
|
|
@@ -10899,6 +11899,38 @@ class DynamicPageConfigEditorComponent {
|
|
|
10899
11899
|
reset() { this.hydrate(); }
|
|
10900
11900
|
pinRecommendedThemePreset() { const theme = this.recommendedThemePresetEntry; if (theme)
|
|
10901
11901
|
this.themePresetControl.setValue(theme.id); }
|
|
11902
|
+
get hasCanvasWidgets() { return !!this.currentPageInput()?.widgets.length; }
|
|
11903
|
+
stackDevice(device) {
|
|
11904
|
+
this.hydrating = true;
|
|
11905
|
+
this.stackedDevices.add(device);
|
|
11906
|
+
this.deviceForms[device].patchValue({ columns: 1, autoRows: 'content' }, { emitEvent: false });
|
|
11907
|
+
for (const [index, target] of this.canvasLimits.targets.entries()) {
|
|
11908
|
+
if (target.scope !== device)
|
|
11909
|
+
continue;
|
|
11910
|
+
this.canvasLimits.form.at(index).patchValue({
|
|
11911
|
+
minColSpan: 1, maxColSpan: 1,
|
|
11912
|
+
heightMode: 'auto', heightPx: null, offsetTopPx: null,
|
|
11913
|
+
}, { emitEvent: false });
|
|
11914
|
+
}
|
|
11915
|
+
this.hydrating = false;
|
|
11916
|
+
this.refreshPanelState();
|
|
11917
|
+
}
|
|
11918
|
+
stackedCanvas(device, previous) {
|
|
11919
|
+
const page = this.currentPageInput() || { widgets: [] };
|
|
11920
|
+
const source = this.completeCanvasItems(page);
|
|
11921
|
+
const widgetOverrides = this.parseWidgetOverrides(this.deviceForms[device].controls.widgetOverrides.value);
|
|
11922
|
+
const items = this.clone(previous.items || {});
|
|
11923
|
+
let row = 1;
|
|
11924
|
+
for (const [key] of Object.entries(source).sort(([aKey, a], [bKey, b]) => a.row - b.row || a.col - b.col || aKey.localeCompare(bKey))) {
|
|
11925
|
+
if (!page.widgets.some(widget => widget.key === key) || items[key]?.hidden || widgetOverrides?.[key]?.hidden)
|
|
11926
|
+
continue;
|
|
11927
|
+
const rowSpan = items[key]?.rowSpan ?? source[key].rowSpan;
|
|
11928
|
+
items[key] = { ...items[key], col: 1, row, colSpan: 1, rowSpan, contentSize: 'auto',
|
|
11929
|
+
constraints: { ...items[key]?.constraints, minColSpan: 1, maxColSpan: 1 } };
|
|
11930
|
+
row += rowSpan;
|
|
11931
|
+
}
|
|
11932
|
+
return { ...previous, items };
|
|
11933
|
+
}
|
|
10902
11934
|
addGroupingNode(seed) { this.groupingNodes.push(this.createGroupingNodeGroup(seed)); this.refreshPanelState(); }
|
|
10903
11935
|
removeGroupingNode(index) { this.groupingNodes.removeAt(index); this.refreshPanelState(); }
|
|
10904
11936
|
layoutPresetSummary(preset) { return this.tx('editor.preview.layoutSummary', '{{columns}} columns · {{gap}}').replace('{{columns}}', String(preset.defaultColumns)).replace('{{gap}}', preset.defaultGap || this.tx('editor.preview.defaultGap', 'default gap')); }
|
|
@@ -10915,9 +11947,104 @@ class DynamicPageConfigEditorComponent {
|
|
|
10915
11947
|
inheritedThemeHelp(theme) { return this.themePresetControl.value ? theme.description : this.tx('editor.preview.inheritedThemeHelp', '{{description}} This theme is inherited automatically while the theme field stays on layout default.').replace('{{description}}', theme.description); }
|
|
10916
11948
|
groupLabel(index) { return this.tx('editor.grouping.groupN', 'Group {{index}}').replace('{{index}}', String(index + 1)); }
|
|
10917
11949
|
tx(key, fallback) { return resolvePraxisPageBuilderText(this.i18n, key, fallback); }
|
|
11950
|
+
limitsTargetLabel(index) {
|
|
11951
|
+
const target = this.canvasLimits.targets[index];
|
|
11952
|
+
if (!target)
|
|
11953
|
+
return '';
|
|
11954
|
+
const scope = target.scope === 'base' ? this.tx('editor.limits.base', 'Base layout') : this.deviceLabels[target.scope];
|
|
11955
|
+
return target.title + ' · ' + scope;
|
|
11956
|
+
}
|
|
11957
|
+
limitFieldError(control) {
|
|
11958
|
+
const code = control.getError('canvasLimit');
|
|
11959
|
+
if (code === 'rendered-height')
|
|
11960
|
+
return this.limitsError() || '';
|
|
11961
|
+
if (code === 'height')
|
|
11962
|
+
return this.tx('editor.height.error', 'Use a whole height of at least 160px, within the effective limits, and a non-negative top inset.');
|
|
11963
|
+
return code ? this.tx('editor.limits.errors.' + code, '') : '';
|
|
11964
|
+
}
|
|
11965
|
+
draftFingerprint() {
|
|
11966
|
+
return JSON.stringify([
|
|
11967
|
+
this.canvasColumnsControl.value, this.canvasRowUnitControl.value,
|
|
11968
|
+
this.canvasGapControl.value, this.canvasAutoRowsControl.value,
|
|
11969
|
+
this.layoutPresetControl.value, this.themePresetControl.value, this.shellPresetControl.value,
|
|
11970
|
+
this.contextControl.value, this.stateControl.value, this.groupingNodes.getRawValue(),
|
|
11971
|
+
this.deviceKeys.map(key => this.deviceForms[key].getRawValue()),
|
|
11972
|
+
this.canvasLimits.form.getRawValue(), [...this.stackedDevices],
|
|
11973
|
+
]);
|
|
11974
|
+
}
|
|
11975
|
+
limitsGeometryLabel() {
|
|
11976
|
+
const target = this.canvasLimits.targets[this.limitsTargetControl.value];
|
|
11977
|
+
if (!target)
|
|
11978
|
+
return '';
|
|
11979
|
+
const columns = target.scope === 'base' ? this.canvasColumnsControl.value : this.deviceForms[target.scope].controls.columns.value ?? this.canvasColumnsControl.value;
|
|
11980
|
+
const size = this.canvasLimits.displayedSize(this.limitsTargetControl.value, columns);
|
|
11981
|
+
return this.tx('editor.limits.geometry', 'Current size: {{width}} columns × {{height}} rows. Grid: {{columns}} columns.')
|
|
11982
|
+
.replace('{{width}}', String(size.width))
|
|
11983
|
+
.replace('{{height}}', String(size.height))
|
|
11984
|
+
.replace('{{columns}}', String(columns));
|
|
11985
|
+
}
|
|
11986
|
+
limitsUseContentHeight() {
|
|
11987
|
+
const target = this.canvasLimits.targets[this.limitsTargetControl.value];
|
|
11988
|
+
const form = target && target.scope !== 'base' ? this.deviceForms[target.scope] : undefined;
|
|
11989
|
+
return (form?.controls.autoRows.value || this.canvasAutoRowsControl.value) === 'content';
|
|
11990
|
+
}
|
|
11991
|
+
applyCanvasLimits(page, reportErrors) {
|
|
11992
|
+
this.renderedCandidate = null;
|
|
11993
|
+
const issue = this.canvasLimits.apply(page);
|
|
11994
|
+
if (!issue) {
|
|
11995
|
+
this.limitsError.set(null);
|
|
11996
|
+
// Optional transient runtime validation supplied through SETTINGS_PANEL_DATA.
|
|
11997
|
+
// The canonical output remains the page only, never the validator/measurements.
|
|
11998
|
+
this.renderedCandidate = page;
|
|
11999
|
+
const renderedIssue = this.readRenderedIssue(page);
|
|
12000
|
+
this.renderedValidationFingerprint = JSON.stringify(renderedIssue);
|
|
12001
|
+
if (!renderedIssue)
|
|
12002
|
+
return page;
|
|
12003
|
+
const index = this.canvasLimits.targets.findIndex(target => target.key === renderedIssue.widgetKey && target.scope === renderedIssue.scope);
|
|
12004
|
+
this.limitsError.set((index >= 0 ? this.limitsTargetLabel(index) + ': ' : '') + renderedIssue.message);
|
|
12005
|
+
if (index >= 0) {
|
|
12006
|
+
const control = this.canvasLimits.form.at(index).controls.heightPx;
|
|
12007
|
+
control.setErrors({ ...control.errors, canvasLimit: 'rendered-height' }, { emitEvent: false });
|
|
12008
|
+
if (reportErrors)
|
|
12009
|
+
this.limitsTargetControl.setValue(index);
|
|
12010
|
+
}
|
|
12011
|
+
if (reportErrors) {
|
|
12012
|
+
this.activeTab.set('limits');
|
|
12013
|
+
this.isValid$.next(false);
|
|
12014
|
+
}
|
|
12015
|
+
return null;
|
|
12016
|
+
}
|
|
12017
|
+
const messages = {
|
|
12018
|
+
height: this.tx('editor.height.error', 'Use a whole height of at least 160px, within the effective limits, and a non-negative top inset.'),
|
|
12019
|
+
integer: this.tx('editor.limits.errors.integer', 'Use positive whole numbers or leave blank.'),
|
|
12020
|
+
range: this.tx('editor.limits.errors.range', 'The minimum cannot exceed the maximum, including inherited limits.'),
|
|
12021
|
+
columns: this.tx('editor.limits.errors.columns', 'The minimum width exceeds the grid columns.'),
|
|
12022
|
+
size: this.tx('editor.limits.errors.size', 'The current size is outside these limits. Resize the widget first, or review the limits.'),
|
|
12023
|
+
};
|
|
12024
|
+
this.limitsError.set(this.limitsTargetLabel(issue.index) + ': ' + messages[issue.code]);
|
|
12025
|
+
if (reportErrors) {
|
|
12026
|
+
this.limitsTargetControl.setValue(issue.index);
|
|
12027
|
+
this.activeTab.set('limits');
|
|
12028
|
+
this.isValid$.next(false);
|
|
12029
|
+
}
|
|
12030
|
+
return null;
|
|
12031
|
+
}
|
|
12032
|
+
readRenderedIssue(page) {
|
|
12033
|
+
const validate = this.injectedData?.validateRenderedCanvas;
|
|
12034
|
+
return typeof validate === 'function' ? validate(page) : null;
|
|
12035
|
+
}
|
|
12036
|
+
refreshRenderedValidation() {
|
|
12037
|
+
if (this.hydrating || !this.renderedCandidate)
|
|
12038
|
+
return;
|
|
12039
|
+
const fingerprint = JSON.stringify(this.readRenderedIssue(this.renderedCandidate));
|
|
12040
|
+
// Read after layout, but rebuild forms/status only when the diagnostic
|
|
12041
|
+
// changes. Measurements remain transient and never dirty the document.
|
|
12042
|
+
if (fingerprint !== this.renderedValidationFingerprint)
|
|
12043
|
+
this.refreshPanelState();
|
|
12044
|
+
}
|
|
10918
12045
|
createDeviceVariantForm() { return new FormGroup({ columns: new FormControl(null, { validators: [Validators.min(1), integerColumnValidator] }), rowUnit: new FormControl('', { nonNullable: true }), gap: new FormControl('', { nonNullable: true }), autoRows: new FormControl('', { nonNullable: true }), groupingOverrides: new FormControl('', { nonNullable: true }), widgetOverrides: new FormControl('', { nonNullable: true }) }); }
|
|
10919
12046
|
createGroupingNodeGroup(seed) { const label = seed && 'label' in seed && typeof seed.label === 'string' ? seed.label : ''; return new FormGroup({ kind: new FormControl(seed?.kind || 'section', { nonNullable: true }), id: new FormControl(seed?.id || '', { nonNullable: true, validators: [Validators.required] }), label: new FormControl(label, { nonNullable: true }), widgetKeysCsv: new FormControl(this.stringifyGroupingWidgetKeys(seed), { nonNullable: true }), layout: new FormControl(seed?.kind === 'section' ? seed.layout || '' : '', { nonNullable: true }), emphasis: new FormControl(seed?.kind === 'hero' ? seed.emphasis || '' : '', { nonNullable: true }), side: new FormControl(seed?.kind === 'rail' ? seed.side || 'right' : 'right', { nonNullable: true }), tabsJson: new FormControl(seed?.kind === 'tabs' ? JSON.stringify(seed.tabs || [], null, 2) : '', { nonNullable: true }) }); }
|
|
10920
|
-
hydrate() { const page = this.currentPageInput() || { widgets: [] }; const canvas = page.canvas || this.defaultCanvas(); const context = this.clone(page.context || {}); this.hydrating = true; this.canvasColumnsControl.setValue(canvas.columns || 12, { emitEvent: false }); this.canvasRowUnitControl.setValue(canvas.rowUnit || '80px', { emitEvent: false }); this.canvasGapControl.setValue(canvas.gap || '16px', { emitEvent: false }); this.canvasAutoRowsControl.setValue(canvas.autoRows || 'fixed', { emitEvent: false }); this.layoutPresetControl.setValue(page.layoutPreset || '', { emitEvent: false }); this.themePresetControl.setValue(page.themePreset || '', { emitEvent: false }); this.shellPresetControl.setValue(this.extractShellPreset(context) || this.pagePreset || '', { emitEvent: false }); this.replaceGroupingNodes(page.grouping); this.contextControl.setValue(this.stringify(this.removeShellPresetFromContext(context)), { emitEvent: false }); this.stateControl.setValue(this.stringify(page.state || {}), { emitEvent: false }); for (const device of this.deviceKeys) {
|
|
12047
|
+
hydrate() { this.stackedDevices.clear(); const page = this.currentPageInput() || { widgets: [] }; const canvas = page.canvas || this.defaultCanvas(); const context = this.clone(page.context || {}); this.hydrating = true; this.canvasLimits.hydrate(page); this.limitsTargetControl.setValue(0, { emitEvent: false }); this.limitsError.set(null); this.canvasColumnsControl.setValue(canvas.columns || 12, { emitEvent: false }); this.canvasRowUnitControl.setValue(canvas.rowUnit || '80px', { emitEvent: false }); this.canvasGapControl.setValue(canvas.gap || '16px', { emitEvent: false }); this.canvasAutoRowsControl.setValue(canvas.autoRows || 'fixed', { emitEvent: false }); this.layoutPresetControl.setValue(page.layoutPreset || '', { emitEvent: false }); this.themePresetControl.setValue(page.themePreset || '', { emitEvent: false }); this.shellPresetControl.setValue(this.extractShellPreset(context) || this.pagePreset || '', { emitEvent: false }); this.replaceGroupingNodes(page.grouping); this.contextControl.setValue(this.stringify(this.removeShellPresetFromContext(context)), { emitEvent: false }); this.stateControl.setValue(this.stringify(page.state || {}), { emitEvent: false }); for (const device of this.deviceKeys) {
|
|
10921
12048
|
const variant = page.deviceLayouts?.[device];
|
|
10922
12049
|
this.deviceForms[device].setValue({ columns: variant?.canvas?.columns ?? null, rowUnit: variant?.canvas?.rowUnit || '', gap: variant?.canvas?.gap || '', autoRows: variant?.canvas?.autoRows || '', groupingOverrides: this.stringify(variant?.groupingOverrides || []), widgetOverrides: this.stringify(variant?.widgetOverrides || {}) }, { emitEvent: false });
|
|
10923
12050
|
} this.canvasError.set(null); this.groupingError.set(null); this.deviceError.set(null); this.contextError.set(null); this.stateError.set(null); this.hydrating = false; this.refreshPanelState(true); }
|
|
@@ -10928,7 +12055,7 @@ class DynamicPageConfigEditorComponent {
|
|
|
10928
12055
|
return null; this.groupingError.set(null); const context = this.parseRecordJson(this.contextControl.value, {}); if (context === null)
|
|
10929
12056
|
return this.invalidate('context', this.contextError, reportErrors, this.tx('editor.errors.contextInvalid', 'Invalid context')); this.contextError.set(null); const state = this.parseRecordJson(this.stateControl.value, {}); if (state === null)
|
|
10930
12057
|
return this.invalidate('state', this.stateError, reportErrors, this.tx('editor.errors.stateInvalid', 'Invalid state')); this.stateError.set(null); const deviceLayouts = this.buildDeviceLayouts(reportErrors, next.deviceLayouts); if (deviceLayouts === null)
|
|
10931
|
-
return null; next.canvas = { ...(next.canvas || this.defaultCanvas()), mode: 'grid', columns: this.canvasColumnsControl.value, rowUnit: this.canvasRowUnitControl.value.trim() || '80px', gap: this.canvasGapControl.value.trim() || '16px', autoRows: this.canvasAutoRowsControl.value, items: next
|
|
12058
|
+
return null; next.canvas = { ...(next.canvas || this.defaultCanvas()), mode: 'grid', columns: this.canvasColumnsControl.value, rowUnit: this.canvasRowUnitControl.value.trim() || '80px', gap: this.canvasGapControl.value.trim() || '16px', autoRows: this.canvasAutoRowsControl.value, items: this.completeCanvasItems(next) }; next.layoutPreset = this.layoutPresetControl.value.trim() || undefined; next.themePreset = this.themePresetControl.value.trim() || undefined; next.grouping = grouping.length ? grouping : undefined; next.deviceLayouts = Object.keys(deviceLayouts).length ? deviceLayouts : undefined; next.context = this.applyShellPresetToContext(context, this.shellPresetControl.value.trim()); next.state = Object.keys(state).length ? state : undefined; return this.applyCanvasLimits(next, reportErrors); }
|
|
10932
12059
|
buildGrouping(reportErrors) { const grouping = []; const seenIds = new Set(); for (const group of this.groupingNodes.controls) {
|
|
10933
12060
|
const kind = group.controls.kind.value;
|
|
10934
12061
|
const id = group.controls.id.value.trim();
|
|
@@ -10958,6 +12085,18 @@ class DynamicPageConfigEditorComponent {
|
|
|
10958
12085
|
}
|
|
10959
12086
|
grouping.push({ kind: 'rail', id, side: (group.controls.side.value || 'right'), widgetKeys });
|
|
10960
12087
|
} return grouping; }
|
|
12088
|
+
/** A grid must place every existing widget before replacing the flow layout. */
|
|
12089
|
+
completeCanvasItems(page) {
|
|
12090
|
+
const items = { ...(page.canvas?.items || {}) };
|
|
12091
|
+
let row = Math.max(1, ...Object.values(items).map(item => item.row + item.rowSpan));
|
|
12092
|
+
for (const widget of page.widgets) {
|
|
12093
|
+
if (items[widget.key])
|
|
12094
|
+
continue;
|
|
12095
|
+
items[widget.key] = { col: 1, row, colSpan: this.canvasColumnsControl.value, rowSpan: 1 };
|
|
12096
|
+
row += 1;
|
|
12097
|
+
}
|
|
12098
|
+
return items;
|
|
12099
|
+
}
|
|
10961
12100
|
buildDeviceLayouts(reportErrors, base) { const next = {}; for (const device of this.deviceKeys) {
|
|
10962
12101
|
const form = this.deviceForms[device];
|
|
10963
12102
|
if (form.controls.columns.invalid)
|
|
@@ -10971,7 +12110,7 @@ class DynamicPageConfigEditorComponent {
|
|
|
10971
12110
|
delete baseVariant.canvas;
|
|
10972
12111
|
delete baseVariant.groupingOverrides;
|
|
10973
12112
|
delete baseVariant.widgetOverrides;
|
|
10974
|
-
const canvas = { ...baseCanvas };
|
|
12113
|
+
const canvas = this.stackedDevices.has(device) ? this.stackedCanvas(device, baseCanvas) : { ...baseCanvas };
|
|
10975
12114
|
if (form.controls.columns.value != null)
|
|
10976
12115
|
canvas.columns = form.controls.columns.value;
|
|
10977
12116
|
else
|
|
@@ -10997,11 +12136,15 @@ class DynamicPageConfigEditorComponent {
|
|
|
10997
12136
|
this.activeTab.set(tab);
|
|
10998
12137
|
this.isValid$.next(false);
|
|
10999
12138
|
} return null; }
|
|
11000
|
-
refreshPanelState(resetSnapshot = false) {
|
|
11001
|
-
this.
|
|
11002
|
-
this.
|
|
11003
|
-
|
|
11004
|
-
|
|
12139
|
+
refreshPanelState(resetSnapshot = false) {
|
|
12140
|
+
this.renderedCandidate = null;
|
|
12141
|
+
const current = this.buildCurrentPage(false);
|
|
12142
|
+
this.isValid$.next(!!current);
|
|
12143
|
+
const fingerprint = this.draftFingerprint();
|
|
12144
|
+
if (resetSnapshot)
|
|
12145
|
+
this.snapshot = fingerprint;
|
|
12146
|
+
this.isDirty$.next(fingerprint !== this.snapshot);
|
|
12147
|
+
}
|
|
11005
12148
|
currentPageInput() { return this.parsePage(this.pageInput) || this.parsePage(this.injectedData?.page || null); }
|
|
11006
12149
|
parsePage(input) { if (!input)
|
|
11007
12150
|
return null; if (typeof input === 'string') {
|
|
@@ -11055,57 +12198,293 @@ class DynamicPageConfigEditorComponent {
|
|
|
11055
12198
|
next.ui.shell.preset = shellPreset;
|
|
11056
12199
|
} return Object.keys(next).length ? next : undefined; }
|
|
11057
12200
|
lookupPresetLabel(entries, value, fallback) { return entries.find((entry) => entry.id === value)?.label || fallback; }
|
|
11058
|
-
defaultCanvas() { return { mode: 'grid', columns: 12, rowUnit: '80px', gap: '16px', autoRows: '
|
|
12201
|
+
defaultCanvas() { return { mode: 'grid', columns: 12, rowUnit: '80px', gap: '16px', autoRows: 'content', items: {} }; }
|
|
11059
12202
|
clone(value) { if (value == null || typeof value !== 'object')
|
|
11060
12203
|
return value; return JSON.parse(JSON.stringify(value)); }
|
|
11061
12204
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageConfigEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11062
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicPageConfigEditorComponent, isStandalone: true, selector: "praxis-dynamic-page-config-editor", inputs: { page: "page", layout: "layout", presets: "presets", pagePreset: "pagePreset" }, outputs: { pageChange: "pageChange" }, providers: [providePraxisPageBuilderI18n()], ngImport: i0, template: `
|
|
12205
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicPageConfigEditorComponent, isStandalone: true, selector: "praxis-dynamic-page-config-editor", inputs: { page: "page", layout: "layout", presets: "presets", pagePreset: "pagePreset" }, outputs: { pageChange: "pageChange" }, host: { listeners: { "window:resize": "refreshRenderedValidation()" } }, providers: [providePraxisPageBuilderI18n()], ngImport: i0, template: `
|
|
11063
12206
|
<div class="editor">
|
|
11064
|
-
<div class="head">
|
|
12207
|
+
@if (!isHostedInSettingsPanel) { <div class="head">
|
|
11065
12208
|
<div>{{ tx('editor.title', 'Page settings') }}</div>
|
|
11066
12209
|
<button mat-stroked-button type="button" (click)="reset()">{{ tx('editor.reload', 'Reload') }}</button>
|
|
11067
|
-
</div>
|
|
11068
|
-
<
|
|
11069
|
-
|
|
11070
|
-
|
|
12210
|
+
</div> }
|
|
12211
|
+
<details class="summary-details">
|
|
12212
|
+
<summary>{{ tx('editor.summaryAria', 'Configuration summary') }}</summary>
|
|
12213
|
+
<div class="summary">
|
|
12214
|
+
@if (!isHostedInSettingsPanel) {
|
|
12215
|
+
<span>{{ validationStateLabel }}</span>
|
|
12216
|
+
<span>{{ dirtyStateLabel }}</span>
|
|
12217
|
+
}
|
|
11071
12218
|
<span>{{ selectedLayoutPresetLabel }}</span>
|
|
11072
12219
|
<span>{{ selectedThemePresetLabel }}</span>
|
|
11073
12220
|
<span>{{ canvasSummaryLabel }}</span>
|
|
11074
12221
|
</div>
|
|
11075
|
-
|
|
12222
|
+
</details>
|
|
12223
|
+
@if (nonLimitError) { <p class="limits-error" role="alert">{{ nonLimitError }}</p> }
|
|
12224
|
+
@if (activeTab() === 'limits' && canvasLimits.targets.length) {
|
|
12225
|
+
<div class="selection-identity" data-testid="canvas-limits-identity">
|
|
12226
|
+
<mat-icon aria-hidden="true">dashboard_customize</mat-icon>
|
|
12227
|
+
<strong>{{ limitsTargetLabel(limitsTargetControl.value) }}</strong>
|
|
12228
|
+
</div>
|
|
12229
|
+
}
|
|
12230
|
+
<mat-tab-group class="editor-tabs" [mat-stretch-tabs]="false" [selectedIndex]="selectedTabIndex" (selectedIndexChange)="onSelectedTabIndexChange($event)">
|
|
11076
12231
|
<mat-tab [label]="tx('editor.tabs.layout', 'Layout')"><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.cols', 'Columns') }}</mat-label><input matInput type="number" min="1" [formControl]="canvasColumnsControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.rowUnit', 'Row unit') }}</mat-label><input matInput [formControl]="canvasRowUnitControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.gap', 'Gap') }}</mat-label><input matInput [formControl]="canvasGapControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.autoRows', 'Auto rows') }}</mat-label><mat-select [formControl]="canvasAutoRowsControl"><mat-option value="fixed">{{ tx('editor.layout.autoRowsFixed', 'Fixed height') }}</mat-option><mat-option value="content">{{ tx('editor.layout.autoRowsContent', 'Fit content') }}</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.layoutPreset', 'Layout preset') }}</mat-label><mat-select [formControl]="layoutPresetControl"><mat-option value="">{{ tx('editor.layout.none', 'None') }}</mat-option>@for (preset of layoutPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.themePreset', 'Theme preset') }}</mat-label><mat-select [formControl]="themePresetControl"><mat-option value="">{{ tx('editor.layout.layoutDefault', 'Layout default') }}</mat-option>@for (preset of themePresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.shellPreset', 'Shell visual preset') }}</mat-label><mat-select [formControl]="shellPresetControl"><mat-option value="">{{ tx('editor.layout.none', 'None') }}</mat-option>@for (preset of shellPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field></div>@if (selectedLayoutPresetEntry; as preset) {<div class="preset-preview"><div class="preset-preview__head"><div><span class="eyebrow">{{ tx('editor.preview.layoutEyebrow', 'Layout template') }} · {{ preset.category }}</span><strong>{{ preset.label }}</strong></div><span>{{ layoutPresetSummary(preset) }}</span></div><p>{{ preset.description || tx('editor.preview.layoutFallbackDescription', 'Page organization preset.') }}</p><div class="preset-preview__chips"><span>{{ slotsSummary(preset) }}</span><span>{{ requiredSlotsSummary(preset) }}</span><span>{{ devicePolicySummary(preset) }}</span></div>@if (recommendedThemePresetEntry; as theme) {<div class="preset-preview__recommendation"><div><span class="eyebrow">{{ tx('editor.preview.inheritedTheme', 'Inherited theme') }}</span><strong>{{ theme.label }}</strong><span>{{ inheritedThemeHelp(theme) }}</span></div><button mat-stroked-button type="button" [disabled]="themePresetControl.value === theme.id" (click)="pinRecommendedThemePreset()">{{ tx('editor.preview.pinTheme', 'Pin theme') }}</button></div>}</div>} @if (selectedThemePresetEntry; as theme) {<div class="preset-preview preset-preview--theme"><div class="preset-preview__head"><div><span class="eyebrow">{{ tx('editor.preview.explicitTheme', 'Explicit theme') }}</span><strong>{{ theme.label }}</strong></div><span>{{ theme.density }} · {{ theme.motion }}</span></div><p>{{ theme.description || tx('editor.preview.themeFallbackDescription', 'Page visual preset.') }}</p><div class="preset-preview__chips"><span>{{ tx('editor.preview.shellChip', 'Shell: {{value}}').replace('{{value}}', theme.shellPreset) }}</span><span>{{ tx('editor.preview.chartsChip', 'Charts: {{value}}').replace('{{value}}', theme.chartThemePreset) }}</span></div></div>}</mat-tab>
|
|
11077
|
-
<mat-tab [label]="tx('editor.tabs.grouping', 'Grouping')"><div class="panel"
|
|
11078
|
-
|
|
12232
|
+
<mat-tab [label]="tx('editor.tabs.grouping', 'Grouping')"><div class="panel">
|
|
12233
|
+
<p class="hint" data-testid="canvas-grouping-notice">{{ tx('editor.grouping.canvasNotice', 'Canvas positions control this page. Groups below are preserved for flow layouts and do not arrange widgets in the canvas. Use the widget move and resize controls to place them side by side.') }}</p><div class="head"><span>{{ tx('editor.grouping.title', 'Grouping') }}</span><button mat-stroked-button type="button" (click)="addGroupingNode()"><mat-icon>add</mat-icon>{{ tx('editor.grouping.add', 'Add group') }}</button></div>@for (group of groupingNodes.controls; track $index) {<div class="card" [formGroup]="group"><div class="head"><span>{{ groupLabel($index) }}</span><button praxisIconButton="delete" size="compact" type="button" [attr.aria-label]="tx('editor.grouping.removeAria', 'Remove group')" (click)="removeGroupingNode($index)"></button></div><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.kind', 'Kind') }}</mat-label><mat-select formControlName="kind"><mat-option value="section">section</mat-option><mat-option value="tabs">tabs</mat-option><mat-option value="hero">hero</mat-option><mat-option value="rail">rail</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.id', 'Id') }}</mat-label><input matInput formControlName="id" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.label', 'Label') }}</mat-label><input matInput formControlName="label" /></mat-form-field>@if (group.controls.kind.value === 'section') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.layout', 'Layout') }}</mat-label><mat-select formControlName="layout"><mat-option value="">{{ tx('editor.grouping.layoutDefault', 'Default') }}</mat-option><mat-option value="stack">stack</mat-option><mat-option value="grid">grid</mat-option><mat-option value="row">row</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'hero') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.emphasis', 'Emphasis') }}</mat-label><mat-select formControlName="emphasis"><mat-option value="">{{ tx('editor.grouping.layoutDefault', 'Default') }}</mat-option><mat-option value="high">high</mat-option><mat-option value="medium">medium</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'rail') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.side', 'Side') }}</mat-label><mat-select formControlName="side"><mat-option value="left">left</mat-option><mat-option value="right">right</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'tabs') {<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.grouping.tabsJson', 'Tabs (JSON)') }}</mat-label><textarea matInput rows="4" formControlName="tabsJson"></textarea></mat-form-field>} @else {<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.grouping.widgetKeysCsv', 'Widget keys (comma-separated)') }}</mat-label><input matInput formControlName="widgetKeysCsv" /></mat-form-field>}</div></div>}</div></mat-tab>
|
|
12234
|
+
<mat-tab [label]="tx('editor.tabs.devices', 'Device Layouts')">
|
|
12235
|
+
<div class="panel">
|
|
12236
|
+
<mat-button-toggle-group [value]="activeDevice()" (change)="activeDevice.set($event.value)" [attr.aria-label]="tx('editor.devices.target', 'Device to configure')">
|
|
12237
|
+
@for (device of deviceKeys; track device) {
|
|
12238
|
+
<mat-button-toggle [value]="device">{{ deviceLabels[device] }}</mat-button-toggle>
|
|
12239
|
+
}
|
|
12240
|
+
</mat-button-toggle-group>
|
|
12241
|
+
@for (device of deviceKeys; track device) {
|
|
12242
|
+
@if (activeDevice() === device) {
|
|
12243
|
+
<div class="card">
|
|
12244
|
+
<div class="head"><strong>{{ deviceLabels[device] }}</strong><button mat-stroked-button type="button" [attr.data-testid]="'stack-device-' + device" [disabled]="!hasCanvasWidgets" (click)="stackDevice(device)"><mat-icon aria-hidden="true">view_agenda</mat-icon>{{ tx('editor.devices.stack', 'Stack widgets') }}</button></div>
|
|
12245
|
+
<p class="hint">{{ tx('editor.devices.stackHelp', 'Use full width and natural height, in reading order. This replaces positions and width limits only for this device; other layouts stay unchanged.') }}</p>
|
|
12246
|
+
@if (stackedDevices.has(device)) { <p class="hint" role="status">{{ tx('editor.devices.stacked', 'Single-column layout prepared. Save to apply; Reset undoes the changes.') }}</p> }
|
|
12247
|
+
<div class="grid">
|
|
12248
|
+
<mat-form-field appearance="outline"><mat-label>{{ tx('editor.devices.columns', 'Columns') }}</mat-label><input matInput type="number" min="1" [formControl]="deviceForms[device].controls.columns" /></mat-form-field>
|
|
12249
|
+
<mat-form-field appearance="outline"><mat-label>{{ tx('editor.devices.gap', 'Gap') }}</mat-label><input matInput [formControl]="deviceForms[device].controls.gap" /></mat-form-field>
|
|
12250
|
+
<mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.autoRows', 'Auto rows') }}</mat-label><mat-select [formControl]="deviceForms[device].controls.autoRows"><mat-option value="">{{ tx('editor.devices.orientationDefault', 'Default') }}</mat-option><mat-option value="fixed">{{ tx('editor.layout.autoRowsFixed', 'Fixed height') }}</mat-option><mat-option value="content">{{ tx('editor.layout.autoRowsContent', 'Fit content') }}</mat-option></mat-select></mat-form-field>
|
|
12251
|
+
</div>
|
|
12252
|
+
<details><summary>{{ tx('editor.devices.advanced', 'Advanced overrides') }}</summary><div class="grid">
|
|
12253
|
+
<mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.rowUnit', 'Row unit') }}</mat-label><input matInput [formControl]="deviceForms[device].controls.rowUnit" /></mat-form-field>
|
|
12254
|
+
<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.devices.groupingOverridesJson', 'Grouping overrides (JSON)') }}</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.groupingOverrides"></textarea></mat-form-field>
|
|
12255
|
+
<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.devices.widgetOverridesJson', 'Widget overrides (JSON)') }}</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.widgetOverrides"></textarea></mat-form-field>
|
|
12256
|
+
</div></details>
|
|
12257
|
+
@if (!stackedDevices.has(device)) { <div class="hint">{{ tx('editor.preview.deviceCanvasHint', 'Existing canvas item overrides are preserved.') }}</div> }
|
|
12258
|
+
</div>
|
|
12259
|
+
}
|
|
12260
|
+
}
|
|
12261
|
+
</div>
|
|
12262
|
+
</mat-tab>
|
|
11079
12263
|
<mat-tab [label]="tx('editor.tabs.context', 'Context')"><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.context.json', 'Context (JSON)') }}</mat-label><textarea matInput rows="12" [formControl]="contextControl"></textarea></mat-form-field></mat-tab>
|
|
11080
12264
|
<mat-tab [label]="tx('editor.tabs.state', 'Page State')"><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.state.valuesJson', 'Primary values (JSON)') }}</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
|
|
12265
|
+
<mat-tab [label]="tx('editor.limits.tab', 'Widget limits')">
|
|
12266
|
+
<section class="limits-panel" data-testid="canvas-limits-editor">
|
|
12267
|
+
<p class="hint" id="canvas-limits-help">{{ tx('editor.limits.help', 'Limits use grid columns and rows, not pixels. Leave blank for defaults, or to inherit the base limits on a device.') }}</p>
|
|
12268
|
+
@if (canvasLimits.targets.length) {
|
|
12269
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12270
|
+
<mat-label>{{ tx('editor.limits.target', 'Widget and layout') }}</mat-label>
|
|
12271
|
+
<mat-select [formControl]="limitsTargetControl" data-testid="canvas-limits-target">
|
|
12272
|
+
@for (target of canvasLimits.targets; track target.scope + ':' + target.key; let index = $index) {
|
|
12273
|
+
<mat-option [value]="index">{{ limitsTargetLabel(index) }}</mat-option>
|
|
12274
|
+
}
|
|
12275
|
+
</mat-select>
|
|
12276
|
+
</mat-form-field>
|
|
12277
|
+
<p class="hint">{{ limitsGeometryLabel() }}</p>
|
|
12278
|
+
@if (canvasLimits.form.controls[limitsTargetControl.value]; as limitsForm) {
|
|
12279
|
+
<div class="limits-fields" aria-describedby="canvas-limits-help">
|
|
12280
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12281
|
+
<mat-label>{{ tx('editor.limits.minColSpan', 'Minimum width (columns)') }}</mat-label>
|
|
12282
|
+
<input matInput [errorStateMatcher]="limitsErrorMatcher" type="number" min="1" step="1" [formControl]="limitsForm.controls.minColSpan" data-testid="canvas-limit-minColSpan">
|
|
12283
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.minColSpan) }}</mat-error>
|
|
12284
|
+
</mat-form-field>
|
|
12285
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12286
|
+
<mat-label>{{ tx('editor.limits.maxColSpan', 'Maximum width (columns)') }}</mat-label>
|
|
12287
|
+
<input matInput [errorStateMatcher]="limitsErrorMatcher" type="number" min="1" step="1" [formControl]="limitsForm.controls.maxColSpan" data-testid="canvas-limit-maxColSpan">
|
|
12288
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.maxColSpan) }}</mat-error>
|
|
12289
|
+
</mat-form-field>
|
|
12290
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12291
|
+
<mat-label>{{ tx('editor.limits.minRowSpan', 'Minimum height (rows)') }}</mat-label>
|
|
12292
|
+
<input matInput [errorStateMatcher]="limitsErrorMatcher" type="number" min="1" step="1" [formControl]="limitsForm.controls.minRowSpan" data-testid="canvas-limit-minRowSpan">
|
|
12293
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.minRowSpan) }}</mat-error>
|
|
12294
|
+
</mat-form-field>
|
|
12295
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12296
|
+
<mat-label>{{ tx('editor.limits.maxRowSpan', 'Maximum height (rows)') }}</mat-label>
|
|
12297
|
+
<input matInput [errorStateMatcher]="limitsErrorMatcher" type="number" min="1" step="1" [formControl]="limitsForm.controls.maxRowSpan" data-testid="canvas-limit-maxRowSpan">
|
|
12298
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.maxRowSpan) }}</mat-error>
|
|
12299
|
+
</mat-form-field>
|
|
12300
|
+
</div>
|
|
12301
|
+
@if (limitsUseContentHeight()) {
|
|
12302
|
+
<p class="limits-notice"><mat-icon aria-hidden="true">height</mat-icon><span>{{ tx('editor.limits.autoHeight', 'Choose natural height or an adjustable height with internal scrolling.') }}</span></p>
|
|
12303
|
+
<mat-button-toggle-group class="height-modes" [formControl]="limitsForm.controls.heightMode" [attr.aria-label]="tx('editor.height.mode', 'Widget height')" data-testid="canvas-height-mode">
|
|
12304
|
+
<mat-button-toggle value="inherit">{{ tx('editor.height.inherit', 'Default') }}</mat-button-toggle>
|
|
12305
|
+
<mat-button-toggle value="auto">{{ tx('editor.height.auto', 'Automatic') }}</mat-button-toggle>
|
|
12306
|
+
<mat-button-toggle value="fixed">{{ tx('editor.height.fixed', 'Adjustable') }}</mat-button-toggle>
|
|
12307
|
+
</mat-button-toggle-group>
|
|
12308
|
+
@if (limitsForm.controls.heightMode.value === 'fixed') {
|
|
12309
|
+
<div class="limits-fields">
|
|
12310
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12311
|
+
<mat-label>{{ tx('editor.height.value', 'Height (px)') }}</mat-label>
|
|
12312
|
+
<input matInput type="number" min="160" step="1" [errorStateMatcher]="limitsErrorMatcher" [formControl]="limitsForm.controls.heightPx" data-testid="canvas-height-px">
|
|
12313
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.heightPx) }}</mat-error>
|
|
12314
|
+
</mat-form-field>
|
|
12315
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12316
|
+
<mat-label>{{ tx('editor.height.top', 'Top inset (px)') }}</mat-label>
|
|
12317
|
+
<input matInput type="number" min="0" step="1" [errorStateMatcher]="limitsErrorMatcher" [formControl]="limitsForm.controls.offsetTopPx" data-testid="canvas-height-top">
|
|
12318
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.offsetTopPx) }}</mat-error>
|
|
12319
|
+
</mat-form-field>
|
|
12320
|
+
</div>
|
|
12321
|
+
}
|
|
12322
|
+
<div class="limits-fields">
|
|
12323
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12324
|
+
<mat-label>{{ tx('editor.height.min', 'Minimum height (px)') }}</mat-label>
|
|
12325
|
+
<input matInput type="number" min="160" step="1" [errorStateMatcher]="limitsErrorMatcher" [formControl]="limitsForm.controls.minHeightPx" data-testid="canvas-limit-minHeightPx">
|
|
12326
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.minHeightPx) }}</mat-error>
|
|
12327
|
+
</mat-form-field>
|
|
12328
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12329
|
+
<mat-label>{{ tx('editor.height.max', 'Maximum height (px)') }}</mat-label>
|
|
12330
|
+
<input matInput type="number" min="160" step="1" [errorStateMatcher]="limitsErrorMatcher" [formControl]="limitsForm.controls.maxHeightPx" data-testid="canvas-limit-maxHeightPx">
|
|
12331
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.maxHeightPx) }}</mat-error>
|
|
12332
|
+
</mat-form-field>
|
|
12333
|
+
</div>
|
|
12334
|
+
}
|
|
12335
|
+
}
|
|
12336
|
+
@if (limitsSummaryError) { <p class="limits-error" role="alert">{{ limitsSummaryError }}</p> }
|
|
12337
|
+
} @else {
|
|
12338
|
+
<p>{{ tx('editor.limits.empty', 'Add widgets to the canvas to configure their limits.') }}</p>
|
|
12339
|
+
}
|
|
12340
|
+
</section>
|
|
12341
|
+
</mat-tab>
|
|
11081
12342
|
</mat-tab-group>
|
|
11082
12343
|
</div>
|
|
11083
|
-
`, isInline: true, styles: [":host{display:block;min-width:0;max-width:100%}.editor,.panel{display:grid;gap:16px;min-width:0;max-width:100%;color:var(--md-sys-color-on-surface, currentColor)}mat-tab-group,mat-form-field{min-width:0;max-width:100%}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr))}@media(max-width:600px){.grid{grid-template-columns:minmax(0,1fr)}.head,.summary,.preset-preview__head,.preset-preview__recommendation{align-items:stretch}.head>button,.preset-preview__recommendation button{width:100%}}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}.preset-preview{display:grid;gap:12px;margin-top:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, transparent) 88%,var(--md-sys-color-primary-container, transparent) 12%)}.preset-preview--theme{background:var(--md-sys-color-surface-container-low, transparent)}.preset-preview__head,.preset-preview__recommendation{display:flex;justify-content:space-between;align-items:center;gap:16px}.preset-preview__head>div,.preset-preview__recommendation>div{display:grid;gap:4px;min-width:0}.preset-preview p{margin:0;color:var(--md-sys-color-on-surface-variant, currentColor);line-height:1.45}.preset-preview__chips{display:flex;flex-wrap:wrap;gap:8px}.preset-preview__chips span{padding:5px 9px;border-radius:999px;background:var(--md-sys-color-surface-container, color-mix(in srgb, currentColor 8%, transparent));color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px;line-height:1.3}.preset-preview__recommendation{padding-top:12px;border-top:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 14%, transparent))}.preset-preview__recommendation span:last-child{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:13px;line-height:1.35}.eyebrow{color:var(--md-sys-color-primary, currentColor);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type:
|
|
12344
|
+
`, isInline: true, styles: [":host{display:block;min-width:0;max-width:100%}.height-modes{width:fit-content;max-width:100%;flex-wrap:wrap;margin-bottom:16px}.editor,.panel{display:grid;gap:16px;min-width:0;max-width:100%;color:var(--md-sys-color-on-surface, currentColor)}mat-tab-group,mat-form-field{min-width:0;max-width:100%}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.selection-identity{position:sticky;top:0;z-index:var(--praxis-layer-sticky-local, 100);display:flex;align-items:flex-start;gap:8px;padding-block:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface));overflow-wrap:anywhere}.selection-identity mat-icon{flex-shrink:0}:host ::ng-deep .editor-tabs>.mat-mdc-tab-header .mdc-tab{min-width:0;padding-inline:12px}:host ::ng-deep .editor-tabs>.mat-mdc-tab-header .mdc-tab__text-label{max-width:128px;white-space:normal;overflow-wrap:anywhere;text-align:center;letter-spacing:normal;line-height:1.25}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr))}@media(max-width:600px){.grid{grid-template-columns:minmax(0,1fr)}.head,.summary,.preset-preview__head,.preset-preview__recommendation{align-items:stretch}.head>button,.preset-preview__recommendation button{width:100%}}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.limits-panel{display:grid;gap:8px;min-width:0}.limits-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:4px 16px}.limits-fields mat-form-field{min-width:0}.limits-notice{display:flex;gap:8px;align-items:flex-start;color:var(--md-sys-color-on-surface-variant, currentColor)}.limits-notice mat-icon{flex-shrink:0}.limits-error{color:var(--md-sys-color-error, #b3261e)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}.preset-preview{display:grid;gap:12px;margin-top:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, transparent) 88%,var(--md-sys-color-primary-container, transparent) 12%)}.preset-preview--theme{background:var(--md-sys-color-surface-container-low, transparent)}.preset-preview__head,.preset-preview__recommendation{display:flex;justify-content:space-between;align-items:center;gap:16px}.preset-preview__head>div,.preset-preview__recommendation>div{display:grid;gap:4px;min-width:0}.preset-preview p{margin:0;color:var(--md-sys-color-on-surface-variant, currentColor);line-height:1.45}.preset-preview__chips{display:flex;flex-wrap:wrap;gap:8px}.preset-preview__chips span{padding:5px 9px;border-radius:999px;background:var(--md-sys-color-surface-container, color-mix(in srgb, currentColor 8%, transparent));color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px;line-height:1.3}.preset-preview__recommendation{padding-top:12px;border-top:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 14%, transparent))}.preset-preview__recommendation span:last-child{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:13px;line-height:1.35}.eyebrow{color:var(--md-sys-color-primary, currentColor);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i3$1.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i3$1.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i10.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i10.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i8.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i8.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
11084
12345
|
}
|
|
11085
12346
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageConfigEditorComponent, decorators: [{
|
|
11086
12347
|
type: Component,
|
|
11087
|
-
args: [{ selector: 'praxis-dynamic-page-config-editor', standalone: true, imports: [ReactiveFormsModule, MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, MatSelectModule, MatTabsModule, PraxisIconButtonComponent], providers: [providePraxisPageBuilderI18n()], template: `
|
|
12348
|
+
args: [{ selector: 'praxis-dynamic-page-config-editor', standalone: true, imports: [ReactiveFormsModule, MatButtonModule, MatButtonToggleModule, MatFormFieldModule, MatIconModule, MatInputModule, MatSelectModule, MatTabsModule, PraxisIconButtonComponent], providers: [providePraxisPageBuilderI18n()], template: `
|
|
11088
12349
|
<div class="editor">
|
|
11089
|
-
<div class="head">
|
|
12350
|
+
@if (!isHostedInSettingsPanel) { <div class="head">
|
|
11090
12351
|
<div>{{ tx('editor.title', 'Page settings') }}</div>
|
|
11091
12352
|
<button mat-stroked-button type="button" (click)="reset()">{{ tx('editor.reload', 'Reload') }}</button>
|
|
11092
|
-
</div>
|
|
11093
|
-
<
|
|
11094
|
-
|
|
11095
|
-
|
|
12353
|
+
</div> }
|
|
12354
|
+
<details class="summary-details">
|
|
12355
|
+
<summary>{{ tx('editor.summaryAria', 'Configuration summary') }}</summary>
|
|
12356
|
+
<div class="summary">
|
|
12357
|
+
@if (!isHostedInSettingsPanel) {
|
|
12358
|
+
<span>{{ validationStateLabel }}</span>
|
|
12359
|
+
<span>{{ dirtyStateLabel }}</span>
|
|
12360
|
+
}
|
|
11096
12361
|
<span>{{ selectedLayoutPresetLabel }}</span>
|
|
11097
12362
|
<span>{{ selectedThemePresetLabel }}</span>
|
|
11098
12363
|
<span>{{ canvasSummaryLabel }}</span>
|
|
11099
12364
|
</div>
|
|
11100
|
-
|
|
12365
|
+
</details>
|
|
12366
|
+
@if (nonLimitError) { <p class="limits-error" role="alert">{{ nonLimitError }}</p> }
|
|
12367
|
+
@if (activeTab() === 'limits' && canvasLimits.targets.length) {
|
|
12368
|
+
<div class="selection-identity" data-testid="canvas-limits-identity">
|
|
12369
|
+
<mat-icon aria-hidden="true">dashboard_customize</mat-icon>
|
|
12370
|
+
<strong>{{ limitsTargetLabel(limitsTargetControl.value) }}</strong>
|
|
12371
|
+
</div>
|
|
12372
|
+
}
|
|
12373
|
+
<mat-tab-group class="editor-tabs" [mat-stretch-tabs]="false" [selectedIndex]="selectedTabIndex" (selectedIndexChange)="onSelectedTabIndexChange($event)">
|
|
11101
12374
|
<mat-tab [label]="tx('editor.tabs.layout', 'Layout')"><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.cols', 'Columns') }}</mat-label><input matInput type="number" min="1" [formControl]="canvasColumnsControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.rowUnit', 'Row unit') }}</mat-label><input matInput [formControl]="canvasRowUnitControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.gap', 'Gap') }}</mat-label><input matInput [formControl]="canvasGapControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.autoRows', 'Auto rows') }}</mat-label><mat-select [formControl]="canvasAutoRowsControl"><mat-option value="fixed">{{ tx('editor.layout.autoRowsFixed', 'Fixed height') }}</mat-option><mat-option value="content">{{ tx('editor.layout.autoRowsContent', 'Fit content') }}</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.layoutPreset', 'Layout preset') }}</mat-label><mat-select [formControl]="layoutPresetControl"><mat-option value="">{{ tx('editor.layout.none', 'None') }}</mat-option>@for (preset of layoutPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.themePreset', 'Theme preset') }}</mat-label><mat-select [formControl]="themePresetControl"><mat-option value="">{{ tx('editor.layout.layoutDefault', 'Layout default') }}</mat-option>@for (preset of themePresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.shellPreset', 'Shell visual preset') }}</mat-label><mat-select [formControl]="shellPresetControl"><mat-option value="">{{ tx('editor.layout.none', 'None') }}</mat-option>@for (preset of shellPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field></div>@if (selectedLayoutPresetEntry; as preset) {<div class="preset-preview"><div class="preset-preview__head"><div><span class="eyebrow">{{ tx('editor.preview.layoutEyebrow', 'Layout template') }} · {{ preset.category }}</span><strong>{{ preset.label }}</strong></div><span>{{ layoutPresetSummary(preset) }}</span></div><p>{{ preset.description || tx('editor.preview.layoutFallbackDescription', 'Page organization preset.') }}</p><div class="preset-preview__chips"><span>{{ slotsSummary(preset) }}</span><span>{{ requiredSlotsSummary(preset) }}</span><span>{{ devicePolicySummary(preset) }}</span></div>@if (recommendedThemePresetEntry; as theme) {<div class="preset-preview__recommendation"><div><span class="eyebrow">{{ tx('editor.preview.inheritedTheme', 'Inherited theme') }}</span><strong>{{ theme.label }}</strong><span>{{ inheritedThemeHelp(theme) }}</span></div><button mat-stroked-button type="button" [disabled]="themePresetControl.value === theme.id" (click)="pinRecommendedThemePreset()">{{ tx('editor.preview.pinTheme', 'Pin theme') }}</button></div>}</div>} @if (selectedThemePresetEntry; as theme) {<div class="preset-preview preset-preview--theme"><div class="preset-preview__head"><div><span class="eyebrow">{{ tx('editor.preview.explicitTheme', 'Explicit theme') }}</span><strong>{{ theme.label }}</strong></div><span>{{ theme.density }} · {{ theme.motion }}</span></div><p>{{ theme.description || tx('editor.preview.themeFallbackDescription', 'Page visual preset.') }}</p><div class="preset-preview__chips"><span>{{ tx('editor.preview.shellChip', 'Shell: {{value}}').replace('{{value}}', theme.shellPreset) }}</span><span>{{ tx('editor.preview.chartsChip', 'Charts: {{value}}').replace('{{value}}', theme.chartThemePreset) }}</span></div></div>}</mat-tab>
|
|
11102
|
-
<mat-tab [label]="tx('editor.tabs.grouping', 'Grouping')"><div class="panel"
|
|
11103
|
-
|
|
12375
|
+
<mat-tab [label]="tx('editor.tabs.grouping', 'Grouping')"><div class="panel">
|
|
12376
|
+
<p class="hint" data-testid="canvas-grouping-notice">{{ tx('editor.grouping.canvasNotice', 'Canvas positions control this page. Groups below are preserved for flow layouts and do not arrange widgets in the canvas. Use the widget move and resize controls to place them side by side.') }}</p><div class="head"><span>{{ tx('editor.grouping.title', 'Grouping') }}</span><button mat-stroked-button type="button" (click)="addGroupingNode()"><mat-icon>add</mat-icon>{{ tx('editor.grouping.add', 'Add group') }}</button></div>@for (group of groupingNodes.controls; track $index) {<div class="card" [formGroup]="group"><div class="head"><span>{{ groupLabel($index) }}</span><button praxisIconButton="delete" size="compact" type="button" [attr.aria-label]="tx('editor.grouping.removeAria', 'Remove group')" (click)="removeGroupingNode($index)"></button></div><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.kind', 'Kind') }}</mat-label><mat-select formControlName="kind"><mat-option value="section">section</mat-option><mat-option value="tabs">tabs</mat-option><mat-option value="hero">hero</mat-option><mat-option value="rail">rail</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.id', 'Id') }}</mat-label><input matInput formControlName="id" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.label', 'Label') }}</mat-label><input matInput formControlName="label" /></mat-form-field>@if (group.controls.kind.value === 'section') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.layout', 'Layout') }}</mat-label><mat-select formControlName="layout"><mat-option value="">{{ tx('editor.grouping.layoutDefault', 'Default') }}</mat-option><mat-option value="stack">stack</mat-option><mat-option value="grid">grid</mat-option><mat-option value="row">row</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'hero') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.emphasis', 'Emphasis') }}</mat-label><mat-select formControlName="emphasis"><mat-option value="">{{ tx('editor.grouping.layoutDefault', 'Default') }}</mat-option><mat-option value="high">high</mat-option><mat-option value="medium">medium</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'rail') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.side', 'Side') }}</mat-label><mat-select formControlName="side"><mat-option value="left">left</mat-option><mat-option value="right">right</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'tabs') {<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.grouping.tabsJson', 'Tabs (JSON)') }}</mat-label><textarea matInput rows="4" formControlName="tabsJson"></textarea></mat-form-field>} @else {<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.grouping.widgetKeysCsv', 'Widget keys (comma-separated)') }}</mat-label><input matInput formControlName="widgetKeysCsv" /></mat-form-field>}</div></div>}</div></mat-tab>
|
|
12377
|
+
<mat-tab [label]="tx('editor.tabs.devices', 'Device Layouts')">
|
|
12378
|
+
<div class="panel">
|
|
12379
|
+
<mat-button-toggle-group [value]="activeDevice()" (change)="activeDevice.set($event.value)" [attr.aria-label]="tx('editor.devices.target', 'Device to configure')">
|
|
12380
|
+
@for (device of deviceKeys; track device) {
|
|
12381
|
+
<mat-button-toggle [value]="device">{{ deviceLabels[device] }}</mat-button-toggle>
|
|
12382
|
+
}
|
|
12383
|
+
</mat-button-toggle-group>
|
|
12384
|
+
@for (device of deviceKeys; track device) {
|
|
12385
|
+
@if (activeDevice() === device) {
|
|
12386
|
+
<div class="card">
|
|
12387
|
+
<div class="head"><strong>{{ deviceLabels[device] }}</strong><button mat-stroked-button type="button" [attr.data-testid]="'stack-device-' + device" [disabled]="!hasCanvasWidgets" (click)="stackDevice(device)"><mat-icon aria-hidden="true">view_agenda</mat-icon>{{ tx('editor.devices.stack', 'Stack widgets') }}</button></div>
|
|
12388
|
+
<p class="hint">{{ tx('editor.devices.stackHelp', 'Use full width and natural height, in reading order. This replaces positions and width limits only for this device; other layouts stay unchanged.') }}</p>
|
|
12389
|
+
@if (stackedDevices.has(device)) { <p class="hint" role="status">{{ tx('editor.devices.stacked', 'Single-column layout prepared. Save to apply; Reset undoes the changes.') }}</p> }
|
|
12390
|
+
<div class="grid">
|
|
12391
|
+
<mat-form-field appearance="outline"><mat-label>{{ tx('editor.devices.columns', 'Columns') }}</mat-label><input matInput type="number" min="1" [formControl]="deviceForms[device].controls.columns" /></mat-form-field>
|
|
12392
|
+
<mat-form-field appearance="outline"><mat-label>{{ tx('editor.devices.gap', 'Gap') }}</mat-label><input matInput [formControl]="deviceForms[device].controls.gap" /></mat-form-field>
|
|
12393
|
+
<mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.autoRows', 'Auto rows') }}</mat-label><mat-select [formControl]="deviceForms[device].controls.autoRows"><mat-option value="">{{ tx('editor.devices.orientationDefault', 'Default') }}</mat-option><mat-option value="fixed">{{ tx('editor.layout.autoRowsFixed', 'Fixed height') }}</mat-option><mat-option value="content">{{ tx('editor.layout.autoRowsContent', 'Fit content') }}</mat-option></mat-select></mat-form-field>
|
|
12394
|
+
</div>
|
|
12395
|
+
<details><summary>{{ tx('editor.devices.advanced', 'Advanced overrides') }}</summary><div class="grid">
|
|
12396
|
+
<mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.rowUnit', 'Row unit') }}</mat-label><input matInput [formControl]="deviceForms[device].controls.rowUnit" /></mat-form-field>
|
|
12397
|
+
<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.devices.groupingOverridesJson', 'Grouping overrides (JSON)') }}</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.groupingOverrides"></textarea></mat-form-field>
|
|
12398
|
+
<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.devices.widgetOverridesJson', 'Widget overrides (JSON)') }}</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.widgetOverrides"></textarea></mat-form-field>
|
|
12399
|
+
</div></details>
|
|
12400
|
+
@if (!stackedDevices.has(device)) { <div class="hint">{{ tx('editor.preview.deviceCanvasHint', 'Existing canvas item overrides are preserved.') }}</div> }
|
|
12401
|
+
</div>
|
|
12402
|
+
}
|
|
12403
|
+
}
|
|
12404
|
+
</div>
|
|
12405
|
+
</mat-tab>
|
|
11104
12406
|
<mat-tab [label]="tx('editor.tabs.context', 'Context')"><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.context.json', 'Context (JSON)') }}</mat-label><textarea matInput rows="12" [formControl]="contextControl"></textarea></mat-form-field></mat-tab>
|
|
11105
12407
|
<mat-tab [label]="tx('editor.tabs.state', 'Page State')"><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.state.valuesJson', 'Primary values (JSON)') }}</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
|
|
12408
|
+
<mat-tab [label]="tx('editor.limits.tab', 'Widget limits')">
|
|
12409
|
+
<section class="limits-panel" data-testid="canvas-limits-editor">
|
|
12410
|
+
<p class="hint" id="canvas-limits-help">{{ tx('editor.limits.help', 'Limits use grid columns and rows, not pixels. Leave blank for defaults, or to inherit the base limits on a device.') }}</p>
|
|
12411
|
+
@if (canvasLimits.targets.length) {
|
|
12412
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12413
|
+
<mat-label>{{ tx('editor.limits.target', 'Widget and layout') }}</mat-label>
|
|
12414
|
+
<mat-select [formControl]="limitsTargetControl" data-testid="canvas-limits-target">
|
|
12415
|
+
@for (target of canvasLimits.targets; track target.scope + ':' + target.key; let index = $index) {
|
|
12416
|
+
<mat-option [value]="index">{{ limitsTargetLabel(index) }}</mat-option>
|
|
12417
|
+
}
|
|
12418
|
+
</mat-select>
|
|
12419
|
+
</mat-form-field>
|
|
12420
|
+
<p class="hint">{{ limitsGeometryLabel() }}</p>
|
|
12421
|
+
@if (canvasLimits.form.controls[limitsTargetControl.value]; as limitsForm) {
|
|
12422
|
+
<div class="limits-fields" aria-describedby="canvas-limits-help">
|
|
12423
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12424
|
+
<mat-label>{{ tx('editor.limits.minColSpan', 'Minimum width (columns)') }}</mat-label>
|
|
12425
|
+
<input matInput [errorStateMatcher]="limitsErrorMatcher" type="number" min="1" step="1" [formControl]="limitsForm.controls.minColSpan" data-testid="canvas-limit-minColSpan">
|
|
12426
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.minColSpan) }}</mat-error>
|
|
12427
|
+
</mat-form-field>
|
|
12428
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12429
|
+
<mat-label>{{ tx('editor.limits.maxColSpan', 'Maximum width (columns)') }}</mat-label>
|
|
12430
|
+
<input matInput [errorStateMatcher]="limitsErrorMatcher" type="number" min="1" step="1" [formControl]="limitsForm.controls.maxColSpan" data-testid="canvas-limit-maxColSpan">
|
|
12431
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.maxColSpan) }}</mat-error>
|
|
12432
|
+
</mat-form-field>
|
|
12433
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12434
|
+
<mat-label>{{ tx('editor.limits.minRowSpan', 'Minimum height (rows)') }}</mat-label>
|
|
12435
|
+
<input matInput [errorStateMatcher]="limitsErrorMatcher" type="number" min="1" step="1" [formControl]="limitsForm.controls.minRowSpan" data-testid="canvas-limit-minRowSpan">
|
|
12436
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.minRowSpan) }}</mat-error>
|
|
12437
|
+
</mat-form-field>
|
|
12438
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12439
|
+
<mat-label>{{ tx('editor.limits.maxRowSpan', 'Maximum height (rows)') }}</mat-label>
|
|
12440
|
+
<input matInput [errorStateMatcher]="limitsErrorMatcher" type="number" min="1" step="1" [formControl]="limitsForm.controls.maxRowSpan" data-testid="canvas-limit-maxRowSpan">
|
|
12441
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.maxRowSpan) }}</mat-error>
|
|
12442
|
+
</mat-form-field>
|
|
12443
|
+
</div>
|
|
12444
|
+
@if (limitsUseContentHeight()) {
|
|
12445
|
+
<p class="limits-notice"><mat-icon aria-hidden="true">height</mat-icon><span>{{ tx('editor.limits.autoHeight', 'Choose natural height or an adjustable height with internal scrolling.') }}</span></p>
|
|
12446
|
+
<mat-button-toggle-group class="height-modes" [formControl]="limitsForm.controls.heightMode" [attr.aria-label]="tx('editor.height.mode', 'Widget height')" data-testid="canvas-height-mode">
|
|
12447
|
+
<mat-button-toggle value="inherit">{{ tx('editor.height.inherit', 'Default') }}</mat-button-toggle>
|
|
12448
|
+
<mat-button-toggle value="auto">{{ tx('editor.height.auto', 'Automatic') }}</mat-button-toggle>
|
|
12449
|
+
<mat-button-toggle value="fixed">{{ tx('editor.height.fixed', 'Adjustable') }}</mat-button-toggle>
|
|
12450
|
+
</mat-button-toggle-group>
|
|
12451
|
+
@if (limitsForm.controls.heightMode.value === 'fixed') {
|
|
12452
|
+
<div class="limits-fields">
|
|
12453
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12454
|
+
<mat-label>{{ tx('editor.height.value', 'Height (px)') }}</mat-label>
|
|
12455
|
+
<input matInput type="number" min="160" step="1" [errorStateMatcher]="limitsErrorMatcher" [formControl]="limitsForm.controls.heightPx" data-testid="canvas-height-px">
|
|
12456
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.heightPx) }}</mat-error>
|
|
12457
|
+
</mat-form-field>
|
|
12458
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12459
|
+
<mat-label>{{ tx('editor.height.top', 'Top inset (px)') }}</mat-label>
|
|
12460
|
+
<input matInput type="number" min="0" step="1" [errorStateMatcher]="limitsErrorMatcher" [formControl]="limitsForm.controls.offsetTopPx" data-testid="canvas-height-top">
|
|
12461
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.offsetTopPx) }}</mat-error>
|
|
12462
|
+
</mat-form-field>
|
|
12463
|
+
</div>
|
|
12464
|
+
}
|
|
12465
|
+
<div class="limits-fields">
|
|
12466
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12467
|
+
<mat-label>{{ tx('editor.height.min', 'Minimum height (px)') }}</mat-label>
|
|
12468
|
+
<input matInput type="number" min="160" step="1" [errorStateMatcher]="limitsErrorMatcher" [formControl]="limitsForm.controls.minHeightPx" data-testid="canvas-limit-minHeightPx">
|
|
12469
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.minHeightPx) }}</mat-error>
|
|
12470
|
+
</mat-form-field>
|
|
12471
|
+
<mat-form-field appearance="outline" subscriptSizing="dynamic">
|
|
12472
|
+
<mat-label>{{ tx('editor.height.max', 'Maximum height (px)') }}</mat-label>
|
|
12473
|
+
<input matInput type="number" min="160" step="1" [errorStateMatcher]="limitsErrorMatcher" [formControl]="limitsForm.controls.maxHeightPx" data-testid="canvas-limit-maxHeightPx">
|
|
12474
|
+
<mat-error>{{ limitFieldError(limitsForm.controls.maxHeightPx) }}</mat-error>
|
|
12475
|
+
</mat-form-field>
|
|
12476
|
+
</div>
|
|
12477
|
+
}
|
|
12478
|
+
}
|
|
12479
|
+
@if (limitsSummaryError) { <p class="limits-error" role="alert">{{ limitsSummaryError }}</p> }
|
|
12480
|
+
} @else {
|
|
12481
|
+
<p>{{ tx('editor.limits.empty', 'Add widgets to the canvas to configure their limits.') }}</p>
|
|
12482
|
+
}
|
|
12483
|
+
</section>
|
|
12484
|
+
</mat-tab>
|
|
11106
12485
|
</mat-tab-group>
|
|
11107
12486
|
</div>
|
|
11108
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;min-width:0;max-width:100%}.editor,.panel{display:grid;gap:16px;min-width:0;max-width:100%;color:var(--md-sys-color-on-surface, currentColor)}mat-tab-group,mat-form-field{min-width:0;max-width:100%}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr))}@media(max-width:600px){.grid{grid-template-columns:minmax(0,1fr)}.head,.summary,.preset-preview__head,.preset-preview__recommendation{align-items:stretch}.head>button,.preset-preview__recommendation button{width:100%}}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}.preset-preview{display:grid;gap:12px;margin-top:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, transparent) 88%,var(--md-sys-color-primary-container, transparent) 12%)}.preset-preview--theme{background:var(--md-sys-color-surface-container-low, transparent)}.preset-preview__head,.preset-preview__recommendation{display:flex;justify-content:space-between;align-items:center;gap:16px}.preset-preview__head>div,.preset-preview__recommendation>div{display:grid;gap:4px;min-width:0}.preset-preview p{margin:0;color:var(--md-sys-color-on-surface-variant, currentColor);line-height:1.45}.preset-preview__chips{display:flex;flex-wrap:wrap;gap:8px}.preset-preview__chips span{padding:5px 9px;border-radius:999px;background:var(--md-sys-color-surface-container, color-mix(in srgb, currentColor 8%, transparent));color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px;line-height:1.3}.preset-preview__recommendation{padding-top:12px;border-top:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 14%, transparent))}.preset-preview__recommendation span:last-child{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:13px;line-height:1.35}.eyebrow{color:var(--md-sys-color-primary, currentColor);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"] }]
|
|
12487
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, host: { '(window:resize)': 'refreshRenderedValidation()' }, styles: [":host{display:block;min-width:0;max-width:100%}.height-modes{width:fit-content;max-width:100%;flex-wrap:wrap;margin-bottom:16px}.editor,.panel{display:grid;gap:16px;min-width:0;max-width:100%;color:var(--md-sys-color-on-surface, currentColor)}mat-tab-group,mat-form-field{min-width:0;max-width:100%}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.selection-identity{position:sticky;top:0;z-index:var(--praxis-layer-sticky-local, 100);display:flex;align-items:flex-start;gap:8px;padding-block:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface));overflow-wrap:anywhere}.selection-identity mat-icon{flex-shrink:0}:host ::ng-deep .editor-tabs>.mat-mdc-tab-header .mdc-tab{min-width:0;padding-inline:12px}:host ::ng-deep .editor-tabs>.mat-mdc-tab-header .mdc-tab__text-label{max-width:128px;white-space:normal;overflow-wrap:anywhere;text-align:center;letter-spacing:normal;line-height:1.25}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr))}@media(max-width:600px){.grid{grid-template-columns:minmax(0,1fr)}.head,.summary,.preset-preview__head,.preset-preview__recommendation{align-items:stretch}.head>button,.preset-preview__recommendation button{width:100%}}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.limits-panel{display:grid;gap:8px;min-width:0}.limits-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:4px 16px}.limits-fields mat-form-field{min-width:0}.limits-notice{display:flex;gap:8px;align-items:flex-start;color:var(--md-sys-color-on-surface-variant, currentColor)}.limits-notice mat-icon{flex-shrink:0}.limits-error{color:var(--md-sys-color-error, #b3261e)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}.preset-preview{display:grid;gap:12px;margin-top:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, transparent) 88%,var(--md-sys-color-primary-container, transparent) 12%)}.preset-preview--theme{background:var(--md-sys-color-surface-container-low, transparent)}.preset-preview__head,.preset-preview__recommendation{display:flex;justify-content:space-between;align-items:center;gap:16px}.preset-preview__head>div,.preset-preview__recommendation>div{display:grid;gap:4px;min-width:0}.preset-preview p{margin:0;color:var(--md-sys-color-on-surface-variant, currentColor);line-height:1.45}.preset-preview__chips{display:flex;flex-wrap:wrap;gap:8px}.preset-preview__chips span{padding:5px 9px;border-radius:999px;background:var(--md-sys-color-surface-container, color-mix(in srgb, currentColor 8%, transparent));color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px;line-height:1.3}.preset-preview__recommendation{padding-top:12px;border-top:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 14%, transparent))}.preset-preview__recommendation span:last-child{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:13px;line-height:1.35}.eyebrow{color:var(--md-sys-color-primary, currentColor);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"] }]
|
|
11109
12488
|
}], ctorParameters: () => [], propDecorators: { page: [{
|
|
11110
12489
|
type: Input
|
|
11111
12490
|
}], layout: [{
|
|
@@ -12554,7 +13933,7 @@ class PageConfigEditorComponent {
|
|
|
12554
13933
|
</div>
|
|
12555
13934
|
}
|
|
12556
13935
|
</div>
|
|
12557
|
-
`, isInline: true, styles: [".page-config{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.page-head{display:flex;align-items:flex-start;gap:12px}.page-head__copy{display:grid;gap:4px}.page-title{font-weight:600;font-size:18px;line-height:1.2}.page-subtitle{max-width:72ch;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.spacer{flex:1}.page-summary{display:flex;flex-wrap:wrap;gap:8px}.page-tabs{border-radius:16px;overflow:hidden;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent)}.page-tabs ::ng-deep .mdc-tab{min-width:120px}.page-tabs ::ng-deep .mdc-tab__text-label{font-size:13px;font-weight:600}.page-tab-panel{display:grid;gap:12px;padding:16px 4px 4px}.page-chip{display:inline-flex;align-items:center;gap:8px;min-height:36px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:500}.page-chip mat-icon{width:18px;height:18px;font-size:18px}.page-chip--accent{border-color:color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 30%,transparent)}.page-chip--warning{border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 35%,transparent)}.page-identity{display:grid;gap:4px;padding:12px 14px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);font-size:13px;color:var(--md-sys-color-on-surface-variant)}.page-section{font-weight:600;margin-top:8px}.page-section-help{margin-top:-4px;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.grid-form{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.state-grid{display:grid;gap:16px}.state-values,.state-group{padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:14px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface-container-low) 92%,transparent),transparent),var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.state-group{display:grid;gap:12px}.state-group-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-group-title{font-weight:600}.state-group-help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-list{display:grid;gap:12px}.state-card{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container) 84%,transparent)}.state-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-card-title{font-weight:600}.state-card-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.span-2{grid-column:span 2}.span-3{grid-column:1 / -1}.state-empty{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-operator-hint{display:flex;align-items:center;gap:8px;min-height:48px;padding:0 12px;border-radius:12px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-secondary-container) 35%,transparent)}.state-operator-hint mat-icon{color:var(--md-sys-color-secondary)}.page-actions{display:flex;justify-content:flex-end}.page-error{color:var(--md-sys-color-error);font-size:13px}.page-config .mat-mdc-form-field{width:100%;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.help-icon-button{margin-right:-4px}.mat-mdc-form-field-icon-suffix{align-self:center}@media(max-width:720px){.span-2,.span-3{grid-column:auto}.page-head{flex-direction:column}.state-group-head{align-items:stretch;flex-direction:column}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13936
|
+
`, isInline: true, styles: [".page-config{display:grid;gap:12px;padding:16px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.page-head{display:flex;align-items:flex-start;gap:12px}.page-head__copy{display:grid;gap:4px}.page-title{font-weight:600;font-size:18px;line-height:1.2}.page-subtitle{max-width:72ch;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.spacer{flex:1}.page-summary{display:flex;flex-wrap:wrap;gap:8px}.page-tabs{border-radius:16px;overflow:hidden;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent)}.page-tabs ::ng-deep .mdc-tab{min-width:120px}.page-tabs ::ng-deep .mdc-tab__text-label{font-size:13px;font-weight:600}.page-tab-panel{display:grid;gap:12px;padding:16px 4px 4px}.page-chip{display:inline-flex;align-items:center;gap:8px;min-height:36px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 88%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:500}.page-chip mat-icon{width:18px;height:18px;font-size:18px}.page-chip--accent{border-color:color-mix(in srgb,var(--md-sys-color-primary) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 30%,transparent)}.page-chip--warning{border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 35%,transparent)}.page-identity{display:grid;gap:4px;padding:12px 14px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);font-size:13px;color:var(--md-sys-color-on-surface-variant)}.page-section{font-weight:600;margin-top:8px}.page-section-help{margin-top:-4px;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.45}.grid-form{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.state-grid{display:grid;gap:16px}.state-values,.state-group{padding:14px;border:1px solid var(--md-sys-color-outline-variant);border-radius:14px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface-container-low) 92%,transparent),transparent),var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface))}.state-group{display:grid;gap:12px}.state-group-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-group-title{font-weight:600}.state-group-help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-list{display:grid;gap:12px}.state-card{display:grid;gap:12px;padding:12px;border-radius:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 80%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container) 84%,transparent)}.state-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.state-card-title{font-weight:600}.state-card-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.span-2{grid-column:span 2}.span-3{grid-column:1 / -1}.state-empty{color:var(--md-sys-color-on-surface-variant);font-size:13px}.state-operator-hint{display:flex;align-items:center;gap:8px;min-height:48px;padding:0 12px;border-radius:12px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-secondary-container) 35%,transparent)}.state-operator-hint mat-icon{color:var(--md-sys-color-secondary)}.page-actions{display:flex;justify-content:flex-end}.page-error{color:var(--md-sys-color-error);font-size:13px}.page-config .mat-mdc-form-field{width:100%;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.help-icon-button{margin-right:-4px}.mat-mdc-form-field-icon-suffix{align-self:center}@media(max-width:720px){.span-2,.span-3{grid-column:auto}.page-head{flex-direction:column}.state-group-head{align-items:stretch;flex-direction:column}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i10.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i10.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i8.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i8.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
12558
13937
|
}
|
|
12559
13938
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PageConfigEditorComponent, decorators: [{
|
|
12560
13939
|
type: Component,
|
|
@@ -14352,7 +15731,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
|
|
|
14352
15731
|
scope: 'templating',
|
|
14353
15732
|
targetKind: 'widgetShell',
|
|
14354
15733
|
target: { kind: 'widgetShell', resolver: 'widget-shell-by-widget-key', ambiguityPolicy: 'fail', required: true },
|
|
14355
|
-
inputSchema: { type: 'object', required: ['widgetKey'], properties: { widgetKey: { type: 'string' }, shell: { type: 'object' } } },
|
|
15734
|
+
inputSchema: { type: 'object', required: ['widgetKey'], properties: { widgetKey: { type: 'string' }, shell: { type: 'object', properties: { stickyHeader: { type: 'boolean', description: 'Retain the existing header within the widget during page scrolling; suspended for drag authoring, collapsed/overlay states and scroll recovery.' } } } } },
|
|
14356
15735
|
effects: [{ kind: 'compile-domain-patch', handler: 'page-builder-widget-shell-configure', handlerContract: {
|
|
14357
15736
|
reads: ['WidgetPageDefinition.widgets', 'WidgetShellEditorComponent', 'SettingsPanelBridge'],
|
|
14358
15737
|
writes: ['page.widgets[].shell'],
|
|
@@ -22725,6 +24104,10 @@ class DynamicPageBuilderComponent {
|
|
|
22725
24104
|
this.agenticAuthoringLastEtag.set(this.authoringDocument.etag?.trim() || null);
|
|
22726
24105
|
}
|
|
22727
24106
|
else if (authoringDocumentChange && !this.authoringDocument) {
|
|
24107
|
+
// Clearing the persisted document hands ownership back to the page input.
|
|
24108
|
+
const parsed = this.parsePage(this.page) || { widgets: [] };
|
|
24109
|
+
this.currentPage.set(parsed);
|
|
24110
|
+
this.lastRuntimePageChangeFingerprint = JSON.stringify(parsed);
|
|
22728
24111
|
this.persistedUiCompositionAuthoringSource.set(null);
|
|
22729
24112
|
this.agenticAuthoringLastEtag.set(null);
|
|
22730
24113
|
}
|