likec4 0.44.1 → 0.45.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 (32) hide show
  1. package/dist/@likec4/diagrams/components/primitives/fullscreen/FullscreenDiagram.js +8 -7
  2. package/dist/@likec4/diagrams/diagram/Diagram.js +16 -5
  3. package/dist/@likec4/diagrams/diagram/Edges.js +32 -16
  4. package/dist/@likec4/diagrams/diagram/Nodes.js +75 -77
  5. package/dist/@likec4/diagrams/diagram/icons/ZoomIn.js +2 -3
  6. package/dist/@likec4/diagrams/diagram/shapes/Browser.js +43 -9
  7. package/dist/@likec4/diagrams/diagram/shapes/Compound.js +8 -10
  8. package/dist/@likec4/diagrams/diagram/shapes/Cylinder.js +3 -1
  9. package/dist/@likec4/diagrams/diagram/shapes/Edge.js +7 -7
  10. package/dist/@likec4/diagrams/diagram/shapes/Mobile.js +19 -4
  11. package/dist/@likec4/diagrams/diagram/shapes/NodeIcon.js +47 -9
  12. package/dist/@likec4/diagrams/diagram/shapes/NodeLabel.js +31 -54
  13. package/dist/@likec4/diagrams/diagram/shapes/Person.js +3 -1
  14. package/dist/@likec4/diagrams/diagram/shapes/Queue.js +3 -1
  15. package/dist/@likec4/diagrams/diagram/shapes/Rectangle.js +3 -1
  16. package/dist/@likec4/diagrams/diagram/shapes/index.js +1 -1
  17. package/dist/@likec4/diagrams/diagram/shapes/utils.js +1 -1
  18. package/dist/@likec4/diagrams/diagram/state/atoms.js +6 -0
  19. package/dist/@likec4/diagrams/diagram/state/hooks.js +10 -1
  20. package/dist/@likec4/diagrams/hooks/useImageLoader.js +7 -1
  21. package/dist/__app__/likec4.css +4 -0
  22. package/dist/__app__/src/App.jsx +25 -5
  23. package/dist/__app__/src/components/DiagramNotFound.jsx +10 -4
  24. package/dist/__app__/src/pages/embed.page.jsx +12 -0
  25. package/dist/__app__/src/pages/export.page.jsx +9 -6
  26. package/dist/__app__/src/pages/index.js +1 -0
  27. package/dist/__app__/src/pages/view.page.jsx +8 -8
  28. package/dist/__app__/src/router.js +2 -2
  29. package/dist/__app__/tailwind.config.cjs +1 -3
  30. package/dist/__app__/tsconfig.json +1 -2
  31. package/dist/cli/index.js +145 -145
  32. package/package.json +6 -7
@@ -1,23 +1,28 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import useImageLoader from "../../hooks/useImageLoader.js";
3
3
  import { Image } from "../../konva.js";
