likec4 1.48.0 → 1.50.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 (118) hide show
  1. package/README.md +11 -1
  2. package/__app__/src/likec4.js +5941 -4496
  3. package/__app__/src/routes/index.js +3 -153
  4. package/__app__/src/routes/projects.js +21 -1087
  5. package/__app__/src/routes/single.js +1228 -16
  6. package/__app__/src/style.css +1 -1
  7. package/__app__/src/vendors.js +4649 -1897
  8. package/__app__/src/webcomponent.js +1 -1
  9. package/config/schema.json +169 -141
  10. package/dist/THIRD-PARTY-LICENSES.md +1769 -0
  11. package/dist/_chunks/LikeC4.mjs +1154 -202
  12. package/dist/_chunks/binary.mjs +72 -0
  13. package/dist/_chunks/index.d.mts +234 -140
  14. package/dist/_chunks/index2.d.mts +2043 -1828
  15. package/dist/_chunks/libs/@chevrotain/cst-dts-gen.mjs +30 -0
  16. package/dist/_chunks/libs/@chevrotain/regexp-to-ast.mjs +9 -785
  17. package/dist/_chunks/libs/@chevrotain/utils.mjs +1 -37
  18. package/dist/_chunks/libs/@hono/mcp.mjs +34 -0
  19. package/dist/_chunks/libs/@hono/node-server.mjs +1 -436
  20. package/dist/_chunks/libs/@logtape/logtape.d.mts +741 -0
  21. package/dist/_chunks/libs/@logtape/logtape.mjs +6 -1354
  22. package/dist/_chunks/libs/@lume/kiwi.mjs +1 -1355
  23. package/dist/_chunks/libs/@modelcontextprotocol/sdk.d.mts +114 -14
  24. package/dist/_chunks/libs/@modelcontextprotocol/sdk.mjs +12 -25105
  25. package/dist/_chunks/libs/@msgpack/msgpack.mjs +1 -1503
  26. package/dist/_chunks/libs/@nanostores/react.d.mts +61 -1
  27. package/dist/_chunks/libs/@nanostores/react.mjs +1 -30
  28. package/dist/_chunks/libs/@smithy/is-array-buffer.mjs +1 -10
  29. package/dist/_chunks/libs/@smithy/util-base64.mjs +1 -100
  30. package/dist/_chunks/libs/ajv.mjs +1 -777
  31. package/dist/_chunks/libs/atomically.mjs +1 -362
  32. package/dist/_chunks/libs/birpc.mjs +1 -201
  33. package/dist/_chunks/libs/chevrotain-allstar.mjs +2 -850
  34. package/dist/_chunks/libs/chevrotain.mjs +55 -6229
  35. package/dist/_chunks/libs/conf.mjs +1 -2258
  36. package/dist/_chunks/libs/defu.mjs +1 -42
  37. package/dist/_chunks/libs/esm-env.mjs +1 -5
  38. package/dist/_chunks/libs/eventemitter3.mjs +1 -243
  39. package/dist/_chunks/libs/fast-equals.mjs +1 -446
  40. package/dist/_chunks/libs/find-up-simple.mjs +1 -24
  41. package/dist/_chunks/libs/get-port.mjs +1 -107
  42. package/dist/_chunks/libs/is-docker.mjs +1 -26
  43. package/dist/_chunks/libs/is-error-instance.mjs +1 -26
  44. package/dist/_chunks/libs/is-inside-container.mjs +1 -20
  45. package/dist/_chunks/libs/is-plain-obj.mjs +1 -9
  46. package/dist/_chunks/libs/isexe.mjs +1 -127
  47. package/dist/_chunks/libs/json5.mjs +14 -959
  48. package/dist/_chunks/libs/khroma.mjs +1 -605
  49. package/dist/_chunks/libs/ky.mjs +2 -807
  50. package/dist/_chunks/libs/langium.d.mts +2913 -2876
  51. package/dist/_chunks/libs/langium.mjs +33 -20351
  52. package/dist/_chunks/libs/merge-error-cause.mjs +2 -746
  53. package/dist/_chunks/libs/p-limit.mjs +1 -120
  54. package/dist/_chunks/libs/p-queue.mjs +1 -449
  55. package/dist/_chunks/libs/package-manager-detector.mjs +1 -559
  56. package/dist/_chunks/libs/package-up.mjs +1 -10
  57. package/dist/_chunks/libs/pako.mjs +1 -0
  58. package/dist/_chunks/libs/parse-ms.mjs +1 -36
  59. package/dist/_chunks/libs/pathe.mjs +1 -0
  60. package/dist/_chunks/libs/picomatch.mjs +1 -1673
  61. package/dist/_chunks/libs/pretty-ms.mjs +1 -80
  62. package/dist/_chunks/libs/remeda.mjs +2 -690
  63. package/dist/_chunks/libs/safe-stringify.mjs +1 -21
  64. package/dist/_chunks/libs/strip-indent.mjs +1 -15
  65. package/dist/_chunks/libs/tinyrainbow.mjs +1 -88
  66. package/dist/_chunks/libs/ts-graphviz.mjs +4 -725
  67. package/dist/_chunks/libs/ufo.mjs +1 -240
  68. package/dist/_chunks/libs/which.mjs +1 -84
  69. package/dist/_chunks/libs/word-wrap.mjs +12 -43
  70. package/dist/_chunks/rolldown-runtime.mjs +1 -48
  71. package/dist/_chunks/sequence.mjs +1 -0
  72. package/dist/_chunks/src.mjs +15 -0
  73. package/dist/_chunks/src2.mjs +499 -0
  74. package/dist/cli/index.mjs +77 -1952
  75. package/dist/config/index.d.mts +2 -2
  76. package/dist/config/index.mjs +1 -6
  77. package/dist/index.d.mts +150 -7
  78. package/dist/index.mjs +1 -21
  79. package/dist/model/builder.mjs +1 -3
  80. package/dist/model/index.d.mts +57 -3
  81. package/dist/model/index.mjs +1 -5
  82. package/dist/vite-plugin/index.d.mts +7 -3
  83. package/dist/vite-plugin/index.mjs +1 -22
  84. package/dist/vite-plugin/internal.d.mts +6 -7
  85. package/dist/vite-plugin/internal.mjs +1 -68
  86. package/package.json +64 -45
  87. package/react/{index.d.ts → index.d.mts} +114 -72
  88. package/react/{index.js → index.mjs} +21320 -22041
  89. package/react/package.json +2 -5
  90. package/vite-plugin-modules.d.ts +10 -5
  91. package/dist/_chunks/LikeC4.d.mts +0 -121
  92. package/dist/_chunks/config-app.prod.d.mts +0 -18
  93. package/dist/_chunks/config-app.prod.mjs +0 -188
  94. package/dist/_chunks/config-webcomponent.prod.mjs +0 -71
  95. package/dist/_chunks/define-config.mjs +0 -409
  96. package/dist/_chunks/index3.d.mts +0 -60
  97. package/dist/_chunks/libs/@chevrotain/gast.mjs +0 -3969
  98. package/dist/_chunks/libs/hono.mjs +0 -1829
  99. package/dist/_chunks/libs/nanoid.mjs +0 -29
  100. package/dist/_chunks/libs/nanostores.d.mts +0 -63
  101. package/dist/_chunks/libs/nanostores.mjs +0 -198
  102. package/dist/_chunks/model.mjs +0 -12
  103. package/dist/_chunks/module.d.mts +0 -71
  104. package/dist/_chunks/module.mjs +0 -18657
  105. package/dist/_chunks/plugin.mjs +0 -996
  106. package/dist/_chunks/sequence-view.mjs +0 -575
  107. package/dist/_chunks/vite-build.mjs +0 -69
  108. package/dist/_chunks/vite-dev.mjs +0 -79
  109. package/dist/_chunks/vite-preview.mjs +0 -27
  110. package/dist/language/module.d.mts +0 -5
  111. package/dist/language/module.mjs +0 -20
  112. package/dist/vite/vite-build.d.mts +0 -26
  113. package/dist/vite/vite-build.mjs +0 -27
  114. package/dist/vite/vite-dev.d.mts +0 -34
  115. package/dist/vite/vite-dev.mjs +0 -29
  116. package/dist/vite/vite-preview.d.mts +0 -20
  117. package/dist/vite/vite-preview.mjs +0 -26
  118. /package/dist/_chunks/{index4.d.mts → libs/@chevrotain/types.d.mts} +0 -0
