@likec4/diagram 1.24.0 → 1.24.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 (116) hide show
  1. package/dist/LikeC4Diagram.css.d.ts +5 -0
  2. package/dist/LikeC4Diagram.css.js +1 -0
  3. package/dist/LikeC4Diagram.d.ts +1 -1
  4. package/dist/LikeC4Diagram.js +6 -2
  5. package/dist/LikeC4Diagram.props.d.ts +6 -0
  6. package/dist/base/BaseXYFlow.d.ts +1 -1
  7. package/dist/base/BaseXYFlow.js +12 -3
  8. package/dist/base/const.d.ts +1 -1
  9. package/dist/base/const.js +1 -1
  10. package/dist/base/primitives/compound/CompoundActionButton.css.js +2 -0
  11. package/dist/base/primitives/compound/CompoundDetailsButton.css.js +2 -0
  12. package/dist/base/primitives/compound/CompoundNodeContainer.css.d.ts +0 -1
  13. package/dist/base/primitives/compound/CompoundNodeContainer.css.js +4 -4
  14. package/dist/base/primitives/compound/CompoundNodeContainer.js +35 -22
  15. package/dist/base/primitives/compound/CompoundTitle.css.js +3 -1
  16. package/dist/base/primitives/customNode.js +1 -1
  17. package/dist/base/primitives/edge/EdgeContainer.js +5 -4
  18. package/dist/base/primitives/edge/EdgeLabel.css.d.ts +0 -1
  19. package/dist/base/primitives/edge/EdgeLabel.css.js +2 -5
  20. package/dist/base/primitives/edge/EdgeLabel.js +5 -5
  21. package/dist/base/primitives/edge/edge.css.d.ts +1 -1
  22. package/dist/base/primitives/edge/edge.css.js +4 -5
  23. package/dist/base/primitives/element/ElementActionButtons.css.js +2 -0
  24. package/dist/base/primitives/element/ElementActionButtons.js +4 -3
  25. package/dist/base/primitives/element/ElementDetailsButton.css.js +2 -0
  26. package/dist/base/primitives/element/ElementNodeContainer.css.js +2 -0
  27. package/dist/base/primitives/element/ElementNodeContainer.js +3 -1
  28. package/dist/base/primitives/element/ElementShape.css.js +4 -2
  29. package/dist/base/primitives/element/ElementShape.js +2 -3
  30. package/dist/base/primitives/element/ElementTitle.css.js +2 -0
  31. package/dist/base/primitives/element/styles.css.js +2 -0
  32. package/dist/components/SearchControl.css.js +2 -0
  33. package/dist/context/FramerMotionConfig.d.ts +9 -1
  34. package/dist/context/FramerMotionConfig.js +5 -2
  35. package/dist/context/RootContainer.js +13 -1
  36. package/dist/diagram.css +1 -1
  37. package/dist/globals.css.d.ts +2 -0
  38. package/dist/hooks/safeContext.js +1 -0
  39. package/dist/hooks/useDiagram.d.ts +554 -864
  40. package/dist/hooks/useDiagram.js +1 -0
  41. package/dist/hooks/useIsReducedGraphics.d.ts +4 -0
  42. package/dist/hooks/useIsReducedGraphics.js +8 -0
  43. package/dist/hooks/useXYFlow.js +1 -1
  44. package/dist/likec4diagram/DiagramUI.d.ts +2 -1
  45. package/dist/likec4diagram/DiagramUI.js +5 -3
  46. package/dist/likec4diagram/custom/nodes/nodeTypes.js +2 -2
  47. package/dist/likec4diagram/ui/controls/styles.css.js +2 -0
  48. package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.css.js +2 -0
  49. package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +3 -4
  50. package/dist/likec4diagram/ui/search/LikeC4Search.css.js +2 -0
  51. package/dist/overlays/element-details/ElementDetailsCard.js +12 -8
  52. package/dist/overlays/element-details/actor.d.ts +9084 -2569
  53. package/dist/overlays/overlay/Overlay.js +6 -3
  54. package/dist/overlays/relationship-details/RelationshipDetails.js +31 -17
  55. package/dist/overlays/relationship-details/actor.d.ts +228 -3
  56. package/dist/overlays/relationship-details/actor.js +86 -14
  57. package/dist/overlays/relationship-details/hooks.d.ts +3 -0
  58. package/dist/overlays/relationship-details/hooks.js +6 -2
  59. package/dist/overlays/relationships-browser/-useRelationshipsView.js +12 -3
  60. package/dist/overlays/relationships-browser/RelationshipsBrowser.js +12 -3
  61. package/dist/overlays/relationships-browser/actor.d.ts +271 -54
  62. package/dist/overlays/relationships-browser/actor.js +86 -23
  63. package/dist/state/DiagramActorProvider.js +12 -2
  64. package/dist/state/diagram-machine.d.ts +563 -867
  65. package/dist/state/diagram-machine.js +82 -81
  66. package/dist/state/persistence.d.ts +5 -0
  67. package/dist/state/persistence.js +23 -0
  68. package/package.json +9 -9
  69. package/src/LikeC4Diagram.css.ts +13 -5
  70. package/src/LikeC4Diagram.props.ts +7 -0
  71. package/src/LikeC4Diagram.tsx +33 -24
  72. package/src/base/BaseXYFlow.tsx +14 -9
  73. package/src/base/const.ts +1 -1
  74. package/src/base/primitives/compound/CompoundActionButton.css.ts +6 -0
  75. package/src/base/primitives/compound/CompoundDetailsButton.css.ts +4 -0
  76. package/src/base/primitives/compound/CompoundNodeContainer.css.ts +41 -59
  77. package/src/base/primitives/compound/CompoundNodeContainer.tsx +42 -22
  78. package/src/base/primitives/compound/CompoundTitle.css.ts +14 -13
  79. package/src/base/primitives/customNode.ts +3 -2
  80. package/src/base/primitives/edge/EdgeContainer.tsx +4 -3
  81. package/src/base/primitives/edge/EdgeLabel.css.ts +17 -11
  82. package/src/base/primitives/edge/EdgeLabel.tsx +4 -4
  83. package/src/base/primitives/edge/edge.css.ts +47 -27
  84. package/src/base/primitives/element/ElementActionButtons.css.ts +4 -0
  85. package/src/base/primitives/element/ElementActionButtons.tsx +4 -2
  86. package/src/base/primitives/element/ElementDetailsButton.css.ts +6 -8
  87. package/src/base/primitives/element/ElementNodeContainer.css.ts +18 -21
  88. package/src/base/primitives/element/ElementNodeContainer.tsx +3 -1
  89. package/src/base/primitives/element/ElementShape.css.ts +10 -6
  90. package/src/base/primitives/element/ElementShape.tsx +2 -2
  91. package/src/components/SearchControl.css.ts +11 -4
  92. package/src/context/FramerMotionConfig.tsx +13 -2
  93. package/src/context/RootContainer.tsx +9 -2
  94. package/src/globals.css.ts +3 -0
  95. package/src/hooks/safeContext.tsx +2 -1
  96. package/src/hooks/useDiagram.ts +1 -0
  97. package/src/hooks/useIsReducedGraphics.ts +5 -0
  98. package/src/hooks/useXYFlow.ts +1 -1
  99. package/src/likec4diagram/DiagramUI.tsx +5 -3
  100. package/src/likec4diagram/custom/nodes/nodeTypes.tsx +2 -2
  101. package/src/likec4diagram/ui/controls/styles.css.ts +11 -1
  102. package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.css.ts +10 -3
  103. package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.tsx +6 -3
  104. package/src/likec4diagram/ui/search/LikeC4Search.css.ts +1 -0
  105. package/src/overlays/element-details/ElementDetailsCard.tsx +238 -231
  106. package/src/overlays/overlay/Overlay.css.ts +1 -9
  107. package/src/overlays/overlay/Overlay.tsx +6 -3
  108. package/src/overlays/relationship-details/RelationshipDetails.tsx +83 -66
  109. package/src/overlays/relationship-details/actor.ts +106 -13
  110. package/src/overlays/relationship-details/hooks.ts +6 -2
  111. package/src/overlays/relationships-browser/-useRelationshipsView.ts +10 -0
  112. package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +16 -8
  113. package/src/overlays/relationships-browser/actor.ts +92 -22
  114. package/src/state/DiagramActorProvider.tsx +13 -2
  115. package/src/state/diagram-machine.ts +80 -79
  116. package/src/state/persistence.ts +22 -0
