@tightknitai/block-kitchen 0.10.24 → 0.10.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -6
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +345 -190
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +347 -192
- package/dist/index.js.map +1 -1
- package/dist/{palette-Bup6i-9c.d.cts → palette-DTE9U5si.d.cts} +69 -1
- package/dist/{palette-Bup6i-9c.d.ts → palette-DTE9U5si.d.ts} +69 -1
- package/dist/palette.cjs.map +1 -1
- package/dist/palette.d.cts +1 -1
- package/dist/palette.d.ts +1 -1
- package/dist/palette.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -140,6 +140,7 @@ Given no height to work with — a plain `<div>` in ordinary document flow — i
|
|
|
140
140
|
| `previewHooks` | `PreviewHooks` | no | Hooks forwarded to `slack-blocks-to-jsx`'s `<Message>` for resolving user / channel / emoji directives. |
|
|
141
141
|
| `blockActions` | `BlockAction[]` | no | Host buttons added to every block's action toolbar, before Edit / Duplicate / Delete. Each is `{ id, label, icon, onSelect }`, and `onSelect` receives the block's `{ index, childIndex }`. See [Adding your own block actions](#adding-your-own-block-actions-blockactions). |
|
|
142
142
|
| `renderBlockAdornment` | `(position: BlockPosition) => ReactNode` | no | Host content shown beside every block, at its right edge, all the time (unlike `blockActions`, which show on hover), e.g. a count of comments on the block. Return `null` for a block with nothing to show. See [Adding your own block actions](#adding-your-own-block-actions-blockactions). |
|
|
143
|
+
| `blockEditors` | `CustomBlockEditor[]` | no | Host forms that replace the built-in editor for the blocks they match. Each is `{ id, label, match, component }`. The block stays ordinary Block Kit. See [Editing a block your way](#editing-a-block-your-way-blockeditors). |
|
|
143
144
|
| `customEmojis` | `CustomEmoji[]` | no | Workspace custom emoji (`{ name, url, alias }`) the preview resolves. Entries with a `url` render `:name:` as the workspace image; alias entries (`url: null`) fall back to their target emoji. Render-only — never serialized into the emitted Block Kit JSON. A caller-supplied `previewHooks.emoji` takes precedence. |
|
|
144
145
|
| `mentions` | `{ searchUsers, getUserName?, searchChannels?, getChannelName? }` | no | Opt-in rich-text mentions. `@` and the Mention button search users; when `searchChannels` is provided, `#` and the Channel button search channels. Picks serialize as Slack `user` / `channel` elements. See [Mentions](#mentions-opt-in). |
|
|
145
146
|
| `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). |
|
|
@@ -150,6 +151,7 @@ Given no height to work with — a plain `<div>` in ordinary document flow — i
|
|
|
150
151
|
| `paletteSearchPlaceholder` | `string` | no | Placeholder text for the palette search input. Defaults to `'Search blocks…'`. Useful for localization. |
|
|
151
152
|
| `allowedSurfaces` | `PreviewSurface[]` | no | Allowlist of preview surfaces (`'message'`, `'modal'`, `'app_home'`). Defaults to `['message']` — surface dropdown is hidden when only one surface is allowed. The first entry is the initial selection. |
|
|
152
153
|
| `showThemeControl` | `boolean` | no | Defaults to `true`. When `false`, the toolbar's light/dark toggle is hidden and the theme stays at `defaultPreviewTheme`. Ignored when `previewTheme` is set (a controlled theme always hides the toggle). |
|
|
154
|
+
| `undoRedoShortcuts` | `boolean` | no | Defaults to `true`: `Ctrl`/`Cmd` + `Z` undoes and `Ctrl`/`Cmd` + `Shift` + `Z` (or `Ctrl` + `Y`) redoes, like the toolbar's Undo / Redo buttons. Pass `false` to leave those keys to the host. See [Undo & redo](#undo--redo). |
|
|
153
155
|
| `defaultPreviewTheme` | `'light' \| 'dark'` | no | Initial (uncontrolled) preview theme. Pass the host app's current theme so the preview opens matched to the consuming app's appearance. Ignored when `previewTheme` is provided. |
|
|
154
156
|
| `previewTheme` | `'light' \| 'dark'` | no | Controlled preview theme. When set, the preview renders in this theme, follows it reactively, and the toolbar's light/dark toggle is hidden so the host app fully owns the theme. Leave unset to keep the preview uncontrolled (seeded from `defaultPreviewTheme`, toggle shown). |
|
|
155
157
|
| `sendButtonLabel` | `string` | no | Label and accessible name for the toolbar's Send button (which opens the send dialog). Defaults to `'Review & send'` (the dialog is the review step). Override it for product-specific copy, e.g. `'Send to channel…'`. |
|
|
@@ -489,6 +491,41 @@ the canvas, for example to scroll to it or highlight it:
|
|
|
489
491
|
document.querySelector(`.bk-root [data-bk-block-index="${index}"]:not([data-bk-child-index])`);
|
|
490
492
|
```
|
|
491
493
|
|
|
494
|
+
## Editing a block your way (`blockEditors`)
|
|
495
|
+
|
|
496
|
+
Some blocks mean something to your app beyond their Block Kit shape: a
|
|
497
|
+
"Share on LinkedIn" button, say, whose URL is built from the text of a post.
|
|
498
|
+
Editing that URL by hand in the built-in buttons form is no way to write a
|
|
499
|
+
post. `blockEditors` lets the host supply the form instead:
|
|
500
|
+
|
|
501
|
+
```tsx
|
|
502
|
+
const LINKEDIN_EDITOR: CustomBlockEditor = {
|
|
503
|
+
id: "linkedin-share",
|
|
504
|
+
label: "Share on LinkedIn",
|
|
505
|
+
match: (block) => isLinkedInShareBlock(block), // your own check
|
|
506
|
+
component: ({ block, onChange }) => (
|
|
507
|
+
<Textarea
|
|
508
|
+
value={postTextFrom(block)}
|
|
509
|
+
onChange={(e) => onChange(withPostText(block, e.target.value))}
|
|
510
|
+
/>
|
|
511
|
+
),
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
<BlockKitchen blockEditors={[LINKEDIN_EDITOR]} {...rest} />;
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
When a block's edit popover opens, the first editor whose `match` accepts the
|
|
518
|
+
block replaces the built-in form, under the heading "Edit {label}". The
|
|
519
|
+
popover keeps its validation errors, Block ID field and Done button. Blocks no
|
|
520
|
+
editor matches keep the built-in form, and so does every block when the prop
|
|
521
|
+
is left out.
|
|
522
|
+
|
|
523
|
+
The block itself stays ordinary Block Kit, so the preview, validation, the
|
|
524
|
+
JSON view and sending all treat it like any other. That also means `match` has
|
|
525
|
+
to recognize the block from what it holds (a URL, an `action_id`): a message
|
|
526
|
+
loaded back from Slack carries nothing else. Keep the array referentially
|
|
527
|
+
stable (module scope or `useMemo`).
|
|
528
|
+
|
|
492
529
|
## Customizing the palette
|
|
493
530
|
|
|
494
531
|
On desktop the palette is a rail down the left-hand side, with a chevron handle on its outer border that hides and restores it — collapsed, the preview gets the full width, and the rail comes back with its open sections and search exactly as they were. Below the `md` breakpoint there's no rail: the toolbar's **Blocks** button opens the palette as a bottom sheet instead, and picking a block closes it.
|
|
@@ -525,6 +562,28 @@ const PALETTE: readonly PaletteSection[] = [
|
|
|
525
562
|
|
|
526
563
|
Variant `id`s must be unique across the array — the drag-drop lookup keys by id.
|
|
527
564
|
|
|
565
|
+
### Badges and locked variants
|
|
566
|
+
|
|
567
|
+
A variant can carry a `badge`, a small tag beside its label such as the plan
|
|
568
|
+
it belongs to. Set `locked` as well to show a block without letting the user
|
|
569
|
+
add it: it can't be dragged, has no add button, and picking it calls
|
|
570
|
+
`onLockedSelect`, for example to open an upgrade prompt.
|
|
571
|
+
|
|
572
|
+
```tsx
|
|
573
|
+
const shareVariant: PaletteVariant = {
|
|
574
|
+
id: "linkedin_share",
|
|
575
|
+
label: "Share on LinkedIn",
|
|
576
|
+
factory: () => linkedInShareBlock(),
|
|
577
|
+
badge: { label: "Enterprise", icon: Crown },
|
|
578
|
+
locked: !plan.includesLinkedIn,
|
|
579
|
+
onLockedSelect: () => openUpgradeDialog(),
|
|
580
|
+
};
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
A locked variant without `onLockedSelect` is inert. In the mobile sheet,
|
|
584
|
+
picking one closes the sheet first, so whatever the host opens isn't stacked
|
|
585
|
+
on top of it.
|
|
586
|
+
|
|
528
587
|
### Simple vs advanced palette
|
|
529
588
|
|
|
530
589
|
By default the palette opens on everything it has: every section, plus the search input. For consumers whose users are writing ordinary messages rather than building interactive apps, `paletteMode="simple"` opens on a short starter list instead — no sections, no search — behind an **Advanced** link that swaps in the full palette (and back).
|
|
@@ -728,8 +787,8 @@ Defense-in-depth: blocks are validated against [slack-block-kit-validator](https
|
|
|
728
787
|
Every edit to the draft is undoable — adding, deleting, duplicating,
|
|
729
788
|
reordering, dragging in and out of containers, editing a block's fields, and
|
|
730
789
|
the toolbar's **Clear** and **View JSON → apply**. The toolbar shows **Undo**
|
|
731
|
-
and **Redo** buttons (disabled when there's nothing to step to), and
|
|
732
|
-
keyboard shortcuts
|
|
790
|
+
and **Redo** buttons (disabled when there's nothing to step to), and these
|
|
791
|
+
keyboard shortcuts do the same:
|
|
733
792
|
|
|
734
793
|
| Shortcut | Action |
|
|
735
794
|
|---|---|
|
|
@@ -743,10 +802,23 @@ Notes:
|
|
|
743
802
|
character at a time. Editing a different block, or any structural change,
|
|
744
803
|
starts a new step.
|
|
745
804
|
- **Native text undo is preserved.** While a text input, textarea, or the
|
|
746
|
-
inline rich-text editor is focused
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
805
|
+
inline rich-text editor is focused (including the fields in a block's
|
|
806
|
+
editor popover), `Ctrl/Cmd+Z` performs the browser's own per-character
|
|
807
|
+
undo. The builder only takes over when focus is on the canvas or toolbar.
|
|
808
|
+
- **The shortcuts are scoped to the builder**, so they don't hijack the host
|
|
809
|
+
page's own `Ctrl/Cmd+Z`. They act while focus is inside the builder, or
|
|
810
|
+
while nothing on the page has focus (focus is on `<body>`, or on a host
|
|
811
|
+
element wrapping the builder) and the last click landed in the builder.
|
|
812
|
+
That second case covers a click on the canvas background, or deleting a
|
|
813
|
+
block, which unmounts the Delete button that had focus. After a click
|
|
814
|
+
elsewhere on the page, or with focus in one of the host's own fields, the
|
|
815
|
+
keys are left alone.
|
|
816
|
+
- With nothing to undo or redo, or when something else already handled the
|
|
817
|
+
key press (`defaultPrevented`), the shortcut does nothing and doesn't call
|
|
818
|
+
`preventDefault`.
|
|
819
|
+
- **Opting out.** Pass `undoRedoShortcuts={false}` to turn the shortcuts off
|
|
820
|
+
and leave those keys to the host. The toolbar buttons still work, and
|
|
821
|
+
their tooltips stop mentioning the shortcuts.
|
|
750
822
|
- **Loading is a fresh baseline.** [Loading an existing
|
|
751
823
|
message](#loading-an-existing-message-opt-in) (or "open as new") starts a
|
|
752
824
|
new document with an empty history — undo won't step back across the load
|
package/dist/helpers.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SupportedBlock } from './palette-
|
|
2
|
-
export {
|
|
1
|
+
import { S as SupportedBlock } from './palette-DTE9U5si.cjs';
|
|
2
|
+
export { ad as SupportedBlockType } from './palette-DTE9U5si.cjs';
|
|
3
3
|
import 'react';
|
|
4
4
|
import 'slack-web-api-client';
|
|
5
5
|
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SupportedBlock } from './palette-
|
|
2
|
-
export {
|
|
1
|
+
import { S as SupportedBlock } from './palette-DTE9U5si.js';
|
|
2
|
+
export { ad as SupportedBlockType } from './palette-DTE9U5si.js';
|
|
3
3
|
import 'react';
|
|
4
4
|
import 'slack-web-api-client';
|
|
5
5
|
|