ranuts 0.4.0-alpha.5 → 0.4.1-alpha.2

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 (44) hide show
  1. package/CLAUDE.md +180 -32
  2. package/README.md +2 -0
  3. package/README.zh-CN.md +2 -0
  4. package/dist/{color-DPV7TsVU.js → color-BTvZUuf-.js} +1 -1
  5. package/dist/i18n-DW21b_DJ.js +1 -0
  6. package/dist/index.js +1 -1
  7. package/dist/src/conversation/engine.d.ts +109 -0
  8. package/dist/src/conversation/index.d.ts +12 -0
  9. package/dist/src/conversation/index.js +1 -0
  10. package/dist/src/conversation/types.d.ts +99 -0
  11. package/dist/src/node/index.js +1 -1
  12. package/dist/src/stream/accumulator.d.ts +51 -0
  13. package/dist/src/stream/budget.d.ts +89 -0
  14. package/dist/src/stream/index.d.ts +25 -0
  15. package/dist/src/stream/index.js +1 -0
  16. package/dist/src/stream/sse.d.ts +51 -0
  17. package/dist/src/stream/types.d.ts +106 -0
  18. package/dist/src/utils/binary.d.ts +33 -0
  19. package/dist/src/utils/canvas.d.ts +1 -0
  20. package/dist/src/utils/device.d.ts +8 -0
  21. package/dist/src/utils/diff.d.ts +51 -0
  22. package/dist/src/utils/i18n/index.js +1 -1
  23. package/dist/src/utils/index.d.ts +12 -7
  24. package/dist/src/utils/index.js +1 -1
  25. package/dist/src/utils/number.d.ts +20 -0
  26. package/dist/src/utils/placement.d.ts +42 -5
  27. package/dist/src/utils/scroll.d.ts +93 -0
  28. package/dist/src/utils/secure.d.ts +58 -0
  29. package/dist/src/utils/str.d.ts +75 -0
  30. package/dist/test/budget.test.d.ts +1 -0
  31. package/dist/test/conversation.test.d.ts +1 -0
  32. package/dist/test/diff.test.d.ts +1 -0
  33. package/dist/test/formatBytes.test.d.ts +1 -0
  34. package/dist/test/scroll.test.d.ts +1 -0
  35. package/dist/test/stream.test.d.ts +1 -0
  36. package/dist/test/utils/secure.test.d.ts +1 -0
  37. package/dist/test/utils/text-boundary.test.d.ts +1 -0
  38. package/dist/umd/index.umd.cjs +1 -1
  39. package/dist/umd/utils/utils.umd.cjs +1 -1
  40. package/dist/utils-B4FnyUzW.js +1 -0
  41. package/docs/API.md +94 -6
  42. package/package.json +11 -2
  43. package/dist/i18n-Bq-f7htr.js +0 -1
  44. package/dist/utils-BSvtPyGl.js +0 -1
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Provider-neutral vocabulary for one streamed model response.
3
+ *
4
+ * Every mainstream chat completion API streams the same four things — assistant text,
5
+ * separately-billed reasoning text, tool calls, and a token count — but each names them
6
+ * differently and interleaves them differently. Normalizing to one union at the edge means
7
+ * a renderer, an accumulator, and a test fixture never learn a vendor's wire format.
8
+ *
9
+ * The union is the contract; the shape below is what makes it usable:
10
+ *
11
+ * - **`index` correlates interleaved deltas.** Reasoning and text can arrive interleaved,
12
+ * and a response can open several tool calls at once. Consumers group by `index` rather
13
+ * than assuming a delta belongs to whatever arrived last.
14
+ * - **`block-end` carries the assembled block.** A consumer that accumulated the deltas
15
+ * itself can adopt or verify it; a consumer that only wants finished blocks can ignore
16
+ * every delta.
17
+ * - **Tool arguments stay raw JSON text.** `argumentsDelta` is never parsed mid-stream:
18
+ * half a JSON document is not a value, and pretending otherwise is where streaming tool
19
+ * calls usually break.
20
+ * - **`finish` terminates.** `usage` arrives before it, and nothing follows it. A consumer
21
+ * can treat `finish` as the point where its state is complete.
22
+ *
23
+ * @module ranuts/stream
24
+ */
25
+ /** Discriminator for the content a block accumulates. */
26
+ export type ContentBlockType = 'text' | 'reasoning' | 'tool-call';
27
+ /** Assistant prose addressed to the user. */
28
+ export interface TextBlock {
29
+ type: 'text';
30
+ text: string;
31
+ }
32
+ /**
33
+ * Model reasoning, when the provider exposes it. Kept separate from {@link TextBlock}
34
+ * because it is billed, displayed, and retained differently — a UI usually collapses it,
35
+ * and it is normally dropped from the history sent back on the next request.
36
+ */
37
+ export interface ReasoningBlock {
38
+ type: 'reasoning';
39
+ text: string;
40
+ }
41
+ /** One tool invocation requested by the model. */
42
+ export interface ToolCallBlock {
43
+ type: 'tool-call';
44
+ /** Provider-assigned call id, echoed back with the result. */
45
+ id: string;
46
+ /** Tool name; empty until the provider has sent it. */
47
+ name: string;
48
+ /** Raw JSON text of the arguments — deliberately unparsed. */
49
+ arguments: string;
50
+ }
51
+ /** One completed unit of assistant output. */
52
+ export type ContentBlock = TextBlock | ReasoningBlock | ToolCallBlock;
53
+ /**
54
+ * Why the response ended.
55
+ *
56
+ * `tool-calls` is not a failure: the model finished its turn by asking for tools, and the
57
+ * caller is expected to run them and continue. `aborted` means the consumer stopped the
58
+ * stream, which is why it is distinct from `error`.
59
+ */
60
+ export type FinishReason = 'stop' | 'length' | 'tool-calls' | 'content-filter' | 'error' | 'aborted';
61
+ /** Token counts reported for one response. Every field is optional: providers differ. */
62
+ export interface TokenUsage {
63
+ inputTokens?: number;
64
+ outputTokens?: number;
65
+ /** Reasoning tokens, where the provider bills them separately from output. */
66
+ reasoningTokens?: number;
67
+ /** Input tokens served from a provider-side cache, where reported. */
68
+ cachedInputTokens?: number;
69
+ totalTokens?: number;
70
+ }
71
+ /**
72
+ * One normalized event from a streamed response.
73
+ *
74
+ * `block-start` is optional in practice — several providers begin a block with its first
75
+ * delta — so consumers must tolerate a delta for an index they have not seen.
76
+ * {@link createStreamAccumulator} does.
77
+ */
78
+ export type StreamChunk = {
79
+ type: 'block-start';
80
+ index: number;
81
+ blockType: ContentBlockType;
82
+ } | {
83
+ type: 'text-delta';
84
+ index: number;
85
+ text: string;
86
+ } | {
87
+ type: 'reasoning-delta';
88
+ index: number;
89
+ text: string;
90
+ } | {
91
+ type: 'tool-call-delta';
92
+ index: number;
93
+ id: string;
94
+ name?: string;
95
+ argumentsDelta: string;
96
+ } | {
97
+ type: 'block-end';
98
+ index: number;
99
+ block: ContentBlock;
100
+ } | {
101
+ type: 'usage';
102
+ usage: TokenUsage;
103
+ } | {
104
+ type: 'finish';
105
+ reason: FinishReason;
106
+ };
@@ -28,6 +28,39 @@ export declare const bytesToBase64: (data: Uint8Array | ArrayBuffer) => string;
28
28
  * @return {Uint8Array}
29
29
  */
30
30
  export declare const base64ToBytes: (base64: string) => Uint8Array<ArrayBuffer>;
