modern-cmdk 1.2.3 → 1.4.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 +1 -1
- package/README.md +109 -154
- package/dist/codemod/cli.mjs +205 -120
- package/dist/codemod/transforms/data-attrs.mjs +1 -1
- package/dist/core/index.d.mts +10 -10
- package/dist/core/index.mjs +9 -8
- package/dist/react/chunk-dialog.mjs +237 -0
- package/dist/react/dialog.d.mts +18 -0
- package/dist/react/dialog.mjs +3 -0
- package/dist/react/index.d.mts +11 -333
- package/dist/react/index.mjs +34 -1373
- package/dist/react/styles.css +18 -9
- package/package.json +8 -12
- package/dist/codemod/cli.d.mts +0 -1
- package/dist/codemod/transforms/data-attrs.d.mts +0 -6
- package/dist/codemod/transforms/forward-ref.d.mts +0 -6
- package/dist/codemod/transforms/import-rewrite.d.mts +0 -6
- package/dist/codemod/transforms/should-filter.d.mts +0 -5
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -9,43 +9,55 @@
|
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
11
|
<a href="https://www.npmjs.com/package/modern-cmdk"><img alt="npm version" src="https://img.shields.io/npm/v/modern-cmdk?style=flat-square&color=dc2626&labelColor=0a0e27"/></a>
|
|
12
|
-
<a href="https://bundlephobia.com/package/modern-cmdk"><img alt="bundle size" src="https://img.shields.io/bundlephobia/minzip/modern-cmdk?style=flat-square&color=dc2626&labelColor=0a0e27&label=core"/></a>
|
|
13
12
|
<a href="https://github.com/ABCrimson/modern-cmdk/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/ABCrimson/modern-cmdk/ci.yml?style=flat-square&color=dc2626&labelColor=0a0e27&label=CI"/></a>
|
|
14
|
-
<a href="https://www.typescriptlang.org/"><img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-7.0-dc2626?style=flat-square&labelColor=0a0e27"/></a>
|
|
15
|
-
<a href="https://react.dev/"><img alt="React" src="https://img.shields.io/badge/React-19-dc2626?style=flat-square&labelColor=0a0e27"/></a>
|
|
16
13
|
<a href="https://github.com/ABCrimson/modern-cmdk/blob/main/LICENSE"><img alt="MIT License" src="https://img.shields.io/npm/l/modern-cmdk?style=flat-square&color=dc2626&labelColor=0a0e27"/></a>
|
|
17
14
|
</p>
|
|
18
15
|
|
|
19
16
|
<p align="center">
|
|
20
|
-
<a href="https://
|
|
21
|
-
<a href="https://
|
|
22
|
-
<a href="https://
|
|
23
|
-
<a href="https://
|
|
17
|
+
<a href="https://abcrimson.github.io/modern-cmdk/">Documentation</a> ·
|
|
18
|
+
<a href="https://abcrimson.github.io/modern-cmdk/guide/getting-started.html">Getting Started</a> ·
|
|
19
|
+
<a href="https://abcrimson.github.io/modern-cmdk/api/command.html">API Reference</a> ·
|
|
20
|
+
<a href="https://abcrimson.github.io/modern-cmdk/examples/basic.html">Examples</a>
|
|
24
21
|
</p>
|
|
25
22
|
|
|
26
23
|
---
|
|
27
24
|
|
|
25
|
+
A ground-up rewrite of `cmdk` for **React 19**, written in modern ECMAScript: a framework-agnostic state machine (search, frecency ranking, keyboard shortcuts) in the core, and a thin React adapter on top.
|
|
26
|
+
|
|
28
27
|
## Install
|
|
29
28
|
|
|
30
29
|
```bash
|
|
31
30
|
npm install modern-cmdk
|
|
32
31
|
```
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
> `modern-cmdk` is ESM-only and declares `engines.node >= 26.4.0`. The optional WASM search
|
|
36
|
-
> engine (`modern-cmdk-search-wasm`) is experimental and not yet published to npm.
|
|
37
|
-
|
|
38
|
-
The package exports three entry points:
|
|
33
|
+
The package exports four entry points:
|
|
39
34
|
|
|
40
35
|
```ts
|
|
41
|
-
import { createCommandMachine } from 'modern-cmdk';
|
|
42
|
-
import { Command } from 'modern-cmdk/react';
|
|
43
|
-
import 'modern-cmdk/
|
|
36
|
+
import { createCommandMachine } from 'modern-cmdk'; // Core engine (no React)
|
|
37
|
+
import { Command } from 'modern-cmdk/react'; // React components
|
|
38
|
+
import { CommandDialog } from 'modern-cmdk/react/dialog'; // CommandDialog alone
|
|
39
|
+
import 'modern-cmdk/styles.css'; // Default styles
|
|
44
40
|
```
|
|
45
41
|
|
|
46
|
-
|
|
42
|
+
`modern-cmdk` is ESM-only. The core entry imports no peer. Every import of `modern-cmdk/react` and of `modern-cmdk/react/dialog` loads `react`, `react-dom` and `radix-ui` (the `radix-ui` import is static), so these are the peers:
|
|
47
43
|
|
|
48
|
-
|
|
44
|
+
| Peer | Range | Status |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `react` | `>=19.0.0 <21.0.0` | optional (only the React entries use it) |
|
|
47
|
+
| `react-dom` | `>=19.0.0 <21.0.0` | optional (only the React entries use it) |
|
|
48
|
+
| `radix-ui` | `>=1.4.0 <2.0.0` | required through 1.x |
|
|
49
|
+
|
|
50
|
+
`radix-ui` is a required peer of `modern-cmdk` in 1.x, so npm 7+ and pnpm install it with `modern-cmdk` (or warn when they cannot), and with it its own required peers `react` and `react-dom`, even when you use only the core; `modern-cmdk` itself marks only `react` and `react-dom` optional. It becomes optional again in 2.0, when the barrel drops `Command.Dialog` and only `modern-cmdk/react/dialog` needs it. For the React entries, add the React peers yourself:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm install modern-cmdk react react-dom
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`Command.Dialog` stays on the `modern-cmdk/react` barrel through 1.x and leaves it in 2.0; `modern-cmdk/react/dialog` exports `CommandDialog` alone.
|
|
57
|
+
|
|
58
|
+
The codemod bin and `create-modern-cmdk` are supported on Node >=26.4.0 (`create-modern-cmdk` declares it in `engines`; the codemod no longer does, from 1.4.0). `modern-cmdk` itself declares no `engines`.
|
|
59
|
+
|
|
60
|
+
`sideEffects` lists only `./dist/react/styles.css`; every JavaScript entry is side-effect-free for bundlers.
|
|
49
61
|
|
|
50
62
|
## Quick Start
|
|
51
63
|
|
|
@@ -54,122 +66,63 @@ React is an **optional** peer dependency — use the core engine standalone in a
|
|
|
54
66
|
|
|
55
67
|
import { Command } from 'modern-cmdk/react';
|
|
56
68
|
import 'modern-cmdk/styles.css';
|
|
69
|
+
import { useEffect, useState } from 'react';
|
|
57
70
|
|
|
58
71
|
function CommandPalette() {
|
|
72
|
+
const [open, setOpen] = useState(false);
|
|
73
|
+
|
|
74
|
+
// Nothing opens the dialog for you: toggle it from a Mod+K listener (Cmd+K / Ctrl+K).
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
const onKeyDown = (e: KeyboardEvent) => {
|
|
77
|
+
if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
setOpen((o) => !o);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
document.addEventListener('keydown', onKeyDown);
|
|
83
|
+
return () => document.removeEventListener('keydown', onKeyDown);
|
|
84
|
+
}, []);
|
|
85
|
+
|
|
59
86
|
return (
|
|
60
|
-
<Command.Dialog>
|
|
87
|
+
<Command.Dialog open={open} onOpenChange={setOpen} label="Command Menu">
|
|
61
88
|
<Command.Input placeholder="Type a command..." />
|
|
62
89
|
<Command.List>
|
|
63
90
|
<Command.Empty>No results found.</Command.Empty>
|
|
64
91
|
|
|
65
92
|
<Command.Group heading="Actions">
|
|
66
|
-
<Command.Item value="copy" onSelect={() =>
|
|
67
|
-
|
|
68
|
-
<Command.Shortcut
|
|
93
|
+
<Command.Item value="copy" onSelect={() => setOpen(false)}>
|
|
94
|
+
Copy to Clipboard
|
|
95
|
+
<Command.Shortcut shortcut="Mod+C" />
|
|
69
96
|
</Command.Item>
|
|
70
|
-
<Command.Item value="paste" onSelect={() =>
|
|
71
|
-
|
|
72
|
-
<Command.Shortcut
|
|
97
|
+
<Command.Item value="paste" onSelect={() => setOpen(false)}>
|
|
98
|
+
Paste
|
|
99
|
+
<Command.Shortcut shortcut="Mod+V" />
|
|
73
100
|
</Command.Item>
|
|
74
101
|
</Command.Group>
|
|
75
102
|
|
|
76
103
|
<Command.Group heading="Navigation">
|
|
77
|
-
<Command.Item value="settings" onSelect={() =>
|
|
104
|
+
<Command.Item value="settings" onSelect={() => setOpen(false)}>
|
|
78
105
|
Settings
|
|
79
106
|
<Command.Badge>New</Command.Badge>
|
|
80
107
|
</Command.Item>
|
|
81
108
|
</Command.Group>
|
|
82
109
|
</Command.List>
|
|
83
|
-
<Command.Loading>Searching...</Command.Loading>
|
|
84
110
|
</Command.Dialog>
|
|
85
111
|
);
|
|
86
112
|
}
|
|
87
113
|
```
|
|
88
114
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
npm create modern-cmdk
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## Why modern-cmdk?
|
|
98
|
-
|
|
99
|
-
A ground-up rewrite of `cmdk` for **React 19**, **ES2026**, and **TypeScript 7**. Framework-agnostic core. Zero compromise on performance, accessibility, or developer experience.
|
|
100
|
-
|
|
101
|
-
| | cmdk | modern-cmdk |
|
|
102
|
-
|---|---|---|
|
|
103
|
-
| **Architecture** | React-only, tightly coupled | Framework-agnostic core + thin adapters |
|
|
104
|
-
| **React** | 18 | 19 (`use()`, `useOptimistic`, `useId`, `ref` as prop) |
|
|
105
|
-
| **Search** | Basic substring | Fuzzy scoring + optional WASM (sub-1ms on 100K items) |
|
|
106
|
-
| **Ranking** | Static order | Frecency with time-based exponential decay |
|
|
107
|
-
| **Virtualization** | None | Automatic variable-height, `content-visibility: auto` |
|
|
108
|
-
| **Animations** | CSS transitions | GPU-composited: `@starting-style`, `scroll-timeline`, spring easing |
|
|
109
|
-
| **Keyboard** | External | Built-in registry, `Mod` key, conflict detection |
|
|
110
|
-
| **Accessibility** | Partial ARIA | Full WAI-ARIA combobox, `forced-colors`, `prefers-contrast` |
|
|
111
|
-
| **Bundle** | ~6 KB | Core ~6.4 KB, React ~9.8 KB |
|
|
112
|
-
| **TypeScript** | 4.x/5.x | 7.0, isolated declarations, branded types |
|
|
113
|
-
| **Cleanup** | Manual | `using`/`await using` (Explicit Resource Management) |
|
|
114
|
-
| **Error handling** | None | `CommandErrorBoundary` with fallback UI |
|
|
115
|
-
| **DevTools** | None | Built-in devtools hook for browser inspection |
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
## Features
|
|
120
|
-
|
|
121
|
-
- **Framework-agnostic core** -- Pure TypeScript state machine. No DOM. No React. Portable to any runtime. The sole runtime dependency (`idb-keyval`) is lazy-loaded only if you opt into IndexedDB frecency persistence.
|
|
122
|
-
- **React 19 adapter** -- 14 compound components. `useSyncExternalStore`, `useTransition`, `useOptimistic`, `use()` for Suspense. React Compiler compatible.
|
|
123
|
-
- **Automatic virtualization** -- Variable-height virtual scrolling kicks in at a configurable threshold (`virtualizeThreshold`, default 100). Handles 100K+ items smoothly with `content-visibility: auto`.
|
|
124
|
-
- **Fuzzy search** -- Built-in TypeScript scorer with incremental filtering. Optional Rust/WASM engine for sub-1ms on 100K items with graceful TS fallback _(experimental, not yet published to npm)_.
|
|
125
|
-
- **Frecency ranking** -- Frequency x recency with time-based exponential decay. Pluggable persistence (memory or IndexedDB).
|
|
126
|
-
- **Keyboard shortcuts** -- Built-in registry with cross-platform `Mod` key, conflict detection, and `RegExp.escape` parsing. Cross-browser helper functions for grouping and set operations.
|
|
127
|
-
- **Full accessibility** -- WAI-ARIA combobox pattern, `aria-live` announcements, `forced-colors`, `prefers-contrast`, `prefers-reduced-motion`.
|
|
128
|
-
- **GPU-composited animations** -- `@starting-style` entry, `scroll-timeline` progress, spring `linear()` easing. All customizable via CSS custom properties.
|
|
129
|
-
- **Error boundary** -- `CommandErrorBoundary` with static or render-function fallback.
|
|
130
|
-
- **DevTools** -- `useCommandDevtools()` exposes machine state via `CustomEvent` for browser inspection.
|
|
131
|
-
- **Telemetry middleware** -- Pluggable hooks for palette open/close, search, and item selection analytics.
|
|
132
|
-
- **ESM-only** -- Zero CommonJS. Tree-shakeable -- the framework-agnostic core is side-effect-free; only the React entry and `styles.css` are flagged in `sideEffects`. Isolated declarations.
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## React Components
|
|
137
|
-
|
|
138
|
-
```tsx
|
|
139
|
-
<Command> {/* Root -- state machine provider */}
|
|
140
|
-
<Command.Input /> {/* Search input */}
|
|
141
|
-
<Command.List> {/* Scrollable list with auto-virtualization */}
|
|
142
|
-
<Command.Empty /> {/* Shown when filteredCount === 0 */}
|
|
143
|
-
<Command.Loading /> {/* Shown when loading */}
|
|
144
|
-
<Command.Group> {/* Labeled group of items */}
|
|
145
|
-
<Command.Item> {/* Selectable item */}
|
|
146
|
-
<Command.Highlight /> {/* Fuzzy match highlighting */}
|
|
147
|
-
<Command.Badge /> {/* Status badge */}
|
|
148
|
-
<Command.Shortcut /> {/* Keyboard shortcut display */}
|
|
149
|
-
</Command.Item>
|
|
150
|
-
</Command.Group>
|
|
151
|
-
<Command.Separator />
|
|
152
|
-
</Command.List>
|
|
153
|
-
</Command>
|
|
154
|
-
|
|
155
|
-
<Command.Dialog /> {/* Radix Dialog + overlay + portal */}
|
|
156
|
-
<Command.Page /> {/* Nested page navigation */}
|
|
157
|
-
<Command.AsyncItems /> {/* Suspense-powered async loading */}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Core API (No React)
|
|
115
|
+
`<Command label="Command menu">` takes the same children inline, with no dialog; `<Command.Highlight text={...} ranges={...} />` renders match highlighting from scorer ranges. To scaffold a project instead: `npm create modern-cmdk@latest my-palette -- --template=react-basic`.
|
|
163
116
|
|
|
164
|
-
|
|
117
|
+
## Core API (no React)
|
|
165
118
|
|
|
166
119
|
```ts
|
|
167
120
|
import { createCommandMachine, itemId } from 'modern-cmdk';
|
|
168
121
|
|
|
169
122
|
using machine = createCommandMachine({
|
|
170
123
|
items: [
|
|
171
|
-
{ id: itemId('copy'), value: 'Copy', shortcut: 'Mod+C', onSelect: () =>
|
|
172
|
-
{ id: itemId('paste'), value: 'Paste', shortcut: 'Mod+V', onSelect: () =>
|
|
124
|
+
{ id: itemId('copy'), value: 'Copy', shortcut: 'Mod+C', onSelect: () => navigator.clipboard.writeText(getSelection()?.toString() ?? '') },
|
|
125
|
+
{ id: itemId('paste'), value: 'Paste', shortcut: 'Mod+V', onSelect: () => navigator.clipboard.readText().then((text) => console.log('Pasted:', text)) },
|
|
173
126
|
],
|
|
174
127
|
frecency: { enabled: true },
|
|
175
128
|
loop: true,
|
|
@@ -185,81 +138,83 @@ machine.subscribe(() => {
|
|
|
185
138
|
// Automatic cleanup via `using` -- no manual dispose needed
|
|
186
139
|
```
|
|
187
140
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
## Performance
|
|
191
|
-
|
|
192
|
-
| Benchmark | Target | Measured |
|
|
193
|
-
|---|---|---|
|
|
194
|
-
| Search 10K items (TS scorer) | < 16 ms | ~8.2 ms |
|
|
195
|
-
| Search 100K items (WASM) | < 1 ms | ~0.7 ms |
|
|
196
|
-
| Filter 10K (incremental) | < 2 ms | ~1.1 ms |
|
|
197
|
-
| State update cycle | < 4 ms | ~2.3 ms |
|
|
198
|
-
| Core bundle (gzipped) | <= 6.5 KB | ~6.4 KB |
|
|
199
|
-
| React bundle (gzipped) | <= 12 KB | ~9.8 KB |
|
|
200
|
-
|
|
201
|
-
CI enforces 5% warning / 15% failure regression thresholds with 3-run averaging.
|
|
141
|
+
## What is in it
|
|
202
142
|
|
|
203
|
-
|
|
143
|
+
- **Framework-agnostic core** -- a pure TypeScript state machine; DOM APIs are feature-detected and SSR-safe. The sole runtime dependency (`idb-keyval`) is lazy-loaded only if you opt into IndexedDB frecency persistence.
|
|
144
|
+
- **React 19 adapter** -- compound components over `useSyncExternalStore`, `useTransition` and `use()`; React Compiler compatible.
|
|
145
|
+
- **Automatic virtualization** -- turns on when more than 100 items match and off again at 50 or fewer (fixed thresholds; force it with `<Command.List virtualize>` or `virtualize={false}`). The `virtualizeThreshold` option is accepted but not read yet.
|
|
146
|
+
- **Fuzzy search and frecency** -- a built-in TypeScript scorer with match ranges, and frequency x recency ranking with memory or IndexedDB persistence. `modern-cmdk-search-wasm` is an experimental, unpublished workspace package that does not work yet.
|
|
147
|
+
- **Keyboard shortcuts** -- a registry with a cross-platform `Mod` key and conflict detection.
|
|
148
|
+
- **Accessibility** -- WAI-ARIA combobox pattern, `aria-live` announcements, `forced-colors`, `prefers-contrast`, `prefers-reduced-motion`.
|
|
149
|
+
- **Animation** -- the stylesheet defines the dialog enter and exit on opacity, scale and translate, which are compositor-only; the overlay fades opacity and also transitions `--command-overlay-opacity`, its background alpha, which repaints, and the list height and item background-color transitions are not compositor-only either. In 1.x neither the dialog nor the overlay animates on enter or exit, because their duration and easing tokens are declared only on `[data-command-root]`, which sits inside the dialog (DT-19, planned for 1.8.0).
|
|
150
|
+
- **Extras** -- `CommandErrorBoundary`, `useCommandDevtools()` and telemetry middleware.
|
|
204
151
|
|
|
205
|
-
|
|
152
|
+
Theming (CSS custom properties, `@layer command`) is covered in the [theming guide](https://abcrimson.github.io/modern-cmdk/guide/theming.html).
|
|
206
153
|
|
|
207
|
-
|
|
154
|
+
## Sizes
|
|
208
155
|
|
|
209
|
-
|
|
210
|
-
[data-command-root] {
|
|
211
|
-
--command-duration-enter: 200ms;
|
|
212
|
-
--command-duration-exit: 150ms;
|
|
213
|
-
--command-scale-from: 0.96;
|
|
214
|
-
--command-overlay-blur: 4px;
|
|
215
|
-
--command-dialog-radius: 12px;
|
|
216
|
-
--command-dialog-max-width: 640px;
|
|
217
|
-
--command-item-height: 44px;
|
|
218
|
-
--command-highlight-color: oklch(0.85 0.15 90 / 0.3);
|
|
219
|
-
}
|
|
220
|
-
```
|
|
156
|
+
Figures come from [`benchmarks/size-history/1.4.0.json`](https://github.com/ABCrimson/modern-cmdk/blob/5f1e01e/benchmarks/size-history/1.4.0.json) (committed in `5f1e01e`, measured at `07bfe79` with size-limit 14.3.0) and the `size-limit` entries in the root `package.json`. Method: size-limit, gzip, peers (`react`, `react-dom`, `radix-ui`) ignored; the codemod bin is raw installed size.
|
|
221
157
|
|
|
222
|
-
|
|
158
|
+
| Entry | Bytes | Method |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `modern-cmdk` (core) | 6355 | gzip |
|
|
161
|
+
| `modern-cmdk/react`, adapter only | 5403 | gzip, `modern-cmdk` ignored |
|
|
162
|
+
| `modern-cmdk` + `modern-cmdk/react` | 9830 | gzip, core included |
|
|
163
|
+
| `modern-cmdk/react/dialog`, adapter only | 1425 | gzip, `modern-cmdk` ignored |
|
|
164
|
+
| `modern-cmdk/react`, `CommandSeparator` only | 4767 | gzip, `modern-cmdk` ignored; still contains `CommandDialog`, `CommandRoot` and the `radix-ui` import (tree-shaking of the barrel is a 2.0 item) |
|
|
165
|
+
| `modern-cmdk/styles.css` | 3959 | gzip |
|
|
166
|
+
| codemod bin (`dist/codemod/cli.mjs` plus `dist/codemod/transforms/*.mjs`) | 3325793 | raw installed size, not gzip |
|
|
223
167
|
|
|
224
|
-
|
|
168
|
+
1.3's 9844 B React figure measured `dist/react/index.mjs` with the core inlined, so it was core plus adapter, not the adapter.
|
|
225
169
|
|
|
226
170
|
## Migration from cmdk
|
|
227
171
|
|
|
228
|
-
|
|
172
|
+
Four codemods ship as the `modern-cmdk` bin, supported on Node >= 26.4.0. Pass a transform name and a glob (quote the glob so your shell does not expand it):
|
|
229
173
|
|
|
230
174
|
```bash
|
|
231
|
-
npx modern-cmdk
|
|
232
|
-
npx modern-cmdk
|
|
233
|
-
npx modern-cmdk
|
|
234
|
-
npx modern-cmdk should-filter ./src
|
|
175
|
+
npx modern-cmdk --help
|
|
176
|
+
npx modern-cmdk import-rewrite "./src/**/*.tsx" --dry-run
|
|
177
|
+
npx modern-cmdk import-rewrite "./src/**/*.tsx"
|
|
235
178
|
```
|
|
236
179
|
|
|
237
|
-
|
|
180
|
+
| Transform | What it does |
|
|
181
|
+
|---|---|
|
|
182
|
+
| `import-rewrite` | Rewrites `cmdk` imports to `modern-cmdk/react` |
|
|
183
|
+
| `data-attrs` | Converts `[cmdk-*]` selectors to `[data-command-*]` |
|
|
184
|
+
| `forward-ref` | Removes `React.forwardRef` wrappers (React 19) |
|
|
185
|
+
| `should-filter` | Converts the `shouldFilter` prop to `filter` |
|
|
238
186
|
|
|
239
|
-
|
|
187
|
+
Options: `--dry-run` lists the files that would change and writes nothing; `--concurrency=N` sets how many files are processed at once (default 8); `--strict` is described below.
|
|
240
188
|
|
|
241
|
-
|
|
189
|
+
A run prints one `changed <file>` line per rewritten file and a summary. With `--dry-run` the lines read `would change <file>` and the summary ends in `(dry run, nothing written)`:
|
|
242
190
|
|
|
243
|
-
|
|
191
|
+
```text
|
|
192
|
+
would change src/a.tsx
|
|
193
|
+
1 changed, 0 unchanged, 0 errors (dry run, nothing written)
|
|
194
|
+
```
|
|
244
195
|
|
|
245
|
-
|
|
196
|
+
Exit codes in 1.x are unchanged by default: `0` for `--help`, missing arguments and per-file errors, and `1` for an unknown transform, a glob that matches no files, or an uncaught error. An unknown option is warned about on stderr and ignored when the transform and glob are present. A malformed known option (`--concurrency` with no value, `--dry-run=yes`) is a usage error that writes nothing and exits `0`. With `--strict`, every usage error (including an unknown option, an unknown transform and a malformed option) exits `2`, and any file error exits `1`.
|
|
246
197
|
|
|
247
|
-
|
|
198
|
+
See the [full migration guide](https://abcrimson.github.io/modern-cmdk/guide/migration-from-cmdk.html).
|
|
248
199
|
|
|
249
|
-
|
|
200
|
+
## Documentation
|
|
250
201
|
|
|
251
|
-
|
|
202
|
+
**[abcrimson.github.io/modern-cmdk](https://abcrimson.github.io/modern-cmdk/)** -- [Installation](https://abcrimson.github.io/modern-cmdk/guide/installation.html) | [Basic Usage](https://abcrimson.github.io/modern-cmdk/guide/basic-usage.html) | [SSR / Next.js](https://abcrimson.github.io/modern-cmdk/guide/ssr.html) | [Theming](https://abcrimson.github.io/modern-cmdk/guide/theming.html) | [Accessibility](https://abcrimson.github.io/modern-cmdk/guide/accessibility.html) | [Core API](https://abcrimson.github.io/modern-cmdk/api/command.html) | [React API](https://abcrimson.github.io/modern-cmdk/api/command-react.html) | [Benchmarks](https://abcrimson.github.io/modern-cmdk/benchmarks.html)
|
|
252
203
|
|
|
253
|
-
|
|
204
|
+
**More guides:** [Async Items](https://abcrimson.github.io/modern-cmdk/guide/async-items.html) | [Frecency](https://abcrimson.github.io/modern-cmdk/guide/frecency.html) | [Shortcuts](https://abcrimson.github.io/modern-cmdk/guide/shortcuts.html) | [Virtualization](https://abcrimson.github.io/modern-cmdk/guide/virtualization.html) | [TypeScript](https://abcrimson.github.io/modern-cmdk/guide/typescript-integration.html) | [Controlled Dialog](https://abcrimson.github.io/modern-cmdk/guide/controlled-dialog.html) | [WASM Search (experimental)](https://abcrimson.github.io/modern-cmdk/guide/wasm-search.html) | [WASM Search API (experimental)](https://abcrimson.github.io/modern-cmdk/api/command-search-wasm.html)
|
|
254
205
|
|
|
255
|
-
|
|
|
206
|
+
**Recipes:** [File Picker](https://abcrimson.github.io/modern-cmdk/recipes/file-picker.html) | [Emoji Picker](https://abcrimson.github.io/modern-cmdk/recipes/emoji-picker.html) | [AI Chat Commands](https://abcrimson.github.io/modern-cmdk/recipes/ai-chat-commands.html) | [Nested Commands](https://abcrimson.github.io/modern-cmdk/recipes/nested-commands.html) | [Spotlight Search](https://abcrimson.github.io/modern-cmdk/recipes/spotlight-search.html)
|
|
207
|
+
|
|
208
|
+
## Related packages
|
|
209
|
+
|
|
210
|
+
| Package | Status |
|
|
256
211
|
|---|---|
|
|
257
|
-
| [`create-modern-cmdk`](https://www.npmjs.com/package/create-modern-cmdk) | `npm create modern-cmdk
|
|
258
|
-
| `modern-cmdk-search-wasm`
|
|
259
|
-
|
|
|
212
|
+
| [`create-modern-cmdk`](https://www.npmjs.com/package/create-modern-cmdk) | Published. `npm create modern-cmdk@latest <name>` scaffolds a new project. |
|
|
213
|
+
| `modern-cmdk-search-wasm` | Experimental Rust/WASM fuzzy search; private (0.9.0), not on npm. |
|
|
214
|
+
| `vscode-modern-cmdk` | Not on the VS Code Marketplace. The npm 1.0.0 of that name was an accidental publish and is not the extension; the package is private from 1.4.0. |
|
|
260
215
|
|
|
261
|
-
|
|
216
|
+
The repository page, with development and contributing notes, is [github.com/ABCrimson/modern-cmdk](https://github.com/ABCrimson/modern-cmdk).
|
|
262
217
|
|
|
263
218
|
## License
|
|
264
219
|
|
|
265
|
-
[MIT](https://github.com/ABCrimson/modern-cmdk/blob/main/LICENSE) -- Copyright (c) 2026
|
|
220
|
+
[MIT](https://github.com/ABCrimson/modern-cmdk/blob/main/LICENSE) -- Copyright (c) 2026 Albert Badalov
|