@hanzo/ui 8.27.14 → 8.27.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/NOTICE +19 -0
  2. package/dist/agents/Attachments.cjs +29 -0
  3. package/dist/agents/Attachments.d.ts +31 -0
  4. package/dist/agents/Attachments.d.ts.map +1 -0
  5. package/dist/agents/Attachments.js +27 -0
  6. package/dist/agents/Attachments.js.map +1 -0
  7. package/dist/agents/Choice.cjs +47 -0
  8. package/dist/agents/Choice.d.ts +34 -0
  9. package/dist/agents/Choice.d.ts.map +1 -0
  10. package/dist/agents/Choice.js +44 -0
  11. package/dist/agents/Choice.js.map +1 -0
  12. package/dist/agents/Console.cjs +106 -0
  13. package/dist/agents/Console.d.ts +54 -0
  14. package/dist/agents/Console.d.ts.map +1 -0
  15. package/dist/agents/Console.js +104 -0
  16. package/dist/agents/Console.js.map +1 -0
  17. package/dist/agents/Feedback.cjs +50 -0
  18. package/dist/agents/Feedback.d.ts +25 -0
  19. package/dist/agents/Feedback.d.ts.map +1 -0
  20. package/dist/agents/Feedback.js +48 -0
  21. package/dist/agents/Feedback.js.map +1 -0
  22. package/dist/agents/FileTabs.cjs +63 -0
  23. package/dist/agents/FileTabs.d.ts +45 -0
  24. package/dist/agents/FileTabs.d.ts.map +1 -0
  25. package/dist/agents/FileTabs.js +61 -0
  26. package/dist/agents/FileTabs.js.map +1 -0
  27. package/dist/agents/FileTree.cjs +160 -0
  28. package/dist/agents/FileTree.d.ts +41 -0
  29. package/dist/agents/FileTree.d.ts.map +1 -0
  30. package/dist/agents/FileTree.js +157 -0
  31. package/dist/agents/FileTree.js.map +1 -0
  32. package/dist/agents/PreviewFrame.cjs +108 -0
  33. package/dist/agents/PreviewFrame.d.ts +78 -0
  34. package/dist/agents/PreviewFrame.d.ts.map +1 -0
  35. package/dist/agents/PreviewFrame.js +105 -0
  36. package/dist/agents/PreviewFrame.js.map +1 -0
  37. package/dist/agents/Suggestions.cjs +29 -0
  38. package/dist/agents/Suggestions.d.ts +28 -0
  39. package/dist/agents/Suggestions.d.ts.map +1 -0
  40. package/dist/agents/Suggestions.js +26 -0
  41. package/dist/agents/Suggestions.js.map +1 -0
  42. package/dist/agents/Workspace.cjs +103 -0
  43. package/dist/agents/Workspace.d.ts +104 -0
  44. package/dist/agents/Workspace.d.ts.map +1 -0
  45. package/dist/agents/Workspace.js +98 -0
  46. package/dist/agents/Workspace.js.map +1 -0
  47. package/dist/agents/bridge.cjs +201 -0
  48. package/dist/agents/bridge.d.ts +102 -0
  49. package/dist/agents/bridge.d.ts.map +1 -0
  50. package/dist/agents/bridge.js +197 -0
  51. package/dist/agents/bridge.js.map +1 -0
  52. package/dist/agents/index.cjs +64 -1
  53. package/dist/agents/index.d.ts +23 -0
  54. package/dist/agents/index.d.ts.map +1 -1
  55. package/dist/agents/index.js +23 -0
  56. package/dist/agents/index.js.map +1 -1
  57. package/dist/agents/log.cjs +75 -0
  58. package/dist/agents/log.d.ts +58 -0
  59. package/dist/agents/log.d.ts.map +1 -0
  60. package/dist/agents/log.js +65 -0
  61. package/dist/agents/log.js.map +1 -0
  62. package/dist/agents/tree.cjs +238 -0
  63. package/dist/agents/tree.d.ts +99 -0
  64. package/dist/agents/tree.d.ts.map +1 -0
  65. package/dist/agents/tree.js +226 -0
  66. package/dist/agents/tree.js.map +1 -0
  67. package/dist/backends/gui/3d-card.d.ts +6 -6
  68. package/dist/backends/gui/3d-marquee.d.ts +7 -8
  69. package/dist/backends/gui/3d-marquee.d.ts.map +1 -1
  70. package/dist/backends/gui/3d-pin.d.ts +1 -1
  71. package/dist/backends/gui/alert.d.ts +3 -3
  72. package/dist/backends/gui/android.d.ts +1 -1
  73. package/dist/backends/gui/animated-testimonials.d.ts +1 -1
  74. package/dist/backends/gui/animated-tooltip.d.ts +1 -1
  75. package/dist/backends/gui/announcement.d.ts +1 -1
  76. package/dist/backends/gui/banner.d.ts +1 -1
  77. package/dist/backends/gui/button.d.ts +1 -1
  78. package/dist/backends/gui/card.d.ts +7 -7
  79. package/dist/backends/gui/code-editor.cjs +2 -2
  80. package/dist/backends/gui/code-editor.d.ts +7 -1
  81. package/dist/backends/gui/code-editor.d.ts.map +1 -1
  82. package/dist/backends/gui/code-editor.js +2 -2
  83. package/dist/backends/gui/code-editor.js.map +1 -1
  84. package/dist/backends/gui/command.d.ts +5 -5
  85. package/dist/backends/gui/command.d.ts.map +1 -1
  86. package/dist/backends/gui/context-menu.d.ts +14 -14
  87. package/dist/backends/gui/context-menu.d.ts.map +1 -1
  88. package/dist/backends/gui/credit-card.d.ts +1 -1
  89. package/dist/backends/gui/desktop.d.ts +1 -1
  90. package/dist/backends/gui/dock.d.ts +3 -3
  91. package/dist/backends/gui/dropdown-menu.d.ts +16 -16
  92. package/dist/backends/gui/dropdown-menu.d.ts.map +1 -1
  93. package/dist/backends/gui/empty.d.ts +6 -6
  94. package/dist/backends/gui/field.d.ts +3 -3
  95. package/dist/backends/gui/gantt.d.ts +1 -1
  96. package/dist/backends/gui/grid-pattern.d.ts +1 -2
  97. package/dist/backends/gui/grid-pattern.d.ts.map +1 -1
  98. package/dist/backends/gui/image-zoom.d.ts +1 -1
  99. package/dist/backends/gui/iphone-15-pro.d.ts +1 -1
  100. package/dist/backends/gui/item.d.ts +9 -9
  101. package/dist/backends/gui/list.d.ts +2 -2
  102. package/dist/backends/gui/macos-dock.d.ts +2 -2
  103. package/dist/backends/gui/magnetic.d.ts +1 -1
  104. package/dist/backends/gui/marquee.d.ts +1 -15
  105. package/dist/backends/gui/marquee.d.ts.map +1 -1
  106. package/dist/backends/gui/menu-dock.d.ts +1 -1
  107. package/dist/backends/gui/menubar.d.ts +15 -15
  108. package/dist/backends/gui/menubar.d.ts.map +1 -1
  109. package/dist/backends/gui/message-dock.d.ts +1 -1
  110. package/dist/backends/gui/motion-highlight.d.ts +1 -12
  111. package/dist/backends/gui/motion-highlight.d.ts.map +1 -1
  112. package/dist/backends/gui/pagination.d.ts +4 -4
  113. package/dist/backends/gui/qr-code.d.ts +1 -2
  114. package/dist/backends/gui/qr-code.d.ts.map +1 -1
  115. package/dist/backends/gui/scroll-area.d.ts +3 -14
  116. package/dist/backends/gui/scroll-area.d.ts.map +1 -1
  117. package/dist/backends/gui/sheet.d.ts +3 -3
  118. package/dist/backends/gui/sheet.d.ts.map +1 -1
  119. package/dist/backends/gui/status.d.ts +1 -1
  120. package/dist/backends/gui/table.d.ts +8 -8
  121. package/dist/backends/gui/toaster.d.ts +1 -15
  122. package/dist/backends/gui/toaster.d.ts.map +1 -1
  123. package/dist/backends/gui/toggle.d.ts +1 -1
  124. package/dist/backends/gui/video-player.d.ts +1 -1
  125. package/dist/chat/Composer.cjs +60 -9
  126. package/dist/chat/Composer.d.ts +42 -2
  127. package/dist/chat/Composer.d.ts.map +1 -1
  128. package/dist/chat/Composer.js +61 -11
  129. package/dist/chat/Composer.js.map +1 -1
  130. package/dist/chat/EmptyPrompt.cjs +27 -0
  131. package/dist/chat/EmptyPrompt.d.ts +30 -0
  132. package/dist/chat/EmptyPrompt.d.ts.map +1 -0
  133. package/dist/chat/EmptyPrompt.js +24 -0
  134. package/dist/chat/EmptyPrompt.js.map +1 -0
  135. package/dist/chat/SessionRail.cjs +97 -0
  136. package/dist/chat/SessionRail.d.ts +97 -0
  137. package/dist/chat/SessionRail.d.ts.map +1 -0
  138. package/dist/chat/SessionRail.js +94 -0
  139. package/dist/chat/SessionRail.js.map +1 -0
  140. package/dist/chat/Thread.d.ts +2 -8
  141. package/dist/chat/Thread.d.ts.map +1 -1
  142. package/dist/chat/index.cjs +8 -1
  143. package/dist/chat/index.d.ts +3 -1
  144. package/dist/chat/index.d.ts.map +1 -1
  145. package/dist/chat/index.js +3 -1
  146. package/dist/chat/index.js.map +1 -1
  147. package/dist/gallery.cjs +28 -1
  148. package/dist/gallery.d.ts.map +1 -1
  149. package/dist/gallery.html +71 -3
  150. package/dist/gallery.js +30 -3
  151. package/dist/gallery.js.map +1 -1
  152. package/dist/product/BranchSelect.cjs +27 -0
  153. package/dist/product/BranchSelect.d.ts +27 -0
  154. package/dist/product/BranchSelect.d.ts.map +1 -0
  155. package/dist/product/BranchSelect.js +23 -0
  156. package/dist/product/BranchSelect.js.map +1 -0
  157. package/dist/product/ChipSelect.cjs +267 -0
  158. package/dist/product/ChipSelect.d.ts +71 -0
  159. package/dist/product/ChipSelect.d.ts.map +1 -0
  160. package/dist/product/ChipSelect.js +265 -0
  161. package/dist/product/ChipSelect.js.map +1 -0
  162. package/dist/product/RepoSelect.cjs +75 -0
  163. package/dist/product/RepoSelect.d.ts +63 -0
  164. package/dist/product/RepoSelect.d.ts.map +1 -0
  165. package/dist/product/RepoSelect.js +69 -0
  166. package/dist/product/RepoSelect.js.map +1 -0
  167. package/dist/product/chipSelect.logic.cjs +147 -0
  168. package/dist/product/chipSelect.logic.d.ts +92 -0
  169. package/dist/product/chipSelect.logic.d.ts.map +1 -0
  170. package/dist/product/chipSelect.logic.js +138 -0
  171. package/dist/product/chipSelect.logic.js.map +1 -0
  172. package/dist/product/index.cjs +23 -1
  173. package/dist/product/index.d.ts +4 -0
  174. package/dist/product/index.d.ts.map +1 -1
  175. package/dist/product/index.js +7 -0
  176. package/dist/product/index.js.map +1 -1
  177. package/dist/styles.css +68 -0
  178. package/package.json +2 -4
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Feedback — copy a reply, and say whether it was good.
3
+ *
4
+ * Ported from build-v2 `components/editor/ask-ai/chat-thread.tsx` (MIT, derived
5
+ * from OSW Studio and DeepSite — see NOTICE). It goes in `Message`'s `actions`
6
+ * slot, which is where chat already puts a turn's row of controls; v2 drew the
7
+ * same three buttons under every settled turn.
8
+ *
9
+ * The verdict is a toggle: pressing the chosen thumb again takes it back. Where
10
+ * it goes — an analytics event, a reward signal — is the host's `onVerdict`.
11
+ */
12
+ import { XStack } from '@hanzo/gui';
13
+ import { type ComponentProps } from 'react';
14
+ type Row = Omit<ComponentProps<typeof XStack>, 'children'>;
15
+ export type Verdict = 'up' | 'down' | null;
16
+ export interface FeedbackProps extends Row {
17
+ /** What Copy puts on the clipboard. Omit and there is no Copy. */
18
+ text?: string;
19
+ /** Controlled verdict. Omit to let the row hold its own. */
20
+ verdict?: Verdict;
21
+ onVerdict?: (verdict: Verdict) => void;
22
+ }
23
+ export declare function Feedback({ text, verdict, onVerdict, ...rest }: FeedbackProps): import("react").JSX.Element;
24
+ export {};
25
+ //# sourceMappingURL=Feedback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Feedback.d.ts","sourceRoot":"","sources":["../../src/agents/Feedback.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAEnC,OAAO,EAAE,KAAK,cAAc,EAA+B,MAAM,OAAO,CAAA;AAKxE,KAAK,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC,CAAA;AAE1D,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;AAE1C,MAAM,WAAW,aAAc,SAAQ,GAAG;IACxC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CACvC;AAED,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,aAAa,+BAwD5E"}
@@ -0,0 +1,48 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Feedback — copy a reply, and say whether it was good.
5
+ *
6
+ * Ported from build-v2 `components/editor/ask-ai/chat-thread.tsx` (MIT, derived
7
+ * from OSW Studio and DeepSite — see NOTICE). It goes in `Message`'s `actions`
8
+ * slot, which is where chat already puts a turn's row of controls; v2 drew the
9
+ * same three buttons under every settled turn.
10
+ *
11
+ * The verdict is a toggle: pressing the chosen thumb again takes it back. Where
12
+ * it goes — an analytics event, a reward signal — is the host's `onVerdict`.
13
+ */
14
+ import { XStack } from '@hanzo/gui';
15
+ import { Check, Copy, ThumbsDown, ThumbsUp } from '@hanzogui/lucide-icons-2';
16
+ import { useEffect, useRef, useState } from 'react';
17
+ import { Button } from '../backends/gui/button.js';
18
+ import { slot } from '../backends/gui/slot.js';
19
+ export function Feedback({ text, verdict, onVerdict, ...rest }) {
20
+ const [held, setHeld] = useState(null);
21
+ const [copied, setCopied] = useState(false);
22
+ const timer = useRef(null);
23
+ useEffect(() => () => {
24
+ if (timer.current)
25
+ clearTimeout(timer.current);
26
+ }, []);
27
+ const current = verdict === undefined ? held : verdict;
28
+ const judge = (next) => {
29
+ const settled = current === next ? null : next;
30
+ setHeld(settled);
31
+ onVerdict?.(settled);
32
+ };
33
+ const copy = async () => {
34
+ if (!text)
35
+ return;
36
+ try {
37
+ await navigator.clipboard.writeText(text);
38
+ setCopied(true);
39
+ timer.current = setTimeout(() => setCopied(false), 1500);
40
+ }
41
+ catch {
42
+ /* a browser that refuses the clipboard leaves the button as it was */
43
+ }
44
+ };
45
+ const icon = { variant: 'ghost', size: 'icon-sm', minHeight: 28, minWidth: 28, type: 'button' };
46
+ return (_jsxs(XStack, { ...slot('feedback'), items: "center", gap: 2, ...rest, children: [text ? (_jsx(Button, { ...icon, "aria-label": copied ? 'Copied' : 'Copy reply', title: copied ? 'Copied' : 'Copy', onClick: copy, children: copied ? _jsx(Check, { size: 13 }) : _jsx(Copy, { size: 13 }) })) : null, _jsx(Button, { ...icon, "aria-label": "Good result", title: "Good result", "aria-pressed": current === 'up', bg: current === 'up' ? '$raised' : 'transparent', onClick: () => judge('up'), children: _jsx(ThumbsUp, { size: 13 }) }), _jsx(Button, { ...icon, "aria-label": "Bad result", title: "Bad result", "aria-pressed": current === 'down', bg: current === 'down' ? '$raised' : 'transparent', onClick: () => judge('down'), children: _jsx(ThumbsDown, { size: 13 }) })] }));
47
+ }
48
+ //# sourceMappingURL=Feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Feedback.js","sourceRoot":"","sources":["../../src/agents/Feedback.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.FileTabs = FileTabs;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * FileTabs — the open files, one tab each, over the editor.
8
+ *
9
+ * Ported from build-v2 `components/editor/multi-tab-editor.tsx` (MIT, derived
10
+ * from OSW Studio and DeepSite — see NOTICE). v2 carried CodeMirror, its own
11
+ * undo stacks and a save pipeline; this is the tab strip and the body, over the
12
+ * package's own `CodeEditor`, with the files and every change handed back to
13
+ * the host. What saving MEANS — a commit, a run, nothing — is the host's.
14
+ *
15
+ * Distinct from `CodeTabs`, which is a snippet shown in several languages. A
16
+ * snippet has variants; a workspace has files.
17
+ *
18
+ * File contents are TEXT, shown in a plain text field. Nothing here renders a
19
+ * file's markup, runs it, or reads it as anything but characters.
20
+ */
21
+ const gui_1 = require("@hanzo/gui");
22
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
23
+ const react_1 = require("react");
24
+ const code_editor_1 = require("../backends/gui/code-editor.cjs");
25
+ const slot_1 = require("../backends/gui/slot.cjs");
26
+ const FileTree_1 = require("./FileTree.cjs");
27
+ const tree_1 = require("./tree.cjs");
28
+ function FileTabs({ files, value, onSelect, onClose, onChange, empty, ...rest }) {
29
+ const tabs = (0, react_1.useRef)([]);
30
+ const shown = files.find((f) => f.path === value) ?? files[0];
31
+ if (!shown) {
32
+ return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('file-tabs'), flex: 1, minH: 0, items: "center", justify: "center", p: "$4", ...rest, children: (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: "$soft", text: "center", children: empty ?? 'Open a file to see it here.' }) }));
33
+ }
34
+ const move = (e, index) => {
35
+ const last = files.length - 1;
36
+ const to = e.key === 'ArrowRight' ? Math.min(index + 1, last)
37
+ : e.key === 'ArrowLeft' ? Math.max(index - 1, 0)
38
+ : e.key === 'Home' ? 0
39
+ : e.key === 'End' ? last
40
+ : -1;
41
+ if (to >= 0) {
42
+ e.preventDefault();
43
+ onSelect(files[to].path);
44
+ tabs.current[to]?.focus();
45
+ return;
46
+ }
47
+ if (e.key === 'Delete' && onClose) {
48
+ e.preventDefault();
49
+ onClose(files[index].path);
50
+ }
51
+ };
52
+ const editable = Boolean(onChange) && !shown.readOnly;
53
+ return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('file-tabs'), flex: 1, minH: 0, minW: 0, ...rest, children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { role: "tablist", "aria-label": "Open files", items: "stretch", minH: 36, shrink: 0, overflow: "scroll", borderBottomWidth: 1, borderColor: "$borderColor", children: files.map((file, index) => {
54
+ const on = file.path === shown.path;
55
+ const name = (0, tree_1.base)(file.path);
56
+ return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ref: ((el) => {
57
+ tabs.current[index] = el;
58
+ }), render: "button", ...{ type: 'button', title: file.path, 'aria-keyshortcuts': onClose ? 'Delete' : undefined }, role: "tab", "aria-selected": on, "aria-label": file.dirty ? `${file.path}, unsaved` : file.path, tabIndex: on ? 0 : -1, onPress: () => onSelect(file.path), onKeyDown: ((e) => move(e, index)), items: "center", gap: "$1.5", pl: "$3", pr: onClose ? '$1.5' : '$3', shrink: 0, cursor: "pointer", borderWidth: 0, borderRightWidth: 1, borderColor: "$borderColor", borderBottomWidth: 2, borderBottomColor: on ? '$ink' : 'transparent', bg: on ? '$hover' : 'transparent', hoverStyle: { bg: '$hover' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$rim', outlineOffset: -2 }, children: [(0, FileTree_1.glyph)(name, 13), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: on ? '$ink' : '$quiet', numberOfLines: 1, maxW: 180, children: name }), file.dirty ? ((0, jsx_runtime_1.jsx)(gui_1.YStack, { width: 6, height: 6, rounded: 3, bg: "$ink", "aria-hidden": true, ...(0, slot_1.slot)('file-tabs-dirty') })) : null, onClose ? ((0, jsx_runtime_1.jsx)(gui_1.XStack, { ...(0, slot_1.slot)('file-tabs-close'), "aria-hidden": true, width: 20, height: 20, rounded: "$2", items: "center", justify: "center", opacity: on ? 0.8 : 0.5, hoverStyle: { bg: '$raised', opacity: 1 }, onClick: ((e) => {
59
+ e.stopPropagation?.();
60
+ onClose(file.path);
61
+ }), children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.X, { size: 12 }) })) : null] }, file.path));
62
+ }) }), (0, jsx_runtime_1.jsx)(gui_1.YStack, { role: "tabpanel", "aria-label": shown.path, flex: 1, minH: 0, children: shown.error ? ((0, jsx_runtime_1.jsx)(gui_1.YStack, { flex: 1, items: "center", justify: "center", p: "$4", children: (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: "$soft", text: "center", children: shown.error }) })) : shown.content === undefined ? ((0, jsx_runtime_1.jsx)(gui_1.YStack, { flex: 1, items: "center", justify: "center", p: "$4", children: (0, jsx_runtime_1.jsxs)(gui_1.SizableText, { size: "$2", color: "$soft", children: ["Reading ", (0, tree_1.base)(shown.path), "\u2026"] }) })) : ((0, jsx_runtime_1.jsx)(code_editor_1.CodeEditor, { value: shown.content, language: (0, tree_1.language)(shown.path), readOnly: !editable, label: shown.path, onChange: editable ? (text) => onChange?.(shown.path, text) : undefined, showLanguageSelector: false, showCopyButton: false, height: "100%", fontSize: 13, flex: 1, rounded: 0, borderWidth: 0 }, shown.path)) })] }));
63
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * FileTabs — the open files, one tab each, over the editor.
3
+ *
4
+ * Ported from build-v2 `components/editor/multi-tab-editor.tsx` (MIT, derived
5
+ * from OSW Studio and DeepSite — see NOTICE). v2 carried CodeMirror, its own
6
+ * undo stacks and a save pipeline; this is the tab strip and the body, over the
7
+ * package's own `CodeEditor`, with the files and every change handed back to
8
+ * the host. What saving MEANS — a commit, a run, nothing — is the host's.
9
+ *
10
+ * Distinct from `CodeTabs`, which is a snippet shown in several languages. A
11
+ * snippet has variants; a workspace has files.
12
+ *
13
+ * File contents are TEXT, shown in a plain text field. Nothing here renders a
14
+ * file's markup, runs it, or reads it as anything but characters.
15
+ */
16
+ import { YStack } from '@hanzo/gui';
17
+ import { type ComponentProps, type ReactNode } from 'react';
18
+ type Col = Omit<ComponentProps<typeof YStack>, 'children' | 'onChange'>;
19
+ /** One open file. */
20
+ export interface OpenFile {
21
+ path: string;
22
+ /** The text. Absent while it is being read. */
23
+ content?: string;
24
+ /** Why it cannot be shown — too large, binary, unreadable. */
25
+ error?: string;
26
+ /** Changed since it was opened. */
27
+ dirty?: boolean;
28
+ /** This file may not be edited, whatever the tabs allow. */
29
+ readOnly?: boolean;
30
+ }
31
+ export interface FileTabsProps extends Col {
32
+ files: readonly OpenFile[];
33
+ /** The path of the shown file. */
34
+ value: string | null;
35
+ onSelect: (path: string) => void;
36
+ /** Omit to make tabs unclosable. */
37
+ onClose?: (path: string) => void;
38
+ /** Omit to make every file read-only. */
39
+ onChange?: (path: string, content: string) => void;
40
+ /** Drawn when nothing is open. */
41
+ empty?: ReactNode;
42
+ }
43
+ export declare function FileTabs({ files, value, onSelect, onClose, onChange, empty, ...rest }: FileTabsProps): import("react").JSX.Element;
44
+ export {};
45
+ //# sourceMappingURL=FileTabs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTabs.d.ts","sourceRoot":"","sources":["../../src/agents/FileTabs.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAuB,MAAM,EAAE,MAAM,YAAY,CAAA;AAExD,OAAO,EAAE,KAAK,cAAc,EAAsB,KAAK,SAAS,EAAU,MAAM,OAAO,CAAA;AAOvF,KAAK,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,CAAA;AAEvE,qBAAqB;AACrB,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,aAAc,SAAQ,GAAG;IACxC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IAC1B,kCAAkC;IAClC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,yCAAyC;IACzC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAClD,kCAAkC;IAClC,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,aAAa,+BAkJpG"}
@@ -0,0 +1,61 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * FileTabs — the open files, one tab each, over the editor.
5
+ *
6
+ * Ported from build-v2 `components/editor/multi-tab-editor.tsx` (MIT, derived
7
+ * from OSW Studio and DeepSite — see NOTICE). v2 carried CodeMirror, its own
8
+ * undo stacks and a save pipeline; this is the tab strip and the body, over the
9
+ * package's own `CodeEditor`, with the files and every change handed back to
10
+ * the host. What saving MEANS — a commit, a run, nothing — is the host's.
11
+ *
12
+ * Distinct from `CodeTabs`, which is a snippet shown in several languages. A
13
+ * snippet has variants; a workspace has files.
14
+ *
15
+ * File contents are TEXT, shown in a plain text field. Nothing here renders a
16
+ * file's markup, runs it, or reads it as anything but characters.
17
+ */
18
+ import { SizableText, XStack, YStack } from '@hanzo/gui';
19
+ import { X } from '@hanzogui/lucide-icons-2';
20
+ import { useRef } from 'react';
21
+ import { CodeEditor } from '../backends/gui/code-editor.js';
22
+ import { slot } from '../backends/gui/slot.js';
23
+ import { glyph } from './FileTree.js';
24
+ import { base, language } from './tree.js';
25
+ export function FileTabs({ files, value, onSelect, onClose, onChange, empty, ...rest }) {
26
+ const tabs = useRef([]);
27
+ const shown = files.find((f) => f.path === value) ?? files[0];
28
+ if (!shown) {
29
+ return (_jsx(YStack, { ...slot('file-tabs'), flex: 1, minH: 0, items: "center", justify: "center", p: "$4", ...rest, children: _jsx(SizableText, { size: "$2", color: "$soft", text: "center", children: empty ?? 'Open a file to see it here.' }) }));
30
+ }
31
+ const move = (e, index) => {
32
+ const last = files.length - 1;
33
+ const to = e.key === 'ArrowRight' ? Math.min(index + 1, last)
34
+ : e.key === 'ArrowLeft' ? Math.max(index - 1, 0)
35
+ : e.key === 'Home' ? 0
36
+ : e.key === 'End' ? last
37
+ : -1;
38
+ if (to >= 0) {
39
+ e.preventDefault();
40
+ onSelect(files[to].path);
41
+ tabs.current[to]?.focus();
42
+ return;
43
+ }
44
+ if (e.key === 'Delete' && onClose) {
45
+ e.preventDefault();
46
+ onClose(files[index].path);
47
+ }
48
+ };
49
+ const editable = Boolean(onChange) && !shown.readOnly;
50
+ return (_jsxs(YStack, { ...slot('file-tabs'), flex: 1, minH: 0, minW: 0, ...rest, children: [_jsx(XStack, { role: "tablist", "aria-label": "Open files", items: "stretch", minH: 36, shrink: 0, overflow: "scroll", borderBottomWidth: 1, borderColor: "$borderColor", children: files.map((file, index) => {
51
+ const on = file.path === shown.path;
52
+ const name = base(file.path);
53
+ return (_jsxs(XStack, { ref: ((el) => {
54
+ tabs.current[index] = el;
55
+ }), render: "button", ...{ type: 'button', title: file.path, 'aria-keyshortcuts': onClose ? 'Delete' : undefined }, role: "tab", "aria-selected": on, "aria-label": file.dirty ? `${file.path}, unsaved` : file.path, tabIndex: on ? 0 : -1, onPress: () => onSelect(file.path), onKeyDown: ((e) => move(e, index)), items: "center", gap: "$1.5", pl: "$3", pr: onClose ? '$1.5' : '$3', shrink: 0, cursor: "pointer", borderWidth: 0, borderRightWidth: 1, borderColor: "$borderColor", borderBottomWidth: 2, borderBottomColor: on ? '$ink' : 'transparent', bg: on ? '$hover' : 'transparent', hoverStyle: { bg: '$hover' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$rim', outlineOffset: -2 }, children: [glyph(name, 13), _jsx(SizableText, { size: "$2", color: on ? '$ink' : '$quiet', numberOfLines: 1, maxW: 180, children: name }), file.dirty ? (_jsx(YStack, { width: 6, height: 6, rounded: 3, bg: "$ink", "aria-hidden": true, ...slot('file-tabs-dirty') })) : null, onClose ? (_jsx(XStack, { ...slot('file-tabs-close'), "aria-hidden": true, width: 20, height: 20, rounded: "$2", items: "center", justify: "center", opacity: on ? 0.8 : 0.5, hoverStyle: { bg: '$raised', opacity: 1 }, onClick: ((e) => {
56
+ e.stopPropagation?.();
57
+ onClose(file.path);
58
+ }), children: _jsx(X, { size: 12 }) })) : null] }, file.path));
59
+ }) }), _jsx(YStack, { role: "tabpanel", "aria-label": shown.path, flex: 1, minH: 0, children: shown.error ? (_jsx(YStack, { flex: 1, items: "center", justify: "center", p: "$4", children: _jsx(SizableText, { size: "$2", color: "$soft", text: "center", children: shown.error }) })) : shown.content === undefined ? (_jsx(YStack, { flex: 1, items: "center", justify: "center", p: "$4", children: _jsxs(SizableText, { size: "$2", color: "$soft", children: ["Reading ", base(shown.path), "\u2026"] }) })) : (_jsx(CodeEditor, { value: shown.content, language: language(shown.path), readOnly: !editable, label: shown.path, onChange: editable ? (text) => onChange?.(shown.path, text) : undefined, showLanguageSelector: false, showCopyButton: false, height: "100%", fontSize: 13, flex: 1, rounded: 0, borderWidth: 0 }, shown.path)) })] }));
60
+ }
61
+ //# sourceMappingURL=FileTabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTabs.js","sourceRoot":"","sources":["../../src/agents/FileTabs.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,160 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.glyph = glyph;
5
+ exports.FileTree = FileTree;
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ /**
8
+ * FileTree — a repository's files, folders first, one level read at a time.
9
+ *
10
+ * Ported from build-v2 `components/editor/file-tree/{index,glyph}.tsx` (MIT,
11
+ * derived from OSW Studio and DeepSite — see NOTICE). v2 listed a site's pages
12
+ * and let you add, rename and delete them; a repository's files change by runs
13
+ * that commit, so this tree reads and selects and does nothing else.
14
+ *
15
+ * Two ways in, one renderer (`tree.ts`):
16
+ * files every path at once — a flat list the tree groups itself;
17
+ * load one directory per call, the way a repository answers (`''` is the
18
+ * root), read the first time a folder opens and kept after.
19
+ *
20
+ * Names are TEXT. A path comes from a repository somebody else wrote, so it is
21
+ * drawn as a string and never interpreted as markup.
22
+ *
23
+ * Keyboard and roles are the WAI-ARIA tree: one tab stop, arrows move and open,
24
+ * Enter picks. The decisions are `step()` in `tree.ts`; this only applies them.
25
+ */
26
+ const gui_1 = require("@hanzo/gui");
27
+ const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
28
+ const react_1 = require("react");
29
+ const slot_1 = require("../backends/gui/slot.cjs");
30
+ const tree_1 = require("./tree.cjs");
31
+ /**
32
+ * A file's icon, from its extension. The glyph varies and the colour does not:
33
+ * the chrome is monochrome and colour means state (live, failed), so a green
34
+ * `.env` would say "healthy" in a vocabulary that already means something.
35
+ */
36
+ const BY_EXTENSION = {
37
+ html: lucide_icons_2_1.FileCode2,
38
+ htm: lucide_icons_2_1.FileCode2,
39
+ css: lucide_icons_2_1.Hash,
40
+ scss: lucide_icons_2_1.Hash,
41
+ js: lucide_icons_2_1.Braces,
42
+ mjs: lucide_icons_2_1.Braces,
43
+ cjs: lucide_icons_2_1.Braces,
44
+ jsx: lucide_icons_2_1.Braces,
45
+ ts: lucide_icons_2_1.FileType,
46
+ tsx: lucide_icons_2_1.FileType,
47
+ json: lucide_icons_2_1.FileJson,
48
+ md: lucide_icons_2_1.FileText,
49
+ mdx: lucide_icons_2_1.FileText,
50
+ txt: lucide_icons_2_1.FileText,
51
+ svg: lucide_icons_2_1.Image,
52
+ png: lucide_icons_2_1.Image,
53
+ jpg: lucide_icons_2_1.Image,
54
+ jpeg: lucide_icons_2_1.Image,
55
+ gif: lucide_icons_2_1.Image,
56
+ webp: lucide_icons_2_1.Image,
57
+ ico: lucide_icons_2_1.Image,
58
+ toml: lucide_icons_2_1.Settings2,
59
+ yml: lucide_icons_2_1.Settings2,
60
+ yaml: lucide_icons_2_1.Settings2,
61
+ env: lucide_icons_2_1.Settings2,
62
+ };
63
+ /** A file's icon, drawn. `.env` splits to `['', 'env']`, so the last segment is the extension. */
64
+ function glyph(name, size = 14) {
65
+ const ext = name.split('.').pop()?.toLowerCase() ?? '';
66
+ const Icon = BY_EXTENSION[ext] ?? lucide_icons_2_1.FileText;
67
+ return (0, jsx_runtime_1.jsx)(Icon, { size: size });
68
+ }
69
+ function FileTree({ files, load, value = null, onSelect, label = 'Files', empty, ...rest }) {
70
+ const [loaded, setLoaded] = (0, react_1.useState)(() => new Map());
71
+ const [reads, setReads] = (0, react_1.useState)(() => new Map());
72
+ const [open, setOpen] = (0, react_1.useState)(() => new Set(value ? (0, tree_1.ancestors)(value) : []));
73
+ const [focus, setFocus] = (0, react_1.useState)(0);
74
+ const items = (0, react_1.useRef)([]);
75
+ const asked = (0, react_1.useRef)(new Set());
76
+ const listing = (0, react_1.useMemo)(() => (files ? (0, tree_1.group)([...files]) : loaded), [files, loaded]);
77
+ const read = (dir) => {
78
+ if (!load || asked.current.has(dir))
79
+ return;
80
+ asked.current.add(dir);
81
+ setReads((m) => new Map(m).set(dir, 'loading'));
82
+ load(dir).then((entries) => {
83
+ setLoaded((l) => (0, tree_1.put)(l, dir, entries));
84
+ setReads((m) => {
85
+ const next = new Map(m);
86
+ next.delete(dir);
87
+ return next;
88
+ });
89
+ }, (e) => {
90
+ asked.current.delete(dir);
91
+ setReads((m) => new Map(m).set(dir, { error: e instanceof Error ? e.message : 'Could not read this folder' }));
92
+ });
93
+ };
94
+ // The root, and every folder above the chosen file, as soon as there is a
95
+ // way to read them. Revealing the selection is the tree's job: a file opened
96
+ // from elsewhere must not be "selected" inside a folder nobody opened.
97
+ (0, react_1.useEffect)(() => {
98
+ if (!load)
99
+ return;
100
+ read('');
101
+ for (const dir of value ? (0, tree_1.ancestors)(value) : [])
102
+ read(dir);
103
+ // eslint-disable-next-line react-hooks/exhaustive-deps
104
+ }, [load, value]);
105
+ (0, react_1.useEffect)(() => {
106
+ if (!value)
107
+ return;
108
+ const reveal = (0, tree_1.ancestors)(value);
109
+ if (reveal.length)
110
+ setOpen((o) => (reveal.every((d) => o.has(d)) ? o : new Set([...o, ...reveal])));
111
+ }, [value]);
112
+ const list = (0, react_1.useMemo)(() => (0, tree_1.rows)(listing, open), [listing, open]);
113
+ const at = Math.min(focus, Math.max(list.length - 1, 0));
114
+ const toggle = (dir) => {
115
+ const opening = !open.has(dir);
116
+ setOpen((o) => {
117
+ const next = new Set(o);
118
+ if (opening)
119
+ next.add(dir);
120
+ else
121
+ next.delete(dir);
122
+ return next;
123
+ });
124
+ if (opening)
125
+ read(dir);
126
+ };
127
+ const keyed = (e) => {
128
+ const move = (0, tree_1.step)(list, at, e.key);
129
+ if (!move)
130
+ return;
131
+ e.preventDefault();
132
+ if (move.toggle)
133
+ toggle(move.toggle);
134
+ if (move.pick)
135
+ onSelect?.(move.pick);
136
+ setFocus(move.focus);
137
+ items.current[move.focus]?.focus();
138
+ };
139
+ const root = reads.get('');
140
+ if (list.length === 0) {
141
+ return ((0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('file-tree'), flex: 1, minH: 0, items: "center", justify: "center", p: "$4", ...rest, children: (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: "$soft", text: "center", children: root === 'loading'
142
+ ? 'Reading files…'
143
+ : root && typeof root === 'object'
144
+ ? root.error
145
+ : (empty ?? 'No files yet.') }) }));
146
+ }
147
+ return ((0, jsx_runtime_1.jsx)(gui_1.ScrollView, { ...(0, slot_1.slot)('file-tree'), flex: 1, minH: 0, ...rest, children: (0, jsx_runtime_1.jsx)(gui_1.YStack, { role: "tree", "aria-label": label, py: "$1.5", px: "$1.5", onKeyDown: keyed, children: list.map((row, index) => ((0, jsx_runtime_1.jsx)(Item, { row: row, index: index, size: list.length, focused: index === at, chosen: row.kind === 'file' && row.path === value, state: row.kind === 'dir' && row.open ? reads.get(row.path) : undefined, onRef: (el) => {
148
+ items.current[index] = el;
149
+ }, onPress: () => {
150
+ setFocus(index);
151
+ if (row.kind === 'dir')
152
+ toggle(row.path);
153
+ else
154
+ onSelect?.(row.path);
155
+ } }, `${row.kind}:${row.path}`))) }) }));
156
+ }
157
+ function Item({ row, index, size, focused, chosen, state, onRef, onPress, }) {
158
+ const dir = row.kind === 'dir';
159
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { ref: onRef, role: "treeitem", "aria-level": row.depth + 1, "aria-setsize": size, "aria-posinset": index + 1, "aria-selected": chosen, ...(dir ? { 'aria-expanded': row.open } : null), tabIndex: focused ? 0 : -1, onPress: onPress, items: "center", gap: "$1.5", minH: 28, pr: "$2", rounded: "$3", cursor: "pointer", bg: chosen ? '$raised' : 'transparent', hoverStyle: { bg: chosen ? '$raised' : '$hover' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$rim', outlineOffset: -2 }, style: { paddingLeft: 8 + row.depth * 12 }, ...{ 'data-path': row.path }, children: [dir ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [row.open ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 13, opacity: 0.6 }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronRight, { size: 13, opacity: 0.6 }), row.open ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.FolderOpen, { size: 14 }) : (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Folder, { size: 14 })] })) : ((0, jsx_runtime_1.jsx)(gui_1.XStack, { pl: 17, items: "center", children: glyph(row.name) })), (0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$2", color: chosen || dir ? '$ink' : '$quiet', numberOfLines: 1, flex: 1, minW: 0, children: row.name })] }), state ? ((0, jsx_runtime_1.jsx)(gui_1.SizableText, { size: "$1", color: state === 'loading' ? '$soft' : '$bad', style: { paddingLeft: 8 + (row.depth + 1) * 12 + 17 }, py: "$1", "aria-live": "polite", children: state === 'loading' ? 'Reading…' : state.error })) : null] }));
160
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * FileTree — a repository's files, folders first, one level read at a time.
3
+ *
4
+ * Ported from build-v2 `components/editor/file-tree/{index,glyph}.tsx` (MIT,
5
+ * derived from OSW Studio and DeepSite — see NOTICE). v2 listed a site's pages
6
+ * and let you add, rename and delete them; a repository's files change by runs
7
+ * that commit, so this tree reads and selects and does nothing else.
8
+ *
9
+ * Two ways in, one renderer (`tree.ts`):
10
+ * files every path at once — a flat list the tree groups itself;
11
+ * load one directory per call, the way a repository answers (`''` is the
12
+ * root), read the first time a folder opens and kept after.
13
+ *
14
+ * Names are TEXT. A path comes from a repository somebody else wrote, so it is
15
+ * drawn as a string and never interpreted as markup.
16
+ *
17
+ * Keyboard and roles are the WAI-ARIA tree: one tab stop, arrows move and open,
18
+ * Enter picks. The decisions are `step()` in `tree.ts`; this only applies them.
19
+ */
20
+ import { YStack } from '@hanzo/gui';
21
+ import { type ComponentProps, type ReactNode } from 'react';
22
+ import { type Entry } from './tree.js';
23
+ type Col = Omit<ComponentProps<typeof YStack>, 'children'>;
24
+ /** A file's icon, drawn. `.env` splits to `['', 'env']`, so the last segment is the extension. */
25
+ export declare function glyph(name: string, size?: number): ReactNode;
26
+ export interface FileTreeProps extends Col {
27
+ /** Every file path at once. Folders are implied by the paths. */
28
+ files?: readonly string[];
29
+ /** One directory's children (`''` is the root). Called once per folder, on first open. */
30
+ load?: (dir: string) => Promise<Entry[]>;
31
+ /** The open file. Its folders are opened so it can be seen. */
32
+ value?: string | null;
33
+ onSelect?: (path: string) => void;
34
+ /** The tree's accessible name. */
35
+ label?: string;
36
+ /** Drawn when the root has nothing in it. */
37
+ empty?: ReactNode;
38
+ }
39
+ export declare function FileTree({ files, load, value, onSelect, label, empty, ...rest }: FileTreeProps): import("react").JSX.Element;
40
+ export {};
41
+ //# sourceMappingURL=FileTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileTree.d.ts","sourceRoot":"","sources":["../../src/agents/FileTree.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAmC,MAAM,EAAE,MAAM,YAAY,CAAA;AAepE,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,SAAS,EAKf,MAAM,OAAO,CAAA;AAGd,OAAO,EAAa,KAAK,KAAK,EAAkD,MAAM,QAAQ,CAAA;AAE9F,KAAK,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,CAAC,CAAA;AAmC1D,kGAAkG;AAClG,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,SAAS,CAIxD;AAED,MAAM,WAAW,aAAc,SAAQ,GAAG;IACxC,iEAAiE;IACjE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,0FAA0F;IAC1F,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;IACxC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAID,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,IAAI,EACJ,KAAY,EACZ,QAAQ,EACR,KAAe,EACf,KAAK,EACL,GAAG,IAAI,EACR,EAAE,aAAa,+BA8Gf"}