@shapesos/clay 0.18.0 → 0.19.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.
Files changed (60) hide show
  1. package/dist/artifacts.cjs +207 -139
  2. package/dist/artifacts.cjs.map +1 -1
  3. package/dist/artifacts.js +5 -2
  4. package/dist/badge.cjs +70 -0
  5. package/dist/badge.cjs.map +1 -0
  6. package/dist/badge.d.cts +28 -0
  7. package/dist/badge.d.ts +28 -0
  8. package/dist/badge.js +9 -0
  9. package/dist/badge.js.map +1 -0
  10. package/dist/blocks.cjs +452 -185
  11. package/dist/blocks.cjs.map +1 -1
  12. package/dist/blocks.css +1 -1
  13. package/dist/blocks.d.cts +14 -3
  14. package/dist/blocks.d.ts +14 -3
  15. package/dist/blocks.js +17 -5
  16. package/dist/chat.cjs +457 -240
  17. package/dist/chat.cjs.map +1 -1
  18. package/dist/chat.d.cts +1 -1
  19. package/dist/chat.d.ts +1 -1
  20. package/dist/chat.js +10 -5
  21. package/dist/{chunk-JGMN6W72.js → chunk-2X4KUXYP.js} +1 -1
  22. package/dist/{chunk-QR4VBGK4.js → chunk-63AGNGKG.js} +81 -200
  23. package/dist/chunk-63AGNGKG.js.map +1 -0
  24. package/dist/chunk-CSTCTO3B.js +161 -0
  25. package/dist/chunk-CSTCTO3B.js.map +1 -0
  26. package/dist/chunk-EIAWZXE4.js +69 -0
  27. package/dist/chunk-EIAWZXE4.js.map +1 -0
  28. package/dist/chunk-EXRNGIQ2.js +41 -0
  29. package/dist/chunk-EXRNGIQ2.js.map +1 -0
  30. package/dist/{chunk-4MZZH3WX.js → chunk-HU5W7CGE.js} +37 -2
  31. package/dist/chunk-HU5W7CGE.js.map +1 -0
  32. package/dist/chunk-PISZYS2H.js +406 -0
  33. package/dist/chunk-PISZYS2H.js.map +1 -0
  34. package/dist/{chunk-CATIRDZP.js → chunk-PWSEEUVL.js} +10 -44
  35. package/dist/chunk-PWSEEUVL.js.map +1 -0
  36. package/dist/copy-button.cjs +439 -0
  37. package/dist/copy-button.cjs.map +1 -0
  38. package/dist/copy-button.d.cts +20 -0
  39. package/dist/copy-button.d.ts +20 -0
  40. package/dist/copy-button.js +12 -0
  41. package/dist/copy-button.js.map +1 -0
  42. package/dist/index.cjs +533 -298
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.cts +4 -2
  45. package/dist/index.d.ts +4 -2
  46. package/dist/index.js +26 -9
  47. package/dist/table.cjs +40 -0
  48. package/dist/table.cjs.map +1 -1
  49. package/dist/table.d.cts +37 -2
  50. package/dist/table.d.ts +37 -2
  51. package/dist/table.js +11 -1
  52. package/dist/{types-BDYPVP2N.d.cts → types-Bhg0_ES8.d.cts} +74 -2
  53. package/dist/{types-BMwa4bPW.d.ts → types-orOQcI2z.d.ts} +74 -2
  54. package/package.json +11 -1
  55. package/dist/chunk-4MZZH3WX.js.map +0 -1
  56. package/dist/chunk-7MY4X4YL.js +0 -250
  57. package/dist/chunk-7MY4X4YL.js.map +0 -1
  58. package/dist/chunk-CATIRDZP.js.map +0 -1
  59. package/dist/chunk-QR4VBGK4.js.map +0 -1
  60. /package/dist/{chunk-JGMN6W72.js.map → chunk-2X4KUXYP.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { ColorToken, TypographyStyle, TypographyType, colors, fontFamilies, typographyMixin, typographyStyles, typographyTypes } from './tokens.cjs';
2
- export { ArtifactRefBlock, ArtifactRefBlockService, Block, BlockContext, BlockContextValue, BlockServices, TextBlockService, useBlockContext } from './blocks.cjs';
3
- export { A as ArtifactRefBlockRecord, B as BlockComponentProps, a as BlockRecord, b as BlockService, c as BlockType, T as TextBlockRecord, d as blockTypes } from './types-BDYPVP2N.cjs';
2
+ export { ArtifactRefBlock, ArtifactRefBlockService, Block, BlockContext, BlockContextValue, BlockServices, NotificationDraftBlock, NotificationDraftBlockService, TextBlockService, useBlockContext } from './blocks.cjs';
3
+ export { A as ArtifactRefBlockRecord, B as BlockComponentProps, a as BlockRecord, b as BlockService, c as BlockType, N as NotificationChannel, d as NotificationDraftBlockRecord, e as NotificationDraftPayload, f as NotificationEmailType, g as NotificationRecipient, T as TextBlockRecord, h as blockTypes, n as notificationChannels, i as notificationEmailTypes } from './types-Bhg0_ES8.cjs';
4
4
  export { CHAT_STATUS, ChatStatus, MouseGrid, MouseGridProps, PromptInput, PromptInputFooter, PromptInputFooterProps, PromptInputMessage, PromptInputProps, PromptInputSubmit, PromptInputSubmitProps, PromptInputTextarea, PromptInputTextareaProps, PromptInputTools, PromptInputToolsProps, Suggestion, SuggestionProps, Suggestions, SuggestionsProps } from './ai-elements.cjs';
5
5
  export { A as ArtifactCallbacksOf, a as ArtifactDataRow, b as ArtifactLabelsOf, c as ArtifactRecord, d as ArtifactService, e as ArtifactServiceProps, f as ArtifactType, B as BarChartConfig, C as ChartArtifactLabels, g as ChartArtifactRecord, h as ChartConfig, i as ChartStats, D as DEFAULT_CHART_ARTIFACT_LABELS, j as DEFAULT_DECK_ARTIFACT_LABELS, k as DEFAULT_TABLE_ARTIFACT_LABELS, l as DeckArtifactCallbacks, m as DeckArtifactLabels, n as DeckArtifactRecord, o as DeckBlock, p as DeckChartBlock, q as DeckConfig, r as DeckMeta, s as DeckSlide, t as DeckSlideKind, u as DeckStats, v as DeckTableBlock, w as DeckTextBlock, L as LineChartConfig, P as PieChartConfig, T as TableArtifactLabels, x as TableArtifactRecord, y as TableColumn, z as TableConfig, E as TableRow, F as TableStats, G as artifactTypes, H as deckBlockTypes, I as deckSlideKinds } from './types-DTdDFU3O.cjs';
6
6
  export { ArtifactCopyAsImageButton, ArtifactCopyAsImageButtonProps, ArtifactDownloadButton, ArtifactDownloadButtonProps, ArtifactDownloadMenu, ArtifactDownloadMenuCsvAction, ArtifactDownloadMenuPngAction, ArtifactDownloadMenuProps, ArtifactServices, ChartArtifact, DeckArtifact, TableArtifact, artifactToClipboardText, isSafeDownloadUrl } from './artifacts.cjs';
@@ -12,6 +12,8 @@ export { TextArea } from './text-area.cjs';
12
12
  export { T as TextAreaProps } from './types-CMzZsL_J.cjs';
13
13
  export { MarkdownTable, convertTableToCSV, escapeCsvField, markdownToPlainText, mergeRefs, parseMarkdownTable } from './utils.cjs';
14
14
  export { BUTTON_INTENT, BUTTON_SIZE, BUTTON_VARIANT, Button, ButtonIntent, ButtonProps, ButtonSize, ButtonVariant, ICON_POSITION, IconPosition } from './button.cjs';
15
+ export { Badge, BadgeProps, BadgeSize, BadgeTone, BadgeVariant } from './badge.cjs';
16
+ export { CopyButton, CopyButtonProps } from './copy-button.cjs';
15
17
  export { C as ChartSeries, a as ChartVariant } from './types-B2aYk82c.cjs';
16
18
  import 'react';
17
19
  import 'react/jsx-runtime';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { ColorToken, TypographyStyle, TypographyType, colors, fontFamilies, typographyMixin, typographyStyles, typographyTypes } from './tokens.js';
2
- export { ArtifactRefBlock, ArtifactRefBlockService, Block, BlockContext, BlockContextValue, BlockServices, TextBlockService, useBlockContext } from './blocks.js';
3
- export { A as ArtifactRefBlockRecord, B as BlockComponentProps, a as BlockRecord, b as BlockService, c as BlockType, T as TextBlockRecord, d as blockTypes } from './types-BMwa4bPW.js';
2
+ export { ArtifactRefBlock, ArtifactRefBlockService, Block, BlockContext, BlockContextValue, BlockServices, NotificationDraftBlock, NotificationDraftBlockService, TextBlockService, useBlockContext } from './blocks.js';
3
+ export { A as ArtifactRefBlockRecord, B as BlockComponentProps, a as BlockRecord, b as BlockService, c as BlockType, N as NotificationChannel, d as NotificationDraftBlockRecord, e as NotificationDraftPayload, f as NotificationEmailType, g as NotificationRecipient, T as TextBlockRecord, h as blockTypes, n as notificationChannels, i as notificationEmailTypes } from './types-orOQcI2z.js';
4
4
  export { CHAT_STATUS, ChatStatus, MouseGrid, MouseGridProps, PromptInput, PromptInputFooter, PromptInputFooterProps, PromptInputMessage, PromptInputProps, PromptInputSubmit, PromptInputSubmitProps, PromptInputTextarea, PromptInputTextareaProps, PromptInputTools, PromptInputToolsProps, Suggestion, SuggestionProps, Suggestions, SuggestionsProps } from './ai-elements.js';
5
5
  export { A as ArtifactCallbacksOf, a as ArtifactDataRow, b as ArtifactLabelsOf, c as ArtifactRecord, d as ArtifactService, e as ArtifactServiceProps, f as ArtifactType, B as BarChartConfig, C as ChartArtifactLabels, g as ChartArtifactRecord, h as ChartConfig, i as ChartStats, D as DEFAULT_CHART_ARTIFACT_LABELS, j as DEFAULT_DECK_ARTIFACT_LABELS, k as DEFAULT_TABLE_ARTIFACT_LABELS, l as DeckArtifactCallbacks, m as DeckArtifactLabels, n as DeckArtifactRecord, o as DeckBlock, p as DeckChartBlock, q as DeckConfig, r as DeckMeta, s as DeckSlide, t as DeckSlideKind, u as DeckStats, v as DeckTableBlock, w as DeckTextBlock, L as LineChartConfig, P as PieChartConfig, T as TableArtifactLabels, x as TableArtifactRecord, y as TableColumn, z as TableConfig, E as TableRow, F as TableStats, G as artifactTypes, H as deckBlockTypes, I as deckSlideKinds } from './types-C8JtnwNY.js';
6
6
  export { ArtifactCopyAsImageButton, ArtifactCopyAsImageButtonProps, ArtifactDownloadButton, ArtifactDownloadButtonProps, ArtifactDownloadMenu, ArtifactDownloadMenuCsvAction, ArtifactDownloadMenuPngAction, ArtifactDownloadMenuProps, ArtifactServices, ChartArtifact, DeckArtifact, TableArtifact, artifactToClipboardText, isSafeDownloadUrl } from './artifacts.js';
@@ -12,6 +12,8 @@ export { TextArea } from './text-area.js';
12
12
  export { T as TextAreaProps } from './types-CMzZsL_J.js';
13
13
  export { MarkdownTable, convertTableToCSV, escapeCsvField, markdownToPlainText, mergeRefs, parseMarkdownTable } from './utils.js';
14
14
  export { BUTTON_INTENT, BUTTON_SIZE, BUTTON_VARIANT, Button, ButtonIntent, ButtonProps, ButtonSize, ButtonVariant, ICON_POSITION, IconPosition } from './button.js';
15
+ export { Badge, BadgeProps, BadgeSize, BadgeTone, BadgeVariant } from './badge.js';
16
+ export { CopyButton, CopyButtonProps } from './copy-button.js';
15
17
  export { C as ChartSeries, a as ChartVariant } from './types-B2aYk82c.js';
16
18
  import 'react';
17
19
  import 'react/jsx-runtime';
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import "./chunk-72TJUKMV.js";
2
1
  import {
3
2
  Lottie
4
3
  } from "./chunk-BIATJTD4.js";
@@ -19,21 +18,28 @@ import {
19
18
  ChatMessage,
20
19
  MESSAGE_ROLE,
21
20
  copyMessageText,
22
- useChatContext,
23
- useCopyToClipboard
24
- } from "./chunk-CATIRDZP.js";
21
+ useChatContext
22
+ } from "./chunk-PWSEEUVL.js";
25
23
  import {
26
24
  BlockContext,
27
25
  useBlockContext
28
- } from "./chunk-JGMN6W72.js";
26
+ } from "./chunk-2X4KUXYP.js";
29
27
  import {
30
28
  ArtifactRefBlock,
31
29
  ArtifactRefBlockService,
32
30
  Block,
33
31
  BlockServices,
32
+ NotificationDraftBlock,
33
+ NotificationDraftBlockService,
34
34
  TextBlockService,
35
- blockTypes
36
- } from "./chunk-7MY4X4YL.js";
35
+ blockTypes,
36
+ notificationChannels,
37
+ notificationEmailTypes
38
+ } from "./chunk-PISZYS2H.js";
39
+ import {
40
+ CopyButton,
41
+ useCopyToClipboard
42
+ } from "./chunk-EIAWZXE4.js";
37
43
  import {
38
44
  markdownToPlainText
39
45
  } from "./chunk-NMKKU2UG.js";
