@erd-studio/renderer 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +8 -3
  3. package/dist/{chunk-DUQ2TTQH.js → chunk-64BVOHOR.js} +4 -3
  4. package/dist/chunk-JDL3BFJZ.js +10479 -0
  5. package/dist/{chunk-WOTSQZCQ.js → chunk-YLXBIRPE.js} +132 -2
  6. package/dist/edge-routing-worker.js +1 -0
  7. package/dist/editor.js +43 -3
  8. package/dist/index.js +14 -3
  9. package/dist/sizing.js +2 -2
  10. package/dist/store.js +1 -1
  11. package/dist/styles.css +912 -359
  12. package/dist/types/ErdCanvas.d.ts +38 -1
  13. package/dist/types/canvas/CanvasBackdrop.d.ts +3 -2
  14. package/dist/types/canvas/EdgeRouting.d.ts +56 -0
  15. package/dist/types/canvas/useCanvasGraph.d.ts +7 -1
  16. package/dist/types/canvas/useHoverFocus.d.ts +64 -0
  17. package/dist/types/components/DetailPanel/AliasEditor.d.ts +15 -1
  18. package/dist/types/components/DetailPanel/ColumnEditor.d.ts +18 -2
  19. package/dist/types/components/DetailPanel/DescriptionEditor.d.ts +1 -1
  20. package/dist/types/components/DetailPanel/DetailPanel.d.ts +31 -2
  21. package/dist/types/components/DetailPanel/FieldsSection.d.ts +68 -0
  22. package/dist/types/components/Graph/EdgeFlow.d.ts +55 -0
  23. package/dist/types/components/Graph/EdgeLabels.d.ts +18 -0
  24. package/dist/types/components/Graph/FkEdge.d.ts +8 -1
  25. package/dist/types/components/Graph/ModelNode.d.ts +1 -1
  26. package/dist/types/components/Legend/Legend.d.ts +34 -3
  27. package/dist/types/components/StatusBar/StatusBar.d.ts +45 -0
  28. package/dist/types/components/common/ColumnRowEditor.d.ts +18 -2
  29. package/dist/types/components/common/KeyBadgeGroup.d.ts +5 -1
  30. package/dist/types/editor.d.ts +8 -2
  31. package/dist/types/hooks/usePrefersReducedMotion.d.ts +13 -0
  32. package/dist/types/index.d.ts +2 -1
  33. package/dist/types/lib/badgeLabels.d.ts +6 -0
  34. package/dist/types/lib/canvasContext.d.ts +20 -0
  35. package/dist/types/lib/canvasFocus.d.ts +66 -0
  36. package/dist/types/lib/edgeFlow.d.ts +84 -0
  37. package/dist/types/lib/edgeRouting/index.d.ts +146 -0
  38. package/dist/types/lib/edgeRouting/input.d.ts +35 -0
  39. package/dist/types/lib/edgeRouting/lineStyle.d.ts +16 -0
  40. package/dist/types/lib/edgeRouting/render/corners.d.ts +52 -0
  41. package/dist/types/lib/edgeRouting/render/crossings.d.ts +27 -0
  42. package/dist/types/lib/edgeRouting/render/curveCrossings.d.ts +35 -0
  43. package/dist/types/lib/edgeRouting/render/pathRender.d.ts +74 -0
  44. package/dist/types/lib/edgeRouting/render/tunnels.d.ts +49 -0
  45. package/dist/types/lib/edgeRouting/routeAll.d.ts +20 -0
  46. package/dist/types/lib/edgeRouting/routers/orthogonal/geom.d.ts +58 -0
  47. package/dist/types/lib/edgeRouting/routers/orthogonal/grid.d.ts +77 -0
  48. package/dist/types/lib/edgeRouting/routers/orthogonal/nudge.d.ts +62 -0
  49. package/dist/types/lib/edgeRouting/routers/orthogonal/params.d.ts +152 -0
  50. package/dist/types/lib/edgeRouting/routers/orthogonal/router.d.ts +51 -0
  51. package/dist/types/lib/edgeRouting/routers/orthogonal/search.d.ts +81 -0
  52. package/dist/types/lib/edgeRouting/routers/orthogonalAvoid.d.ts +11 -0
  53. package/dist/types/lib/edgeRouting/types.d.ts +113 -0
  54. package/dist/types/lib/edgeRouting/worker/client.d.ts +38 -0
  55. package/dist/types/lib/edgeRouting/worker/entry.d.ts +1 -0
  56. package/dist/types/lib/edgeRouting/worker/protocol.d.ts +23 -0
  57. package/dist/types/lib/hoverIntent.d.ts +44 -0
  58. package/dist/types/lib/layerCues.d.ts +26 -0
  59. package/dist/types/lib/nodeOverlays.d.ts +6 -0
  60. package/dist/types/lib/nodeSizing.d.ts +1 -1
  61. package/dist/types/lib/pathGeometry.d.ts +45 -0
  62. package/dist/types/lib/reuseUnchanged.d.ts +28 -0
  63. package/dist/types/lib/roleOptions.d.ts +13 -0
  64. package/dist/types/store/editorStore.d.ts +66 -1
  65. package/dist/types/types/graph.d.ts +20 -1
  66. package/package.json +3 -2
  67. package/dist/chunk-HWA32XG5.js +0 -5652
  68. package/dist/types/components/DetailPanel/GrainEditor.d.ts +0 -16
  69. package/dist/types/components/DetailPanel/MetaEditor.d.ts +0 -21
  70. package/dist/types/components/DetailPanel/ModelRationale.d.ts +0 -27
  71. package/dist/types/components/DetailPanel/RationaleField.d.ts +0 -28
  72. package/dist/types/components/DetailPanel/RoleEditor.d.ts +0 -13
package/dist/styles.css CHANGED
@@ -296,6 +296,7 @@
296
296
  font-size: 12px;
297
297
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
298
298
  overflow: hidden;
299
+ transition: opacity 0.15s ease, filter 0.15s ease;
299
300
  }
