modern-cmdk 1.2.2 → 1.2.3

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.
@@ -4,10 +4,10 @@ import { Component, Suspense, createContext, use, useCallback, useEffect, useId,
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { Dialog } from "radix-ui";
6
6
  import { createPortal } from "react-dom";
7
- //#region src/react/activity.tsx
7
+ // src/react/activity.tsx
8
8
  const ActivityComponent = "Activity" in React ? React.Activity : null;
9
9
  /**
10
- * Wraps content in React 19.3.0-canary Activity API.
10
+ * Wraps content in React's <Activity> API (React 19.2+).
11
11
  * When mode="hidden", the component tree is preserved in memory but not rendered.
12
12
  * Falls back to conditional rendering if Activity is unavailable.
13
13
  */
@@ -19,8 +19,7 @@ function CommandActivity({ mode, children }) {
19
19
  if (mode === "hidden") return null;
20
20
  return /* @__PURE__ */ jsx(Fragment, { children });
21
21
  }
22
- //#endregion
23
- //#region src/react/context.ts
22
+ // src/react/context.ts
24
23
  const CommandStableContext = createContext(null);
25
24
  CommandStableContext.displayName = "CommandStableContext";
26
25
  const CommandStateContext = createContext(null);
@@ -42,8 +41,7 @@ CommandGroupContext.displayName = "CommandGroupContext";
42
41
  /** Context for the status container rendered outside the listbox — used by Command.Empty */
43
42
  const CommandListStatusContext = createContext(null);
44
43
  CommandListStatusContext.displayName = "CommandListStatusContext";
45
- //#endregion
46
- //#region src/react/async-items.tsx
44
+ // src/react/async-items.tsx
47
45
  /** Inner component that suspends via use() until items resolve */
48
46
  function AsyncItemsInner({ items: itemsPromise, children }) {
49
47
  const stable = useStableContext("Command.AsyncItems");
@@ -68,8 +66,7 @@ function CommandAsyncItems({ items, fallback, children }) {
68
66
  })
69
67
  });
70
68
  }
71
- //#endregion
72
- //#region src/react/badge.tsx
69
+ // src/react/badge.tsx
73
70
  /** Inline badge for categorization or status indicators on command items. */
74
71
  function CommandBadge({ ref, children, ...props }) {
75
72
  return /* @__PURE__ */ jsx("span", {
@@ -79,8 +76,7 @@ function CommandBadge({ ref, children, ...props }) {
79
76
  children
80
77
  });
81
78
  }
82
- //#endregion
83
- //#region src/core/utils/string-wellformed.ts
79
+ // src/core/utils/string-wellformed.ts
84
80
  /**
85
81
  * Regex matching lone surrogates (unpaired high or low surrogates).
86
82
  * A lone high surrogate (U+D800–U+DBFF) not followed by a low surrogate,
@@ -97,8 +93,7 @@ const REPLACEMENT_CHAR = "�";
97
93
  function ensureWellFormed(str) {
98
94
  return str.replace(LONE_SURROGATE_RE, REPLACEMENT_CHAR);
99
95
  }
100
- //#endregion
101
- //#region src/core/types.ts
96
+ // src/core/types.ts
102
97
  /** Create a branded {@link ItemId} from a plain string. Ensures well-formed Unicode. */
103
98
  function itemId(id) {
104
99
  return ensureWellFormed(id);
@@ -130,8 +125,7 @@ function createInitialState(options) {
130
125
  lastUpdated: Date.now()
131
126
  };
132
127
  }
133
- //#endregion
134
- //#region src/core/frecency/memory-storage.ts
128
+ // src/core/frecency/memory-storage.ts
135
129
  /**
136
130
  * In-memory implementation of FrecencyStorage using a Map.
137
131
  * Data does not persist across page reloads. Suitable for ephemeral
@@ -153,8 +147,7 @@ var MemoryFrecencyStorage = class {
153
147
  this.#store.clear();
154
148
  }
155
149
  };
156
- //#endregion
157
- //#region src/core/frecency/index.ts
150
+ // src/core/frecency/index.ts
158
151
  /** Shared empty bonus map — avoids allocation when no frecency records exist */
159
152
  const EMPTY_BONUS_MAP = /* @__PURE__ */ new Map();
160
153
  /** Pre-computed bucket boundaries in hours — avoids Duration.total() per call */
@@ -256,8 +249,7 @@ var FrecencyEngine = class {
256
249
  this.#storage[Symbol.dispose]();
257
250
  }
258
251
  };
