likec4 1.32.2 → 1.33.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.
@@ -7,9 +7,8 @@ import ReactDOM__default, { createPortal, flushSync } from "react-dom";
7
7
  import { ComponentName, useHashHistory, withOverviewGraph, krokiPumlSvgUrl, isDevelopment, krokiD2SvgUrl, basepath } from "./const.js";
8
8
  import { projects, isSingleProject } from "likec4:projects";
9
9
  import { $likec4model, $likec4data, IconRenderer as IconRenderer$1, projectId } from "likec4:single-project";
10
- import { nano } from "likec4/react";
11
- import { isTagColorSpecified, invariant as invariant$2, hasAtLeast, nonexhaustive, isStepEdgeId, extractStep, nameFromFqn, nonNullable, defaultTheme, ElementShapes, toArray, ifind, DefaultMap, ancestorsFqn, isAncestor, sortParentsFirst, ifilter, Queue, whereOperatorAsPredicate, GroupElementKind, delay as delay$1, BBox, getParallelStepsPrefix, isDeploymentView, compareNatural as compareNatural$1, isDescendantOf } from "@likec4/core";
12
- import { DefaultShapeSize, DefaultTextSize, DefaultPaddingSize } from "@likec4/core/types";
10
+ import { isTagColorSpecified, invariant as invariant$2, hasAtLeast, nonexhaustive, isStepEdgeId, extractStep, nameFromFqn, nonNullable, defaultTheme, ElementShapes, toArray, RichText, ifind, DefaultMap, ancestorsFqn, isAncestor, sortParentsFirst, ifilter, Queue, whereOperatorAsPredicate, GroupElementKind, delay as delay$1, BBox, getParallelStepsPrefix, isDeploymentView, compareNatural as compareNatural$1, isDescendantOf } from "@likec4/core";
11
+ import { DefaultShapeSize, DefaultTextSize, DefaultPaddingSize, RichText as RichText$1 } from "@likec4/core/types";
13
12
  import { computeRelationshipsView, treeFromElements as treeFromElements$1 } from "@likec4/core/compute-view/relationships";
14
13
  import { compareNatural, ifind as ifind$1, DefaultMap as DefaultMap$1 } from "@likec4/core/utils";
15
14
  import { modelConnection } from "@likec4/core/model";
@@ -743,26 +742,34 @@ function useCallbackRef(callback) {
743
742
  }), useMemo(() => (...args) => callbackRef.current?.(...args), []);
744
743
  }