300
301
  .model-node--logical {
301
302
  border-color: var(--stage-logical);
@@ -303,6 +304,21 @@
303
304
  .model-node--physical {
304
305
  border-color: var(--stage-physical);
305
306
  }
307
+ .model-node {
308
+ --model-node-ring: var(--stage-logical);
309
+ --model-node-ring-glow: var(--stage-logical-ring);
310
+ }
311
+ .model-node--stage-physical {
312
+ --model-node-ring: var(--stage-physical);
313
+ --model-node-ring-glow: var(--stage-physical-ring);
314
+ }
315
+ .editor-canvas--neutral .model-node--logical {
316
+ border-color: var(--canvas-neutral-border);
317
+ }
318
+ .editor-canvas--neutral .model-node {
319
+ --model-node-ring: var(--canvas-selection);
320
+ --model-node-ring-glow: var(--canvas-selection-glow);
321
+ }
306
322
  .model-node--ghost {
307
323
  border-color: var(--stage-ghost);
308
324
  border-style: dashed;
@@ -314,19 +330,17 @@
314
330
  .model-node--disc-extra {
315
331
  box-shadow: 0 0 0 2px var(--discrepancy-extra), 0 0 12px 2px rgba(245, 158, 11, 0.35);
316
332
  }
317
- .model-node--selected {
318
- box-shadow: 0 0 0 2px var(--stage-logical), 0 0 10px 1px rgba(96, 165, 250, 0.4);
319
- }
320
- .model-node--physical.model-node--selected {
321
- box-shadow: 0 0 0 2px var(--stage-physical), 0 0 10px 1px rgba(34, 197, 94, 0.4);
333
+ .model-node--selected,
334
+ .react-flow__node.selected .model-node {
335
+ box-shadow: 0 0 0 2px var(--model-node-ring), 0 0 10px 1px var(--model-node-ring-glow);
322
336
  }
323
- .model-node--disc-extra.model-node--selected {
337
+ .model-node--disc-extra.model-node--selected,
338
+ .react-flow__node.selected .model-node--disc-extra {
324
339
  box-shadow: 0 0 0 2px var(--discrepancy-extra), 0 0 12px 2px rgba(245, 158, 11, 0.35);
325
340
  }
326
341
  .model-node--dimmed {
327
342
  opacity: 0.25;
328
343
  filter: grayscale(0.4);
329
- transition: opacity 0.15s ease, filter 0.15s ease;
330
344
  }
331
345
  .model-node--dimmed:hover {
332
346
  opacity: 0.4;
@@ -348,6 +362,13 @@
348
362
  flex: 1;
349
363
  white-space: nowrap;
350
364
  }
365
+ .model-node__schema {
366
+ font-weight: 400;
367
+ color: var(--dim-fg);
368
+ }
369
+ .model-node--layered .model-node__header {
370
+ box-shadow: inset 0 3px 0 var(--model-node-layer-color);
371
+ }
351
372
  .model-node__model-id {
352
373
  margin-left: 8px;
353
374
  font-family: var(--vscode-editor-font-family, monospace);
@@ -379,10 +400,6 @@
379
400
  background: var(--ok-bg);
380
401
  color: var(--ok-fg);
381
402
  }
382
- .model-node__badge--layer {
383
- opacity: 0.7;
384
- font-style: italic;
385
- }
386
403
  .model-node__discrepancy-badge {
387
404
  flex-shrink: 0;
388
405
  display: inline-flex;
@@ -762,18 +779,55 @@
762
779
  color: var(--discrepancy-extra);
763
780
  font-weight: 500;
764
781
  }
765
- .react-flow__node.selected .model-node {
766
- box-shadow: 0 0 0 2px var(--vscode-focusBorder, #007fd4), 0 2px 8px rgba(0, 127, 212, 0.3);
767
- }
768
782
  .react-flow__node.dragging .model-node {
769
783
  opacity: 0.85;
770
784
  box-shadow: 0 0 0 2px var(--vscode-focusBorder, #007fd4), 0 4px 12px rgba(0, 0, 0, 0.25);
771
785
  }
786
+ .erd-flow--hover-focus .model-node {
787
+ opacity: 0.22;
788
+ filter: none;
789
+ }
790
+ .erd-flow--hover-focus .model-node--selected {
791
+ opacity: 0.4;
792
+ }
793
+ .erd-flow--hover-focus .model-node.model-node--focus-origin,
794
+ .erd-flow--hover-focus .model-node.model-node--focus-related {
795
+ opacity: 1;
796
+ filter: none;
797
+ }
798
+ .erd-flow--hover-focus .model-node--ghost.model-node--focus-related {
799
+ opacity: 0.65;
800
+ }
801
+ .model-node--logical.model-node--focus-origin:not(.model-node--selected):not(.model-node--disc-extra) {
802
+ box-shadow: 0 0 0 3px var(--stage-logical-ring);
803
+ }
804
+ .model-node--physical.model-node--focus-origin:not(.model-node--selected):not(.model-node--disc-extra) {
805
+ box-shadow: 0 0 0 3px var(--stage-physical-ring);
806
+ }
807
+ @media (prefers-reduced-motion: reduce) {
808
+ .model-node {
809
+ transition: none;
810
+ }
811
+ }
812
+ .model-node__off-diagram {
813
+ flex-shrink: 0;
814
+ padding: 0 5px;
815
+ border: 1px solid var(--panel-border);
816
+ border-radius: 8px;
817
+ font-size: 9px;
818
+ font-weight: 600;
819
+ line-height: 14px;
820
+ color: var(--dim-fg);
821
+ }
772
822
 
773
823
  /* src/components/Graph/FkEdge.css */
774
824
  .fk-edge {
775
825
  stroke-width: 2;
776
826
  fill: none;
827
+ transition: opacity 0.15s ease, filter 0.15s ease;
828
+ }
829
+ .fk-edge--flowing {
830
+ stroke-width: 2.5;
777
831
  }
778
832
  .fk-edge--logical {
779
833
  stroke: var(--stage-logical);
@@ -799,7 +853,6 @@
799
853
  .fk-edge--dimmed {
800
854
  opacity: 0.25;
801
855
  filter: grayscale(0.4);
802
- transition: opacity 0.15s ease, filter 0.15s ease;
803
856
  }
804
857
  .fk-edge--dimmed:hover {
805
858
  opacity: 0.4;
@@ -873,8 +926,33 @@
873
926
  .fk-edge__label--dimmed {
874
927
  opacity: 0.25;
875
928
  filter: grayscale(0.4);
929
+ }
930
+ .fk-edge__adornment {
876
931
  transition: opacity 0.15s ease, filter 0.15s ease;
877
932
  }
933
+ .fk-edge__flow-chevron,
934
+ .fk-edge__flow-dot {
935
+ fill: currentColor;
936
+ stroke: var(--edge-flow-halo);
937
+ stroke-width: 1.5;
938
+ paint-order: stroke fill;
939
+ stroke-linejoin: round;
940
+ }
941
+ .fk-edge__flow--logical {
942
+ color: var(--stage-logical);
943
+ }
944
+ .fk-edge__flow--physical {
945
+ color: var(--stage-physical);
946
+ }
947
+ .fk-edge__flow--ghost {
948
+ color: var(--stage-ghost);
949
+ }
950
+ .fk-edge__flow--discrepancy-extra {
951
+ color: var(--discrepancy-extra);
952
+ }
953
+ .fk-edge__flow--discrepancy-cardinality-mismatch {
954
+ color: var(--discrepancy-mismatch);
955
+ }
878
956
  .fk-edge:hover {
879
957
  stroke-width: 3;
880
958
  }
@@ -957,6 +1035,31 @@
957
1035
  background: var(--button-bg);
958
1036
  color: var(--button-fg);
959
1037
  }
1038
+ .erd-flow--hover-focus .fk-edge {
1039
+ opacity: 0.15;
1040
+ filter: none;
1041
+ }
1042
+ .erd-flow--hover-focus .fk-edge.fk-edge--lit {
1043
+ opacity: 1;
1044
+ }
1045
+ .erd-flow--hover-focus .fk-edge__adornment {
1046
+ opacity: 0.2;
1047
+ }
1048
+ .erd-flow--hover-focus .fk-edge__adornment.fk-edge__adornment--lit {
1049
+ opacity: 1;
1050
+ filter: none;
1051
+ }
1052
+ @media (prefers-reduced-motion: reduce) {
1053
+ .fk-edge,
1054
+ .fk-edge__adornment {
1055
+ transition: none;
1056
+ }
1057
+ }
1058
+ @media print {
1059
+ .fk-edge__flow {
1060
+ display: none;
1061
+ }
1062
+ }
960
1063
 
961
1064
  /* src/components/Graph/AnnotationNode.css */
962
1065
  .annotation-node {
@@ -1896,199 +1999,528 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
1896
1999
  font-size: 10px;
1897
2000
  }
1898
2001
 
1899
- /* src/components/DetailPanel/ColumnEditor.css */
1900
- .column-editor {
2002
+ /* src/components/DetailPanel/FieldsSection.css */
2003
+ .fields-section {
1901
2004
  display: flex;
1902
2005
  flex-direction: column;
1903
2006
  gap: 8px;
1904
2007
  }
1905
- .column-editor__header {
2008
+ .fields-section__head {
1906
2009
  display: flex;
1907
- align-items: center;
2010
+ align-items: baseline;
1908
2011
  justify-content: space-between;
1909
2012
  gap: 8px;
1910
2013
  }
1911
- .column-editor__header-actions {
1912
- display: flex;
1913
- align-items: center;
1914
- gap: 6px;
2014
+ .fields-section__title {
2015
+ margin: 0;
1915
2016
  }
1916
- .column-editor__expand-controls {
1917
- display: flex;
1918
- align-items: center;
1919
- gap: 2px;
2017
+ .fields-section__head .fields-section__title {
2018
+ margin: 0;
1920
2019
  }
1921
- .column-editor__expand-btn {
1922
- position: relative;
1923
- display: flex;
1924
- align-items: center;
1925
- justify-content: center;
1926
- width: 20px;
1927
- height: 20px;
2020
+ .fields-section__customise {
2021
+ flex-shrink: 0;
1928
2022
  padding: 0;
1929
2023
  border: none;
1930
- border-radius: 3px;
1931
2024
  background: transparent;
1932
- color: var(--vscode-descriptionForeground, #888);
1933
- font-size: 12px;
2025
+ color: var(--dim-fg);
2026
+ font-size: 10px;
1934
2027
  cursor: pointer;
1935
- transition: color 0.1s ease, background 0.1s ease;
1936
- }
1937
- .column-editor__expand-btn:hover {
1938
- color: var(--editor-fg);
1939
- background: rgba(255, 255, 255, 0.08);
2028
+ text-decoration: underline;
2029
+ text-decoration-style: dotted;
1940
2030
  }
1941
- .column-editor__expand-btn::after {
1942
- content: attr(data-tooltip);
1943
- position: absolute;
1944
- top: 100%;
1945
- left: 50%;
1946
- transform: translateX(-50%);
1947
- margin-top: 4px;
1948
- padding: 3px 6px;
1949
- background: var(--vscode-editorWidget-background, #252526);
1950
- border: 1px solid var(--panel-border);
1951
- border-radius: 3px;
1952
- font-size: 10px;
1953
- white-space: nowrap;
2031
+ .fields-section__customise:hover,
2032
+ .fields-section__customise:focus-visible {
1954
2033
  color: var(--editor-fg);
1955
- opacity: 0;
1956
- visibility: hidden;
1957
- transition: opacity 0.1s ease, visibility 0.1s ease;
1958
- pointer-events: none;
1959
- z-index: 100;
1960
- }
1961
- .column-editor__expand-btn:hover::after {
1962
- opacity: 1;
1963
- visibility: visible;
1964
2034
  }
1965
- .column-editor__title {
1966
- margin: 0;
1967
- font-size: 11px;
1968
- font-weight: 600;
1969
- text-transform: uppercase;
1970
- letter-spacing: 0.5px;
1971
- color: var(--vscode-descriptionForeground, #888);
2035
+ .fields-section__customise:focus-visible {
2036
+ outline: 1px solid var(--focus-border);
2037
+ outline-offset: 2px;
1972
2038
  }
1973
- .column-editor__add-btn {
1974
- padding: 3px 8px;
1975
- border: 1px dashed var(--panel-border);
1976
- border-radius: 3px;
1977
- background: transparent;
1978
- color: var(--button-bg);
2039
+ .fields-section__label {
1979
2040
  font-size: 10px;
1980
- font-weight: 500;
1981
- cursor: pointer;
1982
- transition: background 0.1s ease, border-color 0.1s ease;
1983
- }
1984
- .column-editor__add-btn:hover:not(:disabled) {
1985
- background: rgba(59, 130, 246, 0.08);
1986
- border-color: var(--button-bg);
2041
+ text-transform: uppercase;
2042
+ letter-spacing: 0.04em;
2043
+ color: var(--dim-fg);
1987
2044
  }
1988
- .column-editor__add-btn:disabled {
1989
- opacity: 0.5;
1990
- cursor: not-allowed;
2045
+ .fields-section__list {
2046
+ margin: 0;
2047
+ display: flex;
2048
+ flex-direction: column;
2049
+ gap: 8px;
1991
2050
  }
1992
- .column-editor__list {
2051
+ .fields-section__row {
1993
2052
  display: flex;
1994
2053
  flex-direction: column;
1995
- gap: 1px;
2054
+ gap: 2px;
1996
2055
  }
1997
- .column-editor__empty {
1998
- padding: 8px 6px;
1999
- color: var(--vscode-descriptionForeground, #888);
2000
- font-style: italic;
2001
- text-align: center;
2002
- font-size: 11px;
2056
+ .fields-section__row .fields-section__name {
2057
+ margin: 0;
2003
2058
  }
2004
- .column-editor__separator {
2005
- display: flex;
2006
- align-items: center;
2007
- gap: 8px;
2008
- padding: 6px 0;
2059
+ .fields-section__list[hidden] {
2060
+ display: none;
2009
2061
  }
2010
- .column-editor__separator::before,
2011
- .column-editor__separator::after {
2012
- content: "";
2013
- flex: 1;
2014
- height: 1px;
2015
- background: var(--panel-border);
2062
+ .fields-section--read-only:not(.fields-section--compact) .fields-section__list {
2063
+ gap: 0;
2016
2064
  }
2017
- .column-editor__separator-text {
2018
- font-size: 9px;
2019
- font-weight: 600;
2020
- letter-spacing: 1px;
2021
- color: var(--model-design);
2022
- text-transform: uppercase;
2065
+ .fields-section--read-only:not(.fields-section--compact) .fields-section__row {
2066
+ display: grid;
2067
+ grid-template-columns: minmax(64px, 34%) minmax(0, 1fr);
2068
+ column-gap: 10px;
2069
+ align-items: baseline;
2070
+ padding: 5px 0;
2071
+ border-top: 1px solid var(--panel-border);
2023
2072
  }
2024
- .column-editor__separator--approved .column-editor__separator-text {
2025
- color: var(--model-approved);
2073
+ .fields-section--read-only:not(.fields-section--compact) .fields-section__row:first-child {
2074
+ border-top: none;
2075
+ padding-top: 0;
2026
2076
  }
2027
- .column-editor__add-btn--bottom {
2028
- width: 100%;
2029
- margin-top: 6px;
2030
- justify-content: center;
2077
+ .fields-section--read-only:not(.fields-section--compact) .fields-section__row:last-child {
2078
+ padding-bottom: 0;
2031
2079
  }
2032
- .column-editor__accept-all-btn {
2033
- padding: 3px 8px;
2034
- border: 1px solid var(--vscode-editorWarning-foreground, #cca700);
2035
- border-radius: 3px;
2036
- background: rgba(204, 167, 0, 0.1);
2037
- color: var(--vscode-editorWarning-foreground, #cca700);
2038
- font-size: 10px;
2080
+ .fields-section--read-only:not(.fields-section--compact) .fields-section__name {
2081
+ line-height: 1.6;
2082
+ font-size: 11px;
2039
2083
  font-weight: 500;
2040
- cursor: pointer;
2041
- transition: background 0.1s ease;
2084
+ text-transform: none;
2085
+ letter-spacing: normal;
2042
2086
  }
2043
- .column-editor__accept-all-btn:hover {
2044
- background: rgba(204, 167, 0, 0.2);
2087
+ .fields-section--collapsible {
2088
+ gap: 0;
2045
2089
  }
2046
-
2047
- /* src/components/DetailPanel/DetailPanel.css */
2048
- .detail-panel {
2049
- width: 340px;
2050
- max-height: calc(100vh - 100px);
2051
- overflow-y: auto;
2052
- background: var(--panel-bg);
2053
- border: 1px solid var(--panel-border);
2054
- border-radius: 6px;
2055
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
2056
- font-size: 12px;
2090
+ .fields-section--collapsible .fields-section__title {
2091
+ margin: 0;
2057
2092
  }
2058
- .detail-panel__header {
2059
- display: flex;
2060
- align-items: center;
2061
- justify-content: space-between;
2093
+ .fields-section--collapsible.fields-section--open {
2062
2094
  gap: 8px;
2063
- padding: 10px 12px;
2064
- border-bottom: 1px solid var(--panel-border);
2065
- background: var(--panel-bg);
2066
- position: sticky;
2067
- top: 0;
2068
- z-index: 1;
2069
2095
  }
2070
- .detail-panel__title {
2096
+ .fields-section__toggle {
2097
+ display: inline-flex;
2098
+ align-items: center;
2099
+ gap: 6px;
2100
+ width: 100%;
2071
2101
  margin: 0;
2072
- font-size: 14px;
2073
- font-weight: 600;
2102
+ padding: 0;
2103
+ border: none;
2104
+ background: transparent;
2105
+ color: inherit;
2106
+ font: inherit;
2107
+ letter-spacing: inherit;
2108
+ text-transform: inherit;
2109
+ text-align: left;
2110
+ cursor: pointer;
2111
+ }
2112
+ .fields-section__toggle:hover {
2074
2113
  color: var(--editor-fg);
2075
- overflow: hidden;
2076
- text-overflow: ellipsis;
2077
- white-space: nowrap;
2078
- flex: 1;
2079
- min-width: 0;
2080
2114
  }
2081
- .detail-panel__title--editable {
2082
- cursor: pointer;
2115
+ .fields-section__toggle:focus-visible {
2116
+ outline: 1px solid var(--focus-border);
2117
+ outline-offset: 2px;
2118
+ border-radius: 2px;
2083
2119
  }
2084
- .detail-panel__title--editable:hover {
2085
- text-decoration: underline;
2086
- text-decoration-style: dotted;
2087
- text-underline-offset: 3px;
2120
+ .fields-section__chevron {
2121
+ width: 10px;
2122
+ font-size: 11px;
2123
+ text-align: center;
2088
2124
  }
2089
- .detail-panel__title-input {
2090
- flex: 1;
2091
- min-width: 0;
2125
+ .fields-section__count {
2126
+ font-variant-numeric: tabular-nums;
2127
+ }
2128
+ .fields-section__value {
2129
+ margin: 0;
2130
+ min-width: 0;
2131
+ font-size: 11px;
2132
+ line-height: 1.5;
2133
+ color: var(--editor-fg);
2134
+ white-space: pre-wrap;
2135
+ overflow-wrap: anywhere;
2136
+ }
2137
+ .fields-section__value--structured {
2138
+ font-family: var(--vscode-editor-font-family);
2139
+ color: var(--dim-fg);
2140
+ }
2141
+ .fields-section__field {
2142
+ display: flex;
2143
+ flex-direction: column;
2144
+ gap: 3px;
2145
+ }
2146
+ .fields-section__field-head {
2147
+ display: flex;
2148
+ align-items: center;
2149
+ flex-wrap: wrap;
2150
+ gap: 6px;
2151
+ min-height: 20px;
2152
+ }
2153
+ .fields-section__name {
2154
+ font-size: 10px;
2155
+ font-weight: 600;
2156
+ text-transform: uppercase;
2157
+ letter-spacing: 0.5px;
2158
+ color: var(--dim-fg);
2159
+ overflow-wrap: anywhere;
2160
+ }
2161
+ .fields-section__badge {
2162
+ padding: 0 5px;
2163
+ border-radius: 8px;
2164
+ font-size: 9px;
2165
+ line-height: 15px;
2166
+ white-space: nowrap;
2167
+ border: 1px solid var(--panel-border);
2168
+ color: var(--dim-fg);
2169
+ }
2170
+ .fields-section__badge--retired {
2171
+ border-color: var(--warning-fg);
2172
+ background: var(--warning-bg);
2173
+ color: var(--warning-fg);
2174
+ }
2175
+ .fields-section__badge--dbt {
2176
+ border-color: var(--ai-fg);
2177
+ background: var(--ai-bg);
2178
+ color: var(--ai-fg);
2179
+ }
2180
+ .fields-section__actions {
2181
+ display: flex;
2182
+ gap: 2px;
2183
+ margin-left: auto;
2184
+ visibility: hidden;
2185
+ }
2186
+ .fields-section__field:hover .fields-section__actions,
2187
+ .fields-section__field:focus-within .fields-section__actions {
2188
+ visibility: visible;
2189
+ }
2190
+ .fields-section__icon-btn {
2191
+ border: none;
2192
+ background: transparent;
2193
+ color: var(--dim-fg);
2194
+ cursor: pointer;
2195
+ font-size: 12px;
2196
+ line-height: 1;
2197
+ padding: 1px 3px;
2198
+ }
2199
+ .fields-section__icon-btn:hover,
2200
+ .fields-section__icon-btn:focus-visible {
2201
+ color: var(--editor-fg);
2202
+ }
2203
+ .fields-section__text {
2204
+ font-size: 11px;
2205
+ line-height: 1.5;
2206
+ color: var(--editor-fg);
2207
+ white-space: pre-wrap;
2208
+ overflow-wrap: anywhere;
2209
+ }
2210
+ .fields-section__empty-value {
2211
+ color: var(--dim-fg);
2212
+ }
2213
+ .fields-section__placeholder {
2214
+ padding: 3px 6px;
2215
+ border: 1px dashed var(--panel-border);
2216
+ border-radius: 3px;
2217
+ background: transparent;
2218
+ color: var(--dim-fg);
2219
+ font-size: 11px;
2220
+ line-height: 1.4;
2221
+ text-align: left;
2222
+ cursor: text;
2223
+ }
2224
+ .fields-section__placeholder:hover,
2225
+ .fields-section__placeholder:focus-visible {
2226
+ border-color: var(--ai-fg);
2227
+ background: var(--ai-bg);
2228
+ color: var(--editor-fg);
2229
+ }
2230
+ .fields-section__edit {
2231
+ display: flex;
2232
+ flex-direction: column;
2233
+ gap: 6px;
2234
+ }
2235
+ .fields-section__input,
2236
+ .fields-section__select {
2237
+ width: 100%;
2238
+ box-sizing: border-box;
2239
+ padding: 3px 6px;
2240
+ border: 1px solid var(--input-border, var(--panel-border));
2241
+ border-radius: 3px;
2242
+ background: var(--input-bg);
2243
+ color: var(--input-fg);
2244
+ font-size: 12px;
2245
+ }
2246
+ .fields-section__select {
2247
+ cursor: pointer;
2248
+ }
2249
+ .fields-section__input:focus,
2250
+ .fields-section__select:focus {
2251
+ outline: 1px solid var(--focus-border);
2252
+ outline-offset: -1px;
2253
+ }
2254
+ .fields-section__input--key {
2255
+ font-family: var(--vscode-editor-font-family);
2256
+ }
2257
+ .fields-section__option--outside {
2258
+ color: var(--warning-fg);
2259
+ }
2260
+ .fields-section__hint {
2261
+ font-size: 10px;
2262
+ line-height: 1.4;
2263
+ color: var(--dim-fg);
2264
+ }
2265
+ .fields-section__group {
2266
+ display: flex;
2267
+ flex-direction: column;
2268
+ gap: 6px;
2269
+ padding-top: 6px;
2270
+ border-top: 1px dashed var(--panel-border);
2271
+ }
2272
+ .fields-section__group-title {
2273
+ font-size: 10px;
2274
+ font-weight: 600;
2275
+ letter-spacing: 0.04em;
2276
+ color: var(--dim-fg);
2277
+ }
2278
+ .fields-section__new {
2279
+ display: flex;
2280
+ flex-direction: column;
2281
+ gap: 4px;
2282
+ }
2283
+ .fields-section__new-actions {
2284
+ display: flex;
2285
+ gap: 6px;
2286
+ }
2287
+ .fields-section__error {
2288
+ font-size: 11px;
2289
+ color: var(--error-fg);
2290
+ }
2291
+ .fields-section__warning {
2292
+ font-size: 11px;
2293
+ color: var(--warning-fg);
2294
+ }
2295
+ .fields-section__add-btn {
2296
+ align-self: flex-start;
2297
+ }
2298
+ .fields-section--compact {
2299
+ margin-top: 6px;
2300
+ gap: 4px;
2301
+ }
2302
+ .fields-section--compact .fields-section__list {
2303
+ gap: 4px;
2304
+ }
2305
+ .fields-section--compact .fields-section__add-btn {
2306
+ padding: 3px 8px;
2307
+ font-size: 10px;
2308
+ }
2309
+
2310
+ /* src/components/DetailPanel/ColumnEditor.css */
2311
+ .column-editor {
2312
+ display: flex;
2313
+ flex-direction: column;
2314
+ gap: 8px;
2315
+ }
2316
+ .column-editor__header {
2317
+ display: flex;
2318
+ align-items: center;
2319
+ justify-content: space-between;
2320
+ gap: 8px;
2321
+ }
2322
+ .column-editor__header-actions {
2323
+ display: flex;
2324
+ align-items: center;
2325
+ gap: 6px;
2326
+ }
2327
+ .column-editor__expand-controls {
2328
+ display: flex;
2329
+ align-items: center;
2330
+ gap: 2px;
2331
+ }
2332
+ .column-editor__expand-btn {
2333
+ position: relative;
2334
+ display: flex;
2335
+ align-items: center;
2336
+ justify-content: center;
2337
+ width: 20px;
2338
+ height: 20px;
2339
+ padding: 0;
2340
+ border: none;
2341
+ border-radius: 3px;
2342
+ background: transparent;
2343
+ color: var(--vscode-descriptionForeground, #888);
2344
+ font-size: 12px;
2345
+ cursor: pointer;
2346
+ transition: color 0.1s ease, background 0.1s ease;
2347
+ }
2348
+ .column-editor__expand-btn:hover {
2349
+ color: var(--editor-fg);
2350
+ background: rgba(255, 255, 255, 0.08);
2351
+ }
2352
+ .column-editor__expand-btn::after {
2353
+ content: attr(data-tooltip);
2354
+ position: absolute;
2355
+ top: 100%;
2356
+ left: 50%;
2357
+ transform: translateX(-50%);
2358
+ margin-top: 4px;
2359
+ padding: 3px 6px;
2360
+ background: var(--vscode-editorWidget-background, #252526);
2361
+ border: 1px solid var(--panel-border);
2362
+ border-radius: 3px;
2363
+ font-size: 10px;
2364
+ white-space: nowrap;
2365
+ color: var(--editor-fg);
2366
+ opacity: 0;
2367
+ visibility: hidden;
2368
+ transition: opacity 0.1s ease, visibility 0.1s ease;
2369
+ pointer-events: none;
2370
+ z-index: 100;
2371
+ }
2372
+ .column-editor__expand-btn:hover::after {
2373
+ opacity: 1;
2374
+ visibility: visible;
2375
+ }
2376
+ .column-editor__title {
2377
+ margin: 0;
2378
+ font-size: 11px;
2379
+ font-weight: 600;
2380
+ text-transform: uppercase;
2381
+ letter-spacing: 0.5px;
2382
+ color: var(--vscode-descriptionForeground, #888);
2383
+ }
2384
+ .column-editor__add-btn {
2385
+ padding: 3px 8px;
2386
+ border: 1px dashed var(--panel-border);
2387
+ border-radius: 3px;
2388
+ background: transparent;
2389
+ color: var(--button-bg);
2390
+ font-size: 10px;
2391
+ font-weight: 500;
2392
+ cursor: pointer;
2393
+ transition: background 0.1s ease, border-color 0.1s ease;
2394
+ }
2395
+ .column-editor__add-btn:hover:not(:disabled) {
2396
+ background: rgba(59, 130, 246, 0.08);
2397
+ border-color: var(--button-bg);
2398
+ }
2399
+ .column-editor__add-btn:disabled {
2400
+ opacity: 0.5;
2401
+ cursor: not-allowed;
2402
+ }
2403
+ .column-editor__list {
2404
+ display: flex;
2405
+ flex-direction: column;
2406
+ gap: 1px;
2407
+ }
2408
+ .column-editor__empty {
2409
+ padding: 8px 6px;
2410
+ color: var(--vscode-descriptionForeground, #888);
2411
+ font-style: italic;
2412
+ text-align: center;
2413
+ font-size: 11px;
2414
+ }
2415
+ .column-editor__separator {
2416
+ display: flex;
2417
+ align-items: center;
2418
+ gap: 8px;
2419
+ padding: 6px 0;
2420
+ }
2421
+ .column-editor__separator::before,
2422
+ .column-editor__separator::after {
2423
+ content: "";
2424
+ flex: 1;
2425
+ height: 1px;
2426
+ background: var(--panel-border);
2427
+ }
2428
+ .column-editor__separator-text {
2429
+ font-size: 9px;
2430
+ font-weight: 600;
2431
+ letter-spacing: 1px;
2432
+ color: var(--model-design);
2433
+ text-transform: uppercase;
2434
+ }
2435
+ .column-editor__separator--approved .column-editor__separator-text {
2436
+ color: var(--model-approved);
2437
+ }
2438
+ .column-editor__add-btn--bottom {
2439
+ width: 100%;
2440
+ margin-top: 6px;
2441
+ justify-content: center;
2442
+ }
2443
+ .column-editor__accept-all-btn {
2444
+ padding: 3px 8px;
2445
+ border: 1px solid var(--vscode-editorWarning-foreground, #cca700);
2446
+ border-radius: 3px;
2447
+ background: rgba(204, 167, 0, 0.1);
2448
+ color: var(--vscode-editorWarning-foreground, #cca700);
2449
+ font-size: 10px;
2450
+ font-weight: 500;
2451
+ cursor: pointer;
2452
+ transition: background 0.1s ease;
2453
+ }
2454
+ .column-editor__accept-all-btn:hover {
2455
+ background: rgba(204, 167, 0, 0.2);
2456
+ }
2457
+ .column-editor .column-row-editor__name {
2458
+ flex: 1 1 auto;
2459
+ min-width: min(10ch, 40%);
2460
+ }
2461
+ .column-editor .column-row-editor__type {
2462
+ flex: 0 1 auto;
2463
+ min-width: 0;
2464
+ max-width: 55%;
2465
+ overflow: hidden;
2466
+ text-overflow: ellipsis;
2467
+ white-space: nowrap;
2468
+ }
2469
+
2470
+ /* src/components/DetailPanel/DetailPanel.css */
2471
+ .detail-panel {
2472
+ width: 340px;
2473
+ max-height: calc(100vh - 100px);
2474
+ overflow-y: auto;
2475
+ background: var(--panel-bg);
2476
+ border: 1px solid var(--panel-border);
2477
+ border-radius: 6px;
2478
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
2479
+ font-size: 12px;
2480
+ }
2481
+ .detail-panel--viewer {
2482
+ max-height: min(calc(100vh - 100px), calc(100% - 192px));
2483
+ overflow-x: hidden;
2484
+ overscroll-behavior: contain;
2485
+ }
2486
+ .detail-panel--viewer .detail-panel__value {
2487
+ min-width: 0;
2488
+ overflow-wrap: anywhere;
2489
+ }
2490
+ .detail-panel__header {
2491
+ display: flex;
2492
+ align-items: center;
2493
+ justify-content: space-between;
2494
+ gap: 8px;
2495
+ padding: 10px 12px;
2496
+ border-bottom: 1px solid var(--panel-border);
2497
+ background: var(--panel-bg);
2498
+ position: sticky;
2499
+ top: 0;
2500
+ z-index: 1;
2501
+ }
2502
+ .detail-panel__title {
2503
+ margin: 0;
2504
+ font-size: 14px;
2505
+ font-weight: 600;
2506
+ color: var(--editor-fg);
2507
+ overflow: hidden;
2508
+ text-overflow: ellipsis;
2509
+ white-space: nowrap;
2510
+ flex: 1;
2511
+ min-width: 0;
2512
+ }
2513
+ .detail-panel__title--editable {
2514
+ cursor: pointer;
2515
+ }
2516
+ .detail-panel__title--editable:hover {
2517
+ text-decoration: underline;
2518
+ text-decoration-style: dotted;
2519
+ text-underline-offset: 3px;
2520
+ }
2521
+ .detail-panel__title-input {
2522
+ flex: 1;
2523
+ min-width: 0;
2092
2524
  margin: 0;
2093
2525
  padding: 2px 6px;
2094
2526
  font-size: 14px;
@@ -2436,6 +2868,41 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
2436
2868
  text-overflow: ellipsis;
2437
2869
  white-space: nowrap;
2438
2870
  }
2871
+ .detail-panel__relationship--wrap {
2872
+ display: grid;
2873
+ grid-template-columns: 16px minmax(0, 1fr);
2874
+ column-gap: 6px;
2875
+ row-gap: 2px;
2876
+ align-items: start;
2877
+ }
2878
+ .detail-panel__relationship--wrap .detail-panel__rel-cardinality {
2879
+ grid-column: 2;
2880
+ justify-self: start;
2881
+ }
2882
+ .detail-panel__relationship--wrap .detail-panel__rel-columns {
2883
+ flex-wrap: wrap;
2884
+ row-gap: 1px;
2885
+ overflow: visible;
2886
+ }
2887
+ .detail-panel__relationship--wrap .detail-panel__rel-local,
2888
+ .detail-panel__relationship--wrap .detail-panel__rel-target {
2889
+ min-width: 0;
2890
+ white-space: normal;
2891
+ overflow: visible;
2892
+ text-overflow: clip;
2893
+ overflow-wrap: anywhere;
2894
+ }
2895
+ .detail-panel__relationship--wrap .detail-panel__rel-direction,
2896
+ .detail-panel__relationship--wrap .detail-panel__rel-cardinality {
2897
+ margin-top: 1px;
2898
+ }
2899
+ .detail-panel__rel-role {
2900
+ flex-basis: 100%;
2901
+ font-size: 10px;
2902
+ font-style: italic;
2903
+ color: var(--dim-fg);
2904
+ overflow-wrap: anywhere;
2905
+ }
2439
2906
  .detail-panel__rel-cardinality {
2440
2907
  flex-shrink: 0;
2441
2908
  padding: 1px 4px;
@@ -2583,49 +3050,7 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
2583
3050
  }
2584
3051
  .detail-panel__confirm-actions .detail-panel__button--danger:hover {
2585
3052
  background: rgba(239, 68, 68, 0.2);
2586
- border-color: #ef4444;
2587
- }
2588
- .detail-panel__rationale-section {
2589
- display: flex;
2590
- flex-direction: column;
2591
- gap: 8px;
2592
- }
2593
- .detail-panel__rationale-toggle {
2594
- display: flex;
2595
- align-items: center;
2596
- gap: 4px;
2597
- padding: 0;
2598
- border: none;
2599
- background: none;
2600
- cursor: pointer;
2601
- color: var(--vscode-descriptionForeground, #888);
2602
- font-size: 11px;
2603
- font-weight: 600;
2604
- text-transform: uppercase;
2605
- letter-spacing: 0.5px;
2606
- font-family: inherit;
2607
- }
2608
- .detail-panel__rationale-toggle:hover {
2609
- color: var(--editor-fg);
2610
- }
2611
- .detail-panel__rationale-chevron {
2612
- display: inline-block;
2613
- font-size: 10px;
2614
- transition: transform 0.15s ease;
2615
- }
2616
- .detail-panel__rationale-chevron--open {
2617
- transform: rotate(90deg);
2618
- }
2619
- .detail-panel__rationale-count {
2620
- font-weight: 400;
2621
- font-size: 10px;
2622
- color: var(--vscode-descriptionForeground, #888);
2623
- opacity: 0.7;
2624
- }
2625
- .detail-panel__rationale-body {
2626
- display: flex;
2627
- flex-direction: column;
2628
- gap: 8px;
3053
+ border-color: #ef4444;
2629
3054
  }
2630
3055
  .detail-panel__rationale-header {
2631
3056
  display: flex;
@@ -2654,9 +3079,6 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
2654
3079
  background 0.1s ease,
2655
3080
  color 0.1s ease;
2656
3081
  }
2657
- .detail-panel__rationale-section:hover .detail-panel__rationale-edit-btn {
2658
- opacity: 1;
2659
- }
2660
3082
  .detail-panel__rationale-edit-btn:hover {
2661
3083
  background: var(--button-bg);
2662
3084
  color: var(--button-fg);
@@ -2666,13 +3088,6 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
2666
3088
  flex-direction: column;
2667
3089
  gap: 2px;
2668
3090
  }
2669
- .detail-panel__rationale-label {
2670
- font-size: 10px;
2671
- font-weight: 600;
2672
- text-transform: uppercase;
2673
- letter-spacing: 0.5px;
2674
- color: #8b5cf6;
2675
- }
2676
3091
  .detail-panel__rationale-text {
2677
3092
  margin: 0;
2678
3093
  font-size: 11px;
@@ -2722,169 +3137,109 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
2722
3137
  border-color 0.1s ease;
2723
3138
  }
2724
3139
  .detail-panel__rationale-add-btn:hover {
2725
- background: rgba(139, 92, 246, 0.08);
2726
- color: #8b5cf6;
2727
- border-color: #8b5cf6;
2728
- }
2729
- .detail-panel__role-section {
2730
- display: flex;
2731
- flex-direction: column;
2732
- gap: 6px;
3140
+ background: var(--ai-bg);
3141
+ color: var(--ai-fg);
3142
+ border-color: var(--ai-fg);
2733
3143
  }
2734
- .detail-panel__role-select {
2735
- padding: 4px 6px;
2736
- border: 1px solid var(--input-border, var(--panel-border));
2737
- background: var(--input-bg);
2738
- color: var(--input-fg);
2739
- font-size: 12px;
3144
+ .detail-panel__rel-backwards {
3145
+ flex-shrink: 0;
3146
+ padding: 1px 6px;
3147
+ border: 1px solid var(--warning-fg);
2740
3148
  border-radius: 3px;
3149
+ background: var(--warning-bg);
3150
+ color: var(--warning-fg);
3151
+ font-size: 11px;
3152
+ line-height: 1.4;
3153
+ white-space: nowrap;
2741
3154
  cursor: pointer;
2742
- width: 100%;
2743
- }
2744
- .detail-panel__role-select:focus {
2745
- outline: 1px solid var(--focus-border);
2746
- outline-offset: -1px;
2747
3155
  }
2748
- .detail-panel__grain-section {
2749
- display: flex;
2750
- flex-direction: column;
2751
- gap: 8px;
2752
- }
2753
- .detail-panel__grain-section:hover .detail-panel__rationale-edit-btn {
2754
- opacity: 1;
2755
- }
2756
- .meta-editor {
2757
- display: flex;
2758
- flex-direction: column;
2759
- gap: 6px;
3156
+ .detail-panel__rel-backwards:hover {
3157
+ border-color: var(--focus-border);
3158
+ background: var(--button-bg);
3159
+ color: var(--button-fg);
2760
3160
  }
2761
- .meta-editor__title {
2762
- margin: 0;
3161
+ .detail-panel__file-path {
3162
+ flex: 1;
3163
+ min-width: 0;
3164
+ overflow: hidden;
3165
+ text-overflow: ellipsis;
3166
+ white-space: nowrap;
2763
3167
  }
2764
- .meta-editor__label {
3168
+ .detail-panel__file-open,
3169
+ .detail-panel__off-add,
3170
+ .detail-panel__off-add-all {
3171
+ flex-shrink: 0;
3172
+ padding: 1px 6px;
3173
+ border: 1px solid var(--panel-border);
3174
+ border-radius: 3px;
3175
+ background: transparent;
3176
+ color: var(--editor-fg);
2765
3177
  font-size: 10px;
2766
- text-transform: uppercase;
2767
- letter-spacing: 0.04em;
2768
- color: var(--vscode-descriptionForeground, #888);
3178
+ cursor: pointer;
3179
+ white-space: nowrap;
2769
3180
  }
2770
- .meta-editor__list {
2771
- margin: 0;
2772
- display: flex;
2773
- flex-direction: column;
2774
- gap: 2px;
3181
+ .detail-panel__file-open:hover,
3182
+ .detail-panel__off-add:hover,
3183
+ .detail-panel__off-add-all:hover {
3184
+ background: var(--button-hover-bg);
3185
+ border-color: var(--focus-border);
3186
+ color: var(--button-fg);
2775
3187
  }
2776
- .meta-editor__row {
2777
- display: grid;
2778
- grid-template-columns: minmax(70px, 35%) 1fr auto;
2779
- align-items: baseline;
3188
+ .detail-panel__off-diagram-head {
3189
+ display: flex;
3190
+ align-items: center;
3191
+ justify-content: space-between;
2780
3192
  gap: 8px;
2781
- padding: 2px 4px;
2782
- border-radius: 3px;
3193
+ margin-bottom: 8px;
2783
3194
  }
2784
- .meta-editor__row:hover {
2785
- background: var(--input-bg);
3195
+ .detail-panel__off-diagram-title {
3196
+ margin: 0;
2786
3197
  }
2787
- .meta-editor__key {
2788
- font-family: var(--vscode-editor-font-family);
2789
- font-size: 11px;
2790
- color: var(--vscode-descriptionForeground, #888);
3198
+ .detail-panel__off-text {
3199
+ flex: 1;
3200
+ min-width: 0;
2791
3201
  overflow: hidden;
2792
3202
  text-overflow: ellipsis;
2793
3203
  white-space: nowrap;
2794
3204
  }
2795
- .meta-editor__value {
2796
- margin: 0;
2797
- min-width: 0;
2798
- font-size: 12px;
2799
- color: var(--editor-fg);
2800
- }
2801
- .meta-editor__text {
2802
- overflow-wrap: anywhere;
2803
- }
2804
- .meta-editor__text--structured {
2805
- font-family: var(--vscode-editor-font-family);
2806
- font-size: 11px;
3205
+ .detail-panel__off-detail {
2807
3206
  color: var(--dim-fg);
2808
3207
  }
2809
- .meta-editor__actions {
2810
- display: flex;
2811
- gap: 2px;
2812
- visibility: hidden;
2813
- }
2814
- .meta-editor__row:hover .meta-editor__actions,
2815
- .meta-editor__row:focus-within .meta-editor__actions {
2816
- visibility: visible;
3208
+ .detail-panel__modelling {
3209
+ padding-top: 6px;
3210
+ padding-bottom: 6px;
2817
3211
  }
2818
- .meta-editor__icon-btn {
3212
+ .detail-panel__modelling-toggle {
3213
+ display: flex;
3214
+ align-items: center;
3215
+ gap: 6px;
3216
+ width: 100%;
3217
+ padding: 2px 0;
2819
3218
  border: none;
2820
3219
  background: transparent;
2821
- color: var(--vscode-descriptionForeground, #888);
3220
+ color: var(--dim-fg);
3221
+ font-size: 11px;
3222
+ font-weight: 600;
3223
+ letter-spacing: 0.5px;
3224
+ text-transform: uppercase;
3225
+ text-align: left;
2822
3226
  cursor: pointer;
2823
- font-size: 12px;
2824
- line-height: 1;
2825
- padding: 1px 3px;
2826
3227
  }
2827
- .meta-editor__icon-btn:hover,
2828
- .meta-editor__icon-btn:focus-visible {
3228
+ .detail-panel__modelling-toggle:hover {
2829
3229
  color: var(--editor-fg);
2830
3230
  }
2831
- .meta-editor__input {
2832
- width: 100%;
2833
- box-sizing: border-box;
2834
- padding: 3px 6px;
2835
- border: 1px solid var(--panel-border);
2836
- border-radius: 3px;
2837
- background: var(--input-bg);
2838
- color: var(--input-fg);
2839
- font-size: 12px;
2840
- }
2841
- .meta-editor__input:focus {
2842
- outline: none;
2843
- border-color: var(--focus-border);
2844
- }
2845
- .meta-editor__input--key {
2846
- font-family: var(--vscode-editor-font-family);
2847
- }
2848
- .meta-editor__new {
2849
- display: flex;
2850
- flex-direction: column;
2851
- gap: 4px;
2852
- }
2853
- .meta-editor__new-actions {
2854
- display: flex;
2855
- gap: 6px;
2856
- }
2857
- .meta-editor__error {
2858
- font-size: 11px;
2859
- color: var(--error-fg);
2860
- }
2861
- .meta-editor__add-btn {
2862
- align-self: flex-start;
2863
- }
2864
- .meta-editor--compact {
2865
- margin-top: 6px;
2866
- gap: 4px;
3231
+ .detail-panel__modelling-toggle:focus-visible {
3232
+ outline: 1px solid var(--focus-border);
3233
+ outline-offset: 2px;
2867
3234
  }
2868
- .meta-editor--compact .meta-editor__add-btn {
2869
- padding: 3px 8px;
3235
+ .detail-panel__modelling-chevron {
3236
+ width: 10px;
2870
3237
  font-size: 10px;
2871
3238
  }
2872
- .detail-panel__rel-backwards {
2873
- flex-shrink: 0;
2874
- padding: 1px 6px;
2875
- border: 1px solid var(--warning-fg);
2876
- border-radius: 3px;
2877
- background: var(--warning-bg);
2878
- color: var(--warning-fg);
2879
- font-size: 11px;
2880
- line-height: 1.4;
2881
- white-space: nowrap;
2882
- cursor: pointer;
2883
- }
2884
- .detail-panel__rel-backwards:hover {
2885
- border-color: var(--focus-border);
2886
- background: var(--button-bg);
2887
- color: var(--button-fg);
3239
+ .detail-panel__modelling-optional {
3240
+ font-weight: 400;
3241
+ text-transform: none;
3242
+ letter-spacing: 0;
2888
3243
  }
2889
3244
 
2890
3245
  /* src/components/Legend/Legend.css */
@@ -2911,6 +3266,10 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
2911
3266
  background: var(--button-bg);
2912
3267
  color: var(--button-fg);
2913
3268
  }
3269
+ .legend--stage-physical {
3270
+ --stage-logical: var(--stage-physical);
3271
+ --stage-logical-ring: var(--stage-physical-ring);
3272
+ }
2914
3273
  .legend {
2915
3274
  max-width: 260px;
2916
3275
  background: var(--panel-bg);
@@ -2959,6 +3318,8 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
2959
3318
  max-height: min(60vh, 520px);
2960
3319
  overflow-y: auto;
2961
3320
  overflow-x: hidden;
3321
+ scrollbar-width: thin;
3322
+ scrollbar-color: var(--dim-fg) transparent;
2962
3323
  }
2963
3324
  .legend__section {
2964
3325
  padding: 8px 12px;
@@ -3053,6 +3414,15 @@ body[data-vscode-theme-kind=vscode-high-contrast] .annotation-node__link-badge {
3053
3414
  .legend__edge {
3054
3415
  stroke-width: 2;
3055
3416
  }
3417
+ .legend__flow-line {
3418
+ width: 48px;
3419
+ height: 12px;
3420
+ flex-shrink: 0;
3421
+ overflow: visible;
3422
+ }
3423
+ .legend__items--flow {
3424
+ gap: 6px;
3425
+ }
3056
3426
  .legend__edge--logical {
3057
3427
  stroke: var(--stage-logical);
3058
3428
  }
@@ -3146,14 +3516,21 @@ body[data-vscode-theme-kind=vscode-high-contrast] .legend__annotation-card {
3146
3516
  .legend__items--symbols {
3147
3517
  margin-top: 10px;
3148
3518
  }
3149
- .legend__badge--schema,
3519
+ .legend__badge--layer,
3150
3520
  .legend__badge--source {
3151
3521
  flex-shrink: 0;
3152
3522
  min-width: 26px;
3153
3523
  }
3154
- .legend__badge--schema {
3155
- background: rgba(96, 165, 250, 0.2);
3156
- color: var(--stage-logical);
3524
+ .legend__badge--layer {
3525
+ background: var(--layer-silver-bg);
3526
+ color: var(--layer-silver);
3527
+ }
3528
+ .legend__schema-sample {
3529
+ flex-shrink: 0;
3530
+ min-width: 26px;
3531
+ font-size: 11px;
3532
+ font-weight: 400;
3533
+ color: var(--dim-fg);
3157
3534
  }
3158
3535
  .legend__badge--source {
3159
3536
  background: var(--dim-fg);
@@ -3212,6 +3589,80 @@ body[data-vscode-theme-kind=vscode-high-contrast] .legend__annotation-card {
3212
3589
  background: rgba(156, 163, 175, 0.12);
3213
3590
  }
3214
3591
 
3592
+ /* src/components/StatusBar/StatusBar.css */
3593
+ .status-bar {
3594
+ display: flex;
3595
+ align-items: center;
3596
+ gap: 8px;
3597
+ padding: 4px 10px;
3598
+ margin-left: 40px;
3599
+ background: var(--panel-bg);
3600
+ border: 1px solid var(--panel-border);
3601
+ border-radius: 4px;
3602
+ font-size: 11px;
3603
+ color: var(--editor-fg);
3604
+ opacity: 0.85;
3605
+ }
3606
+ .status-bar__item {
3607
+ font-variant-numeric: tabular-nums;
3608
+ white-space: nowrap;
3609
+ }
3610
+ .status-bar__counts {
3611
+ display: inline-flex;
3612
+ align-items: center;
3613
+ gap: 8px;
3614
+ white-space: nowrap;
3615
+ }
3616
+ .status-bar__divider {
3617
+ color: var(--panel-border);
3618
+ }
3619
+ .status-bar__layers {
3620
+ display: inline-flex;
3621
+ align-items: center;
3622
+ gap: 10px;
3623
+ }
3624
+ .status-bar__layer {
3625
+ display: inline-flex;
3626
+ align-items: center;
3627
+ gap: 4px;
3628
+ font-variant-numeric: tabular-nums;
3629
+ white-space: nowrap;
3630
+ }
3631
+ .status-bar__badge {
3632
+ padding: 0 4px;
3633
+ border-radius: 3px;
3634
+ font-size: 9px;
3635
+ font-weight: 700;
3636
+ letter-spacing: 0.5px;
3637
+ line-height: 1.5;
3638
+ background: var(--button-bg);
3639
+ color: var(--button-fg);
3640
+ }
3641
+ .status-bar--viewer {
3642
+ margin-left: 51px;
3643
+ max-width: calc(100% - 51px - 231px);
3644
+ flex-direction: column;
3645
+ align-items: flex-start;
3646
+ flex-wrap: nowrap;
3647
+ row-gap: 2px;
3648
+ }
3649
+ .status-bar--viewer .status-bar__divider--layers {
3650
+ display: none;
3651
+ }
3652
+ .status-bar--viewer.status-bar--beside-legend {
3653
+ margin-left: 283px;
3654
+ max-width: calc(100% - 283px - 231px);
3655
+ }
3656
+ .status-bar--viewer .status-bar__layers {
3657
+ flex-wrap: wrap;
3658
+ row-gap: 2px;
3659
+ }
3660
+ @container (max-width: 719px) {
3661
+ .status-bar--viewer.status-bar--beside-legend {
3662
+ display: none;
3663
+ }
3664
+ }
3665
+
3215
3666
  /* src/styles/theme.css */
3216
3667
  *,
3217
3668
  *::before,
@@ -3258,6 +3709,12 @@ body {
3258
3709
  --stage-physical-border: rgba(34, 197, 94, 0.2);
3259
3710
  --stage-ghost: #9ca3af;
3260
3711
  --stage-ghost-bg: rgba(156, 163, 175, 0.08);
3712
+ --canvas-neutral-line: var(--vscode-descriptionForeground, #8a94a3);
3713
+ --canvas-neutral-border: color-mix(in srgb, var(--canvas-neutral-line) 55%, transparent);
3714
+ --canvas-neutral-ring: color-mix(in srgb, var(--canvas-neutral-line) 30%, transparent);
3715
+ --canvas-selection: var(--vscode-focusBorder, #007fd4);
3716
+ --canvas-selection-glow: color-mix(in srgb, var(--canvas-selection) 40%, transparent);
3717
+ --edge-flow-halo: var(--editor-bg);
3261
3718
  --discrepancy-extra: #f59e0b;
3262
3719
  --discrepancy-mismatch: #ef4444;
3263
3720
  --model-built: var(--stage-physical);
@@ -3279,6 +3736,17 @@ body {
3279
3736
  --layer-silver-bg: rgba(192, 192, 192, 0.2);
3280
3737
  --layer-gold: #d4a800;
3281
3738
  --layer-gold-bg: rgba(255, 215, 0, 0.2);
3739
+ --star-gold: #e3b341;
3740
+ --star-gold-light: #f5d76e;
3741
+ --star-gold-dark: #b8860b;
3742
+ --star-gold-fg: #241a00;
3743
+ --star-gold-glow: rgba(227, 179, 65, 0.5);
3744
+ --star-gold-shine: rgba(255, 255, 255, 0.6);
3745
+ }
3746
+ .editor-canvas--neutral .react-flow__viewport,
3747
+ .editor-canvas--neutral .legend {
3748
+ --stage-logical: var(--canvas-neutral-line);
3749
+ --stage-logical-ring: var(--canvas-neutral-ring);
3282
3750
  }
3283
3751
  .react-flow {
3284
3752
  background-color: var(--editor-bg);
@@ -3287,4 +3755,89 @@ body {
3287
3755
  display: none;
3288
3756
  }
3289
3757
 
3758
+ /* src/canvas/EdgeRouting.css */
3759
+ .edge-overlay {
3760
+ position: absolute;
3761
+ left: 0;
3762
+ top: 0;
3763
+ overflow: visible;
3764
+ pointer-events: none;
3765
+ z-index: 1000;
3766
+ color: var(--stage-logical);
3767
+ }
3768
+ .edge-overlay__tunnel {
3769
+ color: var(--stage-logical);
3770
+ transition: opacity 0.15s ease;
3771
+ }
3772
+ .edge-overlay__tunnel--physical {
3773
+ color: var(--stage-physical);
3774
+ }
3775
+ .edge-overlay__tunnel--ghost {
3776
+ color: var(--stage-ghost);
3777
+ }
3778
+ .edge-overlay__tunnel--discrepancy-extra {
3779
+ color: var(--discrepancy-extra);
3780
+ }
3781
+ .edge-overlay__tunnel--discrepancy-missing {
3782
+ color: var(--stage-ghost);
3783
+ }
3784
+ .edge-overlay__tunnel--discrepancy-cardinality-mismatch {
3785
+ color: var(--discrepancy-mismatch);
3786
+ }
3787
+ .edge-overlay__tunnel-line {
3788
+ fill: none;
3789
+ stroke: color-mix(in srgb, currentColor 70%, var(--editor-fg));
3790
+ stroke-width: 1.5;
3791
+ stroke-dasharray: 4 4;
3792
+ stroke-linecap: butt;
3793
+ opacity: 0.55;
3794
+ transition: opacity 0.15s ease, stroke-width 0.15s ease;
3795
+ }
3796
+ .edge-overlay__portal {
3797
+ stroke: currentColor;
3798
+ stroke-width: 1.75;
3799
+ stroke-linecap: round;
3800
+ opacity: 0.9;
3801
+ fill: var(--editor-bg);
3802
+ transition: opacity 0.15s ease;
3803
+ }
3804
+ .edge-overlay__tunnel--lit .edge-overlay__tunnel-line {
3805
+ opacity: 0.95;
3806
+ stroke-width: 2;
3807
+ }
3808
+ .edge-overlay__tunnel--lit .edge-overlay__portal {
3809
+ opacity: 1;
3810
+ }
3811
+ .edge-overlay__tunnel--dimmed {
3812
+ opacity: 0.2;
3813
+ }
3814
+ .erd-flow--hover-focus .edge-overlay__tunnel {
3815
+ opacity: 0.1;
3816
+ }
3817
+ .erd-flow--hover-focus .edge-overlay__tunnel.edge-overlay__tunnel--lit {
3818
+ opacity: 1;
3819
+ }
3820
+ @media (prefers-reduced-motion: reduce) {
3821
+ .edge-overlay__tunnel,
3822
+ .edge-overlay__tunnel-line,
3823
+ .edge-overlay__portal {
3824
+ transition: none;
3825
+ }
3826
+ }
3827
+ .fk-edge__halo {
3828
+ fill: none;
3829
+ stroke: var(--editor-bg);
3830
+ stroke-width: 7;
3831
+ stroke-linecap: butt;
3832
+ }
3833
+ .editor-canvas--neutral .fk-edge--logical.fk-edge--lit,
3834
+ .editor-canvas--neutral .fk-edge--logical.fk-edge--flowing,
3835
+ .editor-canvas--neutral .fk-edge__flow--logical,
3836
+ .editor-canvas--neutral .fk-edge__adornment--lit {
3837
+ --stage-logical: var(--diagram-layer-color, var(--canvas-neutral-line));
3838
+ }
3839
+ .editor-canvas--neutral .edge-overlay__tunnel--logical.edge-overlay__tunnel--lit {
3840
+ color: var(--diagram-layer-color, var(--canvas-neutral-line));
3841
+ }
3842
+
3290
3843
  /* src/styles.css */