Componentes React
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.
Como usar
Seção intitulada “Como usar”É necessário ter react e react-dom instalados.
Adicione @likec4/core e @likec4/diagram:
npm i @likec4/core @likec4/diagrampnpm add @likec4/core @likec4/diagramyarn add @likec4/core @likec4/diagrambun add @likec4/core @likec4/diagramAtalhos de teclado
Seção intitulada “Atalhos de teclado”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.
Pacote completo
Seção intitulada “Pacote completo”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.
LikeC4ModelProvider
Seção intitulada “LikeC4ModelProvider”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:
likec4 codegen model --outfile ./likec4-model.tsEm seguida:
import { LikeC4ModelProvider } from 'likec4/react'// import model from generated fileimport { likec4model } from './likec4-model.ts'
function App() { return ( <LikeC4ModelProvider likec4model={likec4model}> {/* ... */} </LikeC4ModelProvider> )}Também é possível preparar o modelo a partir de uma string. Consulte Utilização da API:
import { LikeC4 } from 'likec4'import { LikeC4ModelProvider } from 'likec4/react'
const likec4 = await LikeC4.fromWorkspace('/path/to/workspace')const likec4model = await likec4.layoutedModel()
function App() { return ( <LikeC4ModelProvider likec4model={likec4model}> {/* ... */} </LikeC4ModelProvider> )}Você pode preparar o modelo com o Builder e depois calcular o layout com layoutLikeC4Model:
import { LikeC4ModelProvider } from 'likec4/react'import { Builder } from "@likec4/core/builder"import { layoutLikeC4Model } from "@likec4/layouts"
const computedModel = Builder .specification({46 collapsed lines
elements: { actor: { style: { shape: 'person', }, }, system: {}, component: {}, }, relationships: { likes: {}, }, tags: ['tag1', 'tag2', 'tag1'], }) .model(({ actor, system, component, relTo, rel }, _) => _( actor('alice'), actor('bob'), rel('alice', 'bob', { tags: ['tag1'], // you get code completion for tags kind: 'likes', // code completion for kind }), system('cloud', { tags: ['tag1', 'tag2'] }).with( component('backend').with( component('api'), component('db'), // code completion for relationships rel('cloud.backend.api', 'cloud.backend.db') ), component('frontend').with( relTo('cloud.backend.api') ), ), ) ) .views(({ view, viewOf, $include, $style }, _) => _( view('index', 'Index').with( $include('cloud.*'), ), viewOf('ui', 'cloud.ui').with( $include('* -> cloud.**'), $style('cloud.ui', { color: 'red' }), ), ) ) .toLikeC4Model()
// The Builder returns a computed model. To render it, you need to lay it outconst likec4model = await layoutLikeC4Model(computedModel)
function App() { return ( <LikeC4ModelProvider likec4model={likec4model}> {/* ... */} </LikeC4ModelProvider> )}LikeC4View
Seção intitulada “LikeC4View”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.
ReactLikeC4
Seção intitulada “ReactLikeC4”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 momentconst 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> )}Biblioteca
Seção intitulada “Biblioteca”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:
Com estilos incluídos
Seção intitulada “Com estilos incluídos”-
Importe todos os estilos
@import '@likec4/diagram/styles.css'Isso inclui todos os estilos, inclusive os do Mantine.
-
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"; -
Fonte.
Por padrão,LikeC4Diagramutiliza a fonteIBM 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.
Com PandaCSS
Seção intitulada “Com PandaCSS”Consulte a documentação do PandaCSS para obter as instruções completas de configuração.
O LikeC4 disponibiliza um preset.
npm i @likec4/stylespnpm add @likec4/stylesyarn add @likec4/stylesbun add @likec4/stylesConfigure 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";Como usar
Seção intitulada “Como usar”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> )}Personalização
Seção intitulada “Personalização”É 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> )}Renderizadores personalizados de nós
Seção intitulada “Renderizadores personalizados de nós”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.
Estilos personalizados
Seção intitulada “Estilos personalizados”LikeC4Diagram utiliza PandaCSS para aplicar estilos, que podem ser personalizados.
TODO: adicionar exemplo