@@ -1,7 +1,7 @@
1
- import { rem } from '@mantine/core'
2
1
  import { createVar, fallbackVar, globalStyle, keyframes, style } from '@vanilla-extract/css'
3
2
  import { calc } from '@vanilla-extract/css-utils'
4
- import { easings, mantine, vars, whereLight } from '../../../theme-vars'
3
+ import { whereNotReducedGraphics } from '../../../LikeC4Diagram.css'
4
+ import { easings, vars, whereLight } from '../../../theme-vars'
5
5
 
6
6
  export const varCompoundOpacity = createVar('opacity')
7
7
  export const varBorderRadius = createVar('borderRadius')
@@ -10,75 +10,55 @@ export const varBorderColor = createVar('border-color')
10
10
  const varBorderWidth = createVar('border-width')
11
11
 
12
12
  export const container = style({
13
+ vars: {
14
+ [varBorderRadius]: '6px',
15
+ [varBorderWidth]: '3px',
16
+ },
13
17
  position: 'relative',
14
18
  width: '100%',
15
19
  height: '100%',
16
20
  padding: 0,
17
21
  margin: 0,
18
22
  border: '0px solid transparent',
19
- vars: {
20
- [varBorderRadius]: '6px',
21
- [varBorderWidth]: '3px',
22
- },
23
- })
24
-
25
- globalStyle(`.react-flow__node:has(${container}[data-likec4-dimmed="true"])`, {
26
- opacity: 0.25,
27
- transition: 'opacity 600ms ease-in-out, filter 600ms ease-in-out',
28
- transitionDelay: '200ms',
29
- filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
30
- willChange: 'opacity, filter',
31
- })
32
-
33
- globalStyle(`.react-flow__node:has(${container}[data-likec4-dimmed="immediate"])`, {
34
- opacity: 0.25,
35
- transition: 'opacity 100ms ease-in-out, filter 100ms ease-in-out',
36
- filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
37
- willChange: 'opacity, filter',
38
- })
39
-
40
- const outlineColor = fallbackVar(
41
- mantine.colors.primaryColors.outline,
42
- mantine.colors.primaryColors.filled,
43
- vars.element.stroke,
44
- )
45
-
46
- export const compoundBg = style({
47
- borderRadius: varBorderRadius,
48
23
  boxShadow: '0 4px 10px 0.5px rgba(0,0,0,0.1) , 0 2px 2px -1px rgba(0,0,0,0.4)',
49
- padding: 0,
50
- margin: 0,
51
- transition: `all 250ms ${easings.inOut}`,
52
- // backgroundClip: 'padding-box',
53
- // overflow: 'hidden',
54
- cursor: 'default',
24
+ ':before': {
25
+ borderRadius: varBorderRadius,
26
+ content: ' ',
27
+ position: 'absolute',
28
+ top: 0,
29
+ left: 0,
30
+ width: '100%',
31
+ height: '100%',
32
+ border: '0px solid transparent',
33
+ background: vars.element.fill,
34
+ backgroundClip: 'padding-box',
35
+ },
55
36
  selectors: {
56
- [`:where(.react-flow__node.dragging) &`]: {
37
+ [`&:is([data-compound-transparent="true"])`]: {
57
38
  boxShadow: 'none',
58
39
  },
59
- ':where(.react-flow__node:focus-visible) &': {
60
- transitionDuration: '0ms',
61
- outline: `3px solid ${outlineColor}`,
62
- outlineOffset: rem(1.5),
63
- },
64
- [`:where([data-compound-transparent="true"]) &`]: {
40
+ [`&:is([data-compound-transparent="true"]):before`]: {
65
41
  opacity: varCompoundOpacity,
66
42
  borderWidth: calc(varBorderWidth).subtract('1px').toString(),
67
43
  },
68
- [`:where([data-compound-transparent="true"]:is([data-hovered="true"])) &`]: {
69
- transitionDelay: '0.15s',
70
- transitionDuration: '0.4s',
44
+ [`${whereNotReducedGraphics} &:is([data-compound-transparent="true"]):before`]: {
45
+ transition: `all 200ms ${easings.inOut}`,
46
+ },
47
+ [`:where(.react-flow__node.dragging) &`]: {
48
+ boxShadow: 'none',
49
+ },
50
+ [`&:is([data-likec4-dimmed="true"])`]: {
51
+ opacity: 0.25,
52
+ transition: 'opacity 600ms ease-in-out, filter 600ms ease-in-out',
53
+ transitionDelay: '200ms',
54
+ filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
55
+ },
56
+ [`&:is([data-likec4-dimmed="immediate"])`]: {
57
+ opacity: 0.25,
58
+ transition: 'opacity 100ms ease-in-out, filter 100ms ease-in-out',
59
+ filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
71
60
  },
72
61
  },
73
- position: 'absolute',
74
- top: 0,
75
- left: 0,
76
- width: '100%',
77
- height: '100%',
78
- pointerEvents: 'none',
79
- border: '0px solid transparent',
80
- background: vars.element.fill,
81
- backgroundClip: 'padding-box',
82
62
  })
83
63
 
84
64
  globalStyle(`:where([data-mantine-color-scheme='dark'] [data-compound-transparent="true"])`, {
@@ -157,11 +137,13 @@ export const indicator = style({
157
137
 
158
138
  globalStyle(`${indicator} rect`, {
159
139
  stroke: indicatorStroke,
160
- transformOrigin: 'center center',
161
140
  strokeWidth: indicatorStrokeWidth,
141
+ fill: 'none',
142
+ })
143
+ globalStyle(`${whereNotReducedGraphics} ${indicator} rect`, {
144
+ transformOrigin: 'center center',
162
145
  animationDuration: '800ms',
163
- animationName: indicatorKeyframes,
164
146
  animationIterationCount: 'infinite',
165
147
  animationDirection: 'alternate',
166
- fill: 'none',
148
+ animationName: indicatorKeyframes,
167
149
  })
@@ -1,10 +1,11 @@
1
1
  import type { DiagramNode } from '@likec4/core'
2
2
  import { type BoxProps, Box, createPolymorphicComponent } from '@mantine/core'
3
- import { assignInlineVars } from '@vanilla-extract/dynamic'
3
+ import { useDebouncedValue } from '@mantine/hooks'
4
4
  import clsx from 'clsx'
5
5
  import { m } from 'framer-motion'
6
6
  import { type PropsWithChildren, forwardRef } from 'react'
7
7
  import { clamp, isNumber } from 'remeda'
8
+ import { useIsReducedGraphics } from '../../../hooks/useIsReducedGraphics'
8
9
  import type { NodeProps } from '../../types'
9
10
  import * as css from './CompoundNodeContainer.css'
10
11
 
@@ -22,32 +23,49 @@ type CompoundNodeContainerProps =
22
23
  nodeProps: NodeProps<RequiredData>
23
24
  }>
24
25
 
26
+ function getVarName(variable: string): string {
27
+ var matches = variable.match(/^var\((.*)\)$/)
28
+ if (matches) {
29
+ return matches[1]!
30
+ }
31
+ return variable
32
+ }
33
+
34
+ const opacityVar = getVarName(css.varCompoundOpacity)
35
+ const borderTransparencyVar = getVarName(css.varBorderTransparency)
36
+
25
37
  export const CompoundNodeContainer = createPolymorphicComponent<'div', CompoundNodeContainerProps>(
26
38
  forwardRef<HTMLDivElement, CompoundNodeContainerProps>(({
27
39
  nodeProps: {
40
+ selected: isSelected = false,
28
41
  data: {
29
42
  hovered: isHovered = false,
30
43
  dimmed: isDimmed = false,
31
- style,
32
44
  ...data
33
45
  },
34
46
  },
35
47
  children,
48
+ style,
36
49
  ...rest
37
50
  }, ref) => {
38
- const isTransparent = isNumber(style.opacity) && style.opacity < 100
39
- let opacity = clamp((style.opacity ?? 100) / 100, {
51
+ const isReducedGraphics = useIsReducedGraphics()
52
+ const isTransparent = isNumber(data.style.opacity) && data.style.opacity < 100
53
+ let _opacity = clamp((data.style.opacity ?? 100) / 100, {
40
54
  min: 0,
41
55
  max: 1,
42
56
  })
43
- if (isTransparent && isHovered) {
44
- opacity = Math.min(opacity + 0.11, 1)
57
+ if (isTransparent && isHovered && !isReducedGraphics) {
58
+ _opacity = Math.min(_opacity + 0.11, 1)
45
59
  }
60
+
61
+ const [opacity] = useDebouncedValue(Math.round(_opacity * 100) / 100, isHovered ? 200 : 50)
62
+
46
63
  const MAX_TRANSPARENCY = 40
47
64
  const borderTransparency = clamp(MAX_TRANSPARENCY - opacity * MAX_TRANSPARENCY, {
48
65
  min: 0,
49
66
  max: MAX_TRANSPARENCY,
50
67
  })
68
+
51
69
  return (
52
70
  <Box
53
71
  ref={ref}
@@ -63,30 +81,32 @@ export const CompoundNodeContainer = createPolymorphicComponent<'div', CompoundN
63
81
  data-compound-transparent={isTransparent}
64
82
  data-likec4-dimmed={isDimmed}
65
83
  data-likec4-shape={data.shape}
66
- style={assignInlineVars({
67
- [css.varCompoundOpacity]: opacity.toFixed(2),
68
- [css.varBorderTransparency]: `${borderTransparency}%`,
69
- })}
84
+ style={{
85
+ ...style,
86
+ [opacityVar]: opacity,
87
+ [borderTransparencyVar]: `${borderTransparency}%`,
88
+ }}
70
89
  {...rest}
71
90
  >
72
- <svg className={css.indicator}>
73
- <rect
74
- x={0}
75
- y={0}
76
- width={'100%'}
77
- height={'100%'}
78
- rx={6}
79
- />
80
- </svg>
81
- <div className={css.compoundBg} />
82
- {isTransparent && style.border !== 'none' && (
91
+ {isTransparent && !isSelected && data.style.border !== 'none' && (
83
92
  <div
84
93
  className={css.compoundBorder}
85
94
  style={{
86
- borderStyle: style.border ?? 'dashed',
95
+ borderStyle: data.style.border ?? 'dashed',
87
96
  }}
88
97
  />
89
98
  )}
99
+ {isSelected && (
100
+ <svg className={css.indicator}>
101
+ <rect
102
+ x={0}
103
+ y={0}
104
+ width={'100%'}
105
+ height={'100%'}
106
+ rx={6}
107
+ />
108
+ </svg>
109
+ )}
90
110
  {children}
91
111
  </Box>
92
112
  )
@@ -1,15 +1,18 @@
1
1
  import { rem } from '@mantine/core'
2
2
  import { globalStyle, style } from '@vanilla-extract/css'
3
- import { vars, whereLight } from '../../../theme-vars'
3
+ import { hiddenIfZoomTooSmall, whereNotReducedGraphics } from '../../../LikeC4Diagram.css'
4
+ import { vars } from '../../../theme-vars'
4
5
 
5
- export const compoundTitle = style({
6
+ export const compoundTitle = style([hiddenIfZoomTooSmall, {
7
+ position: 'absolute',
6
8
  display: 'flex',
7
9
  alignItems: 'center',
8
10
  gap: 6,
9
- paddingLeft: 14,
10
- paddingTop: 6,
11
+ left: 14,
12
+ top: 6,
13
+ right: 30,
14
+ width: 'auto',
11
15
  minHeight: 30,
12
- paddingRight: 2,
13
16
  selectors: {
14
17
  [`:where(.react-flow__node.draggable) &`]: {
15
18
  cursor: 'grab',
@@ -18,7 +21,7 @@ export const compoundTitle = style({
18
21
  paddingLeft: 30,
19
22
  },
20
23
  },
21
- })
24
+ }])
22
25
 
23
26
  export const title = style({
24
27
  flex: 1,
@@ -27,14 +30,12 @@ export const title = style({
27
30
  fontSize: rem(15),
28
31
  textTransform: 'uppercase',
29
32
  letterSpacing: '0.2px',
30
- // lineHeight: 1,
31
- //
32
33
  color: `var(--_compound-title-color,${vars.compound.titleColor})`,
33
- // paddingLeft: 0,
34
- // paddingTop: 13,
35
- // paddingBottom: 6,
36
- // minHeight: 20,
37
- mixBlendMode: 'screen',
34
+ selectors: {
35
+ [`${whereNotReducedGraphics} &`]: {
36
+ mixBlendMode: 'screen',
37
+ },
38
+ },
38
39
  })
39
40
 
40
41
  const iconSize = '20px'
@@ -12,8 +12,9 @@ export const nodePropsEqual = <P extends Record<string, unknown> = Base.NodeData
12
12
  && eq(prev.width ?? 0, next.width ?? 0)
13
13
  && eq(prev.height ?? 0, next.height ?? 0)
14
14
  && eq(prev.zIndex, next.zIndex)
15
- && eq(prev.positionAbsoluteX, next.positionAbsoluteX)
16
- && eq(prev.positionAbsoluteY, next.positionAbsoluteY)
15
+ // we can ignore position, as custom nodes positioned relative to it's NodeRenderer
16
+ // && eq(prev.positionAbsoluteX, next.positionAbsoluteX)
17
+ // && eq(prev.positionAbsoluteY, next.positionAbsoluteY)
17
18
  && eq(prev.data, next.data)
18
19
  )
19
20
 
@@ -32,8 +32,7 @@ export function EdgeContainer({
32
32
  return (
33
33
  <g
34
34
  className={clsx(
35
- css.edgeVars,
36
- isDimmed && css.dimmed,
35
+ css.edgeContainer,
37
36
  className,
38
37
  )}
39
38
  data-likec4-color={data.color ?? 'gray'}
@@ -41,7 +40,9 @@ export function EdgeContainer({
41
40
  data-edge-active={isActive}
42
41
  data-edge-animated={isActive}
43
42
  data-edge-hovered={isHovered}
44
- data-edge-dimmed={isDimmed}>
43
+ {...isDimmed !== false && {
44
+ 'data-edge-dimmed': isDimmed,
45
+ }}>
45
46
  {children}
46
47
  </g>
47
48
  )
@@ -1,9 +1,8 @@
1
1
  import { rem } from '@mantine/core'
2
2
  import { createVar, fallbackVar, globalStyle, style } from '@vanilla-extract/css'
3
+ import { whereNotReducedGraphics } from '../../../LikeC4Diagram.css'
3
4
  import { easings, mantine, transitions, vars, whereDark, whereLight, xyvars } from '../../../theme-vars'
4
- import { mixColor } from './edge.css'
5
-
6
- export { dimmed, edgeVars } from './edge.css'
5
+ import { edgeVars, mixColor } from './edge.css'
7
6
 
8
7
  const labelBorderRadius = 4
9
8
  export const stepEdgeNumber = style({
@@ -24,6 +23,7 @@ export const stepEdgeNumber = style({
24
23
  backgroundColor: `color-mix(in srgb, ${vars.relation.labelBgColor}, ${mixColor} 15%)`,
25
24
  },
26
25
  [`:where([data-edge-active='true'], [data-edge-hovered="true"]) &`]: {
26
+ transition: transitions.fast,
27
27
  backgroundColor: 'transparent',
28
28
  },
29
29
  },
@@ -34,7 +34,7 @@ export const varLabelY = createVar('label-y')
34
34
 
35
35
  export const varTranslate = createVar('translate')
36
36
 
37
- export const edgeLabelContainer = style({
37
+ export const edgeLabelContainer = style([edgeVars, {
38
38
  top: 0,
39
39
  left: 0,
40
40
  position: 'absolute',
@@ -45,7 +45,6 @@ export const edgeLabelContainer = style({
45
45
  backgroundColor: xyvars.edge.labelBgColor,
46
46
  borderRadius: labelBorderRadius,
47
47
  border: '0px solid transparent',
48
- mixBlendMode: 'plus-lighter',
49
48
  transform: varTranslate,
50
49
  transition: transitions.fast,
51
50
  vars: {
@@ -54,21 +53,28 @@ export const edgeLabelContainer = style({
54
53
  selectors: {
55
54
  '&[data-edge-hovered="true"]': {
56
55
  mixBlendMode: 'normal',
57
- transition: `all 140ms ${easings.inOut}`,
56
+ transition: `all 190ms ${easings.inOut}`,
58
57
  transform: `${varTranslate} scale(1.12)`,
59
58
  },
60
- '&:is([data-edge-dimmed="true"])': {
61
- opacity: 0.3,
59
+ [`&:is([data-edge-dimmed="true"])`]: {
60
+ opacity: 0.2,
62
61
  transition: 'opacity 600ms ease-in-out, filter 600ms ease-in-out',
63
62
  transitionDelay: '200ms',
64
63
  filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
65
- willChange: 'opacity, filter',
66
64
  },
67
- [`${whereLight} &`]: {
65
+ [`&:is([data-edge-dimmed="immediate"])`]: {
66
+ opacity: 0.1,
67
+ transition: 'opacity 75ms ease-in-out, filter 100ms ease-in-out',
68
+ filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
69
+ },
70
+ [`${whereNotReducedGraphics} &`]: {
71
+ mixBlendMode: 'plus-lighter',
72
+ },
73
+ [`${whereLight} ${whereNotReducedGraphics} &`]: {
68
74
  mixBlendMode: 'screen',
69
75
  },
70
76
  },
71
- })
77
+ }])
72
78
 
73
79
  export const edgeLabel = style({
74
80
  fontFamily: vars.likec4.font,
@@ -49,7 +49,7 @@ export const EdgeLabel = createPolymorphicComponent<'div', EdgeLabelProps>(
49
49
  technology,
50
50
  hovered: isHovered = false,
51
51
  active: isActive = false,
52
- dimmed = false,
52
+ dimmed: isDimmed = false,
53
53
  labelBBox,
54
54
  ...data
55
55
  },
@@ -83,16 +83,16 @@ export const EdgeLabel = createPolymorphicComponent<'div', EdgeLabelProps>(
83
83
  <Box
84
84
  className={clsx(
85
85
  'nodrag nopan',
86
- css.edgeVars,
87
86
  css.edgeLabelContainer,
88
- !!dimmed && css.dimmed,
89
87
  className,
90
88
  )}
91
89
  data-likec4-color={data.color ?? 'gray'}
92
90
  data-edge-active={isActive}
93
91
  data-edge-animated={isActive}
94
92
  data-edge-hovered={isHovered}
95
- data-edge-dimmed={dimmed}
93
+ {...isDimmed !== false && {
94
+ 'data-edge-dimmed': isDimmed,
95
+ }}
96
96
  style={{
97
97
  top: toCssVarValue(labelY),
98
98
  left: toCssVarValue(labelX),
@@ -1,5 +1,10 @@
1
1
  import { createVar, fallbackVar, globalStyle, keyframes, style } from '@vanilla-extract/css'
2
- import { cssReactFlow } from '../../../LikeC4Diagram.css'
2
+ import {
3
+ hiddenIfReducedGraphics,
4
+ hiddenIfZoomTooSmall,
5
+ reactFlow,
6
+ whereNotReducedGraphics,
7
+ } from '../../../LikeC4Diagram.css'
3
8
  import { vars, xyvars } from '../../../theme-vars'
4
9
  import { whereDark, whereLight } from '../../../theme-vars.css'
5
10
 
@@ -11,19 +16,44 @@ export const edgeVars = style({
11
16
  [xyvars.edge.stroke]: vars.relation.lineColor,
12
17
  [xyvars.edge.strokeSelected]: `color-mix(in srgb, ${vars.relation.lineColor}, ${mixColor} 35%)`,
13
18
  [xyvars.edge.labelColor]: `color-mix(in srgb, ${vars.relation.labelColor}, rgba(255 255 255 / 0.85) 40%)`,
14
- [xyvars.edge.labelBgColor]: `color-mix(in srgb, ${vars.relation.labelBgColor}, transparent 40%)`,
19
+ [xyvars.edge.labelBgColor]: vars.relation.labelBgColor,
15
20
  [xyvars.edge.strokeWidth]: '3',
16
21
  },
17
- })
18
-
19
- globalStyle(`${whereDark} ${edgeVars}`, {
20
- vars: {
21
- [mixColor]: `white`,
22
- [xyvars.edge.labelColor]: vars.relation.labelColor,
23
- [xyvars.edge.labelBgColor]: `color-mix(in srgb, ${vars.relation.labelBgColor}, transparent 50%)`,
22
+ selectors: {
23
+ [`${whereDark} &`]: {
24
+ vars: {
25
+ [mixColor]: `white`,
26
+ [xyvars.edge.labelColor]: vars.relation.labelColor,
27
+ },
28
+ },
29
+ [`${whereNotReducedGraphics} &`]: {
30
+ vars: {
31
+ [xyvars.edge.labelBgColor]: `color-mix(in srgb, ${vars.relation.labelBgColor}, transparent 40%)`,
32
+ },
33
+ },
34
+ [`${whereDark} ${whereNotReducedGraphics} &`]: {
35
+ vars: {
36
+ [xyvars.edge.labelBgColor]: `color-mix(in srgb, ${vars.relation.labelBgColor}, transparent 50%)`,
37
+ },
38
+ },
24
39
  },
25
40
  })
26
41
 
42
+ export const edgeContainer = style([edgeVars, {
43
+ selectors: {
44
+ [`&:is([data-edge-dimmed="true"])`]: {
45
+ opacity: 0.6,
46
+ transition: 'opacity 600ms ease-in-out, filter 600ms ease-in-out',
47
+ transitionDelay: '200ms',
48
+ filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
49
+ },
50
+ [`&:is([data-edge-dimmed="immediate"])`]: {
51
+ opacity: 0.25,
52
+ transition: 'opacity 100ms ease-in-out, filter 100ms ease-in-out',
53
+ filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
54
+ },
55
+ },
56
+ }])
27
57
  const isSelected = '.react-flow__edge.selected'
28
58
 
29
59
  globalStyle(`:where(${isSelected}) ${edgeVars}`, {
@@ -47,24 +77,14 @@ globalStyle(`:where(${isSelected}) ${edgeVars}[data-edge-hovered='true']`, {
47
77
  },
48
78
  })
49
79
 
50
- globalStyle(`${cssReactFlow} .react-flow__edges > svg`, {
80
+ globalStyle(`${reactFlow} .react-flow__edges > svg`, {
51
81
  mixBlendMode: 'plus-lighter',
52
82
  })
53
- globalStyle(`${whereLight} ${cssReactFlow} .react-flow__edges > svg`, {
83
+ globalStyle(`${whereLight} ${reactFlow} .react-flow__edges > svg`, {
54
84
  mixBlendMode: 'screen',
55
85
  })
56
86
 
57
- export const dimmed = style({})
58
-
59
- globalStyle(`${cssReactFlow} .react-flow__edges > svg:has(${dimmed})`, {
60
- opacity: 0.6,
61
- transition: 'opacity 600ms ease-in-out, filter 600ms ease-in-out',
62
- transitionDelay: '200ms',
63
- filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(1px)')}`,
64
- willChange: 'opacity, filter',
65
- })
66
-
67
- export const edgePathBg = style({
87
+ export const edgePathBg = style([hiddenIfZoomTooSmall, hiddenIfReducedGraphics, {
68
88
  // strokeWidth: xyvars.edge.strokeWidth,
69
89
  strokeOpacity: 0.08,
70
90
  // transition: 'stroke-width 175ms ease-in-out',
@@ -78,7 +98,7 @@ export const edgePathBg = style({
78
98
  strokeOpacity: 0.15,
79
99
  },
80
100
  },
81
- })
101
+ }])
82
102
 
83
103
  // To fix issue with marker not inheriting color from path - we need to create container
84
104
  export const markerContext = style({
@@ -102,20 +122,20 @@ export const cssEdgePath = style({
102
122
  animationFillMode: 'both',
103
123
  strokeDashoffset: 10,
104
124
  selectors: {
105
- [`:where([data-edge-hovered='true']) &`]: {
125
+ [`${reactFlow} :where([data-edge-hovered='true']) &`]: {
106
126
  animationName: strokeKeyframes,
107
127
  animationDelay: '450ms',
108
128
  transition: 'stroke 130ms ease-out,stroke-width 130ms ease-out',
109
129
  },
110
- [`:where(${isSelected}, [data-edge-active='true'], [data-edge-animated='true']) &`]: {
130
+ [`${reactFlow} :where(${isSelected}, [data-edge-active='true'], [data-edge-animated='true']) &`]: {
111
131
  animationName: strokeKeyframes,
112
132
  animationDelay: '0ms',
113
133
  transition: 'stroke 130ms ease-out,stroke-width 130ms ease-out',
114
134
  },
115
- [`:where([data-edge-dir='back']) &`]: {
135
+ [`${reactFlow} :where([data-edge-dir='back']) &`]: {
116
136
  animationDirection: 'reverse',
117
137
  },
118
- [`${dimmed} &`]: {
138
+ [`:where([data-edge-dimmed]) &`]: {
119
139
  animationPlayState: 'paused',
120
140
  },
121
141
  },
@@ -1,4 +1,5 @@
1
1
  import { style } from '@vanilla-extract/css'
2
+ import { reactFlowReducedGraphics } from '../../../LikeC4Diagram.css'
2
3
  import { transitions, vars } from '../../../theme-vars'
3
4
 
4
5
  export const container = style({
@@ -41,6 +42,9 @@ export const actionIcon = style({
41
42
  '--ai-bg': `var(--ai-bg-hover)`,
42
43
  },
43
44
  },
45
+ [`${reactFlowReducedGraphics} &`]: {
46
+ boxShadow: 'none',
47
+ },
44
48
  },
45
49
  })
46
50
  // globalStyle(`${actionIcon} > *`, {
@@ -1,6 +1,7 @@
1
1
  import { ActionIcon, Box } from '@mantine/core'
2
2
  import clsx from 'clsx'
3
3
  import { m } from 'framer-motion'
4
+ import { useIsZoomTooSmall } from '../../../hooks/useXYFlow'
4
5
  import { hiddenIfZoomTooSmall } from '../../../LikeC4Diagram.css'
5
6
  import { stopPropagation } from '../../../utils/xyflow'
6
7
  import type { NodeProps } from '../../types'
@@ -18,11 +19,12 @@ export function ElementActionButtons({
18
19
  },
19
20
  buttons,
20
21
  }: ElementActionButtonsProps) {
21
- if (!buttons.length) {
22
+ const zoomTooSmall = useIsZoomTooSmall()
23
+ if (!buttons.length || zoomTooSmall) {
22
24
  return null
23
25
  }
24
26
  return (
25
- <Box className={clsx(css.container, hiddenIfZoomTooSmall)}>
27
+ <Box className={clsx(css.container)}>
26
28
  <Box
27
29
  component={m.div}
28
30
  layoutRoot
@@ -1,4 +1,5 @@
1
1
  import { style } from '@vanilla-extract/css'
2
+ import { reactFlowReducedGraphics } from '../../../LikeC4Diagram.css'
2
3
  import { vars } from '../../../theme-vars'
3
4
 
4
5
  export const container = style({
@@ -43,12 +44,9 @@ export const actionIcon = style({
43
44
  ':hover': {
44
45
  boxShadow: '1px 1px 3px 0px rgba(0, 0, 0, 0.15)',
45
46
  },
46
- // selectors: {
47
- // [`:where([data-hovered='true']) &`]: {
48
- // // boxShadow: '1px 1px 3px 0px rgba(0, 0, 0, 0.15)',
49
- // // vars: {
50
- // // '--ai-bg': `var(--ai-bg-hover)`,
51
- // // },
52
- // },
53
- // },
47
+ selectors: {
48
+ [`${reactFlowReducedGraphics} &`]: {
49
+ boxShadow: 'none',
50
+ },
51
+ },
54
52
  })