@likec4/diagram 1.7.3 → 1.8.0

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.
@@ -0,0 +1,6 @@
1
+ export declare const container: string;
2
+ export declare const card: string;
3
+ export declare const tabPanel: string;
4
+ export declare const elementNotation: string;
5
+ export declare const shapeSvg: string;
6
+ export declare const shapeBadge: string;
@@ -0,0 +1 @@
1
+ export declare function NotationPanel(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export { NotationPanel as default } from './NotationPanel';
@@ -4,3 +4,4 @@ export declare const ZIndexes: {
4
4
  readonly Element: 6;
5
5
  };
6
6
  export declare const MinZoom = 0.1;
7
+ export declare const MaxZoom = 2;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@likec4/diagram",
3
- "version": "1.7.3",
3
+ "version": "1.8.0",
4
4
  "license": "MIT",
5
5
  "bugs": "https://github.com/likec4/likec4/issues",
6
6
  "homepage": "https://likec4.dev",
@@ -50,31 +50,31 @@
50
50
  "dependencies": {
51
51
  "@lume/kiwi": "^0.4.3",
52
52
  "@react-hookz/web": "^24.0.4",
53
- "@tabler/icons-react": "^3.11.0",
53
+ "@tabler/icons-react": "^3.12.0",
54
54
  "@vanilla-extract/css": "^1.15.3",
55
55
  "@vanilla-extract/css-utils": "^0.1.4",
56
56
  "@vanilla-extract/dynamic": "^2.1.1",
57
- "@xyflow/react": "12.0.4",
58
- "@xyflow/system": "0.0.37",
57
+ "@xyflow/react": "12.1.1",
58
+ "@xyflow/system": "0.0.39",
59
59
  "bezier-js": "^6.1.4",
60
60
  "clsx": "^2.1.1",
61
61
  "d3-shape": "^3.2.0",
62
62
  "esm-env": "^1.0.0",
63
63
  "fast-equals": "^5.0.1",
64
- "framer-motion": "^11.3.24",
65
- "remeda": "^2.3.0",
66
- "zustand": "^4.5.4"
64
+ "framer-motion": "^11.3.28",
65
+ "remeda": "^2.11.0",
66
+ "zustand": "^4.5.5"
67
67
  },
68
68
  "peerDependencies": {
69
- "@likec4/core": "1.7.3",
69
+ "@likec4/core": "1.8.0",
70
70
  "@mantine/core": "^7.11.2",
71
71
  "@mantine/hooks": "^7.11.2",
72
72
  "react": "^18.3.1",
73
73
  "react-dom": "^18.3.1"
74
74
  },
75
75
  "devDependencies": {
76
- "@likec4/core": "1.7.3",
77
- "@likec4/tsconfig": "1.7.3",
76
+ "@likec4/core": "1.8.0",
77
+ "@likec4/tsconfig": "1.8.0",
78
78
  "@mantine/core": "7.11.2",
79
79
  "@mantine/hooks": "7.11.2",
80
80
  "@mantine/vanilla-extract": "7.11.2",
@@ -85,7 +85,7 @@
85
85
  "@types/react-dom": "^18.3.0",
86
86
  "@vanilla-extract/esbuild-plugin": "^2.3.8",
87
87
  "@vitejs/plugin-react": "^4.3.1",
88
- "execa": "^9.3.0",
88
+ "execa": "^9.3.1",
89
89
  "khroma": "^2.1.0",
90
90
  "react": "^18.3.1",
91
91
  "react-dom": "^18.3.1",
@@ -203,6 +203,12 @@ export interface LikeC4DiagramProperties {
203
203
  */
204
204
  showNavigationButtons?: undefined | boolean
205
205
 
206
+ /**
207
+ * Display notations of the view
208
+ * @default true
209
+ */
210
+ showNotations?: boolean | undefined
211
+
206
212
  /**
207
213
  * If double click on a node should enable focus mode, i.e. highlight incoming/outgoing edges
208
214
  * @default true
@@ -30,6 +30,7 @@ export function LikeC4Diagram({
30
30
  controls = false,
31
31
  showElementLinks = true,
32
32
  showDiagramTitle = true,
33
+ showNotations = true,
33
34
  enableDynamicViewWalkthrough = false,
34
35
  enableFocusMode = false,
35
36
  initialWidth,
@@ -80,6 +81,7 @@ export function LikeC4Diagram({
80
81
  fitViewPadding={fitViewPadding}
81
82
  showElementLinks={showElementLinks}
82
83
  showNavigationButtons={showNavigationButtons}
84
+ showNotations={showNotations}
83
85
  nodesDraggable={nodesDraggable}
84
86
  nodesSelectable={nodesSelectable}
85
87
  experimentalEdgeEditing={experimentalEdgeEditing}
@@ -34,6 +34,7 @@ export function StaticLikeC4Diagram({
34
34
  background={background}
35
35
  showElementLinks
36
36
  showDiagramTitle={false}
37
+ showNotations={false}
37
38
  enableDynamicViewWalkthrough={false}
38
39
  enableFocusMode={false}
39
40
  nodesSelectable={false}
@@ -2,7 +2,7 @@ import { defaultTheme } from '@likec4/core'
2
2
  import { createGlobalTheme, globalStyle } from '@vanilla-extract/css'
3
3
  import { scale, toHex } from 'khroma'
4
4
  import { keys, omit } from 'remeda'
5
- import { mantine } from './mantine.css'
5
+ import { mantine, whereDark } from './mantine.css'
6
6
  import { vars } from './theme.css'
7
7
 
8
8
  export const rootClassName = 'likec4-diagram-root'
@@ -18,6 +18,10 @@ globalStyle(`.${rootClassName}`, {
18
18
  WebkitFontSmoothing: mantine.webkitFontSmoothing,
19
19
  MozOsxFontSmoothing: mantine.mozFontSmoothing
20
20
  })
21
+ globalStyle(`.${rootClassName} .mantine-ActionIcon-icon .tabler-icon`, {
22
+ width: '75%',
23
+ height: '75%'
24
+ })
21
25
 
22
26
  createGlobalTheme(`.${rootClassName}`, {
23
27
  ...omit(vars, ['optionsPanel', 'navigationPanel', 'safariAnimationHook', 'default'])
@@ -28,7 +32,7 @@ createGlobalTheme(`.${rootClassName}`, {
28
32
  background: {
29
33
  color: mantine.colors.body,
30
34
  pattern: {
31
- color: mantine.colors.dark[3]
35
+ color: mantine.colors.gray[4]
32
36
  }
33
37
  }
34
38
  },
@@ -43,33 +47,9 @@ createGlobalTheme(`.${rootClassName}`, {
43
47
  relation: {
44
48
  ...defaultTheme.relationships.slate
45
49
  }
46
- // likec4: {
47
- // font: `var(--likec4-font-family,'ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"')`,
48
- // backgroundColor: fallbackVar(globalvars.likec4.backgroundColor, mantine.colors.body)
49
- // },
50
- // compound: {
51
- // font: fallbackVar(vars.compound.font, vars.likec4.font),
52
- // titleColor: fallbackVar(globalvars.compound.titleColor, globalvars.element.loContrast),
53
- // },
54
- // element: {
55
- // font: fallbackVar(globalvars.element.font, vars.likec4.font),
56
- // fill: fallbackVar(globalvars.element.fill, defaultTheme.elements.primary.fill),
57
- // stroke: fallbackVar(globalvars.element.stroke, defaultTheme.elements.primary.stroke),
58
- // hiContrast: fallbackVar(globalvars.element.hiContrast, defaultTheme.elements.primary.hiContrast),
59
- // loContrast: fallbackVar(globalvars.element.loContrast, defaultTheme.elements.primary.loContrast),
60
- // },
61
- // relation: {
62
- // lineColor: fallbackVar(globalvars.relation.lineColor, defaultTheme.relationships.slate.lineColor),
63
- // labelColor: fallbackVar(globalvars.relation.labelColor, defaultTheme.relationships.slate.labelColor),
64
- // labelBgColor: fallbackVar(globalvars.relation.labelBgColor, defaultTheme.relationships.slate.labelBgColor),
65
- // },
66
- // optionsPanel: {
67
- // top: globalvars.optionsPanel.top,
68
- // right: globalvars.optionsPanel.right
69
- // }
70
50
  })
71
51
 
72
- createGlobalTheme(`:where([data-mantine-color-scheme='light']) .${rootClassName}`, {
52
+ createGlobalTheme(`${whereDark} .${rootClassName}`, {
73
53
  likec4: {
74
54
  background: {
75
55
  pattern: {
@@ -81,7 +61,7 @@ createGlobalTheme(`:where([data-mantine-color-scheme='light']) .${rootClassName}
81
61
  likec4: {
82
62
  background: {
83
63
  pattern: {
84
- color: mantine.colors.gray[6]
64
+ color: mantine.colors.dark[5]
85
65
  }
86
66
  }
87
67
  }
@@ -138,7 +118,7 @@ for (const color of keys(defaultTheme.elements)) {
138
118
  )
139
119
 
140
120
  createGlobalTheme(
141
- `:where([data-mantine-color-scheme='dark']) :where([data-likec4-color='${color}'][data-compound-depth='${depth}'])`,
121
+ `${whereDark} :where([data-likec4-color='${color}'][data-compound-depth='${depth}'])`,
142
122
  compounds,
143
123
  {
144
124
  fill: compoundDarkColor(defaultTheme.elements[color].fill, depth),
@@ -1,4 +1,7 @@
1
1
  import { themeToVars } from '@mantine/vanilla-extract'
2
2
 
3
+ export const whereLight = ':where([data-mantine-color-scheme="light"])'
4
+ export const whereDark = ':where([data-mantine-color-scheme="dark"])'
5
+
3
6
  // we need only variables names
4
7
  export const mantine = themeToVars({})
@@ -55,10 +55,11 @@ export function diagramViewToXYFlowData(
55
55
  let next: typeof traverse[0] | undefined
56
56
  while ((next = traverse.shift())) {
57
57
  const { node, parent } = next
58
- if (node.children.length > 0) {
58
+ const isCompound = hasAtLeast(node.children, 1)
59
+ if (isCompound) {
59
60
  traverse.push(...node.children.map(child => ({ node: nodeById(child), parent: node })))
60
61
  }
61
- const isCompound = hasAtLeast(node.children, 1)
62
+
62
63
  const position = {
63
64
  x: node.position[0],
64
65
  y: node.position[1]
@@ -82,6 +83,7 @@ export function diagramViewToXYFlowData(
82
83
  },
83
84
  draggable,
84
85
  selectable: opts.selectable,
86
+ focusable: opts.selectable && !isCompound,
85
87
  deletable: false,
86
88
  position,
87
89
  zIndex: isCompound ? ZIndexes.Compound : ZIndexes.Element,
@@ -102,18 +104,11 @@ export function diagramViewToXYFlowData(
102
104
  const source = edge.source
103
105
  const target = edge.target
104
106
  const id = ns + edge.id
105
- // const points = isElkEdge(edge) ? edge.points : deriveEdgePoints(edge.points)
106
- // const controlPoints = deriveEdgePoints(edge.points)
107
- // if (edge.tailArrowPoint) {
108
- // controlPoints.unshift([...edge.tailArrowPoint])
109
- // }
110
- // if (edge.headArrowPoint) {
111
- // controlPoints.push([...edge.headArrowPoint])
112
- // }
113
- invariant(hasAtLeast(edge.points, 2), 'edge should have at least 2 points')
114
- // invariant(hasAtLeast(controlPoints, 2), 'edge controlPoints should have at least 2 points')
115
107
 
116
- // const level = Math.max(nodeZIndex(nodeById(source)), nodeZIndex(nodeById(target)))
108
+ if (!hasAtLeast(edge.points, 2)) {
109
+ console.error('edge should have at least 2 points', edge)
110
+ continue
111
+ }
117
112
 
118
113
  xyedges.push({
119
114
  id,
@@ -1,4 +1,13 @@
1
- import type { DiagramNode, DiagramView, Fqn, NodeId, ViewChange, ViewID } from '@likec4/core'
1
+ import type {
2
+ DiagramNode,
3
+ DiagramView,
4
+ ElementKind,
5
+ ElementNotation,
6
+ Fqn,
7
+ NodeId,
8
+ ViewChange,
9
+ ViewID
10
+ } from '@likec4/core'
2
11
  import { getBBoxCenter, invariant, nonexhaustive, nonNullable, StepEdgeId } from '@likec4/core'
3
12
  import {
4
13
  applyEdgeChanges,
@@ -11,8 +20,8 @@ import { boxToRect, getBoundsOfRects, getNodeDimensions } from '@xyflow/system'
11
20
  import { DEV } from 'esm-env'
12
21
  import { deepEqual as eq, shallowEqual } from 'fast-equals'
13
22
  import type { MouseEvent as ReactMouseEvent } from 'react'
14
- import { entries, hasAtLeast, isNullish, reduce } from 'remeda'
15
- import type { ConditionalKeys, Exact, Except, RequiredKeysOf, Simplify } from 'type-fest'
23
+ import { entries, hasAtLeast, isNullish, map, prop, reduce } from 'remeda'
24
+ import type { ConditionalKeys, Except, RequiredKeysOf, Simplify } from 'type-fest'
16
25
  import { devtools, subscribeWithSelector } from 'zustand/middleware'
17
26
  import { shallow } from 'zustand/shallow'
18
27
  import { createWithEqualityFn } from 'zustand/traditional'
@@ -37,6 +46,7 @@ export type DiagramInitialState = {
37
46
  readonly: boolean
38
47
  showElementLinks: boolean
39
48
  showNavigationButtons: boolean
49
+ showNotations: boolean
40
50
  fitViewEnabled: boolean
41
51
  fitViewPadding: number
42
52
  zoomable: boolean
@@ -132,6 +142,8 @@ export type DiagramState = Simplify<
132
142
  onInit: (xyflow: XYFlowInstance) => void
133
143
  onNodesChange: OnNodesChange<XYFlowNode>
134
144
  onEdgesChange: OnEdgesChange<XYFlowEdge>
145
+
146
+ highlightByElementNotation: (notation: ElementNotation, onlyOfKind?: ElementKind) => void
135
147
  }
136
148
  >
137
149
 
@@ -162,7 +174,7 @@ let StoreDevId = 1
162
174
 
163
175
  const EmptyStringSet: ReadonlySet<string> = new StringSet()
164
176
 
165
- export function createDiagramStore<T extends Exact<DiagramInitialState, T>>(props: T) {
177
+ export function createDiagramStore(props: DiagramInitialState) {
166
178
  const storeDevId = 'DiagramStore' + String(StoreDevId++).padStart(2, '0')
167
179
  const {
168
180
  xynodes,
@@ -878,6 +890,21 @@ export function createDiagramStore<T extends Exact<DiagramInitialState, T>>(prop
878
890
  'onInit'
879
891
  )
880
892
  }
893
+ },
894
+
895
+ highlightByElementNotation: (notation: ElementNotation, onlyOfKind?: ElementKind) => {
896
+ const { xynodes, xyedges } = get()
897
+ const dimmed = new StringSet(map(xyedges, prop('id')))
898
+ xynodes.forEach(({ id, data }) => {
899
+ const node = data.element
900
+ if (
901
+ node.shape !== notation.shape || node.color !== notation.color || !notation.kinds.includes(node.kind)
902
+ || (onlyOfKind && node.kind !== onlyOfKind)
903
+ ) {
904
+ dimmed.add(id)
905
+ }
906
+ })
907
+ set({ dimmed }, noReplace, 'highlightByElementNotation')
881
908
  }
882
909
  }),
883
910
  {
@@ -1,5 +1,5 @@
1
1
  import { fallbackVar, globalStyle, style } from '@vanilla-extract/css'
2
- import { mantine } from '../mantine.css'
2
+ import { mantine, whereDark } from '../mantine.css'
3
3
  import { vars } from '../theme.css'
4
4
 
5
5
  export const container = style({
@@ -18,16 +18,16 @@ export const card = style({
18
18
  backdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
19
19
  '@media': {
20
20
  [mantine.largerThan('sm')]: {
21
- minWidth: 300,
21
+ minWidth: 250,
22
22
  maxWidth: '90vw'
23
23
  },
24
24
  [mantine.largerThan('md')]: {
25
- minWidth: 400,
25
+ minWidth: 350,
26
26
  maxWidth: '70vw'
27
27
  }
28
28
  },
29
29
  selectors: {
30
- [`:where([data-mantine-color-scheme='dark']) &`]: {
30
+ [`${whereDark} &`]: {
31
31
  backgroundColor: `color-mix(in srgb, ${mantine.colors.dark[6]}, transparent 20%)`
32
32
  }
33
33
  }
@@ -37,8 +37,10 @@ export const title = style({})
37
37
 
38
38
  export const description = style({
39
39
  whiteSpaceCollapse: 'preserve-breaks',
40
- color: mantine.colors.gray[7]
41
- })
42
- globalStyle(`:where([data-mantine-color-scheme="dark"]) ${description}`, {
43
- color: mantine.colors.gray[5]
40
+ color: mantine.colors.gray[7],
41
+ selectors: {
42
+ [`${whereDark} &`]: {
43
+ color: mantine.colors.gray[5]
44
+ }
45
+ }
44
46
  })
@@ -39,53 +39,70 @@ export default function DiagramTitlePanel() {
39
39
  <Card
40
40
  radius="sm"
41
41
  className={css.card}
42
- withBorder
43
- p={'md'}
44
- pb={isCollapsed ? 'sm' : 'md'}
42
+ withBorder={!isCollapsed}
43
+ p={isCollapsed ? 'sm' : 'md'}
45
44
  onDoubleClick={e => e.stopPropagation()}>
46
- <CardSection mb={isCollapsed ? 10 : 'sm'}>
47
- <Button
48
- fullWidth
49
- size="xs"
50
- h={'sm'}
51
- py={2}
52
- radius={'0'}
53
- variant={isCollapsed ? 'light' : 'subtle'}
54
- color="gray"
55
- onClick={toggle}
56
- >
57
- <IconMenu size={11} opacity={0.7} />
58
- </Button>
59
- </CardSection>
60
- <Group justify="stretch" wrap="nowrap" mb={isCollapsed ? 0 : 'sm'}>
61
- <Text
62
- component={'div'}
63
- flex={'1'}
64
- size={isCollapsed ? 'sm' : 'lg'}
65
- fw={500}
66
- lh={1.1}
67
- className={css.title}
68
- >
69
- {title}
70
- </Text>
71
- <Text
72
- hidden={isCollapsed}
73
- component={'div'}
74
- flex={'0 0 auto'}
75
- inline
76
- size="xs"
77
- fz={9}
78
- fw={500}
79
- c={'dimmed'}
80
- style={{
81
- userSelect: 'all'
82
- }}>
83
- <span style={{ userSelect: 'none' }}>id:{' '}</span>
84
- {id}
85
- </Text>
86
- </Group>
45
+ {isCollapsed && (
46
+ <CardSection>
47
+ <Button
48
+ fullWidth
49
+ justify="stretch"
50
+ size="md"
51
+ radius={'0'}
52
+ variant={'subtle'}
53
+ color="gray"
54
+ onClick={toggle}
55
+ fw={500}
56
+ fz={'sm'}
57
+ >
58
+ {title}
59
+ </Button>
60
+ </CardSection>
61
+ )}
87
62
  {!isCollapsed && (
88
63
  <>
64
+ <CardSection mb={'xs'}>
65
+ <Button
66
+ fullWidth
67
+ size="xs"
68
+ h={'sm'}
69
+ py={2}
70
+ radius={'0'}
71
+ variant={'subtle'}
72
+ color="gray"
73
+ onClick={toggle}
74
+ >
75
+ <IconMenu size={11} opacity={0.7} />
76
+ </Button>
77
+ </CardSection>
78
+
79
+ <Group justify="stretch" wrap="nowrap" mb={'sm'}>
80
+ <Text
81
+ component={'div'}
82
+ flex={'1'}
83
+ size={'md'}
84
+ fw={500}
85
+ lh={1.1}
86
+ className={css.title}
87
+ >
88
+ {title}
89
+ </Text>
90
+ <Text
91
+ hidden={isCollapsed}
92
+ component={'div'}
93
+ flex={'0 0 auto'}
94
+ inline
95
+ size="xs"
96
+ fz={9}
97
+ fw={500}
98
+ c={'dimmed'}
99
+ style={{
100
+ userSelect: 'all'
101
+ }}>
102
+ <span style={{ userSelect: 'none' }}>id:{' '}</span>
103
+ {id}
104
+ </Text>
105
+ </Group>
89
106
  {description && (
90
107
  <Spoiler
91
108
  maxHeight={42}
@@ -113,19 +130,19 @@ export default function DiagramTitlePanel() {
113
130
  justify="stretch"
114
131
  align="stretch">
115
132
  {links.map((link) => (
116
- <Group key={link} wrap="nowrap" align="center" gap={'sm'}>
133
+ <Group key={link.url} wrap="nowrap" align="center" gap={'sm'}>
117
134
  <Box flex={'1'} style={{ overflow: 'hidden' }}>
118
135
  <Anchor
119
- href={link}
136
+ href={link.url}
120
137
  target="_blank"
121
138
  fz="xs"
122
139
  truncate="end"
123
140
  display={'inline-block'}
124
141
  w={'100%'}>
125
- {link}
142
+ {link.title || link.url}
126
143
  </Anchor>
127
144
  </Box>
128
- <CopyButton value={link}>
145
+ <CopyButton value={link.url}>
129
146
  {({ copied, copy }) => (
130
147
  <Button
131
148
  size="compact-xs"
@@ -0,0 +1,103 @@
1
+ import { fallbackVar, globalStyle, style } from '@vanilla-extract/css'
2
+ import { calc } from '@vanilla-extract/css-utils'
3
+ import { mantine, whereDark } from '../../mantine.css'
4
+ import { vars } from '../../theme.css'
5
+ import { stokeFillMix } from '../../xyflow/nodes/element/element.css'
6
+
7
+ export const container = style({
8
+ bottom: 0,
9
+ right: 0,
10
+ padding: 8,
11
+ margin: 0
12
+ })
13
+
14
+ export const card = style({
15
+ cursor: 'default',
16
+ userSelect: 'none',
17
+ minWidth: 200,
18
+ maxWidth: 'calc(100vw - 20px)',
19
+ backgroundColor: `color-mix(in srgb, ${mantine.colors.body}, transparent 20%)`,
20
+ WebkitBackdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
21
+ backdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
22
+ '@media': {
23
+ [mantine.largerThan('sm')]: {
24
+ minWidth: 300,
25
+ maxWidth: `65vw`
26
+ },
27
+ [mantine.largerThan('md')]: {
28
+ // minWidth: 350,
29
+ maxWidth: `40vw`
30
+ }
31
+ },
32
+ selectors: {
33
+ [`${whereDark} &`]: {
34
+ backgroundColor: `color-mix(in srgb, ${mantine.colors.dark[6]}, transparent 20%)`
35
+ }
36
+ }
37
+ })
38
+
39
+ export const tabPanel = style({
40
+ padding: calc(mantine.spacing.xs).divide(2).toString()
41
+ })
42
+
43
+ // export const description = style({
44
+ // whiteSpaceCollapse: 'preserve-breaks',
45
+ // color: mantine.colors.gray[7],
46
+ // selectors: {
47
+ // [`${whereDark} &`]: {
48
+ // color: mantine.colors.gray[5]
49
+ // }
50
+ // }
51
+ // })
52
+
53
+ export const elementNotation = style({
54
+ backgroundColor: 'transparent',
55
+ transition: 'all 100ms ease-in',
56
+ // WebkitBackdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
57
+ // backdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
58
+ vars: {
59
+ [stokeFillMix]: `color-mix(in srgb, ${vars.element.stroke} 90%, ${vars.element.fill})`
60
+ },
61
+ ':hover': {
62
+ transition: 'all 120ms ease-out',
63
+ // backgroundColor:
64
+ backgroundColor: `color-mix(in srgb, ${mantine.colors.primaryColors[2]}, transparent 50%)`
65
+ },
66
+ selectors: {
67
+ [`${whereDark} &:hover`]: {
68
+ backgroundColor: `color-mix(in srgb, ${mantine.colors.dark[3]}, transparent 60%)`
69
+ }
70
+ }
71
+ })
72
+
73
+ export const shapeSvg = style({
74
+ fill: vars.element.fill,
75
+ stroke: vars.element.stroke,
76
+ strokeWidth: 1,
77
+ overflow: 'visible',
78
+ width: '100%',
79
+ height: 'auto',
80
+ filter: `
81
+ drop-shadow(0 2px 3px rgb(0 0 0 / 22%))
82
+ drop-shadow(0 1px 8px rgb(0 0 0 / 10%))
83
+ `
84
+ })
85
+
86
+ export const shapeBadge = style({
87
+ fontWeight: 500,
88
+ letterSpacing: '0.2px',
89
+ paddingTop: 0,
90
+ paddingBottom: 0,
91
+ textTransform: 'lowercase',
92
+ transition: 'all 150ms ease-in-out',
93
+ cursor: 'pointer',
94
+ vars: {
95
+ ['--badge-radius']: '2px',
96
+ ['--badge-fz']: '9.5px',
97
+ ['--badge-padding-x']: '3px',
98
+ ['--badge-height']: '13.5px',
99
+ ['--badge-lh']: '1'
100
+ // ['--badge-bg']: vars.element.fill,
101
+ // ['--badge-color']: vars.element.hiContrast
102
+ }
103
+ })