@sanity/block-insert-picker 0.0.1 → 1.0.1

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sanity.io
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,45 +1,152 @@
1
1
  # @sanity/block-insert-picker
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
4
-
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
6
-
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
8
-
9
- ## Purpose
10
-
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@sanity/block-insert-picker`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
15
-
16
- ## What is OIDC Trusted Publishing?
17
-
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
19
-
20
- ## Setup Instructions
21
-
22
- To properly configure OIDC trusted publishing for this package:
23
-
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
28
-
29
- ## DO NOT USE THIS PACKAGE
30
-
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
-
37
- ## More Information
38
-
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
-
43
- ---
44
-
45
- **Maintained for OIDC setup purposes only**
3
+ Slash-command block-insert picker and markdown input rules for Portable Text fields in Sanity Studio.
4
+
5
+ Type `/` at the start of a line (or press `Cmd`/`Ctrl` + `/` anywhere) to open a caret-anchored menu of every object block the field's schema allows — searchable by title, trigger, and alias keywords, grouped into sections, keyboard-first. Selecting an item resolves the member type's initial value, inserts the block as a single undo step, and opens it for editing. Optional markdown input rules give the heaviest block types an even faster path, for example ` ```ts ` + space straight into a code block.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ npm install @sanity/block-insert-picker
11
+ ```
12
+
13
+ Requires `sanity` v5.6 or later.
14
+
15
+ ## Usage
16
+
17
+ Attach the picker to a Portable Text array type via `components.portableText.plugins`. Zero config is the intended call — the picker detects the array it is mounted on and derives its items from that array's members, so it only ever offers blocks the field accepts:
18
+
19
+ ```ts
20
+ import {blockInsertPicker} from '@sanity/block-insert-picker'
21
+ import {defineType} from 'sanity'
22
+
23
+ export const content = defineType({
24
+ name: 'content',
25
+ type: 'array',
26
+ of: [{type: 'block'}, {type: 'callout'}, {type: 'codeBlock'}],
27
+ components: {
28
+ portableText: {
29
+ plugins: blockInsertPicker(),
30
+ },
31
+ },
32
+ })
33
+ ```
34
+
35
+ Titles, icons, and descriptions come from each member's schema type (with the same fallbacks Studio's built-in insert menu uses), and detection handles aliased members (`{type: 'image', name: 'photo'}`) and inline-declared members with full fidelity.
36
+
37
+ When an array derives zero items — its only member is the text block — and no `inputRules` are configured, the picker disables itself: no behaviors register and `/` inserts plain text (with a `console.warn` in dev builds). Items appended via `resolveItems` (or configured `inputRules`) re-enable it, so a custom-command-only picker on a text-only field works.
38
+
39
+ ### Curating items
40
+
41
+ The optional `items` metadata curates the derived items — slash triggers, alias keywords, section grouping, badges, per-item visibility, and rank (array order). Entries match a member's name or any name in its resolved type chain, and a curated `description` wins over the schema type's:
42
+
43
+ ```ts
44
+ blockInsertPicker({
45
+ items: [
46
+ {
47
+ type: 'codeBlock',
48
+ trigger: '/code',
49
+ keywords: ['snippet', 'syntax'],
50
+ group: 'Code',
51
+ description: 'Syntax-highlighted code sample',
52
+ },
53
+ {
54
+ type: 'callout',
55
+ trigger: '/callout',
56
+ keywords: ['note', 'warning', 'tip'],
57
+ group: 'Callouts',
58
+ },
59
+ {type: 'legacyEmbed', hidden: true},
60
+ ],
61
+ })
62
+ ```
63
+
64
+ Members without an entry still get picker items, appended in schema order. Entries whose `type` matches no member log a dev-mode warning.
65
+
66
+ ### Presets for well-known blocks
67
+
68
+ Members whose type resolves to a well-known name — `image`, `file`, `code` (`@sanity/code-input`), `table`, `color`, `latex`, `mux.video`, `sanity.video` — get default triggers and search keywords out of the box. Presets never add items, never group, and always lose to your `items` metadata. Opt out with `presets: false`.
69
+
70
+ ### Markdown input rules
71
+
72
+ `inputRules` adds typed transforms that replace markdown-style text with an inserted block — one undo step, and the block opens for editing just like a picker insert. Rules are opt-in; two factories cover the common cases:
73
+
74
+ ````ts
75
+ import {blockInsertPicker, blockquoteRule, codeFenceRule} from '@sanity/block-insert-picker'
76
+
77
+ blockInsertPicker({
78
+ inputRules: [
79
+ // "```lang" + space inserts a code block with the language resolved
80
+ codeFenceRule({
81
+ blockType: 'codeBlock',
82
+ defaultLanguage: 'typescript',
83
+ languages: [
84
+ {value: 'typescript', aliases: ['ts'], filename: 'index.ts'},
85
+ {value: 'javascript', aliases: ['js'], filename: 'index.js'},
86
+ ],
87
+ createValue: ({language, filename}) => ({
88
+ language,
89
+ ...(filename ? {filename} : {}),
90
+ }),
91
+ }),
92
+ // "> " at the start of a block inserts a quote/callout
93
+ blockquoteRule({
94
+ blockType: 'callout',
95
+ createValue: () => ({tone: 'info'}),
96
+ }),
97
+ ],
98
+ })
99
+ ````
100
+
101
+ `createValue` builds the inserted block's fields synchronously from the resolved fence language (and optional tab filename), shaped for **your** schema. Each rule's `blockType` resolves against the array's members by name or resolved type chain (aliased members included; the inserted `_type` is always the member name); rules matching nothing are ignored. For fully custom transforms, pass a `{pattern, blockType, buildValue}` config directly. A ready-made `wellKnownInputRules` bundle covers `@sanity/code-input`'s `code` type: `inputRules: [...wellKnownInputRules]`.
102
+
103
+ ### Reacting to inserts
104
+
105
+ `onInsert` fires after every successful insert, from either path:
106
+
107
+ ```ts
108
+ blockInsertPicker({
109
+ onInsert: ({blockKey, blockType, via, mode, query}) => {
110
+ // via is 'picker' or 'inputRule'; mode and query are picker-only
111
+ },
112
+ })
113
+ ```
114
+
115
+ ### Escape hatches
116
+
117
+ For anything the declarative options don't cover:
118
+
119
+ - **`resolveItems`** — a function over the fully-presented item list: reorder, remove, relabel, or append items. Appended items can carry a `custom` action that runs your code instead of inserting a block:
120
+
121
+ ```ts
122
+ blockInsertPicker({
123
+ resolveItems: (items, {schemaType}) => [
124
+ ...items,
125
+ {
126
+ id: 'ai-draft',
127
+ title: 'Draft with AI',
128
+ action: {type: 'custom', onSelect: ({editor}) => startDraft(editor)},
129
+ },
130
+ ],
131
+ })
132
+ ```
133
+
134
+ - **`filter`** — replaces the built-in matching (case-insensitive substring over title, keywords, and description, plus trigger prefixes). It receives the bare query in both modes; the slash-mode `/` prefix is stripped.
135
+ - **`labels`** — overrides any user-facing string in the picker chrome (header, empty state, footer hints, error toast), for reworded or translated UI.
136
+ - **`shortcut: false`** — disables the `Cmd`/`Ctrl` + `/` shortcut; `openOnInsert: false` — keeps inserted blocks closed (also available per item via metadata).
137
+ - **`BlockInsertPicker` / `MarkdownInputRules`** — the underlying components, exported for hosts composing their own `components.portableText.plugins` chain, along with the pure `derivePickerItems` and `filterPickerItems` utilities.
138
+ - **`arrayTypeName`** — names the array type explicitly, for environments where the member-schema context is unavailable. Normally unnecessary.
139
+
140
+ ## Keyboard reference
141
+
142
+ | Key | Action |
143
+ | ------------------ | -------------------------------------------------- |
144
+ | `/` at line start | Open the picker; keep typing to filter |
145
+ | `Cmd`/`Ctrl` + `/` | Open the picker anywhere; type to filter privately |
146
+ | `↑` / `↓` | Move the highlight |
147
+ | `Enter` | Insert the highlighted block |
148
+ | `Escape` | Dismiss |
149
+
150
+ ## License
151
+
152
+ [MIT](LICENSE) © Sanity.io
@@ -0,0 +1,385 @@
1
+ import { Editor } from "@portabletext/editor";
2
+ import { ComponentType } from "react";
3
+ import { ArraySchemaType, ObjectSchemaType, PortableTextPluginsProps } from "sanity";
4
+ import "@portabletext/plugin-input-rule";
5
+ /**
6
+ * Every user-facing string in the picker chrome, centralized so hosts can
7
+ * translate or reword them via the `labels` option (the same pattern
8
+ * `@sanity/insert-menu` uses for its label overrides). Item titles and
9
+ * descriptions are schema/metadata content, not chrome — localize those
10
+ * through `items` or `resolveItems` instead.
11
+ */
12
+ type BlockInsertPickerLabels = {
13
+ /** Popover header; also the listbox aria-label. */
14
+ title: string;
15
+ /** Empty state; `{query}` is replaced with the typed filter text. */
16
+ noMatches: string;
17
+ /**
18
+ * Screen-reader position announcement for the highlighted row; `{index}`
19
+ * and `{count}` are replaced with the 1-based position and list length.
20
+ */
21
+ positionAnnouncement: string;
22
+ /**
23
+ * Section header for items without a `group`, shown only when grouped
24
+ * sections are also present.
25
+ */
26
+ ungroupedSection: string;
27
+ /** Footer legend verbs. */
28
+ footerNavigate: string;
29
+ footerInsert: string;
30
+ footerDismiss: string;
31
+ footerAnywhere: string;
32
+ /** Toast title when resolving a block's initial value fails. */
33
+ insertError: string;
34
+ /**
35
+ * Toast description when the block the picker was anchored to is deleted
36
+ * before the insert completes.
37
+ */
38
+ insertAnchorRemoved: string;
39
+ };
40
+ /**
41
+ * Emitted after a block lands in the document, whether via picker selection
42
+ * or a markdown input rule. The public seam for hosts that need to react to
43
+ * inserts (analytics, custom focus handling) without reaching into Studio
44
+ * internals the way the built-in open-on-insert does (see openBlockOnInsert).
45
+ */
46
+ type PickerInsertEvent = {
47
+ blockKey: string;
48
+ blockType: string;
49
+ via: 'inputRule' | 'picker';
50
+ /** How the picker was opened; only present when `via` is `'picker'`. */
51
+ mode?: PickerMode;
52
+ /** The filter query at select time; only present when `via` is `'picker'`. */
53
+ query?: string;
54
+ };
55
+ type PickerItem = {
56
+ id: string;
57
+ trigger?: string;
58
+ title: string;
59
+ /**
60
+ * One-line explanation shown under the title. Curated metadata wins over
61
+ * the member schema type's own `description` — curation is the more
62
+ * specific intent (see resolveItemPresentation).
63
+ */
64
+ description?: string;
65
+ /**
66
+ * Category label used to partition the menu into sections. Items without a
67
+ * group render in a single unlabelled list (e.g. a curated `items` prop).
68
+ */
69
+ group?: string;
70
+ icon?: ComponentType;
71
+ keywords?: readonly string[];
72
+ /** Short keyboard-style hint rendered at the row's trailing edge. */
73
+ badge?: string;
74
+ /** Per-item override of the plugin-level `openOnInsert` default. */
75
+ openOnInsert?: boolean;
76
+ action: PickerItemAction;
77
+ };
78
+ /**
79
+ * What selecting an item does. An open union: further named actions (for
80
+ * example setting a text style) can be added without a breaking change.
81
+ * `custom` items never insert anything themselves — the host's `onSelect`
82
+ * runs with the editor after the picker closes and the typed query text
83
+ * (slash mode) has been cleaned up.
84
+ */
85
+ type PickerItemAction = {
86
+ type: 'custom';
87
+ onSelect: (context: PickerActionContext) => void;
88
+ } | {
89
+ type: 'insertBlock';
90
+ blockType: string;
91
+ };
92
+ /** Handed to a `custom` item's `onSelect` when the item is chosen. */
93
+ interface PickerActionContext {
94
+ editor: Editor;
95
+ closePicker: () => void;
96
+ }
97
+ /**
98
+ * Host-supplied curation for schema-derived picker items, keyed by member
99
+ * type name (falling back to a name anywhere in the member's resolved type
100
+ * chain, so `{type: 'image', name: 'photo'}` matches both `photo` and
101
+ * `image` — the member name wins when both have entries): slash trigger,
102
+ * alias keywords, section grouping, badge, visibility, per-item
103
+ * open-on-insert, and description. Array position is the sort rank — members
104
+ * without an entry still get picker items, appended after the ranked ones in
105
+ * schema order.
106
+ */
107
+ type PickerItemMetadata = {
108
+ type: string;
109
+ trigger?: string;
110
+ keywords?: readonly string[];
111
+ group?: string;
112
+ description?: string;
113
+ /** Short keyboard-style hint rendered at the row's trailing edge. */
114
+ badge?: string;
115
+ /** Removes the derived item from the picker without touching the schema. */
116
+ hidden?: boolean;
117
+ /** Per-item override of the plugin-level `openOnInsert` default. */
118
+ openOnInsert?: boolean;
119
+ };
120
+ /**
121
+ * The schema surroundings picker items derive from: the Portable Text array
122
+ * type itself and its insertable (non-text-block) member types. Sourced from
123
+ * Studio's member-schema context when available, or resolved from an
124
+ * explicit `arrayTypeName` otherwise (see memberSchemaTypes.ts).
125
+ */
126
+ interface PickerItemsContext {
127
+ schemaType: ArraySchemaType;
128
+ memberTypes: readonly ObjectSchemaType[];
129
+ }
130
+ /**
131
+ * Programmatic escape hatch over the derived item list: reorder, remove,
132
+ * relabel, or append items (including `custom`-action items) after schema
133
+ * derivation, presets, and `items` metadata have been applied.
134
+ */
135
+ type PickerItemsResolver = (items: readonly PickerItem[], context: PickerItemsContext) => readonly PickerItem[];
136
+ type PickerMode = 'shortcut' | 'slash';
137
+ type BlockInsertPickerProps = {
138
+ /**
139
+ * Per-member curation (trigger, keywords, group, description, badge,
140
+ * hidden, openOnInsert) merged into the items derived from the array's
141
+ * members; array order is the rank. Members without an entry still get
142
+ * items, in schema order.
143
+ */
144
+ items?: readonly PickerItemMetadata[];
145
+ /**
146
+ * Escape hatch: names the portable-text array type to resolve items from
147
+ * when Studio's member-schema context is unavailable. With the context
148
+ * present (any supported sanity version) this is ignored — the containing
149
+ * array and its members are detected automatically.
150
+ */
151
+ arrayTypeName?: string;
152
+ /**
153
+ * Programmatic seam over the derived-and-curated item list: reorder,
154
+ * remove, relabel, or append items (including `custom`-action items).
155
+ */
156
+ resolveItems?: PickerItemsResolver;
157
+ /**
158
+ * Replaces the built-in matching (see filterPickerItems). Receives the
159
+ * bare query in both modes — the slash-mode "/" prefix is stripped.
160
+ */
161
+ filter?: (items: readonly PickerItem[], query: string) => readonly PickerItem[];
162
+ /** Overrides for the picker chrome's user-facing strings. */
163
+ labels?: Partial<BlockInsertPickerLabels>;
164
+ /** Notified after each successful insert, alongside open-on-insert. */
165
+ onInsert?: (event: PickerInsertEvent) => void;
166
+ /**
167
+ * Whether an inserted block opens for editing (default true). Items can
168
+ * override per member via their metadata's `openOnInsert`.
169
+ */
170
+ openOnInsert?: boolean;
171
+ /** Whether Cmd/Ctrl+/ opens the picker (default true). */
172
+ shortcut?: boolean;
173
+ /**
174
+ * Whether well-known block types (image, file, code, table, ...) get
175
+ * default triggers and keywords when the host's `items` doesn't cover
176
+ * them (default true). See standardBlockPresets.
177
+ */
178
+ presets?: boolean;
179
+ };
180
+ declare function BlockInsertPicker({ arrayTypeName, filter, items, labels: labelOverrides, onInsert, openOnInsert, presets, resolveItems, shortcut }: BlockInsertPickerProps): import("react").JSX.Element | null;
181
+ /**
182
+ * Derives picker items from a portable-text array's insertable member types
183
+ * (see PickerItemsContext), so the picker automatically covers every object
184
+ * block the schema allows. The optional metadata list curates triggers,
185
+ * keywords, grouping, badges, visibility, and descriptions per member type;
186
+ * its array order is the sort rank (see PickerItemMetadata). Titles and
187
+ * icons intentionally stay unresolved here: BlockInsertPicker resolves
188
+ * presentation from the member schema type, which carries member-level
189
+ * config (a member-specific icon, a per-member title override).
190
+ */
191
+ declare function derivePickerItems(context: PickerItemsContext, metadata?: readonly PickerItemMetadata[]): PickerItem[];
192
+ declare function filterPickerItems(items: readonly PickerItem[], query: string): readonly PickerItem[];
193
+ /**
194
+ * Generic machinery for markdown-style input rules that replace typed text
195
+ * with an inserted object block, complementing the slash/⌘+/ picker with a
196
+ * keyboard-only path that mirrors what writers already type in markdown.
197
+ *
198
+ * The rules run through `@portabletext/plugin-input-rule` (see
199
+ * `markdownInputRules.tsx`), which applies the delete + insert as a single
200
+ * behavior action set — so each transform is one undo step.
201
+ *
202
+ * Block values are built synchronously via each config's `buildValue` rather
203
+ * than resolved from the schema's async initial values: the insert has to
204
+ * happen inside the rule's action set for that single-undo guarantee to hold,
205
+ * so anything the writer would otherwise have to fill in (language, filename,
206
+ * callout type) is seeded from the host's rule config.
207
+ */
208
+ type KeyGenerator = () => string;
209
+ /**
210
+ * One markdown input rule: when `pattern` matches the block text, the match
211
+ * is deleted and a block of `blockType` is inserted in its place, carrying
212
+ * the fields `buildValue` returns. `buildValue` must stay synchronous so the
213
+ * delete + insert land in one action set (one undo step).
214
+ */
215
+ type MarkdownInputRuleConfig = {
216
+ pattern: RegExp;
217
+ blockType: string;
218
+ buildValue: (context: {
219
+ matchText: string;
220
+ keyGenerator: KeyGenerator;
221
+ }) => Record<string, unknown>;
222
+ };
223
+ declare const CODE_FENCE_PATTERN: RegExp;
224
+ declare const BLOCKQUOTE_PATTERN: RegExp;
225
+ /**
226
+ * A row of a code-fence language table: the stored `value`, the markdown
227
+ * fence tokens that should resolve to it, and an optional tab filename.
228
+ */
229
+ type LanguageEntry = {
230
+ value: string;
231
+ aliases?: readonly string[];
232
+ filename?: string;
233
+ };
234
+ /** Sugar: a blockquote rule ("> " at the start of a block) for `blockType`. */
235
+ declare function blockquoteRule(options: {
236
+ blockType: string;
237
+ createValue?: (context: {
238
+ keyGenerator: KeyGenerator;
239
+ }) => Record<string, unknown>;
240
+ }): MarkdownInputRuleConfig;
241
+ /**
242
+ * Sugar: a code-fence rule ("```lang␣") for `blockType`. The language table
243
+ * resolves fence tokens (aliases included) to the values the block's language
244
+ * selector stores, plus an optional filename; tokens outside the table pass
245
+ * through as typed so nothing the writer means is lost. `createValue` turns
246
+ * the resolved language and filename into the block's fields.
247
+ */
248
+ declare function codeFenceRule(options: {
249
+ blockType: string;
250
+ languages?: readonly LanguageEntry[];
251
+ defaultLanguage?: string;
252
+ createValue: (context: {
253
+ filename: string | undefined;
254
+ keyGenerator: KeyGenerator;
255
+ language: string | undefined;
256
+ }) => Record<string, unknown>;
257
+ }): MarkdownInputRuleConfig;
258
+ /** Strips the leading "```" fence and surrounding whitespace from a match. */
259
+ declare function fenceLanguageFromMatch(matchText: string): string;
260
+ /**
261
+ * Resolves a typed fence token against a language table: a canonical value,
262
+ * an alias (`py`→python, `yml`→yaml), or — for anything the table doesn't
263
+ * know — the token as typed. An empty token yields `defaultLanguage`.
264
+ */
265
+ declare function normalizeFenceLanguage(raw: string, languages: readonly LanguageEntry[], defaultLanguage?: string): string | undefined;
266
+ type MarkdownInputRulesProps = {
267
+ /**
268
+ * Escape hatch: names the portable-text array type when Studio's
269
+ * member-schema context is unavailable (see BlockInsertPickerProps).
270
+ * Rules are only enabled for block types the array actually allows.
271
+ */
272
+ arrayTypeName?: string;
273
+ /** The markdown transforms to enable (see inputRules.ts). */
274
+ rules: readonly MarkdownInputRuleConfig[];
275
+ /** Notified after each successful insert, alongside open-on-insert. */
276
+ onInsert?: (event: PickerInsertEvent) => void;
277
+ /** Whether an inserted block opens for editing (default true). */
278
+ openOnInsert?: boolean;
279
+ };
280
+ /**
281
+ * Mounts markdown input rules on the PTE and opens each inserted block for
282
+ * editing once its member item mounts — the same open-on-insert behavior the
283
+ * picker uses, so a fenced code block lands ready to type into.
284
+ */
285
+ declare function MarkdownInputRules({ arrayTypeName, onInsert, openOnInsert, rules }: MarkdownInputRulesProps): null;
286
+ interface BlockInsertPickerConfig {
287
+ /**
288
+ * Per-member curation (slash trigger, alias keywords, section grouping,
289
+ * description, badge, visibility, per-item open-on-insert) merged into the
290
+ * items derived from the array's members; array order is the sort rank.
291
+ * Members without an entry still get picker items, appended in schema
292
+ * order. Entries whose `type` matches no member warn in dev mode.
293
+ */
294
+ items?: readonly PickerItemMetadata[];
295
+ /**
296
+ * Programmatic seam over the derived item list — reorder, remove, relabel,
297
+ * or append items (including `custom`-action items) — running after schema
298
+ * derivation, presets, and `items` metadata.
299
+ */
300
+ resolveItems?: PickerItemsResolver;
301
+ /**
302
+ * Markdown-style transforms (for example from the {@link codeFenceRule} and
303
+ * {@link blockquoteRule} factories) that replace typed text with an
304
+ * inserted block, as one undo step. Opt-in only; rules targeting block
305
+ * types the array does not allow are ignored.
306
+ */
307
+ inputRules?: readonly MarkdownInputRuleConfig[];
308
+ /**
309
+ * Replaces the built-in matching (case-insensitive substring over title,
310
+ * keywords, and description, plus trigger prefixes). Receives the bare
311
+ * query in both modes — the slash-mode "/" prefix is stripped.
312
+ */
313
+ filter?: (items: readonly PickerItem[], query: string) => readonly PickerItem[];
314
+ /** Overrides for the picker chrome's user-facing strings. */
315
+ labels?: Partial<BlockInsertPickerLabels>;
316
+ /**
317
+ * Notified after each successful insert — picker selection or input rule —
318
+ * alongside the built-in open-for-editing behavior.
319
+ */
320
+ onInsert?: (event: PickerInsertEvent) => void;
321
+ /**
322
+ * Whether an inserted block opens for editing (default true). Items can
323
+ * override per member via their metadata's `openOnInsert`.
324
+ */
325
+ openOnInsert?: boolean;
326
+ /** Whether Cmd/Ctrl+/ opens the picker (default true). */
327
+ shortcut?: boolean;
328
+ /**
329
+ * Whether well-known block types (image, file, code, table, ...) get
330
+ * default triggers and keywords when `items` doesn't cover them
331
+ * (default true). See {@link standardBlockPresets}.
332
+ */
333
+ presets?: boolean;
334
+ /**
335
+ * Escape hatch: names the portable-text array type to resolve items
336
+ * against when Studio's member-schema context is unavailable. Normally
337
+ * unnecessary — the containing array and its members are detected
338
+ * automatically from where the plugin is mounted.
339
+ */
340
+ arrayTypeName?: string;
341
+ }
342
+ /**
343
+ * Creates the Portable Text editor plugins component for the block-insert
344
+ * picker: a slash-command / Cmd+/ menu of the blocks the host array allows,
345
+ * plus optional markdown input rules. Zero-config is the intended call —
346
+ * items derive from the array the plugin is mounted on. Attach it to the
347
+ * array type's `components.portableText.plugins`:
348
+ *
349
+ * ```ts
350
+ * defineType({
351
+ * name: 'content',
352
+ * type: 'array',
353
+ * of: [{type: 'block'}, {type: 'callout'}],
354
+ * components: {
355
+ * portableText: {
356
+ * plugins: blockInsertPicker(),
357
+ * },
358
+ * },
359
+ * })
360
+ * ```
361
+ */
362
+ declare function blockInsertPicker(config?: BlockInsertPickerConfig): ComponentType<PortableTextPluginsProps>;
363
+ /**
364
+ * Default triggers and search keywords for block types with fixed, official
365
+ * names: Studio's intrinsic types (`image`, `file`), first-party plugin
366
+ * types (`code`, `table`, `color`, `latex`, `mux.video`), and the Media
367
+ * Library's `sanity.video`. Presets are deliberately presentation-only —
368
+ * they never add items (a type must actually be a member of the array),
369
+ * never set groups (partial grouping would strand unmatched items in an
370
+ * "Other" bucket), never affect rank, and always lose to a host's `items`
371
+ * entry for the same type. Opt out entirely with `presets: false`.
372
+ */
373
+ declare const standardBlockPresets: readonly PickerItemMetadata[];
374
+ /**
375
+ * Opt-in input rules for well-known block types — spread into `inputRules`
376
+ * (`inputRules: [...wellKnownInputRules]`) rather than applied by default.
377
+ * Today: a code fence for `@sanity/code-input`'s `code` type that stores the
378
+ * typed fence token as the language. Like all rules, each resolves against
379
+ * the array's members by name or resolved type chain (so an aliased
380
+ * `{type: 'code', name: 'snippet'}` member still gets the fence, inserted
381
+ * with the member's `_type`) and is ignored when nothing matches.
382
+ */
383
+ declare const wellKnownInputRules: readonly MarkdownInputRuleConfig[];
384
+ export { BLOCKQUOTE_PATTERN, BlockInsertPicker, type BlockInsertPickerConfig, type BlockInsertPickerLabels, type BlockInsertPickerProps, CODE_FENCE_PATTERN, type KeyGenerator, type LanguageEntry, type MarkdownInputRuleConfig, MarkdownInputRules, type MarkdownInputRulesProps, type PickerActionContext, type PickerInsertEvent, type PickerItem, type PickerItemAction, type PickerItemMetadata, type PickerItemsContext, type PickerItemsResolver, type PickerMode, blockInsertPicker, blockquoteRule, codeFenceRule, derivePickerItems, fenceLanguageFromMatch, filterPickerItems, normalizeFenceLanguage, standardBlockPresets, wellKnownInputRules };
385
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/labels.ts","../src/types.ts","../src/blockInsertPicker.tsx","../src/deriveItems.ts","../src/filterItems.ts","../src/inputRules.ts","../src/markdownInputRules.tsx","../src/plugin.tsx","../src/presets.ts"],"mappings":";;;;;;;;;;;KAOY;;EAEV;;EAEA;;;;;EAKA;;;;;EAKA;;EAEA;EACA;EACA;EACA;;EAEA;;;;;EAKA;;;;;;;;KCvBU;EACV;EACA;EACA;;EAEA,OAAO;;EAEP;;KAWU;EACV;EACA;EACA;;;;;;EAMA;;;;;EAKA;EACA,OAAO;EACP;;EAEA;;EAEA;EACA,QAAQ;;;;;;;;;KAUE;EACP;EAAgB,WAAW,SAAS;;EACpC;EAAqB;;;UAGT;EACf,QAAQ;EACR;;;;;;;;;;;;KAaU;EACV;EACA;EACA;EACA;EACA;;EAEA;;EAEA;;EAEA;;;;;;;;UASe;EACf,YAAY;EACZ,sBAAsB;;;;;;;KAQZ,uBACV,gBAAgB,cAChB,SAAS,gCACG;KAEF;KChFA;;;;;;;EAOV,iBAAiB;;;;;;;EAOjB;;;;;EAKA,eAAe;;;;;EAKf,UAAU,gBAAgB,cAAc,2BAA2B;;EAEnE,SAAS,QAAQ;;EAEjB,YAAY,OAAO;;;;;EAKnB;;EAEA;;;;;;EAMA;;iBAGc,oBACd,eACA,QACA,OACA,QAAQ,gBACR,UACA,cACA,SACA,cACA,YACC,yCAAsB,IAAA;;;;;;;;;;;iBCrDT,kBACd,SAAS,oBACT,oBAAmB,uBAClB;iBCpCa,kBACd,gBAAgB,cAChB,yBACU;;;;;;;;;;;;;;;;KCeA;;;;;;;KAQA;EACV,SAAS;EACT;EACA,aAAa;IAAU;IAAmB,cAAc;QAAkB;;cAgC/D,oBAAkB;cAClB,oBAAkB;;;;;KAMnB;EACV;EACA;EACA;;;iBAIc,eAAe;EAC7B;EACA,eAAe;IAAU,cAAc;QAAkB;IACvD;;;;;;;;iBAeY,cAAc;EAC5B;EACA,qBAAqB;EACrB;EACA,cAAc;IACZ;IACA,cAAc;IACd;QACI;IACJ;;iBAoBY,uBAAuB;;;;;;iBASvB,uBACd,aACA,oBAAoB,iBACpB;KC9HU;;;;;;EAMV;;EAEA,gBAAgB;;EAEhB,YAAY,OAAO;;EAEnB;;;;;;;iBAQc,qBACd,eACA,UACA,cACA,SACC;UC1Bc;;;;;;;;EAQf,iBAAiB;;;;;;EAMjB,eAAe;;;;;;;EAOf,sBAAsB;;;;;;EAMtB,UAAU,gBAAgB,cAAc,2BAA2B;;EAEnE,SAAS,QAAQ;;;;;EAKjB,YAAY,OAAO;;;;;EAKnB;;EAEA;;;;;;EAMA;;;;;;;EAOA;;;;;;;;;;;;;;;;;;;;;;iBAuBc,kBACd,SAAQ,0BACP,cAAc;;;;;;;;;;;cC1EJ,+BAA+B;;;;;;;;;;cAoB/B,8BAA8B"}