asdf
Squash the current repository state back into one baseline commit while preserving the README reframing and repository contents. Constraint: User explicitly requested a single squashed commit with subject "asdf" Confidence: high Scope-risk: broad Reversibility: clean Directive: This commit intentionally rewrites published history; coordinate before future force-pushes Tested: git status clean; local history rewritten to one commit; force-pushed main to origin and instructkr Not-tested: Fresh clone verification after push
This commit is contained in:
commit
4b9d30f795
1903 files changed
+513517
No files matched your search
@@ -0,0 +1,63 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import * as React from 'react';
|
||||
import { Box } from '../ink.js';
|
||||
type QueuedMessageContextValue = {
|
||||
isQueued: boolean;
|
||||
isFirst: boolean;
|
||||
/** Width reduction for container padding (e.g., 4 for paddingX={2}) */
|
||||
paddingWidth: number;
|
||||
};
|
||||
const QueuedMessageContext = React.createContext<QueuedMessageContextValue | undefined>(undefined);
|
||||
export function useQueuedMessage() {
|
||||
return React.useContext(QueuedMessageContext);
|
||||
}
|
||||
const PADDING_X = 2;
|
||||
type Props = {
|
||||
isFirst: boolean;
|
||||
useBriefLayout?: boolean;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
export function QueuedMessageProvider(t0) {
|
||||
const $ = _c(9);
|
||||
const {
|
||||
isFirst,
|
||||
useBriefLayout,
|
||||
children
|
||||
} = t0;
|
||||
const padding = useBriefLayout ? 0 : PADDING_X;
|
||||
const t1 = padding * 2;
|
||||
let t2;
|
||||
if ($[0] !== isFirst || $[1] !== t1) {
|
||||
t2 = {
|
||||
isQueued: true,
|
||||
isFirst,
|
||||
paddingWidth: t1
|
||||
};
|
||||
$[0] = isFirst;
|
||||
$[1] = t1;
|
||||
$[2] = t2;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
}
|
||||
const value = t2;
|
||||
let t3;
|
||||
if ($[3] !== children || $[4] !== padding) {
|
||||
t3 = <Box paddingX={padding}>{children}</Box>;
|
||||
$[3] = children;
|
||||
$[4] = padding;
|
||||
$[5] = t3;
|
||||
} else {
|
||||
t3 = $[5];
|
||||
}
|
||||
let t4;
|
||||
if ($[6] !== t3 || $[7] !== value) {
|
||||
t4 = <QueuedMessageContext.Provider value={value}>{t3}</QueuedMessageContext.Provider>;
|
||||
$[6] = t3;
|
||||
$[7] = value;
|
||||
$[8] = t4;
|
||||
} else {
|
||||
t4 = $[8];
|
||||
}
|
||||
return t4;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkJveCIsIlF1ZXVlZE1lc3NhZ2VDb250ZXh0VmFsdWUiLCJpc1F1ZXVlZCIsImlzRmlyc3QiLCJwYWRkaW5nV2lkdGgiLCJRdWV1ZWRNZXNzYWdlQ29udGV4dCIsImNyZWF0ZUNvbnRleHQiLCJ1bmRlZmluZWQiLCJ1c2VRdWV1ZWRNZXNzYWdlIiwidXNlQ29udGV4dCIsIlBBRERJTkdfWCIsIlByb3BzIiwidXNlQnJpZWZMYXlvdXQiLCJjaGlsZHJlbiIsIlJlYWN0Tm9kZSIsIlF1ZXVlZE1lc3NhZ2VQcm92aWRlciIsInQwIiwiJCIsIl9jIiwicGFkZGluZyIsInQxIiwidDIiLCJ2YWx1ZSIsInQzIiwidDQiXSwic291cmNlcyI6WyJRdWV1ZWRNZXNzYWdlQ29udGV4dC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBCb3ggfSBmcm9tICcuLi9pbmsuanMnXG5cbnR5cGUgUXVldWVkTWVzc2FnZUNvbnRleHRWYWx1ZSA9IHtcbiAgaXNRdWV1ZWQ6IGJvb2xlYW5cbiAgaXNGaXJzdDogYm9vbGVhblxuICAvKiogV2lkdGggcmVkdWN0aW9uIGZvciBjb250YWluZXIgcGFkZGluZyAoZS5nLiwgNCBmb3IgcGFkZGluZ1g9ezJ9KSAqL1xuICBwYWRkaW5nV2lkdGg6IG51bWJlclxufVxuXG5jb25zdCBRdWV1ZWRNZXNzYWdlQ29udGV4dCA9IFJlYWN0LmNyZWF0ZUNvbnRleHQ8XG4gIFF1ZXVlZE1lc3NhZ2VDb250ZXh0VmFsdWUgfCB1bmRlZmluZWRcbj4odW5kZWZpbmVkKVxuXG5leHBvcnQgZnVuY3Rpb24gdXNlUXVldWVkTWVzc2FnZSgpOiBRdWV1ZWRNZXNzYWdlQ29udGV4dFZhbHVlIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIFJlYWN0LnVzZUNvbnRleHQoUXVldWVkTWVzc2FnZUNvbnRleHQpXG59XG5cbmNvbnN0IFBBRERJTkdfWCA9IDJcblxudHlwZSBQcm9wcyA9IHtcbiAgaXNGaXJzdDogYm9vbGVhblxuICB1c2VCcmllZkxheW91dD86IGJvb2xlYW5cbiAgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gUXVldWVkTWVzc2FnZVByb3ZpZGVyKHtcbiAgaXNGaXJzdCxcbiAgdXNlQnJpZWZMYXlvdXQsXG4gIGNoaWxkcmVuLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICAvLyBCcmllZiBtb2RlIGFscmVhZHkgaW5kZW50cyB2aWEgcGFkZGluZ0xlZnQgaW4gSGlnaGxpZ2h0ZWRUaGlua2luZ1RleHQgL1xuICAvLyBCcmllZlRvb2wgVUkg4oCUIGFkZGluZyBwYWRkaW5nWCBoZXJlIHdvdWxkIGRvdWJsZS1pbmRlbnQgdGhlIHF1ZXVlLlxuICBjb25zdCBwYWRkaW5nID0gdXNlQnJpZWZMYXlvdXQgPyAwIDogUEFERElOR19YXG4gIGNvbnN0IHZhbHVlID0gUmVhY3QudXNlTWVtbyhcbiAgICAoKSA9PiAoeyBpc1F1ZXVlZDogdHJ1ZSwgaXNGaXJzdCwgcGFkZGluZ1dpZHRoOiBwYWRkaW5nICogMiB9KSxcbiAgICBbaXNGaXJzdCwgcGFkZGluZ10sXG4gIClcblxuICByZXR1cm4gKFxuICAgIDxRdWV1ZWRNZXNzYWdlQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PlxuICAgICAgPEJveCBwYWRkaW5nWD17cGFkZGluZ30+e2NoaWxkcmVufTwvQm94PlxuICAgIDwvUXVldWVkTWVzc2FnZUNvbnRleHQuUHJvdmlkZXI+XG4gIClcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sS0FBS0EsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0MsR0FBRyxRQUFRLFdBQVc7QUFFL0IsS0FBS0MseUJBQXlCLEdBQUc7RUFDL0JDLFFBQVEsRUFBRSxPQUFPO0VBQ2pCQyxPQUFPLEVBQUUsT0FBTztFQUNoQjtFQUNBQyxZQUFZLEVBQUUsTUFBTTtBQUN0QixDQUFDO0FBRUQsTUFBTUMsb0JBQW9CLEdBQUdOLEtBQUssQ0FBQ08sYUFBYSxDQUM5Q0wseUJBQXlCLEdBQUcsU0FBUyxDQUN0QyxDQUFDTSxTQUFTLENBQUM7QUFFWixPQUFPLFNBQUFDLGlCQUFBO0VBQUEsT0FDRVQsS0FBSyxDQUFBVSxVQUFXLENBQUNKLG9CQUFvQixDQUFDO0FBQUE7QUFHL0MsTUFBTUssU0FBUyxHQUFHLENBQUM7QUFFbkIsS0FBS0MsS0FBSyxHQUFHO0VBQ1hSLE9BQU8sRUFBRSxPQUFPO0VBQ2hCUyxjQUFjLENBQUMsRUFBRSxPQUFPO0VBQ3hCQyxRQUFRLEVBQUVkLEtBQUssQ0FBQ2UsU0FBUztBQUMzQixDQUFDO0FBRUQsT0FBTyxTQUFBQyxzQkFBQUMsRUFBQTtFQUFBLE1BQUFDLENBQUEsR0FBQUMsRUFBQTtFQUErQjtJQUFBZixPQUFBO0lBQUFTLGNBQUE7SUFBQUM7RUFBQSxJQUFBRyxFQUk5QjtFQUdOLE1BQUFHLE9BQUEsR0FBZ0JQLGNBQWMsR0FBZCxDQUE4QixHQUE5QkYsU0FBOEI7RUFFSSxNQUFBVSxFQUFBLEdBQUFELE9BQU8sR0FBRyxDQUFDO0VBQUEsSUFBQUUsRUFBQTtFQUFBLElBQUFKLENBQUEsUUFBQWQsT0FBQSxJQUFBYyxDQUFBLFFBQUFHLEVBQUE7SUFBcERDLEVBQUE7TUFBQW5CLFFBQUEsRUFBWSxJQUFJO01BQUFDLE9BQUE7TUFBQUMsWUFBQSxFQUF5QmdCO0lBQVksQ0FBQztJQUFBSCxDQUFBLE1BQUFkLE9BQUE7SUFBQWMsQ0FBQSxNQUFBRyxFQUFBO0lBQUFILENBQUEsTUFBQUksRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQUosQ0FBQTtFQUFBO0VBRC9ELE1BQUFLLEtBQUEsR0FDU0QsRUFBc0Q7RUFFOUQsSUFBQUUsRUFBQTtFQUFBLElBQUFOLENBQUEsUUFBQUosUUFBQSxJQUFBSSxDQUFBLFFBQUFFLE9BQUE7SUFJR0ksRUFBQSxJQUFDLEdBQUcsQ0FBV0osUUFBTyxDQUFQQSxRQUFNLENBQUMsQ0FBR04sU0FBTyxDQUFFLEVBQWpDLEdBQUcsQ0FBb0M7SUFBQUksQ0FBQSxNQUFBSixRQUFBO0lBQUFJLENBQUEsTUFBQUUsT0FBQTtJQUFBRixDQUFBLE1BQUFNLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFOLENBQUE7RUFBQTtFQUFBLElBQUFPLEVBQUE7RUFBQSxJQUFBUCxDQUFBLFFBQUFNLEVBQUEsSUFBQU4sQ0FBQSxRQUFBSyxLQUFBO0lBRDFDRSxFQUFBLGtDQUFzQ0YsS0FBSyxDQUFMQSxNQUFJLENBQUMsQ0FDekMsQ0FBQUMsRUFBdUMsQ0FDekMsZ0NBQWdDO0lBQUFOLENBQUEsTUFBQU0sRUFBQTtJQUFBTixDQUFBLE1BQUFLLEtBQUE7SUFBQUwsQ0FBQSxNQUFBTyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBUCxDQUFBO0VBQUE7RUFBQSxPQUZoQ08sRUFFZ0M7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|
||||
@@ -0,0 +1,30 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import type { FpsMetrics } from '../utils/fpsTracker.js';
|
||||
type FpsMetricsGetter = () => FpsMetrics | undefined;
|
||||
const FpsMetricsContext = createContext<FpsMetricsGetter | undefined>(undefined);
|
||||
type Props = {
|
||||
getFpsMetrics: FpsMetricsGetter;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
export function FpsMetricsProvider(t0) {
|
||||
const $ = _c(3);
|
||||
const {
|
||||
getFpsMetrics,
|
||||
children
|
||||
} = t0;
|
||||
let t1;
|
||||
if ($[0] !== children || $[1] !== getFpsMetrics) {
|
||||
t1 = <FpsMetricsContext.Provider value={getFpsMetrics}>{children}</FpsMetricsContext.Provider>;
|
||||
$[0] = children;
|
||||
$[1] = getFpsMetrics;
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
export function useFpsMetrics() {
|
||||
return useContext(FpsMetricsContext);
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsImNyZWF0ZUNvbnRleHQiLCJ1c2VDb250ZXh0IiwiRnBzTWV0cmljcyIsIkZwc01ldHJpY3NHZXR0ZXIiLCJGcHNNZXRyaWNzQ29udGV4dCIsInVuZGVmaW5lZCIsIlByb3BzIiwiZ2V0RnBzTWV0cmljcyIsImNoaWxkcmVuIiwiUmVhY3ROb2RlIiwiRnBzTWV0cmljc1Byb3ZpZGVyIiwidDAiLCIkIiwiX2MiLCJ0MSIsInVzZUZwc01ldHJpY3MiXSwic291cmNlcyI6WyJmcHNNZXRyaWNzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QsIHsgY3JlYXRlQ29udGV4dCwgdXNlQ29udGV4dCB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHR5cGUgeyBGcHNNZXRyaWNzIH0gZnJvbSAnLi4vdXRpbHMvZnBzVHJhY2tlci5qcydcblxudHlwZSBGcHNNZXRyaWNzR2V0dGVyID0gKCkgPT4gRnBzTWV0cmljcyB8IHVuZGVmaW5lZFxuXG5jb25zdCBGcHNNZXRyaWNzQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8RnBzTWV0cmljc0dldHRlciB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKVxuXG50eXBlIFByb3BzID0ge1xuICBnZXRGcHNNZXRyaWNzOiBGcHNNZXRyaWNzR2V0dGVyXG4gIGNoaWxkcmVuOiBSZWFjdC5SZWFjdE5vZGVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIEZwc01ldHJpY3NQcm92aWRlcih7XG4gIGdldEZwc01ldHJpY3MsXG4gIGNoaWxkcmVuLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICByZXR1cm4gKFxuICAgIDxGcHNNZXRyaWNzQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17Z2V0RnBzTWV0cmljc30+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9GcHNNZXRyaWNzQ29udGV4dC5Qcm92aWRlcj5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXNlRnBzTWV0cmljcygpOiBGcHNNZXRyaWNzR2V0dGVyIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHVzZUNvbnRleHQoRnBzTWV0cmljc0NvbnRleHQpXG59XG4iXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPQSxLQUFLLElBQUlDLGFBQWEsRUFBRUMsVUFBVSxRQUFRLE9BQU87QUFDeEQsY0FBY0MsVUFBVSxRQUFRLHdCQUF3QjtBQUV4RCxLQUFLQyxnQkFBZ0IsR0FBRyxHQUFHLEdBQUdELFVBQVUsR0FBRyxTQUFTO0FBRXBELE1BQU1FLGlCQUFpQixHQUFHSixhQUFhLENBQUNHLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxDQUFDRSxTQUFTLENBQUM7QUFFaEYsS0FBS0MsS0FBSyxHQUFHO0VBQ1hDLGFBQWEsRUFBRUosZ0JBQWdCO0VBQy9CSyxRQUFRLEVBQUVULEtBQUssQ0FBQ1UsU0FBUztBQUMzQixDQUFDO0FBRUQsT0FBTyxTQUFBQyxtQkFBQUMsRUFBQTtFQUFBLE1BQUFDLENBQUEsR0FBQUMsRUFBQTtFQUE0QjtJQUFBTixhQUFBO0lBQUFDO0VBQUEsSUFBQUcsRUFHM0I7RUFBQSxJQUFBRyxFQUFBO0VBQUEsSUFBQUYsQ0FBQSxRQUFBSixRQUFBLElBQUFJLENBQUEsUUFBQUwsYUFBQTtJQUVKTyxFQUFBLCtCQUFtQ1AsS0FBYSxDQUFiQSxjQUFZLENBQUMsQ0FDN0NDLFNBQU8sQ0FDViw2QkFBNkI7SUFBQUksQ0FBQSxNQUFBSixRQUFBO0lBQUFJLENBQUEsTUFBQUwsYUFBQTtJQUFBSyxDQUFBLE1BQUFFLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFGLENBQUE7RUFBQTtFQUFBLE9BRjdCRSxFQUU2QjtBQUFBO0FBSWpDLE9BQU8sU0FBQUMsY0FBQTtFQUFBLE9BQ0VkLFVBQVUsQ0FBQ0csaUJBQWlCLENBQUM7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|
||||
@@ -0,0 +1,38 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import React, { createContext, useContext, useMemo } from 'react';
|
||||
import { Mailbox } from '../utils/mailbox.js';
|
||||
const MailboxContext = createContext<Mailbox | undefined>(undefined);
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
export function MailboxProvider(t0) {
|
||||
const $ = _c(3);
|
||||
const {
|
||||
children
|
||||
} = t0;
|
||||
let t1;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = new Mailbox();
|
||||
$[0] = t1;
|
||||
} else {
|
||||
t1 = $[0];
|
||||
}
|
||||
const mailbox = t1;
|
||||
let t2;
|
||||
if ($[1] !== children) {
|
||||
t2 = <MailboxContext.Provider value={mailbox}>{children}</MailboxContext.Provider>;
|
||||
$[1] = children;
|
||||
$[2] = t2;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
export function useMailbox() {
|
||||
const mailbox = useContext(MailboxContext);
|
||||
if (!mailbox) {
|
||||
throw new Error("useMailbox must be used within a MailboxProvider");
|
||||
}
|
||||
return mailbox;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsImNyZWF0ZUNvbnRleHQiLCJ1c2VDb250ZXh0IiwidXNlTWVtbyIsIk1haWxib3giLCJNYWlsYm94Q29udGV4dCIsInVuZGVmaW5lZCIsIlByb3BzIiwiY2hpbGRyZW4iLCJSZWFjdE5vZGUiLCJNYWlsYm94UHJvdmlkZXIiLCJ0MCIsIiQiLCJfYyIsInQxIiwiU3ltYm9sIiwiZm9yIiwibWFpbGJveCIsInQyIiwidXNlTWFpbGJveCIsIkVycm9yIl0sInNvdXJjZXMiOlsibWFpbGJveC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0LCB7IGNyZWF0ZUNvbnRleHQsIHVzZUNvbnRleHQsIHVzZU1lbW8gfSBmcm9tICdyZWFjdCdcbmltcG9ydCB7IE1haWxib3ggfSBmcm9tICcuLi91dGlscy9tYWlsYm94LmpzJ1xuXG5jb25zdCBNYWlsYm94Q29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8TWFpbGJveCB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKVxuXG50eXBlIFByb3BzID0ge1xuICBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBNYWlsYm94UHJvdmlkZXIoeyBjaGlsZHJlbiB9OiBQcm9wcyk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IG1haWxib3ggPSB1c2VNZW1vKCgpID0+IG5ldyBNYWlsYm94KCksIFtdKVxuICByZXR1cm4gKFxuICAgIDxNYWlsYm94Q29udGV4dC5Qcm92aWRlciB2YWx1ZT17bWFpbGJveH0+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9NYWlsYm94Q29udGV4dC5Qcm92aWRlcj5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXNlTWFpbGJveCgpOiBNYWlsYm94IHtcbiAgY29uc3QgbWFpbGJveCA9IHVzZUNvbnRleHQoTWFpbGJveENvbnRleHQpXG4gIGlmICghbWFpbGJveCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXNlTWFpbGJveCBtdXN0IGJlIHVzZWQgd2l0aGluIGEgTWFpbGJveFByb3ZpZGVyJylcbiAgfVxuICByZXR1cm4gbWFpbGJveFxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBT0EsS0FBSyxJQUFJQyxhQUFhLEVBQUVDLFVBQVUsRUFBRUMsT0FBTyxRQUFRLE9BQU87QUFDakUsU0FBU0MsT0FBTyxRQUFRLHFCQUFxQjtBQUU3QyxNQUFNQyxjQUFjLEdBQUdKLGFBQWEsQ0FBQ0csT0FBTyxHQUFHLFNBQVMsQ0FBQyxDQUFDRSxTQUFTLENBQUM7QUFFcEUsS0FBS0MsS0FBSyxHQUFHO0VBQ1hDLFFBQVEsRUFBRVIsS0FBSyxDQUFDUyxTQUFTO0FBQzNCLENBQUM7QUFFRCxPQUFPLFNBQUFDLGdCQUFBQyxFQUFBO0VBQUEsTUFBQUMsQ0FBQSxHQUFBQyxFQUFBO0VBQXlCO0lBQUFMO0VBQUEsSUFBQUcsRUFBbUI7RUFBQSxJQUFBRyxFQUFBO0VBQUEsSUFBQUYsQ0FBQSxRQUFBRyxNQUFBLENBQUFDLEdBQUE7SUFDbkJGLEVBQUEsT0FBSVYsT0FBTyxDQUFDLENBQUM7SUFBQVEsQ0FBQSxNQUFBRSxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBRixDQUFBO0VBQUE7RUFBM0MsTUFBQUssT0FBQSxHQUE4QkgsRUFBYTtFQUFLLElBQUFJLEVBQUE7RUFBQSxJQUFBTixDQUFBLFFBQUFKLFFBQUE7SUFFOUNVLEVBQUEsNEJBQWdDRCxLQUFPLENBQVBBLFFBQU0sQ0FBQyxDQUNwQ1QsU0FBTyxDQUNWLDBCQUEwQjtJQUFBSSxDQUFBLE1BQUFKLFFBQUE7SUFBQUksQ0FBQSxNQUFBTSxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBTixDQUFBO0VBQUE7RUFBQSxPQUYxQk0sRUFFMEI7QUFBQTtBQUk5QixPQUFPLFNBQUFDLFdBQUE7RUFDTCxNQUFBRixPQUFBLEdBQWdCZixVQUFVLENBQUNHLGNBQWMsQ0FBQztFQUMxQyxJQUFJLENBQUNZLE9BQU87SUFDVixNQUFNLElBQUlHLEtBQUssQ0FBQyxrREFBa0QsQ0FBQztFQUFBO0VBQ3BFLE9BQ01ILE9BQU87QUFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|
||||
@@ -0,0 +1,58 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { createContext, type RefObject, useContext } from 'react';
|
||||
import type { ScrollBoxHandle } from '../ink/components/ScrollBox.js';
|
||||
|
||||
/**
|
||||
* Set by FullscreenLayout when rendering content in its `modal` slot —
|
||||
* the absolute-positioned bottom-anchored pane for slash-command dialogs.
|
||||
* Consumers use this to:
|
||||
*
|
||||
* - Suppress top-level framing — `Pane` skips its full-terminal-width
|
||||
* `Divider` (FullscreenLayout already draws the ▔ divider).
|
||||
* - Size Select pagination to the available rows — the modal's inner
|
||||
* area is smaller than the terminal (rows minus transcript peek minus
|
||||
* divider), so components that cap their visible option count from
|
||||
* `useTerminalSize().rows` would overflow without this context.
|
||||
* - Reset scroll on tab switch — Tabs keys its ScrollBox by
|
||||
* `selectedTabIndex`, remounting on tab switch so scrollTop resets to 0
|
||||
* without scrollTo() timing games.
|
||||
*
|
||||
* null = not inside the modal slot.
|
||||
*/
|
||||
type ModalCtx = {
|
||||
rows: number;
|
||||
columns: number;
|
||||
scrollRef: RefObject<ScrollBoxHandle | null> | null;
|
||||
};
|
||||
export const ModalContext = createContext<ModalCtx | null>(null);
|
||||
export function useIsInsideModal() {
|
||||
return useContext(ModalContext) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Available content rows/columns when inside a Modal, else falls back to
|
||||
* the provided terminal size. Use instead of `useTerminalSize()` when a
|
||||
* component caps its visible content height — the modal's inner area is
|
||||
* smaller than the terminal.
|
||||
*/
|
||||
export function useModalOrTerminalSize(fallback) {
|
||||
const $ = _c(3);
|
||||
const ctx = useContext(ModalContext);
|
||||
let t0;
|
||||
if ($[0] !== ctx || $[1] !== fallback) {
|
||||
t0 = ctx ? {
|
||||
rows: ctx.rows,
|
||||
columns: ctx.columns
|
||||
} : fallback;
|
||||
$[0] = ctx;
|
||||
$[1] = fallback;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
export function useModalScrollRef() {
|
||||
return useContext(ModalContext)?.scrollRef ?? null;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjcmVhdGVDb250ZXh0IiwiUmVmT2JqZWN0IiwidXNlQ29udGV4dCIsIlNjcm9sbEJveEhhbmRsZSIsIk1vZGFsQ3R4Iiwicm93cyIsImNvbHVtbnMiLCJzY3JvbGxSZWYiLCJNb2RhbENvbnRleHQiLCJ1c2VJc0luc2lkZU1vZGFsIiwidXNlTW9kYWxPclRlcm1pbmFsU2l6ZSIsImZhbGxiYWNrIiwiJCIsIl9jIiwiY3R4IiwidDAiLCJ1c2VNb2RhbFNjcm9sbFJlZiJdLCJzb3VyY2VzIjpbIm1vZGFsQ29udGV4dC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlQ29udGV4dCwgdHlwZSBSZWZPYmplY3QsIHVzZUNvbnRleHQgfSBmcm9tICdyZWFjdCdcbmltcG9ydCB0eXBlIHsgU2Nyb2xsQm94SGFuZGxlIH0gZnJvbSAnLi4vaW5rL2NvbXBvbmVudHMvU2Nyb2xsQm94LmpzJ1xuXG4vKipcbiAqIFNldCBieSBGdWxsc2NyZWVuTGF5b3V0IHdoZW4gcmVuZGVyaW5nIGNvbnRlbnQgaW4gaXRzIGBtb2RhbGAgc2xvdCDigJRcbiAqIHRoZSBhYnNvbHV0ZS1wb3NpdGlvbmVkIGJvdHRvbS1hbmNob3JlZCBwYW5lIGZvciBzbGFzaC1jb21tYW5kIGRpYWxvZ3MuXG4gKiBDb25zdW1lcnMgdXNlIHRoaXMgdG86XG4gKlxuICogLSBTdXBwcmVzcyB0b3AtbGV2ZWwgZnJhbWluZyDigJQgYFBhbmVgIHNraXBzIGl0cyBmdWxsLXRlcm1pbmFsLXdpZHRoXG4gKiAgIGBEaXZpZGVyYCAoRnVsbHNjcmVlbkxheW91dCBhbHJlYWR5IGRyYXdzIHRoZSDilpQgZGl2aWRlcikuXG4gKiAtIFNpemUgU2VsZWN0IHBhZ2luYXRpb24gdG8gdGhlIGF2YWlsYWJsZSByb3dzIOKAlCB0aGUgbW9kYWwncyBpbm5lclxuICogICBhcmVhIGlzIHNtYWxsZXIgdGhhbiB0aGUgdGVybWluYWwgKHJvd3MgbWludXMgdHJhbnNjcmlwdCBwZWVrIG1pbnVzXG4gKiAgIGRpdmlkZXIpLCBzbyBjb21wb25lbnRzIHRoYXQgY2FwIHRoZWlyIHZpc2libGUgb3B0aW9uIGNvdW50IGZyb21cbiAqICAgYHVzZVRlcm1pbmFsU2l6ZSgpLnJvd3NgIHdvdWxkIG92ZXJmbG93IHdpdGhvdXQgdGhpcyBjb250ZXh0LlxuICogLSBSZXNldCBzY3JvbGwgb24gdGFiIHN3aXRjaCDigJQgVGFicyBrZXlzIGl0cyBTY3JvbGxCb3ggYnlcbiAqICAgYHNlbGVjdGVkVGFiSW5kZXhgLCByZW1vdW50aW5nIG9uIHRhYiBzd2l0Y2ggc28gc2Nyb2xsVG9wIHJlc2V0cyB0byAwXG4gKiAgIHdpdGhvdXQgc2Nyb2xsVG8oKSB0aW1pbmcgZ2FtZXMuXG4gKlxuICogbnVsbCA9IG5vdCBpbnNpZGUgdGhlIG1vZGFsIHNsb3QuXG4gKi9cbnR5cGUgTW9kYWxDdHggPSB7XG4gIHJvd3M6IG51bWJlclxuICBjb2x1bW5zOiBudW1iZXJcbiAgc2Nyb2xsUmVmOiBSZWZPYmplY3Q8U2Nyb2xsQm94SGFuZGxlIHwgbnVsbD4gfCBudWxsXG59XG5leHBvcnQgY29uc3QgTW9kYWxDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxNb2RhbEN0eCB8IG51bGw+KG51bGwpXG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VJc0luc2lkZU1vZGFsKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gdXNlQ29udGV4dChNb2RhbENvbnRleHQpICE9PSBudWxsXG59XG5cbi8qKlxuICogQXZhaWxhYmxlIGNvbnRlbnQgcm93cy9jb2x1bW5zIHdoZW4gaW5zaWRlIGEgTW9kYWwsIGVsc2UgZmFsbHMgYmFjayB0b1xuICogdGhlIHByb3ZpZGVkIHRlcm1pbmFsIHNpemUuIFVzZSBpbnN0ZWFkIG9mIGB1c2VUZXJtaW5hbFNpemUoKWAgd2hlbiBhXG4gKiBjb21wb25lbnQgY2FwcyBpdHMgdmlzaWJsZSBjb250ZW50IGhlaWdodCDigJQgdGhlIG1vZGFsJ3MgaW5uZXIgYXJlYSBpc1xuICogc21hbGxlciB0aGFuIHRoZSB0ZXJtaW5hbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZU1vZGFsT3JUZXJtaW5hbFNpemUoZmFsbGJhY2s6IHtcbiAgcm93czogbnVtYmVyXG4gIGNvbHVtbnM6IG51bWJlclxufSk6IHsgcm93czogbnVtYmVyOyBjb2x1bW5zOiBudW1iZXIgfSB7XG4gIGNvbnN0IGN0eCA9IHVzZUNvbnRleHQoTW9kYWxDb250ZXh0KVxuICByZXR1cm4gY3R4ID8geyByb3dzOiBjdHgucm93cywgY29sdW1uczogY3R4LmNvbHVtbnMgfSA6IGZhbGxiYWNrXG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VNb2RhbFNjcm9sbFJlZigpOiBSZWZPYmplY3Q8U2Nyb2xsQm94SGFuZGxlIHwgbnVsbD4gfCBudWxsIHtcbiAgcmV0dXJuIHVzZUNvbnRleHQoTW9kYWxDb250ZXh0KT8uc2Nyb2xsUmVmID8/IG51bGxcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLFNBQVNBLGFBQWEsRUFBRSxLQUFLQyxTQUFTLEVBQUVDLFVBQVUsUUFBUSxPQUFPO0FBQ2pFLGNBQWNDLGVBQWUsUUFBUSxnQ0FBZ0M7O0FBRXJFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLQyxRQUFRLEdBQUc7RUFDZEMsSUFBSSxFQUFFLE1BQU07RUFDWkMsT0FBTyxFQUFFLE1BQU07RUFDZkMsU0FBUyxFQUFFTixTQUFTLENBQUNFLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJO0FBQ3JELENBQUM7QUFDRCxPQUFPLE1BQU1LLFlBQVksR0FBR1IsYUFBYSxDQUFDSSxRQUFRLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO0FBRWhFLE9BQU8sU0FBQUssaUJBQUE7RUFBQSxPQUNFUCxVQUFVLENBQUNNLFlBQVksQ0FBQyxLQUFLLElBQUk7QUFBQTs7QUFHMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxTQUFBRSx1QkFBQUMsUUFBQTtFQUFBLE1BQUFDLENBQUEsR0FBQUMsRUFBQTtFQUlMLE1BQUFDLEdBQUEsR0FBWVosVUFBVSxDQUFDTSxZQUFZLENBQUM7RUFBQSxJQUFBTyxFQUFBO0VBQUEsSUFBQUgsQ0FBQSxRQUFBRSxHQUFBLElBQUFGLENBQUEsUUFBQUQsUUFBQTtJQUM3QkksRUFBQSxHQUFBRCxHQUFHLEdBQUg7TUFBQVQsSUFBQSxFQUFjUyxHQUFHLENBQUFULElBQUs7TUFBQUMsT0FBQSxFQUFXUSxHQUFHLENBQUFSO0lBQW9CLENBQUMsR0FBekRLLFFBQXlEO0lBQUFDLENBQUEsTUFBQUUsR0FBQTtJQUFBRixDQUFBLE1BQUFELFFBQUE7SUFBQUMsQ0FBQSxNQUFBRyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBSCxDQUFBO0VBQUE7RUFBQSxPQUF6REcsRUFBeUQ7QUFBQTtBQUdsRSxPQUFPLFNBQUFDLGtCQUFBO0VBQUEsT0FDRWQsVUFBVSxDQUFDTSxZQUF1QixDQUFDLEVBQUFELFNBQVEsSUFBM0MsSUFBMkM7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|
||||
@@ -0,0 +1,240 @@
|
||||
import type * as React from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useAppStateStore, useSetAppState } from 'src/state/AppState.js';
|
||||
import type { Theme } from '../utils/theme.js';
|
||||
type Priority = 'low' | 'medium' | 'high' | 'immediate';
|
||||
type BaseNotification = {
|
||||
key: string;
|
||||
/**
|
||||
* Keys of notifications that this notification invalidates.
|
||||
* If a notification is invalidated, it will be removed from the queue
|
||||
* and, if currently displayed, cleared immediately.
|
||||
*/
|
||||
invalidates?: string[];
|
||||
priority: Priority;
|
||||
timeoutMs?: number;
|
||||
/**
|
||||
* Combine notifications with the same key, like Array.reduce().
|
||||
* Called as fold(accumulator, incoming) when a notification with a matching
|
||||
* key already exists in the queue or is currently displayed.
|
||||
* Returns the merged notification (should carry fold forward for future merges).
|
||||
*/
|
||||
fold?: (accumulator: Notification, incoming: Notification) => Notification;
|
||||
};
|
||||
type TextNotification = BaseNotification & {
|
||||
text: string;
|
||||
color?: keyof Theme;
|
||||
};
|
||||
type JSXNotification = BaseNotification & {
|
||||
jsx: React.ReactNode;
|
||||
};
|
||||
type AddNotificationFn = (content: Notification) => void;
|
||||
type RemoveNotificationFn = (key: string) => void;
|
||||
export type Notification = TextNotification | JSXNotification;
|
||||
const DEFAULT_TIMEOUT_MS = 8000;
|
||||
|
||||
// Track current timeout to clear it when immediate notifications arrive
|
||||
let currentTimeoutId: NodeJS.Timeout | null = null;
|
||||
export function useNotifications(): {
|
||||
addNotification: AddNotificationFn;
|
||||
removeNotification: RemoveNotificationFn;
|
||||
} {
|
||||
const store = useAppStateStore();
|
||||
const setAppState = useSetAppState();
|
||||
|
||||
// Process queue when current notification finishes or queue changes
|
||||
const processQueue = useCallback(() => {
|
||||
setAppState(prev => {
|
||||
const next = getNext(prev.notifications.queue);
|
||||
if (prev.notifications.current !== null || !next) {
|
||||
return prev;
|
||||
}
|
||||
currentTimeoutId = setTimeout((setAppState, nextKey, processQueue) => {
|
||||
currentTimeoutId = null;
|
||||
setAppState(prev => {
|
||||
// Compare by key instead of reference to handle re-created notifications
|
||||
if (prev.notifications.current?.key !== nextKey) {
|
||||
return prev;
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
notifications: {
|
||||
queue: prev.notifications.queue,
|
||||
current: null
|
||||
}
|
||||
};
|
||||
});
|
||||
processQueue();
|
||||
}, next.timeoutMs ?? DEFAULT_TIMEOUT_MS, setAppState, next.key, processQueue);
|
||||
return {
|
||||
...prev,
|
||||
notifications: {
|
||||
queue: prev.notifications.queue.filter(_ => _ !== next),
|
||||
current: next
|
||||
}
|
||||
};
|
||||
});
|
||||
}, [setAppState]);
|
||||
const addNotification = useCallback<AddNotificationFn>((notif: Notification) => {
|
||||
// Handle immediate priority notifications
|
||||
if (notif.priority === 'immediate') {
|
||||
// Clear any existing timeout since we're showing a new immediate notification
|
||||
if (currentTimeoutId) {
|
||||
clearTimeout(currentTimeoutId);
|
||||
currentTimeoutId = null;
|
||||
}
|
||||
|
||||
// Set up timeout for the immediate notification
|
||||
currentTimeoutId = setTimeout((setAppState, notif, processQueue) => {
|
||||
currentTimeoutId = null;
|
||||
setAppState(prev => {
|
||||
// Compare by key instead of reference to handle re-created notifications
|
||||
if (prev.notifications.current?.key !== notif.key) {
|
||||
return prev;
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
notifications: {
|
||||
queue: prev.notifications.queue.filter(_ => !notif.invalidates?.includes(_.key)),
|
||||
current: null
|
||||
}
|
||||
};
|
||||
});
|
||||
processQueue();
|
||||
}, notif.timeoutMs ?? DEFAULT_TIMEOUT_MS, setAppState, notif, processQueue);
|
||||
|
||||
// Show the immediate notification right away
|
||||
setAppState(prev => ({
|
||||
...prev,
|
||||
notifications: {
|
||||
current: notif,
|
||||
queue:
|
||||
// Only re-queue the current notification if it's not immediate
|
||||
[...(prev.notifications.current ? [prev.notifications.current] : []), ...prev.notifications.queue].filter(_ => _.priority !== 'immediate' && !notif.invalidates?.includes(_.key))
|
||||
}
|
||||
}));
|
||||
return; // IMPORTANT: Exit addNotification for immediate notifications
|
||||
}
|
||||
|
||||
// Handle non-immediate notifications
|
||||
setAppState(prev => {
|
||||
// Check if we can fold into an existing notification with the same key
|
||||
if (notif.fold) {
|
||||
// Fold into current notification if keys match
|
||||
if (prev.notifications.current?.key === notif.key) {
|
||||
const folded = notif.fold(prev.notifications.current, notif);
|
||||
// Reset timeout for the folded notification
|
||||
if (currentTimeoutId) {
|
||||
clearTimeout(currentTimeoutId);
|
||||
currentTimeoutId = null;
|
||||
}
|
||||
currentTimeoutId = setTimeout((setAppState, foldedKey, processQueue) => {
|
||||
currentTimeoutId = null;
|
||||
setAppState(p => {
|
||||
if (p.notifications.current?.key !== foldedKey) {
|
||||
return p;
|
||||
}
|
||||
return {
|
||||
...p,
|
||||
notifications: {
|
||||
queue: p.notifications.queue,
|
||||
current: null
|
||||
}
|
||||
};
|
||||
});
|
||||
processQueue();
|
||||
}, folded.timeoutMs ?? DEFAULT_TIMEOUT_MS, setAppState, folded.key, processQueue);
|
||||
return {
|
||||
...prev,
|
||||
notifications: {
|
||||
current: folded,
|
||||
queue: prev.notifications.queue
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Fold into queued notification if keys match
|
||||
const queueIdx = prev.notifications.queue.findIndex(_ => _.key === notif.key);
|
||||
if (queueIdx !== -1) {
|
||||
const folded = notif.fold(prev.notifications.queue[queueIdx]!, notif);
|
||||
const newQueue = [...prev.notifications.queue];
|
||||
newQueue[queueIdx] = folded;
|
||||
return {
|
||||
...prev,
|
||||
notifications: {
|
||||
current: prev.notifications.current,
|
||||
queue: newQueue
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Only add to queue if not already present (prevent duplicates)
|
||||
const queuedKeys = new Set(prev.notifications.queue.map(_ => _.key));
|
||||
const shouldAdd = !queuedKeys.has(notif.key) && prev.notifications.current?.key !== notif.key;
|
||||
if (!shouldAdd) return prev;
|
||||
const invalidatesCurrent = prev.notifications.current !== null && notif.invalidates?.includes(prev.notifications.current.key);
|
||||
if (invalidatesCurrent && currentTimeoutId) {
|
||||
clearTimeout(currentTimeoutId);
|
||||
currentTimeoutId = null;
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
notifications: {
|
||||
current: invalidatesCurrent ? null : prev.notifications.current,
|
||||
queue: [...prev.notifications.queue.filter(_ => _.priority !== 'immediate' && !notif.invalidates?.includes(_.key)), notif]
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// Process queue after adding the notification
|
||||
processQueue();
|
||||
}, [setAppState, processQueue]);
|
||||
const removeNotification = useCallback<RemoveNotificationFn>((key: string) => {
|
||||
setAppState(prev => {
|
||||
const isCurrent = prev.notifications.current?.key === key;
|
||||
const inQueue = prev.notifications.queue.some(n => n.key === key);
|
||||
if (!isCurrent && !inQueue) {
|
||||
return prev;
|
||||
}
|
||||
if (isCurrent && currentTimeoutId) {
|
||||
clearTimeout(currentTimeoutId);
|
||||
currentTimeoutId = null;
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
notifications: {
|
||||
current: isCurrent ? null : prev.notifications.current,
|
||||
queue: prev.notifications.queue.filter(n => n.key !== key)
|
||||
}
|
||||
};
|
||||
});
|
||||
processQueue();
|
||||
}, [setAppState, processQueue]);
|
||||
|
||||
// Process queue on mount if there are notifications in the initial state.
|
||||
// Imperative read (not useAppState) — a subscription in a mount-only
|
||||
// effect would be vestigial and make every caller re-render on queue changes.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: mount-only effect, store is a stable context ref
|
||||
useEffect(() => {
|
||||
if (store.getState().notifications.queue.length > 0) {
|
||||
processQueue();
|
||||
}
|
||||
}, []);
|
||||
return {
|
||||
addNotification,
|
||||
removeNotification
|
||||
};
|
||||
}
|
||||
const PRIORITIES: Record<Priority, number> = {
|
||||
immediate: 0,
|
||||
high: 1,
|
||||
medium: 2,
|
||||
low: 3
|
||||
};
|
||||
export function getNext(queue: Notification[]): Notification | undefined {
|
||||
if (queue.length === 0) return undefined;
|
||||
return queue.reduce((min, n) => PRIORITIES[n.priority] < PRIORITIES[min.priority] ? n : min);
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsInVzZUNhbGxiYWNrIiwidXNlRWZmZWN0IiwidXNlQXBwU3RhdGVTdG9yZSIsInVzZVNldEFwcFN0YXRlIiwiVGhlbWUiLCJQcmlvcml0eSIsIkJhc2VOb3RpZmljYXRpb24iLCJrZXkiLCJpbnZhbGlkYXRlcyIsInByaW9yaXR5IiwidGltZW91dE1zIiwiZm9sZCIsImFjY3VtdWxhdG9yIiwiTm90aWZpY2F0aW9uIiwiaW5jb21pbmciLCJUZXh0Tm90aWZpY2F0aW9uIiwidGV4dCIsImNvbG9yIiwiSlNYTm90aWZpY2F0aW9uIiwianN4IiwiUmVhY3ROb2RlIiwiQWRkTm90aWZpY2F0aW9uRm4iLCJjb250ZW50IiwiUmVtb3ZlTm90aWZpY2F0aW9uRm4iLCJERUZBVUxUX1RJTUVPVVRfTVMiLCJjdXJyZW50VGltZW91dElkIiwiTm9kZUpTIiwiVGltZW91dCIsInVzZU5vdGlmaWNhdGlvbnMiLCJhZGROb3RpZmljYXRpb24iLCJyZW1vdmVOb3RpZmljYXRpb24iLCJzdG9yZSIsInNldEFwcFN0YXRlIiwicHJvY2Vzc1F1ZXVlIiwicHJldiIsIm5leHQiLCJnZXROZXh0Iiwibm90aWZpY2F0aW9ucyIsInF1ZXVlIiwiY3VycmVudCIsInNldFRpbWVvdXQiLCJuZXh0S2V5IiwiZmlsdGVyIiwiXyIsIm5vdGlmIiwiY2xlYXJUaW1lb3V0IiwiaW5jbHVkZXMiLCJmb2xkZWQiLCJmb2xkZWRLZXkiLCJwIiwicXVldWVJZHgiLCJmaW5kSW5kZXgiLCJuZXdRdWV1ZSIsInF1ZXVlZEtleXMiLCJTZXQiLCJtYXAiLCJzaG91bGRBZGQiLCJoYXMiLCJpbnZhbGlkYXRlc0N1cnJlbnQiLCJpc0N1cnJlbnQiLCJpblF1ZXVlIiwic29tZSIsIm4iLCJnZXRTdGF0ZSIsImxlbmd0aCIsIlBSSU9SSVRJRVMiLCJSZWNvcmQiLCJpbW1lZGlhdGUiLCJoaWdoIiwibWVkaXVtIiwibG93IiwidW5kZWZpbmVkIiwicmVkdWNlIiwibWluIl0sInNvdXJjZXMiOlsibm90aWZpY2F0aW9ucy50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QgfSBmcm9tICdyZWFjdCdcbmltcG9ydCB7IHVzZUFwcFN0YXRlU3RvcmUsIHVzZVNldEFwcFN0YXRlIH0gZnJvbSAnc3JjL3N0YXRlL0FwcFN0YXRlLmpzJ1xuaW1wb3J0IHR5cGUgeyBUaGVtZSB9IGZyb20gJy4uL3V0aWxzL3RoZW1lLmpzJ1xuXG50eXBlIFByaW9yaXR5ID0gJ2xvdycgfCAnbWVkaXVtJyB8ICdoaWdoJyB8ICdpbW1lZGlhdGUnXG5cbnR5cGUgQmFzZU5vdGlmaWNhdGlvbiA9IHtcbiAga2V5OiBzdHJpbmdcbiAgLyoqXG4gICAqIEtleXMgb2Ygbm90aWZpY2F0aW9ucyB0aGF0IHRoaXMgbm90aWZpY2F0aW9uIGludmFsaWRhdGVzLlxuICAgKiBJZiBhIG5vdGlmaWNhdGlvbiBpcyBpbnZhbGlkYXRlZCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIHF1ZXVlXG4gICAqIGFuZCwgaWYgY3VycmVudGx5IGRpc3BsYXllZCwgY2xlYXJlZCBpbW1lZGlhdGVseS5cbiAgICovXG4gIGludmFsaWRhdGVzPzogc3RyaW5nW11cbiAgcHJpb3JpdHk6IFByaW9yaXR5XG4gIHRpbWVvdXRNcz86IG51bWJlclxuICAvKipcbiAgICogQ29tYmluZSBub3RpZmljYXRpb25zIHdpdGggdGhlIHNhbWUga2V5LCBsaWtlIEFycmF5LnJlZHVjZSgpLlxuICAgKiBDYWxsZWQgYXMgZm9sZChhY2N1bXVsYXRvciwgaW5jb21pbmcpIHdoZW4gYSBub3RpZmljYXRpb24gd2l0aCBhIG1hdGNoaW5nXG4gICAqIGtleSBhbHJlYWR5IGV4aXN0cyBpbiB0aGUgcXVldWUgb3IgaXMgY3VycmVudGx5IGRpc3BsYXllZC5cbiAgICogUmV0dXJucyB0aGUgbWVyZ2VkIG5vdGlmaWNhdGlvbiAoc2hvdWxkIGNhcnJ5IGZvbGQgZm9yd2FyZCBmb3IgZnV0dXJlIG1lcmdlcykuXG4gICAqL1xuICBmb2xkPzogKGFjY3VtdWxhdG9yOiBOb3RpZmljYXRpb24sIGluY29taW5nOiBOb3RpZmljYXRpb24pID0+IE5vdGlmaWNhdGlvblxufVxuXG50eXBlIFRleHROb3RpZmljYXRpb24gPSBCYXNlTm90aWZpY2F0aW9uICYge1xuICB0ZXh0OiBzdHJpbmdcbiAgY29sb3I/OiBrZXlvZiBUaGVtZVxufVxuXG50eXBlIEpTWE5vdGlmaWNhdGlvbiA9IEJhc2VOb3RpZmljYXRpb24gJiB7XG4gIGpzeDogUmVhY3QuUmVhY3ROb2RlXG59XG5cbnR5cGUgQWRkTm90aWZpY2F0aW9uRm4gPSAoY29udGVudDogTm90aWZpY2F0aW9uKSA9PiB2b2lkXG50eXBlIFJlbW92ZU5vdGlmaWNhdGlvbkZuID0gKGtleTogc3RyaW5nKSA9PiB2b2lkXG5cbmV4cG9ydCB0eXBlIE5vdGlmaWNhdGlvbiA9IFRleHROb3RpZmljYXRpb24gfCBKU1hOb3RpZmljYXRpb25cblxuY29uc3QgREVGQVVMVF9USU1FT1VUX01TID0gODAwMFxuXG4vLyBUcmFjayBjdXJyZW50IHRpbWVvdXQgdG8gY2xlYXIgaXQgd2hlbiBpbW1lZGlhdGUgbm90aWZpY2F0aW9ucyBhcnJpdmVcbmxldCBjdXJyZW50VGltZW91dElkOiBOb2RlSlMuVGltZW91dCB8IG51bGwgPSBudWxsXG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VOb3RpZmljYXRpb25zKCk6IHtcbiAgYWRkTm90aWZpY2F0aW9uOiBBZGROb3RpZmljYXRpb25GblxuICByZW1vdmVOb3RpZmljYXRpb246IFJlbW92ZU5vdGlmaWNhdGlvbkZuXG59IHtcbiAgY29uc3Qgc3RvcmUgPSB1c2VBcHBTdGF0ZVN0b3JlKClcbiAgY29uc3Qgc2V0QXBwU3RhdGUgPSB1c2VTZXRBcHBTdGF0ZSgpXG5cbiAgLy8gUHJvY2VzcyBxdWV1ZSB3aGVuIGN1cnJlbnQgbm90aWZpY2F0aW9uIGZpbmlzaGVzIG9yIHF1ZXVlIGNoYW5nZXNcbiAgY29uc3QgcHJvY2Vzc1F1ZXVlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldEFwcFN0YXRlKHByZXYgPT4ge1xuICAgICAgY29uc3QgbmV4dCA9IGdldE5leHQocHJldi5ub3RpZmljYXRpb25zLnF1ZXVlKVxuICAgICAgaWYgKHByZXYubm90aWZpY2F0aW9ucy5jdXJyZW50ICE9PSBudWxsIHx8ICFuZXh0KSB7XG4gICAgICAgIHJldHVybiBwcmV2XG4gICAgICB9XG5cbiAgICAgIGN1cnJlbnRUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KFxuICAgICAgICAoc2V0QXBwU3RhdGUsIG5leHRLZXksIHByb2Nlc3NRdWV1ZSkgPT4ge1xuICAgICAgICAgIGN1cnJlbnRUaW1lb3V0SWQgPSBudWxsXG4gICAgICAgICAgc2V0QXBwU3RhdGUocHJldiA9PiB7XG4gICAgICAgICAgICAvLyBDb21wYXJlIGJ5IGtleSBpbnN0ZWFkIG9mIHJlZmVyZW5jZSB0byBoYW5kbGUgcmUtY3JlYXRlZCBub3RpZmljYXRpb25zXG4gICAgICAgICAgICBpZiAocHJldi5ub3RpZmljYXRpb25zLmN1cnJlbnQ/LmtleSAhPT0gbmV4dEtleSkge1xuICAgICAgICAgICAgICByZXR1cm4gcHJldlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgLi4ucHJldixcbiAgICAgICAgICAgICAgbm90aWZpY2F0aW9uczoge1xuICAgICAgICAgICAgICAgIHF1ZXVlOiBwcmV2Lm5vdGlmaWNhdGlvbnMucXVldWUsXG4gICAgICAgICAgICAgICAgY3VycmVudDogbnVsbCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICAgIHByb2Nlc3NRdWV1ZSgpXG4gICAgICAgIH0sXG4gICAgICAgIG5leHQudGltZW91dE1zID8/IERFRkFVTFRfVElNRU9VVF9NUyxcbiAgICAgICAgc2V0QXBwU3RhdGUsXG4gICAgICAgIG5leHQua2V5LFxuICAgICAgICBwcm9jZXNzUXVldWUsXG4gICAgICApXG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnByZXYsXG4gICAgICAgIG5vdGlmaWNhdGlvbnM6IHtcbiAgICAgICAgICB
Line truncated
|
||||
@@ -0,0 +1,151 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
/**
|
||||
* Overlay tracking for Escape key coordination.
|
||||
*
|
||||
* This solves the problem of escape key handling when overlays (like Select with onCancel)
|
||||
* are open. The CancelRequestHandler needs to know when an overlay is active so it doesn't
|
||||
* cancel requests when the user just wants to dismiss the overlay.
|
||||
*
|
||||
* Usage:
|
||||
* 1. Call useRegisterOverlay() in any overlay component to automatically register it
|
||||
* 2. Call useIsOverlayActive() to check if any overlay is currently active
|
||||
*
|
||||
* The hook automatically registers on mount and unregisters on unmount,
|
||||
* so no manual cleanup or state management is needed.
|
||||
*/
|
||||
import { useContext, useEffect, useLayoutEffect } from 'react';
|
||||
import instances from '../ink/instances.js';
|
||||
import { AppStoreContext, useAppState } from '../state/AppState.js';
|
||||
|
||||
// Non-modal overlays that shouldn't disable TextInput focus
|
||||
const NON_MODAL_OVERLAYS = new Set(['autocomplete']);
|
||||
|
||||
/**
|
||||
* Hook to register a component as an active overlay.
|
||||
* Automatically registers on mount and unregisters on unmount.
|
||||
*
|
||||
* @param id - Unique identifier for this overlay (e.g., 'select', 'multi-select')
|
||||
* @param enabled - Whether to register (default: true). Use this to conditionally register
|
||||
* based on component props, e.g., only register when onCancel is provided.
|
||||
*
|
||||
* @example
|
||||
* // Conditional registration based on whether cancel is supported
|
||||
* function useSelectInput({ state }) {
|
||||
* useRegisterOverlay('select', !!state.onCancel)
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
export function useRegisterOverlay(id, t0) {
|
||||
const $ = _c(8);
|
||||
const enabled = t0 === undefined ? true : t0;
|
||||
const store = useContext(AppStoreContext);
|
||||
const setAppState = store?.setState;
|
||||
let t1;
|
||||
let t2;
|
||||
if ($[0] !== enabled || $[1] !== id || $[2] !== setAppState) {
|
||||
t1 = () => {
|
||||
if (!enabled || !setAppState) {
|
||||
return;
|
||||
}
|
||||
setAppState(prev => {
|
||||
if (prev.activeOverlays.has(id)) {
|
||||
return prev;
|
||||
}
|
||||
const next = new Set(prev.activeOverlays);
|
||||
next.add(id);
|
||||
return {
|
||||
...prev,
|
||||
activeOverlays: next
|
||||
};
|
||||
});
|
||||
return () => {
|
||||
setAppState(prev_0 => {
|
||||
if (!prev_0.activeOverlays.has(id)) {
|
||||
return prev_0;
|
||||
}
|
||||
const next_0 = new Set(prev_0.activeOverlays);
|
||||
next_0.delete(id);
|
||||
return {
|
||||
...prev_0,
|
||||
activeOverlays: next_0
|
||||
};
|
||||
});
|
||||
};
|
||||
};
|
||||
t2 = [id, enabled, setAppState];
|
||||
$[0] = enabled;
|
||||
$[1] = id;
|
||||
$[2] = setAppState;
|
||||
$[3] = t1;
|
||||
$[4] = t2;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
t2 = $[4];
|
||||
}
|
||||
useEffect(t1, t2);
|
||||
let t3;
|
||||
let t4;
|
||||
if ($[5] !== enabled) {
|
||||
t3 = () => {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
return _temp;
|
||||
};
|
||||
t4 = [enabled];
|
||||
$[5] = enabled;
|
||||
$[6] = t3;
|
||||
$[7] = t4;
|
||||
} else {
|
||||
t3 = $[6];
|
||||
t4 = $[7];
|
||||
}
|
||||
useLayoutEffect(t3, t4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to check if any overlay is currently active.
|
||||
* This is reactive - the component will re-render when the overlay state changes.
|
||||
*
|
||||
* @returns true if any overlay is currently active
|
||||
*
|
||||
* @example
|
||||
* function CancelRequestHandler() {
|
||||
* const isOverlayActive = useIsOverlayActive()
|
||||
* const isActive = !isOverlayActive && canCancelRunningTask
|
||||
* useKeybinding('chat:cancel', handleCancel, { isActive })
|
||||
* }
|
||||
*/
|
||||
function _temp() {
|
||||
return instances.get(process.stdout)?.invalidatePrevFrame();
|
||||
}
|
||||
export function useIsOverlayActive() {
|
||||
return useAppState(_temp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to check if any modal overlay is currently active.
|
||||
* Modal overlays are overlays that should capture all input (like Select dialogs).
|
||||
* Non-modal overlays (like autocomplete) don't disable TextInput focus.
|
||||
*
|
||||
* @returns true if any modal overlay is currently active
|
||||
*
|
||||
* @example
|
||||
* // Use for TextInput focus - allows typing during autocomplete
|
||||
* focus: !isSearchingHistory && !isModalOverlayActive
|
||||
*/
|
||||
function _temp2(s) {
|
||||
return s.activeOverlays.size > 0;
|
||||
}
|
||||
export function useIsModalOverlayActive() {
|
||||
return useAppState(_temp3);
|
||||
}
|
||||
function _temp3(s) {
|
||||
for (const id of s.activeOverlays) {
|
||||
if (!NON_MODAL_OVERLAYS.has(id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJ1c2VDb250ZXh0IiwidXNlRWZmZWN0IiwidXNlTGF5b3V0RWZmZWN0IiwiaW5zdGFuY2VzIiwiQXBwU3RvcmVDb250ZXh0IiwidXNlQXBwU3RhdGUiLCJOT05fTU9EQUxfT1ZFUkxBWVMiLCJTZXQiLCJ1c2VSZWdpc3Rlck92ZXJsYXkiLCJpZCIsInQwIiwiJCIsIl9jIiwiZW5hYmxlZCIsInVuZGVmaW5lZCIsInN0b3JlIiwic2V0QXBwU3RhdGUiLCJzZXRTdGF0ZSIsInQxIiwidDIiLCJwcmV2IiwiYWN0aXZlT3ZlcmxheXMiLCJoYXMiLCJuZXh0IiwiYWRkIiwicHJldl8wIiwibmV4dF8wIiwiZGVsZXRlIiwidDMiLCJ0NCIsIl90ZW1wIiwiZ2V0IiwicHJvY2VzcyIsInN0ZG91dCIsImludmFsaWRhdGVQcmV2RnJhbWUiLCJ1c2VJc092ZXJsYXlBY3RpdmUiLCJfdGVtcDIiLCJzIiwic2l6ZSIsInVzZUlzTW9kYWxPdmVybGF5QWN0aXZlIiwiX3RlbXAzIl0sInNvdXJjZXMiOlsib3ZlcmxheUNvbnRleHQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT3ZlcmxheSB0cmFja2luZyBmb3IgRXNjYXBlIGtleSBjb29yZGluYXRpb24uXG4gKlxuICogVGhpcyBzb2x2ZXMgdGhlIHByb2JsZW0gb2YgZXNjYXBlIGtleSBoYW5kbGluZyB3aGVuIG92ZXJsYXlzIChsaWtlIFNlbGVjdCB3aXRoIG9uQ2FuY2VsKVxuICogYXJlIG9wZW4uIFRoZSBDYW5jZWxSZXF1ZXN0SGFuZGxlciBuZWVkcyB0byBrbm93IHdoZW4gYW4gb3ZlcmxheSBpcyBhY3RpdmUgc28gaXQgZG9lc24ndFxuICogY2FuY2VsIHJlcXVlc3RzIHdoZW4gdGhlIHVzZXIganVzdCB3YW50cyB0byBkaXNtaXNzIHRoZSBvdmVybGF5LlxuICpcbiAqIFVzYWdlOlxuICogMS4gQ2FsbCB1c2VSZWdpc3Rlck92ZXJsYXkoKSBpbiBhbnkgb3ZlcmxheSBjb21wb25lbnQgdG8gYXV0b21hdGljYWxseSByZWdpc3RlciBpdFxuICogMi4gQ2FsbCB1c2VJc092ZXJsYXlBY3RpdmUoKSB0byBjaGVjayBpZiBhbnkgb3ZlcmxheSBpcyBjdXJyZW50bHkgYWN0aXZlXG4gKlxuICogVGhlIGhvb2sgYXV0b21hdGljYWxseSByZWdpc3RlcnMgb24gbW91bnQgYW5kIHVucmVnaXN0ZXJzIG9uIHVubW91bnQsXG4gKiBzbyBubyBtYW51YWwgY2xlYW51cCBvciBzdGF0ZSBtYW5hZ2VtZW50IGlzIG5lZWRlZC5cbiAqL1xuaW1wb3J0IHsgdXNlQ29udGV4dCwgdXNlRWZmZWN0LCB1c2VMYXlvdXRFZmZlY3QgfSBmcm9tICdyZWFjdCdcbmltcG9ydCBpbnN0YW5jZXMgZnJvbSAnLi4vaW5rL2luc3RhbmNlcy5qcydcbmltcG9ydCB7IEFwcFN0b3JlQ29udGV4dCwgdXNlQXBwU3RhdGUgfSBmcm9tICcuLi9zdGF0ZS9BcHBTdGF0ZS5qcydcblxuLy8gTm9uLW1vZGFsIG92ZXJsYXlzIHRoYXQgc2hvdWxkbid0IGRpc2FibGUgVGV4dElucHV0IGZvY3VzXG5jb25zdCBOT05fTU9EQUxfT1ZFUkxBWVMgPSBuZXcgU2V0KFsnYXV0b2NvbXBsZXRlJ10pXG5cbi8qKlxuICogSG9vayB0byByZWdpc3RlciBhIGNvbXBvbmVudCBhcyBhbiBhY3RpdmUgb3ZlcmxheS5cbiAqIEF1dG9tYXRpY2FsbHkgcmVnaXN0ZXJzIG9uIG1vdW50IGFuZCB1bnJlZ2lzdGVycyBvbiB1bm1vdW50LlxuICpcbiAqIEBwYXJhbSBpZCAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGlzIG92ZXJsYXkgKGUuZy4sICdzZWxlY3QnLCAnbXVsdGktc2VsZWN0JylcbiAqIEBwYXJhbSBlbmFibGVkIC0gV2hldGhlciB0byByZWdpc3RlciAoZGVmYXVsdDogdHJ1ZSkuIFVzZSB0aGlzIHRvIGNvbmRpdGlvbmFsbHkgcmVnaXN0ZXJcbiAqICAgICAgICAgICAgICAgICAgYmFzZWQgb24gY29tcG9uZW50IHByb3BzLCBlLmcuLCBvbmx5IHJlZ2lzdGVyIHdoZW4gb25DYW5jZWwgaXMgcHJvdmlkZWQuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIENvbmRpdGlvbmFsIHJlZ2lzdHJhdGlvbiBiYXNlZCBvbiB3aGV0aGVyIGNhbmNlbCBpcyBzdXBwb3J0ZWRcbiAqIGZ1bmN0aW9uIHVzZVNlbGVjdElucHV0KHsgc3RhdGUgfSkge1xuICogICB1c2VSZWdpc3Rlck92ZXJsYXkoJ3NlbGVjdCcsICEhc3RhdGUub25DYW5jZWwpXG4gKiAgIC8vIC4uLlxuICogfVxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlUmVnaXN0ZXJPdmVybGF5KGlkOiBzdHJpbmcsIGVuYWJsZWQgPSB0cnVlKTogdm9pZCB7XG4gIC8vIFVzZSBjb250ZXh0IGRpcmVjdGx5IHNvIHRoaXMgaXMgYSBuby1vcCB3aGVuIHJlbmRlcmVkIG91dHNpZGUgQXBwU3RhdGVQcm92aWRlclxuICAvLyAoZS5nLiwgaW4gaXNvbGF0ZWQgY29tcG9uZW50IHRlc3RzIHRoYXQgZG9uJ3QgbmVlZCB0aGUgZnVsbCBhcHAgc3RhdGUgdHJlZSkuXG4gIGNvbnN0IHN0b3JlID0gdXNlQ29udGV4dChBcHBTdG9yZUNvbnRleHQpXG4gIGNvbnN0IHNldEFwcFN0YXRlID0gc3RvcmU/LnNldFN0YXRlXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFlbmFibGVkIHx8ICFzZXRBcHBTdGF0ZSkgcmV0dXJuXG4gICAgc2V0QXBwU3RhdGUocHJldiA9PiB7XG4gICAgICBpZiAocHJldi5hY3RpdmVPdmVybGF5cy5oYXMoaWQpKSByZXR1cm4gcHJldlxuICAgICAgY29uc3QgbmV4dCA9IG5ldyBTZXQocHJldi5hY3RpdmVPdmVybGF5cylcbiAgICAgIG5leHQuYWRkKGlkKVxuICAgICAgcmV0dXJuIHsgLi4ucHJldiwgYWN0aXZlT3ZlcmxheXM6IG5leHQgfVxuICAgIH0pXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIHNldEFwcFN0YXRlKHByZXYgPT4ge1xuICAgICAgICBpZiAoIXByZXYuYWN0aXZlT3ZlcmxheXMuaGFzKGlkKSkgcmV0dXJuIHByZXZcbiAgICAgICAgY29uc3QgbmV4dCA9IG5ldyBTZXQocHJldi5hY3RpdmVPdmVybGF5cylcbiAgICAgICAgbmV4dC5kZWxldGUoaWQpXG4gICAgICAgIHJldHVybiB7IC4uLnByZXYsIGFjdGl2ZU92ZXJsYXlzOiBuZXh0IH1cbiAgICAgIH0pXG4gICAgfVxuICB9LCBbaWQsIGVuYWJsZWQsIHNldEFwcFN0YXRlXSlcblxuICAvLyBPbiBvdmVybGF5IGNsb3NlLCBmb3JjZSB0aGUgbmV4dCByZW5kZXIgdG8gZnVsbC1kYW1hZ2UgZGlmZiBpbnN0ZWFkXG4gIC8vIG9mIGJsaXQuIEEgdGFsbCBvdmVybGF5IChlLmcuIEZ1enp5UGlja2VyIHdpdGggYSAyMC1saW5lIHByZXZpZXcpXG4gIC8vIHNocmlua3MgdGhlIEluay1tYW5hZ2VkIHJlZ2lvbiBvbiB1bm1vdW50OyB0aGUgYmxpdCBmYXN0IHBhdGggY2FuXG4gIC8vIGNvcHkgc3RhbGUgY2VsbHMgZnJvbSB0aGUgb3ZlcmxheSdzIHByZXZpb3VzIGZyYW1lIGludG8gcm93cyB0aGVcbiAgLy8gc2hvcnRlciBsYXlvdXQgbm8gbG9uZ2VyIHJlYWNoZXMsIGxlYXZpbmcgYSBnaG9zdCB0aXRsZS9kaXZpZGVyLlxuICAvLyB1c2VMYXlvdXRFZmZlY3Qgc28gY2xlYW51cCBydW5zIHN5bmNocm9ub3VzbHkgYmVmb3JlIHRoZSBtaWNyb3Rhc2stXG4gIC8vIGRlZmVycmVkIG9uUmVuZGVyIChzY2hlZHVsZVJlbmRlciBxdWV1ZXMgYSBtaWNyb3Rhc2sgZnJvbVxuICAvLyByZXNldEFmdGVyQ29tbWl0OyBwYXNzaXZlLWVmZmVjdCBjbGVhbnVwIHdvdWxkIGxhbmQgYWZ0ZXIgaXQpLlxuICB1c2VMYXlvdXRFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghZW5hYmxlZCkgcmV0dXJuXG4gICAgcmV0dXJuICgpID0+IGluc3RhbmNlcy5nZXQocHJvY2Vzcy5zdGRvdXQpPy5pbnZhbGlkYXRlUHJldkZyYW1lKClcbiAgfSwgW2VuYWJsZWRdKVxufVxuXG4vKipcbiAqIEhvb2sgdG8gY2hlY2sgaWYgYW55IG92ZXJsYXkgaXMgY3VycmVudGx5IGFjdGl2ZS5cbiAqIFRoaXMgaXMgcmVhY3R
Line truncated
|
||||
@@ -0,0 +1,125 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
/**
|
||||
* Portal for content that floats above the prompt so it escapes
|
||||
* FullscreenLayout's bottom-slot `overflowY:hidden` clip.
|
||||
*
|
||||
* The clip is load-bearing (CC-668: tall pastes squash the ScrollBox
|
||||
* without it), but floating overlays use `position:absolute
|
||||
* bottom="100%"` to float above the prompt — and Ink's clip stack
|
||||
* intersects ALL descendants, so they were clipped to ~1 row.
|
||||
*
|
||||
* Two channels:
|
||||
* - `useSetPromptOverlay` — slash-command suggestion data (structured,
|
||||
* written by PromptInputFooter)
|
||||
* - `useSetPromptOverlayDialog` — arbitrary dialog node (e.g.
|
||||
* AutoModeOptInDialog, written by PromptInput)
|
||||
*
|
||||
* FullscreenLayout reads both and renders them outside the clipped slot.
|
||||
*
|
||||
* Split into data/setter context pairs so writers never re-render on
|
||||
* their own writes — the setter contexts are stable.
|
||||
*/
|
||||
import React, { createContext, type ReactNode, useContext, useEffect, useState } from 'react';
|
||||
import type { SuggestionItem } from '../components/PromptInput/PromptInputFooterSuggestions.js';
|
||||
export type PromptOverlayData = {
|
||||
suggestions: SuggestionItem[];
|
||||
selectedSuggestion: number;
|
||||
maxColumnWidth?: number;
|
||||
};
|
||||
type Setter<T> = (d: T | null) => void;
|
||||
const DataContext = createContext<PromptOverlayData | null>(null);
|
||||
const SetContext = createContext<Setter<PromptOverlayData> | null>(null);
|
||||
const DialogContext = createContext<ReactNode>(null);
|
||||
const SetDialogContext = createContext<Setter<ReactNode> | null>(null);
|
||||
export function PromptOverlayProvider(t0) {
|
||||
const $ = _c(6);
|
||||
const {
|
||||
children
|
||||
} = t0;
|
||||
const [data, setData] = useState(null);
|
||||
const [dialog, setDialog] = useState(null);
|
||||
let t1;
|
||||
if ($[0] !== children || $[1] !== dialog) {
|
||||
t1 = <DialogContext.Provider value={dialog}>{children}</DialogContext.Provider>;
|
||||
$[0] = children;
|
||||
$[1] = dialog;
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
let t2;
|
||||
if ($[3] !== data || $[4] !== t1) {
|
||||
t2 = <SetContext.Provider value={setData}><SetDialogContext.Provider value={setDialog}><DataContext.Provider value={data}>{t1}</DataContext.Provider></SetDialogContext.Provider></SetContext.Provider>;
|
||||
$[3] = data;
|
||||
$[4] = t1;
|
||||
$[5] = t2;
|
||||
} else {
|
||||
t2 = $[5];
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
export function usePromptOverlay() {
|
||||
return useContext(DataContext);
|
||||
}
|
||||
export function usePromptOverlayDialog() {
|
||||
return useContext(DialogContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register suggestion data for the floating overlay. Clears on unmount.
|
||||
* No-op outside the provider (non-fullscreen renders inline instead).
|
||||
*/
|
||||
export function useSetPromptOverlay(data) {
|
||||
const $ = _c(4);
|
||||
const set = useContext(SetContext);
|
||||
let t0;
|
||||
let t1;
|
||||
if ($[0] !== data || $[1] !== set) {
|
||||
t0 = () => {
|
||||
if (!set) {
|
||||
return;
|
||||
}
|
||||
set(data);
|
||||
return () => set(null);
|
||||
};
|
||||
t1 = [set, data];
|
||||
$[0] = data;
|
||||
$[1] = set;
|
||||
$[2] = t0;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
t1 = $[3];
|
||||
}
|
||||
useEffect(t0, t1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a dialog node to float above the prompt. Clears on unmount.
|
||||
* No-op outside the provider (non-fullscreen renders inline instead).
|
||||
*/
|
||||
export function useSetPromptOverlayDialog(node) {
|
||||
const $ = _c(4);
|
||||
const set = useContext(SetDialogContext);
|
||||
let t0;
|
||||
let t1;
|
||||
if ($[0] !== node || $[1] !== set) {
|
||||
t0 = () => {
|
||||
if (!set) {
|
||||
return;
|
||||
}
|
||||
set(node);
|
||||
return () => set(null);
|
||||
};
|
||||
t1 = [set, node];
|
||||
$[0] = node;
|
||||
$[1] = set;
|
||||
$[2] = t0;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
t1 = $[3];
|
||||
}
|
||||
useEffect(t0, t1);
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsImNyZWF0ZUNvbnRleHQiLCJSZWFjdE5vZGUiLCJ1c2VDb250ZXh0IiwidXNlRWZmZWN0IiwidXNlU3RhdGUiLCJTdWdnZXN0aW9uSXRlbSIsIlByb21wdE92ZXJsYXlEYXRhIiwic3VnZ2VzdGlvbnMiLCJzZWxlY3RlZFN1Z2dlc3Rpb24iLCJtYXhDb2x1bW5XaWR0aCIsIlNldHRlciIsImQiLCJUIiwiRGF0YUNvbnRleHQiLCJTZXRDb250ZXh0IiwiRGlhbG9nQ29udGV4dCIsIlNldERpYWxvZ0NvbnRleHQiLCJQcm9tcHRPdmVybGF5UHJvdmlkZXIiLCJ0MCIsIiQiLCJfYyIsImNoaWxkcmVuIiwiZGF0YSIsInNldERhdGEiLCJkaWFsb2ciLCJzZXREaWFsb2ciLCJ0MSIsInQyIiwidXNlUHJvbXB0T3ZlcmxheSIsInVzZVByb21wdE92ZXJsYXlEaWFsb2ciLCJ1c2VTZXRQcm9tcHRPdmVybGF5Iiwic2V0IiwidXNlU2V0UHJvbXB0T3ZlcmxheURpYWxvZyIsIm5vZGUiXSwic291cmNlcyI6WyJwcm9tcHRPdmVybGF5Q29udGV4dC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQb3J0YWwgZm9yIGNvbnRlbnQgdGhhdCBmbG9hdHMgYWJvdmUgdGhlIHByb21wdCBzbyBpdCBlc2NhcGVzXG4gKiBGdWxsc2NyZWVuTGF5b3V0J3MgYm90dG9tLXNsb3QgYG92ZXJmbG93WTpoaWRkZW5gIGNsaXAuXG4gKlxuICogVGhlIGNsaXAgaXMgbG9hZC1iZWFyaW5nIChDQy02Njg6IHRhbGwgcGFzdGVzIHNxdWFzaCB0aGUgU2Nyb2xsQm94XG4gKiB3aXRob3V0IGl0KSwgYnV0IGZsb2F0aW5nIG92ZXJsYXlzIHVzZSBgcG9zaXRpb246YWJzb2x1dGVcbiAqIGJvdHRvbT1cIjEwMCVcImAgdG8gZmxvYXQgYWJvdmUgdGhlIHByb21wdCDigJQgYW5kIEluaydzIGNsaXAgc3RhY2tcbiAqIGludGVyc2VjdHMgQUxMIGRlc2NlbmRhbnRzLCBzbyB0aGV5IHdlcmUgY2xpcHBlZCB0byB+MSByb3cuXG4gKlxuICogVHdvIGNoYW5uZWxzOlxuICogLSBgdXNlU2V0UHJvbXB0T3ZlcmxheWAg4oCUIHNsYXNoLWNvbW1hbmQgc3VnZ2VzdGlvbiBkYXRhIChzdHJ1Y3R1cmVkLFxuICogICB3cml0dGVuIGJ5IFByb21wdElucHV0Rm9vdGVyKVxuICogLSBgdXNlU2V0UHJvbXB0T3ZlcmxheURpYWxvZ2Ag4oCUIGFyYml0cmFyeSBkaWFsb2cgbm9kZSAoZS5nLlxuICogICBBdXRvTW9kZU9wdEluRGlhbG9nLCB3cml0dGVuIGJ5IFByb21wdElucHV0KVxuICpcbiAqIEZ1bGxzY3JlZW5MYXlvdXQgcmVhZHMgYm90aCBhbmQgcmVuZGVycyB0aGVtIG91dHNpZGUgdGhlIGNsaXBwZWQgc2xvdC5cbiAqXG4gKiBTcGxpdCBpbnRvIGRhdGEvc2V0dGVyIGNvbnRleHQgcGFpcnMgc28gd3JpdGVycyBuZXZlciByZS1yZW5kZXIgb25cbiAqIHRoZWlyIG93biB3cml0ZXMg4oCUIHRoZSBzZXR0ZXIgY29udGV4dHMgYXJlIHN0YWJsZS5cbiAqL1xuaW1wb3J0IFJlYWN0LCB7XG4gIGNyZWF0ZUNvbnRleHQsXG4gIHR5cGUgUmVhY3ROb2RlLFxuICB1c2VDb250ZXh0LFxuICB1c2VFZmZlY3QsXG4gIHVzZVN0YXRlLFxufSBmcm9tICdyZWFjdCdcbmltcG9ydCB0eXBlIHsgU3VnZ2VzdGlvbkl0ZW0gfSBmcm9tICcuLi9jb21wb25lbnRzL1Byb21wdElucHV0L1Byb21wdElucHV0Rm9vdGVyU3VnZ2VzdGlvbnMuanMnXG5cbmV4cG9ydCB0eXBlIFByb21wdE92ZXJsYXlEYXRhID0ge1xuICBzdWdnZXN0aW9uczogU3VnZ2VzdGlvbkl0ZW1bXVxuICBzZWxlY3RlZFN1Z2dlc3Rpb246IG51bWJlclxuICBtYXhDb2x1bW5XaWR0aD86IG51bWJlclxufVxuXG50eXBlIFNldHRlcjxUPiA9IChkOiBUIHwgbnVsbCkgPT4gdm9pZFxuXG5jb25zdCBEYXRhQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8UHJvbXB0T3ZlcmxheURhdGEgfCBudWxsPihudWxsKVxuY29uc3QgU2V0Q29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8U2V0dGVyPFByb21wdE92ZXJsYXlEYXRhPiB8IG51bGw+KG51bGwpXG5jb25zdCBEaWFsb2dDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxSZWFjdE5vZGU+KG51bGwpXG5jb25zdCBTZXREaWFsb2dDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxTZXR0ZXI8UmVhY3ROb2RlPiB8IG51bGw+KG51bGwpXG5cbmV4cG9ydCBmdW5jdGlvbiBQcm9tcHRPdmVybGF5UHJvdmlkZXIoe1xuICBjaGlsZHJlbixcbn06IHtcbiAgY2hpbGRyZW46IFJlYWN0Tm9kZVxufSk6IFJlYWN0Tm9kZSB7XG4gIGNvbnN0IFtkYXRhLCBzZXREYXRhXSA9IHVzZVN0YXRlPFByb21wdE92ZXJsYXlEYXRhIHwgbnVsbD4obnVsbClcbiAgY29uc3QgW2RpYWxvZywgc2V0RGlhbG9nXSA9IHVzZVN0YXRlPFJlYWN0Tm9kZT4obnVsbClcbiAgcmV0dXJuIChcbiAgICA8U2V0Q29udGV4dC5Qcm92aWRlciB2YWx1ZT17c2V0RGF0YX0+XG4gICAgICA8U2V0RGlhbG9nQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17c2V0RGlhbG9nfT5cbiAgICAgICAgPERhdGFDb250ZXh0LlByb3ZpZGVyIHZhbHVlPXtkYXRhfT5cbiAgICAgICAgICA8RGlhbG9nQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17ZGlhbG9nfT5cbiAgICAgICAgICAgIHtjaGlsZHJlbn1cbiAgICAgICAgICA8L0RpYWxvZ0NvbnRleHQuUHJvdmlkZXI+XG4gICAgICAgIDwvRGF0YUNvbnRleHQuUHJvdmlkZXI+XG4gICAgICA8L1NldERpYWxvZ0NvbnRleHQuUHJvdmlkZXI+XG4gICAgPC9TZXRDb250ZXh0LlByb3ZpZGVyPlxuICApXG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VQcm9tcHRPdmVybGF5KCk6IFByb21wdE92ZXJsYXlEYXRhIHwgbnVsbCB7XG4gIHJldHVybiB1c2VDb250ZXh0KERhdGFDb250ZXh0KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXNlUHJvbXB0T3ZlcmxheURpYWxvZygpOiBSZWFjdE5vZGUge1xuICByZXR1cm4gdXNlQ29udGV4dChEaWFsb2dDb250ZXh0KVxufVxuXG4vKipcbiAqIFJlZ2lzdGVyIHN1Z2dlc3Rpb24gZGF0YSBmb3IgdGhlIGZsb2F0aW5nIG92ZXJsYXkuIENsZWFycyBvbiB1bm1vdW50LlxuICogTm8tb3Agb3V0c2lkZSB0aGUgcHJvdmlkZXIgKG5vbi1mdWxsc2NyZWVuIHJlbmRlcnMgaW5saW5lIGluc3RlYWQpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlU2V0UHJvbXB0T3ZlcmxheShkYXRhOiBQcm9tcHRPdmVybGF5RGF0YSB8IG51bGwpOiB2b2lkIHtcbiAgY29uc3Qgc2V0ID0gdXNlQ29udGV4dChTZXRDb250ZXh0KVxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghc2V0KSByZXR1cm5cbiAgICBzZXQoZGF0YSlcbiAgICByZXR1cm4gKCkgPT4gc2V0KG51bGwpXG4gIH0sIFtzZXQsIGRhdGFdKVxufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgZGlhbG9nIG5vZGUgdG8gZmxvYXQgYWJvdmUgdGhlIHByb21wdC4gQ2xlYXJzIG9uIHVubW91bnQuXG4gKiBOby1vcCBvdXRzaWRlIHRoZSBwcm92aWRlciAobm9uLWZ1bGxzY3JlZW4gcmVuZGVycyBpbmxpbmUgaW5zdGVhZCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VTZXRQcm9tcHRPdmVybGF5RGlhbG9nKG5vZGU6IFJlYWN0Tm9kZSk6IHZvaWQge1xuICBjb25zdCBzZXQgPSB1c2VDb250ZXh0KFNldERpYWxvZ0NvbnRleHQpXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFzZXQpIHJldHVyblxuICAgIHNldChub2RlKVxuICAgIHJldHVybiAoKSA9PiBzZXQobnVsbClcbiAgfSwgW3NldCwgbm9kZV0pXG59XG4iXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0F
Line truncated
|
||||
@@ -0,0 +1,220 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import React, { createContext, useCallback, useContext, useEffect, useMemo } from 'react';
|
||||
import { saveCurrentProjectConfig } from '../utils/config.js';
|
||||
export type StatsStore = {
|
||||
increment(name: string, value?: number): void;
|
||||
set(name: string, value: number): void;
|
||||
observe(name: string, value: number): void;
|
||||
add(name: string, value: string): void;
|
||||
getAll(): Record<string, number>;
|
||||
};
|
||||
function percentile(sorted: number[], p: number): number {
|
||||
const index = p / 100 * (sorted.length - 1);
|
||||
const lower = Math.floor(index);
|
||||
const upper = Math.ceil(index);
|
||||
if (lower === upper) {
|
||||
return sorted[lower]!;
|
||||
}
|
||||
return sorted[lower]! + (sorted[upper]! - sorted[lower]!) * (index - lower);
|
||||
}
|
||||
const RESERVOIR_SIZE = 1024;
|
||||
type Histogram = {
|
||||
reservoir: number[];
|
||||
count: number;
|
||||
sum: number;
|
||||
min: number;
|
||||
max: number;
|
||||
};
|
||||
export function createStatsStore(): StatsStore {
|
||||
const metrics = new Map<string, number>();
|
||||
const histograms = new Map<string, Histogram>();
|
||||
const sets = new Map<string, Set<string>>();
|
||||
return {
|
||||
increment(name: string, value = 1) {
|
||||
metrics.set(name, (metrics.get(name) ?? 0) + value);
|
||||
},
|
||||
set(name: string, value: number) {
|
||||
metrics.set(name, value);
|
||||
},
|
||||
observe(name: string, value: number) {
|
||||
let h = histograms.get(name);
|
||||
if (!h) {
|
||||
h = {
|
||||
reservoir: [],
|
||||
count: 0,
|
||||
sum: 0,
|
||||
min: value,
|
||||
max: value
|
||||
};
|
||||
histograms.set(name, h);
|
||||
}
|
||||
h.count++;
|
||||
h.sum += value;
|
||||
if (value < h.min) {
|
||||
h.min = value;
|
||||
}
|
||||
if (value > h.max) {
|
||||
h.max = value;
|
||||
}
|
||||
// Reservoir sampling (Algorithm R)
|
||||
if (h.reservoir.length < RESERVOIR_SIZE) {
|
||||
h.reservoir.push(value);
|
||||
} else {
|
||||
const j = Math.floor(Math.random() * h.count);
|
||||
if (j < RESERVOIR_SIZE) {
|
||||
h.reservoir[j] = value;
|
||||
}
|
||||
}
|
||||
},
|
||||
add(name: string, value: string) {
|
||||
let s = sets.get(name);
|
||||
if (!s) {
|
||||
s = new Set();
|
||||
sets.set(name, s);
|
||||
}
|
||||
s.add(value);
|
||||
},
|
||||
getAll() {
|
||||
const result: Record<string, number> = Object.fromEntries(metrics);
|
||||
for (const [name, h] of histograms) {
|
||||
if (h.count === 0) {
|
||||
continue;
|
||||
}
|
||||
result[`${name}_count`] = h.count;
|
||||
result[`${name}_min`] = h.min;
|
||||
result[`${name}_max`] = h.max;
|
||||
result[`${name}_avg`] = h.sum / h.count;
|
||||
const sorted = [...h.reservoir].sort((a, b) => a - b);
|
||||
result[`${name}_p50`] = percentile(sorted, 50);
|
||||
result[`${name}_p95`] = percentile(sorted, 95);
|
||||
result[`${name}_p99`] = percentile(sorted, 99);
|
||||
}
|
||||
for (const [name, s] of sets) {
|
||||
result[name] = s.size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
export const StatsContext = createContext<StatsStore | null>(null);
|
||||
type Props = {
|
||||
store?: StatsStore;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
export function StatsProvider(t0) {
|
||||
const $ = _c(7);
|
||||
const {
|
||||
store: externalStore,
|
||||
children
|
||||
} = t0;
|
||||
let t1;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t1 = createStatsStore();
|
||||
$[0] = t1;
|
||||
} else {
|
||||
t1 = $[0];
|
||||
}
|
||||
const internalStore = t1;
|
||||
const store = externalStore ?? internalStore;
|
||||
let t2;
|
||||
let t3;
|
||||
if ($[1] !== store) {
|
||||
t2 = () => {
|
||||
const flush = () => {
|
||||
const metrics = store.getAll();
|
||||
if (Object.keys(metrics).length > 0) {
|
||||
saveCurrentProjectConfig(current => ({
|
||||
...current,
|
||||
lastSessionMetrics: metrics
|
||||
}));
|
||||
}
|
||||
};
|
||||
process.on("exit", flush);
|
||||
return () => {
|
||||
process.off("exit", flush);
|
||||
};
|
||||
};
|
||||
t3 = [store];
|
||||
$[1] = store;
|
||||
$[2] = t2;
|
||||
$[3] = t3;
|
||||
} else {
|
||||
t2 = $[2];
|
||||
t3 = $[3];
|
||||
}
|
||||
useEffect(t2, t3);
|
||||
let t4;
|
||||
if ($[4] !== children || $[5] !== store) {
|
||||
t4 = <StatsContext.Provider value={store}>{children}</StatsContext.Provider>;
|
||||
$[4] = children;
|
||||
$[5] = store;
|
||||
$[6] = t4;
|
||||
} else {
|
||||
t4 = $[6];
|
||||
}
|
||||
return t4;
|
||||
}
|
||||
export function useStats() {
|
||||
const store = useContext(StatsContext);
|
||||
if (!store) {
|
||||
throw new Error("useStats must be used within a StatsProvider");
|
||||
}
|
||||
return store;
|
||||
}
|
||||
export function useCounter(name) {
|
||||
const $ = _c(3);
|
||||
const store = useStats();
|
||||
let t0;
|
||||
if ($[0] !== name || $[1] !== store) {
|
||||
t0 = value => store.increment(name, value);
|
||||
$[0] = name;
|
||||
$[1] = store;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
export function useGauge(name) {
|
||||
const $ = _c(3);
|
||||
const store = useStats();
|
||||
let t0;
|
||||
if ($[0] !== name || $[1] !== store) {
|
||||
t0 = value => store.set(name, value);
|
||||
$[0] = name;
|
||||
$[1] = store;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
export function useTimer(name) {
|
||||
const $ = _c(3);
|
||||
const store = useStats();
|
||||
let t0;
|
||||
if ($[0] !== name || $[1] !== store) {
|
||||
t0 = value => store.observe(name, value);
|
||||
$[0] = name;
|
||||
$[1] = store;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
export function useSet(name) {
|
||||
const $ = _c(3);
|
||||
const store = useStats();
|
||||
let t0;
|
||||
if ($[0] !== name || $[1] !== store) {
|
||||
t0 = value => store.add(name, value);
|
||||
$[0] = name;
|
||||
$[1] = store;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsImNyZWF0ZUNvbnRleHQiLCJ1c2VDYWxsYmFjayIsInVzZUNvbnRleHQiLCJ1c2VFZmZlY3QiLCJ1c2VNZW1vIiwic2F2ZUN1cnJlbnRQcm9qZWN0Q29uZmlnIiwiU3RhdHNTdG9yZSIsImluY3JlbWVudCIsIm5hbWUiLCJ2YWx1ZSIsInNldCIsIm9ic2VydmUiLCJhZGQiLCJnZXRBbGwiLCJSZWNvcmQiLCJwZXJjZW50aWxlIiwic29ydGVkIiwicCIsImluZGV4IiwibGVuZ3RoIiwibG93ZXIiLCJNYXRoIiwiZmxvb3IiLCJ1cHBlciIsImNlaWwiLCJSRVNFUlZPSVJfU0laRSIsIkhpc3RvZ3JhbSIsInJlc2Vydm9pciIsImNvdW50Iiwic3VtIiwibWluIiwibWF4IiwiY3JlYXRlU3RhdHNTdG9yZSIsIm1ldHJpY3MiLCJNYXAiLCJoaXN0b2dyYW1zIiwic2V0cyIsIlNldCIsImdldCIsImgiLCJwdXNoIiwiaiIsInJhbmRvbSIsInMiLCJyZXN1bHQiLCJPYmplY3QiLCJmcm9tRW50cmllcyIsInNvcnQiLCJhIiwiYiIsInNpemUiLCJTdGF0c0NvbnRleHQiLCJQcm9wcyIsInN0b3JlIiwiY2hpbGRyZW4iLCJSZWFjdE5vZGUiLCJTdGF0c1Byb3ZpZGVyIiwidDAiLCIkIiwiX2MiLCJleHRlcm5hbFN0b3JlIiwidDEiLCJTeW1ib2wiLCJmb3IiLCJpbnRlcm5hbFN0b3JlIiwidDIiLCJ0MyIsImZsdXNoIiwia2V5cyIsImN1cnJlbnQiLCJsYXN0U2Vzc2lvbk1ldHJpY3MiLCJwcm9jZXNzIiwib24iLCJvZmYiLCJ0NCIsInVzZVN0YXRzIiwiRXJyb3IiLCJ1c2VDb3VudGVyIiwidXNlR2F1Z2UiLCJ1c2VUaW1lciIsInVzZVNldCJdLCJzb3VyY2VzIjpbInN0YXRzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QsIHtcbiAgY3JlYXRlQ29udGV4dCxcbiAgdXNlQ2FsbGJhY2ssXG4gIHVzZUNvbnRleHQsXG4gIHVzZUVmZmVjdCxcbiAgdXNlTWVtbyxcbn0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBzYXZlQ3VycmVudFByb2plY3RDb25maWcgfSBmcm9tICcuLi91dGlscy9jb25maWcuanMnXG5cbmV4cG9ydCB0eXBlIFN0YXRzU3RvcmUgPSB7XG4gIGluY3JlbWVudChuYW1lOiBzdHJpbmcsIHZhbHVlPzogbnVtYmVyKTogdm9pZFxuICBzZXQobmFtZTogc3RyaW5nLCB2YWx1ZTogbnVtYmVyKTogdm9pZFxuICBvYnNlcnZlKG5hbWU6IHN0cmluZywgdmFsdWU6IG51bWJlcik6IHZvaWRcbiAgYWRkKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHZvaWRcbiAgZ2V0QWxsKCk6IFJlY29yZDxzdHJpbmcsIG51bWJlcj5cbn1cblxuZnVuY3Rpb24gcGVyY2VudGlsZShzb3J0ZWQ6IG51bWJlcltdLCBwOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBpbmRleCA9IChwIC8gMTAwKSAqIChzb3J0ZWQubGVuZ3RoIC0gMSlcbiAgY29uc3QgbG93ZXIgPSBNYXRoLmZsb29yKGluZGV4KVxuICBjb25zdCB1cHBlciA9IE1hdGguY2VpbChpbmRleClcbiAgaWYgKGxvd2VyID09PSB1cHBlcikge1xuICAgIHJldHVybiBzb3J0ZWRbbG93ZXJdIVxuICB9XG4gIHJldHVybiBzb3J0ZWRbbG93ZXJdISArIChzb3J0ZWRbdXBwZXJdISAtIHNvcnRlZFtsb3dlcl0hKSAqIChpbmRleCAtIGxvd2VyKVxufVxuXG5jb25zdCBSRVNFUlZPSVJfU0laRSA9IDEwMjRcblxudHlwZSBIaXN0b2dyYW0gPSB7XG4gIHJlc2Vydm9pcjogbnVtYmVyW11cbiAgY291bnQ6IG51bWJlclxuICBzdW06IG51bWJlclxuICBtaW46IG51bWJlclxuICBtYXg6IG51bWJlclxufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU3RhdHNTdG9yZSgpOiBTdGF0c1N0b3JlIHtcbiAgY29uc3QgbWV0cmljcyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KClcbiAgY29uc3QgaGlzdG9ncmFtcyA9IG5ldyBNYXA8c3RyaW5nLCBIaXN0b2dyYW0+KClcbiAgY29uc3Qgc2V0cyA9IG5ldyBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj4oKVxuXG4gIHJldHVybiB7XG4gICAgaW5jcmVtZW50KG5hbWU6IHN0cmluZywgdmFsdWUgPSAxKSB7XG4gICAgICBtZXRyaWNzLnNldChuYW1lLCAobWV0cmljcy5nZXQobmFtZSkgPz8gMCkgKyB2YWx1ZSlcbiAgICB9LFxuICAgIHNldChuYW1lOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIpIHtcbiAgICAgIG1ldHJpY3Muc2V0KG5hbWUsIHZhbHVlKVxuICAgIH0sXG4gICAgb2JzZXJ2ZShuYW1lOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIpIHtcbiAgICAgIGxldCBoID0gaGlzdG9ncmFtcy5nZXQobmFtZSlcbiAgICAgIGlmICghaCkge1xuICAgICAgICBoID0geyByZXNlcnZvaXI6IFtdLCBjb3VudDogMCwgc3VtOiAwLCBtaW46IHZhbHVlLCBtYXg6IHZhbHVlIH1cbiAgICAgICAgaGlzdG9ncmFtcy5zZXQobmFtZSwgaClcbiAgICAgIH1cbiAgICAgIGguY291bnQrK1xuICAgICAgaC5zdW0gKz0gdmFsdWVcbiAgICAgIGlmICh2YWx1ZSA8IGgubWluKSB7XG4gICAgICAgIGgubWluID0gdmFsdWVcbiAgICAgIH1cbiAgICAgIGlmICh2YWx1ZSA+IGgubWF4KSB7XG4gICAgICAgIGgubWF4ID0gdmFsdWVcbiAgICAgIH1cbiAgICAgIC8vIFJlc2Vydm9pciBzYW1wbGluZyAoQWxnb3JpdGhtIFIpXG4gICAgICBpZiAoaC5yZXNlcnZvaXIubGVuZ3RoIDwgUkVTRVJWT0lSX1NJWkUpIHtcbiAgICAgICAgaC5yZXNlcnZvaXIucHVzaCh2YWx1ZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGogPSBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBoLmNvdW50KVxuICAgICAgICBpZiAoaiA8IFJFU0VSVk9JUl9TSVpFKSB7XG4gICAgICAgICAgaC5yZXNlcnZvaXJbal0gPSB2YWx1ZVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBhZGQobmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgICBsZXQgcyA9IHNldHMuZ2V0KG5hbWUpXG4gICAgICBpZiAoIXMpIHtcbiAgICAgICAgcyA9IG5ldyBTZXQoKVxuICAgICAgICBzZXRzLnNldChuYW1lLCBzKVxuICAgICAgfVxuICAgICAgcy5hZGQodmFsdWUpXG4gICAgfSxcbiAgICBnZXRBbGwoKSB7XG4gICAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gPSBPYmplY3QuZnJvbUVudHJpZXMobWV0cmljcylcblxuICAgICAgZm9yIChjb25zdCBbbmFtZSwgaF0gb2YgaGlzdG9ncmFtcykge1xuICAgICAgICBpZiAoaC5jb3VudCA9PT0gMCkge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0W2Ake25hbWV9X2NvdW50YF0gPSBoLmNvdW50XG4gICAgICAgIHJlc3VsdFtgJHtuYW1lfV9taW5gXSA9IGgubWluXG4gICAgICAgIHJlc3VsdFtgJHtuYW1lfV9tYXhgXSA9IGgubWF4XG4gICAgICAgIHJlc3VsdFtgJHtuYW1lfV9hdmdgXSA9IGguc3VtIC8gaC5jb3VudFxuICAgICAgICBjb25zdCBzb3J0ZWQgPSBbLi4uaC5yZXNlcnZvaXJdLnNvcnQoKGEsIGIpID0+IGEgLSBiKVxuICAgICAgICByZXN1bHRbYCR7bmFtZX1fcDUwYF0gPSBwZXJjZW50aWxlKHNvcnRlZCwgNTApXG4gICAgICAgIHJlc3VsdFtgJHtuYW1lfV9wOTVgXSA9IHBlcmNlbnRpbGUoc29ydGVkLCA5NSlcbiAgICAgICAgcmVzdWx0W2Ake25hbWV9X3A5OWBdID0gcGVyY2VudGlsZShzb3J0ZWQsIDk5KVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IFtuYW1lLCBzXSBvZiBzZXRzKSB7XG4gICAgICAgIHJlc3VsdFtuYW1lXSA9IHMuc2l6ZVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0XG4gICAgfSxcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgU3RhdHNDb250ZXh0ID0gY3J
Line truncated
|
||||
@@ -0,0 +1,88 @@
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import React, { createContext, useContext, useState, useSyncExternalStore } from 'react';
|
||||
import { createStore, type Store } from '../state/store.js';
|
||||
export type VoiceState = {
|
||||
voiceState: 'idle' | 'recording' | 'processing';
|
||||
voiceError: string | null;
|
||||
voiceInterimTranscript: string;
|
||||
voiceAudioLevels: number[];
|
||||
voiceWarmingUp: boolean;
|
||||
};
|
||||
const DEFAULT_STATE: VoiceState = {
|
||||
voiceState: 'idle',
|
||||
voiceError: null,
|
||||
voiceInterimTranscript: '',
|
||||
voiceAudioLevels: [],
|
||||
voiceWarmingUp: false
|
||||
};
|
||||
type VoiceStore = Store<VoiceState>;
|
||||
const VoiceContext = createContext<VoiceStore | null>(null);
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
export function VoiceProvider(t0) {
|
||||
const $ = _c(3);
|
||||
const {
|
||||
children
|
||||
} = t0;
|
||||
const [store] = useState(_temp);
|
||||
let t1;
|
||||
if ($[0] !== children || $[1] !== store) {
|
||||
t1 = <VoiceContext.Provider value={store}>{children}</VoiceContext.Provider>;
|
||||
$[0] = children;
|
||||
$[1] = store;
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
return t1;
|
||||
}
|
||||
function _temp() {
|
||||
return createStore(DEFAULT_STATE);
|
||||
}
|
||||
function useVoiceStore() {
|
||||
const store = useContext(VoiceContext);
|
||||
if (!store) {
|
||||
throw new Error("useVoiceState must be used within a VoiceProvider");
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to a slice of voice state. Only re-renders when the selected
|
||||
* value changes (compared via Object.is).
|
||||
*/
|
||||
export function useVoiceState(selector) {
|
||||
const $ = _c(3);
|
||||
const store = useVoiceStore();
|
||||
let t0;
|
||||
if ($[0] !== selector || $[1] !== store) {
|
||||
t0 = () => selector(store.getState());
|
||||
$[0] = selector;
|
||||
$[1] = store;
|
||||
$[2] = t0;
|
||||
} else {
|
||||
t0 = $[2];
|
||||
}
|
||||
const get = t0;
|
||||
return useSyncExternalStore(store.subscribe, get, get);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the voice state setter. Stable reference — never causes re-renders.
|
||||
* store.setState is synchronous: callers can read getVoiceState() immediately
|
||||
* after to observe the new value (VoiceKeybindingHandler relies on this).
|
||||
*/
|
||||
export function useSetVoiceState() {
|
||||
return useVoiceStore().setState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a synchronous reader for fresh state inside callbacks. Unlike
|
||||
* useVoiceState (which subscribes), this doesn't cause re-renders — use
|
||||
* inside event handlers that need to read state set earlier in the same tick.
|
||||
*/
|
||||
export function useGetVoiceState() {
|
||||
return useVoiceStore().getState;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsImNyZWF0ZUNvbnRleHQiLCJ1c2VDb250ZXh0IiwidXNlU3RhdGUiLCJ1c2VTeW5jRXh0ZXJuYWxTdG9yZSIsImNyZWF0ZVN0b3JlIiwiU3RvcmUiLCJWb2ljZVN0YXRlIiwidm9pY2VTdGF0ZSIsInZvaWNlRXJyb3IiLCJ2b2ljZUludGVyaW1UcmFuc2NyaXB0Iiwidm9pY2VBdWRpb0xldmVscyIsInZvaWNlV2FybWluZ1VwIiwiREVGQVVMVF9TVEFURSIsIlZvaWNlU3RvcmUiLCJWb2ljZUNvbnRleHQiLCJQcm9wcyIsImNoaWxkcmVuIiwiUmVhY3ROb2RlIiwiVm9pY2VQcm92aWRlciIsInQwIiwiJCIsIl9jIiwic3RvcmUiLCJfdGVtcCIsInQxIiwidXNlVm9pY2VTdG9yZSIsIkVycm9yIiwidXNlVm9pY2VTdGF0ZSIsInNlbGVjdG9yIiwiZ2V0U3RhdGUiLCJnZXQiLCJzdWJzY3JpYmUiLCJ1c2VTZXRWb2ljZVN0YXRlIiwic2V0U3RhdGUiLCJ1c2VHZXRWb2ljZVN0YXRlIl0sInNvdXJjZXMiOlsidm9pY2UudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCwge1xuICBjcmVhdGVDb250ZXh0LFxuICB1c2VDb250ZXh0LFxuICB1c2VTdGF0ZSxcbiAgdXNlU3luY0V4dGVybmFsU3RvcmUsXG59IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3JlYXRlU3RvcmUsIHR5cGUgU3RvcmUgfSBmcm9tICcuLi9zdGF0ZS9zdG9yZS5qcydcblxuZXhwb3J0IHR5cGUgVm9pY2VTdGF0ZSA9IHtcbiAgdm9pY2VTdGF0ZTogJ2lkbGUnIHwgJ3JlY29yZGluZycgfCAncHJvY2Vzc2luZydcbiAgdm9pY2VFcnJvcjogc3RyaW5nIHwgbnVsbFxuICB2b2ljZUludGVyaW1UcmFuc2NyaXB0OiBzdHJpbmdcbiAgdm9pY2VBdWRpb0xldmVsczogbnVtYmVyW11cbiAgdm9pY2VXYXJtaW5nVXA6IGJvb2xlYW5cbn1cblxuY29uc3QgREVGQVVMVF9TVEFURTogVm9pY2VTdGF0ZSA9IHtcbiAgdm9pY2VTdGF0ZTogJ2lkbGUnLFxuICB2b2ljZUVycm9yOiBudWxsLFxuICB2b2ljZUludGVyaW1UcmFuc2NyaXB0OiAnJyxcbiAgdm9pY2VBdWRpb0xldmVsczogW10sXG4gIHZvaWNlV2FybWluZ1VwOiBmYWxzZSxcbn1cblxudHlwZSBWb2ljZVN0b3JlID0gU3RvcmU8Vm9pY2VTdGF0ZT5cblxuY29uc3QgVm9pY2VDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxWb2ljZVN0b3JlIHwgbnVsbD4obnVsbClcblxudHlwZSBQcm9wcyA9IHtcbiAgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gVm9pY2VQcm92aWRlcih7IGNoaWxkcmVuIH06IFByb3BzKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgLy8gU3RvcmUgaXMgY3JlYXRlZCBvbmNlIOKAlCBzdGFibGUgY29udGV4dCB2YWx1ZSBtZWFucyB0aGUgcHJvdmlkZXIgbmV2ZXJcbiAgLy8gdHJpZ2dlcnMgcmUtcmVuZGVycy4gQ29uc3VtZXJzIHN1YnNjcmliZSB0byBzbGljZXMgdmlhIHVzZVZvaWNlU3RhdGUuXG4gIGNvbnN0IFtzdG9yZV0gPSB1c2VTdGF0ZSgoKSA9PiBjcmVhdGVTdG9yZTxWb2ljZVN0YXRlPihERUZBVUxUX1NUQVRFKSlcbiAgcmV0dXJuIDxWb2ljZUNvbnRleHQuUHJvdmlkZXIgdmFsdWU9e3N0b3JlfT57Y2hpbGRyZW59PC9Wb2ljZUNvbnRleHQuUHJvdmlkZXI+XG59XG5cbmZ1bmN0aW9uIHVzZVZvaWNlU3RvcmUoKTogVm9pY2VTdG9yZSB7XG4gIGNvbnN0IHN0b3JlID0gdXNlQ29udGV4dChWb2ljZUNvbnRleHQpXG4gIGlmICghc3RvcmUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3VzZVZvaWNlU3RhdGUgbXVzdCBiZSB1c2VkIHdpdGhpbiBhIFZvaWNlUHJvdmlkZXInKVxuICB9XG4gIHJldHVybiBzdG9yZVxufVxuXG4vKipcbiAqIFN1YnNjcmliZSB0byBhIHNsaWNlIG9mIHZvaWNlIHN0YXRlLiBPbmx5IHJlLXJlbmRlcnMgd2hlbiB0aGUgc2VsZWN0ZWRcbiAqIHZhbHVlIGNoYW5nZXMgKGNvbXBhcmVkIHZpYSBPYmplY3QuaXMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlVm9pY2VTdGF0ZTxUPihzZWxlY3RvcjogKHN0YXRlOiBWb2ljZVN0YXRlKSA9PiBUKTogVCB7XG4gIGNvbnN0IHN0b3JlID0gdXNlVm9pY2VTdG9yZSgpXG4gIGNvbnN0IGdldCA9ICgpID0+IHNlbGVjdG9yKHN0b3JlLmdldFN0YXRlKCkpXG4gIHJldHVybiB1c2VTeW5jRXh0ZXJuYWxTdG9yZShzdG9yZS5zdWJzY3JpYmUsIGdldCwgZ2V0KVxufVxuXG4vKipcbiAqIEdldCB0aGUgdm9pY2Ugc3RhdGUgc2V0dGVyLiBTdGFibGUgcmVmZXJlbmNlIOKAlCBuZXZlciBjYXVzZXMgcmUtcmVuZGVycy5cbiAqIHN0b3JlLnNldFN0YXRlIGlzIHN5bmNocm9ub3VzOiBjYWxsZXJzIGNhbiByZWFkIGdldFZvaWNlU3RhdGUoKSBpbW1lZGlhdGVseVxuICogYWZ0ZXIgdG8gb2JzZXJ2ZSB0aGUgbmV3IHZhbHVlIChWb2ljZUtleWJpbmRpbmdIYW5kbGVyIHJlbGllcyBvbiB0aGlzKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVNldFZvaWNlU3RhdGUoKTogKFxuICB1cGRhdGVyOiAocHJldjogVm9pY2VTdGF0ZSkgPT4gVm9pY2VTdGF0ZSxcbikgPT4gdm9pZCB7XG4gIHJldHVybiB1c2VWb2ljZVN0b3JlKCkuc2V0U3RhdGVcbn1cblxuLyoqXG4gKiBHZXQgYSBzeW5jaHJvbm91cyByZWFkZXIgZm9yIGZyZXNoIHN0YXRlIGluc2lkZSBjYWxsYmFja3MuIFVubGlrZVxuICogdXNlVm9pY2VTdGF0ZSAod2hpY2ggc3Vic2NyaWJlcyksIHRoaXMgZG9lc24ndCBjYXVzZSByZS1yZW5kZXJzIOKAlCB1c2VcbiAqIGluc2lkZSBldmVudCBoYW5kbGVycyB0aGF0IG5lZWQgdG8gcmVhZCBzdGF0ZSBzZXQgZWFybGllciBpbiB0aGUgc2FtZSB0aWNrLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlR2V0Vm9pY2VTdGF0ZSgpOiAoKSA9PiBWb2ljZVN0YXRlIHtcbiAgcmV0dXJuIHVzZVZvaWNlU3RvcmUoKS5nZXRTdGF0ZVxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBT0EsS0FBSyxJQUNWQyxhQUFhLEVBQ2JDLFVBQVUsRUFDVkMsUUFBUSxFQUNSQyxvQkFBb0IsUUFDZixPQUFPO0FBQ2QsU0FBU0MsV0FBVyxFQUFFLEtBQUtDLEtBQUssUUFBUSxtQkFBbUI7QUFFM0QsT0FBTyxLQUFLQyxVQUFVLEdBQUc7RUFDdkJDLFVBQVUsRUFBRSxNQUFNLEdBQUcsV0FBVyxHQUFHLFlBQVk7RUFDL0NDLFVBQVUsRUFBRSxNQUFNLEdBQUcsSUFBSTtFQUN6QkMsc0JBQXNCLEVBQUUsTUFBTTtFQUM5QkMsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFO0VBQzFCQyxjQUFjLEVBQUUsT0FBTztBQUN6QixDQUFDO0FBRUQsTUFBTUMsYUFBYSxFQUFFTixVQUFVLEdBQUc7RUFDaENDLFVBQVUsRUFBRSxNQUFNO0VBQ2xCQyxVQUFVLEVBQUUsSUFBSTtFQUNoQkMsc0JBQXNCLEVBQUUsRUFBRTtFQUMxQkMsZ0JBQWdCLEVBQUUsRUFBRTtFQUNwQkMsY0FBYyxFQUFFO0FBQ2xCLENBQUM7QUFFRCxLQUFLRSxVQUFVLEdBQUdSLEtBQUssQ0FBQ0MsVUFBVSxDQUFDO0FBRW5DLE1BQU1RLFlBQVksR0FBR2QsYUFBYSxDQUFDYSxVQUFVLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO0FBRTNELEtBQUtFLEtBQUssR0FBRztFQUNYQyxRQUFRLEVBQUVqQixLQUFLLENBQUNrQixTQUFTO0FBQzNCLENBQUM7QUFFRCxPQUFPLFNBQUFDLGNBQUFDLEVBQUE7RUFBQSxNQUFBQyxDQUFBLEdBQUFDLEVBQUE7RUFBdUI7SUFBQUw7RUFBQSxJQUFBRyxFQUFtQjtFQUcvQyxPQUFBRyxLQUFBLElBQWdCcEIsUUFBUSxDQUFDcUIsS0FBNEMsQ0FBQztFQUFBLElBQUFDLEVBQUE7RUFBQSxJQUFBSixDQUFBLFFBQUFKLFFBQUEsSUFBQUksQ0FBQSxRQUFBRSxLQUFBO0lBQy9
Line truncated
|
||||
Reference in new issue
Block a user