@bysages/react 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-response-jZy-0Tvv.mjs +127 -0
- package/dist/chevron-BeHvt46K.mjs +17 -0
- package/dist/components/accordion/index.d.mts +7 -0
- package/dist/components/accordion/index.mjs +10 -0
- package/dist/components/affix/index.d.mts +20 -0
- package/dist/components/affix/index.mjs +18 -0
- package/dist/components/ai/index.d.mts +2 -0
- package/dist/components/ai/index.mjs +65 -0
- package/dist/components/ai-action/index.d.mts +14 -0
- package/dist/components/ai-action/index.mjs +18 -0
- package/dist/components/ai-attachments/index.d.mts +19 -0
- package/dist/components/ai-attachments/index.mjs +106 -0
- package/dist/components/ai-message/index.d.mts +11 -0
- package/dist/components/ai-message/index.mjs +15 -0
- package/dist/components/ai-prompt-input/index.d.mts +47 -0
- package/dist/components/ai-prompt-input/index.mjs +135 -0
- package/dist/components/ai-reasoning/index.d.mts +13 -0
- package/dist/components/ai-reasoning/index.mjs +19 -0
- package/dist/components/ai-response/index.d.mts +22 -0
- package/dist/components/ai-response/index.mjs +2 -0
- package/dist/components/ai-source/index.d.mts +17 -0
- package/dist/components/ai-source/index.mjs +27 -0
- package/dist/components/ai-suggestion/index.d.mts +13 -0
- package/dist/components/ai-suggestion/index.mjs +16 -0
- package/dist/components/ai-tool/index.d.mts +21 -0
- package/dist/components/ai-tool/index.mjs +36 -0
- package/dist/components/alert/index.d.mts +23 -0
- package/dist/components/alert/index.mjs +80 -0
- package/dist/components/angle-slider/index.d.mts +16 -0
- package/dist/components/angle-slider/index.mjs +21 -0
- package/dist/components/aspect-ratio/index.d.mts +10 -0
- package/dist/components/aspect-ratio/index.mjs +17 -0
- package/dist/components/autocomplete/index.d.mts +21 -0
- package/dist/components/autocomplete/index.mjs +35 -0
- package/dist/components/avatar/index.d.mts +20 -0
- package/dist/components/avatar/index.mjs +14 -0
- package/dist/components/avatar-group/index.d.mts +11 -0
- package/dist/components/avatar-group/index.mjs +15 -0
- package/dist/components/back-top/index.d.mts +29 -0
- package/dist/components/back-top/index.mjs +82 -0
- package/dist/components/badge/index.d.mts +10 -0
- package/dist/components/badge/index.mjs +15 -0
- package/dist/components/banner/index.d.mts +31 -0
- package/dist/components/banner/index.mjs +63 -0
- package/dist/components/breadcrumb/index.d.mts +32 -0
- package/dist/components/breadcrumb/index.mjs +35 -0
- package/dist/components/button/index.d.mts +19 -0
- package/dist/components/button/index.mjs +29 -0
- package/dist/components/button-group/index.d.mts +24 -0
- package/dist/components/button-group/index.mjs +25 -0
- package/dist/components/calendar/index.d.mts +17 -0
- package/dist/components/calendar/index.mjs +96 -0
- package/dist/components/card/index.d.mts +46 -0
- package/dist/components/card/index.mjs +44 -0
- package/dist/components/carousel/index.d.mts +9 -0
- package/dist/components/carousel/index.mjs +12 -0
- package/dist/components/cascade-select/index.d.mts +31 -0
- package/dist/components/cascade-select/index.mjs +223 -0
- package/dist/components/checkbox/index.d.mts +16 -0
- package/dist/components/checkbox/index.mjs +21 -0
- package/dist/components/checkbox-group/index.d.mts +28 -0
- package/dist/components/checkbox-group/index.mjs +65 -0
- package/dist/components/chip/index.d.mts +12 -0
- package/dist/components/chip/index.mjs +17 -0
- package/dist/components/client-only/index.d.mts +2 -0
- package/dist/components/client-only/index.mjs +2 -0
- package/dist/components/clipboard/index.d.mts +17 -0
- package/dist/components/clipboard/index.mjs +17 -0
- package/dist/components/collapsible/index.d.mts +7 -0
- package/dist/components/collapsible/index.mjs +10 -0
- package/dist/components/collection/index.d.mts +2 -0
- package/dist/components/collection/index.mjs +2 -0
- package/dist/components/color-picker/index.d.mts +20 -0
- package/dist/components/color-picker/index.mjs +25 -0
- package/dist/components/combobox/index.d.mts +17 -0
- package/dist/components/combobox/index.mjs +18 -0
- package/dist/components/command/index.d.mts +43 -0
- package/dist/components/command/index.mjs +137 -0
- package/dist/components/comment/index.d.mts +17 -0
- package/dist/components/comment/index.mjs +47 -0
- package/dist/components/config-provider/index.d.mts +46 -0
- package/dist/components/config-provider/index.mjs +41 -0
- package/dist/components/container/index.d.mts +13 -0
- package/dist/components/container/index.mjs +15 -0
- package/dist/components/date-input/index.d.mts +17 -0
- package/dist/components/date-input/index.mjs +21 -0
- package/dist/components/date-picker/index.d.mts +19 -0
- package/dist/components/date-picker/index.mjs +23 -0
- package/dist/components/descriptions/index.d.mts +25 -0
- package/dist/components/descriptions/index.mjs +32 -0
- package/dist/components/dialog/index.d.mts +9 -0
- package/dist/components/dialog/index.mjs +11 -0
- package/dist/components/download-trigger/index.d.mts +2 -0
- package/dist/components/download-trigger/index.mjs +2 -0
- package/dist/components/drawer/index.d.mts +9 -0
- package/dist/components/drawer/index.mjs +12 -0
- package/dist/components/dynamic-input/index.d.mts +28 -0
- package/dist/components/dynamic-input/index.mjs +83 -0
- package/dist/components/editable/index.d.mts +16 -0
- package/dist/components/editable/index.mjs +17 -0
- package/dist/components/ellipsis/index.d.mts +10 -0
- package/dist/components/ellipsis/index.mjs +19 -0
- package/dist/components/empty/index.d.mts +28 -0
- package/dist/components/empty/index.mjs +32 -0
- package/dist/components/field/index.d.mts +8 -0
- package/dist/components/field/index.mjs +11 -0
- package/dist/components/fieldset/index.d.mts +7 -0
- package/dist/components/fieldset/index.mjs +10 -0
- package/dist/components/file-upload/index.d.mts +18 -0
- package/dist/components/file-upload/index.mjs +23 -0
- package/dist/components/float-button/index.d.mts +59 -0
- package/dist/components/float-button/index.mjs +90 -0
- package/dist/components/floating-panel/index.d.mts +9 -0
- package/dist/components/floating-panel/index.mjs +12 -0
- package/dist/components/focus-trap/index.d.mts +2 -0
- package/dist/components/focus-trap/index.mjs +2 -0
- package/dist/components/form/index.d.mts +2 -0
- package/dist/components/form/index.mjs +67 -0
- package/dist/components/format/index.d.mts +9 -0
- package/dist/components/format/index.mjs +10 -0
- package/dist/components/frame/index.d.mts +10 -0
- package/dist/components/frame/index.mjs +12 -0
- package/dist/components/grid/index.d.mts +13 -0
- package/dist/components/grid/index.mjs +31 -0
- package/dist/components/highlight/index.d.mts +7 -0
- package/dist/components/highlight/index.mjs +11 -0
- package/dist/components/hover-card/index.d.mts +7 -0
- package/dist/components/hover-card/index.mjs +10 -0
- package/dist/components/icon/index.d.mts +19 -0
- package/dist/components/icon/index.mjs +26 -0
- package/dist/components/image/index.d.mts +17 -0
- package/dist/components/image/index.mjs +57 -0
- package/dist/components/image-cropper/index.d.mts +8 -0
- package/dist/components/image-cropper/index.mjs +11 -0
- package/dist/components/image-viewer/index.d.mts +18 -0
- package/dist/components/image-viewer/index.mjs +110 -0
- package/dist/components/input/index.d.mts +16 -0
- package/dist/components/input/index.mjs +21 -0
- package/dist/components/input-group/index.d.mts +17 -0
- package/dist/components/input-group/index.mjs +31 -0
- package/dist/components/json-tree-view/index.d.mts +7 -0
- package/dist/components/json-tree-view/index.mjs +10 -0
- package/dist/components/kbd/index.d.mts +6 -0
- package/dist/components/kbd/index.mjs +14 -0
- package/dist/components/layout/index.d.mts +63 -0
- package/dist/components/layout/index.mjs +133 -0
- package/dist/components/link/index.d.mts +10 -0
- package/dist/components/link/index.mjs +18 -0
- package/dist/components/list/index.d.mts +39 -0
- package/dist/components/list/index.mjs +66 -0
- package/dist/components/listbox/index.d.mts +18 -0
- package/dist/components/listbox/index.mjs +18 -0
- package/dist/components/marquee/index.d.mts +7 -0
- package/dist/components/marquee/index.mjs +10 -0
- package/dist/components/masonry/index.d.mts +11 -0
- package/dist/components/masonry/index.mjs +29 -0
- package/dist/components/mentions/index.d.mts +2 -0
- package/dist/components/mentions/index.mjs +2 -0
- package/dist/components/menu/index.d.mts +20 -0
- package/dist/components/menu/index.mjs +37 -0
- package/dist/components/menubar/index.d.mts +32 -0
- package/dist/components/menubar/index.mjs +35 -0
- package/dist/components/meter/index.d.mts +26 -0
- package/dist/components/meter/index.mjs +59 -0
- package/dist/components/navigation-menu/index.d.mts +8 -0
- package/dist/components/navigation-menu/index.mjs +11 -0
- package/dist/components/number-input/index.d.mts +16 -0
- package/dist/components/number-input/index.mjs +21 -0
- package/dist/components/page-header/index.d.mts +32 -0
- package/dist/components/page-header/index.mjs +34 -0
- package/dist/components/pagination/index.d.mts +18 -0
- package/dist/components/pagination/index.mjs +23 -0
- package/dist/components/password-input/index.d.mts +16 -0
- package/dist/components/password-input/index.mjs +21 -0
- package/dist/components/pin-input/index.d.mts +15 -0
- package/dist/components/pin-input/index.mjs +20 -0
- package/dist/components/popconfirm/index.d.mts +20 -0
- package/dist/components/popconfirm/index.mjs +44 -0
- package/dist/components/popover/index.d.mts +8 -0
- package/dist/components/popover/index.mjs +11 -0
- package/dist/components/presence/index.d.mts +2 -0
- package/dist/components/presence/index.mjs +2 -0
- package/dist/components/progress/index.d.mts +16 -0
- package/dist/components/progress/index.mjs +21 -0
- package/dist/components/progress-group/index.d.mts +22 -0
- package/dist/components/progress-group/index.mjs +56 -0
- package/dist/components/qr-code/index.d.mts +8 -0
- package/dist/components/qr-code/index.mjs +11 -0
- package/dist/components/radio-group/index.d.mts +16 -0
- package/dist/components/radio-group/index.mjs +21 -0
- package/dist/components/rating-group/index.d.mts +16 -0
- package/dist/components/rating-group/index.mjs +21 -0
- package/dist/components/scroll-area/index.d.mts +7 -0
- package/dist/components/scroll-area/index.mjs +10 -0
- package/dist/components/segment-group/index.d.mts +18 -0
- package/dist/components/segment-group/index.mjs +20 -0
- package/dist/components/select/index.d.mts +17 -0
- package/dist/components/select/index.mjs +18 -0
- package/dist/components/separator/index.d.mts +11 -0
- package/dist/components/separator/index.mjs +16 -0
- package/dist/components/signature-pad/index.d.mts +8 -0
- package/dist/components/signature-pad/index.mjs +11 -0
- package/dist/components/skeleton/index.d.mts +7 -0
- package/dist/components/skeleton/index.mjs +13 -0
- package/dist/components/slider/index.d.mts +16 -0
- package/dist/components/slider/index.mjs +21 -0
- package/dist/components/spinner/index.d.mts +9 -0
- package/dist/components/spinner/index.mjs +36 -0
- package/dist/components/split-button/index.d.mts +36 -0
- package/dist/components/split-button/index.mjs +71 -0
- package/dist/components/splitter/index.d.mts +7 -0
- package/dist/components/splitter/index.mjs +10 -0
- package/dist/components/stack/index.d.mts +11 -0
- package/dist/components/stack/index.mjs +32 -0
- package/dist/components/stat/index.d.mts +29 -0
- package/dist/components/stat/index.mjs +37 -0
- package/dist/components/steps/index.d.mts +19 -0
- package/dist/components/steps/index.mjs +24 -0
- package/dist/components/swap/index.d.mts +8 -0
- package/dist/components/swap/index.mjs +11 -0
- package/dist/components/switch/index.d.mts +16 -0
- package/dist/components/switch/index.mjs +21 -0
- package/dist/components/table/index.d.mts +79 -0
- package/dist/components/table/index.mjs +688 -0
- package/dist/components/tabs/index.d.mts +18 -0
- package/dist/components/tabs/index.mjs +23 -0
- package/dist/components/tags-input/index.d.mts +17 -0
- package/dist/components/tags-input/index.mjs +22 -0
- package/dist/components/textarea/index.d.mts +14 -0
- package/dist/components/textarea/index.mjs +20 -0
- package/dist/components/timeline/index.d.mts +24 -0
- package/dist/components/timeline/index.mjs +30 -0
- package/dist/components/timer/index.d.mts +8 -0
- package/dist/components/timer/index.mjs +11 -0
- package/dist/components/toast/index.d.mts +11 -0
- package/dist/components/toast/index.mjs +13 -0
- package/dist/components/toc/index.d.mts +7 -0
- package/dist/components/toc/index.mjs +10 -0
- package/dist/components/toggle/index.d.mts +7 -0
- package/dist/components/toggle/index.mjs +10 -0
- package/dist/components/toggle-group/index.d.mts +15 -0
- package/dist/components/toggle-group/index.mjs +20 -0
- package/dist/components/tooltip/index.d.mts +7 -0
- package/dist/components/tooltip/index.mjs +10 -0
- package/dist/components/tour/index.d.mts +11 -0
- package/dist/components/tour/index.mjs +13 -0
- package/dist/components/transfer/index.d.mts +23 -0
- package/dist/components/transfer/index.mjs +154 -0
- package/dist/components/tree-select/index.d.mts +28 -0
- package/dist/components/tree-select/index.mjs +157 -0
- package/dist/components/tree-view/index.d.mts +19 -0
- package/dist/components/tree-view/index.mjs +18 -0
- package/dist/components/typography/index.d.mts +32 -0
- package/dist/components/typography/index.mjs +34 -0
- package/dist/components/watermark/index.d.mts +16 -0
- package/dist/components/watermark/index.mjs +80 -0
- package/dist/index-DaAbbSz9.d.mts +13416 -0
- package/dist/index-Uefyw7Im.d.mts +108 -0
- package/dist/index-uPyYiWaL.d.mts +1813 -0
- package/dist/index.d.mts +128 -15218
- package/dist/index.mjs +128 -4556
- package/dist/mentions-DMIBCBOd.mjs +181 -0
- package/package.json +77 -3
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
import { renderHtml } from "@tanstack/markdown/html";
|
|
5
|
+
//#region src/components/ai-response/code-copy.ts
|
|
6
|
+
/** The two glyphs a copy affordance needs: the stamp and its
|
|
7
|
+
* confirmation. Inline SVG keeps the enhancement framework-agnostic —
|
|
8
|
+
* it lives beside the renderer's generated code HTML. */
|
|
9
|
+
const COPY_CODE_ICON = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>`;
|
|
10
|
+
const COPIED_CODE_ICON = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>`;
|
|
11
|
+
/** How long the confirmation stays before the stamp returns. */
|
|
12
|
+
const REVERT_MS = 1500;
|
|
13
|
+
/** Make sure every fenced block under `host` carries its copy stamp.
|
|
14
|
+
* The stamp anchors to a wrapper outside the scrolling `pre` — inside,
|
|
15
|
+
* it would fix to the overflow area and travel out of view with the
|
|
16
|
+
* code. The renderer rebuilds the markdown as one HTML string on every
|
|
17
|
+
* stream tick, so this stays idempotent and cheap enough to re-run
|
|
18
|
+
* after each patch. */
|
|
19
|
+
function decorateCodeCopy(host, copyLabel) {
|
|
20
|
+
for (const pre of host.querySelectorAll("pre")) {
|
|
21
|
+
let body = pre.parentElement;
|
|
22
|
+
if (!body || body.getAttribute("data-part") !== "code-body") {
|
|
23
|
+
body = document.createElement("div");
|
|
24
|
+
body.setAttribute("data-scope", "ai");
|
|
25
|
+
body.setAttribute("data-part", "code-body");
|
|
26
|
+
pre.replaceWith(body);
|
|
27
|
+
body.appendChild(pre);
|
|
28
|
+
}
|
|
29
|
+
let button = body.querySelector("[data-part=\"code-copy\"]");
|
|
30
|
+
if (!button) {
|
|
31
|
+
button = document.createElement("button");
|
|
32
|
+
button.type = "button";
|
|
33
|
+
button.setAttribute("data-scope", "ai");
|
|
34
|
+
button.setAttribute("data-part", "code-copy");
|
|
35
|
+
button.innerHTML = COPY_CODE_ICON;
|
|
36
|
+
body.appendChild(button);
|
|
37
|
+
}
|
|
38
|
+
button.title = copyLabel;
|
|
39
|
+
button.setAttribute("aria-label", copyLabel);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** The one delegated click for the whole response: copy the block's
|
|
43
|
+
* text and confirm in place, then return the stamp after a beat. */
|
|
44
|
+
async function clickCodeCopy(event, copyLabel, copiedLabel) {
|
|
45
|
+
const button = event.target?.closest("[data-part=\"code-copy\"]");
|
|
46
|
+
const pre = button?.closest("[data-part=\"code-body\"]")?.querySelector("pre");
|
|
47
|
+
if (!button || !pre) return;
|
|
48
|
+
await navigator.clipboard.writeText(pre.textContent ?? "");
|
|
49
|
+
button.innerHTML = COPIED_CODE_ICON;
|
|
50
|
+
button.setAttribute("data-state", "copied");
|
|
51
|
+
button.title = copiedLabel;
|
|
52
|
+
button.setAttribute("aria-label", copiedLabel);
|
|
53
|
+
setTimeout(() => {
|
|
54
|
+
if (!button.isConnected) return;
|
|
55
|
+
button.innerHTML = COPY_CODE_ICON;
|
|
56
|
+
button.removeAttribute("data-state");
|
|
57
|
+
button.title = copyLabel;
|
|
58
|
+
button.setAttribute("aria-label", copyLabel);
|
|
59
|
+
}, REVERT_MS);
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/components/ai-response/tables.ts
|
|
63
|
+
/** Wide tables ride a scrolling lane instead of bursting the column.
|
|
64
|
+
* The lane is a plain div: the table-as-scroll-container form is what
|
|
65
|
+
* ate the mouse wheel over plain tables. Idempotent, so it can run
|
|
66
|
+
* after every stream patch. */
|
|
67
|
+
const lanes = /* @__PURE__ */ new Set();
|
|
68
|
+
let laneObserver;
|
|
69
|
+
/** A lane's verdict must follow its box — the panel around it can
|
|
70
|
+
* resize at any moment, so each lane stays observed and re-decided
|
|
71
|
+
* whenever its width changes. */
|
|
72
|
+
function watchLane(lane) {
|
|
73
|
+
if (lanes.has(lane)) return;
|
|
74
|
+
lanes.add(lane);
|
|
75
|
+
laneObserver ??= new ResizeObserver(() => {
|
|
76
|
+
for (const lane of lanes) {
|
|
77
|
+
if (!lane.isConnected) {
|
|
78
|
+
laneObserver.unobserve(lane);
|
|
79
|
+
lanes.delete(lane);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
lane.toggleAttribute("data-scrollable", lane.scrollWidth > lane.clientWidth);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
laneObserver.observe(lane);
|
|
86
|
+
}
|
|
87
|
+
function wrapResponseTables(root) {
|
|
88
|
+
for (const table of root.querySelectorAll("table")) {
|
|
89
|
+
if (table.parentElement?.hasAttribute("data-table-scroll")) continue;
|
|
90
|
+
const lane = document.createElement("div");
|
|
91
|
+
lane.setAttribute("data-table-scroll", "");
|
|
92
|
+
table.replaceWith(lane);
|
|
93
|
+
lane.append(table);
|
|
94
|
+
}
|
|
95
|
+
for (const lane of root.querySelectorAll("[data-table-scroll]")) {
|
|
96
|
+
lane.toggleAttribute("data-scrollable", lane.scrollWidth > lane.clientWidth);
|
|
97
|
+
watchLane(lane);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/components/ai-response/index.tsx
|
|
102
|
+
function Response({ content, highlighter, copyLabel = "Copy code", copiedLabel = "Copied", ...rest }) {
|
|
103
|
+
injectComponentStyle("ai");
|
|
104
|
+
const root = useRef(null);
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
const host = root.current;
|
|
107
|
+
if (host) decorateCodeCopy(host, copyLabel);
|
|
108
|
+
if (host) wrapResponseTables(host);
|
|
109
|
+
}, [
|
|
110
|
+
content,
|
|
111
|
+
highlighter,
|
|
112
|
+
copyLabel
|
|
113
|
+
]);
|
|
114
|
+
const onClick = (event) => {
|
|
115
|
+
clickCodeCopy(event.nativeEvent, copyLabel, copiedLabel);
|
|
116
|
+
};
|
|
117
|
+
return /* @__PURE__ */ jsx("div", {
|
|
118
|
+
...rest,
|
|
119
|
+
ref: root,
|
|
120
|
+
"data-scope": "ai",
|
|
121
|
+
"data-part": "response",
|
|
122
|
+
onClick,
|
|
123
|
+
dangerouslySetInnerHTML: { __html: renderHtml(content, highlighter ? { highlighter } : void 0) }
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { Response as t };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
//#region src/components/ai/chevron.tsx
|
|
3
|
+
/** The folding chevron the shared indicator turns. */
|
|
4
|
+
const chevron = /* @__PURE__ */ jsx("svg", {
|
|
5
|
+
viewBox: "0 0 16 16",
|
|
6
|
+
fill: "none",
|
|
7
|
+
"aria-hidden": "true",
|
|
8
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
9
|
+
d: "M6 4l4 4-4 4",
|
|
10
|
+
stroke: "currentColor",
|
|
11
|
+
strokeWidth: 1.5,
|
|
12
|
+
strokeLinecap: "round",
|
|
13
|
+
strokeLinejoin: "round"
|
|
14
|
+
})
|
|
15
|
+
});
|
|
16
|
+
//#endregion
|
|
17
|
+
export { chevron as t };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Accordion as Accordion$1 } from "@ark-ui/react/accordion";
|
|
2
|
+
//#region src/components/accordion/index.d.ts
|
|
3
|
+
/** Ark's Accordion, dressed in the paper-and-ink system: a ruled sheet
|
|
4
|
+
* folded by quiet rows, unfolding with a spring-chevoned dissolve. The
|
|
5
|
+
* API is Ark's own — Root, Item, ItemTrigger, ItemContent, ItemIndicator. */
|
|
6
|
+
export declare const Accordion: typeof Accordion$1;
|
|
7
|
+
//#endregion
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { Accordion as Accordion$1 } from "@ark-ui/react/accordion";
|
|
3
|
+
//#region src/components/accordion/index.tsx
|
|
4
|
+
/** Ark's Accordion, dressed in the paper-and-ink system: a ruled sheet
|
|
5
|
+
* folded by quiet rows, unfolding with a spring-chevoned dissolve. The
|
|
6
|
+
* API is Ark's own — Root, Item, ItemTrigger, ItemContent, ItemIndicator. */
|
|
7
|
+
const Accordion = Accordion$1;
|
|
8
|
+
injectComponentStyle("accordion");
|
|
9
|
+
//#endregion
|
|
10
|
+
export { Accordion };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { HTMLAttributes } from "react";
|
|
2
|
+
//#region src/components/affix/index.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* A nail: the wrapped content travels with the page until it reaches its
|
|
5
|
+
* offset, then stays put while the page moves on. The semantics are
|
|
6
|
+
* plain `position: sticky` — pinning is relative to the nearest
|
|
7
|
+
* *scrolling* ancestor, so the element works inside a scrollable panel
|
|
8
|
+
* exactly as it does on the page itself, and a parent with
|
|
9
|
+
* `overflow: hidden` clips the pin. Both offsets may be given: the
|
|
10
|
+
* content then holds its place inside that band.
|
|
11
|
+
*/
|
|
12
|
+
export interface AffixProps extends HTMLAttributes<HTMLDivElement> {
|
|
13
|
+
/** Where the content pins when it reaches the top of the scrolling
|
|
14
|
+
* ancestor — the height of any fixed header it must clear. */
|
|
15
|
+
offsetTop?: string;
|
|
16
|
+
/** Where it pins from the bottom instead, for footers and action bars. */
|
|
17
|
+
offsetBottom?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function Affix({ offsetTop, offsetBottom, ...rest }: AffixProps): import("react").JSX.Element;
|
|
20
|
+
//#endregion
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/affix/index.tsx
|
|
4
|
+
function Affix({ offsetTop = "0px", offsetBottom = "0px", ...rest }) {
|
|
5
|
+
injectComponentStyle("affix");
|
|
6
|
+
return /* @__PURE__ */ jsx("div", {
|
|
7
|
+
...rest,
|
|
8
|
+
style: {
|
|
9
|
+
...rest.style,
|
|
10
|
+
top: offsetTop,
|
|
11
|
+
bottom: offsetBottom
|
|
12
|
+
},
|
|
13
|
+
"data-scope": "affix",
|
|
14
|
+
"data-part": "root"
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { Affix };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as SourceDocumentUIPart, c as TextUIPart, d as UIMessagePart, i as ReasoningUIPart, l as ToolUIPart, n as DataUIPart, o as SourceUrlUIPart, r as FileUIPart, s as StepStartUIPart, t as Ai, u as UIMessage } from "../../index-DaAbbSz9.mjs";
|
|
2
|
+
export { Ai, type DataUIPart, type FileUIPart, type ReasoningUIPart, type SourceDocumentUIPart, type SourceUrlUIPart, type StepStartUIPart, type TextUIPart, type ToolUIPart, type UIMessage, type UIMessagePart };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Action } from "../ai-action/index.mjs";
|
|
2
|
+
import { AiMessage as Message } from "../ai-message/index.mjs";
|
|
3
|
+
import { AiPromptInput as PromptInput } from "../ai-prompt-input/index.mjs";
|
|
4
|
+
import { AiReasoning as Reasoning } from "../ai-reasoning/index.mjs";
|
|
5
|
+
import { t as Response } from "../../ai-response-jZy-0Tvv.mjs";
|
|
6
|
+
import { AiSource as Source, AiSources as Sources } from "../ai-source/index.mjs";
|
|
7
|
+
import { AiSuggestion as Suggestion } from "../ai-suggestion/index.mjs";
|
|
8
|
+
import { AiTool as Tool } from "../ai-tool/index.mjs";
|
|
9
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
10
|
+
import { jsx } from "react/jsx-runtime";
|
|
11
|
+
//#region src/components/ai/index.tsx
|
|
12
|
+
/** A conversation column: Root is the log, Message carries a role, and
|
|
13
|
+
* the speaking parts — Response, Reasoning, Tool, Sources — part the
|
|
14
|
+
* stream. The interactive folds are the shared Collapsible wearing a
|
|
15
|
+
* `data-ai` marker, so the machine work is never ours. Parts stay
|
|
16
|
+
* agnostic of any client; consumers map their message format (e.g. the
|
|
17
|
+
* `UIMessage` parts re-exported here) onto these primitives. */
|
|
18
|
+
function part(name, tag, extra = {}) {
|
|
19
|
+
const Tag = tag;
|
|
20
|
+
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx(Tag, {
|
|
21
|
+
...extra,
|
|
22
|
+
...rest,
|
|
23
|
+
"data-scope": "ai",
|
|
24
|
+
"data-part": name.toLowerCase(),
|
|
25
|
+
children
|
|
26
|
+
});
|
|
27
|
+
Component.displayName = "Ai" + name;
|
|
28
|
+
return Component;
|
|
29
|
+
}
|
|
30
|
+
/** The log itself: the column every stroke lands in, a landmark to
|
|
31
|
+
* screen readers. */
|
|
32
|
+
const Conversation = part("Conversation", "div", {
|
|
33
|
+
role: "log",
|
|
34
|
+
"aria-label": "Conversation"
|
|
35
|
+
});
|
|
36
|
+
/** The bubble's inner measure — content that belongs to neither side
|
|
37
|
+
* specifically. */
|
|
38
|
+
const MessageContent = part("Content", "div");
|
|
39
|
+
/** The quiet row under a message — copy, retry, feedback. */
|
|
40
|
+
const Actions = part("Actions", "div");
|
|
41
|
+
/** The while-it-works whisper for the in-flight turns. */
|
|
42
|
+
const Loader = part("Loader", "span", {
|
|
43
|
+
role: "status",
|
|
44
|
+
"aria-label": "Loading"
|
|
45
|
+
});
|
|
46
|
+
/** The whole family under one handle — `Ai.Conversation`,
|
|
47
|
+
* `Ai.Message`, and the rest, exactly as before the split. */
|
|
48
|
+
const Ai = Object.assign(Conversation, {
|
|
49
|
+
Conversation,
|
|
50
|
+
MessageContent,
|
|
51
|
+
Actions,
|
|
52
|
+
Loader,
|
|
53
|
+
Message,
|
|
54
|
+
Response,
|
|
55
|
+
Reasoning,
|
|
56
|
+
Tool,
|
|
57
|
+
Sources,
|
|
58
|
+
Source,
|
|
59
|
+
Action,
|
|
60
|
+
Suggestion,
|
|
61
|
+
PromptInput
|
|
62
|
+
});
|
|
63
|
+
injectComponentStyle("ai");
|
|
64
|
+
//#endregion
|
|
65
|
+
export { Ai };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ButtonHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
//#region src/components/ai-action/index.d.ts
|
|
3
|
+
/** A quiet icon button — copy, retry, thumbs. The label names it to
|
|
4
|
+
* assistive tech and as the hover title. The control itself is the
|
|
5
|
+
* shared Button in its ghost register. */
|
|
6
|
+
export interface ActionProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
7
|
+
/** What the button does, spoken to assistive tech and shown as the
|
|
8
|
+
* hover title — copy, retry, thumbs. */
|
|
9
|
+
label: string;
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export declare function Action({ label, children, ...rest }: ActionProps): import("react").JSX.Element;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { Action as AiAction };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Button } from "../button/index.mjs";
|
|
2
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/ai-action/index.tsx
|
|
5
|
+
function Action({ label, children, ...rest }) {
|
|
6
|
+
injectComponentStyle("ai");
|
|
7
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
8
|
+
variant: "ghost",
|
|
9
|
+
size: "sm",
|
|
10
|
+
square: true,
|
|
11
|
+
"aria-label": label,
|
|
12
|
+
title: label,
|
|
13
|
+
...rest,
|
|
14
|
+
children
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { Action, Action as AiAction };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { HTMLAttributes } from "react";
|
|
2
|
+
//#region src/components/ai-attachments/index.d.ts
|
|
3
|
+
/** One file riding the prompt: its glyph by extension, its name and
|
|
4
|
+
* human size, and a quiet way to take it back off. Uploading reads as
|
|
5
|
+
* a dashed ghost, error as danger ink. */
|
|
6
|
+
export interface AttachmentProps extends HTMLAttributes<HTMLSpanElement> {
|
|
7
|
+
/** The file's name — it picks the glyph by extension. */
|
|
8
|
+
name: string;
|
|
9
|
+
/** The file's size in bytes, when known — rendered human. */
|
|
10
|
+
size?: number;
|
|
11
|
+
/** The upload's state on the wire. */
|
|
12
|
+
status?: "uploading" | "ready" | "error";
|
|
13
|
+
onRemove?: () => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function Attachment({ name, size, status, onRemove, ...rest }: AttachmentProps): import("react").JSX.Element;
|
|
16
|
+
/** The row the files ride in — a wrapping line of chips. */
|
|
17
|
+
export declare function Attachments({ children, ...rest }: HTMLAttributes<HTMLSpanElement>): import("react").JSX.Element;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { Attachment as AiAttachment, Attachments as AiAttachments };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/ai-attachments/index.tsx
|
|
4
|
+
const imageGlyph = /* @__PURE__ */ jsxs("svg", {
|
|
5
|
+
viewBox: "0 0 16 16",
|
|
6
|
+
"aria-hidden": "true",
|
|
7
|
+
fill: "none",
|
|
8
|
+
stroke: "currentColor",
|
|
9
|
+
strokeWidth: 1.5,
|
|
10
|
+
strokeLinecap: "square",
|
|
11
|
+
children: [
|
|
12
|
+
/* @__PURE__ */ jsx("rect", {
|
|
13
|
+
x: 2.5,
|
|
14
|
+
y: 3.5,
|
|
15
|
+
width: 11,
|
|
16
|
+
height: 9
|
|
17
|
+
}),
|
|
18
|
+
/* @__PURE__ */ jsx("path", { d: "M2.5 10.5 6 7l3 3 2-1.5 2.5 2" }),
|
|
19
|
+
/* @__PURE__ */ jsx("circle", {
|
|
20
|
+
cx: 6,
|
|
21
|
+
cy: 6,
|
|
22
|
+
r: .75,
|
|
23
|
+
fill: "currentColor",
|
|
24
|
+
stroke: "none"
|
|
25
|
+
})
|
|
26
|
+
]
|
|
27
|
+
});
|
|
28
|
+
const fileGlyph = /* @__PURE__ */ jsxs("svg", {
|
|
29
|
+
viewBox: "0 0 16 16",
|
|
30
|
+
"aria-hidden": "true",
|
|
31
|
+
fill: "none",
|
|
32
|
+
stroke: "currentColor",
|
|
33
|
+
strokeWidth: 1.5,
|
|
34
|
+
strokeLinecap: "square",
|
|
35
|
+
children: [/* @__PURE__ */ jsx("path", { d: "M4 2.5h5l3 3V13.5H4z" }), /* @__PURE__ */ jsx("path", { d: "M9 2.5v3h3" })]
|
|
36
|
+
});
|
|
37
|
+
const removeGlyph = /* @__PURE__ */ jsx("svg", {
|
|
38
|
+
viewBox: "0 0 16 16",
|
|
39
|
+
width: 12,
|
|
40
|
+
height: 12,
|
|
41
|
+
"aria-hidden": "true",
|
|
42
|
+
fill: "none",
|
|
43
|
+
stroke: "currentColor",
|
|
44
|
+
strokeWidth: 1.5,
|
|
45
|
+
strokeLinecap: "square",
|
|
46
|
+
children: /* @__PURE__ */ jsx("path", { d: "M4 4l8 8M12 4l-8 8" })
|
|
47
|
+
});
|
|
48
|
+
const IMAGE_EXTS = [
|
|
49
|
+
"png",
|
|
50
|
+
"jpg",
|
|
51
|
+
"jpeg",
|
|
52
|
+
"gif",
|
|
53
|
+
"webp",
|
|
54
|
+
"svg",
|
|
55
|
+
"avif",
|
|
56
|
+
"bmp",
|
|
57
|
+
"ico"
|
|
58
|
+
];
|
|
59
|
+
const isImage = (name) => IMAGE_EXTS.includes(name.split(".").pop()?.toLowerCase() ?? "");
|
|
60
|
+
const humanSize = (bytes) => {
|
|
61
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
62
|
+
const units = [
|
|
63
|
+
"KB",
|
|
64
|
+
"MB",
|
|
65
|
+
"GB"
|
|
66
|
+
];
|
|
67
|
+
let value = bytes;
|
|
68
|
+
let unit = -1;
|
|
69
|
+
do {
|
|
70
|
+
value /= 1024;
|
|
71
|
+
unit += 1;
|
|
72
|
+
} while (value >= 1024 && unit < units.length - 1);
|
|
73
|
+
return `${value.toFixed(1)} ${units[unit]}`;
|
|
74
|
+
};
|
|
75
|
+
function Attachment({ name, size, status = "ready", onRemove, ...rest }) {
|
|
76
|
+
injectComponentStyle("ai");
|
|
77
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
78
|
+
...rest,
|
|
79
|
+
"data-scope": "ai",
|
|
80
|
+
"data-part": "attachment",
|
|
81
|
+
"data-status": status,
|
|
82
|
+
children: [
|
|
83
|
+
isImage(name) ? imageGlyph : fileGlyph,
|
|
84
|
+
/* @__PURE__ */ jsx("span", { children: name }),
|
|
85
|
+
size !== void 0 ? /* @__PURE__ */ jsx("span", { children: humanSize(size) }) : null,
|
|
86
|
+
/* @__PURE__ */ jsx("button", {
|
|
87
|
+
type: "button",
|
|
88
|
+
"data-remove": "",
|
|
89
|
+
"aria-label": `Remove ${name}`,
|
|
90
|
+
onClick: () => onRemove?.(),
|
|
91
|
+
children: removeGlyph
|
|
92
|
+
})
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/** The row the files ride in — a wrapping line of chips. */
|
|
97
|
+
function Attachments({ children, ...rest }) {
|
|
98
|
+
return /* @__PURE__ */ jsx("span", {
|
|
99
|
+
...rest,
|
|
100
|
+
"data-scope": "ai",
|
|
101
|
+
"data-part": "attachments",
|
|
102
|
+
children
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { Attachment as AiAttachment, Attachment, Attachments as AiAttachments, Attachments };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
//#region src/components/ai-message/index.d.ts
|
|
3
|
+
/** Whose stroke this is — the user's words sit in a recessed bubble,
|
|
4
|
+
* the assistant speaks flat on the paper. */
|
|
5
|
+
export interface MessageProps extends HTMLAttributes<HTMLElement> {
|
|
6
|
+
role?: "user" | "assistant" | "system";
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function Message({ role, children, ...rest }: MessageProps): import("react").JSX.Element;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { Message as AiMessage };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/ai-message/index.tsx
|
|
4
|
+
function Message({ role = "assistant", children, ...rest }) {
|
|
5
|
+
injectComponentStyle("ai");
|
|
6
|
+
return /* @__PURE__ */ jsx("article", {
|
|
7
|
+
...rest,
|
|
8
|
+
"data-scope": "ai",
|
|
9
|
+
"data-part": "message",
|
|
10
|
+
"data-role": role,
|
|
11
|
+
children
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { Message as AiMessage, Message };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { t as MentionEntry } from "../../index-Uefyw7Im.mjs";
|
|
2
|
+
import { HTMLAttributes, ReactNode } from "react";
|
|
3
|
+
//#region src/components/ai-prompt-input/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The prompt vessel: the shared field textarea — self-growing on the
|
|
6
|
+
* machine's autoresize — with the submit seal riding its last line.
|
|
7
|
+
* Around the body, props answer the composer's anatomy: `header` for
|
|
8
|
+
* attachments riding above, `leading` for the tools at the text's
|
|
9
|
+
* left, `trailing` for the seal itself, `footer` for the tools beneath,
|
|
10
|
+
* and `footerEnd` for the controls that close the footer row — the
|
|
11
|
+
* seal falls there by default, so a model picker dropped in rides the
|
|
12
|
+
* send's shoulder. Controlled — bind `value` and take the text on
|
|
13
|
+
* `submit`. Enter sends; Shift+Enter breaks the line. While `busy`
|
|
14
|
+
* the seal becomes a stop seal and Enter holds its breath.
|
|
15
|
+
*/
|
|
16
|
+
export interface PromptInputProps extends Omit<HTMLAttributes<HTMLFormElement>, "onSubmit"> {
|
|
17
|
+
/** The draft in the vessel — bind `value`; it clears itself on a
|
|
18
|
+
* successful submit. */
|
|
19
|
+
value: string;
|
|
20
|
+
onValueChange?: (value: string) => void;
|
|
21
|
+
onSubmit?: (value: string) => void;
|
|
22
|
+
onStop?: () => void;
|
|
23
|
+
/** The quiet invitation before the reader types. */
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
/** Still the words on the canvas, but the submit seal does nothing
|
|
26
|
+
* and Enter stays a line break. */
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
/** The machine is working — the seal becomes a stop seal and Enter
|
|
29
|
+
* holds its breath. */
|
|
30
|
+
busy?: boolean;
|
|
31
|
+
/** Mention candidates for the field: pass the roster and the summon
|
|
32
|
+
* character (`@` unless told otherwise) and the vessel rides the
|
|
33
|
+
* textarea. While candidates are up, Enter inserts and the send
|
|
34
|
+
* waits. */
|
|
35
|
+
mentions?: {
|
|
36
|
+
items: MentionEntry[];
|
|
37
|
+
trigger?: string;
|
|
38
|
+
};
|
|
39
|
+
header?: ReactNode;
|
|
40
|
+
leading?: ReactNode;
|
|
41
|
+
trailing?: ReactNode;
|
|
42
|
+
footer?: ReactNode;
|
|
43
|
+
footerEnd?: ReactNode;
|
|
44
|
+
}
|
|
45
|
+
export declare function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder, disabled, busy, mentions, header, leading, trailing, footer, footerEnd, ...rest }: PromptInputProps): import("react").JSX.Element;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { PromptInput as AiPromptInput };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { Button } from "../button/index.mjs";
|
|
2
|
+
import { Field } from "../field/index.mjs";
|
|
3
|
+
import { n as MentionsVessel, r as useMentions } from "../../mentions-DMIBCBOd.mjs";
|
|
4
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { useRef } from "react";
|
|
7
|
+
//#region src/components/ai-prompt-input/index.tsx
|
|
8
|
+
const arrowUpGlyph = /* @__PURE__ */ jsx("svg", {
|
|
9
|
+
viewBox: "0 0 16 16",
|
|
10
|
+
width: 14,
|
|
11
|
+
height: 14,
|
|
12
|
+
"aria-hidden": "true",
|
|
13
|
+
fill: "none",
|
|
14
|
+
stroke: "currentColor",
|
|
15
|
+
strokeWidth: 1.5,
|
|
16
|
+
strokeLinecap: "square",
|
|
17
|
+
children: /* @__PURE__ */ jsx("path", { d: "M8 13V3M3.5 7.5 8 3l4.5 4.5" })
|
|
18
|
+
});
|
|
19
|
+
const stopGlyph = /* @__PURE__ */ jsx("svg", {
|
|
20
|
+
viewBox: "0 0 16 16",
|
|
21
|
+
width: 14,
|
|
22
|
+
height: 14,
|
|
23
|
+
"aria-hidden": "true",
|
|
24
|
+
children: /* @__PURE__ */ jsx("rect", {
|
|
25
|
+
x: 4.5,
|
|
26
|
+
y: 4.5,
|
|
27
|
+
width: 7,
|
|
28
|
+
height: 7,
|
|
29
|
+
fill: "currentColor"
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
/** An empty slot leaves no part in the anatomy — the bare vessel keeps
|
|
33
|
+
* its single-line posture. */
|
|
34
|
+
function row(part, content) {
|
|
35
|
+
if (content == null || Array.isArray(content) && content.length === 0) return null;
|
|
36
|
+
return /* @__PURE__ */ jsx("div", {
|
|
37
|
+
"data-scope": "ai",
|
|
38
|
+
"data-part": part,
|
|
39
|
+
children: content
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function PromptInput({ value, onValueChange, onSubmit, onStop, placeholder = "Send a message", disabled = false, busy = false, mentions, header, leading, trailing, footer, footerEnd, ...rest }) {
|
|
43
|
+
injectComponentStyle("ai");
|
|
44
|
+
const fieldRef = useRef(null);
|
|
45
|
+
const mentionState = useMentions(() => ({
|
|
46
|
+
items: mentions?.items ?? [],
|
|
47
|
+
trigger: mentions?.trigger
|
|
48
|
+
}), () => fieldRef.current, {
|
|
49
|
+
getText: () => fieldRef.current?.value ?? value,
|
|
50
|
+
setText: (next) => onValueChange?.(next)
|
|
51
|
+
});
|
|
52
|
+
const mentionsActive = mentions != null;
|
|
53
|
+
const submit = () => {
|
|
54
|
+
const text = value.trim();
|
|
55
|
+
if (!text || disabled || busy) return;
|
|
56
|
+
onSubmit?.(text);
|
|
57
|
+
onValueChange?.("");
|
|
58
|
+
};
|
|
59
|
+
const seal = busy ? /* @__PURE__ */ jsx(Button, {
|
|
60
|
+
variant: "solid",
|
|
61
|
+
size: "sm",
|
|
62
|
+
square: true,
|
|
63
|
+
type: "button",
|
|
64
|
+
"aria-label": "Stop",
|
|
65
|
+
disabled,
|
|
66
|
+
onClick: () => onStop?.(),
|
|
67
|
+
children: stopGlyph
|
|
68
|
+
}) : /* @__PURE__ */ jsx(Button, {
|
|
69
|
+
variant: "solid",
|
|
70
|
+
size: "sm",
|
|
71
|
+
square: true,
|
|
72
|
+
type: "submit",
|
|
73
|
+
"aria-label": "Send",
|
|
74
|
+
disabled: disabled || !value.trim(),
|
|
75
|
+
children: arrowUpGlyph
|
|
76
|
+
});
|
|
77
|
+
const hasFooter = footer != null && (!Array.isArray(footer) || footer.length > 0);
|
|
78
|
+
return /* @__PURE__ */ jsxs("form", {
|
|
79
|
+
...rest,
|
|
80
|
+
"data-scope": "ai",
|
|
81
|
+
"data-part": "prompt",
|
|
82
|
+
onSubmit: (event) => {
|
|
83
|
+
event.preventDefault();
|
|
84
|
+
submit();
|
|
85
|
+
},
|
|
86
|
+
children: [
|
|
87
|
+
row("prompt-header", header),
|
|
88
|
+
/* @__PURE__ */ jsxs("div", {
|
|
89
|
+
"data-scope": "ai",
|
|
90
|
+
"data-part": "prompt-main",
|
|
91
|
+
children: [
|
|
92
|
+
row("prompt-leading", leading),
|
|
93
|
+
/* @__PURE__ */ jsx(Field.Root, { children: /* @__PURE__ */ jsx(Field.Textarea, {
|
|
94
|
+
ref: fieldRef,
|
|
95
|
+
autoresize: true,
|
|
96
|
+
rows: 1,
|
|
97
|
+
value,
|
|
98
|
+
placeholder,
|
|
99
|
+
disabled,
|
|
100
|
+
onChange: (event) => {
|
|
101
|
+
onValueChange?.(event.target.value);
|
|
102
|
+
mentionState.onInput();
|
|
103
|
+
},
|
|
104
|
+
onKeyDown: (event) => {
|
|
105
|
+
if (mentionState.onKeydown(event)) return;
|
|
106
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
submit();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}) }),
|
|
112
|
+
mentionsActive ? /* @__PURE__ */ jsx(MentionsVessel, {
|
|
113
|
+
open: mentionState.open,
|
|
114
|
+
matches: mentionState.matches,
|
|
115
|
+
active: mentionState.active,
|
|
116
|
+
anchor: fieldRef.current,
|
|
117
|
+
onInsert: mentionState.insert,
|
|
118
|
+
onActiveChange: mentionState.setActive,
|
|
119
|
+
onOpenChange: (open) => {
|
|
120
|
+
if (!open) mentionState.close();
|
|
121
|
+
}
|
|
122
|
+
}) : null,
|
|
123
|
+
row("prompt-trailing", hasFooter ? trailing : trailing ?? seal)
|
|
124
|
+
]
|
|
125
|
+
}),
|
|
126
|
+
hasFooter ? /* @__PURE__ */ jsxs("div", {
|
|
127
|
+
"data-scope": "ai",
|
|
128
|
+
"data-part": "prompt-footer",
|
|
129
|
+
children: [footer, row("prompt-end", footerEnd == null ? seal : /* @__PURE__ */ jsxs(Fragment, { children: [footerEnd, seal] }))]
|
|
130
|
+
}) : null
|
|
131
|
+
]
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { PromptInput as AiPromptInput, PromptInput };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
//#region src/components/ai-reasoning/index.d.ts
|
|
3
|
+
/** The model's thought, folded by the shared collapsible in its quiet
|
|
4
|
+
* register: bare ink for a trigger, the thought on one hairline. */
|
|
5
|
+
export interface ReasoningProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/** The trigger's words — the fold arrives open under them. */
|
|
7
|
+
label?: string;
|
|
8
|
+
defaultOpen?: boolean;
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export declare function Reasoning({ label, children, ...rest }: ReasoningProps): import("react").JSX.Element;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { Reasoning as AiReasoning };
|