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,21 +1,193 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { cZ as createFileRoute, O as m, cY as Outlet, c$ as useDocumentTitle, cP as Container, dt as SimpleGrid, du as useInViewport, dv as e, ci as Card, aM as Box, bA as Group, R as Text, cT as Link, c_ as redirect, cM as useRouter, k as useMantineColorScheme, cX as stripSearchParams, cV as z, d7 as notFound } from "../vendors.js";
3
- import { F as Fallback } from "./index.js";
4
- import { V as ViewOutlet, L as LikeC4IconRendererContext, k as LikeC4ModelContext, u as useLikeC4Views, A as AdHocViewEditor, H as Header, E as ExportPage, l as EmbedPage, m as ViewEditor, n as ViewReact, o as ViewAsPuml, p as ViewAsMmd, q as ViewAsDot, r as ViewAsD2 } from "./projects.js";
5
- import { c as css, S as StaticLikeC4Diagram, M as Markdown, B as Box$1 } from "../likec4.js";
6
- import { useState, useEffect } from "react";
2
+ import { d8 as useRouter, d9 as useParams, da as isNotFound, db as Container, br as Alert, U as Text, dc as Code, W as Button, dd as e, de as e$1, as as e$2, bt as Group, bh as rem, df as Link, bZ as Title, d1 as createFileRoute, Q as m, d0 as Outlet, d as deepEqual, s as shallowEqual, dg as useMatches, dh as useIsomorphicLayoutEffect, d3 as useDocumentTitle, di as SimpleGrid, dj as useInViewport, dk as e$3, ci as Card, aQ as Box, d2 as redirect, k as useMantineColorScheme, dl as useComputedColorScheme, aA as ActionIcon, aF as MotionDiv, cN as isValidMotionProp, aD as Menu, bc as MenuTarget, bd as MenuDropdown, be as MenuItem, dm as MenuDivider, bp as Stack, b5 as CopyButton$1, dn as Select, dp as ModalRoot, dq as ModalOverlay, dr as ModalContent, ds as ModalBody, bL as Tabs, bM as TabsList, bN as TabsTab, bO as TabsPanel, dt as useMantineTheme, du as useMediaQuery, cq as useDisclosure, aG as Divider, dv as MenuLabel, dw as useSearch, dx as LoadingOverlay, dy as toBlob, c$ as stripSearchParams, cZ as z, cY as useNavigate, bS as useCallbackRef, aL as useIsMounted, T as Tooltip, dz as useAsync, dA as Tt, dB as _t, bP as ScrollArea, dC as Ht, dD as notFound } from "../vendors.js";
3
+ import { loadModel } from "likec4:model";
4
+ import { c as css, s as styled, I as IconRendererProvider, a as LikeC4ModelProvider, u as useUpdateEffect, S as StaticLikeC4Diagram, M as Markdown, b as LikeC4AdHocViewEditor, B as Box$1, 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, q as LikeC4Diagram, r as useLikeC4Model, t as useDiagramContext, v as useDiagram, w as useOnDiagramEvent, x as LikeC4EditorProvider } from "../likec4.js";
5
+ import { getProjectIcons } from "likec4:icons";
6
+ import { useMemo, createContext, useContext, useState, useEffect, memo, useCallback, useRef } from "react";
7
+ import { useStore } from "likec4/vite-plugin/internal";
7
8
  import { RichText } from "@likec4/core/types";