31
+ /**
32
+ * @description: Encode bytes as base64url — the URL- and filename-safe alphabet from RFC 4648
33
+ * §5, with `+/` swapped for `-_` and the `=` padding dropped.
34
+ *
35
+ * This is the spelling JWTs, WebAuthn payloads, OAuth device codes and anything that rides in
36
+ * a query string or a path segment use. Plain base64 breaks in all of those: `+` becomes a
37
+ * space when a form-encoded value is parsed, and `/` splits a path.
38
+ *
39
+ * @param {Uint8Array | ArrayBuffer} data
40
+ * @return {string}
41
+ */
42
+ export declare const bytesToBase64Url: (data: Uint8Array | ArrayBuffer) => string;
43
+ /**
44
+ * @description: Decode base64url back into bytes, restoring the padding the encoder dropped.
45
+ * Returns `null` on anything that is not valid base64url, because the usual caller is
46
+ * checking a token someone else supplied and a throw there is just a crash with extra steps.
47
+ *
48
+ * @param {string} value
49
+ * @return {Uint8Array | null}
50
+ */
51
+ export declare const base64UrlToBytes: (value: string) => Uint8Array | null;
52
+ /**
53
+ * @description: Join byte chunks into one buffer, in order.
54
+ *
55
+ * The reason this exists as its own function: text that arrives in chunks must be joined
56
+ * *before* it is decoded, never after. A multi-byte UTF-8 character straddling a chunk
57
+ * boundary decodes to replacement characters when each chunk is decoded on its own, and the
58
+ * damage is invisible until someone reads a log with a Chinese name in it.
59
+ *
60
+ * @param {Uint8Array[]} chunks
61
+ * @return {Uint8Array}
62
+ */
63
+ export declare const concatBytes: (chunks: readonly Uint8Array[]) => Uint8Array;
31
64
  /** @description: Whether the bytes start with the gzip magic number (1f 8b). */
32
65
  export declare const isGzip: (bytes: Uint8Array) => boolean;
33
66
  /**
@@ -50,5 +50,6 @@ export declare const roundRectByArc: (ctx: CanvasRenderingContext2D, ...[x, y, w
50
50
  * @param {number} h rectangle height
51
51
  * @param {string} background a string such as `linear-gradient(90deg, red, blue)`
52
52
  * @return {CanvasGradient} assignable straight to fillStyle / strokeStyle
53
+ * @throws {TypeError} when `background` is not a `linear-gradient(...)` value
53
54
  */
54
55
  export declare const getLinearGradient: (ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, background: string) => CanvasGradient;
@@ -11,6 +11,14 @@ export declare enum DEVICE {
11
11
  }
12
12
  export type CurrentDevice = 'ipad' | 'android' | 'iphone' | 'pc';
13
13
  export declare const currentDevice: () => CurrentDevice;
14
+ /**
15
+ * @description: Whether a `window` existed **when this module was first imported**.
16
+ *
17
+ * @deprecated Evaluated once at module load, so it is stuck at `false` for the life of the
18
+ * process in any SSR-then-hydrate flow, and cannot be stubbed in a test. New code checks
19
+ * `typeof window === 'undefined'` inside the function that needs it. Kept exported so
20
+ * existing callers keep compiling.
21
+ */
14
22
  export declare const isClient: boolean;
15
23
  /** Viewport breakpoint, matching where the mobile layout takes over */
16
24
  export declare const MOBILE_MEDIA_QUERY = "(max-width: 768px)";
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Line-level text diff.
3
+ *
4
+ * Enough to render "what changed in this file" — a review card, a tool result, a config
5
+ * preview — without a diff library. It is deliberately line-level: word- and
6
+ * character-level diffing is a different problem with different trade-offs, and a
7
+ * component that renders lines gains nothing from it.
8
+ *
9
+ * The shape is the familiar unified-diff one, because that is what consumers already know
10
+ * how to render and because it is what a server-side producer would send.
11
+ */
12
+ /** What happened to one line. */
13
+ export type DiffLineKind = 'context' | 'added' | 'removed';
14
+ /** One line of a diff, carrying both line numbers so a gutter can show either side. */
15
+ export interface DiffLine {
16
+ kind: DiffLineKind;
17
+ text: string;
18
+ /** 1-based line number on the old side, or null for an added line. */
19
+ oldLine: number | null;
20
+ /** 1-based line number on the new side, or null for a removed line. */
21
+ newLine: number | null;
22
+ }
23
+ /** A run of changed lines plus the context around it. */
24
+ export interface DiffHunk {
25
+ /** 1-based first old-side line in this hunk; 0 when the old side is empty. */
26
+ oldStart: number;
27
+ oldLines: number;
28
+ /** 1-based first new-side line in this hunk; 0 when the new side is empty. */
29
+ newStart: number;
30
+ newLines: number;
31
+ lines: DiffLine[];
32
+ }
33
+ /** How to compute a diff. */
34
+ export interface DiffOptions {
35
+ /** Unchanged lines kept either side of a change. Defaults to 3. */
36
+ context?: number;
37
+ }
38
+ /**
39
+ * Diffs two texts by line.
40
+ *
41
+ * A common prefix and suffix are matched directly, so a one-line edit in a large file
42
+ * costs almost nothing; only the differing middle goes through the quadratic table. Past
43
+ * {@link MAX_TABLE_CELLS} that middle degrades to a wholesale replacement rather than
44
+ * allocating an unbounded table.
45
+ *
46
+ * @param oldText The text before. Pass `''` for a file being created.
47
+ * @param newText The text after. Pass `''` for a file being deleted.
48
+ * @param options Context size.
49
+ * @returns Hunks in order; empty when the texts are identical.
50
+ */
51
+ export declare function diffLines(oldText: string, newText: string, options?: DiffOptions): DiffHunk[];
@@ -1 +1 @@
1
- import{n as r,r as s,t as a}from"../../../i18n-Bq-f7htr.js";export{a as I18nCore,r as createI18n,s as useI18n};
1
+ import{n as r,r as s,t as a}from"../../../i18n-DW21b_DJ.js";export{a as I18nCore,r as createI18n,s as useI18n};
@@ -1,6 +1,10 @@
1
+ import { createBottomFollower } from './scroll';
2
+ import { diffLines } from './diff';
1
3
  import { SyncHook } from './subscribe';
2
- import { Mathjs, addNumSym, clamp, fit, inverseLerp, lerp, linearstep, mathjs, parseChineseNumber, parseEnglishNumber, parseRomanNumber, perToNum, range, remap, smoothstep, transformNumber } from './number';
3
- import { MessageCodec, arrayBufferToString, checkEncoding, clearBr, clearStr, getMatchingSentences, getRandomString, isString, md5, randomString, strParse, toFullWidth, toHalfWidth, toString, transformText, truncate } from './str';
4
+ import { Mathjs, addNumSym, formatBytes, clamp, fit, inverseLerp, lerp, linearstep, mathjs, parseChineseNumber, parseEnglishNumber, parseRomanNumber, perToNum, range, remap, smoothstep, transformNumber } from './number';
5
+ import { MessageCodec, arrayBufferToString, checkEncoding, clearBr, clearStr, getMatchingSentences, getRandomString, isString, md5, randomString, strParse, toFullWidth, toHalfWidth, toString, transformText, truncate, truncateWithMarker, fenceCode, slugify, csvEscape } from './str';
6
+ import type { BottomFollower, BottomFollowerOptions } from './scroll';
7
+ import type { DiffHunk, DiffLine, DiffLineKind, DiffOptions } from './diff';
4
8
  import type { TransformText, TruncateOptions, TruncatePosition } from './str';
5
9
  import { createSpeechRecognizer, isSpeechRecognitionSupported } from './speech';
6
10
  import type { SpeechError, SpeechErrorKind, SpeechRecognizer, SpeechRecognizerOptions } from './speech';
