From 28dddcba0655d28dda8e774d47c9f68fd711b8f1 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Fri, 4 Oct 2024 10:00:30 -0600 Subject: [PATCH 1/8] (docs): Document creating packages with Next.js bindings. --- docs/repo-docs/guides/frameworks/nextjs.mdx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/repo-docs/guides/frameworks/nextjs.mdx b/docs/repo-docs/guides/frameworks/nextjs.mdx index 1174785f01e92..1d081fb67f0cb 100644 --- a/docs/repo-docs/guides/frameworks/nextjs.mdx +++ b/docs/repo-docs/guides/frameworks/nextjs.mdx @@ -118,3 +118,21 @@ Make sure to run your package manager's install command. You also may need to up ### Customizing tasks By default, the new application will use the tasks defined in the root `turbo.json`. If you'd like to configure tasks differently for the new application, use [Package Configurations](/repo/docs/reference/package-configurations). + +## Creating packages with Next.js bindings + +At times, you may want to create a package that has bindings specific to Next.js. For example, you may want the package to be using the Next.js `` component. In these cases, install `next` directly into the package and use it there. + +These bindings may make your package incompatible with other frameworks or packages that are not using Next.js. To ensure compatibility, create a specific entrypoint to your package for your Next.js adapter code. + +```json title="./packages/ui/package.json" +{ + "exports": { + "./link": "./dist/link.js" + "./image": "./dist/image.js" + "./next-js/link": "./dist/link.js" + "./next-js/image": "./dist/image.js" + } + } +} +``` From c5f85fe9418e267b47820dea86bd7f5a5d00274a Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Fri, 4 Oct 2024 10:03:29 -0600 Subject: [PATCH 2/8] WIP --- docs/repo-docs/guides/frameworks/nextjs.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/repo-docs/guides/frameworks/nextjs.mdx b/docs/repo-docs/guides/frameworks/nextjs.mdx index 1d081fb67f0cb..5628c9e4e3827 100644 --- a/docs/repo-docs/guides/frameworks/nextjs.mdx +++ b/docs/repo-docs/guides/frameworks/nextjs.mdx @@ -132,7 +132,9 @@ These bindings may make your package incompatible with other frameworks or packa "./image": "./dist/image.js" "./next-js/link": "./dist/link.js" "./next-js/image": "./dist/image.js" - } + }, + "peerDependencies": { + "next": "*" // You may want to specify a version range, according to your package's needs and constraints } } ``` From 083c860d71f3157eeab5107cbc8abcc27c154292 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Wed, 1 Jan 2025 21:43:27 -0700 Subject: [PATCH 3/8] WIP --- .../guides/frameworks/framework-bindings.mdx | 81 +++++++++++++++++++ docs/repo-docs/guides/frameworks/meta.json | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 docs/repo-docs/guides/frameworks/framework-bindings.mdx diff --git a/docs/repo-docs/guides/frameworks/framework-bindings.mdx b/docs/repo-docs/guides/frameworks/framework-bindings.mdx new file mode 100644 index 0000000000000..25c289a28c669 --- /dev/null +++ b/docs/repo-docs/guides/frameworks/framework-bindings.mdx @@ -0,0 +1,81 @@ +--- +title: Framework bindings in libraries +description: Learn how to create framework bindings in packages. +--- + +import { PackageManagerTabs, Tab } from '#/components/tabs'; +import { Callout } from '#/components/callout'; + +Framework bindings in a [Library Package](/repo/docs/core-concepts/package-types#library-packages) integrate your library's code more deeply with a framework by leveraging APIs from the framework directly in the library. + +To do this, use the `peerDependencies` field in `package.json` of the library, which makes the framework APIs available in your library without installing it directly in the package. + + + On this page, we'll be using Next.js for examples, but the concepts below + apply to any framework or other dependency. + + +## Example + +Add a `peerDependency` to your library for the dependency that you intend to create bindings for. + +```json title="./packages/ui/package.json" +{ + "name": "@repo/ui", + "peerDependencies": { + "next": "*" + } +} +``` + + + In the example above, the `peerDependency` for `next` accepts any version. You + may want to specify a range (for example, `">=15"`) according to your needs. + + +This will make the dependency available in your library, allowing you to write code like below. Note the `className` prop, which sets a default styling for this component in the monorepo and can be overridden in the `props` object. + +```tsx title="./packages/ui/src/link.tsx" +import Link from 'next/link'; +import type { ComponentProps } from 'react'; + +type CustomLinkProps = ComponentProps; + +export function CustomLink({ children, ...props }: CustomLinkProps) { + return ( + + {children} + + ); +} +``` + +The version of `next` that will be resolved for the package will come from the consumers of the library. For example, if Next.js 15 is installed in your applications, the TypeScript types and APIs for `next` will also be Next.js 15. + +## Splitting framework bindings using entrypoints + +Using export paths to split a package into framework-specific entrypoints is the simplest way to add bindings to a library that aims to support multiple frameworks. By splitting entrypoints, bundlers have an easier time understanding the framework you intend to target and you're less likely to see strange bundling errors. + +The example below shows a library with two entrypoints, each for a different type of link component. These abstractions likely contain your own styles, APIs, and other adjustments on top of the element they're wrapping. + +- `./link`: An `` HTML tag with some default styles from your design system +- `./next-js/link`: A customized version of [the Next.js `Link` component](https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#link-component) with props that are preset to your organization's preferences + +```json title="./packages/ui/package.json" +{ + "exports": { + "./link": "./dist/link.js", + "./next-js/link": "./dist/next-js/link.js" + }, + "peerDependencies": { + "next": "*" + } +} +``` + + + In the example above, the `peerDependency` for `next` accepts any version. You + may want to specify a range (for example, `">=15"`) according to your needs. + + +This concept can be applied to any number of frameworks or other dependencies that you'd like to provide bindings for. diff --git a/docs/repo-docs/guides/frameworks/meta.json b/docs/repo-docs/guides/frameworks/meta.json index 691dcca5f6d73..a848cb3558b96 100644 --- a/docs/repo-docs/guides/frameworks/meta.json +++ b/docs/repo-docs/guides/frameworks/meta.json @@ -1,3 +1,3 @@ { - "pages": ["nextjs", "sveltekit", "vite", "nuxt"] + "pages": ["framework-bindings", "nextjs", "sveltekit", "vite", "nuxt"] } From 92a3b0af5f2d206c3d5fd8be010ae20f8f8f6c2c Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Wed, 1 Jan 2025 21:44:00 -0700 Subject: [PATCH 4/8] WIP --- docs/repo-docs/guides/frameworks/nextjs.mdx | 24 --------------------- 1 file changed, 24 deletions(-) diff --git a/docs/repo-docs/guides/frameworks/nextjs.mdx b/docs/repo-docs/guides/frameworks/nextjs.mdx index 5628c9e4e3827..68c4eedd81f5d 100644 --- a/docs/repo-docs/guides/frameworks/nextjs.mdx +++ b/docs/repo-docs/guides/frameworks/nextjs.mdx @@ -114,27 +114,3 @@ To add [Internal Packages](/repo/docs/core-concepts/internal-packages) to your n Make sure to run your package manager's install command. You also may need to update `scripts` in `package.json` to fit your use case in your repository. - -### Customizing tasks - -By default, the new application will use the tasks defined in the root `turbo.json`. If you'd like to configure tasks differently for the new application, use [Package Configurations](/repo/docs/reference/package-configurations). - -## Creating packages with Next.js bindings - -At times, you may want to create a package that has bindings specific to Next.js. For example, you may want the package to be using the Next.js `` component. In these cases, install `next` directly into the package and use it there. - -These bindings may make your package incompatible with other frameworks or packages that are not using Next.js. To ensure compatibility, create a specific entrypoint to your package for your Next.js adapter code. - -```json title="./packages/ui/package.json" -{ - "exports": { - "./link": "./dist/link.js" - "./image": "./dist/image.js" - "./next-js/link": "./dist/link.js" - "./next-js/image": "./dist/image.js" - }, - "peerDependencies": { - "next": "*" // You may want to specify a version range, according to your package's needs and constraints - } -} -``` From e9a86b4ef70ccad42fbb0eaeb5818629b67132e3 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Wed, 1 Jan 2025 21:44:23 -0700 Subject: [PATCH 5/8] WIP --- docs/repo-docs/guides/frameworks/nextjs.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/repo-docs/guides/frameworks/nextjs.mdx b/docs/repo-docs/guides/frameworks/nextjs.mdx index 68c4eedd81f5d..1174785f01e92 100644 --- a/docs/repo-docs/guides/frameworks/nextjs.mdx +++ b/docs/repo-docs/guides/frameworks/nextjs.mdx @@ -114,3 +114,7 @@ To add [Internal Packages](/repo/docs/core-concepts/internal-packages) to your n Make sure to run your package manager's install command. You also may need to update `scripts` in `package.json` to fit your use case in your repository. + +### Customizing tasks + +By default, the new application will use the tasks defined in the root `turbo.json`. If you'd like to configure tasks differently for the new application, use [Package Configurations](/repo/docs/reference/package-configurations). From 8c1eef9c5362228567982366f883b5952fecdae1 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Wed, 1 Jan 2025 21:44:49 -0700 Subject: [PATCH 6/8] WIP --- docs/repo-docs/guides/frameworks/meta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/repo-docs/guides/frameworks/meta.json b/docs/repo-docs/guides/frameworks/meta.json index a848cb3558b96..1cd9f18eb93c2 100644 --- a/docs/repo-docs/guides/frameworks/meta.json +++ b/docs/repo-docs/guides/frameworks/meta.json @@ -1,3 +1,3 @@ { - "pages": ["framework-bindings", "nextjs", "sveltekit", "vite", "nuxt"] + "pages": ["nextjs", "sveltekit", "vite", "nuxt", "framework-bindings"] } From 1abcdcc270f11a87e60d40c224e894e0ceadeaeb Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Mon, 6 Jan 2025 14:50:40 -0700 Subject: [PATCH 7/8] Update docs/repo-docs/guides/frameworks/framework-bindings.mdx --- docs/repo-docs/guides/frameworks/framework-bindings.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/repo-docs/guides/frameworks/framework-bindings.mdx b/docs/repo-docs/guides/frameworks/framework-bindings.mdx index 25c289a28c669..bd64ef884e4cd 100644 --- a/docs/repo-docs/guides/frameworks/framework-bindings.mdx +++ b/docs/repo-docs/guides/frameworks/framework-bindings.mdx @@ -31,6 +31,8 @@ Add a `peerDependency` to your library for the dependency that you intend to cre In the example above, the `peerDependency` for `next` accepts any version. You may want to specify a range (for example, `">=15"`) according to your needs. + + Additionally, for older package managers, you may need to instruct your package manager to install peer dependencies with configuration, or add the dependency to `devDependencies` as a workaround. This will make the dependency available in your library, allowing you to write code like below. Note the `className` prop, which sets a default styling for this component in the monorepo and can be overridden in the `props` object. From 0c58aeb4a0708da346c1def0c11517460d71a516 Mon Sep 17 00:00:00 2001 From: Anthony Shew Date: Mon, 6 Jan 2025 14:52:22 -0700 Subject: [PATCH 8/8] Update docs/repo-docs/guides/frameworks/framework-bindings.mdx --- docs/repo-docs/guides/frameworks/framework-bindings.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/repo-docs/guides/frameworks/framework-bindings.mdx b/docs/repo-docs/guides/frameworks/framework-bindings.mdx index bd64ef884e4cd..1aa5fb0add3dc 100644 --- a/docs/repo-docs/guides/frameworks/framework-bindings.mdx +++ b/docs/repo-docs/guides/frameworks/framework-bindings.mdx @@ -62,6 +62,7 @@ The example below shows a library with two entrypoints, each for a different typ - `./link`: An `` HTML tag with some default styles from your design system - `./next-js/link`: A customized version of [the Next.js `Link` component](https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#link-component) with props that are preset to your organization's preferences +- `./svelte/link`: A customized version of an [`a` tag for Svelte](https://svelte.dev/docs/kit/link-options) with presets. ```json title="./packages/ui/package.json" {