@thewhatmatters/wmds 0.2.0 → 0.4.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 (153) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/CONSUMING.md +5 -4
  3. package/README.md +3 -3
  4. package/dist/components/molecules/PromptBar/PromptBar.d.ts +11 -1
  5. package/dist/components/molecules/PromptBar/PromptBar.d.ts.map +1 -1
  6. package/dist/components/molecules/PromptBar/PromptBar.js +54 -43
  7. package/dist/components/molecules/PromptBar/promptBarStyles.d.ts +15 -0
  8. package/dist/components/molecules/PromptBar/promptBarStyles.d.ts.map +1 -1
  9. package/dist/components/molecules/PromptBar/promptBarStyles.js +5 -2
  10. package/dist/components/organisms/ChatDock/ChatDock.d.ts +93 -0
  11. package/dist/components/organisms/ChatDock/ChatDock.d.ts.map +1 -0
  12. package/dist/components/organisms/ChatDock/ChatDock.js +255 -0
  13. package/dist/components/organisms/ChatDock/chatDockStyles.d.ts +48 -0
  14. package/dist/components/organisms/ChatDock/chatDockStyles.d.ts.map +1 -0
  15. package/dist/components/organisms/ChatDock/chatDockStyles.js +15 -0
  16. package/dist/components/organisms/Dialog/AlertDialog.js +11 -11
  17. package/dist/components/organisms/Dialog/Dialog.js +44 -44
  18. package/dist/components/organisms/Sheet/Sheet.js +38 -38
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +30 -28
  22. package/dist/styles.css +1 -1
  23. package/docs/component-contracts.md +1 -1
  24. package/docs/components.md +7 -6
  25. package/docs/exports.json +14 -14
  26. package/docs/patterns/components-avatar--dropdown-row.tsx +1 -1
  27. package/docs/patterns/components-badge--with-avatar.tsx +1 -1
  28. package/docs/patterns/components-button-button--destructive-action.tsx +1 -1
  29. package/docs/patterns/components-button-button--ghost-action.tsx +1 -1
  30. package/docs/patterns/components-button-button--inverse-action.tsx +1 -1
  31. package/docs/patterns/components-button-button--link-render.tsx +1 -1
  32. package/docs/patterns/components-button-button--multi-state-badge.tsx +1 -1
  33. package/docs/patterns/components-button-button--outline-mono.tsx +1 -1
  34. package/docs/patterns/components-button-button--primary-action.tsx +1 -1
  35. package/docs/patterns/components-button-button--row-hug.tsx +1 -1
  36. package/docs/patterns/components-button-button--row-layout.tsx +1 -1
  37. package/docs/patterns/components-button-button--secondary-action.tsx +1 -1
  38. package/docs/patterns/components-button-button--suggestion-pills.tsx +1 -1
  39. package/docs/patterns/components-button-button--with-count.tsx +1 -1
  40. package/docs/patterns/components-button-button--with-icon.tsx +1 -1
  41. package/docs/patterns/components-button-floatingactionbutton--vertical-actions.tsx +1 -1
  42. package/docs/patterns/components-calembed--pattern-skip-in-footer.tsx +1 -1
  43. package/docs/patterns/components-card-card--body-slot-occupancy-history.tsx +1 -1
  44. package/docs/patterns/components-card-card--headerless-media.tsx +1 -1
  45. package/docs/patterns/components-card-card--outlined-layout.tsx +1 -1
  46. package/docs/patterns/components-card-card--pinned-height.tsx +1 -1
  47. package/docs/patterns/components-card-selectablecard--selectable-cards-pattern.tsx +1 -1
  48. package/docs/patterns/components-chart--audience-activity-heatmap.tsx +1 -1
  49. package/docs/patterns/components-chart--cartesian-no-data-gaps.tsx +1 -1
  50. package/docs/patterns/components-chart--occupancy-history-in-card.tsx +1 -1
  51. package/docs/patterns/components-chart--occupancy-in-card.tsx +1 -1
  52. package/docs/patterns/components-chart--post-reach-distribution.tsx +1 -1
  53. package/docs/patterns/components-chart--ranked-audience-breakdown.tsx +1 -1
  54. package/docs/patterns/components-chart--unit-grid-composition.tsx +1 -1
  55. package/docs/patterns/components-chatdock--pattern-chat-dock.tsx +68 -0
  56. package/docs/patterns/components-chatqa--pattern-qa-with-reply.tsx +1 -1
  57. package/docs/patterns/components-checkbox-checkbox--default.tsx +1 -1
  58. package/docs/patterns/components-checkbox-checkbox--with-description.tsx +1 -1
  59. package/docs/patterns/components-checkbox-checkboxgroup--default.tsx +1 -1
  60. package/docs/patterns/components-dialog--alert-dialog-destructive.tsx +1 -1
  61. package/docs/patterns/components-dialog--default-dialog.tsx +1 -1
  62. package/docs/patterns/components-dialog--form-dialog.tsx +1 -1
  63. package/docs/patterns/components-displaycontrols--page-utilities.tsx +1 -1
  64. package/docs/patterns/components-field--horizontal-input.tsx +1 -1
  65. package/docs/patterns/components-field--horizontal-text-area.tsx +1 -1
  66. package/docs/patterns/components-field--multi-control.tsx +1 -1
  67. package/docs/patterns/components-footerreveal--marketing-hero-pattern.tsx +1 -1
  68. package/docs/patterns/components-footerreveal--marketing-hero-ruled-pattern.tsx +1 -1
  69. package/docs/patterns/components-footerreveal--marketing-hero-with-gallery-intro.tsx +1 -1
  70. package/docs/patterns/components-footerreveal--marketing-page-pattern.tsx +1 -1
  71. package/docs/patterns/components-footerreveal--ruled-grid-footer-pattern.tsx +1 -1
  72. package/docs/patterns/components-footerreveal--sequenced-marketing-hero.tsx +1 -1
  73. package/docs/patterns/components-herointro--two-line-intro.tsx +1 -1
  74. package/docs/patterns/components-herotilestack--marketing-hero-pattern.tsx +1 -1
  75. package/docs/patterns/components-herotilestack--marketing-hero-text-sequence.tsx +1 -1
  76. package/docs/patterns/components-herotilestack--marketing-hero-with-gallery-intro.tsx +1 -1
  77. package/docs/patterns/components-intakeconfirmation--booked-pattern.tsx +1 -1
  78. package/docs/patterns/components-intakeconfirmation--emailed-pattern.tsx +1 -1
  79. package/docs/patterns/components-intakeform--about-you-pattern.tsx +1 -1
  80. package/docs/patterns/components-intakemodal--intake-modal-pattern.tsx +1 -1
  81. package/docs/patterns/components-kbd--command-row.tsx +1 -1
  82. package/docs/patterns/components-kbd--numbered-choices.tsx +1 -1
  83. package/docs/patterns/components-kbd--shortcut.tsx +1 -1
  84. package/docs/patterns/components-moremenu--action-menu.tsx +1 -1
  85. package/docs/patterns/components-moremenu--in-card-header.tsx +1 -1
  86. package/docs/patterns/components-navlist--side-nav-settings.tsx +1 -1
  87. package/docs/patterns/components-pageheader--app-header-pattern.tsx +1 -1
  88. package/docs/patterns/components-pageheader--page-section-header.tsx +1 -1
  89. package/docs/patterns/components-pageheader--toolbar-header.tsx +1 -1
  90. package/docs/patterns/components-panel--end-detail-rail.tsx +1 -1
  91. package/docs/patterns/components-pillgroup--pill-group-pattern.tsx +1 -1
  92. package/docs/patterns/components-promptbar--pattern-prompt-bar.tsx +1 -1
  93. package/docs/patterns/components-radio-radiogroup--default.tsx +1 -1
  94. package/docs/patterns/components-scrollhorizontal--project-gallery-pattern.tsx +1 -1
  95. package/docs/patterns/components-scrollhorizontal--with-intro.tsx +1 -1
  96. package/docs/patterns/components-sheet--bottom-sheet.tsx +1 -1
  97. package/docs/patterns/components-sheet--end-sheet.tsx +1 -1
  98. package/docs/patterns/components-sitenav--brand-and-cta.tsx +1 -1
  99. package/docs/patterns/components-sitenav--centered-links.tsx +1 -1
  100. package/docs/patterns/components-sitenav--compact.tsx +1 -1
  101. package/docs/patterns/components-sitenav--marketing-header.tsx +1 -1
  102. package/docs/patterns/components-sitenav--mega-menu.tsx +1 -1
  103. package/docs/patterns/components-stat--insights-row.tsx +1 -1
  104. package/docs/patterns/components-stepprogress--step-progress-pattern.tsx +1 -1
  105. package/docs/patterns/components-switch--default.tsx +1 -1
  106. package/docs/patterns/components-switch--settings-row.tsx +1 -1
  107. package/docs/patterns/components-tab--settings-pages.tsx +1 -1
  108. package/docs/patterns/components-taskrows--action-details.tsx +1 -1
  109. package/docs/patterns/components-taskrows--capsules.tsx +1 -1
  110. package/docs/patterns/components-taskrows--card-with-status-rows.tsx +1 -1
  111. package/docs/patterns/components-taskrows--controlled-expand.tsx +1 -1
  112. package/docs/patterns/components-taskrows--custom-slots.tsx +1 -1
  113. package/docs/patterns/components-taskrows--status-list.tsx +1 -1
  114. package/docs/patterns/components-taskrows--tag-chips.tsx +1 -1
  115. package/docs/patterns/components-textlink--external-destination.tsx +1 -1
  116. package/docs/patterns/components-textlink--inline-prose.tsx +1 -1
  117. package/docs/patterns/components-textlink--supporting-copy.tsx +1 -1
  118. package/docs/patterns/components-textsequence--default.tsx +1 -1
  119. package/docs/patterns/components-textsequence--reduced-motion.tsx +1 -1
  120. package/docs/patterns/components-textsequence--shapes.tsx +1 -1
  121. package/docs/patterns/components-toast--stacked-notifications.tsx +1 -1
  122. package/docs/patterns/components-tooltip--controlled.tsx +1 -1
  123. package/docs/patterns/components-tooltip--disabled-control.tsx +1 -1
  124. package/docs/patterns/components-tooltip--icon-action.tsx +1 -1
  125. package/docs/patterns/components-tooltip--keyboard-shortcut.tsx +1 -1
  126. package/docs/patterns/components-tooltip--placement.tsx +1 -1
  127. package/docs/patterns/foundations-scroll-fade--horizontal-rail.tsx +1 -1
  128. package/docs/patterns/foundations-scroll-fade--overflowing-list.tsx +1 -1
  129. package/docs/patterns/guides-chart-explorations--comparison-gallery.tsx +1 -1
  130. package/docs/patterns/guides-overlay-flows--notification-preferences.tsx +1 -1
  131. package/docs/patterns/guides-profile-typography--editorial-profile.tsx +1 -1
  132. package/docs/patterns/index.json +9 -161
  133. package/package.json +1 -1
  134. package/docs/patterns/components-promptbar--pattern-marketing-composer.tsx +0 -37
  135. package/docs/patterns/sites-pitchkit-account-settings--account-settings-owner.tsx +0 -265
  136. package/docs/patterns/sites-pitchkit-creator-identity--creator-identity-owner-settings.tsx +0 -154
  137. package/docs/patterns/sites-pitchkit-creator-identity--creator-identity-public.tsx +0 -96
  138. package/docs/patterns/sites-pitchkit-insights-and-kit--creator-insights-loading.tsx +0 -1006
  139. package/docs/patterns/sites-pitchkit-insights-and-kit--creator-insights.tsx +0 -1031
  140. package/docs/patterns/sites-pitchkit-insights-and-kit--insufficient-audience-data.tsx +0 -1015
  141. package/docs/patterns/sites-pitchkit-insights-and-kit--insufficient-reach-and-audience-data.tsx +0 -1017
  142. package/docs/patterns/sites-pitchkit-insights-and-kit--insufficient-reach-data.tsx +0 -1033
  143. package/docs/patterns/sites-pitchkit-insights-and-kit--owner-pitch-kit.tsx +0 -838
  144. package/docs/patterns/sites-pitchkit-insights-and-kit--shareable-pitch-kit.tsx +0 -608
  145. package/docs/patterns/sites-pitchkit-intro--intro-owner.tsx +0 -161
  146. package/docs/patterns/sites-pitchkit-intro--intro-public.tsx +0 -111
  147. package/docs/patterns/sites-pitchkit-past-brands--past-brands-owner.tsx +0 -611
  148. package/docs/patterns/sites-pitchkit-past-brands--past-brands-public.tsx +0 -299
  149. package/docs/patterns/sites-pitchkit-theme-picker--theme-picker-owner.tsx +0 -832
  150. package/docs/patterns/sites-whatmatters-intake--start-a-project-pattern.tsx +0 -234
  151. package/docs/patterns/sites-whatmatters-marketing-landing--marketing-landing.tsx +0 -87
  152. package/docs/patterns/sites-whatmatters-prompt-chat--landing-to-chat.tsx +0 -899
  153. package/docs/patterns/sites-whatmatters-rfp-submitted--rfp-submitted.tsx +0 -302