4
- export function NodeIcon({ icon, maxWidth, maxHeight, offsetX = 0, offsetY = 0 }) {
4
+ function IconImage({
5
+ icon,
6
+ centerX,
7
+ centerY,
8
+ maxWidth,
9
+ maxHeight,
10
+ offsetX = 0,
11
+ offsetY = 0
12
+ }) {
5
13
  const [image] = useImageLoader(icon);
6
14
  if (!image) {
7
15
  return null;
8
16
  }
9
- const padding = 16;
10
- const maxIconWidth = Math.round(maxWidth - padding * 2);
11
- const maxIconHeight = Math.round(maxHeight - padding * 2);
12
- const scale = Math.min(maxIconWidth / image.width, maxIconHeight / image.height, 1);
13
- const iconWidth = Math.floor(image.width * scale);
14
- const iconHeight = Math.floor(image.height * scale);
17
+ const scale = Math.min(maxWidth / image.naturalWidth, maxHeight / image.naturalHeight);
18
+ const iconWidth = Math.floor(image.naturalWidth * scale);
19
+ const iconHeight = Math.floor(image.naturalHeight * scale);
15
20
  return /* @__PURE__ */ jsx(
16
21
  Image,
17
22
  {
18
23
  image,
19
- x: padding + (maxIconWidth - iconWidth) / 2,
20
- y: padding + (maxIconHeight - iconHeight) / 2,
24
+ x: centerX - iconWidth / 2,
25
+ y: centerY - iconHeight / 2,
21
26
  offsetX,
22
27
  offsetY,
23
28
  width: iconWidth,
@@ -27,3 +32,36 @@ export function NodeIcon({ icon, maxWidth, maxHeight, offsetX = 0, offsetY = 0 }
27
32
  }
28
33
  );
29
34
  }
35
+ export function NodeIcon({
36
+ node,
37
+ maxWidth,
38
+ paddingX = 24,
39
+ paddingY = 24,
40
+ offsetX = 0,
41
+ offsetY = 0
42
+ }) {
43
+ if (!node.icon) {
44
+ return null;
45
+ }
46
+ const firstLabel = node.labels[0];
47
+ if (!firstLabel) {
48
+ return null;
49
+ }
50
+ const firstLabelY = Math.floor(firstLabel.pt[1] - firstLabel.fontSize * 1.25);
51
+ const maxIconHeight = Math.round(firstLabelY - paddingY - 8);
52
+ const maxIconWidth = maxWidth ?? node.size.width - paddingX * 2;
53
+ const centerY = paddingY + Math.floor(maxIconHeight / 2);
54
+ const centerX = Math.floor(node.size.width / 2);
55
+ return /* @__PURE__ */ jsx(
56
+ IconImage,
57
+ {
58
+ icon: node.icon,
59
+ centerX,
60
+ centerY,
61
+ maxWidth: maxIconWidth,
62
+ maxHeight: maxIconHeight,
63
+ offsetX,
64
+ offsetY
65
+ }
66
+ );
67
+ }
@@ -1,59 +1,36 @@
1
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { Text } from "../../konva.js";
3
- import { NodeIcon } from "./NodeIcon.js";
4
- export function NodeLabels({
5
- node: { icon, labels, size, color },
6
- theme,
7
- offsetX = 0,
8
- offsetY = 0,
9
- maxWidth
10
- }) {
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Group, Text } from "../../konva.js";
3
+ export function NodeLabels({ node, theme, offsetX = 0, offsetY = 0, maxWidth }) {
4
+ const { labels, size, color } = node;
11
5
  const colors = theme.elements[color];
12
- const width = maxWidth ?? size.width;
13
- const firstLabel = labels[0];
14
- const titleFontSize = firstLabel?.fontSize ?? 12;
15
- let nodeIcon;
16
- if (icon) {
17
- const maxHeight = firstLabel ? Math.floor(firstLabel.pt[1] - firstLabel.fontSize / 2) : size.height;
18
- nodeIcon = /* @__PURE__ */ jsx(
19
- NodeIcon,
6
+ const width = maxWidth ?? size.width - 40;
7
+ const titleFontSize = labels[0]?.fontSize ?? 18;
8
+ const x = Math.ceil((size.width - width) / 2);
9
+ return /* @__PURE__ */ jsx(Group, { x, y: 3, offsetX, offsetY, children: labels.map((label, i) => {
10
+ const isTitle = label.fontSize === titleFontSize;
11
+ let color2 = colors.hiContrast;
12
+ if (!isTitle) {
13
+ color2 = colors.loContrast;
14
+ }
15
+ return /* @__PURE__ */ jsx(
16
+ Text,
20
17
  {
21
- icon,
22
- maxWidth: width,
23
- maxHeight,
24
- offsetX,
25
- offsetY
26
- }
18
+ text: label.text,
19
+ x: 0,
20
+ y: label.pt[1] - label.fontSize,
21
+ width,
22
+ fill: color2,
23
+ fontFamily: theme.font,
24
+ fontSize: label.fontSize,
25
+ fontStyle: label.fontStyle ?? "normal",
26
+ align: "center",
27
+ wrap: "none",
28
+ strokeEnablaed: false,
29
+ perfectDrawEnabled: false,
30
+ listening: false
31
+ },
32
+ label.text + i
27
33
  );
28
- }
29
- return /* @__PURE__ */ jsxs(Fragment, { children: [
30
- nodeIcon,
31
- labels.map((label, i) => {
32
- let color2 = colors.hiContrast;
33
- if (label.fontSize !== titleFontSize) {
34
- color2 = colors.loContrast;
35
- }
36
- return /* @__PURE__ */ jsx(
37
- Text,
38
- {
39
- x: 8,
40
- width: width - 16,
41
- y: label.pt[1],
42
- offsetY: offsetY + label.fontSize / 2,
43
- offsetX,
44
- fill: color2,
45
- fontFamily: theme.font,
46
- fontSize: label.fontSize,
47
- fontStyle: label.fontStyle ?? "normal",
48
- align: "center",
49
- text: label.text,
50
- strokeEnabled: false,
51
- perfectDrawEnabled: false,
52
- listening: false
53
- },
54
- label.text + i
55
- );
56
- })
57
- ] });
34
+ }) });
58
35
  }
59
36
  NodeLabels.displayName = "NodeLabels";
@@ -2,6 +2,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useShadowSprings } from "../springs.js";
3
3
  import { AnimatedPath, AnimatedRect } from "../../konva.js";
4
4
  import { NodeLabels } from "./NodeLabel.js";
5
+ import { NodeIcon } from "./NodeIcon.js";
5
6
  const PersonIcon = {
6
7
  width: 115,
7
8
  height: 120,
@@ -37,6 +38,7 @@ export function PersonShape({ node, theme, springs, isHovered }) {
37
38
  listening: false
38
39
  }
39
40
  ),
40
- /* @__PURE__ */ jsx(NodeLabels, { node, theme })
41
+ /* @__PURE__ */ jsx(NodeLabels, { node, theme }),
42
+ /* @__PURE__ */ jsx(NodeIcon, { node })
41
43
  ] });
