@tightknitai/block-kitchen 0.6.1-alpha.0
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/LICENSE +21 -0
- package/README.md +192 -0
- package/dist/index.cjs +6943 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +659 -0
- package/dist/index.d.ts +659 -0
- package/dist/index.js +6906 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +2 -0
- package/package.json +118 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { SectionBlock, HeaderBlock, DividerBlock, ContextBlock, ActionsBlock, ImageBlock, RichTextBlock, ImageElement, Button, ViewInputBlock } from 'slack-web-api-client';
|
|
3
|
+
import { ComponentType, SVGProps } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Brand theme resolver for the BlockKitchen chrome.
|
|
7
|
+
*
|
|
8
|
+
* Consumers can already brand the builder by overriding the shadcn/ui
|
|
9
|
+
* CSS custom properties declared in `styles.src.css` (the lower-level
|
|
10
|
+
* contract). This module wraps that contract in a typed, ergonomic prop
|
|
11
|
+
* — a preset name and/or a `Partial<BrandTokens>` map — and resolves it
|
|
12
|
+
* to the `cssVarName -> value` pairs that `BrandThemeScope` then writes
|
|
13
|
+
* to a scoped `<style>` block around the builder.
|
|
14
|
+
*
|
|
15
|
+
* Scope is intentionally limited to the builder chrome. The Slack
|
|
16
|
+
* preview is rendered by `slack-blocks-to-jsx` under its own
|
|
17
|
+
* `#slack_blocks_to_jsx` CSS namespace and does not consume these vars,
|
|
18
|
+
* so brand tokens never leak into Slack content rendering.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Tokens consumers may override. Mirrors the shadcn/ui token set
|
|
22
|
+
* already defined in `src/styles.src.css`. Color values are HSL
|
|
23
|
+
* component strings ("231.7 48.6% 54.1%") — matching the existing
|
|
24
|
+
* `hsl(var(--token, ...))` contract. `radius` takes a CSS length
|
|
25
|
+
* such as `"0.5rem"`.
|
|
26
|
+
*/
|
|
27
|
+
type BrandTokens = Partial<{
|
|
28
|
+
background: string;
|
|
29
|
+
foreground: string;
|
|
30
|
+
card: string;
|
|
31
|
+
cardForeground: string;
|
|
32
|
+
popover: string;
|
|
33
|
+
popoverForeground: string;
|
|
34
|
+
primary: string;
|
|
35
|
+
primaryForeground: string;
|
|
36
|
+
secondary: string;
|
|
37
|
+
secondaryForeground: string;
|
|
38
|
+
muted: string;
|
|
39
|
+
mutedForeground: string;
|
|
40
|
+
accent: string;
|
|
41
|
+
accentForeground: string;
|
|
42
|
+
destructive: string;
|
|
43
|
+
destructiveForeground: string;
|
|
44
|
+
border: string;
|
|
45
|
+
input: string;
|
|
46
|
+
ring: string;
|
|
47
|
+
radius: string;
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Curated preset names. `'default'` is a no-op (relies on the
|
|
51
|
+
* `styles.src.css` fallbacks). The other entries each define their own
|
|
52
|
+
* color palette and `radius`, demonstrating that brand presets can vary
|
|
53
|
+
* stylistic axes beyond color. Adding more later is non-breaking —
|
|
54
|
+
* extend the string union and add an entry to `PRESETS`.
|
|
55
|
+
*/
|
|
56
|
+
type BrandPreset = 'default' | 'slack' | 'ocean' | 'sunset' | 'mono' | 'cyberpunk';
|
|
57
|
+
/**
|
|
58
|
+
* Brand theme shape.
|
|
59
|
+
*
|
|
60
|
+
* - `preset` seeds the token map (currently a no-op for `'default'`).
|
|
61
|
+
* - `tokens` applies in both light and dark.
|
|
62
|
+
* - `light`/`dark` apply only when the matching dark-mode class is
|
|
63
|
+
* present on an ancestor (or on the scope itself).
|
|
64
|
+
*
|
|
65
|
+
* Merge precedence (later wins): preset → tokens → light/dark.
|
|
66
|
+
*/
|
|
67
|
+
interface BrandTheme {
|
|
68
|
+
preset?: BrandPreset;
|
|
69
|
+
tokens?: BrandTokens;
|
|
70
|
+
light?: BrandTokens;
|
|
71
|
+
dark?: BrandTokens;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* One pre-built block example shown as a draggable item in the palette.
|
|
76
|
+
* Modeled on Slack's real Block Kit Builder ("All selects", "Datepickers",
|
|
77
|
+
* "Filtered conversation", etc).
|
|
78
|
+
*/
|
|
79
|
+
interface PaletteVariant {
|
|
80
|
+
/** Stable id used as the DnD draggable id (`palette:${id}`). */
|
|
81
|
+
id: string;
|
|
82
|
+
/** Visible label shown next to the `+` icon. */
|
|
83
|
+
label: string;
|
|
84
|
+
/** Builds a fresh block payload when this variant is dropped. */
|
|
85
|
+
factory: () => SupportedBlock;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* One section in the palette. Sections group related variants under a
|
|
89
|
+
* single heading + icon, matching Slack's Block Kit Builder sidebar
|
|
90
|
+
* (Agents, Markdown, Section, Actions, Input, Structure, Rich Text,
|
|
91
|
+
* Image, Card and Carousel, Table).
|
|
92
|
+
*
|
|
93
|
+
* Variant ids must be unique across the entire palette — the drag-drop
|
|
94
|
+
* variant lookup keys by id, so a duplicate would shadow the earlier one.
|
|
95
|
+
*/
|
|
96
|
+
interface PaletteSection {
|
|
97
|
+
/** Visible heading for the section. */
|
|
98
|
+
name: string;
|
|
99
|
+
/** Lucide icon component rendered next to the section heading. */
|
|
100
|
+
icon: ComponentType<SVGProps<SVGSVGElement>>;
|
|
101
|
+
variants: PaletteVariant[];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* The built-in palette. Mirrors Slack's real Block Kit Builder: related
|
|
105
|
+
* variants (e.g. every select type) are combined into single showcase
|
|
106
|
+
* `actions` blocks ("All selects", "Datepickers") rather than each
|
|
107
|
+
* variant being its own row. The full set of single-element `input`
|
|
108
|
+
* variants is still available via {@link legacyInputVariants}.
|
|
109
|
+
*/
|
|
110
|
+
declare const defaultPalette: readonly PaletteSection[];
|
|
111
|
+
/**
|
|
112
|
+
* The single-element `input`-block variants that used to ship in
|
|
113
|
+
* `defaultPalette` before it was consolidated to mirror Slack's Block
|
|
114
|
+
* Kit Builder. Kept reachable so consumers who referenced these ids via
|
|
115
|
+
* the `palette` prop can spread them back into a custom palette.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```tsx
|
|
119
|
+
* import { defaultPalette, legacyInputVariants } from '@tightknitai/block-kitchen';
|
|
120
|
+
* import { TextCursorInput } from 'lucide-react';
|
|
121
|
+
*
|
|
122
|
+
* const palette = [
|
|
123
|
+
* ...defaultPalette,
|
|
124
|
+
* { name: 'All inputs', icon: TextCursorInput, variants: [...legacyInputVariants] }
|
|
125
|
+
* ];
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* Note: some ids here (`input_plain_text`, `input_date`, etc.) collide
|
|
129
|
+
* with curated ids in the new `defaultPalette`. `buildVariantById`
|
|
130
|
+
* keeps the last entry for a given id, so spread `legacyInputVariants`
|
|
131
|
+
* after `defaultPalette` to use the legacy factory.
|
|
132
|
+
*/
|
|
133
|
+
declare const legacyInputVariants: readonly PaletteVariant[];
|
|
134
|
+
/**
|
|
135
|
+
* Modal-only `alert` block variant. Dropped from `defaultPalette` to
|
|
136
|
+
* match Slack's Block Kit Builder sidebar (which doesn't list it), but
|
|
137
|
+
* kept reachable so consumers who want it back can re-add via a custom
|
|
138
|
+
* palette section.
|
|
139
|
+
*/
|
|
140
|
+
declare const extraAlertVariant: PaletteVariant;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The Slack Block Kit block types supported by the builder in v1.
|
|
144
|
+
*/
|
|
145
|
+
type SupportedBlockType = 'section' | 'header' | 'divider' | 'context' | 'actions' | 'image' | 'markdown' | 'rich_text' | 'table' | 'alert' | 'card' | 'carousel' | 'context_actions' | 'input';
|
|
146
|
+
/**
|
|
147
|
+
* Slack `markdown` block payload. Renders standard markdown (GFM)
|
|
148
|
+
* via `slack-blocks-to-jsx`'s react-markdown integration.
|
|
149
|
+
* `slack-web-api-client` doesn't ship this type yet, so we declare
|
|
150
|
+
* the minimal shape ourselves.
|
|
151
|
+
*/
|
|
152
|
+
interface MarkdownBlock {
|
|
153
|
+
type: 'markdown';
|
|
154
|
+
text: string;
|
|
155
|
+
block_id?: string;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* One cell in a {@link TableBlock} row. Slack accepts either a raw text
|
|
159
|
+
* cell or a rich-text cell; the visual editor only emits raw text in v1
|
|
160
|
+
* but preserves rich-text cells on edit.
|
|
161
|
+
*/
|
|
162
|
+
type TableCell = {
|
|
163
|
+
type: 'raw_text';
|
|
164
|
+
text: string;
|
|
165
|
+
} | {
|
|
166
|
+
type: 'rich_text';
|
|
167
|
+
elements: unknown[];
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Per-column setting in a {@link TableBlock}. May be null to skip a
|
|
171
|
+
* column. Matches Slack's `table_column_setting` schema.
|
|
172
|
+
*/
|
|
173
|
+
type TableColumnSetting = null | {
|
|
174
|
+
align?: 'left' | 'center' | 'right';
|
|
175
|
+
is_wrapped?: boolean;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Slack `table` block payload. Up to 100 rows, 20 cells per row.
|
|
179
|
+
* `slack-web-api-client` doesn't ship this type, so we declare it.
|
|
180
|
+
*/
|
|
181
|
+
interface TableBlock {
|
|
182
|
+
type: 'table';
|
|
183
|
+
rows: TableCell[][];
|
|
184
|
+
column_settings?: TableColumnSetting[];
|
|
185
|
+
block_id?: string;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Severity level for an {@link AlertBlock}. Controls the icon and color
|
|
189
|
+
* accent rendered by Slack. Defaults to `default` when omitted.
|
|
190
|
+
*/
|
|
191
|
+
type AlertLevel = 'default' | 'info' | 'warning' | 'error' | 'success';
|
|
192
|
+
/**
|
|
193
|
+
* Slack `alert` block payload. Single-line status notification with an
|
|
194
|
+
* optional severity level. Per Slack's surface compatibility rules, alert
|
|
195
|
+
* blocks render on modal surfaces only (not messages or home tabs).
|
|
196
|
+
* `slack-web-api-client` doesn't ship this type yet, so we declare it.
|
|
197
|
+
*/
|
|
198
|
+
interface AlertBlock {
|
|
199
|
+
type: 'alert';
|
|
200
|
+
text: {
|
|
201
|
+
type: 'plain_text' | 'mrkdwn';
|
|
202
|
+
text: string;
|
|
203
|
+
emoji?: boolean;
|
|
204
|
+
verbatim?: boolean;
|
|
205
|
+
};
|
|
206
|
+
level?: AlertLevel;
|
|
207
|
+
block_id?: string;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Slack `card` block payload. Renders a media-rich card with optional
|
|
211
|
+
* hero image, icon, title, subtitle, body, and action buttons. At least
|
|
212
|
+
* one of `hero_image`, `title`, `actions`, or `body` is required.
|
|
213
|
+
* `slack-web-api-client` doesn't ship this type yet, so we declare it.
|
|
214
|
+
*/
|
|
215
|
+
interface CardBlock {
|
|
216
|
+
type: 'card';
|
|
217
|
+
block_id?: string;
|
|
218
|
+
hero_image?: ImageElement;
|
|
219
|
+
icon?: ImageElement;
|
|
220
|
+
title?: {
|
|
221
|
+
type: 'plain_text' | 'mrkdwn';
|
|
222
|
+
text: string;
|
|
223
|
+
emoji?: boolean;
|
|
224
|
+
verbatim?: boolean;
|
|
225
|
+
};
|
|
226
|
+
subtitle?: {
|
|
227
|
+
type: 'plain_text' | 'mrkdwn';
|
|
228
|
+
text: string;
|
|
229
|
+
emoji?: boolean;
|
|
230
|
+
verbatim?: boolean;
|
|
231
|
+
};
|
|
232
|
+
body?: {
|
|
233
|
+
type: 'plain_text' | 'mrkdwn';
|
|
234
|
+
text: string;
|
|
235
|
+
emoji?: boolean;
|
|
236
|
+
verbatim?: boolean;
|
|
237
|
+
};
|
|
238
|
+
actions?: Button[];
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Slack `carousel` block payload. A horizontally scrollable group of
|
|
242
|
+
* 1-10 {@link CardBlock} elements. `slack-web-api-client` doesn't ship
|
|
243
|
+
* this type yet, so we declare it.
|
|
244
|
+
*/
|
|
245
|
+
interface CarouselBlock {
|
|
246
|
+
type: 'carousel';
|
|
247
|
+
elements: CardBlock[];
|
|
248
|
+
block_id?: string;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Sub-button used inside a {@link FeedbackButtonsElement}.
|
|
252
|
+
*/
|
|
253
|
+
interface FeedbackButtonSubobject {
|
|
254
|
+
text: {
|
|
255
|
+
type: 'plain_text';
|
|
256
|
+
text: string;
|
|
257
|
+
emoji?: boolean;
|
|
258
|
+
};
|
|
259
|
+
value: string;
|
|
260
|
+
accessibility_label?: string;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* `feedback_buttons` element. Pair of positive/negative buttons used
|
|
264
|
+
* inside a {@link ContextActionsBlock} (e.g. "Good Response" / "Bad
|
|
265
|
+
* Response" thumbs).
|
|
266
|
+
*/
|
|
267
|
+
interface FeedbackButtonsElement {
|
|
268
|
+
type: 'feedback_buttons';
|
|
269
|
+
positive_button: FeedbackButtonSubobject;
|
|
270
|
+
negative_button: FeedbackButtonSubobject;
|
|
271
|
+
action_id?: string;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Slack icon names valid on an {@link IconButtonElement}. Slack only
|
|
275
|
+
* ships `trash` today; widen as Slack adds more.
|
|
276
|
+
*/
|
|
277
|
+
type IconButtonIcon = 'trash';
|
|
278
|
+
/**
|
|
279
|
+
* `icon_button` element. Compact icon-with-label button used inside a
|
|
280
|
+
* {@link ContextActionsBlock} (e.g. a "Remove" trash-icon button).
|
|
281
|
+
*/
|
|
282
|
+
interface IconButtonElement {
|
|
283
|
+
type: 'icon_button';
|
|
284
|
+
icon: IconButtonIcon;
|
|
285
|
+
text: {
|
|
286
|
+
type: 'plain_text';
|
|
287
|
+
text: string;
|
|
288
|
+
emoji?: boolean;
|
|
289
|
+
};
|
|
290
|
+
action_id?: string;
|
|
291
|
+
value?: string;
|
|
292
|
+
accessibility_label?: string;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Element accepted by a {@link ContextActionsBlock}.
|
|
296
|
+
*/
|
|
297
|
+
type ContextActionsElement = FeedbackButtonsElement | IconButtonElement;
|
|
298
|
+
/**
|
|
299
|
+
* Slack `context_actions` block payload. Renders a row of contextual
|
|
300
|
+
* action buttons (1-5 elements) attached to a message. Only valid on
|
|
301
|
+
* the message surface; the validator already encodes that.
|
|
302
|
+
* `slack-web-api-client` doesn't ship this type yet, so we declare it.
|
|
303
|
+
*/
|
|
304
|
+
interface ContextActionsBlock {
|
|
305
|
+
type: 'context_actions';
|
|
306
|
+
elements: ContextActionsElement[];
|
|
307
|
+
block_id?: string;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Slack `input` block payload. Aliased to `ViewInputBlock` from
|
|
311
|
+
* `slack-web-api-client`, which is the superset that accepts every
|
|
312
|
+
* supported input element (including `rich_text_input` and `file_input`).
|
|
313
|
+
* Surface compatibility (input is valid on modal and home tab; some
|
|
314
|
+
* elements are modal-only) is enforced by the validator, not the type.
|
|
315
|
+
*/
|
|
316
|
+
type InputBlock = ViewInputBlock;
|
|
317
|
+
/**
|
|
318
|
+
* Header heading level shown in the preview. Slack's API has no
|
|
319
|
+
* `level` field on header blocks, so this is a builder-only extension
|
|
320
|
+
* that round-trips on the block payload but is otherwise cosmetic.
|
|
321
|
+
*/
|
|
322
|
+
type HeaderLevel = 1 | 2 | 3 | 4;
|
|
323
|
+
/**
|
|
324
|
+
* Header block as edited by the builder. Extends Slack's HeaderBlock
|
|
325
|
+
* with an optional {@link HeaderLevel}.
|
|
326
|
+
*/
|
|
327
|
+
type SupportedHeaderBlock = HeaderBlock & {
|
|
328
|
+
level?: HeaderLevel;
|
|
329
|
+
};
|
|
330
|
+
/**
|
|
331
|
+
* Discriminated union of supported block payload shapes.
|
|
332
|
+
* Subset of {@link AnyMessageBlock} from `slack-web-api-client`,
|
|
333
|
+
* plus a header `level` extension.
|
|
334
|
+
*/
|
|
335
|
+
type SupportedBlock = SectionBlock | SupportedHeaderBlock | DividerBlock | ContextBlock | ActionsBlock | ImageBlock | MarkdownBlock | RichTextBlock | TableBlock | AlertBlock | CardBlock | CarouselBlock | ContextActionsBlock | InputBlock;
|
|
336
|
+
/**
|
|
337
|
+
* A block as represented inside the builder's working state.
|
|
338
|
+
* `id` is an ephemeral client-side identifier used by DnD and selection.
|
|
339
|
+
* It is stripped before serialization to Slack.
|
|
340
|
+
*/
|
|
341
|
+
interface BuilderBlock {
|
|
342
|
+
id: string;
|
|
343
|
+
block: SupportedBlock;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Channel record returned by {@link BlockKitchenProps.loadChannels}.
|
|
347
|
+
*/
|
|
348
|
+
interface ChannelOption {
|
|
349
|
+
id: string;
|
|
350
|
+
name: string;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* User-token status returned by {@link BlockKitchenProps.loadSendAsUserStatus}.
|
|
354
|
+
* If `canSendAsUser` is false, `oauthUrl` is required so the UI can show a
|
|
355
|
+
* "Sign in with Slack" link.
|
|
356
|
+
*/
|
|
357
|
+
interface SendAsUserStatus {
|
|
358
|
+
canSendAsUser: boolean;
|
|
359
|
+
oauthUrl?: string;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Payload passed to {@link BlockKitchenProps.onSend}.
|
|
363
|
+
*/
|
|
364
|
+
interface SendPayload {
|
|
365
|
+
channelId: string;
|
|
366
|
+
blocks: SupportedBlock[];
|
|
367
|
+
sendAsUser: boolean;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Result returned from {@link BlockKitchenProps.onSend}.
|
|
371
|
+
* `error` is a human-readable message; the dialog renders it as-is.
|
|
372
|
+
*/
|
|
373
|
+
interface SendResult {
|
|
374
|
+
ok: boolean;
|
|
375
|
+
error?: string;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Hooks forwarded to `slack-blocks-to-jsx`'s `<Message>` so the consumer can
|
|
379
|
+
* resolve user mentions, channel mentions, custom emojis, and links to
|
|
380
|
+
* application-specific UI. See the upstream library for the full hook shape.
|
|
381
|
+
* Marked as `unknown`-keyed at this layer to avoid leaking the upstream
|
|
382
|
+
* library's internal types into our public API.
|
|
383
|
+
*/
|
|
384
|
+
type PreviewHooks = Record<string, unknown>;
|
|
385
|
+
/**
|
|
386
|
+
* Light or dark theme for the rendered Slack preview. Wired to
|
|
387
|
+
* `slack-blocks-to-jsx`'s `theme` prop and `data-theme` attribute.
|
|
388
|
+
*/
|
|
389
|
+
type PreviewTheme = 'light' | 'dark';
|
|
390
|
+
/**
|
|
391
|
+
* Which Slack surface the preview is approximating. Affects the
|
|
392
|
+
* chrome rendered around the block list (message header, modal frame,
|
|
393
|
+
* or app home tab).
|
|
394
|
+
*/
|
|
395
|
+
type PreviewSurface = 'message' | 'modal' | 'app_home';
|
|
396
|
+
/**
|
|
397
|
+
* A reusable block layout the user can apply as a starting point.
|
|
398
|
+
* Consumed by the standalone `<TemplatePicker>` component, which renders
|
|
399
|
+
* a categorized grid of template cards (modeled on Slack's own Block
|
|
400
|
+
* Kit Builder templates page) and emits the selected one. The picker
|
|
401
|
+
* is decoupled from {@link BlockKitchen} — wire `onSelect` to whatever
|
|
402
|
+
* state owns the draft blocks (e.g. lift `initialBlocks` into your own
|
|
403
|
+
* state and reset it from the handler).
|
|
404
|
+
*/
|
|
405
|
+
interface Template {
|
|
406
|
+
/** Stable identifier used as the React key and for persistence. */
|
|
407
|
+
id: string;
|
|
408
|
+
/** Display name shown on the template card. */
|
|
409
|
+
name: string;
|
|
410
|
+
/** Optional one-line description shown under the name on the card. */
|
|
411
|
+
description?: string;
|
|
412
|
+
/**
|
|
413
|
+
* Which Slack surface this template was authored for. The picker can
|
|
414
|
+
* filter to a single surface via its `surface` prop; the field is also
|
|
415
|
+
* available to consumers who render templates in their own UI.
|
|
416
|
+
*/
|
|
417
|
+
surface: PreviewSurface;
|
|
418
|
+
/**
|
|
419
|
+
* Optional category name used to group templates into sections in the
|
|
420
|
+
* picker (e.g. `"Approvals"`, `"Notifications"`, `"Onboarding"`).
|
|
421
|
+
* Templates without a category fall into a trailing "Other" section
|
|
422
|
+
* when at least one other template specifies one; otherwise the grid
|
|
423
|
+
* is rendered flat without section headers.
|
|
424
|
+
*/
|
|
425
|
+
category?: string;
|
|
426
|
+
/** Block payloads applied to the draft when the template is selected. */
|
|
427
|
+
blocks: SupportedBlock[];
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Props for the top-level {@link BlockKitchen} component.
|
|
431
|
+
* The package is integration-agnostic: every I/O concern is brokered
|
|
432
|
+
* through these props. The component never makes a network call itself.
|
|
433
|
+
*/
|
|
434
|
+
interface BlockKitchenProps {
|
|
435
|
+
/**
|
|
436
|
+
* Workspace name shown in the preview chrome to mimic a Slack message header.
|
|
437
|
+
* Cosmetic only.
|
|
438
|
+
*/
|
|
439
|
+
workspaceName?: string;
|
|
440
|
+
/**
|
|
441
|
+
* Initial draft blocks. If omitted the builder starts empty.
|
|
442
|
+
*/
|
|
443
|
+
initialBlocks?: SupportedBlock[];
|
|
444
|
+
/**
|
|
445
|
+
* Fires whenever the draft state changes. Use to persist the draft
|
|
446
|
+
* (URL search param, localStorage, etc).
|
|
447
|
+
*/
|
|
448
|
+
onChange?: (blocks: SupportedBlock[]) => void;
|
|
449
|
+
/**
|
|
450
|
+
* Optional hooks forwarded to the underlying `<Message>` component for
|
|
451
|
+
* resolving user / channel / emoji directives. If omitted, those
|
|
452
|
+
* directives render with the library's defaults.
|
|
453
|
+
*/
|
|
454
|
+
previewHooks?: PreviewHooks;
|
|
455
|
+
/**
|
|
456
|
+
* Returns channels available to send to. Called when the send dialog opens.
|
|
457
|
+
*/
|
|
458
|
+
loadChannels: () => Promise<ChannelOption[]>;
|
|
459
|
+
/**
|
|
460
|
+
* Returns whether the current user can post as themselves and, if not, an
|
|
461
|
+
* OAuth URL to start the install flow.
|
|
462
|
+
*/
|
|
463
|
+
loadSendAsUserStatus: () => Promise<SendAsUserStatus>;
|
|
464
|
+
/**
|
|
465
|
+
* Called when the user submits the send dialog. Should return
|
|
466
|
+
* `{ ok: true }` on success or `{ ok: false, error }` on failure.
|
|
467
|
+
*/
|
|
468
|
+
onSend: (payload: SendPayload) => Promise<SendResult>;
|
|
469
|
+
/**
|
|
470
|
+
* The palette shown on the left-hand side. When omitted, the built-in
|
|
471
|
+
* `defaultPalette` is used. Pass a custom array (typically built by
|
|
472
|
+
* spreading and filtering `defaultPalette`, plus your own sections) to
|
|
473
|
+
* curate the variants and pre-configured presets your users can drag
|
|
474
|
+
* onto the surface. An empty array renders an empty palette.
|
|
475
|
+
*
|
|
476
|
+
* The `defaultPalette` mirrors Slack's Block Kit Builder, which
|
|
477
|
+
* consolidates related variants into single showcase entries (e.g.
|
|
478
|
+
* **All selects** is one `actions` block with every select type). If
|
|
479
|
+
* you previously relied on the long flat list of single-element
|
|
480
|
+
* `input` variants (`input_users_select`, `input_multi_users_select`,
|
|
481
|
+
* `input_radio_buttons`, etc.), import `legacyInputVariants` and
|
|
482
|
+
* spread them into a custom section. The modal-only `alert` block was
|
|
483
|
+
* also dropped from the default; reach for `extraAlertVariant` to
|
|
484
|
+
* keep it.
|
|
485
|
+
*
|
|
486
|
+
* Variant ids must be unique across the array — the drag-drop lookup
|
|
487
|
+
* keys by id, so duplicates would shadow each other. The palette is
|
|
488
|
+
* also expected to be referentially stable across renders (wrap in
|
|
489
|
+
* `useMemo` or define at module scope).
|
|
490
|
+
*/
|
|
491
|
+
palette?: readonly PaletteSection[];
|
|
492
|
+
/**
|
|
493
|
+
* Whether the palette renders a quick-search input above the section
|
|
494
|
+
* list. Defaults to `true`. Set `false` for compact palettes (e.g.
|
|
495
|
+
* when you've passed a small custom `palette`) where scanning by eye
|
|
496
|
+
* is faster than typing.
|
|
497
|
+
*/
|
|
498
|
+
showPaletteSearch?: boolean;
|
|
499
|
+
/**
|
|
500
|
+
* Placeholder text for the palette search input. Defaults to
|
|
501
|
+
* `'Search blocks…'`. Useful for localization.
|
|
502
|
+
*/
|
|
503
|
+
paletteSearchPlaceholder?: string;
|
|
504
|
+
/**
|
|
505
|
+
* Controls which palette section headers are expanded on first paint.
|
|
506
|
+
* - `true` (default) — every section starts open
|
|
507
|
+
* - `false` — every section starts closed (Slack-style)
|
|
508
|
+
* - array of section names — only sections whose `name` is in the
|
|
509
|
+
* list start open (e.g. `['Section', 'Actions']`); matched
|
|
510
|
+
* case-sensitively against `PaletteSection.name` so consumer-defined
|
|
511
|
+
* sections are addressable too.
|
|
512
|
+
*
|
|
513
|
+
* After mount, each section owns its own collapse state, so users can
|
|
514
|
+
* still toggle headers freely. An active palette search overrides the
|
|
515
|
+
* collapse state for matching sections.
|
|
516
|
+
*/
|
|
517
|
+
defaultOpenSections?: boolean | readonly string[];
|
|
518
|
+
/**
|
|
519
|
+
* Which Slack preview surfaces the toolbar exposes. Defaults to
|
|
520
|
+
* `['message']`, which locks the preview to Message and hides the
|
|
521
|
+
* surface dropdown. Pass two or more to show the dropdown with those
|
|
522
|
+
* options; the first entry becomes the initial selection.
|
|
523
|
+
*/
|
|
524
|
+
allowedSurfaces?: readonly PreviewSurface[];
|
|
525
|
+
/**
|
|
526
|
+
* Whether the toolbar exposes the light/dark theme dropdown.
|
|
527
|
+
* Defaults to `true`. When `false`, the theme is locked to
|
|
528
|
+
* {@link PreviewTheme} `'light'`.
|
|
529
|
+
*/
|
|
530
|
+
showThemeControl?: boolean;
|
|
531
|
+
/**
|
|
532
|
+
* Customizes or hides the "Docs" link in the toolbar.
|
|
533
|
+
* - `undefined` (default) — links to the Slack Block Kit reference docs
|
|
534
|
+
* - `false` — hides the link entirely
|
|
535
|
+
* - `{ href }` — overrides the URL (label defaults to `'Docs'`)
|
|
536
|
+
* - `{ href, label }` — overrides both
|
|
537
|
+
*
|
|
538
|
+
* Useful when embedding Block Kitchen inside a product that ships its
|
|
539
|
+
* own documentation, or for localizing the label.
|
|
540
|
+
*/
|
|
541
|
+
docsLink?: false | {
|
|
542
|
+
href?: string;
|
|
543
|
+
label?: string;
|
|
544
|
+
};
|
|
545
|
+
/**
|
|
546
|
+
* Initial preview theme. Defaults to `'light'`. Pass the host app's
|
|
547
|
+
* current theme (e.g. from `next-themes` or your own theme hook) so
|
|
548
|
+
* the preview opens matched to the consuming app's appearance. The
|
|
549
|
+
* user can still override via the toolbar dropdown if
|
|
550
|
+
* {@link BlockKitchenProps.showThemeControl} is `true`.
|
|
551
|
+
*/
|
|
552
|
+
defaultPreviewTheme?: PreviewTheme;
|
|
553
|
+
/**
|
|
554
|
+
* Branding tokens applied to the builder chrome (toolbar, palette,
|
|
555
|
+
* popover editors, send dialog, JSON drawer, issues sheet). The
|
|
556
|
+
* Slack preview itself is rendered by `slack-blocks-to-jsx` with its
|
|
557
|
+
* native Slack styling regardless — use {@link BlockKitchenProps.defaultPreviewTheme}
|
|
558
|
+
* for preview light/dark.
|
|
559
|
+
*
|
|
560
|
+
* Pass a preset name as sugar for `{ preset }`, or an object with
|
|
561
|
+
* `tokens` (applied in both modes) and optional `light`/`dark`
|
|
562
|
+
* overrides. The existing CSS-variable override path (importing the
|
|
563
|
+
* stylesheet and setting `--primary`, etc. on your own selector)
|
|
564
|
+
* continues to work; this prop is a typed shortcut on top of it.
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* ```tsx
|
|
568
|
+
* <BlockKitchen
|
|
569
|
+
* theme={{
|
|
570
|
+
* tokens: { primary: '262 83% 58%', radius: '0.75rem' },
|
|
571
|
+
* dark: { primary: '263 70% 65%' }
|
|
572
|
+
* }}
|
|
573
|
+
* {...rest}
|
|
574
|
+
* />
|
|
575
|
+
* ```
|
|
576
|
+
*/
|
|
577
|
+
theme?: BrandTheme | BrandPreset;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Top-level Slack Block Kit builder component.
|
|
582
|
+
* Renders the toolbar, palette, preview surface, popover editors, send
|
|
583
|
+
* dialog, and View-JSON drawer. Integration-agnostic: all I/O is brokered
|
|
584
|
+
* through props.
|
|
585
|
+
* @param props - {@link BlockKitchenProps}
|
|
586
|
+
* @returns the rendered Block Kit Builder
|
|
587
|
+
*/
|
|
588
|
+
declare function BlockKitchen(props: BlockKitchenProps): react_jsx_runtime.JSX.Element;
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Standalone, page-sized picker that displays {@link Template}s as a
|
|
592
|
+
* grid of cards with live block previews, organized into category
|
|
593
|
+
* sections — modeled on Slack's own Block Kit Builder templates page.
|
|
594
|
+
* Pure UI: wire `onSelect` to whatever state owns the draft blocks
|
|
595
|
+
* (e.g. lifted `initialBlocks` on {@link BlockKitchen}, your own
|
|
596
|
+
* store, a router-driven URL param).
|
|
597
|
+
*
|
|
598
|
+
* Compose alongside {@link BlockKitchen} however fits your layout
|
|
599
|
+
* (route, modal, slide-over, tab). This component intentionally does
|
|
600
|
+
* not own its own dialog so the consumer controls placement and
|
|
601
|
+
* dismissal.
|
|
602
|
+
*
|
|
603
|
+
* @param props - picker props
|
|
604
|
+
* @param props.templates - templates to show. Order is preserved within
|
|
605
|
+
* each category section.
|
|
606
|
+
* @param props.onSelect - called when the user clicks a template card.
|
|
607
|
+
* @param props.surface - optional surface filter. When set, only
|
|
608
|
+
* templates whose {@link Template.surface} matches are shown.
|
|
609
|
+
* @param props.theme - preview theme used inside the card thumbnails.
|
|
610
|
+
* Defaults to `'light'`.
|
|
611
|
+
* @param props.heading - optional heading rendered above the grid. When
|
|
612
|
+
* omitted, no heading is rendered.
|
|
613
|
+
* @param props.emptyLabel - text shown when no templates match the
|
|
614
|
+
* surface filter. Defaults to `"No templates available."`.
|
|
615
|
+
* @param props.className - additional classes merged onto the root.
|
|
616
|
+
*/
|
|
617
|
+
declare function TemplatePicker({ templates, onSelect, surface, theme, heading, emptyLabel, className }: {
|
|
618
|
+
templates: readonly Template[];
|
|
619
|
+
onSelect: (template: Template) => void;
|
|
620
|
+
surface?: PreviewSurface;
|
|
621
|
+
theme?: PreviewTheme;
|
|
622
|
+
heading?: string;
|
|
623
|
+
emptyLabel?: string;
|
|
624
|
+
className?: string;
|
|
625
|
+
}): react_jsx_runtime.JSX.Element;
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Strip builder-only fields from blocks so they conform to Slack's
|
|
629
|
+
* Block Kit schema, and scrub dangerous URI schemes from any
|
|
630
|
+
* `url`/`image_url` fields. Currently removes the cosmetic `level`
|
|
631
|
+
* field from header blocks (a builder-only extension Slack would
|
|
632
|
+
* reject) and routes every URL/image-url through the allowlist in
|
|
633
|
+
* `lib/url-safety.ts` so a payload that round-trips through the
|
|
634
|
+
* builder cannot carry `javascript:`/`data:text/html` URIs to a
|
|
635
|
+
* downstream consumer or to the Slack API.
|
|
636
|
+
* @param blocks - the working draft blocks
|
|
637
|
+
* @returns blocks with builder-only fields removed and URLs scrubbed
|
|
638
|
+
*/
|
|
639
|
+
declare function toSlackBlocks(blocks: SupportedBlock[]): SupportedBlock[];
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Encodes a block list to a base64url string suitable for use as a URL
|
|
643
|
+
* search param. The consumer chooses where to put it (search param, hash,
|
|
644
|
+
* localStorage, etc).
|
|
645
|
+
* Returns an empty string for an empty list so the consumer can omit the
|
|
646
|
+
* param entirely.
|
|
647
|
+
* @param blocks - the blocks to encode
|
|
648
|
+
* @returns base64url-encoded JSON, or '' if blocks is empty
|
|
649
|
+
*/
|
|
650
|
+
declare function encodeBlocksToString(blocks: SupportedBlock[]): string;
|
|
651
|
+
/**
|
|
652
|
+
* Decodes a string produced by {@link encodeBlocksToString} back to a
|
|
653
|
+
* block list. Returns null on any decode/parse error.
|
|
654
|
+
* @param encoded - the encoded string
|
|
655
|
+
* @returns decoded blocks, or null if input is empty/invalid
|
|
656
|
+
*/
|
|
657
|
+
declare function decodeBlocksFromString(encoded: string | undefined | null): SupportedBlock[] | null;
|
|
658
|
+
|
|
659
|
+
export { type AlertBlock, type AlertLevel, BlockKitchen, type BlockKitchenProps, type BrandPreset, type BrandTheme, type BrandTokens, type BuilderBlock, type CardBlock, type CarouselBlock, type ChannelOption, type ContextActionsBlock, type ContextActionsElement, type FeedbackButtonSubobject, type FeedbackButtonsElement, type HeaderLevel, type IconButtonElement, type IconButtonIcon, type InputBlock, type MarkdownBlock, type PaletteSection, type PaletteVariant, type PreviewHooks, type PreviewSurface, type PreviewTheme, type SendAsUserStatus, type SendPayload, type SendResult, type SupportedBlock, type SupportedBlockType, type SupportedHeaderBlock, type TableBlock, type TableCell, type TableColumnSetting, type Template, TemplatePicker, decodeBlocksFromString, defaultPalette, encodeBlocksToString, extraAlertVariant, legacyInputVariants, toSlackBlocks };
|