@likec4/diagram 1.3.0 → 1.4.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 (44) hide show
  1. package/dist/LikeC4Diagram.d.ts +1 -1
  2. package/dist/LikeC4Diagram.props.d.ts +6 -1
  3. package/dist/index.mjs +270 -168
  4. package/dist/state/DiagramContext.d.ts +155 -154
  5. package/dist/state/diagramStore.d.ts +154 -154
  6. package/dist/state/index.d.ts +0 -1
  7. package/dist/state/useDiagramStore.d.ts +3 -4622
  8. package/dist/state/useNavigationHistory.d.ts +5 -0
  9. package/dist/style.css +86 -54
  10. package/dist/theme.css.d.ts +5 -0
  11. package/dist/ui/BackwardForwardPanel.css.d.ts +1 -0
  12. package/dist/ui/BackwardForwardPanel.d.ts +1 -0
  13. package/dist/ui/DiagramTitlePanel.css.d.ts +1 -1
  14. package/dist/ui/OptionsPanel.d.ts +1 -3
  15. package/dist/xyflow/XYFlowEvents.d.ts +4 -4
  16. package/dist/xyflow/XYFlowInner.d.ts +1 -0
  17. package/dist/xyflow/edges/RelationshipEdge.d.ts +1 -1
  18. package/dist/xyflow/hooks/useXYFlow.d.ts +9 -9
  19. package/dist/xyflow/nodes/element/element.css.d.ts +1 -0
  20. package/dist/xyflow/types.d.ts +1 -1
  21. package/package.json +10 -10
  22. package/src/LikeC4Diagram.css.ts +11 -1
  23. package/src/LikeC4Diagram.props.ts +10 -3
  24. package/src/LikeC4Diagram.tsx +30 -7
  25. package/src/globals.css.ts +1 -1
  26. package/src/state/DiagramContext.tsx +3 -3
  27. package/src/state/diagramStore.ts +27 -30
  28. package/src/state/index.ts +0 -1
  29. package/src/state/useDiagramStore.ts +6 -13
  30. package/src/state/useNavigationHistory.ts +39 -0
  31. package/src/theme.css.ts +5 -0
  32. package/src/ui/BackwardForwardPanel.css.ts +22 -0
  33. package/src/ui/BackwardForwardPanel.tsx +59 -0
  34. package/src/ui/DiagramTitlePanel.css.ts +11 -5
  35. package/src/ui/DiagramTitlePanel.tsx +105 -93
  36. package/src/ui/OptionsPanel.tsx +28 -19
  37. package/src/xyflow/XYFlowInner.tsx +5 -2
  38. package/src/xyflow/diagram-to-xyflow.ts +2 -13
  39. package/src/xyflow/edges/RelationshipEdge.tsx +11 -8
  40. package/src/xyflow/edges/edges.css.ts +14 -10
  41. package/src/xyflow/hooks/useLayoutConstraints.ts +2 -1
  42. package/src/xyflow/nodes/compound/CompoundNode.css.ts +8 -8
  43. package/src/xyflow/nodes/element/ElementNode.tsx +7 -8
  44. package/src/xyflow/nodes/element/element.css.ts +18 -5
@@ -4,7 +4,7 @@ import clsx from 'clsx'
4
4
  import { DEV } from 'esm-env'
5
5
  import { shallowEqual } from 'fast-equals'
6
6
  import { domAnimation, LazyMotion } from 'framer-motion'
7
- import { memo, useRef } from 'react'
7
+ import { memo, useEffect, useRef, useState } from 'react'
8
8
  import useTilg from 'tilg'
9
9
  import { rootClassName } from './globals.css'
10
10
  import { KeepAspectRatioContainer } from './KeepAspectRatioContainer'
@@ -12,7 +12,7 @@ import { cssDisablePan, cssNoControls, cssReactFlow, cssTransparentBg } from './
12
12
  import { type LikeC4DiagramEventHandlers, type LikeC4DiagramProperties } from './LikeC4Diagram.props'
13
13
  import { EnsureMantine } from './mantine/EnsureMantine'
14
14
  import { DiagramContextProvider } from './state/DiagramContext'
15
- import { WhenInitialized } from './state/WhenInitialized'
15
+ import { useDiagramStoreApi } from './state/useDiagramStore'
16
16
  import { diagramViewToXYFlowData } from './xyflow/diagram-to-xyflow'