745
744
  function useDebouncedCallback$1(callback, options) {
746
- const delay2 = typeof options == "number" ? options : options.delay, flushOnUnmount = typeof options == "number" ? !1 : options.flushOnUnmount, leading = typeof options == "number" ? !1 : options.leading, handleCallback = useCallbackRef(callback), debounceTimerRef = useRef(0), flushRef = useRef(() => {
747
- }), leadingRef = useRef(leading), lastCallback = Object.assign(
748
- useCallback(
745
+ const { delay: delay2, flushOnUnmount, leading } = typeof options == "number" ? { delay: options, flushOnUnmount: !1, leading: !1 } : options, handleCallback = useCallbackRef(callback), debounceTimerRef = useRef(0), lastCallback = useMemo(() => {
746
+ const currentCallback = Object.assign(
749
747
  (...args) => {
750
- if (window.clearTimeout(debounceTimerRef.current), leading && leadingRef.current) {
751
- leadingRef.current = !1, handleCallback(...args);
748
+ window.clearTimeout(debounceTimerRef.current);
749
+ const isFirstCall = currentCallback._isFirstCall;
750
+ if (currentCallback._isFirstCall = !1, leading && isFirstCall) {
751
+ handleCallback(...args);
752
752
  return;
753
753
  }
754
+ function clearTimeoutAndLeadingRef() {
755
+ window.clearTimeout(debounceTimerRef.current), debounceTimerRef.current = 0, currentCallback._isFirstCall = !0;
756
+ }
754
757
  const flush = () => {
755
- debounceTimerRef.current !== 0 && (debounceTimerRef.current = 0, leadingRef.current = !0, handleCallback(...args));
758
+ debounceTimerRef.current !== 0 && (clearTimeoutAndLeadingRef(), handleCallback(...args));
759
+ }, cancel = () => {
760
+ clearTimeoutAndLeadingRef();
756
761
  };
757
- flushRef.current = flush, lastCallback.flush = flush, debounceTimerRef.current = window.setTimeout(flush, delay2), leadingRef.current = !1;
762
+ currentCallback.flush = flush, currentCallback.cancel = cancel, debounceTimerRef.current = window.setTimeout(flush, delay2);
758
763
  },
759
- [handleCallback, delay2, leading]
760
- ),
761
- { flush: flushRef.current }
762
- );
764
+ { flush: () => {
765
+ }, cancel: () => {
766
+ }, _isFirstCall: !0 }
767
+ );
768
+ return currentCallback;
769
+ }, [handleCallback, delay2, leading]);
763
770
  return useEffect(
764
771
  () => () => {
765
- window.clearTimeout(debounceTimerRef.current), flushOnUnmount && lastCallback.flush();
772
+ flushOnUnmount ? lastCallback.flush() : lastCallback.cancel();
766
773
  },
767
774
  [lastCallback, flushOnUnmount]
768
775
  ), lastCallback;
@@ -817,6 +824,19 @@ function useMediaQuery(query, initialValue, { getInitialValueInEffect } = {
817
824
  function useColorScheme(initialValue, options) {
818
825
  return useMediaQuery("(prefers-color-scheme: dark)", initialValue === "dark", options) ? "dark" : "light";
819
826
  }
827
+ function useDebouncedState(defaultValue, wait, options = { leading: !1 }) {
828
+ const [value, setValue] = useState(defaultValue), timeoutRef = useRef(null), leadingRef = useRef(!0), clearTimeout2 = () => window.clearTimeout(timeoutRef.current);
829
+ useEffect(() => clearTimeout2, []);
830
+ const debouncedSetValue = useCallback(
831
+ (newValue) => {
832
+ clearTimeout2(), leadingRef.current && options.leading ? setValue(newValue) : timeoutRef.current = window.setTimeout(() => {
833
+ leadingRef.current = !0, setValue(newValue);
834
+ }, wait), leadingRef.current = !1;
835
+ },
836
+ [options.leading]
837
+ );
838
+ return [value, debouncedSetValue];
839
+ }
820
840
  function useDebouncedValue(value, wait, options = { leading: !1 }) {
821
841
  const [_value, setValue] = useState(value), mountedRef = useRef(!1), timeoutRef = useRef(null), cooldownRef = useRef(!1), cancel = () => window.clearTimeout(timeoutRef.current);
822
842
  return useEffect(() => {
@@ -1214,8 +1234,9 @@ const keyNameMap = {
1214
1234
  ArrowRight: "arrowright",
1215
1235
  ArrowUp: "arrowup",
1216
1236
  ArrowDown: "arrowdown",
1217
- Escape: "esc",
1218
- Esc: "esc",
1237
+ Escape: "escape",
1238
+ Esc: "escape",
1239
+ esc: "escape",
1219
1240
  Enter: "enter",
1220
1241
  Tab: "tab",
1221
1242
  Backspace: "backspace",
@@ -1361,14 +1382,6 @@ function usePrevious$1(value) {
1361
1382
  ref.current = value;
1362
1383
  }, [value]), ref.current;
1363
1384
  }
1364
- function useInViewport() {
1365
- const observer = useRef(null), [inViewport, setInViewport] = useState(!1);
1366
- return { ref: useCallback((node2) => {
1367
- typeof IntersectionObserver < "u" && (node2 && !observer.current ? observer.current = new IntersectionObserver(
1368
- (entries) => setInViewport(entries.some((entry) => entry.isIntersecting))
1369
- ) : observer.current?.disconnect(), node2 ? observer.current?.observe(node2) : setInViewport(!1));
1370
- }, []), inViewport };
1371
- }
1372
1385
  function useMutationObserver(callback, options, target) {
1373
1386
  const observer = useRef(null), ref = useRef(null);
1374
1387
  return useEffect(() => {
@@ -6838,7 +6851,7 @@ function getDefaultMiddlewares$1(middlewares) {
6838
6851
  }
6839
6852
  function getPopoverMiddlewares(options, getFloating, env) {
6840
6853
  const middlewaresOptions = getDefaultMiddlewares$1(options.middlewares), middlewares = [offset$1(options.offset), hide()];
6841
- return options.dropdownVisible && env !== "test" && (middlewaresOptions.flip = !1, middlewaresOptions.shift = !1), middlewaresOptions.shift && middlewares.push(
6854
+ return options.dropdownVisible && env !== "test" && options.preventPositionChangeWhenVisible && (middlewaresOptions.flip = !1, middlewaresOptions.shift = !1), middlewaresOptions.shift && middlewares.push(
6842
6855
  shift(
6843
6856
  typeof middlewaresOptions.shift == "boolean" ? { limiter: limitShift(), padding: 5 } : { limiter: limitShift(), padding: 5, ...middlewaresOptions.shift }
6844
6857
  )
@@ -6869,9 +6882,11 @@ function usePopover(options) {
6869
6882
  onChange: options.onChange
6870
6883
  }), previouslyOpened = useRef(_opened), onClose = () => {
6871
6884
  _opened && !options.disabled && setOpened(!1);
6872
- }, onToggle = () => !options.disabled && setOpened(!_opened), floating = useFloating({
6885
+ }, onToggle = () => {
6886
+ options.disabled || setOpened(!_opened);
6887
+ }, floating = useFloating({
6873
6888
  strategy: options.strategy,
6874
- placement: options.positionRef.current,
6889
+ placement: options.preventPositionChangeWhenVisible ? options.positionRef.current : options.position,
6875
6890
  middleware: getPopoverMiddlewares(options, () => floating, env),
6876
6891
  whileElementsMounted: autoUpdate
6877
6892
  });
@@ -6969,6 +6984,7 @@ function Popover(_props) {
6969
6984
  withOverlay,
6970
6985
  overlayProps,
6971
6986
  hideDetached,
6987
+ preventPositionChangeWhenVisible,
6972
6988
  ...others
6973
6989
  } = props2, getStyles2 = useStyles({
6974
6990
  name: __staticSelector,
@@ -6999,7 +7015,8 @@ function Popover(_props) {
6999
7015
  dropdownVisible,
7000
7016
  setDropdownVisible,
7001
7017
  positionRef,
7002
- disabled
7018
+ disabled,
7019
+ preventPositionChangeWhenVisible
7003
7020
  });
7004
7021
  useClickOutside(
7005
7022
  () => {
@@ -9323,6 +9340,7 @@ function Combobox(_props) {
9323
9340
  Popover,
9324
9341
  {
9325
9342
  opened: store.dropdownOpened,
9343
+ preventPositionChangeWhenVisible: !0,
9326
9344
  ...others,
9327
9345
  onChange: (_opened) => !_opened && onDropdownClose(),
9328
9346
  withRoles: !1,
@@ -13192,7 +13210,7 @@ function TreeNode({
13192
13210
  hasChildren: Array.isArray(node2.children) && node2.children.length > 0,
13193
13211
  elementProps
13194
13212
  }) : /* @__PURE__ */ jsx("div", { ...elementProps, children: node2.label }),
13195
- controller.expandedState[node2.value] && nested.length > 0 && /* @__PURE__ */ jsx("ul", { role: "group", ...getStyles2("subtree"), "data-level": level2, children: nested })
13213
+ controller.expandedState[node2.value] && nested.length > 0 && /* @__PURE__ */ jsx(Box$1, { component: "ul", role: "group", ...getStyles2("subtree"), "data-level": level2, children: nested })
13196
13214
  ]
13197
13215
  }
13198
13216
  );
@@ -22920,13 +22938,13 @@ function creator(name) {
22920
22938
  }
22921
22939
  function none() {
22922
22940
  }
22923
- function selector$p(selector3) {
22941
+ function selector$q(selector3) {
22924
22942
  return selector3 == null ? none : function() {
22925
22943
  return this.querySelector(selector3);
22926
22944
  };
22927
22945
  }
22928
22946
  function selection_select(select2) {
22929
- typeof select2 != "function" && (select2 = selector$p(select2));
22947
+ typeof select2 != "function" && (select2 = selector$q(select2));
22930
22948
  for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j2 = 0; j2 < m2; ++j2)
22931
22949
  for (var group = groups[j2], n2 = group.length, subgroup = subgroups[j2] = new Array(n2), node2, subnode, i2 = 0; i2 < n2; ++i2)
22932
22950
  (node2 = group[i2]) && (subnode = select2.call(node2, node2.__data__, i2, group)) && ("__data__" in node2 && (subnode.__data__ = node2.__data__), subgroup[i2] = subnode);
@@ -23317,7 +23335,7 @@ function constantNull() {
23317
23335
  return null;
23318
23336
  }
23319
23337
  function selection_insert(name, before) {
23320
- var create2 = typeof name == "function" ? name : creator(name), select2 = before == null ? constantNull : typeof before == "function" ? before : selector$p(before);
23338
+ var create2 = typeof name == "function" ? name : creator(name), select2 = before == null ? constantNull : typeof before == "function" ? before : selector$q(before);
23321
23339
  return this.select(function() {
23322
23340
  return this.insertBefore(create2.apply(this, arguments), select2.apply(this, arguments) || null);
23323
23341
  });
@@ -24471,7 +24489,7 @@ function transition_remove() {
24471
24489
  }
24472
24490
  function transition_select(select2) {
24473
24491
  var name = this._name, id2 = this._id;
24474
- typeof select2 != "function" && (select2 = selector$p(select2));
24492
+ typeof select2 != "function" && (select2 = selector$q(select2));
24475
24493
  for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j2 = 0; j2 < m2; ++j2)
24476
24494
  for (var group = groups[j2], n2 = group.length, subgroup = subgroups[j2] = new Array(n2), node2, subnode, i2 = 0; i2 < n2; ++i2)
24477
24495
  (node2 = group[i2]) && (subnode = select2.call(node2, node2.__data__, i2, group)) && ("__data__" in node2 && (subnode.__data__ = node2.__data__), subgroup[i2] = subnode, schedule(subgroup[i2], name, id2, i2, subgroup, get(node2, id2)));
@@ -28830,9 +28848,9 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
28830
28848
  return jsx("div", { className: cc(["react-flow__resize-control", "nodrag", ...positionClassNames, variant, className]), ref: resizeControlRef, style: controlStyle, children: children2 });
28831
28849
  }
28832
28850
  memo$2(ResizeControl);
28833
- const selector$5 = (state) => state.domNode?.querySelector(".react-flow__renderer");
28851
+ const selector$p = (state) => state.domNode?.querySelector(".react-flow__renderer");
28834
28852
  function NodeToolbarPortal({ children: children2 }) {
28835
- const wrapperRef = useStore$1(selector$5);
28853
+ const wrapperRef = useStore$1(selector$p);
28836
28854
  return wrapperRef ? createPortal(children2, wrapperRef) : null;
28837
28855
  }
28838
28856
  const nodeEqualityFn = (a2, b2) => a2?.internals.positionAbsolute.x !== b2?.internals.positionAbsolute.x || a2?.internals.positionAbsolute.y !== b2?.internals.positionAbsolute.y || a2?.measured.width !== b2?.measured.width || a2?.measured.height !== b2?.measured.height || a2?.selected !== b2?.selected || a2?.internals.z !== b2?.internals.z, nodesEqualityFn = (a2, b2) => {
@@ -34950,6 +34968,27 @@ const curveCatmullRomOpen = function custom4(alpha2) {
34950
34968
  return splitProps(props2, likec4tagVariantKeys);
34951
34969
  },
34952
34970
  getVariantProps: likec4tagFn.getVariantProps
34971
+ }), markdownBlockFn = /* @__PURE__ */ createRecipe("likec4-markdown-block", {
34972
+ uselikec4palette: !1
34973
+ }, []), markdownBlockVariantMap = {
34974
+ uselikec4palette: [
34975
+ "true",
34976
+ "false"
34977
+ ]
34978
+ }, markdownBlockVariantKeys = Object.keys(markdownBlockVariantMap), markdownBlock = /* @__PURE__ */ Object.assign(memo$1(markdownBlockFn.recipeFn), {
34979
+ __recipe__: !0,
34980
+ __name__: "markdownBlock",
34981
+ __getCompoundVariantCss__: markdownBlockFn.__getCompoundVariantCss__,
34982
+ raw: (props2) => props2,
34983
+ variantKeys: markdownBlockVariantKeys,
34984
+ variantMap: markdownBlockVariantMap,
34985
+ merge(recipe) {
34986
+ return mergeRecipes(this, recipe);
34987
+ },
34988
+ splitVariantProps(props2) {
34989
+ return splitProps(props2, markdownBlockVariantKeys);
34990
+ },
34991
+ getVariantProps: markdownBlockFn.getVariantProps
34953
34992
  }), MotionButton = /* @__PURE__ */ createMinimalMotionComponent("button"), MotionDiv = /* @__PURE__ */ createMinimalMotionComponent("div"), compoundActionBtn = cva({
34954
34993
  base: {
34955
34994
  transitionDuration: "normal",
@@ -36603,140 +36642,157 @@ const ElementTag = forwardRef(
36603
36642
  }
36604
36643
  );
36605
36644
  }
36606
- ), propsAreEqual = (prev, next) => prev.data.width === next.data.width && deepEqual(prev.data.tags, next.data.tags), ElementTags = memo$2(({ id: id2, data: { tags, width } }) => {
36607
- const zoom2 = useCurrentZoom(), zoomIsLargeEnough = zoom2 > 1.2, portalProps = useMantinePortalProps();
36645
+ ), propsAreEqual = (prev, next) => prev.data.width === next.data.width && deepEqual(prev.data.tags, next.data.tags) && (prev.data.hovered ?? !1) === (next.data.hovered ?? !1), ElementTags = memo$2(({ id: id2, data: { tags, width, hovered = !1 } }) => {
36646
+ const {
36647
+ hovered: isTagsBarHovered,
36648
+ ref: tagsBarRef
36649
+ } = useHover$1(), {
36650
+ hovered: isTagsToolbarHovered,
36651
+ ref: tagsToolbarRef
36652
+ } = useHover$1(), [isVisible, setVisible] = useDebouncedState(!1, hovered ? 120 : 300);
36653
+ useEffect(() => {
36654
+ setVisible((visibleNow) => visibleNow ? hovered || isTagsBarHovered || isTagsToolbarHovered : hovered && (isTagsBarHovered || isTagsToolbarHovered));
36655
+ }, [isTagsBarHovered, isTagsToolbarHovered, hovered]);
36656
+ const zoom2 = useCurrentZoom(), zoomIsLargeEnough = zoom2 > 1.2, diagram = useDiagram(), onHover = (tag) => {
36657
+ diagram.send({ type: "tag.highlight", tag });
36658
+ }, onLeave = useCallback(() => {
36659
+ diagram.send({ type: "tag.unhighlight" });
36660
+ }, []);
36608
36661
  if (!tags || tags.length === 0)
36609
36662
  return null;
36610
36663
  const maxWidth = Math.max(Math.round(width * zoom2) - 10, 200);
36611
- return /* @__PURE__ */ jsxs(
36612
- HoverCard,
36613
- {
36614
- ...portalProps,
36615
- floatingStrategy: "fixed",
36616
- position: "bottom-start",
36617
- offset: {
36618
- alignmentAxis: Math.round(4 * zoom2),
36619
- mainAxis: 8
36620
- },
36621
- keepMounted: !1,
36622
- openDelay: 300,
36623
- closeDelay: 500,
36624
- children: [
36625
- /* @__PURE__ */ jsx(HoverCard.Target, { children: /* @__PURE__ */ jsx(
36626
- "div",
36664
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
36665
+ /* @__PURE__ */ jsx(
36666
+ "div",
36667
+ {
36668
+ ref: tagsBarRef,
36669
+ className: cx(
36670
+ "likec4-element-tags",
36671
+ hstack({
36672
+ pointerEvents: "all",
36673
+ gap: 4,
36674
+ alignItems: "flex-end",
36675
+ justifyItems: "stretch",
36676
+ position: "absolute",
36677
+ width: "100%",
36678
+ bottom: 0,
36679
+ left: 0,
36680
+ padding: 4,
36681
+ _shapeCylinder: {
36682
+ bottom: 5
36683
+ },
36684
+ _shapeStorage: {
36685
+ bottom: 5
36686
+ },
36687
+ _shapeQueue: {
36688
+ bottom: 0,
36689
+ paddingLeft: 14
36690
+ }
36691
+ })
36692
+ ),
36693
+ onClick: stopPropagation$1,
36694
+ children: tags.map((tag) => /* @__PURE__ */ jsx(
36695
+ Box,
36627
36696
  {
36628
- className: cx(
36629
- "likec4-element-tags",
36630
- hstack({
36631
- pointerEvents: "all",
36632
- gap: 4,
36633
- alignItems: "flex-end",
36634
- justifyItems: "stretch",
36635
- position: "absolute",
36636
- width: "100%",
36637
- bottom: 0,
36638
- left: 0,
36639
- padding: 4,
36640
- _shapeCylinder: {
36641
- bottom: 5
36642
- },
36643
- _shapeStorage: {
36644
- bottom: 5
36645
- },
36646
- _shapeQueue: {
36647
- bottom: 0,
36648
- paddingLeft: 14
36649
- }
36650
- })
36651
- ),
36652
- onClick: stopPropagation$1,
36653
- children: tags.map((tag) => /* @__PURE__ */ jsx(
36654
- Box,
36655
- {
36656
- "data-likec4-tag": tag,
36657
- className: css({
36658
- layerStyle: "likec4.tag",
36659
- flex: 1,
36660
- display: "flex",
36661
- alignItems: "center",
36662
- justifyContent: "center",
36663
- maxWidth: 50,
36664
- height: 5,
36665
- _whenHovered: {
36666
- height: 12,
36667
- borderRadius: 4,
36668
- transitionDelay: ".08s"
36669
- },
36670
- transition: "fast"
36671
- })
36697
+ "data-likec4-tag": tag,
36698
+ className: css({
36699
+ layerStyle: "likec4.tag",
36700
+ flex: 1,
36701
+ display: "flex",
36702
+ alignItems: "center",
36703
+ justifyContent: "center",
36704
+ maxWidth: 50,
36705
+ height: 5,
36706
+ _whenHovered: {
36707
+ height: 12,
36708
+ borderRadius: 4,
36709
+ transitionDelay: ".08s"
36672
36710
  },
36673
- id2 + "#" + tag
36674
- ))
36675
- }
36676
- ) }),
36677
- /* @__PURE__ */ jsx(
36678
- HoverCard.Dropdown,
36711
+ transition: "fast"
36712
+ })
36713
+ },
36714
+ id2 + "#" + tag
36715
+ ))
36716
+ }
36717
+ ),
36718
+ /* @__PURE__ */ jsx(NodeToolbar, { isVisible, align: "start", position: Position.Bottom, children: /* @__PURE__ */ jsx(
36719
+ HStack,
36720
+ {
36721
+ ref: tagsToolbarRef,
36722
+ css: {
36723
+ gap: 4,
36724
+ flexWrap: "wrap",
36725
+ pb: "sm",
36726
+ translate: "auto",
36727
+ x: -8,
36728
+ maxWidth
36729
+ },
36730
+ children: tags.map((tag) => /* @__PURE__ */ jsx(
36731
+ ElementTag,
36679
36732
  {
36680
- p: 0,
36681
- w: "auto",
36682
- maw: maxWidth,
36733
+ tag,
36683
36734
  className: css({
36684
- background: "transparent",
36685
- border: "none"
36735
+ userSelect: "none",
36736
+ cursor: "pointer",
36737
+ ...zoomIsLargeEnough && {
36738
+ fontSize: "lg",
36739
+ borderRadius: 4,
36740
+ px: 6
36741
+ }
36686
36742
  }),
36687
- children: /* @__PURE__ */ jsx(ElementTagsDropdown, { tags, zoomIsLargeEnough })
36688
- }
36689
- )
36690
- ]
36691
- }
36692
- );
36743
+ onClick: (e2) => {
36744
+ e2.stopPropagation(), diagram.openSearch(`#${tag}`);
36745
+ },
36746
+ onMouseEnter: () => onHover(tag),
36747
+ onMouseLeave: onLeave
36748
+ },
36749
+ tag
36750
+ ))
36751
+ }
36752
+ ) })
36753
+ ] });
36693
36754
  }, propsAreEqual);
36694
36755
  ElementTags.displayName = "ElementTags";
36695
- function ElementTagsDropdown({ tags, zoomIsLargeEnough }) {
36696
- const diagram = useDiagram(), onHover = (tag) => {
36697
- diagram.send({ type: "tag.highlight", tag });
36698
- }, onLeave = useCallback(() => {
36699
- diagram.send({ type: "tag.unhighlight" });
36700
- }, []);
36756
+ const MarkdownBlock = forwardRef(({
36757
+ value,
36758
+ textScale = 1,
36759
+ uselikec4palette = !1,
36760
+ hideIfEmpty = !1,
36761
+ emptyText = "no content",
36762
+ className,
36763
+ ...props2
36764
+ }, ref) => {
36765
+ if (value.isEmpty && hideIfEmpty)
36766
+ return null;
36767
+ const content2 = value.nonEmpty ? { dangerouslySetInnerHTML: { __html: value.html } } : { children: /* @__PURE__ */ jsx(Text, { component: "span", fz: "xs", c: "dimmed", children: emptyText }) };
36701
36768
  return /* @__PURE__ */ jsx(
36702
- HStack,
36769
+ Box,
36703
36770
  {
36704
- css: {
36705
- gap: 4,
36706
- flexWrap: "wrap",
36707
- pb: "sm"
36771
+ ref,
36772
+ ...props2,
36773
+ className: cx(
36774
+ markdownBlock({
36775
+ uselikec4palette
36776
+ }),
36777
+ className
36778
+ ),
36779
+ style: {
36780
+ // @ts-expect-error
36781
+ "--mantine-scale": textScale
36708
36782
  },
36709
- children: tags.map((tag) => /* @__PURE__ */ jsx(
36710
- ElementTag,
36711
- {
36712
- tag,
36713
- className: css({
36714
- userSelect: "none",
36715
- cursor: "pointer",
36716
- ...zoomIsLargeEnough && {
36717
- fontSize: "lg",
36718
- borderRadius: 4,
36719
- px: 6
36720
- }
36721
- }),
36722
- onClick: (e2) => {
36723
- e2.stopPropagation(), diagram.openSearch(`#${tag}`);
36724
- },
36725
- onMouseEnter: () => onHover(tag),
36726
- onMouseLeave: onLeave
36727
- },
36728
- tag
36729
- ))
36783
+ ...content2
36730
36784
  }
36731
36785
  );
36732
- }
36786
+ });
36787
+ MarkdownBlock.displayName = "MarkdownBlock";
36733
36788
  const iconSize$2 = "--icon-size", title$4 = css.raw({
36734
36789
  textStyle: "likec4.node.primary",
36735
36790
  flex: "0 0 auto",
36736
36791
  textAlign: "center",
36737
36792
  color: "likec4.palette.hiContrast"
36738
36793
  }), description$2 = css.raw({
36739
- flex: "0 1 auto",
36794
+ flexGrow: "0",
36795
+ flexShrink: "1",
36740
36796
  textStyle: "likec4.node.secondary",
36741
36797
  color: "likec4.palette.loContrast",
36742
36798
  textAlign: "center",
@@ -36806,6 +36862,8 @@ const iconSize$2 = "--icon-size", title$4 = css.raw({
36806
36862
  flex: "1",
36807
36863
  height: "fit-content",
36808
36864
  width: "fit-content",
36865
+ maxHeight: "100%",
36866
+ maxWidth: "100%",
36809
36867
  margin: "0 auto",
36810
36868
  display: "flex",
36811
36869
  alignItems: "center",
@@ -36857,6 +36915,8 @@ const iconSize$2 = "--icon-size", title$4 = css.raw({
36857
36915
  textContainer: {
36858
36916
  height: "fit-content",
36859
36917
  width: "fit-content",
36918
+ maxHeight: "100%",
36919
+ maxWidth: "100%",
36860
36920
  flex: "0 1 auto",
36861
36921
  display: "flex",
36862
36922
  flexDirection: "column",
@@ -36926,7 +36986,7 @@ function ElementTitle({ id: id2, data, iconSize: iconSize2 }) {
36926
36986
  className: elementIcon$2
36927
36987
  }), classes2 = elementTitle({
36928
36988
  hasIcon: n$5(elementIcon2),
36929
- hasDescription: !n$1(data.description ?? ""),
36989
+ hasDescription: !!data.description?.nonEmpty,
36930
36990
  hasTechnology: !n$1(data.technology ?? "")
36931
36991
  }), size2 = nodeSizes(data.style).size, isSmOrXs = size2 === "sm" || size2 === "xs";
36932
36992
  return /* @__PURE__ */ jsxs(
@@ -36946,7 +37006,7 @@ function ElementTitle({ id: id2, data, iconSize: iconSize2 }) {
36946
37006
  /* @__PURE__ */ jsx(
36947
37007
  Text,
36948
37008
  {
36949
- component: "h3",
37009
+ component: "div",
36950
37010
  className: cx(classes2.title, "likec4-element-title"),
36951
37011
  lineClamp: isSmOrXs ? 2 : 3,
36952
37012
  children: data.title
@@ -36961,12 +37021,14 @@ function ElementTitle({ id: id2, data, iconSize: iconSize2 }) {
36961
37021
  }
36962
37022
  ),
36963
37023
  data.description && /* @__PURE__ */ jsx(
36964
- Text,
37024
+ MarkdownBlock,
36965
37025
  {
36966
- component: "div",
36967
37026
  className: cx(classes2.description, "likec4-element-description"),
36968
- lineClamp: isSmOrXs ? 3 : 5,
36969
- children: data.description
37027
+ value: data.description,
37028
+ uselikec4palette: !0,
37029
+ hideIfEmpty: !0,
37030
+ maxHeight: data.description.isMarkdown ? "8rem" : void 0,
37031
+ lineClamp: isSmOrXs ? 3 : 5
36970
37032
  }
36971
37033
  )
36972
37034
  ] })
@@ -37442,7 +37504,7 @@ const stopPropagation = (e2) => e2.stopPropagation(), Tooltip$4 = Tooltip$5.with
37442
37504
  ] })
37443
37505
  ] }),
37444
37506
  /* @__PURE__ */ jsx(Box$1, { className: title$3, children: r2.title || "untitled" }),
37445
- r2.description && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: r2.description }),
37507
+ r2.description.nonEmpty && /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: r2.description.text }),
37446
37508
  links.length > 0 && /* @__PURE__ */ jsx(
37447
37509
  Stack,
37448
37510
  {
@@ -38688,11 +38750,13 @@ const useElementDetailsActorRef = () => {
38688
38750
  display: "grid",
38689
38751
  gridTemplateColumns: "min-content 1fr",
38690
38752
  gridAutoRows: "min-content max-content",
38691
- gap: "[20px 16px]",
38753
+ gap: "[24px 20px]",
38692
38754
  alignItems: "baseline",
38693
38755
  justifyItems: "stretch"
38694
38756
  }), propertyLabel = css({
38695
- justifySelf: "end"
38757
+ justifySelf: "end",
38758
+ textAlign: "right",
38759
+ userSelect: "none"
38696
38760
  }), resizeHandle = css({
38697
38761
  position: "absolute",
38698
38762
  width: "14px",
@@ -41707,7 +41771,7 @@ function layoutRelationshipsView$1(data, scope) {
41707
41771
  y: position.y,
41708
41772
  position: [position.x, position.y],
41709
41773
  title: "empty node",
41710
- description: null,
41774
+ description: RichText.EMPTY,
41711
41775
  technology: null,
41712
41776
  tags: [],
41713
41777
  links: [],
@@ -41746,7 +41810,7 @@ function layoutRelationshipsView$1(data, scope) {
41746
41810
  y: position.y,
41747
41811
  position: [position.x, position.y],
41748
41812
  title: element.title,
41749
- description: element.description,
41813
+ description: RichText.from(element.description),
41750
41814
  technology: element.technology,
41751
41815
  tags: [...element.tags],
41752
41816
  links: null,
@@ -42055,7 +42119,7 @@ function RelationshipsBrowser({ actorRef }) {
42055
42119
  initialEdges: []
42056
42120
  }), /* @__PURE__ */ jsx(RelationshipsBrowserActorContext.Provider, { value: actorRef, children: /* @__PURE__ */ jsx(ReactFlowProvider, { ...initialRef.current, children: /* @__PURE__ */ jsx(LayoutGroup, { id: actorRef.sessionId, inherit: !1, children: /* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsx(RelationshipsBrowserXYFlow, {}) }) }) }) });
42057
42121
  }
42058
- const selector$4 = (state) => ({
42122
+ const selector$5 = (state) => ({
42059
42123
  isActive: state.hasTag("active"),
42060
42124
  nodes: state.context.xynodes,
42061
42125
  edges: state.context.xyedges
@@ -42065,7 +42129,7 @@ const selector$4 = (state) => ({
42065
42129
  nodes,
42066
42130
  edges
42067
42131
  } = useRelationshipsBrowserState(
42068
- selector$4,
42132
+ selector$5,
42069
42133
  selectorEq
42070
42134
  );
42071
42135
  return /* @__PURE__ */ jsx(
@@ -42729,7 +42793,22 @@ function ElementDetailsCard({
42729
42793
  /* @__PURE__ */ jsxs(Group, { align: "baseline", gap: "sm", wrap: "nowrap", children: [
42730
42794
  /* @__PURE__ */ jsxs("div", { children: [
42731
42795
  /* @__PURE__ */ jsx(SmallLabel, { children: "kind" }),
42732
- /* @__PURE__ */ jsx(Badge, { radius: "sm", size: "sm", fw: 600, color: "gray", children: elementModel.kind })
42796
+ /* @__PURE__ */ jsx(
42797
+ Badge,
42798
+ {
42799
+ radius: "sm",
42800
+ size: "sm",
42801
+ fw: 600,
42802
+ color: "gray",
42803
+ style: {
42804
+ cursor: "pointer"
42805
+ },
42806
+ onClick: (e2) => {
42807
+ e2.stopPropagation(), diagram.openSearch(`kind:${elementModel.kind}`);
42808
+ },
42809
+ children: elementModel.kind
42810
+ }
42811
+ )
42733
42812
  ] }),
42734
42813
  /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
42735
42814
  /* @__PURE__ */ jsx(SmallLabel, { children: "tags" }),
@@ -42776,7 +42855,9 @@ function ElementDetailsCard({
42776
42855
  variant: "default",
42777
42856
  radius: "sm",
42778
42857
  onClick: (e2) => {
42779
- e2.stopPropagation();
42858
+ e2.stopPropagation(), diagram.openSource({
42859
+ element: elementModel.id
42860
+ });
42780
42861
  },
42781
42862
  children: /* @__PURE__ */ jsx(IconFileSymlink, { stroke: 1.8, style: { width: "62%" } })
42782
42863
  }
@@ -42812,8 +42893,17 @@ function ElementDetailsCard({
42812
42893
  },
42813
42894
  children: [
42814
42895
  /* @__PURE__ */ jsx(TabsList, { children: TABS.map((tab) => /* @__PURE__ */ jsx(TabsTab, { value: tab, children: tab }, tab)) }),
42815
- /* @__PURE__ */ jsx(TabsPanel, { value: "Properties", children: /* @__PURE__ */ jsx(ScrollArea, { scrollbars: "y", type: "auto", children: /* @__PURE__ */ jsxs(Box$1, { className: propertiesGrid, pt: "xs", children: [
42816
- /* @__PURE__ */ jsx(ElementProperty, { title: "description", emptyValue: "no description", children: elementModel.description }),
42896
+ /* @__PURE__ */ jsx(TabsPanel, { value: "Properties", children: /* @__PURE__ */ jsx(ScrollArea, { scrollbars: "y", type: "scroll", offsetScrollbars: !0, children: /* @__PURE__ */ jsxs(Box$1, { className: propertiesGrid, pt: "xs", children: [
42897
+ /* @__PURE__ */ jsxs(Fragment$1, { children: [
42898
+ /* @__PURE__ */ jsx(PropertyLabel, { children: "description" }),
42899
+ /* @__PURE__ */ jsx(
42900
+ MarkdownBlock,
42901
+ {
42902
+ value: elementModel.description,
42903
+ emptyText: "no description"
42904
+ }
42905
+ )
42906
+ ] }),
42817
42907
  elementModel.technology && /* @__PURE__ */ jsx(ElementProperty, { title: "technology", children: elementModel.technology }),
42818
42908
  elementModel.links.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [
42819
42909
  /* @__PURE__ */ jsx(PropertyLabel, { children: "links" }),
@@ -42888,10 +42978,7 @@ const ViewButton$1 = ({
42888
42978
  onNavigateTo
42889
42979
  }) => /* @__PURE__ */ jsx(UnstyledButton, { className: viewButton$1, onClick: (e2) => onNavigateTo(view.id, e2), children: /* @__PURE__ */ jsxs(Group, { gap: 6, align: "start", wrap: "nowrap", children: [
42890
42980
  /* @__PURE__ */ jsx(ThemeIcon, { size: "sm", variant: "transparent", children: view._type === "deployment" ? /* @__PURE__ */ jsx(IconStack2, { stroke: 1.8 }) : /* @__PURE__ */ jsx(IconZoomScan, { stroke: 1.8 }) }),
42891
- /* @__PURE__ */ jsxs(Box$1, { children: [
42892
- /* @__PURE__ */ jsx(Text, { component: "div", className: viewButtonTitle, lineClamp: 1, children: view.title || "untitled" }),
42893
- view.description && /* @__PURE__ */ jsx(Text, { component: "div", mt: 2, fz: "xs", c: "dimmed", lh: 1.4, lineClamp: 1, children: view.description })
42894
- ] })
42981
+ /* @__PURE__ */ jsx(Box$1, { children: /* @__PURE__ */ jsx(Text, { component: "div", className: viewButtonTitle, lineClamp: 1, children: view.title || "untitled" }) })
42895
42982
  ] }) });
42896
42983
  function ElementProperty({
42897
42984
  title: title2,
@@ -42910,6 +42997,7 @@ function ElementProperty({
42910
42997
  fz: "md",
42911
42998
  style: {
42912
42999
  whiteSpace: "preserve-breaks",
43000
+ userSelect: "all",
42913
43001
  ...style2
42914
43002
  },
42915
43003
  ...props2,
@@ -42919,11 +43007,96 @@ function ElementProperty({
42919
43007
  ] });
42920
43008
  }
42921
43009
  function ElementMetata({
42922
- value
43010
+ value: metadata
42923
43011
  }) {
42924
43012
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
42925
43013
  /* @__PURE__ */ jsx(PropertyLabel, { children: "metadata" }),
42926
- /* @__PURE__ */ jsx(Box$1, { children: /* @__PURE__ */ jsx(Code, { block: !0, children: JSON.stringify(value, null, 2) }) })
43014
+ /* @__PURE__ */ jsx(
43015
+ Box$1,
43016
+ {
43017
+ className: css({
43018
+ flex: 1,
43019
+ display: "grid",
43020
+ gridTemplateColumns: "min-content 1fr",
43021
+ gridAutoRows: "min-content max-content",
43022
+ gap: "[4px 4px]",
43023
+ alignItems: "baseline",
43024
+ justifyItems: "stretch",
43025
+ paddingRight: "2xs"
43026
+ }),
43027
+ children: t$1(metadata).map(([key2, value]) => /* @__PURE__ */ jsxs(
43028
+ "div",
43029
+ {
43030
+ className: cx(
43031
+ "group",
43032
+ css({
43033
+ display: "contents"
43034
+ })
43035
+ ),
43036
+ children: [
43037
+ /* @__PURE__ */ jsxs(
43038
+ "div",
43039
+ {
43040
+ className: css({
43041
+ fontSize: "sm",
43042
+ fontWeight: 500,
43043
+ justifySelf: "end",
43044
+ whiteSpace: "nowrap"
43045
+ }),
43046
+ children: [
43047
+ key2,
43048
+ ":"
43049
+ ]
43050
+ }
43051
+ ),
43052
+ /* @__PURE__ */ jsx(
43053
+ "div",
43054
+ {
43055
+ className: css({}),
43056
+ children: /* @__PURE__ */ jsx(
43057
+ ScrollAreaAutosize,
43058
+ {
43059
+ type: "auto",
43060
+ mah: 200,
43061
+ overscrollBehavior: "none",
43062
+ className: css({
43063
+ transitionProperty: "all",
43064
+ transitionDuration: "fast",
43065
+ transitionTimingFunction: "inOut",
43066
+ rounded: "sm",
43067
+ color: "mantine.colors.gray[8]",
43068
+ _dark: {
43069
+ color: "mantine.colors.dark[1]"
43070
+ },
43071
+ _groupHover: {
43072
+ transitionTimingFunction: "out",
43073
+ color: "mantine.colors.defaultColor",
43074
+ background: "mantine.colors.defaultHover"
43075
+ }
43076
+ }),
43077
+ children: /* @__PURE__ */ jsx(
43078
+ "div",
43079
+ {
43080
+ className: css({
43081
+ fontSize: "sm",
43082
+ padding: "2xs",
43083
+ whiteSpace: "pre",
43084
+ fontFamily: "[var(--mantine-font-family-monospace)]",
43085
+ userSelect: "all"
43086
+ }),
43087
+ children: value
43088
+ }
43089
+ )
43090
+ }
43091
+ )
43092
+ }
43093
+ )
43094
+ ]
43095
+ },
43096
+ key2
43097
+ ))
43098
+ }
43099
+ )
42927
43100
  ] });
42928
43101
  }
42929
43102
  function ElementDetails({
@@ -43608,7 +43781,7 @@ function layoutRelationshipDetails(data, scope) {
43608
43781
  y: position.y,
43609
43782
  position: [position.x, position.y],
43610
43783
  title: element.title,
43611
- description: element.description,
43784
+ description: RichText.from(element.description),
43612
43785
  technology: element.technology,
43613
43786
  tags: [...element.tags],
43614
43787
  links: null,
@@ -43890,7 +44063,7 @@ const selectSubject = (state) => ({
43890
44063
  }, [store, instance.viewportInitialized, actor]), useEffect(() => {
43891
44064
  data !== null && actor.send({ type: "update.layoutData", data });
43892
44065
  }, [data, actor]), null;
43893
- }), selector$3 = ({ context: context2 }) => ({
44066
+ }), selector$4 = ({ context: context2 }) => ({
43894
44067
  // subject: context.subject,
43895
44068
  // view: state.context.view,
43896
44069
  initialized: context2.initialized.xydata && context2.initialized.xyflow,
@@ -43901,7 +44074,7 @@ const selectSubject = (state) => ({
43901
44074
  initialized,
43902
44075
  nodes,
43903
44076
  edges
43904
- } = useRelationshipDetailsState(selector$3, deepEqual);
44077
+ } = useRelationshipDetailsState(selector$4, deepEqual);
43905
44078
  return /* @__PURE__ */ jsxs(
43906
44079
  BaseXYFlow,
43907
44080
  {
@@ -44475,11 +44648,11 @@ function ViewButton({ className, view, loop = !1, search, ...props2 }) {
44475
44648
  /* @__PURE__ */ jsx(
44476
44649
  Highlight,
44477
44650
  {
44478
- highlight: view.$view.description ? search : "",
44651
+ highlight: view.description.nonEmpty ? search : "",
44479
44652
  component: "div",
44480
44653
  className: btn$2.description,
44481
44654
  lineClamp: 1,
44482
- children: view.$view.description || "No description"
44655
+ children: view.description.text || "No description"
44483
44656
  }
44484
44657
  )
44485
44658
  ] })
@@ -44640,7 +44813,7 @@ function ElementTreeNode({ node: node2, elementProps, hasChildren, expanded }) {
44640
44813
  }
44641
44814
  ) })
44642
44815
  ] }),
44643
- /* @__PURE__ */ jsx(Highlight, { component: "div", highlight: searchTerms, className: btn$1.description, lineClamp: 1, children: element.description || "No description" })
44816
+ /* @__PURE__ */ jsx(Highlight, { component: "div", highlight: searchTerms, className: btn$1.description, lineClamp: 1, children: element.description.text || "No description" })
44644
44817
  ] }),
44645
44818
  /* @__PURE__ */ jsx(Text, { component: "div", className: cx(elementViewsCount, btn$1.descriptionColor), fz: "xs", children: views.length === 0 ? "No views" : /* @__PURE__ */ jsxs(Fragment$1, { children: [
44646
44819
  views.length,
@@ -45371,7 +45544,7 @@ const autolayoutButton = css({
45371
45544
  borderColor: "mantine.colors.gray[5]",
45372
45545
  borderRadius: 3,
45373
45546
  transform: "translate(-50%, -50%)"
45374
- }), selector$2 = (state) => ({
45547
+ }), selector$3 = (state) => ({
45375
45548
  viewId: state.view.id,
45376
45549
  autoLayout: state.view.autoLayout
45377
45550
  }), ChangeAutoLayoutButton = (props2) => {
@@ -45380,7 +45553,7 @@ const autolayoutButton = css({
45380
45553
  } = useDiagramEventHandlers(), diagram = useDiagram(), [rootRef, setRootRef] = useState(null), [controlsRefs, setControlsRefs] = useState({}), {
45381
45554
  autoLayout,
45382
45555
  viewId
45383
- } = useDiagramContext(selector$2), { ref, hovered: isSpacingHovered } = useHover$1(), setControlRef = (name) => (node2) => {
45556
+ } = useDiagramContext(selector$3), { ref, hovered: isSpacingHovered } = useHover$1(), setControlRef = (name) => (node2) => {
45384
45557
  controlsRefs[name] = node2, setControlsRefs(controlsRefs);
45385
45558
  }, setAutoLayout = (direction) => (event) => {
45386
45559
  event.stopPropagation(), onChange?.({
@@ -45697,11 +45870,11 @@ const autolayoutButton = css({
45697
45870
  "forward"
45698
45871
  )
45699
45872
  ] });
45700
- }, selector$1 = (state) => ({
45873
+ }, selector$2 = (state) => ({
45701
45874
  visible: state.features.enableReadOnly !== !0,
45702
45875
  isReadOnly: state.toggledFeatures.enableReadOnly ?? state.features.enableReadOnly
45703
45876
  }), ToggleReadonly = () => {
45704
- const { visible: visible2, isReadOnly } = useDiagramContext(selector$1), diagram = useDiagram();
45877
+ const { visible: visible2, isReadOnly } = useDiagramContext(selector$2), diagram = useDiagram();
45705
45878
  return visible2 ? /* @__PURE__ */ jsx(Tooltip, { label: isReadOnly ? "Enable editing" : "Disable editing", children: /* @__PURE__ */ jsx(
45706
45879
  ActionIcon,
45707
45880
  {
@@ -45871,14 +46044,17 @@ const autolayoutButton = css({
45871
46044
  color: "mantine.colors.gray[5]"
45872
46045
  }
45873
46046
  });
46047
+ function selector$1(context2) {
46048
+ return {
46049
+ id: context2.view.id,
46050
+ title: context2.view.title ?? "untitled",
46051
+ description: RichText$1.from(context2.view.description),
46052
+ links: context2.view.links,
46053
+ isNotActiveWalkthrough: context2.activeWalkthrough === null
46054
+ };
46055
+ }
45874
46056
  function DiagramTitlePanel() {
45875
- const { id: id2, title: title$12, description: description$12, links, isNotActiveWalkthrough } = useDiagramContext((s2) => ({
45876
- id: s2.view.id,
45877
- title: s2.view.title ?? "untitled",
45878
- description: s2.view.description,
45879
- links: s2.view.links,
45880
- isNotActiveWalkthrough: s2.activeWalkthrough === null
45881
- })), [isCollapsed, setCollapsed] = useLocalStorage({
46057
+ const { id: id2, title: title$12, description: description$12, links, isNotActiveWalkthrough } = useDiagramContext(selector$1), [isCollapsed, setCollapsed] = useLocalStorage({
45882
46058
  key: "diagram-title-webview-collapsed",
45883
46059
  defaultValue: !1
45884
46060
  }), toggle = () => setCollapsed((v) => !v);
@@ -45972,24 +46148,23 @@ function DiagramTitlePanel() {
45972
46148
  }
45973
46149
  )
45974
46150
  ] }),
45975
- description$12 && /* @__PURE__ */ jsx(
46151
+ description$12.nonEmpty && /* @__PURE__ */ jsx(
45976
46152
  Spoiler,
45977
46153
  {
45978
- maxHeight: 42,
46154
+ maxHeight: 60,
45979
46155
  showLabel: /* @__PURE__ */ jsx(Button, { component: "div", color: "gray", variant: "light", fz: "10", size: "compact-xs", tabIndex: -1, children: "show more" }),
45980
46156
  hideLabel: /* @__PURE__ */ jsx(Button, { component: "div", color: "gray", variant: "light", fz: "10", size: "compact-xs", tabIndex: -1, children: "hide" }),
45981
46157
  children: /* @__PURE__ */ jsx(
45982
- Text,
46158
+ MarkdownBlock,
45983
46159
  {
45984
- component: "div",
45985
- size: "sm",
45986
46160
  className: description,
45987
- children: description$12 || "no description"
46161
+ textScale: 0.9,
46162
+ value: description$12
45988
46163
  }
45989
46164
  )
45990
46165
  }
45991
46166
  ),
45992
- !description$12 && /* @__PURE__ */ jsx(
46167
+ description$12.isEmpty && /* @__PURE__ */ jsx(
45993
46168
  Text,
45994
46169
  {
45995
46170
  component: "div",
@@ -46852,7 +47027,7 @@ function viewToNodesEdge$1(opts) {
46852
47027
  id: node2.id,
46853
47028
  title: node2.title,
46854
47029
  technology: node2.technology,
46855
- description: node2.description,
47030
+ description: RichText.from(node2.description),
46856
47031
  height: node2.height,
46857
47032
  width: node2.width,
46858
47033
  level: node2.level,
@@ -47636,7 +47811,7 @@ function layoutResultToXYFlow(layout2) {
47636
47811
  fqn: fqn2,
47637
47812
  title: node2.title,
47638
47813
  technology: node2.technology,
47639
- description: node2.description,
47814
+ description: RichText.from(node2.description),
47640
47815
  height: node2.height,
47641
47816
  width: node2.width,
47642
47817
  color: node2.color,
@@ -47681,8 +47856,8 @@ function layoutResultToXYFlow(layout2) {
47681
47856
  color: color2,
47682
47857
  navigateTo,
47683
47858
  line,
47684
- ...technology2 && { technology: technology2 },
47685
- ...description2 && { description: description2 }
47859
+ description: RichText.from(description2),
47860
+ ...technology2 && { technology: technology2 }
47686
47861
  }
47687
47862
  });
47688
47863
  }
@@ -49131,7 +49306,7 @@ const _diagramMachine = xstate_cjsExports.setup({
49131
49306
  };
49132
49307
  }),
49133
49308
  "tag.highlight": xstate_cjsExports.assign(({ context: context2, event }) => (xstate_cjsExports.assertEvent(event, "tag.highlight"), {
49134
- xynodes: context2.xynodes.map((n2) => n2.data.tags?.includes(event.tag) ? setDimmed(n2, !1) : setDimmed(n2, "immediate"))
49309
+ xynodes: context2.xynodes.map((n2) => n2.data.tags?.includes(event.tag) ? setDimmed(n2, !1) : setDimmed(n2, !0))
49135
49310
  })),
49136
49311
  "undim everything": xstate_cjsExports.assign(({ context: context2 }) => ({
49137
49312
  xynodes: context2.xynodes.map(setDimmed(!1)),
@@ -49748,7 +49923,10 @@ function findCorrespondingNode(context2, event) {
49748
49923
  const fromNodeId = context2.lastOnNavigate?.fromNode, fromNode = fromNodeId && context2.view.nodes.find((n2) => n2.id === fromNodeId), fromRef = fromNode && nodeRef(fromNode), toNode = fromRef && event.view.nodes.find((n2) => nodeRef(n2) === fromRef);
49749
49924
  return { fromNode, toNode };
49750
49925
  }
49751
- const diagramMachine = _diagramMachine, selectToggledFeatures = (state) => state.context.toggledFeatures;
49926
+ const diagramMachine = _diagramMachine, selectToggledFeatures = (state) => state.context.features.enableReadOnly ? {
49927
+ ...state.context.toggledFeatures,
49928
+ enableReadOnly: !0
49929
+ } : state.context.toggledFeatures;
49752
49930
  function DiagramActorProvider({
49753
49931
  view,
49754
49932
  zoomable,
@@ -49995,7 +50173,7 @@ function useLikeC4ModelDataAtom() {
49995
50173
  return useContext(LikeC4ModelDataContext);
49996
50174
  }
49997
50175
  function LikeC4ModelContext({ likec4data, likec4model, children: children2 }) {
49998
- const model = nano.useStore(likec4model);
50176
+ const model = useStore(likec4model);
49999
50177
  return /* @__PURE__ */ jsx(LikeC4ModelDataContext.Provider, { value: likec4data, children: /* @__PURE__ */ jsx(LikeC4ModelProvider, { likec4model: model, children: children2 }) });
50000
50178
  }
50001
50179
  css({
@@ -50121,53 +50299,63 @@ const previewBg = css({
50121
50299
  });
50122
50300
  function RouteComponent$1() {
50123
50301
  useDocumentTitle("LikeC4");
50124
- const views = t$4(useLikeC4Model$1().$model.views);
50125
- return /* @__PURE__ */ jsx(
50302
+ const views = [...useLikeC4Model$1("layouted").views()];
50303
+ return /* @__PURE__ */ jsx(Container, { size: "xl", children: /* @__PURE__ */ jsx(
50126
50304
  SimpleGrid,
50127
50305
  {
50128
50306
  p: { base: "md", sm: "xl" },
50129
- cols: { base: 1, sm: 2, md: 3, lg: 5 },
50307
+ cols: { base: 1, sm: 2, md: 3, xl: 4 },
50130
50308
  spacing: { base: 10, sm: "xl" },
50131
50309
  verticalSpacing: { base: "md", sm: "xl" },
50132
- children: views.map((v) => /* @__PURE__ */ jsx(ViewCard, { viewId: v }, v))
50310
+ children: views.map((v) => /* @__PURE__ */ jsx(ViewCard, { view: v }, v.id))
50133
50311
  }
50134
- );
50312
+ ) });
50135
50313
  }
50136
- const ViewCard = memo$2(({ viewId }) => {
50137
- const diagram = useLikeC4Model$1("layouted").findView(viewId);
50138
- if (!diagram || !diagram.isDiagram())
50139
- return null;
50140
- const { id: id2, title: title2, description: description2 } = diagram.$view;
50141
- return /* @__PURE__ */ jsxs(
50314
+ function ViewCard({ view }) {
50315
+ const [visible2, setVisible] = useState(!1);
50316
+ return useTimeoutEffect(() => {
50317
+ setVisible(!0);
50318
+ }, 100), /* @__PURE__ */ jsxs(
50142
50319
  Card,
50143
50320
  {
50144
50321
  shadow: "xs",
50145
50322
  padding: "lg",
50146
50323
  radius: "sm",
50324
+ className: "group",
50147
50325
  withBorder: !0,
50148
50326
  children: [
50149
- /* @__PURE__ */ jsx(Card.Section, { children: /* @__PURE__ */ jsx(DiagramPreview$1, { diagram: diagram.$view }) }),
50150
- /* @__PURE__ */ jsx(Group, { justify: "space-between", mt: "md", mb: "xs", children: /* @__PURE__ */ jsx(Text, { fw: 500, children: title2 }) }),
50151
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: description2 }),
50152
- /* @__PURE__ */ jsx(Link$1, { to: "/view/$viewId/", params: { viewId: id2 }, search: !0, className: cardLink })
50327
+ /* @__PURE__ */ jsx(Card.Section, { children: /* @__PURE__ */ jsx(Box$1, { className: previewBg, style: { height: 200 }, children: visible2 && /* @__PURE__ */ jsx(
50328
+ StaticLikeC4Diagram,
50329
+ {
50330
+ background: "transparent",
50331
+ view: view.$view,
50332
+ fitView: !0,
50333
+ fitViewPadding: "4px",
50334
+ reduceGraphics: !0
50335
+ }
50336
+ ) }) }),
50337
+ /* @__PURE__ */ jsx(Group, { justify: "space-between", mt: "md", children: /* @__PURE__ */ jsx(Text, { fw: 500, children: view.title ?? view.id }) }),
50338
+ /* @__PURE__ */ jsx(
50339
+ MarkdownBlock,
50340
+ {
50341
+ value: view.description,
50342
+ textScale: 0.75,
50343
+ emptyText: "No description",
50344
+ lineClamp: 3,
50345
+ mt: "2",
50346
+ css: {
50347
+ transition: "fast",
50348
+ opacity: {
50349
+ base: 0.8,
50350
+ _groupHover: 1
50351
+ }
50352
+ }
50353
+ }
50354
+ ),
50355
+ /* @__PURE__ */ jsx(Link$1, { to: "/view/$viewId/", params: { viewId: view.id }, search: !0, className: cardLink })
50153
50356
  ]
50154
50357
  }
50155
50358
  );
50156
- });
50157
- function DiagramPreview$1({ diagram }) {
50158
- const { ref, inViewport } = useInViewport(), [visible2, setVisible] = useState(inViewport);
50159
- return useLayoutEffect$1(() => {
50160
- inViewport && !visible2 && setVisible(!0);
50161
- }, [inViewport]), /* @__PURE__ */ jsx(Box$1, { ref, className: previewBg, style: { height: 175 }, children: visible2 && /* @__PURE__ */ jsx(
50162
- StaticLikeC4Diagram,
50163
- {
50164
- background: "transparent",
50165
- view: diagram,
50166
- fitView: !0,
50167
- fitViewPadding: "4px",
50168
- reduceGraphics: !0
50169
- }
50170
- ) });
50171
50359
  }
50172
50360
  const Route$h = createFileRoute("/project/$projectId")({
50173
50361
  staleTime: 1 / 0,
@@ -51179,7 +51367,7 @@ function layoutRelationshipsView(data) {
51179
51367
  x: position.x,
51180
51368
  y: position.y,
51181
51369
  title: element.title,
51182
- description: element.description,
51370
+ description: element.description.$source,
51183
51371
  technology: element.technology,
51184
51372
  tags: element.tags,
51185
51373
  links: null,
@@ -51899,9 +52087,10 @@ function updateCursor() {
51899
52087
  constraintFlags |= flag;
51900
52088
  }), intersectsHorizontal && intersectsVertical ? setGlobalCursorStyle("intersection", constraintFlags) : intersectsHorizontal ? setGlobalCursorStyle("horizontal", constraintFlags) : intersectsVertical ? setGlobalCursorStyle("vertical", constraintFlags) : resetGlobalCursorStyle();
51901
52089
  }
51902
- let listenersAbortController = new AbortController();
52090
+ let listenersAbortController;
51903
52091
  function updateListeners() {
51904
- listenersAbortController.abort(), listenersAbortController = new AbortController();
52092
+ var _listenersAbortContro;
52093
+ (_listenersAbortContro = listenersAbortController) === null || _listenersAbortContro === void 0 || _listenersAbortContro.abort(), listenersAbortController = new AbortController();
51905
52094
  const options = {
51906
52095
  capture: !0,
51907
52096
  signal: listenersAbortController.signal