package/CHANGELOG.md CHANGED
@@ -7,6 +7,35 @@ Every release of `@thewhatmatters/wmds` is listed here, newest first.
7
7
  - **Pasted patterns:** when a release changes a **Pattern — …** story's Show code, it is named under Consumer actions so apps re-copy it.
8
8
  - **How to add an entry** (contributors): add your change to the top entry. If that version is already on npm (`npm view @thewhatmatters/wmds versions`), start a new entry above it and bump `version` in `package.json` to match. `npm run check:changelog` enforces the format.
9
9
 
10
+ ## 0.4.0
11
+
12
+ **ChatDock** is the site assistant: a pinned composer that shows suggested questions on hover and opens into a chat window, instead of a separate ask page. **PromptBar** gains `start` and `end` slots. **Components/PromptBar → Pattern — marketing composer** is removed. See **ADR-0039**.
13
+
14
+ ### Consumer actions
15
+
16
+ 1. **Replace the marketing composer and the ask page with ChatDock** (the WhatMatters site). Paste **Components/ChatDock → Pattern — chat dock** (`node_modules/@thewhatmatters/wmds/docs/patterns/components-chatdock--pattern-chat-dock.tsx`), pass your assistant request as `ask` and open **IntakeModal** from `onStartProject`, and mount it once in the marketing layout. Then delete the pasted **Pattern — marketing composer** (`npx wmds-check` reports it as `pattern-removed`), the ask page component (`components/ask-what-matters.tsx`), and its `/ask` route. Redirect `/ask` to the homepage if it has inbound links.
17
+ 2. **Reply content is yours to render.** `messages[].content` takes text or Markdown your app has already rendered; WMDS does not parse Markdown.
18
+ 3. **No other changes.** **PromptBar**'s new `start` and `end` props are optional; existing bars render as before.
19
+
20
+ ### Added
21
+
22
+ - **ChatDock** (`ChatDock`, `chatDockDefaultLabels`, `chatDockPlacements`, and the `ChatDock*` types).
23
+ - **PromptBar** `start` (brand mark) and `end` (extra inset controls before send).
24
+
25
+ ### Removed
26
+
27
+ - **Components/PromptBar → Pattern — marketing composer**.
28
+
29
+ ## 0.3.0
30
+
31
+ Storybook no longer mirrors product sites. The **Sites/** section (WhatMatters and PitchKit pages) is removed, and so are its `sites-…` files in `docs/patterns/`. No component, prop, token, or export changed.
32
+
33
+ ### Consumer actions
34
+
35
+ 1. **Pasted Sites patterns are now the app's own code.** If the app pasted any **Sites/WhatMatters/…** or **Sites/PitchKit/…** pattern (for example the ask page, the Start a project intake, or RFP submitted), keep the file and delete its three header lines (`// @thewhatmatters/wmds@…`, `// Storybook: Sites/…`, `// Show code — …`). Until then, `npx wmds-check` reports `pattern-removed` for that file.
36
+ 2. **Skip the 0.2.0 steps that re-copy Sites patterns** if they are still open: the **Sites/** bullets under 0.2.0 step 9, and the re-copy in steps 11, 12, and 13. Make those changes in the app's own files instead: the Button props from step 11, starting the ask page from `q` (step 12), and the RFP `onSubmit` (step 13).
37
+ 3. **Components/PromptBar → Pattern — marketing composer:** its Show code comment no longer names a site component; the code is unchanged. Re-copy it, or update the version in its header line.
38
+
10
39
  ## 0.2.0
11
40
 
12
41
  First release on npm. Earlier builds were installed from git commits and all reported `0.1.0`.
package/CONSUMING.md CHANGED
@@ -25,7 +25,7 @@ import "@thewhatmatters/wmds/styles.css";
25
25
  </span>
26
26
  ```
27
27
 
28
- Find a component A–Z under **Components/** (or by category on **Components → Overview**), read **Guides/** for cross-component choices, and use **Sites/** for approved pages and flows (**Sites/WhatMatters/…**, **Sites/PitchKit/…**) — copy the named **Pattern** story JSX and state wiring; do not re-style with utilities. Sites and Guides pages are not exported from the package.
28
+ Find a component A–Z under **Components/** (or by category on **Components → Overview**), read **Guides/** for cross-component choices — copy the named **Pattern** story JSX and state wiring; do not re-style with utilities. Guides pages are not exported from the package. Product pages and flows are each app's own code; WMDS Storybook does not mirror them.
29
29
 
30
30
  **Show code is the product contract.** Pattern story **Show code** (`storyCopySource`) is the drop-in implementation for consuming apps. It must stay a literal mirror of the live canvas — same layout, chrome, spacing, and typography. Copy Show code; do not choose between the Storybook iframe and an older freeze, and do not reconstruct the page from Storybook-only example modules (`*Example.tsx`, `*Styles.ts`). When the canvas changes, Show code is updated to match; apps re-copy the new freeze.
31
31
 
@@ -264,7 +264,8 @@ import {
264
264
  | `Chip` | `size`, `value`, `selected`, `onRemove`, `icon`, `count`, `readOnly` | Components/Chip — use `ChipFilterGroup` for multi-select filters |
265
265
  | `Input` | `label`, `description`, `status`, `message`, `loading`, `endBadge`, `icon`, `size` | Components/Input — pill shell; Required via `endBadge={<Badge>…</Badge>}` |
266
266
  | `Search` | `size`, `placeholder`, `onSubmit` | Components/Search — inline input + button row |
267
- | `PromptBar` | `value`, `onValueChange`, `onSend`, `placeholder` (default Ask anything…) | Components/PromptBar — **Pattern — prompt bar**. Wide pill, inline field (one line empty, up to 3 lines, then scroll), inset **IconButton** send. Muted until there is text, then `--color-brand` (`#011272`). Enter sends. Page pattern: **Sites/WhatMatters/Prompt chat → Pattern — landing to chat** (motion into a thread that keeps growing on a narrowed page grid, `--grid-max: 40rem`: the page shell is `h-[100svh]` and the thread scrolls inside that column when it is taller than the viewport, and reserves the composer's measured height plus the space under the pill, including while a reply is still growing, so the reply and its follow-ups finish above the composer, follow-ups and **PromptBar** share that column and the bar stays pinned; a follow-up appends in the same thread; a collapsed Thought-for timer (expandable while thinking) as a fleeting supporting muted status that leaves when the reply starts, then a word stream with one **TextLink** and hover-revealed **IconButton** actions; chat reuses **SiteNav**; the brand mark returns home). Voice and attachments are not part of this version. |
267
+ | `PromptBar` | `value`, `onValueChange`, `onSend`, `placeholder` (default Ask anything…), `start`, `end` | Components/PromptBar — **Pattern — prompt bar**. Wide pill, inline field (one line empty, up to 3 lines, then scroll), inset **IconButton** send. Muted until there is text, then `--color-brand` (`#011272`). Enter sends. `start` takes the brand mark; `end` takes extra inset controls. Voice and attachments are not part of this version. |
268
+ | `ChatDock` | `title`, `subtitle`, `mark`, `greeting`, `messages`, `thinking`, `suggestions`, `onSend`, `onSuggestionSelect`, `disclaimer` | Components/ChatDock — **Pattern — chat dock**. The site assistant: a pinned **PromptBar** with suggested-question pills on hover that opens into a non-modal chat window (full screen on phones). The app owns the conversation and the request. Replaces the separate ask page. |
268
269
  | `Card` | `variant`, `shape`, `padding` | Components/Card/Card — `Card.Header` (`start` | `end`), **`Card.Body` slot** (no default fill), `Card.Footer` |
269
270
  | `Accordion` | `variant`, `Accordion.Item` `leading` / `label` / `trailing` / `open` | Components/Accordion — FAQ, settings sections |
270
271
  | `TaskRows` | `variant`, `status`, `meta`, `detailsLayout`, `TaskRows.Detail` | Components/TaskRows — **Pattern — status rows**, **capsules**, **action details** (`Detail variant="button"`), **tag chips** (`Chip readOnly size="sm"`), detail lines (`Detail` + `onPress` → `Button layout="row"`) |
@@ -276,9 +277,9 @@ import {
276
277
  | `HeroTileStack` | `tiles`, `tileSize`, `strength`, `velocityFactor`, `maxVertical`, `spring` | Components/HeroTileStack — **Pattern — marketing hero**. Square tiles, `--hero-tile-size`, max `tileSize` (400px), tighter pile below `md`. Scatter distances scale with the painted tile. Place **SiteNav** above the hero; the hero section is `min-h-[calc(100svh-var(--site-nav-height))]`, `shrink-0`, and `justify-center-safe`. It centers when the copy fits. When the copy is taller, the section grows and the content starts below the nav with the section's top padding. **HeroIntro** is the `h1` (`lead` + children) on centered `type-display-2` at normal weight and display-2 leading, the same size and line-height as the gallery statement. The first sentence wraps, including from `md`; the rest always starts on the next line. The sequenced hero h1 is only “An Austin, TX studio specializing in brand and product design.” (“Austin,” and “TX” stay together). A rock **RiveHand** sits `inline` immediately after “TX”, inside that nowrap phrase (drawn hand about 1.15em, centered, `aria-hidden`). That heading has no second sentence and no circle or pill. The gallery statement places the point hand after “is a first impression”. It sits on `grid-page` (same `--grid-max`, margin, gap, and column count as the guides): columns 4–9 from `lg` (`lg:col-start-4 lg:col-end-10`, 6 of 12 columns, centered), full width of that page grid below `lg`. The tile fan is the last element. Pointer over the fan springs tiles left and right away from it; a quick move adds a small vertical nudge that settles when the pointer slows; leave springs them back. Default `strength` (`120`) stays near the stack — raise it for a wider scatter. `velocityFactor` (`0.02`) and `maxVertical` (`24`) tune that nudge. Reduced motion stays on the resting fan. Coarse pointers get one gentle tap scatter, then a spring back. |
277
278
  | `ScrollHorizontal` | `items` (`id`, `label`, optional `color`), `heading` (`sr-only` while pinned, visible when motion is reduced; omitted when `intro` is set), `intro` (`ScrollHorizontal.Intro`: `eyebrow`, `statement`, optional `action` — `{ label, onClick }` for a modal button or `{ label, href }` for Button `render={<a href />}`), `expandLast` (default false), `expanded`, `className` (layout only, root) | Components/ScrollHorizontal — **Pattern — project gallery**. Also under the hero in **HeroTileStack** and **FooterReveal** **Pattern — marketing hero** (`expandLast`). Each card is a solid token-color placeholder; `label` is the accessible name (`sr-only`). `heading` names the section and stays `sr-only` on the pinned window. `intro` (**Pattern — gallery intro**, and the marketing-hero-with-gallery-intro stories) is the first panel: **Badge** label pill (neutral, the category pill), `type-display-2` statement through **TextSequence** (normal weight, once when the panel scrolls into view), **Button** `role="secondary"` labeled Start a project (no className, no icon). Pass `action={{ label: "Start a project", onClick }}` to open the project modal, or `href` when the action navigates. **FooterReveal → Pattern — marketing hero ruled grid** is the full page: sequenced hero, this intro, `expandLast`, and **FooterReveal.Ruled**. The statement is “Every screen is a first impression and we make yours the one they remember.” with an asterisk after screen, a point **RiveHand** after impression, and a diamond after yours. The eyebrow names the section. The `h2` keeps the plain sentence. At rest the panel's left edge is the page-grid content start; scroll carries it off with the tiles. Tiles follow to the right. Reduced motion stacks the intro above the row. `expandLast` still parks the last card on center before the grow. `300svh` track (`shrink-0` so a flex parent keeps that height), sticky `h-svh` window, translate from the first card centered to the last. `expandLast` uses a `400svh` track: same horizontal distance, then the last tile grows (`clip-path`) to fill the window edge to edge with radius 0 and scrolls away. `expanded` is the slot on that tile. 400×500 / `gap-8` from `sm`; 280×350 / `gap-4` below `sm`; `rounded-xl`. Reduced motion is a native horizontal scroller (`py-12`), including `MotionConfig` `reducedMotion="always"`; with `expandLast` the last tile follows as a static `h-svh` section. The section ends on that tile. **FooterReveal → Pattern — marketing hero** sets `!py-0` on the guide `grid-page` so the tile meets the footer with no page-background strip. |
278
279
  | `RiveHand` | `hand` (`point` \| `rock`), `size`, `active`, `idle` (default true), `entrance` (`slide-up` \| `grow` \| `none`, default `none`), `className`, `aria-hidden` | Components/HeroTileStack — **Pattern — marketing hero**. `point` is artboard `31_Cigarette` (cigarette removed). `rock` is `29_Rock`. `handFill` is `--color-surface` (fallback `--color-background-surface`; white in light mode). `outline` is `--color-brand` (`#011272` in both themes; hardcoded fallback `#011272`). `inline` sizes the canvas past the artboard padding so the drawn hand is about 1.15em, the drawn hand is centered on the line, and the line box does not grow. Inside a TextSequence the slot pops on the beat halfway between the words beside it, with the same scale, rotation, and `back.out(1.8)` ease as the circle and pill. Idle starts after that pop. The sequenced hero places the rock hand immediately after “TX”, inside the same nowrap phrase. The gallery statement places the point hand after “is a first impression”. `entrance="none"`. `idle` holds `Boolean 1` for 1.1s, then waits a random 1–2s before the next pulse, per hand, while the tab is visible and the sized hand box is in view. Reduced motion draws one static frame once that box has size, then pauses. The sequence pop and idle timers stay off. SSR and hydration render that resting pose; the entrance starts after mount only when motion is allowed. `npm install @rive-app/react-canvas`. Serve `public/rive/interactive-icon-set.riv` at `/rive/interactive-icon-set.riv` and `rive.wasm` at `/rive/rive.wasm`. The pattern file starts with `"use client"`. CC BY 4.0, Silvia Sguotti and Gabriele Montinaro. |
279
- | `ConfettiProvider` | `useConfettiOnMount()`, `useConfetti().fire()`, `origin`, `confettiDefaultColors` | Components/Confetti — playground. **Sites/WhatMatters/RFP submitted → Pattern — RFP submitted**. Fire on the confirmation surface after the async action resolves, not on the submit click. `fire()` does nothing under reduced motion. |
280
+ | `ConfettiProvider` | `useConfettiOnMount()`, `useConfetti().fire()`, `origin`, `confettiDefaultColors` | Components/Confetti — playground. **IntakeConfirmation** is the reference composition. Fire on the confirmation surface after the async action resolves, not on the submit click. `fire()` does nothing under reduced motion. |
280
281
 
281
- Copy flow patterns from **Sites/** in Storybook when they ship. See **`src/package.manifest.ts`** for the export contract.
282
+ See **`src/package.manifest.ts`** for the export contract.
282
283
 
283
284
  ### Cluster scale in detail rails
284
285
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # WMDS — WhatMatters Design System
2
2
 
3
- Tailwind v4 theme + **pattern-first** Storybook catalog. **Storybook is canonical** — prescribed components and Sites patterns, not utility-class soup.
3
+ Tailwind v4 theme + **pattern-first** Storybook catalog. **Storybook is canonical** — prescribed components and their patterns, not utility-class soup.
4
4
 
5
5
  ## Stack
6
6
 
@@ -52,11 +52,11 @@ npm run validate:composition # molecules/organisms must compose atoms (CI)
52
52
 
53
53
  The list is `src/package.manifest.ts`. `npm run build` fails when it and `src/index.ts` disagree.
54
54
 
55
- **Storybook-only:** **Sites/** (pages and flows per product — WhatMatters, PitchKit) and **Guides/** (cross-component guidance) — page-level compositions for copy-paste; not package exports.
55
+ **Storybook-only:** **Guides/** (cross-component guidance) — page-level compositions for copy-paste; not package exports. Product pages live in each product's app.
56
56
 
57
57
  **Motion:** CSS tokens for simple transitions; [`motion/react`](https://motion.dev/docs/react) for gestures, layout, and enter/exit. Helpers in **`src/lib/motion.ts`** (reads Theme CSS vars).
58
58
 
59
- **Architecture:** Theme → lib → Atoms → Molecules → Organisms → Sites / Guides. **Pattern-first** for consumers ([ADR-0004](docs/adr/0004-pattern-first-not-utility-first.md)). **Mobile-first** on all tiers ([ADR-0003](docs/adr/0003-responsive-mobile-first.md)). See ADR-0001, ADR-0002.
59
+ **Architecture:** Theme → lib → Atoms → Molecules → Organisms → Guides. **Pattern-first** for consumers ([ADR-0004](docs/adr/0004-pattern-first-not-utility-first.md)). **Mobile-first** on all tiers ([ADR-0003](docs/adr/0003-responsive-mobile-first.md)). See ADR-0001, ADR-0002.
60
60
 
61
61
  ## Paper
62
62
 
@@ -1,4 +1,4 @@
1
- import { type TextareaHTMLAttributes } from "react";
1
+ import { type ReactNode, type TextareaHTMLAttributes } from "react";
2
2
  /** Layout-only — width, margin, flex placement. Not for colors. */
