@alchemy.run/sigil 0.0.0-alpha.8 → 0.1.0-alpha.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.
Files changed (40) hide show
  1. package/README.md +176 -0
  2. package/THIRD_PARTY_NOTICES.md +28 -0
  3. package/dist/ansi.d.ts +53 -53
  4. package/dist/capabilities.js +1 -1
  5. package/dist/{color-policy-DlrZXC0f.js → color-policy-BAC9-TZX.js} +15 -1
  6. package/dist/color.d.ts +8 -8
  7. package/dist/{devtools-DbthxoD1.js → devtools-B_2SDRaO.js} +3 -0
  8. package/dist/index.d.ts +209 -42
  9. package/dist/index.js +354 -171
  10. package/dist/jsx-dev-runtime.d.ts +3 -0
  11. package/dist/jsx-dev-runtime.js +7 -0
  12. package/dist/jsx-runtime-BS_OosoY.js +42 -0
  13. package/dist/jsx-runtime.d.ts +2 -0
  14. package/dist/jsx-runtime.js +8 -0
  15. package/dist/react-CeO3oT_g.js +394 -0
  16. package/dist/react.d.ts +2 -0
  17. package/dist/react.js +50 -0
  18. package/dist/rolldown-runtime-BPOCksWG.js +24 -0
  19. package/dist/router.d.ts +26 -26
  20. package/dist/router.js +45 -42
  21. package/dist/{session-Cg6STjFV.js → session-DDQ5V300.js} +34 -11
  22. package/dist/terminal.d.ts +9 -10
  23. package/dist/terminal.js +1 -1
  24. package/dist/use-focus-B1WVNBQm.js +8383 -0
  25. package/package.json +27 -15
  26. package/src/ansi/strip.ts +2 -2
  27. package/src/capabilities/query.ts +22 -0
  28. package/src/components/VirtualList.tsx +128 -0
  29. package/src/devtools.ts +5 -0
  30. package/src/hooks/use-virtual-scroll.ts +84 -0
  31. package/src/hooks/use-window-size.ts +10 -3
  32. package/src/index.ts +8 -0
  33. package/src/input-parser.ts +31 -11
  34. package/src/jsx-dev-runtime.ts +3 -0
  35. package/src/jsx-runtime.ts +6 -0
  36. package/src/react.ts +53 -0
  37. package/src/reconciler.ts +51 -0
  38. package/src/terminal/input.ts +11 -5
  39. package/src/virtual-scroll.ts +133 -0
  40. package/dist/use-focus-BNG0xsb7.js +0 -1337
