@papermap/papermap 1.0.4 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papermap/papermap",
3
- "version": "1.0.4",
3
+ "version": "1.1.1",
4
4
  "description": "Embeddable AI chat bar and UI components from the Papermap data analytics platform",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -22,8 +22,10 @@
22
22
  "styles.css"
23
23
  ],
24
24
  "scripts": {
25
+ "sync:sdk-version": "node scripts/sync-sdk-version.mjs",
26
+ "prebuild": "npm run sync:sdk-version",
25
27
  "build": "tsup && npm run build:styles",
26
- "build:styles": "cp src/styles.css styles.css",
28
+ "build:styles": "cat node_modules/driver.js/dist/driver.css src/tour-overrides.css src/styles.css > styles.css",
27
29
  "dev": "tsup --watch",
28
30
  "storybook": "storybook dev -p 3001",
29
31
  "build-storybook": "storybook build",
@@ -32,8 +34,11 @@
32
34
  "format": "prettier --write \"src/**/*.{ts,tsx}\"",
33
35
  "format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
34
36
  "test": "vitest run",
37
+ "test:unit": "vitest run --project unit",
38
+ "test:storybook": "vitest run --project storybook",
39
+ "test:integration": "vitest run --project integration",
35
40
  "test:watch": "vitest",
36
- "validate": "npm run lint && npm run ts-check",
41
+ "validate": "npm run lint && npm run ts-check && npm run test",
37
42
  "validate:watch": "npm run validate -- --watch",
38
43
  "clean": "rm -rf dist styles.css",
39
44
  "prepare": "husky || true",
@@ -52,11 +57,15 @@
52
57
  "react-dom": ">=18"
53
58
  },