@@ -41,11 +45,12 @@ import { I18nCore, createI18n, useI18n } from './i18n';
41
45
  import type { I18nConfig, LocaleChangeHandler, LocaleMessages, MessageDict, StringValues, TranslateParams } from './i18n';
42
46
  import { createLocalePath } from './localePath';
43
47
  import type { LocalePath, LocalePathConfig, LocaleRoute } from './localePath';
44
- import { computePlacement } from './placement';
45
- import type { ComputePlacementOptions, ComputedPlacement, Placement, PlacementRect } from './placement';
48
+ import { alignCrossAxis, computePlacement } from './placement';
49
+ import type { ComputePlacementOptions, ComputedPlacement, Placement, PlacementAlign, PlacementRect, PlacementSide } from './placement';
46
50
  import type { ResolveLocaleOptions, TextLanguage } from './lang';
47
51
  import { readFileAsArrayBuffer, readFileAsDataURL, readFileAsText, readFileAsUint8Array } from './file';
48
- import { base64ToBytes, bytesToBase64, decodeTextBytes, fetchMaybeGzip, gunzipMaybe, isGzip, isHtmlDocument, isZipContainer, saveFileToDisk } from './binary';
52
+ import { base64ToBytes, bytesToBase64, decodeTextBytes, fetchMaybeGzip, gunzipMaybe, isGzip, isHtmlDocument, isZipContainer, saveFileToDisk, bytesToBase64Url, base64UrlToBytes, concatBytes } from './binary';
53
+ import { UNAMBIGUOUS_ALPHABET, safeEqual, secureRandomString, secureToken } from './secure';
49
54
  import { WorkerClient, serveWorker } from './worker';
50
55
  import type { ServeWorkerOptions, WorkerClientOptions, WorkerHandlerContext, WorkerRequestBase, WorkerResponseBase } from './worker';
51
56
  import { isUrlCached, networkAllowsDownload, prefetchUrl, prefetchUrls, prefetchWhenIdle, whenIdle } from './prefetch';
@@ -72,5 +77,5 @@ import type { CurrentDevice } from './device';
72
77
  import { MOBILE_MEDIA_QUERY, currentDevice, isClient, isMobile, isWeiXin, matchMediaQuery, watchMediaQuery } from './device';
73
78
  import { Color, ColorScheme, FMT, HEX_COLOR_REGEX, Hsl, Hsla, RGBA_REGEX, RGB_REGEX, Rgb, Rgba, blendMultiply, blendOverlay, blendScreen, brightnessContrast, componentToHex, cosinePalette, hexToAlpha, hexToHsb, hexToHsv, hexToRgb, hsbToHsl, hsbToRgb, hslToHsb, hslToHsv, hslToRgb, hsvToHsl, hsvToRgb, hue2rgb, linearToSrgb, luma, randomColor, rgbToHex, rgbToHsb, rgbToHsl, rgbToHsv, rgbaString, rgbaToHex, rgbaToRgb, saturation, srgbToLinear, vibrance } from '@/utils/color';
74
79
  import type { RGB } from '@/utils/color';
