@particle-academy/react-fancy 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/index.cjs +790 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +234 -1
- package/dist/index.d.ts +234 -1
- package/dist/index.js +787 -3
- package/dist/index.js.map +1 -1
- package/docs/MagicWand.md +65 -0
- package/docs/MoodMeter.md +63 -0
- package/docs/PromptInput.md +69 -0
- package/docs/ReasonTag.md +63 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -9223,11 +9223,11 @@ function computeTicks(min, max, count = 5) {
|
|
|
9223
9223
|
}
|
|
9224
9224
|
return ticks;
|
|
9225
9225
|
}
|
|
9226
|
-
function niceNum(range2,
|
|
9226
|
+
function niceNum(range2, round2) {
|
|
9227
9227
|
const exponent = Math.floor(Math.log10(range2));
|
|
9228
9228
|
const fraction = range2 / Math.pow(10, exponent);
|
|
9229
9229
|
let niceFraction;
|
|
9230
|
-
if (
|
|
9230
|
+
if (round2) {
|
|
9231
9231
|
if (fraction < 1.5) niceFraction = 1;
|
|
9232
9232
|
else if (fraction < 3) niceFraction = 2;
|
|
9233
9233
|
else if (fraction < 7) niceFraction = 5;
|
|
@@ -11840,6 +11840,790 @@ TreeNavRoot.displayName = "TreeNav";
|
|
|
11840
11840
|
var TreeNav = Object.assign(TreeNavRoot, {
|
|
11841
11841
|
Node: TreeNode
|
|
11842
11842
|
});
|
|
11843
|
+
var CONFIDENCE_TIERS = [
|
|
11844
|
+
{ min: 0.85, color: "#10b981", label: "high" },
|
|
11845
|
+
{ min: 0.6, color: "#f59e0b", label: "medium" },
|
|
11846
|
+
{ min: 0, color: "#ef4444", label: "low" }
|
|
11847
|
+
];
|
|
11848
|
+
function tier(c) {
|
|
11849
|
+
return CONFIDENCE_TIERS.find((t) => c >= t.min) ?? CONFIDENCE_TIERS[2];
|
|
11850
|
+
}
|
|
11851
|
+
function ReasonTag({
|
|
11852
|
+
value,
|
|
11853
|
+
reason,
|
|
11854
|
+
confidence = 1,
|
|
11855
|
+
sources = [],
|
|
11856
|
+
by,
|
|
11857
|
+
theme = "dot",
|
|
11858
|
+
pinned = false,
|
|
11859
|
+
onFollowUp,
|
|
11860
|
+
className
|
|
11861
|
+
}) {
|
|
11862
|
+
const t = tier(confidence);
|
|
11863
|
+
const trigger = theme === "chip" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11864
|
+
"span",
|
|
11865
|
+
{
|
|
11866
|
+
className: `inline-flex cursor-help items-center gap-1 rounded-full px-2 py-0.5 text-[12px] font-medium ${className ?? ""}`,
|
|
11867
|
+
style: { backgroundColor: t.color + "22", color: t.color },
|
|
11868
|
+
children: [
|
|
11869
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11870
|
+
"span",
|
|
11871
|
+
{
|
|
11872
|
+
className: "h-1.5 w-1.5 rounded-full",
|
|
11873
|
+
style: { backgroundColor: t.color }
|
|
11874
|
+
}
|
|
11875
|
+
),
|
|
11876
|
+
value,
|
|
11877
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] opacity-70", children: "?" })
|
|
11878
|
+
]
|
|
11879
|
+
}
|
|
11880
|
+
) : theme === "underline" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11881
|
+
"span",
|
|
11882
|
+
{
|
|
11883
|
+
className: `cursor-help underline decoration-dotted underline-offset-2 ${className ?? ""}`,
|
|
11884
|
+
style: { textDecorationColor: t.color },
|
|
11885
|
+
children: [
|
|
11886
|
+
value,
|
|
11887
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11888
|
+
"span",
|
|
11889
|
+
{
|
|
11890
|
+
className: "ml-0.5 font-mono text-[10px]",
|
|
11891
|
+
style: { color: t.color },
|
|
11892
|
+
children: "?"
|
|
11893
|
+
}
|
|
11894
|
+
)
|
|
11895
|
+
]
|
|
11896
|
+
}
|
|
11897
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `inline-flex cursor-help items-baseline gap-1 ${className ?? ""}`, children: [
|
|
11898
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: value }),
|
|
11899
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11900
|
+
"span",
|
|
11901
|
+
{
|
|
11902
|
+
className: "inline-block h-1.5 w-1.5 rounded-full align-middle",
|
|
11903
|
+
style: { backgroundColor: t.color },
|
|
11904
|
+
title: "reason available"
|
|
11905
|
+
}
|
|
11906
|
+
)
|
|
11907
|
+
] });
|
|
11908
|
+
if (pinned) {
|
|
11909
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex flex-col items-start gap-0.5 align-top", children: [
|
|
11910
|
+
trigger,
|
|
11911
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11912
|
+
"span",
|
|
11913
|
+
{
|
|
11914
|
+
className: "block max-w-[280px] rounded border-l-2 pl-2 text-[11px] leading-snug text-zinc-600 dark:text-zinc-300",
|
|
11915
|
+
style: { borderColor: t.color },
|
|
11916
|
+
children: reason
|
|
11917
|
+
}
|
|
11918
|
+
)
|
|
11919
|
+
] });
|
|
11920
|
+
}
|
|
11921
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { hover: true, children: [
|
|
11922
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover.Trigger, { children: trigger }),
|
|
11923
|
+
/* @__PURE__ */ jsxRuntime.jsx(Popover.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-72 space-y-2 text-sm", children: [
|
|
11924
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2", children: [
|
|
11925
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11926
|
+
"span",
|
|
11927
|
+
{
|
|
11928
|
+
className: "text-[10px] font-semibold uppercase tracking-wider",
|
|
11929
|
+
style: { color: t.color },
|
|
11930
|
+
children: [
|
|
11931
|
+
t.label,
|
|
11932
|
+
" confidence \xB7 ",
|
|
11933
|
+
(confidence * 100).toFixed(0),
|
|
11934
|
+
"%"
|
|
11935
|
+
]
|
|
11936
|
+
}
|
|
11937
|
+
),
|
|
11938
|
+
by && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto font-mono text-[10px] text-zinc-400", children: [
|
|
11939
|
+
"@",
|
|
11940
|
+
by
|
|
11941
|
+
] })
|
|
11942
|
+
] }),
|
|
11943
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[13px] leading-snug text-zinc-700 dark:text-zinc-200", children: reason }),
|
|
11944
|
+
sources.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
11945
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] uppercase tracking-wider text-zinc-400", children: "sources" }),
|
|
11946
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-0.5 space-y-0.5 text-[12px]", children: sources.map((s, i) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: s.href ? /* @__PURE__ */ jsxRuntime.jsx("a", { className: "text-violet-600 hover:underline", href: s.href, children: s.label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-600 dark:text-zinc-300", children: s.label }) }, i)) })
|
|
11947
|
+
] }),
|
|
11948
|
+
onFollowUp && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end pt-1", children: /* @__PURE__ */ jsxRuntime.jsx(Action, { size: "sm", variant: "ghost", onClick: onFollowUp, children: "ask follow-up" }) })
|
|
11949
|
+
] }) })
|
|
11950
|
+
] });
|
|
11951
|
+
}
|
|
11952
|
+
function MoodMeter({
|
|
11953
|
+
min,
|
|
11954
|
+
max,
|
|
11955
|
+
step,
|
|
11956
|
+
value,
|
|
11957
|
+
confidence,
|
|
11958
|
+
onChange,
|
|
11959
|
+
posted,
|
|
11960
|
+
width = 320,
|
|
11961
|
+
height = 220,
|
|
11962
|
+
showGrid = true,
|
|
11963
|
+
color = "#0ea5e9",
|
|
11964
|
+
postedColor = "#a855f7",
|
|
11965
|
+
prefix = "",
|
|
11966
|
+
suffix = "",
|
|
11967
|
+
formatValue,
|
|
11968
|
+
className
|
|
11969
|
+
}) {
|
|
11970
|
+
const ref = react.useRef(null);
|
|
11971
|
+
const [dragging, setDragging] = react.useState(false);
|
|
11972
|
+
const snapStep = step ?? (max - min) / 100;
|
|
11973
|
+
const fmt = react.useCallback(
|
|
11974
|
+
(v) => {
|
|
11975
|
+
if (formatValue) return formatValue(v);
|
|
11976
|
+
const num = snapStep < 1 ? v.toFixed(2) : Math.round(v).toString();
|
|
11977
|
+
return `${prefix}${num}${suffix}`;
|
|
11978
|
+
},
|
|
11979
|
+
[formatValue, snapStep, prefix, suffix]
|
|
11980
|
+
);
|
|
11981
|
+
const set = react.useCallback(
|
|
11982
|
+
(clientX, clientY) => {
|
|
11983
|
+
const el = ref.current;
|
|
11984
|
+
if (!el) return;
|
|
11985
|
+
const rect = el.getBoundingClientRect();
|
|
11986
|
+
const x = clamp((clientX - rect.left) / rect.width, 0, 1);
|
|
11987
|
+
const y = clamp((clientY - rect.top) / rect.height, 0, 1);
|
|
11988
|
+
const raw = min + x * (max - min);
|
|
11989
|
+
const snapped = round(raw, snapStep, min);
|
|
11990
|
+
const c = clamp(1 - y, 0, 1);
|
|
11991
|
+
onChange(snapped, Math.round(c * 100) / 100);
|
|
11992
|
+
},
|
|
11993
|
+
[min, max, snapStep, onChange]
|
|
11994
|
+
);
|
|
11995
|
+
const onPointerDown = (e) => {
|
|
11996
|
+
e.target.setPointerCapture?.(e.pointerId);
|
|
11997
|
+
setDragging(true);
|
|
11998
|
+
set(e.clientX, e.clientY);
|
|
11999
|
+
};
|
|
12000
|
+
const onPointerMove = (e) => {
|
|
12001
|
+
if (!dragging) return;
|
|
12002
|
+
set(e.clientX, e.clientY);
|
|
12003
|
+
};
|
|
12004
|
+
const onPointerUp = () => setDragging(false);
|
|
12005
|
+
const xPct = (value - min) / (max - min) * 100;
|
|
12006
|
+
const yPct = (1 - confidence) * 100;
|
|
12007
|
+
const haloR = 18 + (1 - confidence) * 70;
|
|
12008
|
+
const pxPct = posted ? (posted.value - min) / (max - min) * 100 : 0;
|
|
12009
|
+
const pyPct = posted ? (1 - posted.confidence) * 100 : 0;
|
|
12010
|
+
const pHaloR = posted ? 16 + (1 - posted.confidence) * 60 : 0;
|
|
12011
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12012
|
+
"div",
|
|
12013
|
+
{
|
|
12014
|
+
ref,
|
|
12015
|
+
onPointerDown,
|
|
12016
|
+
onPointerMove,
|
|
12017
|
+
onPointerUp,
|
|
12018
|
+
onPointerCancel: onPointerUp,
|
|
12019
|
+
className: `relative cursor-crosshair touch-none select-none overflow-hidden rounded-md border border-zinc-200 bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-950 ${className ?? ""}`,
|
|
12020
|
+
style: { width, height },
|
|
12021
|
+
children: [
|
|
12022
|
+
showGrid && /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "pointer-events-none absolute inset-0 h-full w-full", "aria-hidden": true, children: [
|
|
12023
|
+
[0.25, 0.5, 0.75].map((p, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12024
|
+
"line",
|
|
12025
|
+
{
|
|
12026
|
+
x1: `${p * 100}%`,
|
|
12027
|
+
x2: `${p * 100}%`,
|
|
12028
|
+
y1: "0",
|
|
12029
|
+
y2: "100%",
|
|
12030
|
+
stroke: "#a1a1aa",
|
|
12031
|
+
strokeOpacity: 0.18,
|
|
12032
|
+
strokeDasharray: "3 4"
|
|
12033
|
+
},
|
|
12034
|
+
`v${i}`
|
|
12035
|
+
)),
|
|
12036
|
+
[0.25, 0.5, 0.75].map((p, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
12037
|
+
"line",
|
|
12038
|
+
{
|
|
12039
|
+
x1: "0",
|
|
12040
|
+
x2: "100%",
|
|
12041
|
+
y1: `${p * 100}%`,
|
|
12042
|
+
y2: `${p * 100}%`,
|
|
12043
|
+
stroke: "#a1a1aa",
|
|
12044
|
+
strokeOpacity: 0.18,
|
|
12045
|
+
strokeDasharray: "3 4"
|
|
12046
|
+
},
|
|
12047
|
+
`h${i}`
|
|
12048
|
+
))
|
|
12049
|
+
] }),
|
|
12050
|
+
showGrid && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
12051
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute left-1.5 top-1.5 text-[10px] uppercase tracking-wider text-zinc-400", children: "\u2191 sure" }),
|
|
12052
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute bottom-1.5 left-1.5 text-[10px] uppercase tracking-wider text-zinc-400", children: "\u2193 unsure" }),
|
|
12053
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none absolute right-1.5 top-1.5 text-[10px] uppercase tracking-wider text-zinc-400", children: [
|
|
12054
|
+
fmt(max),
|
|
12055
|
+
" \u2192"
|
|
12056
|
+
] }),
|
|
12057
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none absolute bottom-1.5 right-1.5 text-[10px] uppercase tracking-wider text-zinc-400", children: [
|
|
12058
|
+
"\u2190 ",
|
|
12059
|
+
fmt(min)
|
|
12060
|
+
] })
|
|
12061
|
+
] }),
|
|
12062
|
+
posted && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12063
|
+
Handle,
|
|
12064
|
+
{
|
|
12065
|
+
xPct: pxPct,
|
|
12066
|
+
yPct: pyPct,
|
|
12067
|
+
haloR: pHaloR,
|
|
12068
|
+
color: postedColor,
|
|
12069
|
+
dashed: true,
|
|
12070
|
+
label: "agent"
|
|
12071
|
+
}
|
|
12072
|
+
),
|
|
12073
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12074
|
+
Handle,
|
|
12075
|
+
{
|
|
12076
|
+
xPct,
|
|
12077
|
+
yPct,
|
|
12078
|
+
haloR,
|
|
12079
|
+
color,
|
|
12080
|
+
label: fmt(value)
|
|
12081
|
+
}
|
|
12082
|
+
)
|
|
12083
|
+
]
|
|
12084
|
+
}
|
|
12085
|
+
);
|
|
12086
|
+
}
|
|
12087
|
+
function Handle({
|
|
12088
|
+
xPct,
|
|
12089
|
+
yPct,
|
|
12090
|
+
haloR,
|
|
12091
|
+
color,
|
|
12092
|
+
dashed = false,
|
|
12093
|
+
label
|
|
12094
|
+
}) {
|
|
12095
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
12096
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12097
|
+
"div",
|
|
12098
|
+
{
|
|
12099
|
+
className: "pointer-events-none absolute -translate-x-1/2 -translate-y-1/2 rounded-full",
|
|
12100
|
+
style: {
|
|
12101
|
+
left: `${xPct}%`,
|
|
12102
|
+
top: `${yPct}%`,
|
|
12103
|
+
width: haloR * 2,
|
|
12104
|
+
height: haloR * 2,
|
|
12105
|
+
background: color + (dashed ? "11" : "22"),
|
|
12106
|
+
border: dashed ? `1px dashed ${color}` : "none"
|
|
12107
|
+
}
|
|
12108
|
+
}
|
|
12109
|
+
),
|
|
12110
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12111
|
+
"div",
|
|
12112
|
+
{
|
|
12113
|
+
className: "pointer-events-none absolute -translate-x-1/2 -translate-y-1/2 rounded-full ring-2 ring-white dark:ring-zinc-900",
|
|
12114
|
+
style: {
|
|
12115
|
+
left: `${xPct}%`,
|
|
12116
|
+
top: `${yPct}%`,
|
|
12117
|
+
width: 14,
|
|
12118
|
+
height: 14,
|
|
12119
|
+
background: color,
|
|
12120
|
+
opacity: dashed ? 0.6 : 1
|
|
12121
|
+
}
|
|
12122
|
+
}
|
|
12123
|
+
),
|
|
12124
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12125
|
+
"div",
|
|
12126
|
+
{
|
|
12127
|
+
className: "pointer-events-none absolute -translate-x-1/2 rounded px-1.5 py-0.5 font-mono text-[10px]",
|
|
12128
|
+
style: {
|
|
12129
|
+
left: `${xPct}%`,
|
|
12130
|
+
top: `calc(${yPct}% + 14px)`,
|
|
12131
|
+
color
|
|
12132
|
+
},
|
|
12133
|
+
children: label
|
|
12134
|
+
}
|
|
12135
|
+
)
|
|
12136
|
+
] });
|
|
12137
|
+
}
|
|
12138
|
+
function clamp(n, lo, hi) {
|
|
12139
|
+
return Math.max(lo, Math.min(hi, n));
|
|
12140
|
+
}
|
|
12141
|
+
function round(n, step, min) {
|
|
12142
|
+
if (step >= 1) return Math.round(n);
|
|
12143
|
+
return Math.round((n - min) / step) * step + min;
|
|
12144
|
+
}
|
|
12145
|
+
var DEFAULT_MENTION_COLOR = {
|
|
12146
|
+
agent: "#a855f7",
|
|
12147
|
+
file: "#10b981",
|
|
12148
|
+
person: "#3b82f6"
|
|
12149
|
+
};
|
|
12150
|
+
function PromptInput({
|
|
12151
|
+
budgetTokens,
|
|
12152
|
+
commands = [],
|
|
12153
|
+
mentions = [],
|
|
12154
|
+
showHint = true,
|
|
12155
|
+
onSubmit,
|
|
12156
|
+
placeholder = "Ask anything. Type / for commands, @ for mentions. \u2318/Ctrl+Enter to send.",
|
|
12157
|
+
charsPerToken = 4,
|
|
12158
|
+
mentionColor,
|
|
12159
|
+
maxHeight = 280
|
|
12160
|
+
}) {
|
|
12161
|
+
const [text, setText] = react.useState("");
|
|
12162
|
+
const [attachments, setAttachments] = react.useState([]);
|
|
12163
|
+
const [picker, setPicker] = react.useState(null);
|
|
12164
|
+
const taRef = react.useRef(null);
|
|
12165
|
+
const [dragOver, setDragOver] = react.useState(false);
|
|
12166
|
+
const colors = mentionColor ?? DEFAULT_MENTION_COLOR;
|
|
12167
|
+
const tokens = react.useMemo(
|
|
12168
|
+
() => Math.ceil(text.length / Math.max(1, charsPerToken)),
|
|
12169
|
+
[text, charsPerToken]
|
|
12170
|
+
);
|
|
12171
|
+
const ratio = Math.min(1, tokens / budgetTokens);
|
|
12172
|
+
const meterColor = ratio < 0.6 ? "#10b981" : ratio < 0.85 ? "#f59e0b" : "#ef4444";
|
|
12173
|
+
const filteredCmds = react.useMemo(
|
|
12174
|
+
() => picker?.kind === "cmd" ? commands.filter(
|
|
12175
|
+
(c) => c.name.slice(1).toLowerCase().startsWith(picker.query.toLowerCase())
|
|
12176
|
+
) : [],
|
|
12177
|
+
[picker, commands]
|
|
12178
|
+
);
|
|
12179
|
+
const filteredMentions = react.useMemo(
|
|
12180
|
+
() => picker?.kind === "mention" ? mentions.filter(
|
|
12181
|
+
(m) => m.name.toLowerCase().includes(picker.query.toLowerCase())
|
|
12182
|
+
) : [],
|
|
12183
|
+
[picker, mentions]
|
|
12184
|
+
);
|
|
12185
|
+
const items = picker?.kind === "cmd" ? filteredCmds : picker?.kind === "mention" ? filteredMentions : [];
|
|
12186
|
+
react.useEffect(() => {
|
|
12187
|
+
const ta = taRef.current;
|
|
12188
|
+
if (!ta) return;
|
|
12189
|
+
ta.style.height = "auto";
|
|
12190
|
+
ta.style.height = Math.min(maxHeight, ta.scrollHeight) + "px";
|
|
12191
|
+
}, [text, maxHeight]);
|
|
12192
|
+
const updateText = (next, caret) => {
|
|
12193
|
+
setText(next);
|
|
12194
|
+
let triggerIdx = -1;
|
|
12195
|
+
let triggerKind = null;
|
|
12196
|
+
for (let i = caret - 1; i >= 0; i--) {
|
|
12197
|
+
const ch = next[i];
|
|
12198
|
+
if (ch === "@") {
|
|
12199
|
+
triggerKind = "mention";
|
|
12200
|
+
triggerIdx = i;
|
|
12201
|
+
break;
|
|
12202
|
+
}
|
|
12203
|
+
if (ch === "/" && (i === 0 || /\s/.test(next[i - 1] ?? ""))) {
|
|
12204
|
+
triggerKind = "cmd";
|
|
12205
|
+
triggerIdx = i;
|
|
12206
|
+
break;
|
|
12207
|
+
}
|
|
12208
|
+
if (/\s/.test(ch)) break;
|
|
12209
|
+
}
|
|
12210
|
+
if (triggerKind !== null && triggerIdx >= 0) {
|
|
12211
|
+
const query = next.slice(triggerIdx + 1, caret);
|
|
12212
|
+
setPicker({ kind: triggerKind, start: triggerIdx, query, cursor: 0 });
|
|
12213
|
+
} else {
|
|
12214
|
+
setPicker(null);
|
|
12215
|
+
}
|
|
12216
|
+
};
|
|
12217
|
+
const insertChoice = (i) => {
|
|
12218
|
+
if (!picker || items.length === 0) return;
|
|
12219
|
+
const choice = items[i] ?? items[0];
|
|
12220
|
+
const insert = picker.kind === "cmd" ? choice.name + " " : `@${choice.id} `;
|
|
12221
|
+
const before = text.slice(0, picker.start);
|
|
12222
|
+
const after = text.slice(picker.start + 1 + picker.query.length);
|
|
12223
|
+
const next = before + insert + after;
|
|
12224
|
+
setText(next);
|
|
12225
|
+
setPicker(null);
|
|
12226
|
+
requestAnimationFrame(() => {
|
|
12227
|
+
const ta = taRef.current;
|
|
12228
|
+
if (!ta) return;
|
|
12229
|
+
ta.focus();
|
|
12230
|
+
const pos = before.length + insert.length;
|
|
12231
|
+
ta.setSelectionRange(pos, pos);
|
|
12232
|
+
});
|
|
12233
|
+
};
|
|
12234
|
+
const submit = () => {
|
|
12235
|
+
if (!text.trim() && attachments.length === 0) return;
|
|
12236
|
+
onSubmit(text, attachments);
|
|
12237
|
+
setText("");
|
|
12238
|
+
setAttachments([]);
|
|
12239
|
+
setPicker(null);
|
|
12240
|
+
};
|
|
12241
|
+
const onKeyDown = (e) => {
|
|
12242
|
+
if (picker) {
|
|
12243
|
+
if (e.key === "ArrowDown") {
|
|
12244
|
+
e.preventDefault();
|
|
12245
|
+
setPicker(
|
|
12246
|
+
(p) => p ? { ...p, cursor: Math.min(items.length - 1, p.cursor + 1) } : p
|
|
12247
|
+
);
|
|
12248
|
+
return;
|
|
12249
|
+
}
|
|
12250
|
+
if (e.key === "ArrowUp") {
|
|
12251
|
+
e.preventDefault();
|
|
12252
|
+
setPicker((p) => p ? { ...p, cursor: Math.max(0, p.cursor - 1) } : p);
|
|
12253
|
+
return;
|
|
12254
|
+
}
|
|
12255
|
+
if (e.key === "Enter" && !e.metaKey && !e.ctrlKey && items.length > 0) {
|
|
12256
|
+
e.preventDefault();
|
|
12257
|
+
insertChoice(picker.cursor);
|
|
12258
|
+
return;
|
|
12259
|
+
}
|
|
12260
|
+
if (e.key === "Escape") {
|
|
12261
|
+
e.preventDefault();
|
|
12262
|
+
setPicker(null);
|
|
12263
|
+
return;
|
|
12264
|
+
}
|
|
12265
|
+
}
|
|
12266
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
12267
|
+
e.preventDefault();
|
|
12268
|
+
submit();
|
|
12269
|
+
}
|
|
12270
|
+
};
|
|
12271
|
+
const onDrop = (e) => {
|
|
12272
|
+
e.preventDefault();
|
|
12273
|
+
setDragOver(false);
|
|
12274
|
+
const files = Array.from(e.dataTransfer.files);
|
|
12275
|
+
setAttachments((cur) => [
|
|
12276
|
+
...cur,
|
|
12277
|
+
...files.map((f) => ({
|
|
12278
|
+
id: `${f.name}-${Date.now()}-${Math.random()}`,
|
|
12279
|
+
name: f.name,
|
|
12280
|
+
bytes: f.size
|
|
12281
|
+
}))
|
|
12282
|
+
]);
|
|
12283
|
+
};
|
|
12284
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12285
|
+
"div",
|
|
12286
|
+
{
|
|
12287
|
+
onDragOver: (e) => {
|
|
12288
|
+
e.preventDefault();
|
|
12289
|
+
setDragOver(true);
|
|
12290
|
+
},
|
|
12291
|
+
onDragLeave: () => setDragOver(false),
|
|
12292
|
+
onDrop,
|
|
12293
|
+
className: `relative rounded-md border transition ${dragOver ? "border-violet-400 bg-violet-50/50 dark:border-violet-600 dark:bg-violet-950/30" : "border-zinc-200 dark:border-zinc-800"} bg-white dark:bg-zinc-900`,
|
|
12294
|
+
children: [
|
|
12295
|
+
attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-1.5 border-b border-zinc-200 px-3 py-2 dark:border-zinc-800", children: attachments.map((a) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12296
|
+
"span",
|
|
12297
|
+
{
|
|
12298
|
+
className: "inline-flex items-center gap-1.5 rounded-md bg-zinc-100 px-2 py-0.5 text-[11px] dark:bg-zinc-800",
|
|
12299
|
+
children: [
|
|
12300
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u{1F4CE}" }),
|
|
12301
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: a.name }),
|
|
12302
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-400", children: fmtSize(a.bytes) }),
|
|
12303
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12304
|
+
"button",
|
|
12305
|
+
{
|
|
12306
|
+
onClick: () => setAttachments((cur) => cur.filter((x) => x.id !== a.id)),
|
|
12307
|
+
className: "opacity-50 hover:opacity-100",
|
|
12308
|
+
"aria-label": "Remove attachment",
|
|
12309
|
+
children: "\xD7"
|
|
12310
|
+
}
|
|
12311
|
+
)
|
|
12312
|
+
]
|
|
12313
|
+
},
|
|
12314
|
+
a.id
|
|
12315
|
+
)) }),
|
|
12316
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
12317
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12318
|
+
"textarea",
|
|
12319
|
+
{
|
|
12320
|
+
ref: taRef,
|
|
12321
|
+
value: text,
|
|
12322
|
+
onChange: (e) => updateText(e.target.value, e.target.selectionStart),
|
|
12323
|
+
onKeyDown,
|
|
12324
|
+
placeholder,
|
|
12325
|
+
spellCheck: false,
|
|
12326
|
+
className: "block w-full resize-none bg-transparent px-3 py-2.5 text-[14px] leading-relaxed outline-none placeholder:text-zinc-400",
|
|
12327
|
+
rows: 3
|
|
12328
|
+
}
|
|
12329
|
+
),
|
|
12330
|
+
picker && items.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-full left-2 z-10 mb-1 w-72 overflow-hidden rounded-md border border-zinc-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900", children: [
|
|
12331
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950", children: [
|
|
12332
|
+
picker.kind === "cmd" ? "Commands" : "Mention",
|
|
12333
|
+
" \xB7 ",
|
|
12334
|
+
items.length
|
|
12335
|
+
] }),
|
|
12336
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "max-h-56 overflow-y-auto", children: items.map((item, i) => {
|
|
12337
|
+
const active = i === picker.cursor;
|
|
12338
|
+
if (picker.kind === "cmd") {
|
|
12339
|
+
const c = item;
|
|
12340
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12341
|
+
"li",
|
|
12342
|
+
{
|
|
12343
|
+
onMouseDown: (e) => {
|
|
12344
|
+
e.preventDefault();
|
|
12345
|
+
insertChoice(i);
|
|
12346
|
+
},
|
|
12347
|
+
onMouseEnter: () => setPicker((p) => p ? { ...p, cursor: i } : p),
|
|
12348
|
+
className: `cursor-pointer px-2 py-1.5 text-[12px] ${active ? "bg-violet-100 dark:bg-violet-900/30" : "hover:bg-zinc-50 dark:hover:bg-zinc-800"}`,
|
|
12349
|
+
children: [
|
|
12350
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-mono font-medium text-violet-700 dark:text-violet-300", children: c.name }),
|
|
12351
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] text-zinc-500", children: c.hint })
|
|
12352
|
+
]
|
|
12353
|
+
},
|
|
12354
|
+
c.name
|
|
12355
|
+
);
|
|
12356
|
+
}
|
|
12357
|
+
const m = item;
|
|
12358
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12359
|
+
"li",
|
|
12360
|
+
{
|
|
12361
|
+
onMouseDown: (e) => {
|
|
12362
|
+
e.preventDefault();
|
|
12363
|
+
insertChoice(i);
|
|
12364
|
+
},
|
|
12365
|
+
onMouseEnter: () => setPicker((p) => p ? { ...p, cursor: i } : p),
|
|
12366
|
+
className: `flex cursor-pointer items-center gap-2 px-2 py-1.5 text-[12px] ${active ? "bg-violet-100 dark:bg-violet-900/30" : "hover:bg-zinc-50 dark:hover:bg-zinc-800"}`,
|
|
12367
|
+
children: [
|
|
12368
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12369
|
+
"span",
|
|
12370
|
+
{
|
|
12371
|
+
className: "h-2 w-2 rounded-full",
|
|
12372
|
+
style: { backgroundColor: colors[m.kind] ?? "#71717a" }
|
|
12373
|
+
}
|
|
12374
|
+
),
|
|
12375
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: m.name }),
|
|
12376
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-[10px] uppercase tracking-wider text-zinc-400", children: m.kind })
|
|
12377
|
+
]
|
|
12378
|
+
},
|
|
12379
|
+
m.id
|
|
12380
|
+
);
|
|
12381
|
+
}) })
|
|
12382
|
+
] })
|
|
12383
|
+
] }),
|
|
12384
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-t border-zinc-200 bg-zinc-50/60 px-3 py-2 dark:border-zinc-800 dark:bg-zinc-900/40", children: [
|
|
12385
|
+
/* @__PURE__ */ jsxRuntime.jsx(Tooltip, { content: "Drop files here, or click", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12386
|
+
Action,
|
|
12387
|
+
{
|
|
12388
|
+
variant: "ghost",
|
|
12389
|
+
size: "sm",
|
|
12390
|
+
onClick: () => {
|
|
12391
|
+
},
|
|
12392
|
+
children: "\u{1F4CE} attach"
|
|
12393
|
+
}
|
|
12394
|
+
) }),
|
|
12395
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-2 flex items-center gap-1.5", children: [
|
|
12396
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 w-24 overflow-hidden rounded-full bg-zinc-200 dark:bg-zinc-700", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12397
|
+
"div",
|
|
12398
|
+
{
|
|
12399
|
+
className: "h-full rounded-full transition-all",
|
|
12400
|
+
style: { width: `${ratio * 100}%`, backgroundColor: meterColor }
|
|
12401
|
+
}
|
|
12402
|
+
) }),
|
|
12403
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono text-[11px]", style: { color: meterColor }, children: [
|
|
12404
|
+
fmtTokens(tokens),
|
|
12405
|
+
" / ",
|
|
12406
|
+
fmtTokens(budgetTokens)
|
|
12407
|
+
] })
|
|
12408
|
+
] }),
|
|
12409
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto flex items-center gap-2", children: [
|
|
12410
|
+
showHint && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "hidden text-[10px] text-zinc-500 sm:inline", children: [
|
|
12411
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300", children: "\u2318" }),
|
|
12412
|
+
" ",
|
|
12413
|
+
"+",
|
|
12414
|
+
" ",
|
|
12415
|
+
/* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "rounded border border-zinc-300 bg-zinc-50 px-1 py-0.5 font-mono text-[9px] text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300", children: "Enter" }),
|
|
12416
|
+
" ",
|
|
12417
|
+
"to send"
|
|
12418
|
+
] }),
|
|
12419
|
+
/* @__PURE__ */ jsxRuntime.jsx(Action, { color: "violet", size: "sm", onClick: submit, children: "send \u2192" })
|
|
12420
|
+
] })
|
|
12421
|
+
] })
|
|
12422
|
+
]
|
|
12423
|
+
}
|
|
12424
|
+
);
|
|
12425
|
+
}
|
|
12426
|
+
function fmtTokens(n) {
|
|
12427
|
+
if (n < 1e3) return `${n}`;
|
|
12428
|
+
return `${(n / 1e3).toFixed(1)}k`;
|
|
12429
|
+
}
|
|
12430
|
+
function fmtSize(b) {
|
|
12431
|
+
if (b < 1024) return `${b} B`;
|
|
12432
|
+
if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`;
|
|
12433
|
+
return `${(b / 1024 / 1024).toFixed(1)} MB`;
|
|
12434
|
+
}
|
|
12435
|
+
function MagicWand({
|
|
12436
|
+
value,
|
|
12437
|
+
onValueChange,
|
|
12438
|
+
actions,
|
|
12439
|
+
appearance = "floating",
|
|
12440
|
+
autoHide = true,
|
|
12441
|
+
rows = 6,
|
|
12442
|
+
placeholder,
|
|
12443
|
+
onAction
|
|
12444
|
+
}) {
|
|
12445
|
+
const taRef = react.useRef(null);
|
|
12446
|
+
const wandRef = react.useRef(null);
|
|
12447
|
+
const [sel, setSel] = react.useState(null);
|
|
12448
|
+
const [pos, setPos] = react.useState(null);
|
|
12449
|
+
const [busy, setBusy] = react.useState(null);
|
|
12450
|
+
const measureSelection = react.useCallback(() => {
|
|
12451
|
+
const ta = taRef.current;
|
|
12452
|
+
if (!ta) return;
|
|
12453
|
+
const start = ta.selectionStart ?? 0;
|
|
12454
|
+
const end = ta.selectionEnd ?? 0;
|
|
12455
|
+
if (start === end) {
|
|
12456
|
+
setSel(null);
|
|
12457
|
+
setPos(null);
|
|
12458
|
+
return;
|
|
12459
|
+
}
|
|
12460
|
+
const text = ta.value.slice(start, end);
|
|
12461
|
+
setSel({ start, end, text });
|
|
12462
|
+
const rect = caretRect(ta, start, end);
|
|
12463
|
+
if (rect) setPos({ x: rect.x, y: rect.y });
|
|
12464
|
+
}, []);
|
|
12465
|
+
react.useEffect(() => {
|
|
12466
|
+
if (!autoHide) return;
|
|
12467
|
+
const onScroll = () => {
|
|
12468
|
+
setSel(null);
|
|
12469
|
+
setPos(null);
|
|
12470
|
+
};
|
|
12471
|
+
window.addEventListener("scroll", onScroll, true);
|
|
12472
|
+
return () => window.removeEventListener("scroll", onScroll, true);
|
|
12473
|
+
}, [autoHide]);
|
|
12474
|
+
react.useEffect(() => {
|
|
12475
|
+
if (!autoHide) return;
|
|
12476
|
+
const onDocMouseDown = (e) => {
|
|
12477
|
+
if (wandRef.current?.contains(e.target)) return;
|
|
12478
|
+
if (taRef.current?.contains(e.target)) return;
|
|
12479
|
+
setSel(null);
|
|
12480
|
+
setPos(null);
|
|
12481
|
+
};
|
|
12482
|
+
document.addEventListener("mousedown", onDocMouseDown);
|
|
12483
|
+
return () => document.removeEventListener("mousedown", onDocMouseDown);
|
|
12484
|
+
}, [autoHide]);
|
|
12485
|
+
const handleAction = async (action) => {
|
|
12486
|
+
if (!sel) return;
|
|
12487
|
+
setBusy(action.id);
|
|
12488
|
+
try {
|
|
12489
|
+
const replacement = await action.run(sel.text, sel);
|
|
12490
|
+
const next = value.slice(0, sel.start) + replacement + value.slice(sel.end);
|
|
12491
|
+
onValueChange(next);
|
|
12492
|
+
onAction?.(action, sel, replacement);
|
|
12493
|
+
} finally {
|
|
12494
|
+
setBusy(null);
|
|
12495
|
+
setSel(null);
|
|
12496
|
+
setPos(null);
|
|
12497
|
+
}
|
|
12498
|
+
};
|
|
12499
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
12500
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12501
|
+
Textarea,
|
|
12502
|
+
{
|
|
12503
|
+
ref: taRef,
|
|
12504
|
+
value,
|
|
12505
|
+
onValueChange,
|
|
12506
|
+
onSelect: measureSelection,
|
|
12507
|
+
onKeyUp: measureSelection,
|
|
12508
|
+
onMouseUp: measureSelection,
|
|
12509
|
+
rows,
|
|
12510
|
+
placeholder
|
|
12511
|
+
}
|
|
12512
|
+
),
|
|
12513
|
+
sel && pos && /* @__PURE__ */ jsxRuntime.jsx(
|
|
12514
|
+
Wand,
|
|
12515
|
+
{
|
|
12516
|
+
ref: wandRef,
|
|
12517
|
+
pos,
|
|
12518
|
+
actions,
|
|
12519
|
+
appearance,
|
|
12520
|
+
busy,
|
|
12521
|
+
onAction: handleAction,
|
|
12522
|
+
selectionLength: sel.text.length
|
|
12523
|
+
}
|
|
12524
|
+
)
|
|
12525
|
+
] });
|
|
12526
|
+
}
|
|
12527
|
+
function Wand({
|
|
12528
|
+
ref,
|
|
12529
|
+
pos,
|
|
12530
|
+
actions,
|
|
12531
|
+
appearance,
|
|
12532
|
+
busy,
|
|
12533
|
+
onAction,
|
|
12534
|
+
selectionLength
|
|
12535
|
+
}) {
|
|
12536
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12537
|
+
"div",
|
|
12538
|
+
{
|
|
12539
|
+
ref,
|
|
12540
|
+
className: "absolute z-20 -translate-x-1/2 -translate-y-full",
|
|
12541
|
+
style: { left: pos.x, top: pos.y - 6 },
|
|
12542
|
+
children: [
|
|
12543
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 rounded-full border border-violet-300 bg-white px-1.5 py-1 shadow-lg ring-1 ring-violet-200 dark:border-violet-700 dark:bg-zinc-900 dark:ring-violet-900", children: [
|
|
12544
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-1 mr-0.5 inline-flex items-center gap-1 text-[10px] font-medium text-violet-700 dark:text-violet-300", children: [
|
|
12545
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: "\u2726" }),
|
|
12546
|
+
appearance === "floating" && /* @__PURE__ */ jsxRuntime.jsxs(Badge, { color: "violet", children: [
|
|
12547
|
+
selectionLength,
|
|
12548
|
+
" chars"
|
|
12549
|
+
] })
|
|
12550
|
+
] }),
|
|
12551
|
+
actions.map((a) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12552
|
+
Action,
|
|
12553
|
+
{
|
|
12554
|
+
size: "sm",
|
|
12555
|
+
variant: "ghost",
|
|
12556
|
+
onClick: () => onAction(a),
|
|
12557
|
+
disabled: busy !== null,
|
|
12558
|
+
title: a.hint,
|
|
12559
|
+
children: [
|
|
12560
|
+
busy === a.id ? "\u2026" : appearance === "pill" ? a.label[0] : a.label,
|
|
12561
|
+
appearance === "floating" && a.tag && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 rounded-full bg-zinc-100 px-1 text-[9px] font-medium text-zinc-500 dark:bg-zinc-800", children: a.tag })
|
|
12562
|
+
]
|
|
12563
|
+
},
|
|
12564
|
+
a.id
|
|
12565
|
+
))
|
|
12566
|
+
] }),
|
|
12567
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 top-full -translate-x-1/2 -translate-y-px", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rotate-45 border-b border-r border-violet-300 bg-white dark:border-violet-700 dark:bg-zinc-900" }) })
|
|
12568
|
+
]
|
|
12569
|
+
}
|
|
12570
|
+
);
|
|
12571
|
+
}
|
|
12572
|
+
function caretRect(ta, start, end) {
|
|
12573
|
+
const div = document.createElement("div");
|
|
12574
|
+
const style = getComputedStyle(ta);
|
|
12575
|
+
const props = [
|
|
12576
|
+
"boxSizing",
|
|
12577
|
+
"width",
|
|
12578
|
+
"height",
|
|
12579
|
+
"overflowX",
|
|
12580
|
+
"overflowY",
|
|
12581
|
+
"borderTopWidth",
|
|
12582
|
+
"borderRightWidth",
|
|
12583
|
+
"borderBottomWidth",
|
|
12584
|
+
"borderLeftWidth",
|
|
12585
|
+
"paddingTop",
|
|
12586
|
+
"paddingRight",
|
|
12587
|
+
"paddingBottom",
|
|
12588
|
+
"paddingLeft",
|
|
12589
|
+
"fontStyle",
|
|
12590
|
+
"fontVariant",
|
|
12591
|
+
"fontWeight",
|
|
12592
|
+
"fontStretch",
|
|
12593
|
+
"fontSize",
|
|
12594
|
+
"fontSizeAdjust",
|
|
12595
|
+
"lineHeight",
|
|
12596
|
+
"fontFamily",
|
|
12597
|
+
"textAlign",
|
|
12598
|
+
"textTransform",
|
|
12599
|
+
"textIndent",
|
|
12600
|
+
"letterSpacing",
|
|
12601
|
+
"wordSpacing",
|
|
12602
|
+
"tabSize"
|
|
12603
|
+
];
|
|
12604
|
+
for (const p of props) div.style[p] = style[p];
|
|
12605
|
+
div.style.position = "absolute";
|
|
12606
|
+
div.style.top = "-9999px";
|
|
12607
|
+
div.style.left = "-9999px";
|
|
12608
|
+
div.style.whiteSpace = "pre-wrap";
|
|
12609
|
+
div.style.wordWrap = "break-word";
|
|
12610
|
+
const value = ta.value;
|
|
12611
|
+
div.textContent = value.substring(0, start);
|
|
12612
|
+
const startSpan = document.createElement("span");
|
|
12613
|
+
startSpan.textContent = value.substring(start, end) || ".";
|
|
12614
|
+
div.appendChild(startSpan);
|
|
12615
|
+
document.body.appendChild(div);
|
|
12616
|
+
const taRect = ta.getBoundingClientRect();
|
|
12617
|
+
const parentRect = ta.offsetParent?.getBoundingClientRect() ?? taRect;
|
|
12618
|
+
const spanRect = startSpan.getBoundingClientRect();
|
|
12619
|
+
const divRect = div.getBoundingClientRect();
|
|
12620
|
+
const offsetX = spanRect.left - divRect.left;
|
|
12621
|
+
const offsetY = spanRect.top - divRect.top;
|
|
12622
|
+
document.body.removeChild(div);
|
|
12623
|
+
const x = taRect.left - parentRect.left + offsetX + spanRect.width / 2;
|
|
12624
|
+
const y = taRect.top - parentRect.top + offsetY - ta.scrollTop;
|
|
12625
|
+
return { x, y };
|
|
12626
|
+
}
|
|
11843
12627
|
|
|
11844
12628
|
exports.Accordion = Accordion;
|
|
11845
12629
|
exports.AccordionPanel = AccordionPanel;
|
|
@@ -11878,9 +12662,11 @@ exports.Heading = Heading;
|
|
|
11878
12662
|
exports.Icon = Icon;
|
|
11879
12663
|
exports.Input = Input;
|
|
11880
12664
|
exports.Kanban = Kanban;
|
|
12665
|
+
exports.MagicWand = MagicWand;
|
|
11881
12666
|
exports.Menu = Menu2;
|
|
11882
12667
|
exports.MobileMenu = MobileMenu;
|
|
11883
12668
|
exports.Modal = Modal;
|
|
12669
|
+
exports.MoodMeter = MoodMeter;
|
|
11884
12670
|
exports.MultiSwitch = MultiSwitch;
|
|
11885
12671
|
exports.Navbar = Navbar;
|
|
11886
12672
|
exports.OtpInput = OtpInput;
|
|
@@ -11890,7 +12676,9 @@ exports.Popover = Popover;
|
|
|
11890
12676
|
exports.Portal = Portal;
|
|
11891
12677
|
exports.Profile = Profile;
|
|
11892
12678
|
exports.Progress = Progress;
|
|
12679
|
+
exports.PromptInput = PromptInput;
|
|
11893
12680
|
exports.RadioGroup = RadioGroup;
|
|
12681
|
+
exports.ReasonTag = ReasonTag;
|
|
11894
12682
|
exports.SKIN_TONES = SKIN_TONES;
|
|
11895
12683
|
exports.Select = Select;
|
|
11896
12684
|
exports.Separator = Separator;
|