@likec4/diagram 1.17.1 → 1.18.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.
Files changed (49) hide show
  1. package/package.json +17 -15
  2. package/src/LikeC4Diagram.props.ts +21 -12
  3. package/src/LikeC4Diagram.tsx +5 -7
  4. package/src/LikeC4Search.tsx +54 -51
  5. package/src/hooks/useDiagramState.ts +8 -3
  6. package/src/hooks/useXYFlow.ts +2 -1
  7. package/src/likec4model/useLikeC4ElementsTree.ts +6 -13
  8. package/src/likec4model/useLikeC4Model.ts +21 -11
  9. package/src/overlays/Overlays.tsx +96 -63
  10. package/src/overlays/edge-details/EdgeDetailsXYFlow.tsx +3 -1
  11. package/src/overlays/edge-details/_types.ts +7 -3
  12. package/src/overlays/edge-details/use-layouted-edge-details.ts +21 -14
  13. package/src/overlays/edge-details/xyflow/ElementNode.tsx +4 -2
  14. package/src/overlays/edge-details/xyflow/RelationshipEdge.tsx +4 -4
  15. package/src/overlays/element-details/ElementDetailsCard.tsx +91 -78
  16. package/src/overlays/element-details/TabPanelDeployments.css.ts +69 -0
  17. package/src/overlays/element-details/TabPanelDeployments.tsx +217 -0
  18. package/src/overlays/element-details/TabPanelRelationships.tsx +8 -9
  19. package/src/overlays/element-details/TabPanelStructure.tsx +10 -10
  20. package/src/overlays/relationships-of/RelationshipsOverlay.tsx +1 -1
  21. package/src/overlays/relationships-of/RelationshipsXYFlow.tsx +3 -11
  22. package/src/overlays/relationships-of/SelectElement.tsx +2 -2
  23. package/src/overlays/relationships-of/_types.ts +2 -2
  24. package/src/overlays/relationships-of/use-layouted-relationships.ts +18 -19
  25. package/src/overlays/relationships-of/xyflow/CompoundNode.tsx +1 -3
  26. package/src/overlays/relationships-of/xyflow/ElementNode.tsx +12 -6
  27. package/src/overlays/relationships-of/xyflow/RelationshipEdge.tsx +0 -1
  28. package/src/state/diagramStore.ts +28 -11
  29. package/src/ui/DiagramTitlePanel.tsx +2 -29
  30. package/src/ui/Link.tsx +40 -0
  31. package/src/ui/notation/NotationPanel.tsx +4 -2
  32. package/src/ui/top-left/ChangeAutoLayoutButton.tsx +2 -2
  33. package/src/ui/top-left/TopLeftPanel.tsx +5 -5
  34. package/src/xyflow/edges/EdgeLabel.tsx +4 -4
  35. package/src/xyflow/edges/RelationshipsDropdownMenu.tsx +20 -7
  36. package/src/xyflow/nodes/compound/CompoundNode.css.ts +28 -13
  37. package/src/xyflow/nodes/compound/CompoundNode.tsx +51 -19
  38. package/src/xyflow/nodes/element/ElementNode.tsx +147 -124
  39. package/src/xyflow/nodes/element/element.css.ts +52 -19
  40. package/src/xyflow/nodes/shared/ElementIcon.tsx +1 -1
  41. package/src/xyflow/nodes/shared/Toolbar.tsx +24 -8
  42. package/src/xyflow/useLayoutConstraints.ts +1 -1
  43. package/src/xyflow/useXYFlowEvents.ts +18 -5
  44. package/src/ui/OptionsPanel.css.ts +0 -9
  45. package/src/ui/OptionsPanel.tsx +0 -70
  46. package/src/ui/options/EdgeOptions.tsx +0 -142
  47. package/src/ui/options/NodeOptions.tsx +0 -362
  48. package/src/xyflow/nodes/element/ElementDetails.css.ts +0 -101
  49. package/src/xyflow/nodes/element/ElementDetails.tsx +0 -393
