@agentaily/design-system 0.1.1 → 0.3.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.
Files changed (82) hide show
  1. package/DESIGN.md +58 -7
  2. package/README.md +10 -6
  3. package/dist/components/ai/Confirmation.js +58 -22
  4. package/dist/components/ai/Confirmation.js.map +1 -1
  5. package/dist/components/ai/Queue.d.ts +23 -0
  6. package/dist/components/ai/Queue.js +52 -1
  7. package/dist/components/ai/Queue.js.map +1 -1
  8. package/dist/components/ai/ToolCall.js +69 -30
  9. package/dist/components/ai/ToolCall.js.map +1 -1
  10. package/dist/components/auth/AccountControl.d.ts +23 -0
  11. package/dist/components/auth/AccountControl.js +47 -0
  12. package/dist/components/auth/AccountControl.js.map +1 -0
  13. package/dist/components/auth/AuthDialog.d.ts +39 -0
  14. package/dist/components/auth/AuthDialog.js +327 -0
  15. package/dist/components/auth/AuthDialog.js.map +1 -0
  16. package/dist/components/auth/SignInPage.d.ts +48 -0
  17. package/dist/components/auth/SignInPage.js +217 -0
  18. package/dist/components/auth/SignInPage.js.map +1 -0
  19. package/dist/components/chat/CodeBlock.js +3 -2
  20. package/dist/components/chat/CodeBlock.js.map +1 -1
  21. package/dist/components/chat/ConversationThread.d.ts +67 -0
  22. package/dist/components/chat/ConversationThread.js +129 -0
  23. package/dist/components/chat/ConversationThread.js.map +1 -0
  24. package/dist/components/code/Artifact.js +44 -9
  25. package/dist/components/code/Artifact.js.map +1 -1
  26. package/dist/components/code/JSXPreview.js +19 -12
  27. package/dist/components/code/JSXPreview.js.map +1 -1
  28. package/dist/components/code/Snippet.js +2 -2
  29. package/dist/components/code/Snippet.js.map +1 -1
  30. package/dist/components/code/Terminal.js +24 -10
  31. package/dist/components/code/Terminal.js.map +1 -1
  32. package/dist/components/code/WebPreview.js +44 -10
  33. package/dist/components/code/WebPreview.js.map +1 -1
  34. package/dist/components/display/Skeleton.js +17 -4
  35. package/dist/components/display/Skeleton.js.map +1 -1
  36. package/dist/components/display/StatusPill.d.ts +12 -0
  37. package/dist/components/display/StatusPill.js +17 -0
  38. package/dist/components/display/StatusPill.js.map +1 -0
  39. package/dist/components/inputs/Form.d.ts +164 -0
  40. package/dist/components/inputs/Form.js +484 -0
  41. package/dist/components/inputs/Form.js.map +1 -0
  42. package/dist/components/inputs/Input.d.ts +2 -0
  43. package/dist/components/inputs/Input.js +14 -10
  44. package/dist/components/inputs/Input.js.map +1 -1
  45. package/dist/components/inputs/SecretField.d.ts +21 -0
  46. package/dist/components/inputs/SecretField.js +70 -0
  47. package/dist/components/inputs/SecretField.js.map +1 -0
  48. package/dist/components/layout/AppShell.d.ts +30 -0
  49. package/dist/components/layout/AppShell.js +117 -0
  50. package/dist/components/layout/AppShell.js.map +1 -0
  51. package/dist/components/layout/DesignerShell.d.ts +39 -0
  52. package/dist/components/layout/DesignerShell.js +146 -0
  53. package/dist/components/layout/DesignerShell.js.map +1 -0
  54. package/dist/components/layout/DocsLayout.d.ts +24 -0
  55. package/dist/components/layout/DocsLayout.js +113 -0
  56. package/dist/components/layout/DocsLayout.js.map +1 -0
  57. package/dist/components/layout/SettingsPage.d.ts +31 -0
  58. package/dist/components/layout/SettingsPage.js +92 -0
  59. package/dist/components/layout/SettingsPage.js.map +1 -0
  60. package/dist/components/review/MarkupLayer.d.ts +20 -0
  61. package/dist/components/review/MarkupLayer.js +237 -0
  62. package/dist/components/review/MarkupLayer.js.map +1 -0
  63. package/dist/components/settings/HelpSteps.d.ts +20 -0
  64. package/dist/components/settings/HelpSteps.js +40 -0
  65. package/dist/components/settings/HelpSteps.js.map +1 -0
  66. package/dist/components/settings/IntegrationSettings.d.ts +15 -0
  67. package/dist/components/settings/IntegrationSettings.js +630 -0
  68. package/dist/components/settings/IntegrationSettings.js.map +1 -0
  69. package/dist/components/settings/TestRow.d.ts +21 -0
  70. package/dist/components/settings/TestRow.js +66 -0
  71. package/dist/components/settings/TestRow.js.map +1 -0
  72. package/dist/components/utilities/BrandMark.d.ts +17 -0
  73. package/dist/components/utilities/BrandMark.js +43 -0
  74. package/dist/components/utilities/BrandMark.js.map +1 -0
  75. package/dist/components/utilities/Icon.d.ts +28 -0
  76. package/dist/components/utilities/Icon.js +196 -0
  77. package/dist/components/utilities/Icon.js.map +1 -0
  78. package/dist/index.d.ts +23 -0
  79. package/dist/index.js +35 -0
  80. package/dist/index.js.map +1 -1
  81. package/dist/styles.css +67 -64
  82. package/package.json +2 -2
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Centered single-column settings frame: sticky bar (brand + actions), heading,
3
+ * optional tab row, and section cards as `children`. Use the bundled
4
+ * `SettingsPage.Card` for consistent section cards.
5
+ */
6
+ export interface SettingsTab {
7
+ id: string;
8
+ label: string;
9
+ }
10
+ export interface SettingsPageProps {
11
+ /** Bar brand lockup. @default <BrandMark wordmark blink={false} /> */
12
+ brand?: React.ReactNode;
13
+ /** Mono breadcrumb word shown after the brand (rendered as "/ <word>"). @default "settings" */
14
+ word?: string;
15
+ /** @default "Settings" */
16
+ title?: string;
17
+ subtitle?: string;
18
+ /** Tab row — strings or {id,label}. */
19
+ tabs?: (SettingsTab | string)[];
20
+ activeTab?: string;
21
+ onTabChange?: (id: string) => void;
22
+ /** Right side of the sticky bar (Cancel / Save). */
23
+ actions?: React.ReactNode;
24
+ /** Section cards (ideally SettingsPage.Card). */
25
+ children?: React.ReactNode;
26
+ }
27
+ export declare function SettingsPage(props: SettingsPageProps): JSX.Element;
28
+ export declare namespace SettingsPage {
29
+ interface CardProps { title?: string; description?: string; children?: React.ReactNode; }
30
+ function Card(props: CardProps): JSX.Element;
31
+ }
@@ -0,0 +1,92 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { BrandMark } from "../utilities/BrandMark.js";
4
+ const AX_SPAGE_CSS = `
5
+ .ax-spage { height: 100%; overflow-y: auto; background: var(--surface-page); }
6
+ .ax-spage__bar { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 12px; height: 56px; padding: 0 22px;
7
+ border-bottom: 1px solid var(--border-default); background: var(--bg-overlay); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
8
+ .ax-spage__sp { flex: 1; }
9
+ .ax-spage__crumb { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-faint); }
10
+ .ax-spage__crumb::before { content: "/"; color: var(--text-faint); opacity: 0.6; }
11
+ .ax-spage__col { max-width: 640px; margin: 0 auto; padding: 48px 28px 96px; }
12
+ .ax-spage__h { margin: 0; font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight); color: var(--text-body); }
13
+ .ax-spage__sub { margin: 10px 0 0; font-size: var(--text-md); color: var(--text-muted); }
14
+ .ax-spage__tabs { display: flex; gap: 4px; margin: 26px 0 4px; border-bottom: 1px solid var(--border-default); }
15
+ .ax-spage__tab { padding: 9px 12px; font-size: var(--text-sm); color: var(--text-muted); cursor: pointer; border: none; background: none;
16
+ font-family: inherit; border-bottom: 2px solid transparent; margin-bottom: -1px; }
17
+ .ax-spage__tab:hover { color: var(--text-body); }
18
+ .ax-spage__tab[data-on="true"] { color: var(--text-body); border-bottom-color: var(--accent); }
19
+ .ax-spage__card { border: 1px solid var(--border-default); border-radius: var(--radius-3); background: var(--surface-card); padding: 22px; margin-top: 22px; }
20
+ .ax-spage__cardh { margin: 0 0 4px; font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--weight-medium); color: var(--text-body); }
21
+ .ax-spage__cardd { margin: 0 0 18px; font-size: var(--text-sm); color: var(--text-muted); }
22
+ @media (max-width: 600px) {
23
+ .ax-spage__bar { padding: 0 16px; }
24
+ .ax-spage__col { padding: 32px 18px 72px; }
25
+ .ax-spage__tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
26
+ .ax-spage__tabs::-webkit-scrollbar { display: none; }
27
+ .ax-spage__tab { white-space: nowrap; flex: none; }
28
+ }
29
+ `;
30
+ if (typeof document !== "undefined" && !document.getElementById("ax-spage-css")) {
31
+ const s = document.createElement("style");
32
+ s.id = "ax-spage-css";
33
+ s.textContent = AX_SPAGE_CSS;
34
+ document.head.appendChild(s);
35
+ }
36
+ function SettingsPage({
37
+ brand,
38
+ word = "settings",
39
+ title = "Settings",
40
+ subtitle,
41
+ tabs = [],
42
+ activeTab,
43
+ onTabChange,
44
+ actions,
45
+ children
46
+ }) {
47
+ const [internal, setInternal] = useState(activeTab || tabs[0] && (tabs[0].id || tabs[0]));
48
+ const active = activeTab !== void 0 ? activeTab : internal;
49
+ const go = (id) => {
50
+ if (onTabChange) onTabChange(id);
51
+ else setInternal(id);
52
+ };
53
+ return /* @__PURE__ */ jsxs("div", { className: "ax-spage", children: [
54
+ /* @__PURE__ */ jsxs("header", { className: "ax-spage__bar", children: [
55
+ brand || /* @__PURE__ */ jsx(BrandMark, { size: 18, wordmark: true, blink: false }),
56
+ word ? /* @__PURE__ */ jsx("span", { className: "ax-spage__crumb", children: word }) : null,
57
+ /* @__PURE__ */ jsx("span", { className: "ax-spage__sp" }),
58
+ actions
59
+ ] }),
60
+ /* @__PURE__ */ jsxs("div", { className: "ax-spage__col", children: [
61
+ /* @__PURE__ */ jsx("h1", { className: "ax-spage__h", children: title }),
62
+ subtitle ? /* @__PURE__ */ jsx("p", { className: "ax-spage__sub", children: subtitle }) : null,
63
+ tabs.length ? /* @__PURE__ */ jsx("div", { className: "ax-spage__tabs", children: tabs.map((t) => {
64
+ const id = t.id || t;
65
+ const label = t.label || t;
66
+ return /* @__PURE__ */ jsx(
67
+ "button",
68
+ {
69
+ className: "ax-spage__tab",
70
+ "data-on": active === id,
71
+ onClick: () => go(id),
72
+ children: label
73
+ },
74
+ id
75
+ );
76
+ }) }) : null,
77
+ children
78
+ ] })
79
+ ] });
80
+ }
81
+ function SettingsCard({ title, description, children }) {
82
+ return /* @__PURE__ */ jsxs("div", { className: "ax-spage__card", children: [
83
+ title ? /* @__PURE__ */ jsx("h2", { className: "ax-spage__cardh", children: title }) : null,
84
+ description ? /* @__PURE__ */ jsx("p", { className: "ax-spage__cardd", children: description }) : null,
85
+ children
86
+ ] });
87
+ }
88
+ SettingsPage.Card = SettingsCard;
89
+ export {
90
+ SettingsPage
91
+ };
92
+ //# sourceMappingURL=SettingsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SettingsPage.js","sources":["../../../src/components/layout/SettingsPage.jsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { BrandMark } from \"../utilities/BrandMark.jsx\";\n\n// SettingsPage — centered single-column settings frame: sticky bar (brand +\n// actions), heading, optional tabs, and section cards in `children`.\nconst AX_SPAGE_CSS = `\n.ax-spage { height: 100%; overflow-y: auto; background: var(--surface-page); }\n.ax-spage__bar { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 12px; height: 56px; padding: 0 22px;\n border-bottom: 1px solid var(--border-default); background: var(--bg-overlay); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }\n.ax-spage__sp { flex: 1; }\n.ax-spage__crumb { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-faint); }\n.ax-spage__crumb::before { content: \"/\"; color: var(--text-faint); opacity: 0.6; }\n.ax-spage__col { max-width: 640px; margin: 0 auto; padding: 48px 28px 96px; }\n.ax-spage__h { margin: 0; font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight); color: var(--text-body); }\n.ax-spage__sub { margin: 10px 0 0; font-size: var(--text-md); color: var(--text-muted); }\n.ax-spage__tabs { display: flex; gap: 4px; margin: 26px 0 4px; border-bottom: 1px solid var(--border-default); }\n.ax-spage__tab { padding: 9px 12px; font-size: var(--text-sm); color: var(--text-muted); cursor: pointer; border: none; background: none;\n font-family: inherit; border-bottom: 2px solid transparent; margin-bottom: -1px; }\n.ax-spage__tab:hover { color: var(--text-body); }\n.ax-spage__tab[data-on=\"true\"] { color: var(--text-body); border-bottom-color: var(--accent); }\n.ax-spage__card { border: 1px solid var(--border-default); border-radius: var(--radius-3); background: var(--surface-card); padding: 22px; margin-top: 22px; }\n.ax-spage__cardh { margin: 0 0 4px; font-family: var(--font-display); font-size: var(--text-lg); font-weight: var(--weight-medium); color: var(--text-body); }\n.ax-spage__cardd { margin: 0 0 18px; font-size: var(--text-sm); color: var(--text-muted); }\n@media (max-width: 600px) {\n .ax-spage__bar { padding: 0 16px; }\n .ax-spage__col { padding: 32px 18px 72px; }\n .ax-spage__tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }\n .ax-spage__tabs::-webkit-scrollbar { display: none; }\n .ax-spage__tab { white-space: nowrap; flex: none; }\n}\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-spage-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-spage-css\";\n s.textContent = AX_SPAGE_CSS;\n document.head.appendChild(s);\n}\n\nexport function SettingsPage({\n brand,\n word = \"settings\",\n title = \"Settings\",\n subtitle,\n tabs = [],\n activeTab,\n onTabChange,\n actions,\n children,\n}) {\n const [internal, setInternal] = useState(activeTab || (tabs[0] && (tabs[0].id || tabs[0])));\n const active = activeTab !== undefined ? activeTab : internal;\n const go = (id) => {\n if (onTabChange) onTabChange(id);\n else setInternal(id);\n };\n\n return (\n <div className=\"ax-spage\">\n <header className=\"ax-spage__bar\">\n {brand || <BrandMark size={18} wordmark blink={false} />}\n {word ? <span className=\"ax-spage__crumb\">{word}</span> : null}\n <span className=\"ax-spage__sp\"></span>\n {actions}\n </header>\n\n <div className=\"ax-spage__col\">\n <h1 className=\"ax-spage__h\">{title}</h1>\n {subtitle ? <p className=\"ax-spage__sub\">{subtitle}</p> : null}\n\n {tabs.length ? (\n <div className=\"ax-spage__tabs\">\n {tabs.map((t) => {\n const id = t.id || t;\n const label = t.label || t;\n return (\n <button\n key={id}\n className=\"ax-spage__tab\"\n data-on={active === id}\n onClick={() => go(id)}\n >\n {label}\n </button>\n );\n })}\n </div>\n ) : null}\n\n {children}\n </div>\n </div>\n );\n}\n\n// convenience section card\nfunction SettingsCard({ title, description, children }) {\n return (\n <div className=\"ax-spage__card\">\n {title ? <h2 className=\"ax-spage__cardh\">{title}</h2> : null}\n {description ? <p className=\"ax-spage__cardd\">{description}</p> : null}\n {children}\n </div>\n );\n}\nSettingsPage.Card = SettingsCard;\n"],"names":[],"mappings":";;;AAKA,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BrB,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,cAAc,GAAG;AAC/E,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR;AAAA,EACA,OAAO,CAAA;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAG;AACD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,aAAc,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC,EAAG;AAC1F,QAAM,SAAS,cAAc,SAAY,YAAY;AACrD,QAAM,KAAK,CAAC,OAAO;AACjB,QAAI,yBAAyB,EAAE;AAAA,qBACd,EAAE;AAAA,EACrB;AAEA,SACE,qBAAC,OAAA,EAAI,WAAU,YACb,UAAA;AAAA,IAAA,qBAAC,UAAA,EAAO,WAAU,iBACf,UAAA;AAAA,MAAA,6BAAU,WAAA,EAAU,MAAM,IAAI,UAAQ,MAAC,OAAO,OAAO;AAAA,MACrD,OAAO,oBAAC,QAAA,EAAK,WAAU,mBAAmB,gBAAK,IAAU;AAAA,MAC1D,oBAAC,QAAA,EAAK,WAAU,eAAA,CAAe;AAAA,MAC9B;AAAA,IAAA,GACH;AAAA,IAEA,qBAAC,OAAA,EAAI,WAAU,iBACb,UAAA;AAAA,MAAA,oBAAC,MAAA,EAAG,WAAU,eAAe,UAAA,OAAM;AAAA,MAClC,WAAW,oBAAC,KAAA,EAAE,WAAU,iBAAiB,oBAAS,IAAO;AAAA,MAEzD,KAAK,SACJ,oBAAC,OAAA,EAAI,WAAU,kBACZ,UAAA,KAAK,IAAI,CAAC,MAAM;AACf,cAAM,KAAK,EAAE,MAAM;AACnB,cAAM,QAAQ,EAAE,SAAS;AACzB,eACE;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,WAAU;AAAA,YACV,WAAS,WAAW;AAAA,YACpB,SAAS,MAAM,GAAG,EAAE;AAAA,YAEnB,UAAA;AAAA,UAAA;AAAA,UALI;AAAA,QAAA;AAAA,MAQX,CAAC,GACH,IACE;AAAA,MAEH;AAAA,IAAA,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAGA,SAAS,aAAa,EAAE,OAAO,aAAa,YAAY;AACtD,SACE,qBAAC,OAAA,EAAI,WAAU,kBACZ,UAAA;AAAA,IAAA,QAAQ,oBAAC,MAAA,EAAG,WAAU,mBAAmB,iBAAM,IAAQ;AAAA,IACvD,cAAc,oBAAC,KAAA,EAAE,WAAU,mBAAmB,uBAAY,IAAO;AAAA,IACjE;AAAA,EAAA,GACH;AAEJ;AACA,aAAa,OAAO;"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Element-targeting overlay for "point at what to change" review. Hover
3
+ * highlights any element carrying `data-mk-label`; click selects it; a note
4
+ * composer emits `onSend("〔label · kind〕note")`. Mount inside a
5
+ * position:relative container — the layer fills it (inset:0). Esc deselects,
6
+ * then closes. Personal tool — nothing is persisted.
7
+ */
8
+ export interface MarkupLayerProps {
9
+ /** Called on Esc (when nothing selected) or the 退出 button. */
10
+ onClose?: () => void;
11
+ /** Called with the composed message: `〔label · kind〕note`. */
12
+ onSend?: (message: string) => void;
13
+ /** Composer textarea placeholder. */
14
+ placeholder?: string;
15
+ /** Hint pill text before a target is picked. */
16
+ hintIdle?: string;
17
+ /** Hint pill text while composing on a selected target. */
18
+ hintActive?: string;
19
+ }
20
+ export declare function MarkupLayer(props: MarkupLayerProps): JSX.Element;
@@ -0,0 +1,237 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useRef, useState, useEffect } from "react";
3
+ import { Icon } from "../utilities/Icon.js";
4
+ const AX_MARKUP_CSS = `
5
+ .ax-markup { position: absolute; inset: 0; z-index: 20; pointer-events: none; box-shadow: inset 0 0 0 2px var(--focus-soft); }
6
+ .ax-markup__canvas { position: absolute; inset: 0; cursor: crosshair; touch-action: none; pointer-events: auto; }
7
+ .ax-markup__box { position: absolute; pointer-events: none; border: 1.5px solid var(--accent);
8
+ border-radius: var(--radius-1); background: rgba(127,127,127,0.06); z-index: 22;
9
+ transition: left 80ms var(--ease-out), top 80ms var(--ease-out), width 80ms var(--ease-out), height 80ms var(--ease-out); }
10
+ .ax-markup__box.is-selected { box-shadow: 0 0 0 3px var(--focus-soft); background: rgba(127,127,127,0.10); transition: none; }
11
+ .ax-markup__tag { position: absolute; top: 0; left: -1.5px; transform: translateY(-100%);
12
+ display: inline-flex; align-items: center; padding: 2px 7px; background: var(--accent); color: var(--accent-fg);
13
+ font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.01em;
14
+ border-radius: var(--radius-1) var(--radius-1) 0 0; white-space: nowrap; }
15
+ .ax-markup__tagkind { opacity: 0.7; }
16
+ .ax-markup__pop { position: absolute; width: 248px; z-index: 30; display: flex; flex-direction: column; gap: 9px;
17
+ padding: 11px; background: var(--surface-card); border: 1px solid var(--border-strong);
18
+ border-radius: var(--radius-3); box-shadow: var(--shadow-3); pointer-events: auto; }
19
+ .ax-markup__poptarget { display: flex; align-items: center; gap: 6px; color: var(--text-muted); }
20
+ .ax-markup__poptag { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-body); }
21
+ .ax-markup__ta { width: 100%; min-height: 64px; resize: none; padding: 8px 10px; background: var(--surface-page);
22
+ color: var(--text-body); border: 1px solid var(--border-default); border-radius: var(--radius-2);
23
+ font-family: var(--font-body); font-size: var(--text-sm); line-height: var(--leading-snug); outline: none; }
24
+ .ax-markup__ta:focus { border-color: var(--fg-2); box-shadow: 0 0 0 3px var(--focus-soft); }
25
+ .ax-markup__ta::placeholder { color: var(--text-faint); }
26
+ .ax-markup__popbtns { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
27
+ .ax-markup__cancel, .ax-markup__done { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px;
28
+ border-radius: var(--radius-2); font-family: var(--font-body); font-size: var(--text-sm); cursor: pointer;
29
+ border: 1px solid transparent; transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
30
+ .ax-markup__cancel { background: none; color: var(--text-faint); }
31
+ .ax-markup__cancel:hover { color: var(--text-body); background: var(--surface-raised); }
32
+ .ax-markup__done { background: var(--accent); color: var(--accent-fg); }
33
+ .ax-markup__done:hover { background: var(--accent-hover); }
34
+ .ax-markup__done:disabled { opacity: 0.4; cursor: not-allowed; }
35
+ .ax-markup__pill { position: absolute; top: 16px; left: 50%; transform: translateX(-50%); z-index: 25;
36
+ display: flex; align-items: center; gap: 11px; padding: 7px 7px 7px 14px; max-width: calc(100% - 32px);
37
+ background: var(--surface-card); border: 1px solid var(--border-strong); border-radius: var(--radius-full);
38
+ box-shadow: var(--shadow-2); pointer-events: auto; }
39
+ .ax-markup__dot { flex: none; width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--accent);
40
+ animation: ax-mk-pulse 1.6s var(--ease-out) infinite; }
41
+ @keyframes ax-mk-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
42
+ @media (prefers-reduced-motion: reduce) { .ax-markup__dot { animation: none; } }
43
+ .ax-markup__pilltxt { font-size: var(--text-sm); color: var(--text-body); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
44
+ .ax-markup__pillsep { flex: none; width: 1px; height: 18px; background: var(--border-strong); }
45
+ .ax-markup__pillx { flex: none; display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 11px;
46
+ border: none; background: var(--surface-raised); color: var(--text-muted); border-radius: var(--radius-full);
47
+ font-family: var(--font-body); font-size: var(--text-sm); cursor: pointer; transition: color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out); }
48
+ .ax-markup__pillx:hover { color: var(--text-body); background: var(--border-strong); }
49
+ `;
50
+ if (typeof document !== "undefined" && !document.getElementById("ax-markup-css")) {
51
+ const s = document.createElement("style");
52
+ s.id = "ax-markup-css";
53
+ s.textContent = AX_MARKUP_CSS;
54
+ document.head.appendChild(s);
55
+ }
56
+ function MarkupLayer({
57
+ onClose,
58
+ onSend,
59
+ placeholder = "告诉 Agentaily 这里要怎么改…",
60
+ hintIdle = "移到要改的地方,点击它再描述修改",
61
+ hintActive = "输入修改要求,发送到左侧对话"
62
+ }) {
63
+ const layerRef = useRef(null);
64
+ const capRef = useRef(null);
65
+ const [hover, setHover] = useState(null);
66
+ const [selected, setSelected] = useState(null);
67
+ const [note, setNote] = useState("");
68
+ const findTarget = (cx, cy) => {
69
+ const cap = capRef.current;
70
+ if (!cap) return null;
71
+ const prev = cap.style.pointerEvents;
72
+ cap.style.pointerEvents = "none";
73
+ const el = document.elementFromPoint(cx, cy);
74
+ cap.style.pointerEvents = prev || "auto";
75
+ if (!el) return null;
76
+ return el.closest("[data-mk-label]") || null;
77
+ };
78
+ const boxFor = (el) => {
79
+ const r = el.getBoundingClientRect();
80
+ const lr = layerRef.current.getBoundingClientRect();
81
+ return {
82
+ left: r.left - lr.left,
83
+ top: r.top - lr.top,
84
+ w: r.width,
85
+ h: r.height,
86
+ label: el.getAttribute("data-mk-label"),
87
+ kind: el.getAttribute("data-mk-kind") || ""
88
+ };
89
+ };
90
+ const onMove = (e) => {
91
+ if (selected) return;
92
+ const t = findTarget(e.clientX, e.clientY);
93
+ setHover(t ? boxFor(t) : null);
94
+ };
95
+ const onLeave = () => {
96
+ if (!selected) setHover(null);
97
+ };
98
+ const onClickCap = (e) => {
99
+ const t = findTarget(e.clientX, e.clientY);
100
+ if (!t) {
101
+ setSelected(null);
102
+ setNote("");
103
+ return;
104
+ }
105
+ setSelected(boxFor(t));
106
+ setNote("");
107
+ setHover(null);
108
+ };
109
+ const send = () => {
110
+ if (!selected || !note.trim()) return;
111
+ const tag = selected.kind ? `${selected.label} · ${selected.kind}` : selected.label;
112
+ onSend && onSend(`〔${tag}〕${note.trim()}`);
113
+ setSelected(null);
114
+ setNote("");
115
+ };
116
+ useEffect(() => {
117
+ const onKey = (e) => {
118
+ if (e.key !== "Escape") return;
119
+ if (selected) {
120
+ setSelected(null);
121
+ setNote("");
122
+ } else onClose && onClose();
123
+ };
124
+ window.addEventListener("keydown", onKey);
125
+ return () => window.removeEventListener("keydown", onKey);
126
+ }, [selected, onClose]);
127
+ const box = selected || hover;
128
+ const popStyle = () => {
129
+ const W = layerRef.current ? layerRef.current.clientWidth : 800;
130
+ const H = layerRef.current ? layerRef.current.clientHeight : 600;
131
+ let left = selected.left;
132
+ if (left + 268 > W) left = Math.max(8, W - 268);
133
+ let top = selected.top + selected.h + 10;
134
+ if (top + 150 > H) top = Math.max(8, selected.top - 158);
135
+ return { left, top };
136
+ };
137
+ return /* @__PURE__ */ jsxs("div", { className: "ax-markup", ref: layerRef, children: [
138
+ /* @__PURE__ */ jsx(
139
+ "div",
140
+ {
141
+ className: "ax-markup__canvas",
142
+ ref: capRef,
143
+ onMouseMove: onMove,
144
+ onMouseLeave: onLeave,
145
+ onClick: onClickCap
146
+ }
147
+ ),
148
+ box ? /* @__PURE__ */ jsx(
149
+ "div",
150
+ {
151
+ className: "ax-markup__box" + (selected ? " is-selected" : ""),
152
+ style: { left: box.left, top: box.top, width: box.w, height: box.h },
153
+ children: /* @__PURE__ */ jsxs("span", { className: "ax-markup__tag", children: [
154
+ box.label,
155
+ box.kind ? /* @__PURE__ */ jsxs("span", { className: "ax-markup__tagkind", children: [
156
+ " · ",
157
+ box.kind
158
+ ] }) : null
159
+ ] })
160
+ }
161
+ ) : null,
162
+ selected ? /* @__PURE__ */ jsxs("div", { className: "ax-markup__pop", style: popStyle(), onClick: (e) => e.stopPropagation(), children: [
163
+ /* @__PURE__ */ jsxs("div", { className: "ax-markup__poptarget", children: [
164
+ /* @__PURE__ */ jsx(Icon, { name: "target", size: 13 }),
165
+ /* @__PURE__ */ jsxs("span", { className: "ax-markup__poptag", children: [
166
+ selected.label,
167
+ selected.kind ? ` · ${selected.kind}` : ""
168
+ ] })
169
+ ] }),
170
+ /* @__PURE__ */ jsx(
171
+ "textarea",
172
+ {
173
+ className: "ax-markup__ta",
174
+ autoFocus: true,
175
+ value: note,
176
+ placeholder,
177
+ onChange: (e) => setNote(e.target.value),
178
+ onKeyDown: (e) => {
179
+ if (e.key === "Enter" && !e.shiftKey) {
180
+ e.preventDefault();
181
+ send();
182
+ }
183
+ }
184
+ }
185
+ ),
186
+ /* @__PURE__ */ jsxs("div", { className: "ax-markup__popbtns", children: [
187
+ /* @__PURE__ */ jsx(
188
+ "button",
189
+ {
190
+ type: "button",
191
+ className: "ax-markup__cancel",
192
+ onClick: () => {
193
+ setSelected(null);
194
+ setNote("");
195
+ },
196
+ children: "取消"
197
+ }
198
+ ),
199
+ /* @__PURE__ */ jsxs(
200
+ "button",
201
+ {
202
+ type: "button",
203
+ className: "ax-markup__done",
204
+ disabled: !note.trim(),
205
+ onClick: send,
206
+ children: [
207
+ "发送到对话",
208
+ /* @__PURE__ */ jsx(Icon, { name: "arrow", size: 13 })
209
+ ]
210
+ }
211
+ )
212
+ ] })
213
+ ] }) : null,
214
+ /* @__PURE__ */ jsxs("div", { className: "ax-markup__pill", children: [
215
+ /* @__PURE__ */ jsx("span", { className: "ax-markup__dot" }),
216
+ /* @__PURE__ */ jsx("span", { className: "ax-markup__pilltxt", children: selected ? hintActive : hintIdle }),
217
+ /* @__PURE__ */ jsx("span", { className: "ax-markup__pillsep" }),
218
+ /* @__PURE__ */ jsxs(
219
+ "button",
220
+ {
221
+ type: "button",
222
+ className: "ax-markup__pillx",
223
+ onClick: () => onClose && onClose(),
224
+ "aria-label": "退出",
225
+ children: [
226
+ /* @__PURE__ */ jsx(Icon, { name: "x", size: 14 }),
227
+ /* @__PURE__ */ jsx("span", { children: "退出" })
228
+ ]
229
+ }
230
+ )
231
+ ] })
232
+ ] });
233
+ }
234
+ export {
235
+ MarkupLayer
236
+ };
237
+ //# sourceMappingURL=MarkupLayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkupLayer.js","sources":["../../../src/components/review/MarkupLayer.jsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from \"react\";\nimport { Icon } from \"../utilities/Icon.jsx\";\n\n// MarkupLayer — element-targeting overlay. Hover highlights the real node under\n// the cursor (any element carrying data-mk-label); click selects it; type a note\n// and it's emitted via onSend with the element's identity prefixed — so users\n// point at what they mean instead of describing it. Personal tool, no persistence.\n//\n// Mount inside a position:relative container; the layer fills it (inset:0).\n// Targetable elements opt in with: data-mk-label=\"标题\" data-mk-kind=\"文本\"(optional).\nconst AX_MARKUP_CSS = `\n.ax-markup { position: absolute; inset: 0; z-index: 20; pointer-events: none; box-shadow: inset 0 0 0 2px var(--focus-soft); }\n.ax-markup__canvas { position: absolute; inset: 0; cursor: crosshair; touch-action: none; pointer-events: auto; }\n.ax-markup__box { position: absolute; pointer-events: none; border: 1.5px solid var(--accent);\n border-radius: var(--radius-1); background: rgba(127,127,127,0.06); z-index: 22;\n transition: left 80ms var(--ease-out), top 80ms var(--ease-out), width 80ms var(--ease-out), height 80ms var(--ease-out); }\n.ax-markup__box.is-selected { box-shadow: 0 0 0 3px var(--focus-soft); background: rgba(127,127,127,0.10); transition: none; }\n.ax-markup__tag { position: absolute; top: 0; left: -1.5px; transform: translateY(-100%);\n display: inline-flex; align-items: center; padding: 2px 7px; background: var(--accent); color: var(--accent-fg);\n font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.01em;\n border-radius: var(--radius-1) var(--radius-1) 0 0; white-space: nowrap; }\n.ax-markup__tagkind { opacity: 0.7; }\n.ax-markup__pop { position: absolute; width: 248px; z-index: 30; display: flex; flex-direction: column; gap: 9px;\n padding: 11px; background: var(--surface-card); border: 1px solid var(--border-strong);\n border-radius: var(--radius-3); box-shadow: var(--shadow-3); pointer-events: auto; }\n.ax-markup__poptarget { display: flex; align-items: center; gap: 6px; color: var(--text-muted); }\n.ax-markup__poptag { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-body); }\n.ax-markup__ta { width: 100%; min-height: 64px; resize: none; padding: 8px 10px; background: var(--surface-page);\n color: var(--text-body); border: 1px solid var(--border-default); border-radius: var(--radius-2);\n font-family: var(--font-body); font-size: var(--text-sm); line-height: var(--leading-snug); outline: none; }\n.ax-markup__ta:focus { border-color: var(--fg-2); box-shadow: 0 0 0 3px var(--focus-soft); }\n.ax-markup__ta::placeholder { color: var(--text-faint); }\n.ax-markup__popbtns { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }\n.ax-markup__cancel, .ax-markup__done { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px;\n border-radius: var(--radius-2); font-family: var(--font-body); font-size: var(--text-sm); cursor: pointer;\n border: 1px solid transparent; transition: background var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }\n.ax-markup__cancel { background: none; color: var(--text-faint); }\n.ax-markup__cancel:hover { color: var(--text-body); background: var(--surface-raised); }\n.ax-markup__done { background: var(--accent); color: var(--accent-fg); }\n.ax-markup__done:hover { background: var(--accent-hover); }\n.ax-markup__done:disabled { opacity: 0.4; cursor: not-allowed; }\n.ax-markup__pill { position: absolute; top: 16px; left: 50%; transform: translateX(-50%); z-index: 25;\n display: flex; align-items: center; gap: 11px; padding: 7px 7px 7px 14px; max-width: calc(100% - 32px);\n background: var(--surface-card); border: 1px solid var(--border-strong); border-radius: var(--radius-full);\n box-shadow: var(--shadow-2); pointer-events: auto; }\n.ax-markup__dot { flex: none; width: 7px; height: 7px; border-radius: var(--radius-full); background: var(--accent);\n animation: ax-mk-pulse 1.6s var(--ease-out) infinite; }\n@keyframes ax-mk-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }\n@media (prefers-reduced-motion: reduce) { .ax-markup__dot { animation: none; } }\n.ax-markup__pilltxt { font-size: var(--text-sm); color: var(--text-body); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.ax-markup__pillsep { flex: none; width: 1px; height: 18px; background: var(--border-strong); }\n.ax-markup__pillx { flex: none; display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 11px;\n border: none; background: var(--surface-raised); color: var(--text-muted); border-radius: var(--radius-full);\n font-family: var(--font-body); font-size: var(--text-sm); cursor: pointer; transition: color var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out); }\n.ax-markup__pillx:hover { color: var(--text-body); background: var(--border-strong); }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-markup-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-markup-css\";\n s.textContent = AX_MARKUP_CSS;\n document.head.appendChild(s);\n}\n\nexport function MarkupLayer({\n onClose,\n onSend,\n placeholder = \"告诉 Agentaily 这里要怎么改…\",\n hintIdle = \"移到要改的地方,点击它再描述修改\",\n hintActive = \"输入修改要求,发送到左侧对话\",\n}) {\n const layerRef = useRef(null);\n const capRef = useRef(null);\n const [hover, setHover] = useState(null);\n const [selected, setSelected] = useState(null);\n const [note, setNote] = useState(\"\");\n\n const findTarget = (cx, cy) => {\n const cap = capRef.current;\n if (!cap) return null;\n const prev = cap.style.pointerEvents;\n cap.style.pointerEvents = \"none\";\n const el = document.elementFromPoint(cx, cy);\n cap.style.pointerEvents = prev || \"auto\";\n if (!el) return null;\n return el.closest(\"[data-mk-label]\") || null;\n };\n\n const boxFor = (el) => {\n const r = el.getBoundingClientRect();\n const lr = layerRef.current.getBoundingClientRect();\n return {\n left: r.left - lr.left,\n top: r.top - lr.top,\n w: r.width,\n h: r.height,\n label: el.getAttribute(\"data-mk-label\"),\n kind: el.getAttribute(\"data-mk-kind\") || \"\",\n };\n };\n\n const onMove = (e) => {\n if (selected) return;\n const t = findTarget(e.clientX, e.clientY);\n setHover(t ? boxFor(t) : null);\n };\n const onLeave = () => {\n if (!selected) setHover(null);\n };\n const onClickCap = (e) => {\n const t = findTarget(e.clientX, e.clientY);\n if (!t) {\n setSelected(null);\n setNote(\"\");\n return;\n }\n setSelected(boxFor(t));\n setNote(\"\");\n setHover(null);\n };\n\n const send = () => {\n if (!selected || !note.trim()) return;\n const tag = selected.kind ? `${selected.label} · ${selected.kind}` : selected.label;\n onSend && onSend(`〔${tag}〕${note.trim()}`);\n setSelected(null);\n setNote(\"\");\n };\n\n useEffect(() => {\n const onKey = (e) => {\n if (e.key !== \"Escape\") return;\n if (selected) {\n setSelected(null);\n setNote(\"\");\n } else onClose && onClose();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [selected, onClose]);\n\n const box = selected || hover;\n\n const popStyle = () => {\n const W = layerRef.current ? layerRef.current.clientWidth : 800;\n const H = layerRef.current ? layerRef.current.clientHeight : 600;\n let left = selected.left;\n if (left + 268 > W) left = Math.max(8, W - 268);\n let top = selected.top + selected.h + 10;\n if (top + 150 > H) top = Math.max(8, selected.top - 158);\n return { left, top };\n };\n\n return (\n <div className=\"ax-markup\" ref={layerRef}>\n <div\n className=\"ax-markup__canvas\"\n ref={capRef}\n onMouseMove={onMove}\n onMouseLeave={onLeave}\n onClick={onClickCap}\n />\n\n {box ? (\n <div\n className={\"ax-markup__box\" + (selected ? \" is-selected\" : \"\")}\n style={{ left: box.left, top: box.top, width: box.w, height: box.h }}\n >\n <span className=\"ax-markup__tag\">\n {box.label}\n {box.kind ? <span className=\"ax-markup__tagkind\"> · {box.kind}</span> : null}\n </span>\n </div>\n ) : null}\n\n {selected ? (\n <div className=\"ax-markup__pop\" style={popStyle()} onClick={(e) => e.stopPropagation()}>\n <div className=\"ax-markup__poptarget\">\n <Icon name=\"target\" size={13} />\n <span className=\"ax-markup__poptag\">\n {selected.label}\n {selected.kind ? ` · ${selected.kind}` : \"\"}\n </span>\n </div>\n <textarea\n className=\"ax-markup__ta\"\n autoFocus\n value={note}\n placeholder={placeholder}\n onChange={(e) => setNote(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n send();\n }\n }}\n />\n <div className=\"ax-markup__popbtns\">\n <button\n type=\"button\"\n className=\"ax-markup__cancel\"\n onClick={() => {\n setSelected(null);\n setNote(\"\");\n }}\n >\n 取消\n </button>\n <button\n type=\"button\"\n className=\"ax-markup__done\"\n disabled={!note.trim()}\n onClick={send}\n >\n 发送到对话\n <Icon name=\"arrow\" size={13} />\n </button>\n </div>\n </div>\n ) : null}\n\n <div className=\"ax-markup__pill\">\n <span className=\"ax-markup__dot\" />\n <span className=\"ax-markup__pilltxt\">{selected ? hintActive : hintIdle}</span>\n <span className=\"ax-markup__pillsep\" />\n <button\n type=\"button\"\n className=\"ax-markup__pillx\"\n onClick={() => onClose && onClose()}\n aria-label=\"退出\"\n >\n <Icon name=\"x\" size={14} />\n <span>退出</span>\n </button>\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Collapsible "how to get this credential" guide — auto-numbered steps and an
3
+ * optional external link. Built on the DS Collapsible. Steps accept rich nodes
4
+ * (e.g. <code> spans).
5
+ */
6
+ export interface HelpStepsLink {
7
+ href: string;
8
+ label: string;
9
+ }
10
+ export interface HelpStepsProps {
11
+ /** Collapsible trigger label. */
12
+ title: string;
13
+ /** Ordered steps; each may be a string or rich node. */
14
+ steps: React.ReactNode[];
15
+ /** Optional external link rendered under the steps. */
16
+ link?: HelpStepsLink;
17
+ /** @default false */
18
+ defaultOpen?: boolean;
19
+ }
20
+ export declare function HelpSteps(props: HelpStepsProps): JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import "react";
3
+ import { Collapsible } from "../display/Collapsible.js";
4
+ import { Icon } from "../utilities/Icon.js";
5
+ const AX_HELPSTEPS_CSS = `
6
+ .s-help { margin-top: 2px; }
7
+ .s-help__list { margin: 4px 0 6px; padding: 0; list-style: none; counter-reset: step; display: flex; flex-direction: column; gap: 11px; }
8
+ .s-help__item { display: flex; gap: 11px; font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-snug); }
9
+ .s-help__num { counter-increment: step; flex: none; width: 19px; height: 19px; border-radius: var(--radius-1);
10
+ border: 1px solid var(--border-strong); font-family: var(--font-mono); font-size: 10px; color: var(--text-faint);
11
+ display: flex; align-items: center; justify-content: center; }
12
+ .s-help__num::before { content: counter(step); }
13
+ .s-help__item code { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-body);
14
+ background: var(--surface-raised); border: 1px solid var(--border-default); border-radius: var(--radius-1); padding: 1px 5px; }
15
+ .s-help__link { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-sm); color: var(--text-body);
16
+ text-decoration: none; border-bottom: 1px solid var(--border-strong); padding-bottom: 1px; }
17
+ .s-help__link:hover { border-color: var(--text-body); }
18
+ `;
19
+ if (typeof document !== "undefined" && !document.getElementById("ax-helpsteps-css")) {
20
+ const s = document.createElement("style");
21
+ s.id = "ax-helpsteps-css";
22
+ s.textContent = AX_HELPSTEPS_CSS;
23
+ document.head.appendChild(s);
24
+ }
25
+ function HelpSteps({ title, steps = [], link, defaultOpen = false }) {
26
+ return /* @__PURE__ */ jsx("div", { className: "s-help", children: /* @__PURE__ */ jsxs(Collapsible, { label: title, defaultOpen, children: [
27
+ /* @__PURE__ */ jsx("ol", { className: "s-help__list", children: steps.map((st, i) => /* @__PURE__ */ jsxs("li", { className: "s-help__item", children: [
28
+ /* @__PURE__ */ jsx("span", { className: "s-help__num" }),
29
+ /* @__PURE__ */ jsx("span", { children: st })
30
+ ] }, i)) }),
31
+ link ? /* @__PURE__ */ jsxs("a", { className: "s-help__link", href: link.href, target: "_blank", rel: "noopener noreferrer", children: [
32
+ /* @__PURE__ */ jsx(Icon, { name: "external", size: 13 }),
33
+ link.label
34
+ ] }) : null
35
+ ] }) });
36
+ }
37
+ export {
38
+ HelpSteps
39
+ };
40
+ //# sourceMappingURL=HelpSteps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HelpSteps.js","sources":["../../../src/components/settings/HelpSteps.jsx"],"sourcesContent":["import React from \"react\";\nimport { Collapsible } from \"../display/Collapsible.jsx\";\nimport { Icon } from \"../utilities/Icon.jsx\";\n\n// HelpSteps — a collapsible \"如何获取…\" guide: numbered steps + an optional\n// external link. Built on the DS Collapsible. Steps may contain <code> spans.\nconst AX_HELPSTEPS_CSS = `\n.s-help { margin-top: 2px; }\n.s-help__list { margin: 4px 0 6px; padding: 0; list-style: none; counter-reset: step; display: flex; flex-direction: column; gap: 11px; }\n.s-help__item { display: flex; gap: 11px; font-size: var(--text-sm); color: var(--text-muted); line-height: var(--leading-snug); }\n.s-help__num { counter-increment: step; flex: none; width: 19px; height: 19px; border-radius: var(--radius-1);\n border: 1px solid var(--border-strong); font-family: var(--font-mono); font-size: 10px; color: var(--text-faint);\n display: flex; align-items: center; justify-content: center; }\n.s-help__num::before { content: counter(step); }\n.s-help__item code { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-body);\n background: var(--surface-raised); border: 1px solid var(--border-default); border-radius: var(--radius-1); padding: 1px 5px; }\n.s-help__link { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-sm); color: var(--text-body);\n text-decoration: none; border-bottom: 1px solid var(--border-strong); padding-bottom: 1px; }\n.s-help__link:hover { border-color: var(--text-body); }\n`;\n\nif (typeof document !== \"undefined\" && !document.getElementById(\"ax-helpsteps-css\")) {\n const s = document.createElement(\"style\");\n s.id = \"ax-helpsteps-css\";\n s.textContent = AX_HELPSTEPS_CSS;\n document.head.appendChild(s);\n}\n\nexport function HelpSteps({ title, steps = [], link, defaultOpen = false }) {\n return (\n <div className=\"s-help\">\n <Collapsible label={title} defaultOpen={defaultOpen}>\n <ol className=\"s-help__list\">\n {steps.map((st, i) => (\n <li className=\"s-help__item\" key={i}>\n <span className=\"s-help__num\"></span>\n <span>{st}</span>\n </li>\n ))}\n </ol>\n {link ? (\n <a className=\"s-help__link\" href={link.href} target=\"_blank\" rel=\"noopener noreferrer\">\n <Icon name=\"external\" size={13} />\n {link.label}\n </a>\n ) : null}\n </Collapsible>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;AAMA,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAezB,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,eAAe,kBAAkB,GAAG;AACnF,QAAM,IAAI,SAAS,cAAc,OAAO;AACxC,IAAE,KAAK;AACP,IAAE,cAAc;AAChB,WAAS,KAAK,YAAY,CAAC;AAC7B;AAEO,SAAS,UAAU,EAAE,OAAO,QAAQ,CAAA,GAAI,MAAM,cAAc,SAAS;AAC1E,SACE,oBAAC,SAAI,WAAU,UACb,+BAAC,aAAA,EAAY,OAAO,OAAO,aACzB,UAAA;AAAA,IAAA,oBAAC,MAAA,EAAG,WAAU,gBACX,UAAA,MAAM,IAAI,CAAC,IAAI,MACd,qBAAC,MAAA,EAAG,WAAU,gBACZ,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAU,cAAA,CAAc;AAAA,MAC9B,oBAAC,UAAM,UAAA,GAAA,CAAG;AAAA,IAAA,KAFsB,CAGlC,CACD,GACH;AAAA,IACC,OACC,qBAAC,KAAA,EAAE,WAAU,gBAAe,MAAM,KAAK,MAAM,QAAO,UAAS,KAAI,uBAC/D,UAAA;AAAA,MAAA,oBAAC,MAAA,EAAK,MAAK,YAAW,MAAM,IAAI;AAAA,MAC/B,KAAK;AAAA,IAAA,EAAA,CACR,IACE;AAAA,EAAA,EAAA,CACN,EAAA,CACF;AAEJ;"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Fullscreen integration modal: connect a DeepSeek key (conversation engine) and
3
+ * a Feishu Bitable (data sink). Self-persists to localStorage, reports a 0/2
4
+ * readiness state, and gates Save until both connect. Composes SecretField,
5
+ * StatusPill, TestRow, HelpSteps. The monthly usage-cap block is opt-in.
6
+ */
7
+ export interface IntegrationSettingsProps {
8
+ /** Close handler (Esc + the × button + overlay). */
9
+ onClose?: () => void;
10
+ /** Show the DeepSeek monthly usage-cap warning + toggle. @default true */
11
+ showUsageCap?: boolean;
12
+ /** localStorage key for the persisted config. @default "agentaily.integrations.v1" */
13
+ storageKey?: string;
14
+ }
15
+ export declare function IntegrationSettings(props: IntegrationSettingsProps): JSX.Element;