@drawnagency/primitives 0.1.68 → 0.1.69

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.
@@ -16,7 +16,7 @@ export declare function streamChat(body: {
16
16
  error: string;
17
17
  retryAfterMs?: number;
18
18
  }>;
19
- export default function ChatPanel({ open, onClose, siteName, tasks, isEditor, draftChatbot }: {
19
+ export default function ChatPanel({ open, onClose, siteName, tasks, isEditor, draftChatbot, variant }: {
20
20
  open: boolean;
21
21
  onClose: () => void;
22
22
  siteName: string;
@@ -25,7 +25,9 @@ export default function ChatPanel({ open, onClose, siteName, tasks, isEditor, dr
25
25
  label: string;
26
26
  }[];
27
27
  isEditor?: boolean;
28
- /** Set only by the configurator's test panel. */
28
+ /** Set by the configurator's test panel and the /edit chat FAB. */
29
29
  draftChatbot?: unknown;
30
+ /** Anchors the panel above its launcher: viewer corner FAB vs /edit FAB column. */
31
+ variant?: "viewer" | "editor";
30
32
  }): import("react/jsx-runtime").JSX.Element | null;
31
33
  //# sourceMappingURL=ChatPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../../src/components/chat/ChatPanel.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAoB5E,8EAA8E;AAC9E,wBAAsB,UAAU,CAC9B,IAAI,EAAE;IAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,EAC7F,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC7B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAyCjG;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE;IAC5F,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,kDAyEA"}
1
+ {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../../src/components/chat/ChatPanel.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAoB5E,8EAA8E;AAC9E,wBAAsB,UAAU,CAC9B,IAAI,EAAE;IAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,EAC7F,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAC7B,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAyCjG;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAkB,EAAE,EAAE;IAChH,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mEAAmE;IACnE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mFAAmF;IACnF,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC/B,kDA6EA"}
@@ -6,6 +6,9 @@ export interface ChatWidgetProps {
6
6
  label: string;
7
7
  }[];
8
8
  isEditor?: boolean;
9
+ /** Editor-only: chat against the current (unsaved) chatbot config. */
10
+ draftChatbot?: unknown;
11
+ variant?: "viewer" | "editor";
9
12
  }
10
- export default function ChatWidget({ siteName, tasks, isEditor }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
13
+ export default function ChatWidget({ siteName, tasks, isEditor, draftChatbot, variant }: ChatWidgetProps): import("react/jsx-runtime").JSX.Element;
11
14
  //# sourceMappingURL=ChatWidget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../../../src/components/chat/ChatWidget.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,eAAe,2CAuBhF"}
1
+ {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../../../src/components/chat/ChatWidget.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC/B;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAkB,EAAE,EAAE,eAAe,2CAoClH"}
@@ -1 +1 @@
1
- {"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../../../src/components/shell/EditorShell.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAyEjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQxD,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAIhB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,OAAO,CAAC;QACxB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,GAAG,IAAI,CAAC;IAIhE,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,OAAO,EACP,YAAY,EACZ,MAAM,EACN,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EACZ,WAAW,EACX,sBAA8B,GAC/B,EAAE,KAAK,2CAm7BP"}
1
+ {"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../../../src/components/shell/EditorShell.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AA0EjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAQxD,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAIhB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,OAAO,CAAC;QACxB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,GAAG,IAAI,CAAC;IAIhE,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,OAAO,EACP,YAAY,EACZ,MAAM,EACN,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EACZ,WAAW,EACX,sBAA8B,GAC/B,EAAE,KAAK,2CAi8BP"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawnagency/primitives",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./package.json": "./package.json",
@@ -68,14 +68,16 @@ export async function streamChat(
68
68
  }
69
69
  }
70
70
 
71
- export default function ChatPanel({ open, onClose, siteName, tasks, isEditor, draftChatbot }: {
71
+ export default function ChatPanel({ open, onClose, siteName, tasks, isEditor, draftChatbot, variant = "viewer" }: {
72
72
  open: boolean;
73
73
  onClose: () => void;
74
74
  siteName: string;
75
75
  tasks: { id: string; label: string }[];
76
76
  isEditor?: boolean;
77
- /** Set only by the configurator's test panel. */
77
+ /** Set by the configurator's test panel and the /edit chat FAB. */
78
78
  draftChatbot?: unknown;
79
+ /** Anchors the panel above its launcher: viewer corner FAB vs /edit FAB column. */
80
+ variant?: "viewer" | "editor";
79
81
  }) {
80
82
  const [messages, setMessages] = useState<ChatMessage[]>([]);
81
83
  const [taskId, setTaskId] = useState<string>("");
@@ -114,7 +116,11 @@ export default function ChatPanel({ open, onClose, siteName, tasks, isEditor, dr
114
116
 
115
117
  return (
116
118
  <div role="dialog" aria-label={`Chat with ${siteName}`}
117
- className="fixed bottom-20 right-4 z-40 flex h-[28rem] w-80 flex-col rounded-lg border border-base-200 bg-base shadow-xl">
119
+ className={cn(
120
+ "fixed z-40 flex h-[28rem] w-80 flex-col rounded-lg border border-base-200 bg-base shadow-xl",
121
+ variant === "editor" ? "bottom-40 right-4 lg:right-auto fab-container-right" : "bottom-20 right-4",
122
+ )}>
123
+
118
124
  <div className="flex items-center justify-between gap-2 border-b border-base-200 px-3 py-2">
119
125
  <span className="text-sm font-medium text-base-contrast">{siteName} assistant</span>
120
126
  {tasks.length > 0 && (
@@ -1,7 +1,14 @@
1
- // Viewer-facing chat launcher. Renders ONLY the floating button until first
2
- // open; the panel (and its code) loads lazily so viewers who never click pay
3
- // almost nothing. Browser-safe: no node imports, no process.env.
1
+ // Chat launcher FAB. Renders ONLY the floating button until first open; the
2
+ // panel (and its code) loads lazily so viewers who never click pay almost
3
+ // nothing. Browser-safe: no node imports, no process.env.
4
+ //
5
+ // Two placements:
6
+ // - "viewer" (default): bottom-right corner of viewer pages.
7
+ // - "editor": stacked above the /edit route's existing FAB column (edit-mode
8
+ // toggle at bottom-4, bug report at bottom-16), aligned to the content edge
9
+ // via fab-container-right like its neighbors.
4
10
  import { lazy, Suspense, useState } from "react";
11
+ import { cn } from "../../lib/cn";
5
12
 
6
13
  const ChatPanel = lazy(() => import("./ChatPanel"));
7
14
 
@@ -10,9 +17,12 @@ export interface ChatWidgetProps {
10
17
  /** Already audience-filtered server-side — never pass unfiltered config tasks. */
11
18
  tasks: { id: string; label: string }[];
12
19
  isEditor?: boolean;
20
+ /** Editor-only: chat against the current (unsaved) chatbot config. */
21
+ draftChatbot?: unknown;
22
+ variant?: "viewer" | "editor";
13
23
  }
14
24
 
15
- export default function ChatWidget({ siteName, tasks, isEditor }: ChatWidgetProps) {
25
+ export default function ChatWidget({ siteName, tasks, isEditor, draftChatbot, variant = "viewer" }: ChatWidgetProps) {
16
26
  const [open, setOpen] = useState(false);
17
27
  const [everOpened, setEverOpened] = useState(false);
18
28
 
@@ -22,15 +32,28 @@ export default function ChatWidget({ siteName, tasks, isEditor }: ChatWidgetProp
22
32
  type="button"
23
33
  aria-label={`Chat with ${siteName}`}
24
34
  onClick={() => { setOpen((o) => !o); setEverOpened(true); }}
25
- className="fixed bottom-4 right-4 z-40 flex h-12 w-12 items-center justify-center rounded-full bg-primary text-primary-contrast shadow-lg hover:opacity-90 transition-opacity"
35
+ className={cn(
36
+ "fixed z-40 flex items-center justify-center rounded-full bg-primary text-primary-contrast shadow-lg hover:opacity-90 transition-opacity",
37
+ variant === "editor"
38
+ ? "bottom-28 right-4 lg:right-auto h-10 w-10 fab-container-right"
39
+ : "bottom-4 right-4 h-12 w-12",
40
+ )}
26
41
  >
27
- <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
42
+ <svg xmlns="http://www.w3.org/2000/svg" className={variant === "editor" ? "h-5 w-5" : "h-6 w-6"} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
28
43
  <path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z" />
29
44
  </svg>
30
45
  </button>
31
46
  {everOpened && (
32
47
  <Suspense fallback={null}>
33
- <ChatPanel open={open} onClose={() => setOpen(false)} siteName={siteName} tasks={tasks} isEditor={isEditor} />
48
+ <ChatPanel
49
+ open={open}
50
+ onClose={() => setOpen(false)}
51
+ siteName={siteName}
52
+ tasks={tasks}
53
+ isEditor={isEditor}
54
+ draftChatbot={draftChatbot}
55
+ variant={variant}
56
+ />
34
57
  </Suspense>
35
58
  )}
36
59
  </>
@@ -20,6 +20,7 @@ import { EditorModalProvider, useEditorModal } from "./EditorModalContext";
20
20
  import { EditorModal } from "./EditorModal";
21
21
  import { SiteSettingsModal } from "./SiteSettingsModal";
22
22
  import { ChatbotConfigModal } from "./ChatbotConfigModal";
23
+ import ChatWidget from "../chat/ChatWidget";
23
24
  import { MediaLibraryModal } from "./MediaLibraryModal";
24
25
  import { MediaLibraryContext } from "./MediaLibraryContext";
25
26
  import { ProcessingIndicator } from "./ProcessingIndicator";
@@ -902,6 +903,20 @@ export default function EditorShell({
902
903
  the button would always 401 — hide it there. */}
903
904
  {!capabilities.passwordOnly && <BugReportFAB />}
904
905
 
906
+ {/* Editor chat FAB: chat while editing, against the DRAFT chatbot
907
+ config (tasks + prompt reflect unsaved changes; grounding is
908
+ published content). Gated only on the platform switch — editors
909
+ may chat before the widget is enabled for viewers. */}
910
+ {chatbotPlatformEnabled && siteConfig && (
911
+ <ChatWidget
912
+ siteName={siteConfig.siteName}
913
+ tasks={siteConfig.chatbot.tasks.map((t) => ({ id: t.id, label: t.label }))}
914
+ isEditor
915
+ draftChatbot={siteConfig.chatbot}
916
+ variant="editor"
917
+ />
918
+ )}
919
+
905
920
  {rejectedUploads.length > 0 && (
906
921
  <div className="sticky top-2 z-30 mx-auto w-full max-w-3xl px-4">
907
922
  <UploadRejectionAlert