@eventcatalog/core 5.7.1 → 5.7.4
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/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-GRC67WHC.js → chunk-GOIDVIMH.js} +1 -1
- package/dist/{chunk-HZ3XZKUT.js → chunk-L2PFSX4L.js} +1 -1
- package/dist/{chunk-36XVRD36.js → chunk-PLTHZFTW.js} +1 -1
- package/dist/{chunk-CPF5WE3R.js → chunk-PXYVJK54.js} +1 -1
- package/dist/{chunk-AXWTR2FV.js → chunk-RUG7AIT5.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/01-what-is-eventcatalog-assistant.md +8 -0
- package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/02-configuration.md +24 -0
- package/dist/docs/development/studio/01-introduction.md +2 -1
- package/dist/docs/development/studio/04-collaborate-on-a-canvas.md +10 -2
- package/dist/docs/development/studio/05-connect-your-agent.md +4 -0
- package/dist/docs/development/studio/07-reference.md +40 -7
- package/dist/docs/development/studio/draw-with-ai.md +96 -0
- package/dist/eventcatalog.cjs +1 -1
- package/dist/eventcatalog.js +5 -5
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +113 -8
- package/eventcatalog/src/components/ChatPanel/panel-width.ts +28 -0
- package/eventcatalog/src/components/MDX/Steps/Step.astro +4 -2
- package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +2 -103
- package/eventcatalog/src/components/SchemaExplorer/diff-dark-styles.ts +104 -0
- package/eventcatalog/src/features/mcp/apps/generated/canvas.html +71 -71
- package/eventcatalog/src/features/mcp/apps/generated/viewer.html +1 -1
- package/eventcatalog/src/features/studio/components/StudioDesigner.tsx +25 -3
- package/eventcatalog/src/features/studio/hooks/use-canvas-webmcp.ts +1 -1
- package/eventcatalog/src/features/studio/server/canvas-mcp.ts +1 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_ChangelogPage.astro +297 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.spec.ts +101 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +76 -47
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +4 -168
- package/eventcatalog/src/pages/docs/services/[id]/[version]/changelog/index.astro +14 -0
- package/eventcatalog/src/pages/docs/services/[id]/changelog/index.astro +3 -3
- package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +112 -28
- package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +24 -10
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useRef, useCallback, useState, useMemo, memo } from 'react';
|
|
1
|
+
import { useEffect, useRef, useCallback, useState, useMemo, memo, type RefObject } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
X,
|
|
4
4
|
Square,
|
|
@@ -28,6 +28,7 @@ import * as Dialog from '@radix-ui/react-dialog';
|
|
|
28
28
|
import * as Popover from '@radix-ui/react-popover';
|
|
29
29
|
import { buildUrl } from '@utils/url-builder';
|
|
30
30
|
import OfflineReply, { ConfigurationErrorReply, getChatError, offlineReplyText } from './OfflineReply';
|
|
31
|
+
import { clampPanelWidth, MAX_PANEL_WIDTH, MIN_PANEL_WIDTH, PANEL_WIDTH, readPanelWidth, savePanelWidth } from './panel-width';
|
|
31
32
|
import {
|
|
32
33
|
ASSISTANT_DRAWING_EVENT,
|
|
33
34
|
CANVAS_FOCUS_EVENT,
|
|
@@ -487,7 +488,15 @@ interface ChatPanelProps {
|
|
|
487
488
|
onClose: () => void;
|
|
488
489
|
}
|
|
489
490
|
|
|
490
|
-
|
|
491
|
+
/** The window's width without its scrollbar, which the panel (fixed, on the right) sits inside of (or the window's, where
|
|
492
|
+
* that isn't known) */
|
|
493
|
+
const viewportWidth = () => document.documentElement.clientWidth || window.innerWidth;
|
|
494
|
+
|
|
495
|
+
/** What the panel pushes over to make room for it (looked up each time: ClientRouter navigations swap in new pages) */
|
|
496
|
+
const pageBesidePanel = () =>
|
|
497
|
+
[document.getElementById('eventcatalog-application'), document.getElementById('eventcatalog-header')].filter(
|
|
498
|
+
Boolean
|
|
499
|
+
) as HTMLElement[];
|
|
491
500
|
|
|
492
501
|
// Staggered fade-in animation styles (delays account for 420ms panel slide)
|
|
493
502
|
const fadeInStyles = {
|
|
@@ -793,6 +802,84 @@ const FlaggedHotspots = memo(({ hotspots }: { hotspots: FlaggedHotspot[] }) => (
|
|
|
793
802
|
));
|
|
794
803
|
FlaggedHotspots.displayName = 'FlaggedHotspots';
|
|
795
804
|
|
|
805
|
+
/** The panel's left edge: dragged to make it wider or narrower (or with the arrow keys), double-clicked back to the default */
|
|
806
|
+
const PanelResizeHandle = memo(
|
|
807
|
+
({ panel, width, onResize }: { panel: RefObject<HTMLDivElement | null>; width: number; onResize: (width: number) => void }) => {
|
|
808
|
+
// Pressed, and whether it's moved since (a click, or each click of a double click, changes nothing)
|
|
809
|
+
const dragging = useRef<{ moved: boolean } | null>(null);
|
|
810
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
811
|
+
const widthAt = (clientX: number) => clampPanelWidth(viewportWidth() - clientX, viewportWidth());
|
|
812
|
+
// While dragging, the panel and the page beside it are sized here, outside React, so the messages don't re-render
|
|
813
|
+
// on every move (and the page follows the pointer, without its slide)
|
|
814
|
+
const show = (next: number) => {
|
|
815
|
+
if (panel.current) panel.current.style.width = `min(${next}px, 100vw)`;
|
|
816
|
+
pageBesidePanel().forEach((el) => (el.style.paddingRight = `${next}px`));
|
|
817
|
+
};
|
|
818
|
+
const stop = (next: number) => {
|
|
819
|
+
const moved = dragging.current?.moved;
|
|
820
|
+
dragging.current = null;
|
|
821
|
+
setIsDragging(false);
|
|
822
|
+
show(moved ? next : width);
|
|
823
|
+
pageBesidePanel().forEach((el) => (el.style.transition = ''));
|
|
824
|
+
if (moved) onResize(next);
|
|
825
|
+
};
|
|
826
|
+
return (
|
|
827
|
+
<div
|
|
828
|
+
role="separator"
|
|
829
|
+
aria-orientation="vertical"
|
|
830
|
+
aria-label="Resize the assistant"
|
|
831
|
+
aria-valuemin={MIN_PANEL_WIDTH}
|
|
832
|
+
aria-valuemax={MAX_PANEL_WIDTH}
|
|
833
|
+
aria-valuenow={width}
|
|
834
|
+
tabIndex={0}
|
|
835
|
+
title="Drag to resize"
|
|
836
|
+
onPointerDown={(event) => {
|
|
837
|
+
if (event.button !== 0) return;
|
|
838
|
+
event.preventDefault();
|
|
839
|
+
// Keeps pointer events coming while the pointer is over the page (throws if the pointer has gone)
|
|
840
|
+
try {
|
|
841
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
842
|
+
} catch {}
|
|
843
|
+
dragging.current = { moved: false };
|
|
844
|
+
setIsDragging(true);
|
|
845
|
+
pageBesidePanel().forEach((el) => (el.style.transition = 'none'));
|
|
846
|
+
}}
|
|
847
|
+
onPointerMove={(event) => {
|
|
848
|
+
if (!dragging.current) return;
|
|
849
|
+
dragging.current.moved = true;
|
|
850
|
+
show(widthAt(event.clientX));
|
|
851
|
+
}}
|
|
852
|
+
onPointerUp={(event) => dragging.current && stop(widthAt(event.clientX))}
|
|
853
|
+
onPointerCancel={() => {
|
|
854
|
+
if (!dragging.current) return;
|
|
855
|
+
// Put back as it was
|
|
856
|
+
dragging.current.moved = false;
|
|
857
|
+
stop(width);
|
|
858
|
+
}}
|
|
859
|
+
onDoubleClick={() => onResize(PANEL_WIDTH)}
|
|
860
|
+
onKeyDown={(event) => {
|
|
861
|
+
const step = event.shiftKey ? 64 : 16;
|
|
862
|
+
if (event.key === 'ArrowLeft') onResize(clampPanelWidth(width + step, viewportWidth()));
|
|
863
|
+
else if (event.key === 'ArrowRight') onResize(clampPanelWidth(width - step, viewportWidth()));
|
|
864
|
+
else return;
|
|
865
|
+
event.preventDefault();
|
|
866
|
+
}}
|
|
867
|
+
className="group absolute inset-y-0 left-0 z-10 hidden w-1.5 cursor-col-resize outline-hidden lg:block"
|
|
868
|
+
>
|
|
869
|
+
<span
|
|
870
|
+
aria-hidden="true"
|
|
871
|
+
className={`absolute inset-y-0 left-0 w-0.5 transition-colors ${
|
|
872
|
+
isDragging
|
|
873
|
+
? 'bg-[rgb(var(--ec-accent))]'
|
|
874
|
+
: 'group-hover:bg-[rgb(var(--ec-accent)/0.6)] group-focus-visible:bg-[rgb(var(--ec-accent))]'
|
|
875
|
+
}`}
|
|
876
|
+
/>
|
|
877
|
+
</div>
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
);
|
|
881
|
+
PanelResizeHandle.displayName = 'PanelResizeHandle';
|
|
882
|
+
|
|
796
883
|
const markdownComponents = {
|
|
797
884
|
a: ({ node: _node, ...props }: any) => {
|
|
798
885
|
const nodeIds = nodesInFocusLink(props.href);
|
|
@@ -989,6 +1076,24 @@ const ChatPanel = ({ isOpen, onClose, configured = false }: ChatPanelProps) => {
|
|
|
989
1076
|
const [isWaitingForResponse, setIsWaitingForResponse] = useState(false);
|
|
990
1077
|
const [pathname, setPathname] = useState('');
|
|
991
1078
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
1079
|
+
// How wide they made the panel: the default until the width they left it at is read, after hydrating (within the
|
|
1080
|
+
// panel's own limits: the window's are applied as it's shown, so it's back to that width when the window's wide again)
|
|
1081
|
+
const panelRef = useRef<HTMLDivElement | null>(null);
|
|
1082
|
+
const [panelWidth, setPanelWidth] = useState(PANEL_WIDTH);
|
|
1083
|
+
useEffect(() => setPanelWidth(readPanelWidth(Infinity)), []);
|
|
1084
|
+
// How wide it's shown: that, leaving room for the page in this window (checked again as the window's resized; it only
|
|
1085
|
+
// re-renders when this changes)
|
|
1086
|
+
const [shownWidth, setShownWidth] = useState(PANEL_WIDTH);
|
|
1087
|
+
useEffect(() => {
|
|
1088
|
+
const fit = () => setShownWidth(clampPanelWidth(panelWidth, viewportWidth()));
|
|
1089
|
+
fit();
|
|
1090
|
+
window.addEventListener('resize', fit);
|
|
1091
|
+
return () => window.removeEventListener('resize', fit);
|
|
1092
|
+
}, [panelWidth]);
|
|
1093
|
+
const resizePanel = useCallback((width: number) => {
|
|
1094
|
+
setPanelWidth(width);
|
|
1095
|
+
savePanelWidth(width);
|
|
1096
|
+
}, []);
|
|
992
1097
|
const [tools, setTools] = useState<ToolMetadata[]>([]);
|
|
993
1098
|
const [showScrollButton, setShowScrollButton] = useState(false);
|
|
994
1099
|
const chatApiUrl = useMemo(() => buildUrl('/api/chat', true), []);
|
|
@@ -1186,9 +1291,7 @@ const ChatPanel = ({ isOpen, onClose, configured = false }: ChatPanelProps) => {
|
|
|
1186
1291
|
// Looked up each time: the panel stays open across ClientRouter navigations (the header persists), but each one
|
|
1187
1292
|
// swaps in a new page that needs pushing over too
|
|
1188
1293
|
const getElements = () => ({
|
|
1189
|
-
elements:
|
|
1190
|
-
Boolean
|
|
1191
|
-
) as HTMLElement[],
|
|
1294
|
+
elements: pageBesidePanel(),
|
|
1192
1295
|
docsSidebarEl: document.getElementById('eventcatalog-docs-sidebar'),
|
|
1193
1296
|
});
|
|
1194
1297
|
|
|
@@ -1200,7 +1303,7 @@ const ChatPanel = ({ isOpen, onClose, configured = false }: ChatPanelProps) => {
|
|
|
1200
1303
|
if (!el.style.transition) {
|
|
1201
1304
|
el.style.transition = 'padding-right 420ms cubic-bezier(0.16, 1, 0.3, 1)';
|
|
1202
1305
|
}
|
|
1203
|
-
el.style.paddingRight = pushContent ? `${
|
|
1306
|
+
el.style.paddingRight = pushContent ? `${shownWidth}px` : '0';
|
|
1204
1307
|
});
|
|
1205
1308
|
if (docsSidebarEl) docsSidebarEl.style.display = pushContent ? 'none' : '';
|
|
1206
1309
|
};
|
|
@@ -1221,7 +1324,7 @@ const ChatPanel = ({ isOpen, onClose, configured = false }: ChatPanelProps) => {
|
|
|
1221
1324
|
docsSidebarEl.style.display = '';
|
|
1222
1325
|
}
|
|
1223
1326
|
};
|
|
1224
|
-
}, [isOpen, isFullscreen]);
|
|
1327
|
+
}, [isOpen, isFullscreen, shownWidth]);
|
|
1225
1328
|
|
|
1226
1329
|
// Submit message handler
|
|
1227
1330
|
const submitMessage = useCallback(
|
|
@@ -1342,12 +1445,13 @@ const ChatPanel = ({ isOpen, onClose, configured = false }: ChatPanelProps) => {
|
|
|
1342
1445
|
{!isFullscreen && (
|
|
1343
1446
|
<div
|
|
1344
1447
|
ref={(element) => {
|
|
1448
|
+
panelRef.current = element;
|
|
1345
1449
|
element?.toggleAttribute('inert', !isOpen);
|
|
1346
1450
|
}}
|
|
1347
1451
|
aria-hidden={!isOpen}
|
|
1348
1452
|
className="ec-chat-surface fixed top-0 right-0 h-[100dvh] z-[200] border-l border-[rgb(var(--ec-page-border))] flex flex-col overflow-hidden"
|
|
1349
1453
|
style={{
|
|
1350
|
-
width: `min(${
|
|
1454
|
+
width: `min(${shownWidth}px, 100vw)`,
|
|
1351
1455
|
transform: isOpen ? 'translateX(0)' : 'translateX(100%)',
|
|
1352
1456
|
transition: 'transform 420ms cubic-bezier(0.16, 1, 0.3, 1)',
|
|
1353
1457
|
background: `
|
|
@@ -1356,6 +1460,7 @@ const ChatPanel = ({ isOpen, onClose, configured = false }: ChatPanelProps) => {
|
|
|
1356
1460
|
`,
|
|
1357
1461
|
}}
|
|
1358
1462
|
>
|
|
1463
|
+
<PanelResizeHandle panel={panelRef} width={shownWidth} onResize={resizePanel} />
|
|
1359
1464
|
{/* Header */}
|
|
1360
1465
|
<div className="flex-none shrink-0 border-b border-[rgb(var(--ec-page-border))]">
|
|
1361
1466
|
<div className="flex items-center justify-between px-4 py-3">
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** How wide the assistant's panel is: dragged wider (or back) by its left edge, and remembered in this browser */
|
|
2
|
+
export const PANEL_WIDTH = 400;
|
|
3
|
+
export const MIN_PANEL_WIDTH = 360;
|
|
4
|
+
export const MAX_PANEL_WIDTH = 800;
|
|
5
|
+
// How much of the page stays beside it, at least
|
|
6
|
+
const MIN_PAGE_WIDTH = 480;
|
|
7
|
+
const STORAGE_KEY = 'eventcatalog-chat-panel-width';
|
|
8
|
+
|
|
9
|
+
/** Within the panel's limits, leaving room for the page in a window this wide */
|
|
10
|
+
export const clampPanelWidth = (width: number, viewportWidth: number) =>
|
|
11
|
+
Math.round(Math.max(MIN_PANEL_WIDTH, Math.min(width, MAX_PANEL_WIDTH, viewportWidth - MIN_PAGE_WIDTH)));
|
|
12
|
+
|
|
13
|
+
/** The width they left it at, or the default */
|
|
14
|
+
export const readPanelWidth = (viewportWidth: number) => {
|
|
15
|
+
try {
|
|
16
|
+
const saved = Number(localStorage.getItem(STORAGE_KEY));
|
|
17
|
+
return saved ? clampPanelWidth(saved, viewportWidth) : PANEL_WIDTH;
|
|
18
|
+
} catch {
|
|
19
|
+
return PANEL_WIDTH;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const savePanelWidth = (width: number) => {
|
|
24
|
+
try {
|
|
25
|
+
if (width === PANEL_WIDTH) localStorage.removeItem(STORAGE_KEY);
|
|
26
|
+
else localStorage.setItem(STORAGE_KEY, String(width));
|
|
27
|
+
} catch {}
|
|
28
|
+
};
|
|
@@ -4,7 +4,9 @@ const { title } = Astro.props;
|
|
|
4
4
|
|
|
5
5
|
<li class="mb-8 ml-6 w-full xl:max-w-[90%] step">
|
|
6
6
|
<div class="flex items-center mb-4">
|
|
7
|
-
<span
|
|
7
|
+
<span
|
|
8
|
+
class="step-number absolute flex items-center justify-center w-6 h-6 rounded-md -left-3 text-xs font-semibold bg-[rgb(var(--ec-accent-subtle))] text-[rgb(var(--ec-accent))] ring-4 ring-[rgb(var(--ec-page-bg))]"
|
|
9
|
+
>
|
|
8
10
|
<div></div>
|
|
9
11
|
</span>
|
|
10
12
|
<h3 class="font-semibold text-lg ml-0">{title}</h3>
|
|
@@ -29,7 +31,7 @@ const { title } = Astro.props;
|
|
|
29
31
|
color: rgb(var(--ec-page-text-muted));
|
|
30
32
|
text-decoration: underline;
|
|
31
33
|
&:hover {
|
|
32
|
-
color:
|
|
34
|
+
color: rgb(var(--ec-accent));
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
</style>
|
|
@@ -1,110 +1,9 @@
|
|
|
1
1
|
import { ArrowsPointingOutIcon } from '@heroicons/react/24/outline';
|
|
2
2
|
import type { VersionDiff } from './types';
|
|
3
3
|
import { useDarkMode } from './useDarkMode';
|
|
4
|
+
import { getDiffDarkStyles } from './diff-dark-styles';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
const DIFF_DARK_STYLES = `
|
|
7
|
-
.diff-dark-mode .d2h-wrapper {
|
|
8
|
-
color: #e5e7eb;
|
|
9
|
-
}
|
|
10
|
-
.diff-dark-mode .d2h-file-header {
|
|
11
|
-
background-color: rgba(255,255,255,0.05);
|
|
12
|
-
border-bottom-color: rgba(255,255,255,0.1);
|
|
13
|
-
}
|
|
14
|
-
.diff-dark-mode .d2h-file-header .d2h-file-name {
|
|
15
|
-
color: #e5e7eb;
|
|
16
|
-
}
|
|
17
|
-
.diff-dark-mode .d2h-diff-table {
|
|
18
|
-
border-color: rgba(255,255,255,0.1);
|
|
19
|
-
}
|
|
20
|
-
.diff-dark-mode .d2h-code-side-linenumber,
|
|
21
|
-
.diff-dark-mode .d2h-code-linenumber {
|
|
22
|
-
background-color: rgba(255,255,255,0.03);
|
|
23
|
-
border-color: rgba(255,255,255,0.08);
|
|
24
|
-
color: #6b7280;
|
|
25
|
-
}
|
|
26
|
-
.diff-dark-mode .d2h-code-line,
|
|
27
|
-
.diff-dark-mode .d2h-code-side-line {
|
|
28
|
-
background-color: transparent;
|
|
29
|
-
border-color: rgba(255,255,255,0.06);
|
|
30
|
-
color: #d1d5db;
|
|
31
|
-
}
|
|
32
|
-
.diff-dark-mode .d2h-code-line-ctn {
|
|
33
|
-
color: #d1d5db;
|
|
34
|
-
}
|
|
35
|
-
/* Deletion lines */
|
|
36
|
-
.diff-dark-mode .d2h-del {
|
|
37
|
-
background-color: rgba(239,68,68,0.1);
|
|
38
|
-
border-color: rgba(239,68,68,0.15);
|
|
39
|
-
}
|
|
40
|
-
.diff-dark-mode .d2h-del .d2h-code-side-linenumber,
|
|
41
|
-
.diff-dark-mode .d2h-del .d2h-code-linenumber {
|
|
42
|
-
background-color: rgba(239,68,68,0.15);
|
|
43
|
-
border-color: rgba(239,68,68,0.15);
|
|
44
|
-
color: #f87171;
|
|
45
|
-
}
|
|
46
|
-
.diff-dark-mode .d2h-del .d2h-code-line-ctn {
|
|
47
|
-
color: #fca5a5;
|
|
48
|
-
}
|
|
49
|
-
.diff-dark-mode del {
|
|
50
|
-
background-color: rgba(239,68,68,0.25);
|
|
51
|
-
color: #fca5a5;
|
|
52
|
-
text-decoration: none;
|
|
53
|
-
}
|
|
54
|
-
/* Addition lines */
|
|
55
|
-
.diff-dark-mode .d2h-ins {
|
|
56
|
-
background-color: rgba(34,197,94,0.1);
|
|
57
|
-
border-color: rgba(34,197,94,0.15);
|
|
58
|
-
}
|
|
59
|
-
.diff-dark-mode .d2h-ins .d2h-code-side-linenumber,
|
|
60
|
-
.diff-dark-mode .d2h-ins .d2h-code-linenumber {
|
|
61
|
-
background-color: rgba(34,197,94,0.15);
|
|
62
|
-
border-color: rgba(34,197,94,0.15);
|
|
63
|
-
color: #4ade80;
|
|
64
|
-
}
|
|
65
|
-
.diff-dark-mode .d2h-ins .d2h-code-line-ctn {
|
|
66
|
-
color: #bbf7d0;
|
|
67
|
-
}
|
|
68
|
-
.diff-dark-mode ins {
|
|
69
|
-
background-color: rgba(34,197,94,0.25);
|
|
70
|
-
color: #bbf7d0;
|
|
71
|
-
text-decoration: none;
|
|
72
|
-
}
|
|
73
|
-
/* Info/context header */
|
|
74
|
-
.diff-dark-mode .d2h-info {
|
|
75
|
-
background-color: rgba(59,130,246,0.08);
|
|
76
|
-
border-color: rgba(59,130,246,0.15);
|
|
77
|
-
color: #93c5fd;
|
|
78
|
-
}
|
|
79
|
-
/* File diff border */
|
|
80
|
-
.diff-dark-mode .d2h-file-diff {
|
|
81
|
-
border-color: rgba(255,255,255,0.1);
|
|
82
|
-
}
|
|
83
|
-
.diff-dark-mode .d2h-file-side-diff {
|
|
84
|
-
border-color: rgba(255,255,255,0.1);
|
|
85
|
-
}
|
|
86
|
-
/* Tag styles */
|
|
87
|
-
.diff-dark-mode .d2h-tag {
|
|
88
|
-
background-color: rgba(59,130,246,0.15);
|
|
89
|
-
border-color: rgba(59,130,246,0.3);
|
|
90
|
-
color: #93c5fd;
|
|
91
|
-
}
|
|
92
|
-
/* Empty placeholder lines */
|
|
93
|
-
.diff-dark-mode .d2h-code-side-emptyplaceholder,
|
|
94
|
-
.diff-dark-mode .d2h-emptyplaceholder {
|
|
95
|
-
background-color: rgba(255,255,255,0.02);
|
|
96
|
-
border-color: rgba(255,255,255,0.06);
|
|
97
|
-
}
|
|
98
|
-
/* File wrapper border */
|
|
99
|
-
.diff-dark-mode .d2h-file-wrapper {
|
|
100
|
-
border-color: rgba(255,255,255,0.1);
|
|
101
|
-
border-radius: 0.5rem;
|
|
102
|
-
overflow: hidden;
|
|
103
|
-
}
|
|
104
|
-
.diff-dark-mode .d2h-files-diff {
|
|
105
|
-
border-color: rgba(255,255,255,0.1);
|
|
106
|
-
}
|
|
107
|
-
`;
|
|
6
|
+
const DIFF_DARK_STYLES = getDiffDarkStyles('.diff-dark-mode');
|
|
108
7
|
|
|
109
8
|
interface DiffViewerProps {
|
|
110
9
|
diffs: VersionDiff[];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Dark mode overrides for diff2html, scoped under the given selector.
|
|
2
|
+
// Shared by the Schema Explorer diff viewer and the changelog page.
|
|
3
|
+
export const getDiffDarkStyles = (scope: string) => `
|
|
4
|
+
${scope} .d2h-wrapper {
|
|
5
|
+
color: #e5e7eb;
|
|
6
|
+
}
|
|
7
|
+
${scope} .d2h-file-header {
|
|
8
|
+
background-color: rgba(255,255,255,0.05);
|
|
9
|
+
border-bottom-color: rgba(255,255,255,0.1);
|
|
10
|
+
}
|
|
11
|
+
${scope} .d2h-file-header .d2h-file-name {
|
|
12
|
+
color: #e5e7eb;
|
|
13
|
+
}
|
|
14
|
+
${scope} .d2h-diff-table {
|
|
15
|
+
border-color: rgba(255,255,255,0.1);
|
|
16
|
+
}
|
|
17
|
+
${scope} .d2h-code-side-linenumber,
|
|
18
|
+
${scope} .d2h-code-linenumber {
|
|
19
|
+
background-color: rgba(255,255,255,0.03);
|
|
20
|
+
border-color: rgba(255,255,255,0.08);
|
|
21
|
+
color: #6b7280;
|
|
22
|
+
}
|
|
23
|
+
${scope} .d2h-code-line,
|
|
24
|
+
${scope} .d2h-code-side-line {
|
|
25
|
+
background-color: transparent;
|
|
26
|
+
border-color: rgba(255,255,255,0.06);
|
|
27
|
+
color: #d1d5db;
|
|
28
|
+
}
|
|
29
|
+
${scope} .d2h-code-line-ctn {
|
|
30
|
+
color: #d1d5db;
|
|
31
|
+
}
|
|
32
|
+
/* Deletion lines */
|
|
33
|
+
${scope} .d2h-del {
|
|
34
|
+
background-color: rgba(239,68,68,0.1);
|
|
35
|
+
border-color: rgba(239,68,68,0.15);
|
|
36
|
+
}
|
|
37
|
+
${scope} .d2h-del .d2h-code-side-linenumber,
|
|
38
|
+
${scope} .d2h-del .d2h-code-linenumber {
|
|
39
|
+
background-color: rgba(239,68,68,0.15);
|
|
40
|
+
border-color: rgba(239,68,68,0.15);
|
|
41
|
+
color: #f87171;
|
|
42
|
+
}
|
|
43
|
+
${scope} .d2h-del .d2h-code-line-ctn {
|
|
44
|
+
color: #fca5a5;
|
|
45
|
+
}
|
|
46
|
+
${scope} del {
|
|
47
|
+
background-color: rgba(239,68,68,0.25);
|
|
48
|
+
color: #fca5a5;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
}
|
|
51
|
+
/* Addition lines */
|
|
52
|
+
${scope} .d2h-ins {
|
|
53
|
+
background-color: rgba(34,197,94,0.1);
|
|
54
|
+
border-color: rgba(34,197,94,0.15);
|
|
55
|
+
}
|
|
56
|
+
${scope} .d2h-ins .d2h-code-side-linenumber,
|
|
57
|
+
${scope} .d2h-ins .d2h-code-linenumber {
|
|
58
|
+
background-color: rgba(34,197,94,0.15);
|
|
59
|
+
border-color: rgba(34,197,94,0.15);
|
|
60
|
+
color: #4ade80;
|
|
61
|
+
}
|
|
62
|
+
${scope} .d2h-ins .d2h-code-line-ctn {
|
|
63
|
+
color: #bbf7d0;
|
|
64
|
+
}
|
|
65
|
+
${scope} ins {
|
|
66
|
+
background-color: rgba(34,197,94,0.25);
|
|
67
|
+
color: #bbf7d0;
|
|
68
|
+
text-decoration: none;
|
|
69
|
+
}
|
|
70
|
+
/* Info/context header */
|
|
71
|
+
${scope} .d2h-info {
|
|
72
|
+
background-color: rgba(59,130,246,0.08);
|
|
73
|
+
border-color: rgba(59,130,246,0.15);
|
|
74
|
+
color: #93c5fd;
|
|
75
|
+
}
|
|
76
|
+
/* File diff border */
|
|
77
|
+
${scope} .d2h-file-diff {
|
|
78
|
+
border-color: rgba(255,255,255,0.1);
|
|
79
|
+
}
|
|
80
|
+
${scope} .d2h-file-side-diff {
|
|
81
|
+
border-color: rgba(255,255,255,0.1);
|
|
82
|
+
}
|
|
83
|
+
/* Tag styles */
|
|
84
|
+
${scope} .d2h-tag {
|
|
85
|
+
background-color: rgba(59,130,246,0.15);
|
|
86
|
+
border-color: rgba(59,130,246,0.3);
|
|
87
|
+
color: #93c5fd;
|
|
88
|
+
}
|
|
89
|
+
/* Empty placeholder lines */
|
|
90
|
+
${scope} .d2h-code-side-emptyplaceholder,
|
|
91
|
+
${scope} .d2h-emptyplaceholder {
|
|
92
|
+
background-color: rgba(255,255,255,0.02);
|
|
93
|
+
border-color: rgba(255,255,255,0.06);
|
|
94
|
+
}
|
|
95
|
+
/* File wrapper border */
|
|
96
|
+
${scope} .d2h-file-wrapper {
|
|
97
|
+
border-color: rgba(255,255,255,0.1);
|
|
98
|
+
border-radius: 0.5rem;
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
}
|
|
101
|
+
${scope} .d2h-files-diff {
|
|
102
|
+
border-color: rgba(255,255,255,0.1);
|
|
103
|
+
}
|
|
104
|
+
`;
|