42
44
  }
@@ -3,6 +3,7 @@ import { useShadowSprings } from "../springs.js";
3
3
  import { AnimatedEllipse, AnimatedPath } from "../../konva.js";
4
4
  import { NodeLabels } from "./NodeLabel.js";
5
5
  import { useSpring } from "@react-spring/konva";
6
+ import { NodeIcon } from "./NodeIcon.js";
6
7
  function queueSVGPath(width, height, tilt = 0.2) {
7
8
  const diameter = height;
8
9
  const radius = Math.round(diameter / 2);
@@ -52,6 +53,7 @@ export function QueueShape({ node, theme, springs, isHovered }) {
52
53
  fill: springs.stroke
53
54
  }
54
55
  ),
55
- /* @__PURE__ */ jsx(NodeLabels, { node, maxWidth: width - rx * 2, theme })
56
+ /* @__PURE__ */ jsx(NodeLabels, { node, maxWidth: width - 2 * rx - 10, offsetX: rx, theme }),
57
+ /* @__PURE__ */ jsx(NodeIcon, { node, maxWidth: width - 2 * rx - 10, offsetX: rx })
56
58
  ] });
57
59
  }
@@ -1,6 +1,7 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { AnimatedRect } from "../../konva.js";
3
3
  import { useShadowSprings } from "../springs.js";
4
+ import { NodeIcon } from "./NodeIcon.js";
4
5
  import { NodeLabels } from "./NodeLabel.js";
5
6
  export function RectangleShape({ node, theme, springs, isHovered }) {
6
7
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -15,6 +16,7 @@ export function RectangleShape({ node, theme, springs, isHovered }) {
15
16
  fill: springs.fill
16
17
  }
17
18
  ),
18
- /* @__PURE__ */ jsx(NodeLabels, { node, theme })
19
+ /* @__PURE__ */ jsx(NodeLabels, { node, theme }),
20
+ /* @__PURE__ */ jsx(NodeIcon, { node })
19
21
  ] });
20
22
  }
@@ -4,4 +4,4 @@ export { CylinderShape } from "./Cylinder.js";
4
4
  export { MobileShape } from "./Mobile.js";
5
5
  export { QueueShape } from "./Queue.js";
6
6
  export { PersonShape } from "./Person.js";
7
- export { EdgeShape } from "./Edge.js";
7
+ export { Edge } from "./Edge.js";
@@ -7,6 +7,6 @@ export function mousePointer(e) {
7
7
  export function mouseDefault(e) {
8
8
  const container = e.target.getStage()?.container();
9
9
  if (container) {
10
- container.style.cursor = "auto";
10
+ container.style.cursor = "";
11
11
  }
12
12
  }
@@ -93,3 +93,9 @@ export const hoveredEdgeAtom = atom(
93
93
  }
94
94
  );