3
3
  export type PromptBarLayoutClassName = string;
4
4
  export declare const promptBarPlaceholder = "Ask anything\u2026";
@@ -21,6 +21,16 @@ export interface PromptBarProps extends Omit<TextareaHTMLAttributes<HTMLTextArea
21
21
  /** Accessible name for the send control. Default: "Send". */
22
22
  sendLabel?: string;
23
23
  disabled?: boolean;
24
+ /**
25
+ * Leading slot inside the pill — a brand mark or **Avatar** `sm` (2.25rem). Decorative or
26
+ * labeled by the caller; not a control.
27
+ */
28
+ start?: ReactNode;
29
+ /**
30
+ * Extra inset controls before send — for example a mic **IconButton** `sm` `role="secondary"`.
31
+ * The caller owns the handler and accessible name.
32
+ */
33
+ end?: ReactNode;
24
34
  className?: PromptBarLayoutClassName;
25
35
  }
26
36
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"PromptBar.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/PromptBar/PromptBar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,OAAO,CAAC;AAaf,mEAAmE;AACnE,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAE9C,eAAO,MAAM,oBAAoB,uBAAkB,CAAC;AAEpD,MAAM,WAAW,cACf,SAAQ,IAAI,CACV,sBAAsB,CAAC,mBAAmB,CAAC,EAC3C,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,UAAU,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CACnG;IACD,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,wBAAwB,CAAC;CACtC;AAMD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,gHA2EpB,CAAC"}
1
+ {"version":3,"file":"PromptBar.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/PromptBar/PromptBar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,sBAAsB,EAC5B,MAAM,OAAO,CAAC;AAgBf,mEAAmE;AACnE,MAAM,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAE9C,eAAO,MAAM,oBAAoB,uBAAkB,CAAC;AAEpD,MAAM,WAAW,cACf,SAAQ,IAAI,CACV,sBAAsB,CAAC,mBAAmB,CAAC,EAC3C,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,UAAU,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CACnG;IACD,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0BAA0B;IAC1B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;;OAGG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,SAAS,CAAC,EAAE,wBAAwB,CAAC;CACtC;AAMD;;;;;GAKG;AACH,eAAO,MAAM,SAAS,gHAqFpB,CAAC"}
@@ -2,55 +2,66 @@
2
2
  import { cn as e } from "../../../lib/cn.js";