17
17
  import { FitViewOnDiagramChange } from './xyflow/FitviewOnDiagramChange'
18
18
  import { SelectEdgesOnNodeFocus } from './xyflow/SelectEdgesOnNodeFocus'
@@ -36,6 +36,7 @@ export function LikeC4Diagram({
36
36
  controls = false,
37
37
  showElementLinks = true,
38
38
  showDiagramTitle = true,
39
+ showNavigationButtons = false,
39
40
  enableDynamicViewWalkthrough = true,
40
41
  initialWidth,
41
42
  initialHeight,
@@ -113,6 +114,7 @@ export function LikeC4Diagram({
113
114
  controls={controls}
114
115
  pannable={pannable}
115
116
  showDiagramTitle={showDiagramTitle}
117
+ showNavigationButtons={showNavigationButtons}
116
118
  enableDynamicViewWalkthrough={enableDynamicViewWalkthrough}
117
119
  />
118
120
  </KeepAspectRatioContainer>
@@ -132,6 +134,7 @@ type LikeC4DiagramInnerProps = {
132
134
  defaultNodes: XYFlowNode[]
133
135
  defaultEdges: XYFlowEdge[]
134
136
  showDiagramTitle: boolean
137
+ showNavigationButtons: boolean
135
138
  enableDynamicViewWalkthrough: boolean
136
139
  }
137
140
  const LikeC4DiagramInnerMemo = memo<LikeC4DiagramInnerProps>(function LikeC4DiagramInner({
@@ -143,9 +146,26 @@ const LikeC4DiagramInnerMemo = memo<LikeC4DiagramInnerProps>(function LikeC4Diag
143
146
  defaultNodes,
144
147
  defaultEdges,
145
148
  showDiagramTitle,
149
+ showNavigationButtons,
146
150
  enableDynamicViewWalkthrough
147
151
  }) {
148
152
  DEV && useTilg()
153
+ const diagramApi = useDiagramStoreApi()
154
+ const [isInitialized, setIsInitialized] = useState(diagramApi.getState().initialized)
155
+
156
+ useEffect(() => {
157
+ if (isInitialized) {
158
+ return
159
+ }
160
+ return diagramApi.subscribe(
161
+ s => s.initialized,
162
+ setIsInitialized,
163
+ {
164
+ fireImmediately: true
165
+ }
166
+ )
167
+ }, [isInitialized])
168
+
149
169
  return (
150
170
  <>
151
171
  <XYFlow
@@ -160,17 +180,20 @@ const LikeC4DiagramInnerMemo = memo<LikeC4DiagramInnerProps>(function LikeC4Diag
160
180
  )}
161
181
  >
162
182
  <XYFlowInner
183
+ showNavigationButtons={showNavigationButtons}
163
184
  showDiagramTitle={showDiagramTitle}
164
185
  enableDynamicViewWalkthrough={enableDynamicViewWalkthrough}
165
186
  background={background}
166
187
  controls={controls}
167
188
  />
168
189
  </XYFlow>
169
- <WhenInitialized>
170
- <SyncWithDiagram />
171
- {fitView && <FitViewOnDiagramChange />}
172
- {fitView && zoomable && <SelectEdgesOnNodeFocus />}
173
- </WhenInitialized>
190
+ {isInitialized && (
191
+ <>
192
+ <SyncWithDiagram />
193
+ {fitView && <FitViewOnDiagramChange />}
194
+ {fitView && zoomable && <SelectEdgesOnNodeFocus />}
195
+ </>
196
+ )}
174
197
  </>
175
198
  )
176
199
  }, shallowEqual)
@@ -13,7 +13,7 @@ globalStyle(`.${rootClassName}`, {
13
13
  })
14
14
 
15
15
  createGlobalTheme(`.${rootClassName}`, {
16
- ...omit(vars, ['optionsPanel', 'default'])
16
+ ...omit(vars, ['optionsPanel', 'navigationPanel', 'safariAnimationHook', 'default'])
17
17
  }, {
18
18
  likec4: {
19
19
  font:
@@ -4,12 +4,12 @@ import { useUpdateEffect } from '../hooks'
4
4
  import { useXYFlow } from '../xyflow/hooks'
5
5
  import { createDiagramStore, type DiagramInitialState } from './diagramStore'
6
6
 
7
- type DiagramContextValue = ReturnType<typeof createDiagramStore>
8
- export const DiagramContext = createContext<DiagramContextValue | null>(null)
7
+ export type DiagramZustandStore = ReturnType<typeof createDiagramStore>
8
+ export const DiagramContext = createContext<DiagramZustandStore | null>(null)
9
9
 
10
10
  export function DiagramContextProvider({ children, view, ...props }: PropsWithChildren<DiagramInitialState>) {
11
11
  const xyflow = useXYFlow()
12
- const store = useRef<DiagramContextValue>()
12
+ const store = useRef<DiagramZustandStore>()
13
13
 
14
14
  if (!store.current) {
15
15
  store.current = createDiagramStore({
@@ -1,11 +1,11 @@
1
1
  import type { DiagramNode, DiagramView, Fqn, ViewID } from '@likec4/core'
2
- import { invariant, nonexhaustive, nonNullable, StepEdgeId } from '@likec4/core'
2
+ import { invariant, nonexhaustive, StepEdgeId } from '@likec4/core'
3
3
  import { getViewportForBounds, type XYPosition } from '@xyflow/react'
4
- import { getInternalNodesBounds, getNodeDimensions } from '@xyflow/system'
4
+ import { getNodeDimensions } from '@xyflow/system'
5
5
  import { DEV } from 'esm-env'
6
6
  import { deepEqual, shallowEqual } from 'fast-equals'
7
7
  import type { MouseEvent as ReactMouseEvent } from 'react'
8
- import { debounce, entries, mapToObj, reduce } from 'remeda'
8
+ import { entries, isEmpty, reduce } from 'remeda'
9
9
  import type { Exact, Except, RequiredKeysOf, Simplify } from 'type-fest'
10
10
  import { devtools, subscribeWithSelector } from 'zustand/middleware'
11
11
  import { shallow } from 'zustand/shallow'
@@ -30,7 +30,6 @@ export type DiagramStore = {
30
30
  experimentalEdgeEditing: boolean
31
31
 
32
32
  // Internal state
33
- viewSyncState: 'synced' | 'changed'
34
33
  viewSyncDebounceTimeout: number | null
35
34
 
36
35
  xyflow: XYFlowInstance
@@ -109,6 +108,8 @@ interface DiagramStoreActions {
109
108
 
110
109
  getElement(id: Fqn): DiagramNode | null
111
110
  triggerChangeElementStyle: (change: Changes.ChangeElementStyle) => void
111
+
112
+ cancelSaveManualLayout: () => void
112
113
  triggerSaveManualLayout: (xystore: XYStoreApi) => void
113
114
  triggerOnNavigateTo: (xynodeId: string, event: ReactMouseEvent) => void
114
115
  fitDiagram: (xyStore: XYStoreApi) => void
@@ -120,7 +121,6 @@ interface DiagramStoreActions {
120
121
  export type DiagramState = Simplify<DiagramStore & DiagramStoreActions>
121
122
 
122
123
  const DEFAULT_PROPS: Except<DiagramStore, RequiredKeysOf<DiagramInitialState> | 'xyflow'> = {
123
- viewSyncState: 'synced',
124
124
  viewSyncDebounceTimeout: null,
125
125
  initialized: false,
126
126
  xyflowSynced: false,
@@ -174,7 +174,6 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
174
174
  updateView: (nextView) => {
175
175
  let {
176
176
  viewSyncDebounceTimeout,
177
- viewSyncState,
178
177
  xyflow,
179
178
  dimmed,
180
179
  xyflowSynced,
@@ -189,22 +188,12 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
189
188
  hoveredNodeId
190
189
  } = get()
191
190
 
192
- if (viewSyncDebounceTimeout) {
191
+ if (viewSyncDebounceTimeout !== null) {
193
192
  clearTimeout(viewSyncDebounceTimeout)
194
193
  viewSyncDebounceTimeout = null
195
194
  }
196
195
 
197
196
  if (shallowEqual(current, nextView)) {
198
- if (!xyflowSynced || viewSyncState === 'changed') {
199
- set(
200
- {
201
- viewSyncState: 'synced',
202
- xyflowSynced: true
203
- },
204
- noReplace,
205
- 'updateView: xyflow synced'
206
- )
207
- }
208
197
  DEV && console.debug('store: skip updateView')
209
198
  return
210
199
  }
@@ -272,7 +261,6 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
272
261
 
273
262
  set(
274
263
  {
275
- viewSyncState: 'synced',
276
264
  viewSyncDebounceTimeout,
277
265
  view: nextView,
278
266
  activeDynamicViewStep,
@@ -324,25 +312,25 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
324
312
 
325
313
  setHoveredNode: (nodeId) => {
326
314
  if (nodeId !== get().hoveredNodeId) {
327
- set({ hoveredNodeId: nodeId }, noReplace, nodeId ? 'setHoveredNode' : 'unsetHoveredNode')
315
+ set({ hoveredNodeId: nodeId })
328
316
  }
329
317
  },
330
318
 
331
319
  setHoveredEdge: (edgeId) => {
332
320
  if (edgeId !== get().hoveredEdgeId) {
333
- set({ hoveredEdgeId: edgeId }, noReplace, edgeId ? 'setHoveredEdge' : 'unsetHoveredEdge')
321
+ set({ hoveredEdgeId: edgeId })
334
322
  }
335
323
  },
336
324
 
337
325
  setLastClickedNode: (nodeId) => {
338
326
  if (nodeId !== get().lastClickedNodeId) {
339
- set({ lastClickedNodeId: nodeId }, noReplace, nodeId ? 'setLastClickedNode' : 'unsetLastClickedNode')
327
+ set({ lastClickedNodeId: nodeId })
340
328
  }
341
329
  },
342
330
 
343
331
  setLastClickedEdge: (edgeId) => {
344
332
  if (edgeId !== get().lastClickedEdgeId) {
345
- set({ lastClickedEdgeId: edgeId }, noReplace, edgeId ? 'setLastClickedEdge' : 'unsetLastClickedEdge')
333
+ set({ lastClickedEdgeId: edgeId })
346
334
  }
347
335
  },
348
336
 
@@ -441,15 +429,20 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
441
429
  ...view,
442
430
  nodes
443
431
  })
444
- if (onChange) {
445
- set({ viewSyncState: 'changed' }, noReplace, 'change sync state')
446
- }
447
432
  }
448
433
  // Trigger change event, even if there are no changes with local state
449
434
  // but we maybe out of sync with the server
450
435
  onChange?.({ change })
451
436
  },
452
437
 
438
+ cancelSaveManualLayout: () => {
439
+ let { viewSyncDebounceTimeout } = get()
440
+ if (viewSyncDebounceTimeout !== null) {
441
+ clearTimeout(viewSyncDebounceTimeout)
442
+ set({ viewSyncDebounceTimeout: null })
443
+ }
444
+ },
445
+
453
446
  triggerSaveManualLayout: (xystore) => {
454
447
  let { viewSyncDebounceTimeout: debounced, onChange } = get()
455
448
  if (!onChange) {
@@ -462,6 +455,7 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
462
455
  debounced = setTimeout(() => {
463
456
  const { nodeLookup } = xystore.getState()
464
457
  const { xyflow, onChange } = get()
458
+ set({ viewSyncDebounceTimeout: null })
465
459
 
466
460
  const movedNodes = new StringSet()
467
461
  const nodes = reduce([...nodeLookup.values()], (acc, node) => {
@@ -490,6 +484,10 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
490
484
  }
491
485
  return acc
492
486
  }, {} as Changes.SaveManualLayout['edges'])
487
+ if (movedNodes.size === 0 && isEmpty(edges)) {
488
+ DEV && console.debug('ignore triggerSaveManualLayout, as no changes detected')
489
+ return
490
+ }
493
491
 
494
492
  const change: Changes.SaveManualLayout = {
495
493
  op: 'save-manual-layout',
@@ -500,16 +498,15 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
500
498
  if (DEV) {
501
499
  console.debug('triggerSaveManualLayout', change)
502
500
  }
503
- set({ viewSyncDebounceTimeout: null }, noReplace, 'clear debounce timeout')
501
+
504
502
  onChange?.({ change })
505
- }, 5000)
503
+ }, 2000)
506
504
  set(
507
505
  {
508
- viewSyncDebounceTimeout: debounced,
509
- viewSyncState: 'changed'
506
+ viewSyncDebounceTimeout: debounced
510
507
  },
511
508
  noReplace,
512
- 'change sync state'
509
+ 'debounce sync state'
513
510
  )
514
511
  },
515
512
 
@@ -1,4 +1,3 @@
1
1
  export { DiagramContextProvider } from './DiagramContext'
2
2
  export type * from './diagramStore'
3
3
  export * from './useDiagramStore'
4
- export { WhenInitialized } from './WhenInitialized'
@@ -1,14 +1,14 @@
1
1
  import { shallowEqual } from 'fast-equals'
2
- import { useContext, useMemo } from 'react'
2
+ import { useContext } from 'react'
3
3
  import { useStoreWithEqualityFn as useZustandStore } from 'zustand/traditional'
4
4
 
5
- import { DiagramContext } from './DiagramContext'
5
+ import { DiagramContext, type DiagramZustandStore } from './DiagramContext'
6
6
  import type { DiagramState } from './diagramStore'
7
7
 
8
8
  function useDiagramState<StateSlice = unknown>(
9
9
  selector: (state: DiagramState) => StateSlice,
10
10
  equalityFn?: (a: StateSlice, b: StateSlice) => boolean
11
- ) {
11
+ ): StateSlice {
12
12
  const store = useContext(DiagramContext)
13
13
 
14
14
  if (store === null) {
@@ -18,22 +18,15 @@ function useDiagramState<StateSlice = unknown>(
18
18
  return useZustandStore(store, selector, equalityFn ?? shallowEqual)
19
19
  }
20
20
 
21
- function useDiagramStoreApi() {
21
+ export type DiagramStoreApi = Readonly<Pick<DiagramZustandStore, 'getState' | 'setState' | 'subscribe'>>
22
+ function useDiagramStoreApi(): DiagramStoreApi {
22
23
  const store = useContext(DiagramContext)
23
24
 
24
25
  if (store === null) {
25
26
  throw new Error('useDiagramStoreApi could be used only inside DiagramContext')
26
27
  }
27
28
 
28
- return useMemo(
29
- () => ({
30
- getState: store.getState,
31
- setState: store.setState,
32
- subscribe: store.subscribe
33
- }),
34
- [store]
35
- )
29
+ return store
36
30
  }
37
- export type DiagramStoreApi = ReturnType<typeof useDiagramStoreApi>
38
31
 
39
32
  export { useDiagramState, useDiagramStoreApi }
@@ -0,0 +1,39 @@
1
+ import { useStateHistory } from '@mantine/hooks'
2
+ import { useMemo } from 'react'
3
+ import { useUpdateEffect } from '../hooks/useUpdateEffect'
4
+ import { useDiagramState, useDiagramStoreApi } from './useDiagramStore'
5
+
6
+ export function useNavigationHistory() {
7
+ const store = useDiagramStoreApi()
8
+ const viewId = useDiagramState(s => s.view.id)
9
+
10
+ const [historyViewId, historyOps, {
11
+ history,
12
+ current: historyIndex
13
+ }] = useStateHistory(viewId)
14
+
15
+ const hasBack = historyIndex > 0
16
+ const hasForward = historyIndex < history.length - 1
17
+
18
+ useUpdateEffect(() => {
19
+ if (viewId !== historyViewId) {
20
+ historyOps.set(viewId)
21
+ }
22
+ }, [viewId])
23
+
24
+ useUpdateEffect(() => {
25
+ if (viewId !== historyViewId) {
26
+ store.getState().onNavigateTo?.(historyViewId)
27
+ }
28
+ }, [historyViewId])
29
+
30
+ return useMemo(() => ({
31
+ hasBack,
32
+ hasForward,
33
+ ops: historyOps
34
+ }), [
35
+ hasBack,
36
+ hasForward,
37
+ historyOps
38
+ ])
39
+ }
package/src/theme.css.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createGlobalThemeContract } from '@vanilla-extract/css'
2
2
 
3
3
  export const vars = createGlobalThemeContract({
4
+ safariAnimationHook: 'safari-animation-hook',
4
5
  default: {
5
6
  font: 'default-font-family'
6
7
  },
@@ -32,6 +33,10 @@ export const vars = createGlobalThemeContract({
32
33
  optionsPanel: {
33
34
  top: 'options-panel-top',
34
35
  right: 'options-panel-right'
36
+ },
37
+ navigationPanel: {
38
+ top: 'navigation-panel-top',
39
+ left: 'navigation-panel-left'
35
40
  }
36
41
  }, (value) => `likec4-${value}`)
37
42
 
@@ -0,0 +1,22 @@
1
+ import { fallbackVar, globalStyle, style } from '@vanilla-extract/css'
2
+ import { mantine } from '../mantine.css'
3
+ import { vars } from '../theme.css'
4
+
5
+ export const panel = style({
6
+ top: fallbackVar(vars.navigationPanel.top, '1rem'),
7
+ left: fallbackVar(vars.navigationPanel.left, '1rem'),
8
+ margin: 0
9
+ })
10
+
11
+ globalStyle(`${panel} .mantine-ActionIcon-root`, {
12
+ vars: {
13
+ ['--ai-size']: 'var(--ai-size-md)'
14
+ },
15
+ '@media': {
16
+ [mantine.largerThan('md')]: {
17
+ vars: {
18
+ ['--ai-size']: 'var(--ai-size-lg)'
19
+ }
20
+ }
21
+ }
22
+ })
@@ -0,0 +1,59 @@
1
+ import { ActionIcon, Group } from '@mantine/core'
2
+ import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'
3
+ import clsx from 'clsx'
4
+ import { AnimatePresence, m } from 'framer-motion'
5
+ import { useNavigationHistory } from '../state/useNavigationHistory'
6
+ import * as css from './BackwardForwardPanel.css'
7
+
8
+ export function BackwardForwardPanel() {
9
+ const { hasBack, hasForward, ops } = useNavigationHistory()
10
+
11
+ return (
12
+ <Group
13
+ className={clsx(
14
+ 'react-flow__panel',
15
+ css.panel,
16
+ 'likec4-navigation-panel'
17
+ )}
18
+ gap={'xs'}>
19
+ <AnimatePresence>
20
+ {hasBack && (
21
+ <m.div
22
+ layout
23
+ initial={{ opacity: 0.05, transform: 'translateX(-10px)' }}
24
+ animate={{ opacity: 1, transform: 'translateX(0)' }}
25
+ exit={{
26
+ opacity: 0.05,
27
+ transform: 'translateX(-10px)'
28
+ }}
29
+ key={'back'}>
30
+ <ActionIcon
31
+ variant="light"
32
+ color="gray"
33
+ onClick={() => ops.back()}>
34
+ <IconChevronLeft />
35
+ </ActionIcon>
36
+ </m.div>
37
+ )}
38
+ {hasForward && (
39
+ <m.div
40
+ layout
41
+ initial={{ opacity: 0.05, transform: 'translateX(10px)' }}
42
+ animate={{ opacity: 1, transform: 'translateX(0)' }}
43
+ exit={{
44
+ opacity: 0,
45
+ transform: 'translateX(10px)'
46
+ }}
47
+ key={'forward'}>
48
+ <ActionIcon
49
+ variant="light"
50
+ color="gray"
51
+ onClick={() => ops.forward()}>
52
+ <IconChevronRight />
53
+ </ActionIcon>
54
+ </m.div>
55
+ )}
56
+ </AnimatePresence>
57
+ </Group>
58
+ )
59
+ }
@@ -1,5 +1,6 @@
1
- import { globalStyle, style } from '@vanilla-extract/css'
1
+ import { fallbackVar, globalStyle, style } from '@vanilla-extract/css'
2
2
  import { mantine } from '../mantine.css'
3
+ import { vars } from '../theme.css'
3
4
 
4
5
  export const container = style({
5
6
  bottom: 0,
@@ -8,17 +9,22 @@ export const container = style({
8
9
  margin: 0
9
10
  })
10
11
 
11
- export const paper = style({
12
+ export const card = style({
12
13
  cursor: 'default',
13
- minWidth: 100,
14
+ minWidth: 150,
14
15
  maxWidth: 'calc(100vw - 16px)',
15
16
  backgroundColor: `color-mix(in srgb, ${mantine.colors.body}, transparent 20%)`,
16
- WebkitBackdropFilter: 'blur(8px)',
17
- backdropFilter: 'blur(8px)',
17
+ WebkitBackdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
18
+ backdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
18
19
  '@media': {
19
20
  [mantine.largerThan('md')]: {
20
21
  maxWidth: '45vw'
21
22
  }
23
+ },
24
+ selectors: {
25
+ [`:where([data-mantine-color-scheme='dark']) &`]: {
26
+ backgroundColor: `color-mix(in srgb, ${mantine.colors.dark[6]}, transparent 20%)`
27
+ }
22
28
  }
23
29
  })
24
30