diff --git a/.gitignore b/.gitignore
index 40ce8a4..5b40b6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -85,6 +85,10 @@ dist
# TypeDoc generated docs (auto-generated during build)
site/typedoc
+# Storybook build output
+storybook-static
+site/public/storybook
+
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
diff --git a/package.json b/package.json
index c1e3dc1..6a5142f 100644
--- a/package.json
+++ b/package.json
@@ -7,9 +7,11 @@
"check": "biome check --write",
"check:types": "pnpm build && pnpm run --r --parallel check:types && tsc --noEmit",
"clean": "pnpm run --r --parallel clean",
+ "storybook": "pnpm --filter @mbga/kit storybook",
+ "storybook:build": "pnpm --filter @mbga/kit storybook:build",
"docs:typedoc": "typedoc",
- "docs:dev": "pnpm --filter site dev",
- "docs:build": "pnpm --filter site build",
+ "docs:dev": "pnpm storybook:build && rm -rf site/public/storybook && cp -r packages/kit/storybook-static site/public/storybook && pnpm --filter site dev",
+ "docs:build": "pnpm storybook:build && rm -rf site/public/storybook && cp -r packages/kit/storybook-static site/public/storybook && pnpm --filter site build",
"docs:preview": "pnpm --filter site preview",
"format": "biome format --write",
"test": "vitest",
diff --git a/packages/kit/.storybook/main.ts b/packages/kit/.storybook/main.ts
new file mode 100644
index 0000000..7fe53ea
--- /dev/null
+++ b/packages/kit/.storybook/main.ts
@@ -0,0 +1,8 @@
+import type { StorybookConfig } from 'storybook'
+
+const config: StorybookConfig = {
+ stories: ['../src/**/*.stories.tsx'],
+ framework: '@storybook/react-vite',
+}
+
+export default config
diff --git a/packages/kit/.storybook/preview.tsx b/packages/kit/.storybook/preview.tsx
new file mode 100644
index 0000000..42500f9
--- /dev/null
+++ b/packages/kit/.storybook/preview.tsx
@@ -0,0 +1,28 @@
+import type { Preview } from 'storybook'
+import { withProviders } from '../src/__stories__/decorators'
+
+const preview: Preview = {
+ decorators: [withProviders],
+ parameters: {
+ layout: 'centered',
+ },
+ globalTypes: {
+ theme: {
+ description: 'Kit theme',
+ toolbar: {
+ title: 'Theme',
+ icon: 'paintbrush',
+ items: [
+ { value: 'light', title: 'Light', icon: 'sun' },
+ { value: 'dark', title: 'Dark', icon: 'moon' },
+ ],
+ dynamicTitle: true,
+ },
+ },
+ },
+ initialGlobals: {
+ theme: 'light',
+ },
+}
+
+export default preview
diff --git a/packages/kit/package.json b/packages/kit/package.json
index 5baa0cd..a936038 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -10,6 +10,8 @@
},
"scripts": {
"build": "tsup",
+ "storybook": "storybook dev -p 6006",
+ "storybook:build": "storybook build -o storybook-static",
"check:types": "tsc --noEmit",
"check:publint": "publint",
"check:attw": "attw --pack .",
@@ -21,7 +23,10 @@
"src/**/*.tsx",
"!src/**/*.test.ts",
"!src/**/*.test.tsx",
- "!src/**/*.test-d.ts"
+ "!src/**/*.test-d.ts",
+ "!src/**/*.stories.ts",
+ "!src/**/*.stories.tsx",
+ "!src/__stories__"
],
"sideEffects": false,
"type": "module",
@@ -75,13 +80,15 @@
},
"devDependencies": {
"@mbga/test": "workspace:*",
+ "@storybook/react-vite": "^10.3.4",
"@tanstack/react-query": "^5.49.2",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.2",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
"react": "^19.2.0",
- "react-dom": "^19.2.0"
+ "react-dom": "^19.2.0",
+ "storybook": "^10.3.4"
},
"keywords": [
"mbga",
diff --git a/packages/kit/src/__stories__/decorators.tsx b/packages/kit/src/__stories__/decorators.tsx
new file mode 100644
index 0000000..7536cec
--- /dev/null
+++ b/packages/kit/src/__stories__/decorators.tsx
@@ -0,0 +1,31 @@
+import { createConfig, sparkMainnet } from '@mbga/core'
+import { mock } from '@mbga/test'
+import { MbgaProvider } from 'mbga'
+import type { Decorator } from 'storybook'
+import { KitProvider } from '../components/KitProvider'
+
+function createMockConfig() {
+ return createConfig({
+ network: sparkMainnet,
+ connectors: [
+ mock({
+ accounts: ['sp1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'],
+ balance: 2_100_000n,
+ }),
+ ],
+ storage: null,
+ })
+}
+
+export const withProviders: Decorator = (Story, context) => {
+ const theme = (context.globals.theme as 'light' | 'dark') ?? 'light'
+ const config = createMockConfig()
+
+ return (
+
+
+
+
+
+ )
+}
diff --git a/packages/kit/src/components/AccountModal.stories.tsx b/packages/kit/src/components/AccountModal.stories.tsx
new file mode 100644
index 0000000..f9b2b13
--- /dev/null
+++ b/packages/kit/src/components/AccountModal.stories.tsx
@@ -0,0 +1,37 @@
+import { connect } from '@mbga/core'
+import { useConfig } from 'mbga'
+import { useEffect, useState } from 'react'
+import type { Meta, StoryObj } from 'storybook'
+import { useKitContext } from '../context'
+import { AccountModal } from './AccountModal'
+
+function AccountModalOpener() {
+ const config = useConfig()
+ const { openModal } = useKitContext()
+ const [ready, setReady] = useState(false)
+
+ useEffect(() => {
+ connect(config, { connector: config.connectors[0]! }).then(() => {
+ setReady(true)
+ openModal('account')
+ })
+ }, [config, openModal])
+
+ if (!ready) return
Connecting...
+ return
+}
+
+const meta = {
+ title: 'Components/AccountModal',
+ component: AccountModal,
+ parameters: {
+ layout: 'fullscreen',
+ },
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ render: () => ,
+}
diff --git a/packages/kit/src/components/ConnectButton.stories.tsx b/packages/kit/src/components/ConnectButton.stories.tsx
new file mode 100644
index 0000000..d46748c
--- /dev/null
+++ b/packages/kit/src/components/ConnectButton.stories.tsx
@@ -0,0 +1,66 @@
+import { connect } from '@mbga/core'
+import { useConfig } from 'mbga'
+import { useEffect, useState } from 'react'
+import type { Meta, StoryObj } from 'storybook'
+import { ConnectButton } from './ConnectButton'
+
+const meta = {
+ title: 'Components/ConnectButton',
+ component: ConnectButton,
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Disconnected: Story = {}
+
+export const CustomLabel: Story = {
+ args: {
+ label: 'Link Wallet',
+ },
+}
+
+function ConnectedWrapper() {
+ const config = useConfig()
+ const [ready, setReady] = useState(false)
+
+ useEffect(() => {
+ connect(config, { connector: config.connectors[0]! }).then(() =>
+ setReady(true),
+ )
+ }, [config])
+
+ if (!ready) return Connecting...
+ return
+}
+
+export const Connected: Story = {
+ render: () => ,
+}
+
+function CustomRenderPropWrapper() {
+ return (
+
+ {({ isConnected, show, truncatedAddress }) => (
+
+ )}
+
+ )
+}
+
+export const CustomRenderProp: Story = {
+ render: () => ,
+}
diff --git a/packages/kit/src/components/ConnectModal.stories.tsx b/packages/kit/src/components/ConnectModal.stories.tsx
new file mode 100644
index 0000000..006b331
--- /dev/null
+++ b/packages/kit/src/components/ConnectModal.stories.tsx
@@ -0,0 +1,27 @@
+import { useEffect } from 'react'
+import type { Meta, StoryObj } from 'storybook'
+import { useKitContext } from '../context'
+import { ConnectModal } from './ConnectModal'
+
+function ConnectModalOpener() {
+ const { openModal } = useKitContext()
+ useEffect(() => {
+ openModal('connect')
+ }, [openModal])
+ return
+}
+
+const meta = {
+ title: 'Components/ConnectModal',
+ component: ConnectModal,
+ parameters: {
+ layout: 'fullscreen',
+ },
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ render: () => ,
+}
diff --git a/packages/kit/tsconfig.json b/packages/kit/tsconfig.json
index 99944f6..61705de 100644
--- a/packages/kit/tsconfig.json
+++ b/packages/kit/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"include": ["src/**/*.ts", "src/**/*.tsx"],
+ "exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/__stories__"],
"compilerOptions": {
"composite": true,
"rootDir": "src",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5824cf2..97df908 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -239,6 +239,9 @@ importers:
'@mbga/test':
specifier: workspace:*
version: link:../test
+ '@storybook/react-vite':
+ specifier: ^10.3.4
+ version: 10.3.4(esbuild@0.27.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3))
'@tanstack/react-query':
specifier: ^5.49.2
version: 5.95.2(react@19.2.4)
@@ -260,6 +263,9 @@ importers:
react-dom:
specifier: ^19.2.0
version: 19.2.4(react@19.2.4)
+ storybook:
+ specifier: ^10.3.4
+ version: 10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
packages/react:
dependencies:
@@ -336,6 +342,9 @@ importers:
packages:
+ '@adobe/css-tools@4.4.4':
+ resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==}
+
'@alloc/quick-lru@5.2.0':
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
@@ -1186,6 +1195,15 @@ packages:
resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
engines: {node: '>=8'}
+ '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0':
+ resolution: {integrity: sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==}
+ peerDependencies:
+ typescript: '>= 4.3.x'
+ vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
@@ -1698,6 +1716,65 @@ packages:
'@stitches/core@1.2.8':
resolution: {integrity: sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg==}
+ '@storybook/builder-vite@10.3.4':
+ resolution: {integrity: sha512-dNQyBZpBKvwmhSTpjrsuxxY8FqFCh0hgu5+46h2WbgQ2Te3pO458heWkGb+QO7mC6FmkXO6j6zgYzXticD6F2A==}
+ peerDependencies:
+ storybook: ^10.3.4
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ '@storybook/csf-plugin@10.3.4':
+ resolution: {integrity: sha512-WPP0Z39o82WiohPkhPOs6z+9yJ+bVvqPz4d+QUPfE6FMvOOBLojlwOcGx6Xmclyn5H/CKwywFrjuz4mBO/nHhA==}
+ peerDependencies:
+ esbuild: '*'
+ rollup: '*'
+ storybook: ^10.3.4
+ vite: '*'
+ webpack: '*'
+ peerDependenciesMeta:
+ esbuild:
+ optional: true
+ rollup:
+ optional: true
+ vite:
+ optional: true
+ webpack:
+ optional: true
+
+ '@storybook/global@5.0.0':
+ resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==}
+
+ '@storybook/icons@2.0.1':
+ resolution: {integrity: sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg==}
+ 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
+
+ '@storybook/react-dom-shim@10.3.4':
+ resolution: {integrity: sha512-VIm9YzreGubnOtQOZ6iqEfj6KncHvAkrCR/IilqnJq7DidPWuykrFszyajTASRMiY+p+TElOW+O1PGpv55qNGw==}
+ 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
+ storybook: ^10.3.4
+
+ '@storybook/react-vite@10.3.4':
+ resolution: {integrity: sha512-xaMt7NdvlAb+CwXn5TOiluQ+0WkkMN3mZhCThocpblWGoyfmHH7bgQ5ZwzT+IIp8DGOsAi/HkNmSyS7Z8HRLJg==}
+ 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
+ storybook: ^10.3.4
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ '@storybook/react@10.3.4':
+ resolution: {integrity: sha512-I5ifYqjrqyuhOFjalpy47kMKMXX7QU/qmHj0h/547s9Bg6sEU7xRhJnneXx1RJsEJTySjC4SmGfEU+FJz4Foiw==}
+ 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
+ storybook: ^10.3.4
+ typescript: '>= 4.9.x'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@svgr/babel-plugin-add-jsx-attribute@8.0.0':
resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==}
engines: {node: '>=14'}
@@ -2032,6 +2109,10 @@ packages:
resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
engines: {node: '>=18'}
+ '@testing-library/jest-dom@6.9.1':
+ resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==}
+ engines: {node: '>=14', npm: '>=6', yarn: '>=1'}
+
'@testing-library/react@16.3.2':
resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==}
engines: {node: '>=18'}
@@ -2047,6 +2128,12 @@ packages:
'@types/react-dom':
optional: true
+ '@testing-library/user-event@14.6.1':
+ resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==}
+ engines: {node: '>=12', npm: '>=6'}
+ peerDependencies:
+ '@testing-library/dom': '>=7.21.4'
+
'@types/aria-query@5.0.4':
resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
@@ -2071,6 +2158,9 @@ packages:
'@types/deep-eql@4.0.2':
resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+ '@types/doctrine@0.0.9':
+ resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==}
+
'@types/estree-jsx@1.0.5':
resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
@@ -2106,6 +2196,9 @@ packages:
'@types/react@19.2.14':
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
+ '@types/resolve@1.20.6':
+ resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==}
+
'@types/unist@2.0.11':
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
@@ -2221,6 +2314,9 @@ packages:
resolution: {integrity: sha512-Gt8TnSlDZpAl+RWOOAB/kuvC7RpcdWAlFbHNoi4gsXsfaWa1QCT6LBcfIYTPdOZC9OVZUDwqGuGAcqZejDmHjg==}
engines: {node: '>=16'}
+ '@webcontainer/env@1.1.1':
+ resolution: {integrity: sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==}
+
abort-controller-x@0.4.3:
resolution: {integrity: sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==}
@@ -2313,6 +2409,10 @@ packages:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'}
+ ast-types@0.16.1:
+ resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
+ engines: {node: '>=4'}
+
ast-v8-to-istanbul@0.3.12:
resolution: {integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==}
@@ -2521,6 +2621,10 @@ packages:
buffer@6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
+ bundle-name@4.1.0:
+ resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
+ engines: {node: '>=18'}
+
bundle-require@5.1.0:
resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -2718,6 +2822,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
+ css.escape@1.5.1:
+ resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
+
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
@@ -2744,6 +2851,18 @@ packages:
resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
engines: {node: '>=6'}
+ default-browser-id@5.0.1:
+ resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==}
+ engines: {node: '>=18'}
+
+ default-browser@5.5.0:
+ resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==}
+ engines: {node: '>=18'}
+
+ define-lazy-prop@3.0.0:
+ resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
+ engines: {node: '>=12'}
+
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@@ -2779,9 +2898,16 @@ packages:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
+ doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+
dom-accessibility-api@0.5.16:
resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
+ dom-accessibility-api@0.6.3:
+ resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==}
+
dot-case@3.0.4:
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
@@ -2818,6 +2944,10 @@ packages:
emojilib@2.4.0:
resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==}
+ empathic@2.0.0:
+ resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==}
+ engines: {node: '>=14'}
+
encodeurl@2.0.0:
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
engines: {node: '>= 0.8'}
@@ -2944,6 +3074,10 @@ packages:
estree-walker@3.0.3:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+ esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+
etag@1.8.1:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
@@ -3118,6 +3252,10 @@ packages:
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
hasBin: true
+ glob@13.0.6:
+ resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
+ engines: {node: 18 || 20 || >=22}
+
globby@11.1.0:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
@@ -3224,6 +3362,10 @@ packages:
import-in-the-middle@1.15.0:
resolution: {integrity: sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==}
+ indent-string@4.0.0:
+ resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+ engines: {node: '>=8'}
+
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
@@ -3262,6 +3404,11 @@ packages:
is-decimal@2.0.1:
resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+ is-docker@3.0.0:
+ resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
@@ -3277,6 +3424,11 @@ packages:
is-hexadecimal@2.0.1:
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+ is-inside-container@1.0.0:
+ resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
+ engines: {node: '>=14.16'}
+ hasBin: true
+
is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
@@ -3302,6 +3454,10 @@ packages:
resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
engines: {node: '>=0.10.0'}
+ is-wsl@3.1.1:
+ resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==}
+ engines: {node: '>=16'}
+
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
@@ -3836,6 +3992,10 @@ packages:
resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
engines: {node: '>=18'}
+ min-indent@1.0.1:
+ resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+ engines: {node: '>=4'}
+
minimatch@10.2.4:
resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==}
engines: {node: 18 || 20 || >=22}
@@ -3844,6 +4004,9 @@ packages:
resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==}
engines: {node: '>=16 || 14 >=14.17'}
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
minipass@7.1.3:
resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -3976,6 +4139,10 @@ packages:
oniguruma-to-es@4.3.5:
resolution: {integrity: sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==}
+ open@10.2.0:
+ resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==}
+ engines: {node: '>=18'}
+
outdent@0.5.0:
resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
@@ -4050,6 +4217,10 @@ packages:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
+ path-scurry@2.0.2:
+ resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
+ engines: {node: 18 || 20 || >=22}
+
path-to-regexp@8.4.0:
resolution: {integrity: sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg==}
@@ -4179,6 +4350,15 @@ packages:
react-devtools-inline@4.4.0:
resolution: {integrity: sha512-ES0GolSrKO8wsKbsEkVeiR/ZAaHQTY4zDh1UW8DImVmm8oaGLl3ijJDvSGe+qDRKPZdPRnDtWWnSvvrgxXdThQ==}
+ react-docgen-typescript@2.4.0:
+ resolution: {integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==}
+ peerDependencies:
+ typescript: '>= 4.3.x'
+
+ react-docgen@8.0.3:
+ resolution: {integrity: sha512-aEZ9qP+/M+58x2qgfSFEWH1BxLyHe5+qkLNJOZQb5iGS017jpbRnoKhNRrXPeA6RfBrZO5wZrT9DMC1UqE1f1w==}
+ engines: {node: ^20.9.0 || >=22}
+
react-dom@19.2.4:
resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==}
peerDependencies:
@@ -4237,6 +4417,10 @@ packages:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
+ recast@0.23.11:
+ resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==}
+ engines: {node: '>= 4'}
+
recma-build-jsx@1.0.0:
resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
@@ -4251,6 +4435,10 @@ packages:
recma-stringify@1.0.0:
resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==}
+ redent@3.0.0:
+ resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
+ engines: {node: '>=8'}
+
regex-recursion@6.0.2:
resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
@@ -4343,6 +4531,10 @@ packages:
rsc-html-stream@0.0.7:
resolution: {integrity: sha512-v9+fuY7usTgvXdNl8JmfXCvSsQbq2YMd60kOeeMIqCJFZ69fViuIxztHei7v5mlMMa2h3SqS+v44Gu9i9xANZA==}
+ run-applescript@7.1.0:
+ resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
+ engines: {node: '>=18'}
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -4458,6 +4650,10 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
source-map@0.7.6:
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
engines: {node: '>= 12'}
@@ -4489,6 +4685,15 @@ packages:
std-env@3.10.0:
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+ storybook@10.3.4:
+ resolution: {integrity: sha512-866YXZy9k59tLPl9SN3KZZOFeBC/swxkuBVtW8iQjJIzfCrvk7zXQd8RSQ4ignmCdArVvY4lGMCAT4yNaZSt1g==}
+ hasBin: true
+ peerDependencies:
+ prettier: ^2 || ^3
+ peerDependenciesMeta:
+ prettier:
+ optional: true
+
streamx@2.25.0:
resolution: {integrity: sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==}
@@ -4518,6 +4723,14 @@ packages:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
+ strip-indent@3.0.0:
+ resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+ engines: {node: '>=8'}
+
+ strip-indent@4.1.1:
+ resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==}
+ engines: {node: '>=12'}
+
strip-literal@3.1.0:
resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
@@ -4602,6 +4815,9 @@ packages:
thenify@3.3.1:
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ tiny-invariant@1.3.3:
+ resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
+
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
@@ -4649,6 +4865,10 @@ packages:
trough@2.2.0:
resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+ ts-dedent@2.2.0:
+ resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==}
+ engines: {node: '>=6.10'}
+
ts-error@1.0.6:
resolution: {integrity: sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==}
@@ -4665,6 +4885,10 @@ packages:
resolution: {integrity: sha512-TdXInqG+61pj/TvORqITWjvjTTsL1EZxwX49iEj89+xFAcqPT8tjChpAGQXzfcF4MJwvNiuoCEbBOKqVf3ds3g==}
hasBin: true
+ tsconfig-paths@4.2.0:
+ resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
+ engines: {node: '>=6'}
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -5058,6 +5282,10 @@ packages:
utf-8-validate:
optional: true
+ wsl-utils@0.1.0:
+ resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==}
+ engines: {node: '>=18'}
+
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -5126,6 +5354,8 @@ packages:
snapshots:
+ '@adobe/css-tools@4.4.4': {}
+
'@alloc/quick-lru@5.2.0': {}
'@ampproject/remapping@2.3.0':
@@ -5984,6 +6214,14 @@ snapshots:
'@istanbuljs/schema@0.1.3': {}
+ '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3))':
+ dependencies:
+ glob: 13.0.6
+ react-docgen-typescript: 2.4.0(typescript@5.9.3)
+ vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3)
+ optionalDependencies:
+ typescript: 5.9.3
+
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -6500,6 +6738,75 @@ snapshots:
'@stitches/core@1.2.8': {}
+ '@storybook/builder-vite@10.3.4(esbuild@0.27.4)(rollup@4.60.0)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3))':
+ dependencies:
+ '@storybook/csf-plugin': 10.3.4(esbuild@0.27.4)(rollup@4.60.0)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3))
+ storybook: 10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ ts-dedent: 2.2.0
+ vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3)
+ transitivePeerDependencies:
+ - esbuild
+ - rollup
+ - webpack
+
+ '@storybook/csf-plugin@10.3.4(esbuild@0.27.4)(rollup@4.60.0)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3))':
+ dependencies:
+ storybook: 10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ unplugin: 2.3.11
+ optionalDependencies:
+ esbuild: 0.27.4
+ rollup: 4.60.0
+ vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3)
+
+ '@storybook/global@5.0.0': {}
+
+ '@storybook/icons@2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
+ dependencies:
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+
+ '@storybook/react-dom-shim@10.3.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))':
+ dependencies:
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ storybook: 10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+
+ '@storybook/react-vite@10.3.4(esbuild@0.27.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@4.60.0)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3))':
+ dependencies:
+ '@joshwooding/vite-plugin-react-docgen-typescript': 0.7.0(typescript@5.9.3)(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3))
+ '@rollup/pluginutils': 5.3.0(rollup@4.60.0)
+ '@storybook/builder-vite': 10.3.4(esbuild@0.27.4)(rollup@4.60.0)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3))
+ '@storybook/react': 10.3.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)
+ empathic: 2.0.0
+ magic-string: 0.30.21
+ react: 19.2.4
+ react-docgen: 8.0.3
+ react-dom: 19.2.4(react@19.2.4)
+ resolve: 1.22.11
+ storybook: 10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ tsconfig-paths: 4.2.0
+ vite: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)(yaml@2.8.3)
+ transitivePeerDependencies:
+ - esbuild
+ - rollup
+ - supports-color
+ - typescript
+ - webpack
+
+ '@storybook/react@10.3.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)':
+ dependencies:
+ '@storybook/global': 5.0.0
+ '@storybook/react-dom-shim': 10.3.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))
+ react: 19.2.4
+ react-docgen: 8.0.3
+ react-docgen-typescript: 2.4.0(typescript@5.9.3)
+ react-dom: 19.2.4(react@19.2.4)
+ storybook: 10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
'@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.0)':
dependencies:
'@babel/core': 7.29.0
@@ -6774,6 +7081,15 @@ snapshots:
picocolors: 1.1.1
pretty-format: 27.5.1
+ '@testing-library/jest-dom@6.9.1':
+ dependencies:
+ '@adobe/css-tools': 4.4.4
+ aria-query: 5.3.0
+ css.escape: 1.5.1
+ dom-accessibility-api: 0.6.3
+ picocolors: 1.1.1
+ redent: 3.0.0
+
'@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
dependencies:
'@babel/runtime': 7.29.2
@@ -6784,6 +7100,10 @@ snapshots:
'@types/react': 19.2.14
'@types/react-dom': 19.2.3(@types/react@19.2.14)
+ '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)':
+ dependencies:
+ '@testing-library/dom': 10.4.1
+
'@types/aria-query@5.0.4': {}
'@types/babel__core@7.20.5':
@@ -6818,6 +7138,8 @@ snapshots:
'@types/deep-eql@4.0.2': {}
+ '@types/doctrine@0.0.9': {}
+
'@types/estree-jsx@1.0.5':
dependencies:
'@types/estree': 1.0.8
@@ -6855,6 +7177,8 @@ snapshots:
dependencies:
csstype: 3.2.3
+ '@types/resolve@1.20.6': {}
+
'@types/unist@2.0.11': {}
'@types/unist@3.0.3': {}
@@ -7017,6 +7341,8 @@ snapshots:
dependencies:
'@wallet-standard/base': 1.1.0
+ '@webcontainer/env@1.1.1': {}
+
abort-controller-x@0.4.3: {}
abortcontroller-polyfill@1.7.8: {}
@@ -7097,6 +7423,10 @@ snapshots:
assertion-error@2.0.1: {}
+ ast-types@0.16.1:
+ dependencies:
+ tslib: 2.8.1
+
ast-v8-to-istanbul@0.3.12:
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -7369,6 +7699,10 @@ snapshots:
base64-js: 1.5.1
ieee754: 1.2.1
+ bundle-name@4.1.0:
+ dependencies:
+ run-applescript: 7.1.0
+
bundle-require@5.1.0(esbuild@0.27.4):
dependencies:
esbuild: 0.27.4
@@ -7532,6 +7866,8 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
+ css.escape@1.5.1: {}
+
csstype@3.2.3: {}
d@1.0.2:
@@ -7551,6 +7887,15 @@ snapshots:
deep-eql@5.0.2: {}
+ default-browser-id@5.0.1: {}
+
+ default-browser@5.5.0:
+ dependencies:
+ bundle-name: 4.1.0
+ default-browser-id: 5.0.1
+
+ define-lazy-prop@3.0.0: {}
+
delayed-stream@1.0.0: {}
depd@2.0.0: {}
@@ -7573,8 +7918,14 @@ snapshots:
dependencies:
path-type: 4.0.0
+ doctrine@3.0.0:
+ dependencies:
+ esutils: 2.0.3
+
dom-accessibility-api@0.5.16: {}
+ dom-accessibility-api@0.6.3: {}
+
dot-case@3.0.4:
dependencies:
no-case: 3.0.4
@@ -7606,6 +7957,8 @@ snapshots:
emojilib@2.4.0: {}
+ empathic@2.0.0: {}
+
encodeurl@2.0.0: {}
enhanced-resolve@5.20.1:
@@ -7793,6 +8146,8 @@ snapshots:
dependencies:
'@types/estree': 1.0.8
+ esutils@2.0.3: {}
+
etag@1.8.1: {}
event-emitter@0.3.5:
@@ -8001,6 +8356,12 @@ snapshots:
package-json-from-dist: 1.0.1
path-scurry: 1.11.1
+ glob@13.0.6:
+ dependencies:
+ minimatch: 10.2.4
+ minipass: 7.1.3
+ path-scurry: 2.0.2
+
globby@11.1.0:
dependencies:
array-union: 2.1.0
@@ -8155,6 +8516,8 @@ snapshots:
cjs-module-lexer: 1.4.3
module-details-from-path: 1.0.4
+ indent-string@4.0.0: {}
+
inherits@2.0.4: {}
inline-style-parser@0.2.7: {}
@@ -8182,6 +8545,8 @@ snapshots:
is-decimal@2.0.1: {}
+ is-docker@3.0.0: {}
+
is-extglob@2.1.1: {}
is-fullwidth-code-point@3.0.0: {}
@@ -8192,6 +8557,10 @@ snapshots:
is-hexadecimal@2.0.1: {}
+ is-inside-container@1.0.0:
+ dependencies:
+ is-docker: 3.0.0
+
is-number@7.0.0: {}
is-plain-obj@4.1.0: {}
@@ -8210,6 +8579,10 @@ snapshots:
is-windows@1.0.2: {}
+ is-wsl@3.1.1:
+ dependencies:
+ is-inside-container: 1.0.0
+
isexe@2.0.0: {}
isomorphic-ws@5.0.0(ws@8.20.0):
@@ -8976,6 +9349,8 @@ snapshots:
dependencies:
mime-db: 1.54.0
+ min-indent@1.0.1: {}
+
minimatch@10.2.4:
dependencies:
brace-expansion: 5.0.5
@@ -8984,6 +9359,8 @@ snapshots:
dependencies:
brace-expansion: 2.0.2
+ minimist@1.2.8: {}
+
minipass@7.1.3: {}
minisearch@7.2.0: {}
@@ -9120,6 +9497,13 @@ snapshots:
regex: 6.1.0
regex-recursion: 6.0.2
+ open@10.2.0:
+ dependencies:
+ default-browser: 5.5.0
+ define-lazy-prop: 3.0.0
+ is-inside-container: 1.0.0
+ wsl-utils: 0.1.0
+
outdent@0.5.0: {}
outvariant@1.4.0: {}
@@ -9190,6 +9574,11 @@ snapshots:
lru-cache: 10.4.3
minipass: 7.1.3
+ path-scurry@2.0.2:
+ dependencies:
+ lru-cache: 11.2.7
+ minipass: 7.1.3
+
path-to-regexp@8.4.0: {}
path-type@4.0.0: {}
@@ -9316,6 +9705,25 @@ snapshots:
dependencies:
es6-symbol: 3.1.4
+ react-docgen-typescript@2.4.0(typescript@5.9.3):
+ dependencies:
+ typescript: 5.9.3
+
+ react-docgen@8.0.3:
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/traverse': 7.29.0
+ '@babel/types': 7.29.0
+ '@types/babel__core': 7.20.5
+ '@types/babel__traverse': 7.28.0
+ '@types/doctrine': 0.0.9
+ '@types/resolve': 1.20.6
+ doctrine: 3.0.0
+ resolve: 1.22.11
+ strip-indent: 4.1.1
+ transitivePeerDependencies:
+ - supports-color
+
react-dom@19.2.4(react@19.2.4):
dependencies:
react: 19.2.4
@@ -9364,6 +9772,14 @@ snapshots:
readdirp@4.1.2: {}
+ recast@0.23.11:
+ dependencies:
+ ast-types: 0.16.1
+ esprima: 4.0.1
+ source-map: 0.6.1
+ tiny-invariant: 1.3.3
+ tslib: 2.8.1
+
recma-build-jsx@1.0.0:
dependencies:
'@types/estree': 1.0.8
@@ -9393,6 +9809,11 @@ snapshots:
unified: 11.0.5
vfile: 6.0.3
+ redent@3.0.0:
+ dependencies:
+ indent-string: 4.0.0
+ strip-indent: 3.0.0
+
regex-recursion@6.0.2:
dependencies:
regex-utilities: 2.3.0
@@ -9573,6 +9994,8 @@ snapshots:
rsc-html-stream@0.0.7: {}
+ run-applescript@7.1.0: {}
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
@@ -9748,6 +10171,8 @@ snapshots:
source-map-js@1.2.1: {}
+ source-map@0.6.1: {}
+
source-map@0.7.6: {}
space-separated-tokens@2.0.2: {}
@@ -9774,6 +10199,30 @@ snapshots:
std-env@3.10.0: {}
+ storybook@10.3.4(@testing-library/dom@10.4.1)(prettier@2.8.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ '@storybook/global': 5.0.0
+ '@storybook/icons': 2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ '@testing-library/jest-dom': 6.9.1
+ '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1)
+ '@vitest/expect': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@webcontainer/env': 1.1.1
+ esbuild: 0.27.4
+ open: 10.2.0
+ recast: 0.23.11
+ semver: 7.7.4
+ use-sync-external-store: 1.6.0(react@19.2.4)
+ ws: 8.20.0
+ optionalDependencies:
+ prettier: 2.8.8
+ transitivePeerDependencies:
+ - '@testing-library/dom'
+ - bufferutil
+ - react
+ - react-dom
+ - utf-8-validate
+
streamx@2.25.0:
dependencies:
events-universal: 1.0.1
@@ -9812,6 +10261,12 @@ snapshots:
strip-bom@3.0.0: {}
+ strip-indent@3.0.0:
+ dependencies:
+ min-indent: 1.0.1
+
+ strip-indent@4.1.1: {}
+
strip-literal@3.1.0:
dependencies:
js-tokens: 9.0.1
@@ -9897,6 +10352,8 @@ snapshots:
dependencies:
any-promise: 1.3.0
+ tiny-invariant@1.3.3: {}
+
tinybench@2.9.0: {}
tinyexec@0.3.2: {}
@@ -9928,6 +10385,8 @@ snapshots:
trough@2.2.0: {}
+ ts-dedent@2.2.0: {}
+
ts-error@1.0.6: {}
ts-interface-checker@0.1.13: {}
@@ -9947,6 +10406,12 @@ snapshots:
ts-poet: 6.12.0
ts-proto-descriptors: 2.0.0
+ tsconfig-paths@4.2.0:
+ dependencies:
+ json5: 2.2.3
+ minimist: 1.2.8
+ strip-bom: 3.0.0
+
tslib@2.8.1: {}
tsup@8.5.1(jiti@2.6.1)(postcss@8.5.8)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.3):
@@ -10400,6 +10865,10 @@ snapshots:
ws@8.20.0: {}
+ wsl-utils@0.1.0:
+ dependencies:
+ is-wsl: 3.1.1
+
y18n@5.0.8: {}
yallist@3.1.1: {}
diff --git a/site/pages/components/StorybookEmbed.tsx b/site/pages/components/StorybookEmbed.tsx
new file mode 100644
index 0000000..08d1aed
--- /dev/null
+++ b/site/pages/components/StorybookEmbed.tsx
@@ -0,0 +1,24 @@
+'use client'
+
+export function StorybookEmbed({
+ id,
+ height = 200,
+}: {
+ id: string
+ height?: number
+}) {
+ return (
+
+ )
+}
diff --git a/site/pages/kit/account-modal.mdx b/site/pages/kit/account-modal.mdx
new file mode 100644
index 0000000..eec6737
--- /dev/null
+++ b/site/pages/kit/account-modal.mdx
@@ -0,0 +1,21 @@
+import { StorybookEmbed } from '../components/StorybookEmbed'
+
+# AccountModal
+
+A pre-styled modal showing account details: address, balance, and a disconnect button. Opens when clicking the ConnectButton while connected.
+
+## Preview
+
+
+
+## Usage
+
+```tsx
+import { AccountModal } from '@mbga/kit'
+
+function App() {
+ return
+}
+```
+
+The modal opens automatically when the `ConnectButton` is clicked in a connected state. It displays the full wallet address with a copy button, current balance, and a disconnect action.
diff --git a/site/pages/kit/connect-button.mdx b/site/pages/kit/connect-button.mdx
new file mode 100644
index 0000000..68a3a05
--- /dev/null
+++ b/site/pages/kit/connect-button.mdx
@@ -0,0 +1,53 @@
+import { StorybookEmbed } from '../components/StorybookEmbed'
+
+# ConnectButton
+
+A pre-styled button that shows "Connect Wallet" when disconnected and displays the truncated address with balance when connected.
+
+## Preview
+
+### Disconnected
+
+
+
+### Connected
+
+
+
+### Custom Label
+
+
+
+## Usage
+
+```tsx
+import { ConnectButton } from '@mbga/kit'
+
+function App() {
+ return
+}
+```
+
+## Props
+
+| Prop | Type | Default | Description |
+| --- | --- | --- | --- |
+| `label` | `string` | `'Connect Wallet'` | Label shown when disconnected |
+| `className` | `string` | — | Custom CSS class |
+| `style` | `CSSProperties` | — | Inline styles |
+
+## Custom Render Prop
+
+Use `ConnectButton.Custom` for full control over the rendered UI:
+
+```tsx
+
+ {({ isConnected, show, truncatedAddress }) => (
+
+ )}
+
+```
+
+
diff --git a/site/pages/kit/connect-modal.mdx b/site/pages/kit/connect-modal.mdx
new file mode 100644
index 0000000..39f5de2
--- /dev/null
+++ b/site/pages/kit/connect-modal.mdx
@@ -0,0 +1,21 @@
+import { StorybookEmbed } from '../components/StorybookEmbed'
+
+# ConnectModal
+
+A pre-styled modal that lists available wallet connectors. Automatically opens and closes via KitProvider context.
+
+## Preview
+
+
+
+## Usage
+
+```tsx
+import { ConnectModal } from '@mbga/kit'
+
+function App() {
+ return
+}
+```
+
+The modal opens when `ConnectButton` is clicked while disconnected. It can also be controlled programmatically via the Kit context.
diff --git a/site/pages/kit/index.mdx b/site/pages/kit/index.mdx
new file mode 100644
index 0000000..f6975b4
--- /dev/null
+++ b/site/pages/kit/index.mdx
@@ -0,0 +1,53 @@
+# Kit
+
+`@mbga/kit` provides pre-built, themeable React UI components for Spark wallet connection. Drop them into your app for an instant wallet experience.
+
+## Components
+
+| Component | Description |
+| --- | --- |
+| [`ConnectButton`](/kit/connect-button) | Button that shows "Connect Wallet" when disconnected and account info when connected |
+| [`ConnectModal`](/kit/connect-modal) | Modal listing available wallet connectors |
+| [`AccountModal`](/kit/account-modal) | Modal showing account details, balance, and disconnect |
+
+## Quick Start
+
+```tsx
+import { MbgaProvider } from 'mbga'
+import { KitProvider, ConnectButton, ConnectModal, AccountModal } from '@mbga/kit'
+
+function App() {
+ return (
+
+
+
+
+
+
+
+ )
+}
+```
+
+## Theming
+
+Kit supports `light` and `dark` themes out of the box. Pass the `theme` prop to `KitProvider`:
+
+```tsx
+
+```
+
+You can also provide custom CSS variable overrides:
+
+```tsx
+
+```
+
+## Storybook
+
+Browse all component variants and themes interactively by running `pnpm storybook` from the repository root.
diff --git a/site/sidebar.ts b/site/sidebar.ts
index 59b688c..4a41230 100644
--- a/site/sidebar.ts
+++ b/site/sidebar.ts
@@ -30,6 +30,15 @@ export const sidebar = [
{ text: 'Authentication', link: '/flashnet/authentication' },
],
},
+ {
+ text: 'Kit',
+ items: [
+ { text: 'Overview', link: '/kit' },
+ { text: 'ConnectButton', link: '/kit/connect-button' },
+ { text: 'ConnectModal', link: '/kit/connect-modal' },
+ { text: 'AccountModal', link: '/kit/account-modal' },
+ ],
+ },
{
text: 'API Reference',
collapsed: true,
diff --git a/site/vocs.config.ts b/site/vocs.config.ts
index 7aecd70..947975b 100644
--- a/site/vocs.config.ts
+++ b/site/vocs.config.ts
@@ -25,6 +25,7 @@ export default defineConfig({
match: '/getting-started|/installation|/connectors|/frameworks',
},
{ text: 'API', link: '/api', match: '/api' },
+ { text: 'Kit', link: '/kit', match: '/kit' },
{ text: 'Examples', link: '/examples', match: '/examples' },
{
text: pkg.version,
@@ -46,6 +47,7 @@ export default defineConfig({
'/connectors': sidebar,
'/frameworks': sidebar,
'/flashnet': sidebar,
+ '/kit': sidebar,
'/api': sidebar,
'/examples': sidebar,
'/acknowledgments': sidebar,
diff --git a/vitest.config.ts b/vitest.config.ts
index 607bb48..70f1515 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -26,6 +26,10 @@ export default defineConfig({
'**/*.d.ts',
'**/tsup.config.ts',
'**/version.ts',
+ '**/*.stories.ts',
+ '**/*.stories.tsx',
+ '**/__stories__/**',
+ '**/.storybook/**',
'**/exports/**',
'vitest.config.ts',
'packages/test/**',