@@ -1,70 +0,0 @@
1
- import { Card } from '@mantine/core'
2
- import { useOnSelectionChange } from '@xyflow/react'
3
- import clsx from 'clsx'
4
- import { deepEqual as eq } from 'fast-equals'
5
- import { AnimatePresence, m } from 'framer-motion'
6
- import { useState } from 'react'
7
- import { useDiagramState } from '../hooks/useDiagramState'
8
- import { NodeOptions } from './options/NodeOptions'
9
- import * as styles from './OptionsPanel.css'
10
-
11
- /**
12
- * @deprecated
13
- */
14
- export function OptionsPanel() {
15
- const { isFocused, viewId } = useDiagramState(s => ({
16
- viewId: s.view.id,
17
- isFocused: s.focusedNodeId !== null || s.activeWalkthrough !== null
18
- }))
19
- const [selected, setSelected] = useState<{
20
- nodes: string[]
21
- edges: string[]
22
- }>({
23
- nodes: [],
24
- edges: []
25
- })
26
- useOnSelectionChange({
27
- onChange: ({ nodes, edges }) => {
28
- const newSelected = {
29
- nodes: nodes.map(n => n.id).sort(),
30
- edges: edges.map(e => e.id).sort()
31
- }
32
- if (!eq(selected, newSelected)) {
33
- setSelected(newSelected)
34
- }
35
- }
36
- })
37
- const { nodes } = selected
38
- // const hasAnySelection = !isFocused && (nodes.length > 0 || edges.length > 0)
39
- const hasAnySelection = !isFocused && nodes.length > 0
40
- return (
41
- <AnimatePresence mode="wait">
42
- {hasAnySelection && (
43
- <m.div
44
- key={viewId}
45
- initial={{ opacity: 0, scale: 0.85 }}
46
- animate={{ opacity: 1, scale: 1 }}
47
- exit={{
48
- opacity: 0,
49
- scale: 0.85
50
- }}
51
- transition={{ duration: 0.14 }}
52
- className={clsx('react-flow__panel', styles.panel)}
53
- style={{
54
- transformOrigin: 'center right',
55
- maxWidth: '320px'
56
- }}
57
- >
58
- <Card shadow="md">
59
- {nodes.length > 0 && <NodeOptions selectedNodeIds={nodes} />}
60
- {
61
- /* nodes.length === 0 && edges.length > 0 && (
62
- <EdgeOptions selectedEdgeIds={edges} />
63
- ) */
64
- }
65
- </Card>
66
- </m.div>
67
- )}
68
- </AnimatePresence>
69
- )
70
- }
@@ -1,142 +0,0 @@
1
- import { DefaultRelationshipColor, defaultTheme, type NonEmptyArray, type ThemeColor } from '@likec4/core'
2
- import { CheckIcon, ColorSwatch, Divider, Flex, rem, Stack, Text, Tooltip, TooltipGroup } from '@mantine/core'
3
- import { shallowEqual } from 'fast-equals'
4
- import { memo } from 'react'
5
- import { hasAtLeast, keys, takeWhile } from 'remeda'
6
- import { useDiagramStoreApi, useXYEdgesData } from '../../hooks'
7
- import { type XYFlowEdge } from '../../xyflow/types'
8
-
9
- const {
10
- primary,
11
- secondary,
12
- muted,
13
- ...otherColors
14
- } = defaultTheme.elements
15
-
16
- export const themedColors = [
17
- { key: 'primary', value: primary.fill },
18
- { key: 'secondary', value: secondary.fill },
19
- { key: 'muted', value: muted.fill }
20
- ] satisfies Array<{ key: ThemeColor; value: string }>
21
-
22
- export const colors = keys(otherColors).map(key => ({
23
- key,
24
- value: defaultTheme.elements[key].fill
25
- }))
26
-
27
- export type ThemeColorKey = typeof themedColors[0]['key']
28
- export type ColorKey = typeof colors[0]['key']
29
-
30
- type XYEdgeData = Pick<XYFlowEdge, 'id' | 'data'>
31
-
32
- export const EdgeOptions = memo<{ selectedEdgeIds: string[] }>(({ selectedEdgeIds }) => {
33
- const diagramApi = useDiagramStoreApi()
34
- const edges = useXYEdgesData(selectedEdgeIds)
35
- if (!hasAtLeast(edges, 1)) {
36
- return null
37
- }
38
- if (edges.length !== selectedEdgeIds.length) {
39
- throw new Error('EdgeOptions: edges and props.edges should have the same length')
40
- }
41
- const [firstEdge, ...rest] = edges
42
-
43
- return (
44
- <Stack gap={'xs'}>
45
- <div>
46
- <Text fz={rem(9)} fw={'500'} c={'dimmed'}>
47
- RELATIONSHIP{rest.length > 0 ? 'S' : ''}
48
- </Text>
49
- <Text size="xs" c={rest.length > 0 ? 'dimmed' : ''} truncate>
50
- {rest.length === 0 ? firstEdge.data.edge.label : `[ multiple ]`}
51
- </Text>
52
- </div>
53
- {
54
- /* {showShapeOption && (
55
- <ShapeOption
56
- nodes={edges}
57
- onShapeChange={(shape: ElementShape) => {
58
- triggerChange({ shape })
59
- }} />
60
- )} */
61
- }
62
- <Colors
63
- edges={edges}
64
- onColorChange={(_color: ColorKey | ThemeColorKey) => {
65
- // triggerChange({ color })
66
- }} />
67
- </Stack>
68
- )
69
- }, (prevProps, nextProps) => shallowEqual(prevProps.selectedEdgeIds, nextProps.selectedEdgeIds))
70
-
71
- function Colors({
72
- edges: [firstEdge, ...edges],
73
- onColorChange
74
- }: {
75
- edges: NonEmptyArray<XYEdgeData>
76
- onColorChange: (color: ColorKey | ThemeColorKey) => void
77
- }) {
78
- let selectedColor = (firstEdge.data.edge.color ?? DefaultRelationshipColor) as ThemeColor | null
79
- takeWhile(edges, edge => {
80
- const color = edge.data.edge.color ?? DefaultRelationshipColor
81
- if (color !== selectedColor) {
82
- selectedColor = null
83
- return false
84
- }
85
- return true
86
- })
87
- const changeColor = (color: ColorKey | ThemeColorKey) => () => {
88
- if (selectedColor === color) {
89
- return
90
- }
91
- onColorChange(color)
92
- }
93
- return (
94
- <div>
95
- <TooltipGroup openDelay={400} closeDelay={300}>
96
- <Divider label="color" labelPosition="left" />
97
- <Flex mt={'xs'} maw={150} gap="xs" justify="flex-start" align="flex-start" direction="row" wrap="wrap">
98
- {themedColors.map(({ key, value }) => (
99
- <Tooltip
100
- key={key}
101
- label={key}
102
- fz={'xs'}
103
- color="dark"
104
- offset={2}
105
- transitionProps={{ duration: 140, transition: 'slide-up' }}>
106
- <ColorSwatch
107
- color={value}
108
- size={20}
109
- withShadow
110
- onClick={changeColor(key)}
111
- style={{ color: '#fff', cursor: 'pointer' }}
112
- >
113
- {selectedColor === key && <CheckIcon style={{ width: rem(12), height: rem(12) }} />}
114
- </ColorSwatch>
115
- </Tooltip>
116
- ))}
117
- </Flex>
118
-
119
- <Flex mt="sm" maw={150} gap="xs" justify="flex-start" align="flex-start" direction="row" wrap="wrap">
120
- {colors.map(({ key, value }) => (
121
- <Tooltip
122
- key={key}
123
- label={key}
124
- fz={'xs'}
125
- color="dark"
126
- offset={2}
127
- transitionProps={{ duration: 140, transition: 'slide-up' }}>
128
- <ColorSwatch
129
- color={value}
130
- size={20}
131
- onClick={changeColor(key)}
132
- style={{ color: '#fff', cursor: 'pointer' }}
133
- >
134
- {selectedColor === key && <CheckIcon style={{ width: rem(12), height: rem(12) }} />}
135
- </ColorSwatch>
136
- </Tooltip>
137
- ))}
138
- </Flex>
139
- </TooltipGroup>
140
- </div>
141
- )
142
- }
@@ -1,362 +0,0 @@
1
- import {
2
- type BorderStyle,
3
- defaultTheme,
4
- type ElementShape,
5
- ElementShapes,
6
- invariant,
7
- type NonEmptyArray,
8
- type ThemeColor,
9
- type ViewChange
10
- } from '@likec4/core'
11
- import {
12
- ActionIcon,
13
- Box,
14
- CheckIcon,
15
- ColorSwatch,
16
- Divider,
17
- Flex,
18
- Group,
19
- rem,
20
- SegmentedControl,
21
- Select,
22
- Slider,
23
- Space,
24
- Stack,
25
- Text,
26
- Tooltip,
27
- TooltipGroup
28
- } from '@mantine/core'
29
- import { IconFileSymlink } from '@tabler/icons-react'
30
- import { shallowEqual } from 'fast-equals'
31
- import { memo, useState } from 'react'
32
- import { hasAtLeast, keys, takeWhile } from 'remeda'
33
- import { useDiagramStoreApi, useXYNodesData } from '../../hooks'
34
- import { useUpdateEffect } from '../../hooks/useUpdateEffect'
35
- import { XYFlowNode } from '../../xyflow/types'
36
-
37
- const {
38
- primary,
39
- secondary,
40
- muted,
41
- ...otherColors
42
- } = defaultTheme.elements
43
-
44
- export const themedColors = [
45
- { key: 'primary', value: primary.fill },
46
- { key: 'secondary', value: secondary.fill },
47
- { key: 'muted', value: muted.fill }
48
- ] satisfies Array<{ key: ThemeColor; value: string }>
49
-
50
- export const colors = keys(otherColors).map(key => ({
51
- key,
52
- value: defaultTheme.elements[key].fill
53
- }))
54
-
55
- export type ThemeColorKey = typeof themedColors[0]['key']
56
- export type ColorKey = typeof colors[0]['key']
57
-
58
- type XYNodesData = Pick<XYFlowNode, 'id' | 'data' | 'type'>
59
-
60
- /**
61
- * @deprecated
62
- */
63
- export const NodeOptions = memo<{ selectedNodeIds: string[] }>(({ selectedNodeIds }) => {
64
- // export function NodeOptions(props: { nodes: XYFlowNode[] }) {
65
- const diagramApi = useDiagramStoreApi()
66
- // const nodes = useXYNodesData(props.nodes.map(node => node.id))
67
- const nodes = useXYNodesData(selectedNodeIds)
68
- if (!hasAtLeast(nodes, 1)) {
69
- return null
70
- }
71
- if (nodes.length !== selectedNodeIds.length) {
72
- throw new Error('NodeOptions: nodes and props.nodes should have the same length')
73
- }
74
- // Makes sense to show shape option only if there is at least one element node
75
- const showShapeOption = nodes.some(node => node.type === 'element')
76
-
77
- const [firstNode, ...rest] = nodes
78
-
79
- const showGoToSource = rest.length === 0 && diagramApi.getState().onOpenSourceElement!!
80
-
81
- // Makes sense to show opacity option only if there is at least one compound node
82
- const showOpacityOption = firstNode.type === 'compound'
83
- && (rest.length === 0 || rest.every(node => node.type === 'compound'))
84
-
85
- const triggerChange = (style: ViewChange.ChangeElementStyle['style']) => {
86
- const targets = nodes.map(node => node.data.element.id)
87
- invariant(hasAtLeast(targets, 1), 'At least one target is required')
88
- diagramApi.getState().triggerChangeElementStyle({
89
- op: 'change-element-style',
90
- style,
91
- targets
92
- })
93
- }
94
-
95
- return (
96
- <Stack gap={'xs'}>
97
- <Group wrap="nowrap" align="flex-start">
98
- <Box flex={1} miw={0}>
99
- <Text fz={rem(9)} fw={'500'} c={'dimmed'}>
100
- ELEMENT{rest.length > 0 ? 'S' : ``}
101
- </Text>
102
- <Text size="xs" c={rest.length > 0 ? 'dimmed' : ''} truncate>
103
- {rest.length === 0 ? firstNode.data.element.title : `[ multiple ]`}
104
- </Text>
105
- </Box>
106
- {showGoToSource && (
107
- <Box flex={0}>
108
- <ActionIcon
109
- size={'sm'}
110
- variant="light"
111
- color="gray"
112
- onClick={e => {
113
- e.stopPropagation()
114
- diagramApi.getState().onOpenSourceElement?.(firstNode.data.element.id)
115
- }}>
116
- <IconFileSymlink
117
- stroke={1.2}
118
- style={{
119
- width: '70%',
120
- height: '70%'
121
- }} />
122
- </ActionIcon>
123
- </Box>
124
- )}
125
- </Group>
126
- {showShapeOption && (
127
- <ShapeOption
128
- nodes={nodes}
129
- onShapeChange={(shape: ElementShape) => {
130
- triggerChange({ shape })
131
- }} />
132
- )}
133
- <Colors
134
- nodes={nodes}
135
- onColorChange={(color: ColorKey | ThemeColorKey) => {
136
- triggerChange({ color })
137
- }} />
138
-
139
- {showOpacityOption && (
140
- <div key={firstNode.id}>
141
- <Divider label="opacity and border" labelPosition="left" />
142
- <Space h={'xs'} />
143
- <OpacityOption
144
- node={firstNode}
145
- onOpacityChange={(opacity: number) => {
146
- triggerChange({ opacity })
147
- }} />
148
- <Space h={'sm'} />
149
- <BorderStyleOption
150
- node={firstNode}
151
- onChange={(border: BorderStyle) => {
152
- triggerChange({ border })
153
- }}
154
- />
155
- </div>
156
- )}
157
- <NavigateToOption nodes={nodes} />
158
- </Stack>
159
- )
160
- }, (prevProps, nextProps) => shallowEqual(prevProps.selectedNodeIds, nextProps.selectedNodeIds))
161
-
162
- function Colors({
163
- nodes: [firstNode, ...nodes],
164
- onColorChange
165
- }: {
166
- nodes: NonEmptyArray<XYNodesData>
167
- onColorChange: (color: ColorKey | ThemeColorKey) => void
168
- }) {
169
- let selectedColor = firstNode.data.element.color as ThemeColor | null
170
- takeWhile(nodes, node => {
171
- if (node.data.element.color !== selectedColor) {
172
- selectedColor = null
173
- return false
174
- }
175
- return true
176
- })
177
- const changeColor = (color: ColorKey | ThemeColorKey) => () => {
178
- if (selectedColor === color) {
179
- return
180
- }
181
- onColorChange(color)
182
- }
183
- return (
184
- <div>
185
- <TooltipGroup openDelay={400} closeDelay={300}>
186
- <Divider label="color" labelPosition="left" />
187
- <Flex mt={'xs'} maw={150} gap="xs" justify="flex-start" align="flex-start" direction="row" wrap="wrap">
188
- {themedColors.map(({ key, value }) => (
189
- <Tooltip
190
- key={key}
191
- label={key}
192
- fz={'xs'}
193
- color="dark"
194
- offset={2}
195
- transitionProps={{ duration: 140, transition: 'slide-up' }}>
196
- <ColorSwatch
197
- color={value}
198
- size={20}
199
- withShadow
200
- onClick={changeColor(key)}
201
- style={{ color: '#fff', cursor: 'pointer' }}
202
- >
203
- {selectedColor === key && <CheckIcon style={{ width: rem(12), height: rem(12) }} />}
204
- </ColorSwatch>
205
- </Tooltip>
206
- ))}
207
- </Flex>
208
-
209
- <Flex mt="sm" maw={150} gap="xs" justify="flex-start" align="flex-start" direction="row" wrap="wrap">
210
- {colors.map(({ key, value }) => (
211
- <Tooltip
212
- key={key}
213
- label={key}
214
- fz={'xs'}
215
- color="dark"
216
- offset={2}
217
- transitionProps={{ duration: 140, transition: 'slide-up' }}>
218
- <ColorSwatch
219
- color={value}
220
- size={20}
221
- onClick={changeColor(key)}
222
- style={{ color: '#fff', cursor: 'pointer' }}
223
- >
224
- {selectedColor === key && <CheckIcon style={{ width: rem(12), height: rem(12) }} />}
225
- </ColorSwatch>
226
- </Tooltip>
227
- ))}
228
- </Flex>
229
- </TooltipGroup>
230
- </div>
231
- )
232
- }
233
-
234
- function ShapeOption({
235
- nodes: [firstNode, ...nodes],
236
- onShapeChange
237
- }: {
238
- nodes: NonEmptyArray<XYNodesData>
239
- onShapeChange: (shape: ElementShape) => void
240
- }) {
241
- let selectedShape = firstNode.data.element.shape as ElementShape | null
242
- takeWhile(nodes, node => {
243
- if (node.data.element.shape !== selectedShape) {
244
- selectedShape = null
245
- return false
246
- }
247
- return true
248
- })
249
-
250
- return (
251
- <div>
252
- <Divider label="shape" labelPosition="left" />
253
- <Select
254
- mt={'xs'}
255
- size="xs"
256
- variant="filled"
257
- value={selectedShape}
258
- placeholder={'[ multiple ]'}
259
- data={ElementShapes}
260
- allowDeselect={false}
261
- checkIconPosition="right"
262
- onChange={(value) => {
263
- if (!value || value === selectedShape) {
264
- return
265
- }
266
- onShapeChange(value as ElementShape)
267
- }} />
268
- </div>
269
- )
270
- }
271
-
272
- function NavigateToOption({
273
- nodes: [node, ...nodes]
274
- }: {
275
- nodes: NonEmptyArray<XYNodesData>
276
- }) {
277
- const isMultiple = nodes.length >= 1
278
- return (
279
- <div>
280
- <Divider label="navigate to" labelPosition="left" />
281
- {isMultiple && (
282
- <Text size="xs" c={'dimmed'}>
283
- {'[ multiple ]'}
284
- </Text>
285
- )}
286
- {!isMultiple && (
287
- <>
288
- <Space h={'xs'} />
289
- <Select
290
- size="xs"
291
- variant="filled"
292
- value={node.data.element.navigateTo ?? null}
293
- placeholder={'select'}
294
- data={node.data.element.navigateTo
295
- ? [{ value: node.data.element.navigateTo, label: node.data.element.navigateTo }]
296
- : []}
297
- allowDeselect={true}
298
- checkIconPosition="right"
299
- />
300
- </>
301
- )}
302
- </div>
303
- )
304
- }
305
-
306
- function OpacityOption({
307
- node,
308
- onOpacityChange
309
- }: {
310
- node: XYNodesData
311
- onOpacityChange: (opacity: number) => void
312
- }) {
313
- let selectedOpacity = node.data.element.style.opacity ?? 100
314
- const [value, setValue] = useState(selectedOpacity)
315
- useUpdateEffect(() => {
316
- setValue(selectedOpacity)
317
- }, [selectedOpacity])
318
-
319
- return (
320
- <Slider
321
- size={'sm'}
322
- color={'dark'}
323
- value={value}
324
- onChange={setValue}
325
- onChangeEnd={onOpacityChange} />
326
- )
327
- }
328
-
329
- function BorderStyleOption({
330
- node,
331
- onChange
332
- }: {
333
- node: XYNodesData
334
- onChange: (borderStyle: BorderStyle) => void
335
- }) {
336
- let selecteBorderStyle = node.data.element.style.border ?? 'dashed'
337
- const [value, setValue] = useState(selecteBorderStyle)
338
- useUpdateEffect(() => {
339
- setValue(selecteBorderStyle)
340
- }, [selecteBorderStyle])
341
-
342
- return (
343
- <Box>
344
- <SegmentedControl
345
- size="xs"
346
- fullWidth
347
- withItemsBorders={false}
348
- value={value}
349
- onChange={v => {
350
- setValue(v as BorderStyle)
351
- onChange(v as BorderStyle)
352
- }}
353
- data={[
354
- { label: 'Solid', value: 'solid' },
355
- { label: 'Dashed', value: 'dashed' },
356
- { label: 'Dotted', value: 'dotted' },
357
- { label: 'None', value: 'none' }
358
- ]}
359
- />
360
- </Box>
361
- )
362
- }
@@ -1,101 +0,0 @@
1
- import { createVar, globalStyle, style } from '@vanilla-extract/css'
2
- import { mantine, vars, whereDark, whereLight } from '../../../theme-vars'
3
-
4
- const bg = createVar('bg')
5
-
6
- export const container = style({
7
- backgroundColor: mantine.colors.body,
8
- pointerEvents: 'all',
9
- position: 'absolute',
10
- top: 0,
11
- left: 0,
12
- zIndex: 100,
13
- vars: {
14
- [bg]: `linear-gradient(180deg, ${vars.element.fill}, ${vars.element.fill} 3px, transparent 3px)`
15
- },
16
- backgroundImage: bg,
17
- selectors: {
18
- [`${whereDark} &`]: {
19
- backgroundColor: mantine.colors.dark[6],
20
- vars: {
21
- [bg]: `
22
- linear-gradient(180deg, color-mix(in srgb, ${vars.element.fill} 10%, transparent), transparent 60px),
23
- linear-gradient(180deg, ${vars.element.fill}, ${vars.element.fill} 3px, transparent 3px)
24
- `
25
- }
26
- }
27
- }
28
- })
29
-
30
- export const noPointerEvents = style({
31
- pointerEvents: 'none'
32
- })
33
-
34
- export const fqn = style({
35
- display: 'inline-block',
36
- fontSize: mantine.fontSizes.xs,
37
- fontWeight: 500,
38
- whiteSpace: 'nowrap',
39
- padding: '3px 5px',
40
- borderRadius: 2,
41
- background: `color-mix(in srgb , ${vars.element.fill}, transparent 25%)`,
42
- lineHeight: 1.2,
43
- color: vars.element.hiContrast,
44
- selectors: {
45
- [`${whereDark} &`]: {
46
- // background: `color-mix(in srgb , ${vars.element.fill}, transparent 45%)`,
47
- // color: vars.element.loContrast
48
- }
49
- }
50
- })
51
-
52
- export const edgeNum = style({
53
- display: 'inline-block',
54
- fontSize: mantine.fontSizes.sm,
55
- fontWeight: 600,
56
- padding: '1px 5px',
57
- minWidth: 24,
58
- textAlign: 'center',
59
- borderRadius: mantine.radius.sm,
60
- background: mantine.colors.dark[7],
61
- color: mantine.colors.defaultColor,
62
- selectors: {
63
- [`${whereLight} &`]: {
64
- background: mantine.colors.gray[4],
65
- color: mantine.colors.dark[6]
66
- },
67
- [`&[data-zero]`]: {
68
- color: mantine.colors.dimmed
69
- },
70
- [`${whereLight} &[data-zero]`]: {
71
- background: mantine.colors.gray[3]
72
- },
73
- [`&[data-missing]`]: {
74
- color: mantine.colors.orange[4],
75
- background: `color-mix(in srgb, ${mantine.colors.orange[8]} 20%, transparent)`
76
- },
77
- [`${whereLight} &[data-missing]`]: {
78
- color: mantine.colors.orange[8]
79
- }
80
- }
81
- })
82
-
83
- export const viewButton = style({
84
- paddingLeft: 2,
85
- height: 'auto'
86
- })
87
-
88
- globalStyle(`${viewButton} .mantine-Button-label`, {
89
- color: mantine.colors.text,
90
- fontWeight: 500,
91
- flexDirection: 'column',
92
- alignItems: 'flex-start'
93
- })
94
- globalStyle(`${viewButton} .tabler-icon`, {
95
- width: '75%',
96
- opacity: 0.75
97
- })
98
-
99
- globalStyle(`${whereLight} ${viewButton} .mantine-Button-label`, {
100
- color: mantine.colors.dark[3]
101
- })