@tangle-network/ui 11.11.8 → 11.13.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/CHANGELOG.md +24 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/auth/auth.d.ts +53 -0
- package/dist/{auth-DOETfnd9.js → auth/auth.js} +7 -37
- package/dist/auth/login-layout.d.ts +20 -0
- package/dist/auth/login-layout.js +36 -0
- package/dist/auth.d.ts +2 -1
- package/dist/auth.js +2 -1
- package/dist/chat/agent-timeline.d.ts +83 -0
- package/dist/chat/agent-timeline.js +236 -0
- package/dist/chat/chat-container.d.ts +51 -0
- package/dist/chat/chat-container.js +309 -0
- package/dist/chat/chat-message.d.ts +22 -0
- package/dist/chat/chat-message.js +38 -0
- package/dist/chat/message-list.d.ts +32 -0
- package/dist/chat/message-list.js +37 -0
- package/dist/chat/thinking-indicator.d.ts +6 -0
- package/dist/chat/thinking-indicator.js +38 -0
- package/dist/chat/user-message.d.ts +21 -0
- package/dist/chat/user-message.js +42 -0
- package/dist/chat.d.ts +6 -1
- package/dist/chat.js +6 -1
- package/dist/editor/document-editor-pane.d.ts +37 -0
- package/dist/editor/document-editor-pane.js +199 -0
- package/dist/editor/editor-lazy.js +37 -0
- package/dist/editor/editor-loading.js +21 -0
- package/dist/editor/editor-peers.d.ts +6 -0
- package/dist/editor/editor-peers.js +155 -0
- package/dist/{document-editor-pane-DHM8DDhb.d.ts → editor/editor-provider.d.ts} +10 -47
- package/dist/editor/editor-provider.js +253 -0
- package/dist/editor/editor-toolbar.d.ts +11 -0
- package/dist/editor/editor-toolbar.js +106 -0
- package/dist/editor/markdown-conversion.js +23 -0
- package/dist/editor/markdown-document-editor.js +103 -0
- package/dist/editor/tiptap-editor.d.ts +45 -0
- package/dist/editor/tiptap-editor.js +271 -0
- package/dist/editor/use-editor.d.ts +67 -0
- package/dist/editor/use-editor.js +158 -0
- package/dist/editor.d.ts +6 -119
- package/dist/editor.js +5 -1
- package/dist/files/file-artifact-pane.d.ts +47 -0
- package/dist/files/file-artifact-pane.js +114 -0
- package/dist/files/file-format.d.ts +51 -0
- package/dist/{file-format-BgXbr-Ib.js → files/file-format.js} +1 -1
- package/dist/files/file-preview.d.ts +27 -0
- package/dist/files/file-preview.js +359 -0
- package/dist/files/file-tabs.d.ts +19 -0
- package/dist/files/file-tabs.js +48 -0
- package/dist/files/file-tree.d.ts +31 -0
- package/dist/files/file-tree.js +135 -0
- package/dist/files/rich-file-tree.d.ts +62 -0
- package/dist/files/rich-file-tree.js +122 -0
- package/dist/files.d.ts +6 -1
- package/dist/files.js +6 -2
- package/dist/hooks/use-auth.d.ts +40 -0
- package/dist/hooks/use-auth.js +91 -0
- package/dist/hooks/use-auto-scroll.d.ts +11 -0
- package/dist/hooks/use-auto-scroll.js +48 -0
- package/dist/hooks/use-dropdown-menu.d.ts +12 -0
- package/dist/hooks/use-dropdown-menu.js +31 -0
- package/dist/hooks/use-live-time.d.ts +7 -0
- package/dist/hooks/use-live-time.js +22 -0
- package/dist/hooks/use-realtime-session.d.ts +32 -0
- package/dist/hooks/use-realtime-session.js +235 -0
- package/dist/hooks/use-run-collapse-state.d.ts +13 -0
- package/dist/hooks/use-run-collapse-state.js +24 -0
- package/dist/hooks/use-run-groups.d.ts +11 -0
- package/dist/hooks/use-run-groups.js +85 -0
- package/dist/hooks/use-sdk-session.d.ts +59 -0
- package/dist/hooks/use-sdk-session.js +322 -0
- package/dist/hooks/use-sse-stream.d.ts +124 -0
- package/dist/hooks/use-sse-stream.js +229 -0
- package/dist/hooks/use-tool-call-stream.d.ts +23 -0
- package/dist/hooks/use-tool-call-stream.js +75 -0
- package/dist/hooks.d.ts +11 -49
- package/dist/hooks.js +10 -110
- package/dist/index.d.ts +99 -25
- package/dist/index.js +86 -36
- package/dist/lib/focus.d.ts +55 -0
- package/dist/{focus-BcE_SHqz.js → lib/focus.js} +1 -1
- package/dist/lib/utils.d.ts +4 -0
- package/dist/{utils-C_uf36nf.js → lib/utils.js} +1 -1
- package/dist/{code-block-B9miUPht.d.ts → markdown/code-block.d.ts} +5 -6
- package/dist/{code-block-B36KVUSN.js → markdown/code-block.js} +22 -47
- package/dist/{markdown-C0atSabr.d.ts → markdown/markdown.d.ts} +4 -5
- package/dist/{markdown-Db08KAYF.js → markdown/markdown.js} +3 -3
- package/dist/markdown.d.ts +2 -2
- package/dist/markdown.js +2 -2
- package/dist/{openui-artifact-renderer-fkBQaoLO.d.ts → openui/openui-artifact-renderer.d.ts} +20 -21
- package/dist/{openui-artifact-renderer-DG_i2lOR.js → openui/openui-artifact-renderer.js} +9 -7
- package/dist/{schema-BpW9rSSG.js → openui/schema-compiled.js} +2 -354
- package/dist/{schema-DAstk-J4.d.ts → openui/schema-data.d.ts} +3 -24
- package/dist/openui/schema-data.js +206 -0
- package/dist/openui-schema.d.ts +22 -3
- package/dist/openui-schema.js +138 -1
- package/dist/openui.d.ts +3 -2
- package/dist/openui.js +3 -2
- package/dist/{artifact-pane-BL_DFWNl.d.ts → primitives/artifact-pane.d.ts} +3 -4
- package/dist/{artifact-pane-DMXT9a8U.js → primitives/artifact-pane.js} +2 -2
- package/dist/primitives/avatar.d.ts +8 -0
- package/dist/primitives/avatar.js +25 -0
- package/dist/primitives/badge.d.ts +22 -0
- package/dist/primitives/badge.js +47 -0
- package/dist/{button-yoIv77e2.d.ts → primitives/button.d.ts} +2 -2
- package/dist/primitives/button.js +113 -0
- package/dist/primitives/card.d.ts +18 -0
- package/dist/primitives/card.js +52 -0
- package/dist/primitives/code-block.d.ts +6 -0
- package/dist/primitives/code-block.js +13 -0
- package/dist/primitives/dialog.d.ts +23 -0
- package/dist/primitives/dialog.js +59 -0
- package/dist/primitives/drop-zone.d.ts +23 -0
- package/dist/primitives/drop-zone.js +104 -0
- package/dist/primitives/dropdown-menu.d.ts +29 -0
- package/dist/{dropdown-menu-BpcLa5vF.js → primitives/dropdown-menu.js} +2 -23
- package/dist/primitives/empty-state.d.ts +11 -0
- package/dist/primitives/empty-state.js +32 -0
- package/dist/primitives/heading.d.ts +23 -0
- package/dist/primitives/heading.js +38 -0
- package/dist/primitives/input.d.ts +23 -0
- package/dist/primitives/input.js +110 -0
- package/dist/primitives/label.d.ts +6 -0
- package/dist/primitives/label.js +16 -0
- package/dist/primitives/metric-strip.d.ts +48 -0
- package/dist/primitives/metric-strip.js +52 -0
- package/dist/primitives/page-header.d.ts +25 -0
- package/dist/primitives/page-header.js +47 -0
- package/dist/primitives/page-shell.d.ts +14 -0
- package/dist/primitives/page-shell.js +17 -0
- package/dist/primitives/progress.d.ts +9 -0
- package/dist/primitives/progress.js +29 -0
- package/dist/primitives/segmented-control.d.ts +40 -0
- package/dist/primitives/segmented-control.js +57 -0
- package/dist/primitives/select.d.ts +15 -0
- package/dist/primitives/select.js +74 -0
- package/dist/primitives/sidebar-drop-zone.d.ts +21 -0
- package/dist/primitives/sidebar-drop-zone.js +88 -0
- package/dist/primitives/skeleton.d.ts +10 -0
- package/dist/primitives/skeleton.js +50 -0
- package/dist/primitives/stat-card.d.ts +16 -0
- package/dist/primitives/stat-card.js +60 -0
- package/dist/primitives/status-pill.d.ts +44 -0
- package/dist/primitives/status-pill.js +119 -0
- package/dist/primitives/switch.d.ts +6 -0
- package/dist/primitives/switch.js +16 -0
- package/dist/primitives/table.d.ts +22 -0
- package/dist/primitives/table.js +63 -0
- package/dist/primitives/tabs.d.ts +13 -0
- package/dist/{tabs-BVHR6NkO.js → primitives/tabs.js} +3 -3
- package/dist/primitives/terminal-display.d.ts +25 -0
- package/dist/primitives/terminal-display.js +109 -0
- package/dist/primitives/text-shimmer.d.ts +16 -0
- package/dist/{text-shimmer-BUUo6I-g.js → primitives/text-shimmer.js} +2 -2
- package/dist/primitives/theme-toggle.d.ts +11 -0
- package/dist/primitives/theme-toggle.js +154 -0
- package/dist/primitives/toast.d.ts +29 -0
- package/dist/primitives/toast.js +142 -0
- package/dist/primitives/toolbar.d.ts +55 -0
- package/dist/primitives/toolbar.js +37 -0
- package/dist/primitives/upload-progress.d.ts +23 -0
- package/dist/primitives/upload-progress.js +72 -0
- package/dist/primitives.d.ts +35 -5
- package/dist/primitives.js +35 -9
- package/dist/{index-COgqsFAQ.d.ts → redaction/redacted-document.d.ts} +6 -7
- package/dist/{redaction-CGGB2ENG.js → redaction/redacted-document.js} +2 -2
- package/dist/redaction.d.ts +1 -1
- package/dist/redaction.js +1 -1
- package/dist/run/expandable-content.js +41 -0
- package/dist/run/expanded-tool-detail.d.ts +12 -0
- package/dist/run/expanded-tool-detail.js +163 -0
- package/dist/run/inline-thinking-item.d.ts +11 -0
- package/dist/run/inline-thinking-item.js +60 -0
- package/dist/run/inline-tool-item.d.ts +25 -0
- package/dist/run/inline-tool-item.js +63 -0
- package/dist/run/run-group.d.ts +26 -0
- package/dist/{run-group-BWGeesgs.js → run/run-group.js} +9 -60
- package/dist/run/run-item-primitives.d.ts +5 -0
- package/dist/{run-ZsIKPA6J.js → run/run-item-primitives.js} +2 -2
- package/dist/run/run-row-shell.d.ts +53 -0
- package/dist/run/run-row-shell.js +114 -0
- package/dist/{tool-call-feed-BeB1_4pX.d.ts → run/tool-call-feed.d.ts} +7 -12
- package/dist/{tool-call-feed-BpmMLpPX.js → run/tool-call-feed.js} +4 -4
- package/dist/run/tool-call-step.d.ts +5 -0
- package/dist/run/tool-call-step.js +82 -0
- package/dist/run.d.ts +8 -2
- package/dist/run.js +7 -4
- package/dist/sdk-hooks.d.ts +8 -1
- package/dist/sdk-hooks.js +8 -2
- package/dist/stores/active-sessions-store.d.ts +83 -0
- package/dist/{active-sessions-store-Gt1R0rFG.js → stores/active-sessions-store.js} +1 -1
- package/dist/stores/chat-store.d.ts +14 -0
- package/dist/stores/chat-store.js +33 -0
- package/dist/stores.d.ts +3 -16
- package/dist/stores.js +2 -33
- package/dist/tool-previews/command-preview.d.ts +11 -0
- package/dist/tool-previews/command-preview.js +91 -0
- package/dist/tool-previews/diff-preview.d.ts +7 -0
- package/dist/tool-previews/diff-preview.js +76 -0
- package/dist/tool-previews/glob-results-preview.d.ts +7 -0
- package/dist/tool-previews/glob-results-preview.js +53 -0
- package/dist/tool-previews/grep-results-preview.d.ts +7 -0
- package/dist/tool-previews/grep-results-preview.js +99 -0
- package/dist/tool-previews/preview-primitives.js +58 -0
- package/dist/tool-previews/question-preview.d.ts +7 -0
- package/dist/tool-previews/question-preview.js +63 -0
- package/dist/tool-previews/web-search-preview.d.ts +7 -0
- package/dist/tool-previews/web-search-preview.js +78 -0
- package/dist/tool-previews/write-file-preview.d.ts +11 -0
- package/dist/tool-previews/write-file-preview.js +52 -0
- package/dist/tool-previews.d.ts +7 -1
- package/dist/tool-previews.js +7 -1
- package/dist/{branding-26d5ARIr.d.ts → types/branding.d.ts} +2 -3
- package/dist/{message-vhUI0c5G.d.ts → types/message.d.ts} +2 -3
- package/dist/{parts-5mhy9yJ3.d.ts → types/parts.d.ts} +8 -9
- package/dist/{run-OyWmIDqu.d.ts → types/run.d.ts} +9 -10
- package/dist/{tool-display-DgmL5rIU.d.ts → types/tool-display.d.ts} +5 -6
- package/dist/types.d.ts +5 -5
- package/dist/utils/copy-text.d.ts +7 -0
- package/dist/{utils-Bl_CZ0Qp.js → utils/copy-text.js} +1 -11
- package/dist/utils/format.d.ts +22 -0
- package/dist/{format-DfcLWqMa.js → utils/format.js} +1 -1
- package/dist/utils/time-ago.d.ts +3 -0
- package/dist/utils/time-ago.js +11 -0
- package/dist/utils/tool-display.d.ts +16 -0
- package/dist/{tool-display-BAuAVa43.js → utils/tool-display.js} +1 -1
- package/dist/utils.d.ts +6 -1
- package/dist/utils.js +6 -5
- package/package.json +2 -2
- package/src/editor/document-editor-pane.tsx +4 -1
- package/src/files/file-artifact-pane.test.tsx +23 -0
- package/src/files/file-artifact-pane.tsx +3 -0
- package/src/files/rich-file-tree.stories.tsx +1 -1
- package/src/files/rich-file-tree.tsx +12 -9
- package/src/markdown/code-block.test.tsx +46 -2
- package/src/markdown/code-block.tsx +23 -60
- package/src/markdown/markdown.test.tsx +3 -2
- package/src/primitives/button.stories.tsx +37 -1
- package/src/primitives/button.test.tsx +230 -0
- package/src/primitives/button.tsx +62 -14
- package/src/primitives/card-anatomy.stories.tsx +51 -0
- package/src/primitives/card.test.tsx +71 -0
- package/src/primitives/card.tsx +25 -13
- package/src/primitives/heading.stories.tsx +35 -0
- package/src/primitives/heading.test.tsx +56 -0
- package/src/primitives/heading.tsx +76 -0
- package/src/primitives/index.ts +8 -0
- package/src/primitives/input.stories.tsx +28 -0
- package/src/primitives/input.test.tsx +161 -0
- package/src/primitives/input.tsx +34 -28
- package/src/primitives/page-header.stories.tsx +51 -0
- package/src/primitives/page-header.test.tsx +48 -0
- package/src/primitives/page-header.tsx +35 -35
- package/src/primitives/page-shell.stories.tsx +89 -0
- package/src/primitives/page-shell.test.tsx +24 -0
- package/src/primitives/page-shell.tsx +26 -0
- package/src/primitives/table-wrapper.stories.tsx +54 -0
- package/src/primitives/table.test.tsx +72 -0
- package/src/primitives/table.tsx +33 -12
- package/src/primitives/theme-toggle.test.tsx +167 -0
- package/src/primitives/theme-toggle.tsx +111 -39
- package/dist/active-sessions-store-nl70ZnMC.d.ts +0 -84
- package/dist/button-C87nEe2R.js +0 -78
- package/dist/chat-DDvF2oGQ.js +0 -672
- package/dist/diff-preview-BcK3nRXb.js +0 -533
- package/dist/document-editor-pane-CsFbH2qo.js +0 -1279
- package/dist/files--Unn___t.js +0 -752
- package/dist/index-2UntyjBb.d.ts +0 -52
- package/dist/index-BgUHilZm.d.ts +0 -108
- package/dist/index-CPDET_s1.d.ts +0 -549
- package/dist/index-Cg6gYAqh.d.ts +0 -73
- package/dist/index-Cs7j8V7l.d.ts +0 -203
- package/dist/index-CyGSLGVF.d.ts +0 -234
- package/dist/index-DjKxO357.d.ts +0 -128
- package/dist/primitives-Bx59fT-U.js +0 -1239
- package/dist/table-Bss73DhB.js +0 -146
- package/dist/tool-call-step-DNebqhmX.js +0 -434
- package/dist/use-auto-scroll-C5Pjeqon.js +0 -153
- package/dist/use-sse-stream-DjqRuDft.js +0 -884
- package/dist/use-sse-stream-Dm6R5YWz.d.ts +0 -282
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { focusRing } from "../lib/focus.js";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
|
7
|
+
//#region src/primitives/switch.tsx
|
|
8
|
+
const Switch = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SwitchPrimitives.Root, {
|
|
9
|
+
className: cn("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-[background-color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", focusRing, className),
|
|
10
|
+
...props,
|
|
11
|
+
ref,
|
|
12
|
+
children: /* @__PURE__ */ jsx(SwitchPrimitives.Thumb, { className: cn("pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0") })
|
|
13
|
+
}));
|
|
14
|
+
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Switch };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/table.d.ts
|
|
3
|
+
export interface TableProps extends React.TableHTMLAttributes<HTMLTableElement> {
|
|
4
|
+
/** Keep the existing scroll wrapper by default; false returns only the native table. */
|
|
5
|
+
wrapper?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Attributes for the wrapper, not the table (ignored when wrapper is false).
|
|
8
|
+
* For an overflowing table, supply tabIndex and an accessible region name.
|
|
9
|
+
* No extra tab stop or unnamed landmark is imposed on every small table.
|
|
10
|
+
*/
|
|
11
|
+
wrapperProps?: Omit<React.HTMLAttributes<HTMLDivElement>, "children" | "dangerouslySetInnerHTML">;
|
|
12
|
+
}
|
|
13
|
+
declare const Table: React.ForwardRefExoticComponent<TableProps & React.RefAttributes<HTMLTableElement>>;
|
|
14
|
+
declare const TableHeader: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
|
|
15
|
+
declare const TableBody: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
|
|
16
|
+
declare const TableFooter: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableSectionElement> & React.RefAttributes<HTMLTableSectionElement>>;
|
|
17
|
+
declare const TableRow: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableRowElement> & React.RefAttributes<HTMLTableRowElement>>;
|
|
18
|
+
declare const TableHead: React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>;
|
|
19
|
+
declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & React.RefAttributes<HTMLTableCellElement>>;
|
|
20
|
+
declare const TableCaption: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLTableCaptionElement> & React.RefAttributes<HTMLTableCaptionElement>>;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/primitives/table.tsx
|
|
5
|
+
const Table = React.forwardRef(({ className, wrapper = true, wrapperProps, ...props }, ref) => {
|
|
6
|
+
const table = /* @__PURE__ */ jsx("table", {
|
|
7
|
+
ref,
|
|
8
|
+
className: cn("w-full caption-bottom text-sm", className),
|
|
9
|
+
...props
|
|
10
|
+
});
|
|
11
|
+
if (!wrapper) return table;
|
|
12
|
+
const { className: wrapperClassName, ...attributes } = wrapperProps ?? {};
|
|
13
|
+
return /* @__PURE__ */ jsx("div", {
|
|
14
|
+
...attributes,
|
|
15
|
+
className: cn("relative w-full overflow-auto", wrapperClassName),
|
|
16
|
+
children: table
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
Table.displayName = "Table";
|
|
20
|
+
const TableHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", {
|
|
21
|
+
ref,
|
|
22
|
+
className: cn("[&_tr]:border-b", className),
|
|
23
|
+
...props
|
|
24
|
+
}));
|
|
25
|
+
TableHeader.displayName = "TableHeader";
|
|
26
|
+
const TableBody = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", {
|
|
27
|
+
ref,
|
|
28
|
+
className: cn("[&_tr:last-child]:border-0", className),
|
|
29
|
+
...props
|
|
30
|
+
}));
|
|
31
|
+
TableBody.displayName = "TableBody";
|
|
32
|
+
const TableFooter = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tfoot", {
|
|
33
|
+
ref,
|
|
34
|
+
className: cn("border-t bg-card font-medium [&>tr]:last:border-b-0", className),
|
|
35
|
+
...props
|
|
36
|
+
}));
|
|
37
|
+
TableFooter.displayName = "TableFooter";
|
|
38
|
+
const TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tr", {
|
|
39
|
+
ref,
|
|
40
|
+
className: cn("border-border border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted/50", className),
|
|
41
|
+
...props
|
|
42
|
+
}));
|
|
43
|
+
TableRow.displayName = "TableRow";
|
|
44
|
+
const TableHead = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("th", {
|
|
45
|
+
ref,
|
|
46
|
+
className: cn("h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", className),
|
|
47
|
+
...props
|
|
48
|
+
}));
|
|
49
|
+
TableHead.displayName = "TableHead";
|
|
50
|
+
const TableCell = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("td", {
|
|
51
|
+
ref,
|
|
52
|
+
className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className),
|
|
53
|
+
...props
|
|
54
|
+
}));
|
|
55
|
+
TableCell.displayName = "TableCell";
|
|
56
|
+
const TableCaption = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("caption", {
|
|
57
|
+
ref,
|
|
58
|
+
className: cn("mt-4 text-muted-foreground text-sm", className),
|
|
59
|
+
...props
|
|
60
|
+
}));
|
|
61
|
+
TableCaption.displayName = "TableCaption";
|
|
62
|
+
//#endregion
|
|
63
|
+
export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
3
|
+
//#region src/primitives/tabs.d.ts
|
|
4
|
+
declare const Tabs: React.ForwardRefExoticComponent<TabsPrimitive.TabsProps & React.RefAttributes<HTMLDivElement>>;
|
|
5
|
+
declare const TabsList: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsListProps & React.RefAttributes<HTMLDivElement>, "ref"> & {
|
|
6
|
+
variant?: "default" | "pills" | "underline";
|
|
7
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
declare const TabsTrigger: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & {
|
|
9
|
+
variant?: "default" | "pills" | "underline";
|
|
10
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
11
|
+
declare const TabsContent: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { Tabs, TabsContent, TabsList, TabsTrigger };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { focusRing } from "../lib/focus.js";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
@@ -37,4 +37,4 @@ const TabsContent = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
37
37
|
}));
|
|
38
38
|
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
39
39
|
//#endregion
|
|
40
|
-
export {
|
|
40
|
+
export { Tabs, TabsContent, TabsList, TabsTrigger };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/terminal-display.d.ts
|
|
3
|
+
export interface TerminalDisplayProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
variant?: "default" | "sandbox";
|
|
5
|
+
title?: string;
|
|
6
|
+
showHeader?: boolean;
|
|
7
|
+
autoScroll?: boolean;
|
|
8
|
+
maxHeight?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const TerminalDisplay: React.ForwardRefExoticComponent<TerminalDisplayProps & React.RefAttributes<HTMLDivElement>>;
|
|
11
|
+
export interface TerminalLineProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
12
|
+
type?: "input" | "output" | "error" | "success" | "info" | "thinking" | "command" | "warning";
|
|
13
|
+
prompt?: string;
|
|
14
|
+
timestamp?: string;
|
|
15
|
+
}
|
|
16
|
+
declare const TerminalLine: React.ForwardRefExoticComponent<TerminalLineProps & React.RefAttributes<HTMLDivElement>>;
|
|
17
|
+
declare const TerminalCursor: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>;
|
|
18
|
+
export interface TerminalInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onSubmit"> {
|
|
19
|
+
onSubmit?: (value: string) => void;
|
|
20
|
+
/** Both values render the same field. */
|
|
21
|
+
variant?: "default" | "sandbox";
|
|
22
|
+
}
|
|
23
|
+
declare const TerminalInput: React.ForwardRefExoticComponent<TerminalInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { focusFieldWithin } from "../lib/focus.js";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/primitives/terminal-display.tsx
|
|
7
|
+
const TerminalDisplay = React.forwardRef(({ className, variant = "default", title = "Terminal", showHeader = true, autoScroll = true, maxHeight = "400px", children, ...props }, ref) => {
|
|
8
|
+
const containerRef = useRef(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (autoScroll && containerRef.current) containerRef.current.scrollTop = containerRef.current.scrollHeight;
|
|
11
|
+
}, [autoScroll]);
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
13
|
+
ref,
|
|
14
|
+
className: cn("overflow-hidden rounded-xl border bg-background font-mono text-sm", {
|
|
15
|
+
default: "border-border",
|
|
16
|
+
sandbox: "border-border shadow-[var(--shadow-accent)]"
|
|
17
|
+
}[variant], className),
|
|
18
|
+
...props,
|
|
19
|
+
children: [showHeader && /* @__PURE__ */ jsx("div", {
|
|
20
|
+
className: "flex items-center border-b border-border bg-card px-4 py-3",
|
|
21
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
22
|
+
className: "text-muted-foreground text-xs",
|
|
23
|
+
children: title
|
|
24
|
+
})
|
|
25
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
26
|
+
ref: containerRef,
|
|
27
|
+
className: "overflow-auto p-4",
|
|
28
|
+
style: { maxHeight },
|
|
29
|
+
children
|
|
30
|
+
})]
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
TerminalDisplay.displayName = "TerminalDisplay";
|
|
34
|
+
const TerminalLine = React.forwardRef(({ className, type = "output", prompt = "$", timestamp, children, ...props }, ref) => {
|
|
35
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
36
|
+
ref,
|
|
37
|
+
className: cn("flex items-start gap-2 py-0.5 leading-relaxed", {
|
|
38
|
+
input: "text-foreground",
|
|
39
|
+
output: "text-foreground",
|
|
40
|
+
error: "text-[var(--surface-danger-text)]",
|
|
41
|
+
success: "text-[var(--surface-success-text)]",
|
|
42
|
+
info: "text-[var(--surface-info-text)]",
|
|
43
|
+
thinking: "text-[var(--surface-warning-text)] animate-pulse",
|
|
44
|
+
command: "text-foreground",
|
|
45
|
+
warning: "text-[var(--surface-warning-text)]"
|
|
46
|
+
}[type], className),
|
|
47
|
+
...props,
|
|
48
|
+
children: [
|
|
49
|
+
(type === "input" || type === "command") && /* @__PURE__ */ jsx("span", {
|
|
50
|
+
className: "shrink-0 select-none text-[var(--surface-success-text)]",
|
|
51
|
+
children: prompt
|
|
52
|
+
}),
|
|
53
|
+
type === "thinking" && /* @__PURE__ */ jsx("span", {
|
|
54
|
+
className: "shrink-0 select-none",
|
|
55
|
+
children: "..."
|
|
56
|
+
}),
|
|
57
|
+
timestamp && /* @__PURE__ */ jsxs("span", {
|
|
58
|
+
className: "shrink-0 select-none text-[var(--text-dim)]",
|
|
59
|
+
children: [
|
|
60
|
+
"[",
|
|
61
|
+
timestamp,
|
|
62
|
+
"]"
|
|
63
|
+
]
|
|
64
|
+
}),
|
|
65
|
+
/* @__PURE__ */ jsx("span", {
|
|
66
|
+
className: "whitespace-pre-wrap break-all",
|
|
67
|
+
children
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
TerminalLine.displayName = "TerminalLine";
|
|
73
|
+
const TerminalCursor = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("span", {
|
|
74
|
+
ref,
|
|
75
|
+
className: cn("ml-0.5 inline-block h-4 w-2 animate-pulse bg-foreground", className),
|
|
76
|
+
...props
|
|
77
|
+
}));
|
|
78
|
+
TerminalCursor.displayName = "TerminalCursor";
|
|
79
|
+
const TerminalInput = React.forwardRef(({ className, onSubmit, variant: _variant, ...props }, ref) => {
|
|
80
|
+
const [value, setValue] = React.useState("");
|
|
81
|
+
const handleKeyDown = (e) => {
|
|
82
|
+
if (e.key === "Enter" && value.trim() && onSubmit) {
|
|
83
|
+
onSubmit(value.trim());
|
|
84
|
+
setValue("");
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
88
|
+
className: cn("flex items-center rounded-lg border bg-background px-4 py-2.5 font-mono text-sm", focusFieldWithin, className),
|
|
89
|
+
children: [
|
|
90
|
+
/* @__PURE__ */ jsx("span", {
|
|
91
|
+
className: "mr-2 select-none text-[var(--surface-success-text)]",
|
|
92
|
+
children: "$"
|
|
93
|
+
}),
|
|
94
|
+
/* @__PURE__ */ jsx("input", {
|
|
95
|
+
ref,
|
|
96
|
+
type: "text",
|
|
97
|
+
value,
|
|
98
|
+
onChange: (e) => setValue(e.target.value),
|
|
99
|
+
onKeyDown: handleKeyDown,
|
|
100
|
+
className: "flex-1 bg-transparent text-foreground outline-none placeholder:text-muted-foreground",
|
|
101
|
+
...props
|
|
102
|
+
}),
|
|
103
|
+
/* @__PURE__ */ jsx(TerminalCursor, {})
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
TerminalInput.displayName = "TerminalInput";
|
|
108
|
+
//#endregion
|
|
109
|
+
export { TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/primitives/text-shimmer.d.ts
|
|
3
|
+
export interface TextShimmerProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
/** One sweep across the text, in milliseconds. */
|
|
7
|
+
durationMs?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Inline text with a gradient-mask sweep — the in-flight signal for a run row
|
|
11
|
+
* label ("Thinking…", a tool verb while its call is running). Carries the
|
|
12
|
+
* styles it needs, so a consumer that only scans this package for Tailwind
|
|
13
|
+
* classes still gets the animation.
|
|
14
|
+
*/
|
|
15
|
+
export declare function TextShimmer({ children, className, durationMs }: TextShimmerProps): import("react").JSX.Element;
|
|
16
|
+
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
2
|
import { useEffect, useLayoutEffect } from "react";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
//#region src/primitives/text-shimmer.tsx
|
|
@@ -61,4 +61,4 @@ function TextShimmer({ children, className, durationMs = 1400 }) {
|
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
//#endregion
|
|
64
|
-
export { TextShimmer
|
|
64
|
+
export { TextShimmer };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/primitives/theme-toggle.d.ts
|
|
2
|
+
type Theme = "light" | "dark" | "system";
|
|
3
|
+
type Mode = Exclude<Theme, "system">;
|
|
4
|
+
declare function setTheme(next: Theme): void;
|
|
5
|
+
export declare function useTheme(): {
|
|
6
|
+
theme: Theme;
|
|
7
|
+
setTheme: typeof setTheme;
|
|
8
|
+
resolvedTheme: Mode;
|
|
9
|
+
};
|
|
10
|
+
export declare function ThemeToggle(): import("react").JSX.Element;
|
|
11
|
+
//#endregion
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { useEffect, useSyncExternalStore } from "react";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/primitives/theme-toggle.tsx
|
|
4
|
+
const preferenceEvent = "tangle:theme-preference";
|
|
5
|
+
const systemQuery = "(prefers-color-scheme: dark)";
|
|
6
|
+
const namedModes = [
|
|
7
|
+
{
|
|
8
|
+
dark: "aubergine",
|
|
9
|
+
light: "aubergine-light"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
dark: "arena",
|
|
13
|
+
light: "arena-light"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
dark: "tangle-dark",
|
|
17
|
+
light: "tangle-light"
|
|
18
|
+
}
|
|
19
|
+
];
|
|
20
|
+
let preference;
|
|
21
|
+
function isTheme(value) {
|
|
22
|
+
return value === "light" || value === "dark" || value === "system";
|
|
23
|
+
}
|
|
24
|
+
function getSystemTheme() {
|
|
25
|
+
if (typeof window === "undefined" || !window.matchMedia) return "dark";
|
|
26
|
+
return window.matchMedia(systemQuery).matches ? "dark" : "light";
|
|
27
|
+
}
|
|
28
|
+
function getServerTheme() {
|
|
29
|
+
return "system";
|
|
30
|
+
}
|
|
31
|
+
function getServerMode() {
|
|
32
|
+
return "dark";
|
|
33
|
+
}
|
|
34
|
+
function readInitialTheme() {
|
|
35
|
+
try {
|
|
36
|
+
const stored = window.localStorage.getItem("theme");
|
|
37
|
+
if (isTheme(stored)) return stored;
|
|
38
|
+
} catch {}
|
|
39
|
+
const root = document.documentElement;
|
|
40
|
+
const named = root.getAttribute("data-theme");
|
|
41
|
+
if (named === "light" || named === "dark") return named;
|
|
42
|
+
for (const pair of namedModes) {
|
|
43
|
+
if (named === pair.light) return "light";
|
|
44
|
+
if (named === pair.dark) return "dark";
|
|
45
|
+
}
|
|
46
|
+
if (root.classList.contains("light")) return "light";
|
|
47
|
+
if (root.classList.contains("dark")) return "dark";
|
|
48
|
+
const legacy = root.getAttribute("data-sandbox-theme");
|
|
49
|
+
if (legacy === "vault" || legacy === "dawn") return "light";
|
|
50
|
+
return "system";
|
|
51
|
+
}
|
|
52
|
+
function getTheme() {
|
|
53
|
+
if (typeof window === "undefined") return "system";
|
|
54
|
+
return preference ??= readInitialTheme();
|
|
55
|
+
}
|
|
56
|
+
function applyMode(mode) {
|
|
57
|
+
const root = document.documentElement;
|
|
58
|
+
root.classList.toggle("dark", mode === "dark");
|
|
59
|
+
root.classList.toggle("light", mode === "light");
|
|
60
|
+
const named = root.getAttribute("data-theme");
|
|
61
|
+
if (named === "dark" || named === "light") root.setAttribute("data-theme", mode);
|
|
62
|
+
else {
|
|
63
|
+
const pair = namedModes.find((pair) => named === pair.dark || named === pair.light);
|
|
64
|
+
if (pair) root.setAttribute("data-theme", pair[mode]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function setTheme(next) {
|
|
68
|
+
if (!isTheme(next) || typeof window === "undefined") return;
|
|
69
|
+
preference = next;
|
|
70
|
+
try {
|
|
71
|
+
if (next === "system") window.localStorage.removeItem("theme");
|
|
72
|
+
else window.localStorage.setItem("theme", next);
|
|
73
|
+
} catch {}
|
|
74
|
+
applyMode(next === "system" ? getSystemTheme() : next);
|
|
75
|
+
window.dispatchEvent(new Event(preferenceEvent));
|
|
76
|
+
}
|
|
77
|
+
function subscribeTheme(notify) {
|
|
78
|
+
const onStorage = (event) => {
|
|
79
|
+
if (event.key !== "theme" && event.key !== null) return;
|
|
80
|
+
preference = isTheme(event.newValue) ? event.newValue : "system";
|
|
81
|
+
notify();
|
|
82
|
+
};
|
|
83
|
+
window.addEventListener(preferenceEvent, notify);
|
|
84
|
+
window.addEventListener("storage", onStorage);
|
|
85
|
+
return () => {
|
|
86
|
+
window.removeEventListener(preferenceEvent, notify);
|
|
87
|
+
window.removeEventListener("storage", onStorage);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function subscribeSystem(notify) {
|
|
91
|
+
if (!window.matchMedia) return () => {};
|
|
92
|
+
const media = window.matchMedia(systemQuery);
|
|
93
|
+
media.addEventListener("change", notify);
|
|
94
|
+
return () => media.removeEventListener("change", notify);
|
|
95
|
+
}
|
|
96
|
+
function useTheme() {
|
|
97
|
+
const theme = useSyncExternalStore(subscribeTheme, getTheme, getServerTheme);
|
|
98
|
+
const system = useSyncExternalStore(subscribeSystem, getSystemTheme, getServerMode);
|
|
99
|
+
const resolvedTheme = theme === "system" ? system : theme;
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
const selected = getTheme();
|
|
102
|
+
applyMode(selected === "system" ? getSystemTheme() : selected);
|
|
103
|
+
}, [resolvedTheme]);
|
|
104
|
+
return {
|
|
105
|
+
theme,
|
|
106
|
+
setTheme,
|
|
107
|
+
resolvedTheme
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const iconClass = "h-4 w-4";
|
|
111
|
+
function SunIcon() {
|
|
112
|
+
return /* @__PURE__ */ jsxs("svg", {
|
|
113
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
114
|
+
viewBox: "0 0 24 24",
|
|
115
|
+
fill: "none",
|
|
116
|
+
stroke: "currentColor",
|
|
117
|
+
strokeWidth: 2,
|
|
118
|
+
strokeLinecap: "round",
|
|
119
|
+
strokeLinejoin: "round",
|
|
120
|
+
className: iconClass,
|
|
121
|
+
"aria-hidden": "true",
|
|
122
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
123
|
+
cx: 12,
|
|
124
|
+
cy: 12,
|
|
125
|
+
r: 5
|
|
126
|
+
}), /* @__PURE__ */ jsx("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })]
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function MoonIcon() {
|
|
130
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
131
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
132
|
+
viewBox: "0 0 24 24",
|
|
133
|
+
fill: "none",
|
|
134
|
+
stroke: "currentColor",
|
|
135
|
+
strokeWidth: 2,
|
|
136
|
+
strokeLinecap: "round",
|
|
137
|
+
strokeLinejoin: "round",
|
|
138
|
+
className: iconClass,
|
|
139
|
+
"aria-hidden": "true",
|
|
140
|
+
children: /* @__PURE__ */ jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" })
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
function ThemeToggle() {
|
|
144
|
+
const { resolvedTheme, setTheme } = useTheme();
|
|
145
|
+
return /* @__PURE__ */ jsx("button", {
|
|
146
|
+
type: "button",
|
|
147
|
+
onClick: () => setTheme(resolvedTheme === "dark" ? "light" : "dark"),
|
|
148
|
+
className: "inline-flex items-center justify-center rounded-md p-2 text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors",
|
|
149
|
+
"aria-label": `Switch to ${resolvedTheme === "dark" ? "light" : "dark"} mode`,
|
|
150
|
+
children: resolvedTheme === "dark" ? /* @__PURE__ */ jsx(SunIcon, {}) : /* @__PURE__ */ jsx(MoonIcon, {})
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
export { ThemeToggle, useTheme };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
//#region src/primitives/toast.d.ts
|
|
3
|
+
export interface Toast {
|
|
4
|
+
id: string;
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
variant?: "default" | "success" | "error" | "warning" | "info";
|
|
8
|
+
duration?: number;
|
|
9
|
+
}
|
|
10
|
+
interface ToastContainerProps {
|
|
11
|
+
toasts: Toast[];
|
|
12
|
+
onDismiss: (id: string) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare function ToastContainer({ toasts, onDismiss }: ToastContainerProps): React.JSX.Element;
|
|
15
|
+
type ToastInput = Omit<Toast, "id">;
|
|
16
|
+
interface ToastContextValue {
|
|
17
|
+
toasts: Toast[];
|
|
18
|
+
toast: (input: ToastInput) => void;
|
|
19
|
+
success: (title: string, description?: string) => void;
|
|
20
|
+
error: (title: string, description?: string) => void;
|
|
21
|
+
warning: (title: string, description?: string) => void;
|
|
22
|
+
info: (title: string, description?: string) => void;
|
|
23
|
+
dismiss: (id: string) => void;
|
|
24
|
+
}
|
|
25
|
+
export declare function ToastProvider({ children }: {
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
}): React.JSX.Element;
|
|
28
|
+
export declare function useToast(): ToastContextValue;
|
|
29
|
+
//#endregion
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { focusRing } from "../lib/focus.js";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { AlertCircle, AlertTriangle, CheckCircle2, Info, X } from "lucide-react";
|
|
8
|
+
//#region src/primitives/toast.tsx
|
|
9
|
+
const toastVariants = cva("pointer-events-auto relative flex w-full items-center justify-between gap-3 overflow-hidden rounded-lg border p-4 shadow-lg transition-all", {
|
|
10
|
+
variants: { variant: {
|
|
11
|
+
default: "border-border bg-background text-foreground",
|
|
12
|
+
success: "border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]",
|
|
13
|
+
error: "border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)]",
|
|
14
|
+
warning: "border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)]",
|
|
15
|
+
info: "border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)]"
|
|
16
|
+
} },
|
|
17
|
+
defaultVariants: { variant: "default" }
|
|
18
|
+
});
|
|
19
|
+
const icons = {
|
|
20
|
+
success: CheckCircle2,
|
|
21
|
+
error: AlertCircle,
|
|
22
|
+
warning: AlertTriangle,
|
|
23
|
+
info: Info,
|
|
24
|
+
default: Info
|
|
25
|
+
};
|
|
26
|
+
function ToastComponent({ id, title, description, variant = "default", onDismiss }) {
|
|
27
|
+
const Icon = icons[variant];
|
|
28
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
29
|
+
className: cn(toastVariants({ variant })),
|
|
30
|
+
role: "alert",
|
|
31
|
+
"aria-live": "polite",
|
|
32
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
33
|
+
className: "flex items-start gap-3",
|
|
34
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
35
|
+
className: "h-5 w-5 shrink-0",
|
|
36
|
+
"aria-hidden": "true"
|
|
37
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
38
|
+
className: "flex-1",
|
|
39
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
40
|
+
className: "font-medium text-sm",
|
|
41
|
+
children: title
|
|
42
|
+
}), description && /* @__PURE__ */ jsx("p", {
|
|
43
|
+
className: "mt-1 text-sm opacity-80",
|
|
44
|
+
children: description
|
|
45
|
+
})]
|
|
46
|
+
})]
|
|
47
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
48
|
+
type: "button",
|
|
49
|
+
onClick: () => onDismiss(id),
|
|
50
|
+
className: cn("shrink-0 rounded-md p-1 opacity-70 transition-[opacity,box-shadow] hover:opacity-100 focus-visible:opacity-100", focusRing),
|
|
51
|
+
"aria-label": "Dismiss notification",
|
|
52
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
53
|
+
})]
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function ToastContainer({ toasts, onDismiss }) {
|
|
57
|
+
return /* @__PURE__ */ jsx("div", {
|
|
58
|
+
role: "region",
|
|
59
|
+
className: "fixed right-4 bottom-4 z-50 flex max-w-md flex-col gap-2",
|
|
60
|
+
"aria-label": "Notifications",
|
|
61
|
+
children: toasts.map((toast) => /* @__PURE__ */ jsx(ToastComponent, {
|
|
62
|
+
...toast,
|
|
63
|
+
onDismiss
|
|
64
|
+
}, toast.id))
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
const ToastContext = React.createContext(null);
|
|
68
|
+
function ToastProvider({ children }) {
|
|
69
|
+
const [toasts, setToasts] = React.useState([]);
|
|
70
|
+
const dismiss = React.useCallback((id) => {
|
|
71
|
+
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
72
|
+
}, []);
|
|
73
|
+
const toast = React.useCallback((input) => {
|
|
74
|
+
const id = Math.random().toString(36).slice(2);
|
|
75
|
+
const newToast = {
|
|
76
|
+
id,
|
|
77
|
+
...input
|
|
78
|
+
};
|
|
79
|
+
setToasts((prev) => [...prev, newToast]);
|
|
80
|
+
const duration = input.duration ?? 5e3;
|
|
81
|
+
if (duration > 0) setTimeout(() => dismiss(id), duration);
|
|
82
|
+
}, [dismiss]);
|
|
83
|
+
const success = React.useCallback((title, description) => {
|
|
84
|
+
toast({
|
|
85
|
+
title,
|
|
86
|
+
description,
|
|
87
|
+
variant: "success"
|
|
88
|
+
});
|
|
89
|
+
}, [toast]);
|
|
90
|
+
const error = React.useCallback((title, description) => {
|
|
91
|
+
toast({
|
|
92
|
+
title,
|
|
93
|
+
description,
|
|
94
|
+
variant: "error"
|
|
95
|
+
});
|
|
96
|
+
}, [toast]);
|
|
97
|
+
const warning = React.useCallback((title, description) => {
|
|
98
|
+
toast({
|
|
99
|
+
title,
|
|
100
|
+
description,
|
|
101
|
+
variant: "warning"
|
|
102
|
+
});
|
|
103
|
+
}, [toast]);
|
|
104
|
+
const info = React.useCallback((title, description) => {
|
|
105
|
+
toast({
|
|
106
|
+
title,
|
|
107
|
+
description,
|
|
108
|
+
variant: "info"
|
|
109
|
+
});
|
|
110
|
+
}, [toast]);
|
|
111
|
+
const value = React.useMemo(() => ({
|
|
112
|
+
toasts,
|
|
113
|
+
toast,
|
|
114
|
+
success,
|
|
115
|
+
error,
|
|
116
|
+
warning,
|
|
117
|
+
info,
|
|
118
|
+
dismiss
|
|
119
|
+
}), [
|
|
120
|
+
toasts,
|
|
121
|
+
toast,
|
|
122
|
+
success,
|
|
123
|
+
error,
|
|
124
|
+
warning,
|
|
125
|
+
info,
|
|
126
|
+
dismiss
|
|
127
|
+
]);
|
|
128
|
+
return /* @__PURE__ */ jsxs(ToastContext.Provider, {
|
|
129
|
+
value,
|
|
130
|
+
children: [children, /* @__PURE__ */ jsx(ToastContainer, {
|
|
131
|
+
toasts,
|
|
132
|
+
onDismiss: dismiss
|
|
133
|
+
})]
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function useToast() {
|
|
137
|
+
const context = React.useContext(ToastContext);
|
|
138
|
+
if (!context) throw new Error("useToast must be used within a ToastProvider");
|
|
139
|
+
return context;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { ToastContainer, ToastProvider, useToast };
|