Pular para o conteúdo

Componentes React

NPM Version

A biblioteca React do LikeC4 permite incorporar diagramas às suas aplicações.
Embora você possa utilizá-la diretamente, considere o plugin para Vite ou a geração de código pela CLI para simplificar a experiência de desenvolvimento.

É necessário ter react e react-dom instalados.
Adicione @likec4/core e @likec4/diagram:

npm i @likec4/core @likec4/diagram

Diagramas em foco oferecem atalhos de teclado para zoom. Clique em um diagrama ou acesse-o pela tecla Tab; enquanto ele estiver em foco, esses atalhos controlam o zoom do diagrama, e não o zoom da página do navegador. Retire o foco do diagrama com Tab para utilizar o zoom do navegador.

Atalho Ação
Ctrl/Cmd + + or = Ampliar
Ctrl/Cmd + - or _ Reduzir
Ctrl/Cmd + 0 Redefinir a área de visualização

A biblioteca React do LikeC4 pode ser utilizada de duas formas.

Esta é a maneira mais simples de utilizar a biblioteca.
O diagrama é renderizado no Shadow DOM, com todas as dependências incluídas e estilos gerenciados automaticamente.

A renderização do diagrama exige uma instância de LikeC4Model.Layouted. Prepare o modelo e envolva o diagrama com o componente LikeC4ModelProvider.
A seguir, algumas maneiras de preparar o modelo:

  • Utilizando geração de código pela CLI
  • Utilizando arquivos-fonte
  • Utilizando o Model Builder

Prepare o modelo com a geração de código:

Terminal window
likec4 codegen model --outfile ./likec4-model.ts

Em seguida:

import { LikeC4ModelProvider } from 'likec4/react'
// import model from generated file
import { likec4model } from './likec4-model.ts'
function App() {
return (
<LikeC4ModelProvider likec4model={likec4model}>
{/* ... */}
</LikeC4ModelProvider>
)
}
import { LikeC4View, LikeC4ModelProvider } from 'likec4/react'
function App() {
return (
<LikeC4ModelProvider likec4model={likec4model}>
<LikeC4View
viewId="index1"
onNodeClick={(nodeId) => console.log(nodeId)}
/>
{/* Possible to have multiple views */}
<LikeC4View viewId="index2" />
</LikeC4ModelProvider>
)
}

Consulte LikeC4ViewProps para conhecer as propriedades disponíveis.

LikeC4View renderiza visões do modelo e permite explorá-las em uma janela de navegação. Esse componente atende à maioria dos cenários. Caso precise de mais funcionalidades, utilize ReactLikeC4:

import { ReactLikeC4, LikeC4ModelProvider } from 'likec4/react'
function App() {
const [viewId, setViewId] = useState('index')
return (
<LikeC4ModelProvider likec4model={likec4model}>
<ReactLikeC4
viewId={viewId}
pannable
zoomable={false}
keepAspectRatio
showNavigationButtons
enableDynamicViewWalkthrough={false}
enableElementDetails
enableRelationshipDetails
showDiagramTitle={false}
onNavigateTo={setViewId}
onNodeClick={...}
/>
</LikeC4ModelProvider>
)
}

Hooks disponíveis dentro de LikeC4View ou ReactLikeC4:

import {
useLikeC4Model,
useLikeC4Specification,
useLikeC4ViewModel,
useEnabledFeatures,
useCurrentViewId,
// XYFlow hooks
useXYFlow,
useXYStore,
useXYStoreApi,
// Diagram API
useDiagram,
// Select from state
useDiagramContext
} from 'likec4/react'

Se você utilizar os ícones integrados, instale @likec4/icons (ou utilize likec4/icons):

import type { ElementIconRenderer } from 'likec4/react'
import { LikeC4ModelProvider, LikeC4View, ReactLikeC4 } from 'likec4/react'
import { lazy, Suspense } from 'react'
// Better to lazy load icons, bundle is quite large at the moment
const Icon = lazy(async () => {
const { IconRenderer } = await import('@likec4/icons/all')
return { default: IconRenderer }
})
const IconRenderer: ElementIconRenderer = (props) => (
<Suspense>
<Icon {...props} />
</Suspense>
)
function App() {
return (
<LikeC4ModelProvider likec4model={likec4model}>
<LikeC4View
viewId="index1"
renderIcon={IconRenderer}
/>
{/* Same for ReactLikeC4 */}
<ReactLikeC4
viewId="index2"
renderIcon={IconRenderer}
/>
</LikeC4ModelProvider>
)
}

Se quiser utilizar o pacote como biblioteca com seu bundler, será necessário gerenciar o CSS.

A biblioteca utiliza Mantine. Se sua aplicação já utilizar MantineProvider, o diagrama LikeC4 aproveitará esse provedor. Caso contrário, o diagrama será envolvido automaticamente por MantineProvider.
Mesmo que sua aplicação não utilize Mantine diretamente, os estilos da biblioteca são necessários para os diagramas (e o Mantine permite eliminar código não utilizado via tree-shaking).