259
- //#endregion
260
- //#region src/core/utils/group-by.ts
252
+ // src/core/utils/group-by.ts
261
253
  /**
262
254
  * Groups items from an iterable into a Map keyed by the result of `keyFn`.
263
255
  * Cross-browser replacement for `Map.groupBy()`.
@@ -272,8 +264,7 @@ function mapGroupBy(items, keyFn) {
272
264
  }
273
265
  return map;
274
266
  }
275
- //#endregion
276
- //#region src/core/keyboard/matcher.ts
267
+ // src/core/keyboard/matcher.ts
277
268
  /**
278
269
  * Tests whether a KeyboardEvent exactly matches a ParsedShortcut,
279
270
  * comparing all four modifier keys (meta, ctrl, shift, alt) and the primary key.
@@ -294,8 +285,7 @@ function detectConflicts(shortcuts) {
294
285
  const grouped = mapGroupBy(shortcuts, (s) => s.normalized);
295
286
  return new Map(grouped.entries().filter(([, group]) => group.length > 1));
296
287
  }
297
- //#endregion
298
- //#region src/core/keyboard/parser.ts
288
+ // src/core/keyboard/parser.ts
299
289
  const isMac = typeof navigator !== "undefined" && (navigator.userAgentData?.platform === "macOS" || /Mac|iPod|iPhone|iPad/.test(navigator.platform));
300
290
  /** Modifier aliases — cross-platform Mod resolution */