95
95
  export const hoveredEdgeIdAtom = selectAtom(hoveredEdgeAtom, (edge) => edge?.id ?? null);
96
+ export const resetHoveredStatesAtom = atom(void 0, (get, set) => {
97
+ clearTimeout(get(nodeTimeoutAtom));
98
+ clearTimeout(get(edgeTimeoutAtom));
99
+ set(currentHoveredNodeAtom, null);
100
+ set(currentHoveredEdgeAtom, null);
101
+ });
@@ -1,5 +1,11 @@
1
1
  import { useAtom, useAtomValue, useSetAtom } from "jotai";
2
- import { hoveredEdgeAtom, hoveredEdgeIdAtom, hoveredNodeAtom, hoveredNodeIdAtom } from "./atoms.js";
2
+ import {
3
+ hoveredEdgeAtom,
4
+ hoveredEdgeIdAtom,
5
+ hoveredNodeAtom,
6
+ hoveredNodeIdAtom,
7
+ resetHoveredStatesAtom
8
+ } from "./atoms.js";
3
9
  export function useHoveredNode() {
4
10
  return useAtom(hoveredNodeAtom);
5
11
  }
@@ -18,3 +24,6 @@ export function useHoveredEdgeId() {
18
24
  export function useSetHoveredEdge() {
19
25
  return useSetAtom(hoveredEdgeAtom);
20
26
  }
27
+ export function useResetHoveredStates() {
28
+ return useSetAtom(resetHoveredStatesAtom);
29
+ }
@@ -8,10 +8,14 @@ export default function useImageLoader(url, crossOrigin, referrerpolicy) {
8
8
  const statusRef = useRef(imageRef.current ? "loaded" : "loading");
9
9
  const [_, setStateToken] = useState(0);
10
10
  const urlRef = useRef(url);
11
- if (!url || urlRef.current !== url) {
11
+ const crossOriginRef = useRef(crossOrigin);
12
+ const referrerPolicyRef = useRef(referrerpolicy);
13
+ if (!url || urlRef.current !== url || crossOriginRef.current !== crossOrigin || referrerPolicyRef.current !== referrerpolicy) {
12
14
  statusRef.current = "loading";
13
15
  imageRef.current = void 0;
14
16
  urlRef.current = url;
17
+ crossOriginRef.current = crossOrigin;
18
+ referrerPolicyRef.current = referrerpolicy;
15
19
  }
16
20
  useLayoutEffect(() => {
17
21
  if (!url) {
@@ -28,6 +32,8 @@ export default function useImageLoader(url, crossOrigin, referrerpolicy) {
28
32
  return;
29
33
  }
30
34
  const img = document.createElement("img");
35
+ img.style.width = "100%";
36
+ img.style.height = "auto";
31
37
  function onload() {
32
38
  if (!isMounted())
33
39
  return;
@@ -15,4 +15,8 @@ html, body {
15
15
 
16
16
  .transparent-bg {
17
17
  --color-page-background: transparent !important;
18
+
19
+ body {
20
+ background-color: transparent !important;
21
+ }
18
22
  }
@@ -1,15 +1,35 @@
1
1
  import { Provider } from 'jotai';
2
2
  import { Fragment } from 'react';
3
3
  import { Sidebar } from './components';
4
- import { ExportPage, IndexPage, ViewPage } from './pages';
4
+ import { ExportPage, IndexPage, EmbedPage, ViewPage } from './pages';
5
5
  import { useRoute } from './router';
6
6
  import { Theme } from '@radix-ui/themes';
7
+ import { nonexhaustive } from '@likec4/core';
7
8
  const Routes = () => {
8
9
  const r = useRoute();
9
- return (<Theme hasBackground={r.route !== 'export'} accentColor='indigo' radius='small' appearance={r.params?.theme}>
10
- {r.route === 'index' && <IndexPage key='index'/>}
11
- {r.route === 'view' && <ViewPage key='view' viewId={r.params.viewId} showUI={r.showUI}/>}
12
- {r.route === 'export' && (<ExportPage key='export' viewId={r.params.viewId} padding={r.params.padding}/>)}
10
+ let page = null;
11
+ switch (r.route) {
12
+ case 'view': {
13
+ page = <ViewPage key='view' viewId={r.params.viewId} showUI={r.showUI}/>;
14
+ break;
15
+ }
16
+ case 'export': {
17
+ page = <ExportPage key='export' viewId={r.params.viewId} padding={r.params.padding}/>;
18
+ break;
19
+ }
20
+ case 'embed': {
21
+ page = <EmbedPage key='embed' viewId={r.params.viewId} padding={r.params.padding}/>;
22
+ break;
23
+ }
24
+ case 'index': {
25
+ page = <IndexPage key='index'/>;
26
+ break;
27
+ }
28
+ default:
29
+ nonexhaustive(r);
30
+ }
31
+ return (<Theme hasBackground={r.route !== 'export'} accentColor='indigo' radius='small' appearance={r.route !== 'export' ? r.params?.theme ?? 'inherit' : undefined}>
32
+ {page}
13
33
  {r.showUI && (<Fragment key='ui'>
14
34
  <Sidebar />
15
35
  </Fragment>)}
@@ -1,7 +1,7 @@
1
1
  import { ExclamationTriangleIcon } from '@radix-ui/react-icons';
2
- import { Box, Button, Card, Flex, Heading, IconButton, Text } from '@radix-ui/themes';
2
+ import { Box, Button, Card, Code, Flex, Heading, IconButton, Text } from '@radix-ui/themes';
3
3
  import { $pages } from '../router';
4
- export const DiagramNotFound = () => {
4
+ export const DiagramNotFound = ({ viewId }) => {
5
5
  return (<Flex position='fixed' inset='0' align='center' justify='center'>
6
6
  <Card color='red' size='3'>
7
7
  <Flex gap='4' direction='row' align='start'>
@@ -14,9 +14,15 @@ export const DiagramNotFound = () => {
14
14
  <Heading trim='both' color='amber' size='4'>
15
15
  Diagram not found
16
16
  </Heading>
17
- <Text as='div'>The diagram you are looking for does not exist.</Text>
17
+ <Text as='div'>
18
+ The diagram{' '}
19
+ <Code color='amber' variant='soft'>
20
+ {viewId}
21
+ </Code>{' '}
22
+ does not exist
23
+ </Text>
18
24
  <Box pt='2'>
19
- <Button variant='soft' color='amber' onClick={() => $pages.index.open()}>
25
+ <Button variant='soft' color='amber' className='cursor-pointer' onClick={() => $pages.index.open()}>
20
26
  Go to overview
21
27
  </Button>
22
28
  </Box>
@@ -0,0 +1,12 @@
1
+ import { Diagram } from '@likec4/diagrams';
2
+ import { useWindowSize } from '@react-hookz/web/esm';
3
+ import { DiagramNotFound } from '../components';
4
+ import { useLikeC4View } from '../data';
5
+ export function EmbedPage({ viewId, padding }) {
6
+ const { width, height } = useWindowSize();
7
+ const diagram = useLikeC4View(viewId);
8
+ if (!diagram) {
9
+ return <DiagramNotFound viewId={viewId}/>;
10
+ }
11
+ return <Diagram diagram={diagram} padding={padding} width={width} height={height}/>;
12
+ }
@@ -1,6 +1,6 @@
1
1
  import { Diagram } from '@likec4/diagrams';
2
2
  import { useWindowSize } from '@react-hookz/web/esm';
3
- import { useLayoutEffect } from 'react';
3
+ import { useEffect } from 'react';
4
4
  import { DiagramNotFound } from '../components';
5
5
  import { useLikeC4View } from '../data';
6
6
  export function ExportPage({ viewId, padding }) {
@@ -8,16 +8,19 @@ export function ExportPage({ viewId, padding }) {
8
8
  const diagram = useLikeC4View(viewId);
9
9
  // To get the transparent background
10
10
  // We need to add a class to the HTML element
11
- useLayoutEffect(() => {
11
+ useEffect(() => {
12
+ const htmlEl = document.body.parentElement;
13
+ if (!htmlEl)
14
+ return;
12
15
  // see ../../likec4.css
13
16
  const classname = 'transparent-bg';
14
- document.body.parentElement?.classList.add(classname);
17
+ htmlEl.classList.add(classname);
15
18
  return () => {
16
- document.body.parentElement?.classList.remove(classname);
19
+ htmlEl.classList.remove(classname);
17
20
  };
18
21
  }, []);
19
22
  if (!diagram) {
20
- return <DiagramNotFound />;
23
+ return <DiagramNotFound viewId={viewId}/>;
21
24
  }
22
- return (<Diagram animate={false} pannable={false} zoomable={false} diagram={diagram} padding={padding} width={width} height={height}/>);
25
+ return (<Diagram animate={false} pannable={false} zoomable={false} maxZoom={1} minZoom={1} diagram={diagram} padding={padding} width={width} height={height}/>);
23
26
  }
@@ -1,3 +1,4 @@
1
1
  export * from './index.page';
2
2
  export * from './export.page';
3
+ export * from './embed.page';
3
4
  export * from './view.page';
@@ -1,24 +1,24 @@
1
- import { Diagram, useDiagramApi } from '@likec4/diagrams';
1
+ import { Diagram } from '@likec4/diagrams';
2
2
  import { Box, Flex, Heading, Text } from '@radix-ui/themes';
3
3
  import { useWindowSize } from '@react-hookz/web/esm';
4
4
  import { $pages } from '~/router';
5
5
  import { DiagramNotFound, ViewActionsToolbar } from '../components';
6
6
  import { useLikeC4View } from '../data';
7
- const Paddings = [60, 20, 20, 20];
7
+ import { Fragment } from 'react';
8
+ const Paddings = [70, 20, 20, 40];
8
9
  export function ViewPage({ viewId, showUI = true }) {
9
10
  const { width, height } = useWindowSize();
10
- const [ref, diagramApi] = useDiagramApi();
11
11
  const diagram = useLikeC4View(viewId);
12
12
  if (!diagram) {
13
- return <DiagramNotFound />;
13
+ return <DiagramNotFound viewId={viewId}/>;
14
14
  }
15
15
  return (<Box position={'fixed'} inset='0' className='overflow-hidden'>
16
- <Diagram ref={ref} diagram={diagram} padding={showUI ? Paddings : undefined} width={width} height={height} onNodeClick={node => {
16
+ <Diagram diagram={diagram} padding={showUI ? Paddings : undefined} width={width} height={height} onNodeClick={node => {
17
17
  if (node.navigateTo) {
18
18
  $pages.view.open(node.navigateTo);
19
19
  }
20
20
  }} onEdgeClick={_ => ({})}/>
21
- {showUI && (<>
21
+ {showUI && (<Fragment key='ui'>
22
22
  <Flex position={'fixed'} top='0' p='3' style={{
23
23
  left: 54
24
24
  }} direction={'column'}>
@@ -29,7 +29,7 @@ export function ViewPage({ viewId, showUI = true }) {
29
29
  {diagram.title || 'Untitled'}
30
30
  </Heading>
31
31
  </Flex>
32
- <ViewActionsToolbar diagramApi={diagramApi} diagram={diagram}/>
33
- </>)}
32
+ <ViewActionsToolbar diagram={diagram}/>
33
+ </Fragment>)}
34
34
  </Box>);
35
35
  }
@@ -37,11 +37,11 @@ const $route = computed([$router, $searchParams], (r, v) => {
37
37
  }
38
38
  if (r?.route === 'export' || r?.route === 'embed') {
39
39
  return {
40
- route: 'export',
40
+ route: r.route,
41
41
  params: {
42
42
  viewId: r.params.viewId,
43
43
  padding: asPadding(v.padding),
44
- theme: asTheme(v.theme)
44
+ theme: r.route === 'embed' ? asTheme(v.theme) : undefined
45
45
  },
46
46
  showUI: false
47
47
  };
@@ -1,5 +1,4 @@
1
1
  const { radixThemePreset } = require('radix-themes-tw');
2
- const tailwindcssAnimate = require('tailwindcss-animate');
3
2
  const { resolve } = require('node:path');
4
3
 
5
4
  /** @type {import('tailwindcss').Config} */
@@ -14,6 +13,5 @@ module.exports = {
14
13
  // ...
15
14
  // Preflight is enabled by default, we disable it here
16
15
  preflight: false
17
- },
18
- plugins: [tailwindcssAnimate],
16
+ }
19
17
  };
@@ -31,7 +31,6 @@
31
31
  ]
32
32
  },
33
33
  "include": [
34
- "src",
35
- "src/likec4-views.ts"
34
+ "src"
36
35
  ]
37
36
  }