@@ -78,11 +84,16 @@ import {
78
84
  deckBlockTypes,
79
85
  deckSlideKinds,
80
86
  isSafeDownloadUrl
81
- } from "./chunk-QR4VBGK4.js";
87
+ } from "./chunk-63AGNGKG.js";
88
+ import "./chunk-CSTCTO3B.js";
89
+ import "./chunk-72TJUKMV.js";
82
90
  import {
83
91
  IconButton
84
92
  } from "./chunk-E36VI2HA.js";
85
93
  import "./chunk-LXYCT4YO.js";
94
+ import {
95
+ Badge
96
+ } from "./chunk-EXRNGIQ2.js";
86
97
  import {
87
98
  Icon
88
99
  } from "./chunk-OLJIJYB5.js";
@@ -97,7 +108,7 @@ import {
97
108
  import {
98
109
  colors
99
110
  } from "./chunk-SN3ORQSJ.js";
100
- import "./chunk-4MZZH3WX.js";
111
+ import "./chunk-HU5W7CGE.js";
101
112
  import "./chunk-P6GUNIAE.js";
102
113
  import "./chunk-5WRI5ZAA.js";
103
114
  export {
@@ -110,6 +121,7 @@ export {
110
121
  BUTTON_INTENT,
111
122
  BUTTON_SIZE,
112
123
  BUTTON_VARIANT,
124
+ Badge,
113
125
  Block,
114
126
  BlockContext,
115
127
  BlockServices,
@@ -118,6 +130,7 @@ export {
118
130
  ChartArtifact,
119
131
  ChatContext,
120
132
  ChatMessage,
133
+ CopyButton,
121
134
  DEFAULT_CHART_ARTIFACT_LABELS,
122
135
  DEFAULT_DECK_ARTIFACT_LABELS,
123
136
  DEFAULT_TABLE_ARTIFACT_LABELS,
@@ -131,6 +144,8 @@ export {
131
144
  Lottie,
132
145
  MESSAGE_ROLE,
133
146
  MouseGrid,
147
+ NotificationDraftBlock,
148
+ NotificationDraftBlockService,
134
149
  PromptInput,
135
150
  PromptInputFooter,
136
151
  PromptInputSubmit,
@@ -154,6 +169,8 @@ export {
154
169
  isSafeDownloadUrl,
155
170
  markdownToPlainText,
156
171
  mergeRefs,
172
+ notificationChannels,
173
+ notificationEmailTypes,
157
174
  parseMarkdownTable,
158
175
  typographyMixin,
159
176
  typographyStyles,
package/dist/table.cjs CHANGED
@@ -30,6 +30,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/components/table/index.ts
31
31
  var table_exports = {};
32
32
  __export(table_exports, {
33
+ DATA_TABLE_CELL_CLASS: () => DATA_TABLE_CELL_CLASS,
34
+ DATA_TABLE_HEAD_CLASS: () => DATA_TABLE_HEAD_CLASS,
35
+ DATA_TABLE_ROW_CLASS: () => DATA_TABLE_ROW_CLASS,
36
+ DATA_TABLE_SCROLL_SHADOW: () => DATA_TABLE_SCROLL_SHADOW,
37
+ DataTable: () => DataTable,
33
38
  Table: () => Table,
34
39
  TableBody: () => TableBody,
35
40
  TableCaption: () => TableCaption,
@@ -127,8 +132,43 @@ function useScrollShadow() {
127
132
  }, []);
128
133
  return { targetRef, isScrolled };
129
134
  }
135
+
136
+ // src/components/table/data-table.tsx
137
+ var import_jsx_runtime2 = require("react/jsx-runtime");
138
+ var DATA_TABLE_HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
139
+ var DATA_TABLE_CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
140
+ var DATA_TABLE_ROW_CLASS = "border-b-brown-30 bg-background/70 hover:bg-secondary";
141
+ var DATA_TABLE_SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
142
+ function DataTable({ header, children, maxBodyHeight, className }) {
143
+ const { targetRef, isScrolled } = useScrollShadow();
144
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
145
+ "div",
146
+ {
147
+ ref: targetRef,
148
+ className: cn("overscroll-none", className),
149
+ style: maxBodyHeight !== void 0 ? { maxHeight: maxBodyHeight, overflowY: "auto" } : void 0,
150
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Table, { containerClassName: "overflow-visible", children: [
151
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
152
+ TableHeader,
153
+ {
154
+ "data-scrolled": isScrolled ? "true" : void 0,
155
+ className: "sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow",
156
+ style: isScrolled ? { boxShadow: DATA_TABLE_SCROLL_SHADOW } : void 0,
157
+ children: header
158
+ }
159
+ ),
160
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TableBody, { children })
161
+ ] })
162
+ }
163
+ );
164
+ }
130
165
  // Annotate the CommonJS export names for ESM import in node:
131
166
  0 && (module.exports = {
167
+ DATA_TABLE_CELL_CLASS,
168
+ DATA_TABLE_HEAD_CLASS,
169
+ DATA_TABLE_ROW_CLASS,
170
+ DATA_TABLE_SCROLL_SHADOW,
171
+ DataTable,
132
172
  Table,
133
173
  TableBody,
134
174
  TableCaption,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/table/index.ts","../src/components/ui/table.tsx","../src/lib/utils.ts","../src/components/table/use-scroll-shadow.ts"],"sourcesContent":["/**\n * Public clay table primitives — shadcn-style compound components.\n *\n * Consumers compose tables at the call site from these parts (no wrapper, no smart `Table`):\n *\n * ```tsx\n * import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from \"@shapesos/clay/table\";\n *\n * <Table>\n * <TableHeader>\n * <TableRow>\n * <TableHead>Name</TableHead>\n * <TableHead>Count</TableHead>\n * </TableRow>\n * </TableHeader>\n * <TableBody>\n * {rows.map((row) => (\n * <TableRow key={row.id}>\n * <TableCell>{row.name}</TableCell>\n * <TableCell>{row.count}</TableCell>\n * </TableRow>\n * ))}\n * </TableBody>\n * </Table>\n * ```\n *\n * `Table` extends shadcn's primitive with a `containerClassName` prop so callers can override the\n * wrapping `<div>`'s `overflow-auto` — needed when the table sits inside an outer scroll container\n * (e.g. an artifact card) and you want the sticky-header containing block to align with that\n * outer container.\n *\n * **Style note:** these primitives use Tailwind v4 + the clay theme tokens (`bg-muted`,\n * `text-muted-foreground`, `border-border`, etc.). Consumers must import the compiled stylesheet\n * alongside the JS:\n *\n * ```ts\n * import \"@shapesos/clay/blocks/styles.css\";\n * ```\n *\n * (The stylesheet name is `blocks/styles.css` for historical reasons — it's the single bundle\n * that compiles all clay-side Tailwind output, including the table primitives.)\n */\nexport {\n Table,\n TableBody,\n TableCaption,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/components/ui/table\";\nexport { useScrollShadow } from \"./use-scroll-shadow\";\n","import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/** Extension of shadcn's `Table` registry component: exposes `containerClassName` so callers can\n * override the wrapping `<div>`'s default `overflow-auto`. We need this for sticky-header support\n * (sticky uses the nearest overflow ancestor as its containing block — when the actual scroll\n * container is one level out, the inner overflow-auto needs to be neutralised with\n * `overflow-visible` so sticky aligns with the real scrolling parent). */\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement> & { containerClassName?: string }\n>(({ className, containerClassName, ...props }, ref) => (\n <div className={cn(\"relative w-full overflow-auto\", containerClassName)}>\n <table ref={ref} className={cn(\"w-full caption-bottom text-sm\", className)} {...props} />\n </div>\n));\nTable.displayName = \"Table\";\n\nconst TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n);\nTableHeader.displayName = \"TableHeader\";\n\nconst TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tbody ref={ref} className={cn(\"[&_tr:last-child]:border-0\", className)} {...props} />\n )\n);\nTableBody.displayName = \"TableBody\";\n\nconst TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tfoot ref={ref} className={cn(\"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\", className)} {...props} />\n )\n);\nTableFooter.displayName = \"TableFooter\";\n\nconst TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(\n ({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted\", className)}\n {...props}\n />\n )\n);\nTableRow.displayName = \"TableRow\";\n\nconst TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n )\n);\nTableHead.displayName = \"TableHead\";\n\nconst TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <td ref={ref} className={cn(\"p-4 align-middle [&:has([role=checkbox])]:pr-0\", className)} {...props} />\n )\n);\nTableCell.displayName = \"TableCell\";\n\nconst TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(\n ({ className, ...props }, ref) => (\n <caption ref={ref} className={cn(\"mt-4 text-sm text-muted-foreground\", className)} {...props} />\n )\n);\nTableCaption.displayName = \"TableCaption\";\n\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Combines class names using clsx and tailwind-merge — the standard shadcn/ui helper.\n * Tailwind classes that conflict (e.g. `p-2 p-4`) get merged so the last one wins.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { useEffect, useRef, useState, type RefObject } from \"react\";\n\n/**\n * Tracks whether a scroll container has scrolled past its top edge, for sticky-header shadow effects.\n *\n * Returns `targetRef` (attach to the scroll container itself or any element inside it) and\n * `isScrolled` (true once the container's `scrollTop > 0`). On mount the hook walks up the DOM\n * from the target to find the nearest overflow ancestor (or uses the target itself if it already\n * has `overflowY: auto | scroll`), then listens to its `scroll` event.\n *\n * Used to surface a subtle \"scroll lift\" shadow under sticky headers so users know there is\n * content hidden above.\n *\n * **Why a scroll listener and not a sentinel + IntersectionObserver:** an earlier version used a\n * 1px sentinel as the first child of the scroll container. The sentinel's height pushed the thead\n * down by one pixel in normal flow, and as soon as the user scrolled the thead snapped up to its\n * sticky position — a visible 1px jitter. A scroll listener has no layout footprint.\n *\n * `passive: true` so the listener doesn't block native scroll smoothness; we never call\n * `preventDefault`.\n */\nexport function useScrollShadow(): {\n targetRef: RefObject<HTMLDivElement | null>;\n isScrolled: boolean;\n} {\n const targetRef = useRef<HTMLDivElement>(null);\n const [isScrolled, setIsScrolled] = useState(false);\n\n useEffect(() => {\n const target = targetRef.current;\n if (!target) return;\n\n let scrollContainer: HTMLElement | null = target;\n while (scrollContainer) {\n const overflowY = getComputedStyle(scrollContainer).overflowY;\n if (overflowY === \"auto\" || overflowY === \"scroll\") break;\n scrollContainer = scrollContainer.parentElement;\n }\n if (!scrollContainer) return;\n\n setIsScrolled(scrollContainer.scrollTop > 0);\n\n const handleScroll = () => {\n if (!scrollContainer) return;\n setIsScrolled(scrollContainer.scrollTop > 0);\n };\n scrollContainer.addEventListener(\"scroll\", handleScroll, { passive: true });\n return () => scrollContainer.removeEventListener(\"scroll\", handleScroll);\n }, []);\n\n return { targetRef, isScrolled };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/components/table/index.ts","../src/components/ui/table.tsx","../src/lib/utils.ts","../src/components/table/use-scroll-shadow.ts","../src/components/table/data-table.tsx"],"sourcesContent":["/**\n * Public clay table primitives — shadcn-style compound components.\n *\n * Consumers compose tables at the call site from these parts (no wrapper, no smart `Table`):\n *\n * ```tsx\n * import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from \"@shapesos/clay/table\";\n *\n * <Table>\n * <TableHeader>\n * <TableRow>\n * <TableHead>Name</TableHead>\n * <TableHead>Count</TableHead>\n * </TableRow>\n * </TableHeader>\n * <TableBody>\n * {rows.map((row) => (\n * <TableRow key={row.id}>\n * <TableCell>{row.name}</TableCell>\n * <TableCell>{row.count}</TableCell>\n * </TableRow>\n * ))}\n * </TableBody>\n * </Table>\n * ```\n *\n * `Table` extends shadcn's primitive with a `containerClassName` prop so callers can override the\n * wrapping `<div>`'s `overflow-auto` — needed when the table sits inside an outer scroll container\n * (e.g. an artifact card) and you want the sticky-header containing block to align with that\n * outer container.\n *\n * **Style note:** these primitives use Tailwind v4 + the clay theme tokens (`bg-muted`,\n * `text-muted-foreground`, `border-border`, etc.). Consumers must import the compiled stylesheet\n * alongside the JS:\n *\n * ```ts\n * import \"@shapesos/clay/blocks/styles.css\";\n * ```\n *\n * (The stylesheet name is `blocks/styles.css` for historical reasons — it's the single bundle\n * that compiles all clay-side Tailwind output, including the table primitives.)\n */\nexport {\n Table,\n TableBody,\n TableCaption,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/components/ui/table\";\nexport { useScrollShadow } from \"./use-scroll-shadow\";\nexport {\n DataTable,\n DATA_TABLE_CELL_CLASS,\n DATA_TABLE_HEAD_CLASS,\n DATA_TABLE_ROW_CLASS,\n DATA_TABLE_SCROLL_SHADOW,\n} from \"./data-table\";\nexport type { DataTableProps } from \"./data-table\";\n","import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/** Extension of shadcn's `Table` registry component: exposes `containerClassName` so callers can\n * override the wrapping `<div>`'s default `overflow-auto`. We need this for sticky-header support\n * (sticky uses the nearest overflow ancestor as its containing block — when the actual scroll\n * container is one level out, the inner overflow-auto needs to be neutralised with\n * `overflow-visible` so sticky aligns with the real scrolling parent). */\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement> & { containerClassName?: string }\n>(({ className, containerClassName, ...props }, ref) => (\n <div className={cn(\"relative w-full overflow-auto\", containerClassName)}>\n <table ref={ref} className={cn(\"w-full caption-bottom text-sm\", className)} {...props} />\n </div>\n));\nTable.displayName = \"Table\";\n\nconst TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n);\nTableHeader.displayName = \"TableHeader\";\n\nconst TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tbody ref={ref} className={cn(\"[&_tr:last-child]:border-0\", className)} {...props} />\n )\n);\nTableBody.displayName = \"TableBody\";\n\nconst TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tfoot ref={ref} className={cn(\"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\", className)} {...props} />\n )\n);\nTableFooter.displayName = \"TableFooter\";\n\nconst TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(\n ({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted\", className)}\n {...props}\n />\n )\n);\nTableRow.displayName = \"TableRow\";\n\nconst TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n )\n);\nTableHead.displayName = \"TableHead\";\n\nconst TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <td ref={ref} className={cn(\"p-4 align-middle [&:has([role=checkbox])]:pr-0\", className)} {...props} />\n )\n);\nTableCell.displayName = \"TableCell\";\n\nconst TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(\n ({ className, ...props }, ref) => (\n <caption ref={ref} className={cn(\"mt-4 text-sm text-muted-foreground\", className)} {...props} />\n )\n);\nTableCaption.displayName = \"TableCaption\";\n\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Combines class names using clsx and tailwind-merge — the standard shadcn/ui helper.\n * Tailwind classes that conflict (e.g. `p-2 p-4`) get merged so the last one wins.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { useEffect, useRef, useState, type RefObject } from \"react\";\n\n/**\n * Tracks whether a scroll container has scrolled past its top edge, for sticky-header shadow effects.\n *\n * Returns `targetRef` (attach to the scroll container itself or any element inside it) and\n * `isScrolled` (true once the container's `scrollTop > 0`). On mount the hook walks up the DOM\n * from the target to find the nearest overflow ancestor (or uses the target itself if it already\n * has `overflowY: auto | scroll`), then listens to its `scroll` event.\n *\n * Used to surface a subtle \"scroll lift\" shadow under sticky headers so users know there is\n * content hidden above.\n *\n * **Why a scroll listener and not a sentinel + IntersectionObserver:** an earlier version used a\n * 1px sentinel as the first child of the scroll container. The sentinel's height pushed the thead\n * down by one pixel in normal flow, and as soon as the user scrolled the thead snapped up to its\n * sticky position — a visible 1px jitter. A scroll listener has no layout footprint.\n *\n * `passive: true` so the listener doesn't block native scroll smoothness; we never call\n * `preventDefault`.\n */\nexport function useScrollShadow(): {\n targetRef: RefObject<HTMLDivElement | null>;\n isScrolled: boolean;\n} {\n const targetRef = useRef<HTMLDivElement>(null);\n const [isScrolled, setIsScrolled] = useState(false);\n\n useEffect(() => {\n const target = targetRef.current;\n if (!target) return;\n\n let scrollContainer: HTMLElement | null = target;\n while (scrollContainer) {\n const overflowY = getComputedStyle(scrollContainer).overflowY;\n if (overflowY === \"auto\" || overflowY === \"scroll\") break;\n scrollContainer = scrollContainer.parentElement;\n }\n if (!scrollContainer) return;\n\n setIsScrolled(scrollContainer.scrollTop > 0);\n\n const handleScroll = () => {\n if (!scrollContainer) return;\n setIsScrolled(scrollContainer.scrollTop > 0);\n };\n scrollContainer.addEventListener(\"scroll\", handleScroll, { passive: true });\n return () => scrollContainer.removeEventListener(\"scroll\", handleScroll);\n }, []);\n\n return { targetRef, isScrolled };\n}\n","import type { ReactNode } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Table, TableBody, TableHeader } from \"@/components/ui/table\";\nimport { useScrollShadow } from \"./use-scroll-shadow\";\n\n/**\n * Header cell class — compact, left-aligned, non-wrapping. Apply to each `<TableHead>` composed at\n * the call site so every clay data table shares one header treatment.\n */\nexport const DATA_TABLE_HEAD_CLASS = \"h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left\";\n\n/** Body cell class — roomy padding, top-aligned, left-aligned, min width so columns don't collapse. */\nexport const DATA_TABLE_CELL_CLASS = \"p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left\";\n\n/**\n * Data-row class matching the frosted-glass card scheme: `border-b-brown-30` overrides shadcn's\n * default `--color-border` (brown-40) with the lighter brown-30; hover lifts to opaque `bg-secondary`.\n */\nexport const DATA_TABLE_ROW_CLASS = \"border-b-brown-30 bg-background/70 hover:bg-secondary\";\n\n/** Layered drop-shadow for the scroll-lift effect on the sticky header. */\nexport const DATA_TABLE_SCROLL_SHADOW = \"0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)\";\n\nexport interface DataTableProps {\n /**\n * Header row content — typically a single `<TableRow>` of `<TableHead>` cells (use\n * `DATA_TABLE_HEAD_CLASS`). Rendered inside the sticky, frosted `<TableHeader>` shell.\n */\n header: ReactNode;\n /** Body rows composed at the call site (`<TableRow>`/`<TableCell>`). */\n children: ReactNode;\n /** Max body height (px) before vertical scroll engages. Omit for no cap (grows to content). */\n maxBodyHeight?: number;\n /** Extra classes for the scroll container. */\n className?: string;\n}\n\n/**\n * Shared styled-table shell — the scroll container, sticky frosted (`bg-background/70\n * backdrop-blur-lg`) header, and scroll-lift shadow (via {@link useScrollShadow}) that give clay\n * data tables (table artifact, notification-draft recipients) one consistent look. Callers compose\n * the header cells and body rows at the call site; this is only the shell.\n */\nexport function DataTable({ header, children, maxBodyHeight, className }: DataTableProps): ReactNode {\n const { targetRef, isScrolled } = useScrollShadow();\n return (\n <div\n ref={targetRef}\n className={cn(\"overscroll-none\", className)}\n style={maxBodyHeight !== undefined ? { maxHeight: maxBodyHeight, overflowY: \"auto\" } : undefined}\n >\n <Table containerClassName=\"overflow-visible\">\n <TableHeader\n data-scrolled={isScrolled ? \"true\" : undefined}\n className=\"sticky top-0 z-10 bg-background/70 backdrop-blur-lg transition-shadow\"\n style={isScrolled ? { boxShadow: DATA_TABLE_SCROLL_SHADOW } : undefined}\n >\n {header}\n </TableHeader>\n <TableBody>{children}</TableBody>\n </Table>\n </div>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime"]}
package/dist/table.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { RefObject } from 'react';
2
+ import { RefObject, ReactNode } from 'react';
3
3
 
4
4
  /** Extension of shadcn's `Table` registry component: exposes `containerClassName` so callers can
5
5
  * override the wrapping `<div>`'s default `overflow-auto`. We need this for sticky-header support
@@ -41,4 +41,39 @@ declare function useScrollShadow(): {
41
41
  isScrolled: boolean;
42
42
  };
43
43
 
44
- export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, useScrollShadow };
44
+ /**
45
+ * Header cell class — compact, left-aligned, non-wrapping. Apply to each `<TableHead>` composed at
46
+ * the call site so every clay data table shares one header treatment.
47
+ */
48
+ declare const DATA_TABLE_HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
49
+ /** Body cell class — roomy padding, top-aligned, left-aligned, min width so columns don't collapse. */
50
+ declare const DATA_TABLE_CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
51
+ /**
52
+ * Data-row class matching the frosted-glass card scheme: `border-b-brown-30` overrides shadcn's
53
+ * default `--color-border` (brown-40) with the lighter brown-30; hover lifts to opaque `bg-secondary`.
54
+ */
55
+ declare const DATA_TABLE_ROW_CLASS = "border-b-brown-30 bg-background/70 hover:bg-secondary";
56
+ /** Layered drop-shadow for the scroll-lift effect on the sticky header. */
57
+ declare const DATA_TABLE_SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
58
+ interface DataTableProps {
59
+ /**
60
+ * Header row content — typically a single `<TableRow>` of `<TableHead>` cells (use
61
+ * `DATA_TABLE_HEAD_CLASS`). Rendered inside the sticky, frosted `<TableHeader>` shell.
62
+ */
63
+ header: ReactNode;
64
+ /** Body rows composed at the call site (`<TableRow>`/`<TableCell>`). */
65
+ children: ReactNode;
66
+ /** Max body height (px) before vertical scroll engages. Omit for no cap (grows to content). */
67
+ maxBodyHeight?: number;
68
+ /** Extra classes for the scroll container. */
69
+ className?: string;
70
+ }
71
+ /**
72
+ * Shared styled-table shell — the scroll container, sticky frosted (`bg-background/70
73
+ * backdrop-blur-lg`) header, and scroll-lift shadow (via {@link useScrollShadow}) that give clay
74
+ * data tables (table artifact, notification-draft recipients) one consistent look. Callers compose
75
+ * the header cells and body rows at the call site; this is only the shell.
76
+ */
77
+ declare function DataTable({ header, children, maxBodyHeight, className }: DataTableProps): ReactNode;
78
+
79
+ export { DATA_TABLE_CELL_CLASS, DATA_TABLE_HEAD_CLASS, DATA_TABLE_ROW_CLASS, DATA_TABLE_SCROLL_SHADOW, DataTable, type DataTableProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, useScrollShadow };
package/dist/table.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { RefObject } from 'react';
2
+ import { RefObject, ReactNode } from 'react';
3
3
 
4
4
  /** Extension of shadcn's `Table` registry component: exposes `containerClassName` so callers can
5
5
  * override the wrapping `<div>`'s default `overflow-auto`. We need this for sticky-header support
@@ -41,4 +41,39 @@ declare function useScrollShadow(): {
41
41
  isScrolled: boolean;
42
42
  };
43
43
 
44
- export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, useScrollShadow };
44
+ /**
45
+ * Header cell class — compact, left-aligned, non-wrapping. Apply to each `<TableHead>` composed at
46
+ * the call site so every clay data table shares one header treatment.
47
+ */
48
+ declare const DATA_TABLE_HEAD_CLASS = "h-auto py-2 px-4 text-xs font-medium text-foreground whitespace-nowrap text-left";
49
+ /** Body cell class — roomy padding, top-aligned, left-aligned, min width so columns don't collapse. */
50
+ declare const DATA_TABLE_CELL_CLASS = "p-4 text-sm font-normal text-foreground align-top min-w-[150px] text-left";
51
+ /**
52
+ * Data-row class matching the frosted-glass card scheme: `border-b-brown-30` overrides shadcn's
53
+ * default `--color-border` (brown-40) with the lighter brown-30; hover lifts to opaque `bg-secondary`.
54
+ */
55
+ declare const DATA_TABLE_ROW_CLASS = "border-b-brown-30 bg-background/70 hover:bg-secondary";
56
+ /** Layered drop-shadow for the scroll-lift effect on the sticky header. */
57
+ declare const DATA_TABLE_SCROLL_SHADOW = "0 1px 2px rgb(0 0 0 / 0.01), 0 6px 12px -2px rgb(0 0 0 / 0.03)";
58
+ interface DataTableProps {
59
+ /**
60
+ * Header row content — typically a single `<TableRow>` of `<TableHead>` cells (use
61
+ * `DATA_TABLE_HEAD_CLASS`). Rendered inside the sticky, frosted `<TableHeader>` shell.
62
+ */
63
+ header: ReactNode;
64
+ /** Body rows composed at the call site (`<TableRow>`/`<TableCell>`). */
65
+ children: ReactNode;
66
+ /** Max body height (px) before vertical scroll engages. Omit for no cap (grows to content). */
67
+ maxBodyHeight?: number;
68
+ /** Extra classes for the scroll container. */
69
+ className?: string;
70
+ }
71
+ /**
72
+ * Shared styled-table shell — the scroll container, sticky frosted (`bg-background/70
73
+ * backdrop-blur-lg`) header, and scroll-lift shadow (via {@link useScrollShadow}) that give clay
74
+ * data tables (table artifact, notification-draft recipients) one consistent look. Callers compose
75
+ * the header cells and body rows at the call site; this is only the shell.
76
+ */
77
+ declare function DataTable({ header, children, maxBodyHeight, className }: DataTableProps): ReactNode;
78
+
79
+ export { DATA_TABLE_CELL_CLASS, DATA_TABLE_HEAD_CLASS, DATA_TABLE_ROW_CLASS, DATA_TABLE_SCROLL_SHADOW, DataTable, type DataTableProps, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, useScrollShadow };
package/dist/table.js CHANGED
@@ -1,4 +1,9 @@
1
1
  import {
2
+ DATA_TABLE_CELL_CLASS,
3
+ DATA_TABLE_HEAD_CLASS,
4
+ DATA_TABLE_ROW_CLASS,
5
+ DATA_TABLE_SCROLL_SHADOW,
6
+ DataTable,
2
7
  Table,
3
8
  TableBody,
4
9
  TableCaption,
@@ -8,10 +13,15 @@ import {
8
13
  TableHeader,
9
14
  TableRow,
10
15
  useScrollShadow
11
- } from "./chunk-4MZZH3WX.js";
16
+ } from "./chunk-HU5W7CGE.js";
12
17
  import "./chunk-P6GUNIAE.js";
13
18
  import "./chunk-5WRI5ZAA.js";
14
19
  export {
20
+ DATA_TABLE_CELL_CLASS,
21
+ DATA_TABLE_HEAD_CLASS,
22
+ DATA_TABLE_ROW_CLASS,
23
+ DATA_TABLE_SCROLL_SHADOW,
24
+ DataTable,
15
25
  Table,
16
26
  TableBody,
17
27
  TableCaption,
@@ -1,10 +1,82 @@
1
1
  import { ComponentType } from 'react';
2
2
  import { c as ArtifactRecord, b as ArtifactLabelsOf, A as ArtifactCallbacksOf } from './types-DTdDFU3O.cjs';
3
3
 
4
+ /** Delivery channel the drafted notification targets. */
5
+ declare const notificationChannels: {
6
+ /** Branded email — renders a From/subject header. */
7
+ readonly EMAIL: "email";
8
+ /** Slack DM — renders as a chat bubble, no subject. */
9
+ readonly SLACK: "slack";
10
+ /** Microsoft Teams DM — renders as a chat bubble, no subject. */
11
+ readonly TEAMS: "teams";
12
+ };
13
+ /** One of the supported notification channels. */
14
+ type NotificationChannel = (typeof notificationChannels)[keyof typeof notificationChannels];
15
+ /** Which recipient address the email is sent to (email channel only). */
16
+ declare const notificationEmailTypes: {
17
+ /** Recipient's work email. */
18
+ readonly WORK: "work";
19
+ /** Recipient's personal email. */
20
+ readonly PERSONAL: "personal";
21
+ };
22
+ /** One of the supported email address types. */
23
+ type NotificationEmailType = (typeof notificationEmailTypes)[keyof typeof notificationEmailTypes];
24
+ /**
25
+ * A single resolved recipient of the drafted notification — the block's one source of recipient
26
+ * truth. The summary chips and the detail table are both projected from this (count, chip labels,
27
+ * and fallback count are all derived, never transmitted separately).
28
+ */
29
+ interface NotificationRecipient {
30
+ /** Stable employee identifier — used as the React key. */
31
+ employeeId: string;
32
+ /** Display name; falls back to `email` for the chip label when absent. */
33
+ name?: string | null;
34
+ /** Resolved delivery address (work or personal, already resolved server-side). */
35
+ email?: string | null;
36
+ /**
37
+ * Human-readable label for the channel this recipient is reached on (e.g. "Email", "Slack").
38
+ * Client-provided so clay isn't limited to a fixed channel set and holds no channel copy of its
39
+ * own — the consumer passes whatever label fits its use case in the payload.
40
+ */
41
+ channelLabel: string;
42
+ /** Whether this recipient is unreachable on the chosen channel and falls back to email. */
43
+ fallback: boolean;
44
+ }
45
+ /**
46
+ * Wire payload for a drafted notification preview — populated by the agent from the
47
+ * `validate_send_notification` dry-run. Presentation only: this block previews what will be
48
+ * sent, it is NOT the approval/confirmation control.
49
+ */
50
+ interface NotificationDraftPayload {
51
+ /** Delivery channel; drives whether a subject title is shown (email only). */
52
+ channel: NotificationChannel;
53
+ /** Which address the email is sent to. Email channel only; ignored otherwise. */
54
+ emailType?: NotificationEmailType;
55
+ /** Email subject line. Email channel only; absent for slack/teams. */
56
+ subject?: string;
57
+ /** Message body (markdown source). Rendered as markdown, identical to chat assistant text. */
58
+ body: string;
59
+ /** Resolved From display name, e.g. "Acme HR via Shapes". Email channel only. */
60
+ fromDisplay?: string;
61
+ /**
62
+ * Every resolved recipient. Clay derives the count, the summary chips (`name ?? email`, with a
63
+ * "+N" overflow), and the fallback count from this single array.
64
+ */
65
+ recipients: NotificationRecipient[];
66
+ }
67
+ /** A NOTIFICATION_DRAFT content block — wraps a {@link NotificationDraftPayload}. */
68
+ interface NotificationDraftBlockRecord {
69
+ /** Block-type discriminator. */
70
+ type: typeof blockTypes.NOTIFICATION_DRAFT;
71
+ /** Type-specific data; kept as `payload` to match the wire shape 1:1. */
72
+ payload: NotificationDraftPayload;
73
+ }
74
+
4
75
  /** Block-type discriminator constants. Mirrors the wire shape from io-server / shapes-agent. */
5
76
  declare const blockTypes: {
6
77
  readonly TEXT: "TEXT";
7
78
  readonly ARTIFACT_REF: "ARTIFACT_REF";
79
+ readonly NOTIFICATION_DRAFT: "NOTIFICATION_DRAFT";
8
80
  };
9
81
  /** Discriminator for content blocks. */
10
82
  type BlockType = (typeof blockTypes)[keyof typeof blockTypes];
@@ -65,7 +137,7 @@ type ArtifactRefBlockRecord = ArtifactRecord extends infer TArtifact ? TArtifact
65
137
  };
66
138
  } : never : never;
67
139
  /** Discriminated union of all supported content blocks. Additive — new types extend this union. */
68
- type BlockRecord = TextBlockRecord | ArtifactRefBlockRecord;
140
+ type BlockRecord = TextBlockRecord | ArtifactRefBlockRecord | NotificationDraftBlockRecord;
69
141
  /** Props every concrete block component receives from the dispatcher. */
70
142
  interface BlockComponentProps<TBlock extends BlockRecord = BlockRecord> {
71
143
  /** The block to render. */
@@ -92,4 +164,4 @@ interface BlockService<TBlock extends BlockRecord = BlockRecord> {
92
164
  toClipboardText?: (block: TBlock) => string;
93
165
  }
94
166
 
95
- export { type ArtifactRefBlockRecord as A, type BlockComponentProps as B, type TextBlockRecord as T, type BlockRecord as a, type BlockService as b, type BlockType as c, blockTypes as d };
167
+ export { type ArtifactRefBlockRecord as A, type BlockComponentProps as B, type NotificationChannel as N, type TextBlockRecord as T, type BlockRecord as a, type BlockService as b, type BlockType as c, type NotificationDraftBlockRecord as d, type NotificationDraftPayload as e, type NotificationEmailType as f, type NotificationRecipient as g, blockTypes as h, notificationEmailTypes as i, notificationChannels as n };
@@ -1,10 +1,82 @@
1
1
  import { ComponentType } from 'react';
2
2
  import { c as ArtifactRecord, b as ArtifactLabelsOf, A as ArtifactCallbacksOf } from './types-C8JtnwNY.js';
3
3
 
4
+ /** Delivery channel the drafted notification targets. */
5
+ declare const notificationChannels: {
6
+ /** Branded email — renders a From/subject header. */
7
+ readonly EMAIL: "email";
8
+ /** Slack DM — renders as a chat bubble, no subject. */
9
+ readonly SLACK: "slack";
10
+ /** Microsoft Teams DM — renders as a chat bubble, no subject. */
11
+ readonly TEAMS: "teams";
12
+ };
13
+ /** One of the supported notification channels. */
14
+ type NotificationChannel = (typeof notificationChannels)[keyof typeof notificationChannels];
15
+ /** Which recipient address the email is sent to (email channel only). */
16
+ declare const notificationEmailTypes: {
17
+ /** Recipient's work email. */
18
+ readonly WORK: "work";
19
+ /** Recipient's personal email. */
20
+ readonly PERSONAL: "personal";
21
+ };
22
+ /** One of the supported email address types. */
23
+ type NotificationEmailType = (typeof notificationEmailTypes)[keyof typeof notificationEmailTypes];
24
+ /**
25
+ * A single resolved recipient of the drafted notification — the block's one source of recipient
26
+ * truth. The summary chips and the detail table are both projected from this (count, chip labels,
27
+ * and fallback count are all derived, never transmitted separately).
28
+ */
29
+ interface NotificationRecipient {
30
+ /** Stable employee identifier — used as the React key. */
31
+ employeeId: string;
32
+ /** Display name; falls back to `email` for the chip label when absent. */
33
+ name?: string | null;
34
+ /** Resolved delivery address (work or personal, already resolved server-side). */
35
+ email?: string | null;
36
+ /**
37
+ * Human-readable label for the channel this recipient is reached on (e.g. "Email", "Slack").
38
+ * Client-provided so clay isn't limited to a fixed channel set and holds no channel copy of its
39
+ * own — the consumer passes whatever label fits its use case in the payload.
40
+ */
41
+ channelLabel: string;
42
+ /** Whether this recipient is unreachable on the chosen channel and falls back to email. */
43
+ fallback: boolean;
44
+ }
45
+ /**
46
+ * Wire payload for a drafted notification preview — populated by the agent from the
47
+ * `validate_send_notification` dry-run. Presentation only: this block previews what will be
48
+ * sent, it is NOT the approval/confirmation control.
49
+ */
50
+ interface NotificationDraftPayload {
51
+ /** Delivery channel; drives whether a subject title is shown (email only). */
52
+ channel: NotificationChannel;
53
+ /** Which address the email is sent to. Email channel only; ignored otherwise. */
54
+ emailType?: NotificationEmailType;
55
+ /** Email subject line. Email channel only; absent for slack/teams. */
56
+ subject?: string;
57
+ /** Message body (markdown source). Rendered as markdown, identical to chat assistant text. */
58
+ body: string;
59
+ /** Resolved From display name, e.g. "Acme HR via Shapes". Email channel only. */
60
+ fromDisplay?: string;
61
+ /**
62
+ * Every resolved recipient. Clay derives the count, the summary chips (`name ?? email`, with a
63
+ * "+N" overflow), and the fallback count from this single array.
64
+ */
65
+ recipients: NotificationRecipient[];
66
+ }
67
+ /** A NOTIFICATION_DRAFT content block — wraps a {@link NotificationDraftPayload}. */
68
+ interface NotificationDraftBlockRecord {
69
+ /** Block-type discriminator. */
70
+ type: typeof blockTypes.NOTIFICATION_DRAFT;
71
+ /** Type-specific data; kept as `payload` to match the wire shape 1:1. */
72
+ payload: NotificationDraftPayload;
73
+ }
74
+
4
75
  /** Block-type discriminator constants. Mirrors the wire shape from io-server / shapes-agent. */
5
76
  declare const blockTypes: {
6
77
  readonly TEXT: "TEXT";
7
78
  readonly ARTIFACT_REF: "ARTIFACT_REF";
79
+ readonly NOTIFICATION_DRAFT: "NOTIFICATION_DRAFT";
8
80
  };
9
81
  /** Discriminator for content blocks. */
10
82
  type BlockType = (typeof blockTypes)[keyof typeof blockTypes];
@@ -65,7 +137,7 @@ type ArtifactRefBlockRecord = ArtifactRecord extends infer TArtifact ? TArtifact
65
137
  };
66
138
  } : never : never;
67
139
  /** Discriminated union of all supported content blocks. Additive — new types extend this union. */
68
- type BlockRecord = TextBlockRecord | ArtifactRefBlockRecord;
140
+ type BlockRecord = TextBlockRecord | ArtifactRefBlockRecord | NotificationDraftBlockRecord;
69
141
  /** Props every concrete block component receives from the dispatcher. */
70
142
  interface BlockComponentProps<TBlock extends BlockRecord = BlockRecord> {
71
143
  /** The block to render. */
@@ -92,4 +164,4 @@ interface BlockService<TBlock extends BlockRecord = BlockRecord> {
92
164
  toClipboardText?: (block: TBlock) => string;
93
165
  }
94
166
 
95
- export { type ArtifactRefBlockRecord as A, type BlockComponentProps as B, type TextBlockRecord as T, type BlockRecord as a, type BlockService as b, type BlockType as c, blockTypes as d };
167
+ export { type ArtifactRefBlockRecord as A, type BlockComponentProps as B, type NotificationChannel as N, type TextBlockRecord as T, type BlockRecord as a, type BlockService as b, type BlockType as c, type NotificationDraftBlockRecord as d, type NotificationDraftPayload as e, type NotificationEmailType as f, type NotificationRecipient as g, blockTypes as h, notificationEmailTypes as i, notificationChannels as n };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapesos/clay",
3
- "version": "0.18.0",
3
+ "version": "0.19.1",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.js",
6
6
  "devDependencies": {
@@ -133,6 +133,16 @@
133
133
  "types": "./dist/button.d.ts",
134
134
  "import": "./dist/button.js",
135
135
  "require": "./dist/button.cjs"
136
+ },
137
+ "./badge": {
138
+ "types": "./dist/badge.d.ts",
139
+ "import": "./dist/badge.js",
140
+ "require": "./dist/badge.cjs"
141
+ },
142
+ "./copy-button": {
143
+ "types": "./dist/copy-button.d.ts",
144
+ "import": "./dist/copy-button.js",
145
+ "require": "./dist/copy-button.cjs"
136
146
  }
137
147
  },
138
148
  "description": "Shapes.co design system — tokens and theming",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/table.tsx","../src/components/table/use-scroll-shadow.ts"],"sourcesContent":["import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/** Extension of shadcn's `Table` registry component: exposes `containerClassName` so callers can\n * override the wrapping `<div>`'s default `overflow-auto`. We need this for sticky-header support\n * (sticky uses the nearest overflow ancestor as its containing block — when the actual scroll\n * container is one level out, the inner overflow-auto needs to be neutralised with\n * `overflow-visible` so sticky aligns with the real scrolling parent). */\nconst Table = React.forwardRef<\n HTMLTableElement,\n React.HTMLAttributes<HTMLTableElement> & { containerClassName?: string }\n>(({ className, containerClassName, ...props }, ref) => (\n <div className={cn(\"relative w-full overflow-auto\", containerClassName)}>\n <table ref={ref} className={cn(\"w-full caption-bottom text-sm\", className)} {...props} />\n </div>\n));\nTable.displayName = \"Table\";\n\nconst TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => <thead ref={ref} className={cn(\"[&_tr]:border-b\", className)} {...props} />\n);\nTableHeader.displayName = \"TableHeader\";\n\nconst TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tbody ref={ref} className={cn(\"[&_tr:last-child]:border-0\", className)} {...props} />\n )\n);\nTableBody.displayName = \"TableBody\";\n\nconst TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(\n ({ className, ...props }, ref) => (\n <tfoot ref={ref} className={cn(\"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0\", className)} {...props} />\n )\n);\nTableFooter.displayName = \"TableFooter\";\n\nconst TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(\n ({ className, ...props }, ref) => (\n <tr\n ref={ref}\n className={cn(\"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted\", className)}\n {...props}\n />\n )\n);\nTableRow.displayName = \"TableRow\";\n\nconst TableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <th\n ref={ref}\n className={cn(\n \"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0\",\n className\n )}\n {...props}\n />\n )\n);\nTableHead.displayName = \"TableHead\";\n\nconst TableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>(\n ({ className, ...props }, ref) => (\n <td ref={ref} className={cn(\"p-4 align-middle [&:has([role=checkbox])]:pr-0\", className)} {...props} />\n )\n);\nTableCell.displayName = \"TableCell\";\n\nconst TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(\n ({ className, ...props }, ref) => (\n <caption ref={ref} className={cn(\"mt-4 text-sm text-muted-foreground\", className)} {...props} />\n )\n);\nTableCaption.displayName = \"TableCaption\";\n\nexport { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };\n","import { useEffect, useRef, useState, type RefObject } from \"react\";\n\n/**\n * Tracks whether a scroll container has scrolled past its top edge, for sticky-header shadow effects.\n *\n * Returns `targetRef` (attach to the scroll container itself or any element inside it) and\n * `isScrolled` (true once the container's `scrollTop > 0`). On mount the hook walks up the DOM\n * from the target to find the nearest overflow ancestor (or uses the target itself if it already\n * has `overflowY: auto | scroll`), then listens to its `scroll` event.\n *\n * Used to surface a subtle \"scroll lift\" shadow under sticky headers so users know there is\n * content hidden above.\n *\n * **Why a scroll listener and not a sentinel + IntersectionObserver:** an earlier version used a\n * 1px sentinel as the first child of the scroll container. The sentinel's height pushed the thead\n * down by one pixel in normal flow, and as soon as the user scrolled the thead snapped up to its\n * sticky position — a visible 1px jitter. A scroll listener has no layout footprint.\n *\n * `passive: true` so the listener doesn't block native scroll smoothness; we never call\n * `preventDefault`.\n */\nexport function useScrollShadow(): {\n targetRef: RefObject<HTMLDivElement | null>;\n isScrolled: boolean;\n} {\n const targetRef = useRef<HTMLDivElement>(null);\n const [isScrolled, setIsScrolled] = useState(false);\n\n useEffect(() => {\n const target = targetRef.current;\n if (!target) return;\n\n let scrollContainer: HTMLElement | null = target;\n while (scrollContainer) {\n const overflowY = getComputedStyle(scrollContainer).overflowY;\n if (overflowY === \"auto\" || overflowY === \"scroll\") break;\n scrollContainer = scrollContainer.parentElement;\n }\n if (!scrollContainer) return;\n\n setIsScrolled(scrollContainer.scrollTop > 0);\n\n const handleScroll = () => {\n if (!scrollContainer) return;\n setIsScrolled(scrollContainer.scrollTop > 0);\n };\n scrollContainer.addEventListener(\"scroll\", handleScroll, { passive: true });\n return () => scrollContainer.removeEventListener(\"scroll\", handleScroll);\n }, []);\n\n return { targetRef, isScrolled };\n}\n"],"mappings":";;;;;AAAA,YAAY,WAAW;AAcnB;AALJ,IAAM,QAAc,iBAGlB,CAAC,EAAE,WAAW,oBAAoB,GAAG,MAAM,GAAG,QAC9C,oBAAC,SAAI,WAAW,GAAG,iCAAiC,kBAAkB,GACpE,8BAAC,WAAM,KAAU,WAAW,GAAG,iCAAiC,SAAS,GAAI,GAAG,OAAO,GACzF,CACD;AACD,MAAM,cAAc;AAEpB,IAAM,cAAoB;AAAA,EACxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ,oBAAC,WAAM,KAAU,WAAW,GAAG,mBAAmB,SAAS,GAAI,GAAG,OAAO;AAC7G;AACA,YAAY,cAAc;AAE1B,IAAM,YAAkB;AAAA,EACtB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QACxB,oBAAC,WAAM,KAAU,WAAW,GAAG,8BAA8B,SAAS,GAAI,GAAG,OAAO;AAExF;AACA,UAAU,cAAc;AAExB,IAAM,cAAoB;AAAA,EACxB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QACxB,oBAAC,WAAM,KAAU,WAAW,GAAG,2DAA2D,SAAS,GAAI,GAAG,OAAO;AAErH;AACA,YAAY,cAAc;AAE1B,IAAM,WAAiB;AAAA,EACrB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QACxB;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,+EAA+E,SAAS;AAAA,MACrG,GAAG;AAAA;AAAA,EACN;AAEJ;AACA,SAAS,cAAc;AAEvB,IAAM,YAAkB;AAAA,EACtB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QACxB;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AACA,UAAU,cAAc;AAExB,IAAM,YAAkB;AAAA,EACtB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QACxB,oBAAC,QAAG,KAAU,WAAW,GAAG,kDAAkD,SAAS,GAAI,GAAG,OAAO;AAEzG;AACA,UAAU,cAAc;AAExB,IAAM,eAAqB;AAAA,EACzB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QACxB,oBAAC,aAAQ,KAAU,WAAW,GAAG,sCAAsC,SAAS,GAAI,GAAG,OAAO;AAElG;AACA,aAAa,cAAc;;;AC3E3B,SAAS,WAAW,QAAQ,gBAAgC;AAqBrD,SAAS,kBAGd;AACA,QAAM,YAAY,OAAuB,IAAI;AAC7C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,YAAU,MAAM;AACd,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ;AAEb,QAAI,kBAAsC;AAC1C,WAAO,iBAAiB;AACtB,YAAM,YAAY,iBAAiB,eAAe,EAAE;AACpD,UAAI,cAAc,UAAU,cAAc,SAAU;AACpD,wBAAkB,gBAAgB;AAAA,IACpC;AACA,QAAI,CAAC,gBAAiB;AAEtB,kBAAc,gBAAgB,YAAY,CAAC;AAE3C,UAAM,eAAe,MAAM;AACzB,UAAI,CAAC,gBAAiB;AACtB,oBAAc,gBAAgB,YAAY,CAAC;AAAA,IAC7C;AACA,oBAAgB,iBAAiB,UAAU,cAAc,EAAE,SAAS,KAAK,CAAC;AAC1E,WAAO,MAAM,gBAAgB,oBAAoB,UAAU,YAAY;AAAA,EACzE,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,WAAW,WAAW;AACjC;","names":[]}