3
3
  import { IconButton as t } from "../../atoms/IconButton/IconButton.js";
4
4
  import { TextArea as n } from "../../atoms/TextArea/TextArea.js";
5
- import { promptBarFieldClasses as r, promptBarSendClasses as i, promptBarSendMutedClasses as a, promptBarSendReadyClasses as o, promptBarShellClasses as s } from "./promptBarStyles.js";
6
- import { forwardRef as c, useState as l } from "react";
7
- import { ArrowRight as u } from "lucide-react";
8
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
5
+ import { promptBarEndSlotClasses as r, promptBarFieldClasses as i, promptBarSendClasses as a, promptBarSendMutedClasses as o, promptBarSendReadyClasses as s, promptBarShellClasses as c, promptBarShellStartPadClasses as l, promptBarStartSlotClasses as u } from "./promptBarStyles.js";
6
+ import { forwardRef as d, useState as f } from "react";
7
+ import { ArrowRight as p } from "lucide-react";
8
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
9
9
  //#region src/components/molecules/PromptBar/PromptBar.tsx
10
- var p = "Ask anything…";
11
- function m(e) {
10
+ var g = "Ask anything…";
11
+ function _(e) {
12
12
  return e.trim().length > 0;
13
13
  }
14
- var h = c(function({ value: c, defaultValue: h = "", onValueChange: g, onSend: _, placeholder: v = p, "aria-label": y = "Ask anything", sendLabel: b = "Send", disabled: x = !1, className: S, onKeyDown: C, ...w }, T) {
15
- let E = c !== void 0, [D, O] = l(h), k = E ? c : D, A = !x && m(k);
16
- function j(e) {
17
- E || O(e), g?.(e);
14
+ var v = d(function({ value: d, defaultValue: v = "", onValueChange: y, onSend: b, placeholder: x = g, "aria-label": S = "Ask anything", sendLabel: C = "Send", disabled: w = !1, start: T, end: E, className: D, onKeyDown: O, ...k }, A) {
15
+ let j = d !== void 0, [M, N] = f(v), P = j ? d : M, F = !w && _(P);
16
+ function I(e) {
17
+ j || N(e), y?.(e);
18
18
  }
19
- function M() {
20
- A && (_?.(k), E || O(""));
19
+ function L() {
20
+ F && (b?.(P), j || N(""));
21
21
  }
22
- function N(e) {
23
- C?.(e), !e.defaultPrevented && (e.key !== "Enter" || e.shiftKey || e.nativeEvent.isComposing || (e.preventDefault(), M()));
22
+ function R(e) {
23
+ O?.(e), !e.defaultPrevented && (e.key !== "Enter" || e.shiftKey || e.nativeEvent.isComposing || (e.preventDefault(), L()));
24
24
  }
25
- return /* @__PURE__ */ f("div", {
26
- className: e(s, S),
27
- children: [/* @__PURE__ */ d(n, {
28
- ...w,
29
- ref: T,
30
- inline: !0,
31
- rows: 1,
32
- resize: "none",
33
- value: k,
34
- placeholder: v,
35
- "aria-label": y,
36
- disabled: x,
37
- className: r,
38
- onChange: (e) => {
39
- j(e.target.value);
40
- },
41
- onKeyDown: N
42
- }), /* @__PURE__ */ d(t, {
43
- type: "button",
44
- role: "primary",
45
- size: "sm",
46
- icon: /* @__PURE__ */ d(u, { strokeWidth: 2 }),
47
- "aria-label": b,
48
- title: b,
49
- disabled: !A,
50
- className: e(i, A ? o : a),
51
- onClick: M
52
- })]
25
+ return /* @__PURE__ */ h("div", {
26
+ className: e(c, T == null ? l.field : l.slot, D),
27
+ children: [
28
+ T == null ? null : /* @__PURE__ */ m("div", {
29
+ className: u,
30
+ children: T
31
+ }),
32
+ /* @__PURE__ */ m(n, {
33
+ ...k,
34
+ ref: A,
35
+ inline: !0,
36
+ rows: 1,
37
+ resize: "none",
38
+ value: P,
39
+ placeholder: x,
40
+ "aria-label": S,
41
+ disabled: w,
42
+ className: i,
43
+ onChange: (e) => {
44
+ I(e.target.value);
45
+ },
46
+ onKeyDown: R
47
+ }),
48
+ E == null ? null : /* @__PURE__ */ m("div", {
49
+ className: r,
50
+ children: E
51
+ }),
52
+ /* @__PURE__ */ m(t, {
53
+ type: "button",
54
+ role: "primary",
55
+ size: "sm",
56
+ icon: /* @__PURE__ */ m(p, { strokeWidth: 2 }),
57
+ "aria-label": C,
58
+ title: C,
59
+ disabled: !F,
60
+ className: e(a, F ? s : o),
61
+ onClick: L
62
+ })
63
+ ]
53
64
  });
54
65
  });
55
66
  //#endregion
56
- export { h as PromptBar, p as promptBarPlaceholder };
67
+ export { v as PromptBar, g as promptBarPlaceholder };
@@ -5,6 +5,21 @@
5
5
  * The shell owns the single focus ring (inset, so it does not stack a second edge).
6
6
  */
7
7
  export declare const promptBarShellClasses: string;
8
+ /**
9
+ * Leading inset. The text starts 1.25rem in; with a `start` slot the slot takes the same
10
+ * 0.5rem inset as the send circle, and the field keeps 0.25rem more air than the shell gap.
11
+ */
12
+ export declare const promptBarShellStartPadClasses: {
13
+ readonly field: "pl-5";
14
+ readonly slot: "pl-2";
15
+ };
16
+ /**
17
+ * Leading slot — a brand mark or avatar at the send circle's size (2.25rem), pinned to the
18
+ * last line like the send control.
19
+ */
20
+ export declare const promptBarStartSlotClasses = "mr-1 flex size-9 shrink-0 items-center justify-center";
21
+ /** Trailing slot — extra inset controls (for example a mic **IconButton** `sm`) before send. */
22
+ export declare const promptBarEndSlotClasses = "flex shrink-0 items-end gap-2";
8
23
  /**
9
24
  * Empty is one line — min height matches the send circle, with padding that centers that line.
10
25
  * Grows with the text, stops at three lines (`max-h`), then scrolls.
@@ -1 +1 @@
1
- {"version":3,"file":"promptBarStyles.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/PromptBar/promptBarStyles.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAGN,CAAC;AAE7B;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAEf,CAAC;AAEpB;;GAEG;AACH,eAAO,MAAM,oBAAoB,kFACgD,CAAC;AAElF,0DAA0D;AAC1D,eAAO,MAAM,yBAAyB,8DAA8D,CAAC;AAErG;;;GAGG;AACH,eAAO,MAAM,yBAAyB,qDAAqD,CAAC"}
1
+ {"version":3,"file":"promptBarStyles.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/PromptBar/promptBarStyles.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAGN,CAAC;AAE7B;;;GAGG;AACH,eAAO,MAAM,6BAA6B;;;CAGhC,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,yBAAyB,0DAA0D,CAAC;AAEjG,gGAAgG;AAChG,eAAO,MAAM,uBAAuB,kCAAkC,CAAC;AAEvE;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAEf,CAAC;AAEpB;;GAEG;AACH,eAAO,MAAM,oBAAoB,kFACgD,CAAC;AAElF,0DAA0D;AAC1D,eAAO,MAAM,yBAAyB,8DAA8D,CAAC;AAErG;;;GAGG;AACH,eAAO,MAAM,yBAAyB,qDAAqD,CAAC"}
@@ -1,6 +1,9 @@
1
1
  "use client";
2
2
  import { focusRingTransitionClasses as e } from "../../../lib/motion.js";
3
3
  //#region src/components/molecules/PromptBar/promptBarStyles.ts
4
- var t = "flex w-full items-end gap-2 rounded-[1.625rem] border border-border-control bg-surface p-2 pl-5 focus-within:outline-none focus-within:ring-2 focus-within:ring-inset focus-within:ring-focus-ring " + e, n = "min-h-9 min-w-0 flex-1 overflow-y-auto py-2 type-body [field-sizing:content] max-h-[4.75rem]", r = "focus-visible:!ring-0 focus-visible:!ring-offset-0 focus-visible:!shadow-none", i = "!bg-brand !text-on-brand hover:!bg-brand active:!bg-brand", a = "!bg-neutral !text-disabled disabled:!opacity-100";
4
+ var t = "flex w-full items-end gap-2 rounded-[1.625rem] border border-border-control bg-surface p-2 focus-within:outline-none focus-within:ring-2 focus-within:ring-inset focus-within:ring-focus-ring " + e, n = {
5
+ field: "pl-5",
6
+ slot: "pl-2"
7
+ }, r = "mr-1 flex size-9 shrink-0 items-center justify-center", i = "flex shrink-0 items-end gap-2", a = "min-h-9 min-w-0 flex-1 overflow-y-auto py-2 type-body [field-sizing:content] max-h-[4.75rem]", o = "focus-visible:!ring-0 focus-visible:!ring-offset-0 focus-visible:!shadow-none", s = "!bg-brand !text-on-brand hover:!bg-brand active:!bg-brand", c = "!bg-neutral !text-disabled disabled:!opacity-100";
5
8
  //#endregion
6
- export { n as promptBarFieldClasses, r as promptBarSendClasses, a as promptBarSendMutedClasses, i as promptBarSendReadyClasses, t as promptBarShellClasses };
9
+ export { i as promptBarEndSlotClasses, a as promptBarFieldClasses, o as promptBarSendClasses, c as promptBarSendMutedClasses, s as promptBarSendReadyClasses, t as promptBarShellClasses, n as promptBarShellStartPadClasses, r as promptBarStartSlotClasses };
@@ -0,0 +1,93 @@
1
+ import { type ReactElement, type ReactNode } from "react";
2
+ import { type ChatDockPlacement } from "./chatDockStyles";
3
+ export { chatDockPlacements, type ChatDockPlacement } from "./chatDockStyles";
4
+ /** Layout-only — margin and placement. Not for colors or type. */
5
+ export type ChatDockLayoutClassName = string;
6
+ export interface ChatDockSuggestion {
7
+ id: string;
8
+ label: string;
9
+ /** Leading Lucide icon element, for example `<DollarSign />`. */
10
+ icon?: ReactElement;
11
+ /**
12
+ * Sent as the visitor's message when chosen. Suggestions with a prompt also show as pills
13
+ * above the resting composer. Omit it for an action such as **Get started** — then only
14
+ * `onSuggestionSelect` runs.
15
+ */
16
+ prompt?: string;
17
+ }
18
+ export interface ChatDockMessage {
19
+ id: string;
20
+ role: "user" | "assistant";
21
+ /** Text, or Markdown the app has already rendered. ChatDock does not parse Markdown. */
22
+ content: ReactNode;
23
+ }
24
+ export interface ChatDockLabels {
25
+ /** Close control. Default: "Close chat". */
26
+ close: string;
27
+ /** Shown while `thinking`. Default: "Thinking…". */
28
+ thinking: string;
29
+ /** Accessible name for the message list. Default: "Conversation". */
30
+ conversation: string;
31
+ /** Accessible name for the suggestion groups. Default: "Suggested questions". */
32
+ suggestions: string;
33
+ /** Accessible name for the field. Default: "Ask anything". */
34
+ field: string;
35
+ /** Send control. Default: "Send". */
36
+ send: string;
37
+ }
38
+ export declare const chatDockDefaultLabels: ChatDockLabels;
39
+ export interface ChatDockProps {
40
+ /** Window title — usually the product or brand name. */
41
+ title: string;
42
+ /** Line under the title. */
43
+ subtitle?: string;
44
+ /**
45
+ * Brand mark — **Avatar** `size="md"` (2.25rem). Shown at the start of the composer and in
46
+ * the window header.
47
+ */
48
+ mark?: ReactNode;
49
+ /** First assistant message, always at the top of the window. */
50
+ greeting?: ReactNode;
51
+ /** The conversation, oldest first. The app owns it and appends replies as they stream. */
52
+ messages?: ChatDockMessage[];
53
+ /** Shows the thinking row after the last message while a reply is on its way. */
54
+ thinking?: boolean;
55
+ /** Pills above the resting composer (those with a `prompt`) and rows in the window. */
56
+ suggestions?: ChatDockSuggestion[];
57
+ /** Receives the visitor's message — typed, or a suggestion's `prompt`. */
58
+ onSend: (prompt: string) => void;
59
+ /** Every suggestion choice, including actions without a `prompt`. */
60
+ onSuggestionSelect?: (suggestion: ChatDockSuggestion) => void;
61
+ /** Controlled open state. */
62
+ open?: boolean;
63
+ defaultOpen?: boolean;
64
+ onOpenChange?: (open: boolean) => void;
65
+ /** Field placeholder. Default: "Ask anything…". */
66
+ placeholder?: string;
67
+ /** One line under the window's composer — for example what the assistant can't do. */
68
+ disclaimer?: ReactNode;
69
+ labels?: Partial<ChatDockLabels>;
70
+ /** `fixed` (default) pins the dock to the viewport; `inline` keeps it in flow for specimens. */
71
+ placement?: ChatDockPlacement;
72
+ className?: ChatDockLayoutClassName;
73
+ }
74
+ /** Pills above the resting composer: suggestions that send a prompt. */
75
+ export declare function chatDockPillSuggestions(suggestions: readonly ChatDockSuggestion[]): ChatDockSuggestion[];
76
+ /** Suggestion rows show until the conversation starts. */
77
+ export declare function chatDockShowsSuggestionRows(suggestions: readonly ChatDockSuggestion[], messages: readonly ChatDockMessage[]): boolean;
78
+ /**
79
+ * Window reveal. Closed, the clip is the resting composer's strip at the bottom of the window
80
+ * (full width, 3.25rem tall, pill radius); open, it is the whole card at the shell radius. Both
81
+ * strings share one shape so Motion can interpolate them. The clip is cleared once open so the
82
+ * card's shadow is not cut off.
83
+ */
84
+ export declare const chatDockClosedClip = "inset(calc(100% - 3.25rem) 0rem 0rem 0rem round 1.625rem)";
85
+ export declare const chatDockOpenClip = "inset(calc(0% - 0rem) 0rem 0rem 0rem round 1rem)";
86
+ /**
87
+ * Pinned prompt that opens into a chat window. At rest it is a **PromptBar** with the brand
88
+ * mark; hovering shows suggestion pills above it. Focusing or typing opens a non-modal window
89
+ * in its place — header, conversation, suggestion rows, composer, and an optional disclaimer.
90
+ * Escape or Close returns to the resting bar. The page behind stays usable.
91
+ */
92
+ export declare function ChatDock({ title, subtitle, mark, greeting, messages, thinking, suggestions, onSend, onSuggestionSelect, open: openProp, defaultOpen, onOpenChange, placeholder, disclaimer, labels: labelsProp, placement, className, }: ChatDockProps): import("react").JSX.Element;
93
+ //# sourceMappingURL=ChatDock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatDock.d.ts","sourceRoot":"","sources":["../../../../src/components/organisms/ChatDock/ChatDock.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AASf,OAAO,EAgBL,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE9E,kEAAkE;AAClE,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,wFAAwF;IACxF,OAAO,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,YAAY,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,qBAAqB,EAAE,cAOnC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uFAAuF;IACvF,WAAW,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACnC,0EAA0E;IAC1E,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,qEAAqE;IACrE,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC9D,6BAA6B;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,gGAAgG;IAChG,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC;AAED,wEAAwE;AACxE,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,SAAS,kBAAkB,EAAE,GAAG,kBAAkB,EAAE,CAExG;AAED,0DAA0D;AAC1D,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,SAAS,kBAAkB,EAAE,EAC1C,QAAQ,EAAE,SAAS,eAAe,EAAE,GACnC,OAAO,CAET;AAKD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,8DAA8D,CAAC;AAC9F,eAAO,MAAM,gBAAgB,qDAAqD,CAAC;AAEnF;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,QAAa,EACb,QAAgB,EAChB,WAAgB,EAChB,MAAM,EACN,kBAAkB,EAClB,IAAI,EAAE,QAAQ,EACd,WAAmB,EACnB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,MAAM,EAAE,UAAU,EAClB,SAAmB,EACnB,SAAS,GACV,EAAE,aAAa,+BA0Qf"}
@@ -0,0 +1,255 @@
1
+ "use client";
2
+ import { cn as e } from "../../../lib/cn.js";
3
+ import { motionBeatSeconds as t, motionTransitionProp as n, readMotionDurationSeconds as ee } from "../../../lib/motion.js";
4
+ import { ButtonIcon as r } from "../../atoms/Button/ButtonIcon.js";
5
+ import { Button as i } from "../../atoms/Button/Button.js";
6
+ import { Status as te } from "../../atoms/Status/Status.js";
7
+ import { PromptBar as a } from "../../molecules/PromptBar/PromptBar.js";
8
+ import { OverlayPanelHeader as ne } from "../Dialog/OverlayPanelHeader.js";
9
+ import { chatDockAssistantMessageClasses as o, chatDockComposerClasses as re, chatDockDisclaimerClasses as ie, chatDockDockClasses as ae, chatDockGridClasses as oe, chatDockPillClasses as se, chatDockPillsClasses as ce, chatDockPlacements as s, chatDockRootClasses as le, chatDockSuggestionLabelClasses as ue, chatDockSuggestionListClasses as de, chatDockSuggestionRowContentClasses as fe, chatDockThinkingClasses as pe, chatDockThreadClasses as me, chatDockUserMessageClasses as he, chatDockWindowClasses as ge } from "./chatDockStyles.js";
10
+ import { useEffect as _e, useId as c, useLayoutEffect as ve, useRef as l, useState as u } from "react";
11
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
12
+ import { AnimatePresence as p, motion as m, useReducedMotion as ye } from "motion/react";
13
+ //#region src/components/organisms/ChatDock/ChatDock.tsx
14
+ var h = {
15
+ close: "Close chat",
16
+ thinking: "Thinking…",
17
+ conversation: "Conversation",
18
+ suggestions: "Suggested questions",
19
+ field: "Ask anything",
20
+ send: "Send"
21
+ };
22
+ function g(e) {
23
+ return e.filter((e) => e.prompt != null && e.prompt.trim() !== "");
24
+ }
25
+ function _(e, t) {
26
+ return e.length > 0 && t.length === 0;
27
+ }
28
+ var v = 48, y = "inset(calc(100% - 3.25rem) 0rem 0rem 0rem round 1.625rem)", b = "inset(calc(0% - 0rem) 0rem 0rem 0rem round 1rem)";
29
+ function x({ title: s, subtitle: x, mark: S, greeting: C, messages: w = [], thinking: be = !1, suggestions: T = [], onSend: xe, onSuggestionSelect: Se, open: E, defaultOpen: D = !1, onOpenChange: Ce, placeholder: O, disclaimer: k, labels: A, placement: j = "fixed", className: we }) {
30
+ let M = {
31
+ ...h,
32
+ ...A
33
+ }, N = c(), P = c(), F = ye(), I = E !== void 0, [Te, Ee] = u(D), L = I ? E : Te, [R, z] = u(""), B = l(null), V = l(null), H = l(null), U = l(!0), W = l(!1), G = l(L), K = l(L);
34
+ function q(e) {
35
+ e !== L && (I || Ee(e), Ce?.(e));
36
+ }
37
+ function J(e) {
38
+ let t = e.trim();
39
+ t !== "" && (q(!0), U.current = !0, z(""), xe(t));
40
+ }
41
+ function Y(e) {
42
+ Se?.(e), e.prompt != null && J(e.prompt);
43
+ }
44
+ _e(() => {
45
+ L && !G.current ? V.current?.focus() : !L && G.current && (K.current = !1, W.current = !0, B.current?.focus(), W.current = !1), G.current = L;
46
+ }, [L]), ve(() => {
47
+ let e = H.current;
48
+ e != null && U.current && (e.scrollTop = e.scrollHeight);
49
+ });
50
+ function De(e) {
51
+ e.key !== "Escape" || e.defaultPrevented || (e.preventDefault(), q(!1));
52
+ }
53
+ let X = g(T), Oe = _(T, w), ke = n("medium"), Z = n("fast"), Q = F ? {
54
+ initial: { opacity: 0 },
55
+ animate: { opacity: 1 },
56
+ exit: { opacity: 0 }
57
+ } : {
58
+ initial: {
59
+ clipPath: y,
60
+ opacity: .6
61
+ },
62
+ animate: {
63
+ clipPath: b,
64
+ opacity: 1,
65
+ transitionEnd: { clipPath: "none" }
66
+ },
67
+ exit: {
68
+ clipPath: [b, y],
69
+ opacity: [1, .6]
70
+ }
71
+ }, $ = F || K.current ? {} : {
72
+ initial: {
73
+ opacity: 0,
74
+ y: 8
75
+ },
76
+ animate: {
77
+ opacity: 1,
78
+ y: 0
79
+ },
80
+ transition: {
81
+ ...Z,
82
+ delay: t(1)
83
+ }
84
+ }, Ae = F ? 0 : ee("medium") * .6;
85
+ return /* @__PURE__ */ d("div", {
86
+ className: e(le[j], we),
87
+ "data-open": L ? "" : void 0,
88
+ children: /* @__PURE__ */ d("div", {
89
+ className: oe,
90
+ children: /* @__PURE__ */ d("div", {
91
+ className: "band",
92
+ children: /* @__PURE__ */ d(p, {
93
+ initial: !1,
94
+ mode: "popLayout",
95
+ children: L ? /* @__PURE__ */ f(m.section, {
96
+ role: "dialog",
97
+ "aria-modal": "false",
98
+ "aria-labelledby": N,
99
+ "aria-describedby": x == null ? void 0 : P,
100
+ className: ge[j],
101
+ initial: Q.initial,
102
+ animate: Q.animate,
103
+ exit: Q.exit,
104
+ transition: ke,
105
+ onKeyDown: De,
106
+ children: [
107
+ /* @__PURE__ */ d(ne, {
108
+ titleId: N,
109
+ descriptionId: P,
110
+ title: s,
111
+ description: x,
112
+ headerStart: S,
113
+ closeLabel: M.close,
114
+ onClose: () => q(!1),
115
+ delineated: !0
116
+ }),
117
+ /* @__PURE__ */ f("div", {
118
+ ref: H,
119
+ className: me,
120
+ role: "log",
121
+ "aria-label": M.conversation,
122
+ onScroll: (e) => {
123
+ let t = e.currentTarget;
124
+ U.current = t.scrollHeight - t.scrollTop - t.clientHeight <= v;
125
+ },
126
+ children: [C == null ? null : /* @__PURE__ */ d(m.div, {
127
+ className: o,
128
+ ...$,
129
+ children: C
130
+ }), /* @__PURE__ */ f(p, {
131
+ initial: !1,
132
+ children: [w.map((e) => /* @__PURE__ */ d(m.div, {
133
+ "data-role": e.role,
134
+ className: e.role === "user" ? he : o,
135
+ initial: !F && {
136
+ opacity: 0,
137
+ y: 8
138
+ },
139
+ animate: {
140
+ opacity: 1,
141
+ y: 0
142
+ },
143
+ transition: Z,
144
+ children: e.content
145
+ }, e.id)), be ? /* @__PURE__ */ f(m.div, {
146
+ className: pe,
147
+ initial: !F && { opacity: 0 },
148
+ animate: { opacity: 1 },
149
+ exit: {
150
+ opacity: 0,
151
+ transition: { duration: 0 }
152
+ },
153
+ transition: Z,
154
+ children: [/* @__PURE__ */ d(te, {
155
+ variant: "dot",
156
+ tone: "neutral",
157
+ pulsing: !0,
158
+ besideLabel: !0
159
+ }), /* @__PURE__ */ d("span", { children: M.thinking })]
160
+ }, "thinking") : null]
161
+ })]
162
+ }),
163
+ Oe ? /* @__PURE__ */ d(m.div, {
164
+ className: de,
165
+ role: "group",
166
+ "aria-label": M.suggestions,
167
+ ...$,
168
+ children: T.map((e) => /* @__PURE__ */ d(i, {
169
+ type: "button",
170
+ role: "ghost",
171
+ layout: "row",
172
+ onClick: () => Y(e),
173
+ children: /* @__PURE__ */ f("span", {
174
+ className: fe,
175
+ children: [e.icon == null ? null : /* @__PURE__ */ d(r, {
176
+ size: "md",
177
+ children: e.icon
178
+ }), /* @__PURE__ */ d("span", {
179
+ className: ue,
180
+ children: e.label
181
+ })]
182
+ })
183
+ }, e.id))
184
+ }) : null,
185
+ /* @__PURE__ */ d("div", {
186
+ className: re,
187
+ children: /* @__PURE__ */ d(a, {
188
+ ref: V,
189
+ value: R,
190
+ onValueChange: z,
191
+ onSend: J,
192
+ placeholder: O,
193
+ "aria-label": M.field,
194
+ sendLabel: M.send
195
+ })
196
+ }),
197
+ k == null ? null : /* @__PURE__ */ d("p", {
198
+ className: ie,
199
+ children: k
200
+ })
201
+ ]
202
+ }, "window") : /* @__PURE__ */ f(m.div, {
203
+ className: ae,
204
+ initial: { opacity: 0 },
205
+ animate: {
206
+ opacity: 1,
207
+ transition: {
208
+ ...Z,
209
+ delay: Ae
210
+ }
211
+ },
212
+ exit: {
213
+ opacity: 0,
214
+ transition: { duration: 0 }
215
+ },
216
+ children: [X.length > 0 ? /* @__PURE__ */ d("div", {
217
+ className: ce,
218
+ role: "group",
219
+ "aria-label": M.suggestions,
220
+ children: X.map((e, t) => /* @__PURE__ */ d("span", {
221
+ className: se,
222
+ style: { "--chat-dock-pill-index": t },
223
+ children: /* @__PURE__ */ d(i, {
224
+ type: "button",
225
+ role: "secondary",
226
+ size: "md",
227
+ icon: e.icon,
228
+ onClick: () => Y(e),
229
+ children: e.label
230
+ })
231
+ }, e.id))
232
+ }) : null, /* @__PURE__ */ d(a, {
233
+ ref: B,
234
+ value: R,
235
+ onValueChange: (e) => {
236
+ z(e), q(!0);
237
+ },
238
+ onSend: J,
239
+ onFocus: () => {
240
+ W.current || q(!0);
241
+ },
242
+ onClick: () => q(!0),
243
+ start: S,
244
+ placeholder: O,
245
+ "aria-label": M.field,
246
+ sendLabel: M.send
247
+ })]
248
+ }, "rest")
249
+ })
250
+ })
251
+ })
252
+ });
253
+ }
254
+ //#endregion
255
+ export { x as ChatDock, y as chatDockClosedClip, h as chatDockDefaultLabels, b as chatDockOpenClip, g as chatDockPillSuggestions, s as chatDockPlacements, _ as chatDockShowsSuggestionRows };