301
291
  const MODIFIER_MAP = {
@@ -368,8 +358,7 @@ function formatShortcut(parsed) {
368
358
  parts.push(displayKey);
369
359
  return isMac ? parts.join("") : parts.join("+");
370
360
  }
371
- //#endregion
372
- //#region src/core/keyboard/index.ts
361
+ // src/core/keyboard/index.ts
373
362
  /**
374
363
  * Manages keyboard shortcut bindings with global keydown listening.
375
364
  * Supports `using` for automatic cleanup of both individual bindings and the
@@ -440,8 +429,7 @@ var KeyboardShortcutRegistry = class {
440
429
  this.#bindings.clear();
441
430
  }
442
431
  };
443
- //#endregion
444
- //#region src/core/utils/set-ops.ts
432
+ // src/core/utils/set-ops.ts
445
433
  /** Returns a new Set containing elements present in both `a` and `b`. */
446
434
  function setIntersection(a, b) {
447
435
  const result = /* @__PURE__ */ new Set();
@@ -484,8 +472,7 @@ function setSymmetricDifference(a, b) {
484
472
  else result.add(item);
485
473
  return result;
486
474
  }
487
- //#endregion
488
- //#region src/core/registry.ts
475
+ // src/core/registry.ts
489
476
  /**
490
477
  * Manages registration and lookup of command items and groups.
491
478
  * Uses set operation helpers (union/intersection/difference) for efficient ID operations.
@@ -646,8 +633,23 @@ var CommandRegistry = class {
646
633
  this.clear();
647
634
  }
648
635
  };
649
- //#endregion
650
- //#region src/core/search/default-scorer.ts
636
+ // src/core/utils/env.ts
637
+ /**
638
+ * `true` unless `process.env.NODE_ENV` is `'production'`.
639
+ *
640
+ * Consumer bundlers (Vite, webpack, Next, esbuild) replace `process.env.NODE_ENV` statically,
641
+ * so the dev-only branches guarded by this flag fold away in production builds. A browser
642
+ * running the unbundled module throws a ReferenceError on the bare `process` reference;
643
+ * the catch turns that into the production value (`false`), so dev-only code stays off.
644
+ */
645
+ const isDev = (() => {
646
+ try {
647
+ return process.env.NODE_ENV !== "production";
648
+ } catch {
649
+ return false;
650
+ }
651
+ })();
652
+ // src/core/search/default-scorer.ts
651
653
  function isWordSeparator(code) {
652
654
  return code === 32 || code === 9 || code === 45 || code === 95 || code === 46 || code === 47 || code === 92;
653
655
  }
@@ -769,11 +771,9 @@ function scoreFuzzy(query, qLen, lowerTarget, tLen) {
769
771
  matches
770
772
  };
771
773
  }
772
- //#endregion
773
- //#region src/core/search/index.ts
774
- const __DEV__$1 = globalThis.process ? globalThis.process.env.NODE_ENV !== "production" : false;
774
+ // src/core/search/index.ts
775
775
  let leakRegistry;
776
- if (__DEV__$1) leakRegistry = new FinalizationRegistry((label) => {
776
+ if (isDev && typeof window !== "undefined") leakRegistry = new FinalizationRegistry((label) => {
777
777
  console.warn(`[modern-cmdk] ${label} was garbage collected without being disposed. Use \`using\` or call [Symbol.dispose]() to prevent leaks.`);
778
778
  });
779
779
  /**
@@ -789,7 +789,7 @@ function createSearchEngine(options) {
789
789
  let previousQuery = "";
790
790
  let previousResults = /* @__PURE__ */ new Set();
791
791
  const sentinel = {};
792
- if (__DEV__$1 && leakRegistry) leakRegistry.register(sentinel, "SearchEngine", sentinel);
792
+ if (leakRegistry) leakRegistry.register(sentinel, "SearchEngine", sentinel);
793
793
  return {
794
794
  index(items) {
795
795
  for (const item of items) indexedEntries.set(item.id, {
@@ -839,12 +839,11 @@ function createSearchEngine(options) {
839
839
  [Symbol.dispose]() {
840
840
  indexedEntries.clear();
841
841
  previousResults.clear();
842
- if (__DEV__$1 && leakRegistry) leakRegistry.unregister(sentinel);
842
+ if (leakRegistry) leakRegistry.unregister(sentinel);
843
843
  }
844
844
  };
845
845
  }
846
- //#endregion
847
- //#region src/core/utils/event-emitter.ts
846
+ // src/core/utils/event-emitter.ts
848
847
  /**
849
848
  * Type-safe event emitter with strong references and Disposable subscriptions.
850
849
  * Returns Disposable from `on()` for automatic unsubscription via `using`.
@@ -887,8 +886,7 @@ var TypedEmitter = class {
887
886
  this.#listeners.clear();
888
887
  }
889
888
  };
890
- //#endregion
891
- //#region src/core/utils/scheduler.ts
889
+ // src/core/utils/scheduler.ts
892
890
  /** Whether we're in a browser environment with rAF available */
893
891
  const hasRAF = typeof requestAnimationFrame === "function";
894
892
  /** Feature detection for cutting-edge scheduling APIs */
@@ -949,8 +947,7 @@ function createScheduler() {
949
947
  }
950
948
  };
951
949
  }
952
- //#endregion
953
- //#region src/core/machine.ts
950
+ // src/core/machine.ts
954
951
  /**
955
952
  * Creates a headless command palette state machine with search, frecency,
956
953
  * and keyboard shortcut support. Implements Disposable for `using` cleanup.
@@ -1216,8 +1213,7 @@ function createCommandMachine(options = {}) {
1216
1213
  }
1217
1214
  };
1218
1215
  }
1219
- //#endregion
1220
- //#region src/react/hooks/use-command.ts
1216
+ // src/react/hooks/use-command.ts
1221
1217
  /** Core hook that binds a CommandMachine to React via useSyncExternalStore, useTransition, and useOptimistic. */
1222
1218
  function useCommand(machine) {
1223
1219
  const id = useId();
@@ -1250,8 +1246,7 @@ function useCommand(machine) {
1250
1246
  id
1251
1247
  };
1252
1248
  }
1253
- //#endregion
1254
- //#region src/react/hooks/use-keyboard.ts
1249
+ // src/react/hooks/use-keyboard.ts
1255
1250
  /** Navigation key to machine direction mapping */
1256
1251
  const NAVIGATION_KEYS = {
1257
1252
  ArrowDown: "next",
@@ -1295,8 +1290,7 @@ function createKeydownHandler(machine, getState) {
1295
1290
  }
1296
1291
  };
1297
1292
  }
1298
- //#endregion
1299
- //#region src/react/hooks/use-command-setup.ts
1293
+ // src/react/hooks/use-command-setup.ts
1300
1294
  /**
1301
1295
  * Shared setup for Command and Command.Dialog — creates machine once,
1302
1296
  * subscribes via useSyncExternalStore, memoizes context values, and
@@ -1356,8 +1350,7 @@ function useCommandSetup(machineFactory, label) {
1356
1350
  ])
1357
1351
  };
1358
1352
  }
1359
- //#endregion
1360
- //#region src/react/dialog.tsx
1353
+ // src/react/dialog.tsx
1361
1354
  /** Dialog variant that wraps the command palette in a Radix UI Dialog with focus trap and overlay. */
1362
1355
  function CommandDialog({ children, className, overlayClassName, contentClassName, label = "Command palette", description = "Type a command or search...", open: controlledOpen, onOpenChange, container, ...machineOptions }) {
1363
1356
  const onOpenChangeRef = useRef(onOpenChange);
@@ -1431,8 +1424,7 @@ function CommandDialog({ children, className, overlayClassName, contentClassName
1431
1424
  })
1432
1425
  });
1433
1426
  }
1434
- //#endregion
1435
- //#region src/react/empty.tsx
1427
+ // src/react/empty.tsx
1436
1428
  /** Rendered when no items match the current search query. */
1437
1429
  function CommandEmpty({ ref, children, ...props }) {
1438
1430
  const stateCtx = useStateContext("Command.Empty");
@@ -1449,8 +1441,7 @@ function CommandEmpty({ ref, children, ...props }) {
1449
1441
  if (statusContainerRef?.current) return createPortal(content, statusContainerRef.current);
1450
1442
  return content;
1451
1443
  }
1452
- //#endregion
1453
- //#region src/react/hooks/use-register.ts
1444
+ // src/react/hooks/use-register.ts
1454
1445
  /** Register a command item with the machine — auto-deregisters on unmount */
1455
1446
  function useRegisterItem(value, options) {
1456
1447
  const stable = useStableContext("useRegisterItem");
@@ -1522,8 +1513,7 @@ function useRegisterGroup(heading, options) {
1522
1513
  ]);
1523
1514
  return id;
1524
1515
  }
1525
- //#endregion
1526
- //#region src/react/group.tsx
1516
+ // src/react/group.tsx
1527
1517
  /** Module-level constant — avoids allocating a new object on every render of hidden groups */
1528
1518
  const HIDDEN_STYLE = { display: "none" };
1529
1519
  /** Visual grouping container with an optional heading that hides when no items match. */
@@ -1567,8 +1557,7 @@ function CommandGroup({ ref, children, heading, priority, forceId, ...props }) {
1567
1557
  })