8
- import { pageTitle, ComponentName } from "../const.js";
9
- import { isRpcAvailable } from "likec4:rpc";
9
+ import { pageTitle, ComponentName, useHashHistory, isDevelopment, krokiPumlSvgUrl, krokiD2SvgUrl } from "../const.js";
10
+ import { likec4rpc, isRpcAvailable } from "likec4:rpc";
11
+ import { useLikeC4Projects } from "likec4:projects";
12
+ function Fallback({ error: _error, resetErrorBoundary }) {
13
+ const router = useRouter(), params = useParams({
14
+ strict: !1
15
+ });
16
+ if (isNotFound(_error))
17
+ return /* @__PURE__ */ jsx(Container, { my: "md", children: /* @__PURE__ */ jsxs(Alert, { variant: "light", color: "orange", children: [
18
+ /* @__PURE__ */ jsxs(Text, { c: "orange", fz: "md", children: [
19
+ "The diagram",
20
+ " ",
21
+ /* @__PURE__ */ jsx(Code, { color: "orange", children: params.viewId ?? "unknown" }),
22
+ " ",
23
+ "does not exist or contains errors"
24
+ ] }),
25
+ /* @__PURE__ */ jsx(
26
+ Button,
27
+ {
28
+ onClick: () => {
29
+ resetErrorBoundary(), router.navigate({
30
+ to: "/"
31
+ });
32
+ },
33
+ variant: "light",
34
+ color: "orange",
35
+ mt: "lg",
36
+ size: "xs",
37
+ children: "Go to overview"
38
+ }
39
+ )
40
+ ] }) });
41
+ const error = _error;
42
+ let message = "Unknown error";
43
+ try {
44
+ switch (!0) {
45
+ case e$2(error):
46
+ message = "Unknown error";
47
+ break;
48
+ case e$1(error):
49
+ message = error.stack ?? error.message;
50
+ break;
51
+ case typeof error == "string":
52
+ message = error;
53
+ break;
54
+ case e(error):
55
+ message = error.stack ?? error.message ?? `${error}`;
56
+ break;
57
+ default:
58
+ message = `${error}`;
59
+ break;
60
+ }
61
+ } catch (e2) {
62
+ message = `${e2}`;
63
+ }
64
+ return /* @__PURE__ */ jsx(Container, { my: "md", children: /* @__PURE__ */ jsxs(Alert, { variant: "filled", color: "red", title: "Something went wrong", children: [
65
+ /* @__PURE__ */ jsx(Code, { block: !0, color: "red", children: message }),
66
+ /* @__PURE__ */ jsxs(Group, { mt: "lg", children: [
67
+ /* @__PURE__ */ jsx(
68
+ Button,
69
+ {
70
+ onClick: () => {
71
+ router.invalidate().finally(() => {
72
+ resetErrorBoundary();
73
+ });
74
+ },
75
+ color: "red",
76
+ variant: "white",
77
+ size: "xs",
78
+ children: "Try again"
79
+ }
80
+ ),
81
+ /* @__PURE__ */ jsx(
82
+ Button,
83
+ {
84
+ onClick: () => {
85
+ resetErrorBoundary(), router.navigate({ to: "/" });
86
+ },
87
+ color: "red",
88
+ size: "xs",
89
+ children: "Go to overview"
90
+ }
91
+ )
92
+ ] })
93
+ ] }) });
94
+ }
95
+ const content = css({
96
+ paddingTop: "[120px]",
97
+ position: "relative",
98
+ zIndex: "1",
99
+ sm: {
100
+ paddingTop: "[220px]"
101
+ }
102
+ }), image = css({
103
+ position: "absolute",
104
+ inset: "0",
105
+ opacity: 0.2
106
+ }), inner = css({
107
+ position: "relative"
108
+ }), root = css({
109
+ paddingTop: "[80px]",
110
+ paddingBottom: "[80px]"
111
+ }), description = css({
112
+ maxWidth: rem(540),
113
+ margin: "auto",
114
+ marginTop: "xl",
115
+ marginBottom: "[calc({spacing.xl}*1.5)]"
116
+ }), title = css({
117
+ textAlign: "center",
118
+ fontWeight: "[900]",
119
+ fontSize: "[38px]"
120
+ });
121
+ function NotFound() {
122
+ const params = useParams({
123
+ strict: !1
124
+ });
125
+ return params.viewId ? /* @__PURE__ */ jsx(Container, { my: "md", children: /* @__PURE__ */ jsxs(Alert, { variant: "light", color: "orange", children: [
126
+ /* @__PURE__ */ jsxs(Text, { c: "orange", fz: "md", children: [
127
+ "The diagram",
128
+ " ",
129
+ /* @__PURE__ */ jsx(Code, { color: "orange", children: params.viewId }),
130
+ " ",
131
+ "does not exist or contains errors"
132
+ ] }),
133
+ /* @__PURE__ */ jsx(
134
+ Button,
135
+ {
136
+ component: Link,
137
+ to: "/",
138
+ variant: "light",
139
+ color: "orange",
140
+ mt: "lg",
141
+ size: "xs",
142
+ children: "Go to overview"
143
+ }
144
+ )
145
+ ] }) }) : /* @__PURE__ */ jsx(Container, { className: root, children: /* @__PURE__ */ jsxs("div", { className: inner, children: [
146
+ /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 362 145", className: image, children: /* @__PURE__ */ jsx(
147
+ "path",
148
+ {
149
+ fill: "currentColor",
150
+ d: "M62.6 142c-2.133 0-3.2-1.067-3.2-3.2V118h-56c-2 0-3-1-3-3V92.8c0-1.333.4-2.733 1.2-4.2L58.2 4c.8-1.333 2.067-2 3.8-2h28c2 0 3 1 3 3v85.4h11.2c.933 0 1.733.333 2.4 1 .667.533 1 1.267 1 2.2v21.2c0 .933-.333 1.733-1 2.4-.667.533-1.467.8-2.4.8H93v20.8c0 2.133-1.067 3.2-3.2 3.2H62.6zM33 90.4h26.4V51.2L33 90.4zM181.67 144.6c-7.333 0-14.333-1.333-21-4-6.666-2.667-12.866-6.733-18.6-12.2-5.733-5.467-10.266-13-13.6-22.6-3.333-9.6-5-20.667-5-33.2 0-12.533 1.667-23.6 5-33.2 3.334-9.6 7.867-17.133 13.6-22.6 5.734-5.467 11.934-9.533 18.6-12.2 6.667-2.8 13.667-4.2 21-4.2 7.467 0 14.534 1.4 21.2 4.2 6.667 2.667 12.8 6.733 18.4 12.2 5.734 5.467 10.267 13 13.6 22.6 3.334 9.6 5 20.667 5 33.2 0 12.533-1.666 23.6-5 33.2-3.333 9.6-7.866 17.133-13.6 22.6-5.6 5.467-11.733 9.533-18.4 12.2-6.666 2.667-13.733 4-21.2 4zm0-31c9.067 0 15.6-3.733 19.6-11.2 4.134-7.6 6.2-17.533 6.2-29.8s-2.066-22.2-6.2-29.8c-4.133-7.6-10.666-11.4-19.6-11.4-8.933 0-15.466 3.8-19.6 11.4-4 7.6-6 17.533-6 29.8s2 22.2 6 29.8c4.134 7.467 10.667 11.2 19.6 11.2zM316.116 142c-2.134 0-3.2-1.067-3.2-3.2V118h-56c-2 0-3-1-3-3V92.8c0-1.333.4-2.733 1.2-4.2l56.6-84.6c.8-1.333 2.066-2 3.8-2h28c2 0 3 1 3 3v85.4h11.2c.933 0 1.733.333 2.4 1 .666.533 1 1.267 1 2.2v21.2c0 .933-.334 1.733-1 2.4-.667.533-1.467.8-2.4.8h-11.2v20.8c0 2.133-1.067 3.2-3.2 3.2h-27.2zm-29.6-51.6h26.4V51.2l-26.4 39.2z"
151
+ }
152
+ ) }),
153
+ /* @__PURE__ */ jsxs("div", { className: content, children: [
154
+ /* @__PURE__ */ jsx(Title, { className: title, children: "Nothing to see here" }),
155
+ /* @__PURE__ */ jsx(Text, { c: "dimmed", size: "lg", ta: "center", className: description, children: "Page you are trying to open does not exist. You may have mistyped the address, or the page has been moved to another URL. If you think this is an error contact support." }),
156
+ /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(Button, { component: Link, to: "/", search: !0, size: "md", children: "Take me back to home page" }) })
157
+ ] })
158
+ ] }) });
159
+ }
160
+ const ViewOutlet = styled("div", {
161
+ base: {
162
+ padding: "0",
163
+ margin: "0",
164
+ width: "full",
165
+ height: "full"
166
+ }
167
+ });
168
+ function LikeC4IconRendererContext({ children, projectId }) {
169
+ const IconRenderer = useMemo(() => getProjectIcons(projectId), [projectId]);
170
+ return /* @__PURE__ */ jsx(IconRendererProvider, { value: IconRenderer, children });
171
+ }
172
+ const LikeC4ModelDataContext = createContext(null), LikeC4ModelDataContextProvider = LikeC4ModelDataContext.Provider, useLikeC4ModelAtom = () => {
173
+ const ctx = useContext(LikeC4ModelDataContext);
174
+ if (ctx === null)
175
+ throw new Error("LikeC4ModelAtom is not provided");
176
+ return ctx;
177
+ };
178
+ function LikeC4ModelContext({ likec4model, children }) {
179
+ const model = useStore(likec4model);
180
+ return /* @__PURE__ */ jsx(LikeC4ModelDataContextProvider, { value: likec4model, children: /* @__PURE__ */ jsx(LikeC4ModelProvider, { likec4model: model, children }) });
181
+ }
10
182
  const Route$b = createFileRoute("/_single")({
11
183
  staleTime: 1 / 0,
12
184
  loaderDeps() {
13
185
  return [];
14
186
  },
15
187
  loader: async ({ context }) => {
16
- const { loadModel } = await import("likec4:model"), projectId = context.projectId, { $likec4model } = await loadModel(projectId);
188
+ const projectId = context.projectId;
17
189
  return {
18
- $likec4model,
190
+ $likec4model: (await loadModel(projectId)).$likec4model,
19
191
  projectId
20
192
  };
21
193
  },
@@ -25,8 +197,58 @@ function RouteComponent$1() {
25
197
  const { $likec4model, projectId } = Route$b.useLoaderData();
26
198
  return /* @__PURE__ */ jsx(ViewOutlet, { children: /* @__PURE__ */ jsx(m, { FallbackComponent: Fallback, children: /* @__PURE__ */ jsx(LikeC4IconRendererContext, { projectId, children: /* @__PURE__ */ jsx(LikeC4ModelContext, { likec4model: $likec4model, children: /* @__PURE__ */ jsx(Outlet, {}) }) }) }) });
27
199
  }
200
+ function useTransparentBackground(enabled = !0) {
201
+ useIsomorphicLayoutEffect(() => {
202
+ const htmlEl = document.body.parentElement;
203
+ if (!htmlEl || enabled !== !0) return;
204
+ const classname = "transparent-bg";
205
+ return htmlEl.classList.add(classname), () => {
206
+ htmlEl.classList.remove(classname);
207
+ };
208
+ }, [enabled]);
209
+ }
210
+ function useLikeC4Views() {
211
+ const $likec4model = useLikeC4ModelAtom(), [views, setViews] = useState([]);
212
+ return useEffect(() => $likec4model.subscribe((next) => {
213
+ setViews((prev) => {
214
+ const nextViews = [...next.views()].map((v) => {
215
+ const n = v.$layouted, p = prev.find((_) => _.id === v.id);
216
+ return p && deepEqual(n, p) ? p : n;
217
+ });
218
+ return shallowEqual(prev, nextViews) ? prev : nextViews;
219
+ });
220
+ }), [$likec4model]), views;
221
+ }
222
+ function useCurrentViewId() {
223
+ return useParams({
224
+ select: (params) => params.viewId,
225
+ strict: !1
226
+ }) ?? "index";
227
+ }
228
+ function useCurrentView() {
229
+ const viewId = useCurrentViewId(), $likec4model = useLikeC4ModelAtom(), [layoutType, setLayoutType] = useState("manual");
230
+ useUpdateEffect(() => {
231
+ setLayoutType("manual");
232
+ }, [viewId]);
233
+ const [view, setView] = useState(() => $likec4model.get().findView(viewId)?.$layouted ?? null);
234
+ return useEffect(() => $likec4model.subscribe((next) => {
235
+ setView((current) => {
236
+ const vm = next.findView(viewId);
237
+ if (!vm)
238
+ return null;
239
+ const nextView = layoutType === "auto" ? vm.$view : vm.$layouted;
240
+ return deepEqual(current, nextView) ? current : nextView;
241
+ });
242
+ }), [$likec4model, viewId, layoutType]), [view, setLayoutType];
243
+ }
244
+ function useCurrentProject() {
245
+ const projects = useLikeC4Projects(), projectId = useMatches({
246
+ select: (m2) => m2.find((m22) => m22.routeId === "/project/$projectId")?.params?.projectId ?? m2.at(-1)?.context.projectId ?? "default"
247
+ });
248
+ return projects.find((p) => p.id === projectId) ?? projects[0];
249
+ }
28
250
  css({
29
- color: "mantine.colors.dimmed"
251
+ color: "text.dimmed"
30
252
  });
31
253
  css({
32
254
  // background: 'var(--color-surface)',
@@ -37,7 +259,7 @@ const previewBg = css({
37
259
  padding: "0",
38
260
  margin: "0",
39
261
  backgroundOrigin: "padding-box",
40
- backgroundImage: "radial-gradient({colors.mantine.colors.defaultBorder} 15%, {colors.mantine.colors.body} 15%)",
262
+ backgroundImage: "radial-gradient({colors.default.border} 15%, {colors.body} 15%)",
41
263
  backgroundPosition: "0 0",
42
264
  backgroundSize: "12px 12px",
43
265
  _after: {
@@ -74,7 +296,7 @@ function ViewCard({ view }) {
74
296
  const [visible, setVisible] = useState(!1), { ref, inViewport } = useInViewport();
75
297
  return useEffect(() => {
76
298
  if (!inViewport || visible) return;
77
- const tm = setTimeout(() => setVisible(!0), e(30, 80));
299
+ const tm = setTimeout(() => setVisible(!0), e$3(30, 80));
78
300
  return () => clearTimeout(tm);
79
301
  }, [inViewport, visible]), /* @__PURE__ */ jsxs(
80
302
  Card,
@@ -119,6 +341,18 @@ function ViewCard({ view }) {
119
341
  }
120
342
  );
121
343
  }
344
+ function AdHocViewEditor({ projectId }) {
345
+ return /* @__PURE__ */ jsx(
346
+ LikeC4AdHocViewEditor,
347
+ {
348
+ service: {
349
+ process: async ({ predicates }) => ({
350
+ view: await likec4rpc.calcAdhocView({ projectId, predicates })
351
+ })
352
+ }
353
+ }
354
+ );
355
+ }
122
356
  const Route$9 = createFileRoute("/_single/adhoc")({
123
357
  beforeLoad: () => {
124
358
  if (!isRpcAvailable)
@@ -201,6 +435,411 @@ function WebcomponentPage() {
201
435
  }
202
436
  );
203
437
  }
438
+ function ColorSchemeToggle() {
439
+ const { setColorScheme } = useMantineColorScheme({
440
+ keepTransitions: !0
441
+ }), computedColorScheme = useComputedColorScheme("light");
442
+ return /* @__PURE__ */ jsxs(
443
+ ActionIcon,
444
+ {
445
+ visibleFrom: "sm",
446
+ size: "md",
447
+ variant: "subtle",
448
+ color: "gray",
449
+ onClick: () => setColorScheme(computedColorScheme === "light" ? "dark" : "light"),
450
+ "aria-label": "Toggle color scheme",
451
+ children: [
452
+ /* @__PURE__ */ jsx(IconMoonStars, { stroke: 1.5, display: computedColorScheme === "light" ? "block" : "none" }),
453
+ /* @__PURE__ */ jsx(IconSun, { stroke: 1.5, display: computedColorScheme === "dark" ? "block" : "none" })
454
+ ]
455
+ }
456
+ );
457
+ }
458
+ const { withProvider, withContext } = createStyleContext(navigationPanel), shouldForwardProp = (prop, variantKeys) => !variantKeys.includes(prop) && (isValidMotionProp(prop) || !isCssProperty(prop)), Root = withProvider(MotionDiv, "root", {
459
+ shouldForwardProp
460
+ }), Body = withContext(MotionDiv, "body", {
461
+ shouldForwardProp
462
+ });
463
+ withContext(MotionDiv, "label", {
464
+ shouldForwardProp
465
+ });
466
+ withContext(MotionDiv, "dropdown", {
467
+ shouldForwardProp
468
+ });
469
+ const NavigationPanel = {
470
+ Root,
471
+ Body
472
+ };
473
+ function SelectProject() {
474
+ const projects = useLikeC4Projects$1(), project = useCurrentProject();
475
+ return projects.length < 2 ? null : /* @__PURE__ */ jsxs(Menu, { shadow: "md", width: 200, trigger: "click-hover", openDelay: 200, children: [
476
+ /* @__PURE__ */ jsx(MenuTarget, { children: /* @__PURE__ */ jsx(
477
+ Button,
478
+ {
479
+ variant: "subtle",
480
+ size: "sm",
481
+ color: "gray",
482
+ px: "sm",
483
+ rightSection: /* @__PURE__ */ jsx(IconChevronDown, { opacity: 0.5, size: 14 }),
484
+ visibleFrom: "md",
485
+ children: project.title ?? project.id
486
+ }
487
+ ) }),
488
+ /* @__PURE__ */ jsxs(MenuDropdown, { children: [
489
+ /* @__PURE__ */ jsx(
490
+ MenuItem,
491
+ {
492
+ renderRoot: (props) => /* @__PURE__ */ jsx(
493
+ Link,
494
+ {
495
+ ...props,
496
+ to: "/projects"
497
+ }
498
+ ),
499
+ children: "Projects overview"
500
+ }
501
+ ),
502
+ /* @__PURE__ */ jsx(MenuDivider, {}),
503
+ projects.map(({ id, title: title2 }) => /* @__PURE__ */ jsx(
504
+ MenuItem,
505
+ {
506
+ renderRoot: (props) => /* @__PURE__ */ jsx(
507
+ Link,
508
+ {
509
+ ...props,
510
+ to: "/project/$projectId/view/$viewId/",
511
+ params: {
512
+ projectId: id,
513
+ viewId: "index"
514
+ }
515
+ }
516
+ ),
517
+ children: title2 ?? id
518
+ },
519
+ id
520
+ ))
521
+ ] })
522
+ ] });
523
+ }
524
+ const AlertLocalhost = () => /* @__PURE__ */ jsx(
525
+ Alert,
526
+ {
527
+ color: "yellow",
528
+ icon: /* @__PURE__ */ jsx(IconAlertTriangle, {}),
529
+ title: "Localhost URL",
530
+ styles: { body: { gap: rem(4) } },
531
+ children: /* @__PURE__ */ jsx(Text, { c: "yellow", size: "sm", children: "You need to deploy your project to make it available on the internet" })
532
+ }
533
+ ), CopyButtonChild = ({ copied, copy }) => /* @__PURE__ */ jsx(
534
+ Button,
535
+ {
536
+ size: "xs",
537
+ color: copied ? "teal" : "gray",
538
+ variant: "light",
539
+ leftSection: copied ? /* @__PURE__ */ jsx(IconCheck, { style: { width: rem(16) } }) : /* @__PURE__ */ jsx(IconCopy, { style: { width: rem(16) } }),
540
+ onClick: copy,
541
+ children: copied ? "Copied" : "Copy to clipboard"
542
+ }
543
+ ), EmbedPanel = ({ diagram }) => {
544
+ const router = useRouter(), { colorScheme } = useMantineColorScheme(), [theme, setTheme] = useState(colorScheme), padding = 20;
545
+ let location = router.buildLocation({
546
+ to: "/embed/$viewId/",
547
+ // '/' at the end added by Gemini 3, must have to pass typecheck
548
+ params: { viewId: diagram.id },
549
+ search: {
550
+ padding,
551
+ ...theme !== "auto" ? { theme } : {}
552
+ // changed from "theme: theme !== 'auto' ? theme : undefined" by Gemini 3
553
+ }
554
+ }).href;
555
+ location = useHashHistory ? `#${location}` : location;
556
+ const url = new URL(location, window.location.href), width = diagram.bounds.width + padding * 2, height = diagram.bounds.height + padding * 2, href = url.href, code = `
557
+ <div style="aspect-ratio:${width}/${height};width:100%;height:auto;max-width:${width}px;margin:0 auto">
558
+ <iframe src="${href}" width="100%" height="100%" style="border:0;background:transparent;"></iframe>
559
+ </div>
560
+ `.trim();
561
+ return /* @__PURE__ */ jsxs(Stack, { children: [
562
+ code.includes("http://localhost") && /* @__PURE__ */ jsx(AlertLocalhost, {}),
563
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: "Embedded view is an iframe with a static diagram" }) }),
564
+ /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
565
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
566
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { fw: "500", size: "sm", children: "HTML" }) }),
567
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
568
+ /* @__PURE__ */ jsx(ActionIcon, { component: "a", href, target: "_blank", variant: "light", color: "gray", children: /* @__PURE__ */ jsx(IconExternalLink, {}) }),
569
+ /* @__PURE__ */ jsx(CopyButton$1, { value: code, timeout: 1500, children: CopyButtonChild })
570
+ ] })
571
+ ] }),
572
+ /* @__PURE__ */ jsx(Code, { block: !0, children: code }),
573
+ /* @__PURE__ */ jsx(
574
+ Box,
575
+ {
576
+ style: {
577
+ alignSelf: "flex-start"
578
+ },
579
+ children: /* @__PURE__ */ jsx(
580
+ Select,
581
+ {
582
+ label: "Color scheme",
583
+ value: theme,
584
+ allowDeselect: !1,
585
+ onChange: (v) => setTheme(v ?? "auto"),
586
+ data: [
587
+ { value: "auto", label: "Auto" },
588
+ { value: "light", label: "Light" },
589
+ { value: "dark", label: "Dark" }
590
+ ]
591
+ }
592
+ )
593
+ }
594
+ )
595
+ ] })
596
+ ] });
597
+ };
598
+ function WebcomponentsPanel({ diagram }) {
599
+ const router = useRouter();
600
+ let base = router.basepath.endsWith("/") ? router.basepath : `${router.basepath}/`;
601
+ const jscode = `
602
+ <script module src="${new URL(
603
+ `${base}likec4-views.js`,
604
+ window.location.href
605
+ ).href}"><\/script>
606
+ `.trim(), htmlCode = `
607
+ <${ComponentName.View}
608
+ view-id="${encodeURIComponent(diagram.id)}"
609
+ browser="true"
610
+ dynamic-variant="sequence">
611
+ </${ComponentName.View}>
612
+ `.trim(), webcomponentPreview = router.buildLocation(
613
+ {
614
+ to: "/webcomponent/$/",
615
+ // '/' at the end added by Gemini 3, must have to pass typecheck
616
+ params: { _splat: diagram.id },
617
+ search: !0
618
+ }
619
+ );
620
+ return /* @__PURE__ */ jsxs(Stack, { children: [
621
+ jscode.includes("http://localhost") && /* @__PURE__ */ jsx(AlertLocalhost, {}),
622
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { size: "sm", children: "Add this script to your page:" }) }),
623
+ /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
624
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
625
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { fw: "500", size: "sm", children: "JavaScript" }) }),
626
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
627
+ /* @__PURE__ */ jsx(ActionIcon, { component: "a", href: webcomponentPreview.href, target: "_blank", variant: "light", color: "gray", children: /* @__PURE__ */ jsx(IconExternalLink, {}) }),
628
+ /* @__PURE__ */ jsx(
629
+ CopyButton$1,
630
+ {
631
+ value: jscode,
632
+ timeout: 1500,
633
+ children: CopyButtonChild
634
+ }
635
+ )
636
+ ] })
637
+ ] }),
638
+ /* @__PURE__ */ jsx(Code, { block: !0, children: jscode }),
639
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
640
+ "This script defines a custom element (webcomponent) that renders your diagrams.",
641
+ /* @__PURE__ */ jsx("br", {}),
642
+ "Script must be inserted once in the ",
643
+ /* @__PURE__ */ jsx("code", { children: "<head>" }),
644
+ " or at the end of the ",
645
+ /* @__PURE__ */ jsx("code", { children: "<body>" }),
646
+ " ",
647
+ "tag."
648
+ ] }) })
649
+ ] }),
650
+ /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
651
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
652
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { fw: "500", size: "sm", children: "HTML" }) }),
653
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
654
+ CopyButton$1,
655
+ {
656
+ value: htmlCode,
657
+ timeout: 1500,
658
+ children: CopyButtonChild
659
+ }
660
+ ) })
661
+ ] }),
662
+ /* @__PURE__ */ jsx(Code, { block: !0, children: htmlCode }),
663
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
664
+ "Insert this code to your page. Page may have multiple ",
665
+ /* @__PURE__ */ jsx("code", { children: "<likec4-view>" }),
666
+ "."
667
+ ] }) })
668
+ ] })
669
+ ] });
670
+ }
671
+ function ShareModal({
672
+ onClose
673
+ }) {
674
+ const [diagram] = useCurrentView(), [activeTab, setActiveTab] = useState("webcomponent");
675
+ return diagram ? /* @__PURE__ */ jsxs(
676
+ ModalRoot,
677
+ {
678
+ size: "xl",
679
+ opened: !0,
680
+ onClose,
681
+ children: [
682
+ /* @__PURE__ */ jsx(ModalOverlay, { backgroundOpacity: 0.5, blur: 3 }),
683
+ /* @__PURE__ */ jsx(ModalContent, { children: /* @__PURE__ */ jsxs(ModalBody, { children: [
684
+ /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onChange: (tab) => setActiveTab(tab ?? "webcomponent"), children: [
685
+ /* @__PURE__ */ jsxs(TabsList, { children: [
686
+ /* @__PURE__ */ jsx(TabsTab, { value: "webcomponent", children: "Webcomponent" }),
687
+ /* @__PURE__ */ jsx(TabsTab, { value: "embed", children: "Embedded" })
688
+ ] }),
689
+ /* @__PURE__ */ jsx(TabsPanel, { value: "embed", pt: "md", children: /* @__PURE__ */ jsx(EmbedPanel, { diagram }) }),
690
+ /* @__PURE__ */ jsx(TabsPanel, { value: "webcomponent", pt: "md", children: /* @__PURE__ */ jsx(WebcomponentsPanel, { diagram }) })
691
+ ] }),
692
+ /* @__PURE__ */ jsx(Group, { justify: "flex-end", mt: "lg", children: /* @__PURE__ */ jsx(Button, { size: "sm", onClick: onClose, children: "Close" }) })
693
+ ] }) })
694
+ ]
695
+ }
696
+ ) : null;
697
+ }
698
+ const Header = memo(() => {
699
+ const projects = useLikeC4Projects$1(), isReactDiagramRoute = useMatches({
700
+ select(matches) {
701
+ return matches.some(
702
+ ({ routeId }) => routeId === "/_single/view/$viewId/" || routeId === "/project/$projectId/view/$viewId/"
703
+ );
704
+ }
705
+ }), { breakpoints } = useMantineTheme(), isTablet = useMediaQuery(`(min-width: ${breakpoints.md})`) ?? !1, [opened, { open, close }] = useDisclosure(!1);
706
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
707
+ /* @__PURE__ */ jsx(NavigationPanel.Root, { panelPosition: "right", hideBelow: "md", children: /* @__PURE__ */ jsxs(NavigationPanel.Body, { gap: "2", children: [
708
+ isReactDiagramRoute ? /* @__PURE__ */ jsxs(Fragment, { children: [
709
+ /* @__PURE__ */ jsx(SelectProject, {}),
710
+ projects.length <= 1 && /* @__PURE__ */ jsx(
711
+ Button,
712
+ {
713
+ size: isTablet ? "sm" : "xs",
714
+ leftSection: /* @__PURE__ */ jsx(IconShare, { size: 14 }),
715
+ onClick: open,
716
+ children: "Share"
717
+ }
718
+ ),
719
+ /* @__PURE__ */ jsx(ExportButton, {})
720
+ ] }) : /* @__PURE__ */ jsx(
721
+ Button,
722
+ {
723
+ component: Link,
724
+ to: "/view/$viewId/",
725
+ size: isTablet ? "sm" : "xs",
726
+ variant: "subtle",
727
+ color: "gray",
728
+ children: "Back to diagram"
729
+ }
730
+ ),
731
+ /* @__PURE__ */ jsx(Divider, { orientation: "vertical", visibleFrom: "md" }),
732
+ /* @__PURE__ */ jsx(ColorSchemeToggle, {})
733
+ ] }) }),
734
+ opened && /* @__PURE__ */ jsx(ShareModal, { onClose: close })
735
+ ] });
736
+ }), enableDownload = (params) => ({
737
+ ...params,
738
+ download: !0
739
+ });
740
+ function ExportButton() {
741
+ const isInsideProject = useMatches({
742
+ select: (matches) => matches.some(({ routeId }) => routeId === "/project/$projectId")
743
+ }), project = useCurrentProject(), viewId = useCurrentViewId(), handleDrawioExport = useCallback(async () => {
744
+ try {
745
+ const { loadDrawioSources } = await import("likec4:drawio"), { drawioEditUrl } = await loadDrawioSources(project.id), url = drawioEditUrl(viewId);
746
+ window.open(url, "_blank", "noopener,noreferrer");
747
+ } catch (error) {
748
+ console.error("Failed to export to Draw.io:", error);
749
+ }
750
+ }, [project.id, viewId]);
751
+ return /* @__PURE__ */ jsxs(Menu, { shadow: "md", width: 200, trigger: "click-hover", openDelay: 200, children: [
752
+ /* @__PURE__ */ jsx(MenuTarget, { children: /* @__PURE__ */ jsx(
753
+ Button,
754
+ {
755
+ variant: "subtle",
756
+ size: "sm",
757
+ color: "gray",
758
+ px: "sm",
759
+ rightSection: /* @__PURE__ */ jsx(IconChevronDown, { opacity: 0.5, size: 14 }),
760
+ visibleFrom: "md",
761
+ children: "Export"
762
+ }
763
+ ) }),
764
+ /* @__PURE__ */ jsxs(MenuDropdown, { children: [
765
+ /* @__PURE__ */ jsx(MenuLabel, { children: "Current view" }),
766
+ /* @__PURE__ */ jsx(
767
+ MenuItem,
768
+ {
769
+ renderRoot: (props) => /* @__PURE__ */ jsx(
770
+ Link,
771
+ {
772
+ target: "_blank",
773
+ to: isInsideProject ? "/project/$projectId/export/$viewId/" : "/export/$viewId/",
774
+ search: enableDownload,
775
+ ...props
776
+ }
777
+ ),
778
+ children: "Export as .png"
779
+ }
780
+ ),
781
+ /* @__PURE__ */ jsx(
782
+ MenuItem,
783
+ {
784
+ renderRoot: (props) => /* @__PURE__ */ jsx(
785
+ Link,
786
+ {
787
+ to: isInsideProject ? "/project/$projectId/view/$viewId/dot/" : "/view/$viewId/dot/",
788
+ search: !0,
789
+ ...props
790
+ }
791
+ ),
792
+ children: "Export as .dot"
793
+ }
794
+ ),
795
+ /* @__PURE__ */ jsx(
796
+ MenuItem,
797
+ {
798
+ renderRoot: (props) => /* @__PURE__ */ jsx(
799
+ Link,
800
+ {
801
+ to: isInsideProject ? "/project/$projectId/view/$viewId/d2" : "/view/$viewId/d2",
802
+ search: !0,
803
+ ...props
804
+ }
805
+ ),
806
+ children: "Export as .d2"
807
+ }
808
+ ),
809
+ /* @__PURE__ */ jsx(
810
+ MenuItem,
811
+ {
812
+ renderRoot: (props) => /* @__PURE__ */ jsx(
813
+ Link,
814
+ {
815
+ to: isInsideProject ? "/project/$projectId/view/$viewId/mmd" : "/view/$viewId/mmd",
816
+ search: !0,
817
+ ...props
818
+ }
819
+ ),
820
+ children: "Export as .mmd"
821
+ }
822
+ ),
823
+ /* @__PURE__ */ jsx(
824
+ MenuItem,
825
+ {
826
+ renderRoot: (props) => /* @__PURE__ */ jsx(
827
+ Link,
828
+ {
829
+ to: isInsideProject ? "/project/$projectId/view/$viewId/puml" : "/view/$viewId/puml",
830
+ search: !0,
831
+ ...props
832
+ }
833
+ ),
834
+ children: "Export as .puml"
835
+ }
836
+ ),
837
+ /* @__PURE__ */ jsx(MenuItem, { onClick: handleDrawioExport, children: "Export to Draw.io" }),
838
+ /* @__PURE__ */ jsx(MenuItem, { disabled: !0, children: "Export to Miro" }),
839
+ /* @__PURE__ */ jsx(MenuItem, { disabled: !0, children: "Export to Notion" })
840
+ ] })
841
+ ] });
842
+ }
204
843
  const Route$7 = createFileRoute("/_single/view/$viewId")({
205
844
  component: ViewLayout,
206
845
  errorComponent: ({ error, reset }) => /* @__PURE__ */ jsx(Fallback, { error, resetErrorBoundary: reset })
@@ -211,6 +850,113 @@ function ViewLayout() {
211
850
  /* @__PURE__ */ jsx(Header, {})
212
851
  ] });
