Skip to content

Commit

Permalink
Merge branch 'main' into shew-bae6f
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonyshew authored Jan 10, 2025
2 parents 03b8e1f + a21c30f commit e26fbb8
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 22 deletions.
19 changes: 6 additions & 13 deletions .github/workflows/test-js-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ jobs:
- js_packages
steps:
- name: Compute info
id: info
if: always()
run: |
cancelled=false
failure=false
Expand All @@ -106,17 +104,12 @@ jobs:
subjob ${{needs.js_packages.result}}
if [ "$cancelled" = "true" ]; then
echo "cancelled=true" >> $GITHUB_OUTPUT
echo "Job was cancelled."
exit 0
elif [ "$failure" = "true" ]; then
echo "failure=true" >> $GITHUB_OUTPUT
echo "Job failed."
exit 1
else
echo "success=true" >> $GITHUB_OUTPUT
echo "Job succeeded."
exit 0
fi
- name: Failed
if: steps.info.outputs.failure == 'true'
run: exit 1

- name: Succeeded
if: steps.info.outputs.success == 'true'
run: echo Ok
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Files, File, Folder } from '#/components/files';

![Visual representation of a Package Graph in a Turborepo.](/images/docs/package-graph.png)

Let's create your first Internal Package to share math utilities in your repo using the guidance in the [Anatomy of a package](/repo/docs/crafting-your-repository/structuring-a-repository#anatomy-of-a-package) section. In the steps below, we assume you've [created a new repository using `create-turbo`](/repo/docs/getting-started/installation) or are using a similarly structured repository.
Let's create your first Internal Package to share math utilities in your repo using the guidance in the [Anatomy of a package](/repo/docs/crafting-your-repository/structuring-a-repository#anatomy-of-a-package) section and the [Compiled Packages](/repo/docs/core-concepts/internal-packages#compiled-packages) pattern. In the steps below, we assume you've [created a new repository using `create-turbo`](/repo/docs/getting-started/installation) or are using a similarly structured repository.

<Steps>
<Step>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,15 @@ For example, if you had a `@repo/math` package, you might have the following `ex
```json title="./packages/math/package.json"
{
"exports": {
".": "./dist/constants.ts",
"./add": "./dist/add.ts",
"./subtract": "./dist/subtract.ts"
".": "./src/constants.ts",
"./add": "./src/add.ts",
"./subtract": "./src/subtract.ts"
}
}
```

Note that this example uses the [Just-in-Time Package](/repo/docs/core-concepts/internal-packages#just-in-time-packages) pattern for simplicity. It exports TypeScript directly, but you might choose to use the [Compiled Package](/repo/docs/core-concepts/internal-packages#compiled-packages) pattern instead.

<Callout type="info">
The `exports` field in this example requires modern versions of Node.js and
TypeScript.
Expand All @@ -307,9 +309,9 @@ Using exports this way provides three major benefits:
- **IDE autocompletion**: By specifying the entrypoints for your package using `exports`, you can ensure that your code editor can provide auto-completion for the package's exports.

<Callout type="good-to-know">
You may also specify `exports` using a wildcard. However, you will lose IDE
autocompletion due to performance tradeoffs with the TypeScript compiler. For
more information, visit [the TypeScript
You may also specify `exports` using a wildcard. However, you will lose some
IDE autocompletion due to performance tradeoffs with the TypeScript compiler.
For more information, visit [the TypeScript
guide](/repo/docs/guides/tools/typescript#package-entrypoint-wildcards).
</Callout>

Expand Down
84 changes: 84 additions & 0 deletions docs/repo-docs/guides/frameworks/framework-bindings.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
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.

<Callout type="good-to-know">
On this page, we'll be using Next.js for examples, but the concepts below
apply to any framework or other dependency.
</Callout>

## 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": "*"
}
}
```

<Callout type="good-to-know">
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.
</Callout>

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<typeof Link>;

export function CustomLink({ children, ...props }: CustomLinkProps) {
return (
<Link className="text-underline hover:text-green-400" {...props}>
{children}
</Link>
);
}
```

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 `<a>` 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"
{
"exports": {
"./link": "./dist/link.js",
"./next-js/link": "./dist/next-js/link.js"
},
"peerDependencies": {
"next": "*"
}
}
```

<Callout type="good-to-know">
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.
</Callout>

This concept can be applied to any number of frameworks or other dependencies that you'd like to provide bindings for.
2 changes: 1 addition & 1 deletion docs/repo-docs/guides/frameworks/meta.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"pages": ["nextjs", "sveltekit", "vite", "nuxt"]
"pages": ["nextjs", "sveltekit", "vite", "nuxt", "framework-bindings"]
}
70 changes: 70 additions & 0 deletions docs/repo-docs/guides/tools/shadcn-ui.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: shadcn/ui
description: Learn how to use shadcn/ui in a Turborepo.
---

import { PackageManagerTabs, Tab } from '#/components/tabs';

[shadcn/ui](https://ui.shadcn.com/docs/monorepo) is an open-source set of beautifully designed components made with Tailwind CSS that you can copy and paste into your apps.

To get started with shadcn/ui in a new monorepo, run:

<PackageManagerTabs>
<Tab>

```bash title="Terminal"
npx shadcn@canary init
```

</Tab>

<Tab>

```bash title="Terminal"
npx shadcn@canary init
```

</Tab>

<Tab>

```bash title="Terminal"
pnpm dlx shadcn@canary init
```

</Tab>
</PackageManagerTabs>

When prompted, select the option for monorepos.

To add a component, run:

<PackageManagerTabs>
<Tab>

```bash title="Terminal"
npx shadcn@canary add [COMPONENT]
```

</Tab>

<Tab>

```bash title="Terminal"
npx shadcn@canary add [COMPONENT]
```

</Tab>

<Tab>

```bash title="Terminal"
pnpm dlx shadcn@canary add [COMPONENT]
```

</Tab>
</PackageManagerTabs>

## More information

To learn more about using shadcn/ui in Turborepo, [visit the docs for shadcn/ui](https://ui.shadcn.com/docs/monorepo).
2 changes: 1 addition & 1 deletion docs/repo-docs/guides/tools/typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ The other `tsconfig` files in this package use the `extends` key to start with t

Inside `package.json`, name the package so it can be referenced in the rest of the Workspace:

```json title="packages/tsconfig/package.json"
```json title="packages/typescript-config/package.json"
{
"name": "@repo/typescript-config"
}
Expand Down

0 comments on commit e26fbb8

Please sign in to comment.