Confira as opções:

  1. Importe todos os estilos

    @import '@likec4/diagram/styles.css'

    Isso inclui todos os estilos, inclusive os do Mantine.

  2. Se você já utiliza Mantine

    @layer reset, base, mantine, xyflow, tokens, recipes, utilities;
    @import "@mantine/core/styles.layer.css";
    @import "@likec4/diagram/styles-min.css";
  3. Fonte.
    Por padrão, LikeC4Diagram utiliza a fonte IBM Plex Sans Variable.
    Você pode incluí-la no bundle, importá-la pelo fontsource, utilizar outra CDN ou usar:

    @import '@likec4/diagram/styles-font.css'

    Você pode substituir a fonte, conforme explicado adiante.

Consulte a documentação do PandaCSS para obter as instruções completas de configuração.
O LikeC4 disponibiliza um preset.

npm i @likec4/styles

Configure seu panda.config.ts:

import likec4preset from '@likec4/styles/preset'
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
include: [
'src/**/*.{ts,tsx}',
// Include likec4 diagram source code to get the styles
'./node_modules/@likec4/diagram/panda.buildinfo.json',
],
importMap: [
'@likec4/styles',
],
presets: [
likec4preset,
],
theme: {
extend: {
// Here you can override/extend the theme
},
},
})

Seu CSS global deverá ter esta estrutura:

@layer reset, base, mantine, xyflow, tokens, recipes, utilities;
@import "@mantine/core/styles.layer.css";
@import "@likec4/diagram/styles-xyflow.css";
@import "@likec4/diagram/styles-font.css";

O uso é semelhante ao de ReactLikeC4, mas a importação deve ser feita de @likec4/diagram. É necessário fornecer uma instância de DiagramView:

import { LikeC4Diagram, LikeC4ModelProvider, useLikeC4ViewModel } from '@likec4/diagram'
function LikeC4View({viewId}: {viewId: string}) {
const view = useLikeC4ViewModel(viewId)
if (!view) {
return <>View not found</>
}
return (
<LikeC4Diagram
view={view.$view}
readOnly
pannable
zoomable={false}
keepAspectRatio
showNavigationButtons
enableDynamicViewWalkthrough={false}
enableElementDetails
enableRelationshipDetails
showDiagramTitle={false}
/>
)
}
function App() {
return (
<LikeC4ModelProvider likec4model={likec4model}>
<LikeC4View viewId="index" />
</LikeC4ModelProvider>
)
}

É possível renderizar qualquer componente dentro de LikeC4Diagram
(ou de LikeC4View/ReactLikeC4, caso utilize o pacote completo):

import { LikeC4Diagram, LikeC4ModelProvider } from '@likec4/diagram'
import { Panel, ViewportPortal } from '@xyflow/react'
function App() {
return (
<LikeC4Diagram>
<YourComponent />
{/* You can use components from xyflow */}
<Panel position="top">
<p>Your component as a panel</p>
<a href="https://reactflow.dev/examples">Check examples</a>
</Panel>
<ViewportPortal>
<div
style={{
transform: 'translate(100px, 100px)',
position: 'absolute',
}}>
This div is positioned at [100, 100] on the diagram canvas
</div>
</ViewportPortal>
</LikeC4Diagram>
)
}

LikeC4Diagram permite utilizar renderizadores personalizados para os nós.
Crie renderizadores personalizados usando os componentes básicos de @likec4/diagram/custom
(ou de likec4/react, que também exporta esses componentes).
Consulte customNodes.tsx para ver exemplos.

import { LikeC4Diagram } from '@likec4/diagram'
import {
ElementActions,
ElementDetailsButtonWithHandler,
elementNode,
ElementNodeContainer,
ElementShape,
ElementToolbar,
IfNotReadOnly,
} from '@likec4/diagram/custom'
import { IconPlus } from '@tabler/icons-react'
const customNodes = {
element: elementNode(({ nodeProps, nodeModel }) => (
<ElementNodeContainer nodeProps={nodeProps}>
<ElementShape {...nodeProps} />
{/* Add extra buttons */}
<ElementActions
{...nodeProps}
extraButtons={[
{
key: 'plus',
icon: <IconPlus />,
onClick: () => console.log('extra'),
},
]}
/>
{/* Add extra info */}
<div style={{ position: 'absolute', bottom: 0 }}>
{nodeModel.element.getMetadata('your-attr')}
</div>
</ElementNodeContainer>
)),
}
function App() {
return (
<LikeC4Diagram
view={view}
renderNodes={customNodes}
/>
)
}

Você também pode utilizar hooks para acessar o modelo e a API do diagrama.

LikeC4Diagram utiliza PandaCSS para aplicar estilos, que podem ser personalizados.

TODO: adicionar exemplo