75
- export { performanceTime, timeFormat, timestampToTime, throttle, SyncHook, clearBr, clearStr, isString, randomString, strParse, scriptOnLoad, handleFetchHook, createData, report, QuestQueue, noop, getPerformance, querystring, formatJson, filterObj, merge, replaceOld, mergeExports, perToNum, range, clamp, lerp, inverseLerp, remap, fit, linearstep, smoothstep, Mathjs, mathjs, getStatus, status, Monitor, MimeType, getExtensions, setMime, getMime, memoize, once, isImageSize, convertImageToBase64, handleError, addClassToElement, removeClassToElement, createDocumentFragment, escapeHtml, isClient, isWeiXin, isMobile, debounce, currentDevice, handleConsole, compose, Color, FMT, Hsl, Hsla, Rgb, Rgba, randomColor, hexToRgb, componentToHex, rgbToHex, rgbToHsl, hue2rgb, hslToRgb, rgbToHsb, hsbToRgb, hsvToRgb, hsvToHsl, ColorScheme, AudioRecorder, getCookie, requestUrlToBuffer, getPixelRatio, createObjectURL, getFrame, getAllQueryString, queryFlag, isInIframe, appendUrl, getCookieByName, getWindow, connection, encodeUrl, imageRequest, durationHandler, networkSpeed, TOTP, localStorageGetItem, localStorageSetItem, localStorageRemoveItem, createStore, setFontSize2html, autosizeTextarea, createSpeechRecognizer, isSpeechRecognitionSupported, Chain, create, isEqual, cloneDeep, createSignal, subscribers, getMatchingSentences, transformNumber, toString, addNumSym, checkEncoding, transformText, isSafari, md5, getRandomString, bridgeManager, Client, BridgeManager, PostMessageBridge, MessageCodec, Platform, openPortBridge, acceptPortBridge, createPortBridge, BRIDGE_MARKER, DEFAULT_CHANNEL, singleFlight, WebDB, createHandoff, buildOffsets, paginateText, indexForOffset, segmentByRanges, detectLanguage, navigatorLanguage, resolveLocale, readFileAsArrayBuffer, readFileAsUint8Array, base64ToBytes, bytesToBase64, decodeTextBytes, fetchMaybeGzip, gunzipMaybe, isGzip, isHtmlDocument, isZipContainer, saveFileToDisk, readFileAsText, readFileAsDataURL, WorkerClient, serveWorker, whenIdle, networkAllowsDownload, isUrlCached, prefetchUrl, prefetchUrls, prefetchWhenIdle, deferred, withTimeout, withTimeoutFallback, delay, TimeoutError, createRaceGuard, crc32, inflateRaw, readZipEntries, readZipEntry, zipHasEntry, rewriteZip, createZip, ZIP_STORED, ZIP_DEFLATE, arrayBufferToString, toHalfWidth, toFullWidth, truncate, parseChineseNumber, parseRomanNumber, parseEnglishNumber, MOBILE_MEDIA_QUERY, matchMediaQuery, watchMediaQuery, createLocalePath, setReportUrl, getReportUrl, formatDate, formatDuration, formatRelative, parseVttCueTiming, parseVttTimestamp, handleXhrHook, EventManager, createDoubleTapDetector, quad, cubic, quart, quint, sine, expo, circ, getImage, cutRound, opacity, getMatrix, getAngle, getArcPointerByDeg, getTangentByPointer, fanShapedByArc, roundRectByArc, getLinearGradient, adoptStyles, adoptSheetText, ADOPTED_STYLE_MARKER, ADOPTED_SHEET_MARKER, rgbToHsv, hexToHsb, hexToHsv, hsbToHsl, hslToHsb, hslToHsv, hexToAlpha, rgbaString, rgbaToRgb, rgbaToHex, srgbToLinear, linearToSrgb, luma, blendScreen, blendMultiply, blendOverlay, brightnessContrast, saturation, vibrance, cosinePalette, HEX_COLOR_REGEX, RGB_REGEX, RGBA_REGEX, loadScript, I18nCore, createI18n, useI18n, computePlacement, };
76
- export type { RGB, DateInput, FormatRelativeOptions, RelativeStyle, TruncateOptions, TruncatePosition, SpeechError, SpeechErrorKind, SpeechRecognizer, SpeechRecognizerOptions, EasingFn, SpeedType, ImgSource, LoadScriptOptions, I18nConfig, MessageDict, StringValues, LocaleMessages, TranslateParams, LocaleChangeHandler, Debounced, Throttled, BeaconPayload, ReportConfig, LocalePath, LocalePathConfig, LocaleRoute, SingleFlight, IDBCollection, IDBResult, IDBStoreSchema, WebDBOptions, Handoff, HandoffOptions, JsonStore, Deferred, RaceGuard, DoubleTapDetector, DoubleTapDetectorOptions, ZipEntry, RewriteZipOptions, ResolveLocaleOptions, OffsetRange, PaginateOptions, PaginateResult, TextBox, TextGridMetrics, TextPage, Segment, TextLanguage, ServeWorkerOptions, WorkerClientOptions, WorkerHandlerContext, WorkerRequestBase, WorkerResponseBase, WhenIdleOptions, NetworkAllowanceOptions, PrefetchOptions, CurrentDevice, TransformText, MessageHandler, MessageData, PendingRequest, BridgeManagerOptions, BroadcastPayload, CallToPayload, PortBridge, OpenPortBridgeOptions, AcceptPortBridgeOptions, ComputePlacementOptions, ComputedPlacement, Placement, PlacementRect, };
80
+ export { createBottomFollower, diffLines, formatBytes, performanceTime, timeFormat, timestampToTime, throttle, SyncHook, clearBr, clearStr, isString, randomString, strParse, scriptOnLoad, handleFetchHook, createData, report, QuestQueue, noop, getPerformance, querystring, formatJson, filterObj, merge, replaceOld, mergeExports, perToNum, range, clamp, lerp, inverseLerp, remap, fit, linearstep, smoothstep, Mathjs, mathjs, getStatus, status, Monitor, MimeType, getExtensions, setMime, getMime, memoize, once, isImageSize, convertImageToBase64, handleError, addClassToElement, removeClassToElement, createDocumentFragment, escapeHtml, isClient, isWeiXin, isMobile, debounce, currentDevice, handleConsole, compose, Color, FMT, Hsl, Hsla, Rgb, Rgba, randomColor, hexToRgb, componentToHex, rgbToHex, rgbToHsl, hue2rgb, hslToRgb, rgbToHsb, hsbToRgb, hsvToRgb, hsvToHsl, ColorScheme, AudioRecorder, getCookie, requestUrlToBuffer, getPixelRatio, createObjectURL, getFrame, getAllQueryString, queryFlag, isInIframe, appendUrl, getCookieByName, getWindow, connection, encodeUrl, imageRequest, durationHandler, networkSpeed, TOTP, localStorageGetItem, localStorageSetItem, localStorageRemoveItem, createStore, setFontSize2html, autosizeTextarea, createSpeechRecognizer, isSpeechRecognitionSupported, Chain, create, isEqual, cloneDeep, createSignal, subscribers, getMatchingSentences, transformNumber, toString, addNumSym, checkEncoding, transformText, isSafari, md5, getRandomString, bridgeManager, Client, BridgeManager, PostMessageBridge, MessageCodec, Platform, openPortBridge, acceptPortBridge, createPortBridge, BRIDGE_MARKER, DEFAULT_CHANNEL, singleFlight, WebDB, createHandoff, buildOffsets, paginateText, indexForOffset, segmentByRanges, detectLanguage, navigatorLanguage, resolveLocale, readFileAsArrayBuffer, readFileAsUint8Array, base64ToBytes, bytesToBase64, decodeTextBytes, fetchMaybeGzip, gunzipMaybe, isGzip, isHtmlDocument, isZipContainer, saveFileToDisk, readFileAsText, readFileAsDataURL, WorkerClient, serveWorker, whenIdle, networkAllowsDownload, isUrlCached, prefetchUrl, prefetchUrls, prefetchWhenIdle, deferred, withTimeout, withTimeoutFallback, delay, TimeoutError, createRaceGuard, crc32, inflateRaw, readZipEntries, readZipEntry, zipHasEntry, rewriteZip, createZip, ZIP_STORED, ZIP_DEFLATE, arrayBufferToString, toHalfWidth, toFullWidth, truncate, parseChineseNumber, parseRomanNumber, parseEnglishNumber, MOBILE_MEDIA_QUERY, matchMediaQuery, watchMediaQuery, createLocalePath, setReportUrl, getReportUrl, formatDate, formatDuration, formatRelative, parseVttCueTiming, parseVttTimestamp, handleXhrHook, EventManager, createDoubleTapDetector, quad, cubic, quart, quint, sine, expo, circ, getImage, cutRound, opacity, getMatrix, getAngle, getArcPointerByDeg, getTangentByPointer, fanShapedByArc, roundRectByArc, getLinearGradient, adoptStyles, adoptSheetText, ADOPTED_STYLE_MARKER, ADOPTED_SHEET_MARKER, rgbToHsv, hexToHsb, hexToHsv, hsbToHsl, hslToHsb, hslToHsv, hexToAlpha, rgbaString, rgbaToRgb, rgbaToHex, srgbToLinear, linearToSrgb, luma, blendScreen, blendMultiply, blendOverlay, brightnessContrast, saturation, vibrance, cosinePalette, HEX_COLOR_REGEX, RGB_REGEX, RGBA_REGEX, loadScript, I18nCore, createI18n, useI18n, alignCrossAxis, computePlacement, safeEqual, secureRandomString, secureToken, UNAMBIGUOUS_ALPHABET, bytesToBase64Url, base64UrlToBytes, concatBytes, truncateWithMarker, fenceCode, slugify, csvEscape, };
81
+ export type { RGB, DateInput, FormatRelativeOptions, RelativeStyle, TruncateOptions, TruncatePosition, SpeechError, SpeechErrorKind, SpeechRecognizer, SpeechRecognizerOptions, EasingFn, SpeedType, ImgSource, LoadScriptOptions, I18nConfig, MessageDict, StringValues, LocaleMessages, TranslateParams, LocaleChangeHandler, Debounced, Throttled, BeaconPayload, ReportConfig, LocalePath, LocalePathConfig, LocaleRoute, SingleFlight, IDBCollection, IDBResult, IDBStoreSchema, WebDBOptions, Handoff, HandoffOptions, JsonStore, Deferred, RaceGuard, DoubleTapDetector, DoubleTapDetectorOptions, ZipEntry, RewriteZipOptions, ResolveLocaleOptions, OffsetRange, PaginateOptions, PaginateResult, TextBox, TextGridMetrics, TextPage, Segment, TextLanguage, ServeWorkerOptions, WorkerClientOptions, WorkerHandlerContext, WorkerRequestBase, WorkerResponseBase, WhenIdleOptions, NetworkAllowanceOptions, PrefetchOptions, CurrentDevice, TransformText, MessageHandler, MessageData, PendingRequest, BridgeManagerOptions, BroadcastPayload, CallToPayload, PortBridge, OpenPortBridgeOptions, AcceptPortBridgeOptions, ComputePlacementOptions, ComputedPlacement, Placement, PlacementAlign, PlacementRect, PlacementSide, BottomFollower, BottomFollowerOptions, DiffHunk, DiffLine, DiffLineKind, DiffOptions, };
@@ -1 +1 @@
1
- import{i as s}from"../../enums-BAgbyGdH.js";import{$ as a,A as t,B as n,C as o,D as r,E as m,F as i,G as p,H as f,I as j,J as c,K as l,L as u,M as h,N as x,O as b,P as d,Q as e,R as g,S as k,T as v,U as w,V as y,W as C,X as D,Y as E,Z as S,_ as T,a as _,at as z,b as A,c as B,d as F,et as H,f as I,g as L,h as M,i as N,it as O,j as P,k as R,l as U,m as V,n as q,nt as G,o as J,ot as K,p as Q,q as W,r as X,rt as Y,s as Z,st as $,t as ss,tt as as,u as ts,v as ns,w as os,x as rs,y as ms,z as is}from"../../color-DPV7TsVU.js";import{$ as ps,$t as fs,A as js,At as cs,B as ls,Bt as us,C as hs,Cn as xs,Ct as bs,D as ds,Dn as es,Dt as gs,E as ks,En as vs,Et as ws,F as ys,Ft as Cs,G as Ds,Gt as Es,H as Ss,Ht as Ts,I as _s,It as zs,J as As,Jt as Bs,K as Fs,Kt as Hs,L as Is,Lt as Ls,M as Ms,Mt as Ns,N as Os,Nt as Ps,O as Rs,On as Us,Ot as Vs,P as qs,Pt as Gs,Q as Js,Qt as Ks,R as Qs,Rt as Ws,S as Xs,Sn as Ys,St as Zs,T as $s,Tn as sa,Tt as aa,U as ta,Ut as na,V as oa,Vt as ra,W as ma,Wt as ia,X as pa,Xt as fa,Y as ja,Yt as ca,Z as la,Zt as ua,_ as ha,_n as xa,_t as ba,a as da,an as ea,at as ga,b as ka,bn as va,bt as wa,c as ya,cn as Ca,ct as Da,d as Ea,dn as Sa,dt as Ta,en as _a,et as za,f as Aa,fn as Ba,ft as Fa,g as Ha,gn as Ia,gt as La,h as Ma,hn as Na,ht as Oa,i as Pa,in as Ra,it as Ua,j as Va,jt as qa,k as Ga,kn as Ja,kt as Ka,l as Qa,ln as Wa,lt as Xa,m as Ya,mn as Za,mt as $a,n as st,nn as at,nt as tt,o as nt,on as ot,ot as rt,p as mt,pn as it,pt,q as ft,qt as jt,r as ct,rn as lt,rt as ut,s as ht,sn as xt,st as bt,t as dt,tn as et,tt as gt,u as kt,un as vt,ut as wt,v as yt,vn as Ct,vt as Dt,w as Et,wn as St,wt as Tt,x as _t,xn as zt,xt as At,y as Bt,yn as Ft,yt as Ht,z as It,zt as Lt}from"../../utils-BSvtPyGl.js";import{A as Mt,B as Nt,C as Ot,D as Pt,E as Rt,F as Ut,H as Vt,I as qt,L as Gt,M as Jt,N as Kt,P as Qt,R as Wt,S as Xt,T as Yt,U as Zt,V as $t,_ as sn,a as an,b as tn,c as nn,d as on,f as rn,g as mn,h as pn,i as fn,j as jn,k as cn,l as ln,m as un,n as hn,o as xn,p as bn,r as dn,s as en,t as gn,u as kn,v as vn,w as wn,x as yn,y as Cn,z as Dn}from"../../i18n-Bq-f7htr.js";import{n as En,t as Sn}from"../../chain-CTywmh_H.js";export{ga as ADOPTED_SHEET_MARKER,rt as ADOPTED_STYLE_MARKER,na as AudioRecorder,at as BRIDGE_MARKER,lt as BridgeManager,Sn as Chain,Ra as Client,ss as Color,q as ColorScheme,ea as DEFAULT_CHANNEL,Vs as EventManager,X as FMT,N as HEX_COLOR_REGEX,_ as Hsl,J as Hsla,gn as I18nCore,cn as MOBILE_MEDIA_QUERY,Za as Mathjs,l as MessageCodec,f as MimeType,nt as Monitor,ot as Platform,xt as PostMessageBridge,ct as QuestQueue,Z as RGBA_REGEX,B as RGB_REGEX,U as Rgb,ts as Rgba,s as SyncHook,us as TOTP,Et as TimeoutError,ut as WebDB,_s as WorkerClient,Ma as ZIP_DEFLATE,Ha as ZIP_STORED,Ca as acceptPortBridge,qa as addClassToElement,Na as addNumSym,bt as adoptSheetText,Da as adoptStyles,on as appendUrl,W as arrayBufferToString,Ns as autosizeTextarea,Qs as base64ToBytes,F as blendMultiply,I as blendOverlay,Q as blendScreen,Wa as bridgeManager,V as brightnessContrast,za as buildOffsets,It as bytesToBase64,c as checkEncoding,At as circ,Ia as clamp,E as clearBr,D as clearStr,ia as cloneDeep,M as componentToHex,Lt as compose,la as computePlacement,rn as connection,Xa as convertImageToBase64,L as cosinePalette,ha as crc32,En as create,kt as createData,Ps as createDocumentFragment,Ka as createDoubleTapDetector,Ua as createHandoff,hn as createI18n,Js as createLocalePath,bn as createObjectURL,vt as createPortBridge,$s as createRaceGuard,ra as createSignal,Ba as createSpeechRecognizer,en as createStore,yt as createZip,Zs as cubic,Mt as currentDevice,wt as cutRound,Ls as debounce,ls as decodeTextBytes,ks as deferred,ds as delay,fn as detectLanguage,un as durationHandler,pn as encodeUrl,Gs as escapeHtml,bs as expo,Oa as fanShapedByArc,oa as fetchMaybeGzip,Es as filterObj,xa as fit,qt as formatDate,Gt as formatDuration,Hs as formatJson,Wt as formatRelative,mn as getAllQueryString,La as getAngle,ba as getArcPointerByDeg,sn as getCookie,vn as getCookieByName,w as getExtensions,Cn as getFrame,Ta as getImage,Dt as getLinearGradient,S as getMatchingSentences,Fa as getMatrix,C as getMime,Ya as getPerformance,tn as getPixelRatio,e as getRandomString,Ea as getReportUrl,Pa as getStatus,Ht as getTangentByPointer,yn as getWindow,Ss as gunzipMaybe,Ws as handleConsole,cs as handleError,ya as handleFetchHook,Qa as handleXhrHook,T as hexToAlpha,ns as hexToHsb,ms as hexToHsv,A as hexToRgb,rs as hsbToHsl,k as hsbToRgb,o as hslToHsb,os as hslToHsv,v as hslToRgb,m as hsvToHsl,r as hsvToRgb,b as hue2rgb,Xt as imageRequest,gt as indexForOffset,Bt as inflateRaw,Ct as inverseLerp,jn as isClient,jt as isEqual,ta as isGzip,ma as isHtmlDocument,pt as isImageSize,Ot as isInIframe,Jt as isMobile,wn as isSafari,it as isSpeechRecognitionSupported,a as isString,js as isUrlCached,Kt as isWeiXin,Ds as isZipContainer,Ft as lerp,R as linearToSrgb,va as linearstep,dt as loadScript,nn as localStorageGetItem,ln as localStorageRemoveItem,kn as localStorageSetItem,t as luma,Qt as matchMediaQuery,zt as mathjs,H as md5,fs as memoize,Bs as merge,ca as mergeExports,an as navigatorLanguage,Va as networkAllowsDownload,Yt as networkSpeed,Ks as noop,_a as once,$a as opacity,Sa as openPortBridge,ps as paginateText,Ys as parseChineseNumber,xs as parseEnglishNumber,St as parseRomanNumber,Dn as parseVttCueTiming,Nt as parseVttTimestamp,sa as perToNum,$t as performanceTime,Ms as prefetchUrl,Os as prefetchUrls,qs as prefetchWhenIdle,Tt as quad,aa as quart,Rt as queryFlag,fa as querystring,ws as quint,P as randomColor,as as randomString,vs as range,ft as readFileAsArrayBuffer,As as readFileAsDataURL,ja as readFileAsText,pa as readFileAsUint8Array,ka as readZipEntries,_t as readZipEntry,es as remap,Cs as removeClassToElement,ua as replaceOld,Aa as report,Pt as requestUrlToBuffer,xn as resolveLocale,Xs as rewriteZip,h as rgbToHex,x as rgbToHsb,d as rgbToHsl,i as rgbToHsv,j as rgbaString,u as rgbaToHex,g as rgbaToRgb,wa as roundRectByArc,is as saturation,Fs as saveFileToDisk,st as scriptOnLoad,tt as segmentByRanges,Is as serveWorker,zs as setFontSize2html,p as setMime,mt as setReportUrl,gs as sine,et as singleFlight,Us as smoothstep,n as srgbToLinear,da as status,G as strParse,Ts as subscribers,ht as throttle,Vt as timeFormat,Zt as timestampToTime,Y as toFullWidth,O as toHalfWidth,z as toString,Ja as transformNumber,K as transformText,$ as truncate,dn as useI18n,y as vibrance,Ut as watchMediaQuery,ys as whenIdle,Rs as withTimeout,Ga as withTimeoutFallback,hs as zipHasEntry};
1
+ import{$ as s,$t as a,A as t,An as n,At as o,B as r,Bn as m,Bt as i,C as p,Cn as f,Ct as j,D as c,Dn as l,Dt as u,E as d,En as h,Et as x,F as b,Fn as e,Ft as g,G as k,Gn as v,Gt as w,H as y,Hn as A,Ht as C,I as D,In as E,It as F,J as M,Jt as N,K as O,Kn as P,Kt as S,L as T,Ln as _,Lt as q,M as z,Mn as B,Mt as G,N as H,Nn as I,Nt as K,O as L,On as R,Ot as U,P as V,Pn as W,Pt as J,Q,Qt as X,R as Y,Rn as Z,Rt as $,S as ss,Sn as as,St as ts,T as ns,Tn as os,Tt as rs,U as ms,Un as is,Ut as ps,V as fs,Vn as js,Vt as cs,W as ls,Wn as us,Wt as ds,X as hs,Xt as xs,Y as bs,Yt as es,Z as gs,Zt as ks,_ as vs,_n as ws,_t as ys,a as As,an as Cs,at as Ds,b as Es,bn as Fs,bt as Ms,c as Ns,cn as Os,ct as Ps,d as Ss,dn as Ts,dt as _s,en as qs,et as zs,f as Bs,fn as Gs,ft as Hs,g as Is,gn as Ks,gt as Ls,h as Rs,hn as Us,ht as Vs,i as Ws,in as Js,it as Qs,j as Xs,jn as Ys,jt as Zs,k as $s,kn as sa,kt as aa,l as ta,ln as na,lt as oa,m as ra,mn as ma,mt as ia,n as pa,nn as fa,nt as ja,o as ca,on as la,ot as ua,p as da,pn as ha,pt as xa,q as ba,qn as ea,qt as ga,r as ka,rn as va,rt as wa,s as ya,sn as Aa,st as Ca,t as Da,tn as Ea,tt as Fa,u as Ma,un as Na,ut as Oa,v as Pa,vn as Sa,vt as Ta,w as _a,wn as qa,wt as za,x as Ba,xn as Ga,xt as Ha,y as Ia,yn as Ka,yt as La,z as Ra,zn as Ua,zt as Va}from"../../utils-B4FnyUzW.js";import{i as Wa}from"../../enums-BAgbyGdH.js";import{$ as Ja,A as Qa,B as Xa,C as Ya,D as Za,E as $a,F as st,G as at,H as tt,I as nt,J as ot,K as rt,L as mt,M as it,N as pt,O as ft,P as jt,Q as ct,R as lt,S as ut,T as dt,U as ht,V as xt,W as bt,X as et,Y as gt,Z as kt,_ as vt,a as wt,at as yt,b as At,c as Ct,ct as Dt,d as Et,dt as Ft,et as Mt,f as Nt,g as Ot,h as Pt,i as St,it as Tt,j as _t,k as qt,l as zt,lt as Bt,m as Gt,n as Ht,nt as It,o as Kt,ot as Lt,p as Rt,q as Ut,r as Vt,rt as Wt,s as Jt,st as Qt,t as Xt,tt as Yt,u as Zt,ut as $t,v as sn,w as an,x as tn,y as nn,z as on}from"../../color-BTvZUuf-.js";import{A as rn,C as mn,D as pn,E as fn,F as jn,M as cn,N as ln,O as un,P as dn,S as hn,T as xn,_ as bn,a as en,b as gn,c as kn,d as vn,f as wn,g as yn,h as An,i as Cn,j as Dn,k as En,l as Fn,m as Mn,n as Nn,o as On,p as Pn,r as Sn,s as Tn,t as _n,u as qn,v as zn,w as Bn,x as Gn,y as Hn}from"../../i18n-DW21b_DJ.js";import{n as In,t as Kn}from"../../chain-CTywmh_H.js";export{xa as ADOPTED_SHEET_MARKER,ia as ADOPTED_STYLE_MARKER,Js as AudioRecorder,ws as BRIDGE_MARKER,Sa as BridgeManager,Kn as Chain,Ka as Client,Xt as Color,Ht as ColorScheme,Fs as DEFAULT_CHANNEL,F as EventManager,Vt as FMT,St as HEX_COLOR_REGEX,wt as Hsl,Kt as Hsla,_n as I18nCore,w as MOBILE_MEDIA_QUERY,sa as Mathjs,rt as MessageCodec,tt as MimeType,ca as Monitor,Ga as Platform,as as PostMessageBridge,ka as QuestQueue,Jt as RGBA_REGEX,Ct as RGB_REGEX,zt as Rgb,Zt as Rgba,Wa as SyncHook,Ea as TOTP,_a as TimeoutError,Y as UNAMBIGUOUS_ALPHABET,_s as WebDB,D as WorkerClient,Rs as ZIP_DEFLATE,Is as ZIP_STORED,f as acceptPortBridge,Va as addClassToElement,n as addNumSym,Vs as adoptSheetText,Ls as adoptStyles,Qs as alignCrossAxis,vn as appendUrl,Ut as arrayBufferToString,i as autosizeTextarea,y as base64ToBytes,ms as base64UrlToBytes,Et as blendMultiply,Nt as blendOverlay,Rt as blendScreen,qa as bridgeManager,Gt as brightnessContrast,Ps as buildOffsets,ls as bytesToBase64,k as bytesToBase64Url,ot as checkEncoding,aa as circ,Ys as clamp,gt as clearBr,et as clearStr,Cs as cloneDeep,Pt as componentToHex,qs as compose,Ds as computePlacement,O as concatBytes,wn as connection,ys as convertImageToBase64,Ot as cosinePalette,vs as crc32,In as create,ea as createBottomFollower,Ma as createData,cs as createDocumentFragment,q as createDoubleTapDetector,Hs as createHandoff,Nn as createI18n,ua as createLocalePath,Pn as createObjectURL,os as createPortBridge,ns as createRaceGuard,fa as createSignal,l as createSpeechRecognizer,Tn as createStore,Pa as createZip,kt as csvEscape,o as cubic,S as currentDevice,Ta as cutRound,X as debounce,ba as decodeTextBytes,d as deferred,c as delay,Cn as detectLanguage,P as diffLines,Mn as durationHandler,An as encodeUrl,C as escapeHtml,Zs as expo,j as fanShapedByArc,ct as fenceCode,M as fetchMaybeGzip,la as filterObj,B as fit,I as formatBytes,un as formatDate,En as formatDuration,Aa as formatJson,rn as formatRelative,yn as getAllQueryString,za as getAngle,rs as getArcPointerByDeg,bn as getCookie,zn as getCookieByName,ht as getExtensions,Hn as getFrame,La as getImage,x as getLinearGradient,Ja as getMatchingSentences,Ms as getMatrix,bt as getMime,ra as getPerformance,gn as getPixelRatio,Mt as getRandomString,Ss as getReportUrl,Ws as getStatus,u as getTangentByPointer,Gn as getWindow,bs as gunzipMaybe,a as handleConsole,$ as handleError,Ns as handleFetchHook,ta as handleXhrHook,vt as hexToAlpha,sn as hexToHsb,nn as hexToHsv,At as hexToRgb,tn as hsbToHsl,ut as hsbToRgb,Ya as hslToHsb,an as hslToHsv,dt as hslToRgb,$a as hsvToHsl,Za as hsvToRgb,ft as hue2rgb,hn as imageRequest,oa as indexForOffset,Ia as inflateRaw,W as inverseLerp,ga as isClient,Os as isEqual,hs as isGzip,gs as isHtmlDocument,Ha as isImageSize,mn as isInIframe,N as isMobile,Bn as isSafari,R as isSpeechRecognitionSupported,Yt as isString,t as isUrlCached,es as isWeiXin,Q as isZipContainer,e as lerp,qt as linearToSrgb,E as linearstep,Da as loadScript,kn as localStorageGetItem,Fn as localStorageRemoveItem,qn as localStorageSetItem,Qa as luma,xs as matchMediaQuery,_ as mathjs,It as md5,ma as memoize,na as merge,Na as mergeExports,en as navigatorLanguage,Xs as networkAllowsDownload,xn as networkSpeed,ha as noop,Us as once,ts as opacity,h as openPortBridge,Ca as paginateText,Z as parseChineseNumber,Ua as parseEnglishNumber,m as parseRomanNumber,Dn as parseVttCueTiming,cn as parseVttTimestamp,js as perToNum,ln as performanceTime,z as prefetchUrl,H as prefetchUrls,V as prefetchWhenIdle,G as quad,K as quart,fn as queryFlag,Ts as querystring,J as quint,_t as randomColor,Wt as randomString,A as range,zs as readFileAsArrayBuffer,Fa as readFileAsDataURL,ja as readFileAsText,wa as readFileAsUint8Array,Es as readZipEntries,Ba as readZipEntry,is as remap,ps as removeClassToElement,Gs as replaceOld,Bs as report,pn as requestUrlToBuffer,On as resolveLocale,ss as rewriteZip,it as rgbToHex,pt as rgbToHsb,jt as rgbToHsl,st as rgbToHsv,nt as rgbaString,mt as rgbaToHex,lt as rgbaToRgb,U as roundRectByArc,Ra as safeEqual,on as saturation,s as saveFileToDisk,pa as scriptOnLoad,r as secureRandomString,fs as secureToken,Oa as segmentByRanges,T as serveWorker,ds as setFontSize2html,at as setMime,da as setReportUrl,g as sine,Ks as singleFlight,Tt as slugify,us as smoothstep,Xa as srgbToLinear,As as status,yt as strParse,va as subscribers,ya as throttle,dn as timeFormat,jn as timestampToTime,Lt as toFullWidth,Qt as toHalfWidth,Dt as toString,v as transformNumber,Bt as transformText,$t as truncate,Ft as truncateWithMarker,Sn as useI18n,xt as vibrance,ks as watchMediaQuery,b as whenIdle,L as withTimeout,$s as withTimeoutFallback,p as zipHasEntry};
@@ -139,4 +139,24 @@ export declare const linearstep: (edge0: number, edge1: number, x: number) => nu
139
139
  * @return {number}
