Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
id: $installDevtoolsBridge
title: $installDevtoolsBridge
---

# Function: $installDevtoolsBridge()

```ts
function $installDevtoolsBridge(bridge): () => void;
```

Defined in: [devtoolsBridge.ts:23](https://github.com/TanStack/store/blob/main/packages/store/src/devtoolsBridge.ts#L23)

Installs the active Devtools bridge for store lifecycle notifications.

This is intentionally an internals-only API. Store Devtools calls it when the
Devtools panel/context is mounted, and core runtime code reads the active
bridge through `devtools()`. The returned cleanup removes this bridge only if
it is still the active bridge.

## Parameters

### bridge

[`$StoreDevtoolsBridge`](../interfaces/$StoreDevtoolsBridge.md)

## Returns

```ts
(): void;
```

### Returns

`void`
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
id: $storeDevtools
title: $storeDevtools
---

# Function: $storeDevtools()

```ts
function $storeDevtools(): $StoreDevtoolsBridge;
```

Defined in: [devtoolsBridge.ts:49](https://github.com/TanStack/store/blob/main/packages/store/src/devtoolsBridge.ts#L49)

Returns the active bridge, or an empty bridge object when Devtools is absent. This is what
should be used throughout the core to emit events when necessary.

## Returns

[`$StoreDevtoolsBridge`](../interfaces/$StoreDevtoolsBridge.md)

## Example

```ts
mount() {
$storeDevtools().mountAtom?.(this)
}
```
15 changes: 15 additions & 0 deletions docs/reference/@tanstack/namespaces/$internals/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
id: $internals
title: $internals
---

# $internals

## Interfaces

- [$StoreDevtoolsBridge](interfaces/$StoreDevtoolsBridge.md)

## Functions

- [$installDevtoolsBridge](functions/$installDevtoolsBridge.md)
- [$storeDevtools](functions/$storeDevtools.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
id: $StoreDevtoolsBridge
title: $StoreDevtoolsBridge
---

# Interface: $StoreDevtoolsBridge

Defined in: [devtoolsBridge.ts:4](https://github.com/TanStack/store/blob/main/packages/store/src/devtoolsBridge.ts#L4)

## Properties

### mountStore()?

```ts
optional mountStore: (atom) => void;
```

Defined in: [devtoolsBridge.ts:10](https://github.com/TanStack/store/blob/main/packages/store/src/devtoolsBridge.ts#L10)

Be descriptive here! It's important that the function call can be easily reasoned about when someone is confused.

As far as parameters go, keep it vague. Core should do as little calculation as possible.

#### Parameters

##### atom

[`InternalBaseAtom`](../../../../interfaces/InternalBaseAtom.md)\<`any`\> | [`InternalReadonlyAtom`](../../../../interfaces/InternalReadonlyAtom.md)\<`any`\>

#### Returns

`void`
4 changes: 4 additions & 0 deletions docs/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ title: "@tanstack/store"

# @tanstack/store

## Namespaces

- [$internals](@tanstack/namespaces/$internals/index.md)

## Classes

- [ReadonlyStore](classes/ReadonlyStore.md)
Expand Down
26 changes: 26 additions & 0 deletions packages/react-store-devtools/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @ts-check

import pluginReact from '@eslint-react/eslint-plugin'
import pluginReactCompiler from 'eslint-plugin-react-compiler'
import pluginReactHooks from 'eslint-plugin-react-hooks'
import rootConfig from '../../eslint.config.js'

/** @type {import('eslint').Linter.Config[]} */
export default [
...rootConfig,
{
files: ['**/*.{ts,tsx}'],
...pluginReact.configs.recommended,
},
{
plugins: {
'react-hooks': pluginReactHooks,
'react-compiler': pluginReactCompiler,
},
rules: {
'react-compiler/react-compiler': 'error',
'react-hooks/exhaustive-deps': 'error',
'react-hooks/rules-of-hooks': 'error',
},
},
]
74 changes: 74 additions & 0 deletions packages/react-store-devtools/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"name": "@tanstack/react-store-devtools",
"version": "0.11.0",
"description": "TanStack Store devtools for React",
"author": "Tanner Linsley",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/TanStack/store.git",
"directory": "packages/react-store"
},
"homepage": "https://tanstack.com/store",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"keywords": [
"react",
"tanstack",
"store",
"devtools"
],
"scripts": {
"clean": "premove ./dist ./coverage",
"test:eslint": "eslint ./src ./tests",
"test:types": "tsc",
"test:lib": "vitest",
"test:lib:dev": "pnpm run test:lib --watch",
"test:build": "publint --strict",
"build": "tsdown"
},
"type": "module",
"types": "./dist/index.d.cts",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./production": {
"import": {
"types": "./dist/production.d.ts",
"default": "./dist/production.js"
}
},
"./package.json": "./package.json"
},
"sideEffects": false,
"files": [
"dist",
"src"
],
"dependencies": {
"@tanstack/devtools": "^0.12.2",
"@tanstack/devtools-utils": "^0.5.0",
"@tanstack/store-devtools": "workspace:*"
},
"devDependencies": {
"@testing-library/react": "^16.3.2",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@types/use-sync-external-store": "^1.5.0",
"@vitejs/plugin-react": "^6.0.1",
"react": "^19.2.5",
"react-dom": "^19.2.5"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
}
17 changes: 17 additions & 0 deletions packages/react-store-devtools/src/StoreDevtools.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use client'

import { createReactPanel } from '@tanstack/devtools-utils/react'
import { StoreDevtoolsCore } from '@tanstack/store-devtools'

import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/react'
import type { StoreDevtoolsInit } from '@tanstack/store-devtools'

export interface StoreDevtoolsReactInit
extends DevtoolsPanelProps, StoreDevtoolsInit {}

const [StoreDevtoolsPanel, StoreDevtoolsPanelNoOp] = createReactPanel<
StoreDevtoolsReactInit,
InstanceType<typeof StoreDevtoolsCore>
>(StoreDevtoolsCore)

export { StoreDevtoolsPanel, StoreDevtoolsPanelNoOp }
16 changes: 16 additions & 0 deletions packages/react-store-devtools/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use client'

import * as Devtools from './StoreDevtools'
import * as plugin from './plugin'

export const StoreDevtoolsPanel =
process.env.NODE_ENV !== 'development'
? Devtools.StoreDevtoolsPanelNoOp
: Devtools.StoreDevtoolsPanel

export const storeDevtoolsPlugin =
process.env.NODE_ENV !== 'development'
? plugin.storeDevtoolsNoOpPlugin
: plugin.storeDevtoolsPlugin

export type { StoreDevtoolsReactInit } from './StoreDevtools'
20 changes: 20 additions & 0 deletions packages/react-store-devtools/src/plugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client'

import { createReactPlugin } from '@tanstack/devtools-utils/react'
import { StoreDevtoolsPanel } from './StoreDevtools'
import type { ReactStoreDevtoolsPlugin } from './types'
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/react'

function ReactStoreDevtoolsPanel(props: DevtoolsPanelProps) {
return <StoreDevtoolsPanel {...props} adapterName="React" />
}

const [storeDevtoolsPlugin, storeDevtoolsNoOpPlugin]: readonly [
ReactStoreDevtoolsPlugin,
ReactStoreDevtoolsPlugin,
] = createReactPlugin({
name: 'TanStack Store',
Component: ReactStoreDevtoolsPanel,
})

export { storeDevtoolsNoOpPlugin, storeDevtoolsPlugin }
5 changes: 5 additions & 0 deletions packages/react-store-devtools/src/production.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client'

export { StoreDevtoolsPanel } from './production/StoreDevtools'
export type { StoreDevtoolsReactInit } from './production/StoreDevtools'
export { storeDevtoolsPlugin } from './production/plugin'
17 changes: 17 additions & 0 deletions packages/react-store-devtools/src/production/StoreDevtools.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use client'

import { createReactPanel } from '@tanstack/devtools-utils/react'
import { StoreDevtoolsCore } from '@tanstack/store-devtools/production'

import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/react'
import type { StoreDevtoolsInit } from '@tanstack/store-devtools/production'

export interface StoreDevtoolsReactInit
extends DevtoolsPanelProps, StoreDevtoolsInit {}

const [StoreDevtoolsPanel] = createReactPanel<
StoreDevtoolsReactInit,
InstanceType<typeof StoreDevtoolsCore>
>(StoreDevtoolsCore)

export { StoreDevtoolsPanel }
20 changes: 20 additions & 0 deletions packages/react-store-devtools/src/production/plugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client'

import { createReactPlugin } from '@tanstack/devtools-utils/react'
import { StoreDevtoolsPanel } from './StoreDevtools'
import type { ReactStoreDevtoolsPlugin } from '../types'
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/react'

function ReactStoreDevtoolsPanel(props: DevtoolsPanelProps) {
return <StoreDevtoolsPanel {...props} adapterName="React" />
}

const [storeDevtoolsPlugin]: readonly [
ReactStoreDevtoolsPlugin,
ReactStoreDevtoolsPlugin,
] = createReactPlugin({
name: 'TanStack Store',
Component: ReactStoreDevtoolsPanel,
})

export { storeDevtoolsPlugin }
10 changes: 10 additions & 0 deletions packages/react-store-devtools/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { TanStackDevtoolsPluginProps } from '@tanstack/devtools'
import type { JSX } from 'react'
// TODO
// Type errors show up regarding portability. We should fix this, it's ugly.
export type ReactStoreDevtoolsPlugin = () => {
name: string
id?: string
defaultOpen?: boolean
render: (el: HTMLElement, props: TanStackDevtoolsPluginProps) => JSX.Element
}
9 changes: 9 additions & 0 deletions packages/react-store-devtools/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"jsx": "react-jsx",
"types": ["node"]
},
"include": ["src", "vitest.config.ts", "tests"],
"exclude": ["eslint.config.js"]
}
20 changes: 20 additions & 0 deletions packages/react-store-devtools/tsdown.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { defineConfig } from 'tsdown'

export default defineConfig([
{
entry: { index: 'src/index.ts' },
format: ['esm'],
outDir: 'dist',
fixedExtension: false,
dts: true,
clean: true,
},
{
entry: { production: 'src/production.ts' },
format: ['esm'],
outDir: 'dist',
fixedExtension: false,
dts: true,
clean: false,
},
])
11 changes: 11 additions & 0 deletions packages/store-devtools/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @ts-check

import rootConfig from '../../eslint.config.js'

/** @type {import('eslint').Linter.Config[]} */
export default [
...rootConfig,
{
rules: {},
},
]
Loading
Loading