@likec4/diagram 1.28.0 → 1.28.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.
- package/bundle/index.js +967 -1150
- package/dist/LikeC4CustomColors.js +2 -2
- package/dist/LikeC4Diagram.js +2 -2
- package/dist/LikeC4ModelProvider.js +1 -1
- package/dist/_virtual/index.js +5 -0
- package/dist/_virtual/index2.js +3 -0
- package/dist/_virtual/react.production.js +3 -0
- package/dist/base/BaseXYFlow.js +5 -5
- package/dist/base/primitives/compound/CompoundActionButton.js +1 -1
- package/dist/base/primitives/compound/CompoundDetailsButton.js +1 -1
- package/dist/base/primitives/compound/CompoundNodeContainer.d.ts +1 -1
- package/dist/base/primitives/compound/CompoundNodeContainer.js +2 -2
- package/dist/base/primitives/customEdge.d.ts +1 -1
- package/dist/base/primitives/customEdge.js +2 -2
- package/dist/base/primitives/customNode.js +2 -2
- package/dist/base/primitives/edge/EdgeContainer.js +1 -1
- package/dist/base/primitives/edge/EdgeLabel.js +1 -1
- package/dist/base/primitives/edge/EdgeLabelContainer.js +1 -1
- package/dist/base/primitives/edge/EdgePath.d.ts +10 -42
- package/dist/base/primitives/edge/EdgePath.js +23 -16
- package/dist/base/primitives/edge/edge.css.js +1 -1
- package/dist/base/primitives/element/ElementActionButtons.js +1 -2
- package/dist/base/primitives/element/ElementDetailsButton.js +1 -2
- package/dist/base/primitives/element/ElementNodeContainer.js +3 -3
- package/dist/base/updateEdges.js +7 -2
- package/dist/base/updateNodes.js +11 -3
- package/dist/bundle/LikeC4View.js +3 -3
- package/dist/bundle/ReactLikeC4.js +1 -1
- package/dist/bundle/ShadowRoot.js +3 -3
- package/dist/bundle/styles.css.js +3 -3
- package/dist/context/ControlsCustomLayout.js +1 -1
- package/dist/context/DiagramEventHandlers.js +5 -5
- package/dist/context/DiagramFeatures.js +7 -7
- package/dist/context/EnsureMantine.js +2 -2
- package/dist/context/FramerMotionConfig.js +2 -2
- package/dist/context/IconRenderer.js +4 -4
- package/dist/context/ReduceGraphics.js +2 -2
- package/dist/context/RootContainer.js +5 -9
- package/dist/hooks/safeContext.js +3 -3
- package/dist/hooks/useCurrentViewId.js +1 -1
- package/dist/hooks/useDiagram.d.ts +4 -4
- package/dist/hooks/useDiagram.js +2 -2
- package/dist/hooks/useMantinePortalProps.js +2 -2
- package/dist/hooks/useSetState.js +3 -3
- package/dist/hooks/useUpdateEffect.js +1 -1
- package/dist/hooks/useXYFlow.d.ts +2 -2
- package/dist/likec4diagram/DiagramUI.js +2 -2
- package/dist/likec4diagram/DiagramXYFlow.js +2 -2
- package/dist/likec4diagram/custom/edges/NotePopover.js +2 -2
- package/dist/likec4diagram/custom/edges/RelationshipEdge.d.ts +2 -2
- package/dist/likec4diagram/custom/edges/RelationshipEdge.js +7 -7
- package/dist/likec4diagram/custom/edges/RelationshipsDropdownMenu.js +6 -6
- package/dist/likec4diagram/custom/index.d.ts +1 -2
- package/dist/likec4diagram/custom/nodes/toolbar/ColorButton.js +2 -2
- package/dist/likec4diagram/custom/nodes/toolbar/CompoundToolbar.js +3 -3
- package/dist/likec4diagram/custom/nodes/toolbar/_shared.js +2 -2
- package/dist/likec4diagram/ui/controls/ChangeAutoLayoutButton.js +4 -4
- package/dist/likec4diagram/ui/controls/Controls.js +6 -6
- package/dist/likec4diagram/ui/controls/NavigationButtons.js +1 -1
- package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +1 -1
- package/dist/likec4diagram/ui/notation/NotationPanel.js +4 -4
- package/dist/likec4diagram/ui/search/ElementsColumn.js +88 -77
- package/dist/likec4diagram/ui/search/LikeC4Search.d.ts +2 -1
- package/dist/likec4diagram/ui/search/LikeC4Search.js +27 -24
- package/dist/likec4diagram/ui/search/SearchInput.js +1 -1
- package/dist/likec4diagram/ui/search/ViewsColum.js +3 -2
- package/dist/likec4diagram/ui/search/state.js +11 -9
- package/dist/likec4diagram/ui/walkthrough/DynamicViewWalkthrough.js +1 -1
- package/dist/likec4diagram/useLayoutConstraints.js +3 -3
- package/dist/likec4model/LikeC4ModelContext.js +2 -2
- package/dist/likec4model/useLikeC4ElementsTree.js +2 -2
- package/dist/likec4model/useLikeC4Model.js +2 -2
- package/dist/node_modules/.pnpm/react@19.0.0/node_modules/react/cjs/react.production.js +548 -0
- package/dist/node_modules/.pnpm/react@19.0.0/node_modules/react/index.js +15 -0
- package/dist/overlays/Overlays.js +6 -6
- package/dist/overlays/element-details/ElementDetailsCard.js +5 -5
- package/dist/overlays/element-details/TabPanelDeployments.js +7 -4
- package/dist/overlays/element-details/TabPanelRelationships.js +2 -2
- package/dist/overlays/element-details/TabPanelStructure.js +6 -3
- package/dist/overlays/element-details/actor.d.ts +2 -2
- package/dist/overlays/element-details/actorContext.js +3 -3
- package/dist/overlays/overlay/Overlay.js +8 -7
- package/dist/overlays/relationship-details/RelationshipDetails.d.ts +1 -1
- package/dist/overlays/relationship-details/RelationshipDetails.js +28 -23
- package/dist/overlays/relationship-details/SelectEdge.js +3 -6
- package/dist/overlays/relationship-details/actor.d.ts +4 -1
- package/dist/overlays/relationship-details/custom/edgeTypes.d.ts +1 -1
- package/dist/overlays/relationship-details/custom/edgeTypes.js +1 -1
- package/dist/overlays/relationship-details/hooks.d.ts +4 -1
- package/dist/overlays/relationship-details/hooks.js +4 -4
- package/dist/overlays/relationships-browser/RelationshipsBrowser.d.ts +1 -1
- package/dist/overlays/relationships-browser/RelationshipsBrowser.js +9 -11
- package/dist/overlays/relationships-browser/SelectElement.js +8 -5
- package/dist/overlays/relationships-browser/actor.d.ts +2 -1
- package/dist/overlays/relationships-browser/actor.js +6 -12
- package/dist/overlays/relationships-browser/const.d.ts +2 -1
- package/dist/overlays/relationships-browser/const.js +6 -1
- package/dist/overlays/relationships-browser/custom/edgeTypes.d.ts +1 -1
- package/dist/overlays/relationships-browser/custom/edgeTypes.js +3 -4
- package/dist/overlays/relationships-browser/custom/nodeTypes.js +1 -1
- package/dist/overlays/relationships-browser/hooks.d.ts +2 -1
- package/dist/overlays/relationships-browser/hooks.js +4 -4
- package/dist/overlays/relationships-browser/layout.js +2 -2
- package/dist/overlays/relationships-browser/useViewToNodesEdges.js +1 -2
- package/dist/state/DiagramActorProvider.js +5 -3
- package/dist/state/diagram-machine.d.ts +4 -4
- package/dist/state/diagram-machine.js +3 -4
- package/dist/styles.css.js +1 -1
- package/package.json +17 -13
- package/src/base/BaseXYFlow.tsx +2 -2
- package/src/base/primitives/compound/CompoundActionButton.tsx +1 -1
- package/src/base/primitives/compound/CompoundDetailsButton.tsx +1 -1
- package/src/base/primitives/compound/CompoundNodeContainer.tsx +1 -1
- package/src/base/primitives/edge/EdgePath.tsx +22 -14
- package/src/base/primitives/edge/edge.css.ts +1 -1
- package/src/base/primitives/element/ElementActionButtons.tsx +2 -2
- package/src/base/primitives/element/ElementDetailsButton.tsx +2 -2
- package/src/base/primitives/element/ElementNodeContainer.tsx +1 -1
- package/src/base/updateEdges.ts +6 -9
- package/src/base/updateNodes.ts +10 -14
- package/src/context/FramerMotionConfig.tsx +1 -1
- package/src/context/RootContainer.tsx +0 -4
- package/src/likec4diagram/custom/edges/RelationshipEdge.tsx +2 -2
- package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.tsx +1 -1
- package/src/likec4diagram/ui/controls/Controls.tsx +53 -55
- package/src/likec4diagram/ui/controls/NavigationButtons.tsx +1 -1
- package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.tsx +1 -1
- package/src/likec4diagram/ui/notation/NotationPanel.tsx +1 -1
- package/src/likec4diagram/ui/search/ElementsColumn.tsx +94 -71
- package/src/likec4diagram/ui/search/LikeC4Search.tsx +48 -55
- package/src/likec4diagram/ui/search/ViewsColum.tsx +2 -2
- package/src/likec4diagram/ui/search/state.ts +8 -6
- package/src/likec4diagram/ui/walkthrough/DynamicViewWalkthrough.tsx +1 -1
- package/src/overlays/Overlays.tsx +2 -2
- package/src/overlays/element-details/ElementDetailsCard.tsx +1 -1
- package/src/overlays/element-details/TabPanelDeployments.tsx +2 -0
- package/src/overlays/element-details/TabPanelStructure.tsx +2 -1
- package/src/overlays/overlay/Overlay.tsx +2 -1
- package/src/overlays/relationship-details/RelationshipDetails.tsx +25 -16
- package/src/overlays/relationship-details/SelectEdge.tsx +0 -14
- package/src/overlays/relationship-details/actor.ts +2 -1
- package/src/overlays/relationship-details/custom/edgeTypes.tsx +1 -1
- package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +1 -3
- package/src/overlays/relationships-browser/SelectElement.tsx +2 -0
- package/src/overlays/relationships-browser/actor.ts +8 -13
- package/src/overlays/relationships-browser/const.ts +8 -1
- package/src/overlays/relationships-browser/custom/edgeTypes.tsx +2 -3
- package/src/overlays/relationships-browser/custom/nodeTypes.tsx +1 -1
- package/src/overlays/relationships-browser/useViewToNodesEdges.ts +1 -2
- package/src/state/DiagramActorProvider.tsx +4 -1
- package/src/state/diagram-machine.ts +2 -3
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
import { useCallbackRef } from '@mantine/hooks'
|
|
24
24
|
import { IconChevronRight } from '@tabler/icons-react'
|
|
25
25
|
import clsx from 'clsx'
|
|
26
|
-
import
|
|
27
|
-
import { useEffect, useMemo } from 'react'
|
|
26
|
+
import * as m from 'motion/react-m'
|
|
27
|
+
import { type KeyboardEventHandler, useCallback, useEffect, useMemo } from 'react'
|
|
28
28
|
import { first, indexBy, isEmpty, only, partition, pipe, prop, reduce } from 'remeda'
|
|
29
29
|
import { IconOrShapeRenderer } from '../../../context/IconRenderer'
|
|
30
30
|
import { sortByLabel } from '../../../likec4model/useLikeC4ElementsTree'
|
|
@@ -61,11 +61,8 @@ const btn = buttonsva()
|
|
|
61
61
|
export function ElementsColumn() {
|
|
62
62
|
const search = useNormalizedSearch()
|
|
63
63
|
const model = useLikeC4Model(true)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
byid,
|
|
67
|
-
roots: data,
|
|
68
|
-
} = useMemo(() => {
|
|
64
|
+
|
|
65
|
+
const data = useMemo(() => {
|
|
69
66
|
const searchTerms = search.split('.')
|
|
70
67
|
let elements
|
|
71
68
|
if (isEmpty(search) || search === 'kind:') {
|
|
@@ -82,9 +79,9 @@ export function ElementsColumn() {
|
|
|
82
79
|
.toLocaleLowerCase().includes(search)
|
|
83
80
|
})
|
|
84
81
|
}
|
|
82
|
+
const byid = {} as Record<Fqn, LikeC4ModelTreeNodeData>
|
|
85
83
|
const { all, roots } = pipe(
|
|
86
|
-
elements,
|
|
87
|
-
toArray(),
|
|
84
|
+
[...elements],
|
|
88
85
|
sortParentsFirst,
|
|
89
86
|
reduce((acc, element) => {
|
|
90
87
|
const treeItem: LikeC4ModelTreeNodeData = {
|
|
@@ -94,6 +91,7 @@ export function ElementsColumn() {
|
|
|
94
91
|
searchTerms,
|
|
95
92
|
children: [],
|
|
96
93
|
}
|
|
94
|
+
byid[treeItem.value] = treeItem
|
|
97
95
|
const parent = acc.all.findLast((root) => isAncestor(root.value, treeItem.value))
|
|
98
96
|
if (parent) {
|
|
99
97
|
parent.children.push(treeItem)
|
|
@@ -112,14 +110,42 @@ export function ElementsColumn() {
|
|
|
112
110
|
)
|
|
113
111
|
return {
|
|
114
112
|
all,
|
|
115
|
-
byid
|
|
113
|
+
byid,
|
|
116
114
|
roots: roots.sort(sortByLabel),
|
|
117
115
|
}
|
|
118
116
|
}, [model, search])
|
|
119
117
|
|
|
118
|
+
const handleClick = useHandleElementSelection()
|
|
119
|
+
|
|
120
|
+
if (data.all.length === 0) {
|
|
121
|
+
return <NothingFound />
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return <ElementsTree data={data} handleClick={handleClick} />
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const setHoveredNode = () => {}
|
|
128
|
+
|
|
129
|
+
function ElementsTree({
|
|
130
|
+
data: {
|
|
131
|
+
all,
|
|
132
|
+
byid,
|
|
133
|
+
roots,
|
|
134
|
+
},
|
|
135
|
+
handleClick,
|
|
136
|
+
}: {
|
|
137
|
+
data: {
|
|
138
|
+
all: LikeC4ModelTreeNodeData[]
|
|
139
|
+
byid: Record<Fqn, LikeC4ModelTreeNodeData>
|
|
140
|
+
roots: LikeC4ModelTreeNodeData[]
|
|
141
|
+
}
|
|
142
|
+
handleClick: (element: LikeC4Model.Element) => void
|
|
143
|
+
}) {
|
|
120
144
|
const tree = useTree({
|
|
121
145
|
multiple: false,
|
|
122
146
|
})
|
|
147
|
+
tree.setHoveredNode = setHoveredNode
|
|
148
|
+
|
|
123
149
|
useEffect(() => {
|
|
124
150
|
tree.collapseAllNodes()
|
|
125
151
|
for (const nd of all) {
|
|
@@ -129,66 +155,63 @@ export function ElementsColumn() {
|
|
|
129
155
|
}
|
|
130
156
|
}, [all])
|
|
131
157
|
|
|
132
|
-
const
|
|
158
|
+
const onKeyDownCapture: KeyboardEventHandler = useCallbackRef((e) => {
|
|
159
|
+
const target = e.target as HTMLElement
|
|
160
|
+
const id = target.getAttribute('data-value')
|
|
161
|
+
const node = !!id && byid[id as Fqn]
|
|
162
|
+
if (!node) return
|
|
163
|
+
if (e.key === 'ArrowUp') {
|
|
164
|
+
if (id === roots[0]?.value) {
|
|
165
|
+
stopAndPrevent(e)
|
|
166
|
+
moveFocusToSearchInput()
|
|
167
|
+
}
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
if (e.key === 'ArrowRight') {
|
|
171
|
+
const hasChildren = node.children.length > 0
|
|
172
|
+
if (hasChildren && tree.expandedState[id] === false) {
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
const label = (e.target as HTMLLIElement).querySelector<HTMLLIElement>('.mantine-Tree-label') ?? target
|
|
176
|
+
const maxY = label.getBoundingClientRect().y
|
|
177
|
+
const viewButtons = [...document.querySelectorAll<HTMLButtonElement>(
|
|
178
|
+
`[data-likec4-search-views] .${styles.focusable}`,
|
|
179
|
+
)]
|
|
180
|
+
let view = viewButtons.length > 1
|
|
181
|
+
? viewButtons.find((el, i, all) => centerY(el) > maxY || i === all.length - 1)
|
|
182
|
+
: null
|
|
183
|
+
view ??= first(viewButtons)
|
|
184
|
+
if (view) {
|
|
185
|
+
stopAndPrevent(e)
|
|
186
|
+
view.focus()
|
|
187
|
+
}
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
if (e.key === ' ' || e.key === 'Enter') {
|
|
191
|
+
stopAndPrevent(e)
|
|
192
|
+
handleClick(node.element)
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
})
|
|
133
196
|
|
|
134
197
|
return (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const target = e.target as HTMLElement
|
|
153
|
-
const id = target.getAttribute('data-value')
|
|
154
|
-
const node = !!id && byid[id as Fqn]
|
|
155
|
-
if (!node) return
|
|
156
|
-
if (e.key === 'ArrowUp') {
|
|
157
|
-
if (id === data[0]?.value) {
|
|
158
|
-
stopAndPrevent(e)
|
|
159
|
-
moveFocusToSearchInput()
|
|
160
|
-
}
|
|
161
|
-
return
|
|
162
|
-
}
|
|
163
|
-
if (e.key === 'ArrowRight') {
|
|
164
|
-
const hasChildren = node.children.length > 0
|
|
165
|
-
if (hasChildren && tree.expandedState[id] === false) {
|
|
166
|
-
return
|
|
167
|
-
}
|
|
168
|
-
const label = (e.target as HTMLLIElement).querySelector<HTMLLIElement>('.mantine-Tree-label') ?? target
|
|
169
|
-
const maxY = label.getBoundingClientRect().y
|
|
170
|
-
const viewButtons = [...document.querySelectorAll<HTMLButtonElement>(
|
|
171
|
-
`[data-likec4-search-views] .${styles.focusable}`,
|
|
172
|
-
)]
|
|
173
|
-
let view = viewButtons.length > 1
|
|
174
|
-
? viewButtons.find((el, i, all) => centerY(el) > maxY || i === all.length - 1)
|
|
175
|
-
: null
|
|
176
|
-
view ??= first(viewButtons)
|
|
177
|
-
if (view) {
|
|
178
|
-
stopAndPrevent(e)
|
|
179
|
-
view.focus()
|
|
180
|
-
}
|
|
181
|
-
return
|
|
182
|
-
}
|
|
183
|
-
if (e.key === ' ' || e.key === 'Enter') {
|
|
184
|
-
stopAndPrevent(e)
|
|
185
|
-
handleClick(node.element)
|
|
186
|
-
return
|
|
187
|
-
}
|
|
188
|
-
}}
|
|
189
|
-
renderNode={ElementTreeNode}
|
|
190
|
-
/>
|
|
191
|
-
</>
|
|
198
|
+
<Tree
|
|
199
|
+
data-likec4-search-elements
|
|
200
|
+
allowRangeSelection={false}
|
|
201
|
+
clearSelectionOnOutsideClick
|
|
202
|
+
selectOnClick={false}
|
|
203
|
+
tree={tree}
|
|
204
|
+
data={roots}
|
|
205
|
+
levelOffset={'lg'}
|
|
206
|
+
classNames={{
|
|
207
|
+
root: styles.treeRoot,
|
|
208
|
+
node: cx(styles.focusable, styles.treeNode),
|
|
209
|
+
label: styles.treeLabel,
|
|
210
|
+
subtree: styles.treeSubtree,
|
|
211
|
+
}}
|
|
212
|
+
onKeyDownCapture={onKeyDownCapture}
|
|
213
|
+
renderNode={ElementTreeNode}
|
|
214
|
+
/>
|
|
192
215
|
)
|
|
193
216
|
}
|
|
194
217
|
|
|
@@ -212,7 +235,7 @@ function ElementTreeNode(
|
|
|
212
235
|
const key = `@tree.${node.value}`
|
|
213
236
|
|
|
214
237
|
return (
|
|
215
|
-
<m.div layoutId={key}
|
|
238
|
+
<m.div layoutId={key} {...elementProps as any}>
|
|
216
239
|
<ActionIcon
|
|
217
240
|
variant="transparent"
|
|
218
241
|
size={16}
|
|
@@ -278,7 +301,7 @@ function ElementTreeNode(
|
|
|
278
301
|
function useHandleElementSelection() {
|
|
279
302
|
const navigateTo = useCloseSearchAndNavigateTo()
|
|
280
303
|
|
|
281
|
-
return
|
|
304
|
+
return useCallback((element: LikeC4Model.Element) => {
|
|
282
305
|
const views = [...element.views()]
|
|
283
306
|
if (views.length === 0) {
|
|
284
307
|
return
|
|
@@ -294,5 +317,5 @@ function useHandleElementSelection() {
|
|
|
294
317
|
scoped,
|
|
295
318
|
others,
|
|
296
319
|
})
|
|
297
|
-
})
|
|
320
|
+
}, [setPickView, navigateTo])
|
|
298
321
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { css } from '@likec4/styles/css'
|
|
2
|
+
import { Box } from '@likec4/styles/jsx'
|
|
1
3
|
import {
|
|
2
4
|
ActionIcon,
|
|
3
|
-
Box,
|
|
4
5
|
Grid,
|
|
5
6
|
GridCol,
|
|
6
7
|
Group,
|
|
7
8
|
Portal,
|
|
8
|
-
RemoveScroll,
|
|
9
9
|
ScrollArea,
|
|
10
10
|
ScrollAreaAutosize,
|
|
11
11
|
Stack,
|
|
@@ -20,24 +20,25 @@ import {
|
|
|
20
20
|
useWindowEvent,
|
|
21
21
|
} from '@mantine/hooks'
|
|
22
22
|
import { IconX } from '@tabler/icons-react'
|
|
23
|
-
import { AnimatePresence, LayoutGroup, m } from '
|
|
24
|
-
import { useRef } from 'react'
|
|
23
|
+
import { AnimatePresence, LayoutGroup, m } from 'motion/react'
|
|
24
|
+
import { memo, useRef } from 'react'
|
|
25
25
|
import { SearchControl } from '../../../components/SearchControl'
|
|
26
26
|
import { useMantinePortalProps } from '../../../hooks'
|
|
27
27
|
import { ElementsColumn } from './ElementsColumn'
|
|
28
|
-
import * as
|
|
28
|
+
import * as styles from './LikeC4Search.css'
|
|
29
29
|
import { LikeC4SearchInput } from './SearchInput'
|
|
30
30
|
import {
|
|
31
31
|
LikeC4SearchContext,
|
|
32
32
|
setPickView,
|
|
33
33
|
useCloseSearch,
|
|
34
|
+
useIsPickViewActive,
|
|
34
35
|
usePickView,
|
|
35
36
|
wasResetPickView,
|
|
36
37
|
} from './state'
|
|
37
38
|
import { stopAndPrevent } from './utils'
|
|
38
39
|
import { ViewButton, ViewsColumn } from './ViewsColum'
|
|
39
40
|
|
|
40
|
-
export
|
|
41
|
+
export const LikeC4Search = memo(() => {
|
|
41
42
|
const [searchOpened, searchOps] = useDisclosure(false)
|
|
42
43
|
useHotkeys([
|
|
43
44
|
['mod+k', () => searchOps.toggle(), {
|
|
@@ -69,41 +70,38 @@ export function LikeC4Search() {
|
|
|
69
70
|
e.stopPropagation()
|
|
70
71
|
searchOps.toggle()
|
|
71
72
|
}} />
|
|
72
|
-
<Portal {...portalProps}>
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
</>
|
|
96
|
-
)}
|
|
97
|
-
</AnimatePresence>
|
|
98
|
-
</RemoveScroll>
|
|
73
|
+
<Portal {...portalProps} reuseTargetNode>
|
|
74
|
+
<AnimatePresence onExitComplete={onExitComplete}>
|
|
75
|
+
{searchOpened && (
|
|
76
|
+
<m.div
|
|
77
|
+
key={'backdrop'}
|
|
78
|
+
className={styles.backdrop}
|
|
79
|
+
initial={{ opacity: 0.7 }}
|
|
80
|
+
animate={{
|
|
81
|
+
opacity: 1,
|
|
82
|
+
transition: {
|
|
83
|
+
duration: 0.13,
|
|
84
|
+
},
|
|
85
|
+
}}
|
|
86
|
+
exit={{
|
|
87
|
+
opacity: 0,
|
|
88
|
+
transition: {
|
|
89
|
+
duration: 0.13,
|
|
90
|
+
},
|
|
91
|
+
}}>
|
|
92
|
+
</m.div>
|
|
93
|
+
)}
|
|
94
|
+
{searchOpened && <LikeC4SearchOverlay key="overlay" />}
|
|
95
|
+
</AnimatePresence>
|
|
99
96
|
</Portal>
|
|
100
97
|
</LikeC4SearchContext>
|
|
101
98
|
)
|
|
102
|
-
}
|
|
99
|
+
})
|
|
100
|
+
LikeC4Search.displayName = 'LikeC4Search'
|
|
103
101
|
|
|
104
|
-
|
|
102
|
+
const LikeC4SearchOverlay = () => {
|
|
105
103
|
const close = useCloseSearch()
|
|
106
|
-
const
|
|
104
|
+
const pickViewActive = useIsPickViewActive()
|
|
107
105
|
|
|
108
106
|
useWindowEvent(
|
|
109
107
|
'keydown',
|
|
@@ -120,14 +118,9 @@ function LikeC4SearchOverlay() {
|
|
|
120
118
|
|
|
121
119
|
return (
|
|
122
120
|
<m.div
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// initial={{
|
|
127
|
-
// opacity: 0,
|
|
128
|
-
// // scale: 0.9,
|
|
129
|
-
// translateY: -20,
|
|
130
|
-
// }}
|
|
121
|
+
className={styles.root}
|
|
122
|
+
data-likec4-search="true"
|
|
123
|
+
initial={false}
|
|
131
124
|
animate={{
|
|
132
125
|
opacity: 1,
|
|
133
126
|
scale: 1,
|
|
@@ -136,8 +129,9 @@ function LikeC4SearchOverlay() {
|
|
|
136
129
|
exit={{
|
|
137
130
|
opacity: 0,
|
|
138
131
|
scale: 0.9,
|
|
132
|
+
translateY: -30,
|
|
139
133
|
transition: {
|
|
140
|
-
duration: 0.
|
|
134
|
+
duration: 0.13,
|
|
141
135
|
},
|
|
142
136
|
}}
|
|
143
137
|
>
|
|
@@ -166,16 +160,16 @@ function LikeC4SearchOverlay() {
|
|
|
166
160
|
</GridCol>
|
|
167
161
|
</Grid>
|
|
168
162
|
<Grid
|
|
169
|
-
|
|
163
|
+
className={css({
|
|
170
164
|
containerName: 'likec4-search-elements',
|
|
171
165
|
containerType: 'size',
|
|
172
166
|
overflow: 'hidden',
|
|
173
167
|
flexGrow: 1,
|
|
174
|
-
}}>
|
|
168
|
+
})}>
|
|
175
169
|
<GridCol span={6}>
|
|
176
170
|
<ScrollArea
|
|
177
171
|
type="hover"
|
|
178
|
-
className={
|
|
172
|
+
className={styles.scrollArea}
|
|
179
173
|
pr="xs"
|
|
180
174
|
scrollbars="y">
|
|
181
175
|
<AnimatePresence>
|
|
@@ -188,7 +182,7 @@ function LikeC4SearchOverlay() {
|
|
|
188
182
|
<GridCol span={6}>
|
|
189
183
|
<ScrollArea
|
|
190
184
|
type="hover"
|
|
191
|
-
className={
|
|
185
|
+
className={styles.scrollArea}
|
|
192
186
|
pr="xs"
|
|
193
187
|
scrollbars="y">
|
|
194
188
|
<AnimatePresence>
|
|
@@ -199,8 +193,7 @@ function LikeC4SearchOverlay() {
|
|
|
199
193
|
</ScrollArea>
|
|
200
194
|
</GridCol>
|
|
201
195
|
</Grid>
|
|
202
|
-
<
|
|
203
|
-
<PickView />
|
|
196
|
+
{pickViewActive && <PickView />}
|
|
204
197
|
</m.div>
|
|
205
198
|
)
|
|
206
199
|
}
|
|
@@ -220,7 +213,7 @@ function PickView() {
|
|
|
220
213
|
<>
|
|
221
214
|
<m.div
|
|
222
215
|
key="backdrop"
|
|
223
|
-
className={
|
|
216
|
+
className={styles.pickviewBackdrop}
|
|
224
217
|
onClick={e => {
|
|
225
218
|
e.stopPropagation()
|
|
226
219
|
setPickView(null)
|
|
@@ -248,7 +241,7 @@ function PickView() {
|
|
|
248
241
|
duration: 0.1,
|
|
249
242
|
},
|
|
250
243
|
}}
|
|
251
|
-
className={
|
|
244
|
+
className={styles.pickview}
|
|
252
245
|
data-likec4-search-views
|
|
253
246
|
ref={focusTrapRef}>
|
|
254
247
|
<Group px="sm" py="md" justify="space-between">
|
|
@@ -266,7 +259,7 @@ function PickView() {
|
|
|
266
259
|
|
|
267
260
|
<ScrollAreaAutosize mah={'calc(100vh - 8rem - 50px)'} type="never">
|
|
268
261
|
{pickview.scoped.length > 0 && (
|
|
269
|
-
<Stack gap={'sm'} px={'sm'} className={
|
|
262
|
+
<Stack gap={'sm'} px={'sm'} className={styles.pickviewGroup}>
|
|
270
263
|
<Title order={6} c={'dimmed'}>scoped views of the element</Title>
|
|
271
264
|
{pickview.scoped.map((view, i) => (
|
|
272
265
|
<ViewButton
|
|
@@ -283,7 +276,7 @@ function PickView() {
|
|
|
283
276
|
)}
|
|
284
277
|
|
|
285
278
|
{pickview.others.length > 0 && (
|
|
286
|
-
<Stack gap={'sm'} px={'sm'} className={
|
|
279
|
+
<Stack gap={'sm'} px={'sm'} className={styles.pickviewGroup}>
|
|
287
280
|
<Title order={6} c={'dimmed'}>views including this element</Title>
|
|
288
281
|
{pickview.others.map((view, i) => (
|
|
289
282
|
<ViewButton
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
isDeploymentView,
|
|
5
5
|
} from '@likec4/core'
|
|
6
6
|
import { cx } from '@likec4/styles/css'
|
|
7
|
+
import { Box } from '@likec4/styles/jsx'
|
|
7
8
|
import {
|
|
8
9
|
type ElementProps,
|
|
9
10
|
type UnstyledButtonProps,
|
|
10
11
|
Badge,
|
|
11
|
-
Box,
|
|
12
12
|
createScopedKeydownHandler,
|
|
13
13
|
Group,
|
|
14
14
|
Highlight,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
VisuallyHidden,
|
|
19
19
|
} from '@mantine/core'
|
|
20
20
|
import { IconStack2, IconZoomScan } from '@tabler/icons-react'
|
|
21
|
-
import
|
|
21
|
+
import * as m from 'motion/react-m'
|
|
22
22
|
import { first } from 'remeda'
|
|
23
23
|
import { useCurrentViewId } from '../../../hooks/useCurrentViewId'
|
|
24
24
|
import { useLikeC4Model } from '../../../likec4model/useLikeC4Model'
|
|
@@ -3,7 +3,7 @@ import { createSafeContext } from '@mantine/core'
|
|
|
3
3
|
import { useCallbackRef } from '@mantine/hooks'
|
|
4
4
|
import { useStore } from '@nanostores/react'
|
|
5
5
|
import { atom, computed, onMount } from 'nanostores'
|
|
6
|
-
import { useDeferredValue } from 'react'
|
|
6
|
+
import { useCallback, useDeferredValue } from 'react'
|
|
7
7
|
import { useDiagram } from '../../../hooks/useDiagram'
|
|
8
8
|
|
|
9
9
|
const $search = atom('')
|
|
@@ -59,18 +59,20 @@ export function useIsPickViewActive() {
|
|
|
59
59
|
export function useCloseSearchAndNavigateTo() {
|
|
60
60
|
const diagram = useDiagram()
|
|
61
61
|
const close = useCloseSearch()
|
|
62
|
-
return
|
|
62
|
+
return useCallback((viewId: ViewId, fromElementFqn?: Fqn) => {
|
|
63
63
|
close(() => {
|
|
64
64
|
fromElementFqn ??= $pickView.get()?.elementFqn
|
|
65
65
|
setPickView(null)
|
|
66
66
|
const fromNode = fromElementFqn
|
|
67
67
|
? diagram.getContext().view.nodes.find(n => DiagramNode.modelRef(n) === fromElementFqn)?.id
|
|
68
68
|
: undefined
|
|
69
|
-
if (diagram.currentView.id
|
|
70
|
-
diagram.
|
|
69
|
+
if (diagram.currentView.id !== viewId) {
|
|
70
|
+
diagram.navigateTo(viewId, fromNode)
|
|
71
71
|
return
|
|
72
72
|
}
|
|
73
|
-
|
|
73
|
+
if (fromNode) {
|
|
74
|
+
diagram.focusNode(fromNode)
|
|
75
|
+
}
|
|
74
76
|
})
|
|
75
|
-
})
|
|
77
|
+
}, [close, diagram])
|
|
76
78
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
IconPlayerStopFilled,
|
|
7
7
|
} from '@tabler/icons-react'
|
|
8
8
|
import clsx from 'clsx'
|
|
9
|
-
import { AnimatePresence, m } from '
|
|
9
|
+
import { AnimatePresence, m } from 'motion/react'
|
|
10
10
|
import { isNonNull, isTruthy } from 'remeda'
|
|
11
11
|
import { useXYStore } from '../../../hooks'
|
|
12
12
|
import { useDiagram, useDiagramContext } from '../../../hooks/useDiagram'
|
|
@@ -2,8 +2,8 @@ import { nonexhaustive } from '@likec4/core'
|
|
|
2
2
|
import { Box, Button, Code, Group, Notification, ScrollAreaAutosize } from '@mantine/core'
|
|
3
3
|
import { IconX } from '@tabler/icons-react'
|
|
4
4
|
import { useSelector } from '@xstate/react'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { animate } from 'motion'
|
|
6
|
+
import { AnimatePresence, LayoutGroup, useReducedMotionConfig } from 'motion/react'
|
|
7
7
|
import { memo, useEffect, useMemo } from 'react'
|
|
8
8
|
import { type FallbackProps, ErrorBoundary } from 'react-error-boundary'
|
|
9
9
|
import { isNonNullish } from 'remeda'
|
|
@@ -38,7 +38,7 @@ import { useSessionStorage, useViewportSize } from '@mantine/hooks'
|
|
|
38
38
|
import { useDebouncedCallback, useSyncedRef, useTimeoutEffect } from '@react-hookz/web'
|
|
39
39
|
import { IconExternalLink, IconFileSymlink, IconStack2, IconZoomScan } from '@tabler/icons-react'
|
|
40
40
|
import type { Rect } from '@xyflow/system'
|
|
41
|
-
import { type PanInfo, m, useDragControls, useMotionValue } from '
|
|
41
|
+
import { type PanInfo, m, useDragControls, useMotionValue } from 'motion/react'
|
|
42
42
|
import { type PropsWithChildren, useCallback, useRef, useState } from 'react'
|
|
43
43
|
import { clamp, isNullish, map, only, partition, pipe } from 'remeda'
|
|
44
44
|
import { Link } from '../../components/Link'
|
|
@@ -105,6 +105,7 @@ const DeployedInstanceRenderer = (
|
|
|
105
105
|
)
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
const setHoveredNode = () => {}
|
|
108
109
|
export const TabPanelDeployments = memo<TabPanelDeploymentsProps>(({ elementFqn }) => {
|
|
109
110
|
const element = useLikeC4Model(true).element(elementFqn)
|
|
110
111
|
const deployments = [...element.deployments()]
|
|
@@ -112,6 +113,7 @@ export const TabPanelDeployments = memo<TabPanelDeploymentsProps>(({ elementFqn
|
|
|
112
113
|
const tree = useTree({
|
|
113
114
|
multiple: false,
|
|
114
115
|
})
|
|
116
|
+
tree.setHoveredNode = setHoveredNode
|
|
115
117
|
|
|
116
118
|
const data = useMemo(() => {
|
|
117
119
|
let roots = [] as TreeNodeData[]
|
|
@@ -37,13 +37,14 @@ export const ElementLabel = ({
|
|
|
37
37
|
// node
|
|
38
38
|
// }: RenderTreeNodePayload) => {
|
|
39
39
|
// }
|
|
40
|
-
|
|
40
|
+
const setHoveredNode = () => {}
|
|
41
41
|
export function TabPanelStructure({
|
|
42
42
|
element,
|
|
43
43
|
}: TabPanelStructureProps) {
|
|
44
44
|
const tree = useTree({
|
|
45
45
|
multiple: false,
|
|
46
46
|
})
|
|
47
|
+
tree.setHoveredNode = setHoveredNode
|
|
47
48
|
|
|
48
49
|
const data = useMemo(() => {
|
|
49
50
|
let seq = 1
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from '@mantine/core'
|
|
6
6
|
import { useMergedRef } from '@mantine/hooks'
|
|
7
7
|
import { useDebouncedCallback, useSyncedRef, useTimeoutEffect } from '@react-hookz/web'
|
|
8
|
-
import { m, useReducedMotionConfig } from '
|
|
8
|
+
import { m, useReducedMotionConfig } from 'motion/react'
|
|
9
9
|
import { type PropsWithChildren, forwardRef, useEffect, useRef, useState } from 'react'
|
|
10
10
|
import { stopPropagation } from '../../utils'
|
|
11
11
|
import { backdropBlur, backdropOpacity, level as cssVarLevel, overlay as overlayCVA } from './Overlay.css'
|
|
@@ -49,6 +49,7 @@ export const Overlay = forwardRef<HTMLDialogElement, OverlayProps>(({
|
|
|
49
49
|
useEffect(() => {
|
|
50
50
|
const cancel = (e: Event) => {
|
|
51
51
|
e.preventDefault()
|
|
52
|
+
e.stopPropagation()
|
|
52
53
|
close()
|
|
53
54
|
}
|
|
54
55
|
dialogRef.current?.addEventListener('cancel', cancel, { capture: true })
|