1568
1558
  });
1569
1559
  }
1570
- //#endregion
1571
- //#region src/react/highlight.tsx
1560
+ // src/react/highlight.tsx
1572
1561
  /** Renders search match highlighting by splitting text at scored match ranges. */
1573
1562
  function CommandHighlight({ text, ranges, highlightClassName }) {
1574
1563
  return useMemo(() => {
@@ -1593,8 +1582,7 @@ function CommandHighlight({ text, ranges, highlightClassName }) {
1593
1582
  highlightClassName
1594
1583
  ]);
1595
1584
  }
1596
- //#endregion
1597
- //#region src/react/input.tsx
1585
+ // src/react/input.tsx
1598
1586
  /** Combobox input that drives the command palette search state. */
1599
1587
  function CommandInput({ ref, placeholder = "Search...", onValueChange, ...props }) {
1600
1588
  const stable = useStableContext("Command.Input");
@@ -1624,8 +1612,7 @@ function CommandInput({ ref, placeholder = "Search...", onValueChange, ...props
1624
1612
  ...props
1625
1613
  });
1626
1614
  }
1627
- //#endregion
1628
- //#region src/react/item.tsx
1615
+ // src/react/item.tsx
1629
1616
  /** Individual selectable item in the command list with keyboard and pointer activation. */
1630
1617
  function CommandItem({ ref, children, value, keywords, onSelect, disabled = false, shortcut, forceId, ...props }) {
1631
1618
  const stable = useStableContext("Command.Item");
@@ -1695,8 +1682,7 @@ function CommandItem({ ref, children, value, keywords, onSelect, disabled = fals
1695
1682
  children
1696
1683
  });
1697
1684
  }
1698
- //#endregion
1699
- //#region src/react/hooks/use-virtualizer.ts
1685
+ // src/react/hooks/use-virtualizer.ts
1700
1686
  /** Lightweight virtualizer for large item lists using ResizeObserver and scroll tracking. */
1701
1687
  function useVirtualizer(options) {
1702
1688
  const { count, estimateSize, overscan = 8, scrollElement, enabled = true } = options;
@@ -1800,8 +1786,7 @@ function useVirtualizer(options) {
1800
1786
  }, [enabled])
1801
1787
  };
