From cb6d2a2759316a93095446f47f0a1d783c22d8a6 Mon Sep 17 00:00:00 2001 From: Zach Hawtof Date: Tue, 19 May 2026 01:35:21 -0400 Subject: [PATCH] feat!: prepare 0.7.0 release with peer-dep migration and consumer polish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exits the 0.6.x-alpha line. Tightens up the consumer-facing surface ahead of the first stable 0.x release. BREAKING CHANGE: A narrow set of dependencies moved from `dependencies` to `peerDependencies` — specifically the ones a typical consumer is likely to already have, where deduplication gives them a real win (single copy of Radix → consistent React context across `` etc.; single copy of `lucide-react`): - react, react-dom - @radix-ui/react-{dialog,label,popover,radio-group,slot,tooltip} - lucide-react Modern package managers (pnpm 8+, npm 7+, yarn berry) auto-install peers, so most consumers will not need to change anything. Older tooling can follow the explicit install command in the README. `@dnd-kit/*`, `@tiptap/*`, `slack-blocks-to-jsx`, and `@tightknitai/slack-block-kit-validator` stay as direct dependencies — most consumers don't already have these, so peer would only add version-skew surface with no dedupe upside. `slack-web-api-client` is now a devDependency (type-only consumer; stays in tsup's `external` list). What's new: - feat(exports): subpath entries for headless usage - `@tightknitai/block-kitchen/helpers` (~4.5 KB) — `toSlackBlocks`, `encode/decodeBlocksFromString` and supporting types, with no React dependency cone. Safe for backends (Workers, Lambdas). - `@tightknitai/block-kitchen/palette` — `defaultPalette`, `legacyInputVariants`, `extraAlertVariant`, and `buildVariantById` without pulling in the builder. The root entry still re-exports everything, so existing imports are unaffected. - feat(palette): `disabledBlockTypes` prop on ``. Filters at the variant level — mixed-type sections (e.g. "Structure") keep the variants whose types aren't disabled and sections that go empty drop out. Convenient when you want the default palette minus a few block types without rebuilding it. - refactor(styles): scope the package's Tailwind theme and utility imports in named cascade layers (`bk-theme`, `bk-utilities`) so consumer utilities win against the package's on class-name collisions without source-order luck. Consumers can override layer order explicitly if they want — documented in the README. - docs(readme): bundlephobia minzip badge; framework recipes for Next.js (App + Pages Router), Remix, Vite, and Astro; portal- stylesheet pitfall callout (import at app root, not in a route); subpath-export examples; cascade-layer ordering snippet; `disabledBlockTypes` row in the props table; explanation of the narrow peer-dep set and the deliberate cut-off. - chore(release): version bumped to 0.7.0 in package.json and .release-please-manifest.json. Verification: typecheck ✓, 217/217 tests ✓, library build ✓, demo install + build ✓, demo dev server renders with no console errors and themed surface intact. Co-Authored-By: Claude Opus 4.7 (1M context) --- .release-please-manifest.json | 2 +- README.md | 121 ++++++++++++++++++++++++++++++- package.json | 35 ++++++--- pnpm-lock.yaml | 48 ++++++------ src/components/block-kitchen.tsx | 23 +++++- src/helpers.ts | 11 +++ src/palette.ts | 16 ++++ src/styles.src.css | 16 +++- src/types.ts | 11 +++ tsup.config.ts | 18 ++++- 10 files changed, 260 insertions(+), 41 deletions(-) create mode 100644 src/helpers.ts create mode 100644 src/palette.ts diff --git a/.release-please-manifest.json b/.release-please-manifest.json index de6fbab..e7ca613 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.6.3-alpha.0" + ".": "0.7.0" } diff --git a/README.md b/README.md index cd367fd..dcea378 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![CI](https://github.com/TightknitAI/block-kitchen/actions/workflows/ci.yml/badge.svg)](https://github.com/TightknitAI/block-kitchen/actions/workflows/ci.yml) [![npm version](https://img.shields.io/npm/v/@tightknitai/block-kitchen.svg)](https://www.npmjs.com/package/@tightknitai/block-kitchen) +[![minzipped size](https://img.shields.io/bundlephobia/minzip/@tightknitai/block-kitchen)](https://bundlephobia.com/package/@tightknitai/block-kitchen) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Live demo](https://img.shields.io/badge/demo-live-6366f1)](https://block-kitchen.tightknit.dev) @@ -27,10 +28,48 @@ The package owns the entire builder UX — palette, sortable preview surface, pe pnpm add @tightknitai/block-kitchen ``` -Peer deps: `react`, `react-dom`. +Modern package managers (pnpm 8+, npm 7+, yarn berry) auto-install peer +dependencies — no extra command needed. The peer set is deliberately +narrow: only the dependencies a typical consumer is likely to *already* +have, where deduplication gives them a real win: + +- `react` `^18 || ^19`, `react-dom` `^18 || ^19` +- `@radix-ui/react-{dialog,label,popover,radio-group,slot,tooltip}` — + the dialog/popover/tooltip/sheet primitives the builder uses. If + you already use shadcn/ui you already have these, and peer + deduplication avoids two Radix copies (which would split React + context — a `` from your copy can't reach a + `` from ours). +- `lucide-react` — every icon in the toolbar, palette, and editors. + Universal in modern React UI stacks; peer keeps a single copy. + +Everything else (`@dnd-kit/*`, `@tiptap/*`, `slack-blocks-to-jsx`, +`@tightknitai/slack-block-kit-validator`) is a regular dependency. +Most consumers don't already have these, so there's no dedupe benefit +to forcing them into a peer position — and you don't have to think +about their versions. + +If your package manager doesn't auto-install peers: + +```bash +pnpm add @tightknitai/block-kitchen \ + react react-dom \ + @radix-ui/react-dialog @radix-ui/react-label \ + @radix-ui/react-popover @radix-ui/react-radio-group \ + @radix-ui/react-slot @radix-ui/react-tooltip \ + lucide-react +``` ## Usage +> **Import the stylesheet once, at app root.** The builder mounts +> dialogs, popovers, tooltips, and the mobile palette sheet via React +> portals, which render to `document.body` — outside the route tree. +> If you import `styles.css` inside a single route module, those +> portal contents will be unstyled on every other route that doesn't +> import it. Put the import in your root layout (Next.js `app/layout.tsx`, +> Remix `app/root.tsx`, Vite `src/main.tsx`, etc.). + ```tsx import { BlockKitchen } from "@tightknitai/block-kitchen"; import "@tightknitai/block-kitchen/styles.css"; @@ -71,6 +110,7 @@ export function MyBuilderPage() { | `onSend` | `(payload) => Promise<{ ok: boolean; error?: string }>` | yes | Called when the user submits the send dialog. Payload is `{ channelId, blocks, sendAsUser }`. | | `previewHooks` | `PreviewHooks` | no | Hooks forwarded to `slack-blocks-to-jsx`'s `` for resolving user / channel / emoji directives. | | `palette` | `PaletteSection[]` | no | The left-hand palette of draggable variants. Defaults to `defaultPalette`. Spread it to filter, reorder, or add your own pre-configured variants — see [Customizing the palette](#customizing-the-palette). | +| `disabledBlockTypes` | `SupportedBlockType[]` | no | Block types to hide from the palette without rebuilding it. Filters at the variant level — a section keeps any variants whose block types aren't disabled; sections that end up empty are dropped. Convenient when you want the default palette minus a few types (e.g. `['image', 'table']` for a text-only builder). | | `defaultOpenSections` | `boolean \| string[]` | no | Which palette section headers are expanded on first paint. `true` (default) opens all sections; `false` collapses all (Slack-style); an array opens only sections whose `name` is in the list (e.g. `['Section', 'Actions']`). The palette also has a built-in search input that expands matching sections on demand. | | `showPaletteSearch` | `boolean` | no | Whether the palette renders the quick-search input above the section list. Defaults to `true`. Set `false` for compact palettes (e.g. when you've passed a small custom `palette`) where scanning by eye is faster than typing. | | `paletteSearchPlaceholder` | `string` | no | Placeholder text for the palette search input. Defaults to `'Search blocks…'`. Useful for localization. | @@ -183,6 +223,85 @@ The lower-level CSS-variable contract above keeps working; the `theme` prop simp Fonts are deliberately not part of `BrandTheme`. The builder sets no `font-family` of its own (aside from `font-mono` on the JSON viewer, which is intentional), so it inherits whatever the host page declares on `` or ``. Set your brand typography globally and the builder will pick it up automatically — no additional configuration needed. The Slack preview surface continues to render with Slack's own typography via `slack-blocks-to-jsx`. +## Frameworks & SSR + +The builder is client-only by design — it uses drag sensors, contentEditable +(TipTap), portals, and `useEffect`-driven state. It cannot be statically +rendered on the server. The component still ships fine inside SSR/SSG +frameworks; just mark its tree as client-side. + +- **Next.js (App Router)** — put `'use client'` at the top of the file + that renders ``. Import `styles.css` from + `app/layout.tsx` (the root layout) so portal content stays styled + on every route. +- **Next.js (Pages Router)** — render the component inside a page + module; the bundled-client default works. Import `styles.css` from + `pages/_app.tsx`. +- **Remix / React Router** — render inside any route component; + put the `styles.css` import in `app/root.tsx`. If you ship the + builder on a single route, import the stylesheet there *and* + in `root.tsx` so portals on other routes don't render unstyled. +- **Vite SPA** — import `styles.css` once from `src/main.tsx`. +- **Astro** — load the React component with `client:only="react"`. + +The package exports React JSX with the automatic runtime, so any +JSX-transform-aware bundler from the last few years works without +extra configuration. + +## Subpath exports + +Three import paths are published: + +```ts +// 1. Full builder (default) +import { BlockKitchen } from "@tightknitai/block-kitchen"; + +// 2. Headless helpers — no React component tree, safe for backends. +// Use this when you only need to round-trip / validate / encode +// blocks (e.g. inside a Worker that calls Slack's chat.postMessage). +import { + toSlackBlocks, + encodeBlocksToString, + decodeBlocksFromString, +} from "@tightknitai/block-kitchen/helpers"; + +// 3. Palette catalog — for tooling that needs the default variants +// (e.g. a Storybook story or a config generator) without pulling +// in the builder. +import { + defaultPalette, + legacyInputVariants, + extraAlertVariant, +} from "@tightknitai/block-kitchen/palette"; +``` + +The root entry (`.`) still re-exports everything from `./helpers` and +`./palette`, so existing imports keep working — the subpaths are a tree- +shaking-friendly shortcut, not a breaking split. + +## Cascade layer ordering (Tailwind users) + +The stylesheet emits all utility classes into a named cascade layer: + +```css +@layer bk-theme, bk-utilities; +``` + +Per CSS Cascade Level 5, unlayered rules and rules in later-declared +layers win over `bk-utilities`. In practice this means a consumer who +imports both this package's `styles.css` and their own Tailwind output +will see *their* utilities win on any class-name collision (e.g. they +define `bg-background` differently). No action needed for that +common case. + +If you want explicit control — for example, to make this package's +utilities win, or to layer them alongside a `shadcn/ui` token stack — +declare the order at the top of your own root stylesheet: + +```css +@layer bk-theme, bk-utilities, theme, base, components, utilities; +``` + ## License MIT. See [LICENSE](./LICENSE). diff --git a/package.json b/package.json index 75f9485..a5d5d5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tightknitai/block-kitchen", - "version": "0.6.3-alpha.0", + "version": "0.7.0", "description": "A drag-and-drop, no-code-friendly visual builder for Slack Block Kit messages. Integration-agnostic React component.", "type": "module", "main": "./dist/index.cjs", @@ -12,6 +12,16 @@ "import": "./dist/index.js", "require": "./dist/index.cjs" }, + "./helpers": { + "types": "./dist/helpers.d.ts", + "import": "./dist/helpers.js", + "require": "./dist/helpers.cjs" + }, + "./palette": { + "types": "./dist/palette.d.ts", + "import": "./dist/palette.js", + "require": "./dist/palette.cjs" + }, "./styles.css": "./dist/styles.css" }, "files": [ @@ -46,30 +56,35 @@ "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", - "@radix-ui/react-dialog": "^1.1.15", - "@radix-ui/react-label": "^2.1.8", - "@radix-ui/react-popover": "^1.1.15", - "@radix-ui/react-radio-group": "^1.3.8", - "@radix-ui/react-slot": "^1.2.4", - "@radix-ui/react-tooltip": "^1.2.8", "@tightknitai/slack-block-kit-validator": "^0.1.0-alpha.0", "@tiptap/extension-link": "^3.23.4", "@tiptap/react": "^3.23.4", "@tiptap/starter-kit": "^3.23.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^1.16.0", "nanoid": "^5.1.11", "slack-blocks-to-jsx": "^1.0.4", - "slack-web-api-client": "^1.1.12", "tailwind-merge": "^3.6.0" }, "peerDependencies": { + "@radix-ui/react-dialog": "^1.1.0", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-popover": "^1.1.0", + "@radix-ui/react-radio-group": "^1.3.0", + "@radix-ui/react-slot": "^1.2.0", + "@radix-ui/react-tooltip": "^1.2.0", + "lucide-react": "^1.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "devDependencies": { "@biomejs/biome": "^2.4.15", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-radio-group": "^1.3.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-tooltip": "^1.2.8", "@storybook/addon-a11y": "^10.4.0", "@storybook/addon-docs": "^10.4.0", "@storybook/addon-vitest": "^10.4.0", @@ -85,9 +100,11 @@ "@vitest/coverage-v8": "^4.1.6", "jsdom": "^29.1.1", "lefthook": "^2.1.6", + "lucide-react": "^1.16.0", "playwright": "^1.60.0", "react": "^19.2.6", "react-dom": "^19.2.6", + "slack-web-api-client": "^1.1.12", "storybook": "^10.4.0", "tailwindcss": "^4.3.0", "tsup": "^8.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e66dcf6..61e3dc8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,24 +17,6 @@ importers: '@dnd-kit/utilities': specifier: ^3.2.2 version: 3.2.2(react@19.2.6) - '@radix-ui/react-dialog': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-label': - specifier: ^2.1.8 - version: 2.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-popover': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-radio-group': - specifier: ^1.3.8 - version: 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - '@radix-ui/react-slot': - specifier: ^1.2.4 - version: 1.2.4(@types/react@19.2.14)(react@19.2.6) - '@radix-ui/react-tooltip': - specifier: ^1.2.8 - version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@tightknitai/slack-block-kit-validator': specifier: ^0.1.0-alpha.0 version: 0.1.0-alpha.0 @@ -53,18 +35,12 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 - lucide-react: - specifier: ^1.16.0 - version: 1.16.0(react@19.2.6) nanoid: specifier: ^5.1.11 version: 5.1.11 slack-blocks-to-jsx: specifier: ^1.0.4 version: 1.0.4(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) - slack-web-api-client: - specifier: ^1.1.12 - version: 1.1.12 tailwind-merge: specifier: ^3.6.0 version: 3.6.0 @@ -72,6 +48,24 @@ importers: '@biomejs/biome': specifier: ^2.4.15 version: 2.4.15 + '@radix-ui/react-dialog': + specifier: ^1.1.15 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-label': + specifier: ^2.1.8 + version: 2.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-popover': + specifier: ^1.1.15 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-radio-group': + specifier: ^1.3.8 + version: 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + '@radix-ui/react-slot': + specifier: ^1.2.4 + version: 1.2.4(@types/react@19.2.14)(react@19.2.6) + '@radix-ui/react-tooltip': + specifier: ^1.2.8 + version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) '@storybook/addon-a11y': specifier: ^10.4.0 version: 10.4.0(storybook@10.4.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@testing-library/dom@10.4.1)(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)) @@ -117,6 +111,9 @@ importers: lefthook: specifier: ^2.1.6 version: 2.1.6 + lucide-react: + specifier: ^1.16.0 + version: 1.16.0(react@19.2.6) playwright: specifier: ^1.60.0 version: 1.60.0 @@ -126,6 +123,9 @@ importers: react-dom: specifier: ^19.2.6 version: 19.2.6(react@19.2.6) + slack-web-api-client: + specifier: ^1.1.12 + version: 1.1.12 storybook: specifier: ^10.4.0 version: 10.4.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@testing-library/dom@10.4.1)(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) diff --git a/src/components/block-kitchen.tsx b/src/components/block-kitchen.tsx index 2cdc9a8..dfd5385 100644 --- a/src/components/block-kitchen.tsx +++ b/src/components/block-kitchen.tsx @@ -15,7 +15,7 @@ import { import { sortableKeyboardCoordinates } from '@dnd-kit/sortable'; import { GripVertical } from 'lucide-react'; import { useCallback, useMemo, useState } from 'react'; -import { buildVariantById, defaultPalette } from '../lib/default-blocks'; +import { buildVariantById, defaultPalette, type PaletteSection } from '../lib/default-blocks'; import { Sheet, SheetContent, SheetDescription, SheetTitle } from '../lib/ui/sheet'; import { TooltipProvider } from '../lib/ui/tooltip'; import { useIsMobile } from '../lib/use-is-mobile'; @@ -48,6 +48,7 @@ export function BlockKitchen(props: BlockKitchenProps) { loadSendAsUserStatus, onSend, palette, + disabledBlockTypes, showPaletteSearch, paletteSearchPlaceholder, defaultOpenSections, @@ -58,7 +59,25 @@ export function BlockKitchen(props: BlockKitchenProps) { theme } = props; - const paletteSections = palette ?? defaultPalette; + const paletteSections = useMemo(() => { + const sections = palette ?? defaultPalette; + if (!disabledBlockTypes || disabledBlockTypes.length === 0) { + return sections; + } + // Filter at the variant level: a section may mix block types (e.g. + // Structure contains divider + header + context), so dropping a + // whole section by name would over-prune. Run each factory once to + // peek at the block type; drop sections that end up empty. + const blocked = new Set(disabledBlockTypes); + const filtered: PaletteSection[] = []; + for (const section of sections) { + const variants = section.variants.filter((variant) => !blocked.has(variant.factory().type)); + if (variants.length > 0) { + filtered.push({ ...section, variants }); + } + } + return filtered; + }, [palette, disabledBlockTypes]); const variantById = useMemo(() => buildVariantById(paletteSections), [paletteSections]); // Default to message-only when omitted (or passed empty). The toolbar diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..bb5cad3 --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,11 @@ +/** + * Headless helper subpath: `@tightknitai/block-kitchen/helpers`. + * + * Re-exports the framework-agnostic helpers from this package without + * dragging in the React component tree. Useful for backend code (e.g. + * a Worker that round-trips a draft and posts to Slack) that only + * needs to sanitize blocks or encode/decode draft state. + */ +export { toSlackBlocks } from './lib/to-slack-blocks'; +export { decodeBlocksFromString, encodeBlocksToString } from './lib/url-state'; +export type { SupportedBlock, SupportedBlockType } from './types'; diff --git a/src/palette.ts b/src/palette.ts new file mode 100644 index 0000000..e778305 --- /dev/null +++ b/src/palette.ts @@ -0,0 +1,16 @@ +/** + * Palette subpath: `@tightknitai/block-kitchen/palette`. + * + * Re-exports the default palette and its building blocks for consumers + * who want to compose a custom palette without importing the full + * builder component tree. + */ + +export type { PaletteSection, PaletteVariant } from './lib/default-blocks'; +export { + buildVariantById, + defaultPalette, + extraAlertVariant, + legacyInputVariants +} from './lib/default-blocks'; +export type { SupportedBlock, SupportedBlockType } from './types'; diff --git a/src/styles.src.css b/src/styles.src.css index 8cfee48..917cc01 100644 --- a/src/styles.src.css +++ b/src/styles.src.css @@ -11,13 +11,25 @@ * vars — the standard shadcn/ui token set works as-is. */ +/* Cascade-layer order: declare our named layers up front so consumer + stylesheets that load after ours can override deterministically. + - `bk-theme` carries our `@theme` token mappings. + - `bk-utilities` carries every Tailwind utility class compiled from + this package. Consumer Tailwind utilities are typically in the + unnamed (top-level) cascade or in their own `utilities` layer, + either of which wins against a named layer per CSS Cascade Level + 5. A consumer who wants explicit ordering can write + `@layer bk-theme, bk-utilities, utilities;` (or similar) at the + top of their own root stylesheet. */ +@layer bk-theme, bk-utilities; + /* Tailwind v4 split imports. Skip the `preflight` layer so the package does not re-reset the host document's `*`, `body`, headings, etc. Studio loads this stylesheet from a route module; in an SPA it stays parsed for the rest of the session, so a global preflight here would affect every other page after a single visit. */ -@import "tailwindcss/theme.css" layer(theme); -@import "tailwindcss/utilities.css" layer(utilities); +@import "tailwindcss/theme.css" layer(bk-theme); +@import "tailwindcss/utilities.css" layer(bk-utilities); /* Bundle slack-blocks-to-jsx's own stylesheet so the preview component gets its button / mention / divider styling out of the box. The diff --git a/src/types.ts b/src/types.ts index 83b3a8b..d26b4da 100644 --- a/src/types.ts +++ b/src/types.ts @@ -403,6 +403,17 @@ export interface BlockKitchenProps { * `useMemo` or define at module scope). */ palette?: readonly PaletteSection[]; + /** + * Block types to hide from the palette without rebuilding it. Each + * palette section is keyed by a `blockType`; any section whose + * `blockType` matches an entry here is filtered out before render. + * Convenient when you want the default palette minus a few block + * types (e.g. `disabledBlockTypes: ['image', 'table']` for a + * text-only builder). For finer-grained control (filtering + * individual variants, reordering, or adding custom presets), pass + * a custom `palette` array instead. + */ + disabledBlockTypes?: readonly SupportedBlockType[]; /** * Whether the palette renders a quick-search input above the section * list. Defaults to `true`. Set `false` for compact palettes (e.g. diff --git a/tsup.config.ts b/tsup.config.ts index eea3433..ad94630 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,7 +1,7 @@ import { defineConfig } from 'tsup'; export default defineConfig({ - entry: ['src/index.ts'], + entry: ['src/index.ts', 'src/helpers.ts', 'src/palette.ts'], format: ['esm', 'cjs'], dts: true, target: 'es2022', @@ -9,5 +9,19 @@ export default defineConfig({ clean: true, splitting: false, treeshake: true, - external: ['react', 'react-dom', 'slack-web-api-client'] + // tsup auto-externalizes `dependencies` and `peerDependencies` from + // package.json. Listed explicitly: `react`/`react-dom` (so JSX runtime + // imports are external) and `slack-web-api-client` (types-only consumer + // moved to devDependencies — must stay external in the runtime bundle). + external: [ + 'react', + 'react-dom', + 'react/jsx-runtime', + /^@radix-ui\//, + /^@dnd-kit\//, + /^@tiptap\//, + 'lucide-react', + 'slack-blocks-to-jsx', + 'slack-web-api-client' + ] });