213
852
  }
853
+ async function downloadAsPng({
854
+ pngFilename,
855
+ viewport
856
+ }) {
857
+ try {
858
+ const blob = await toBlob(viewport, {
859
+ backgroundColor: "transparent",
860
+ cacheBust: !0,
861
+ imagePlaceholder: "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
862
+ });
863
+ if (!blob)
864
+ throw new Error("Failed to create PNG blob");
865
+ var url = URL.createObjectURL(blob), link = document.createElement("a");
866
+ 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();
867
+ } catch (err) {
868
+ console.error(err), window.alert("Failed to export to PNG, check the console for more details.");
869
+ }
870
+ }
871
+ function ExportPage() {
872
+ const [diagram] = useCurrentView();
873
+ return useTransparentBackground(), diagram ? /* @__PURE__ */ jsx(GuardedExportPage, { diagram }) : /* @__PURE__ */ jsx("div", { children: "Loading..." });
874
+ }
875
+ function GuardedExportPage({ diagram }) {
876
+ const {
877
+ padding = 20,
878
+ download = !1,
879
+ dynamic
880
+ } = useSearch({
881
+ strict: !1
882
+ }), viewportRef = useRef(null), loadingOverlayRef = useRef(null), downloadedRef = useRef(!1), bounds = pickViewBounds(diagram, dynamic), downloadDiagram = () => {
883
+ const viewport = viewportRef.current;
884
+ if (!download || !viewport || !diagram || downloadedRef.current)
885
+ return;
886
+ const loadingOverlay = loadingOverlayRef.current;
887
+ loadingOverlay && (loadingOverlay.style.display = "none"), downloadedRef.current = !0, downloadAsPng({
888
+ pngFilename: diagram.id,
889
+ viewport
890
+ });
891
+ }, extraPadding = 16, width = bounds.width + padding * 2 + extraPadding, height = bounds.height + padding * 2 + extraPadding;
892
+ return /* @__PURE__ */ jsxs(
893
+ Box$1,
894
+ {
895
+ ref: viewportRef,
896
+ "data-testid": "export-page",
897
+ css: {
898
+ position: "fixed",
899
+ top: "0",
900
+ left: "0",
901
+ padding: "0",
902
+ margin: "0",
903
+ background: "transparent",
904
+ overflow: "hidden",
905
+ zIndex: 2
906
+ },
907
+ style: {
908
+ marginRight: "auto",
909
+ marginBottom: "auto",
910
+ minWidth: width,
911
+ width,
912
+ minHeight: height,
913
+ height
914
+ },
915
+ children: [
916
+ download && /* @__PURE__ */ jsx(LoadingOverlay, { ref: loadingOverlayRef, visible: !0 }),
917
+ /* @__PURE__ */ jsx(
918
+ LikeC4Diagram,
919
+ {
920
+ view: diagram,
921
+ fitView: !1,
922
+ fitViewPadding: {
923
+ top: "0px",
924
+ bottom: "0px",
925
+ left: "0px",
926
+ right: "0px"
927
+ },
928
+ background: "transparent",
929
+ reduceGraphics: !1,
930
+ dynamicViewVariant: dynamic,
931
+ className: "likec4-static-view",
932
+ pannable: !1,
933
+ zoomable: !1,
934
+ controls: !1,
935
+ enableNotations: !1,
936
+ enableElementDetails: !1,
937
+ enableRelationshipDetails: !1,
938
+ enableRelationshipBrowser: !1,
939
+ enableDynamicViewWalkthrough: !1,
940
+ enableFocusMode: !1,
941
+ enableSearch: !1,
942
+ nodesSelectable: !1,
943
+ enableElementTags: !1,
944
+ onInitialized: () => {
945
+ if (!viewportRef.current) {
946
+ console.error("viewportRef.current is null");
947
+ return;
948
+ }
949
+ const x = Math.round(-bounds.x + padding), y = Math.round(-bounds.y + padding);
950
+ [...viewportRef.current.querySelectorAll(".react-flow__viewport")].forEach((el) => {
951
+ el.style.transform = "translate(" + x + "px, " + y + "px)";
952
+ }), download && window.setTimeout(downloadDiagram, 500);
953
+ }
954
+ }
955
+ )
956
+ ]
957
+ }
958
+ );
959
+ }
214
960
  const Route$6 = createFileRoute("/_single/export/$viewId")({
215
961
  validateSearch: z.object({
216
962
  download: z.boolean().optional().catch(!1)
@@ -223,11 +969,318 @@ const Route$6 = createFileRoute("/_single/export/$viewId")({
223
969
  ]
224
970
  },
225
971
  component: ExportPage
226
- }), Route$5 = createFileRoute("/_single/embed/$viewId")({
972
+ });
973
+ function EmbedPage() {
974
+ const {
975
+ padding = 20,
976
+ dynamic
977
+ } = useSearch({
978
+ strict: !1
979
+ }), [diagram] = useCurrentView();
980
+ if (useTransparentBackground(!!diagram), !diagram)
981
+ return /* @__PURE__ */ jsx("div", { children: "Loading..." });
982
+ const bounds = pickViewBounds(diagram, dynamic);
983
+ return /* @__PURE__ */ jsx(
984
+ "div",
985
+ {
986
+ style: {
987
+ position: "absolute",
988
+ top: 0,
989
+ left: "50%",
990
+ boxSizing: "border-box",
991
+ padding,
992
+ transform: "translateX(-50%)",
993
+ aspectRatio: `${bounds.width + padding * 2} / ${bounds.height + padding * 2}`,
994
+ width: "100vw",
995
+ maxWidth: bounds.width + padding * 2,
996
+ height: "auto",
997
+ maxHeight: "100vh"
998
+ },
999
+ children: /* @__PURE__ */ jsx(
1000
+ StaticLikeC4Diagram,
1001
+ {
1002
+ view: diagram,
1003
+ fitView: !0,
1004
+ background: "transparent",
1005
+ fitViewPadding: 0,
1006
+ dynamicViewVariant: dynamic,
1007
+ initialWidth: bounds.width,
1008
+ initialHeight: bounds.height
1009
+ }
1010
+ )
1011
+ }
1012
+ );
1013
+ }
1014
+ const Route$5 = createFileRoute("/_single/embed/$viewId")({
227
1015
  component: EmbedPage
228
- }), Route$4 = createFileRoute("/_single/view/$viewId/")({
1016
+ });
1017
+ function ViewReact() {
1018
+ const navigate = useNavigate(), [view, setLayoutType] = useCurrentView(), model = useLikeC4Model(), { dynamic } = useSearch({
1019
+ from: "__root__"
1020
+ }), onNavigateTo = useCallbackRef((viewId) => {
1021
+ navigate({
1022
+ to: "./",
1023
+ viewTransition: !1,
1024
+ params: (current) => ({
1025
+ ...current,
1026
+ viewId
1027
+ }),
1028
+ search: !0
1029
+ });
1030
+ }), title2 = view ? view.title ?? view.id : "View not found", pageTitle$1 = model.project.title ?? pageTitle;
1031
+ if (useDocumentTitle(`${title2} - ${pageTitle$1}`), !view)
1032
+ return /* @__PURE__ */ jsx(NotFound, {});
1033
+ const hasNotations = (view.notation?.nodes ?? []).length > 0;
1034
+ return /* @__PURE__ */ jsxs(
1035
+ LikeC4Diagram,
1036
+ {
1037
+ view,
1038
+ zoomable: !0,
1039
+ pannable: !0,
1040
+ controls: !0,
1041
+ fitViewPadding: {
1042
+ top: "70px",
1043
+ bottom: "32px",
1044
+ left: "32px",
1045
+ right: "32px"
1046
+ },
1047
+ showNavigationButtons: !0,
1048
+ enableSearch: !0,
1049
+ enableFocusMode: !0,
1050
+ enableDynamicViewWalkthrough: !0,
1051
+ dynamicViewVariant: dynamic,
1052
+ enableElementDetails: !0,
1053
+ enableRelationshipDetails: !0,
1054
+ enableRelationshipBrowser: !0,
1055
+ enableElementTags: !0,
1056
+ enableCompareWithLatest: !0,
1057
+ enableNotations: hasNotations,
1058
+ nodesSelectable: !0,
1059
+ onNavigateTo,
1060
+ onLayoutTypeChange: setLayoutType,
1061
+ onLogoClick: () => {
1062
+ navigate({
1063
+ to: "/"
1064
+ });
1065
+ },
1066
+ children: [
1067
+ /* @__PURE__ */ jsx(ListenForDynamicVariantChange, {}),
1068
+ /* @__PURE__ */ jsx(OpenRelationshipBrowserFromUrl, {})
1069
+ ]
1070
+ }
1071
+ );
1072
+ }
1073
+ function OpenRelationshipBrowserFromUrl() {
1074
+ const router = useRouter(), diagram = useDiagram(), { relationships } = useSearch({
1075
+ from: "__root__"
1076
+ }), processedRef = useRef(null), isInitializedRef = useRef(!1), isProcessingRef = useRef(Promise.resolve()), isMounted = useIsMounted(), openAndClear = (fqn) => {
1077
+ isProcessingRef.current = isProcessingRef.current.then(async () => {
1078
+ if (!(!isMounted() || processedRef.current === fqn))
1079
+ try {
1080
+ processedRef.current = fqn, diagram.openRelationshipsBrowser(fqn), await router.buildAndCommitLocation({
1081
+ search: (s) => {
1082
+ const { relationships: _, ...rest } = s;
1083
+ return rest;
1084
+ },
1085
+ replace: !0,
1086
+ viewTransition: !1
1087
+ });
1088
+ } catch (error) {
1089
+ console.error("Failed to open relationship browser:", error);
1090
+ }
1091
+ });
1092
+ }, process = () => {
1093
+ if (!relationships) {
1094
+ processedRef.current = null;
1095
+ return;
1096
+ }
1097
+ relationships && processedRef.current !== relationships && openAndClear(relationships);
1098
+ };
1099
+ return useOnDiagramEvent("initialized", () => {
1100
+ isInitializedRef.current = !0, process();
1101
+ }), useUpdateEffect(() => {
1102
+ process();
1103
+ }, [relationships]), null;
1104
+ }
1105
+ function ListenForDynamicVariantChange() {
1106
+ const router = useRouter(), dynamicViewVariant = useDiagramContext((c) => c.dynamicViewVariant);
1107
+ return useUpdateEffect(() => {
1108
+ (router.latestLocation.search.dynamic ?? "diagram") !== dynamicViewVariant && router.buildAndCommitLocation({
1109
+ search: (current) => ({
1110
+ ...current,
1111
+ dynamic: dynamicViewVariant
1112
+ }),
1113
+ viewTransition: !1
1114
+ });
1115
+ }, [dynamicViewVariant]), null;
1116
+ }
1117
+ function ViewEditor() {
1118
+ const navigate = useNavigate(), project = useCurrentProject(), [view, setLayoutType] = useCurrentView(), $likec4model = useLikeC4ModelAtom(), { dynamic } = useSearch({ strict: !1 }), onNavigateTo = useCallbackRef((viewId) => {
1119
+ navigate({
1120
+ to: "./",
1121
+ viewTransition: !1,
1122
+ params: (current) => ({
1123
+ ...current,
1124
+ viewId
1125
+ }),
1126
+ search: !0
1127
+ });
1128
+ });
1129
+ if (!view)
1130
+ return /* @__PURE__ */ jsx(NotFound, {});
1131
+ const hasNotations = (view.notation?.nodes ?? []).length > 0;
1132
+ return /* @__PURE__ */ jsx(
1133
+ LikeC4EditorProvider,
1134
+ {
1135
+ editor: {
1136
+ fetchView: (id, layout) => {
1137
+ const model = $likec4model.get().view(id);
1138
+ return layout === "auto" ? model.$view : model.$layouted;
1139
+ },
1140
+ handleChange: (viewId, change) => {
1141
+ const event = {
1142
+ projectId: project.id,
1143
+ viewId,
1144
+ change
1145
+ };
1146
+ return likec4rpc.updateView(event);
1147
+ }
1148
+ },
1149
+ children: /* @__PURE__ */ jsxs(
1150
+ LikeC4Diagram,
1151
+ {
1152
+ view,
1153
+ zoomable: !0,
1154
+ pannable: !0,
1155
+ controls: !0,
1156
+ fitViewPadding: {
1157
+ top: "70px",
1158
+ bottom: "32px",
1159
+ left: "50px",
1160
+ right: "32px"
1161
+ },
1162
+ showNavigationButtons: !0,
1163
+ enableNotations: isDevelopment || hasNotations,
1164
+ enableSearch: !0,
1165
+ enableDynamicViewWalkthrough: !0,
1166
+ enableFocusMode: !0,
1167
+ enableElementDetails: !0,
1168
+ enableRelationshipDetails: !0,
1169
+ enableRelationshipBrowser: !0,
1170
+ enableElementTags: !0,
1171
+ enableCompareWithLatest: !0,
1172
+ dynamicViewVariant: dynamic,
1173
+ onNavigateTo,
1174
+ onLayoutTypeChange: setLayoutType,
1175
+ onLogoClick: () => {
1176
+ navigate({
1177
+ to: "/"
1178
+ });
1179
+ },
1180
+ children: [
1181
+ /* @__PURE__ */ jsx(ListenForDynamicVariantChange, {}),
1182
+ /* @__PURE__ */ jsx(OpenRelationshipBrowserFromUrl, {})
1183
+ ]
1184
+ }
1185
+ )
1186
+ }
1187
+ );
1188
+ }
1189
+ const Route$4 = createFileRoute("/_single/view/$viewId/")({
229
1190
  component: isRpcAvailable ? ViewEditor : ViewReact
230
- }), Route$3 = createFileRoute("/_single/view/$viewId/puml")({
1191
+ });
1192
+ function CopyButton({ text }) {
1193
+ 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) } }) }) }) });
1194
+ }
1195
+ function CopyToClipboard({ text }) {
1196
+ return /* @__PURE__ */ jsx(Box, { pos: "absolute", top: "0", right: "0", p: "4", children: /* @__PURE__ */ jsx(CopyButton, { text }) });
1197
+ }
1198
+ const svgContainer = css({
1199
+ minWidth: 300,
1200
+ "& svg": {
1201
+ width: "100%",
1202
+ height: "auto"
1203
+ }
1204
+ }), cssScrollArea = css({
1205
+ height: "100%",
1206
+ "& .mantine-ScrollArea-viewport": {
1207
+ minHeight: "100%"
1208
+ },
1209
+ "& .mantine-ScrollArea-viewport > div": {
1210
+ minHeight: "100%",
1211
+ height: "100%"
1212
+ }
1213
+ }), cssCodeBlock = css({
1214
+ minHeight: "100%"
1215
+ }), viewWithTopPadding = css({
1216
+ height: "100%",
1217
+ paddingTop: "[var(--header-height)]"
1218
+ }), fetchFromKroki$1 = async (puml) => await (await fetch(krokiPumlSvgUrl, {
1219
+ method: "POST",
1220
+ cache: "force-cache",
1221
+ body: JSON.stringify({
1222
+ diagram_source: puml,
1223
+ output_format: "svg"
1224
+ }),
1225
+ headers: {
1226
+ "Content-Type": "application/json"
1227
+ }
1228
+ })).text();
1229
+ function ViewAsPuml({ pumlSource }) {
1230
+ const [krokiSvg, { execute }] = useAsync(fetchFromKroki$1, null);
1231
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1232
+ Tt,
1233
+ {
1234
+ className: viewWithTopPadding,
1235
+ orientation: "horizontal",
1236
+ children: [
1237
+ /* @__PURE__ */ jsx(_t, { children: /* @__PURE__ */ jsxs(
1238
+ ScrollArea,
1239
+ {
1240
+ className: cssScrollArea,
1241
+ p: 5,
1242
+ styles: {
1243
+ viewport: {
1244
+ borderRadius: 6
1245
+ }
1246
+ },
1247
+ children: [
1248
+ /* @__PURE__ */ jsx(Code, { block: !0, className: cssCodeBlock, children: pumlSource }),
1249
+ /* @__PURE__ */ jsx(CopyToClipboard, { text: pumlSource })
1250
+ ]
1251
+ }
1252
+ ) }),
1253
+ /* @__PURE__ */ jsx(
1254
+ Ht,
1255
+ {
1256
+ style: {
1257
+ width: 10
1258
+ }
1259
+ }
1260
+ ),
1261
+ /* @__PURE__ */ jsx(_t, { children: /* @__PURE__ */ jsxs(ScrollArea, { h: "100%", children: [
1262
+ krokiSvg.status !== "success" && /* @__PURE__ */ jsxs(Fragment, { children: [
1263
+ /* @__PURE__ */ jsx(
1264
+ Button,
1265
+ {
1266
+ mt: "xs",
1267
+ variant: "light",
1268
+ disabled: krokiSvg.status === "loading",
1269
+ onClick: () => {
1270
+ execute(pumlSource);
1271
+ },
1272
+ children: krokiSvg.status === "loading" ? "Loading..." : "Render with Kroki"
1273
+ }
1274
+ ),
1275
+ krokiSvg.status === "error" && /* @__PURE__ */ jsx(Box$1, { children: krokiSvg.error?.message })
1276
+ ] }),
1277
+ 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" }) })
1278
+ ] }) })
1279
+ ]
1280
+ }
1281
+ ) });
1282
+ }
1283
+ const Route$3 = createFileRoute("/_single/view/$viewId/puml")({
231
1284
  component: Page$3,
232
1285
  staleTime: 1 / 0,
233
1286
  loader: async ({ params, context }) => {
@@ -246,6 +1299,53 @@ function Page$3() {
246
1299
  const { source } = Route$3.useLoaderData();
247
1300
  return /* @__PURE__ */ jsx(ViewAsPuml, { pumlSource: source });
248
1301
  }
1302
+ const renderSvg = async (viewId, diagram) => {
1303
+ const { default: mermaid } = await import("https://cdn.jsdelivr.net/npm/mermaid@11.12/dist/mermaid.esm.min.mjs");
1304
+ mermaid.initialize({
1305
+ theme: "dark"
1306
+ });
1307
+ const { svg } = await mermaid.render(viewId, diagram);
1308
+ return svg;
1309
+ };
1310
+ function ViewAsMmd({ viewId, mmdSource }) {
1311
+ const [mmdSvg, { execute }] = useAsync(renderSvg, null);
1312
+ return useEffect(() => {
1313
+ execute(viewId, mmdSource);
1314
+ }, [mmdSource]), /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1315
+ Tt,
1316
+ {
1317
+ className: viewWithTopPadding,
1318
+ orientation: "horizontal",
1319
+ children: [
1320
+ /* @__PURE__ */ jsx(_t, { children: /* @__PURE__ */ jsxs(
1321
+ ScrollArea,
1322
+ {
1323
+ className: cssScrollArea,
1324
+ p: 5,
1325
+ styles: {
1326
+ viewport: {
1327
+ borderRadius: 6
1328
+ }
1329
+ },
1330
+ children: [
1331
+ /* @__PURE__ */ jsx(Code, { block: !0, className: cssCodeBlock, children: mmdSource }),
1332
+ /* @__PURE__ */ jsx(CopyToClipboard, { text: mmdSource })
1333
+ ]
1334
+ }
1335
+ ) }),
1336
+ /* @__PURE__ */ jsx(
1337
+ Ht,
1338
+ {
1339
+ style: {
1340
+ width: 10
1341
+ }
1342
+ }
1343
+ ),
1344
+ /* @__PURE__ */ jsx(_t, { children: /* @__PURE__ */ jsx(ScrollArea, { h: "100%", children: mmdSvg.result && /* @__PURE__ */ jsx(Box$1, { className: svgContainer, dangerouslySetInnerHTML: { __html: mmdSvg.result } }) }) })
1345
+ ]
1346
+ }
1347
+ ) });
1348
+ }
249
1349
  const Route$2 = createFileRoute("/_single/view/$viewId/mmd")({
250
1350
  component: Page$2,
251
1351
  staleTime: 1 / 0,
@@ -265,6 +1365,35 @@ function Page$2() {
265
1365
  const { viewId } = Route$2.useParams(), { source } = Route$2.useLoaderData();
266
1366
  return /* @__PURE__ */ jsx(ViewAsMmd, { viewId, mmdSource: source });
267
1367
  }
1368
+ function ViewAsDot({ dot, dotSvg }) {
1369
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Tt, { className: viewWithTopPadding, children: [
1370
+ /* @__PURE__ */ jsx(_t, { children: /* @__PURE__ */ jsxs(
1371
+ ScrollArea,
1372
+ {
1373
+ className: cssScrollArea,
1374
+ p: 5,
1375
+ styles: {
1376
+ viewport: {
1377
+ borderRadius: 6
1378
+ }
1379
+ },
1380
+ children: [
1381
+ /* @__PURE__ */ jsx(Code, { block: !0, className: cssCodeBlock, children: dot }),
1382
+ /* @__PURE__ */ jsx(CopyToClipboard, { text: dot })
1383
+ ]
1384
+ }
1385
+ ) }),
1386
+ /* @__PURE__ */ jsx(
1387
+ Ht,
1388
+ {
1389
+ style: {
1390
+ width: 10
1391
+ }
1392
+ }
1393
+ ),
1394
+ /* @__PURE__ */ jsx(_t, { children: /* @__PURE__ */ jsx(ScrollArea, { h: "100%", children: /* @__PURE__ */ jsx("div", { className: svgContainer, dangerouslySetInnerHTML: { __html: dotSvg } }) }) })
1395
+ ] }) });
1396
+ }
268
1397
  const Route$1 = createFileRoute("/_single/view/$viewId/dot")({
269
1398
  component: Page$1,
270
1399
  staleTime: 1 / 0,
@@ -285,6 +1414,74 @@ function Page$1() {
285
1414
  const { dot, dotSvg } = Route$1.useLoaderData();
286
1415
  return /* @__PURE__ */ jsx(ViewAsDot, { dot, dotSvg });
287
1416
  }
1417
+ const fetchFromKroki = async (d2) => await (await fetch(krokiD2SvgUrl, {
1418
+ method: "POST",
1419
+ cache: "force-cache",
1420
+ body: JSON.stringify({
1421
+ diagram_source: d2,
1422
+ // diagram_options: {
1423
+ // theme: 'colorblind-clear'
1424
+ // },
1425
+ output_format: "svg"
1426
+ }),
1427
+ headers: {
1428
+ "Content-Type": "application/json"
1429
+ }
1430
+ })).text();
1431
+ function ViewAsD2({ d2Source }) {
1432
+ const [krokiSvg, { execute }] = useAsync(fetchFromKroki, null);
1433
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1434
+ Tt,
1435
+ {
1436
+ className: viewWithTopPadding,
1437
+ orientation: "horizontal",
1438
+ children: [
1439
+ /* @__PURE__ */ jsx(_t, { children: /* @__PURE__ */ jsxs(
1440
+ ScrollArea,
1441
+ {
1442
+ className: cssScrollArea,
1443
+ p: 5,
1444
+ styles: {
1445
+ viewport: {
1446
+ borderRadius: 6
1447
+ }
1448
+ },
1449
+ children: [
1450
+ /* @__PURE__ */ jsx(Code, { block: !0, className: cssCodeBlock, children: d2Source }),
1451
+ /* @__PURE__ */ jsx(CopyToClipboard, { text: d2Source })
1452
+ ]
1453
+ }
1454
+ ) }),
1455
+ /* @__PURE__ */ jsx(
1456
+ Ht,
1457
+ {
1458
+ style: {
1459
+ width: 10
1460
+ }
1461
+ }
1462
+ ),
1463
+ /* @__PURE__ */ jsx(_t, { children: /* @__PURE__ */ jsxs(ScrollArea, { h: "100%", children: [
1464
+ krokiSvg.status !== "success" && /* @__PURE__ */ jsxs(Fragment, { children: [
1465
+ /* @__PURE__ */ jsx(
1466
+ Button,
1467
+ {
1468
+ mt: "xs",
1469
+ variant: "light",
1470
+ disabled: krokiSvg.status === "loading",
1471
+ onClick: () => {
1472
+ execute(d2Source);
1473
+ },
1474
+ children: krokiSvg.status === "loading" ? "Loading..." : "Render with Kroki"
1475
+ }
1476
+ ),
1477
+ krokiSvg.status === "error" && /* @__PURE__ */ jsx(Box$1, { children: krokiSvg.error?.message })
1478
+ ] }),
1479
+ 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" }) })
1480
+ ] }) })
1481
+ ]
1482
+ }
1483
+ ) });
1484
+ }
288
1485
  const Route = createFileRoute("/_single/view/$viewId/d2")({
289
1486
  component: Page,
290
1487
  staleTime: 1 / 0,
@@ -305,7 +1502,14 @@ function Page() {
305
1502
  return /* @__PURE__ */ jsx(ViewAsD2, { d2Source: source });
306
1503
  }
307
1504
  export {
1505
+ AdHocViewEditor as A,
1506
+ ExportPage as E,
1507
+ Fallback as F,
1508
+ Header as H,
1509
+ LikeC4IconRendererContext as L,
1510
+ NotFound as N,
308
1511
  Route$b as R,
1512
+ ViewOutlet as V,
309
1513
  Route$a as a,
310
1514
  Route$9 as b,
311
1515
  Route$8 as c,
@@ -316,5 +1520,13 @@ export {
316
1520
  Route$3 as h,
317
1521
  Route$2 as i,
318
1522
  Route$1 as j,
319
- Route as k
1523
+ Route as k,
1524
+ LikeC4ModelContext as l,
1525
+ EmbedPage as m,
1526
+ ViewEditor as n,
1527
+ ViewReact as o,
1528
+ ViewAsPuml as p,
1529
+ ViewAsMmd as q,
1530
+ ViewAsDot as r,
1531
+ ViewAsD2 as s
320
1532
  };