1802
1788
  }
1803
- //#endregion
1804
- //#region src/react/list.tsx
1789
+ // src/react/list.tsx
1805
1790
  /** Scrollable list container with auto-virtualization and aria-live announcements. */
1806
1791
  function CommandList({ ref, children, virtualize, estimateSize = 44, overscan = 8, announceResults, style, ...props }) {
1807
1792
  const stable = useStableContext("Command.List");
@@ -1941,8 +1926,7 @@ function CommandList({ ref, children, virtualize, estimateSize = 44, overscan =
1941
1926
  ]
1942
1927
  });
1943
1928
  }
1944
- //#endregion
1945
- //#region src/react/loading.tsx
1929
+ // src/react/loading.tsx
1946
1930
  /** Shown during async operations, with configurable loading state override. */
1947
1931
  function CommandLoading({ ref, children, loading: loadingOverride, ...props }) {
1948
1932
  const stateCtx = useStateContext("Command.Loading");
@@ -1957,8 +1941,7 @@ function CommandLoading({ ref, children, loading: loadingOverride, ...props }) {
1957
1941
  children
1958
1942
  });
1959
1943
  }
1960
- //#endregion
1961
- //#region src/react/page.tsx
1944
+ // src/react/page.tsx
1962
1945
  /** Page navigation container that only renders when its ID matches the active page. */
1963
1946
  function CommandPage({ id, children }) {
1964
1947
  if (useStateContext("Command.Page").state.page !== id) return null;
@@ -1968,8 +1951,7 @@ function CommandPage({ id, children }) {
1968
1951
  children
1969
1952
  });
1970
1953
  }
1971
- //#endregion
1972
- //#region src/react/separator.tsx
1954
+ // src/react/separator.tsx
1973
1955
  /** Visual divider between items or groups, rendered as a presentational element. */
1974
1956
  function CommandSeparator({ ref, ...props }) {
1975
1957
  return /* @__PURE__ */ jsx("div", {
@@ -1979,8 +1961,7 @@ function CommandSeparator({ ref, ...props }) {
1979
1961
  ...props
1980
1962
  });
1981
1963
  }
1982
- //#endregion
1983
- //#region src/react/shortcut.tsx
1964
+ // src/react/shortcut.tsx
1984
1965
  /** Keyboard shortcut display with platform-aware formatting (e.g., Cmd vs Ctrl). */
1985
1966
  function CommandShortcut({ ref, shortcut, children, ...props }) {
1986
1967
  const formattedShortcut = useMemo(() => shortcut ? formatShortcut(parseShortcut(shortcut)) : null, [shortcut]);
@@ -1991,8 +1972,7 @@ function CommandShortcut({ ref, shortcut, children, ...props }) {
1991
1972
  children: formattedShortcut ?? children
1992
1973
  });
1993
1974
  }
1994
- //#endregion
1995
- //#region src/react/command.tsx
1975
+ // src/react/command.tsx
1996
1976
  /** Root compound component that provides the command state machine context to all children. */
1997
1977
  function CommandRoot({ children, className, label = "Command palette", ...machineOptions }) {
1998
1978
  const rootRef = useRef(null);
@@ -2041,8 +2021,7 @@ const Command = Object.assign(CommandRoot, {
2041
2021
  AsyncItems: CommandAsyncItems,
2042
2022
  Activity: CommandActivity
2043
2023
  });
2044
- //#endregion
2045
- //#region src/react/error-boundary.tsx
2024
+ // src/react/error-boundary.tsx
2046
2025
  /** Initial state — no error captured */
2047
2026
  const INITIAL_STATE = { error: null };
2048
2027
  /** Error boundary for graceful failure recovery in command subtrees. */
@@ -2064,8 +2043,7 @@ var CommandErrorBoundary = class extends Component {
2064
2043
  return this.props.children;
2065
2044
  }
2066
2045
  };
