{"id":51295934,"url":"https://github.com/collagejs/react","last_synced_at":"2026-06-30T14:30:47.485Z","repository":{"id":366736509,"uuid":"1277568673","full_name":"collagejs/react","owner":"collagejs","description":"React integration for the CollageJS micro-frontend library","archived":false,"fork":false,"pushed_at":"2026-06-23T05:03:00.000Z","size":82,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-23T06:17:02.526Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/collagejs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-23T02:21:35.000Z","updated_at":"2026-06-23T04:48:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/collagejs/react","commit_stats":null,"previous_names":["collagejs/react"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/collagejs/react","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collagejs%2Freact","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collagejs%2Freact/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collagejs%2Freact/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collagejs%2Freact/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/collagejs","download_url":"https://codeload.github.com/collagejs/react/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/collagejs%2Freact/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34971616,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-30T14:30:46.492Z","updated_at":"2026-06-30T14:30:47.477Z","avatar_url":"https://github.com/collagejs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg src=\"https://raw.githubusercontent.com/collagejs/core/HEAD/src/logos/collagejs-48.svg\" alt=\"CollageJS Logo\" width=\"48\" height=\"48\" align=\"left\"\u003e @collagejs/react\n\n\u003e React integration for the CollageJS micro-frontend library\n\n[Online Documentation](https://collagejs.dev)\n\nThis is the official React package for *CollageJS*. It is used for two complementary tasks:\n\n1. Create `CorePiece` objects from React components.\n2. Consume `CorePiece` objects (built with any framework or library) in React projects.\n\n\u003e ⚠️ **AI-GENERATED**\n\u003e \n\u003e This package's main functionality was mainly produced by Github Copilot.  Unit testing and test projects say this is working as expected, but if you encounter issues, have this in mind and if you have the expertise, have a look at the source code to help speed up any potential fixes.\n\n## Installation\n\nAs a first step, create your Vite + React project:\n\n```bash\nnpm create vite@latest --template react-ts\n# OR:\nnpm create vite@latest --template react-compiler-ts\n```\n\nNow proceed to add these packages to make the project a CollageJS Piece project:\n\n```bash\nnpm install @collagejs/react @collagejs/vite-css\n```\n\nThis is the same for React projects that wish to expose a *CollageJS* piec and React projects that wish to consume *CollageJS* pieces.\n\n## Creating React-Powered CorePiece Objects\n\nWhen building a React-powered *CollageJS* piece (micro-frontend), wrap your root React component with `buildPiece()`.\n\n```tsx\n// piece.tsx\nimport { buildPiece } from \"@collagejs/react\";\nimport { cssMountFactory } from \"@collagejs/vite-css/ex\";\nimport { App } from \"./App\";\n\n// Only one cssMount per entry file is needed.\n// REQUIRED:  The string here is the file's name, without extension.\nconst cssMount = cssMountFactory(\"piece\");\n\nexport function myPieceFactory() {\n  const piece = buildPiece(App /*, { options } */);\n\n  return {\n    // Keep cssMount before piece.mount to prevent FOUC.\n    mount: [cssMount, piece.mount],\n    update: piece.update,\n  };\n}\n```\n\n`buildPiece()` is the public helper. It wraps a React component into a\nCollageJS `CorePiece` object and can be customized with lifecycle hooks and default props through its options argument.\n\n### buildPiece() Options\n\n`buildPiece(Component, options)` supports the following options:\n\n1. `props`: default props merged with runtime props.\n2. `preMount`: callback invoked before the React root is created.\n3. `postUnmount`: callback invoked after unmounting the React root.\n4. `rootOptions`: options forwarded to React's `createRoot(...)`.\n\nExample:\n\n```tsx\nimport { buildPiece } from \"@collagejs/react\";\nimport { App } from \"./App\";\n\nexport const myPieceFactory = () =\u003e\n  buildPiece(App, {\n    rootOptions: {\n      identifierPrefix: \"my-piece-\",\n    },\n  });\n```\n\n## Consuming CorePiece Objects in React\n\nUse the `Piece` component to mount any CollageJS `CorePiece` in a React app.\n\n```tsx\nimport { Piece, piece } from \"@collagejs/react\";\nimport { myPieceFactory } from \"@my/bare-module-specifier\";\n\nexport function Host() {\n  return \u003cPiece {...piece(myPieceFactory())} extra=\"yes\" data={true} /\u003e;\n}\n```\n\nImportant points:\n\n1. Pass the `CorePiece` through the `piece()` helper.\n2. Any other props are forwarded to the mounted piece.\n3. `Piece` can mount into light DOM (default) or shadow DOM.\n\n### React Best Practice: Keep Piece Identity Stable\n\nIn React, avoid creating a new `CorePiece` object on every render. Because\nCollageJS pieces are single-use, repeatedly creating them inline can trigger\nunnecessary remounts and lifecycle conflicts.\n\nPrefer memoizing the piece object:\n\n```tsx\nimport { useMemo } from \"react\";\nimport { Piece, piece } from \"@collagejs/react\";\nimport { myPieceFactory } from \"@my/bare-module-specifier\";\n\nexport function Host() {\n  const corePiece = useMemo(() =\u003e myPieceFactory(), []);\n\n  return \u003cPiece {...piece(corePiece)} extra=\"yes\" data={true} /\u003e;\n}\n```\n\nThis keeps the same piece identity for the lifetime of the component instance.\nDuring HMR, React may still replace modules and identities internally, and this\npackage accepts that development-only case.\n\n### piece() Options\n\nUse the second argument of `piece()` to configure mounting behavior.\n\n```tsx\n\u003cPiece\n  {...piece(myPieceFactory(), {\n    shadow: true,\n    containerProps: { className: \"host\" },\n  })}\n/\u003e\n```\n\n\u003e ⚠️ **IMPORTANT**:  While the development server is running, touching the values inside the `piece()` function will cause the page to reload.\n\nThe options object accepts:\n\n1. `shadow`: See below.\n2. `containerProps`: props forwarded to the host `\u003cdiv\u003e` element.\n\n#### Shadow Mounting\n\nThe `shadow` option supports:\n\n1. `undefined` or `false`: mount in the host element (light DOM).\n2. `true`: mount in `attachShadow({ mode: \"open\" })`.\n3. `ShadowRootInit`: mount in a shadow root with custom options, including `mode: \"closed\"`.\n\n#### Host Container Styling\n\nThe host `\u003cdiv\u003e` is intentionally unstyled by this package.\n\nIf you want host-level styling, pass it through `containerProps`, for example\n`containerProps.style` or `containerProps.className`.\n\nEach host `\u003cdiv\u003e` also includes a `data-cjs-piece-host` attribute with one of the following values:\n\n1. `dom` for light DOM mounts.\n2. `open` for open shadow-root mounts.\n3. `closed` for closed shadow-root mounts.\n\nThis is useful for global CSS selectors in host apps, for example:\n\n```css\n:where([data-cjs-piece-host=\"dom\"]) {\n  display: contents;\n}\n```\n\nOr where the attribute value doesn't matter:\n\n```css\n:where([data-cjs-piece-host]) {\n  display: contents;\n}\n```\n\nWe recommend this display setting whenever possible to minimize the layout effects the DIV container may introduce.\n\n#### Host Container Events\n\n`containerProps` accepts any standard React `\u003cdiv\u003e` props, including event\nhandlers. This lets you react to host-level interactions around a mounted\npiece without changing the piece implementation.\n\nUse bubbling events (for example `onClick`, `onKeyDown`, `onInput`) so events\nfrom descendants can reach the host container:\n\n```tsx\nimport { useState, useMemo } from \"react\";\nimport { Piece, piece } from \"@collagejs/react\";\n\nexport function Host() {\n  const [lastEvent, setLastEvent] = useState(\"none\");\n  const corePiece = useMemo(() =\u003e myPieceFactory(), []);\n\n  return (\n    \u003c\u003e\n      \u003cPiece\n        {...piece(corePiece, {\n          containerProps: {\n            onClick: () =\u003e setLastEvent(\"click\"),\n            onKeyDown: () =\u003e setLastEvent(\"keydown\"),\n          },\n        })}\n      /\u003e\n      \u003cp\u003eLast host event: {lastEvent}\u003c/p\u003e\n    \u003c/\u003e\n  );\n}\n```\n\nThis pattern works well for listening to interactions that bubble from content\nmounted inside the piece.  A notable pair of useful, bubbling events:  `focusin` and `focusout`.  These can notify the host application whenever a *CollageJS* piece has received or lost keyboard focus.\n\n## Lifecycle Policy (Single-Use)\n\nThis package follows CollageJS lifecycle policy strictly:\n\n1. A `CorePiece` instance must not be remounted after unmount.\n2. A mounted `CorePiece` instance must not be mounted again concurrently.\n3. A `Piece` instance must not switch to a different `CorePiece` input after initialization.\n4. A `Piece` instance must not switch shadow mode after mount.\n\nIf any of these rules are violated, the library throws explicit runtime errors.\n\n## Parent-Aware Mounting and Context\n\n*CollageJS* supports parent-aware lifecycle management: When a parent piece unmounts, child pieces mounted through that parent-aware `mountPiece` function are unmounted first.\n\nThis package supports that model by:\n\n1. Exposing `CollageProvider` and `useCollageContext`.\n2. Injecting the parent-aware `mountPiece` into context when using `buildPiece()`.\n3. Making `Piece` consume context and prefer the parent-aware `mountPiece` when available.\n\nIn most cases, this works automatically when both sides use `@collagejs/react` APIs.\n\n## IntelliSense for CorePiece Props\n\nYou can get IntelliSense for props passed to `Piece` if your factory function's return type is known.\n\nOne approach is to declare the module in a `.d.ts` file:\n\n```ts\nimport type { CorePiece } from \"@collagejs/core\";\n\ndeclare module \"@my/bare-module-specifier\" {\n  export function myPieceFactory(): CorePiece\u003c{\n    extra: string;\n    data: boolean;\n  }\u003e;\n}\n```\n\n## Development\n\nWhen cloning this repository, install packages and Playwrite browsers:\n\n```bash\nnpm install\nnpx playwright install\n```\n\nTests are run with `vitest` in Browser Mode:\n\n```bash\nnpm run test\n```\n\n### Test Projects\n\nThere are 2 test projects under the `test-projects/` folder:  One creates a *CollageJS* piece using `buildPiece()`; the other one consumes pieces using the `Piece` component.\n\nBoth projects are standard Vite + React projects with the corresponding Vite plug-ins installed according to their roles.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcollagejs%2Freact","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcollagejs%2Freact","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcollagejs%2Freact/lists"}