54
59
  "dependencies": {
60
+ "@dicebear/collection": "^9.2.2",
61
+ "@dicebear/core": "^9.2.2",
62
+ "@radix-ui/react-avatar": "^1.1.2",
55
63
  "@radix-ui/react-collapsible": "^1.1.12",
56
64
  "@radix-ui/react-dialog": "^1.1.15",
57
65
  "@radix-ui/react-dropdown-menu": "^2.1.16",
58
66
  "@radix-ui/react-hover-card": "^1.1.15",
59
67
  "@radix-ui/react-icons": "^1.3.2",
68
+ "@radix-ui/react-popover": "^1.1.15",
60
69
  "@radix-ui/react-select": "^2.2.6",
61
70
  "@radix-ui/react-separator": "^1.1.8",
62
71
  "@radix-ui/react-slider": "^1.3.6",
@@ -69,10 +78,12 @@
69
78
  "axios": "1.8.2",
70
79
  "class-variance-authority": "^0.7.1",
71
80
  "clsx": "^2.1.1",
81
+ "driver.js": "^1.4.0",
72
82
  "framer-motion": "^11.17.0",
73
83
  "html2canvas": "^1.4.1",
74
84
  "lottie-react": "^2.4.1",
75
85
  "lucide-react": "^0.460.0",
86
+ "next-themes": "^0.4.6",
76
87
  "react-grid-layout": "^1.4.4",
77
88
  "react-markdown": "^10.1.0",
78
89
  "react-resizable": "^3.0.5",
@@ -86,9 +97,11 @@
86
97
  "devDependencies": {
87
98
  "@changesets/cli": "^2.29.7",
88
99
  "@storybook/addon-essentials": "^8.6.14",
100
+ "@storybook/addon-interactions": "^8.6.18",
89
101
  "@storybook/blocks": "^8.6.14",
90
102
  "@storybook/react": "^8.6.18",
91
103
  "@storybook/react-vite": "^8.6.18",
104
+ "@storybook/test": "^8.6.18",
92
105
  "@testing-library/jest-dom": "^6.9.1",
93
106
  "@testing-library/react": "^16.3.2",
94
107
  "@testing-library/user-event": "^14.6.1",
package/readme.md CHANGED
@@ -8,20 +8,52 @@ For **server-side setup** (HMAC auth, dashboards per tenant, embed tokens, API e
8
8
 
9
9
  ## Main components
10
10
 
11
- - **`PaperChat`** — Full AI chat assistant with streaming, conversation history, and chart generation.
11
+ - **`PaperChat`** — Full AI chat assistant with streaming, conversation history, and chart generation. Supports four layouts: **default** (floating toolbar + modal assistant), **side** (fixed side panel for sheet-style pages), **floating** (chart preview overlay), and **dialog** (tawk.to-style floating launcher + popup chat widget).
12
12
  - **`PaperCard`** — Standalone chart card with toolbar actions. Use `variant="streaming"` for an embedded chart + conversation dialog (without the floating assistant).
13
13
  - **`PaperBoard`** — Responsive grid layout of chart cards, toolbar (screenshot, generate dashboard, theme), optional chat assistant, and controlled or uncontrolled layouts.
14
14
 
15
15
  ```tsx
16
16
  import { PaperChat, PaperCard, PaperBoard } from '@papermap/papermap'
17
17
 
18
- // AI chat assistant
18
+ // Default: floating toolbar + expandable assistant (dashboard-style)
19
19
  <PaperChat
20
20
  token="your-base64-api-token"
21
21
  workspaceId="your-workspace-id"
22
22
  dashboardId="your-dashboard-id"
23
23
  />
24
24
 
25
+ // Side panel (controlled open state; typical for sheet / narrow layouts)
26
+ <PaperChat
27
+ variant="side"
28
+ token="..."
29
+ workspaceId="..."
30
+ dashboardId="..."
31
+ open={sideOpen}
32
+ onOpenChange={setSideOpen}
33
+ />
34
+
35
+ // Floating chart overlay (preview over your content)
36
+ <PaperChat
37
+ variant="floating"
38
+ token="..."
39
+ workspaceId="..."
40
+ dashboardId="..."
41
+ open={overlayOpen}
42
+ onOpenChange={setOverlayOpen}
43
+ />
44
+
45
+ // Dialog (live-chat widget: floating launcher + popup; outside-click is ignored,
46
+ // closes only via the X button or by clicking the launcher again)
47
+ <PaperChat
48
+ variant="dialog"
49
+ token="..."
50
+ workspaceId="..."
51
+ dashboardId="..."
52
+ title="Support"
53
+ subtitle="Ask anything about your data"
54
+ launcherPosition="bottom-right"
55
+ />
56
+
25
57
  // Standalone chart card
26
58
  <PaperCard
27
59
  token="your-base64-api-token"
@@ -125,21 +157,125 @@ function App() {
125
157
 
126
158
  #### `PaperChat` props
127
159
 
128
- | Prop | Type | Required | Default | Description |
129
- | ------------- | ------------------- | -------- | ----------------------------- | ------------------------------------ |
130
- | `token` | `string` | Yes\* | -- | Base64-encoded API key token |
131
- | `workspaceId` | `string` | Yes\* | -- | Workspace ID |
132
- | `dashboardId` | `string` | Yes\* | -- | Dashboard ID |
133
- | `apiUrl` | `string` | No | `https://dataapi.papermap.ai` | API base URL |
134
- | `theme` | `'light' \| 'dark'` | No | -- | Force light or dark theme |
135
- | `placeholder` | `string` | No | `"Ask anything..."` | Input placeholder text |
136
- | `shortcutKey` | `string` | No | `"k"` | Keyboard shortcut (Cmd/Ctrl + key) |
137
- | `autoFade` | `boolean` | No | `false` | Fade toolbar after inactivity |
138
- | `fadeDelay` | `number` | No | `5000` | Milliseconds before auto-fade |
139
- | `className` | `string` | No | -- | Extra CSS class on toolbar container |
160
+ | Prop | Type | Required | Default | Description |
161
+ | --------------------------- | -------------------------------------------------------------- | ----------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
162
+ | `variant` | `'default' \| 'side' \| 'floating' \| 'dialog'` | No | `'default'` | Layout: floating dashboard chat, fixed side panel, chart overlay, or popup widget. |
163
+ | `token` | `string` | Yes\* | -- | Base64-encoded API key token |
164
+ | `workspaceId` | `string` | Yes\* | -- | Workspace ID |
165
+ | `dashboardId` | `string` | Yes\* | -- | Dashboard ID |
166
+ | `apiUrl` | `string` | No | `https://dataapi.papermap.ai` | API base URL |
167
+ | `placeholder` | `string` | No | `"Ask anything..."` | Input placeholder (default variant) |
168
+ | `shortcutKey` | `string` | No | `"k"` | Focus shortcut (Cmd/Ctrl + key, default variant) |
169
+ | `autoFade` | `boolean` | No | `false` | Fade toolbar after inactivity (default variant) |
170
+ | `fadeDelay` | `number` | No | `5000` | Milliseconds before auto-fade |
171
+ | `className` | `string` | No | -- | Extra CSS class on toolbar container (default variant) |
172
+ | `showToolbar` | `boolean` | No | `true` | Show the bottom chat toolbar (default variant) |
173
+ | `hideChartArea` | `boolean` | No | `false` | Hides chart preview regions where applicable |
174
+ | `onToolbarHeightChange` | `(height: number) => void` | No | -- | Fired when toolbar height changes (e.g. multiline input) |
175
+ | `onAssistantClose` | `() => void` | No | -- | Fired when the floating assistant panel closes (default variant) |
176
+ | `initialChatScroll` | `'top' \| 'bottom'` | No | -- | Conversation scroll anchoring; `top` matches main-app onboarding |
177
+ | `isViewer` | `boolean` | No | -- | Hides bookmark actions (viewer workspaces); use provider when nested |
178
+ | `showAvatars` | `boolean` | No | see below | Hide message-row avatars when `false`. When omitted on **`variant="default"`**, `ChatAssistant` shows avatars whenever the layout is not inline (`assistantInline` in the store, default `false`). **`variant="side"`** and **`variant="dialog"`** default to showing avatars (`true`). |
179
+ | `avatars` | `PaperChatAvatars` | No | -- | Replace the user / assistant / “thinking” icons in each message row (see [Chat assistant customization](#chat-assistant-customization)). |
180
+ | `assistantInline` | `boolean` | No | -- | Inline assistant layout; for `variant="side"` defaults to `true` |
181
+ | `open` | `boolean` | Yes† / Yes‡ | -- | Surface open: **`side`** rail, **`floating`** overlay, **`dialog`** modal (see `onOpenChange`) |
182
+ | `onOpenChange` | `(open: boolean) => void` | Yes† / Yes‡ | -- | Toggle for **`side`**, **`floating`**, and **`dialog`** |
183
+ | `onChartVisibilityChange` | `(visible: boolean) => void` | No | -- | Sheet: chart overlay visibility |
184
+ | `chartOverlayPortalRef` | `RefObject<HTMLDivElement \| null>` | No | -- | Optional portal target for chart overlay |
185
+ | `onPendingSheetEditsChange` | `(edits: { edit_session_id?: string }[]) => void` | No | -- | Sheet: pending edit sessions |
186
+ | `clearPendingSheetEditsRef` | `MutableRefObject<(() => void) \| null>` | No | -- | Ref to clear pending edits |
187
+ | `visible` | `boolean` | No | -- | **Deprecated.** Use **`open`** for `variant="floating"`. |
188
+ | `onClose` | `() => void` | No | -- | **Deprecated.** Use **`onOpenChange(false)`** for `variant="floating"`; still called after `onOpenChange` on close if both are passed. |
189
+ | `historyOpen` | `boolean` | No | -- | Show chart history in overlay instead of chat column |
190
+ | `onCloseHistory` | `() => void` | No | -- | Close history sub-view in overlay |
191
+ | `title` | `string` | No | `"Chat"` | Dialog header title (`variant="dialog"`) |
192
+ | `subtitle` | `string` | No | ask-anything hint | Dialog header subtitle (`variant="dialog"`) |
193
+ | `showLauncher` | `boolean` | No | `true` | Render the floating launcher (`variant="dialog"`) |
194
+ | `launcherAriaLabel` | `string` | No | `"Open chat"` | Accessible label for the launcher (`variant="dialog"`) |
195
+ | `launcherPosition` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | No | `'bottom-right'` | Viewport corner for the launcher (`variant="dialog"`) |
196
+ | `dialogTitle` | `string` | No | -- | **Deprecated.** Use **`title`**. |
197
+ | `dialogSubtitle` | `string` | No | -- | **Deprecated.** Use **`subtitle`**. |
198
+ | `dialogOpen` | `boolean` | No | -- | **Deprecated.** Use **`open`** for controlled dialog. |
199
+ | `onDialogOpenChange` | `(open: boolean) => void` | No | -- | **Deprecated.** Use **`onOpenChange`**. |
200
+ | `showDialogLauncher` | `boolean` | No | -- | **Deprecated.** Use **`showLauncher`**. |
201
+ | `dialogLauncherAriaLabel` | `string` | No | -- | **Deprecated.** Use **`launcherAriaLabel`**. |
202
+ | `dialogLauncherPosition` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | No | -- | **Deprecated.** Use **`launcherPosition`**. |
140
203
 
141
204
  \*Omit on the component when values come from `PapermapConfigProvider` / `PapermapProvider`.
142
205
 
206
+ †Required when `variant` is `"side"`. ‡For `variant="floating"`, pass **`open`** + **`onOpenChange`** (or the deprecated **`visible`** + **`onClose`**).
207
+
208
+ #### Chat assistant customization
209
+
210
+ The transcript UI is implemented by **`ChatAssistant`** (also exported for custom layouts). **`PaperChat`** forwards branding-related props on every variant except **`floating`** (that variant is chart-first and does not expose these).
211
+
212
+ ##### Avatars (`PaperChatAvatars`)
213
+
214
+ Import the type and pass an `avatars` object on **`PaperChat`**, **`PaperChatSidePanel`** / **`ChatSidePanel`**, or **`PaperChatDialogInner`**:
215
+
216
+ ```tsx
217
+ import { PaperChat, type PaperChatAvatars } from '@papermap/papermap'
218
+
219
+ const avatars: PaperChatAvatars = {
220
+ user: <span className="text-xs font-bold text-primary-foreground">ME</span>,
221
+ assistant: <img src="/your-product-mark.svg" alt="" className="h-4 w-4" />,
222
+ thinking: <img src="/your-spinner-or-mark.svg" alt="" className="h-4 w-4" />,
223
+ }
224
+
225
+ <PaperChat
226
+ token="..."
227
+ workspaceId="..."
228
+ dashboardId="..."
229
+ avatars={avatars}
230
+ />
231
+ ```
232
+
233
+ Each slot replaces **only the inner icon**. The outer **32px circular** affordance (background colors, alignment) stays the same—size custom icons for parity with the defaults.
234
+
235
+ ##### Showing or hiding avatars
236
+
237
+ Set **`showAvatars={false}`** for a denser transcript without avatar columns.
238
+
239
+ When **`showAvatars` is omitted** on **`variant="default"`**, visibility is handled inside **`ChatAssistant`**: avatars show unless the assistant is in **inline** column mode (`assistantInline` in the store). With **`variant="side"`** or **`variant="dialog"`**, omitting **`showAvatars`** defaults to **`true`**.
240
+
241
+ If you compose **`ChatAssistant`** yourself with **`inline`** (compact column layout), avatars are **hidden by default** unless you pass **`showAvatars={true}`**—matching the main app’s compact sidebar behavior.
242
+
243
+ ##### Dialog variant: floating launcher “button”
244
+
245
+ For **`variant="dialog"`**, the launcher is a fixed circular control portaled to **`document.body`** (MessageSquare icon). You can:
246
+
247
+ - Move it with **`launcherPosition`** (`bottom-right` \| `bottom-left` \| `top-right` \| `top-left`).
248
+ - Change the accessible name with **`launcherAriaLabel`** (also used as the native **`title`** tooltip on the launcher).
249
+ - Hide it with **`showLauncher={false}`** and drive the popup yourself via **`open`** / **`onOpenChange`** from your own button elsewhere in the host UI.
250
+
251
+ Legacy names (`dialogLauncherPosition`, `dialogLauncherAriaLabel`, `showDialogLauncher`, `dialogOpen`, `onDialogOpenChange`, `dialogTitle`, `dialogSubtitle`) still work; **`open`**, **`title`**, and the other canonical props take precedence when both are set.
252
+
253
+ ##### Side variant: custom open trigger
254
+
255
+ When **`variant="side"`** and the panel is closed, pass **`renderSidePanelOpenTrigger`** to render your own control. It receives **`{ open, show, toggle }`** so you can wire a menu item, FAB, or icon button while **`open`** / **`onOpenChange`** remain the source of truth.
256
+
257
+ ```tsx
258
+ <PaperChat
259
+ variant="side"
260
+ token="..."
261
+ workspaceId="..."
262
+ dashboardId="..."
263
+ open={open}
264
+ onOpenChange={setOpen}
265
+ renderSidePanelOpenTrigger={({ toggle }) => (
266
+ <button type="button" className="your-menu-styles" onClick={toggle}>
267
+ Open assistant
268
+ </button>
269
+ )}
270
+ />
271
+ ```
272
+
273
+ ##### Advanced composition
274
+
275
+ Use **`PapermapProvider`** (or **`PapermapConfigProvider`**) and render **`ChatAssistant`** with **`avatars`**, **`showAvatars`**, **`inline`**, and **`hideChartArea`** as needed—the same props **`PaperChat`** uses internally.
276
+
277
+ Prefer **`PaperChat`** with `variant` for a single integration path. If you already wrap subtrees in `PapermapProvider`, you can compose **`PaperChatSidePanel`** or **`PaperChatFloatingChartOverlay`** directly (they reuse the parent store when present, or create a provider when not).
278
+
143
279
  #### `PaperCard` props
144
280
 
145
281
  | Prop | Type | Required | Default | Description |
@@ -234,9 +370,315 @@ export function EmbeddedStreamingChart() {
234
370
 
235
371
  ---
236
372
 
373
+ ## Examples
374
+
375
+ Every example below has a matching Storybook story — run `npm run storybook` (http://localhost:3001) to see it live. Replace the `'...'` placeholders with your own `token` / `workspaceId` / `dashboardId`, or supply them once via `PapermapConfigProvider` / `PapermapProvider`. Controlled examples use React `useState`.
376
+
377
+ ### PaperChat
378
+
379
+ #### Auto-fading toolbar
380
+
381
+ Fade the floating toolbar after a period of inactivity.
382
+
383
+ ```tsx
384
+ <PaperChat token="..." workspaceId="..." dashboardId="..." autoFade fadeDelay={3000} />
385
+ ```
386
+
387
+ #### Custom placeholder and focus shortcut
388
+
389
+ ```tsx
390
+ <PaperChat
391
+ token="..."
392
+ workspaceId="..."
393
+ dashboardId="..."
394
+ placeholder="Ask about your data..."
395
+ shortcutKey="j"
396
+ />
397
+ ```
398
+
399
+ #### Side panel (controlled)
400
+
401
+ Fixed-width rail for sheet-style pages. `open` / `onOpenChange` are required.
402
+
403
+ ```tsx
404
+ function SidePanelExample() {
405
+ const [open, setOpen] = useState(true)
406
+ return (
407
+ <div className="flex h-screen min-h-0">
408
+ <PaperChat
409
+ variant="side"
410
+ token="..."
411
+ workspaceId="..."
412
+ dashboardId="..."
413
+ sidePosition="left"
414
+ sideContentInsetMode="auto"
415
+ open={open}
416
+ onOpenChange={setOpen}
417
+ className="h-full min-h-0 shrink-0"
418
+ />
419
+ <main className="min-h-0 min-w-0 flex-1 overflow-auto">Your page</main>
420
+ </div>
421
+ )
422
+ }
423
+ ```
424
+
425
+ `sideContentInsetMode="auto"` places the panel in a flex row beside your main column; `"none"` keeps it viewport-fixed and overlays content. `sidePosition` docks it `left` or `right`.
426
+
427
+ #### Floating chart overlay
428
+
429
+ ```tsx
430
+ function FloatingExample() {
431
+ const [open, setOpen] = useState(true)
432
+ return (
433
+ <PaperChat
434
+ variant="floating"
435
+ token="..."
436
+ workspaceId="..."
437
+ dashboardId="..."
438
+ open={open}
439
+ onOpenChange={setOpen}
440
+ />
441
+ )
442
+ }
443
+ ```
444
+
445
+ #### Dialog widget (floating launcher)
446
+
447
+ ```tsx
448
+ <PaperChat
449
+ variant="dialog"
450
+ token="..."
451
+ workspaceId="..."
452
+ dashboardId="..."
453
+ title="Ask Alan"
454
+ subtitle="Continue your conversation about this report"
455
+ launcherAriaLabel="Open chat"
456
+ launcherPosition="bottom-right"
457
+ />
458
+ ```
459
+
460
+ #### Dialog widget (controlled, no launcher)
461
+
462
+ Hide the built-in launcher and drive the popup from your own button.
463
+
464
+ ```tsx
465
+ function ControlledDialog() {
466
+ const [open, setOpen] = useState(false)
467
+ return (
468
+ <>
469
+ <button type="button" onClick={() => setOpen(true)}>
470
+ Open chat
471
+ </button>
472
+ <PaperChat
473
+ variant="dialog"
474
+ token="..."
475
+ workspaceId="..."
476
+ dashboardId="..."
477
+ title="Support"
478
+ open={open}
479
+ onOpenChange={setOpen}
480
+ showLauncher={false}
481
+ />
482
+ </>
483
+ )
484
+ }
485
+ ```
486
+
487
+ ### PaperCard
488
+
489
+ These examples pass a preloaded `chart` (a `TChartResponse`) — see [Pre-loaded chart](#papercard-props) above for the shape.
490
+
491
+ #### Streaming card with a preloaded chart
492
+
493
+ `variant="streaming"` with `chart` data skips the API round-trip.
494
+
495
+ ```tsx
496
+ <PaperCard token="..." workspaceId="..." dashboardId="..." variant="streaming" chart={chart} />
497
+ ```
498
+
499
+ #### Standalone streaming card (no chart yet)
500
+
501
+ Pass a stable `id` and no `chartId` — the card shows an empty state and does not call the chart API until a link exists.
502
+
503
+ ```tsx
504
+ <PaperCard
505
+ token="..."
506
+ workspaceId="..."
507
+ dashboardId="..."
508
+ variant="streaming"
509
+ id="my-card-1"
510
+ onSave={(chart) => console.log('Saved', chart)}
511
+ />
512
+ ```
513
+
514
+ #### Wide table card
515
+
516
+ ```tsx
517
+ <PaperCard token="..." workspaceId="..." dashboardId="..." chart={tableChart} wide />
518
+ ```
519
+
520
+ #### Showing the variant selector
521
+
522
+ The chart variation combobox is hidden by default (`hideVariants` is `true`).
523
+
524
+ ```tsx
525
+ <PaperCard token="..." workspaceId="..." dashboardId="..." chart={chart} hideVariants={false} />
526
+ ```
527
+
528
+ #### Scoped dashboard theme
529
+
530
+ ```tsx
531
+ <PaperCard
532
+ token="..."
533
+ workspaceId="..."
534
+ dashboardId="..."
535
+ chart={chart}
536
+ dashboardTheme={{
537
+ primary: '#0f766e',
538
+ secondary: '#64748b',
539
+ interactive: '#14b8a6',
540
+ container: '#f0fdfa',
541
+ module: '#ffffff',
542
+ accent: '#ccfbf1',
543
+ outline: '#99f6e4',
544
+ dialog: '#ffffff',
545
+ fontFamily: 'Inter',
546
+ borderRadius: 0.75,
547
+ }}
548
+ />
549
+ ```
550
+
551
+ #### Streaming lifecycle hooks
552
+
553
+ Refetch host state after a chart is pinned or the embedded assistant closes.
554
+
555
+ ```tsx
556
+ <PaperCard
557
+ token="..."
558
+ workspaceId="..."
559
+ dashboardId="..."
560
+ variant="streaming"
561
+ chart={chart}
562
+ onPinnedToDashboard={(chart) => console.log('Pinned', chart)}
563
+ onAssistantClosed={() => console.log('Assistant closed')}
564
+ />
565
+ ```
566
+
567
+ ### PaperBoard
568
+
569
+ #### Default streaming grid
570
+
571
+ ```tsx
572
+ <PaperBoard token="..." workspaceId="..." dashboardId="..." variant="streaming" showToolbar />
573
+ ```
574
+
575
+ #### With app chrome and chat assistant
576
+
577
+ `showAppChrome` adds the dashboard header + tab bar (off by default).
578
+
579
+ ```tsx
580
+ <PaperBoard
581
+ token="..."
582
+ workspaceId="..."
583
+ dashboardId="..."
584
+ variant="streaming"
585
+ showAppChrome
586
+ showToolbar
587
+ showChatAssistant
588
+ />
589
+ ```
590
+
591
+ #### Embed mode (no app chrome)
592
+
593
+ ```tsx
594
+ <PaperBoard
595
+ token="..."
596
+ workspaceId="..."
597
+ dashboardId="..."
598
+ variant="streaming"
599
+ showAppChrome={false}
600
+ showToolbar
601
+ />
602
+ ```
603
+
604
+ #### Static charts without fetching
605
+
606
+ `enableFetch={false}` renders the supplied `charts` + `layouts` and skips the API. `layouts` is keyed per breakpoint (`lg` / `md` / `sm` / `xs` / `xxs`).
607
+
608
+ ```tsx
609
+ <PaperBoard
610
+ token="..."
611
+ workspaceId="..."
612
+ dashboardId="..."
613
+ variant="streaming"
614
+ enableFetch={false}
615
+ charts={charts}
616
+ layouts={layouts}
617
+ showToolbar
618
+ showHeader={false}
619
+ />
620
+ ```
621
+
622
+ #### Minimal toolbar
623
+
624
+ ```tsx
625
+ <PaperBoard
626
+ token="..."
627
+ workspaceId="..."
628
+ dashboardId="..."
629
+ variant="streaming"
630
+ showToolbar
631
+ showScreenshot={false}
632
+ showGenerateDashboard={false}
633
+ />
634
+ ```
635
+
636
+ #### Dashboard tour control
637
+
638
+ Adds an opt-in tour button to the header (does not auto-start).
639
+
640
+ ```tsx
641
+ <PaperBoard
642
+ token="..."
643
+ workspaceId="..."
644
+ dashboardId="..."
645
+ variant="streaming"
646
+ showToolbar
647
+ showDashboardTour
648
+ autoStartDashboardTour={false}
649
+ />
650
+ ```
651
+
652
+ ---
653
+
237
654
  ## Advanced exports
238
655
 
239
- For custom layouts, the package also exports subcomponents (for example `ChatAssistant`, `StreamingChartDialog`, `ChartView`, `DataTable`), Zustand store helpers (`usePapermapStore`, `createPapermapStore`), hooks (`useAnalyticsStream`, …), API helpers (`createApiClient`, `decodeToken`, `buildAuthHeaders`), streaming and chart types, **theme presets** (`themePresets`, `defaultTheme`, `ThemeCustomizationSettings`), and **chart card id ↔ chat id** persistence helpers (`getChartCardIdLink`, `resolveChartFetchChatId`, …). Import paths are the same as the main entry: `@papermap/papermap`.
656
+ For custom layouts, the package also exports:
657
+
658
+ - **Composition:** `ChatAssistant`, `PaperChatSidePanel` / `ChatSidePanel` (alias), `PaperChatFloatingChartOverlay` / `FloatingChartOverlay` (alias), `StreamingChartDialog`, `StreamingChatPanel`, `StreamingTimeline`, `ChartView`, `DataTable`, dashboard panels (`RecentConversations`, `ChartHistory`, `ToolCallDisplay`, …).
659
+ - **Store:** `usePapermapStore`, `usePapermapStoreApi`, `createPapermapStore`, `PapermapProvider`, `CHAT_MODAL_TAB`, and **`openPapermapChatAssistant(storeApi, options?)`** — opens/focuses the assistant and optionally primes edit mode from a chart (`editChartId`, `chart`, `suppressOpen` for embedded streaming UIs).
660
+ - **Hooks:** `useAnalyticsStream`, `useKeyboardShortcuts`, `useAutoResize`, `useAutoFade`, `useTour`, …
661
+ - **API:** `createApiClient`, `decodeToken`, `buildAuthHeaders`, `papermapQueryKeys`
662
+ - **Types:** streaming (`TimelineEvent`, `ToolCall`, …), charts (`TChartResponse`, …), messages
663
+ - **Theming:** `themePresets`, `defaultTheme`, `ThemeCustomizationSettings`
664
+ - **Persistence:** chart card `id` ↔ backend chat id helpers (`getChartCardIdLink`, `resolveChartFetchChatId`, …)
665
+ - **Platform (hosts / extensions):** `PAPERMAP_SDK_VERSION`, `PAPERMAP_PLUGIN_CONTRACT_VERSION`, `checkPluginPeerCompatibility`, `createPluginContext`, `createPapermapObservability`, and related types
666
+
667
+ All paths use the package entry: `@papermap/papermap`.
668
+
669
+ ---
670
+
671
+ <!--
672
+ ## Local development
673
+
674
+ ```bash
675
+ npm install
676
+ npm run storybook # UI at http://localhost:3001
677
+ npm run validate # lint, TypeScript, tests
678
+ npm run test:unit # Vitest project `unit` (default `*.test`, excludes `*.integration.test`)
679
+ npm run test:integration # Vitest project `integration` (`*.integration.test`, longer timeout)
680
+ npm run build # dist + bundled styles.css
681
+ ```
240
682
 
241
683
  ---
242
684
 
@@ -293,12 +735,13 @@ The library decodes it and sends these headers on API requests:
293
735
 
294
736
  ### What users see in `PaperChat`
295
737
 
296
- - Floating input bar (portaled to `document.body`), Cmd/Ctrl+K to focus, Escape to dismiss.
297
- - Expanding input, backdrop, conversation panel, stop during load, new chat, scroll and history pagination.
298
- - Recent conversations, per-chat chart history, feedback, optional execution view, model selector, and related toolbar actions.
738
+ - **Default:** Floating input bar (portaled to `document.body`), Cmd/Ctrl+shortcut to focus, Escape to dismiss; expanding input, backdrop, conversation panel, stop during load, new chat, scroll and history pagination; recent conversations, per-chat chart history, feedback, optional execution view, model selector, and toolbar actions.
739
+ - **Side:** Fixed-width panel with the same assistant and composer, suited to sheet-style pages; chart can open in an overlay with optional history mode.
740
+ - **Floating:** Chart-first overlay with maximize, screenshot, and conversation alongside the preview.
741
+ - **Dialog:** Floating circular launcher button + popup anchored to its corner (`bottom-right` by default). The popup keeps a fixed header (title/subtitle + close `X`) and composer with the message list scrolling internally — the dialog itself never overflows the viewport. Outside-click and `Escape` are intentionally ignored: the dialog only closes via the explicit close button or by clicking the launcher again. Layered above page content (`z-[102]`) with the launcher remaining clickable underneath (overlay is `pointer-events-none`). Responsive sizing (`min(100vw - 1.5rem, 472px)` wide, `min(80vh, 640px)` tall) keeps it usable on mobile and desktop.
299
742
 
300
743
  ---
301
744
 
302
745
  ## Roadmap
303
746
 
304
- Additional embeddable surfaces (for example richer explorers) will follow the same pattern: self-contained components with `token` / `workspaceId` / `dashboardId` and optional callbacks, exported from `@papermap/papermap`.
747
+ Additional embeddable surfaces (for example richer explorers) will follow the same pattern: self-contained components with `token` / `workspaceId` / `dashboardId` and optional callbacks, exported from `@papermap/papermap`. -->