@@ -1,101 +1,8 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { d4 as Loader, d5 as useStore, d as deepEqual, s as shallowEqual, d6 as useMatches, cN as useParams, v as useIsomorphicLayoutEffect, cZ as createFileRoute, cP as Container, ba as Stack, b$ as Title, V as Button, cT as Link, d7 as notFound, c_ as redirect, O as m, cY as Outlet, d8 as Navigate, k as useMantineColorScheme, d9 as useComputedColorScheme, aA as ActionIcon, aF as MotionDiv, cI as isValidMotionProp, aD as Menu, bg as MenuTarget, bh as MenuDropdown, bi as MenuItem, da as MenuDivider, by as Alert, bc as rem, R as Text, cM as useRouter, aM as Box, bA as Group, b1 as CopyButton$1, cQ as Code, db as Select, dc as ModalRoot, dd as ModalOverlay, de as ModalContent, df as ModalBody, bP as Tabs, bQ as TabsList, bR as TabsTab, bS as TabsPanel, dg as useMantineTheme, dh as useMediaQuery, di as useDisclosure, aG as Divider, dj as MenuLabel, dk as useSearch, dl as LoadingOverlay, dm as toBlob, cU as useNavigate, bU as useCallbackRef, c$ as useDocumentTitle, dn as useIsMounted, cX as stripSearchParams, cV as z, T as Tooltip, dp as useAsync, dq as It, dr as Ot, bT as ScrollArea, ds as Nt } from "../vendors.js";
3
- import { F as Fallback, N as NotFound } from "./index.js";
4
- import { s as styled, I as IconRendererProvider, a as LikeC4ModelProvider, u as useUpdateEffect, b as LikeC4AdHocViewEditor, d as IconMoonStars, e as IconSun, f as createStyleContext, n as navigationPanel, i as isCssProperty, g as useLikeC4Projects$1, h as IconChevronDown, j as IconAlertTriangle, k as IconCheck, l as IconCopy, m as IconExternalLink, o as IconShare, p as pickViewBounds, B as Box$1, q as LikeC4Diagram, S as StaticLikeC4Diagram, r as useLikeC4Model, t as useDiagramContext, v as useDiagram, w as useOnDiagramEvent, x as LikeC4EditorProvider, c as css } from "../likec4.js";
5
- import { lazy, Suspense, createContext, useContext, useState, useEffect, memo, useRef } from "react";
6
- import { likec4rpc, isRpcAvailable } from "likec4:rpc";
7
- import { useHashHistory, ComponentName, pageTitle, isDevelopment, krokiPumlSvgUrl, krokiD2SvgUrl } from "../const.js";
8
- import { useLikeC4Projects } from "likec4:projects";
9
- const ViewOutlet = styled("div", {
10
- base: {
11
- padding: "0",
12
- margin: "0",
13
- width: "full",
14
- height: "full"
15
- }
16
- }), ProjectIcons = lazy(async () => {
17
- const { ProjectIcons: ProjectIcons2 } = await import("likec4:icons");
18
- return {
19
- default: ProjectIcons2
20
- };
21
- }), ProjectIconRenderer = (props) => /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Loader, { className: "pending", type: "oval", size: "xs" }), children: /* @__PURE__ */ jsx(ProjectIcons, { ...props }) });
22
- let _renderers = {};
23
- function LikeC4IconRendererContext({ children, projectId }) {
24
- const IconRenderer = _renderers[projectId] ??= (props) => /* @__PURE__ */ jsx(ProjectIconRenderer, { ...props, projectId });
25
- return /* @__PURE__ */ jsx(IconRendererProvider, { value: IconRenderer, children });
26
- }
27
- const LikeC4ModelDataContext = createContext(null), LikeC4ModelDataContextProvider = LikeC4ModelDataContext.Provider, useLikeC4ModelAtom = () => {
28
- const ctx = useContext(LikeC4ModelDataContext);
29
- if (ctx === null)
30
- throw new Error("LikeC4ModelAtom is not provided");
31
- return ctx;
32
- };
33
- function LikeC4ModelContext({ likec4model, children }) {
34
- const model = useStore(likec4model);
35
- return /* @__PURE__ */ jsx(LikeC4ModelDataContextProvider, { value: likec4model, children: /* @__PURE__ */ jsx(LikeC4ModelProvider, { likec4model: model, children }) });
36
- }
37
- function useTransparentBackground(enabled = !0) {
38
- useIsomorphicLayoutEffect(() => {
39
- const htmlEl = document.body.parentElement;
40
- if (!htmlEl || enabled !== !0) return;
41
- const classname = "transparent-bg";
42
- return htmlEl.classList.add(classname), () => {
43
- htmlEl.classList.remove(classname);
44
- };
45
- }, [enabled]);
46
- }
47
- function useLikeC4Views() {
48
- const $likec4model = useLikeC4ModelAtom(), [views, setViews] = useState([]);
49
- return useEffect(() => $likec4model.subscribe((next) => {
50
- setViews((prev) => {
51
- const nextViews = [...next.views()].map((v) => {
52
- const n = v.$layouted, p = prev.find((_) => _.id === v.id);
53
- return p && deepEqual(n, p) ? p : n;
54
- });
55
- return shallowEqual(prev, nextViews) ? prev : nextViews;
56
- });
57
- }), [$likec4model]), views;
58
- }
59
- function useCurrentViewId() {
60
- return useParams({
61
- select: (params) => params.viewId,
62
- strict: !1
63
- }) ?? "index";
64
- }
65
- function useCurrentView() {
66
- const viewId = useCurrentViewId(), $likec4model = useLikeC4ModelAtom(), [layoutType, setLayoutType] = useState("manual");
67
- useUpdateEffect(() => {
68
- setLayoutType("manual");
69
- }, [viewId]);
70
- const [view, setView] = useState(() => $likec4model.get().findView(viewId)?.$layouted ?? null);
71
- return useEffect(() => $likec4model.subscribe((next) => {
72
- setView((current) => {
73
- const vm = next.findView(viewId);
74
- if (!vm)
75
- return null;
76
- const nextView = layoutType === "auto" ? vm.$view : vm.$layouted;
77
- return deepEqual(current, nextView) ? current : nextView;
78
- });
79
- }), [$likec4model, viewId, layoutType]), [view, setLayoutType];
80
- }
81
- function useCurrentProject() {
82
- const projects = useLikeC4Projects(), projectId = useMatches({
83
- select: (m2) => m2.find((m22) => m22.routeId === "/project/$projectId")?.params?.projectId ?? m2.at(-1)?.context.projectId ?? "default"
84
- });
85
- return projects.find((p) => p.id === projectId) ?? projects[0];
86
- }
87
- function AdHocViewEditor({ projectId }) {
88
- return /* @__PURE__ */ jsx(
89
- LikeC4AdHocViewEditor,
90
- {
91
- service: {
92
- process: async ({ predicates }) => ({
93
- view: await likec4rpc.calcAdhocView({ projectId, predicates })
94
- })
95
- }
96
- }
97
- );
98
- }
2
+ import { d1 as createFileRoute, db as Container, bp as Stack, bZ as Title, W as Button, df as Link, dD as notFound, d2 as redirect, Q as m, d0 as Outlet, dE as Navigate, c$ as stripSearchParams, cZ as z } from "../vendors.js";
3
+ import { loadModel } from "likec4:model";
4
+ import { V as ViewOutlet, F as Fallback, L as LikeC4IconRendererContext, l as LikeC4ModelContext, A as AdHocViewEditor, H as Header, E as ExportPage, m as EmbedPage, n as ViewEditor, o as ViewReact, p as ViewAsPuml, q as ViewAsMmd, r as ViewAsDot, s as ViewAsD2 } from "./single.js";
5
+ import { isRpcAvailable } from "likec4:rpc";
99
6
  const Route$a = createFileRoute("/project/$projectId")({
100
7
  staleTime: 1 / 0,
101
8
  beforeLoad: ({ params }) => ({
@@ -105,26 +12,21 @@ const Route$a = createFileRoute("/project/$projectId")({
105
12
  return [];
106
13
  },
107
14
  loader: async ({ context }) => {
108
- const projectId = context.projectId;
109
- return await import("likec4:model").then((m2) => m2.loadModel(projectId)).catch((err) => {
110
- throw console.error(err), notFound();
111
- }).then((likec4model) => {
112
- const data = likec4model.$likec4data.value;
113
- if (!data)
114
- throw notFound();
115
- if (data.projectId !== projectId)
116
- throw redirect({
117
- to: "/project/$projectId/",
118
- search: !0,
119
- params: {
120
- projectId: data.projectId
121
- }
122
- });
123
- return {
124
- $likec4model: likec4model.$likec4model,
125
- projectId
126
- };
127
- });
15
+ const projectId = context.projectId, likec4model = await loadModel(projectId), data = likec4model.$likec4data.value;
16
+ if (!data)
17
+ throw notFound();
18
+ if (data.projectId !== projectId)
19
+ throw redirect({
20
+ to: "/project/$projectId/",
21
+ search: !0,
22
+ params: {
23
+ projectId: data.projectId
24
+ }
25
+ });
26
+ return {
27
+ $likec4model: likec4model.$likec4model,
28
+ projectId
29
+ };
128
30
  },
129
31
  remountDeps({ params }) {
130
32
  return [params.projectId];
@@ -170,724 +72,6 @@ function Page$4() {
170
72
  const { projectId } = Route$8.useRouteContext();
171
73
  return /* @__PURE__ */ jsx(AdHocViewEditor, { projectId });
172
74
  }
173
- function ColorSchemeToggle() {
174
- const { setColorScheme } = useMantineColorScheme({
175
- keepTransitions: !0
176
- }), computedColorScheme = useComputedColorScheme("light");
177
- return /* @__PURE__ */ jsxs(
178
- ActionIcon,
179
- {
180
- visibleFrom: "sm",
181
- size: "md",
182
- variant: "subtle",
183
- color: "gray",
184
- onClick: () => setColorScheme(computedColorScheme === "light" ? "dark" : "light"),
185
- "aria-label": "Toggle color scheme",
186
- children: [
187
- /* @__PURE__ */ jsx(IconMoonStars, { stroke: 1.5, display: computedColorScheme === "light" ? "block" : "none" }),
188
- /* @__PURE__ */ jsx(IconSun, { stroke: 1.5, display: computedColorScheme === "dark" ? "block" : "none" })
189
- ]
190
- }
191
- );
192
- }
193
- const { withProvider, withContext } = createStyleContext(navigationPanel), shouldForwardProp = (prop, variantKeys) => !variantKeys.includes(prop) && (isValidMotionProp(prop) || !isCssProperty(prop)), Root = withProvider(MotionDiv, "root", {
194
- shouldForwardProp
195
- }), Body = withContext(MotionDiv, "body", {
196
- shouldForwardProp
197
- });
198
- withContext(MotionDiv, "label", {
199
- shouldForwardProp
200
- });
201
- withContext(MotionDiv, "dropdown", {
202
- shouldForwardProp
203
- });
204
- const NavigationPanel = {
205
- Root,
206
- Body
207
- };
208
- function SelectProject() {
209
- const projects = useLikeC4Projects$1(), project = useCurrentProject();
210
- return projects.length < 2 ? null : /* @__PURE__ */ jsxs(Menu, { shadow: "md", width: 200, trigger: "click-hover", openDelay: 200, children: [
211
- /* @__PURE__ */ jsx(MenuTarget, { children: /* @__PURE__ */ jsx(
212
- Button,
213
- {
214
- variant: "subtle",
215
- size: "sm",
216
- color: "gray",
217
- px: "sm",
218
- rightSection: /* @__PURE__ */ jsx(IconChevronDown, { opacity: 0.5, size: 14 }),
219
- visibleFrom: "md",
220
- children: project.title ?? project.id
221
- }
222
- ) }),
223
- /* @__PURE__ */ jsxs(MenuDropdown, { children: [
224
- /* @__PURE__ */ jsx(
225
- MenuItem,
226
- {
227
- renderRoot: (props) => /* @__PURE__ */ jsx(
228
- Link,
229
- {
230
- ...props,
231
- to: "/projects"
232
- }
233
- ),
234
- children: "Projects overview"
235
- }
236
- ),
237
- /* @__PURE__ */ jsx(MenuDivider, {}),
238
- projects.map(({ id, title }) => /* @__PURE__ */ jsx(
239
- MenuItem,
240
- {
241
- renderRoot: (props) => /* @__PURE__ */ jsx(
242
- Link,
243
- {
244
- ...props,
245
- to: "/project/$projectId/view/$viewId/",
246
- params: {
247
- projectId: id,
248
- viewId: "index"
249
- }
250
- }
251
- ),
252
- children: title ?? id
253
- },
254
- id
255
- ))
256
- ] })
257
- ] });
258
- }
259
- const AlertLocalhost = () => /* @__PURE__ */ jsx(
260
- Alert,
261
- {
262
- color: "yellow",
263
- icon: /* @__PURE__ */ jsx(IconAlertTriangle, {}),
264
- title: "Localhost URL",
265
- styles: { body: { gap: rem(4) } },
266
- children: /* @__PURE__ */ jsx(Text, { c: "yellow", size: "sm", children: "You need to deploy your project to make it available on the internet" })
267
- }
268
- ), CopyButtonChild = ({ copied, copy }) => /* @__PURE__ */ jsx(
269
- Button,
270
- {
271
- size: "xs",
272
- color: copied ? "teal" : "gray",
273
- variant: "light",
274
- leftSection: copied ? /* @__PURE__ */ jsx(IconCheck, { style: { width: rem(16) } }) : /* @__PURE__ */ jsx(IconCopy, { style: { width: rem(16) } }),
275
- onClick: copy,
276
- children: copied ? "Copied" : "Copy to clipboard"
277
- }
278
- ), EmbedPanel = ({ diagram }) => {
279
- const router = useRouter(), { colorScheme } = useMantineColorScheme(), [theme, setTheme] = useState(colorScheme), padding = 20;
280
- let location = router.buildLocation({
281
- to: "/embed/$viewId/",
282
- // '/' at the end added by Gemini 3, must have to pass typecheck
283
- params: { viewId: diagram.id },
284
- search: {
285
- padding,
286
- ...theme !== "auto" ? { theme } : {}
287
- // changed from "theme: theme !== 'auto' ? theme : undefined" by Gemini 3
288
- }
289
- }).href;
290
- location = useHashHistory ? `#${location}` : location;
291
- const url = new URL(location, window.location.href), width = diagram.bounds.width + padding * 2, height = diagram.bounds.height + padding * 2, href = url.href, code = `
292
- <div style="aspect-ratio:${width}/${height};width:100%;height:auto;max-width:${width}px;margin:0 auto">
293
- <iframe src="${href}" width="100%" height="100%" style="border:0;background:transparent;"></iframe>
294
- </div>
295
- `.trim();
296
- return /* @__PURE__ */ jsxs(Stack, { children: [
297
- code.includes("http://localhost") && /* @__PURE__ */ jsx(AlertLocalhost, {}),
298
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: "Embedded view is an iframe with a static diagram" }) }),
299
- /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
300
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
301
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { fw: "500", size: "sm", children: "HTML" }) }),
302
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
303
- /* @__PURE__ */ jsx(ActionIcon, { component: "a", href, target: "_blank", variant: "light", color: "gray", children: /* @__PURE__ */ jsx(IconExternalLink, {}) }),
304
- /* @__PURE__ */ jsx(CopyButton$1, { value: code, timeout: 1500, children: CopyButtonChild })
305
- ] })
306
- ] }),
307
- /* @__PURE__ */ jsx(Code, { block: !0, children: code }),
308
- /* @__PURE__ */ jsx(
309
- Box,
310
- {
311
- style: {
312
- alignSelf: "flex-start"
313
- },
314
- children: /* @__PURE__ */ jsx(
315
- Select,
316
- {
317
- label: "Color scheme",
318
- value: theme,
319
- allowDeselect: !1,
320
- onChange: (v) => setTheme(v ?? "auto"),
321
- data: [
322
- { value: "auto", label: "Auto" },
323
- { value: "light", label: "Light" },
324
- { value: "dark", label: "Dark" }
325
- ]
326
- }
327
- )
328
- }
329
- )
330
- ] })
331
- ] });
332
- };
333
- function WebcomponentsPanel({ diagram }) {
334
- const router = useRouter();
335
- let base = router.basepath.endsWith("/") ? router.basepath : `${router.basepath}/`;
336
- const jscode = `
337
- <script module src="${new URL(
338
- `${base}likec4-views.js`,
339
- window.location.href
340
- ).href}"><\/script>
341
- `.trim(), htmlCode = `
342
- <${ComponentName.View}
343
- view-id="${encodeURIComponent(diagram.id)}"
344
- browser="true"
345
- dynamic-variant="sequence">
346
- </${ComponentName.View}>
347
- `.trim(), webcomponentPreview = router.buildLocation(
348
- {
349
- to: "/webcomponent/$/",
350
- // '/' at the end added by Gemini 3, must have to pass typecheck
351
- params: { _splat: diagram.id },
352
- search: !0
353
- }
354
- );
355
- return /* @__PURE__ */ jsxs(Stack, { children: [
356
- jscode.includes("http://localhost") && /* @__PURE__ */ jsx(AlertLocalhost, {}),
357
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: "Add this script to your page:" }) }),
358
- /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
359
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
360
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { fw: "500", size: "sm", children: "JavaScript" }) }),
361
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
362
- /* @__PURE__ */ jsx(ActionIcon, { component: "a", href: webcomponentPreview.href, target: "_blank", variant: "light", color: "gray", children: /* @__PURE__ */ jsx(IconExternalLink, {}) }),
363
- /* @__PURE__ */ jsx(
364
- CopyButton$1,
365
- {
366
- value: jscode,
367
- timeout: 1500,
368
- children: CopyButtonChild
369
- }
370
- )
371
- ] })
372
- ] }),
373
- /* @__PURE__ */ jsx(Code, { block: !0, children: jscode }),
374
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
375
- "This script defines a custom element (webcomponent) that renders your diagrams.",
376
- /* @__PURE__ */ jsx("br", {}),
377
- "Script must be inserted once in the ",
378
- /* @__PURE__ */ jsx("code", { children: "<head>" }),
379
- " or at the end of the ",
380
- /* @__PURE__ */ jsx("code", { children: "<body>" }),
381
- " ",
382
- "tag."
383
- ] }) })
384
- ] }),
385
- /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
386
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
387
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { fw: "500", size: "sm", children: "HTML" }) }),
388
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
389
- CopyButton$1,
390
- {
391
- value: htmlCode,
392
- timeout: 1500,
393
- children: CopyButtonChild
394
- }
395
- ) })
396
- ] }),
397
- /* @__PURE__ */ jsx(Code, { block: !0, children: htmlCode }),
398
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
399
- "Insert this code to your page. Page may have multiple ",
400
- /* @__PURE__ */ jsx("code", { children: "<likec4-view>" }),
401
- "."
402
- ] }) })
403
- ] })
404
- ] });
405
- }
406
- function ShareModal({
407
- onClose
408
- }) {
409
- const [diagram] = useCurrentView(), [activeTab, setActiveTab] = useState("webcomponent");
410
- return diagram ? /* @__PURE__ */ jsxs(
411
- ModalRoot,
412
- {
413
- size: "xl",
414
- opened: !0,
415
- onClose,
416
- children: [
417
- /* @__PURE__ */ jsx(ModalOverlay, { backgroundOpacity: 0.5, blur: 3 }),
418
- /* @__PURE__ */ jsx(ModalContent, { children: /* @__PURE__ */ jsxs(ModalBody, { children: [
419
- /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onChange: (tab) => setActiveTab(tab ?? "webcomponent"), children: [
420
- /* @__PURE__ */ jsxs(TabsList, { children: [
421
- /* @__PURE__ */ jsx(TabsTab, { value: "webcomponent", children: "Webcomponent" }),
422
- /* @__PURE__ */ jsx(TabsTab, { value: "embed", children: "Embedded" })
423
- ] }),
424
- /* @__PURE__ */ jsx(TabsPanel, { value: "embed", pt: "md", children: /* @__PURE__ */ jsx(EmbedPanel, { diagram }) }),
425
- /* @__PURE__ */ jsx(TabsPanel, { value: "webcomponent", pt: "md", children: /* @__PURE__ */ jsx(WebcomponentsPanel, { diagram }) })
426
- ] }),
427
- /* @__PURE__ */ jsx(Group, { justify: "flex-end", mt: "lg", children: /* @__PURE__ */ jsx(Button, { size: "sm", onClick: onClose, children: "Close" }) })
428
- ] }) })
429
- ]
430
- }
431
- ) : null;
432
- }
433
- const Header = memo(() => {
434
- const projects = useLikeC4Projects$1(), isReactDiagramRoute = useMatches({
435
- select(matches) {
436
- return matches.some(
437
- ({ routeId }) => routeId === "/_single/view/$viewId/" || routeId === "/project/$projectId/view/$viewId/"
438
- );
439
- }
440
- }), { breakpoints } = useMantineTheme(), isTablet = useMediaQuery(`(min-width: ${breakpoints.md})`) ?? !1, [opened, { open, close }] = useDisclosure(!1);
441
- return /* @__PURE__ */ jsxs(Fragment, { children: [
442
- /* @__PURE__ */ jsx(NavigationPanel.Root, { panelPosition: "right", hideBelow: "md", children: /* @__PURE__ */ jsxs(NavigationPanel.Body, { gap: "2", children: [
443
- isReactDiagramRoute ? /* @__PURE__ */ jsxs(Fragment, { children: [
444
- /* @__PURE__ */ jsx(SelectProject, {}),
445
- projects.length <= 1 && /* @__PURE__ */ jsx(
446
- Button,
447
- {
448
- size: isTablet ? "sm" : "xs",
449
- leftSection: /* @__PURE__ */ jsx(IconShare, { size: 14 }),
450
- onClick: open,
451
- children: "Share"
452
- }
453
- ),
454
- /* @__PURE__ */ jsx(ExportButton, {})
455
- ] }) : /* @__PURE__ */ jsx(
456
- Button,
457
- {
458
- component: Link,
459
- to: "/view/$viewId/",
460
- size: isTablet ? "sm" : "xs",
461
- variant: "subtle",
462
- color: "gray",
463
- children: "Back to diagram"
464
- }
465
- ),
466
- /* @__PURE__ */ jsx(Divider, { orientation: "vertical", visibleFrom: "md" }),
467
- /* @__PURE__ */ jsx(ColorSchemeToggle, {})
468
- ] }) }),
469
- opened && /* @__PURE__ */ jsx(ShareModal, { onClose: close })
470
- ] });
471
- }), enableDownload = (params) => ({
472
- ...params,
473
- download: !0
474
- });
475
- function ExportButton() {
476
- const isInsideProject = useMatches({
477
- select: (matches) => matches.some(({ routeId }) => routeId === "/project/$projectId")
478
- });
479
- return /* @__PURE__ */ jsxs(Menu, { shadow: "md", width: 200, trigger: "click-hover", openDelay: 200, children: [
480
- /* @__PURE__ */ jsx(MenuTarget, { children: /* @__PURE__ */ jsx(
481
- Button,
482
- {
483
- variant: "subtle",
484
- size: "sm",
485
- color: "gray",
486
- px: "sm",
487
- rightSection: /* @__PURE__ */ jsx(IconChevronDown, { opacity: 0.5, size: 14 }),
488
- visibleFrom: "md",
489
- children: "Export"
490
- }
491
- ) }),
492
- /* @__PURE__ */ jsxs(MenuDropdown, { children: [
493
- /* @__PURE__ */ jsx(MenuLabel, { children: "Current view" }),
494
- /* @__PURE__ */ jsx(
495
- MenuItem,
496
- {
497
- renderRoot: (props) => /* @__PURE__ */ jsx(
498
- Link,
499
- {
500
- target: "_blank",
501
- to: isInsideProject ? "/project/$projectId/export/$viewId/" : "/export/$viewId/",
502
- search: enableDownload,
503
- ...props
504
- }
505
- ),
506
- children: "Export as .png"
507
- }
508
- ),
509
- /* @__PURE__ */ jsx(
510
- MenuItem,
511
- {
512
- renderRoot: (props) => /* @__PURE__ */ jsx(
513
- Link,
514
- {
515
- to: isInsideProject ? "/project/$projectId/view/$viewId/dot/" : "/view/$viewId/dot/",
516
- search: !0,
517
- ...props
518
- }
519
- ),
520
- children: "Export as .dot"
521
- }
522
- ),
523
- /* @__PURE__ */ jsx(
524
- MenuItem,
525
- {
526
- renderRoot: (props) => /* @__PURE__ */ jsx(
527
- Link,
528
- {
529
- to: isInsideProject ? "/project/$projectId/view/$viewId/d2" : "/view/$viewId/d2",
530
- search: !0,
531
- ...props
532
- }
533
- ),
534
- children: "Export as .d2"
535
- }
536
- ),
537
- /* @__PURE__ */ jsx(
538
- MenuItem,
539
- {
540
- renderRoot: (props) => /* @__PURE__ */ jsx(
541
- Link,
542
- {
543
- to: isInsideProject ? "/project/$projectId/view/$viewId/mmd" : "/view/$viewId/mmd",
544
- search: !0,
545
- ...props
546
- }
547
- ),
548
- children: "Export as .mmd"
549
- }
550
- ),
551
- /* @__PURE__ */ jsx(
552
- MenuItem,
553
- {
554
- renderRoot: (props) => /* @__PURE__ */ jsx(
555
- Link,
556
- {
557
- to: isInsideProject ? "/project/$projectId/view/$viewId/puml" : "/view/$viewId/puml",
558
- search: !0,
559
- ...props
560
- }
561
- ),
562
- children: "Export as .puml"
563
- }
564
- ),
565
- /* @__PURE__ */ jsx(MenuItem, { disabled: !0, children: "Export to Draw.io" }),
566
- /* @__PURE__ */ jsx(MenuItem, { disabled: !0, children: "Export to Miro" }),
567
- /* @__PURE__ */ jsx(MenuItem, { disabled: !0, children: "Export to Notion" })
568
- ] })
569
- ] });
570
- }
571
- async function downloadAsPng({
572
- pngFilename,
573
- viewport
574
- }) {
575
- try {
576
- const blob = await toBlob(viewport, {
577
- backgroundColor: "transparent",
578
- cacheBust: !0,
579
- imagePlaceholder: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
580
- });
581
- if (!blob)
582
- throw new Error("Failed to create PNG blob");
583
- var url = URL.createObjectURL(blob), link = document.createElement("a");
584
- link.setAttribute("download", `${pngFilename}.png`), link.href = url, document.body.appendChild(link), link.click(), await new Promise((resolve) => setTimeout(resolve, 1e3)), document.body.removeChild(link), URL.revokeObjectURL(url), window.close();
585
- } catch (err) {
586
- console.error(err), window.alert("Failed to export to PNG, check the console for more details.");
587
- }
588
- }
589
- function ExportPage() {
590
- const [diagram] = useCurrentView();
591
- return useTransparentBackground(), diagram ? /* @__PURE__ */ jsx(GuardedExportPage, { diagram }) : /* @__PURE__ */ jsx("div", { children: "Loading..." });
592
- }
593
- function GuardedExportPage({ diagram }) {
594
- const {
595
- padding = 20,
596
- download = !1,
597
- dynamic
598
- } = useSearch({
599
- strict: !1
600
- }), viewportRef = useRef(null), loadingOverlayRef = useRef(null), downloadedRef = useRef(!1), bounds = pickViewBounds(diagram, dynamic), downloadDiagram = () => {
601
- const viewport = viewportRef.current;
602
- if (!download || !viewport || !diagram || downloadedRef.current)
603
- return;
604
- const loadingOverlay = loadingOverlayRef.current;
605
- loadingOverlay && (loadingOverlay.style.display = "none"), downloadedRef.current = !0, downloadAsPng({
606
- pngFilename: diagram.id,
607
- viewport
608
- });
609
- }, extraPadding = 16, width = bounds.width + padding * 2 + extraPadding, height = bounds.height + padding * 2 + extraPadding;
610
- return /* @__PURE__ */ jsxs(
611
- Box$1,
612
- {
613
- ref: viewportRef,
614
- "data-testid": "export-page",
615
- css: {
616
- position: "fixed",
617
- top: "0",
618
- left: "0",
619
- padding: "0",
620
- margin: "0",
621
- background: "transparent",
622
- overflow: "hidden",
623
- zIndex: 2
624
- },
625
- style: {
626
- marginRight: "auto",
627
- marginBottom: "auto",
628
- minWidth: width,
629
- width,
630
- minHeight: height,
631
- height
632
- },
633
- children: [
634
- download && /* @__PURE__ */ jsx(LoadingOverlay, { ref: loadingOverlayRef, visible: !0 }),
635
- /* @__PURE__ */ jsx(
636
- LikeC4Diagram,
637
- {
638
- view: diagram,
639
- fitView: !1,
640
- fitViewPadding: {
641
- top: "0px",
642
- bottom: "0px",
643
- left: "0px",
644
- right: "0px"
645
- },
646
- background: "transparent",
647
- reduceGraphics: !1,
648
- dynamicViewVariant: dynamic,
649
- className: "likec4-static-view",
650
- pannable: !1,
651
- zoomable: !1,
652
- controls: !1,
653
- enableNotations: !1,
654
- enableElementDetails: !1,
655
- enableRelationshipDetails: !1,
656
- enableRelationshipBrowser: !1,
657
- enableDynamicViewWalkthrough: !1,
658
- enableFocusMode: !1,
659
- enableSearch: !1,
660
- nodesSelectable: !1,
661
- enableElementTags: !1,
662
- onInitialized: () => {
663
- if (!viewportRef.current) {
664
- console.error("viewportRef.current is null");
665
- return;
666
- }
667
- const x = Math.round(-bounds.x + padding), y = Math.round(-bounds.y + padding);
668
- [...viewportRef.current.querySelectorAll(".react-flow__viewport")].forEach((el) => {
669
- el.style.transform = "translate(" + x + "px, " + y + "px)";
670
- }), download && window.setTimeout(downloadDiagram, 500);
671
- }
672
- }
673
- )
674
- ]
675
- }
676
- );
677
- }
678
- function EmbedPage() {
679
- const {
680
- padding = 20,
681
- dynamic
682
- } = useSearch({
683
- strict: !1
684
- }), [diagram] = useCurrentView();
685
- if (useTransparentBackground(!!diagram), !diagram)
686
- return /* @__PURE__ */ jsx("div", { children: "Loading..." });
687
- const bounds = pickViewBounds(diagram, dynamic);
688
- return /* @__PURE__ */ jsx(
689
- "div",
690
- {
691
- style: {
692
- position: "absolute",
693
- top: 0,
694
- left: "50%",
695
- boxSizing: "border-box",
696
- padding,
697
- transform: "translateX(-50%)",
698
- aspectRatio: `${bounds.width + padding * 2} / ${bounds.height + padding * 2}`,
699
- width: "100vw",
700
- maxWidth: bounds.width + padding * 2,
701
- height: "auto",
702
- maxHeight: "100vh"
703
- },
704
- children: /* @__PURE__ */ jsx(
705
- StaticLikeC4Diagram,
706
- {
707
- view: diagram,
708
- fitView: !0,
709
- background: "transparent",
710
- fitViewPadding: 0,
711
- dynamicViewVariant: dynamic,
712
- initialWidth: bounds.width,
713
- initialHeight: bounds.height
714
- }
715
- )
716
- }
717
- );
718
- }
719
- function ViewReact() {
720
- const navigate = useNavigate(), [view, setLayoutType] = useCurrentView(), model = useLikeC4Model(), { dynamic } = useSearch({
721
- from: "__root__"
722
- }), onNavigateTo = useCallbackRef((viewId) => {
723
- navigate({
724
- to: "./",
725
- viewTransition: !1,
726
- params: (current) => ({
727
- ...current,
728
- viewId
729
- }),
730
- search: !0
731
- });
732
- }), title = view ? view.title ?? view.id : "View not found", pageTitle$1 = model.project.title ?? pageTitle;
733
- if (useDocumentTitle(`${title} - ${pageTitle$1}`), !view)
734
- return /* @__PURE__ */ jsx(NotFound, {});
735
- const hasNotations = (view.notation?.nodes ?? []).length > 0;
736
- return /* @__PURE__ */ jsxs(
737
- LikeC4Diagram,
738
- {
739
- view,
740
- zoomable: !0,
741
- pannable: !0,
742
- controls: !0,
743
- fitViewPadding: {
744
- top: "70px",
745
- bottom: "32px",
746
- left: "32px",
747
- right: "32px"
748
- },
749
- showNavigationButtons: !0,
750
- enableSearch: !0,
751
- enableFocusMode: !0,
752
- enableDynamicViewWalkthrough: !0,
753
- dynamicViewVariant: dynamic,
754
- enableElementDetails: !0,
755
- enableRelationshipDetails: !0,
756
- enableRelationshipBrowser: !0,
757
- enableElementTags: !0,
758
- enableCompareWithLatest: !0,
759
- enableNotations: hasNotations,
760
- nodesSelectable: !0,
761
- onNavigateTo,
762
- onLayoutTypeChange: setLayoutType,
763
- onLogoClick: () => {
764
- navigate({
765
- to: "/"
766
- });
767
- },
768
- children: [
769
- /* @__PURE__ */ jsx(ListenForDynamicVariantChange, {}),
770
- /* @__PURE__ */ jsx(OpenRelationshipBrowserFromUrl, {})
771
- ]
772
- }
773
- );
774
- }
775
- function OpenRelationshipBrowserFromUrl() {
776
- const router = useRouter(), diagram = useDiagram(), { relationships } = useSearch({
777
- from: "__root__"
778
- }), processedRef = useRef(null), isInitializedRef = useRef(!1), isProcessingRef = useRef(Promise.resolve()), isMounted = useIsMounted(), openAndClear = (fqn) => {
779
- isProcessingRef.current = isProcessingRef.current.then(async () => {
780
- if (!(!isMounted() || processedRef.current === fqn))
781
- try {
782
- processedRef.current = fqn, diagram.openRelationshipsBrowser(fqn), await router.buildAndCommitLocation({
783
- search: (s) => {
784
- const { relationships: _, ...rest } = s;
785
- return rest;
786
- },
787
- replace: !0,
788
- viewTransition: !1
789
- });
790
- } catch (error) {
791
- console.error("Failed to open relationship browser:", error);
792
- }
793
- });
794
- }, process = () => {
795
- if (!relationships) {
796
- processedRef.current = null;
797
- return;
798
- }
799
- relationships && processedRef.current !== relationships && openAndClear(relationships);
800
- };
801
- return useOnDiagramEvent("initialized", () => {
802
- isInitializedRef.current = !0, process();
803
- }), useUpdateEffect(() => {
804
- process();
805
- }, [relationships]), null;
806
- }
807
- function ListenForDynamicVariantChange() {
808
- const router = useRouter(), dynamicViewVariant = useDiagramContext((c) => c.dynamicViewVariant);
809
- return useUpdateEffect(() => {
810
- (router.latestLocation.search.dynamic ?? "diagram") !== dynamicViewVariant && router.buildAndCommitLocation({
811
- search: (current) => ({
812
- ...current,
813
- dynamic: dynamicViewVariant
814
- }),
815
- viewTransition: !1
816
- });
817
- }, [dynamicViewVariant]), null;
818
- }
819
- function ViewEditor() {
820
- const navigate = useNavigate(), project = useCurrentProject(), [view, setLayoutType] = useCurrentView(), $likec4model = useLikeC4ModelAtom(), { dynamic } = useSearch({ strict: !1 }), onNavigateTo = useCallbackRef((viewId) => {
821
- navigate({
822
- to: "./",
823
- viewTransition: !1,
824
- params: (current) => ({
825
- ...current,
826
- viewId
827
- }),
828
- search: !0
829
- });
830
- });
831
- if (!view)
832
- return /* @__PURE__ */ jsx(NotFound, {});
833
- const hasNotations = (view.notation?.nodes ?? []).length > 0;
834
- return /* @__PURE__ */ jsx(
835
- LikeC4EditorProvider,
836
- {
837
- editor: {
838
- fetchView: (id, layout) => {
839
- const model = $likec4model.get().view(id);
840
- return layout === "auto" ? model.$view : model.$layouted;
841
- },
842
- handleChange: (viewId, change) => {
843
- const event = {
844
- projectId: project.id,
845
- viewId,
846
- change
847
- };
848
- return likec4rpc.updateView(event);
849
- }
850
- },
851
- children: /* @__PURE__ */ jsxs(
852
- LikeC4Diagram,
853
- {
854
- view,
855
- zoomable: !0,
856
- pannable: !0,
857
- controls: !0,
858
- fitViewPadding: {
859
- top: "70px",
860
- bottom: "32px",
861
- left: "50px",
862
- right: "32px"
863
- },
864
- showNavigationButtons: !0,
865
- enableNotations: isDevelopment || hasNotations,
866
- enableSearch: !0,
867
- enableDynamicViewWalkthrough: !0,
868
- enableFocusMode: !0,
869
- enableElementDetails: !0,
870
- enableRelationshipDetails: !0,
871
- enableRelationshipBrowser: !0,
872
- enableElementTags: !0,
873
- enableCompareWithLatest: !0,
874
- dynamicViewVariant: dynamic,
875
- onNavigateTo,
876
- onLayoutTypeChange: setLayoutType,
877
- onLogoClick: () => {
878
- navigate({
879
- to: "/"
880
- });
881
- },
882
- children: [
883
- /* @__PURE__ */ jsx(ListenForDynamicVariantChange, {}),
884
- /* @__PURE__ */ jsx(OpenRelationshipBrowserFromUrl, {})
885
- ]
886
- }
887
- )
888
- }
889
- );
890
- }
891
75
  const Route$7 = createFileRoute("/project/$projectId/view/$viewId")({
892
76
  component: ViewLayout,
893
77
  errorComponent: ({ error, reset }) => /* @__PURE__ */ jsx(Fallback, { error, resetErrorBoundary: reset })
@@ -912,243 +96,7 @@ const Route$6 = createFileRoute("/project/$projectId/export/$viewId")({
912
96
  component: ExportPage
913
97
  }), Route$5 = createFileRoute("/project/$projectId/embed/$viewId")({
914
98
  component: EmbedPage
915
- });
916
- function CopyButton({ text }) {
917
- return /* @__PURE__ */ jsx(CopyButton$1, { value: text, timeout: 2e3, children: ({ copied, copy }) => /* @__PURE__ */ jsx(Tooltip, { label: copied ? "Copied" : "Copy", withArrow: !0, position: "right", children: /* @__PURE__ */ jsx(ActionIcon, { color: copied ? "teal" : "gray", variant: copied ? "light" : "subtle", onClick: copy, children: copied ? /* @__PURE__ */ jsx(IconCheck, { style: { width: rem(16) } }) : /* @__PURE__ */ jsx(IconCopy, { style: { width: rem(16) } }) }) }) });
918
- }
919
- function CopyToClipboard({ text }) {
920
- return /* @__PURE__ */ jsx(Box, { pos: "absolute", top: "0", right: "0", p: "4", children: /* @__PURE__ */ jsx(CopyButton, { text }) });
921
- }
922
- const svgContainer = css({
923
- minWidth: 300,
924
- "& svg": {
925
- width: "100%",
926
- height: "auto"
927
- }
928
- }), cssScrollArea = css({
929
- height: "100%",
930
- "& .mantine-ScrollArea-viewport": {
931
- minHeight: "100%"
932
- },
933
- "& .mantine-ScrollArea-viewport > div": {
934
- minHeight: "100%",
935
- height: "100%"
936
- }
937
- }), cssCodeBlock = css({
938
- minHeight: "100%"
939
- }), viewWithTopPadding = css({
940
- height: "100%",
941
- paddingTop: "[var(--header-height)]"
942
- }), fetchFromKroki$1 = async (puml) => await (await fetch(krokiPumlSvgUrl, {
943
- method: "POST",
944
- cache: "force-cache",
945
- body: JSON.stringify({
946
- diagram_source: puml,
947
- output_format: "svg"
948
- }),
949
- headers: {
950
- "Content-Type": "application/json"
951
- }
952
- })).text();
953
- function ViewAsPuml({ pumlSource }) {
954
- const [krokiSvg, { execute }] = useAsync(fetchFromKroki$1, null);
955
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
956
- It,
957
- {
958
- className: viewWithTopPadding,
959
- orientation: "horizontal",
960
- children: [
961
- /* @__PURE__ */ jsx(Ot, { children: /* @__PURE__ */ jsxs(
962
- ScrollArea,
963
- {
964
- className: cssScrollArea,
965
- p: 5,
966
- styles: {
967
- viewport: {
968
- borderRadius: 6
969
- }
970
- },
971
- children: [
972
- /* @__PURE__ */ jsx(Code, { block: !0, className: cssCodeBlock, children: pumlSource }),
973
- /* @__PURE__ */ jsx(CopyToClipboard, { text: pumlSource })
974
- ]
975
- }
976
- ) }),
977
- /* @__PURE__ */ jsx(
978
- Nt,
979
- {
980
- style: {
981
- width: 10
982
- }
983
- }
984
- ),
985
- /* @__PURE__ */ jsx(Ot, { children: /* @__PURE__ */ jsxs(ScrollArea, { h: "100%", children: [
986
- krokiSvg.status !== "success" && /* @__PURE__ */ jsxs(Fragment, { children: [
987
- /* @__PURE__ */ jsx(
988
- Button,
989
- {
990
- mt: "xs",
991
- variant: "light",
992
- disabled: krokiSvg.status === "loading",
993
- onClick: () => {
994
- execute(pumlSource);
995
- },
996
- children: krokiSvg.status === "loading" ? "Loading..." : "Render with Kroki"
997
- }
998
- ),
999
- krokiSvg.status === "error" && /* @__PURE__ */ jsx(Box$1, { children: krokiSvg.error?.message })
1000
- ] }),
1001
- krokiSvg.status === "success" && /* @__PURE__ */ jsx(Box$1, { className: svgContainer, children: krokiSvg.result ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: krokiSvg.result } }) : /* @__PURE__ */ jsx(Box$1, { children: "Empty result" }) })
1002
- ] }) })
1003
- ]
1004
- }
1005
- ) });
1006
- }
1007
- const renderSvg = async (viewId, diagram) => {
1008
- const { default: mermaid } = await import("https://cdn.jsdelivr.net/npm/mermaid@11.12/dist/mermaid.esm.min.mjs");
1009
- mermaid.initialize({
1010
- theme: "dark"
1011
- });
1012
- const { svg } = await mermaid.render(viewId, diagram);
1013
- return svg;
1014
- };
1015
- function ViewAsMmd({ viewId, mmdSource }) {
1016
- const [mmdSvg, { execute }] = useAsync(renderSvg, null);
1017
- return useEffect(() => {
1018
- execute(viewId, mmdSource);
1019
- }, [mmdSource]), /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1020
- It,
1021
- {
1022
- className: viewWithTopPadding,
1023
- orientation: "horizontal",
1024
- children: [
1025
- /* @__PURE__ */ jsx(Ot, { children: /* @__PURE__ */ jsxs(
1026
- ScrollArea,
1027
- {
1028
- className: cssScrollArea,
1029
- p: 5,
1030
- styles: {
1031
- viewport: {
1032
- borderRadius: 6
1033
- }
1034
- },
1035
- children: [
1036
- /* @__PURE__ */ jsx(Code, { block: !0, className: cssCodeBlock, children: mmdSource }),
1037
- /* @__PURE__ */ jsx(CopyToClipboard, { text: mmdSource })
1038
- ]
1039
- }
1040
- ) }),
1041
- /* @__PURE__ */ jsx(
1042
- Nt,
1043
- {
1044
- style: {
1045
- width: 10
1046
- }
1047
- }
1048
- ),
1049
- /* @__PURE__ */ jsx(Ot, { children: /* @__PURE__ */ jsx(ScrollArea, { h: "100%", children: mmdSvg.result && /* @__PURE__ */ jsx(Box$1, { className: svgContainer, dangerouslySetInnerHTML: { __html: mmdSvg.result } }) }) })
1050
- ]
1051
- }
1052
- ) });
1053
- }
1054
- function ViewAsDot({ dot, dotSvg }) {
1055
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(It, { className: viewWithTopPadding, children: [
1056
- /* @__PURE__ */ jsx(Ot, { children: /* @__PURE__ */ jsxs(
1057
- ScrollArea,
1058
- {
1059
- className: cssScrollArea,
1060
- p: 5,
1061
- styles: {
1062
- viewport: {
1063
- borderRadius: 6
1064
- }
1065
- },
1066
- children: [
1067
- /* @__PURE__ */ jsx(Code, { block: !0, className: cssCodeBlock, children: dot }),
1068
- /* @__PURE__ */ jsx(CopyToClipboard, { text: dot })
1069
- ]
1070
- }
1071
- ) }),
1072
- /* @__PURE__ */ jsx(
1073
- Nt,
1074
- {
1075
- style: {
1076
- width: 10
1077
- }
1078
- }
1079
- ),
1080
- /* @__PURE__ */ jsx(Ot, { children: /* @__PURE__ */ jsx(ScrollArea, { h: "100%", children: /* @__PURE__ */ jsx("div", { className: svgContainer, dangerouslySetInnerHTML: { __html: dotSvg } }) }) })
1081
- ] }) });
1082
- }
1083
- const fetchFromKroki = async (d2) => await (await fetch(krokiD2SvgUrl, {
1084
- method: "POST",
1085
- cache: "force-cache",
1086
- body: JSON.stringify({
1087
- diagram_source: d2,
1088
- // diagram_options: {
1089
- // theme: 'colorblind-clear'
1090
- // },
1091
- output_format: "svg"
1092
- }),
1093
- headers: {
1094
- "Content-Type": "application/json"
1095
- }
1096
- })).text();
1097
- function ViewAsD2({ d2Source }) {
1098
- const [krokiSvg, { execute }] = useAsync(fetchFromKroki, null);
1099
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1100
- It,
1101
- {
1102
- className: viewWithTopPadding,
1103
- orientation: "horizontal",
1104
- children: [
1105
- /* @__PURE__ */ jsx(Ot, { children: /* @__PURE__ */ jsxs(
1106
- ScrollArea,
1107
- {
1108
- className: cssScrollArea,
1109
- p: 5,
1110
- styles: {
1111
- viewport: {
1112
- borderRadius: 6
1113
- }
1114
- },
1115
- children: [
1116
- /* @__PURE__ */ jsx(Code, { block: !0, className: cssCodeBlock, children: d2Source }),
1117
- /* @__PURE__ */ jsx(CopyToClipboard, { text: d2Source })
1118
- ]
1119
- }
1120
- ) }),
1121
- /* @__PURE__ */ jsx(
1122
- Nt,
1123
- {
1124
- style: {
1125
- width: 10
1126
- }
1127
- }
1128
- ),
1129
- /* @__PURE__ */ jsx(Ot, { children: /* @__PURE__ */ jsxs(ScrollArea, { h: "100%", children: [
1130
- krokiSvg.status !== "success" && /* @__PURE__ */ jsxs(Fragment, { children: [
1131
- /* @__PURE__ */ jsx(
1132
- Button,
1133
- {
1134
- mt: "xs",
1135
- variant: "light",
1136
- disabled: krokiSvg.status === "loading",
1137
- onClick: () => {
1138
- execute(d2Source);
1139
- },
1140
- children: krokiSvg.status === "loading" ? "Loading..." : "Render with Kroki"
1141
- }
1142
- ),
1143
- krokiSvg.status === "error" && /* @__PURE__ */ jsx(Box$1, { children: krokiSvg.error?.message })
1144
- ] }),
1145
- krokiSvg.status === "success" && /* @__PURE__ */ jsx(Box$1, { className: svgContainer, children: krokiSvg.result ? /* @__PURE__ */ jsx("div", { dangerouslySetInnerHTML: { __html: krokiSvg.result } }) : /* @__PURE__ */ jsx(Box$1, { children: "Empty result" }) })
1146
- ] }) })
1147
- ]
1148
- }
1149
- ) });
1150
- }
1151
- const Route$4 = createFileRoute("/project/$projectId/view/$viewId/")({
99
+ }), Route$4 = createFileRoute("/project/$projectId/view/$viewId/")({
1152
100
  component: isRpcAvailable ? ViewEditor : ViewReact
1153
101
  }), Route$3 = createFileRoute("/project/$projectId/view/$viewId/puml")({
1154
102
  component: Page$3,
@@ -1227,12 +175,7 @@ function Page() {
1227
175
  return /* @__PURE__ */ jsx(ViewAsD2, { d2Source: source });
1228
176
  }
1229
177
  export {
1230
- AdHocViewEditor as A,
1231
- ExportPage as E,
1232
- Header as H,
1233
- LikeC4IconRendererContext as L,
1234
178
  Route$a as R,
1235
- ViewOutlet as V,
1236
179
  Route$9 as a,
1237
180
  Route$8 as b,
1238
181
  Route$7 as c,
@@ -1242,14 +185,5 @@ export {
1242
185
  Route$3 as g,
1243
186
  Route$2 as h,
1244
187
  Route$1 as i,
1245
- Route as j,
1246
- LikeC4ModelContext as k,
1247
- EmbedPage as l,
1248
- ViewEditor as m,
1249
- ViewReact as n,
1250
- ViewAsPuml as o,
1251
- ViewAsMmd as p,
1252
- ViewAsDot as q,
1253
- ViewAsD2 as r,
1254
- useLikeC4Views as u
188
+ Route as j
1255
189
  };