package/README.md CHANGED
@@ -164,6 +164,7 @@ _(PRs welcome. Append new entries at the end. Repos must have 100+ stars and sho
164
164
  - [`<Spacer>`](#spacer)
165
165
  - [`<Static>`](#static)
166
166
  - [`<Transform>`](#transform)
167
+ - [`<VirtualList>`](#virtuallist)
167
168
  - [Hooks](#hooks)
168
169
  - [`useInput`](#useinputinputhandler-options)
169
170
  - [`usePaste`](#usepastehandler-options)
@@ -171,6 +172,7 @@ _(PRs welcome. Append new entries at the end. Repos must have 100+ stars and sho
171
172
  - [`useStdin`](#usestdin)
172
173
  - [`useStdout`](#usestdout)
173
174
  - [`useBoxMetrics`](#useboxmetricsref)
175
+ - [`useVirtualScroll`](#usevirtualscrolloptions)
174
176
  - [`useStderr`](#usestderr)
175
177
  - [`useWindowSize`](#usewindowsize)
176
178
  - [`useFocus`](#usefocusoptions)
@@ -1655,6 +1657,87 @@ Type: `number`
1655
1657
 
1656
1658
  The zero-indexed line number of the line that's currently being transformed.
1657
1659
 
1660
+ ### `<VirtualList>`
1661
+
1662
+ A vertically windowed list. Only the items that intersect the viewport are rendered, inside a clipped box that scrolls by whole rows. Items may have different heights, and the item at the top edge may be partially visible.
1663
+
1664
+ Give it a fixed `height`, or omit it and bound an ancestor instead: the list then takes the height of its content and shrinks to whatever rows the container leaves over. Siblings that must keep their size need `flexShrink={0}`, because every `<Box>` shrinks by default.
1665
+
1666
+ ```jsx
1667
+ import { useState } from "react";
1668
+ import { render, Box, Text, VirtualList, useInput, useWindowSize } from "@alchemy.run/sigil";
1669
+
1670
+ const entries = Array.from({ length: 200 }, (_, index) => `entry ${index}`);
1671
+
1672
+ const Example = () => {
1673
+ const { rows } = useWindowSize();
1674
+ const [cursor, setCursor] = useState(0);
1675
+
1676
+ useInput((_, key) => {
1677
+ if (key.upArrow) setCursor((index) => Math.max(0, index - 1));
1678
+ if (key.downArrow) setCursor((index) => Math.min(entries.length - 1, index + 1));
1679
+ });
1680
+
1681
+ return (
1682
+ <Box flexDirection="column" maxHeight={rows}>
1683
+ <Box flexShrink={0}>
1684
+ <Text bold>Entries</Text>
1685
+ </Box>
1686
+ <VirtualList
1687
+ items={entries}
1688
+ itemHeight={() => 1}
1689
+ focusedIndex={cursor}
1690
+ renderItem={(entry, index) => <Text inverse={index === cursor}>{entry}</Text>}
1691
+ />
1692
+ <Box flexShrink={0}>
1693
+ <Text dimColor>↑/↓ move</Text>
1694
+ </Box>
1695
+ </Box>
1696
+ );
1697
+ };
1698
+
1699
+ render(<Example />);
1700
+ ```
1701
+
1702
+ #### items
1703
+
1704
+ Type: `ReadonlyArray<Item>`
1705
+
1706
+ Items to window over.
1707
+
1708
+ #### itemHeight
1709
+
1710
+ Type: `(item: Item, index: number) => number`
1711
+
1712
+ Height of an item in rows. It must match what `renderItem` produces for it: the window is computed from these numbers, never from the rendered output.
1713
+
1714
+ #### renderItem
1715
+
1716
+ Type: `(item: Item, index: number) => ReactNode`
1717
+
1718
+ Render one item. Only items intersecting the viewport are rendered.
1719
+
1720
+ #### getKey
1721
+
1722
+ Type: `(item: Item, index: number) => React.Key`
1723
+
1724
+ React key for an item. Defaults to its index.
1725
+
1726
+ #### focusedIndex
1727
+
1728
+ Type: `number`
1729
+
1730
+ Item to keep fully visible. When it changes, the list scrolls as little as necessary to show it. An item taller than the viewport is aligned to its top.
1731
+
1732
+ #### height
1733
+
1734
+ Type: `number`
1735
+
1736
+ Viewport height in rows. When omitted the list shrinks to the space its container leaves over, as described above.
1737
+
1738
+ > [!NOTE]
1739
+ > Until the first layout pass has measured the viewport, every item is rendered inside the clipped box so the first frame already looks right.
1740
+
1658
1741
  ## Hooks
1659
1742
 
1660
1743
  ### useInput(inputHandler, options?)
@@ -2174,6 +2257,99 @@ Whether the currently tracked element has been measured.
2174
2257
  > [!NOTE]
2175
2258
  > The hook returns `{width: 0, height: 0, left: 0, top: 0}` until the first layout pass completes. It also returns zeros when the tracked ref is detached.
2176
2259
 
2260
+ ### useVirtualScroll(options)
2261
+
2262
+ A React hook that owns the scroll position of a windowed list and returns which items to render for it. The position is clamped to the scrollable range and, while `focusedIndex` is set, moved as little as necessary to keep that item fully visible.
2263
+
2264
+ [`<VirtualList>`](#virtuallist) wraps this hook. Use it directly to draw your own chrome around the window, such as overflow markers or a scrollbar.
2265
+
2266
+ ```jsx
2267
+ import { Box, Text, useVirtualScroll } from "@alchemy.run/sigil";
2268
+
2269
+ const Example = ({ lines, cursor }) => {
2270
+ const { start, end, offset, hiddenAbove, hiddenBelow } = useVirtualScroll({
2271
+ count: lines.length,
2272
+ itemHeight: () => 1,
2273
+ viewportHeight: 10,
2274
+ focusedIndex: cursor,
2275
+ });
2276
+
2277
+ return (
2278
+ <Box flexDirection="column">
2279
+ <Text dimColor>{hiddenAbove > 0 ? `↑ ${hiddenAbove} more` : ""}</Text>
2280
+ <Box flexDirection="column" height={10} overflowY="hidden">
2281
+ <Box flexDirection="column" flexShrink={0} marginTop={offset}>
2282
+ {lines.slice(start, end).map((line, index) => (
2283
+ <Text key={start + index} inverse={start + index === cursor}>
2284
+ {line}
2285
+ </Text>
2286
+ ))}
2287
+ </Box>
2288
+ </Box>
2289
+ <Text dimColor>{hiddenBelow > 0 ? `↓ ${hiddenBelow} more` : ""}</Text>
2290
+ </Box>
2291
+ );
2292
+ };
2293
+ ```
2294
+
2295
+ #### options
2296
+
2297
+ ##### count
2298
+
2299
+ Type: `number`
2300
+
2301
+ Number of items in the list.
2302
+
2303
+ ##### itemHeight
2304
+
2305
+ Type: `(index: number) => number`
2306
+
2307
+ Height of the item at `index` in rows. It must match what the item renders.
2308
+
2309
+ ##### viewportHeight
2310
+
2311
+ Type: `number`
2312
+
2313
+ Rows available to show items.
2314
+
2315
+ ##### focusedIndex
2316
+
2317
+ Type: `number`
2318
+
2319
+ Item that must stay fully visible. An item taller than the viewport is aligned to the top. Out-of-range values are ignored.
2320
+
2321
+ #### Result
2322
+
2323
+ ##### start, end
2324
+
2325
+ Type: `number`
2326
+
2327
+ The items intersecting the viewport are `[start, end)`.
2328
+
2329
+ ##### offset
2330
+
2331
+ Type: `number`
2332
+
2333
+ Position of the `start` item relative to the top of the viewport. Zero or negative: a negative value means the item is partially scrolled out above. Apply it as `marginTop` on the box holding the rendered items.
2334
+
2335
+ ##### scrollTop, maxScrollTop, totalHeight
2336
+
2337
+ Type: `number`
2338
+
2339
+ The effective position, the largest position that still fills the viewport, and the height of every item combined, all in rows.
2340
+
2341
+ ##### hiddenAbove, hiddenBelow
2342
+
2343
+ Type: `number`
2344
+
2345
+ Rows scrolled out above the viewport and rows left below it.
2346
+
2347
+ ##### scrollTo(top), scrollBy(delta)
2348
+
2349
+ Type: `(rows: number) => void`
2350
+
2351
+ Move the viewport. While `focusedIndex` is set, a position that would hide it is corrected on the next render.
2352
+
2177
2353
  ### useStderr()
2178
2354
 
2179
2355
  A React hook that returns the stderr stream and stderr-related utilities.
@@ -179,3 +179,31 @@ Licensed under the MIT License (text above).
179
179
  Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
180
180
 
181
181
  Licensed under the MIT License (text above).
182
+
183
+ ## React
184
+
185
+ The published `dist/` bundles [React](https://github.com/facebook/react),
186
+ `react-reconciler`, and `scheduler` so the renderer owns a single React
187
+ instance.
188
+
189
+ MIT License
190
+
191
+ Copyright (c) Meta Platforms, Inc. and affiliates.
192
+
193
+ Permission is hereby granted, free of charge, to any person obtaining a copy
194
+ of this software and associated documentation files (the "Software"), to deal
195
+ in the Software without restriction, including without limitation the rights
196
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
197
+ copies of the Software, and to permit persons to whom the Software is
198
+ furnished to do so, subject to the following conditions:
199
+
200
+ The above copyright notice and this permission notice shall be included in all
201
+ copies or substantial portions of the Software.
202
+
203
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
204
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
205
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
206
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
208
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
209
+ SOFTWARE.
package/dist/ansi.d.ts CHANGED
@@ -3,7 +3,7 @@ import { A as exitAlternativeScreen, C as enableBracketedPaste, D as eraseLines,
3
3
  import { a as queryClipboard, c as setTerminalProgress, d as tmuxPassthrough, i as notify, l as setWindowTitle, n as TerminalProgressState, o as setClipboard, r as clearClipboard, s as setPointerShape, t as ClipboardSelection, u as setWorkingDirectory } from "./osc-Cn0fw77g.js";
4
4
  import { _ as tokenize, a as StyledChar, c as diffAnsiCodes, d as getLinkStartCode, f as isIntensityCode, g as styledCharsToString, h as styledCharsFromTokens, i as ControlToken, l as endCodesSet, m as reduceAnsiCodesIncremental, n as AnsiToken, o as Token, p as reduceAnsiCodes, r as CharToken, s as ansiCodesToString, t as AnsiCode, u as getEndCode, v as undoAnsiCodes } from "./tokenize-Dx1y_l5H.js";
5
5
  //#region src/ansi/sgr.d.ts
6
- type StylePair = {
6
+ export type StylePair = {
7
7
  readonly open: string;
8
8
  readonly close: string;
9
9
  };
@@ -58,39 +58,39 @@ declare const bgColorCodes: {
58
58
  readonly bgCyanBright: readonly [106, 49];
59
59
  readonly bgWhiteBright: readonly [107, 49];
60
60
  };
61
- type ModifierName = keyof typeof modifierCodes;
62
- type ForegroundColorName = keyof typeof colorCodes;
63
- type BackgroundColorName = keyof typeof bgColorCodes;
64
- type StyleName = ModifierName | ForegroundColorName | BackgroundColorName;
65
- declare const modifierNames: ModifierName[];
66
- declare const foregroundColorNames: ForegroundColorName[];
67
- declare const backgroundColorNames: BackgroundColorName[];
61
+ export type ModifierName = keyof typeof modifierCodes;
62
+ export type ForegroundColorName = keyof typeof colorCodes;
63
+ export type BackgroundColorName = keyof typeof bgColorCodes;
64
+ export type StyleName = ModifierName | ForegroundColorName | BackgroundColorName;
65
+ export declare const modifierNames: ModifierName[];
66
+ export declare const foregroundColorNames: ForegroundColorName[];
67
+ export declare const backgroundColorNames: BackgroundColorName[];
68
68
  /**
69
69
  Named SGR styles as `{open, close}` escape sequence pairs.
70
70
  */
71
- declare const styles: Record<StyleName, StylePair>;
71
+ export declare const styles: Record<StyleName, StylePair>;
72
72
  /**
73
73
  Raw SGR code numbers: open code → close code.
74
74
  */
75
- declare const codes: ReadonlyMap<number, number>;
76
- declare const foreground: {
75
+ export declare const codes: ReadonlyMap<number, number>;
76
+ export declare const foreground: {
77
77
  close: string;
78
78
  ansi: (code: number) => string;
79
79
  ansi256: (code: number) => string;
80
80
  ansi16m: (red: number, green: number, blue: number) => string;
81
81
  };
82
- declare const background: {
82
+ export declare const background: {
83
83
  close: string;
84
84
  ansi: (code: number) => string;
85
85
  ansi256: (code: number) => string;
86
86
  ansi16m: (red: number, green: number, blue: number) => string;
87
87
  };
88
- declare const rgbToAnsi256: (red: number, green: number, blue: number) => number;
89
- declare const hexToRgb: (hex: string) => [number, number, number];
90
- declare const hexToAnsi256: (hex: string) => number;
91
- declare const ansi256ToAnsi: (code: number) => number;
92
- declare const rgbToAnsi: (red: number, green: number, blue: number) => number;
93
- declare const hexToAnsi: (hex: string) => number;
88
+ export declare const rgbToAnsi256: (red: number, green: number, blue: number) => number;
89
+ export declare const hexToRgb: (hex: string) => [number, number, number];
90
+ export declare const hexToAnsi256: (hex: string) => number;
91
+ export declare const ansi256ToAnsi: (code: number) => number;
92
+ export declare const rgbToAnsi: (red: number, green: number, blue: number) => number;
93
+ export declare const hexToAnsi: (hex: string) => number;
94
94
  //#endregion
95
95
  //#region src/ansi/chalk.d.ts
96
96
  type StyleFunction = (text: string) => string;
@@ -104,8 +104,8 @@ type Chalk = NamedStyles & {
104
104
  ansi256: (code: number) => StyleFunction;
105
105
  bgAnsi256: (code: number) => StyleFunction;
106
106
  };
107
- declare const chalk: Chalk;
108
- declare const supportsColor: ColorInfo;
107
+ export declare const chalk: Chalk;
108
+ export declare const supportsColor: ColorInfo;
109
109
  //#endregion
110
110
  //#region src/ansi/hyperlink.d.ts
111
111
  type HyperlinkOptions = {
@@ -136,66 +136,66 @@ import { hyperlink } from "@alchemy.run/sigil/ansi";
136
136
  console.log(hyperlink("Documentation", "https://example.com"));
137
137
  ```
138
138
  */
139
- declare const hyperlink: (text: string, url: string, { fallback, stream }?: HyperlinkOptions) => string;
139
+ export declare const hyperlink: (text: string, url: string, { fallback, stream }?: HyperlinkOptions) => string;
140
140
  //#endregion
141
141
  //#region src/ansi/cursor.d.ts
142
142
  type CursorStream = {
143
143
  isTTY?: boolean;
144
144
  write: (data: string) => unknown;
145
145
  };
146
- declare const cliCursor: {
146
+ export declare const cliCursor: {
147
147
  show(writableStream?: CursorStream): void;
148
148
  hide(writableStream?: CursorStream): void;
149
149
  };
150
150
  //#endregion
151
151
  //#region src/ansi/string-width.d.ts
152
- declare const stringWidth: (input: string) => number;
153
- declare const widestLine: (text: string) => number;
152
+ export declare const stringWidth: (input: string) => number;
153
+ export declare const widestLine: (text: string) => number;
154
154
  //#endregion
155
155
  //#region src/ansi/east-asian-width.d.ts
156
- type EastAsianWidthType = "ambiguous" | "fullwidth" | "halfwidth" | "narrow" | "neutral" | "wide";
157
- declare const ambiguousMinimalCodePoint = 161;
158
- declare const ambiguousMaximumCodePoint = 1114109;
159
- declare const ambiguousRanges: readonly number[];
160
- declare const fullwidthMinimalCodePoint = 12288;
161
- declare const fullwidthMaximumCodePoint = 65510;
162
- declare const fullwidthRanges: readonly number[];
163
- declare const halfwidthMinimalCodePoint = 8361;
164
- declare const halfwidthMaximumCodePoint = 65518;
165
- declare const halfwidthRanges: readonly number[];
166
- declare const narrowMinimalCodePoint = 32;
167
- declare const narrowMaximumCodePoint = 10630;
168
- declare const narrowRanges: readonly number[];
169
- declare const wideMinimalCodePoint = 4352;
170
- declare const wideMaximumCodePoint = 262141;
171
- declare const wideRanges: readonly number[];
172
- declare const isAmbiguous: (codePoint: number) => boolean;
173
- declare const isFullWidth: (codePoint: number) => boolean;
174
- declare const isWide: (codePoint: number) => boolean;
175
- declare function getCategory(codePoint: number): EastAsianWidthType;
176
- declare function eastAsianWidthType(codePoint: number): EastAsianWidthType;
177
- declare function eastAsianWidth(codePoint: number, { ambiguousAsWide }?: {
156
+ export type EastAsianWidthType = "ambiguous" | "fullwidth" | "halfwidth" | "narrow" | "neutral" | "wide";
157
+ export declare const ambiguousMinimalCodePoint = 161;
158
+ export declare const ambiguousMaximumCodePoint = 1114109;
159
+ export declare const ambiguousRanges: readonly number[];
160
+ export declare const fullwidthMinimalCodePoint = 12288;
161
+ export declare const fullwidthMaximumCodePoint = 65510;
162
+ export declare const fullwidthRanges: readonly number[];
163
+ export declare const halfwidthMinimalCodePoint = 8361;
164
+ export declare const halfwidthMaximumCodePoint = 65518;
165
+ export declare const halfwidthRanges: readonly number[];
166
+ export declare const narrowMinimalCodePoint = 32;
167
+ export declare const narrowMaximumCodePoint = 10630;
168
+ export declare const narrowRanges: readonly number[];
169
+ export declare const wideMinimalCodePoint = 4352;
170
+ export declare const wideMaximumCodePoint = 262141;
171
+ export declare const wideRanges: readonly number[];
172
+ export declare const isAmbiguous: (codePoint: number) => boolean;
173
+ export declare const isFullWidth: (codePoint: number) => boolean;
174
+ export declare const isWide: (codePoint: number) => boolean;
175
+ export declare function getCategory(codePoint: number): EastAsianWidthType;
176
+ export declare function eastAsianWidthType(codePoint: number): EastAsianWidthType;
177
+ export declare function eastAsianWidth(codePoint: number, { ambiguousAsWide }?: {
178
178
  ambiguousAsWide?: boolean;
179
179
  }): 1 | 2;
180
180
  /**
181
181
  Grapheme-cluster width test shared by the tokenizer (slice/clip path): the
182
182
  base code point's East Asian Width, plus emoji presentation rules.
183
183
  */
184
- declare function isFullwidthGrapheme(grapheme: string, baseCodePoint: number): boolean;
184
+ export declare function isFullwidthGrapheme(grapheme: string, baseCodePoint: number): boolean;
185
185
  /**
186
186
  Wide code points not covered by string-width's CJKT script regex or emoji
187
187
  regex — the fallback bucket of its block parser. A disjoint decomposition of
188
188
  the `wide` table above, kept alongside it so the width data lives in one
189
189
  module.
190
190
  */
191
- declare const isWideNotCJKTNotEmoji: (x: number) => boolean;
192
- declare function isFullwidthCodePoint(codePoint: number): boolean;
191
+ export declare const isWideNotCJKTNotEmoji: (x: number) => boolean;
192
+ export declare function isFullwidthCodePoint(codePoint: number): boolean;
193
193
  //#endregion
194
194
  //#region src/ansi/strip.d.ts
195
- declare const stripAnsi: (input: string) => string;
195
+ export declare const stripAnsi: (input: string) => string;
196
196
  //#endregion
197
197
  //#region src/ansi/slice.d.ts
198
- declare function sliceAnsi(string: string, start: number, end?: number): string;
198
+ export declare function sliceAnsi(string: string, start: number, end?: number): string;
199
199
  //#endregion
200
200
  //#region src/ansi/truncate.d.ts
201
201
  type TruncateOptions = {
@@ -212,6 +212,6 @@ type WrapOptions = {
212
212
  readonly hard?: boolean;
213
213
  readonly wordWrap?: boolean;
214
214
  };
215
- declare function wrapAnsi(string: string, columns: number, options?: WrapOptions): string;
215
+ export declare function wrapAnsi(string: string, columns: number, options?: WrapOptions): string;
216
216
  //#endregion
217
- export { AnsiCode, AnsiToken, BEL, BackgroundColorName, C1_CSI, C1_ST, CSI, CharToken, ClipboardSelection, ControlToken, CursorShape, DEL, ESC, EastAsianWidthType, ForegroundColorName, ModifierName, OSC, ST, StyleName, StylePair, StyledChar, TerminalProgressState, Token, ambiguousMaximumCodePoint, ambiguousMinimalCodePoint, ambiguousRanges, ansi256ToAnsi, ansiCodesToString, ansiEscapes, background, backgroundColorNames, bsu, chalk, clearClipboard, clearTerminal, cliCursor, codes, cursorColor, cursorDown, cursorHide, cursorLeft, cursorNextLine, cursorShape, cursorShow, cursorTo, cursorUp, diffAnsiCodes, disableBracketedPaste, eastAsianWidth, eastAsianWidthType, enableBracketedPaste, endCodesSet, enterAlternativeScreen, eraseEndLine, eraseLine, eraseLines, eraseScreen, esu, exitAlternativeScreen, foreground, foregroundColorNames, fullwidthMaximumCodePoint, fullwidthMinimalCodePoint, fullwidthRanges, getCategory, getEndCode, getLinkStartCode, halfwidthMaximumCodePoint, halfwidthMinimalCodePoint, halfwidthRanges, hexToAnsi, hexToAnsi256, hexToRgb, hyperlink, isAmbiguous, isFullWidth, isFullwidthCodePoint, isFullwidthGrapheme, isIntensityCode, isWide, isWideNotCJKTNotEmoji, kittyQuery, link, modifierNames, narrowMaximumCodePoint, narrowMinimalCodePoint, narrowRanges, notify, pasteEnd, pasteStart, popKittyKeyboard, pushKittyKeyboard, queryClipboard, reduceAnsiCodes, reduceAnsiCodesIncremental, resetCursorColor, rgbToAnsi, rgbToAnsi256, setClipboard, setPointerShape, setTerminalProgress, setWindowTitle, setWorkingDirectory, sliceAnsi, stringWidth, stripAnsi, styledCharsFromTokens, styledCharsToString, styles, supportsColor, tmuxPassthrough, tokenize, cliTruncate as truncateAnsi, undoAnsiCodes, wideMaximumCodePoint, wideMinimalCodePoint, wideRanges, widestLine, wrapAnsi };
217
+ export { AnsiCode, AnsiToken, BEL, C1_CSI, C1_ST, CSI, CharToken, ClipboardSelection, ControlToken, CursorShape, DEL, ESC, OSC, ST, StyledChar, TerminalProgressState, Token, ansiCodesToString, ansiEscapes, bsu, clearClipboard, clearTerminal, cursorColor, cursorDown, cursorHide, cursorLeft, cursorNextLine, cursorShape, cursorShow, cursorTo, cursorUp, diffAnsiCodes, disableBracketedPaste, enableBracketedPaste, endCodesSet, enterAlternativeScreen, eraseEndLine, eraseLine, eraseLines, eraseScreen, esu, exitAlternativeScreen, getEndCode, getLinkStartCode, isIntensityCode, kittyQuery, link, notify, pasteEnd, pasteStart, popKittyKeyboard, pushKittyKeyboard, queryClipboard, reduceAnsiCodes, reduceAnsiCodesIncremental, resetCursorColor, setClipboard, setPointerShape, setTerminalProgress, setWindowTitle, setWorkingDirectory, styledCharsFromTokens, styledCharsToString, tmuxPassthrough, tokenize, cliTruncate as truncateAnsi, undoAnsiCodes };
@@ -1,3 +1,3 @@
1
1
  import { a as detectTerminal, i as detectHyperlinkSupport, n as detectCapabilities, o as detectUnicodeSupport, r as detectColorLevel, t as createSupportsColor } from "./detect-B3dL4Q11.js";
2
- import { d as queryTerminal, f as refreshTerminalQuery, i as getCapabilities, l as getTerminalQuery, n as resolveColorProfile, r as capabilities, s as applyTerminalQuery, t as colorState } from "./color-policy-DlrZXC0f.js";
2
+ import { f as queryTerminal, i as getCapabilities, l as getTerminalQuery, n as resolveColorProfile, p as refreshTerminalQuery, r as capabilities, s as applyTerminalQuery, t as colorState } from "./color-policy-BAC9-TZX.js";
3
3
  export { applyTerminalQuery, capabilities, colorState, createSupportsColor, detectCapabilities, detectColorLevel, detectHyperlinkSupport, detectTerminal, detectUnicodeSupport, getCapabilities, getTerminalQuery, queryTerminal, refreshTerminalQuery, resolveColorProfile };
@@ -66,6 +66,18 @@ const kittyGraphicsResponse = new RegExp(`_G([^]*)\\\\`);
66
66
  const winopsResponse = new RegExp(`\\[(4|6);(\\d+);(\\d+)t`);
67
67
  const colorSchemeResponse = new RegExp(`\\[\\?997;(\\d+)n`);
68
68
  const da1Response = new RegExp(`\\[\\?([\\d;]*)c`);
69
+ const terminalResponses = [
70
+ oscColorResponse,
71
+ kittyKeyboardResponse,
72
+ decrqmResponse,
73
+ xtversionResponse,
74
+ xtgettcapResponse,
75
+ kittyGraphicsResponse,
76
+ winopsResponse,
77
+ colorSchemeResponse,
78
+ da1Response
79
+ ].map((pattern) => new RegExp(`^(?:${pattern.source})$`));
80
+ const isTerminalQueryResponse = (sequence) => terminalResponses.some((pattern) => pattern.test(sequence));
69
81
  const buildQuery = (palette, scope) => {
70
82
  const queries = [
71
83
  `${OSC}10;?`,
@@ -125,6 +137,7 @@ const queryTerminal = async (stdin, stdout, { timeout = 500, palette = true, sco
125
137
  if (done) return;
126
138
  done = true;
127
139
  clearTimeout(timer);
140
+ stdin.pause();
128
141
  stdin.removeListener("data", onData);
129
142
  if (paletteColors.size === paletteSize) result.palette = Array.from({ length: paletteSize }, (_, index) => paletteColors.get(index));
130
143
  result.systemAppearance = reportedAppearance;
@@ -213,6 +226,7 @@ const queryTerminal = async (stdin, stdout, { timeout = 500, palette = true, sco
213
226
  };
214
227
  stdin.on("data", onData);
215
228
  const timer = setTimeout(finish, timeout);
229
+ stdin.resume();
216
230
  stdout.write(buildQuery(palette, scope));
217
231
  });
218
232
  const queryPromises = /* @__PURE__ */ new WeakMap();
@@ -575,4 +589,4 @@ function colorState(capabilities, policy = "auto") {
575
589
  };
576
590
  }
577
591
  //#endregion
578
- export { registerTerminalIntegration as a, ensureTerminalQuery as c, queryTerminal as d, refreshTerminalQuery as f, getCapabilities as i, getTerminalQuery as l, resolveColorProfile as n, getRawModeStream as o, capabilities as r, applyTerminalQuery as s, colorState as t, getTerminalQueryPromise as u };
592
+ export { registerTerminalIntegration as a, ensureTerminalQuery as c, isTerminalQueryResponse as d, queryTerminal as f, getCapabilities as i, getTerminalQuery as l, resolveColorProfile as n, getRawModeStream as o, refreshTerminalQuery as p, capabilities as r, applyTerminalQuery as s, colorState as t, getTerminalQueryPromise as u };
package/dist/color.d.ts CHANGED
@@ -2,20 +2,20 @@ import { c as Color, d as RgbColor } from "./color-profile-CyeHnG1T.js";
2
2
  import { _ as perimeterGradient, a as LinearGradient, c as PaintContext, d as adaptive, f as ansi, g as perProfile, h as named, i as InterpolationSpace, l as PerimeterGradient, m as linearGradient, n as ColorInput, o as NamedColor, p as ansi256, r as GradientStop, s as Paint, t as AdaptiveColor, u as ProfileColor, v as rgb } from "./paint-Cx-zC_sX.js";
3
3
  import { n as Rect } from "./geometry-BxXOzJgo.js";
4
4
  //#region src/color/palette.d.ts
5
- declare const canonicalAnsiPalette: readonly RgbColor[];
6
- declare function colorToRgb(color: Color, palette?: readonly {
5
+ export declare const canonicalAnsiPalette: readonly RgbColor[];
6
+ export declare function colorToRgb(color: Color, palette?: readonly {
7
7
  r: number;
8
8
  g: number;
9
9
  b: number;
10
10
  }[]): RgbColor;
11
11
  //#endregion
12
12
  //#region src/color/sample.d.ts
13
- declare function samplePaint(paint: Paint, x: number, y: number, bounds: Rect, context?: PaintContext): Color | undefined;
14
- declare function blend(source: Color, destination: Color, palette?: PaintContext["palette"]): Color;
13
+ export declare function samplePaint(paint: Paint, x: number, y: number, bounds: Rect, context?: PaintContext): Color | undefined;
14
+ export declare function blend(source: Color, destination: Color, palette?: PaintContext["palette"]): Color;
15
15
  /** Progressively moves a color toward white in perceptual OKLab space. */
16
- declare function lighten(color: Color, amount: number, palette?: PaintContext["palette"]): RgbColor;
16
+ export declare function lighten(color: Color, amount: number, palette?: PaintContext["palette"]): RgbColor;
17
17
  /** Progressively moves a color toward black in perceptual OKLab space. */
18
- declare function darken(color: Color, amount: number, palette?: PaintContext["palette"]): RgbColor;
19
- declare function interpolateColor(from: Color, to: Color, amount: number, space?: InterpolationSpace, palette?: PaintContext["palette"]): RgbColor;
18
+ export declare function darken(color: Color, amount: number, palette?: PaintContext["palette"]): RgbColor;
19
+ export declare function interpolateColor(from: Color, to: Color, amount: number, space?: InterpolationSpace, palette?: PaintContext["palette"]): RgbColor;
20
20
  //#endregion
21
- export { AdaptiveColor, ColorInput, GradientStop, InterpolationSpace, LinearGradient, NamedColor, Paint, PaintContext, PerimeterGradient, ProfileColor, adaptive, ansi, ansi256, blend, canonicalAnsiPalette, colorToRgb, darken, interpolateColor, lighten, linearGradient, named, perProfile, perimeterGradient, rgb, samplePaint };
21
+ export { AdaptiveColor, ColorInput, GradientStop, InterpolationSpace, LinearGradient, NamedColor, Paint, PaintContext, PerimeterGradient, ProfileColor, adaptive, ansi, ansi256, linearGradient, named, perProfile, perimeterGradient, rgb };
@@ -50,7 +50,10 @@ Object.defineProperty(globalThis, "__REACT_DEVTOOLS_COMPONENT_FILTERS__", { valu
50
50
  ] });
51
51
  const isDevToolsReachable = () => new Promise((resolve) => {
52
52
  const socket = new WebSocket("ws://localhost:8097");
53
+ let settled = false;
53
54
  const settle = (reachable) => {
55
+ if (settled) return;
56
+ settled = true;
54
57
  clearTimeout(timeout);
55
58
  socket.close();
56
59
  resolve(reachable);