2067
- //#endregion
2068
- //#region src/react/hooks/use-command-state.ts
2046
+ // src/react/hooks/use-command-state.ts
2069
2047
  function useCommandState(selector) {
2070
2048
  const stable = useStableContext("useCommandState");
2071
2049
  const selectorRef = useRef(selector);
@@ -2073,19 +2051,20 @@ function useCommandState(selector) {
2073
2051
  const getSnapshot = useCallback(() => selectorRef.current ? selectorRef.current(stable.machine.getState()) : stable.machine.getState(), [stable.machine]);
2074
2052
  return useSyncExternalStore(stable.machine.subscribe, getSnapshot, getSnapshot);
2075
2053
  }
2076
- //#endregion
2077
- //#region src/react/hooks/use-devtools.ts
2054
+ // src/react/hooks/use-devtools.ts
2078
2055
  /** Branded key for the global devtools instance map */
2079
2056
  const DEVTOOLS_KEY = "__CRIMSON_COMMAND_DEVTOOLS__";
2080
2057
  /**
2081
2058
  * Exposes command palette internals to browser devtools.
2082
- * Only active in development — completely tree-shaken in production builds.
2059
+ * Development only: the effect is gated on `process.env.NODE_ENV` and returns early in
2060
+ * production builds (the hook itself still ships). Call it from a component rendered inside
2061
+ * `<Command>`: outside one there is no machine to inspect and the hook does nothing.
2083
2062
  *
2084
2063
  * @example
2085
2064
  * ```tsx
2086
- * function MyPalette() {
2065
+ * function DevtoolsBridge() {
2087
2066
  * useCommandDevtools('main');
2088
- * return <Command>...</Command>;
2067
+ * return null;
2089
2068
  * }
2090
2069
  * ```
2091
2070
  */
@@ -2094,7 +2073,7 @@ function useCommandDevtools(label = "default") {
2094
2073
  const stateCtx = use(CommandStateContext);
2095
2074
  const stateRef = useRef(null);
2096
2075
  useEffect(() => {
2097
- if (!__DEV__) return;
2076
+ if (!isDev) return;
2098
2077
  if (!stable || !stateCtx) return;
2099
2078
  const update = () => {
2100
2079
  const s = stateCtx.state;
@@ -2129,5 +2108,4 @@ function useCommandDevtools(label = "default") {
2129
2108
  label
2130
2109
  ]);
2131
2110
  }
2132
- //#endregion
2133
2111
  export { Command, CommandActivity, CommandAsyncItems, CommandBadge, CommandDialog, CommandEmpty, CommandErrorBoundary, CommandGroup, CommandHighlight, CommandInput, CommandItem, CommandList, CommandLoading, CommandPage, CommandSeparator, CommandShortcut, CommandStableContext, CommandStateContext, createKeydownHandler, useCommand, useCommandDevtools, useCommandState, useRegisterGroup, useRegisterItem, useVirtualizer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modern-cmdk",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "type": "module",
5
5
  "description": "The definitive command palette engine for the modern web",
6
6
  "license": "MIT",
@@ -62,7 +62,7 @@
62
62
  "devDependencies": {
63
63
  "globby": "16.2.4",
64
64
  "jscodeshift": "17.4.0",
65
- "radix-ui": "1.6.7",
65
+ "radix-ui": "1.8.2-rc.1791984254107",
66
66
  "@types/jscodeshift": "17.3.0"
67
67
  },
68
68
  "keywords": [
@@ -80,8 +80,8 @@
80
80
  "directory": "packages/modern-cmdk"
81
81
  },
82
82
  "scripts": {
83
- "build": "tsdown --config tsdown.config.ts && node -e \"const fs=require('fs');fs.cpSync('src/react/styles.css','dist/react/styles.css')\"",
84
- "dev": "tsdown src/core/index.ts src/react/index.ts --format esm --dts --watch",
83
+ "build": "tsdown",
84
+ "dev": "tsdown --watch",
85
85
  "typecheck": "tsc --noEmit"
86
86
  }
87
87
  }
package/CHANGELOG.md DELETED
@@ -1,98 +0,0 @@
1
- # modern-cmdk
2
-
3
- ## 1.2.2
4
-
5
- ### Patch Changes
6
-
7
- - [`05d3b74`](https://github.com/ABCrimson/modern-cmdk/commit/05d3b74868419c5076452bcdf23d9b7bc6a3fabd) Thanks [@ABCrimson](https://github.com/ABCrimson)! - Evergreen dependency refresh: bump runtime dependency `idb-keyval` to 6.3.0; rebuild with TypeScript 7.0.2, tsdown 0.23.0-rc.0, and React 19.3 canary 20260826 toolchain.
8
-
9
- - docs: refresh npm README + modernized toolchain — disclose the sole runtime dependency (`idb-keyval`, lazy-loaded only for IndexedDB frecency persistence), note ESM-only + `engines.node >= 26.4.0` and the unpublished/experimental WASM engine, and correct the virtualization threshold to `virtualizeThreshold` (default 100).
10
-
11
- ## 1.2.1
12
-
13
- ### Patch Changes
14
-
15
- - **docs: documentation accuracy pass** — Corrected the codemod CLI usage everywhere to its real positional form `npx modern-cmdk <transform> <glob>` (one transform per run; only `--dry-run` and `--concurrency=N` are accepted). The previous `migrate` / `--transform` / `--verbose` / `--extensions` / `--ignore` forms never matched the implementation. Replaced the inaccurate `sideEffects: false` claim with the actual scoped array (`./dist/react/styles.css`, `./dist/react/index.mjs`), and clarified that the optional `modern-cmdk-search-wasm` engine is experimental and not yet published to npm. No code, API, or behavior changes — republished so the corrected README ships to npm.
16
-
17
- ## 1.2.0
18
-
19
- ### Minor Changes
20
-
21
- - **chore: bleeding-edge evergreen upgrade** — Moved the entire toolchain and dependencies to their newest releases: TypeScript 7.0.1-rc (native compiler), React 19.3 canary, radix-ui 1.6.0, Vite 8.1, Vitest 5, Playwright 1.62, Biome 2.5.1, pnpm 11.9, tsdown 0.22.3, and the Rust/WASM crate to edition 2024 + wasm-bindgen 0.2.126. Raised `engines.node` to `>=26.4.0` and bumped the `idb-keyval` runtime dependency to 6.2.5. No public API or behavior changes.
22
-
23
- - **chore: size-limit measures own code** — The React adapter budget now externalizes the `react`/`react-dom`/`radix-ui` peers and reports the adapter's own gzipped size (~10.2 KB), so the gate stays stable across peer version bumps.
24
-
25
- - **docs: full accuracy pass** — Corrected every version reference, bundle-size figure, and API example across the README, npm page, and the documentation site to match the upgraded code (including the real `FrecencyEngine`, `KeyboardShortcutRegistry`, and `ParsedShortcut` signatures).
26
-
27
- ## 1.1.5
28
-
29
- ### Patch Changes
30
-
31
- - **fix(ci): remove `--coverage` from sharded tests** — Vitest coverage thresholds are incompatible with sharding; removed flag to fix CI failures.
32
-
33
- - **fix: pre-launch readiness** — Aligned package exports, `engines` field, and docs across `modern-cmdk` and `command-search-wasm`. Fixed bundle size limits in root `package.json` and benchmarks documentation (25 KB -> 25.5 KB for React bundle).
34
-
35
- - **docs: comprehensive API reference expansion** — Expanded `apps/docs/api/command.md` with full core engine documentation covering state machine, search engine, frecency, keyboard registry, telemetry, and branded types.
36
-
37
- - **chore: docs and build cleanup** — Fixed `Iterator.range` bug in virtualization guide, aligned tsdown targets across packages, updated README bundle sizes and pnpm version.
38
-
39
- ## 1.1.4
40
-
41
- ### Patch Changes
42
-
43
- - **fix(ci): resolve all 7 Biome lint/format errors** — Trailing zero in OKLCH value, import ordering (value before type), regex line width wrapping, `useExhaustiveDependencies` dependency extraction, `expect.poll()` chain formatting, `noUncheckedIndexedAccess` narrowing in `objectGroupBy`.
44
-
45
- - **chore(ci): modernize all GitHub Actions workflows** — Added explicit `permissions` blocks (principle of least privilege) and `timeout-minutes` to all jobs across ci.yml, benchmarks.yml, codeql.yml, docs.yml, and release.yml. Improved CI summary table with status labels. Added `security-extended` query suite to CodeQL. Optimized build commands in benchmarks and release workflows.
46
-
47
- - **chore(deps): enhance Dependabot configuration** — Added dependency groups for TypeScript, Biome, Playwright, and Vitest. Added ignore rules to prevent major version bumps on pinned React pre-releases.
48
-
49
- ## 1.1.3
50
-
51
- ### Patch Changes
52
-
53
- - **fix(react): virtualization now removes off-screen items from the DOM** — Items check `visibleIdSet` before rendering, reducing DOM nodes from thousands to ~30 in virtualized lists. Latch-based auto-virtualization with hysteresis prevents race conditions.
54
-
55
- - **fix(core): replace browser-incompatible ES2026 APIs with cross-browser helpers** — Replaced `Temporal.Now.instant()` / `Temporal.Duration` with `Date.now()`, `Math.sumPrecise` with `+=` loops, `Map.groupBy` / `Object.groupBy` with helper functions, `Set.intersection` / `.difference` / `.union` / `.isSubsetOf` with set operation helpers, `Promise.try` with `Promise.resolve().then()`, `String.isWellFormed` with regex-based surrogate replacement. All Iterator Helpers, `using`/`await using`, `Promise.withResolvers`, and `RegExp.escape` remain (supported in target browsers).
56
-
57
- - **fix(css): WCAG 2.1 AA contrast compliance** — Updated OKLCH color values in dark mode (`--text-muted: oklch(0.83)`, `--text-secondary: oklch(0.75)`) and light mode (`--text-secondary: oklch(0.38)`, `--text-muted: oklch(0.48)`, `--accent: oklch(0.45)`) to meet 4.5:1 contrast ratio requirements. Re-enabled axe-core color-contrast checks in E2E tests.
58
-
59
- - **fix(css): RTL support** — Changed `transform-origin: left center` to `transform-origin: inline-start center` for logical property compliance.
60
-
61
- - **fix(e2e): test reliability improvements** — Replaced snapshot reads (`getAttribute`) with auto-retrying assertions (`toHaveAttribute`, `expect.poll()`) throughout virtualization, accessibility, and keyboard test suites. Virtualization tests use `?count=2000` instead of being skipped in CI.
62
-
63
- ## 1.0.2
64
-
65
- ### Patch Changes
66
-
67
- - [`f5576bb`](https://github.com/ABCrimson/modern-cmdk/commit/f5576bb917e8d254aae20b419ea02dccfbcab7cd) Thanks [@ABCrimson](https://github.com/ABCrimson)! - Performance: split React context to prevent all-item re-renders, O(1) filtered set lookup, single-pass index build, lazy iterators. Fix CSS sideEffects, invalid transform-origin, GPU will-change misuse. Fix broken docs examples and README links.
68
-
69
- ## 1.0.1
70
-
71
- ### Patch Changes
72
-
73
- - [`f6a9294`](https://github.com/ABCrimson/modern-cmdk/commit/f6a9294d0f868b4848cfad40770f455f3745d56e) Thanks [@ABCrimson](https://github.com/ABCrimson)! - Fix lint issues, O(1) navigate lookup, error-resilient fuzzy scorer, and modernize branding
74
-
75
- ## 1.0.0
76
-
77
- ### Major Changes
78
-
79
- - [`f00ac85`](https://github.com/ABCrimson/modern-cmdk/commit/f00ac85f23a9823234f507015c423d0aa066a12c) Thanks [@ABCrimson](https://github.com/ABCrimson)! - modern-cmdk 1.0.0 — consolidated package replacing @crimson_dev/command + @crimson_dev/command-react + @crimson_dev/command-codemod.
80
-
81
- ### Import paths
82
-
83
- - `import { createCommandMachine } from 'modern-cmdk'` — core engine
84
- - `import { Command } from 'modern-cmdk/react'` — React 19 adapter
85
- - `import 'modern-cmdk/styles.css'` — default styles
86
- - `npx modern-cmdk <transform> <glob>` — codemods
87
-
88
- ### Highlights
89
-
90
- - Pure TypeScript state machine with zero DOM dependencies
91
- - 14 React 19 compound components with Radix UI Dialog
92
- - Built-in fuzzy search with incremental filtering
93
- - Frecency ranking with time-based decay
94
- - Keyboard shortcut registry
95
- - GPU-composited CSS animations
96
- - Full WAI-ARIA combobox pattern
97
- - Automatic virtualization at 100+ items
98
- - ES2026: Iterator Helpers, Explicit Resource Management, cross-browser helpers