140
140
  */
141
141
  export declare const smoothstep: (edge0: number, edge1: number, x: number) => number;
142
+ /**
143
+ * @description: Format a byte count for a person to read.
144
+ *
145
+ * Steps in units of 1024 and keeps one decimal from KB up, because "1.4 MB" is the number a
146
+ * file manager shows for the same file and a reader comparing the two should not have to
147
+ * wonder. Bytes get no decimal — a fraction of a byte is not a thing.
148
+ *
149
+ * @param {number} bytes Byte count. Negative or non-finite input yields `'0 B'`, since there
150
+ * is no honest reading of a file with a negative size.
151
+ * @return {string}
152
+ * @example
153
+ * ```ts
154
+ * formatBytes(0); // '0 B'
155
+ * formatBytes(999); // '999 B'
156
+ * formatBytes(1024); // '1.0 KB'
157
+ * formatBytes(1536); // '1.5 KB'
158
+ * formatBytes(1048576); // '1.0 MB'
159
+ * ```
160
+ */
161
+ export declare const formatBytes: (bytes: number) => string;
142
162
  export {};
@@ -1,4 +1,18 @@
1
- export type Placement = 'top' | 'bottom' | 'left' | 'right';
1
+ /** The side of the anchor a floating panel sits on. */
2
+ export type PlacementSide = 'top' | 'bottom' | 'left' | 'right';
3
+ /**
4
+ * Where the panel lines up along the cross axis: with the anchor's leading
5
+ * edge, its centre, or its trailing edge. For a `top`/`bottom` placement that
6
+ * is horizontal (left edge / centre / right edge); for `left`/`right` it is
7
+ * vertical (top edge / centre / bottom edge).
8
+ */
9
+ export type PlacementAlign = 'start' | 'center' | 'end';
10
+ /**
11
+ * A side, optionally suffixed with a cross-axis alignment — the same grammar
12
+ * Floating UI and Popper use (`bottom`, `bottom-end`, `right-center`, …).
13
+ * A bare side means `-start`, which is what this module has always done.
14
+ */
15
+ export type Placement = PlacementSide | `${PlacementSide}-${PlacementAlign}`;
2
16
  export interface PlacementRect {
3
17
  top: number;
4
18
  left: number;
@@ -13,7 +27,7 @@ export interface ComputePlacementOptions {
13
27
  width: number;
14
28
  height: number;
15
29
  };
16
- /** Preferred side. Flips to the opposite side when it lacks room and the opposite side has more. */
30
+ /** Preferred side, optionally with a cross-axis alignment. Flips to the opposite side when it lacks room and the opposite side has more; the alignment is carried across the flip. */
17
31
  placement: Placement;
18
32
  /** Gap kept between the anchor and the floating panel, in px. */
19
33
  offset?: number;
@@ -25,14 +39,37 @@ export interface ComputePlacementOptions {
25
39
  export interface ComputedPlacement {
26
40
  top: number;
27
41
  left: number;
28
- /** The side actually used, after flip. */
42
+ /**
43
+ * The placement actually used, after flip, in the form the caller asked for:
44
+ * a bare side stays bare, a suffixed one keeps its suffix. Callers that key a
45
+ * lookup table off four sides therefore keep working unchanged.
46
+ */
29
47
  placement: Placement;
48
+ /** The side actually used, after flip — always bare, whatever form `placement` took. */
49
+ side: PlacementSide;
50
+ /** The cross-axis alignment actually used. `start` when the caller named none. */
51
+ align: PlacementAlign;
30
52
  }
53
+ /**
54
+ * @description: Where a floating panel starts along the cross axis, given how
55
+ * it should line up with its anchor. `start` pins the leading edges together,
56
+ * `end` the trailing ones, `center` splits the difference. Exported because a
57
+ * caller that computes its own coordinates -- a panel positioned inside a
58
+ * custom container rather than the viewport -- still has to align the same way
59
+ * `computePlacement` does, and two implementations of that would drift.
60
+ * @param align cross-axis alignment
61
+ * @param anchorStart anchor's leading edge on that axis (`left` or `top`)
62
+ * @param anchorSize anchor's size on that axis (`width` or `height`)
63
+ * @param floatingSize the panel's size on that axis
64
+ * @return the panel's leading edge on that axis
65
+ */
66
+ export declare const alignCrossAxis: (align: PlacementAlign, anchorStart: number, anchorSize: number, floatingSize: number) => number;
31
67
  /**
32
68
  * Position a floating panel relative to an anchor rect: flips to the opposite
33
69
  * side when the preferred side doesn't have room and the opposite side has
34
- * more, then shifts along the cross axis to stay within `boundary`. Mirrors
35
- * Floating UI's `flip`/`shift` middleware, minus the dependency.
70
+ * more, aligns along the cross axis as asked, then shifts to stay within
71
+ * `boundary`. Mirrors Floating UI's `flip`/`shift` middleware, minus the
72
+ * dependency.
36
73
  *
37
74
  * Coordinates are viewport-relative throughout (same space as `anchor`); the
38
75
  * caller adds `scrollX`/`scrollY` when writing `position: absolute` styles.
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Bottom-follow for append-only scrollers — a streaming chat transcript, a log tail, a
3
+ * terminal pane.
4
+ *
5
+ * The requirement sounds trivial and is not: stay pinned to the floor as content arrives,
6
+ * but the instant the reader scrolls up to read something, stop — and re-pin only when
7
+ * they come back down themselves. Naive implementations fight the reader, because they
8
+ * cannot tell their own scroll writes apart from the reader's.
9
+ *
10
+ * The mechanism here is an **observed-top ledger**. Every programmatic write records the
11
+ * `scrollTop` it produced. When a scroll event arrives, a position that matches the ledger
12
+ * is this module's own write echoing back; a position that deviates is the reader. That
13
+ * covers wheel, touch, scrollbar drag, keyboard, and `scrollIntoView` from unrelated code
14
+ * uniformly, without listening for any input device — which matters because no set of
15
+ * device listeners is ever complete.
16
+ *
17
+ * Two cases the ledger has to survive:
18
+ *
19
+ * - **Shrink-clamp.** When content shrinks, the browser clamps `scrollTop` to the new
20
+ * floor without any reader involvement. Comparing against `min(ledger, floor)` treats
21
+ * that clamp as the ledger's own value rather than as a reader scroll, so a clamp
22
+ * never changes who owns the scroll position — a reader who had scrolled up stays
23
+ * unpinned even when the clamp happens to leave them at the floor, and re-pins on
24
+ * their next scroll. Re-pinning on a clamp would take control back without input.
25
+ * - **Growth while pinned.** Appended content moves the floor away. A scroll event that
26
+ * the reader did not cause, while pinned, re-snaps to the new floor.
27
+ *
28
+ * Scrolling is always instant. Smooth scrolling animates over a moving target, so during
29
+ * streaming it visibly lags the content and, worse, its own intermediate positions read as
30
+ * reader input on the next event.
31
+ */
32
+ /** How to construct a follower. */
33
+ export interface BottomFollowerOptions {
34
+ /** The element that scrolls. */
35
+ scrollport: HTMLElement;
36
+ /**
37
+ * Elements whose size changes should re-follow the floor while pinned — the content
38
+ * column, and any sticky footer that resizes outside it. Streaming text grows an
39
+ * existing node rather than appending one, so growth is observed rather than announced.
40
+ */
41
+ observe?: readonly HTMLElement[];
42
+ /** Distance from the floor still counted as pinned. Defaults to 24. */
43
+ threshold?: number;
44
+ /**
45
+ * Called when the pinned state flips, so a caller can show or hide a "jump to latest"
46
+ * affordance. Never called for a change the caller itself just made synchronously.
47
+ */
48
+ onPinnedChange?: (pinned: boolean) => void;
49
+ }
50
+ /** Imperative bottom-follow controller. */
51
+ export interface BottomFollower {
52
+ /** Whether new content is currently being followed. */
53
+ readonly pinned: boolean;
54
+ /** Scrolls to the floor and pins, regardless of the current state. */
55
+ toBottom(): void;
56
+ /**
57
+ * Follows the floor only if currently pinned. Safe to call on every content change —
58
+ * a reader who has scrolled up is left alone.
59
+ */
60
+ follow(): void;
61
+ /**
62
+ * Remembers a row's current offset from the scrollport top, before content is prepended
63
+ * above it. Capture a row that is actually on screen, so the restore keeps what the
64
+ * reader is looking at exactly where it was.
65
+ *
66
+ * @param row The row to keep still.
67
+ */
68
+ captureAnchor(row: HTMLElement): void;
69
+ /**
70
+ * Restores the captured row to its captured offset, then forgets it.
71
+ *
72
+ * @param resolve Re-resolves the row after the prepend, for callers that replace nodes
73
+ * rather than reuse them. Omit when the captured element is still in the document.
74
+ * @returns Whether an anchor was restored.
75
+ */
76
+ restoreAnchor(resolve?: () => HTMLElement | null): boolean;
77
+ /** Discards any captured anchor without restoring it. */
78
+ releaseAnchor(): void;
79
+ /** Removes the scroll listener and disconnects the resize observer. */
80
+ destroy(): void;
81
+ }
82
+ /**
83
+ * Creates a bottom-follow controller for one scrollport.
84
+ *
85
+ * The controller starts pinned, which is what an append-only view wants on first paint and
86
+ * after a reload. To restore a remembered position instead, set `scrollTop` before or
87
+ * after construction and the first scroll event will settle the pinned state from the
88
+ * geometry.
89
+ *
90
+ * @param options Scrollport, elements to observe, and threshold.
91
+ * @returns The controller; call `destroy` to release its listeners.
92
+ */
93
+ export declare function createBottomFollower(options: BottomFollowerOptions): BottomFollower;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Primitives whose correctness depends on *how* they compute, not just what they return:
3
+ * comparisons that must not leak their answer through timing, and randomness that must not
4
+ * be predictable.
5
+ *
6
+ * Kept apart from `str.ts` deliberately. `randomString` and `getRandomString` there are
7
+ * `Math.random()` based — fine for a DOM id or a message correlation key, unsafe for anything
8
+ * an attacker would want to guess. Someone reaching for a token generator should land here.
9
+ *
10
+ * Uses the Web Crypto global, which exists in browsers, Node >= 19, Deno, Workers and
11
+ * service workers alike.
12
+ */
13
+ /**
14
+ * @description: Compare two secrets in time that does not depend on where they first differ.
15
+ *
16
+ * A plain `a === b` returns as soon as it finds a mismatch, so the time it takes reveals how
17
+ * long a shared prefix was — enough to recover a token one character at a time across many
18
+ * requests. Use this whenever one side of the comparison is attacker-supplied: access keys,
19
+ * session tokens, HMAC digests, pairing codes.
20
+ *
21
+ * **It hides the contents, not the length.** Inputs of different lengths return `false`
22
+ * immediately, because comparing to a fixed length would either truncate or pad the very data
23
+ * under test. Length is rarely the secret; when it is, compare fixed-width digests instead.
24
+ *
25
+ * @param {string | Uint8Array} a
26
+ * @param {string | Uint8Array} b
27
+ * @return {boolean} whether the two are byte-for-byte equal
28
+ */
29
+ export declare const safeEqual: (a: string | Uint8Array, b: string | Uint8Array) => boolean;
30
+ /** Unambiguous by design: no `0`/`O`, no `1`/`l`/`I`. For codes a human reads aloud or retypes. */
31
+ export declare const UNAMBIGUOUS_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
32
+ /**
33
+ * @description: A random string drawn from `alphabet` using the platform CSPRNG.
34
+ *
35
+ * Unlike `randomString` / `getRandomString` in `str.ts`, this is safe for values an attacker
36
+ * must not be able to predict: device-pairing codes, one-time tokens, invite links.
37
+ *
38
+ * The draw is rejection-sampled, so every character is uniform no matter what the alphabet
39
+ * length is. A plain `byte % alphabet.length` is biased toward the first
40
+ * `256 % alphabet.length` characters — small enough to ignore for a short-lived,
41
+ * rate-limited code, and not small enough to reason about again every time someone reuses
42
+ * this for something longer-lived.
43
+ *
44
+ * @param {number} length how many characters to draw
45
+ * @param {string} alphabet characters to draw from; defaults to an unambiguous set
46
+ * @return {string}
47
+ */
48
+ export declare const secureRandomString: (length: number, alphabet?: string) => string;
49
+ /**
50
+ * @description: A random hex token of `bytes` bytes, from the platform CSPRNG.
51
+ *
52
+ * The default of 32 bytes is 256 bits — the usual floor for a bearer token that is not
53
+ * expected to expire soon.
54
+ *
55
+ * @param {number} bytes how many random bytes to draw
56
+ * @return {string} lowercase hex, twice as long as `bytes`
57
+ */
58
+ export declare const secureToken: (bytes?: number) => string;